@pantoken/utils 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +4 -2
- package/dist/index.mjs +15 -9
- package/dist/scope.d.mts +53 -0
- package/dist/scope.mjs +79 -0
- package/package.json +6 -5
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BOUNDARY_ATTR, BOUNDARY_CLASS, COLOR_ATTR, INSTANCE_ATTR, SCHEME_ATTR, SCOPE_ATTRS, SCOPE_LAYERS, Scheme, THEME_ATTR, colorClass, colorScopeSelector, colorScopeSelectors, isScheme, schemeClass, schemeScopeSelector, schemeScopeSelectors, themeClass, themeScopeSelector, themeScopeSelectors } from "./scope.mjs";
|
|
1
2
|
import { Token } from "@pantoken/model";
|
|
2
3
|
//#region src/declarations.d.ts
|
|
3
4
|
/**
|
|
@@ -77,7 +78,8 @@ interface ResolveOptions {
|
|
|
77
78
|
/**
|
|
78
79
|
* Build a resolver that expands `var(--x)` references to concrete leaf values against `base` (plus
|
|
79
80
|
* any `overrides`). With `mode` it collapses `light-dark()` to that branch; without, it leaves
|
|
80
|
-
* `light-dark()` in place.
|
|
81
|
+
* `light-dark()` in place. A token carrying a {@link Token.flatValue} resolves through that rather
|
|
82
|
+
* than its CSS-expression `value`, so callers always land on a real colour.
|
|
81
83
|
*
|
|
82
84
|
* @param base - The token set to resolve references against.
|
|
83
85
|
* @param options - {@link ResolveOptions}.
|
|
@@ -387,4 +389,4 @@ interface TokenUtilityGroup {
|
|
|
387
389
|
*/
|
|
388
390
|
export declare function tokenUtilitiesCss(groups: readonly TokenUtilityGroup[], options?: UtilityOptions): string;
|
|
389
391
|
//#endregion
|
|
390
|
-
export type
|
|
392
|
+
export { BOUNDARY_ATTR, BOUNDARY_CLASS, COLOR_ATTR, type ColorUtilityEntry, type ColorUtilityNames, INSTANCE_ATTR, type Mode, type ResolveOptions, type Rgba, SCHEME_ATTR, SCOPE_ATTRS, SCOPE_LAYERS, type Scheme, type SpacingStep, THEME_ATTR, type TokenUtilityGroup, type UtilityOptions, colorClass, colorScopeSelector, colorScopeSelectors, isScheme, schemeClass, schemeScopeSelector, schemeScopeSelectors, themeClass, themeScopeSelector, themeScopeSelectors };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BOUNDARY_ATTR, BOUNDARY_CLASS, COLOR_ATTR, INSTANCE_ATTR, SCHEME_ATTR, SCOPE_ATTRS, SCOPE_LAYERS, THEME_ATTR, colorClass, colorScopeSelector, colorScopeSelectors, isScheme, schemeClass, schemeScopeSelector, schemeScopeSelectors, themeClass, themeScopeSelector, themeScopeSelectors } from "./scope.mjs";
|
|
1
2
|
import { regex } from "arkregex";
|
|
2
3
|
//#region src/declarations.ts
|
|
3
4
|
/**
|
|
@@ -134,7 +135,8 @@ const MAX_DEPTH = 12;
|
|
|
134
135
|
/**
|
|
135
136
|
* Build a resolver that expands `var(--x)` references to concrete leaf values against `base` (plus
|
|
136
137
|
* any `overrides`). With `mode` it collapses `light-dark()` to that branch; without, it leaves
|
|
137
|
-
* `light-dark()` in place.
|
|
138
|
+
* `light-dark()` in place. A token carrying a {@link Token.flatValue} resolves through that rather
|
|
139
|
+
* than its CSS-expression `value`, so callers always land on a real colour.
|
|
138
140
|
*
|
|
139
141
|
* @param base - The token set to resolve references against.
|
|
140
142
|
* @param options - {@link ResolveOptions}.
|
|
@@ -185,8 +187,8 @@ const MAX_DEPTH = 12;
|
|
|
185
187
|
* ```
|
|
186
188
|
*/
|
|
187
189
|
function makeResolver(base, options = {}) {
|
|
188
|
-
const map = new Map(base.map((t) => [t.name, t.value]));
|
|
189
|
-
for (const t of options.overrides ?? []) map.set(t.name, t.value);
|
|
190
|
+
const map = new Map(base.map((t) => [t.name, t.flatValue ?? t.value]));
|
|
191
|
+
for (const t of options.overrides ?? []) map.set(t.name, t.flatValue ?? t.value);
|
|
190
192
|
const pickMode = (value) => {
|
|
191
193
|
if (!options.mode) return value;
|
|
192
194
|
const m = LIGHT_DARK_RE.exec(value.trim());
|
|
@@ -223,7 +225,7 @@ function makeResolver(base, options = {}) {
|
|
|
223
225
|
*/
|
|
224
226
|
function resolveTokens(base, options = {}) {
|
|
225
227
|
const resolve = makeResolver(base, options);
|
|
226
|
-
return new Map(base.map((t) => [t.name, resolve(t.value)]));
|
|
228
|
+
return new Map(base.map((t) => [t.name, resolve(t.flatValue ?? t.value)]));
|
|
227
229
|
}
|
|
228
230
|
//#endregion
|
|
229
231
|
//#region src/drift.ts
|
|
@@ -258,6 +260,11 @@ function extractInstuiRefs(text) {
|
|
|
258
260
|
function tokenNames(ir) {
|
|
259
261
|
return new Set(ir.map((t) => t.name));
|
|
260
262
|
}
|
|
263
|
+
function declaredInstuiProperties(text) {
|
|
264
|
+
const declared = new Set([...text.matchAll(/@property\s+(--instui-[\w-]+)/g)].map((m) => m[1]));
|
|
265
|
+
for (const match of text.matchAll(/(--instui-[\w]+(?:-[\w]+)*)\s*:/g)) declared.add(match[1]);
|
|
266
|
+
return declared;
|
|
267
|
+
}
|
|
261
268
|
/**
|
|
262
269
|
* Drift check: `--instui-*` names in `text` that the IR doesn't define (sorted; empty means no
|
|
263
270
|
* drift). Use for outputs that *reference* tokens defined elsewhere — e.g. the docusaurus/vitepress
|
|
@@ -283,7 +290,8 @@ function tokenNames(ir) {
|
|
|
283
290
|
*/
|
|
284
291
|
function unknownReferences(text, ir) {
|
|
285
292
|
const names = tokenNames(ir);
|
|
286
|
-
|
|
293
|
+
const declared = declaredInstuiProperties(text);
|
|
294
|
+
return [...extractInstuiRefs(text)].filter((name) => !names.has(name) && !declared.has(name)).sort();
|
|
287
295
|
}
|
|
288
296
|
/**
|
|
289
297
|
* Self-containment check: `--instui-*` names referenced via `var()` in a stylesheet that it never
|
|
@@ -308,9 +316,7 @@ function unknownReferences(text, ir) {
|
|
|
308
316
|
*/
|
|
309
317
|
function danglingReferences(css) {
|
|
310
318
|
const referenced = new Set([...css.matchAll(/var\(\s*?(--instui-[\w-]+)/g)].map((m) => m[1]));
|
|
311
|
-
const defined =
|
|
312
|
-
for (const m of css.matchAll(/@property\s+(--instui-[\w-]+)/g)) defined.add(m[1]);
|
|
313
|
-
for (const m of css.matchAll(/(--instui-[\w]+(?:-[\w]+)*)\s*:/g)) defined.add(m[1]);
|
|
319
|
+
const defined = declaredInstuiProperties(css);
|
|
314
320
|
return [...referenced].filter((name) => !defined.has(name)).sort();
|
|
315
321
|
}
|
|
316
322
|
//#endregion
|
|
@@ -511,4 +517,4 @@ function tokenUtilitiesCss(groups, options = {}) {
|
|
|
511
517
|
})).join("\n")}\n`;
|
|
512
518
|
}
|
|
513
519
|
//#endregion
|
|
514
|
-
export { ELEVATION_NAMES, FOCUSABLE_SELECTOR, LIGHT_DARK_RE, SPACING_AUTO_STEP, SPACING_STEPS, VAR_RE, camelCase, colorUtilitiesCss, danglingReferences, elevationDeclarations, extractInstuiRefs, focusOutlineDeclarations, focusOutlineRules, globalModifierSelector, makeResolver, parseHexColor, resolveTokens, sanitizeSvg, tokenNames, tokenUtilitiesCss, unknownReferences };
|
|
520
|
+
export { BOUNDARY_ATTR, BOUNDARY_CLASS, COLOR_ATTR, ELEVATION_NAMES, FOCUSABLE_SELECTOR, INSTANCE_ATTR, LIGHT_DARK_RE, SCHEME_ATTR, SCOPE_ATTRS, SCOPE_LAYERS, SPACING_AUTO_STEP, SPACING_STEPS, THEME_ATTR, VAR_RE, camelCase, colorClass, colorScopeSelector, colorScopeSelectors, colorUtilitiesCss, danglingReferences, elevationDeclarations, extractInstuiRefs, focusOutlineDeclarations, focusOutlineRules, globalModifierSelector, isScheme, makeResolver, parseHexColor, resolveTokens, sanitizeSvg, schemeClass, schemeScopeSelector, schemeScopeSelectors, themeClass, themeScopeSelector, themeScopeSelectors, tokenNames, tokenUtilitiesCss, unknownReferences };
|
package/dist/scope.d.mts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/scope.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The scope attribute contract — the single source of truth shared by the CSS emitter
|
|
4
|
+
* (`@pantoken/css`, which selects on these) and the runtime (`@pantoken/scope`, which writes them).
|
|
5
|
+
*
|
|
6
|
+
* Its own module with zero imports, exposed at the `@pantoken/utils/scope` entry, so the browser
|
|
7
|
+
* runtime can take the names without pulling `arkregex` or the resolver in behind the barrel.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
/** Attribute that roots a theme scope. Matches any element, not just `:root`. */
|
|
12
|
+
export declare const THEME_ATTR = "data-pantoken-theme";
|
|
13
|
+
/** Attribute that pins a subtree to a color scheme. */
|
|
14
|
+
export declare const SCHEME_ATTR = "data-pantoken-scheme";
|
|
15
|
+
/** Attribute that selects a custom brand color. */
|
|
16
|
+
export declare const COLOR_ATTR = "data-pantoken-color";
|
|
17
|
+
/** Attribute marking a scope that ancestor resolution must not cross. */
|
|
18
|
+
export declare const BOUNDARY_ATTR = "data-pantoken-boundary";
|
|
19
|
+
/** Attribute carrying the owning instance id, so sibling instances can tell scopes apart. */
|
|
20
|
+
export declare const INSTANCE_ATTR = "data-pantoken-instance";
|
|
21
|
+
/** Every attribute that participates in scope resolution. */
|
|
22
|
+
export declare const SCOPE_ATTRS: readonly ["data-pantoken-theme", "data-pantoken-scheme", "data-pantoken-color", "data-pantoken-boundary", "data-pantoken-instance"];
|
|
23
|
+
/** Cascade layers the scoped sheets emit into, in ascending precedence order. */
|
|
24
|
+
export declare const SCOPE_LAYERS: readonly ["pantoken.base", "pantoken.theme", "pantoken.scheme", "pantoken.color"];
|
|
25
|
+
/** A color scheme a scope can be pinned to. */
|
|
26
|
+
export type Scheme = "light" | "dark";
|
|
27
|
+
/** Narrow an arbitrary value to a {@link Scheme}. */
|
|
28
|
+
export declare function isScheme(value: unknown): value is Scheme;
|
|
29
|
+
/**
|
|
30
|
+
* Class equivalents of the scope attributes, for hosts that sanitize `data-*` but allow `class` —
|
|
31
|
+
* Canvas RCE content being the one that forced them. They follow the repo's global-modifier naming
|
|
32
|
+
* (`.--name`), and the emitter pairs each attribute selector with its class twin.
|
|
33
|
+
*/
|
|
34
|
+
export declare const themeClass: (theme: string) => string;
|
|
35
|
+
/** Class equivalent of `data-pantoken-scheme`. */
|
|
36
|
+
export declare const schemeClass: (scheme: Scheme) => string;
|
|
37
|
+
/** Class equivalent of `data-pantoken-color`. */
|
|
38
|
+
export declare const colorClass: (color: string) => string;
|
|
39
|
+
/** Class equivalent of `data-pantoken-boundary`. */
|
|
40
|
+
export declare const BOUNDARY_CLASS = "--pantoken-boundary";
|
|
41
|
+
/** The selector matching any element that roots `theme`. */
|
|
42
|
+
export declare function themeScopeSelector(theme: string): string;
|
|
43
|
+
/** The selector matching any element pinned to `scheme`. */
|
|
44
|
+
export declare function schemeScopeSelector(scheme: Scheme): string;
|
|
45
|
+
/** The selector matching any element using custom brand color `color`. */
|
|
46
|
+
export declare function colorScopeSelector(color: string): string;
|
|
47
|
+
/** Both forms of the theme scope selector, as a selector list. */
|
|
48
|
+
export declare function themeScopeSelectors(theme: string): string;
|
|
49
|
+
/** Both forms of the scheme scope selector, as a selector list. */
|
|
50
|
+
export declare function schemeScopeSelectors(scheme: Scheme): string;
|
|
51
|
+
/** Both forms of the color scope selector, as a selector list. */
|
|
52
|
+
export declare function colorScopeSelectors(color: string): string;
|
|
53
|
+
//#endregion
|
package/dist/scope.mjs
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region src/scope.ts
|
|
2
|
+
/**
|
|
3
|
+
* The scope attribute contract — the single source of truth shared by the CSS emitter
|
|
4
|
+
* (`@pantoken/css`, which selects on these) and the runtime (`@pantoken/scope`, which writes them).
|
|
5
|
+
*
|
|
6
|
+
* Its own module with zero imports, exposed at the `@pantoken/utils/scope` entry, so the browser
|
|
7
|
+
* runtime can take the names without pulling `arkregex` or the resolver in behind the barrel.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
/** Attribute that roots a theme scope. Matches any element, not just `:root`. */
|
|
12
|
+
const THEME_ATTR = "data-pantoken-theme";
|
|
13
|
+
/** Attribute that pins a subtree to a color scheme. */
|
|
14
|
+
const SCHEME_ATTR = "data-pantoken-scheme";
|
|
15
|
+
/** Attribute that selects a custom brand color. */
|
|
16
|
+
const COLOR_ATTR = "data-pantoken-color";
|
|
17
|
+
/** Attribute marking a scope that ancestor resolution must not cross. */
|
|
18
|
+
const BOUNDARY_ATTR = "data-pantoken-boundary";
|
|
19
|
+
/** Attribute carrying the owning instance id, so sibling instances can tell scopes apart. */
|
|
20
|
+
const INSTANCE_ATTR = "data-pantoken-instance";
|
|
21
|
+
/** Every attribute that participates in scope resolution. */
|
|
22
|
+
const SCOPE_ATTRS = [
|
|
23
|
+
THEME_ATTR,
|
|
24
|
+
SCHEME_ATTR,
|
|
25
|
+
COLOR_ATTR,
|
|
26
|
+
BOUNDARY_ATTR,
|
|
27
|
+
INSTANCE_ATTR
|
|
28
|
+
];
|
|
29
|
+
/** Cascade layers the scoped sheets emit into, in ascending precedence order. */
|
|
30
|
+
const SCOPE_LAYERS = [
|
|
31
|
+
"pantoken.base",
|
|
32
|
+
"pantoken.theme",
|
|
33
|
+
"pantoken.scheme",
|
|
34
|
+
"pantoken.color"
|
|
35
|
+
];
|
|
36
|
+
const SCHEMES = /* @__PURE__ */ new Set(["light", "dark"]);
|
|
37
|
+
/** Narrow an arbitrary value to a {@link Scheme}. */
|
|
38
|
+
function isScheme(value) {
|
|
39
|
+
return typeof value === "string" && SCHEMES.has(value);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Class equivalents of the scope attributes, for hosts that sanitize `data-*` but allow `class` —
|
|
43
|
+
* Canvas RCE content being the one that forced them. They follow the repo's global-modifier naming
|
|
44
|
+
* (`.--name`), and the emitter pairs each attribute selector with its class twin.
|
|
45
|
+
*/
|
|
46
|
+
const themeClass = (theme) => `--pantoken-theme-${theme}`;
|
|
47
|
+
/** Class equivalent of `data-pantoken-scheme`. */
|
|
48
|
+
const schemeClass = (scheme) => `--pantoken-scheme-${scheme}`;
|
|
49
|
+
/** Class equivalent of `data-pantoken-color`. */
|
|
50
|
+
const colorClass = (color) => `--pantoken-color-${color}`;
|
|
51
|
+
/** Class equivalent of `data-pantoken-boundary`. */
|
|
52
|
+
const BOUNDARY_CLASS = "--pantoken-boundary";
|
|
53
|
+
/** The selector matching any element that roots `theme`. */
|
|
54
|
+
function themeScopeSelector(theme) {
|
|
55
|
+
return `[${THEME_ATTR}="${theme}"]`;
|
|
56
|
+
}
|
|
57
|
+
/** The selector matching any element pinned to `scheme`. */
|
|
58
|
+
function schemeScopeSelector(scheme) {
|
|
59
|
+
return `[${SCHEME_ATTR}="${scheme}"]`;
|
|
60
|
+
}
|
|
61
|
+
/** The selector matching any element using custom brand color `color`. */
|
|
62
|
+
function colorScopeSelector(color) {
|
|
63
|
+
return `[${COLOR_ATTR}="${color}"]`;
|
|
64
|
+
}
|
|
65
|
+
const classSelector = (cls) => `:where(*).${cls}.${cls}.${cls}`;
|
|
66
|
+
/** Both forms of the theme scope selector, as a selector list. */
|
|
67
|
+
function themeScopeSelectors(theme) {
|
|
68
|
+
return `${themeScopeSelector(theme)}, ${classSelector(themeClass(theme))}`;
|
|
69
|
+
}
|
|
70
|
+
/** Both forms of the scheme scope selector, as a selector list. */
|
|
71
|
+
function schemeScopeSelectors(scheme) {
|
|
72
|
+
return `${schemeScopeSelector(scheme)}, ${classSelector(schemeClass(scheme))}`;
|
|
73
|
+
}
|
|
74
|
+
/** Both forms of the color scope selector, as a selector list. */
|
|
75
|
+
function colorScopeSelectors(color) {
|
|
76
|
+
return `${colorScopeSelector(color)}, ${classSelector(colorClass(color))}`;
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { BOUNDARY_ATTR, BOUNDARY_CLASS, COLOR_ATTR, INSTANCE_ATTR, SCHEME_ATTR, SCOPE_ATTRS, SCOPE_LAYERS, THEME_ATTR, colorClass, colorScopeSelector, colorScopeSelectors, isScheme, schemeClass, schemeScopeSelector, schemeScopeSelectors, themeClass, themeScopeSelector, themeScopeSelectors };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pantoken/utils",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Shared pantoken helpers: token reference resolver, typed regexes (arkregex), name-case, and hex-colour parsing.",
|
|
5
5
|
"homepage": "https://pantoken.app",
|
|
6
6
|
"bugs": "https://github.com/thedannywahl/pantoken/issues",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"exports": {
|
|
19
19
|
".": "./dist/index.mjs",
|
|
20
20
|
"./token-syntax": "./dist/token-syntax.mjs",
|
|
21
|
+
"./scope": "./dist/scope.mjs",
|
|
21
22
|
"./package.json": "./package.json"
|
|
22
23
|
},
|
|
23
24
|
"publishConfig": {
|
|
@@ -25,16 +26,16 @@
|
|
|
25
26
|
"provenance": true
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@pantoken/model": "0.
|
|
29
|
+
"@pantoken/model": "0.5.0",
|
|
29
30
|
"arkregex": "^0.0.8",
|
|
30
31
|
"css-tree": "^3.2.1"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/css-tree": "^3.2.0",
|
|
34
|
-
"@types/node": "^26.
|
|
35
|
+
"@types/node": "^26.6.3",
|
|
35
36
|
"typescript": "^7.0.2",
|
|
36
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@0.
|
|
37
|
-
"vite-plus": "0.
|
|
37
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.0.0-rc.0",
|
|
38
|
+
"vite-plus": "1.0.0-rc.0"
|
|
38
39
|
},
|
|
39
40
|
"engines": {
|
|
40
41
|
"node": ">=22.18.0"
|