@robomous/ui-core 0.1.1 → 0.2.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.
- package/README.md +15 -7
- package/dist/{primitives → components}/alert.js +1 -1
- package/dist/{primitives → components}/badge.js +1 -1
- package/dist/{primitives → components}/button.d.ts +1 -1
- package/dist/{primitives → components}/button.js +4 -1
- package/dist/{primitives → components}/card.d.ts +1 -1
- package/dist/{primitives → components}/card.js +2 -2
- package/dist/{primitives → components}/combobox.js +3 -3
- package/dist/{primitives → components}/dialog.js +1 -1
- package/dist/{primitives → components}/dropdown-menu.js +11 -6
- package/dist/{primitives → components}/field.js +2 -4
- package/dist/{primitives → components}/input-group.js +1 -1
- package/dist/{primitives → components}/input.js +1 -1
- package/dist/{primitives → components}/label.js +1 -1
- package/dist/components/progress.js +7 -0
- package/dist/{primitives → components}/select.d.ts +3 -1
- package/dist/{primitives → components}/select.js +6 -4
- package/dist/{primitives → components}/separator.js +1 -1
- package/dist/{primitives → components}/sheet.js +1 -1
- package/dist/{primitives → components}/skeleton.js +1 -1
- package/dist/{primitives → components}/sonner.js +17 -12
- package/dist/{primitives → components}/table.d.ts +1 -1
- package/dist/{primitives → components}/table.js +3 -3
- package/dist/{primitives → components}/tabs.js +1 -1
- package/dist/{primitives → components}/textarea.js +1 -1
- package/dist/{primitives → components}/tooltip.js +1 -1
- package/dist/gates/index.d.ts +28 -0
- package/dist/gates/index.js +142 -0
- package/dist/index.d.ts +31 -32
- package/dist/index.js +32 -33
- package/dist/{tokens.d.ts → theme/tokens.d.ts} +5 -5
- package/dist/{tokens.js → theme/tokens.js} +12 -12
- package/package.json +23 -12
- package/{shadcn → src/components}/alert.tsx +14 -21
- package/src/{primitives → components}/badge.tsx +15 -21
- package/src/{primitives → components}/button.tsx +13 -10
- package/{shadcn → src/components}/card.tsx +16 -31
- package/src/{primitives → components}/combobox.test.tsx +15 -2
- package/src/{primitives → components}/combobox.tsx +45 -74
- package/src/{primitives/primitives.test.tsx → components/components.test.tsx} +106 -69
- package/src/{primitives → components}/dialog.tsx +31 -54
- package/src/{primitives → components}/dropdown-menu.tsx +51 -65
- package/src/{primitives → components}/field.tsx +48 -62
- package/src/{primitives → components}/input-group.tsx +37 -49
- package/{shadcn → src/components}/input.tsx +5 -5
- package/{shadcn → src/components}/label.tsx +7 -10
- package/src/{primitives → components}/progress.tsx +7 -6
- package/{shadcn → src/components}/select.tsx +39 -41
- package/{shadcn → src/components}/separator.tsx +7 -7
- package/src/{primitives → components}/sheet.tsx +27 -44
- package/{shadcn → src/components}/skeleton.tsx +3 -3
- package/src/{primitives → components}/sonner.test.tsx +12 -4
- package/src/components/sonner.tsx +67 -0
- package/{shadcn → src/components}/table.tsx +17 -44
- package/{shadcn → src/components}/tabs.tsx +16 -26
- package/{shadcn → src/components}/textarea.tsx +5 -5
- package/{shadcn → src/components}/tooltip.tsx +12 -16
- package/src/gates/design.test.ts +188 -0
- package/src/gates/index.test.ts +11 -0
- package/src/gates/index.ts +165 -0
- package/src/gates/tokens.test.ts +215 -0
- package/src/harness.test.tsx +1 -1
- package/src/index.ts +63 -33
- package/src/theme/imports.test.ts +160 -0
- package/src/{statusTone.test.ts → theme/statusTone.test.ts} +5 -1
- package/src/{styles.css → theme/styles.css} +45 -31
- package/src/theme/tailwind.css +646 -0
- package/src/{tokens.test.ts → theme/tokens.test.ts} +30 -23
- package/src/{tokens.ts → theme/tokens.ts} +12 -12
- package/components.json +0 -13
- package/dist/lib/button.d.ts +0 -1
- package/dist/lib/button.js +0 -4
- package/dist/lib/cn.d.ts +0 -18
- package/dist/lib/cn.js +0 -21
- package/dist/lib/menu.d.ts +0 -1
- package/dist/lib/menu.js +0 -16
- package/dist/lib/progress.d.ts +0 -3
- package/dist/lib/progress.js +0 -6
- package/dist/lib/select.d.ts +0 -1
- package/dist/lib/select.js +0 -3
- package/dist/primitives/progress.js +0 -7
- package/gates/canonical.test.mjs +0 -71
- package/gates/extensions.test.mjs +0 -373
- package/gates/index.d.mts +0 -51
- package/gates/index.mjs +0 -514
- package/gates/tokens.test.mjs +0 -276
- package/shadcn/README.md +0 -13
- package/shadcn/badge.tsx +0 -49
- package/shadcn/button.tsx +0 -67
- package/shadcn/combobox.tsx +0 -299
- package/shadcn/dialog.tsx +0 -166
- package/shadcn/dropdown-menu.tsx +0 -267
- package/shadcn/field.tsx +0 -236
- package/shadcn/input-group.tsx +0 -154
- package/shadcn/progress.tsx +0 -29
- package/shadcn/sheet.tsx +0 -145
- package/shadcn/sonner.tsx +0 -49
- package/src/lib/button.ts +0 -4
- package/src/lib/cn.test.ts +0 -33
- package/src/lib/cn.ts +0 -23
- package/src/lib/menu.ts +0 -16
- package/src/lib/progress.ts +0 -6
- package/src/lib/select.ts +0 -4
- package/src/primitives/alert.tsx +0 -76
- package/src/primitives/card.tsx +0 -103
- package/src/primitives/input.tsx +0 -19
- package/src/primitives/label.tsx +0 -22
- package/src/primitives/select.tsx +0 -192
- package/src/primitives/separator.tsx +0 -28
- package/src/primitives/skeleton.tsx +0 -13
- package/src/primitives/sonner.tsx +0 -65
- package/src/primitives/table.tsx +0 -114
- package/src/primitives/tabs.tsx +0 -88
- package/src/primitives/textarea.tsx +0 -18
- package/src/primitives/tooltip.tsx +0 -57
- /package/dist/{primitives → components}/alert.d.ts +0 -0
- /package/dist/{primitives → components}/badge.d.ts +0 -0
- /package/dist/{primitives → components}/combobox.d.ts +0 -0
- /package/dist/{primitives → components}/dialog.d.ts +0 -0
- /package/dist/{primitives → components}/dropdown-menu.d.ts +0 -0
- /package/dist/{primitives → components}/field.d.ts +0 -0
- /package/dist/{primitives → components}/input-group.d.ts +0 -0
- /package/dist/{primitives → components}/input.d.ts +0 -0
- /package/dist/{primitives → components}/label.d.ts +0 -0
- /package/dist/{primitives → components}/progress.d.ts +0 -0
- /package/dist/{primitives → components}/separator.d.ts +0 -0
- /package/dist/{primitives → components}/sheet.d.ts +0 -0
- /package/dist/{primitives → components}/skeleton.d.ts +0 -0
- /package/dist/{primitives → components}/sonner.d.ts +0 -0
- /package/dist/{primitives → components}/tabs.d.ts +0 -0
- /package/dist/{primitives → components}/textarea.d.ts +0 -0
- /package/dist/{primitives → components}/tooltip.d.ts +0 -0
- /package/dist/{statusTone.d.ts → theme/statusTone.d.ts} +0 -0
- /package/dist/{statusTone.js → theme/statusTone.js} +0 -0
- /package/src/{statusTone.ts → theme/statusTone.ts} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @vitest-environment node
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
* the one Robomous extension. `tokens.ts` is the
|
|
4
|
+
* The token contract: `styles.css` is the one home for a colour (`:root`,
|
|
5
|
+
* `.dark`, `@theme inline`, the base layer) — the semantic vocabulary plus
|
|
6
|
+
* `brand`, the one Robomous extension. `tokens.ts` is the mirror a
|
|
7
7
|
* `<canvas>`/`<svg>` or a test reads a colour off of; this suite parses the
|
|
8
8
|
* stylesheet structurally and asserts the two agree, declaration for
|
|
9
9
|
* declaration, and that none of the tokens this rewrite retired have crept
|
|
@@ -23,9 +23,14 @@ import { cssVar, DARK_THEME, LIGHT_THEME, THEME } from "./tokens";
|
|
|
23
23
|
|
|
24
24
|
const STYLESHEET = readFileSync(fileURLToPath(new URL("./styles.css", import.meta.url)), "utf8");
|
|
25
25
|
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Whitespace and quote style are presentation: a value that wraps, and a font
|
|
28
|
+
* family spelled in double quotes rather than single, are the same value. Both
|
|
29
|
+
* change under an ordinary formatter run and neither changes what a browser
|
|
30
|
+
* resolves, so neither may fail this suite.
|
|
31
|
+
*/
|
|
27
32
|
function normalize(value: string): string {
|
|
28
|
-
return value.replace(/\s+/g, " ").trim();
|
|
33
|
+
return value.replace(/\s+/g, " ").replace(/"/g, "'").trim();
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
/**
|
|
@@ -65,9 +70,9 @@ function declarations(block: string): Map<string, string> {
|
|
|
65
70
|
return map;
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
// The
|
|
69
|
-
//
|
|
70
|
-
//
|
|
73
|
+
// The semantic vocabulary, written out here rather than derived from
|
|
74
|
+
// `tokens.ts`, so a mistake in the mirror cannot also erase the thing it was
|
|
75
|
+
// supposed to mirror.
|
|
71
76
|
const CHART_NAMES = ["chart-1", "chart-2", "chart-3", "chart-4", "chart-5"];
|
|
72
77
|
const SIDEBAR_NAMES = [
|
|
73
78
|
"sidebar",
|
|
@@ -101,10 +106,10 @@ const BASE_SEMANTIC_NAMES = [
|
|
|
101
106
|
];
|
|
102
107
|
const SEMANTIC_NAMES = [...BASE_SEMANTIC_NAMES, ...CHART_NAMES, ...SIDEBAR_NAMES];
|
|
103
108
|
|
|
104
|
-
// The one
|
|
109
|
+
// The one name this package keeps beyond the semantic vocabulary.
|
|
105
110
|
const EXTENSION_NAMES = ["brand"];
|
|
106
111
|
|
|
107
|
-
const
|
|
112
|
+
const NEUTRAL_CHART = {
|
|
108
113
|
"chart-1": "oklch(0.87 0 0)",
|
|
109
114
|
"chart-2": "oklch(0.556 0 0)",
|
|
110
115
|
"chart-3": "oklch(0.439 0 0)",
|
|
@@ -115,7 +120,7 @@ const ORANGE_CHART = {
|
|
|
115
120
|
describe(":root", () => {
|
|
116
121
|
const root = declarations(blockBody(STYLESHEET, ":root {"));
|
|
117
122
|
|
|
118
|
-
it("declares every
|
|
123
|
+
it("declares every semantic variable, the one extension, and --radius, and nothing else", () => {
|
|
119
124
|
expect([...root.keys()].sort()).toEqual(
|
|
120
125
|
[...SEMANTIC_NAMES, ...EXTENSION_NAMES, "radius"].sort(),
|
|
121
126
|
);
|
|
@@ -134,13 +139,13 @@ describe(":root", () => {
|
|
|
134
139
|
expect(lightKeys).toEqual(rootKeys);
|
|
135
140
|
});
|
|
136
141
|
|
|
137
|
-
it("pins --radius to the
|
|
142
|
+
it("pins --radius to the medium step, in both the CSS and THEME", () => {
|
|
138
143
|
expect(root.get("radius")).toBe("0.625rem");
|
|
139
144
|
expect(THEME.radius).toBe("0.625rem");
|
|
140
145
|
});
|
|
141
146
|
|
|
142
147
|
it("pins the neutral chart palette exactly", () => {
|
|
143
|
-
for (const [name, value] of Object.entries(
|
|
148
|
+
for (const [name, value] of Object.entries(NEUTRAL_CHART)) {
|
|
144
149
|
expect(root.get(name)).toBe(value);
|
|
145
150
|
}
|
|
146
151
|
});
|
|
@@ -149,7 +154,7 @@ describe(":root", () => {
|
|
|
149
154
|
describe(".dark", () => {
|
|
150
155
|
const dark = declarations(blockBody(STYLESHEET, ".dark {"));
|
|
151
156
|
|
|
152
|
-
it("declares every
|
|
157
|
+
it("declares every semantic variable and the one extension, and nothing else (no --radius)", () => {
|
|
153
158
|
expect([...dark.keys()].sort()).toEqual([...SEMANTIC_NAMES, ...EXTENSION_NAMES].sort());
|
|
154
159
|
});
|
|
155
160
|
|
|
@@ -164,7 +169,7 @@ describe(".dark", () => {
|
|
|
164
169
|
});
|
|
165
170
|
|
|
166
171
|
it("pins the neutral chart palette exactly, unchanged from light", () => {
|
|
167
|
-
for (const [name, value] of Object.entries(
|
|
172
|
+
for (const [name, value] of Object.entries(NEUTRAL_CHART)) {
|
|
168
173
|
expect(dark.get(name)).toBe(value);
|
|
169
174
|
}
|
|
170
175
|
});
|
|
@@ -200,8 +205,8 @@ describe("@theme inline", () => {
|
|
|
200
205
|
/**
|
|
201
206
|
* The four `--text-*` custom properties this rewrite retired (Task 2 moved
|
|
202
207
|
* their consumers onto Tailwind's standard scale: xs/sm/base/2xl). Assembled
|
|
203
|
-
* from fragments — the same trick `
|
|
204
|
-
*
|
|
208
|
+
* from fragments — the same trick `src/gates/tokens.test.ts`'s `HEX` uses — so
|
|
209
|
+
* this guard's own source never spells any retired name as a
|
|
205
210
|
* contiguous string and cannot trip the repo-wide sweep that proves the
|
|
206
211
|
* migration complete everywhere else.
|
|
207
212
|
*/
|
|
@@ -231,8 +236,10 @@ describe("structure", () => {
|
|
|
231
236
|
const anchors = [
|
|
232
237
|
'@import "tailwindcss";',
|
|
233
238
|
'@import "tw-animate-css";',
|
|
234
|
-
|
|
235
|
-
//
|
|
239
|
+
// The variant and utility layer, ahead of the token blocks: a variant
|
|
240
|
+
// has to exist before a utility can qualify on it.
|
|
241
|
+
'@import "./tailwind.css";',
|
|
242
|
+
// One family, so one font import: the heading face resolves to the body's
|
|
236
243
|
// rather than naming a second one.
|
|
237
244
|
'@import "@fontsource-variable/geist";',
|
|
238
245
|
"@custom-variant dark (&:is(.dark *));",
|
|
@@ -249,17 +256,17 @@ describe("structure", () => {
|
|
|
249
256
|
it("reaches its own package's classes: @source after the imports", () => {
|
|
250
257
|
const sourceAt = STYLESHEET.indexOf('@source ".";');
|
|
251
258
|
const lastImportAt = STYLESHEET.lastIndexOf("@import");
|
|
252
|
-
expect(sourceAt,
|
|
259
|
+
expect(sourceAt, 'styles.css has no @source ".";').toBeGreaterThan(-1);
|
|
253
260
|
expect(sourceAt).toBeGreaterThan(lastImportAt);
|
|
254
261
|
});
|
|
255
262
|
|
|
256
|
-
it("applies the base-layer ring/border rule
|
|
263
|
+
it("applies the base-layer ring/border rule to every element", () => {
|
|
257
264
|
expect(/\*\s*\{\s*@apply border-border outline-ring\/50;\s*\}/.test(STYLESHEET)).toBe(true);
|
|
258
265
|
});
|
|
259
266
|
|
|
260
267
|
/**
|
|
261
268
|
* The `*` rule above names the outline *colour* and nothing else about focus.
|
|
262
|
-
* The geometry
|
|
269
|
+
* The geometry belongs to the components: every focusable one carries its own
|
|
263
270
|
* `focus-visible:ring-3 focus-visible:ring-ring/50` (the tab bar adds a 1px
|
|
264
271
|
* `outline-ring` on top of it), so a stylesheet-level `:focus-visible`
|
|
265
272
|
* override would now fight the components instead of backing them up.
|
|
@@ -268,7 +275,7 @@ describe("structure", () => {
|
|
|
268
275
|
* re-adding a blanket rule here is how a single global declaration would
|
|
269
276
|
* quietly start overriding thirteen components again.
|
|
270
277
|
*/
|
|
271
|
-
it("leaves focus geometry to the
|
|
278
|
+
it("leaves focus geometry to the components: no stylesheet-level :focus-visible rule", () => {
|
|
272
279
|
expect(STYLESHEET).not.toContain(":focus-visible");
|
|
273
280
|
});
|
|
274
281
|
|
|
@@ -8,24 +8,24 @@
|
|
|
8
8
|
* which parses the stylesheet and asserts the two agree, declaration for
|
|
9
9
|
* declaration.
|
|
10
10
|
*
|
|
11
|
-
* `LIGHT_THEME`/`DARK_THEME`
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* consumer
|
|
11
|
+
* `LIGHT_THEME`/`DARK_THEME` carry the semantic vocabulary on a neutral base
|
|
12
|
+
* colour and chart palette, plus one name of this package's own: `brand`,
|
|
13
|
+
* Robomous orange, identity only. A consumer's own vocabulary lives in the
|
|
14
|
+
* consumer's stylesheet and token module, never here — DESIGN.md,
|
|
15
|
+
* *Per-consumer extensions*.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
export const LIGHT_THEME: Readonly<Record<string, string>> = Object.freeze({
|
|
19
19
|
background: "oklch(1 0 0)",
|
|
20
|
-
foreground: "oklch(0.
|
|
20
|
+
foreground: "oklch(0.2 0 0)",
|
|
21
21
|
card: "oklch(1 0 0)",
|
|
22
22
|
"card-foreground": "oklch(0.145 0 0)",
|
|
23
23
|
popover: "oklch(1 0 0)",
|
|
24
24
|
"popover-foreground": "oklch(0.145 0 0)",
|
|
25
|
-
primary: "oklch(0.
|
|
25
|
+
primary: "oklch(0.2 0 0)",
|
|
26
26
|
"primary-foreground": "oklch(0.985 0 0)",
|
|
27
27
|
secondary: "oklch(0.97 0 0)",
|
|
28
|
-
"secondary-foreground": "oklch(0.
|
|
28
|
+
"secondary-foreground": "oklch(0.269 0 0)",
|
|
29
29
|
muted: "oklch(0.97 0 0)",
|
|
30
30
|
"muted-foreground": "oklch(0.556 0 0)",
|
|
31
31
|
accent: "oklch(0.97 0 0)",
|
|
@@ -48,9 +48,9 @@ export const LIGHT_THEME: Readonly<Record<string, string>> = Object.freeze({
|
|
|
48
48
|
"sidebar-border": "oklch(0.922 0 0)",
|
|
49
49
|
"sidebar-ring": "oklch(0.708 0 0)",
|
|
50
50
|
|
|
51
|
-
// Robomous
|
|
52
|
-
// — never a functional-UI colour.
|
|
53
|
-
brand: "oklch(0.
|
|
51
|
+
// Robomous orange (#F5580B). Identity only — the wordmark and its styleguide
|
|
52
|
+
// swatch — never a functional-UI colour.
|
|
53
|
+
brand: "oklch(0.663 0.205 39.9)",
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
export const DARK_THEME: Readonly<Record<string, string>> = Object.freeze({
|
|
@@ -86,7 +86,7 @@ export const DARK_THEME: Readonly<Record<string, string>> = Object.freeze({
|
|
|
86
86
|
"sidebar-border": "oklch(1 0 0 / 10%)",
|
|
87
87
|
"sidebar-ring": "oklch(0.556 0 0)",
|
|
88
88
|
|
|
89
|
-
brand: "oklch(0.
|
|
89
|
+
brand: "oklch(0.663 0.205 39.9)",
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
/** The two provenance facts a colour string alone cannot carry. */
|
package/components.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
-
"style": "radix-nova",
|
|
4
|
-
"rsc": false,
|
|
5
|
-
"tsx": true,
|
|
6
|
-
"tailwind": { "config": "", "css": "src/styles.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" },
|
|
7
|
-
"iconLibrary": "lucide",
|
|
8
|
-
"rtl": false,
|
|
9
|
-
"aliases": { "components": "@/components", "utils": "@/lib/cn", "ui": "@/primitives", "lib": "@/lib", "hooks": "@/hooks" },
|
|
10
|
-
"menuColor": "default",
|
|
11
|
-
"menuAccent": "subtle",
|
|
12
|
-
"registries": {}
|
|
13
|
-
}
|
package/dist/lib/button.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const inlineLink = "h-auto p-0";
|
package/dist/lib/button.js
DELETED
package/dist/lib/cn.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cn` — merge class names, last conflicting utility wins.
|
|
3
|
-
*
|
|
4
|
-
* `clsx` handles the conditionals; `tailwind-merge` handles the part a naive
|
|
5
|
-
* join gets wrong. Without it `cn("px-4", props.className)` with `px-6`
|
|
6
|
-
* passed in emits both, and which one applies is decided by the order
|
|
7
|
-
* Tailwind happened to write them into the stylesheet — so a caller's
|
|
8
|
-
* override works or does not depending on a rule nobody can see. That is why
|
|
9
|
-
* the `className` prop on every primitive here is a real extension point
|
|
10
|
-
* rather than a suggestion.
|
|
11
|
-
*
|
|
12
|
-
* The shadcn preset's own vocabulary needs no custom `tailwind-merge`
|
|
13
|
-
* configuration — unlike v1's `--text-*` scale, none of its names collide
|
|
14
|
-
* with a stock Tailwind class group — so this is the bare merge, the same
|
|
15
|
-
* shape the CLI scratch's own `lib/utils.ts` ships.
|
|
16
|
-
*/
|
|
17
|
-
import { type ClassValue } from "clsx";
|
|
18
|
-
export declare function cn(...inputs: readonly ClassValue[]): string;
|
package/dist/lib/cn.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cn` — merge class names, last conflicting utility wins.
|
|
3
|
-
*
|
|
4
|
-
* `clsx` handles the conditionals; `tailwind-merge` handles the part a naive
|
|
5
|
-
* join gets wrong. Without it `cn("px-4", props.className)` with `px-6`
|
|
6
|
-
* passed in emits both, and which one applies is decided by the order
|
|
7
|
-
* Tailwind happened to write them into the stylesheet — so a caller's
|
|
8
|
-
* override works or does not depending on a rule nobody can see. That is why
|
|
9
|
-
* the `className` prop on every primitive here is a real extension point
|
|
10
|
-
* rather than a suggestion.
|
|
11
|
-
*
|
|
12
|
-
* The shadcn preset's own vocabulary needs no custom `tailwind-merge`
|
|
13
|
-
* configuration — unlike v1's `--text-*` scale, none of its names collide
|
|
14
|
-
* with a stock Tailwind class group — so this is the bare merge, the same
|
|
15
|
-
* shape the CLI scratch's own `lib/utils.ts` ships.
|
|
16
|
-
*/
|
|
17
|
-
import { clsx } from "clsx";
|
|
18
|
-
import { twMerge } from "tailwind-merge";
|
|
19
|
-
export function cn(...inputs) {
|
|
20
|
-
return twMerge(clsx(inputs));
|
|
21
|
-
}
|
package/dist/lib/menu.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const menuSurface = "data-closed:animate-none! w-auto";
|
package/dist/lib/menu.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// What every `DropdownMenuContent` call site adds to the canonical surface, in
|
|
2
|
-
// one constant because both halves are the same rule — a menu that behaves like
|
|
3
|
-
// a menu (DESIGN.md, Motion).
|
|
4
|
-
//
|
|
5
|
-
// `data-closed:animate-none!`: a menu surface leaves on the frame it is
|
|
6
|
-
// dismissed. While Radix runs an exit animation the dismissable layer stays
|
|
7
|
-
// mounted, and a press that should open the next menu is swallowed as the
|
|
8
|
-
// dismissal of this one.
|
|
9
|
-
//
|
|
10
|
-
// `w-auto`: a menu sizes to its items, not to its trigger. Canonical carries
|
|
11
|
-
// `w-(--radix-dropdown-menu-trigger-width) min-w-32`, which pins the surface to
|
|
12
|
-
// the trigger — behind an icon-sized button that is the 128px floor, and every
|
|
13
|
-
// item longer than that wraps (the row actions on ModelsScreen, the Annotate
|
|
14
|
-
// picker). `min-w-32` survives as the floor it was meant to be, because
|
|
15
|
-
// tailwind-merge replaces only the `w-*` in the same utility group.
|
|
16
|
-
export const menuSurface = "data-closed:animate-none! w-auto";
|
package/dist/lib/progress.d.ts
DELETED
package/dist/lib/progress.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// Canonical `Progress` reads `value` only to size the indicator and never
|
|
2
|
-
// forwards it to Radix's `Root`, so the number a screen reader would announce
|
|
3
|
-
// is otherwise never rendered at all — a caller that needs it says so again here.
|
|
4
|
-
export function progressAria(value) {
|
|
5
|
-
return { "aria-valuenow": value };
|
|
6
|
-
}
|
package/dist/lib/select.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const twoLineTrigger = "data-[size=default]:h-auto min-h-8 *:data-[slot=select-value]:line-clamp-none";
|
package/dist/lib/select.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// A two-line option needs the closed trigger to grow and to stop clamping its
|
|
2
|
-
// value; both overrides name canonical's own variants so the merge replaces them.
|
|
3
|
-
export const twoLineTrigger = "data-[size=default]:h-auto min-h-8 *:data-[slot=select-value]:line-clamp-none";
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Progress as ProgressPrimitive } from "radix-ui";
|
|
3
|
-
import { cn } from "../lib/cn.js";
|
|
4
|
-
function Progress({ className, value, ...props }) {
|
|
5
|
-
return (_jsx(ProgressPrimitive.Root, { "data-slot": "progress", className: cn("relative flex h-1 w-full items-center overflow-x-hidden rounded-full bg-muted", className), ...props, children: _jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: "size-full flex-1 bg-primary transition-all", style: { transform: `translateX(-${100 - (value || 0)}%)` } }) }));
|
|
6
|
-
}
|
|
7
|
-
export { Progress };
|
package/gates/canonical.test.mjs
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { test } from "node:test";
|
|
6
|
-
import { relativize } from "../scripts/shadcn_relativize.mjs";
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
ADAPTER_REMOVED_LINES,
|
|
10
|
-
additiveOnly,
|
|
11
|
-
checkAdapter,
|
|
12
|
-
withoutLines,
|
|
13
|
-
} from "./index.mjs";
|
|
14
|
-
|
|
15
|
-
const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
16
|
-
const PRIMITIVES = path.join(REPO, "src/primitives");
|
|
17
|
-
const SNAPSHOTS = path.join(REPO, "shadcn");
|
|
18
|
-
|
|
19
|
-
test("additiveOnly accepts an added line and refuses a changed one", () => {
|
|
20
|
-
assert.equal(additiveOnly("a\nb\n", "a\nx\nb\n").ok, true);
|
|
21
|
-
assert.equal(additiveOnly("a\nb\n", "a\nB\n").ok, false);
|
|
22
|
-
assert.equal(additiveOnly("a\nb\n", "b\na\n").ok, false);
|
|
23
|
-
assert.equal(additiveOnly("a\n\nb\n", "a\nb\n").ok, false);
|
|
24
|
-
assert.equal(additiveOnly("a\r\nb \r\n", "a\nb\n").ok, true);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test("checkAdapter refuses an unlisted file carrying the marker", () => {
|
|
28
|
-
const result = checkAdapter("unlisted.tsx", "// SHADCN FRAMEWORK ADAPTER\nconst x = 1\n");
|
|
29
|
-
assert.equal(result.ok, false);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test("checkAdapter accepts a listed file carrying the marker", () => {
|
|
33
|
-
const result = checkAdapter("sonner.tsx", "// SHADCN FRAMEWORK ADAPTER\nconst x = 1\n");
|
|
34
|
-
assert.deepEqual(result, { ok: true, isAdapter: true });
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("checkAdapter ignores a file with no marker even if unlisted", () => {
|
|
38
|
-
const result = checkAdapter("unlisted.tsx", "const x = 1\n");
|
|
39
|
-
assert.deepEqual(result, { ok: true, isAdapter: false });
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("a listed adapter passes when only the two next-themes lines are removed", () => {
|
|
43
|
-
const snapshot = 'import { useTheme } from "next-themes"\nconst x = 1\n const { theme = "system" } = useTheme()\nconst y = 2\n';
|
|
44
|
-
const actual = "// SHADCN FRAMEWORK ADAPTER\nconst x = 1\nconst y = 2\n";
|
|
45
|
-
const result = additiveOnly(withoutLines(relativize(snapshot), ADAPTER_REMOVED_LINES), actual);
|
|
46
|
-
assert.equal(result.ok, true);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test("a listed adapter that also drops a different snapshot line still fails", () => {
|
|
50
|
-
const snapshot = 'import { useTheme } from "next-themes"\nconst x = 1\n const { theme = "system" } = useTheme()\nconst y = 2\n';
|
|
51
|
-
const actual = "// SHADCN FRAMEWORK ADAPTER\nconst y = 2\n"; // "const x = 1" went missing too
|
|
52
|
-
const result = additiveOnly(withoutLines(relativize(snapshot), ADAPTER_REMOVED_LINES), actual);
|
|
53
|
-
assert.equal(result.ok, false);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const primitives = readdirSync(PRIMITIVES).filter((f) => f.endsWith(".tsx") && !f.endsWith(".test.tsx"));
|
|
57
|
-
|
|
58
|
-
for (const file of primitives) {
|
|
59
|
-
test(`${file} is shadcn's canonical file plus added lines only`, () => {
|
|
60
|
-
const snapshot = path.join(SNAPSHOTS, file);
|
|
61
|
-
assert.ok(existsSync(snapshot), `${file} has no snapshot in shadcn/ — install it with pnpm shadcn:add`);
|
|
62
|
-
const snapshotText = relativize(readFileSync(snapshot, "utf8"));
|
|
63
|
-
const actualText = readFileSync(path.join(PRIMITIVES, file), "utf8");
|
|
64
|
-
const adapter = checkAdapter(file, actualText);
|
|
65
|
-
assert.ok(adapter.ok, adapter.reason);
|
|
66
|
-
const result = adapter.isAdapter
|
|
67
|
-
? additiveOnly(withoutLines(snapshotText, ADAPTER_REMOVED_LINES), actualText)
|
|
68
|
-
: additiveOnly(snapshotText, actualText);
|
|
69
|
-
assert.ok(result.ok, `${file} diverges from its snapshot at: ${result.missing}`);
|
|
70
|
-
});
|
|
71
|
-
}
|