@pitlane/theme 0.2.0 → 0.3.1

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/dist/index.d.mts CHANGED
@@ -1,325 +1,7 @@
1
- import { ElementProps, Handle, MixinDescriptor, RemixElement, css as css$1 } from "remix/ui";
1
+ import { A as DimensionToken, B as UntypedToken, E as BorderToken, F as NumberToken, I as ShadowToken, L as StrokeStyleToken, M as FontFamilyToken, N as FontWeightToken, O as ColorToken, P as GradientToken, R as TokenType, T as AnyToken, j as DurationToken, k as CubicBezierToken, z as TransitionToken } from "./schema-CRP607Pg.mjs";
2
+ import { a as DeepPartialTokens, c as ScaleFn, d as ThemePatch, f as TokenTree, i as createTheme, l as ThemeInit, m as Tokens, n as ThemeProps, o as Merged, p as TokenValue, r as ThemeResult, s as ScalableToken, t as ThemeComponent, u as ThemeMode } from "./theme-CaHfWYnM.mjs";
3
+ import { ElementProps, MixinDescriptor, css as css$1 } from "remix/ui";
2
4
  import * as CSS from "csstype";
3
- //#region src/brands.d.ts
4
- /**
5
- * The twelve DTCG token types, in canonical order.
6
- *
7
- * @internal
8
- */
9
- declare const TOKEN_TYPES: readonly ["color", "dimension", "duration", "fontFamily", "fontWeight", "number", "cubicBezier", "shadow", "border", "transition", "gradient", "strokeStyle"];
10
- /** The twelve DTCG token `$type` values. @see {@link AnyToken} */
11
- type TokenType = (typeof TOKEN_TYPES)[number];
12
- declare const COLOR: unique symbol;
13
- declare const DIMENSION: unique symbol;
14
- declare const DURATION: unique symbol;
15
- declare const FONT_FAMILY: unique symbol;
16
- declare const FONT_WEIGHT: unique symbol;
17
- declare const NUMBER: unique symbol;
18
- declare const CUBIC_BEZIER: unique symbol;
19
- declare const SHADOW: unique symbol;
20
- declare const BORDER: unique symbol;
21
- declare const TRANSITION: unique symbol;
22
- declare const GRADIENT: unique symbol;
23
- declare const STROKE_STYLE: unique symbol;
24
- /** Compile-time brand for a `color` token. */
25
- type ColorToken = string & {
26
- readonly [COLOR]: true;
27
- };
28
- /** Compile-time brand for a `dimension` token. */
29
- type DimensionToken = string & {
30
- readonly [DIMENSION]: true;
31
- };
32
- /** Compile-time brand for a `duration` token. */
33
- type DurationToken = string & {
34
- readonly [DURATION]: true;
35
- };
36
- /** Compile-time brand for a `fontFamily` token. */
37
- type FontFamilyToken = string & {
38
- readonly [FONT_FAMILY]: true;
39
- };
40
- /** Compile-time brand for a `fontWeight` token. */
41
- type FontWeightToken = string & {
42
- readonly [FONT_WEIGHT]: true;
43
- };
44
- /** Compile-time brand for a `number` token. */
45
- type NumberToken = string & {
46
- readonly [NUMBER]: true;
47
- };
48
- /** Compile-time brand for a `cubicBezier` token. */
49
- type CubicBezierToken = string & {
50
- readonly [CUBIC_BEZIER]: true;
51
- };
52
- /** Compile-time brand for a `shadow` token. */
53
- type ShadowToken = string & {
54
- readonly [SHADOW]: true;
55
- };
56
- /** Compile-time brand for a `border` token. */
57
- type BorderToken = string & {
58
- readonly [BORDER]: true;
59
- };
60
- /** Compile-time brand for a `transition` token. */
61
- type TransitionToken = string & {
62
- readonly [TRANSITION]: true;
63
- };
64
- /** Compile-time brand for a `gradient` token. */
65
- type GradientToken = string & {
66
- readonly [GRADIENT]: true;
67
- };
68
- /** Compile-time brand for a `strokeStyle` token. */
69
- type StrokeStyleToken = string & {
70
- readonly [STROKE_STYLE]: true;
71
- };
72
- /**
73
- * Maps each {@link TokenType} to its token brand.
74
- *
75
- * @internal
76
- */
77
- interface BrandByType {
78
- color: ColorToken;
79
- dimension: DimensionToken;
80
- duration: DurationToken;
81
- fontFamily: FontFamilyToken;
82
- fontWeight: FontWeightToken;
83
- number: NumberToken;
84
- cubicBezier: CubicBezierToken;
85
- shadow: ShadowToken;
86
- border: BorderToken;
87
- transition: TransitionToken;
88
- gradient: GradientToken;
89
- strokeStyle: StrokeStyleToken;
90
- }
91
- /**
92
- * The union of all twelve token brands. Brands are compile-time tags
93
- * naming each token's type; they let {@link css} reject a dimension
94
- * where a color belongs. They exist only in the type system — every
95
- * ref is a plain string at runtime, so brands cost nothing — and they
96
- * are theme-independent, so tokens minted by two different
97
- * {@link createTheme} calls mix freely in one {@link css} call.
98
- */
99
- type AnyToken = BrandByType[TokenType];
100
- //#endregion
101
- //#region src/types.d.ts
102
- /**
103
- * A DTCG group node: an optional `$type` shared by descendants, plus
104
- * nested groups and tokens.
105
- *
106
- * @internal
107
- */
108
- interface TokenGroup {
109
- $type?: TokenType;
110
- $description?: string;
111
- $extensions?: Record<string, unknown>;
112
- [key: string]: unknown;
113
- }
114
- /**
115
- * The input document {@link createTheme} accepts, shaped by the
116
- * [W3C DTCG format](https://www.designtokens.org/tr/drafts/format/). A
117
- * node with a `$value` is a token; every other key is a group, and
118
- * groups nest to any depth. A token's type comes from its own
119
- * `$type`, from the token it aliases, or from the nearest ancestor
120
- * group's `$type`, in that order.
121
- *
122
- * Each `$type` fixes the accepted `$value` forms and how the value
123
- * serializes into CSS:
124
- *
125
- * | `$type` | Accepted `$value` | Serializes to |
126
- * | --- | --- | --- |
127
- * | `color` | CSS color string, or `{ colorSpace, components, alpha?, hex? }` | the string as written, `hex` when present, or the color-space function (`oklch(…)`, `color(display-p3 …)`) |
128
- * | `dimension` | `"16px"`, or `{ value, unit }` with `px` or `rem` | the string verbatim, or concatenation |
129
- * | `duration` | `"200ms"`, or `{ value, unit }` with `ms` or `s` | the string verbatim, or concatenation |
130
- * | `fontFamily` | string or non-empty array of strings | quoted where needed, comma-joined |
131
- * | `fontWeight` | number 1–1000, or a DTCG keyword like `"semi-bold"` | the number (keywords map to numbers) |
132
- * | `number` | number | the number |
133
- * | `cubicBezier` | `[x1, y1, x2, y2]` | `cubic-bezier(…)` |
134
- * | `shadow` | `{ color, offsetX, offsetY, blur?, spread?, inset? }`, or an array of them | a CSS shadow list, `inset` first when `inset` is `true` |
135
- * | `border` | `{ color, width, style }` | `width style color` |
136
- * | `transition` | `{ duration, timingFunction, delay? }` | `duration timing-function delay` |
137
- * | `gradient` | array of `{ color, position }` stops | a color-stop list for use inside `linear-gradient(…)` |
138
- * | `strokeStyle` | keyword or object | the keyword, or `dashed` for the object form |
139
- *
140
- * Gradient stop positions must be literal numbers, though stop colors
141
- * may be aliases. `typography` tokens throw — they need one variable
142
- * per subproperty, which is not built.
143
- *
144
- * Only the object form of a `dimension` or `duration` is unit-checked.
145
- * The string form is emitted verbatim, which is the way in for units
146
- * the DTCG format does not cover (`em`, `ch`, `%`) and for computed
147
- * values such as `clamp(…)`.
148
- *
149
- * A `$value` of `"{path.to.token}"` is an alias: it resolves to
150
- * `var()` indirection in the emitted CSS, not a copied value, which is
151
- * what makes mode overrides cascade. Aliases work as full token values
152
- * and inside composite sub-values (e.g. a shadow's `color`), and they
153
- * are type-checked — a token with an explicit `$type` only aliases a
154
- * token of that same type. Unknown targets and reference cycles throw.
155
- *
156
- * @see {@link createTheme}
157
- * @see {@link TokenTree} for the resulting accessor shape.
158
- * @see {@link DeepPartialTokens} for the mode-override shape.
159
- */
160
- type DTCGDocument = TokenGroup;
161
- type GroupType<N, Inherited> = N extends {
162
- $type: infer Ty extends TokenType;
163
- } ? Ty : Inherited;
164
- type BrandOf<Ty> = Ty extends TokenType ? BrandByType[Ty] : never;
165
- type TokenTypeOf<N, Root, Inherited> = N extends {
166
- $type: infer Ty extends TokenType;
167
- } ? Ty : N extends {
168
- $value: `{${infer P}}`;
169
- } ? TypeAtPath<Root, P, Root, GroupType<Root, undefined>> : Inherited extends TokenType ? Inherited : never;
170
- type MatchKey<N, S extends string> = keyof N extends (infer K) ? K extends string | number ? `${K}` extends S ? K : never : never : never;
171
- type TypeAtPath<N, P extends string, Root, Inherited> = P extends `${infer Head}.${infer Rest}` ? MatchKey<N, Head> extends (infer K) ? [K] extends [never] ? never : TypeAtPath<N[K & keyof N], Rest, Root, GroupType<N[K & keyof N], Inherited>> : never : MatchKey<N, P> extends (infer K) ? [K] extends [never] ? never : TokenTypeOf<N[K & keyof N], Root, Inherited> : never;
172
- type TreeOf<N, Root, Inherited> = { [K in Exclude<keyof N, `$${string}`>]: N[K] extends {
173
- $value: unknown;
174
- } ? BrandOf<TokenTypeOf<N[K], Root, Inherited>> : TreeOf<N[K], Root, GroupType<N[K], Inherited>>; };
175
- /**
176
- * The accessor shape for a document `T`: the same nesting as the
177
- * document, with every token leaf replaced by its branded `var(--…)`
178
- * reference string. Numeric keys index with brackets
179
- * (`t.color.gray[900]`).
180
- *
181
- * An `any` document (e.g. from `JSON.parse`) short-circuits to
182
- * `unknown` — mapping over `any` would otherwise recurse without
183
- * bound.
184
- *
185
- * @see {@link ThemeResult}
186
- */
187
- type TokenTree<T> = 0 extends 1 & T ? unknown : TreeOf<T, T, GroupType<T, undefined>>;
188
- /**
189
- * The mode-override shape for a document `T`: every group is optional
190
- * and each token node is reduced to `{ $value }`. A mode overrides a
191
- * token's value only, never its `$type` or structure.
192
- *
193
- * An `any` document short-circuits to `unknown`, as in
194
- * {@link TokenTree}.
195
- *
196
- * @see {@link ThemeOptions}
197
- */
198
- type DeepPartialTokens<T> = 0 extends 1 & T ? unknown : { [K in Exclude<keyof T, `$${string}`>]?: T[K] extends {
199
- $value: unknown;
200
- } ? {
201
- $value: unknown;
202
- } : DeepPartialTokens<T[K]>; };
203
- //#endregion
204
- //#region src/theme.d.ts
205
- /**
206
- * Options for {@link createTheme}.
207
- *
208
- * @see {@link DeepPartialTokens} for the override shape.
209
- */
210
- interface ThemeOptions<T> {
211
- /**
212
- * Per-appearance token overrides. Each mode is a partial of the
213
- * base document that may set `$value` only; its overrides emit
214
- * inside an `@media (prefers-color-scheme: <mode>)` block, so the
215
- * OS appearance setting flips the affected variables with no
216
- * attribute selectors and no JavaScript.
217
- */
218
- modes?: {
219
- /** Overrides applied under `prefers-color-scheme: light`. */
220
- light?: DeepPartialTokens<T>;
221
- /** Overrides applied under `prefers-color-scheme: dark`. */
222
- dark?: DeepPartialTokens<T>;
223
- };
224
- }
225
- /**
226
- * Props for the {@link ThemeComponent}. `nonce` sets the `nonce`
227
- * attribute on the emitted `<style>` element for Content Security
228
- * Policy setups.
229
- */
230
- type ThemeProps = {
231
- /** CSP nonce forwarded to the `<style>` element's `nonce` attribute. */
232
- nonce?: string;
233
- };
234
- /**
235
- * The `<Theme />` component returned by {@link createTheme}. Render it
236
- * once near the document root (e.g. inside `<head>`). It renders a
237
- * `<style data-pitlane-theme>` element holding the base `:root`
238
- * declarations plus one `@media` block per configured mode, streams
239
- * identically on the server and the client, and escapes the style
240
- * text so token values cannot break out of the tag.
241
- *
242
- * @see {@link ThemeProps} for the `nonce` prop.
243
- */
244
- type ThemeComponent = (handle: Handle<ThemeProps>) => () => RemixElement;
245
- /**
246
- * The object returned by {@link createTheme}: the typed token
247
- * accessor, the `raw` resolver, and the `<Theme />` component.
248
- */
249
- interface ThemeResult<T> {
250
- /**
251
- * Same-shape accessor over the document: every token leaf is a
252
- * branded `var(--…)` reference string. Numeric keys index with
253
- * brackets (`t.color.gray[900]`).
254
- *
255
- * @see {@link TokenTree}
256
- */
257
- token: TokenTree<T>;
258
- /**
259
- * Resolves a token ref to its serialized base-mode value, chasing
260
- * aliases and composite sub-value references to the end. It always
261
- * answers for the base mode, even when a dark override exists,
262
- * since mode resolution happens in CSS rather than in JavaScript.
263
- * Because refs are plain strings, two themes that mint the same
264
- * token path produce identical refs and `raw` cannot tell them
265
- * apart, answering for its own theme.
266
- *
267
- * @param ref - A branded token ref from this theme's accessor.
268
- * @throws ThemeError if `ref` names a variable this theme never
269
- * minted.
270
- */
271
- raw(ref: AnyToken): string;
272
- /** The `<Theme />` component. @see {@link ThemeComponent} */
273
- Theme: ThemeComponent;
274
- }
275
- /**
276
- * Compiles a DTCG design-token document into a typed accessor, a
277
- * `raw` resolver, and a `<Theme />` component. All validation and
278
- * serialization happen eagerly here: a malformed document throws
279
- * {@link ThemeError} rather than emitting broken CSS.
280
- *
281
- * Each token becomes a CSS custom property named after its
282
- * kebab-cased path — `color.gray.900` becomes `--color-gray-900`.
283
- * Two paths that collide after kebab-casing throw, as do names
284
- * containing `.`, `{`, or `}`, which the alias syntax reserves.
285
- *
286
- * Author the document in TypeScript, not imported JSON: `createTheme`
287
- * infers a `const` type parameter, so an inline object needs no
288
- * `as const`, but a JSON import widens its literals and the token
289
- * brands degrade.
290
- *
291
- * @param config - The token document. Groups nest to any depth; a
292
- * node with a `$value` is a token.
293
- * @param options - Optional per-mode overrides ({@link ThemeOptions}).
294
- * @returns The {@link ThemeResult}: `token`, `raw`, and `Theme`.
295
- * @throws ThemeError on any validation failure (unknown or
296
- * unresolvable `$type`, reserved characters, variable collision,
297
- * unknown or wrong-typed alias, alias cycle, invalid value, or a bad
298
- * mode override).
299
- *
300
- * @see {@link DTCGDocument} for the document shape, the accepted
301
- * `$value` forms, and alias semantics.
302
- *
303
- * @example
304
- * ```ts
305
- * export let { token: t, raw, Theme } = createTheme(
306
- * {
307
- * color: {
308
- * $type: "color",
309
- * white: { $value: "#fff" },
310
- * gray: { 900: { $value: "#171717" } },
311
- * bg: { $value: "{color.white}" }, // alias → var() indirection
312
- * },
313
- * },
314
- * { modes: { dark: { color: { bg: { $value: "{color.gray.900}" } } } } },
315
- * );
316
- *
317
- * t.color.bg; // "var(--color-bg)"
318
- * raw(t.color.bg); // "#fff" (base mode, alias chased to the end)
319
- * ```
320
- */
321
- declare function createTheme<const T extends DTCGDocument>(config: T, options?: ThemeOptions<T>): ThemeResult<T>;
322
- //#endregion
323
5
  //#region src/props.d.ts
324
6
  type Wide = "inherit" | "initial" | "unset" | "revert" | "revert-layer";
325
7
  type ColorLike = ColorToken | "transparent" | "currentColor" | Wide;
@@ -541,6 +223,78 @@ type ThemedCSSMixin<node extends Element = Element> = MixinDescriptor<node, [sty
541
223
  */
542
224
  declare function css<node extends Element = Element>(styles: ThemedCSSProps): ThemedCSSMixin<node>;
543
225
  //#endregion
226
+ //#region src/scale.d.ts
227
+ /**
228
+ * Turns one token into a multiplier, so a scale does not have to name
229
+ * every step. The returned function produces
230
+ * `calc(<base> * <steps>)`, keeping whichever brand the base carried.
231
+ *
232
+ * Use this for a token you did not declare as a scale. A token
233
+ * declared with `s.scale()` is already a multiplier, and its base is
234
+ * `t.spacing.token` when you need it.
235
+ *
236
+ * The result is a CSS string like any other, so it also works as an
237
+ * authored token value.
238
+ *
239
+ * @param base - The token to multiply
240
+ * @returns A function from steps to a token of the same type
241
+ *
242
+ * @example
243
+ * ```ts
244
+ * import { scale } from "@pitlane/theme";
245
+ *
246
+ * let step = scale(t.tracking.tight);
247
+ * css({ letterSpacing: step(2) }); // calc(var(--tracking-tight) * 2)
248
+ * ```
249
+ */
250
+ declare function scale<base extends ScalableToken>(base: base): (steps: number) => base;
251
+ /**
252
+ * A `light-dark()` color, resolved by the browser against the
253
+ * `color-scheme` property. A subtree that sets `color-scheme` flips
254
+ * whatever the media query says, which is what a theme toggle needs.
255
+ *
256
+ * Both arguments may be token references, so a mode override of either
257
+ * primitive still reaches the result.
258
+ *
259
+ * `light-dark()` is color-only. Use `modes` for anything else.
260
+ *
261
+ * @param light - The color for a light `color-scheme`
262
+ * @param dark - The color for a dark `color-scheme`
263
+ * @returns The `light-dark()` function text
264
+ *
265
+ * @example
266
+ * ```ts
267
+ * tokens: { surface: { page: lightDark("#ffffff", "#1a1a1a") } }
268
+ * ```
269
+ */
270
+ declare function lightDark(light: string, dark: string): string;
271
+ //#endregion
272
+ //#region src/tokens.d.ts
273
+ /**
274
+ * The error {@link createTheme} throws for every structural failure:
275
+ * one problem, one sentence.
276
+ *
277
+ * | Failure | Message shape |
278
+ * | --- | --- |
279
+ * | No schema entry | `"space.md" has no schema entry` |
280
+ * | Unknown reference | `"color.bg" references unknown token "color.nope"` |
281
+ * | Reference type mismatch | `"color.bg" references "space.md" of type "dimension" where "color" is required` |
282
+ * | Reference to an untyped token | `"color.bg" references untyped token "animate.spin"` |
283
+ * | Reference cycle | `Reference cycle: color.a → color.b → color.a` |
284
+ * | Variable collision | `Tokens "a.b" and "a-b" both produce the CSS variable --a-b` |
285
+ * | Reserved characters | `Token or group name "a.b" contains characters reserved by references (".", "{", "}")` |
286
+ * | Empty identifier | `Token path segment "!!" produces an empty CSS identifier` |
287
+ * | Unknown mode token | `Mode "dark" overrides unknown token "color.nope"` |
288
+ *
289
+ * Bad token *values* raise `ValidationError` from `remix/data-schema`
290
+ * instead, because there may be several and each carries its own path.
291
+ *
292
+ * @see {@link createTheme}
293
+ */
294
+ declare class ThemeError extends Error {
295
+ name: string;
296
+ }
297
+ //#endregion
544
298
  //#region src/tva.d.ts
545
299
  type VariantShape = Record<string, Record<string, ThemedCSSProps>>;
546
300
  type VariantValue<K> = K extends "true" | "false" ? boolean : K;
@@ -693,30 +447,4 @@ type ClassValue = string | number | null | undefined | false | readonly ClassVal
693
447
  */
694
448
  declare function cx(...inputs: ClassValue[]): string;
695
449
  //#endregion
696
- //#region src/tokens.d.ts
697
- /**
698
- * The error {@link createTheme} throws for every validation and
699
- * serialization failure. Validation is eager, so a bad document never
700
- * emits CSS. Every message names the offending token path.
701
- *
702
- * | Condition | Message shape |
703
- * | --- | --- |
704
- * | Unknown `$type` | `"color.brand" has unknown $type "sparkles"` |
705
- * | Unresolvable `$type` | `"color.brand" has no resolvable $type` |
706
- * | Typography token | `"heading": typography tokens are not supported in v1` |
707
- * | Reserved character in a name | `Token or group name "a.b" contains characters reserved by DTCG references (".", "{", "}")` |
708
- * | Empty CSS identifier | `Token path segment "!" produces an empty CSS identifier` |
709
- * | Malformed node | `"color.bg" is neither a group nor a token` |
710
- * | Variable-name collision | `Tokens "a" and "b" both produce the CSS variable --x` |
711
- * | Alias to a missing token | `"color.bg" references unknown token "color.white"` |
712
- * | Alias to a wrong-typed token | `"x" references "space.sm" of type "dimension" where "color" is required` |
713
- * | Alias cycle | `Alias cycle: a → b → a` |
714
- * | Invalid value for a declared type | `"x" has an invalid color value: …` — also `unknown colorSpace`, `unknown fontWeight keyword`, and `unknown strokeStyle keyword`; an empty `fontFamily` array counts |
715
- * | Bad mode override | `Mode override "x" does not exist in the base document`, `Mode override "x" may only set $value`, or (via a cross-type alias) the wrong-typed-alias message |
716
- * | Unminted `raw()` ref | `raw(): "var(--x)" names a var this theme never minted` |
717
- */
718
- declare class ThemeError extends Error {
719
- name: string;
720
- }
721
- //#endregion
722
- export { type AnyToken, type BorderToken, type ClassValue, type ColorToken, type CombinedTVAFn, type CubicBezierToken, type DTCGDocument, type DeepPartialTokens, type DimensionToken, type DurationToken, type FontFamilyToken, type FontWeightToken, type GradientToken, type NumberToken, type ShadowToken, type StrokeStyleToken, type TVAConfig, type TVAFn, type TVAProps, type ThemeComponent, ThemeError, type ThemeOptions, type ThemeProps, type ThemeResult, type ThemedCSSMixin, type ThemedCSSProps, type TokenTree, type TokenType, type TransitionToken, combine, createTheme, css, cx, tva };
450
+ export { type AnyToken, type BorderToken, type ClassValue, type ColorToken, type CombinedTVAFn, type CubicBezierToken, type DeepPartialTokens, type DimensionToken, type DurationToken, type FontFamilyToken, type FontWeightToken, type GradientToken, type Merged, type NumberToken, type ScalableToken, type ScaleFn, type ShadowToken, type StrokeStyleToken, type TVAConfig, type TVAFn, type TVAProps, type ThemeComponent, ThemeError, type ThemeInit, type ThemeMode, type ThemePatch, type ThemeProps, type ThemeResult, type ThemedCSSMixin, type ThemedCSSProps, type TokenTree, type TokenType, type TokenValue, type Tokens, type TransitionToken, type UntypedToken, combine, createTheme, css, cx, lightDark, scale, tva };