diff --git a/.github/ISSUE_TEMPLATE/bug-template.md b/.github/ISSUE_TEMPLATE/bug-template.md index 4c19a2490e..8338f8f54f 100644 --- a/.github/ISSUE_TEMPLATE/bug-template.md +++ b/.github/ISSUE_TEMPLATE/bug-template.md @@ -6,7 +6,7 @@ assignees: '' --- -**Vuestic-ui version:** 1.8.0 +**Vuestic-ui version:** 1.8.3 **Steps to reproduce** diff --git a/packages/ui/.storybook/assets/fonts.scss b/packages/ui/.storybook/assets/fonts.scss index 83e6df8f1b..1d0073bc5f 100644 --- a/packages/ui/.storybook/assets/fonts.scss +++ b/packages/ui/.storybook/assets/fonts.scss @@ -1,6 +1,7 @@ // Fonts // @import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,700); @import url(https://fonts.googleapis.com/icon?family=Material+Icons); +@import url(https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined); body { margin: 0; diff --git a/packages/ui/.storybook/assets/icons/icons.scss b/packages/ui/.storybook/assets/icons/icons.scss index 0f17ff1ef4..c95fd28d7c 100644 --- a/packages/ui/.storybook/assets/icons/icons.scss +++ b/packages/ui/.storybook/assets/icons/icons.scss @@ -14,3 +14,4 @@ $fa-font-path: "@fortawesome/fontawesome-free/webfonts"; // material icons @import url(https://fonts.googleapis.com/icon?family=Material+Icons); @import url(https://fonts.googleapis.com/icon?family=Material+Icons+Outlined); +@import url(https://fonts.googleapis.com/icon?family=Material+Sym+Outlined); diff --git a/packages/ui/.storybook/vuestic-config/demo-icon-fonts.ts b/packages/ui/.storybook/vuestic-config/demo-icon-fonts.ts index a7640738c3..d61280543c 100644 --- a/packages/ui/.storybook/vuestic-config/demo-icon-fonts.ts +++ b/packages/ui/.storybook/vuestic-config/demo-icon-fonts.ts @@ -29,6 +29,10 @@ const fontsConfig: IconConfig = [ name: 'entypo-{code}', resolve: ({ code }) => ({ class: `entypo-${code}` }), }, + { + name: 'mso-{name}', + resolve: ({ name }) => ({ content: name, class: 'material-symbols-outlined' }), + }, { name: 'text', }, diff --git a/packages/ui/build/common-config.ts b/packages/ui/build/common-config.ts index c9eb8a7c95..5712cd2812 100644 --- a/packages/ui/build/common-config.ts +++ b/packages/ui/build/common-config.ts @@ -35,6 +35,12 @@ export const resolve = { }, } +const rollupOutputOptions = (ext: string): RollupOptions['output'] => ({ + entryFileNames: `[name].${ext}`, + chunkFileNames: `[name].${ext}`, + assetFileNames: '[name].[ext]', +}) + const rollupMjsBuildOptions: RollupOptions = { input: resolver(process.cwd(), 'src/main.ts'), @@ -42,9 +48,7 @@ const rollupMjsBuildOptions: RollupOptions = { sourcemap: true, dir: 'dist/esm-node', format: 'esm', - entryFileNames: '[name].mjs', - chunkFileNames: '[name].mjs', - assetFileNames: '[name].[ext]', + ...rollupOutputOptions('mjs'), }, } @@ -76,17 +80,7 @@ export default function createViteConfig (format: BuildFormat) { // target: 'esnext', // default esbuild, not available for esm format in lib mode - minify: 'terser', - - terserOptions: { - // https://stackoverflow.com/questions/57720816/rails-webpacker-terser-keep-fnames - - // disable mangling class names (for vue class component) - keep_classnames: true, - - // disable mangling functions names - keep_fnames: true, - }, + minify: isEsm ? false : 'esbuild', lib: libBuildOptions(isNode ? 'es' : format), }, @@ -105,7 +99,14 @@ export default function createViteConfig (format: BuildFormat) { isEsm && config.plugins.push(removeSideEffectedChunks()) isEsm && config.plugins.push(componentVBindFix()) - config.build.rollupOptions = isNode ? { ...external, ...rollupMjsBuildOptions } : external + if (isNode) { + config.build.rollupOptions = { ...external, ...rollupMjsBuildOptions } + } else { + config.build.rollupOptions = { + ...external, + output: rollupOutputOptions('js'), + } + } return config } diff --git a/packages/ui/build/plugins/append-component-css.ts b/packages/ui/build/plugins/append-component-css.ts index 94a4c01ba1..6858a38cda 100644 --- a/packages/ui/build/plugins/append-component-css.ts +++ b/packages/ui/build/plugins/append-component-css.ts @@ -13,16 +13,38 @@ const parsePath = (path: string) => { } /** - * Checks if file is Vuestic component script source - * Component always have script which is stored in file with name like Va[ComponentName].vue_vue_type_script_lang + * Checks if file is Vuestic component template source + * If file is script source, but there is not template then add css to script. + * Component usually have script which is stored in file with name like Va[ComponentName].vue_vue_type_script_lang + * + * @notice Component can have render function without template block. It also can have only template without script block. */ const isVuesticComponent = (filename: string) => { - // Va[ComponentName]-[hash].mjs - return /Va\w*-\w*\.mjs$/.test(filename) + // Va[ComponentName].vue_vue_type_script_lang.mjs + // Va[ComponentName].vue_vue_type_script_setup_true_lang.mjs + const isScriptFile = /Va\w*.vue_vue_type_script\w*_lang.m?js$/.test(filename) + if (isScriptFile) { + return true + } + + // Va[ComponentName].mjs + const isTemplateFile = /Va\w*\.m?js$/.test(filename) + + // Va[ComponentName].vue_vue_type_script_lang.mjs + const scriptFilePath = filename.replace('.mjs', '.vue_vue_type_script_lang.mjs') + const scriptSetupFilePath = filename.replace('.mjs', '.vue_vue_type_script_setup_true_lang.mjs') + + const haveScript = existsSync(scriptFilePath) || existsSync(scriptSetupFilePath) + + if (isTemplateFile && !haveScript) { + return true + } + + return false } const extractVuesticComponentName = (filename: string) => { - return filename.match(/(Va\w*)-\w*/)?.[1] + return filename.match(/(Va\w*)/)?.[1] } const SOURCE_MAP_COMMENT_FRAGMENT = '//# sourceMappingURL=' diff --git a/packages/ui/package.json b/packages/ui/package.json index 025d549e1c..1b2fae372a 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "vuestic-ui", - "version": "1.8.0", + "version": "1.8.3", "description": "Vue 3 UI Framework", "license": "MIT", "homepage": "https://vuestic.dev", diff --git a/packages/ui/src/components/va-alert/useAlertStyles.ts b/packages/ui/src/components/va-alert/useAlertStyles.ts index a7065b70a5..125357100a 100644 --- a/packages/ui/src/components/va-alert/useAlertStyles.ts +++ b/packages/ui/src/components/va-alert/useAlertStyles.ts @@ -51,7 +51,7 @@ export const useAlertStyles = (props: AlertStyleProps) => { const contentStyle = computed(() => { return { alignItems: props.center ? 'center' : '', - color: (props.border || props.outline) ? currentColor : textColorComputed.value, + color: (props.border || props.outline) ? currentColor.value : textColorComputed.value, } }) diff --git a/packages/ui/src/components/va-breadcrumbs/VaBreadcrumbs.demo.vue b/packages/ui/src/components/va-breadcrumbs/VaBreadcrumbs.demo.vue deleted file mode 100644 index ed7ec51a00..0000000000 --- a/packages/ui/src/components/va-breadcrumbs/VaBreadcrumbs.demo.vue +++ /dev/null @@ -1,194 +0,0 @@ - - - diff --git a/packages/ui/src/components/va-breadcrumbs/VaBreadcrumbs.stories.ts b/packages/ui/src/components/va-breadcrumbs/VaBreadcrumbs.stories.ts index fc9cc73b2c..f725b31882 100644 --- a/packages/ui/src/components/va-breadcrumbs/VaBreadcrumbs.stories.ts +++ b/packages/ui/src/components/va-breadcrumbs/VaBreadcrumbs.stories.ts @@ -1,12 +1,152 @@ -import { defineComponent } from 'vue' -import VaBreadcrumbs from './VaBreadcrumbs.demo.vue' +import { VaBreadcrumbs, VaBreadcrumbsItem } from './' +import { addText } from '../../../.storybook/interaction-utils/addText' export default { title: 'VaBreadcrumbs', component: VaBreadcrumbs, + tags: ['autodocs'], } -export const Default = defineComponent({ - components: { VaBreadcrumbs }, - template: '', +export const Default = () => ({ + components: { VaBreadcrumbs, VaBreadcrumbsItem }, + template: ` + + + + + + `, +}) + +export const Disabled = () => ({ + components: { VaBreadcrumbs, VaBreadcrumbsItem }, + template: ` + [false] + + + + + [true] + + + + + `, +}) + +export const Color = () => ({ + components: { VaBreadcrumbs, VaBreadcrumbsItem }, + template: ` + + + + + + `, +}) +addText( + Color, + 'Active item doesn\'t have a way to color it, only categories do', + 'broken', +) + +export const ActiveColor = () => ({ + components: { VaBreadcrumbs, VaBreadcrumbsItem }, + template: ` + + + + + + `, +}) + +export const Separator = () => ({ + components: { VaBreadcrumbs, VaBreadcrumbsItem }, + template: ` + + + + + + `, +}) + +export const SeparatorSlot = () => ({ + components: { VaBreadcrumbs, VaBreadcrumbsItem }, + template: ` + + + + + + + `, +}) + +export const SeparatorColor = () => ({ + components: { VaBreadcrumbs, VaBreadcrumbsItem }, + template: ` + + + + + + `, +}) + +export const Align = () => ({ + components: { VaBreadcrumbs, VaBreadcrumbsItem }, + template: ` +
+ [left] + + + + + + [center] + + + + + + [right] + + + + + + [between] + + + + + + [around] + + + + + + [stretch] + + + + + +
+ `, }) diff --git a/packages/ui/src/components/va-checkbox/VaCheckbox-validation.vue b/packages/ui/src/components/va-checkbox/VaCheckbox-validation.vue deleted file mode 100644 index c14604f9f8..0000000000 --- a/packages/ui/src/components/va-checkbox/VaCheckbox-validation.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/packages/ui/src/components/va-checkbox/VaCheckbox.demo.vue b/packages/ui/src/components/va-checkbox/VaCheckbox.demo.vue deleted file mode 100644 index f9d058068e..0000000000 --- a/packages/ui/src/components/va-checkbox/VaCheckbox.demo.vue +++ /dev/null @@ -1,230 +0,0 @@ - - - - - diff --git a/packages/ui/src/components/va-checkbox/VaCheckbox.stories.ts b/packages/ui/src/components/va-checkbox/VaCheckbox.stories.ts index c8858bc466..9675c5914f 100644 --- a/packages/ui/src/components/va-checkbox/VaCheckbox.stories.ts +++ b/packages/ui/src/components/va-checkbox/VaCheckbox.stories.ts @@ -1,12 +1,261 @@ -import { defineComponent } from 'vue' -import VaCheckbox from './VaCheckbox.demo.vue' +import { VaCheckbox } from './' +import { VaButton } from '../va-button' export default { title: 'VaCheckbox', component: VaCheckbox, + tags: ['autodocs'], } -export const Default = defineComponent({ +export const Default = () => ({ components: { VaCheckbox }, - template: '', + data: () => ({ value: true }), + template: ` + + `, +}) + +export const Stateful = () => ({ + components: { VaCheckbox }, + template: ` + [true] + + [false] + + `, +}) + +export const Color = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const Label = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const LeftLabel = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const CheckedIcon = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const Indeterminate = () => ({ + components: { VaCheckbox }, + data: () => ({ value: false }), + template: ` + + `, +}) + +export const IndeterminateIcon = () => ({ + components: { VaCheckbox }, + data: () => ({ value: false }), + template: ` + + `, +}) + +export const Disabled = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const Readonly = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const Messages = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const Error = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const ErrorMessages = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const ErrorCount = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const Rules = () => ({ + components: { VaCheckbox }, + data: () => ({ value: false }), + template: ` + + `, +}) + +export const ImmediateValidation = () => ({ + components: { VaCheckbox }, + data: () => ({ value: false }), + template: ` + + `, +}) + +export const Success = () => ({ + components: { VaCheckbox }, + data: () => ({ value: true }), + template: ` + + `, +}) + +export const ArrayValue = () => ({ + components: { VaCheckbox }, + data: () => ({ value: ['One', 'Two'] }), + template: ` + + + + {{ value }} + `, +}) + +export const TrueValue = () => ({ + components: { VaCheckbox }, + data: () => ({ value: 'One' }), + template: ` + + {{ value }} + `, +}) + +export const FalseValue = () => ({ + components: { VaCheckbox }, + data: () => ({ value: 'One' }), + template: ` + + {{ value }} + `, +}) + +export const IndeterminateValue = () => ({ + components: { VaCheckbox }, + data: () => ({ value: 'One' }), + template: ` + + {{ value }} + `, }) diff --git a/packages/ui/src/components/va-checkbox/VaCheckbox.vue b/packages/ui/src/components/va-checkbox/VaCheckbox.vue index 99ca8d887e..e3d87d7cc9 100644 --- a/packages/ui/src/components/va-checkbox/VaCheckbox.vue +++ b/packages/ui/src/components/va-checkbox/VaCheckbox.vue @@ -89,6 +89,7 @@ export default defineComponent({ name: { type: String, default: '' }, ariaLabel: { type: String, default: undefined }, }, + setup (props, { emit }) { const elements: Elements = { container: shallowRef(), @@ -124,7 +125,7 @@ export default defineComponent({ const labelStyle = computed(() => { return { - color: computedError.value ? getColor('danger') : '', + color: computedError.value ? getColor('danger') : (props.success ? getColor('success') : ''), padding: !props.label ? '' : props.leftLabel @@ -143,6 +144,10 @@ export default defineComponent({ style.borderColor = getColor('danger') } + if (props.success) { + style.borderColor = getColor('success') + } + return style }) diff --git a/packages/ui/src/components/va-collapse/VaCollapse.stories.ts b/packages/ui/src/components/va-collapse/VaCollapse.stories.ts index 9e8a1c3031..7e1a9adfa2 100644 --- a/packages/ui/src/components/va-collapse/VaCollapse.stories.ts +++ b/packages/ui/src/components/va-collapse/VaCollapse.stories.ts @@ -1,12 +1,36 @@ +import { StoryFn } from '@storybook/vue3' import { defineComponent } from 'vue' -import VaCollapse from './VaCollapse.demo.vue' +import VaCollapseDemo from './VaCollapse.demo.vue' +import { VaCollapse } from './index' +import { userEvent } from '@storybook/testing-library' +import { expect } from '@storybook/jest' export default { title: 'VaCollapse', component: VaCollapse, + tags: ['autodocs'], } -export const Default = defineComponent({ +export const OldDemos = () => defineComponent({ + components: { VaCollapseDemo }, + template: '', +}) + +export const Overflow: StoryFn = () => defineComponent({ components: { VaCollapse }, - template: '', + + data: () => ({ open: true }), // Open be default + + template: ` + + + + + `, }) diff --git a/packages/ui/src/components/va-collapse/VaCollapse.vue b/packages/ui/src/components/va-collapse/VaCollapse.vue index 072241842f..e76b08e8ff 100644 --- a/packages/ui/src/components/va-collapse/VaCollapse.vue +++ b/packages/ui/src/components/va-collapse/VaCollapse.vue @@ -57,6 +57,7 @@ 'va-collapse__body-wrapper--bordered': !$slots.body && !$slots.header, }" :style="contentStyle" + @transitionend="onTransitionEnd" >
diff --git a/packages/ui/src/components/va-time-input/_variables.scss b/packages/ui/src/components/va-time-input/_variables.scss deleted file mode 100644 index 81bdbe6e80..0000000000 --- a/packages/ui/src/components/va-time-input/_variables.scss +++ /dev/null @@ -1,4 +0,0 @@ -:root, -:host { - --va-time-input-min-width: var(--va-form-element-min-width); -} diff --git a/packages/ui/src/components/va-tree-view/VaTreeView.demo.vue b/packages/ui/src/components/va-tree-view/VaTreeView.demo.vue deleted file mode 100644 index b3e5b4dce6..0000000000 --- a/packages/ui/src/components/va-tree-view/VaTreeView.demo.vue +++ /dev/null @@ -1,425 +0,0 @@ - - - - - diff --git a/packages/ui/src/components/va-tree-view/VaTreeView.stories.ts b/packages/ui/src/components/va-tree-view/VaTreeView.stories.ts index b48ed4d210..ec322ba254 100644 --- a/packages/ui/src/components/va-tree-view/VaTreeView.stories.ts +++ b/packages/ui/src/components/va-tree-view/VaTreeView.stories.ts @@ -1,12 +1,558 @@ -import { defineComponent } from 'vue' -import VaTreeView from './VaTreeView.demo.vue' +import { VaTreeView } from '.' +import { VaRadio } from '../va-radio' +import { VaColorPalette } from '../va-color-palette' +import { VaInput } from '../va-input' +import { VaCheckbox } from '../va-checkbox' export default { title: 'VaTreeView', component: VaTreeView, + tags: ['autodocs'], } -export const Default = defineComponent({ +const nodes = () => [ + { + id: 1, + label: 'Category', + children: [ + { id: 2, label: 'Item' }, + { + id: 3, + label: 'Subcategory', + children: [ + { id: 4, label: 'Item' }, + { id: 5, label: 'Item' }, + ], + }, + { id: 6, label: 'Item' }, + ], + }, + { id: 7, label: 'Item' }, +] + +export const Default = () => ({ + components: { VaTreeView }, + data: () => ({ + nodes: nodes(), + }), + template: ` + + `, +}) + +export const Stateless = () => ({ + components: { VaTreeView }, + data: () => ({ + stateChecked: [], + stateExpanded: [], + nodes: nodes(), + }), + template: ` +

+ expansion/selection should work: +
+ checked model: {{stateChecked}} +
+ expanded model: {{stateExpanded}} +

+ +

+ expansion/selection shouldn't work: +

+ + `, +}) + +export const Selectable = () => ({ + components: { VaTreeView, VaRadio }, + data: () => ({ + selectionTypeOptions: ['leaf', 'independent'], + selectionType: 'leaf', + selectedNodes: [], + nodes: nodes(), + }), + template: ` +

Selection strategy

+ + + `, +}) + +const COLORS_PALETTE = [ + '#4ae387', + '#e34a4a', + '#4ab2e3', + '#db76df', + '#f7cc36', + '#f3f3f3', + '#000', +] + +const nodesChecked = () => [ + { + id: 1, + label: 'Category', + checked: true, + children: [ + { + id: 2, + label: 'Subcategory', + checked: true, + children: [ + { id: 3, label: 'Item', checked: true }, + ], + }, + ], + }, + { id: 4, label: 'Item', checked: true }, +] + +export const ColoredCheckboxes = () => ({ + components: { VaTreeView, VaColorPalette }, + data: () => ({ + colorsPalette: COLORS_PALETTE, + selectedColor: COLORS_PALETTE[0], + nodesChecked: nodesChecked(), + }), + template: ` + + + `, +}) + +export const SelectionModel = () => ({ + components: { VaTreeView, VaRadio }, + data: () => ({ + selectionTypeOptions: ['leaf', 'independent'], + selectionType: 'leaf', + selectedNodes: [], + nodes: nodes(), + }), + template: ` +

Selection strategy

+ +

+ Single selection model for two tree views: +
+ {{ selectedNodes }} +

+ + + `, +}) + +export const ValueBy = () => ({ + components: { VaTreeView }, + data: () => ({ + selectedNodesValueBy: [], + nodes: nodes(), + }), + template: ` +

{{ selectedNodesValueBy }}

+
+ + `, +}) + +const nodesChildrenBy = () => [ + { + id: 1, + label: 'Category', + items: [ + { id: 2, label: 'Item' }, + { + id: 3, + label: 'Subcategory', + items: [ + { id: 4, label: 'Item' }, + { id: 5, label: 'Item' }, + ], + }, + { id: 6, label: 'Item' }, + ], + }, + { id: 7, label: 'Item' }, +] + +export const ChildrenBy = () => ({ + components: { VaTreeView }, + data: () => ({ + nodesChildrenBy: nodesChildrenBy(), + }), + template: ` + + `, +}) + +const nodesTextBy = () => [ + { + id: 1, + title: 'Category', + children: [ + { + id: 2, + title: 'Subcategory', + children: [ + { + id: 3, + title: 'Item', + }, + ], + }, + ], + }, + { id: 4, title: 'Item' }, +] + +export const TextBy = () => ({ + components: { VaTreeView }, + data: () => ({ + nodesTextBy: nodesTextBy(), + }), + template: ` + + `, +}) + +const nodesTrackBy = () => [ + { + trackId: 1, + label: 'Category', + children: [ + { + trackId: 2, + label: 'Subcategory', + children: [ + { + trackId: 3, + label: 'Item', + }, + ], + }, + ], + }, + { trackId: 4, label: 'Item' }, +] + +export const TrackBy = () => ({ + components: { VaTreeView }, + data: () => ({ + nodesTrackBy: nodesTrackBy(), + }), + template: ` + + `, +}) + +const nodesIconBy = [ + { + id: 1, + label: 'Category', + image: 'mail', + children: [ + { + id: 2, + label: 'Subcategory', + image: 'mail', + children: [ + { id: 3, label: 'Item' }, + ], + }, + ], + }, + { id: 4, image: 'mail', label: 'Item' }, +] + +export const IconBy = () => ({ + components: { VaTreeView }, + data: () => ({ + nodesIconBy, + }), + template: ` + + `, +}) + +const nodesDisabledBy = () => [ + { + id: 1, + label: 'Category', + children: [ + { id: 2, label: 'Item' }, + { + id: 3, + label: 'Subcategory', + inactive: true, + children: [ + { id: 4, label: 'Item' }, + ], + }, + { id: 5, label: 'Item' }, + ], + }, + { id: 6, label: 'Item' }, +] + +export const DisabledBy = () => ({ + components: { VaTreeView }, + data: () => ({ + nodesDisabledBy: nodesDisabledBy(), + }), + template: ` + + `, +}) + +const nodesExpandedBy = () => [ + { + id: 1, + label: 'Category', + shouldExpand: true, + children: [ + { id: 2, label: 'Item' }, + { + id: 3, + label: 'Subcategory', + shouldExpand: false, + children: [ + { id: 4, label: 'Item' }, + ], + }, + { id: 5, label: 'Item' }, + ], + }, + { id: 6, shouldExpand: true, label: 'Item' }, +] + +export const ExpandedBy = () => ({ + components: { VaTreeView }, + data: () => ({ + nodesExpandedBy: nodesExpandedBy(), + }), + template: ` + + `, +}) + +export const Expandable = () => ({ + components: { VaTreeView }, + data: () => ({ + nodes: nodes(), + expandedNodes: [1], + }), + template: ` +

Expand all

+ +

Expanded v-model: {{ expandedNodes }}

+ + + `, +}) + +const filterableNodes = () => [ + { + id: 1, + label: 'One', + children: [ + { + id: 2, + label: 'Two', + children: [ + { id: 3, label: 'Three' }, + { id: 4, label: 'Four' }, + ], + }, + ], + }, + { id: 5, label: 'Five' }, +] + +export const Filter = () => ({ + components: { VaTreeView, VaInput, VaCheckbox }, + data: () => ({ + filterValue: '', + isFilterCaseSensitive: false, + filterableNodes: filterableNodes(), + }), + computed: { + customFilterMethod () { + return this.isFilterCaseSensitive + ? (node, filter, textBy) => node[textBy].includes(filter) + : undefined + }, + }, + template: ` + +
+ + + `, +}) + +const customBodyNodes = () => [ + { + id: 1, + label: 'Category', + description: 'It is absolutely optional', + expanded: true, + children: [ + { + id: 2, + label: 'Photo', + description: 'This item works so well with the other one.', + image: 'https://picsum.photos/id/450/100', + hasAction: true, + }, + { + id: 3, + label: 'Emoji', + description: 'This item corresponds the first item perfectly.', + image: 'https://picsum.photos/id/450/100', + hasAction: true, + }, + { + id: 4, + label: 'Password was updated', + description: 'This one as well.', + children: [ + { id: 5, label: 'Node' }, + { id: 6, label: 'It is node also' }, + ], + }, + ], + }, + { + id: 7, + label: 'Super category', + children: [ + { id: 8, label: 'Super node' }, + { id: 9, label: 'Common node' }, + ], + }, +] + +export const WithCustomBody = () => ({ + components: { VaTreeView }, + data: () => ({ + customBodyNodes: customBodyNodes(), + }), + template: ` + + + + `, +}) + +export const ExpandByNode = () => ({ components: { VaTreeView }, - template: '', + data: () => ({ + nodesChecked: nodesChecked(), + }), + template: ` +

Node description text is expandable on click

+ +

Node description text is not expandable on click

+ + `, }) diff --git a/packages/ui/src/components/va-tree-view/VaTreeViewKeyboardNavigation.demo.vue b/packages/ui/src/components/va-tree-view/VaTreeViewKeyboardNavigation.demo.vue deleted file mode 100644 index b0de14b05b..0000000000 --- a/packages/ui/src/components/va-tree-view/VaTreeViewKeyboardNavigation.demo.vue +++ /dev/null @@ -1,188 +0,0 @@ - - - diff --git a/packages/ui/src/components/va-tree-view/VaTreeViewKeyboardNavigation.stories.ts b/packages/ui/src/components/va-tree-view/VaTreeViewKeyboardNavigation.stories.ts index aabfe5f758..a70b0553be 100644 --- a/packages/ui/src/components/va-tree-view/VaTreeViewKeyboardNavigation.stories.ts +++ b/packages/ui/src/components/va-tree-view/VaTreeViewKeyboardNavigation.stories.ts @@ -1,12 +1,221 @@ -import { defineComponent } from 'vue' -import VaTreeViewKeyboardNavigation from './VaTreeViewKeyboardNavigation.demo.vue' +import { VaTreeView } from '.' export default { title: 'VaTreeViewKeyboardNavigation', - component: VaTreeViewKeyboardNavigation, + component: VaTreeView, + tags: ['autodocs'], } -export const Default = defineComponent({ - components: { VaTreeViewKeyboardNavigation }, - template: '', +const flat = () => [ + { + id: 1, + label: 'Item', + }, + { + id: 2, + label: 'Item', + }, + { + id: 3, + label: 'Item', + }, +] + +export const FlatLikeNavigation = () => ({ + components: { VaTreeView }, + data: () => ({ + flat: flat(), + }), + template: ` + + `, +}) + +const stairs = () => [ + { + id: 1, + label: 'Item', + children: [ + { + id: 2, + label: 'Item', + children: [ + { + id: 3, + label: 'Item', + children: [ + { + id: 4, + label: 'Item', + }, + ], + }, + ], + }, + ], + }, + { + id: 5, + label: 'Item', + children: [ + { + id: 6, + label: 'Item', + children: [ + { + id: 7, + label: 'Item', + children: [ + { + id: 8, + label: 'Item', + }, + ], + }, + ], + }, + ], + }, +] + +export const StairLikeNavigation = () => ({ + components: { VaTreeView }, + data: () => ({ + stairs: stairs(), + }), + template: ` + + `, +}) + +const triangle = () => [ + { + id: 1, + label: 'Item', + children: [ + { + id: 2, + label: 'Item', + children: [ + { + id: 3, + label: 'Item', + }, + { + id: 4, + label: 'Item', + }, + ], + }, + { + id: 5, + label: 'Item', + }, + ], + }, + { + id: 6, + label: 'Item', + }, +] + +export const TriangleLikeNavigation = () => ({ + components: { VaTreeView }, + data: () => ({ + triangle: triangle(), + }), + template: ` + + `, +}) + +const waves = () => [ + { + id: 1, + label: 'Item', + }, + { + id: 2, + label: 'Item', + children: [ + { + id: 3, + label: 'Item', + }, + ], + }, + { + id: 4, + label: 'Item', + children: [ + { + id: 5, + label: 'Item', + }, + ], + }, + { + id: 6, + label: 'Item', + children: [ + { + id: 6, + label: 'Item', + }, + ], + }, + { + id: 7, + label: 'Item', + }, +] + +export const WavesLikeNavigation = () => ({ + components: { VaTreeView }, + data: () => ({ + waves: waves(), + }), + template: ` + + `, +}) + +export const Selection = () => ({ + components: { VaTreeView }, + data: () => ({ + selectedNode: null, + triangle: triangle(), + }), + methods: { + onSelectNode (node) { + this.selectedNode = node ? `${node.id} ${node.label}` : null + }, + }, + template: ` +

Selected node: {{selectedNode}}

+
+ + `, +}) + +export const CheckboxsSelection = () => ({ + components: { VaTreeView }, + data: () => ({ + checkedNodes: [], + triangle: triangle(), + }), + template: ` +

Checked nodes: {{checkedNodes}}

+
+ + `, }) diff --git a/packages/ui/src/components/va-tree-view/hooks/useTreeView.ts b/packages/ui/src/components/va-tree-view/hooks/useTreeView.ts index 8201c58b8f..6f215ea28e 100644 --- a/packages/ui/src/components/va-tree-view/hooks/useTreeView.ts +++ b/packages/ui/src/components/va-tree-view/hooks/useTreeView.ts @@ -162,7 +162,7 @@ const useTreeView: UseTreeViewFunc = (props, emit) => { const getFilteredNodes = (nodes: TreeNode[]): TreeNode[] => nodes.filter((node) => { if (node.children) { node.children = getFilteredNodes(node.children) } - + if (node.children.length === 0) { node.hasChildren = false } return node.matchesFilter diff --git a/packages/ui/src/components/va-value/VaValue.demo.vue b/packages/ui/src/components/va-value/VaValue.demo.vue deleted file mode 100644 index ae2e9c829b..0000000000 --- a/packages/ui/src/components/va-value/VaValue.demo.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - diff --git a/packages/ui/src/components/va-value/VaValue.stories.ts b/packages/ui/src/components/va-value/VaValue.stories.ts index ed537daa09..278d1d6360 100644 --- a/packages/ui/src/components/va-value/VaValue.stories.ts +++ b/packages/ui/src/components/va-value/VaValue.stories.ts @@ -1,12 +1,50 @@ -import { defineComponent } from 'vue' -import VaValue from './VaValue.demo.vue' +import { VaValue } from '.' +import { VaInput } from '../va-input' +import { VaButton } from '../va-button' +import { within, userEvent } from '@storybook/testing-library' +import { expect } from '@storybook/jest' +import { sleep } from '../../utils/sleep' export default { title: 'VaValue', component: VaValue, + tags: ['autodocs'], } -export const Default = defineComponent({ - components: { VaValue }, - template: '', +export const Default = () => ({ + components: { VaValue, VaButton }, + template: ` + +

{{ v }}

+ + Change + +
+ `, +}) + +Default.play = async ({ canvasElement, step }) => { + const canvas = within(canvasElement) + const button = canvas.getByRole('button') + const value = canvas.getByTestId('value') + + await step('value is false by default', async () => { + expect(value.innerText).toEqual('false') + }) + + await step('and can be reassigned', async () => { + userEvent.click(button) + await sleep() + expect(value.innerText).toEqual('true') + }) +} + +export const DefaultValue = () => ({ + components: { VaValue, VaInput }, + template: ` + +

{{ v.value.name }}

+ +
+ `, }) diff --git a/packages/ui/src/composables/useBem.ts b/packages/ui/src/composables/useBem.ts index 6d946a6c40..31590ba392 100644 --- a/packages/ui/src/composables/useBem.ts +++ b/packages/ui/src/composables/useBem.ts @@ -7,7 +7,7 @@ import { isDev } from '../utils/env' type Key = `${Prefix}--${ModifierKey}` -type ClassesObject = Record +type ClassesObject = Record type ComputedClasses = ClassesObject & { // TODO: How to remove it from spread? @@ -32,7 +32,7 @@ type ComputedClasses = ClassesObject & { */ export const useBem = ( prefix: Prefix, - modifiers: Record | Ref> | (() => Record), + modifiers: Record | Ref> | (() => Record), ) => { if (isDev && !prefix) { console.warn('You must pass the @param "prefix" to the useBem hook!') diff --git a/packages/ui/src/services/color/types.ts b/packages/ui/src/services/color/types.ts index c64ca7a97d..66c577d2a5 100644 --- a/packages/ui/src/services/color/types.ts +++ b/packages/ui/src/services/color/types.ts @@ -31,7 +31,7 @@ type Capitalize = S extends `${infer First}${infer Rest}` type OnColors = `on${Capitalize}` export type ColorVariables = { [colorName: string]: CssColor } & EssentialVariables & { - [key in OnColors]: CssColor + [key in OnColors]?: CssColor } export type ColorConfig = { diff --git a/packages/vue-cli-plugin/generator/configs/default.js b/packages/vue-cli-plugin/generator/configs/default.js index 219c186af4..cd0859c157 100644 --- a/packages/vue-cli-plugin/generator/configs/default.js +++ b/packages/vue-cli-plugin/generator/configs/default.js @@ -7,7 +7,7 @@ module.exports = { ], extendPackage: { dependencies: { - 'vuestic-ui': '^1.8.0', + 'vuestic-ui': '^1.8.3', } }, vueUse: [ diff --git a/yarn.lock b/yarn.lock index ce031783f5..a296c39bf8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17831,9 +17831,9 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.21 source-map "^0.6.1" postcss@^8.1.10, postcss@^8.2.1, postcss@^8.2.15, postcss@^8.2.6, postcss@^8.3.5, postcss@^8.4.18, postcss@^8.4.19, postcss@^8.4.23: - version "8.4.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab" - integrity sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA== + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== dependencies: nanoid "^3.3.6" picocolors "^1.0.0"