vueless 1.3.6-beta.0 → 1.3.6-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/components.d.ts +2 -0
  2. package/components.ts +2 -0
  3. package/constants.d.ts +2 -0
  4. package/constants.js +2 -0
  5. package/index.d.ts +10 -1
  6. package/index.ts +10 -1
  7. package/package.json +2 -2
  8. package/types.ts +2 -0
  9. package/ui.button/UButton.vue +1 -1
  10. package/ui.button/storybook/stories.ts +2 -2
  11. package/ui.container-card/storybook/stories.ts +2 -2
  12. package/ui.container-drawer/UDrawer.vue +2 -2
  13. package/ui.container-drawer/storybook/stories.ts +2 -2
  14. package/ui.container-grid/UGrid.vue +39 -0
  15. package/ui.container-grid/config.ts +123 -0
  16. package/ui.container-grid/constants.ts +5 -0
  17. package/ui.container-grid/storybook/docs.mdx +17 -0
  18. package/ui.container-grid/storybook/stories.ts +246 -0
  19. package/ui.container-grid/tests/UGrid.test.ts +297 -0
  20. package/ui.container-grid/types.ts +91 -0
  21. package/ui.container-modal/storybook/stories.ts +2 -2
  22. package/ui.container-modal-confirm/storybook/stories.ts +2 -2
  23. package/ui.container-page/storybook/stories.ts +3 -3
  24. package/ui.form-calendar/tests/UCalendar.test.ts +113 -0
  25. package/ui.form-date-picker-range/UDatePickerRangeInputs.vue +5 -1
  26. package/ui.form-date-picker-range/tests/UDatePickerRange.test.ts +114 -0
  27. package/ui.form-date-picker-range/types.ts +1 -0
  28. package/ui.form-listbox/config.ts +1 -1
  29. package/ui.image-avatar/UAvatar.vue +55 -28
  30. package/ui.image-avatar/config.ts +18 -1
  31. package/ui.image-avatar/storybook/docs.mdx +16 -1
  32. package/ui.image-avatar/storybook/stories.ts +17 -3
  33. package/ui.image-avatar/tests/UAvatar.test.ts +35 -7
  34. package/ui.image-avatar/types.ts +13 -0
  35. package/ui.image-avatar-group/UAvatarGroup.vue +87 -0
  36. package/ui.image-avatar-group/config.ts +11 -0
  37. package/ui.image-avatar-group/constants.ts +5 -0
  38. package/ui.image-avatar-group/storybook/docs.mdx +16 -0
  39. package/ui.image-avatar-group/storybook/stories.ts +147 -0
  40. package/ui.image-avatar-group/tests/UAvatarGroup.test.ts +141 -0
  41. package/ui.image-avatar-group/types.ts +51 -0
  42. package/ui.navigation-pagination/storybook/stories.ts +2 -2
  43. package/ui.navigation-tab/tests/UTab.test.ts +2 -3
  44. package/ui.navigation-tabs/UTabs.vue +44 -1
  45. package/ui.navigation-tabs/storybook/stories.ts +33 -0
  46. package/ui.navigation-tabs/tests/UTabs.test.ts +88 -0
  47. package/ui.text-block/config.ts +1 -0
  48. package/ui.text-block/storybook/stories.ts +2 -2
  49. package/ui.text-notify/UNotify.vue +31 -8
  50. package/ui.text-notify/config.ts +1 -1
  51. package/ui.text-notify/tests/UNotify.test.ts +22 -7
package/components.d.ts CHANGED
@@ -41,6 +41,7 @@ export { default as UBadge } from "./ui.text-badge/UBadge.vue";
41
41
  export { default as UDivider } from "./ui.container-divider/UDivider.vue";
42
42
  export { default as UCol } from "./ui.container-col/UCol.vue";
43
43
  export { default as URow } from "./ui.container-row/URow.vue";
44
+ export { default as UGrid } from "./ui.container-grid/UGrid.vue";
44
45
  export { default as UGroup } from "./ui.container-group/UGroup.vue";
45
46
  export { default as UGroups } from "./ui.container-groups/UGroups.vue";
46
47
  export { default as UAccordion } from "./ui.container-accordion/UAccordion.vue";
@@ -55,6 +56,7 @@ export { default as UPage } from "./ui.container-page/UPage.vue";
55
56
  /* Images and Icons */
56
57
  export { default as UIcon } from "./ui.image-icon/UIcon.vue";
57
58
  export { default as UAvatar } from "./ui.image-avatar/UAvatar.vue";
59
+ export { default as UAvatarGroup } from "./ui.image-avatar-group/UAvatarGroup.vue";
58
60
  /* Data */
59
61
  export { default as UTable } from "./ui.data-table/UTable.vue";
60
62
  export { default as UDataList } from "./ui.data-list/UDataList.vue";
package/components.ts CHANGED
@@ -41,6 +41,7 @@ export { default as UBadge } from "./ui.text-badge/UBadge.vue";
41
41
  export { default as UDivider } from "./ui.container-divider/UDivider.vue";
42
42
  export { default as UCol } from "./ui.container-col/UCol.vue";
43
43
  export { default as URow } from "./ui.container-row/URow.vue";
44
+ export { default as UGrid } from "./ui.container-grid/UGrid.vue";
44
45
  export { default as UGroup } from "./ui.container-group/UGroup.vue";
45
46
  export { default as UGroups } from "./ui.container-groups/UGroups.vue";
46
47
  export { default as UAccordion } from "./ui.container-accordion/UAccordion.vue";
@@ -55,6 +56,7 @@ export { default as UPage } from "./ui.container-page/UPage.vue";
55
56
  /* Images and Icons */
56
57
  export { default as UIcon } from "./ui.image-icon/UIcon.vue";
57
58
  export { default as UAvatar } from "./ui.image-avatar/UAvatar.vue";
59
+ export { default as UAvatarGroup } from "./ui.image-avatar-group/UAvatarGroup.vue";
58
60
  /* Data */
59
61
  export { default as UTable } from "./ui.data-table/UTable.vue";
60
62
  export { default as UDataList } from "./ui.data-list/UDataList.vue";
package/constants.d.ts CHANGED
@@ -180,6 +180,7 @@ export namespace COMPONENTS {
180
180
  let UDivider: string;
181
181
  let UCol: string;
182
182
  let URow: string;
183
+ let UGrid: string;
183
184
  let UGroup: string;
184
185
  let UGroups: string;
185
186
  let UAccordion: string;
@@ -193,6 +194,7 @@ export namespace COMPONENTS {
193
194
  let UDrawer: string;
194
195
  let UIcon: string;
195
196
  let UAvatar: string;
197
+ let UAvatarGroup: string;
196
198
  let UTable: string;
197
199
  let UDataList: string;
198
200
  let UTab: string;
package/constants.js CHANGED
@@ -290,6 +290,7 @@ export const COMPONENTS = {
290
290
  UDivider: "ui.container-divider",
291
291
  UCol: "ui.container-col",
292
292
  URow: "ui.container-row",
293
+ UGrid: "ui.container-grid",
293
294
  UGroup: "ui.container-group",
294
295
  UGroups: "ui.container-groups",
295
296
  UAccordion: "ui.container-accordion",
@@ -305,6 +306,7 @@ export const COMPONENTS = {
305
306
  /* Images and Icons */
306
307
  UIcon: "ui.image-icon",
307
308
  UAvatar: "ui.image-avatar",
309
+ UAvatarGroup: "ui.image-avatar-group",
308
310
 
309
311
  /* Data */
310
312
  UTable: "ui.data-table",
package/index.d.ts CHANGED
@@ -15,9 +15,18 @@ export {
15
15
  createDebounce,
16
16
  hasSlotContent,
17
17
  } from "./utils/helper";
18
+ export {
19
+ cx,
20
+ cva,
21
+ compose,
22
+ setColor,
23
+ getDefaults,
24
+ vuelessConfig,
25
+ setVuelessConfig,
26
+ getMergedConfig as mergeConfigs,
27
+ } from "./utils/ui";
18
28
  export { addToRequestQueue, removeFromRequestQueue } from "./utils/requestQueue";
19
29
  export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform";
20
- export { cx, cva, compose, getDefaults, setVuelessConfig, setColor, vuelessConfig } from "./utils/ui";
21
30
  export { getTheme, setTheme, resetTheme, normalizeThemeConfig, cssVar, setRootCSSVariables } from "./utils/theme";
22
31
  export { getArgs, getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook";
23
32
  /* adapters */
package/index.ts CHANGED
@@ -21,9 +21,18 @@ export {
21
21
  createDebounce,
22
22
  hasSlotContent,
23
23
  } from "./utils/helper";
24
+ export {
25
+ cx,
26
+ cva,
27
+ compose,
28
+ setColor,
29
+ getDefaults,
30
+ vuelessConfig,
31
+ setVuelessConfig,
32
+ getMergedConfig as mergeConfigs,
33
+ } from "./utils/ui";
24
34
  export { addToRequestQueue, removeFromRequestQueue } from "./utils/requestQueue";
25
35
  export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform";
26
- export { cx, cva, compose, getDefaults, setVuelessConfig, setColor, vuelessConfig } from "./utils/ui";
27
36
  export { getTheme, setTheme, resetTheme, normalizeThemeConfig, cssVar, setRootCSSVariables } from "./utils/theme";
28
37
  export { getArgs, getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook";
29
38
  /* adapters */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "1.3.6-beta.0",
3
+ "version": "1.3.6-beta.10",
4
4
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
5
5
  "author": "Johnny Grid <hello@vueless.com> (https://vueless.com)",
6
6
  "homepage": "https://vueless.com",
@@ -57,7 +57,7 @@
57
57
  "@vue/eslint-config-typescript": "^14.6.0",
58
58
  "@vue/test-utils": "^2.4.6",
59
59
  "@vue/tsconfig": "^0.7.0",
60
- "@vueless/storybook": "^1.3.4",
60
+ "@vueless/storybook": "^1.3.14",
61
61
  "eslint": "^9.32.0",
62
62
  "eslint-plugin-storybook": "^10.0.2",
63
63
  "eslint-plugin-vue": "^10.3.0",
package/types.ts CHANGED
@@ -39,6 +39,7 @@ import UTabConfig from "./ui.navigation-tab/config";
39
39
  import UTabsConfig from "./ui.navigation-tabs/config";
40
40
  import UBreadcrumbsConfig from "./ui.navigation-breadcrumbs/config";
41
41
  import UAvatarConfig from "./ui.image-avatar/config";
42
+ import UAvatarGroupConfig from "./ui.image-avatar-group/config";
42
43
  import UIconConfig from "./ui.image-icon/config";
43
44
  import UCheckboxConfig from "./ui.form-checkbox/config";
44
45
  import UCheckboxGroupConfig from "./ui.form-checkbox-group/config";
@@ -306,6 +307,7 @@ export interface Components {
306
307
  UTabs: Partial<typeof UTabsConfig>;
307
308
  UBreadcrumbs: Partial<typeof UBreadcrumbsConfig>;
308
309
  UAvatar: Partial<typeof UAvatarConfig>;
310
+ UAvatarGroup: Partial<typeof UAvatarGroupConfig>;
309
311
  UIcon: Partial<typeof UIconConfig>;
310
312
  UCheckbox: Partial<typeof UCheckboxConfig>;
311
313
  UCheckboxGroup: Partial<typeof UCheckboxGroupConfig>;
@@ -62,7 +62,7 @@ defineExpose({
62
62
  * Applies: `class`, `config`, redefined default `props` and dev `vl-...` attributes.
63
63
  */
64
64
  const mutatedProps = computed(() => ({
65
- icon: Boolean(props.icon) || hasSlotContent(slots["default"]),
65
+ icon: Boolean(props.icon) || (!props.label && hasSlotContent(slots["default"])),
66
66
  leftIcon: Boolean(props.leftIcon) || hasSlotContent(slots["left"]),
67
67
  rightIcon: Boolean(props.rightIcon) || hasSlotContent(slots["right"]),
68
68
  label: Boolean(props.label),
@@ -79,8 +79,8 @@ const MultiEnumTemplate: StoryFn<UButtonArgs> = (args: UButtonArgs, { argTypes }
79
79
  export const Default = DefaultTemplate.bind({});
80
80
  Default.args = { label: "Button" };
81
81
 
82
- export const Variant = EnumTemplate.bind({});
83
- Variant.args = { enum: "variant", label: "{enumValue}" };
82
+ export const Variants = EnumTemplate.bind({});
83
+ Variants.args = { enum: "variant", label: "{enumValue}" };
84
84
 
85
85
  export const Round = EnumTemplate.bind({});
86
86
  Round.args = { enum: "variant", label: "{enumValue}", round: true };
@@ -125,8 +125,8 @@ Description.args = {
125
125
  description: "Customize your cookie settings to enhance your browsing experience.",
126
126
  };
127
127
 
128
- export const Variant = EnumTemplate.bind({});
129
- Variant.args = { enum: "variant", title: "{enumValue}" };
128
+ export const Variants = EnumTemplate.bind({});
129
+ Variants.args = { enum: "variant", title: "{enumValue}" };
130
130
 
131
131
  export const BeforeTitleSlot = DefaultTemplate.bind({});
132
132
  BeforeTitleSlot.args = {
@@ -197,8 +197,6 @@ function closeDrawer() {
197
197
  }
198
198
 
199
199
  function onDragStart(e: MouseEvent | TouchEvent) {
200
- e.preventDefault();
201
-
202
200
  const clientX = "touches" in e ? e.touches[0].clientX : e.clientX;
203
201
  const clientY = "touches" in e ? e.touches[0].clientY : e.clientY;
204
202
 
@@ -211,6 +209,8 @@ function onDragStart(e: MouseEvent | TouchEvent) {
211
209
 
212
210
  if (!props.handle || !isDraggingFromHandle.value) return;
213
211
 
212
+ e.preventDefault();
213
+
214
214
  document.addEventListener("mousemove", onDragMove);
215
215
  document.addEventListener("mouseup", onDragEnd);
216
216
  document.addEventListener("touchmove", onDragMove, { passive: false });
@@ -162,8 +162,8 @@ NoCloseOnCross.args = { closeOnCross: false };
162
162
  export const Position = EnumTemplate.bind({});
163
163
  Position.args = { enum: "position", modelValues: {} };
164
164
 
165
- export const Variant = EnumTemplate.bind({});
166
- Variant.args = { enum: "variant", modelValues: {} };
165
+ export const Variants = EnumTemplate.bind({});
166
+ Variants.args = { enum: "variant", modelValues: {} };
167
167
 
168
168
  export const BeforeTitleSlot = DefaultTemplate.bind({});
169
169
  BeforeTitleSlot.args = {
@@ -0,0 +1,39 @@
1
+ <script setup lang="ts">
2
+ import { useTemplateRef } from "vue";
3
+ import { useUI } from "../composables/useUI";
4
+ import { getDefaults } from "../utils/ui";
5
+
6
+ import { COMPONENT_NAME } from "./constants";
7
+ import defaultConfig from "./config";
8
+
9
+ import type { Props, Config } from "./types";
10
+
11
+ defineOptions({ inheritAttrs: false });
12
+
13
+ withDefaults(defineProps<Props>(), {
14
+ ...getDefaults<Props, Config>(defaultConfig, COMPONENT_NAME),
15
+ });
16
+
17
+ const wrapperRef = useTemplateRef<HTMLElement>("wrapper");
18
+
19
+ defineExpose({
20
+ /**
21
+ * A reference to the component's wrapper element for direct DOM manipulation.
22
+ * @property {HTMLElement}
23
+ */
24
+ wrapperRef,
25
+ });
26
+
27
+ /**
28
+ * Get element / nested component attributes for each config token ✨
29
+ * Applies: `class`, `config`, redefined default `props` and dev `vl-...` attributes.
30
+ */
31
+ const { getDataTest, wrapperAttrs } = useUI<Config>(defaultConfig);
32
+ </script>
33
+
34
+ <template>
35
+ <component :is="tag" ref="wrapper" v-bind="wrapperAttrs" :data-test="getDataTest()">
36
+ <!-- @slot Use it to add grid items. -->
37
+ <slot />
38
+ </component>
39
+ </template>
@@ -0,0 +1,123 @@
1
+ export default /*tw*/ {
2
+ wrapper: {
3
+ base: "grid",
4
+ variants: {
5
+ cols: {
6
+ "1": "grid-cols-1",
7
+ "2": "grid-cols-2",
8
+ "3": "grid-cols-3",
9
+ "4": "grid-cols-4",
10
+ "5": "grid-cols-5",
11
+ "6": "grid-cols-6",
12
+ "7": "grid-cols-7",
13
+ "8": "grid-cols-8",
14
+ "9": "grid-cols-9",
15
+ "10": "grid-cols-10",
16
+ "11": "grid-cols-11",
17
+ "12": "grid-cols-12",
18
+ },
19
+ rows: {
20
+ "1": "grid-rows-1",
21
+ "2": "grid-rows-2",
22
+ "3": "grid-rows-3",
23
+ "4": "grid-rows-4",
24
+ "5": "grid-rows-5",
25
+ "6": "grid-rows-6",
26
+ "7": "grid-rows-7",
27
+ "8": "grid-rows-8",
28
+ "9": "grid-rows-9",
29
+ "10": "grid-rows-10",
30
+ "11": "grid-rows-11",
31
+ "12": "grid-rows-12",
32
+ },
33
+ gap: {
34
+ none: "gap-0",
35
+ "2xs": "gap-1",
36
+ xs: "gap-2",
37
+ sm: "gap-3",
38
+ md: "gap-4",
39
+ lg: "gap-5",
40
+ xl: "gap-6",
41
+ "2xl": "gap-8",
42
+ },
43
+ rowGap: {
44
+ none: "gap-y-0",
45
+ "2xs": "gap-y-1",
46
+ xs: "gap-y-2",
47
+ sm: "gap-y-3",
48
+ md: "gap-y-4",
49
+ lg: "gap-y-5",
50
+ xl: "gap-y-6",
51
+ "2xl": "gap-y-8",
52
+ },
53
+ colGap: {
54
+ none: "gap-x-0",
55
+ "2xs": "gap-x-1",
56
+ xs: "gap-x-2",
57
+ sm: "gap-x-3",
58
+ md: "gap-x-4",
59
+ lg: "gap-x-5",
60
+ xl: "gap-x-6",
61
+ "2xl": "gap-x-8",
62
+ },
63
+ align: {
64
+ start: "items-start",
65
+ end: "items-end",
66
+ center: "items-center",
67
+ stretch: "items-stretch",
68
+ baseline: "items-baseline",
69
+ normal: "items-normal",
70
+ },
71
+ content: {
72
+ start: "content-start",
73
+ end: "content-end",
74
+ center: "content-center",
75
+ around: "content-around",
76
+ evenly: "content-evenly",
77
+ between: "content-between",
78
+ normal: "content-normal",
79
+ stretch: "content-stretch",
80
+ baseline: "content-baseline",
81
+ },
82
+ justify: {
83
+ start: "justify-items-start",
84
+ end: "justify-items-end",
85
+ "end-safe": "justify-items-end-safe",
86
+ center: "justify-items-center",
87
+ "center-safe": "justify-items-center-safe",
88
+ stretch: "justify-items-stretch",
89
+ normal: "justify-items-normal",
90
+ },
91
+ placeContent: {
92
+ start: "place-content-start",
93
+ end: "place-content-end",
94
+ "end-safe": "place-content-end-safe",
95
+ center: "place-content-center",
96
+ "center-safe": "place-content-center-safe",
97
+ around: "place-content-around",
98
+ evenly: "place-content-evenly",
99
+ between: "place-content-between",
100
+ stretch: "place-content-stretch",
101
+ baseline: "place-content-baseline",
102
+ },
103
+ placeItems: {
104
+ start: "place-items-start",
105
+ end: "place-items-end",
106
+ "end-safe": "place-items-end-safe",
107
+ center: "place-items-center",
108
+ "center-safe": "place-items-center-safe",
109
+ stretch: "place-items-stretch",
110
+ baseline: "place-items-baseline",
111
+ },
112
+ },
113
+ },
114
+ defaults: {
115
+ gap: "md",
116
+ align: "normal",
117
+ content: "normal",
118
+ justify: "normal",
119
+ placeContent: "start",
120
+ placeItems: "start",
121
+ tag: "div",
122
+ },
123
+ };
@@ -0,0 +1,5 @@
1
+ /*
2
+ This const is needed to prevent the issue in script setup:
3
+ `defineProps` is referencing locally declared variables. (vue/valid-define-props)
4
+ */
5
+ export const COMPONENT_NAME = "UGrid";
@@ -0,0 +1,17 @@
1
+ import { Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/addon-docs/blocks";
2
+ import { getSource } from "../../utils/storybook";
3
+
4
+ import * as stories from "./stories";
5
+ import defaultConfig from "../config?raw"
6
+
7
+ <Meta of={stories} />
8
+ <Title of={stories} />
9
+ <Subtitle of={stories} />
10
+ <Description of={stories} />
11
+ <Primary of={stories} />
12
+ <Controls of={stories.Default} />
13
+ <Stories of={stories} />
14
+
15
+ ## Default config
16
+ <Source code={getSource(defaultConfig)} language="jsx" dark />
17
+
@@ -0,0 +1,246 @@
1
+ import {
2
+ getArgs,
3
+ getArgTypes,
4
+ getSlotNames,
5
+ getSlotsFragment,
6
+ getDocsDescription,
7
+ } from "../../utils/storybook";
8
+
9
+ import UGrid from "../UGrid.vue";
10
+ import UText from "../../ui.text-block/UText.vue";
11
+ import UPlaceholder from "../../ui.container-placeholder/UPlaceholder.vue";
12
+ import UCol from "../../ui.container-col/UCol.vue";
13
+
14
+ import type { Meta, StoryFn } from "@storybook/vue3-vite";
15
+ import type { Props } from "../types";
16
+
17
+ interface UGridArgs extends Props {
18
+ slotTemplate?: string;
19
+ enum:
20
+ | "gap"
21
+ | "rowGap"
22
+ | "colGap"
23
+ | "align"
24
+ | "content"
25
+ | "justify"
26
+ | "placeContent"
27
+ | "placeItems";
28
+ class?: string;
29
+ itemClass?: string;
30
+ }
31
+
32
+ export default {
33
+ id: "5025",
34
+ title: "Containers / Grid",
35
+ component: UGrid,
36
+ argTypes: {
37
+ ...getArgTypes(UGrid.__name),
38
+ },
39
+ parameters: {
40
+ docs: {
41
+ ...getDocsDescription(UGrid.__name),
42
+ },
43
+ },
44
+ } as Meta;
45
+
46
+ const defaultTemplate = `
47
+ <UPlaceholder label="1" class="min-h-10 col-span-1 row-span-3" />
48
+ <UPlaceholder label="2" class="min-h-10 col-span-3 row-span-1" />
49
+ <UPlaceholder label="3" class="min-h-10 col-span-3 row-span-2" />
50
+ `;
51
+
52
+ const DefaultTemplate: StoryFn<UGridArgs> = (args: UGridArgs) => ({
53
+ components: { UGrid, UPlaceholder },
54
+ setup: () => ({ args, slots: getSlotNames(UGrid.__name) }),
55
+ template: `
56
+ <UGrid v-bind="args">
57
+ ${args.slotTemplate || getSlotsFragment(defaultTemplate)}
58
+ </UGrid>
59
+ `,
60
+ });
61
+
62
+ const EnumTemplate: StoryFn<UGridArgs> = (args: UGridArgs, { argTypes }) => ({
63
+ components: { UGrid, UText, UPlaceholder, UCol },
64
+ setup: () => ({ args, argTypes, getArgs }),
65
+ template: `
66
+ <UCol block gap="lg">
67
+ <UGrid
68
+ v-for="option in argTypes?.[args.enum]?.options"
69
+ v-bind="getArgs(args, option)"
70
+ :key="option"
71
+ cols="3"
72
+ class="border border-primary border-dashed rounded p-4 w-full"
73
+ :class="args.class"
74
+ >
75
+ <UPlaceholder :label="option" class="h-auto" :class="args.itemClass" />
76
+ <UPlaceholder :label="option" class="h-auto" :class="args.itemClass" />
77
+ <UPlaceholder :label="option" class="h-auto" :class="args.itemClass" />
78
+ <UPlaceholder :label="option" class="h-auto" :class="args.itemClass" />
79
+ <UPlaceholder :label="option" class="h-auto" :class="args.itemClass" />
80
+ <UPlaceholder :label="option" class="h-auto" :class="args.itemClass" />
81
+ </UGrid>
82
+ </UCol>
83
+ `,
84
+ });
85
+
86
+ export const Default = DefaultTemplate.bind({});
87
+ Default.args = { cols: "4", rows: "3", gap: "md" };
88
+
89
+ export const Gap = EnumTemplate.bind({});
90
+ Gap.args = { enum: "gap" };
91
+ Gap.parameters = {
92
+ docs: {
93
+ description: {
94
+ story: "Gap between items.",
95
+ },
96
+ },
97
+ };
98
+
99
+ export const RowGap = EnumTemplate.bind({});
100
+ RowGap.args = { enum: "rowGap" };
101
+ RowGap.parameters = {
102
+ docs: {
103
+ description: {
104
+ story: "Vertical gap override.",
105
+ },
106
+ },
107
+ };
108
+
109
+ export const ColGap = EnumTemplate.bind({});
110
+ ColGap.args = { enum: "colGap" };
111
+ ColGap.parameters = {
112
+ docs: {
113
+ description: {
114
+ story: "Horizontal gap override.",
115
+ },
116
+ },
117
+ };
118
+
119
+ export const Justify = EnumTemplate.bind({});
120
+ Justify.args = { enum: "justify", itemClass: "w-auto min-w-20" };
121
+ Justify.parameters = {
122
+ docs: {
123
+ description: {
124
+ story: "Horizontal alignment (justify-items).",
125
+ },
126
+ },
127
+ };
128
+
129
+ export const Align = EnumTemplate.bind({});
130
+ Align.args = {
131
+ enum: "align",
132
+ class: "h-40 !content-normal",
133
+ };
134
+ Align.parameters = {
135
+ docs: {
136
+ description: {
137
+ story: "Vertical alignment (align-items).",
138
+ },
139
+ },
140
+ };
141
+
142
+ export const Content: StoryFn<UGridArgs> = (args: UGridArgs, { argTypes }) => ({
143
+ components: { UGrid, UText, UPlaceholder, UCol },
144
+ setup: () => ({ args, argTypes, getArgs }),
145
+ template: `
146
+ <UCol gap="lg" block>
147
+ <UGrid
148
+ v-for="option in argTypes?.[args.enum]?.options"
149
+ v-bind="getArgs(args, option)"
150
+ :key="option"
151
+ cols="3"
152
+ class="h-52 w-full border border-primary border-dashed rounded-medium p-4"
153
+ >
154
+ <UPlaceholder :label="option" />
155
+ <UPlaceholder :label="option" />
156
+ <UPlaceholder :label="option" />
157
+ <UPlaceholder :label="option" />
158
+ <UPlaceholder :label="option" />
159
+ </UGrid>
160
+ </UCol>
161
+ `,
162
+ });
163
+ Content.args = { enum: "content", gap: "md" };
164
+ Content.parameters = {
165
+ docs: {
166
+ description: {
167
+ story: "Items vertical align for multi-row grid containers (align-content).",
168
+ },
169
+ },
170
+ };
171
+
172
+ export const PlaceContent: StoryFn<UGridArgs> = (args: UGridArgs, { argTypes }) => ({
173
+ components: { UGrid, UText, UPlaceholder, UCol },
174
+ setup: () => {
175
+ function getItemClass(option: string) {
176
+ return option === "stretch" ? "w-auto" : "size-14";
177
+ }
178
+
179
+ function getGridClass(option: string) {
180
+ return option === "stretch" ? "grid-cols-2" : "grid-cols-[repeat(2,56px)]";
181
+ }
182
+
183
+ return { args, argTypes, getArgs, getItemClass, getGridClass };
184
+ },
185
+ template: `
186
+ <UCol block gap="lg">
187
+ <UGrid
188
+ v-for="option in argTypes?.[args.enum]?.options"
189
+ v-bind="getArgs(args, option)"
190
+ :key="option"
191
+ class="border border-primary border-dashed rounded p-4 w-full h-56"
192
+ :class="getGridClass(option)"
193
+ >
194
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
195
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
196
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
197
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
198
+ </UGrid>
199
+ </UCol>
200
+ `,
201
+ });
202
+ PlaceContent.args = { enum: "placeContent" };
203
+ PlaceContent.parameters = {
204
+ docs: {
205
+ description: {
206
+ story: "Control how content is justified and aligned within the grid (place-content).",
207
+ },
208
+ },
209
+ };
210
+
211
+ export const PlaceItems: StoryFn<UGridArgs> = (args: UGridArgs, { argTypes }) => ({
212
+ components: { UGrid, UText, UPlaceholder, UCol },
213
+ setup: () => {
214
+ function getItemClass(option: string) {
215
+ return option === "stretch" ? "w-auto" : "size-14";
216
+ }
217
+
218
+ return { args, argTypes, getArgs, getItemClass };
219
+ },
220
+ template: `
221
+ <UCol block gap="lg">
222
+ <UGrid
223
+ v-for="option in argTypes?.[args.enum]?.options"
224
+ v-bind="getArgs(args, option)"
225
+ :key="option"
226
+ cols="3"
227
+ class="border border-primary border-dashed rounded p-4 w-full h-56"
228
+ >
229
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
230
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
231
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
232
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
233
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
234
+ <UPlaceholder :label="option" :class="getItemClass(option)" />
235
+ </UGrid>
236
+ </UCol>
237
+ `,
238
+ });
239
+ PlaceItems.args = { enum: "placeItems" };
240
+ PlaceItems.parameters = {
241
+ docs: {
242
+ description: {
243
+ story: "Control how items are justified and aligned within the grid (place-items).",
244
+ },
245
+ },
246
+ };