@nebutra/tokens 0.1.2 → 2.0.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 (72) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/brands/README.md +66 -0
  3. package/brands/cosmos/DESIGN.md +356 -0
  4. package/brands/cosmos/brand.json +209 -0
  5. package/brands/cosmos/refero-tokens.json +312 -0
  6. package/brands/gsap/brand.json +18 -91
  7. package/brands/linear/DESIGN.md +478 -0
  8. package/brands/linear/brand.json +20 -76
  9. package/brands/notion/brand.json +20 -90
  10. package/brands/raycast/brand.json +19 -81
  11. package/brands/stripe/brand.json +17 -88
  12. package/brands/vanta/brand.json +17 -101
  13. package/brands/vercel/brand.json +17 -68
  14. package/dist/brand-package/index.d.ts +123 -0
  15. package/dist/brand-package/index.js +2316 -0
  16. package/dist/brand-package/index.js.map +1 -0
  17. package/dist/brand-package/use-brand.d.ts +2 -0
  18. package/dist/brand-package/use-brand.js +963 -0
  19. package/dist/brand-package/use-brand.js.map +1 -0
  20. package/dist/index.d.ts +81 -0
  21. package/dist/index.js +2581 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/use-brand-ClmvK_lC.d.ts +387 -0
  24. package/package.json +41 -10
  25. package/recipe.css +330 -1
  26. package/skins/README.md +2 -4
  27. package/skins/cosmos.css +239 -0
  28. package/skins/gsap.css +62 -138
  29. package/skins/linear.css +85 -132
  30. package/skins/notion.css +62 -141
  31. package/skins/raycast.css +68 -137
  32. package/skins/stripe.css +60 -143
  33. package/skins/vanta.css +60 -151
  34. package/skins/vercel.css +83 -128
  35. package/styles.css +477 -115
  36. package/.turbo/turbo-build.log +0 -8
  37. package/.turbo/turbo-typecheck.log +0 -4
  38. package/AGENTS.md +0 -45
  39. package/DESIGN.md +0 -357
  40. package/scripts/compile-brand-run.ts +0 -79
  41. package/scripts/compile-brand.mjs +0 -25
  42. package/scripts/emit-skins-run.ts +0 -62
  43. package/scripts/emit-skins.mjs +0 -31
  44. package/scripts/sync-styles.mjs +0 -29
  45. package/src/brand-package/__tests__/compile-refero.test.ts +0 -427
  46. package/src/brand-package/__tests__/emit-css.test.ts +0 -130
  47. package/src/brand-package/apply-brand.ts +0 -92
  48. package/src/brand-package/compile-helpers.ts +0 -170
  49. package/src/brand-package/compile-refero.ts +0 -69
  50. package/src/brand-package/emit-css.ts +0 -468
  51. package/src/brand-package/hex-to-hsl.ts +0 -100
  52. package/src/brand-package/index.ts +0 -71
  53. package/src/brand-package/infer-recipe.ts +0 -198
  54. package/src/brand-package/normalize.ts +0 -295
  55. package/src/brand-package/presets/context.ts +0 -17
  56. package/src/brand-package/presets/generic.ts +0 -214
  57. package/src/brand-package/presets/gsap.ts +0 -146
  58. package/src/brand-package/presets/index.ts +0 -31
  59. package/src/brand-package/presets/linear.ts +0 -183
  60. package/src/brand-package/presets/notion.ts +0 -208
  61. package/src/brand-package/presets/raycast.ts +0 -138
  62. package/src/brand-package/presets/recipe.ts +0 -61
  63. package/src/brand-package/presets/stripe.ts +0 -207
  64. package/src/brand-package/presets/vanta.ts +0 -220
  65. package/src/brand-package/presets/vercel.ts +0 -187
  66. package/src/brand-package/types.ts +0 -285
  67. package/src/brand-package/use-brand.ts +0 -207
  68. package/src/brand-package/validate.ts +0 -108
  69. package/src/index.ts +0 -67
  70. package/src/theme-provider.tsx +0 -246
  71. package/tsconfig.json +0 -11
  72. package/turbo.json +0 -15
@@ -1,170 +0,0 @@
1
- /**
2
- * Shared helpers for Refero → Brand Package compilation.
3
- * Preset builders live in compile-refero.ts; keep color/font extraction here.
4
- */
5
-
6
- export type Json = Record<string, unknown>;
7
-
8
- export type PresetId =
9
- | "linear"
10
- | "gsap"
11
- | "raycast"
12
- | "vercel"
13
- | "vanta"
14
- | "stripe"
15
- | "notion"
16
- | "generic";
17
-
18
- export function leafHex(tree: Json | undefined, path: string[]): string | undefined {
19
- let cur: unknown = tree;
20
- for (const p of path) {
21
- if (!cur || typeof cur !== "object") return undefined;
22
- cur = (cur as Json)[p];
23
- }
24
- if (!cur || typeof cur !== "object") return undefined;
25
- const v = (cur as Json).$value ?? (cur as Json).value;
26
- return typeof v === "string" ? v : undefined;
27
- }
28
-
29
- export function detectPreset(idHint: string, colors: Record<string, string>): PresetId {
30
- const id = idHint.toLowerCase();
31
- if (id.includes("linear")) return "linear";
32
- if (id.includes("gsap")) return "gsap";
33
- if (id.includes("raycast")) return "raycast";
34
- if (id.includes("vercel")) return "vercel";
35
- if (id.includes("vanta")) return "vanta";
36
- if (id.includes("stripe")) return "stripe";
37
- if (id.includes("notion")) return "notion";
38
- // Heuristics from Refero extractions
39
- if (colors["paper-white"] && colors.obsidian && colors.hairline) return "vercel";
40
- if (colors["coral-pulse"] || (colors["void-black"] && colors.mist && colors.ink)) {
41
- return "raycast";
42
- }
43
- if (colors["acid-lime"] || colors.void) return "linear";
44
- if (colors["shockingly-green"] || colors["surface-cream"] || colors["just-black"]) return "gsap";
45
- if (colors["just-black"] && colors["surface-cream"]) return "gsap";
46
- // Notion: warm paper canvas + single blue CTA + ink hierarchy
47
- if (
48
- (colors["notion-blue"] || colors["paper-warmth"]) &&
49
- (colors["paper-warmth"] || colors["ink-black"]) &&
50
- (colors["sky-tint"] || colors.marigold || colors.coral)
51
- ) {
52
- return "notion";
53
- }
54
- // Stripe: indigo-ink action + pure-white canvas + frost borders + midnight text
55
- if (
56
- colors["indigo-ink"] &&
57
- colors["pure-white"] &&
58
- (colors.frost || colors["lavender-border"] || colors["midnight-ink"]) &&
59
- !colors["paper-warmth"]
60
- ) {
61
- return "stripe";
62
- }
63
- // Vanta: indigo-ink as logo + vivid-violet CTA + parchment (not pure-white ledger)
64
- if (
65
- (colors["indigo-ink"] || colors["vivid-violet"]) &&
66
- (colors.parchment || colors["lavender-wash"] || colors.paper) &&
67
- !colors["pure-white"]
68
- ) {
69
- return "vanta";
70
- }
71
- return "generic";
72
- }
73
-
74
- /** First font family leaf that is UI/sans (not display/serif display faces). */
75
- export function pickUiFontFamily(font: Json): string | undefined {
76
- const preferUi = /(inter|geist|manrope|dm sans|sans|ui)/i;
77
- const avoidDisplay = /(reckless|serif|display|editorial|playfair|lora|source serif)/i;
78
- const entries = Object.entries(font);
79
- for (const [k, v] of entries) {
80
- if (!v || typeof v !== "object") continue;
81
- const name = String((v as Json).$value ?? (v as Json).value ?? "");
82
- if (!name || avoidDisplay.test(k) || avoidDisplay.test(name)) continue;
83
- if (preferUi.test(k) || preferUi.test(name) || entries.length === 1) return name;
84
- }
85
- for (const [k, v] of entries) {
86
- if (!v || typeof v !== "object") continue;
87
- const name = String((v as Json).$value ?? (v as Json).value ?? "");
88
- if (name && !avoidDisplay.test(k) && !avoidDisplay.test(name)) return name;
89
- }
90
- return undefined;
91
- }
92
-
93
- export function pickDisplayFontFamily(font: Json): string | undefined {
94
- const prefer = /(reckless|serif|display|editorial|playfair|lora|source serif|mori)/i;
95
- for (const [k, v] of Object.entries(font)) {
96
- if (!v || typeof v !== "object") continue;
97
- const name = String((v as Json).$value ?? (v as Json).value ?? "");
98
- if (name && (prefer.test(k) || prefer.test(name))) return name;
99
- }
100
- return undefined;
101
- }
102
-
103
- /**
104
- * shadcn / Appearance / playground token names → keys generic + presets already pick.
105
- * Kebab and camel both land on the same slot so compileReferoTokens works for imports.
106
- */
107
- const COLOR_KEY_ALIASES: Record<string, string[]> = {
108
- background: ["background", "canvas", "page-canvas"],
109
- foreground: ["foreground", "ink", "ink-black"],
110
- card: ["card", "card-surface", "surface"],
111
- "card-foreground": ["card-foreground"],
112
- cardForeground: ["card-foreground"],
113
- primary: ["primary", "action"],
114
- "primary-foreground": ["primary-foreground"],
115
- primaryForeground: ["primary-foreground"],
116
- secondary: ["secondary", "quiet"],
117
- "secondary-foreground": ["secondary-foreground"],
118
- secondaryForeground: ["secondary-foreground"],
119
- muted: ["muted"],
120
- "muted-foreground": ["muted-foreground", "mutedForeground", "stone"],
121
- mutedForeground: ["muted-foreground", "stone"],
122
- accent: ["accent"],
123
- "accent-foreground": ["accent-foreground"],
124
- accentForeground: ["accent-foreground"],
125
- border: ["border", "hairline"],
126
- input: ["input"],
127
- ring: ["ring"],
128
- destructive: ["destructive"],
129
- "destructive-foreground": ["destructive-foreground"],
130
- destructiveForeground: ["destructive-foreground"],
131
- success: ["success"],
132
- popover: ["popover"],
133
- "popover-foreground": ["popover-foreground"],
134
- popoverForeground: ["popover-foreground"],
135
- };
136
-
137
- function isUsableColorValue(val: string): boolean {
138
- const t = val.trim();
139
- if (!t) return false;
140
- if (t.startsWith("#")) return true;
141
- if (/^\d+(\.\d+)?\s+\d+(\.\d+)?%\s+\d+(\.\d+)?%$/.test(t)) return true;
142
- if (/^hsla?\(/i.test(t) || /^rgba?\(/i.test(t)) return true;
143
- // oklch/lab left out of compile path (no reliable SSR convert); Appearance still has canvas probe
144
- return false;
145
- }
146
-
147
- export function collectColors(colorRoot: Json | undefined): Record<string, string> {
148
- const raw: Record<string, string> = {};
149
- if (!colorRoot || typeof colorRoot !== "object") return raw;
150
- for (const [k, v] of Object.entries(colorRoot)) {
151
- if (!v || typeof v !== "object") continue;
152
- const val = (v as Json).$value ?? (v as Json).value;
153
- if (typeof val === "string" && isUsableColorValue(val)) raw[k] = val.trim();
154
- }
155
-
156
- // Expand aliases so shadcn-named imports hit preset pick() keys
157
- const out: Record<string, string> = { ...raw };
158
- for (const [key, value] of Object.entries(raw)) {
159
- const aliases = COLOR_KEY_ALIASES[key];
160
- if (!aliases) continue;
161
- for (const alias of aliases) {
162
- if (!out[alias]) out[alias] = value;
163
- }
164
- }
165
- return out;
166
- }
167
-
168
- export function collectSurfaces(surfaceRoot: Json | undefined): Record<string, string> {
169
- return collectColors(surfaceRoot as Json | undefined);
170
- }
@@ -1,69 +0,0 @@
1
- /**
2
- * Compile Refero DTCG tokens.json (+ optional DESIGN.md) into a Brand Package.
3
- *
4
- * Structure:
5
- * compile-helpers.ts — detectPreset, color/font leaf helpers
6
- * presets/* — named fixture builders (linear…notion) + generic
7
- * compile-refero.ts — orchestration only
8
- *
9
- * Named fixtures are stress-test carriers (not mood presets). Prefer extending
10
- * the generic path + DESIGN.md inference over adding one-off hacks.
11
- */
12
-
13
- import { collectColors, collectSurfaces, detectPreset, type Json } from "./compile-helpers";
14
- import { emitBrandCss } from "./emit-css";
15
- import { inferRecipeFromDesignMd } from "./infer-recipe";
16
- import { normalizeBrandPackage } from "./normalize";
17
- import { buildPresetBrand } from "./presets";
18
- import type { BrandPackage, CompileResult } from "./types";
19
-
20
- function finish(brand: BrandPackage, warnings: string[]): CompileResult {
21
- const b = normalizeBrandPackage(brand);
22
- return { brand: b, css: emitBrandCss(b), warnings };
23
- }
24
-
25
- /**
26
- * Compile a Refero-style DTCG tokens.json (+ optional DESIGN.md text) into a Brand Package.
27
- * Known fixtures get opinionated recipes; generic brands get solid CTAs.
28
- */
29
- export function compileReferoTokens(input: {
30
- tokens: Json;
31
- id?: string;
32
- name?: string;
33
- designMd?: string;
34
- }): CompileResult {
35
- const warnings: string[] = [];
36
- const color = (input.tokens.color ?? {}) as Json;
37
- const surface = (input.tokens.surface ?? {}) as Json;
38
- const font = (input.tokens.font ?? {}) as Json;
39
- const radius = (input.tokens.radius ?? {}) as Json;
40
- const ext = (input.tokens.$extensions ?? {}) as Json;
41
- const refero = (ext["com.refero.extraction"] ?? {}) as Json;
42
-
43
- const colors = { ...collectColors(color), ...collectSurfaces(surface) };
44
- const siteName =
45
- (typeof refero.siteName === "string" && refero.siteName) || input.name || "Custom Brand";
46
- const id =
47
- input.id ||
48
- siteName
49
- .toLowerCase()
50
- .replace(/[^a-z0-9]+/g, "-")
51
- .replace(/^-|-$/g, "") ||
52
- "custom";
53
-
54
- const preset = detectPreset(id, colors);
55
- const recipeHints = inferRecipeFromDesignMd(input.designMd ?? "");
56
-
57
- const brand = buildPresetBrand(preset, {
58
- colors,
59
- font,
60
- radius,
61
- refero,
62
- recipeHints,
63
- warnings,
64
- id,
65
- siteName,
66
- });
67
-
68
- return finish(brand, warnings);
69
- }