@zentauri-ui/zentauri-components 2.1.6 → 2.1.7

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 (115) hide show
  1. package/README.md +10 -8
  2. package/cli/cli.integration.test.ts +36 -0
  3. package/cli/index.mjs +43 -7
  4. package/cli/props.json +273 -0
  5. package/cli/registry.json +20 -0
  6. package/cli/rewrite-imports.mjs +29 -4
  7. package/cli/rewrite-imports.test.ts +35 -0
  8. package/dist/{chunk-QE7OJW4J.js → chunk-5ELR6MIN.js} +6 -6
  9. package/dist/{chunk-QE7OJW4J.js.map → chunk-5ELR6MIN.js.map} +1 -1
  10. package/dist/chunk-5FU57ZVQ.js +19 -0
  11. package/dist/{chunk-3W2UUKWP.js.map → chunk-5FU57ZVQ.js.map} +1 -1
  12. package/dist/chunk-74SKXGTM.js +4 -0
  13. package/dist/chunk-74SKXGTM.js.map +1 -0
  14. package/dist/{chunk-CHI6MBTI.mjs → chunk-7UXPXCKV.mjs} +3 -3
  15. package/dist/{chunk-CHI6MBTI.mjs.map → chunk-7UXPXCKV.mjs.map} +1 -1
  16. package/dist/chunk-CYKSS5S5.mjs +128 -0
  17. package/dist/chunk-CYKSS5S5.mjs.map +1 -0
  18. package/dist/chunk-DBNGLT5U.mjs +221 -0
  19. package/dist/chunk-DBNGLT5U.mjs.map +1 -0
  20. package/dist/{chunk-A4IB3C23.mjs → chunk-FUCW5GPE.mjs} +22 -6
  21. package/dist/chunk-FUCW5GPE.mjs.map +1 -0
  22. package/dist/chunk-G7FVHZRB.js +225 -0
  23. package/dist/chunk-G7FVHZRB.js.map +1 -0
  24. package/dist/chunk-HMDH4BQJ.js +123 -0
  25. package/dist/chunk-HMDH4BQJ.js.map +1 -0
  26. package/dist/chunk-I7EBE7BD.js +98 -0
  27. package/dist/chunk-I7EBE7BD.js.map +1 -0
  28. package/dist/{chunk-WWKAJHIV.mjs → chunk-KVSRUAXP.mjs} +3 -3
  29. package/dist/{chunk-WWKAJHIV.mjs.map → chunk-KVSRUAXP.mjs.map} +1 -1
  30. package/dist/chunk-LHBJD57K.mjs +143 -0
  31. package/dist/chunk-LHBJD57K.mjs.map +1 -0
  32. package/dist/chunk-OYAJG2BO.js +83 -0
  33. package/dist/chunk-OYAJG2BO.js.map +1 -0
  34. package/dist/chunk-PTU5ZAYX.js +145 -0
  35. package/dist/chunk-PTU5ZAYX.js.map +1 -0
  36. package/dist/chunk-QKO5DA4N.mjs +81 -0
  37. package/dist/chunk-QKO5DA4N.mjs.map +1 -0
  38. package/dist/chunk-T7PIKDUZ.js +130 -0
  39. package/dist/chunk-T7PIKDUZ.js.map +1 -0
  40. package/dist/chunk-TDK5TVJE.mjs +3 -0
  41. package/dist/chunk-TDK5TVJE.mjs.map +1 -0
  42. package/dist/{chunk-VA6SB6NN.js → chunk-TJ2EWPER.js} +28 -5
  43. package/dist/chunk-TJ2EWPER.js.map +1 -0
  44. package/dist/chunk-VBNW2B4D.mjs +3 -0
  45. package/dist/chunk-VBNW2B4D.mjs.map +1 -0
  46. package/dist/chunk-W6DO36XD.mjs +96 -0
  47. package/dist/chunk-W6DO36XD.mjs.map +1 -0
  48. package/dist/chunk-XR3J46TZ.js +4 -0
  49. package/dist/chunk-XR3J46TZ.js.map +1 -0
  50. package/dist/chunk-ZOHCADDL.mjs +121 -0
  51. package/dist/chunk-ZOHCADDL.mjs.map +1 -0
  52. package/dist/design-system/data-table.d.ts +8 -0
  53. package/dist/design-system/data-table.d.ts.map +1 -0
  54. package/dist/design-system/facade.js +5 -5
  55. package/dist/design-system/facade.mjs +4 -4
  56. package/dist/design-system/index.d.ts +1 -0
  57. package/dist/design-system/index.d.ts.map +1 -1
  58. package/dist/hooks/useTableFilter.js +6 -116
  59. package/dist/hooks/useTableFilter.js.map +1 -1
  60. package/dist/hooks/useTableFilter.mjs +1 -118
  61. package/dist/hooks/useTableFilter.mjs.map +1 -1
  62. package/dist/hooks/useTableSort.js +6 -91
  63. package/dist/hooks/useTableSort.js.map +1 -1
  64. package/dist/hooks/useTableSort.mjs +1 -93
  65. package/dist/hooks/useTableSort.mjs.map +1 -1
  66. package/dist/hooks/useVirtualList.js +6 -76
  67. package/dist/hooks/useVirtualList.js.map +1 -1
  68. package/dist/hooks/useVirtualList.mjs +1 -78
  69. package/dist/hooks/useVirtualList.mjs.map +1 -1
  70. package/dist/ui/buttons/animated.js +7 -7
  71. package/dist/ui/buttons/animated.mjs +5 -5
  72. package/dist/ui/buttons.js +9 -8
  73. package/dist/ui/buttons.mjs +7 -6
  74. package/dist/ui/checkbox.js +7 -123
  75. package/dist/ui/checkbox.js.map +1 -1
  76. package/dist/ui/checkbox.mjs +2 -126
  77. package/dist/ui/checkbox.mjs.map +1 -1
  78. package/dist/ui/data-table/data-table-base.d.ts +6 -0
  79. package/dist/ui/data-table/data-table-base.d.ts.map +1 -0
  80. package/dist/ui/data-table/data-table.d.ts +6 -0
  81. package/dist/ui/data-table/data-table.d.ts.map +1 -0
  82. package/dist/ui/data-table/index.d.ts +4 -0
  83. package/dist/ui/data-table/index.d.ts.map +1 -0
  84. package/dist/ui/data-table/types.d.ts +92 -0
  85. package/dist/ui/data-table/types.d.ts.map +1 -0
  86. package/dist/ui/data-table/variants.d.ts +8 -0
  87. package/dist/ui/data-table/variants.d.ts.map +1 -0
  88. package/dist/ui/data-table.js +620 -0
  89. package/dist/ui/data-table.js.map +1 -0
  90. package/dist/ui/data-table.mjs +611 -0
  91. package/dist/ui/data-table.mjs.map +1 -0
  92. package/dist/ui/dynamic-stepper.js +17 -17
  93. package/dist/ui/dynamic-stepper.mjs +6 -6
  94. package/dist/ui/inputs.js +7 -138
  95. package/dist/ui/inputs.js.map +1 -1
  96. package/dist/ui/inputs.mjs +2 -141
  97. package/dist/ui/inputs.mjs.map +1 -1
  98. package/dist/ui/pagination.js +19 -220
  99. package/dist/ui/pagination.js.map +1 -1
  100. package/dist/ui/pagination.mjs +7 -222
  101. package/dist/ui/pagination.mjs.map +1 -1
  102. package/dist/ui/table.js +1 -0
  103. package/dist/ui/table.mjs +1 -0
  104. package/package.json +1 -1
  105. package/src/design-system/data-table.ts +20 -0
  106. package/src/design-system/index.ts +1 -0
  107. package/src/ui/data-table/data-table-base.tsx +701 -0
  108. package/src/ui/data-table/data-table.test.tsx +389 -0
  109. package/src/ui/data-table/data-table.tsx +11 -0
  110. package/src/ui/data-table/index.ts +24 -0
  111. package/src/ui/data-table/types.ts +121 -0
  112. package/src/ui/data-table/variants.ts +21 -0
  113. package/dist/chunk-3W2UUKWP.js +0 -19
  114. package/dist/chunk-A4IB3C23.mjs.map +0 -1
  115. package/dist/chunk-VA6SB6NN.js.map +0 -1
package/README.md CHANGED
@@ -15,7 +15,7 @@ Published artifacts live under `dist/`. Imports use **per-entry subpaths**: `@ze
15
15
 
16
16
  | Surface | Count | Import shape |
17
17
  | ------------------- | ----: | ----------------------------------------------------- |
18
- | Static UI entries | 41 | `@zentauri-ui/zentauri-components/ui/<name>` |
18
+ | Static UI entries | 42 | `@zentauri-ui/zentauri-components/ui/<name>` |
19
19
  | Animated UI entries | 27 | `@zentauri-ui/zentauri-components/ui/<name>/animated` |
20
20
  | Animation entries | 41 | `@zentauri-ui/zentauri-components/animations/<name>` |
21
21
  | Chart entries | 9 | `@zentauri-ui/zentauri-components/charts/<type>` |
@@ -29,16 +29,16 @@ Generated from the component package Vitest JSON report via `pnpm --filter @zent
29
29
 
30
30
  | Metric | Result |
31
31
  | ---------- | ---------------- |
32
- | Test files | 96 passed (96) |
33
- | Tests | 792 passed (792) |
32
+ | Test files | 97 passed (97) |
33
+ | Tests | 808 passed (808) |
34
34
 
35
35
  | Area | Test files | Tests |
36
36
  | ------------------------------ | ---------- | ----- |
37
- | Components and UI utilities | 47 | 490 |
37
+ | Components and UI utilities | 48 | 503 |
38
38
  | Standalone animations | 1 | 45 |
39
39
  | React hooks | 41 | 174 |
40
40
  | Design system facade | 1 | 11 |
41
- | CLI and import rewriting | 4 | 30 |
41
+ | CLI and import rewriting | 4 | 33 |
42
42
  | Accessibility (axe + keyboard) | 2 | 42 |
43
43
 
44
44
  ### Per-suite snapshot
@@ -52,10 +52,11 @@ Generated from the component package Vitest JSON report via `pnpm --filter @zent
52
52
  | `src/ui/peer-isolation.test.ts` | 29 |
53
53
  | `src/accessibility/axe-core.test.tsx` | 24 |
54
54
  | `src/ui/combobox/combobox.test.tsx` | 24 |
55
- | `cli/cli.integration.test.ts` | 20 |
55
+ | `cli/cli.integration.test.ts` | 21 |
56
56
  | `src/accessibility/keyboard-interaction.test.tsx` | 18 |
57
57
  | `src/ui/pagination/pagination.test.tsx` | 15 |
58
58
  | `src/ui/timeline/timeline.test.tsx` | 14 |
59
+ | `src/ui/data-table/data-table.test.tsx` | 13 |
59
60
  | `src/ui/context-menu/context-menu.test.tsx` | 12 |
60
61
  | `src/lib/facade.test.ts` | 11 |
61
62
  | `src/ui/alert/alert.test.tsx` | 11 |
@@ -78,6 +79,7 @@ Generated from the component package Vitest JSON report via `pnpm --filter @zent
78
79
  | `src/ui/progress/progress.test.tsx` | 8 |
79
80
  | `src/ui/scroll-area/scroll-area.test.tsx` | 8 |
80
81
  | `src/ui/spinner/animated/spinner.test.tsx` | 8 |
82
+ | `cli/rewrite-imports.test.ts` | 7 |
81
83
  | `src/hooks/useDynamicStepper/useDynamicStepper.test.ts` | 7 |
82
84
  | `src/hooks/useHotkeys/useHotkeys.test.ts` | 7 |
83
85
  | `src/hooks/useTableSort/useTableSort.test.ts` | 7 |
@@ -101,7 +103,6 @@ Generated from the component package Vitest JSON report via `pnpm --filter @zent
101
103
  | `src/ui/empty-state/empty-state.test.tsx` | 6 |
102
104
  | `src/ui/search/filter-search-suggestions.test.ts` | 6 |
103
105
  | `src/ui/toast/toast.test.tsx` | 6 |
104
- | `cli/rewrite-imports.test.ts` | 5 |
105
106
  | `src/hooks/useCookie/useCookie.test.ts` | 5 |
106
107
  | `src/hooks/useDisclosure/useDisclosure.test.ts` | 5 |
107
108
  | `src/hooks/useEventListener/useEventListener.test.ts` | 5 |
@@ -221,6 +222,7 @@ Import static primitives from `@zentauri-ui/zentauri-components/ui/<subpath>` wh
221
222
  | Command | `command` | `command/animated` |
222
223
  | Context menu | `context-menu` | — |
223
224
  | Copy button | `copy-button` | `copy-button/animated` |
225
+ | DataTable | `data-table` | — |
224
226
  | Divider | `divider` | `divider/animated` |
225
227
  | Drawer | `drawer` | `drawer/animated` |
226
228
  | Dropdown | `dropdown` | — |
@@ -850,7 +852,7 @@ From this package directory in the monorepo:
850
852
 
851
853
  - `pnpm build` (or `npm run build`) — production bundle via `tsup` (Rollup treeshake + `scripts/prepend-use-client.mjs` via `onSuccess` so each UI entry under `dist/ui/`, animation entry under `dist/animations/`, chart entry under `dist/charts/`, and `dist/ui/<name>/animated.*` starts with `"use client"` where needed)
852
854
  - `pnpm dev` — `tsup` watch mode (same `onSuccess` hook after each rebuild)
853
- - `pnpm test` / `pnpm test:watch` — **Vitest** and **Testing Library** unit tests // currently covered 792 test cases in total
855
+ - `pnpm test` / `pnpm test:watch` — **Vitest** and **Testing Library** unit tests // currently covered 808 test cases in total
854
856
  - `pnpm test:a11y` — focused accessibility coverage for package-level UI primitives and compound components: **axe-core** audits for every interactive component plus **keyboard-interaction** tests (focus order, arrow-key nav, Home/End, Escape/Enter) for the compound components
855
857
  - `pnpm check:tokens` — enforce the `--zui-*` token contract across design-system, variant, and local custom-property usage without generating a large checked-in token catalog
856
858
  - **`pnpm run generate:registry`** — runs `scripts/generate-registry.mjs`, which reads **`uiComponentNames`**, **`uiAnimatedComponentNames`**, **`animationEntryNames`**, **`chartEntryNames`**, and **`hooksEntryNames`** from `tsup.config.ts`, applies fixed **`nameAliases`**, scans each component/chart source to build **`peerHints`**, and writes **`cli/registry.json`** (`components` + `animations` + `hooks` + `peerHints`). Run this after adding or renaming UI, animation, chart, or hook entries so the CLI stays in sync (the script prints counts).
@@ -295,6 +295,42 @@ describe("zentauri-ui CLI", () => {
295
295
  }
296
296
  });
297
297
 
298
+ it("should add data-table with vendored sibling UI dependencies", () => {
299
+ const dir = mkdtempSync(join(tmpdir(), "zentauri-cli-data-table-"));
300
+ try {
301
+ runCli(dir, ["init"]);
302
+ const out = runCli(dir, ["add", "data-table"]);
303
+ expect(
304
+ existsSync(join(dir, "src/components/ui/data-table/data-table.tsx")),
305
+ ).toBe(true);
306
+ expect(
307
+ existsSync(join(dir, "src/components/ui/buttons/button.tsx")),
308
+ ).toBe(true);
309
+ expect(
310
+ existsSync(join(dir, "src/components/ui/checkbox/checkbox.tsx")),
311
+ ).toBe(true);
312
+ expect(existsSync(join(dir, "src/components/ui/inputs/input.tsx"))).toBe(
313
+ true,
314
+ );
315
+ expect(
316
+ existsSync(join(dir, "src/components/ui/pagination/pagination.tsx")),
317
+ ).toBe(true);
318
+ expect(existsSync(join(dir, "src/components/ui/table/table.tsx"))).toBe(
319
+ true,
320
+ );
321
+ const base = readFileSync(
322
+ join(dir, "src/components/ui/data-table/data-table-base.tsx"),
323
+ "utf8",
324
+ );
325
+ expect(base).toContain('from "@/components/ui/buttons"');
326
+ expect(base).not.toContain('from "../buttons"');
327
+ expect(out).toContain("Adding data-table…");
328
+ expect(out).toContain("Adding buttons…");
329
+ } finally {
330
+ rmSync(dir, { recursive: true, force: true });
331
+ }
332
+ });
333
+
298
334
  it("should print react-icons peer hint for components that use icons", () => {
299
335
  const dir = mkdtempSync(join(tmpdir(), "zentauri-cli-peer-"));
300
336
  try {
package/cli/index.mjs CHANGED
@@ -548,6 +548,27 @@ function isAnimatedComponent(name, registry) {
548
548
  return (registry.animatedComponents ?? []).includes(name);
549
549
  }
550
550
 
551
+ function expandComponentDependencies(names, registry) {
552
+ const dependencies = registry.componentDependencies ?? {};
553
+ const expanded = [];
554
+ const seen = new Set();
555
+ const queue = [...names];
556
+
557
+ while (queue.length > 0) {
558
+ const name = queue.shift();
559
+ if (seen.has(name)) {
560
+ continue;
561
+ }
562
+ seen.add(name);
563
+ expanded.push(name);
564
+ for (const dependency of dependencies[name] ?? []) {
565
+ queue.push(dependency);
566
+ }
567
+ }
568
+
569
+ return expanded;
570
+ }
571
+
551
572
  function printList(registry) {
552
573
  const ui = Array.from(
553
574
  new Set([
@@ -922,7 +943,13 @@ async function collectHookTransitiveClosure(packageRoot, seedHooks) {
922
943
  * // src/components/ui/buttons/Button.tsx
923
944
  * // with imports pointing at @/lib/utils, @/hooks/useX, etc.
924
945
  */
925
- async function copyUiComponent(componentName, config, configDir, packageRoot) {
946
+ async function copyUiComponent(
947
+ componentName,
948
+ config,
949
+ configDir,
950
+ packageRoot,
951
+ registry,
952
+ ) {
926
953
  const isChartEntry = componentName.startsWith("charts/");
927
954
  const isAnimationEntry = componentName.startsWith("animations/");
928
955
  const animationName = componentName.slice("animations/".length);
@@ -979,6 +1006,7 @@ async function copyUiComponent(componentName, config, configDir, packageRoot) {
979
1006
  utilsAlias: config.aliases.utils,
980
1007
  hooksAlias: config.aliases.hooks,
981
1008
  uiAlias: config.aliases.ui,
1009
+ uiComponents: registry.uiComponents ?? [],
982
1010
  });
983
1011
  const rewrittenCode = designSystemImportTarget
984
1012
  ? rewriteDesignSystemBarrelImports(code, designSystemImportTarget)
@@ -1310,8 +1338,9 @@ async function cmdAdd(names, cwd, options = {}) {
1310
1338
  }
1311
1339
 
1312
1340
  const resolvedNames = payload.map((n) => resolveComponentName(n, registry));
1341
+ const requestedNames = [...resolvedNames];
1313
1342
  if (animated) {
1314
- for (const name of resolvedNames) {
1343
+ for (const name of requestedNames) {
1315
1344
  if (!isAnimatedComponent(name, registry)) {
1316
1345
  console.error(`Component "${name}" has no animated entry.`);
1317
1346
  process.exitCode = 1;
@@ -1319,17 +1348,24 @@ async function cmdAdd(names, cwd, options = {}) {
1319
1348
  }
1320
1349
  }
1321
1350
  }
1351
+ const namesToCopy = expandComponentDependencies(requestedNames, registry);
1322
1352
 
1323
1353
  await ensureUtilsFile(config, configDir, packageRoot);
1324
- await copyDesignSystemFiles(resolvedNames, config, configDir, packageRoot);
1354
+ await copyDesignSystemFiles(namesToCopy, config, configDir, packageRoot);
1325
1355
 
1326
1356
  const allHooks = new Set();
1327
- for (const name of resolvedNames) {
1357
+ for (const name of namesToCopy) {
1328
1358
  console.log(`Adding ${name}…`);
1329
- if (animated) {
1359
+ if (animated && requestedNames.includes(name)) {
1330
1360
  console.log(`Including animated entry for ${name}…`);
1331
1361
  }
1332
- const uh = await copyUiComponent(name, config, configDir, packageRoot);
1362
+ const uh = await copyUiComponent(
1363
+ name,
1364
+ config,
1365
+ configDir,
1366
+ packageRoot,
1367
+ registry,
1368
+ );
1333
1369
  for (const h of uh) {
1334
1370
  allHooks.add(h);
1335
1371
  }
@@ -1345,7 +1381,7 @@ async function cmdAdd(names, cwd, options = {}) {
1345
1381
  }
1346
1382
 
1347
1383
  console.log("Done.");
1348
- printAdoptionHints(resolvedNames, registry, config, configDir);
1384
+ printAdoptionHints(namesToCopy, registry, config, configDir);
1349
1385
  }
1350
1386
 
1351
1387
  async function cmdTheme(hex, options, cwd) {
package/cli/props.json CHANGED
@@ -5308,6 +5308,279 @@
5308
5308
  }
5309
5309
  ]
5310
5310
  },
5311
+ "data-table": {
5312
+ "slug": "data-table",
5313
+ "subcomponents": [
5314
+ {
5315
+ "name": "static:DataTable",
5316
+ "displayName": "DataTable",
5317
+ "propsType": "DataTableProps",
5318
+ "source": "static",
5319
+ "props": [
5320
+ {
5321
+ "name": "appearance",
5322
+ "type": "'default' | 'ghost' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | 'sky' | 'rose' | 'purple' | 'pink' | 'orange' | 'yellow' | 'teal' | 'indigo' | 'emerald' | 'gray' | 'violet' | 'amber' | 'striped' | 'bordered' | null | undefined",
5323
+ "required": false,
5324
+ "group": "behavior",
5325
+ "deprecated": false
5326
+ },
5327
+ {
5328
+ "name": "bulkActions",
5329
+ "type": "readonly DataTableBulkAction<TData>[] | undefined",
5330
+ "required": false,
5331
+ "group": "behavior",
5332
+ "deprecated": false
5333
+ },
5334
+ {
5335
+ "name": "caption",
5336
+ "type": "ReactNode",
5337
+ "required": false,
5338
+ "group": "behavior",
5339
+ "deprecated": false
5340
+ },
5341
+ {
5342
+ "name": "columns",
5343
+ "type": "readonly DataTableColumn<TData, TKey>[]",
5344
+ "required": true,
5345
+ "group": "behavior",
5346
+ "deprecated": false
5347
+ },
5348
+ {
5349
+ "name": "data",
5350
+ "type": "readonly TData[]",
5351
+ "required": true,
5352
+ "group": "behavior",
5353
+ "deprecated": false
5354
+ },
5355
+ {
5356
+ "name": "defaultSelectedRowIds",
5357
+ "type": "readonly string[] | undefined",
5358
+ "required": false,
5359
+ "group": "behavior",
5360
+ "deprecated": false
5361
+ },
5362
+ {
5363
+ "name": "defaultSortDirection",
5364
+ "type": "TableSortDirection | undefined",
5365
+ "required": false,
5366
+ "group": "behavior",
5367
+ "deprecated": false
5368
+ },
5369
+ {
5370
+ "name": "defaultSortKey",
5371
+ "type": "TKey | undefined",
5372
+ "required": false,
5373
+ "group": "behavior",
5374
+ "deprecated": false
5375
+ },
5376
+ {
5377
+ "name": "defaultVisibleColumnIds",
5378
+ "type": "readonly TKey[] | undefined",
5379
+ "required": false,
5380
+ "group": "behavior",
5381
+ "deprecated": false
5382
+ },
5383
+ {
5384
+ "name": "emptyContent",
5385
+ "type": "ReactNode",
5386
+ "required": false,
5387
+ "group": "behavior",
5388
+ "deprecated": false
5389
+ },
5390
+ {
5391
+ "name": "enableColumnVisibility",
5392
+ "type": "boolean | undefined",
5393
+ "required": false,
5394
+ "group": "behavior",
5395
+ "deprecated": false
5396
+ },
5397
+ {
5398
+ "name": "enableRowSelection",
5399
+ "type": "boolean | undefined",
5400
+ "required": false,
5401
+ "group": "behavior",
5402
+ "deprecated": false
5403
+ },
5404
+ {
5405
+ "name": "getRowId",
5406
+ "type": "((row: TData, index: number) => string) | undefined",
5407
+ "required": false,
5408
+ "group": "behavior",
5409
+ "deprecated": false
5410
+ },
5411
+ {
5412
+ "name": "loading",
5413
+ "type": "boolean | undefined",
5414
+ "required": false,
5415
+ "group": "behavior",
5416
+ "deprecated": false
5417
+ },
5418
+ {
5419
+ "name": "loadingContent",
5420
+ "type": "ReactNode",
5421
+ "required": false,
5422
+ "group": "behavior",
5423
+ "deprecated": false
5424
+ },
5425
+ {
5426
+ "name": "onColumnVisibilityChange",
5427
+ "type": "((visibleColumnIds: TKey[]) => void) | undefined",
5428
+ "required": false,
5429
+ "group": "behavior",
5430
+ "deprecated": false
5431
+ },
5432
+ {
5433
+ "name": "onRowSelectionChange",
5434
+ "type": "((selectedRowIds: string[], selectedRows: TData[]) => void) | undefined",
5435
+ "required": false,
5436
+ "group": "behavior",
5437
+ "deprecated": false
5438
+ },
5439
+ {
5440
+ "name": "onSortChange",
5441
+ "type": "((sort: { sortKey?: TKey; sortDirection: TableSortDirection; }) => void) | undefined",
5442
+ "required": false,
5443
+ "group": "behavior",
5444
+ "deprecated": false
5445
+ },
5446
+ {
5447
+ "name": "pagination",
5448
+ "type": "boolean | DataTablePaginationOptions | undefined",
5449
+ "required": false,
5450
+ "group": "behavior",
5451
+ "deprecated": false
5452
+ },
5453
+ {
5454
+ "name": "ref",
5455
+ "type": "Ref<HTMLElement> | undefined",
5456
+ "required": false,
5457
+ "group": "behavior",
5458
+ "description": "Allows getting a ref to the component instance.\nOnce the component unmounts, React will set `ref.current` to `null`\n(or call the ref with `null` if you passed a callback ref).",
5459
+ "deprecated": false
5460
+ },
5461
+ {
5462
+ "name": "search",
5463
+ "type": "boolean | DataTableSearchOptions<TKey> | undefined",
5464
+ "required": false,
5465
+ "group": "behavior",
5466
+ "deprecated": false
5467
+ },
5468
+ {
5469
+ "name": "selectedRowIds",
5470
+ "type": "readonly string[] | undefined",
5471
+ "required": false,
5472
+ "group": "behavior",
5473
+ "deprecated": false
5474
+ },
5475
+ {
5476
+ "name": "showRowCount",
5477
+ "type": "boolean | undefined",
5478
+ "required": false,
5479
+ "group": "behavior",
5480
+ "deprecated": false
5481
+ },
5482
+ {
5483
+ "name": "size",
5484
+ "type": "'md' | 'sm' | 'lg' | null | undefined",
5485
+ "required": false,
5486
+ "group": "behavior",
5487
+ "deprecated": false
5488
+ },
5489
+ {
5490
+ "name": "sortDirection",
5491
+ "type": "TableSortDirection | undefined",
5492
+ "required": false,
5493
+ "group": "behavior",
5494
+ "deprecated": false
5495
+ },
5496
+ {
5497
+ "name": "sortKey",
5498
+ "type": "TKey | undefined",
5499
+ "required": false,
5500
+ "group": "behavior",
5501
+ "deprecated": false
5502
+ },
5503
+ {
5504
+ "name": "stickyHeader",
5505
+ "type": "boolean | null | undefined",
5506
+ "required": false,
5507
+ "group": "behavior",
5508
+ "deprecated": false
5509
+ },
5510
+ {
5511
+ "name": "tableClassName",
5512
+ "type": "string | undefined",
5513
+ "required": false,
5514
+ "group": "behavior",
5515
+ "deprecated": false
5516
+ },
5517
+ {
5518
+ "name": "tableScrollAreaAriaLabel",
5519
+ "type": "string | undefined",
5520
+ "required": false,
5521
+ "group": "behavior",
5522
+ "deprecated": false
5523
+ },
5524
+ {
5525
+ "name": "textAlign",
5526
+ "type": "'center' | 'left' | 'right' | undefined",
5527
+ "required": false,
5528
+ "group": "behavior",
5529
+ "deprecated": false
5530
+ },
5531
+ {
5532
+ "name": "virtualization",
5533
+ "type": "DataTableVirtualizationOptions | undefined",
5534
+ "required": false,
5535
+ "group": "behavior",
5536
+ "deprecated": false
5537
+ },
5538
+ {
5539
+ "name": "visibleColumnIds",
5540
+ "type": "readonly TKey[] | undefined",
5541
+ "required": false,
5542
+ "group": "behavior",
5543
+ "deprecated": false
5544
+ },
5545
+ {
5546
+ "name": "className",
5547
+ "type": "string | undefined",
5548
+ "required": false,
5549
+ "group": "dom",
5550
+ "deprecated": false
5551
+ },
5552
+ {
5553
+ "name": "id",
5554
+ "type": "string | undefined",
5555
+ "required": false,
5556
+ "group": "dom",
5557
+ "deprecated": false
5558
+ },
5559
+ {
5560
+ "name": "onClick",
5561
+ "type": "MouseEventHandler<HTMLElement> | undefined",
5562
+ "required": false,
5563
+ "group": "dom",
5564
+ "deprecated": false
5565
+ },
5566
+ {
5567
+ "name": "style",
5568
+ "type": "CSSProperties | undefined",
5569
+ "required": false,
5570
+ "group": "dom",
5571
+ "deprecated": false
5572
+ },
5573
+ {
5574
+ "name": "title",
5575
+ "type": "string | undefined",
5576
+ "required": false,
5577
+ "group": "dom",
5578
+ "deprecated": false
5579
+ }
5580
+ ]
5581
+ }
5582
+ ]
5583
+ },
5311
5584
  "divider": {
5312
5585
  "slug": "divider",
5313
5586
  "subcomponents": [
package/cli/registry.json CHANGED
@@ -16,6 +16,7 @@
16
16
  "command",
17
17
  "context-menu",
18
18
  "copy-button",
19
+ "data-table",
19
20
  "divider",
20
21
  "drawer",
21
22
  "dropdown",
@@ -151,6 +152,7 @@
151
152
  "command",
152
153
  "context-menu",
153
154
  "copy-button",
155
+ "data-table",
154
156
  "divider",
155
157
  "drawer",
156
158
  "dropdown",
@@ -268,6 +270,24 @@
268
270
  "useVirtualList",
269
271
  "useWindowSize"
270
272
  ],
273
+ "componentDependencies": {
274
+ "data-table": [
275
+ "buttons",
276
+ "checkbox",
277
+ "inputs",
278
+ "pagination",
279
+ "table"
280
+ ],
281
+ "dynamic-stepper": [
282
+ "buttons"
283
+ ],
284
+ "pagination": [
285
+ "buttons"
286
+ ],
287
+ "search": [
288
+ "inputs"
289
+ ]
290
+ },
271
291
  "peerHints": {
272
292
  "accordion": [
273
293
  "framer-motion"
@@ -2,12 +2,14 @@
2
2
  * Rewrites internal package-relative imports to app aliases.
3
3
  *
4
4
  * @param {string} source
5
- * @param {{ utilsAlias: string; hooksAlias: string; uiAlias?: string }} options
6
- * @returns {{ code: string; usedHooks: string[] }}
5
+ * @param {{ utilsAlias: string; hooksAlias: string; uiAlias?: string; uiComponents?: string[] }} options
6
+ * @returns {{ code: string; usedHooks: string[]; usedUiComponents: string[] }}
7
7
  */
8
8
  export function rewriteImports(source, options) {
9
- const { utilsAlias, hooksAlias, uiAlias } = options;
9
+ const { utilsAlias, hooksAlias, uiAlias, uiComponents = [] } = options;
10
10
  const usedHooks = new Set();
11
+ const usedUiComponents = new Set();
12
+ const uiComponentSet = new Set(uiComponents);
11
13
 
12
14
  const collectHooks = (text) => {
13
15
  const re = /from\s+(["'])((?:\.\.\/)+)hooks\/([^'"]+)\1/g;
@@ -24,6 +26,25 @@ export function rewriteImports(source, options) {
24
26
 
25
27
  let code = source;
26
28
 
29
+ if (uiAlias) {
30
+ // Single-parent imports (`../<name>`) point at a sibling UI component.
31
+ // The leading `[^'"./]` excludes deeper relatives like `../../lib/utils`,
32
+ // which are rewritten by the dedicated blocks below. When a `uiComponents`
33
+ // allowlist is supplied, only those siblings are rewritten; otherwise every
34
+ // sibling import is treated as a UI component.
35
+ code = code.replace(
36
+ /from\s+(["'])\.\.\/([^'"./][^'"]*)\1/g,
37
+ (match, quote, rest) => {
38
+ const componentName = rest.split("/")[0];
39
+ if (uiComponentSet.size > 0 && !uiComponentSet.has(componentName)) {
40
+ return match;
41
+ }
42
+ usedUiComponents.add(componentName);
43
+ return `from ${quote}${uiAlias}/${rest}${quote}`;
44
+ },
45
+ );
46
+ }
47
+
27
48
  code = code.replace(
28
49
  /from\s+(["'])((?:\.\.\/)+)lib\/utils\1/g,
29
50
  (_, quote) => `from ${quote}${utilsAlias}${quote}`,
@@ -47,7 +68,11 @@ export function rewriteImports(source, options) {
47
68
  );
48
69
  }
49
70
 
50
- return { code, usedHooks: [...usedHooks] };
71
+ return {
72
+ code,
73
+ usedHooks: [...usedHooks],
74
+ usedUiComponents: [...usedUiComponents],
75
+ };
51
76
  }
52
77
 
53
78
  /**
@@ -42,11 +42,46 @@ import { useFocusManagement as u } from "../../../hooks/useFocusManagement";
42
42
  utilsAlias: "@/lib/utils",
43
43
  hooksAlias: "@/hooks",
44
44
  uiAlias: "@/components/ui",
45
+ uiComponents: ["buttons", "pagination"],
45
46
  });
46
47
  expect(code).toContain('from "@/components/ui/pagination/types"');
47
48
  expect(code).not.toContain("../../ui/");
48
49
  });
49
50
 
51
+ it("should rewrite sibling ui paths when uiAlias is set", () => {
52
+ const input = `
53
+ import { Button } from "../buttons";
54
+ import type { PaginationAppearance } from "../pagination";
55
+ `;
56
+ const { code } = rewriteImports(input, {
57
+ utilsAlias: "@/lib/utils",
58
+ hooksAlias: "@/hooks",
59
+ uiAlias: "@/components/ui",
60
+ });
61
+ expect(code).toContain('from "@/components/ui/buttons"');
62
+ expect(code).toContain('from "@/components/ui/pagination"');
63
+ expect(code).not.toContain("../buttons");
64
+ });
65
+
66
+ it("should collect sibling ui imports", () => {
67
+ const input = `
68
+ import { Button } from "../buttons";
69
+ import { Checkbox } from "../checkbox";
70
+ import type { PaginationAppearance } from "../pagination";
71
+ `;
72
+ const { usedUiComponents } = rewriteImports(input, {
73
+ utilsAlias: "@/lib/utils",
74
+ hooksAlias: "@/hooks",
75
+ uiAlias: "@/components/ui",
76
+ uiComponents: ["buttons", "checkbox", "pagination"],
77
+ });
78
+ expect(usedUiComponents.sort()).toEqual([
79
+ "buttons",
80
+ "checkbox",
81
+ "pagination",
82
+ ]);
83
+ });
84
+
50
85
  it("should preserve single-quote import style", () => {
51
86
  const input = `import { cn } from '../../lib/utils';\n`;
52
87
  const { code } = rewriteImports(input, {