@zentauri-ui/zentauri-components 2.1.5 → 2.1.6

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 (68) hide show
  1. package/README.md +7 -5
  2. package/cli/index.mjs +48 -5
  3. package/cli/index.test.ts +180 -0
  4. package/cli/props.json +336 -14
  5. package/cli/registry.json +2 -0
  6. package/dist/chunk-3W2UUKWP.js +19 -0
  7. package/dist/{chunk-D2GISTDL.js.map → chunk-3W2UUKWP.js.map} +1 -1
  8. package/dist/{chunk-BL6UVCV7.mjs → chunk-A4IB3C23.mjs} +16 -7
  9. package/dist/chunk-A4IB3C23.mjs.map +1 -0
  10. package/dist/{chunk-WBZKMSXW.mjs → chunk-CHI6MBTI.mjs} +3 -3
  11. package/dist/{chunk-WBZKMSXW.mjs.map → chunk-CHI6MBTI.mjs.map} +1 -1
  12. package/dist/chunk-COCPCZMR.mjs +77 -0
  13. package/dist/chunk-COCPCZMR.mjs.map +1 -0
  14. package/dist/chunk-PG7LQVU6.js +86 -0
  15. package/dist/chunk-PG7LQVU6.js.map +1 -0
  16. package/dist/{chunk-RENXBUZY.js → chunk-QE7OJW4J.js} +6 -6
  17. package/dist/{chunk-RENXBUZY.js.map → chunk-QE7OJW4J.js.map} +1 -1
  18. package/dist/{chunk-NZSZE36T.js → chunk-VA6SB6NN.js} +16 -7
  19. package/dist/{chunk-BL6UVCV7.mjs.map → chunk-VA6SB6NN.js.map} +1 -1
  20. package/dist/{chunk-PAG5CTLN.mjs → chunk-WWKAJHIV.mjs} +3 -3
  21. package/dist/{chunk-PAG5CTLN.mjs.map → chunk-WWKAJHIV.mjs.map} +1 -1
  22. package/dist/design-system/audio-player.d.ts +61 -0
  23. package/dist/design-system/audio-player.d.ts.map +1 -0
  24. package/dist/design-system/facade.js +8 -7
  25. package/dist/design-system/facade.js.map +1 -1
  26. package/dist/design-system/facade.mjs +7 -6
  27. package/dist/design-system/facade.mjs.map +1 -1
  28. package/dist/design-system/index.d.ts +1 -0
  29. package/dist/design-system/index.d.ts.map +1 -1
  30. package/dist/ui/audio-player/audio-player-base.d.ts +20 -0
  31. package/dist/ui/audio-player/audio-player-base.d.ts.map +1 -0
  32. package/dist/ui/audio-player/audio-player.d.ts +6 -0
  33. package/dist/ui/audio-player/audio-player.d.ts.map +1 -0
  34. package/dist/ui/audio-player/index.d.ts +5 -0
  35. package/dist/ui/audio-player/index.d.ts.map +1 -0
  36. package/dist/ui/audio-player/types.d.ts +44 -0
  37. package/dist/ui/audio-player/types.d.ts.map +1 -0
  38. package/dist/ui/audio-player/variants.d.ts +12 -0
  39. package/dist/ui/audio-player/variants.d.ts.map +1 -0
  40. package/dist/ui/audio-player.js +556 -0
  41. package/dist/ui/audio-player.js.map +1 -0
  42. package/dist/ui/audio-player.mjs +545 -0
  43. package/dist/ui/audio-player.mjs.map +1 -0
  44. package/dist/ui/buttons/animated.js +10 -9
  45. package/dist/ui/buttons/animated.js.map +1 -1
  46. package/dist/ui/buttons/animated.mjs +8 -7
  47. package/dist/ui/buttons/animated.mjs.map +1 -1
  48. package/dist/ui/buttons.js +11 -10
  49. package/dist/ui/buttons.mjs +9 -8
  50. package/dist/ui/dynamic-stepper.js +20 -19
  51. package/dist/ui/dynamic-stepper.js.map +1 -1
  52. package/dist/ui/dynamic-stepper.mjs +9 -8
  53. package/dist/ui/dynamic-stepper.mjs.map +1 -1
  54. package/dist/ui/pagination.js +16 -15
  55. package/dist/ui/pagination.js.map +1 -1
  56. package/dist/ui/pagination.mjs +8 -7
  57. package/dist/ui/pagination.mjs.map +1 -1
  58. package/package.json +1 -1
  59. package/src/design-system/audio-player.ts +109 -0
  60. package/src/design-system/index.ts +1 -0
  61. package/src/ui/audio-player/audio-player-base.tsx +557 -0
  62. package/src/ui/audio-player/audio-player.test.tsx +485 -0
  63. package/src/ui/audio-player/audio-player.tsx +8 -0
  64. package/src/ui/audio-player/index.ts +24 -0
  65. package/src/ui/audio-player/types.ts +57 -0
  66. package/src/ui/audio-player/variants.ts +43 -0
  67. package/dist/chunk-D2GISTDL.js +0 -19
  68. package/dist/chunk-NZSZE36T.js.map +0 -1
package/README.md CHANGED
@@ -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 | 94 passed (94) |
33
- | Tests | 754 passed (754) |
32
+ | Test files | 96 passed (96) |
33
+ | Tests | 792 passed (792) |
34
34
 
35
35
  | Area | Test files | Tests |
36
36
  | ------------------------------ | ---------- | ----- |
37
- | Components and UI utilities | 46 | 456 |
37
+ | Components and UI utilities | 47 | 490 |
38
38
  | Standalone animations | 1 | 45 |
39
39
  | React hooks | 41 | 174 |
40
40
  | Design system facade | 1 | 11 |
41
- | CLI and import rewriting | 3 | 26 |
41
+ | CLI and import rewriting | 4 | 30 |
42
42
  | Accessibility (axe + keyboard) | 2 | 42 |
43
43
 
44
44
  ### Per-suite snapshot
@@ -48,6 +48,7 @@ Generated from the component package Vitest JSON report via `pnpm --filter @zent
48
48
  | `src/animations/animations.test.tsx` | 45 |
49
49
  | `src/ui/buttons/button.test.tsx` | 44 |
50
50
  | `src/ui/inputs/input.test.tsx` | 40 |
51
+ | `src/ui/audio-player/audio-player.test.tsx` | 34 |
51
52
  | `src/ui/peer-isolation.test.ts` | 29 |
52
53
  | `src/accessibility/axe-core.test.tsx` | 24 |
53
54
  | `src/ui/combobox/combobox.test.tsx` | 24 |
@@ -109,6 +110,7 @@ Generated from the component package Vitest JSON report via `pnpm --filter @zent
109
110
  | `src/ui/popover/popover.test.tsx` | 5 |
110
111
  | `src/ui/radio-group/radio-group.test.tsx` | 5 |
111
112
  | `src/ui/toggle/toggle.test.tsx` | 5 |
113
+ | `cli/index.test.ts` | 4 |
112
114
  | `src/hooks/useBodyScrollLock/useBodyScrollLock.test.ts` | 4 |
113
115
  | `src/hooks/useControllableState/useControllableState.test.ts` | 4 |
114
116
  | `src/hooks/useDebouncedValue/useDebouncedValue.test.ts` | 4 |
@@ -848,7 +850,7 @@ From this package directory in the monorepo:
848
850
 
849
851
  - `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)
850
852
  - `pnpm dev` — `tsup` watch mode (same `onSuccess` hook after each rebuild)
851
- - `pnpm test` / `pnpm test:watch` — **Vitest** and **Testing Library** unit tests // currently covered 754 test cases in total
853
+ - `pnpm test` / `pnpm test:watch` — **Vitest** and **Testing Library** unit tests // currently covered 792 test cases in total
852
854
  - `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
853
855
  - `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
854
856
  - **`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).
package/cli/index.mjs CHANGED
@@ -84,7 +84,7 @@
84
84
  * command, or refused `init` overwrite. Successful runs leave default exit 0.
85
85
  */
86
86
 
87
- import { existsSync, readFileSync } from "node:fs";
87
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
88
88
  import {
89
89
  readFile,
90
90
  writeFile,
@@ -1464,7 +1464,50 @@ async function main() {
1464
1464
  process.exitCode = 1;
1465
1465
  }
1466
1466
 
1467
- main().catch((err) => {
1468
- console.error(err instanceof Error ? err.message : err);
1469
- process.exitCode = 1;
1470
- });
1467
+ export {
1468
+ buildCompactThemeCss,
1469
+ cmdAdd,
1470
+ cmdInit,
1471
+ cmdTheme,
1472
+ collectHookTransitiveClosure,
1473
+ copyDesignSystemFiles,
1474
+ copyHookFolder,
1475
+ copyUiComponent,
1476
+ defaultConfig,
1477
+ detectFramework,
1478
+ findComponentsJson,
1479
+ getMissingDependencies,
1480
+ importPathFor,
1481
+ isTestFile,
1482
+ loadRegistry,
1483
+ main,
1484
+ normalizeHexColor,
1485
+ printAdoptionHints,
1486
+ printInfo,
1487
+ printList,
1488
+ resolveComponentName,
1489
+ resolveHookName,
1490
+ validateConfig,
1491
+ walkFiles,
1492
+ };
1493
+
1494
+ function isDirectCliRun() {
1495
+ if (!process.argv[1]) {
1496
+ return false;
1497
+ }
1498
+ try {
1499
+ return (
1500
+ realpathSync(process.argv[1]) ===
1501
+ realpathSync(fileURLToPath(import.meta.url))
1502
+ );
1503
+ } catch {
1504
+ return resolve(process.argv[1]) === fileURLToPath(import.meta.url);
1505
+ }
1506
+ }
1507
+
1508
+ if (isDirectCliRun()) {
1509
+ main().catch((err) => {
1510
+ console.error(err instanceof Error ? err.message : err);
1511
+ process.exitCode = 1;
1512
+ });
1513
+ }
@@ -0,0 +1,180 @@
1
+ import {
2
+ existsSync,
3
+ mkdtempSync,
4
+ readFileSync,
5
+ rmSync,
6
+ writeFileSync,
7
+ } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+
11
+ import { afterEach, describe, expect, it, vi } from "vitest";
12
+
13
+ import {
14
+ cmdAdd,
15
+ cmdInit,
16
+ cmdTheme,
17
+ defaultConfig,
18
+ importPathFor,
19
+ normalizeHexColor,
20
+ resolveComponentName,
21
+ resolveHookName,
22
+ validateConfig,
23
+ } from "./index.mjs";
24
+
25
+ type TestRegistry = Parameters<typeof resolveComponentName>[1] &
26
+ Parameters<typeof resolveHookName>[1];
27
+
28
+ function makeTempDir(prefix: string) {
29
+ return mkdtempSync(join(tmpdir(), prefix));
30
+ }
31
+
32
+ function silenceConsole() {
33
+ const logs: string[] = [];
34
+ const errors: string[] = [];
35
+
36
+ vi.spyOn(console, "log").mockImplementation((...args) => {
37
+ logs.push(args.join(" "));
38
+ });
39
+ vi.spyOn(console, "error").mockImplementation((...args) => {
40
+ errors.push(args.join(" "));
41
+ });
42
+
43
+ return { errors, logs };
44
+ }
45
+
46
+ describe("CLI module commands", () => {
47
+ afterEach(() => {
48
+ vi.restoreAllMocks();
49
+ process.exitCode = undefined;
50
+ });
51
+
52
+ it("resolves aliases, hooks, imports, hex colors, and config validation", () => {
53
+ const registry: TestRegistry = {
54
+ components: ["buttons", "card", "charts/line"],
55
+ hooks: ["useWindowSize"],
56
+ nameAliases: { button: "buttons" },
57
+ animatedComponents: ["buttons", "spinner"],
58
+ uiComponents: ["buttons", "card"],
59
+ };
60
+
61
+ expect(resolveComponentName("button", registry)).toBe("buttons");
62
+ expect(resolveComponentName("CARD", registry)).toBe("card");
63
+ expect(resolveHookName("usewindowsize", registry)).toBe("useWindowSize");
64
+ expect(importPathFor("useWindowSize", "hook", registry)).toBe(
65
+ "@zentauri-ui/zentauri-components/hooks/useWindowSize",
66
+ );
67
+ expect(importPathFor("charts/line", "component", registry)).toBe(
68
+ "@zentauri-ui/zentauri-components/charts/line",
69
+ );
70
+ expect(importPathFor("spinner", "component", registry)).toBe(
71
+ "@zentauri-ui/zentauri-components/ui/spinner/animated",
72
+ );
73
+ expect(normalizeHexColor("38b")).toBe("#3388bb");
74
+ expect(() => validateConfig(defaultConfig())).not.toThrow();
75
+ expect(() => resolveComponentName("missing", registry)).toThrow(
76
+ /Unknown component/,
77
+ );
78
+ expect(() => normalizeHexColor("not-a-color")).toThrow(
79
+ /Invalid brand color/,
80
+ );
81
+ });
82
+
83
+ it("initializes components.json with framework-aware guidance", async () => {
84
+ const dir = makeTempDir("zentauri-cli-module-init-");
85
+ const { errors, logs } = silenceConsole();
86
+
87
+ try {
88
+ writeFileSync(
89
+ join(dir, "package.json"),
90
+ JSON.stringify({ dependencies: { next: "16.0.0" } }),
91
+ );
92
+
93
+ await cmdInit(dir);
94
+
95
+ expect(existsSync(join(dir, "components.json"))).toBe(true);
96
+ expect(
97
+ JSON.parse(readFileSync(join(dir, "components.json"), "utf8")),
98
+ ).toEqual(defaultConfig());
99
+ expect(logs.join("\n")).toContain("Detected framework: Next.js");
100
+ expect(logs.join("\n")).toContain('@source "./src/components/ui";');
101
+
102
+ await cmdInit(dir);
103
+
104
+ expect(process.exitCode).toBe(1);
105
+ expect(errors.join("\n")).toContain("Refusing to overwrite existing");
106
+ } finally {
107
+ rmSync(dir, { recursive: true, force: true });
108
+ }
109
+ });
110
+
111
+ it("vendors components, animated entries, design tokens, and transitive hooks", async () => {
112
+ const dir = makeTempDir("zentauri-cli-module-add-");
113
+ const { logs } = silenceConsole();
114
+
115
+ try {
116
+ await cmdInit(dir);
117
+ await cmdAdd(["button"], dir);
118
+ await cmdAdd(["hook", "usePrefersReducedMotion"], dir);
119
+ await cmdAdd(["button"], dir, { animated: true });
120
+
121
+ expect(
122
+ existsSync(join(dir, "src/components/ui/buttons/button.tsx")),
123
+ ).toBe(true);
124
+ expect(
125
+ existsSync(join(dir, "src/components/ui/buttons/animated/index.ts")),
126
+ ).toBe(true);
127
+ expect(
128
+ existsSync(join(dir, "src/components/design-system/button.ts")),
129
+ ).toBe(true);
130
+ expect(
131
+ existsSync(join(dir, "src/components/design-system/tokens.ts")),
132
+ ).toBe(true);
133
+ expect(
134
+ existsSync(
135
+ join(
136
+ dir,
137
+ "src/hooks/usePrefersReducedMotion/usePrefersReducedMotion.ts",
138
+ ),
139
+ ),
140
+ ).toBe(true);
141
+ expect(
142
+ existsSync(join(dir, "src/hooks/useMediaQuery/useMediaQuery.ts")),
143
+ ).toBe(true);
144
+ expect(
145
+ readFileSync(
146
+ join(dir, "src/components/ui/buttons/button-base.tsx"),
147
+ "utf8",
148
+ ),
149
+ ).toContain('from "@/lib/utils"');
150
+ expect(logs.join("\n")).toContain("Including animated entry for buttons");
151
+ expect(logs.join("\n")).toContain("Missing peer dependencies");
152
+ } finally {
153
+ rmSync(dir, { recursive: true, force: true });
154
+ }
155
+ });
156
+
157
+ it("generates theme CSS to stdout or a requested file", async () => {
158
+ const dir = makeTempDir("zentauri-cli-module-theme-");
159
+ const { errors, logs } = silenceConsole();
160
+
161
+ try {
162
+ await cmdTheme("#2563eb", { dark: "#60a5fa" }, dir);
163
+ expect(logs.join("\n")).toContain("--zui-brand: #2563eb;");
164
+ expect(logs.join("\n")).toContain("--zui-brand-dark: #60a5fa;");
165
+
166
+ await cmdTheme("38bdf8", { out: "src/styles/zentauri-theme.css" }, dir);
167
+ const themePath = join(dir, "src/styles/zentauri-theme.css");
168
+ expect(existsSync(themePath)).toBe(true);
169
+ expect(readFileSync(themePath, "utf8")).toContain(
170
+ "--zui-brand: #38bdf8;",
171
+ );
172
+
173
+ await cmdTheme("", {}, dir);
174
+ expect(process.exitCode).toBe(1);
175
+ expect(errors.join("\n")).toContain("Usage: zentauri-components theme");
176
+ } finally {
177
+ rmSync(dir, { recursive: true, force: true });
178
+ }
179
+ });
180
+ });