@tenphi/tasty 2.0.3 → 2.1.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/{ssr/async-storage.js → async-storage-B7_o6FKt.js} +2 -2
- package/dist/async-storage-B7_o6FKt.js.map +1 -0
- package/dist/{ssr/collector.js → collector-DrgDE7QB.js} +5 -10
- package/dist/collector-DrgDE7QB.js.map +1 -0
- package/dist/{ssr/collector.d.ts → collector-LuU1vZ68.d.ts} +3 -3
- package/dist/config-_aQ_PZ-P.js +10131 -0
- package/dist/config-_aQ_PZ-P.js.map +1 -0
- package/dist/config-vuCRkBWX.d.ts +884 -0
- package/dist/{ssr/context.js → context-CkSg-kDT.js} +11 -3
- package/dist/context-CkSg-kDT.js.map +1 -0
- package/dist/core/index.d.ts +5 -34
- package/dist/core/index.js +6 -27
- package/dist/core-BqO8pplb.js +1592 -0
- package/dist/core-BqO8pplb.js.map +1 -0
- package/dist/{zero/extractor.js → css-writer-D--REwtp.js} +74 -11
- package/dist/css-writer-D--REwtp.js.map +1 -0
- package/dist/{ssr/format-global-rules.js → format-global-rules-Dbc_1tc3.js} +2 -2
- package/dist/format-global-rules-Dbc_1tc3.js.map +1 -0
- package/dist/format-rules-xwteB7a1.js +143 -0
- package/dist/format-rules-xwteB7a1.js.map +1 -0
- package/dist/{ssr/hydrate.js → hydrate-BvPT4ndL.js} +3 -3
- package/dist/hydrate-BvPT4ndL.js.map +1 -0
- package/dist/index-ZRxZWzlj.d.ts +1602 -0
- package/dist/{styles/types.d.ts → index-dUtwpOux.d.ts} +707 -5
- package/dist/index.d.ts +5 -51
- package/dist/index.js +732 -36
- package/dist/index.js.map +1 -0
- package/dist/keyframes-ClPFWy33.js +587 -0
- package/dist/keyframes-ClPFWy33.js.map +1 -0
- package/dist/{utils/merge-styles.js → merge-styles-BUQsEpbv.js} +3 -4
- package/dist/merge-styles-BUQsEpbv.js.map +1 -0
- package/dist/{utils/merge-styles.d.ts → merge-styles-CtDJMhpJ.d.ts} +3 -3
- package/dist/{utils/resolve-recipes.js → resolve-recipes-C0-AMzCz.js} +4 -6
- package/dist/resolve-recipes-C0-AMzCz.js.map +1 -0
- package/dist/ssr/astro-client.js +1 -1
- package/dist/ssr/astro.js +4 -4
- package/dist/ssr/index.d.ts +44 -4
- package/dist/ssr/index.js +4 -4
- package/dist/ssr/next.d.ts +1 -1
- package/dist/ssr/next.js +6 -6
- package/dist/ssr/next.js.map +1 -1
- package/dist/static/index.d.ts +91 -5
- package/dist/static/index.js +49 -3
- package/dist/static/index.js.map +1 -0
- package/dist/zero/babel.d.ts +1 -1
- package/dist/zero/babel.js +10 -6
- package/dist/zero/babel.js.map +1 -1
- package/dist/zero/index.d.ts +67 -3
- package/dist/zero/index.js +1 -2
- package/docs/injector.md +2 -2
- package/package.json +10 -9
- package/dist/_virtual/_rolldown/runtime.js +0 -7
- package/dist/chunks/cacheKey.d.ts +0 -1
- package/dist/chunks/cacheKey.js +0 -77
- package/dist/chunks/cacheKey.js.map +0 -1
- package/dist/chunks/definitions.d.ts +0 -37
- package/dist/chunks/definitions.js +0 -258
- package/dist/chunks/definitions.js.map +0 -1
- package/dist/chunks/index.d.ts +0 -1
- package/dist/chunks/renderChunk.d.ts +0 -1
- package/dist/chunks/renderChunk.js +0 -59
- package/dist/chunks/renderChunk.js.map +0 -1
- package/dist/compute-styles.d.ts +0 -31
- package/dist/compute-styles.js +0 -322
- package/dist/compute-styles.js.map +0 -1
- package/dist/config.d.ts +0 -407
- package/dist/config.js +0 -591
- package/dist/config.js.map +0 -1
- package/dist/counter-style/index.js +0 -51
- package/dist/counter-style/index.js.map +0 -1
- package/dist/debug.d.ts +0 -89
- package/dist/debug.js +0 -453
- package/dist/debug.js.map +0 -1
- package/dist/font-face/index.js +0 -63
- package/dist/font-face/index.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -7
- package/dist/hooks/useCounterStyle.d.ts +0 -36
- package/dist/hooks/useCounterStyle.js +0 -65
- package/dist/hooks/useCounterStyle.js.map +0 -1
- package/dist/hooks/useFontFace.d.ts +0 -45
- package/dist/hooks/useFontFace.js +0 -66
- package/dist/hooks/useFontFace.js.map +0 -1
- package/dist/hooks/useGlobalStyles.d.ts +0 -46
- package/dist/hooks/useGlobalStyles.js +0 -88
- package/dist/hooks/useGlobalStyles.js.map +0 -1
- package/dist/hooks/useKeyframes.d.ts +0 -58
- package/dist/hooks/useKeyframes.js +0 -55
- package/dist/hooks/useKeyframes.js.map +0 -1
- package/dist/hooks/useProperty.d.ts +0 -81
- package/dist/hooks/useProperty.js +0 -96
- package/dist/hooks/useProperty.js.map +0 -1
- package/dist/hooks/useRawCSS.d.ts +0 -22
- package/dist/hooks/useRawCSS.js +0 -103
- package/dist/hooks/useRawCSS.js.map +0 -1
- package/dist/hooks/useStyles.d.ts +0 -40
- package/dist/hooks/useStyles.js +0 -31
- package/dist/hooks/useStyles.js.map +0 -1
- package/dist/injector/index.d.ts +0 -182
- package/dist/injector/index.js +0 -185
- package/dist/injector/index.js.map +0 -1
- package/dist/injector/injector.d.ts +0 -198
- package/dist/injector/injector.js +0 -651
- package/dist/injector/injector.js.map +0 -1
- package/dist/injector/sheet-manager.d.ts +0 -132
- package/dist/injector/sheet-manager.js +0 -699
- package/dist/injector/sheet-manager.js.map +0 -1
- package/dist/injector/types.d.ts +0 -235
- package/dist/keyframes/index.js +0 -206
- package/dist/keyframes/index.js.map +0 -1
- package/dist/parser/classify.js +0 -319
- package/dist/parser/classify.js.map +0 -1
- package/dist/parser/const.js +0 -60
- package/dist/parser/const.js.map +0 -1
- package/dist/parser/lru.js +0 -109
- package/dist/parser/lru.js.map +0 -1
- package/dist/parser/parser.d.ts +0 -25
- package/dist/parser/parser.js +0 -115
- package/dist/parser/parser.js.map +0 -1
- package/dist/parser/tokenizer.js +0 -69
- package/dist/parser/tokenizer.js.map +0 -1
- package/dist/parser/types.d.ts +0 -51
- package/dist/parser/types.js +0 -46
- package/dist/parser/types.js.map +0 -1
- package/dist/pipeline/conditions.d.ts +0 -134
- package/dist/pipeline/conditions.js +0 -406
- package/dist/pipeline/conditions.js.map +0 -1
- package/dist/pipeline/exclusive.js +0 -389
- package/dist/pipeline/exclusive.js.map +0 -1
- package/dist/pipeline/index.d.ts +0 -55
- package/dist/pipeline/index.js +0 -749
- package/dist/pipeline/index.js.map +0 -1
- package/dist/pipeline/materialize-contradictions.js +0 -125
- package/dist/pipeline/materialize-contradictions.js.map +0 -1
- package/dist/pipeline/materialize.js +0 -1038
- package/dist/pipeline/materialize.js.map +0 -1
- package/dist/pipeline/parseStateKey.d.ts +0 -15
- package/dist/pipeline/parseStateKey.js +0 -446
- package/dist/pipeline/parseStateKey.js.map +0 -1
- package/dist/pipeline/simplify.js +0 -725
- package/dist/pipeline/simplify.js.map +0 -1
- package/dist/pipeline/warnings.js +0 -18
- package/dist/pipeline/warnings.js.map +0 -1
- package/dist/plugins/index.d.ts +0 -2
- package/dist/plugins/okhsl-plugin.d.ts +0 -35
- package/dist/plugins/okhsl-plugin.js +0 -97
- package/dist/plugins/okhsl-plugin.js.map +0 -1
- package/dist/plugins/types.d.ts +0 -87
- package/dist/properties/index.js +0 -222
- package/dist/properties/index.js.map +0 -1
- package/dist/properties/property-type-resolver.d.ts +0 -24
- package/dist/properties/property-type-resolver.js +0 -90
- package/dist/properties/property-type-resolver.js.map +0 -1
- package/dist/rsc-cache.js +0 -79
- package/dist/rsc-cache.js.map +0 -1
- package/dist/ssr/async-storage.d.ts +0 -17
- package/dist/ssr/async-storage.js.map +0 -1
- package/dist/ssr/collect-auto-properties.js +0 -58
- package/dist/ssr/collect-auto-properties.js.map +0 -1
- package/dist/ssr/collector.js.map +0 -1
- package/dist/ssr/context.js.map +0 -1
- package/dist/ssr/format-global-rules.js.map +0 -1
- package/dist/ssr/format-keyframes.js +0 -69
- package/dist/ssr/format-keyframes.js.map +0 -1
- package/dist/ssr/format-property.js +0 -49
- package/dist/ssr/format-property.js.map +0 -1
- package/dist/ssr/format-rules.js +0 -73
- package/dist/ssr/format-rules.js.map +0 -1
- package/dist/ssr/hydrate.d.ts +0 -29
- package/dist/ssr/hydrate.js.map +0 -1
- package/dist/ssr/ssr-collector-ref.js +0 -29
- package/dist/ssr/ssr-collector-ref.js.map +0 -1
- package/dist/states/index.d.ts +0 -49
- package/dist/states/index.js +0 -170
- package/dist/states/index.js.map +0 -1
- package/dist/static/tastyStatic.d.ts +0 -46
- package/dist/static/tastyStatic.js +0 -30
- package/dist/static/tastyStatic.js.map +0 -1
- package/dist/static/types.d.ts +0 -49
- package/dist/static/types.js +0 -24
- package/dist/static/types.js.map +0 -1
- package/dist/styles/border.d.ts +0 -25
- package/dist/styles/border.js +0 -120
- package/dist/styles/border.js.map +0 -1
- package/dist/styles/color.d.ts +0 -14
- package/dist/styles/color.js +0 -26
- package/dist/styles/color.js.map +0 -1
- package/dist/styles/const.js +0 -17
- package/dist/styles/const.js.map +0 -1
- package/dist/styles/createStyle.js +0 -79
- package/dist/styles/createStyle.js.map +0 -1
- package/dist/styles/dimension.js +0 -109
- package/dist/styles/dimension.js.map +0 -1
- package/dist/styles/directional.js +0 -133
- package/dist/styles/directional.js.map +0 -1
- package/dist/styles/display.d.ts +0 -30
- package/dist/styles/display.js +0 -73
- package/dist/styles/display.js.map +0 -1
- package/dist/styles/fade.d.ts +0 -15
- package/dist/styles/fade.js +0 -62
- package/dist/styles/fade.js.map +0 -1
- package/dist/styles/fill.d.ts +0 -42
- package/dist/styles/fill.js +0 -51
- package/dist/styles/fill.js.map +0 -1
- package/dist/styles/flow.d.ts +0 -16
- package/dist/styles/flow.js +0 -12
- package/dist/styles/flow.js.map +0 -1
- package/dist/styles/gap.d.ts +0 -31
- package/dist/styles/gap.js +0 -38
- package/dist/styles/gap.js.map +0 -1
- package/dist/styles/height.d.ts +0 -17
- package/dist/styles/height.js +0 -19
- package/dist/styles/height.js.map +0 -1
- package/dist/styles/index.d.ts +0 -1
- package/dist/styles/index.js +0 -8
- package/dist/styles/index.js.map +0 -1
- package/dist/styles/inset.d.ts +0 -24
- package/dist/styles/inset.js +0 -34
- package/dist/styles/inset.js.map +0 -1
- package/dist/styles/list.d.ts +0 -16
- package/dist/styles/list.js +0 -100
- package/dist/styles/list.js.map +0 -1
- package/dist/styles/margin.d.ts +0 -24
- package/dist/styles/margin.js +0 -32
- package/dist/styles/margin.js.map +0 -1
- package/dist/styles/outline.d.ts +0 -29
- package/dist/styles/outline.js +0 -55
- package/dist/styles/outline.js.map +0 -1
- package/dist/styles/padding.d.ts +0 -24
- package/dist/styles/padding.js +0 -32
- package/dist/styles/padding.js.map +0 -1
- package/dist/styles/placement.d.ts +0 -37
- package/dist/styles/placement.js +0 -74
- package/dist/styles/placement.js.map +0 -1
- package/dist/styles/predefined.d.ts +0 -71
- package/dist/styles/predefined.js +0 -237
- package/dist/styles/predefined.js.map +0 -1
- package/dist/styles/preset.d.ts +0 -52
- package/dist/styles/preset.js +0 -127
- package/dist/styles/preset.js.map +0 -1
- package/dist/styles/radius.d.ts +0 -12
- package/dist/styles/radius.js +0 -83
- package/dist/styles/radius.js.map +0 -1
- package/dist/styles/scrollMargin.d.ts +0 -24
- package/dist/styles/scrollMargin.js +0 -32
- package/dist/styles/scrollMargin.js.map +0 -1
- package/dist/styles/scrollbar.d.ts +0 -25
- package/dist/styles/scrollbar.js +0 -51
- package/dist/styles/scrollbar.js.map +0 -1
- package/dist/styles/shadow.d.ts +0 -14
- package/dist/styles/shadow.js +0 -25
- package/dist/styles/shadow.js.map +0 -1
- package/dist/styles/shared.js +0 -17
- package/dist/styles/shared.js.map +0 -1
- package/dist/styles/transition.d.ts +0 -14
- package/dist/styles/transition.js +0 -159
- package/dist/styles/transition.js.map +0 -1
- package/dist/styles/width.d.ts +0 -17
- package/dist/styles/width.js +0 -19
- package/dist/styles/width.js.map +0 -1
- package/dist/tasty.d.ts +0 -134
- package/dist/tasty.js +0 -248
- package/dist/tasty.js.map +0 -1
- package/dist/types.d.ts +0 -184
- package/dist/utils/cache-wrapper.js +0 -21
- package/dist/utils/cache-wrapper.js.map +0 -1
- package/dist/utils/case-converter.js +0 -8
- package/dist/utils/case-converter.js.map +0 -1
- package/dist/utils/color-math.d.ts +0 -46
- package/dist/utils/color-math.js +0 -749
- package/dist/utils/color-math.js.map +0 -1
- package/dist/utils/color-space.d.ts +0 -5
- package/dist/utils/color-space.js +0 -228
- package/dist/utils/color-space.js.map +0 -1
- package/dist/utils/colors.d.ts +0 -5
- package/dist/utils/colors.js +0 -10
- package/dist/utils/colors.js.map +0 -1
- package/dist/utils/css-types.d.ts +0 -7
- package/dist/utils/deps-equal.js +0 -15
- package/dist/utils/deps-equal.js.map +0 -1
- package/dist/utils/dotize.d.ts +0 -26
- package/dist/utils/dotize.js +0 -122
- package/dist/utils/dotize.js.map +0 -1
- package/dist/utils/filter-base-props.d.ts +0 -15
- package/dist/utils/filter-base-props.js +0 -45
- package/dist/utils/filter-base-props.js.map +0 -1
- package/dist/utils/get-display-name.d.ts +0 -7
- package/dist/utils/get-display-name.js +0 -10
- package/dist/utils/get-display-name.js.map +0 -1
- package/dist/utils/has-keys.js +0 -13
- package/dist/utils/has-keys.js.map +0 -1
- package/dist/utils/hash.js +0 -14
- package/dist/utils/hash.js.map +0 -1
- package/dist/utils/is-dev-env.js +0 -19
- package/dist/utils/is-dev-env.js.map +0 -1
- package/dist/utils/is-valid-element-type.js +0 -15
- package/dist/utils/is-valid-element-type.js.map +0 -1
- package/dist/utils/merge-styles.js.map +0 -1
- package/dist/utils/mod-attrs.d.ts +0 -6
- package/dist/utils/mod-attrs.js +0 -20
- package/dist/utils/mod-attrs.js.map +0 -1
- package/dist/utils/process-tokens.d.ts +0 -17
- package/dist/utils/process-tokens.js +0 -83
- package/dist/utils/process-tokens.js.map +0 -1
- package/dist/utils/resolve-recipes.d.ts +0 -17
- package/dist/utils/resolve-recipes.js.map +0 -1
- package/dist/utils/selector-transform.js +0 -32
- package/dist/utils/selector-transform.js.map +0 -1
- package/dist/utils/string.js +0 -8
- package/dist/utils/string.js.map +0 -1
- package/dist/utils/styles.d.ts +0 -99
- package/dist/utils/styles.js +0 -220
- package/dist/utils/styles.js.map +0 -1
- package/dist/utils/typography.d.ts +0 -58
- package/dist/utils/typography.js +0 -51
- package/dist/utils/typography.js.map +0 -1
- package/dist/utils/warnings.d.ts +0 -16
- package/dist/utils/warnings.js +0 -16
- package/dist/utils/warnings.js.map +0 -1
- package/dist/zero/css-writer.d.ts +0 -45
- package/dist/zero/css-writer.js +0 -73
- package/dist/zero/css-writer.js.map +0 -1
- package/dist/zero/extractor.d.ts +0 -24
- package/dist/zero/extractor.js.map +0 -1
|
@@ -1,651 +0,0 @@
|
|
|
1
|
-
import { getEffectiveDefinition, normalizePropertyDefinition } from "../properties/index.js";
|
|
2
|
-
import { hashString } from "../utils/hash.js";
|
|
3
|
-
import { isDevEnv } from "../utils/is-dev-env.js";
|
|
4
|
-
import { parseStyle } from "../utils/styles.js";
|
|
5
|
-
import { SheetManager } from "./sheet-manager.js";
|
|
6
|
-
import { fontFaceContentHash, formatFontFaceDeclarations } from "../font-face/index.js";
|
|
7
|
-
import { formatCounterStyleDeclarations } from "../counter-style/index.js";
|
|
8
|
-
//#region src/injector/injector.ts
|
|
9
|
-
/**
|
|
10
|
-
* Generate a deterministic class name from a cache key using content hash.
|
|
11
|
-
* The same cache key always produces the same class name across environments.
|
|
12
|
-
*/
|
|
13
|
-
function generateClassName(cacheKey) {
|
|
14
|
-
return `t${hashString(cacheKey)}`;
|
|
15
|
-
}
|
|
16
|
-
const RSC_CLASS_RE = /\.(t[a-z0-9]+)\.\1/g;
|
|
17
|
-
/**
|
|
18
|
-
* Extract class names from `<style data-tasty-rsc>` tags.
|
|
19
|
-
* The doubled-specificity pattern `.tXXX.tXXX` makes extraction reliable.
|
|
20
|
-
*/
|
|
21
|
-
function extractRSCClassNames() {
|
|
22
|
-
if (typeof document === "undefined") return [];
|
|
23
|
-
const styles = document.querySelectorAll("style[data-tasty-rsc]");
|
|
24
|
-
if (styles.length === 0) return [];
|
|
25
|
-
const classSet = /* @__PURE__ */ new Set();
|
|
26
|
-
for (const style of styles) {
|
|
27
|
-
const text = style.textContent;
|
|
28
|
-
if (!text) continue;
|
|
29
|
-
let match;
|
|
30
|
-
RSC_CLASS_RE.lastIndex = 0;
|
|
31
|
-
while ((match = RSC_CLASS_RE.exec(text)) !== null) classSet.add(match[1]);
|
|
32
|
-
}
|
|
33
|
-
return Array.from(classSet);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Lazily sync server-rendered class names into the client registry.
|
|
37
|
-
*
|
|
38
|
-
* Sources:
|
|
39
|
-
* 1. `window.__TASTY__` — pushed by SSR/RSC streaming scripts
|
|
40
|
-
* 2. `<style data-tasty-rsc>` tags — inline CSS emitted by RSC components
|
|
41
|
-
*
|
|
42
|
-
* Called inside `inject()` / `allocateClassName()` to pick up
|
|
43
|
-
* class names rendered on the server (including during SPA navigation).
|
|
44
|
-
*/
|
|
45
|
-
function syncServerClasses(registry) {
|
|
46
|
-
if (typeof window === "undefined") return;
|
|
47
|
-
const classes = window.__TASTY__;
|
|
48
|
-
if (classes && classes.length > registry.serverClassSyncIndex) {
|
|
49
|
-
for (let i = registry.serverClassSyncIndex; i < classes.length; i++) registerHydratedClass(registry, classes[i]);
|
|
50
|
-
registry.serverClassSyncIndex = classes.length;
|
|
51
|
-
}
|
|
52
|
-
if (!registry.rscStylesScanned) {
|
|
53
|
-
registry.rscStylesScanned = true;
|
|
54
|
-
for (const cls of extractRSCClassNames()) registerHydratedClass(registry, cls);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function registerHydratedClass(registry, className) {
|
|
58
|
-
if (registry.rules.has(className)) return;
|
|
59
|
-
registry.rules.set(className, {
|
|
60
|
-
className,
|
|
61
|
-
ruleIndex: -2,
|
|
62
|
-
sheetIndex: -2
|
|
63
|
-
});
|
|
64
|
-
registry.refCounts.set(className, 0);
|
|
65
|
-
}
|
|
66
|
-
var StyleInjector = class StyleInjector {
|
|
67
|
-
sheetManager;
|
|
68
|
-
config;
|
|
69
|
-
globalRuleCounter = 0;
|
|
70
|
-
pendingGCHandle = null;
|
|
71
|
-
/** @internal — exposed for debug utilities only */
|
|
72
|
-
get _sheetManager() {
|
|
73
|
-
return this.sheetManager;
|
|
74
|
-
}
|
|
75
|
-
constructor(config = {}) {
|
|
76
|
-
this.config = config;
|
|
77
|
-
this.sheetManager = new SheetManager(config);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Check if `className` was hydrated from server-rendered styles and,
|
|
81
|
-
* if so, wire the cacheKey mapping. Returns true on hit.
|
|
82
|
-
*/
|
|
83
|
-
tryHydratedHit(registry, cacheKey, className) {
|
|
84
|
-
syncServerClasses(registry);
|
|
85
|
-
const rule = registry.rules.get(className);
|
|
86
|
-
if (rule && rule.ruleIndex === -2 && rule.sheetIndex === -2) {
|
|
87
|
-
registry.cacheKeyToClassName.set(cacheKey, className);
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Allocate a className for a cacheKey without injecting styles yet.
|
|
94
|
-
* This allows separating className allocation (render phase) from style injection (insertion phase).
|
|
95
|
-
*/
|
|
96
|
-
allocateClassName(cacheKey, options) {
|
|
97
|
-
const root = options?.root || document;
|
|
98
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
99
|
-
if (registry.cacheKeyToClassName.has(cacheKey)) return {
|
|
100
|
-
className: registry.cacheKeyToClassName.get(cacheKey),
|
|
101
|
-
isNewAllocation: false
|
|
102
|
-
};
|
|
103
|
-
const className = generateClassName(cacheKey);
|
|
104
|
-
if (this.tryHydratedHit(registry, cacheKey, className)) return {
|
|
105
|
-
className,
|
|
106
|
-
isNewAllocation: false
|
|
107
|
-
};
|
|
108
|
-
if (registry.rules.get(className)) {
|
|
109
|
-
if (isDevEnv()) console.warn(`[tasty] Hash collision: cache keys produce the same class "${className}". Styles may be incorrect.`);
|
|
110
|
-
registry.cacheKeyToClassName.set(cacheKey, className);
|
|
111
|
-
return {
|
|
112
|
-
className,
|
|
113
|
-
isNewAllocation: false
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
const placeholderRuleInfo = {
|
|
117
|
-
className,
|
|
118
|
-
ruleIndex: -1,
|
|
119
|
-
sheetIndex: -1
|
|
120
|
-
};
|
|
121
|
-
registry.rules.set(className, placeholderRuleInfo);
|
|
122
|
-
registry.cacheKeyToClassName.set(cacheKey, className);
|
|
123
|
-
return {
|
|
124
|
-
className,
|
|
125
|
-
isNewAllocation: true
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Inject styles from StyleResult objects
|
|
130
|
-
*/
|
|
131
|
-
inject(rules, options) {
|
|
132
|
-
const root = options?.root || document;
|
|
133
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
134
|
-
if (rules.length === 0) return {
|
|
135
|
-
className: "",
|
|
136
|
-
dispose: () => {}
|
|
137
|
-
};
|
|
138
|
-
const cacheKey = options?.cacheKey;
|
|
139
|
-
let className;
|
|
140
|
-
let isPreAllocated = false;
|
|
141
|
-
if (cacheKey && registry.cacheKeyToClassName.has(cacheKey)) {
|
|
142
|
-
className = registry.cacheKeyToClassName.get(cacheKey);
|
|
143
|
-
const existingRuleInfo = registry.rules.get(className);
|
|
144
|
-
isPreAllocated = existingRuleInfo.ruleIndex === -1 && existingRuleInfo.sheetIndex === -1;
|
|
145
|
-
if (!isPreAllocated) {
|
|
146
|
-
const currentRefCount = registry.refCounts.get(className) || 0;
|
|
147
|
-
registry.refCounts.set(className, currentRefCount + 1);
|
|
148
|
-
if (registry.metrics) registry.metrics.hits++;
|
|
149
|
-
return {
|
|
150
|
-
className,
|
|
151
|
-
dispose: () => this.dispose(className, registry)
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
} else if (cacheKey) {
|
|
155
|
-
className = generateClassName(cacheKey);
|
|
156
|
-
if (this.tryHydratedHit(registry, cacheKey, className)) {
|
|
157
|
-
registry.refCounts.set(className, (registry.refCounts.get(className) || 0) + 1);
|
|
158
|
-
if (registry.metrics) registry.metrics.hits++;
|
|
159
|
-
return {
|
|
160
|
-
className,
|
|
161
|
-
dispose: () => this.dispose(className, registry)
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
} else className = `t${hashString(rules.map((r) => `${r.selector}\0${r.declarations}`).join("\n"))}`;
|
|
165
|
-
const rulesToInsert = rules.map((rule) => {
|
|
166
|
-
let newSelector = rule.selector;
|
|
167
|
-
if (rule.needsClassName) {
|
|
168
|
-
const selectorParts = newSelector ? newSelector.split("|||") : [""];
|
|
169
|
-
const classPrefix = `.${className}.${className}`;
|
|
170
|
-
newSelector = selectorParts.map((part) => {
|
|
171
|
-
const classSelector = part ? `${classPrefix}${part}` : classPrefix;
|
|
172
|
-
if (rule.rootPrefix) return `${rule.rootPrefix} ${classSelector}`;
|
|
173
|
-
return classSelector;
|
|
174
|
-
}).join(", ");
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
...rule,
|
|
178
|
-
selector: newSelector,
|
|
179
|
-
needsClassName: void 0,
|
|
180
|
-
rootPrefix: void 0
|
|
181
|
-
};
|
|
182
|
-
});
|
|
183
|
-
if (this.config.autoPropertyTypes !== false) {
|
|
184
|
-
const resolver = registry.propertyTypeResolver;
|
|
185
|
-
const defined = registry.injectedProperties;
|
|
186
|
-
for (const rule of rulesToInsert) {
|
|
187
|
-
if (!rule.declarations) continue;
|
|
188
|
-
resolver.scanDeclarations(rule.declarations, (name) => defined.has(name), (name, syntax, initialValue) => {
|
|
189
|
-
this.property(name, {
|
|
190
|
-
syntax,
|
|
191
|
-
inherits: true,
|
|
192
|
-
initialValue,
|
|
193
|
-
root
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
const ruleInfo = this.sheetManager.insertRule(registry, rulesToInsert, className, root);
|
|
199
|
-
if (!ruleInfo) {
|
|
200
|
-
if (registry.metrics) registry.metrics.misses++;
|
|
201
|
-
return {
|
|
202
|
-
className,
|
|
203
|
-
dispose: () => {}
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
registry.refCounts.set(className, 1);
|
|
207
|
-
if (isPreAllocated) registry.rules.set(className, ruleInfo);
|
|
208
|
-
else {
|
|
209
|
-
registry.rules.set(className, ruleInfo);
|
|
210
|
-
if (cacheKey) registry.cacheKeyToClassName.set(cacheKey, className);
|
|
211
|
-
}
|
|
212
|
-
if (registry.metrics) {
|
|
213
|
-
registry.metrics.totalInsertions++;
|
|
214
|
-
registry.metrics.misses++;
|
|
215
|
-
}
|
|
216
|
-
return {
|
|
217
|
-
className,
|
|
218
|
-
dispose: () => this.dispose(className, registry)
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Inject global styles (rules without a generated tasty class selector)
|
|
223
|
-
* This ensures we don't reserve a tasty class name (t{number}) for global rules,
|
|
224
|
-
* which could otherwise collide with element-level styles and break lookups.
|
|
225
|
-
*/
|
|
226
|
-
injectGlobal(rules, options) {
|
|
227
|
-
const root = options?.root || document;
|
|
228
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
229
|
-
if (!rules || rules.length === 0) return { dispose: () => {} };
|
|
230
|
-
if (this.config.autoPropertyTypes !== false) {
|
|
231
|
-
const resolver = registry.propertyTypeResolver;
|
|
232
|
-
const defined = registry.injectedProperties;
|
|
233
|
-
for (const rule of rules) {
|
|
234
|
-
if (!rule.declarations) continue;
|
|
235
|
-
resolver.scanDeclarations(rule.declarations, (name) => defined.has(name), (name, syntax, initialValue) => {
|
|
236
|
-
this.property(name, {
|
|
237
|
-
syntax,
|
|
238
|
-
inherits: true,
|
|
239
|
-
initialValue,
|
|
240
|
-
root
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const key = `global:${this.globalRuleCounter++}`;
|
|
246
|
-
const info = this.sheetManager.insertGlobalRule(registry, rules, key, root);
|
|
247
|
-
if (registry.metrics) registry.metrics.totalInsertions++;
|
|
248
|
-
return { dispose: () => {
|
|
249
|
-
if (info) this.sheetManager.deleteGlobalRule(registry, key);
|
|
250
|
-
} };
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Inject raw CSS text directly without parsing
|
|
254
|
-
* This is a low-overhead alternative to createGlobalStyle for raw CSS
|
|
255
|
-
* The CSS is inserted into a separate style element to avoid conflicts with tasty's chunking
|
|
256
|
-
*/
|
|
257
|
-
injectRawCSS(css, options) {
|
|
258
|
-
const root = options?.root || document;
|
|
259
|
-
return this.sheetManager.injectRawCSS(css, root);
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Get raw CSS text for SSR
|
|
263
|
-
*/
|
|
264
|
-
getRawCSSText(options) {
|
|
265
|
-
const root = options?.root || document;
|
|
266
|
-
return this.sheetManager.getRawCSSText(root);
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Increment refCount for an already-injected cacheKey and return a dispose.
|
|
270
|
-
* Used by useStyles on cache hits (hydration or runtime reuse) where
|
|
271
|
-
* the pipeline was skipped but refCount tracking is still needed.
|
|
272
|
-
* Returns null if the cacheKey is not found.
|
|
273
|
-
*/
|
|
274
|
-
trackRef(cacheKey, options) {
|
|
275
|
-
const root = options?.root || document;
|
|
276
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
277
|
-
if (!registry.cacheKeyToClassName.has(cacheKey)) return null;
|
|
278
|
-
const className = registry.cacheKeyToClassName.get(cacheKey);
|
|
279
|
-
const currentRefCount = registry.refCounts.get(className) || 0;
|
|
280
|
-
registry.refCounts.set(className, currentRefCount + 1);
|
|
281
|
-
if (registry.metrics) registry.metrics.hits++;
|
|
282
|
-
return {
|
|
283
|
-
className,
|
|
284
|
-
dispose: () => this.dispose(className, registry)
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Dispose of a className (decrements refCount only).
|
|
289
|
-
*/
|
|
290
|
-
dispose(className, registry) {
|
|
291
|
-
const currentRefCount = registry.refCounts.get(className);
|
|
292
|
-
if (currentRefCount == null || currentRefCount <= 0) return;
|
|
293
|
-
const newRefCount = currentRefCount - 1;
|
|
294
|
-
registry.refCounts.set(className, newRefCount);
|
|
295
|
-
if (newRefCount === 0 && registry.metrics) registry.metrics.totalUnused++;
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Force bulk cleanup of unused styles
|
|
299
|
-
*/
|
|
300
|
-
cleanup(root) {
|
|
301
|
-
const registry = this.sheetManager.getRegistry(root || document);
|
|
302
|
-
this.sheetManager.forceCleanup(registry);
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Get CSS text from all sheets (for SSR)
|
|
306
|
-
*/
|
|
307
|
-
getCssText(options) {
|
|
308
|
-
const root = options?.root || document;
|
|
309
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
310
|
-
return this.sheetManager.getCssText(registry);
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Get CSS only for the provided tasty classNames (e.g., ["t0","t3"])
|
|
314
|
-
*/
|
|
315
|
-
getCssTextForClasses(classNames, options) {
|
|
316
|
-
const root = options?.root || document;
|
|
317
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
318
|
-
const cssChunks = [];
|
|
319
|
-
for (const cls of classNames) {
|
|
320
|
-
const info = registry.rules.get(cls);
|
|
321
|
-
if (info) {
|
|
322
|
-
const styleSheet = registry.sheets[info.sheetIndex]?.sheet?.sheet;
|
|
323
|
-
if (styleSheet) {
|
|
324
|
-
const start = Math.max(0, info.ruleIndex);
|
|
325
|
-
const end = Math.min(styleSheet.cssRules.length - 1, info.endRuleIndex ?? info.ruleIndex);
|
|
326
|
-
if (start >= 0 && end >= start && start < styleSheet.cssRules.length) for (let i = start; i <= end; i++) {
|
|
327
|
-
const rule = styleSheet.cssRules[i];
|
|
328
|
-
if (rule) cssChunks.push(rule.cssText);
|
|
329
|
-
}
|
|
330
|
-
} else if (info.cssText && info.cssText.length) cssChunks.push(...info.cssText);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
return cssChunks.join("\n");
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Get cache performance metrics
|
|
337
|
-
*/
|
|
338
|
-
getMetrics(options) {
|
|
339
|
-
const root = options?.root || document;
|
|
340
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
341
|
-
return this.sheetManager.getMetrics(registry);
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Reset cache performance metrics
|
|
345
|
-
*/
|
|
346
|
-
resetMetrics(options) {
|
|
347
|
-
const root = options?.root || document;
|
|
348
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
349
|
-
this.sheetManager.resetMetrics(registry);
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Define a CSS @property custom property.
|
|
353
|
-
*
|
|
354
|
-
* Accepts tasty token syntax for the property name:
|
|
355
|
-
* - `$name` → defines `--name`
|
|
356
|
-
* - `#name` → defines `--name-color` (auto-sets syntax: '<color>', defaults initialValue: 'transparent')
|
|
357
|
-
* - `--name` → defines `--name` (legacy format)
|
|
358
|
-
*
|
|
359
|
-
* Example:
|
|
360
|
-
* @property --rotation { syntax: "<angle>"; inherits: false; initial-value: 45deg; }
|
|
361
|
-
*
|
|
362
|
-
* Note: No caching or dispose — this defines a global property.
|
|
363
|
-
*
|
|
364
|
-
* If the same property is registered with different options, a warning is emitted
|
|
365
|
-
* but the original definition is preserved (CSS @property cannot be redefined).
|
|
366
|
-
*/
|
|
367
|
-
property(name, options) {
|
|
368
|
-
const root = options?.root || document;
|
|
369
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
370
|
-
const effectiveResult = getEffectiveDefinition(name, {
|
|
371
|
-
syntax: options?.syntax,
|
|
372
|
-
inherits: options?.inherits,
|
|
373
|
-
initialValue: options?.initialValue
|
|
374
|
-
});
|
|
375
|
-
if (!effectiveResult.isValid) {
|
|
376
|
-
if (isDevEnv()) console.warn(`[Tasty] property(): ${effectiveResult.error}. Got: "${name}"`);
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
const cssName = effectiveResult.cssName;
|
|
380
|
-
const definition = effectiveResult.definition;
|
|
381
|
-
const normalizedDef = normalizePropertyDefinition(definition);
|
|
382
|
-
if (registry.injectedProperties.get(cssName) !== void 0) return;
|
|
383
|
-
const parts = [];
|
|
384
|
-
if (definition.syntax != null) {
|
|
385
|
-
let syntax = String(definition.syntax).trim();
|
|
386
|
-
if (!/^['"]/u.test(syntax)) syntax = `"${syntax}"`;
|
|
387
|
-
parts.push(`syntax: ${syntax};`);
|
|
388
|
-
}
|
|
389
|
-
const inherits = definition.inherits ?? true;
|
|
390
|
-
parts.push(`inherits: ${inherits ? "true" : "false"};`);
|
|
391
|
-
if (definition.initialValue != null) {
|
|
392
|
-
let initialValueStr;
|
|
393
|
-
if (typeof definition.initialValue === "number") initialValueStr = String(definition.initialValue);
|
|
394
|
-
else initialValueStr = parseStyle(definition.initialValue).output;
|
|
395
|
-
parts.push(`initial-value: ${initialValueStr};`);
|
|
396
|
-
}
|
|
397
|
-
const declarations = parts.join(" ").trim();
|
|
398
|
-
const rule = {
|
|
399
|
-
selector: `@property ${cssName}`,
|
|
400
|
-
declarations
|
|
401
|
-
};
|
|
402
|
-
if (!this.sheetManager.insertGlobalRule(registry, [rule], `property:${name}`, root)) return;
|
|
403
|
-
registry.injectedProperties.set(cssName, normalizedDef);
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Check whether a given @property name was already injected by this injector.
|
|
407
|
-
*
|
|
408
|
-
* Accepts tasty token syntax:
|
|
409
|
-
* - `$name` → checks `--name`
|
|
410
|
-
* - `#name` → checks `--name-color`
|
|
411
|
-
* - `--name` → checks `--name` (legacy format)
|
|
412
|
-
*/
|
|
413
|
-
isPropertyDefined(name, options) {
|
|
414
|
-
const root = options?.root || document;
|
|
415
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
416
|
-
const effectiveResult = getEffectiveDefinition(name, {});
|
|
417
|
-
if (!effectiveResult.isValid) return false;
|
|
418
|
-
return registry.injectedProperties.has(effectiveResult.cssName);
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* Inject a CSS @font-face rule.
|
|
422
|
-
*
|
|
423
|
-
* Permanent and global — no dispose or ref-counting.
|
|
424
|
-
* Deduplicates by content hash (family + descriptors).
|
|
425
|
-
*/
|
|
426
|
-
fontFace(family, descriptors, options) {
|
|
427
|
-
const root = options?.root || document;
|
|
428
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
429
|
-
const hash = fontFaceContentHash(family, descriptors);
|
|
430
|
-
if (registry.injectedFontFaces.has(hash)) return;
|
|
431
|
-
const rule = {
|
|
432
|
-
selector: "@font-face",
|
|
433
|
-
declarations: formatFontFaceDeclarations(family, descriptors)
|
|
434
|
-
};
|
|
435
|
-
if (this.sheetManager.insertGlobalRule(registry, [rule], `fontface:${hash}`, root)) registry.injectedFontFaces.add(hash);
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Inject a CSS @counter-style rule.
|
|
439
|
-
*
|
|
440
|
-
* Permanent and global — no dispose or ref-counting.
|
|
441
|
-
* Deduplicates by name (first definition wins).
|
|
442
|
-
*/
|
|
443
|
-
counterStyle(name, descriptors, options) {
|
|
444
|
-
const root = options?.root || document;
|
|
445
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
446
|
-
if (registry.injectedCounterStyles.has(name)) return;
|
|
447
|
-
const rule = {
|
|
448
|
-
selector: `@counter-style ${name}`,
|
|
449
|
-
declarations: formatCounterStyleDeclarations(descriptors)
|
|
450
|
-
};
|
|
451
|
-
if (this.sheetManager.insertGlobalRule(registry, [rule], `counterstyle:${name}`, root)) registry.injectedCounterStyles.add(name);
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Inject keyframes and return object with toString() and dispose()
|
|
455
|
-
*
|
|
456
|
-
* Keyframes are cached by content (steps). If the same content is injected
|
|
457
|
-
* multiple times with different provided names, the first injected name is reused.
|
|
458
|
-
*
|
|
459
|
-
* If the same name is provided with different content (collision), a unique
|
|
460
|
-
* name is generated to avoid overwriting the existing keyframes.
|
|
461
|
-
*/
|
|
462
|
-
keyframes(steps, nameOrOptions) {
|
|
463
|
-
const isStringName = typeof nameOrOptions === "string";
|
|
464
|
-
const providedName = isStringName ? nameOrOptions : nameOrOptions?.name;
|
|
465
|
-
const root = isStringName ? document : nameOrOptions?.root || document;
|
|
466
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
467
|
-
if (Object.keys(steps).length === 0) return {
|
|
468
|
-
toString: () => "",
|
|
469
|
-
dispose: () => {}
|
|
470
|
-
};
|
|
471
|
-
const contentHash = JSON.stringify(steps);
|
|
472
|
-
const existing = registry.keyframesCache.get(contentHash);
|
|
473
|
-
if (existing) {
|
|
474
|
-
existing.refCount++;
|
|
475
|
-
return {
|
|
476
|
-
toString: () => existing.name,
|
|
477
|
-
dispose: () => this.disposeKeyframes(contentHash, registry)
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
let actualName;
|
|
481
|
-
if (providedName) {
|
|
482
|
-
const existingContentForName = registry.keyframesNameToContent.get(providedName);
|
|
483
|
-
if (existingContentForName && existingContentForName !== contentHash) actualName = `${providedName}-k${registry.keyframesCounter++}`;
|
|
484
|
-
else {
|
|
485
|
-
actualName = providedName;
|
|
486
|
-
registry.keyframesNameToContent.set(providedName, contentHash);
|
|
487
|
-
}
|
|
488
|
-
} else actualName = `k${registry.keyframesCounter++}`;
|
|
489
|
-
const result = this.sheetManager.insertKeyframes(registry, steps, actualName, root);
|
|
490
|
-
if (!result) return {
|
|
491
|
-
toString: () => "",
|
|
492
|
-
dispose: () => {}
|
|
493
|
-
};
|
|
494
|
-
const { info, declarations } = result;
|
|
495
|
-
if (this.config.autoPropertyTypes !== false && declarations) registry.propertyTypeResolver.scanDeclarations(declarations, (name) => registry.injectedProperties.has(name), (name, syntax, initialValue) => {
|
|
496
|
-
this.property(name, {
|
|
497
|
-
syntax,
|
|
498
|
-
inherits: true,
|
|
499
|
-
initialValue,
|
|
500
|
-
root
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
registry.keyframesCache.set(contentHash, {
|
|
504
|
-
name: actualName,
|
|
505
|
-
refCount: 1,
|
|
506
|
-
info
|
|
507
|
-
});
|
|
508
|
-
if (registry.metrics) {
|
|
509
|
-
registry.metrics.totalInsertions++;
|
|
510
|
-
registry.metrics.misses++;
|
|
511
|
-
}
|
|
512
|
-
return {
|
|
513
|
-
toString: () => actualName,
|
|
514
|
-
dispose: () => this.disposeKeyframes(contentHash, registry)
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Dispose keyframes
|
|
519
|
-
*/
|
|
520
|
-
disposeKeyframes(contentHash, registry) {
|
|
521
|
-
const entry = registry.keyframesCache.get(contentHash);
|
|
522
|
-
if (!entry) return;
|
|
523
|
-
entry.refCount--;
|
|
524
|
-
if (entry.refCount <= 0) {
|
|
525
|
-
this.sheetManager.deleteKeyframes(registry, entry.info);
|
|
526
|
-
registry.keyframesCache.delete(contentHash);
|
|
527
|
-
for (const [name, hash] of registry.keyframesNameToContent.entries()) if (hash === contentHash) {
|
|
528
|
-
registry.keyframesNameToContent.delete(name);
|
|
529
|
-
break;
|
|
530
|
-
}
|
|
531
|
-
if (registry.metrics) {
|
|
532
|
-
registry.metrics.totalUnused++;
|
|
533
|
-
registry.metrics.stylesCleanedUp++;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
static TASTY_CLASS_RE = /^t[a-z0-9]+$/;
|
|
538
|
-
/**
|
|
539
|
-
* Record a render-time usage hit for one or more classNames.
|
|
540
|
-
* Handles space-separated multi-chunk classNames.
|
|
541
|
-
* When the global touch counter reaches `touchInterval`, schedules a GC
|
|
542
|
-
* via `requestIdleCallback`.
|
|
543
|
-
* No-op on the server.
|
|
544
|
-
*/
|
|
545
|
-
touch(className, options) {
|
|
546
|
-
if (typeof document === "undefined") return;
|
|
547
|
-
if (!this.config.gc) return;
|
|
548
|
-
const root = options?.root || document;
|
|
549
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
550
|
-
const now = Date.now();
|
|
551
|
-
const parts = className.indexOf(" ") === -1 ? [className] : className.split(" ");
|
|
552
|
-
for (const cls of parts) {
|
|
553
|
-
if (!StyleInjector.TASTY_CLASS_RE.test(cls)) continue;
|
|
554
|
-
if (!registry.rules.has(cls)) continue;
|
|
555
|
-
const entry = registry.usageMap.get(cls);
|
|
556
|
-
if (entry) entry.lastTouchedAt = now;
|
|
557
|
-
else registry.usageMap.set(cls, { lastTouchedAt: now });
|
|
558
|
-
registry.touchCount++;
|
|
559
|
-
}
|
|
560
|
-
const touchInterval = this.config.gc.touchInterval ?? 1e3;
|
|
561
|
-
if (registry.touchCount >= touchInterval) {
|
|
562
|
-
registry.touchCount = 0;
|
|
563
|
-
this.scheduleGC();
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
/**
|
|
567
|
-
* Schedule a GC via `requestIdleCallback` (or synchronously as fallback).
|
|
568
|
-
* Runs GC on all active roots. Avoids double-scheduling via `pendingGCHandle`.
|
|
569
|
-
*/
|
|
570
|
-
scheduleGC() {
|
|
571
|
-
if (this.pendingGCHandle != null) return;
|
|
572
|
-
const runGC = () => {
|
|
573
|
-
this.pendingGCHandle = null;
|
|
574
|
-
this.sheetManager.pruneDisconnectedRoots();
|
|
575
|
-
for (const root of this.sheetManager.getActiveRoots()) this.gc({ root });
|
|
576
|
-
};
|
|
577
|
-
if (typeof requestIdleCallback !== "undefined") this.pendingGCHandle = requestIdleCallback(() => runGC());
|
|
578
|
-
else runGC();
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* Synchronous garbage collection.
|
|
582
|
-
*
|
|
583
|
-
* 1. Quick upper-bound check: skip if unused count can't exceed capacity.
|
|
584
|
-
* 2. Scans the DOM for live tasty classNames (safety guard).
|
|
585
|
-
* 3. With `force: true`: deletes all unused entries inline.
|
|
586
|
-
* Without `force`: collects unused, sorts oldest-first, evicts over capacity.
|
|
587
|
-
*
|
|
588
|
-
* @returns Number of styles evicted.
|
|
589
|
-
*/
|
|
590
|
-
gc(options) {
|
|
591
|
-
if (typeof document === "undefined") return 0;
|
|
592
|
-
if (this.pendingGCHandle != null) {
|
|
593
|
-
if (typeof cancelIdleCallback !== "undefined") cancelIdleCallback(this.pendingGCHandle);
|
|
594
|
-
this.pendingGCHandle = null;
|
|
595
|
-
}
|
|
596
|
-
const root = options?.root || document;
|
|
597
|
-
const force = options?.force ?? false;
|
|
598
|
-
const registry = this.sheetManager.getRegistry(root);
|
|
599
|
-
const capacity = this.config.gc?.capacity ?? 1e3;
|
|
600
|
-
if (!force) {
|
|
601
|
-
let activeCount = 0;
|
|
602
|
-
for (const refCount of registry.refCounts.values()) if (refCount > 0) activeCount++;
|
|
603
|
-
if (registry.usageMap.size - activeCount <= capacity) return 0;
|
|
604
|
-
}
|
|
605
|
-
const liveClasses = /* @__PURE__ */ new Set();
|
|
606
|
-
for (const el of root.querySelectorAll("[class]")) for (const token of el.classList) if (StyleInjector.TASTY_CLASS_RE.test(token)) liveClasses.add(token);
|
|
607
|
-
let swept = 0;
|
|
608
|
-
if (force) for (const [className] of registry.usageMap) {
|
|
609
|
-
if (liveClasses.has(className)) continue;
|
|
610
|
-
if ((registry.refCounts.get(className) ?? 0) > 0) continue;
|
|
611
|
-
registry.usageMap.delete(className);
|
|
612
|
-
swept++;
|
|
613
|
-
}
|
|
614
|
-
else {
|
|
615
|
-
const unused = [];
|
|
616
|
-
for (const [className, usage] of registry.usageMap) {
|
|
617
|
-
if (liveClasses.has(className)) continue;
|
|
618
|
-
if ((registry.refCounts.get(className) ?? 0) > 0) continue;
|
|
619
|
-
unused.push({
|
|
620
|
-
className,
|
|
621
|
-
lastTouchedAt: usage.lastTouchedAt
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
if (unused.length > capacity) {
|
|
625
|
-
unused.sort((a, b) => a.lastTouchedAt - b.lastTouchedAt);
|
|
626
|
-
const toEvict = unused.length - capacity;
|
|
627
|
-
for (let i = 0; i < toEvict; i++) {
|
|
628
|
-
registry.usageMap.delete(unused[i].className);
|
|
629
|
-
swept++;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
if (swept > 0) this.sheetManager.forceCleanup(registry);
|
|
634
|
-
return swept;
|
|
635
|
-
}
|
|
636
|
-
/**
|
|
637
|
-
* Destroy all resources for a root
|
|
638
|
-
*/
|
|
639
|
-
destroy(root) {
|
|
640
|
-
const targetRoot = root || document;
|
|
641
|
-
this.sheetManager.cleanup(targetRoot);
|
|
642
|
-
if (this.pendingGCHandle != null && !this.sheetManager.hasActiveRoots()) {
|
|
643
|
-
if (typeof cancelIdleCallback !== "undefined") cancelIdleCallback(this.pendingGCHandle);
|
|
644
|
-
this.pendingGCHandle = null;
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
};
|
|
648
|
-
//#endregion
|
|
649
|
-
export { StyleInjector };
|
|
650
|
-
|
|
651
|
-
//# sourceMappingURL=injector.js.map
|