@umodeapporg/ui 0.11.1 → 0.13.0

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 (36) hide show
  1. package/dist/components/Form/ControlledButton.d.ts +12 -0
  2. package/dist/components/Form/ControlledButton.js +10 -5
  3. package/dist/components/Form/ControlledButton.js.map +1 -1
  4. package/dist/components/Form/ControlledDialog.d.ts +9 -2
  5. package/dist/components/Form/ControlledDialog.js +14 -8
  6. package/dist/components/Form/ControlledDialog.js.map +1 -1
  7. package/dist/components/Form/ControlledDialogPrimitives.d.ts +23 -0
  8. package/dist/components/Form/ControlledDialogPrimitives.js +114 -5
  9. package/dist/components/Form/ControlledDialogPrimitives.js.map +1 -1
  10. package/dist/components/Form/ControlledSelect.d.ts +11 -2
  11. package/dist/components/Form/ControlledSelect.js +273 -48
  12. package/dist/components/Form/ControlledSelect.js.map +1 -1
  13. package/dist/components/Form/ControlledSwitch.d.ts +9 -2
  14. package/dist/components/Form/ControlledSwitch.js +88 -69
  15. package/dist/components/Form/ControlledSwitch.js.map +1 -1
  16. package/dist/components/Navigation/LinkButton.d.ts +26 -0
  17. package/dist/components/Navigation/LinkButton.js +82 -0
  18. package/dist/components/Navigation/LinkButton.js.map +1 -0
  19. package/dist/components/UI/ControlledMenu.d.ts +6 -0
  20. package/dist/components/UI/ControlledMenu.js +3 -4
  21. package/dist/components/UI/ControlledMenu.js.map +1 -1
  22. package/dist/components/UI/DataTable/DataTable.d.ts +9 -1
  23. package/dist/components/UI/DataTable/DataTable.js +7 -3
  24. package/dist/components/UI/DataTable/DataTable.js.map +1 -1
  25. package/dist/components/UI/DataTable/DataTableBulkEditRowsPicker.js +2 -1
  26. package/dist/components/UI/DataTable/DataTableBulkEditRowsPicker.js.map +1 -1
  27. package/dist/components/UI/DataTable/DataTableFilters.js +1 -0
  28. package/dist/components/UI/DataTable/DataTableFilters.js.map +1 -1
  29. package/dist/components/UI/DataTable/DataTableToolbar.js +2 -1
  30. package/dist/components/UI/DataTable/DataTableToolbar.js.map +1 -1
  31. package/dist/components/UI/DataTable/applyDataTableFilters.js +1 -0
  32. package/dist/components/UI/DataTable/applyDataTableFilters.js.map +1 -1
  33. package/dist/index.d.ts +2 -1
  34. package/dist/index.js +50 -47
  35. package/dist/index.js.map +1 -1
  36. package/package.json +9 -2
@@ -1 +1 @@
1
- {"version":3,"file":"applyDataTableFilters.js","sources":["../../../../src/components/UI/DataTable/applyDataTableFilters.ts"],"sourcesContent":["import { countActiveFilters, isFilterValueEmpty } from '@/components/Search/filters';\n\nimport type { IDataTableFiltersConfig, IDataTableRow, TDataTableFilterField, TDataTableFilterValues } from './types';\n\nconst isFieldActive = <T extends IDataTableRow>(\n field: TDataTableFilterField<T>,\n values: TDataTableFilterValues,\n): boolean => !isFilterValueEmpty(field, values?.[field.key]);\n\n/**\n * CLIENT-mode filtering driven by the table's filter config. Only active fields\n * that declare a `predicate` narrow the rows. Server-only fields (no\n * `predicate`) are ignored here. `combinator` decides whether a row must pass\n * every active field or at least one.\n */\nexport const applyDataTableFilters = <T extends IDataTableRow>(\n rows: Array<T>,\n filters: IDataTableFiltersConfig<T> | undefined,\n values: TDataTableFilterValues,\n): Array<T> => {\n if (!filters) return rows;\n\n const activeFields = (filters.fields ?? []).filter((field) => isFieldActive(field, values) && field.predicate);\n if (activeFields.length === 0) return rows;\n\n const matches = (row: T, field: TDataTableFilterField<T>) =>\n field.predicate ? field.predicate(row, values?.[field.key]) : true;\n\n if (filters.combinator === 'OR') {\n return (rows ?? []).filter((row) => activeFields.some((field) => matches(row, field)));\n }\n\n return (rows ?? []).filter((row) => activeFields.every((field) => matches(row, field)));\n};\n\n/**\n * SERVER-mode counterpart: collects the backend query params from every active\n * field that declares `toServerParams`. The host merges these into its fetch\n * instead of filtering in memory.\n */\nexport const buildDataTableFilterParams = <T extends IDataTableRow>(\n filters: IDataTableFiltersConfig<T> | undefined,\n values: TDataTableFilterValues,\n): Record<string, unknown> => {\n if (!filters) return {};\n\n return (filters.fields ?? []).reduce<Record<string, unknown>>((params, field) => {\n if (!isFieldActive(field, values) || !field.toServerParams) return params;\n\n return { ...params, ...field.toServerParams(values?.[field.key]) };\n }, {});\n};\n\n/** Number of active filter fields. Drives the filter button badge count. */\nexport const countActiveDataTableFilters = <T extends IDataTableRow>(\n filters: IDataTableFiltersConfig<T> | undefined,\n values: TDataTableFilterValues,\n): number => (filters ? countActiveFilters(filters.fields ?? [], values ?? {}) : 0);\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,gBAAgB,CACpB,OACA,WACY,CAAC,mBAAmB,OAAO,SAAS,MAAM,GAAG,CAAC;AAQrD,MAAM,wBAAwB,CACnC,MACA,SACA,WACa;AACb,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,gBAAgB,QAAQ,UAAU,CAAA,GAAI,OAAO,CAAC,UAAU,cAAc,OAAO,MAAM,KAAK,MAAM,SAAS;AAC7G,MAAI,aAAa,WAAW,EAAG,QAAO;AAEtC,QAAM,UAAU,CAAC,KAAQ,UACvB,MAAM,YAAY,MAAM,UAAU,KAAK,SAAS,MAAM,GAAG,CAAC,IAAI;AAEhE,MAAI,QAAQ,eAAe,MAAM;AAC/B,YAAQ,QAAQ,CAAA,GAAI,OAAO,CAAC,QAAQ,aAAa,KAAK,CAAC,UAAU,QAAQ,KAAK,KAAK,CAAC,CAAC;AAAA,EACvF;AAEA,UAAQ,QAAQ,CAAA,GAAI,OAAO,CAAC,QAAQ,aAAa,MAAM,CAAC,UAAU,QAAQ,KAAK,KAAK,CAAC,CAAC;AACxF;AAOO,MAAM,6BAA6B,CACxC,SACA,WAC4B;AAC5B,MAAI,CAAC,QAAS,QAAO,CAAA;AAErB,UAAQ,QAAQ,UAAU,CAAA,GAAI,OAAgC,CAAC,QAAQ,UAAU;AAC/E,QAAI,CAAC,cAAc,OAAO,MAAM,KAAK,CAAC,MAAM,eAAgB,QAAO;AAEnE,WAAO,EAAE,GAAG,QAAQ,GAAG,MAAM,eAAe,SAAS,MAAM,GAAG,CAAC,EAAA;AAAA,EACjE,GAAG,CAAA,CAAE;AACP;AAGO,MAAM,8BAA8B,CACzC,SACA,WACY,UAAU,mBAAmB,QAAQ,UAAU,CAAA,GAAI,UAAU,CAAA,CAAE,IAAI;"}
1
+ {"version":3,"file":"applyDataTableFilters.js","sources":["../../../../src/components/UI/DataTable/applyDataTableFilters.ts"],"sourcesContent":["import { countActiveFilters, isFilterValueEmpty } from '@/components/Search/filters';\n\nimport type { IDataTableFiltersConfig, IDataTableRow, TDataTableFilterField, TDataTableFilterValues } from './types';\n\nconst isFieldActive = <T extends IDataTableRow>(\n field: TDataTableFilterField<T>,\n values: TDataTableFilterValues,\n): boolean => !isFilterValueEmpty(field, values?.[field.key]);\n\n/**\n * CLIENT-mode filtering driven by the table's filter config. Only active fields\n * that declare a `predicate` narrow the rows. Server-only fields (no\n * `predicate`) are ignored here. `combinator` decides whether a row must pass\n * every active field or at least one.\n */\nexport const applyDataTableFilters = <T extends IDataTableRow>(\n rows: Array<T>,\n filters: IDataTableFiltersConfig<T> | undefined,\n values: TDataTableFilterValues,\n): Array<T> => {\n if (!filters) return rows;\n\n const activeFields = (filters.fields ?? []).filter((field) => isFieldActive(field, values) && field.predicate);\n if (activeFields.length === 0) return rows;\n\n const matches = (row: T, field: TDataTableFilterField<T>) =>\n field.predicate ? field.predicate(row, values?.[field.key]) : true;\n\n if (filters.combinator === 'OR') {\n return (rows ?? []).filter((row) => activeFields.some((field) => matches(row, field)));\n }\n\n return (rows ?? []).filter((row) => activeFields.every((field) => matches(row, field)));\n};\n\n/**\n * SERVER-mode counterpart: collects the backend query params from every active\n * field that declares `toServerParams`. The host merges these into its fetch\n * instead of filtering in memory.\n */\nexport const buildDataTableFilterParams = <T extends IDataTableRow>(\n filters: IDataTableFiltersConfig<T> | undefined,\n values: TDataTableFilterValues,\n): Record<string, unknown> => {\n if (!filters) return {};\n\n return (filters.fields ?? []).reduce<Record<string, unknown>>((params, field) => {\n if (!isFieldActive(field, values) || !field.toServerParams) return params;\n\n return { ...params, ...field.toServerParams(values?.[field.key]) };\n }, {});\n};\n\n/** Number of active filter fields. Drives the filter button badge count. */\nexport const countActiveDataTableFilters = <T extends IDataTableRow>(\n filters: IDataTableFiltersConfig<T> | undefined,\n values: TDataTableFilterValues,\n): number => (filters ? countActiveFilters(filters.fields ?? [], values ?? {}) : 0);\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,gBAAgB,CACpB,OACA,WACY,CAAC,mBAAmB,OAAO,SAAS,MAAM,GAAG,CAAC;AAQrD,MAAM,wBAAwB,CACnC,MACA,SACA,WACa;AACb,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,gBAAgB,QAAQ,UAAU,CAAA,GAAI,OAAO,CAAC,UAAU,cAAc,OAAO,MAAM,KAAK,MAAM,SAAS;AAC7G,MAAI,aAAa,WAAW,EAAG,QAAO;AAEtC,QAAM,UAAU,CAAC,KAAQ,UACvB,MAAM,YAAY,MAAM,UAAU,KAAK,SAAS,MAAM,GAAG,CAAC,IAAI;AAEhE,MAAI,QAAQ,eAAe,MAAM;AAC/B,YAAQ,QAAQ,CAAA,GAAI,OAAO,CAAC,QAAQ,aAAa,KAAK,CAAC,UAAU,QAAQ,KAAK,KAAK,CAAC,CAAC;AAAA,EACvF;AAEA,UAAQ,QAAQ,CAAA,GAAI,OAAO,CAAC,QAAQ,aAAa,MAAM,CAAC,UAAU,QAAQ,KAAK,KAAK,CAAC,CAAC;AACxF;AAOO,MAAM,6BAA6B,CACxC,SACA,WAC4B;AAC5B,MAAI,CAAC,QAAS,QAAO,CAAA;AAErB,UAAQ,QAAQ,UAAU,CAAA,GAAI,OAAgC,CAAC,QAAQ,UAAU;AAC/E,QAAI,CAAC,cAAc,OAAO,MAAM,KAAK,CAAC,MAAM,eAAgB,QAAO;AAEnE,WAAO,EAAE,GAAG,QAAQ,GAAG,MAAM,eAAe,SAAS,MAAM,GAAG,CAAC,EAAA;AAAA,EACjE,GAAG,CAAA,CAAE;AACP;AAGO,MAAM,8BAA8B,CACzC,SACA,WACY,UAAU,mBAAmB,QAAQ,UAAU,CAAA,GAAI,UAAU,CAAA,CAAE,IAAI;"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { default as ControlledButton } from './components/Form/ControlledButton';
1
+ export { default as ControlledButton, getButtonClassName } from './components/Form/ControlledButton';
2
2
  export { default as ControlledCheckbox } from './components/Form/ControlledCheckbox';
3
3
  export { default as ControlledDialog } from './components/Form/ControlledDialog';
4
4
  export { default as ControlledDrawer } from './components/Form/ControlledDrawer';
@@ -12,6 +12,7 @@ export { default as ControlledTextarea } from './components/Form/ControlledTexta
12
12
  export { default as ControlledViewToggle } from './components/Form/ControlledViewToggle';
13
13
  export { default as ControlledBreadcrumb } from './components/Navigation/ControlledBreadcrumb';
14
14
  export { default as ErrorPage } from './components/Navigation/ErrorPage';
15
+ export { default as LinkButton } from './components/Navigation/LinkButton';
15
16
  export { default as PageTitle } from './components/Navigation/PageTitle';
16
17
  export * from './components/Navigation/PageTitleNavigationContext';
17
18
  export * from './components/Navigation/UiNavigationContext';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { default as default2 } from "./components/Form/ControlledButton.js";
1
+ import { default as default2, getButtonClassName } from "./components/Form/ControlledButton.js";
2
2
  import { default as default3 } from "./components/Form/ControlledCheckbox.js";
3
3
  import { default as default4 } from "./components/Form/ControlledDialog.js";
4
4
  import { default as default5 } from "./components/Form/ControlledDrawer.js";
@@ -12,34 +12,35 @@ import { default as default11 } from "./components/Form/ControlledTextarea.js";
12
12
  import { default as default12 } from "./components/Form/ControlledViewToggle.js";
13
13
  import { default as default13 } from "./components/Navigation/ControlledBreadcrumb.js";
14
14
  import { default as default14 } from "./components/Navigation/ErrorPage.js";
15
- import { default as default15 } from "./components/Navigation/PageTitle.js";
15
+ import { default as default15 } from "./components/Navigation/LinkButton.js";
16
+ import { default as default16 } from "./components/Navigation/PageTitle.js";
16
17
  import { PageTitleNavigationProvider, usePageTitleNavigation } from "./components/Navigation/PageTitleNavigationContext.js";
17
18
  import { UiNavigationProvider, useUiNavigation } from "./components/Navigation/UiNavigationContext.js";
18
- import { default as default16 } from "./components/Search/UnifiedSearchBar.js";
19
- import { default as default17 } from "./components/Shell/AppShell.js";
20
- import { default as default18 } from "./components/Shell/LanguageToggle.js";
19
+ import { default as default17 } from "./components/Search/UnifiedSearchBar.js";
20
+ import { default as default18 } from "./components/Shell/AppShell.js";
21
+ import { default as default19 } from "./components/Shell/LanguageToggle.js";
21
22
  import { resolveSidebarItemId } from "./components/Shell/SidebarMenu.js";
22
- import { default as default19 } from "./components/Shell/ThemeToggle.js";
23
+ import { default as default20 } from "./components/Shell/ThemeToggle.js";
23
24
  import { UiAccessProvider, useUiAccess } from "./components/UI/access/UiAccessContext.js";
24
- import { default as default20 } from "./components/UI/BaseDataCard.js";
25
- import { default as default21 } from "./components/UI/Chips/OutlinedChip.js";
26
- import { default as default22 } from "./components/UI/Colors.js";
27
- import { default as default23 } from "./components/UI/ColorSwatch.js";
28
- import { default as default24 } from "./components/UI/ControlledAccordion.js";
29
- import { default as default25 } from "./components/UI/ControlledCollapse.js";
30
- import { default as default26 } from "./components/UI/ControlledMenu.js";
31
- import { default as default27 } from "./components/UI/ControlledPopover.js";
32
- import { default as default28 } from "./components/UI/ControlledProgress.js";
33
- import { default as default29 } from "./components/UI/ControlledSlider.js";
34
- import { default as default30 } from "./components/UI/ControlledTooltip.js";
35
- import { default as default31 } from "./components/UI/CustomBadge.js";
36
- import { default as default32 } from "./components/UI/CustomCard.js";
37
- import { default as default33 } from "./components/UI/InformationCard.js";
38
- import { default as default34 } from "./components/UI/LoadingSpinner.js";
25
+ import { default as default21 } from "./components/UI/BaseDataCard.js";
26
+ import { default as default22 } from "./components/UI/Chips/OutlinedChip.js";
27
+ import { default as default23 } from "./components/UI/Colors.js";
28
+ import { default as default24 } from "./components/UI/ColorSwatch.js";
29
+ import { default as default25 } from "./components/UI/ControlledAccordion.js";
30
+ import { default as default26 } from "./components/UI/ControlledCollapse.js";
31
+ import { default as default27 } from "./components/UI/ControlledMenu.js";
32
+ import { default as default28 } from "./components/UI/ControlledPopover.js";
33
+ import { default as default29 } from "./components/UI/ControlledProgress.js";
34
+ import { default as default30 } from "./components/UI/ControlledSlider.js";
35
+ import { default as default31 } from "./components/UI/ControlledTooltip.js";
36
+ import { default as default32 } from "./components/UI/CustomBadge.js";
37
+ import { default as default33 } from "./components/UI/CustomCard.js";
38
+ import { default as default34 } from "./components/UI/InformationCard.js";
39
+ import { default as default35 } from "./components/UI/LoadingSpinner.js";
39
40
  import { MaterialSymbol, combineClasses } from "./components/UI/MaterialSymbol/index.js";
40
- import { default as default35 } from "./components/UI/NoDataFound/index.js";
41
- import { default as default36 } from "./components/UI/SkeletonLoading.js";
42
- import { default as default37 } from "./components/UI/UserMenu.js";
41
+ import { default as default36 } from "./components/UI/NoDataFound/index.js";
42
+ import { default as default37 } from "./components/UI/SkeletonLoading.js";
43
+ import { default as default38 } from "./components/UI/UserMenu.js";
43
44
  import { composeRefs } from "./helpers/composeRefs.js";
44
45
  import { isPressOnLayeredSurface } from "./helpers/layeredSurfaces.js";
45
46
  import { readThemeToken, useThemeChartTokens } from "./helpers/themeTokens.js";
@@ -56,49 +57,50 @@ import { uiLocales } from "./locales/index.js";
56
57
  import { collapseVariants, createDrawerVariants, dialogVariants, fadeVariants, floatingVariants, scrimVariants, tooltipVariants } from "./motion/motionPresets.js";
57
58
  import { MOTION_OFFSET_PX, enterTransition, exitTransition, motionDuration, motionEase } from "./motion/motionTokens.js";
58
59
  export {
59
- default17 as AppShell,
60
+ default18 as AppShell,
60
61
  BREAKPOINTS,
61
- default20 as BaseDataCard,
62
- default23 as ColorSwatch,
63
- default22 as Colors,
64
- default24 as ControlledAccordion,
62
+ default21 as BaseDataCard,
63
+ default24 as ColorSwatch,
64
+ default23 as Colors,
65
+ default25 as ControlledAccordion,
65
66
  default13 as ControlledBreadcrumb,
66
67
  default2 as ControlledButton,
67
68
  default3 as ControlledCheckbox,
68
- default25 as ControlledCollapse,
69
+ default26 as ControlledCollapse,
69
70
  default4 as ControlledDialog,
70
71
  default5 as ControlledDrawer,
71
72
  default6 as ControlledImage,
72
73
  default7 as ControlledInput,
73
- default26 as ControlledMenu,
74
- default27 as ControlledPopover,
75
- default28 as ControlledProgress,
74
+ default27 as ControlledMenu,
75
+ default28 as ControlledPopover,
76
+ default29 as ControlledProgress,
76
77
  default8 as ControlledRadio,
77
78
  ControlledSelect,
78
- default29 as ControlledSlider,
79
+ default30 as ControlledSlider,
79
80
  default9 as ControlledSwitch,
80
81
  default10 as ControlledTabs,
81
82
  default11 as ControlledTextarea,
82
- default30 as ControlledTooltip,
83
+ default31 as ControlledTooltip,
83
84
  default12 as ControlledViewToggle,
84
- default31 as CustomBadge,
85
- default32 as CustomCard,
85
+ default32 as CustomBadge,
86
+ default33 as CustomCard,
86
87
  default14 as ErrorPage,
87
- default33 as InformationCard,
88
- default34 as LoadingSpinner,
88
+ default34 as InformationCard,
89
+ default15 as LinkButton,
90
+ default35 as LoadingSpinner,
89
91
  MOTION_OFFSET_PX,
90
92
  MaterialSymbol,
91
- default35 as NoDataFound,
92
- default21 as OutlinedChip,
93
- default15 as PageTitle,
93
+ default36 as NoDataFound,
94
+ default22 as OutlinedChip,
95
+ default16 as PageTitle,
94
96
  PageTitleNavigationProvider,
95
- default18 as ShellLanguageToggle,
96
- default19 as ShellThemeToggle,
97
- default36 as SkeletonLoading,
97
+ default19 as ShellLanguageToggle,
98
+ default20 as ShellThemeToggle,
99
+ default37 as SkeletonLoading,
98
100
  UiAccessProvider,
99
101
  UiNavigationProvider,
100
- default16 as UnifiedSearchBar,
101
- default37 as UserMenu,
102
+ default17 as UnifiedSearchBar,
103
+ default38 as UserMenu,
102
104
  collapseVariants,
103
105
  combineClasses,
104
106
  composeRefs,
@@ -110,6 +112,7 @@ export {
110
112
  exitTransition,
111
113
  fadeVariants,
112
114
  floatingVariants,
115
+ getButtonClassName,
113
116
  isPressOnLayeredSurface,
114
117
  motionDuration,
115
118
  motionEase,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umodeapporg/ui",
3
- "version": "0.11.1",
3
+ "version": "0.13.0",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -80,6 +80,7 @@
80
80
  "typecheck": "tsc -p tsconfig.json",
81
81
  "build": "npm run typecheck && vite build",
82
82
  "lint": "eslint \"src/**/*.{ts,tsx}\" --report-unused-disable-directives --max-warnings 0",
83
+ "test": "vitest run",
83
84
  "format": "prettier --write .",
84
85
  "lint:fix": "npm run format && npm run lint -- --fix",
85
86
  "audit:theme": "node scripts/theme-audit.mjs",
@@ -177,6 +178,10 @@
177
178
  "@semantic-release/changelog": "^6.0.3",
178
179
  "@semantic-release/git": "^10.0.1",
179
180
  "@tanstack/react-table": "^8.21.3",
181
+ "@testing-library/dom": "^10.4.2",
182
+ "@testing-library/jest-dom": "^6.9.1",
183
+ "@testing-library/react": "^16.3.3",
184
+ "@testing-library/user-event": "^14.6.7",
180
185
  "@types/node": "^24.13.3",
181
186
  "@types/react": "^18.3.12",
182
187
  "@types/react-dom": "^18.3.1",
@@ -195,6 +200,7 @@
195
200
  "eslint-plugin-simple-import-sort": "^12.1.1",
196
201
  "fast-glob": "^3.3.2",
197
202
  "i18next": "^26.1.0",
203
+ "jsdom": "^26.1.0",
198
204
  "konva": "^9.3.22",
199
205
  "motion": "^13.1.0",
200
206
  "postcss": "^8.4.40",
@@ -216,7 +222,8 @@
216
222
  "tailwindcss": "^3.4.7",
217
223
  "typescript": "^5.2.2",
218
224
  "vite": "^6.3.2",
219
- "vite-plugin-dts": "^4.5.4"
225
+ "vite-plugin-dts": "^4.5.4",
226
+ "vitest": "^3.2.7"
220
227
  },
221
228
  "repository": {
222
229
  "type": "git",