@pitlane/theme 0.1.0 → 0.3.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.
@@ -0,0 +1,237 @@
1
+ import { C as assertNoStringReference, E as mentionedVarNames, S as ThemeError, T as kebabSegment, _ as selfSchema, a as childSchema, h as pathKey, p as isTokenSchema, w as collectTokens, x as serializeValue } from "./schema-JmfNnMzr.mjs";
2
+ import { createElement } from "remix/ui";
3
+ import { createSchema, fail, object, parse } from "remix/data-schema";
4
+ //#region src/validate.ts
5
+ /**
6
+ * Composes the sparse schema tree and the token tree into one
7
+ * `remix/data-schema` object schema, so a single `parse` validates
8
+ * every token and reports each failure with its own path.
9
+ *
10
+ * A token with no schema entry gets a schema that always fails, so a
11
+ * missing declaration is reported alongside any bad values rather than
12
+ * short-circuiting them.
13
+ *
14
+ * @internal
15
+ */
16
+ function composeSchema(tokens, schema) {
17
+ return compose(tokens, schema, void 0);
18
+ }
19
+ function compose(tokens, schema, inherited) {
20
+ let shape = {};
21
+ for (let [key, value] of Object.entries(tokens)) {
22
+ let child = childSchema(schema, key);
23
+ let own = selfSchema(child) ?? inherited;
24
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) shape[key] = compose(value, child, own);
25
+ else if (own === void 0) shape[key] = createSchema((_, context) => fail(`"${pathKey(context.path)}" has no schema entry`, context.path));
26
+ else shape[key] = own;
27
+ }
28
+ return object(shape);
29
+ }
30
+ //#endregion
31
+ //#region src/theme.ts
32
+ const REF_RE = /^var\((--[a-z0-9-]+)\)$/;
33
+ function createTheme(input) {
34
+ return compile(typeof input === "function" ? input.$theme : input);
35
+ }
36
+ function compile(init) {
37
+ parse(composeSchema(init.tokens, init.schema), init.tokens, { abortEarly: false });
38
+ let entries = collectTokens(init.tokens, init.schema);
39
+ let byKey = new Map(entries.map((entry) => [entry.key, entry]));
40
+ let byVarName = new Map(entries.map((entry) => [entry.varName, entry]));
41
+ let ctx = referenceContext(byKey);
42
+ let cssText = buildCssText(entries.map((entry) => [entry.varName, declare(entry, ctx)]), modeBlocks(init.modes, byKey, ctx));
43
+ return {
44
+ cssText,
45
+ token: buildAccessor(entries),
46
+ Theme: createThemeComponent(cssText, init),
47
+ raw(ref) {
48
+ return resolveRaw(ref, byVarName, byKey, []);
49
+ },
50
+ extend(patch) {
51
+ let accessor = buildAccessor(entries);
52
+ let next = typeof patch === "function" ? patch(accessor) : patch;
53
+ return compile({
54
+ schema: mergeDeep(init.schema, next.schema ?? {}),
55
+ tokens: mergeDeep(init.tokens, next.tokens),
56
+ modes: {
57
+ ...init.modes,
58
+ ...next.modes
59
+ }
60
+ });
61
+ },
62
+ select(projection) {
63
+ let next = projection(buildAccessor(entries));
64
+ let projected = reroot(next.tokens, byVarName);
65
+ assertNoDroppedReferences(projected, byVarName);
66
+ return compile({
67
+ schema: next.schema,
68
+ tokens: projected,
69
+ modes: next.modes
70
+ });
71
+ }
72
+ };
73
+ }
74
+ function referenceContext(byKey) {
75
+ return { varRefFor(key, from, expected) {
76
+ let target = byKey.get(key);
77
+ if (target === void 0) throw new ThemeError(`"${from}" references unknown token "${key}"`);
78
+ if (target.kind === "untyped") throw new ThemeError(`"${from}" references untyped token "${key}"`);
79
+ let type = target.kind === "scale" ? "dimension" : target.type;
80
+ if (type !== expected) throw new ThemeError(`"${from}" references "${key}" of type "${type}" where "${expected}" is required`);
81
+ return `var(${target.varName})`;
82
+ } };
83
+ }
84
+ function declare(entry, ctx) {
85
+ if (entry.kind === "untyped") return entry.value;
86
+ if (entry.kind === "scale") return serializeValue("dimension", entry.value, ctx, entry.key);
87
+ if (entry.aliasOf !== void 0) return ctx.varRefFor(entry.aliasOf, entry.key, entry.type);
88
+ return serializeValue(entry.type, entry.value, ctx, entry.key);
89
+ }
90
+ function modeBlocks(modes, byKey, ctx) {
91
+ if (modes === void 0) return [];
92
+ let selectorBlocks = [];
93
+ let mediaBlocks = [];
94
+ for (let [name, mode] of Object.entries(modes)) {
95
+ let overrides = [];
96
+ walkMode(mode.tokens, [], name, byKey, ctx, overrides);
97
+ if (overrides.length === 0) continue;
98
+ if (mode.selector !== void 0) {
99
+ let lines = overrides.map(([varName, value]) => ` ${varName}: ${value};`);
100
+ selectorBlocks.push(`${mode.selector} {\n${lines.join("\n")}\n}`);
101
+ }
102
+ let media = mode.media ?? `(prefers-color-scheme: ${name})`;
103
+ let lines = overrides.map(([varName, value]) => ` ${varName}: ${value};`);
104
+ mediaBlocks.push(`@media ${media} {\n :root {\n${lines.join("\n")}\n }\n}`);
105
+ }
106
+ return [...selectorBlocks, ...mediaBlocks];
107
+ }
108
+ function walkMode(node, path, mode, byKey, ctx, out) {
109
+ if (typeof node !== "object" || node === null || Array.isArray(node)) throw new ThemeError(`Mode "${mode}" override at "${path.join(".")}" is not a group`);
110
+ for (let [key, value] of Object.entries(node)) {
111
+ let childPath = [...path, key];
112
+ let childKey = childPath.join(".");
113
+ let entry = byKey.get(childKey);
114
+ if (entry === void 0) {
115
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
116
+ walkMode(value, childPath, mode, byKey, ctx, out);
117
+ continue;
118
+ }
119
+ throw new ThemeError(`Mode "${mode}" overrides unknown token "${childKey}"`);
120
+ }
121
+ if (entry.kind === "untyped") {
122
+ out.push([entry.varName, String(value)]);
123
+ continue;
124
+ }
125
+ assertNoStringReference(value, childKey);
126
+ let type = entry.kind === "scale" ? "dimension" : entry.type;
127
+ out.push([entry.varName, serializeValue(type, value, ctx, childKey)]);
128
+ }
129
+ }
130
+ function resolveRaw(ref, byVarName, byKey, chain) {
131
+ let match = REF_RE.exec(ref);
132
+ let entry = match === null ? void 0 : byVarName.get(match[1]);
133
+ if (entry === void 0) throw new ThemeError(`"${ref}" was not minted by this theme`);
134
+ if (chain.includes(entry.key)) throw new ThemeError(`Reference cycle: ${[...chain, entry.key].join(" → ")}`);
135
+ if (entry.kind === "typed" && entry.aliasOf !== void 0) {
136
+ let target = byKey.get(entry.aliasOf);
137
+ if (target === void 0) throw new ThemeError(`"${entry.key}" references unknown token "${entry.aliasOf}"`);
138
+ return resolveRaw(`var(${target.varName})`, byVarName, byKey, [...chain, entry.key]);
139
+ }
140
+ if (entry.kind === "untyped") return entry.value;
141
+ return serializeValue(entry.kind === "scale" ? "dimension" : entry.type, entry.value, { varRefFor: (key, from, expected) => {
142
+ let target = byKey.get(key);
143
+ if (target === void 0) throw new ThemeError(`"${from}" references unknown token "${key}"`);
144
+ return resolveRaw(`var(${target.varName})`, byVarName, byKey, [...chain, entry.key]);
145
+ } }, entry.key);
146
+ }
147
+ /**
148
+ * A projected value may itself be a `var()` reference to a token the projection
149
+ * left behind, which the cascade would resolve to nothing. The reference is
150
+ * detectable because its variable belonged to the theme being projected from.
151
+ */
152
+ function assertNoDroppedReferences(tokens, sourceByVarName) {
153
+ let kept = /* @__PURE__ */ new Set();
154
+ let walkValues = (node, path) => {
155
+ if (typeof node === "object" && node !== null && !Array.isArray(node)) {
156
+ for (let [key, value] of Object.entries(node)) walkValues(value, [...path, key]);
157
+ return;
158
+ }
159
+ for (let varName of mentionedVarNames(node)) {
160
+ let source = sourceByVarName.get(varName);
161
+ if (source !== void 0 && !kept.has(source.varName)) throw new ThemeError(`"${path.join(".")}" references "${source.key}", which the projection dropped`);
162
+ }
163
+ };
164
+ let record = (node, path) => {
165
+ if (typeof node === "object" && node !== null && !Array.isArray(node)) {
166
+ for (let [key, value] of Object.entries(node)) record(value, [...path, key]);
167
+ return;
168
+ }
169
+ kept.add(`--${path.map(kebabSegment).join("-")}`);
170
+ };
171
+ record(tokens, []);
172
+ walkValues(tokens, []);
173
+ }
174
+ function buildAccessor(entries) {
175
+ let root = Object.create(null);
176
+ for (let entry of entries) {
177
+ let node = root;
178
+ for (let segment of entry.path.slice(0, -1)) {
179
+ let next = node[segment];
180
+ if (next === void 0) {
181
+ next = Object.create(null);
182
+ node[segment] = next;
183
+ }
184
+ node = next;
185
+ }
186
+ let ref = `var(${entry.varName})`;
187
+ node[entry.path.at(-1)] = entry.kind === "scale" ? scaleLeaf(ref) : ref;
188
+ }
189
+ return root;
190
+ }
191
+ function scaleLeaf(ref) {
192
+ let fn = (steps) => `calc(${ref} * ${steps})`;
193
+ return Object.assign(fn, { token: ref });
194
+ }
195
+ function buildCssText(declarations, blocks) {
196
+ let lines = declarations.map(([name, value]) => ` ${name}: ${value};`);
197
+ if (declarations.some(([, value]) => value.includes("light-dark("))) lines.unshift(" color-scheme: light dark;");
198
+ return [`:root {\n${lines.join("\n")}\n}`, ...blocks].join("\n\n");
199
+ }
200
+ function createThemeComponent(cssText, init) {
201
+ let escaped = cssText.replaceAll("</style", "<\\/style");
202
+ let component = (handle) => () => createElement("style", {
203
+ nonce: handle.props.nonce,
204
+ "data-pitlane-theme": "",
205
+ innerHTML: escaped
206
+ });
207
+ return Object.assign(component, { $theme: init });
208
+ }
209
+ function mergeDeep(a, b) {
210
+ if (!isPlainRecord(a) || !isPlainRecord(b)) return b;
211
+ let out = { ...a };
212
+ for (let [key, value] of Object.entries(b)) out[key] = mergeDeep(out[key], value);
213
+ return out;
214
+ }
215
+ function isPlainRecord(value) {
216
+ return typeof value === "object" && value !== null && !Array.isArray(value) && !isTokenSchema(value);
217
+ }
218
+ /**
219
+ * A projection holds accessor references, so each one resolves back to
220
+ * the value its token holds. A scale leaf is projected through its
221
+ * `.token`, which is an ordinary reference by the time it arrives.
222
+ */
223
+ function reroot(node, byVarName) {
224
+ if (typeof node === "object" && node !== null && !Array.isArray(node)) {
225
+ let out = {};
226
+ for (let [key, value] of Object.entries(node)) out[key] = reroot(value, byVarName);
227
+ return out;
228
+ }
229
+ if (typeof node !== "string") return node;
230
+ let match = REF_RE.exec(node);
231
+ if (match === null) return node;
232
+ let source = byVarName.get(match[1]);
233
+ if (source === void 0) throw new ThemeError(`"${node}" was not minted by the theme being selected from`);
234
+ return source.value;
235
+ }
236
+ //#endregion
237
+ export { createTheme as t };
@@ -0,0 +1,278 @@
1
+ import { A as DimensionToken, B as UntypedToken, D as BrandByType, F as NumberToken, R as TokenType, T as AnyToken, a as TAG, i as SchemaTag, j as DurationToken, t as SELF } from "./schema-CRP607Pg.mjs";
2
+ import { Handle, RemixElement } from "remix/ui";
3
+ //#region src/types.d.ts
4
+ /**
5
+ * A token value: the CSS it becomes. A string, a number, or an array
6
+ * of either. Anything else is a group.
7
+ *
8
+ * @see {@link Tokens}
9
+ */
10
+ type TokenValue = number | readonly (number | string)[] | string;
11
+ /**
12
+ * The token tree {@link createTheme} accepts: nested records whose
13
+ * leaves are {@link TokenValue}s. No reserved keys, so it is plain
14
+ * JSON and a designer can diff it.
15
+ */
16
+ interface Tokens {
17
+ [key: string]: Tokens | TokenValue;
18
+ }
19
+ /**
20
+ * The accessor leaf for a token declared with `s.scale()`: callable
21
+ * for steps, with the base itself as `.token`.
22
+ *
23
+ * `.token` is what a projection re-roots and what `raw` resolves, so
24
+ * it is load-bearing rather than decorative.
25
+ *
26
+ * @see {@link TokenTree}
27
+ */
28
+ interface ScaleFn {
29
+ (steps: number): DimensionToken;
30
+ readonly token: DimensionToken;
31
+ }
32
+ /** A theme's mode: a condition plus the values it overrides. */
33
+ interface ThemeMode<T> {
34
+ /**
35
+ * The media query this mode applies under. Defaults to
36
+ * `(prefers-color-scheme: <name>)` for the names `light` and
37
+ * `dark`, and is required for any other name.
38
+ */
39
+ media?: string;
40
+ /**
41
+ * A selector this mode also applies under, for a user-selectable
42
+ * toggle. An attribute selector outranks the media block on
43
+ * specificity, so an explicit choice beats the OS preference.
44
+ */
45
+ selector?: string;
46
+ /** The values this mode overrides. Structure only, never types. */
47
+ tokens: DeepPartialTokens<T>;
48
+ }
49
+ /**
50
+ * The argument {@link createTheme} accepts: a schema tree, the token
51
+ * tree it describes, and any modes.
52
+ *
53
+ * The members are typed as bare objects on purpose. A `const` type
54
+ * parameter constrained to an index-signature type widens the literal
55
+ * it was inferred from, which would erase every brand; the shapes are
56
+ * enforced by the schema factories being typed values, by an
57
+ * undeclared leaf resolving to `unknown`, and by validation at module
58
+ * load.
59
+ */
60
+ interface ThemeInit {
61
+ schema: object;
62
+ tokens: object;
63
+ modes?: object;
64
+ }
65
+ /**
66
+ * The argument `extend` accepts. `schema` is optional, because a patch
67
+ * that only adds tokens to an existing namespace needs no new entry.
68
+ */
69
+ interface ThemePatch {
70
+ schema?: object;
71
+ tokens: object;
72
+ modes?: object;
73
+ }
74
+ /**
75
+ * The mode-override shape for a token tree: every group optional, every
76
+ * leaf a value. A mode overrides values, never structure or types.
77
+ */
78
+ type DeepPartialTokens<T> = 0 extends 1 & T ? unknown : { [K in keyof T]?: T[K] extends Leaf ? TokenValue : DeepPartialTokens<T[K]>; };
79
+ type Leaf = number | readonly (number | string)[] | string;
80
+ type BrandOf<tag> = [tag] extends [never] ? unknown : [tag] extends ["any"] ? UntypedToken : [tag] extends ["scale"] ? ScaleFn : tag extends TokenType ? BrandByType[tag] : unknown;
81
+ /** The tag a schema node declares for itself and its unlabelled children. */
82
+ type NodeTag<S, Inherited> = S extends {
83
+ readonly [TAG]: infer tag extends SchemaTag;
84
+ } ? tag : S extends {
85
+ readonly [SELF]: {
86
+ readonly [TAG]: infer tag extends SchemaTag;
87
+ };
88
+ } ? tag : Inherited;
89
+ type Child<S, K> = K extends keyof S ? S[K] : undefined;
90
+ type LeafTag<S, Inherited> = S extends {
91
+ readonly [TAG]: infer tag extends SchemaTag;
92
+ } ? tag : Inherited;
93
+ type TreeOf<Tok, Sch, Inherited> = { [K in keyof Tok]: Tok[K] extends Leaf ? BrandOf<LeafTag<Child<Sch, K>, Inherited>> : TreeOf<Tok[K], Child<Sch, K>, NodeTag<Child<Sch, K>, Inherited>>; };
94
+ /**
95
+ * The accessor shape for an init `T`: the same nesting as its token
96
+ * tree, with every leaf replaced by the branded `var(--…)` reference
97
+ * its schema declares. Numeric keys index with brackets
98
+ * (`t.color.gray[900]`).
99
+ *
100
+ * A leaf whose schema entry is missing resolves to `unknown`, which is
101
+ * unusable in `css()`. The compiler also throws for it at module load.
102
+ *
103
+ * @see {@link ThemeResult}
104
+ */
105
+ type TokenTree<T> = 0 extends 1 & T ? unknown : T extends {
106
+ schema: infer Sch;
107
+ tokens: infer Tok;
108
+ } ? TreeOf<Tok, Sch, never> : unknown;
109
+ /**
110
+ * Deep-merges an `extend` patch onto the tree it extends. A leaf
111
+ * replaces wholesale; every other node recurses.
112
+ *
113
+ * @internal
114
+ */
115
+ type DeepMerge<A, B> = { [K in keyof A | keyof B]: K extends keyof B ? K extends keyof A ? B[K] extends Leaf ? B[K] : A[K] extends Leaf ? B[K] : DeepMerge<A[K], B[K]> : B[K] : K extends keyof A ? A[K] : never; };
116
+ /**
117
+ * The init an `extend` produces: both trees merged.
118
+ *
119
+ * @internal
120
+ */
121
+ interface Merged<T, E> {
122
+ schema: DeepMerge<T extends {
123
+ schema: infer S;
124
+ } ? S : {}, E extends {
125
+ schema: infer S;
126
+ } ? S : {}>;
127
+ tokens: DeepMerge<T extends {
128
+ tokens: infer S;
129
+ } ? S : {}, E extends {
130
+ tokens: infer S;
131
+ } ? S : {}>;
132
+ }
133
+ /** The bases {@link scale} accepts. @internal */
134
+ type ScalableToken = DimensionToken | DurationToken | NumberToken;
135
+ //#endregion
136
+ //#region src/theme.d.ts
137
+ /**
138
+ * Props for the {@link ThemeComponent}. `nonce` sets the `nonce`
139
+ * attribute on the emitted `<style>` element for Content Security
140
+ * Policy setups.
141
+ */
142
+ type ThemeProps = {
143
+ nonce?: string;
144
+ };
145
+ /**
146
+ * The `<Theme />` component {@link createTheme} returns. Render it
147
+ * once near the document root to install the custom properties.
148
+ *
149
+ * It is an ordinary component with one extra property, `$theme`,
150
+ * holding the init it was compiled from, so a published theme can be
151
+ * handed straight back to {@link createTheme}.
152
+ */
153
+ interface ThemeComponent<T> {
154
+ (handle: Handle<ThemeProps>): () => RemixElement;
155
+ readonly $theme: T;
156
+ }
157
+ /**
158
+ * The object {@link createTheme} returns: the typed token accessor,
159
+ * the `raw` resolver, the `<Theme />` component, and the two
160
+ * derivation methods.
161
+ */
162
+ interface ThemeResult<T> {
163
+ /**
164
+ * The compiled CSS text `<Theme />` installs. Exposed for tests
165
+ * and for a build step that emits it as an asset.
166
+ *
167
+ * @internal
168
+ */
169
+ readonly cssText: string;
170
+ /**
171
+ * A typed mirror of the token tree whose leaves are branded
172
+ * `var()` reference strings. A `s.scale()` leaf is callable.
173
+ */
174
+ readonly token: TokenTree<T>;
175
+ /**
176
+ * Resolves a token reference to its concrete base value, following
177
+ * references to the end.
178
+ *
179
+ * @param ref - A token reference minted by this theme
180
+ * @returns The serialized base value
181
+ * @throws ThemeError when the reference was not minted here
182
+ */
183
+ raw(ref: AnyToken | UntypedToken): string;
184
+ /** The component that installs the custom properties. */
185
+ readonly Theme: ThemeComponent<T>;
186
+ /**
187
+ * Deep-merges a patch onto this theme and returns a new one. A
188
+ * leaf replaces wholesale; every other node recurses.
189
+ *
190
+ * The callback form receives this theme's accessor, so a patch can
191
+ * reference what it extends.
192
+ *
193
+ * @param patch - The tokens and schema to merge, or a callback returning them
194
+ * @returns A new theme
195
+ */
196
+ extend<const schema extends object, const tokens extends object>(patch: ExtendPatch<T, schema, tokens> | ((base: TokenTree<T>) => ExtendPatch<T, schema, tokens>)): ThemeResult<Merged<T, {
197
+ schema: schema;
198
+ tokens: tokens;
199
+ }>>;
200
+ /**
201
+ * Replaces this theme with a projection of it. The callback
202
+ * receives this theme's accessor; every value in the projection is
203
+ * a reference into it, and the new path decides the new custom
204
+ * property name, so a projection may also reshape and rename.
205
+ *
206
+ * @param projection - A callback returning the schema and tokens to keep
207
+ * @returns A new theme
208
+ */
209
+ select<const P extends ThemeInit>(projection: (base: TokenTree<T>) => P): ThemeResult<P>;
210
+ }
211
+ /**
212
+ * An `extend` patch. Its modes are checked against the merged token tree rather
213
+ * than the patch's own, because a layer whose only job is to override a base
214
+ * token in a mode declares no tokens of its own.
215
+ */
216
+ type ExtendPatch<T, schema, tokens> = {
217
+ schema?: schema;
218
+ tokens: tokens;
219
+ modes?: Record<string, ThemeMode<T extends {
220
+ tokens: infer base;
221
+ } ? DeepMerge<base, tokens> : tokens>>;
222
+ };
223
+ /**
224
+ * Compiles a theme from a schema tree and the token tree it describes.
225
+ *
226
+ * Values are the CSS they become: a color is any CSS color, a
227
+ * dimension is any CSS length, and a composite is the shorthand text.
228
+ * The schema names each token's type, which is what the accessor's
229
+ * compile-time brands are read from and what `css()` enforces.
230
+ *
231
+ * A reference to another token is a property access on the layer below,
232
+ * so it needs an {@link ThemeResult.extend} layer. The accessor leaf is
233
+ * already a `var()` string, which keeps its indirection in the emitted
234
+ * CSS so a mode override cascades through it. There is no string syntax
235
+ * for a reference; a leftover `"{a.b.c}"` raises {@link ThemeError}.
236
+ *
237
+ * All validation and serialization happen eagerly: a malformed theme
238
+ * throws at module load rather than emitting broken CSS. Bad values
239
+ * raise `ValidationError` from `remix/data-schema`, carrying one issue
240
+ * per bad token with its path. Structural problems raise
241
+ * {@link ThemeError}.
242
+ *
243
+ * @param init - The schema, tokens, and modes, or a `<Theme />` to re-derive from
244
+ * @returns The {@link ThemeResult}
245
+ * @throws ThemeError on a structural failure
246
+ * @throws ValidationError on one or more invalid values
247
+ *
248
+ * @see {@link ThemeInit} for the accepted shape.
249
+ *
250
+ * @example
251
+ * ```ts
252
+ * import { createTheme } from "@pitlane/theme";
253
+ * import * as s from "@pitlane/theme/schema";
254
+ *
255
+ * export let { token: t, raw, Theme } = createTheme({
256
+ * schema: { color: s.color(), spacing: s.scale() },
257
+ * tokens: { color: { white: "#fff" }, spacing: "0.25rem" },
258
+ * }).extend(base => ({
259
+ * schema: { color: s.color() },
260
+ * tokens: { color: { page: base.color.white } },
261
+ * }));
262
+ *
263
+ * t.color.page; // "var(--color-page)"
264
+ * raw(t.color.page); // "#fff"
265
+ * t.spacing(4); // "calc(var(--spacing) * 4)"
266
+ * ```
267
+ */
268
+ declare function createTheme<const schema extends object, const tokens extends object>(init: {
269
+ schema: schema;
270
+ tokens: tokens;
271
+ modes?: Record<string, ThemeMode<tokens>>;
272
+ }): ThemeResult<{
273
+ schema: schema;
274
+ tokens: tokens;
275
+ }>;
276
+ declare function createTheme<T>(theme: ThemeComponent<T>): ThemeResult<T>;
277
+ //#endregion
278
+ export { DeepPartialTokens as a, ScaleFn as c, ThemePatch as d, TokenTree as f, createTheme as i, ThemeInit as l, Tokens as m, ThemeProps as n, Merged as o, TokenValue as p, ThemeResult as r, ScalableToken as s, ThemeComponent as t, ThemeMode as u };
package/package.json CHANGED
@@ -1,53 +1,63 @@
1
1
  {
2
- "name": "@pitlane/theme",
3
- "version": "0.1.0",
4
- "description": "Type-safe styling with W3C design tokens for Remix 3.",
5
- "keywords": [
6
- "css-variables",
7
- "design-tokens",
8
- "dtcg",
9
- "pitlane",
10
- "remix",
11
- "theme"
12
- ],
13
- "homepage": "https://pitlane.tools/package/theme/",
14
- "bugs": {
15
- "url": "https://github.com/pitlane-tools/pitlane/issues"
2
+ "name": "@pitlane/theme",
3
+ "version": "0.3.0",
4
+ "description": "Type-safe styling with W3C design tokens for Remix 3.",
5
+ "keywords": [
6
+ "css-variables",
7
+ "design-tokens",
8
+ "dtcg",
9
+ "pitlane",
10
+ "remix",
11
+ "theme"
12
+ ],
13
+ "homepage": "https://pitlane.tools/package/theme/",
14
+ "bugs": {
15
+ "url": "https://github.com/pitlane-tools/pitlane/issues"
16
+ },
17
+ "license": "MIT",
18
+ "author": "Mark Malstrom <mark@malstrom.me>",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/pitlane-tools/pitlane.git",
22
+ "directory": "packages/theme"
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "CHANGELOG.md"
27
+ ],
28
+ "type": "module",
29
+ "types": "./dist/index.d.mts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.mts",
33
+ "import": "./dist/index.mjs"
16
34
  },
17
- "license": "MIT",
18
- "author": "Mark Malstrom <mark@malstrom.me>",
19
- "repository": {
20
- "type": "git",
21
- "url": "git+https://github.com/pitlane-tools/pitlane.git",
22
- "directory": "packages/theme"
35
+ "./schema": {
36
+ "types": "./dist/schema.d.mts",
37
+ "import": "./dist/schema.mjs"
23
38
  },
24
- "files": [
25
- "dist",
26
- "CHANGELOG.md"
27
- ],
28
- "type": "module",
29
- "types": "./dist/index.d.mts",
30
- "exports": {
31
- ".": {
32
- "types": "./dist/index.d.mts",
33
- "import": "./dist/index.mjs"
34
- }
39
+ "./default": {
40
+ "types": "./dist/default.d.mts",
41
+ "import": "./dist/default.mjs"
35
42
  },
36
- "scripts": {
37
- "prepublishOnly": "vp run build"
38
- },
39
- "dependencies": {
40
- "csstype": "^3.2.3"
41
- },
42
- "devDependencies": {
43
- "remix": "3.0.0-beta.5",
44
- "typescript": "^7.0.2",
45
- "vite-plus": "^0.2.6"
46
- },
47
- "peerDependencies": {
48
- "remix": "^3.0.0-beta.5"
49
- },
50
- "engines": {
51
- "node": "^20.19.0 || >=22.12.0"
43
+ "./dtcg": {
44
+ "types": "./dist/dtcg.d.mts",
45
+ "import": "./dist/dtcg.mjs"
52
46
  }
53
- }
47
+ },
48
+ "dependencies": {
49
+ "csstype": "^3.2.3"
50
+ },
51
+ "devDependencies": {
52
+ "remix": "3.0.0-beta.10",
53
+ "typescript": "^7.0.2",
54
+ "vite-plus": "^0.2.6"
55
+ },
56
+ "peerDependencies": {
57
+ "remix": "^3.0.0-beta.10"
58
+ },
59
+ "engines": {
60
+ "node": "^20.19.0 || >=22.12.0"
61
+ },
62
+ "scripts": {}
63
+ }