import { ref, watch } from 'vue'
import {
faAlignCenter,
faAlignJustify,
faAlignLeft,
faAlignRight,
faArrowLeft,
faArrowRight, faBold,
faCodeBranch, faEarth,
faHeart,
faPause, faSearch,
faShoppingCart,
faSignOut, faStrikethrough,
faUnderline, faUser,
} from '@fortawesome/free-solid-svg-icons'
import { action } from '@storybook/addon-actions'
import type { Meta, StoryObj } from '@storybook/vue3'
import Button from 'src/components/button/Button.vue'
import Icon from 'src/components/icon/Icon.vue'
import Input from 'src/components/input/Input.vue'
import omit from 'src/utils/omit'
const meta = {
component: Input,
parameters: {
actions: {
argTypesRegex: `^(${(Input.emits as string[])?.join('|')})$`,
},
},
argTypes: {
'append': {
table: {
category: 'slots',
type: { summary: 'VNode' },
},
},
'prepend': {
table: {
category: 'slots',
type: { summary: 'VNode' },
},
},
'modelValue': {
description: 'value',
control: 'text',
table: {
category: 'props',
type: { summary: 'string' },
},
},
'maxLength': {
description: 'max length',
control: 'number',
table: {
category: 'props',
type: { summary: 'number' },
},
},
'placeholder': {
control: 'text',
description: 'Placeholder',
table: {
category: 'props',
type: { summary: 'text' },
},
},
'size': {
description: 'The size of button
Also you can use `mini` `small` `large` `massive` prop directly',
control: { type: 'inline-radio' },
options: ['mini', 'small', 'middle', 'large', 'massive'],
table: {
category: 'props',
type: { summary: 'enum' },
defaultValue: { summary: 'middle' },
},
},
'focus': {
control: 'boolean',
table: {
category: 'props',
defaultValue: { summary: 'false' },
},
},
'disabled': {
control: 'boolean',
table: {
category: 'props',
defaultValue: { summary: 'false' },
},
},
'loading': {
control: 'boolean',
table: {
category: 'props',
defaultValue: { summary: 'false' },
},
},
'error': {
control: 'boolean',
table: {
category: 'props',
defaultValue: { summary: 'false' },
},
},
'fluid': {
control: 'boolean',
table: {
category: 'props',
defaultValue: { summary: 'false' },
},
},
'update:modelValue': {
action: 'update:modelValue',
table: {
category: 'events',
},
},
},
args: {
'modelValue': 'Hello',
'update:modelValue': null,
},
render: (args: Record, { argTypes }) => {
const attrs: Record = {}
const props: Record = {}
const slots: Record = {}
const events: Record = {}
for (const [k, argType] of Object.entries(argTypes) as any) {
const v = args[k]
if (k in Input.props) props[k] = v
else if (argType.table?.category === 'slots') slots[k] = argType
else if (argType.table?.category === 'events' && v) events[k] = v
else if (v) attrs[k] = v
}
const { default: defaultSlot, ...otherSlots } = slots
return {
components: { Input },
props: Object.keys(argTypes),
setup (props) { return { action, args } },
template: ` args[prop] ? `:${prop}="args.${prop}"` : '').join('\n')}
${Object.keys(attrs).map(attr => args[attr] ? `:${attr}="args.${attr}"` : '').join('\n')}
${Object.keys(events).map(event => `@${event}="action('${event}')"`).join('\n')}
>
${defaultSlot ? '{{args.default}}' : ''}
${Object.entries(otherSlots).map(([nameWithSlot, argTypes]) =>
`{{args.${nameWithSlot}}}`).join('\n')}
`,
}
},
} satisfies Meta
export default meta
type Story = StoryObj
export const Basic: Story = {
args: {},
}
export const Controlled: Story = {
render: (args) => {
return {
components: { Input },
setup () {
const inputValue = ref('Hello')
return { inputValue }
},
template: `
Value: {{inputValue}}
`,
}
},
}
export const Focus: Story = {
render: () => {
return {
components: { Input, Button },
setup () {
const inputRef = ref()
function handleFocus () {
inputRef.value?.focus()
}
return { inputRef, handleFocus }
},
template: `
`,
}
},
}
/**
* Input components can have different appearances to remind the user of the current state of the input box
*/
export const Status: Story = {
render: args => ({
components: { Input },
template: `
`,
}),
}
/**
* TypedInputs allows touchscreen devices to have a better interactive experience
*/
export const TypedInputs: Story = {
render: (args) => {
return {
components: { Input },
template: `
`,
}
},
}
export const WithIcon: Story = {
render: (args) => {
return {
components: { Input },
setup: () => ({ faUser, faSearch }),
template: `
`,
}
},
}
export const PrependAppend: Story = {
name: 'Prepend / Append Slots',
render: (args) => {
return {
components: { Input, Icon },
setup: () => ({ faEarth }),
template: `
https://
`,
}
},
}
export const Fluid: Story = {
render: args => ({
components: { Input },
template: `
`,
}),
}