mirror of
https://github.com/gotson/komga.git
synced 2026-05-08 12:35:30 +02:00
add FormattedMessage component
This commit is contained in:
parent
bab8e88843
commit
565b59c4d0
3 changed files with 110 additions and 0 deletions
11
next-ui/src/components/FormattedMessage.mdx
Normal file
11
next-ui/src/components/FormattedMessage.mdx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import {Canvas, Meta} from '@storybook/addon-docs/blocks';
|
||||
|
||||
import * as Stories from './FormattedMessage.stories';
|
||||
|
||||
<Meta of={Stories} />
|
||||
|
||||
# FormattedMessage
|
||||
|
||||
Component to display formatted `formatjs` messages using dynamic slots.
|
||||
|
||||
<Canvas of={Stories.Default} />
|
||||
73
next-ui/src/components/FormattedMessage.stories.ts
Normal file
73
next-ui/src/components/FormattedMessage.stories.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
|
||||
import FormattedMessage from './FormattedMessage.ts'
|
||||
|
||||
const meta = {
|
||||
component: FormattedMessage,
|
||||
parameters: {
|
||||
// More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
|
||||
},
|
||||
args: {},
|
||||
} satisfies Meta<typeof Details>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
render: (args: object) => ({
|
||||
components: { FormattedMessage },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<FormattedMessage :messageDescriptor="{
|
||||
defaultMessage: 'Please accept <a>terms <b>and<br></br></b> conditions</a> first',
|
||||
id: 'test',
|
||||
}">
|
||||
<template #a="Content">
|
||||
<a href="#" target="_blank">
|
||||
<component :is="Content"/>
|
||||
</a>
|
||||
</template>
|
||||
<template #b="Content">
|
||||
<strong>
|
||||
<component :is="Content"/>
|
||||
</strong>
|
||||
</template>
|
||||
<template #br>
|
||||
<br/>
|
||||
</template>
|
||||
</FormattedMessage>
|
||||
`,
|
||||
}),
|
||||
}
|
||||
|
||||
export const NoMarkup: Story = {
|
||||
render: (args: object) => ({
|
||||
components: { FormattedMessage },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<FormattedMessage :messageDescriptor="{
|
||||
defaultMessage: 'Please accept terms and conditions first',
|
||||
id: 'test',
|
||||
}"/>
|
||||
`,
|
||||
}),
|
||||
}
|
||||
|
||||
export const NoMarkupTag: Story = {
|
||||
render: (args: object) => ({
|
||||
components: { FormattedMessage },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<FormattedMessage :messageDescriptor="{
|
||||
defaultMessage: 'Please accept terms and conditions first',
|
||||
id: 'test',
|
||||
}" tag="div"/>
|
||||
`,
|
||||
}),
|
||||
}
|
||||
26
next-ui/src/components/FormattedMessage.ts
Normal file
26
next-ui/src/components/FormattedMessage.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { defineComponent, h } from 'vue'
|
||||
import { type MessageDescriptor, useIntl } from 'vue-intl'
|
||||
|
||||
// from: https://github.com/formatjs/formatjs/discussions/3961
|
||||
export default defineComponent({
|
||||
props: {
|
||||
messageDescriptor: Object as PropType<MessageDescriptor>,
|
||||
tag: String,
|
||||
values: Object,
|
||||
},
|
||||
setup(props, context) {
|
||||
const { messageDescriptor, tag, values = {} } = props
|
||||
const intl = useIntl()
|
||||
const slotNames = Object.keys(context.slots)
|
||||
|
||||
const message = intl.formatMessage(messageDescriptor, {
|
||||
...values,
|
||||
...slotNames.reduce((slots, name) => {
|
||||
slots[name] = (content) => context.slots[name](() => content)
|
||||
return slots
|
||||
}, {}),
|
||||
})
|
||||
|
||||
return () => (tag || Array.isArray(message) ? h(tag || 'div', message) : message)
|
||||
},
|
||||
})
|
||||
Loading…
Reference in a new issue