@usetheo/ui 0.4.0-next.0 → 0.5.1-next.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/CHANGELOG.md +118 -0
- package/dist/preset-v3-legacy.d.ts +35 -0
- package/dist/preset-v3-legacy.js +159 -0
- package/dist/preset-v3-legacy.js.map +1 -0
- package/dist/preset.css +27 -0
- package/dist/styles-v3-legacy.css +88 -0
- package/dist/styles.css +22 -5
- package/dist/tokens-v4.css +187 -0
- package/dist/vite-plugin.d.ts +29 -0
- package/dist/vite-plugin.js +72 -0
- package/dist/vite-plugin.js.map +1 -0
- package/package.json +28 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,124 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.1-next.0] - 2026-05-22
|
|
11
|
+
|
|
12
|
+
Patch — RFC 0008 follow-up. The 0.5.0-next.0 release declared `tailwindcss@^4`
|
|
13
|
+
as a peer dependency and shipped the `./vite-plugin` + `./preset` subpaths,
|
|
14
|
+
but the actual CSS / token / preset artifacts inside the tarball were still
|
|
15
|
+
Tailwind v3 internally. Result: every TheoKit consumer of 0.5.0-next.0 booted
|
|
16
|
+
with unstyled UI in dev and production — `bg-primary`, `text-muted-foreground`,
|
|
17
|
+
`border-border`, `text-body-sm`, etc. emitted as className strings with no
|
|
18
|
+
matching CSS rule.
|
|
19
|
+
|
|
20
|
+
This release rewrites the three v3-shaped artifacts to v4-native syntax and
|
|
21
|
+
ships a fixture-backed real-build dogfood so the regression cannot recur.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **`dist/styles.css` is now Tailwind v4 native.** Uses `@import "tailwindcss"`
|
|
26
|
+
(replaces the v3 `@tailwind base; @tailwind components; @tailwind utilities;`
|
|
27
|
+
trio that Tailwind v4 emits as literal strings, with zero utility generation).
|
|
28
|
+
Imports `tokens.css` (runtime cascade) AND `tokens-v4.css` (`@theme` namespace)
|
|
29
|
+
so consumers' Tailwind v4 build resolves both layers correctly. Same
|
|
30
|
+
`@layer base` content (border-color, body font, focus ring, scrollbar
|
|
31
|
+
styling) as before. (#TBD)
|
|
32
|
+
- **`./preset` subpath is now a CSS file.** Tailwind v4 dropped the v3 JS
|
|
33
|
+
preset format — `theme.extend.colors.{name}` declarations are a no-op for
|
|
34
|
+
v4. The new `dist/preset.css` simply chains `@import "./tokens.css"` and
|
|
35
|
+
`@import "./tokens-v4.css"` so consumers can `@import "@usetheo/ui/preset.css"`
|
|
36
|
+
from their own Tailwind v4 entry CSS. (#TBD)
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- **`@usetheo/ui/tokens-v4.css` (NEW)** — `@theme {}` block declaring 28
|
|
41
|
+
`--color-*` aliases (full color set), 14 `--text-*` typescale tiers
|
|
42
|
+
(Violet Forge — `--text-display-2xl` through `--text-code-sm` with companion
|
|
43
|
+
`--*--line-height`, `--*--letter-spacing`, `--*--font-weight`), 3 `--font-*`
|
|
44
|
+
family tokens, 7 `--radius-*` tiers, 5 `--shadow-*` levels, 3 `--ease-*`
|
|
45
|
+
timings, and 2 `--animate-*` keyframe-bound utilities. Every color alias
|
|
46
|
+
uses `hsl(var(--*))` indirection so `<ThemeProvider>`'s runtime
|
|
47
|
+
`[data-theme]` cascade keeps working — switching themes still recolors
|
|
48
|
+
every utility. (#TBD)
|
|
49
|
+
- **`@usetheo/ui/styles-v3-legacy.css` (NEW)** — the previous v3-shaped
|
|
50
|
+
`@tailwind base/components/utilities` entry. Pinned consumers on
|
|
51
|
+
`tailwindcss@^3` who still want a prebuilt stylesheet can import this
|
|
52
|
+
subpath. New code SHOULD use `@usetheo/ui/styles.css` (v4) instead.
|
|
53
|
+
- **`@usetheo/ui/preset-v3-legacy` (NEW)** — the v3 JS `Partial<Config>`
|
|
54
|
+
preset that previously lived at `./preset`. Renamed so the canonical
|
|
55
|
+
`./preset` subpath can host the v4 CSS preset. v3 consumers update
|
|
56
|
+
imports from `@usetheo/ui/preset` to `@usetheo/ui/preset-v3-legacy`.
|
|
57
|
+
- **Dogfood scripts** — `pnpm dogfood:v4-zero-config` (shape check, runs in
|
|
58
|
+
`quality:gates`) and `pnpm dogfood:v4-real-build` (end-to-end: packs the
|
|
59
|
+
tarball, installs in a tmp project alongside `@tailwindcss/cli@^4`, runs
|
|
60
|
+
Tailwind v4 against `tests/fixtures/v4-zero-config/`, and grep-asserts the
|
|
61
|
+
expected utility classes appear in the emitted CSS — 12 assertions). The
|
|
62
|
+
real-build dogfood is opt-in (slow, requires network) but catches any
|
|
63
|
+
future regression where v3-shaped artifacts get shipped under a v4 peer
|
|
64
|
+
declaration. (#TBD)
|
|
65
|
+
|
|
66
|
+
### Notes
|
|
67
|
+
|
|
68
|
+
- **Breaking for any 0.5.0-next.0 consumer.** The `./preset` subpath changed
|
|
69
|
+
from JS (`Partial<Config>` default-export) to CSS file. Code importing
|
|
70
|
+
`import preset from "@usetheo/ui/preset"` will break and must migrate to
|
|
71
|
+
`@import "@usetheo/ui/preset.css"` in an entry CSS. Blast radius: TheoKit
|
|
72
|
+
(already reverted away from 0.5.x by the time this fix shipped) plus any
|
|
73
|
+
community consumer that adopted 0.5.0-next.0 in the same day — likely zero.
|
|
74
|
+
- The runtime indirection via `hsl(var(--*))` aliases keeps `<ThemeProvider>`
|
|
75
|
+
and every built-in theme (`violet-forge`, `dracula`, `vercel-mono`, etc.)
|
|
76
|
+
working with zero changes — the v4 utilities transparently follow the v3
|
|
77
|
+
cascade.
|
|
78
|
+
|
|
79
|
+
## [0.5.0-next.0] - 2026-05-22
|
|
80
|
+
|
|
81
|
+
Minor bump — public API gains two subpath exports (`./vite-plugin` and
|
|
82
|
+
`./preset`) so the TheoKit framework's `integrateUseTheoUI()` can
|
|
83
|
+
auto-wire Tailwind v4 for consumers with zero further configuration.
|
|
84
|
+
Zero visual break and no runtime behavior change for existing consumers.
|
|
85
|
+
|
|
86
|
+
### Added
|
|
87
|
+
|
|
88
|
+
- **`@usetheo/ui/vite-plugin` (NEW, RFC 0008)** — Default-export factory
|
|
89
|
+
returning one Vite `Plugin`. The plugin's `config()` hook
|
|
90
|
+
dynamic-imports `@tailwindcss/vite` v4 and chains it into the
|
|
91
|
+
consumer's plugin array when resolvable, and degrades to `console.warn`
|
|
92
|
+
+ CSS-only mode (via the pre-built `@usetheo/ui/styles.css` subpath)
|
|
93
|
+
when the peer is not installed. A virtual module
|
|
94
|
+
`virtual:@usetheo/ui/library-sources.css` provides the `@source`
|
|
95
|
+
directive covering `node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}`
|
|
96
|
+
so Tailwind scans the library's published JS for utilities. Plugin
|
|
97
|
+
name slug: `@usetheo/ui/vite-plugin`. Options: `tailwind?: boolean`
|
|
98
|
+
(default `true`), `contentExtra?: string[]` (extra `@source` globs).
|
|
99
|
+
(#TBD)
|
|
100
|
+
- **`@usetheo/ui/preset` (NEW, RFC 0008)** — Default-export Tailwind v4
|
|
101
|
+
`Partial<Config>` mirroring the design tokens in `tokens.css`
|
|
102
|
+
(colors via `hsl(var(--x) / <alpha-value>)`, font families, the
|
|
103
|
+
Violet Forge typescale, radii, shadows, animations, motion timing)
|
|
104
|
+
with `content` paths covering `./node_modules/@usetheo/ui/dist/**` and
|
|
105
|
+
the `tailwindcss-animate` plugin. Consumer usage:
|
|
106
|
+
`import preset from "@usetheo/ui/preset"; export default { presets: [preset] }`.
|
|
107
|
+
Internally delegates to the existing `src/styles/tailwind-preset.ts` —
|
|
108
|
+
the v3 shadcn-registry preset and the v4 import preset stay
|
|
109
|
+
byte-for-byte aligned and impossible to drift. (#TBD)
|
|
110
|
+
- **`@tailwindcss/vite ^4`, `tailwindcss ^4`, `vite ^6 || ^7` peer-deps
|
|
111
|
+
(all optional)** — added to `peerDependenciesMeta` so consumers
|
|
112
|
+
importing `@usetheo/ui` standalone (no framework) are not forced into
|
|
113
|
+
Tailwind v4. Required only when consuming via TheoKit's auto-wire path
|
|
114
|
+
or the new `./vite-plugin` subpath. (#TBD)
|
|
115
|
+
|
|
116
|
+
### Notes
|
|
117
|
+
|
|
118
|
+
- Existing `tailwindcss@^3` consumers continue to work via the shadcn
|
|
119
|
+
registry preset (`registry/r/tailwind-preset.json`) and the prebuilt
|
|
120
|
+
`@usetheo/ui/styles.css`. The new subpaths are additive — they do not
|
|
121
|
+
break v3-based setups.
|
|
122
|
+
- The `vite-plugin` returns ONE `Plugin` object (not `Plugin[]`) per the
|
|
123
|
+
cross-repo contract with TheoKit's `integrateUseTheoUI()`. The chain
|
|
124
|
+
to `@tailwindcss/vite` happens via the `config()` hook's `plugins`
|
|
125
|
+
field — Vite 5+ tightened the TypeScript signature, the runtime still
|
|
126
|
+
merges plugins as expected.
|
|
127
|
+
|
|
10
128
|
## [0.4.0-next.0] - 2026-05-22
|
|
11
129
|
|
|
12
130
|
Minor bump — public API gains 7 new theme exports. Zero visual break for
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Config } from 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `@usetheo/ui/preset-v3-legacy` — Tailwind v3 JS preset (legacy path).
|
|
5
|
+
*
|
|
6
|
+
* Default-export a `Partial<Config>` mirroring the design tokens shipped
|
|
7
|
+
* in `@usetheo/ui/tokens.css`. Adds a `content` field covering the
|
|
8
|
+
* library's published artifact tree so v3-based Tailwind builds emit
|
|
9
|
+
* the utilities used by `@usetheo/ui` components.
|
|
10
|
+
*
|
|
11
|
+
* **Tailwind v4 consumers MUST use `@usetheo/ui/preset.css`**, not this
|
|
12
|
+
* file — Tailwind v4 dropped the JS preset format entirely. This file
|
|
13
|
+
* exists for any remaining `tailwindcss@^3` consumer (notably the
|
|
14
|
+
* shadcn-style copy-paste registry path); new code should not import
|
|
15
|
+
* from this subpath.
|
|
16
|
+
*
|
|
17
|
+
* The token surface is delegated to `./styles/tailwind-preset.ts` (the
|
|
18
|
+
* existing source of truth used by the local Ladle dev surface and the
|
|
19
|
+
* shadcn registry).
|
|
20
|
+
*
|
|
21
|
+
* v3 consumer usage:
|
|
22
|
+
*
|
|
23
|
+
* // tailwind.config.ts (Tailwind v3 only)
|
|
24
|
+
* import preset from "@usetheo/ui/preset-v3-legacy";
|
|
25
|
+
* export default {
|
|
26
|
+
* presets: [preset],
|
|
27
|
+
* content: ["./app/**\/*.{ts,tsx}"],
|
|
28
|
+
* };
|
|
29
|
+
*
|
|
30
|
+
* See RFC 0008 follow-up.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
declare const preset: Partial<Config>;
|
|
34
|
+
|
|
35
|
+
export { preset as default };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import animate from 'tailwindcss-animate';
|
|
2
|
+
|
|
3
|
+
// src/styles/tailwind-preset.ts
|
|
4
|
+
var hsl = (token) => `hsl(var(${token}) / <alpha-value>)`;
|
|
5
|
+
var theoUIPreset = {
|
|
6
|
+
theme: {
|
|
7
|
+
container: {
|
|
8
|
+
center: true,
|
|
9
|
+
padding: "1rem",
|
|
10
|
+
screens: {
|
|
11
|
+
"2xl": "1280px"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
extend: {
|
|
15
|
+
colors: {
|
|
16
|
+
background: hsl("--background"),
|
|
17
|
+
foreground: hsl("--foreground"),
|
|
18
|
+
card: {
|
|
19
|
+
DEFAULT: hsl("--card"),
|
|
20
|
+
foreground: hsl("--card-foreground")
|
|
21
|
+
},
|
|
22
|
+
popover: {
|
|
23
|
+
DEFAULT: hsl("--popover"),
|
|
24
|
+
foreground: hsl("--popover-foreground")
|
|
25
|
+
},
|
|
26
|
+
primary: {
|
|
27
|
+
DEFAULT: hsl("--primary"),
|
|
28
|
+
deep: hsl("--primary-deep"),
|
|
29
|
+
glow: hsl("--primary-glow"),
|
|
30
|
+
foreground: hsl("--primary-foreground")
|
|
31
|
+
},
|
|
32
|
+
secondary: {
|
|
33
|
+
DEFAULT: hsl("--secondary"),
|
|
34
|
+
foreground: hsl("--secondary-foreground")
|
|
35
|
+
},
|
|
36
|
+
accent: {
|
|
37
|
+
DEFAULT: hsl("--accent"),
|
|
38
|
+
deep: hsl("--accent-deep"),
|
|
39
|
+
foreground: hsl("--accent-foreground")
|
|
40
|
+
},
|
|
41
|
+
muted: {
|
|
42
|
+
DEFAULT: hsl("--muted"),
|
|
43
|
+
foreground: hsl("--muted-foreground")
|
|
44
|
+
},
|
|
45
|
+
success: {
|
|
46
|
+
DEFAULT: hsl("--success"),
|
|
47
|
+
foreground: hsl("--success-foreground")
|
|
48
|
+
},
|
|
49
|
+
warning: {
|
|
50
|
+
DEFAULT: hsl("--warning"),
|
|
51
|
+
foreground: hsl("--warning-foreground")
|
|
52
|
+
},
|
|
53
|
+
destructive: {
|
|
54
|
+
DEFAULT: hsl("--destructive"),
|
|
55
|
+
foreground: hsl("--destructive-foreground")
|
|
56
|
+
},
|
|
57
|
+
info: {
|
|
58
|
+
DEFAULT: hsl("--info"),
|
|
59
|
+
foreground: hsl("--info-foreground")
|
|
60
|
+
},
|
|
61
|
+
border: hsl("--border"),
|
|
62
|
+
input: hsl("--input"),
|
|
63
|
+
ring: hsl("--ring")
|
|
64
|
+
},
|
|
65
|
+
fontFamily: {
|
|
66
|
+
display: "var(--font-display)",
|
|
67
|
+
sans: "var(--font-body)",
|
|
68
|
+
mono: "var(--font-mono)"
|
|
69
|
+
},
|
|
70
|
+
/* Geist-inspired Violet Forge typescale.
|
|
71
|
+
*
|
|
72
|
+
* Three strict weights: 400 (body), 500 (UI), 600 (display/headings).
|
|
73
|
+
* Letter-spacing scales with size — aggressive negative on display.
|
|
74
|
+
* Mirrors the Vercel/Geist vocabulary while keeping Theo's identity.
|
|
75
|
+
*/
|
|
76
|
+
fontSize: {
|
|
77
|
+
// Display tier — aggressive compression, content-led headlines
|
|
78
|
+
"display-2xl": ["64px", { lineHeight: "1", letterSpacing: "-0.0464em", fontWeight: "600" }],
|
|
79
|
+
"display-xl": ["48px", { lineHeight: "1.05", letterSpacing: "-0.05em", fontWeight: "600" }],
|
|
80
|
+
"display-lg": ["40px", { lineHeight: "1.1", letterSpacing: "-0.05em", fontWeight: "600" }],
|
|
81
|
+
"display-md": ["32px", { lineHeight: "1.2", letterSpacing: "-0.04em", fontWeight: "600" }],
|
|
82
|
+
headline: ["28px", { lineHeight: "1.25", letterSpacing: "-0.035em", fontWeight: "600" }],
|
|
83
|
+
// Title tier — section / card heads
|
|
84
|
+
"title-lg": ["24px", { lineHeight: "1.33", letterSpacing: "-0.04em", fontWeight: "600" }],
|
|
85
|
+
"title-md": ["20px", { lineHeight: "1.4", letterSpacing: "-0.03em", fontWeight: "600" }],
|
|
86
|
+
// Body tier — FAANG-density realignment 2026-05-22: body-md is the
|
|
87
|
+
// industry-standard 14px (shadcn / Vercel Geist / Linear / Stripe /
|
|
88
|
+
// Mantine). The previous 15px was idiosyncratic. body-sm (14px label
|
|
89
|
+
// weight) remains separate via its line-height / weight signature.
|
|
90
|
+
"body-lg": ["18px", { lineHeight: "1.56", letterSpacing: "-0.01em", fontWeight: "400" }],
|
|
91
|
+
"body-md": ["14px", { lineHeight: "1.43", letterSpacing: "0", fontWeight: "400" }],
|
|
92
|
+
"body-sm": ["13px", { lineHeight: "1.46", fontWeight: "400" }],
|
|
93
|
+
// Label tier — used on buttons, nav, secondary actions
|
|
94
|
+
label: ["14px", { lineHeight: "1.43", fontWeight: "500" }],
|
|
95
|
+
"label-caps": ["12px", { lineHeight: "1.33", letterSpacing: "0.04em", fontWeight: "500" }],
|
|
96
|
+
// Mono — code surfaces, technical labels
|
|
97
|
+
"code-md": ["14px", { lineHeight: "1.5", fontWeight: "400" }],
|
|
98
|
+
"code-sm": ["13px", { lineHeight: "1.54", fontWeight: "500" }]
|
|
99
|
+
},
|
|
100
|
+
borderRadius: {
|
|
101
|
+
none: "var(--radius-none)",
|
|
102
|
+
sm: "var(--radius-sm)",
|
|
103
|
+
md: "var(--radius-md)",
|
|
104
|
+
lg: "var(--radius-lg)",
|
|
105
|
+
xl: "var(--radius-xl)",
|
|
106
|
+
"2xl": "var(--radius-2xl)",
|
|
107
|
+
full: "var(--radius-full)"
|
|
108
|
+
},
|
|
109
|
+
boxShadow: {
|
|
110
|
+
sm: "var(--shadow-sm)",
|
|
111
|
+
md: "var(--shadow-md)",
|
|
112
|
+
lg: "var(--shadow-lg)",
|
|
113
|
+
glow: "var(--shadow-glow)",
|
|
114
|
+
"glow-strong": "var(--shadow-glow-strong)"
|
|
115
|
+
},
|
|
116
|
+
transitionTimingFunction: {
|
|
117
|
+
"out-soft": "var(--ease-out-soft)",
|
|
118
|
+
snap: "var(--ease-snap)"
|
|
119
|
+
},
|
|
120
|
+
transitionDuration: {
|
|
121
|
+
fast: "var(--duration-fast)",
|
|
122
|
+
base: "var(--duration-base)",
|
|
123
|
+
slow: "var(--duration-slow)"
|
|
124
|
+
},
|
|
125
|
+
keyframes: {
|
|
126
|
+
"fade-in-up": {
|
|
127
|
+
"0%": { opacity: "0", transform: "translateY(8px)" },
|
|
128
|
+
"100%": { opacity: "1", transform: "translateY(0)" }
|
|
129
|
+
},
|
|
130
|
+
"pulse-glow": {
|
|
131
|
+
"0%, 100%": { boxShadow: "0 0 0 0 hsl(var(--primary) / 0.5)" },
|
|
132
|
+
"50%": { boxShadow: "0 0 0 8px hsl(var(--primary) / 0)" }
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
animation: {
|
|
136
|
+
"fade-in-up": "fade-in-up var(--duration-base) var(--ease-out-soft) both",
|
|
137
|
+
"pulse-glow": "pulse-glow 1.5s var(--ease-in-out) infinite"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
plugins: [animate]
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// src/preset-v3-legacy.ts
|
|
145
|
+
var LIBRARY_CONTENT_GLOBS = [
|
|
146
|
+
// Resolved relative to the consumer's `tailwind.config.{ts,js}`.
|
|
147
|
+
"./node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}",
|
|
148
|
+
// Yarn PnP / pnpm hoist fallback — Tailwind's globbing tolerates both.
|
|
149
|
+
"./node_modules/@usetheo/ui/dist/**/*.{ts,tsx}"
|
|
150
|
+
];
|
|
151
|
+
var preset = {
|
|
152
|
+
...theoUIPreset,
|
|
153
|
+
content: LIBRARY_CONTENT_GLOBS
|
|
154
|
+
};
|
|
155
|
+
var preset_v3_legacy_default = preset;
|
|
156
|
+
|
|
157
|
+
export { preset_v3_legacy_default as default };
|
|
158
|
+
//# sourceMappingURL=preset-v3-legacy.js.map
|
|
159
|
+
//# sourceMappingURL=preset-v3-legacy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/styles/tailwind-preset.ts","../src/preset-v3-legacy.ts"],"names":[],"mappings":"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","file":"preset-v3-legacy.js","sourcesContent":["/**\n * Theo UI Tailwind preset — Violet Forge identity.\n *\n * Single source of truth for the design system's utility-level tokens:\n * - colors mapped to CSS variables (HSL split via `hsl(var(--x) / <alpha>)`)\n * - Geist-inspired typescale (display / title / body / label / code tiers)\n * - radii, shadows, motion timing & duration, keyframes\n * - tailwindcss-animate plugin\n *\n * Consumed by:\n * - `tailwind.config.ts` (this repo) via `presets: [theoUIPreset]`\n * - registry/r/tailwind-preset.json (shipped to consumers via shadcn CLI)\n *\n * Consumers integrate as:\n *\n * import type { Config } from \"tailwindcss\";\n * import { theoUIPreset } from \"./styles/tailwind-preset\";\n *\n * export default {\n * darkMode: \"class\",\n * content: [\"./src/**\\/*.{ts,tsx}\"],\n * presets: [theoUIPreset],\n * } satisfies Config;\n *\n * Note: `darkMode` and `content` are NOT in the preset — they are consumer\n * decisions. The preset only contains `theme.extend.*` and `plugins`.\n */\n\nimport type { Config } from \"tailwindcss\";\nimport animate from \"tailwindcss-animate\";\n\nconst hsl = (token: string) => `hsl(var(${token}) / <alpha-value>)`;\n\nexport const theoUIPreset: Partial<Config> = {\n theme: {\n container: {\n center: true,\n padding: \"1rem\",\n screens: {\n \"2xl\": \"1280px\",\n },\n },\n extend: {\n colors: {\n background: hsl(\"--background\"),\n foreground: hsl(\"--foreground\"),\n card: {\n DEFAULT: hsl(\"--card\"),\n foreground: hsl(\"--card-foreground\"),\n },\n popover: {\n DEFAULT: hsl(\"--popover\"),\n foreground: hsl(\"--popover-foreground\"),\n },\n primary: {\n DEFAULT: hsl(\"--primary\"),\n deep: hsl(\"--primary-deep\"),\n glow: hsl(\"--primary-glow\"),\n foreground: hsl(\"--primary-foreground\"),\n },\n secondary: {\n DEFAULT: hsl(\"--secondary\"),\n foreground: hsl(\"--secondary-foreground\"),\n },\n accent: {\n DEFAULT: hsl(\"--accent\"),\n deep: hsl(\"--accent-deep\"),\n foreground: hsl(\"--accent-foreground\"),\n },\n muted: {\n DEFAULT: hsl(\"--muted\"),\n foreground: hsl(\"--muted-foreground\"),\n },\n success: {\n DEFAULT: hsl(\"--success\"),\n foreground: hsl(\"--success-foreground\"),\n },\n warning: {\n DEFAULT: hsl(\"--warning\"),\n foreground: hsl(\"--warning-foreground\"),\n },\n destructive: {\n DEFAULT: hsl(\"--destructive\"),\n foreground: hsl(\"--destructive-foreground\"),\n },\n info: {\n DEFAULT: hsl(\"--info\"),\n foreground: hsl(\"--info-foreground\"),\n },\n border: hsl(\"--border\"),\n input: hsl(\"--input\"),\n ring: hsl(\"--ring\"),\n },\n fontFamily: {\n display: \"var(--font-display)\",\n sans: \"var(--font-body)\",\n mono: \"var(--font-mono)\",\n },\n /* Geist-inspired Violet Forge typescale.\n *\n * Three strict weights: 400 (body), 500 (UI), 600 (display/headings).\n * Letter-spacing scales with size — aggressive negative on display.\n * Mirrors the Vercel/Geist vocabulary while keeping Theo's identity.\n */\n fontSize: {\n // Display tier — aggressive compression, content-led headlines\n \"display-2xl\": [\"64px\", { lineHeight: \"1\", letterSpacing: \"-0.0464em\", fontWeight: \"600\" }],\n \"display-xl\": [\"48px\", { lineHeight: \"1.05\", letterSpacing: \"-0.05em\", fontWeight: \"600\" }],\n \"display-lg\": [\"40px\", { lineHeight: \"1.1\", letterSpacing: \"-0.05em\", fontWeight: \"600\" }],\n \"display-md\": [\"32px\", { lineHeight: \"1.2\", letterSpacing: \"-0.04em\", fontWeight: \"600\" }],\n headline: [\"28px\", { lineHeight: \"1.25\", letterSpacing: \"-0.035em\", fontWeight: \"600\" }],\n // Title tier — section / card heads\n \"title-lg\": [\"24px\", { lineHeight: \"1.33\", letterSpacing: \"-0.04em\", fontWeight: \"600\" }],\n \"title-md\": [\"20px\", { lineHeight: \"1.4\", letterSpacing: \"-0.03em\", fontWeight: \"600\" }],\n // Body tier — FAANG-density realignment 2026-05-22: body-md is the\n // industry-standard 14px (shadcn / Vercel Geist / Linear / Stripe /\n // Mantine). The previous 15px was idiosyncratic. body-sm (14px label\n // weight) remains separate via its line-height / weight signature.\n \"body-lg\": [\"18px\", { lineHeight: \"1.56\", letterSpacing: \"-0.01em\", fontWeight: \"400\" }],\n \"body-md\": [\"14px\", { lineHeight: \"1.43\", letterSpacing: \"0\", fontWeight: \"400\" }],\n \"body-sm\": [\"13px\", { lineHeight: \"1.46\", fontWeight: \"400\" }],\n // Label tier — used on buttons, nav, secondary actions\n label: [\"14px\", { lineHeight: \"1.43\", fontWeight: \"500\" }],\n \"label-caps\": [\"12px\", { lineHeight: \"1.33\", letterSpacing: \"0.04em\", fontWeight: \"500\" }],\n // Mono — code surfaces, technical labels\n \"code-md\": [\"14px\", { lineHeight: \"1.5\", fontWeight: \"400\" }],\n \"code-sm\": [\"13px\", { lineHeight: \"1.54\", fontWeight: \"500\" }],\n },\n borderRadius: {\n none: \"var(--radius-none)\",\n sm: \"var(--radius-sm)\",\n md: \"var(--radius-md)\",\n lg: \"var(--radius-lg)\",\n xl: \"var(--radius-xl)\",\n \"2xl\": \"var(--radius-2xl)\",\n full: \"var(--radius-full)\",\n },\n boxShadow: {\n sm: \"var(--shadow-sm)\",\n md: \"var(--shadow-md)\",\n lg: \"var(--shadow-lg)\",\n glow: \"var(--shadow-glow)\",\n \"glow-strong\": \"var(--shadow-glow-strong)\",\n },\n transitionTimingFunction: {\n \"out-soft\": \"var(--ease-out-soft)\",\n snap: \"var(--ease-snap)\",\n },\n transitionDuration: {\n fast: \"var(--duration-fast)\",\n base: \"var(--duration-base)\",\n slow: \"var(--duration-slow)\",\n },\n keyframes: {\n \"fade-in-up\": {\n \"0%\": { opacity: \"0\", transform: \"translateY(8px)\" },\n \"100%\": { opacity: \"1\", transform: \"translateY(0)\" },\n },\n \"pulse-glow\": {\n \"0%, 100%\": { boxShadow: \"0 0 0 0 hsl(var(--primary) / 0.5)\" },\n \"50%\": { boxShadow: \"0 0 0 8px hsl(var(--primary) / 0)\" },\n },\n },\n animation: {\n \"fade-in-up\": \"fade-in-up var(--duration-base) var(--ease-out-soft) both\",\n \"pulse-glow\": \"pulse-glow 1.5s var(--ease-in-out) infinite\",\n },\n },\n },\n plugins: [animate],\n};\n","/**\n * `@usetheo/ui/preset-v3-legacy` — Tailwind v3 JS preset (legacy path).\n *\n * Default-export a `Partial<Config>` mirroring the design tokens shipped\n * in `@usetheo/ui/tokens.css`. Adds a `content` field covering the\n * library's published artifact tree so v3-based Tailwind builds emit\n * the utilities used by `@usetheo/ui` components.\n *\n * **Tailwind v4 consumers MUST use `@usetheo/ui/preset.css`**, not this\n * file — Tailwind v4 dropped the JS preset format entirely. This file\n * exists for any remaining `tailwindcss@^3` consumer (notably the\n * shadcn-style copy-paste registry path); new code should not import\n * from this subpath.\n *\n * The token surface is delegated to `./styles/tailwind-preset.ts` (the\n * existing source of truth used by the local Ladle dev surface and the\n * shadcn registry).\n *\n * v3 consumer usage:\n *\n * // tailwind.config.ts (Tailwind v3 only)\n * import preset from \"@usetheo/ui/preset-v3-legacy\";\n * export default {\n * presets: [preset],\n * content: [\"./app/**\\/*.{ts,tsx}\"],\n * };\n *\n * See RFC 0008 follow-up.\n */\nimport type { Config } from \"tailwindcss\";\nimport { theoUIPreset } from \"./styles/tailwind-preset.js\";\n\nconst LIBRARY_CONTENT_GLOBS: string[] = [\n // Resolved relative to the consumer's `tailwind.config.{ts,js}`.\n \"./node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}\",\n // Yarn PnP / pnpm hoist fallback — Tailwind's globbing tolerates both.\n \"./node_modules/@usetheo/ui/dist/**/*.{ts,tsx}\",\n];\n\nconst preset: Partial<Config> = {\n ...theoUIPreset,\n content: LIBRARY_CONTENT_GLOBS,\n};\n\nexport default preset;\n"]}
|
package/dist/preset.css
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* Theo UI — Tailwind v4 CSS preset.
|
|
2
|
+
*
|
|
3
|
+
* For consumers running their own Tailwind v4 build (TheoKit framework
|
|
4
|
+
* path, custom Vite/Astro/Next apps with @tailwindcss/vite, etc.). The
|
|
5
|
+
* preset pulls in:
|
|
6
|
+
* 1. `tokens.css` — runtime `--*` vars `<ThemeProvider>` mutates per
|
|
7
|
+
* theme cascade.
|
|
8
|
+
* 2. `tokens-v4.css` — the `@theme { --color-*, --font-*, --text-*,
|
|
9
|
+
* --radius-*, --shadow-*, --ease-*, --animate-* }` namespace
|
|
10
|
+
* Tailwind v4 actually reads to generate utilities.
|
|
11
|
+
*
|
|
12
|
+
* Consumer usage (their entry CSS):
|
|
13
|
+
*
|
|
14
|
+
* @import "tailwindcss";
|
|
15
|
+
* @import "@usetheo/ui/preset.css";
|
|
16
|
+
*
|
|
17
|
+
* /* the consumer's own @theme overrides come AFTER, so they win. * /
|
|
18
|
+
*
|
|
19
|
+
* Tailwind v4 dropped the v3 JS preset format. The previous JS preset
|
|
20
|
+
* remains shipped under `@usetheo/ui/preset-v3-legacy` (which works only
|
|
21
|
+
* with `tailwindcss@^3`). New v4 consumers MUST use this CSS preset.
|
|
22
|
+
*
|
|
23
|
+
* See RFC 0008 follow-up.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
@import "./tokens.css";
|
|
27
|
+
@import "./tokens-v4.css";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
@import "./fonts.css";
|
|
2
|
+
@import "./tokens.css";
|
|
3
|
+
|
|
4
|
+
@tailwind base;
|
|
5
|
+
@tailwind components;
|
|
6
|
+
@tailwind utilities;
|
|
7
|
+
|
|
8
|
+
@layer base {
|
|
9
|
+
* {
|
|
10
|
+
border-color: hsl(var(--border));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
html {
|
|
14
|
+
font-family: var(--font-body);
|
|
15
|
+
-webkit-font-smoothing: antialiased;
|
|
16
|
+
-moz-osx-font-smoothing: grayscale;
|
|
17
|
+
text-rendering: optimizeLegibility;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
body {
|
|
21
|
+
background-color: hsl(var(--background));
|
|
22
|
+
color: hsl(var(--foreground));
|
|
23
|
+
/* OpenType ligatures globally — Geist's "liga" feature is structural
|
|
24
|
+
* and gives the Vercel-tight glyph combinations. */
|
|
25
|
+
font-feature-settings: "liga" 1, "ss01" 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Display headings inherit theme display font (Geist by default).
|
|
29
|
+
* Per-size tracking is set in tailwind.config.ts; this is the safety net. */
|
|
30
|
+
h1,
|
|
31
|
+
h2,
|
|
32
|
+
h3,
|
|
33
|
+
h4 {
|
|
34
|
+
font-family: var(--font-display);
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Code surfaces: use the mono token + tabular numerals so columns of
|
|
39
|
+
* numbers line up in tables/logs/metrics. */
|
|
40
|
+
code,
|
|
41
|
+
pre,
|
|
42
|
+
kbd,
|
|
43
|
+
samp {
|
|
44
|
+
font-family: var(--font-mono);
|
|
45
|
+
font-feature-settings: "tnum" 1, "liga" 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Focus ring — violet (signature) */
|
|
49
|
+
:focus-visible {
|
|
50
|
+
outline: 2px solid hsl(var(--ring));
|
|
51
|
+
outline-offset: 2px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Selection — soft violet */
|
|
55
|
+
::selection {
|
|
56
|
+
background-color: hsl(var(--primary) / 0.25);
|
|
57
|
+
color: hsl(var(--foreground));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Native scrollbar fallback (Violet Forge).
|
|
61
|
+
* Used for native browser scroll on elements that don't wrap in <ScrollArea>.
|
|
62
|
+
* Components that DO use <ScrollArea> hide the native scrollbar via Radix.
|
|
63
|
+
*/
|
|
64
|
+
*::-webkit-scrollbar {
|
|
65
|
+
width: 10px;
|
|
66
|
+
height: 10px;
|
|
67
|
+
}
|
|
68
|
+
*::-webkit-scrollbar-track {
|
|
69
|
+
background: transparent;
|
|
70
|
+
}
|
|
71
|
+
*::-webkit-scrollbar-thumb {
|
|
72
|
+
background-color: hsl(var(--primary) / 0.25);
|
|
73
|
+
border: 2px solid transparent;
|
|
74
|
+
background-clip: content-box;
|
|
75
|
+
border-radius: 9999px;
|
|
76
|
+
transition: background-color var(--duration-fast) var(--ease-out-soft);
|
|
77
|
+
}
|
|
78
|
+
*::-webkit-scrollbar-thumb:hover {
|
|
79
|
+
background-color: hsl(var(--primary) / 0.5);
|
|
80
|
+
}
|
|
81
|
+
*::-webkit-scrollbar-thumb:active {
|
|
82
|
+
background-color: hsl(var(--primary) / 0.75);
|
|
83
|
+
}
|
|
84
|
+
* {
|
|
85
|
+
scrollbar-width: thin;
|
|
86
|
+
scrollbar-color: hsl(var(--primary) / 0.3) transparent;
|
|
87
|
+
}
|
|
88
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
|
+
/* Theo UI — Tailwind v4 prebuilt entry stylesheet.
|
|
2
|
+
*
|
|
3
|
+
* What ships at `@usetheo/ui/styles.css` since RFC 0008 follow-up
|
|
4
|
+
* (`0.5.1-next.0`). Consumer imports this once and the framework's
|
|
5
|
+
* Tailwind v4 build picks up:
|
|
6
|
+
* - `@import "tailwindcss"` — Tailwind v4 core (preflight + utilities)
|
|
7
|
+
* - `@import "./fonts.css"` — self-hosted Geist + Geist Mono @font-face
|
|
8
|
+
* - `@import "./tokens.css"` — runtime `--*` vars (theme cascade target)
|
|
9
|
+
* - `@import "./tokens-v4.css"` — `@theme { --color-*, --text-*, … }`
|
|
10
|
+
* namespace Tailwind v4 reads to emit utilities
|
|
11
|
+
* - `@layer base` — `border-color`, body font, focus ring, scrollbar
|
|
12
|
+
* styling that depend on the runtime vars
|
|
13
|
+
*
|
|
14
|
+
* v3-only consumers (Tailwind 3.x + the shadcn registry preset) should
|
|
15
|
+
* load `@usetheo/ui/styles-v3-legacy.css` instead — that file is the
|
|
16
|
+
* unchanged `@tailwind base; @tailwind components; @tailwind utilities`
|
|
17
|
+
* variant. See RFC 0008 follow-up.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
@import "tailwindcss";
|
|
1
21
|
@import "./fonts.css";
|
|
2
22
|
@import "./tokens.css";
|
|
3
|
-
|
|
4
|
-
@tailwind base;
|
|
5
|
-
@tailwind components;
|
|
6
|
-
@tailwind utilities;
|
|
23
|
+
@import "./tokens-v4.css";
|
|
7
24
|
|
|
8
25
|
@layer base {
|
|
9
26
|
* {
|
|
@@ -26,7 +43,7 @@
|
|
|
26
43
|
}
|
|
27
44
|
|
|
28
45
|
/* Display headings inherit theme display font (Geist by default).
|
|
29
|
-
* Per-size tracking is set in
|
|
46
|
+
* Per-size tracking is set in tokens-v4.css; this is the safety net. */
|
|
30
47
|
h1,
|
|
31
48
|
h2,
|
|
32
49
|
h3,
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/* Theo UI — Tailwind v4 theme aliases.
|
|
2
|
+
*
|
|
3
|
+
* Companion to `tokens.css`. The base file declares the v3-style runtime
|
|
4
|
+
* variables (`--primary`, `--background`, …) that `<ThemeProvider>` and
|
|
5
|
+
* `[data-theme]` cascades mutate at runtime. This file declares the
|
|
6
|
+
* Tailwind v4 `@theme` namespace (`--color-primary`, `--color-background`,
|
|
7
|
+
* …) by aliasing back to those runtime vars via `hsl(var(--*))`.
|
|
8
|
+
*
|
|
9
|
+
* Why two layers:
|
|
10
|
+
* - `<ThemeProvider>` (and the 10 built-in themes) sets `--primary`
|
|
11
|
+
* etc. at runtime — that's the theme switch surface.
|
|
12
|
+
* - Tailwind v4 resolves color utilities exclusively through
|
|
13
|
+
* `--color-*` tokens declared in `@theme`. Without these aliases
|
|
14
|
+
* `bg-primary`, `text-muted-foreground`, `border-border`, etc. emit
|
|
15
|
+
* a className with no matching CSS rule.
|
|
16
|
+
*
|
|
17
|
+
* The indirection (`--color-primary: hsl(var(--primary))`) preserves the
|
|
18
|
+
* runtime theme cascade — browsers resolve `var(--color-primary)` →
|
|
19
|
+
* `hsl(var(--primary))` → current `[data-theme]` value at paint time.
|
|
20
|
+
*
|
|
21
|
+
* See RFC 0008 follow-up.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
@theme {
|
|
25
|
+
/* Color tokens ------------------------------------------------------ */
|
|
26
|
+
--color-background: hsl(var(--background));
|
|
27
|
+
--color-foreground: hsl(var(--foreground));
|
|
28
|
+
|
|
29
|
+
--color-card: hsl(var(--card));
|
|
30
|
+
--color-card-foreground: hsl(var(--card-foreground));
|
|
31
|
+
|
|
32
|
+
--color-popover: hsl(var(--popover));
|
|
33
|
+
--color-popover-foreground: hsl(var(--popover-foreground));
|
|
34
|
+
|
|
35
|
+
--color-primary: hsl(var(--primary));
|
|
36
|
+
--color-primary-deep: hsl(var(--primary-deep));
|
|
37
|
+
--color-primary-glow: hsl(var(--primary-glow));
|
|
38
|
+
--color-primary-foreground: hsl(var(--primary-foreground));
|
|
39
|
+
|
|
40
|
+
--color-secondary: hsl(var(--secondary));
|
|
41
|
+
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
|
42
|
+
|
|
43
|
+
--color-accent: hsl(var(--accent));
|
|
44
|
+
--color-accent-deep: hsl(var(--accent-deep));
|
|
45
|
+
--color-accent-foreground: hsl(var(--accent-foreground));
|
|
46
|
+
|
|
47
|
+
--color-muted: hsl(var(--muted));
|
|
48
|
+
--color-muted-foreground: hsl(var(--muted-foreground));
|
|
49
|
+
|
|
50
|
+
--color-border: hsl(var(--border));
|
|
51
|
+
--color-input: hsl(var(--input));
|
|
52
|
+
--color-ring: hsl(var(--ring));
|
|
53
|
+
|
|
54
|
+
--color-success: hsl(var(--success));
|
|
55
|
+
--color-success-foreground: hsl(var(--success-foreground));
|
|
56
|
+
--color-warning: hsl(var(--warning));
|
|
57
|
+
--color-warning-foreground: hsl(var(--warning-foreground));
|
|
58
|
+
--color-destructive: hsl(var(--destructive));
|
|
59
|
+
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
|
60
|
+
--color-info: hsl(var(--info));
|
|
61
|
+
--color-info-foreground: hsl(var(--info-foreground));
|
|
62
|
+
|
|
63
|
+
/* Fonts ------------------------------------------------------------- */
|
|
64
|
+
--font-display: var(--font-display);
|
|
65
|
+
--font-sans: var(--font-body);
|
|
66
|
+
--font-mono: var(--font-mono);
|
|
67
|
+
|
|
68
|
+
/* Violet Forge typescale -------------------------------------------- *
|
|
69
|
+
* Compound text utilities: each `--text-{name}` declares the size,
|
|
70
|
+
* with companion `--*--line-height`, `--*--letter-spacing`, and
|
|
71
|
+
* `--*--font-weight` properties Tailwind v4 picks up automatically.
|
|
72
|
+
*/
|
|
73
|
+
--text-display-2xl: 64px;
|
|
74
|
+
--text-display-2xl--line-height: 1;
|
|
75
|
+
--text-display-2xl--letter-spacing: -0.0464em;
|
|
76
|
+
--text-display-2xl--font-weight: 600;
|
|
77
|
+
|
|
78
|
+
--text-display-xl: 48px;
|
|
79
|
+
--text-display-xl--line-height: 1.05;
|
|
80
|
+
--text-display-xl--letter-spacing: -0.05em;
|
|
81
|
+
--text-display-xl--font-weight: 600;
|
|
82
|
+
|
|
83
|
+
--text-display-lg: 40px;
|
|
84
|
+
--text-display-lg--line-height: 1.1;
|
|
85
|
+
--text-display-lg--letter-spacing: -0.05em;
|
|
86
|
+
--text-display-lg--font-weight: 600;
|
|
87
|
+
|
|
88
|
+
--text-display-md: 32px;
|
|
89
|
+
--text-display-md--line-height: 1.2;
|
|
90
|
+
--text-display-md--letter-spacing: -0.04em;
|
|
91
|
+
--text-display-md--font-weight: 600;
|
|
92
|
+
|
|
93
|
+
--text-headline: 28px;
|
|
94
|
+
--text-headline--line-height: 1.25;
|
|
95
|
+
--text-headline--letter-spacing: -0.035em;
|
|
96
|
+
--text-headline--font-weight: 600;
|
|
97
|
+
|
|
98
|
+
--text-title-lg: 24px;
|
|
99
|
+
--text-title-lg--line-height: 1.33;
|
|
100
|
+
--text-title-lg--letter-spacing: -0.04em;
|
|
101
|
+
--text-title-lg--font-weight: 600;
|
|
102
|
+
|
|
103
|
+
--text-title-md: 20px;
|
|
104
|
+
--text-title-md--line-height: 1.4;
|
|
105
|
+
--text-title-md--letter-spacing: -0.03em;
|
|
106
|
+
--text-title-md--font-weight: 600;
|
|
107
|
+
|
|
108
|
+
--text-body-lg: 18px;
|
|
109
|
+
--text-body-lg--line-height: 1.56;
|
|
110
|
+
--text-body-lg--letter-spacing: -0.01em;
|
|
111
|
+
--text-body-lg--font-weight: 400;
|
|
112
|
+
|
|
113
|
+
--text-body-md: 14px;
|
|
114
|
+
--text-body-md--line-height: 1.43;
|
|
115
|
+
--text-body-md--letter-spacing: 0;
|
|
116
|
+
--text-body-md--font-weight: 400;
|
|
117
|
+
|
|
118
|
+
--text-body-sm: 13px;
|
|
119
|
+
--text-body-sm--line-height: 1.46;
|
|
120
|
+
--text-body-sm--font-weight: 400;
|
|
121
|
+
|
|
122
|
+
--text-label: 14px;
|
|
123
|
+
--text-label--line-height: 1.43;
|
|
124
|
+
--text-label--font-weight: 500;
|
|
125
|
+
|
|
126
|
+
--text-label-caps: 12px;
|
|
127
|
+
--text-label-caps--line-height: 1.33;
|
|
128
|
+
--text-label-caps--letter-spacing: 0.04em;
|
|
129
|
+
--text-label-caps--font-weight: 500;
|
|
130
|
+
|
|
131
|
+
--text-code-md: 14px;
|
|
132
|
+
--text-code-md--line-height: 1.5;
|
|
133
|
+
--text-code-md--font-weight: 400;
|
|
134
|
+
|
|
135
|
+
--text-code-sm: 13px;
|
|
136
|
+
--text-code-sm--line-height: 1.54;
|
|
137
|
+
--text-code-sm--font-weight: 500;
|
|
138
|
+
|
|
139
|
+
/* Radii — Tailwind v4 reads the value directly (no var indirection). */
|
|
140
|
+
--radius-none: 0px;
|
|
141
|
+
--radius-sm: 4px;
|
|
142
|
+
--radius-md: 6px;
|
|
143
|
+
--radius-lg: 10px;
|
|
144
|
+
--radius-xl: 14px;
|
|
145
|
+
--radius-2xl: 20px;
|
|
146
|
+
--radius-full: 9999px;
|
|
147
|
+
|
|
148
|
+
/* Shadows — alias to tokens.css computed values (which already use
|
|
149
|
+
* `hsl(var(--foreground) / …)` so theme-switch keeps them in step). */
|
|
150
|
+
--shadow-sm: var(--shadow-sm);
|
|
151
|
+
--shadow-md: var(--shadow-md);
|
|
152
|
+
--shadow-lg: var(--shadow-lg);
|
|
153
|
+
--shadow-glow: var(--shadow-glow);
|
|
154
|
+
--shadow-glow-strong: var(--shadow-glow-strong);
|
|
155
|
+
|
|
156
|
+
/* Motion ------------------------------------------------------------ */
|
|
157
|
+
--ease-out-soft: var(--ease-out-soft);
|
|
158
|
+
--ease-snap: var(--ease-snap);
|
|
159
|
+
|
|
160
|
+
/* Animations — declare so `animate-fade-in-up` and `animate-pulse-glow`
|
|
161
|
+
* resolve. Keyframes are declared below (outside @theme — Tailwind v4
|
|
162
|
+
* picks them up via the @keyframes namespace).
|
|
163
|
+
*/
|
|
164
|
+
--animate-fade-in-up: fade-in-up var(--duration-base) var(--ease-out-soft) both;
|
|
165
|
+
--animate-pulse-glow: pulse-glow 1.5s var(--ease-in-out) infinite;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@keyframes fade-in-up {
|
|
169
|
+
0% {
|
|
170
|
+
opacity: 0;
|
|
171
|
+
transform: translateY(8px);
|
|
172
|
+
}
|
|
173
|
+
100% {
|
|
174
|
+
opacity: 1;
|
|
175
|
+
transform: translateY(0);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@keyframes pulse-glow {
|
|
180
|
+
0%,
|
|
181
|
+
100% {
|
|
182
|
+
box-shadow: 0 0 0 0 hsl(var(--primary) / 0.5);
|
|
183
|
+
}
|
|
184
|
+
50% {
|
|
185
|
+
box-shadow: 0 0 0 8px hsl(var(--primary) / 0);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `@usetheo/ui/vite-plugin` — auto-wire Tailwind v4 for consumers.
|
|
5
|
+
*
|
|
6
|
+
* Default export is a factory returning ONE Vite Plugin. Internally:
|
|
7
|
+
* 1. chains `@tailwindcss/vite` v4 via the `config()` hook when resolvable
|
|
8
|
+
* and `opts.tailwind !== false`,
|
|
9
|
+
* 2. exposes a virtual module `virtual:@usetheo/ui/library-sources.css`
|
|
10
|
+
* whose contents register `@source` directives covering the library's
|
|
11
|
+
* published files, so consumer-side Tailwind scans `@usetheo/ui` JSX
|
|
12
|
+
* and emits its utility classes,
|
|
13
|
+
* 3. degrades gracefully via `console.warn` (never throws) when
|
|
14
|
+
* `@tailwindcss/vite` is not installed — the surface stays usable in
|
|
15
|
+
* CSS-only mode via the pre-built `@usetheo/ui/styles.css` subpath.
|
|
16
|
+
*
|
|
17
|
+
* This is the cross-repo contract TheoKit's `integrateUseTheoUI()` probes
|
|
18
|
+
* for. See `docs/rfcs/0008-vite-plugin-and-preset.md`.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
interface UseTheoUIPluginOptions {
|
|
22
|
+
/** Disable Tailwind v4 auto-chain. Default: `true`. */
|
|
23
|
+
tailwind?: boolean;
|
|
24
|
+
/** Extra `@source` globs merged into the library defaults. */
|
|
25
|
+
contentExtra?: string[];
|
|
26
|
+
}
|
|
27
|
+
declare function useTheoUIVite(opts?: UseTheoUIPluginOptions): Plugin;
|
|
28
|
+
|
|
29
|
+
export { type UseTheoUIPluginOptions, useTheoUIVite as default };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// src/vite-plugin.ts
|
|
2
|
+
var PLUGIN_NAME = "@usetheo/ui/vite-plugin";
|
|
3
|
+
var VIRTUAL_ID = "virtual:@usetheo/ui/library-sources.css";
|
|
4
|
+
var RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_ID}`;
|
|
5
|
+
function buildLibrarySourcesCss(extra = []) {
|
|
6
|
+
const defaults = [
|
|
7
|
+
'"../node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}"',
|
|
8
|
+
'"./node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}"'
|
|
9
|
+
];
|
|
10
|
+
const all = [...defaults, ...extra.map((g) => JSON.stringify(g))];
|
|
11
|
+
return `${all.map((src) => `@source ${src};`).join("\n")}
|
|
12
|
+
`;
|
|
13
|
+
}
|
|
14
|
+
function useTheoUIVite(opts = {}) {
|
|
15
|
+
const wantsTailwind = opts.tailwind !== false;
|
|
16
|
+
const extra = opts.contentExtra ?? [];
|
|
17
|
+
let warned = false;
|
|
18
|
+
const warnMissingPeer = () => {
|
|
19
|
+
if (warned) return;
|
|
20
|
+
warned = true;
|
|
21
|
+
console.warn(
|
|
22
|
+
`[${PLUGIN_NAME}] @tailwindcss/vite was not resolvable; falling back to CSS-only mode. Install \`@tailwindcss/vite@^4\` to get the utility-driven design tokens, or import \`@usetheo/ui/styles.css\` directly for the pre-built surface.`
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
name: PLUGIN_NAME,
|
|
27
|
+
// Vite's typing for `config()` since 5.x explicitly omits `plugins` from
|
|
28
|
+
// the allowed return shape to nudge authors toward `Plugin[]` factories.
|
|
29
|
+
// The runtime still honors `{ plugins }` merge, and the TheoKit contract
|
|
30
|
+
// requires ONE Plugin object (so we can't return `Plugin[]` here).
|
|
31
|
+
// The cast keeps the public surface honest and the type-checker quiet.
|
|
32
|
+
async config(_userConfig, _env) {
|
|
33
|
+
if (!wantsTailwind) {
|
|
34
|
+
return void 0;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const specifier = "@tailwindcss/vite";
|
|
38
|
+
const mod = await import(
|
|
39
|
+
/* @vite-ignore */
|
|
40
|
+
specifier
|
|
41
|
+
);
|
|
42
|
+
const factory = mod.default;
|
|
43
|
+
if (typeof factory !== "function") {
|
|
44
|
+
warnMissingPeer();
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
47
|
+
const tw = factory();
|
|
48
|
+
const tailwindPlugins = Array.isArray(tw) ? tw : [tw];
|
|
49
|
+
return { plugins: tailwindPlugins };
|
|
50
|
+
} catch {
|
|
51
|
+
warnMissingPeer();
|
|
52
|
+
return void 0;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
resolveId(id) {
|
|
56
|
+
if (id === VIRTUAL_ID) {
|
|
57
|
+
return RESOLVED_VIRTUAL_ID;
|
|
58
|
+
}
|
|
59
|
+
return void 0;
|
|
60
|
+
},
|
|
61
|
+
load(id) {
|
|
62
|
+
if (id === RESOLVED_VIRTUAL_ID) {
|
|
63
|
+
return buildLibrarySourcesCss(extra);
|
|
64
|
+
}
|
|
65
|
+
return void 0;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { useTheoUIVite as default };
|
|
71
|
+
//# sourceMappingURL=vite-plugin.js.map
|
|
72
|
+
//# sourceMappingURL=vite-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vite-plugin.ts"],"names":[],"mappings":";AA0BA,IAAM,WAAA,GAAc,yBAAA;AACpB,IAAM,UAAA,GAAa,yCAAA;AACnB,IAAM,mBAAA,GAAsB,KAAK,UAAU,CAAA,CAAA;AAE3C,SAAS,sBAAA,CAAuB,KAAA,GAAkB,EAAC,EAAW;AAK5D,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,sDAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,GAAA,GAAM,CAAC,GAAG,QAAA,EAAU,GAAG,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,CAAC,CAAC,CAAC,CAAA;AAChE,EAAA,OAAO,CAAA,EAAG,GAAA,CAAI,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAA,QAAA,EAAW,GAAG,CAAA,CAAA,CAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC;AAAA,CAAA;AAC1D;AAEe,SAAR,aAAA,CAA+B,IAAA,GAA+B,EAAC,EAAW;AAC/E,EAAA,MAAM,aAAA,GAAgB,KAAK,QAAA,KAAa,KAAA;AACxC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,YAAA,IAAgB,EAAC;AAEpC,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,MAAM,kBAAkB,MAAY;AAClC,IAAA,IAAI,MAAA,EAAQ;AACZ,IAAA,MAAA,GAAS,IAAA;AAET,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,IAAI,WAAW,CAAA,yNAAA;AAAA,KACjB;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAON,MAAM,MAAA,CAAO,WAAA,EAAa,IAAA,EAAwD;AAChF,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA,OAAO,MAAA;AAAA,MACT;AAEA,MAAA,IAAI;AAKF,QAAA,MAAM,SAAA,GAAY,mBAAA;AAClB,QAAA,MAAM,MAAM,MAAM;AAAA;AAAA,UAA0B;AAAA,SAAA;AAC5C,QAAA,MAAM,UAAW,GAAA,CAA8B,OAAA;AAC/C,QAAA,IAAI,OAAO,YAAY,UAAA,EAAY;AACjC,UAAA,eAAA,EAAgB;AAChB,UAAA,OAAO,KAAA,CAAA;AAAA,QACT;AACA,QAAA,MAAM,KAAM,OAAA,EAAoC;AAChD,QAAA,MAAM,kBAAkB,KAAA,CAAM,OAAA,CAAQ,EAAE,CAAA,GAAI,EAAA,GAAK,CAAC,EAAE,CAAA;AACpD,QAAA,OAAO,EAAE,SAAS,eAAA,EAAgB;AAAA,MACpC,CAAA,CAAA,MAAQ;AACN,QAAA,eAAA,EAAgB;AAChB,QAAA,OAAO,MAAA;AAAA,MACT;AAAA,IACF,CAAA;AAAA,IAEA,UAAU,EAAA,EAAI;AACZ,MAAA,IAAI,OAAO,UAAA,EAAY;AACrB,QAAA,OAAO,mBAAA;AAAA,MACT;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IAEA,KAAK,EAAA,EAAI;AACP,MAAA,IAAI,OAAO,mBAAA,EAAqB;AAC9B,QAAA,OAAO,uBAAuB,KAAK,CAAA;AAAA,MACrC;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,GACF;AACF","file":"vite-plugin.js","sourcesContent":["/**\n * `@usetheo/ui/vite-plugin` — auto-wire Tailwind v4 for consumers.\n *\n * Default export is a factory returning ONE Vite Plugin. Internally:\n * 1. chains `@tailwindcss/vite` v4 via the `config()` hook when resolvable\n * and `opts.tailwind !== false`,\n * 2. exposes a virtual module `virtual:@usetheo/ui/library-sources.css`\n * whose contents register `@source` directives covering the library's\n * published files, so consumer-side Tailwind scans `@usetheo/ui` JSX\n * and emits its utility classes,\n * 3. degrades gracefully via `console.warn` (never throws) when\n * `@tailwindcss/vite` is not installed — the surface stays usable in\n * CSS-only mode via the pre-built `@usetheo/ui/styles.css` subpath.\n *\n * This is the cross-repo contract TheoKit's `integrateUseTheoUI()` probes\n * for. See `docs/rfcs/0008-vite-plugin-and-preset.md`.\n */\nimport type { Plugin, UserConfig } from \"vite\";\n\nexport interface UseTheoUIPluginOptions {\n /** Disable Tailwind v4 auto-chain. Default: `true`. */\n tailwind?: boolean;\n /** Extra `@source` globs merged into the library defaults. */\n contentExtra?: string[];\n}\n\nconst PLUGIN_NAME = \"@usetheo/ui/vite-plugin\";\nconst VIRTUAL_ID = \"virtual:@usetheo/ui/library-sources.css\";\nconst RESOLVED_VIRTUAL_ID = `\\0${VIRTUAL_ID}`;\n\nfunction buildLibrarySourcesCss(extra: string[] = []): string {\n // `@source` paths are resolved relative to the importing CSS file in\n // Tailwind v4. The library defaults below cover the published artifact\n // tree under the consumer's `node_modules/@usetheo/ui/dist/`. Extra globs\n // are appended verbatim — consumers can register additional roots.\n const defaults = [\n '\"../node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}\"',\n '\"./node_modules/@usetheo/ui/dist/**/*.{js,mjs,cjs}\"',\n ];\n const all = [...defaults, ...extra.map((g) => JSON.stringify(g))];\n return `${all.map((src) => `@source ${src};`).join(\"\\n\")}\\n`;\n}\n\nexport default function useTheoUIVite(opts: UseTheoUIPluginOptions = {}): Plugin {\n const wantsTailwind = opts.tailwind !== false;\n const extra = opts.contentExtra ?? [];\n\n let warned = false;\n const warnMissingPeer = (): void => {\n if (warned) return;\n warned = true;\n // biome-ignore lint/suspicious/noConsole: TheoKit cross-repo contract requires `console.warn` (not throw) when the optional `@tailwindcss/vite` peer is missing. See RFC 0008 §3 D1.\n console.warn(\n `[${PLUGIN_NAME}] @tailwindcss/vite was not resolvable; falling back to CSS-only mode. Install \\`@tailwindcss/vite@^4\\` to get the utility-driven design tokens, or import \\`@usetheo/ui/styles.css\\` directly for the pre-built surface.`,\n );\n };\n\n return {\n name: PLUGIN_NAME,\n\n // Vite's typing for `config()` since 5.x explicitly omits `plugins` from\n // the allowed return shape to nudge authors toward `Plugin[]` factories.\n // The runtime still honors `{ plugins }` merge, and the TheoKit contract\n // requires ONE Plugin object (so we can't return `Plugin[]` here).\n // The cast keeps the public surface honest and the type-checker quiet.\n async config(_userConfig, _env): Promise<Omit<UserConfig, \"plugins\"> | undefined> {\n if (!wantsTailwind) {\n return undefined;\n }\n\n try {\n // Dynamic import keeps `@tailwindcss/vite` as an OPTIONAL peer. The\n // specifier is held in a variable so Vite's import-analysis pass\n // leaves it alone — at runtime the consumer's resolver does the\n // actual resolution. Resolution failure must not crash the build.\n const specifier = \"@tailwindcss/vite\";\n const mod = await import(/* @vite-ignore */ specifier);\n const factory = (mod as { default?: unknown }).default;\n if (typeof factory !== \"function\") {\n warnMissingPeer();\n return undefined;\n }\n const tw = (factory as () => Plugin | Plugin[])();\n const tailwindPlugins = Array.isArray(tw) ? tw : [tw];\n return { plugins: tailwindPlugins } as unknown as Omit<UserConfig, \"plugins\">;\n } catch {\n warnMissingPeer();\n return undefined;\n }\n },\n\n resolveId(id) {\n if (id === VIRTUAL_ID) {\n return RESOLVED_VIRTUAL_ID;\n }\n return undefined;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_ID) {\n return buildLibrarySourcesCss(extra);\n }\n return undefined;\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usetheo/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1-next.0",
|
|
4
4
|
"description": "Theo UI — framework-agnostic React component library with the Violet Forge design system. Focused on AI-agent interfaces, cloud dashboards, and developer-tooling surfaces.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"./styles.css": "./dist/styles.css",
|
|
14
|
+
"./styles-v3-legacy.css": "./dist/styles-v3-legacy.css",
|
|
14
15
|
"./tokens.css": "./dist/tokens.css",
|
|
16
|
+
"./tokens-v4.css": "./dist/tokens-v4.css",
|
|
17
|
+
"./preset.css": "./dist/preset.css",
|
|
18
|
+
"./preset": "./dist/preset.css",
|
|
15
19
|
"./fonts.css": "./dist/fonts.css",
|
|
16
20
|
"./fonts-cdn.css": "./dist/fonts-cdn.css",
|
|
17
21
|
"./slide/themes/default.css": "./dist/slide/themes/default.css",
|
|
@@ -439,6 +443,14 @@
|
|
|
439
443
|
"./slide-deck": {
|
|
440
444
|
"types": "./dist/slide-deck/index.d.ts",
|
|
441
445
|
"import": "./dist/slide-deck/index.js"
|
|
446
|
+
},
|
|
447
|
+
"./vite-plugin": {
|
|
448
|
+
"types": "./dist/vite-plugin.d.ts",
|
|
449
|
+
"import": "./dist/vite-plugin.js"
|
|
450
|
+
},
|
|
451
|
+
"./preset-v3-legacy": {
|
|
452
|
+
"types": "./dist/preset-v3-legacy.d.ts",
|
|
453
|
+
"import": "./dist/preset-v3-legacy.js"
|
|
442
454
|
}
|
|
443
455
|
},
|
|
444
456
|
"files": ["dist", "registry/r", "registry/index.json", "LICENSE", "CHANGELOG.md"],
|
|
@@ -473,10 +485,13 @@
|
|
|
473
485
|
"dogfood:slide": "tsx scripts/dogfood-slide.ts",
|
|
474
486
|
"dogfood:slide-deck": "tsx scripts/dogfood-slide-deck.ts",
|
|
475
487
|
"dogfood:slide-rich": "tsx scripts/dogfood-slide-rich.ts",
|
|
476
|
-
"
|
|
488
|
+
"dogfood:v4-zero-config": "tsx scripts/dogfood-v4-zero-config.ts",
|
|
489
|
+
"dogfood:v4-real-build": "bash scripts/dogfood-v4-real-build.sh",
|
|
490
|
+
"quality:gates": "pnpm format:check && pnpm lint:ci && pnpm typecheck && pnpm test && pnpm build && pnpm registry:build && pnpm registry:validate && pnpm quality:structure && pnpm quality:bundle && pnpm quality:a11y && pnpm ladle:build && pnpm dogfood:whiteboard && pnpm dogfood:slide && pnpm dogfood:slide-deck && pnpm dogfood:slide-rich && pnpm dogfood:v4-zero-config",
|
|
477
491
|
"quality:gates:fast": "pnpm format:check && pnpm lint:ci && pnpm typecheck && pnpm registry:build && pnpm registry:validate && pnpm quality:structure"
|
|
478
492
|
},
|
|
479
493
|
"peerDependencies": {
|
|
494
|
+
"@tailwindcss/vite": "^4.0.0",
|
|
480
495
|
"hast-util-from-html": "^2.0.0",
|
|
481
496
|
"hast-util-sanitize": "^5.0.0",
|
|
482
497
|
"hast-util-to-jsx-runtime": "^2.0.0",
|
|
@@ -493,8 +508,10 @@
|
|
|
493
508
|
"react-dom": ">=18.2.0 <20",
|
|
494
509
|
"roughjs": "^4.6.0",
|
|
495
510
|
"shiki": "^1.0.0",
|
|
511
|
+
"tailwindcss": "^4.0.0",
|
|
496
512
|
"unist-util-visit": "^5.0.0",
|
|
497
513
|
"unist-util-visit-parents": "^6.0.0",
|
|
514
|
+
"vite": "^6.0.0 || ^7.0.0",
|
|
498
515
|
"yaml": "^2.0.0"
|
|
499
516
|
},
|
|
500
517
|
"peerDependenciesMeta": {
|
|
@@ -548,6 +565,15 @@
|
|
|
548
565
|
},
|
|
549
566
|
"mermaid": {
|
|
550
567
|
"optional": true
|
|
568
|
+
},
|
|
569
|
+
"@tailwindcss/vite": {
|
|
570
|
+
"optional": true
|
|
571
|
+
},
|
|
572
|
+
"tailwindcss": {
|
|
573
|
+
"optional": true
|
|
574
|
+
},
|
|
575
|
+
"vite": {
|
|
576
|
+
"optional": true
|
|
551
577
|
}
|
|
552
578
|
},
|
|
553
579
|
"dependencies": {
|