@jalvin/ui 2.0.36 → 2.0.38

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=children-signature.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"children-signature.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/children-signature.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,106 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ /**
5
+ * Tests to ensure all child-accepting UI components use consistent
6
+ * second-argument children signature (not props-style).
7
+ *
8
+ * This prevents runtime mismatches like the 2.0.35 incident where
9
+ * Scaffold/Card took children as second arg, but Column/Row read from props.
10
+ */
11
+ describe("UI children signature consistency", () => {
12
+ // Components that accept children
13
+ const CHILD_COMPONENTS = [
14
+ "Scaffold",
15
+ "Card",
16
+ "Column",
17
+ "Row",
18
+ "Box",
19
+ "Button",
20
+ "IconButton",
21
+ ];
22
+ // Text is intentionally different (uses props.children and props.text)
23
+ const INTENTIONAL_EXCEPTIONS = ["Text"];
24
+ it("all child-accepting components use second-argument style in TypeScript", () => {
25
+ const srcDir = path.join(__dirname, "..");
26
+ const tsxFiles = [
27
+ path.join(srcDir, "surface.tsx"),
28
+ path.join(srcDir, "layout.tsx"),
29
+ path.join(srcDir, "button.tsx"),
30
+ ];
31
+ const content = tsxFiles
32
+ .map((f) => fs.readFileSync(f, "utf-8"))
33
+ .join("\n");
34
+ for (const component of CHILD_COMPONENTS) {
35
+ // Find the component function definition
36
+ const componentRegex = new RegExp(`export function ${component}\\([\\s\\S]*?\\):\\s*React\\.ReactElement`, "");
37
+ const match = content.match(componentRegex);
38
+ expect(match, `${component} function not found`).toBeTruthy();
39
+ const functionSig = match[0];
40
+ // Check: should have children as second parameter (after Props)
41
+ // Pattern: }: PropType, children?: React.ReactNode
42
+ // (handles multi-line with whitespace variations)
43
+ const hasSecondArgChildren = /:\s*\w+Props\s*,\s*children\?/s.test(functionSig);
44
+ expect(hasSecondArgChildren, `${component} should have children as second-argument, not in props`).toBe(true);
45
+ // Check: should NOT have children in props destructuring
46
+ // Pattern: { ..., children... }
47
+ const propsMatch = functionSig.match(/\{[\s\S]*?\}:\s*\w+Props/);
48
+ if (propsMatch) {
49
+ const propsBody = propsMatch[0];
50
+ expect(!propsBody.includes("children"), `${component} props should NOT include children field`).toBe(true);
51
+ }
52
+ }
53
+ });
54
+ it("interface props do not include children field", () => {
55
+ const srcDir = path.join(__dirname, "..");
56
+ const tsxFiles = [
57
+ path.join(srcDir, "surface.tsx"),
58
+ path.join(srcDir, "layout.tsx"),
59
+ path.join(srcDir, "button.tsx"),
60
+ ];
61
+ const content = tsxFiles
62
+ .map((f) => fs.readFileSync(f, "utf-8"))
63
+ .join("\n");
64
+ // Get interface definitions for components with children
65
+ for (const component of CHILD_COMPONENTS) {
66
+ // Look for interfaces like ScaffoldProps, CardProps, etc.
67
+ const interfaceName = `${component}Props`;
68
+ const interfacePattern = new RegExp(`export interface ${interfaceName}\\s*\\{[^}]*?\\}`, "s");
69
+ const match = content.match(interfacePattern);
70
+ if (match) {
71
+ const interfaceBody = match[0];
72
+ // For non-exception components, children should NOT be in the interface
73
+ if (!INTENTIONAL_EXCEPTIONS.includes(component)) {
74
+ expect(!interfaceBody.includes("children"), `${interfaceName} should NOT include children field (children are second-argument)`).toBe(true);
75
+ }
76
+ }
77
+ }
78
+ });
79
+ it("component implementations spread children correctly as second arg", () => {
80
+ const srcDir = path.join(__dirname, "..");
81
+ const layoutContent = fs.readFileSync(path.join(srcDir, "layout.tsx"), "utf-8");
82
+ // Check that Column/Row/Box all use ...(children ?? []) pattern
83
+ for (const component of ["Column", "Row", "Box"]) {
84
+ // Should have pattern: ...(children ?? [])
85
+ expect(layoutContent.includes(`...(children ?? [])`), `${component} should spread children with ...(children ?? []) pattern`).toBe(true);
86
+ }
87
+ });
88
+ it("compiled dist files maintain second-argument children signature", () => {
89
+ const distDir = path.join(__dirname, "../../dist");
90
+ // Check if dist exists (it will after build)
91
+ if (!fs.existsSync(distDir)) {
92
+ console.warn("dist/ not found; skipping compiled output check");
93
+ return;
94
+ }
95
+ const jsFiles = [
96
+ path.join(distDir, "surface.js"),
97
+ path.join(distDir, "layout.js"),
98
+ path.join(distDir, "button.js"),
99
+ ].filter((f) => fs.existsSync(f));
100
+ const content = jsFiles.map((f) => fs.readFileSync(f, "utf-8")).join("\n");
101
+ // Check that second-argument children patterns exist in compiled code
102
+ // Pattern: }, children) or }, children =
103
+ expect(/},\s*children\s*[),=]/m.test(content), "Compiled code should have children as second parameter").toBe(true);
104
+ });
105
+ });
106
+ //# sourceMappingURL=children-signature.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"children-signature.test.js","sourceRoot":"","sources":["../../src/__tests__/children-signature.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jalvin/ui",
3
- "version": "2.0.36",
3
+ "version": "2.0.38",
4
4
  "description": "Jalvin UI — Compose-style component library (Column, Row, Box, Button, Text, …)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -21,7 +21,7 @@
21
21
  "react": ">=18.0.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@jalvin/runtime": "^2.0.36",
24
+ "@jalvin/runtime": "^2.0.38",
25
25
  "@testing-library/jest-dom": "^6.9.1",
26
26
  "@testing-library/react": "^16.3.2",
27
27
  "@types/node": "^20.0.0",