@tenphi/tasty 0.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/LICENSE +21 -0
- package/README.md +236 -0
- package/dist/_virtual/_rolldown/runtime.mjs +7 -0
- package/dist/chunks/cacheKey.d.ts +1 -0
- package/dist/chunks/cacheKey.js +70 -0
- package/dist/chunks/cacheKey.js.map +1 -0
- package/dist/chunks/cacheKey.mjs +70 -0
- package/dist/chunks/cacheKey.mjs.map +1 -0
- package/dist/chunks/definitions.d.ts +37 -0
- package/dist/chunks/definitions.js +260 -0
- package/dist/chunks/definitions.js.map +1 -0
- package/dist/chunks/definitions.mjs +260 -0
- package/dist/chunks/definitions.mjs.map +1 -0
- package/dist/chunks/index.d.ts +3 -0
- package/dist/chunks/renderChunk.d.ts +2 -0
- package/dist/chunks/renderChunk.js +61 -0
- package/dist/chunks/renderChunk.js.map +1 -0
- package/dist/chunks/renderChunk.mjs +61 -0
- package/dist/chunks/renderChunk.mjs.map +1 -0
- package/dist/config.d.ts +279 -0
- package/dist/config.js +400 -0
- package/dist/config.js.map +1 -0
- package/dist/config.mjs +231 -0
- package/dist/config.mjs.map +1 -0
- package/dist/css-writer.d.mts +45 -0
- package/dist/css-writer.mjs +74 -0
- package/dist/css-writer.mjs.map +1 -0
- package/dist/debug.d.ts +204 -0
- package/dist/debug.js +733 -0
- package/dist/debug.js.map +1 -0
- package/dist/extractor.d.mts +24 -0
- package/dist/extractor.mjs +150 -0
- package/dist/extractor.mjs.map +1 -0
- package/dist/hooks/index.d.ts +5 -0
- package/dist/hooks/useGlobalStyles.d.ts +27 -0
- package/dist/hooks/useGlobalStyles.js +56 -0
- package/dist/hooks/useGlobalStyles.js.map +1 -0
- package/dist/hooks/useKeyframes.d.ts +56 -0
- package/dist/hooks/useKeyframes.js +54 -0
- package/dist/hooks/useKeyframes.js.map +1 -0
- package/dist/hooks/useProperty.d.ts +79 -0
- package/dist/hooks/useProperty.js +91 -0
- package/dist/hooks/useProperty.js.map +1 -0
- package/dist/hooks/useRawCSS.d.ts +53 -0
- package/dist/hooks/useRawCSS.js +28 -0
- package/dist/hooks/useRawCSS.js.map +1 -0
- package/dist/hooks/useStyles.d.ts +40 -0
- package/dist/hooks/useStyles.js +169 -0
- package/dist/hooks/useStyles.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +30 -0
- package/dist/injector/index.d.ts +157 -0
- package/dist/injector/index.js +154 -0
- package/dist/injector/index.js.map +1 -0
- package/dist/injector/injector.d.ts +139 -0
- package/dist/injector/injector.js +404 -0
- package/dist/injector/injector.js.map +1 -0
- package/dist/injector/injector.mjs +404 -0
- package/dist/injector/injector.mjs.map +1 -0
- package/dist/injector/sheet-manager.d.ts +127 -0
- package/dist/injector/sheet-manager.js +714 -0
- package/dist/injector/sheet-manager.js.map +1 -0
- package/dist/injector/sheet-manager.mjs +714 -0
- package/dist/injector/sheet-manager.mjs.map +1 -0
- package/dist/injector/types.d.mts +18 -0
- package/dist/injector/types.d.ts +135 -0
- package/dist/keyframes/index.js +206 -0
- package/dist/keyframes/index.js.map +1 -0
- package/dist/keyframes/index.mjs +156 -0
- package/dist/keyframes/index.mjs.map +1 -0
- package/dist/parser/classify.js +319 -0
- package/dist/parser/classify.js.map +1 -0
- package/dist/parser/classify.mjs +319 -0
- package/dist/parser/classify.mjs.map +1 -0
- package/dist/parser/const.js +33 -0
- package/dist/parser/const.js.map +1 -0
- package/dist/parser/const.mjs +33 -0
- package/dist/parser/const.mjs.map +1 -0
- package/dist/parser/lru.js +109 -0
- package/dist/parser/lru.js.map +1 -0
- package/dist/parser/lru.mjs +109 -0
- package/dist/parser/lru.mjs.map +1 -0
- package/dist/parser/parser.d.ts +25 -0
- package/dist/parser/parser.js +116 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/parser/parser.mjs +116 -0
- package/dist/parser/parser.mjs.map +1 -0
- package/dist/parser/tokenizer.js +69 -0
- package/dist/parser/tokenizer.js.map +1 -0
- package/dist/parser/tokenizer.mjs +69 -0
- package/dist/parser/tokenizer.mjs.map +1 -0
- package/dist/parser/types.d.mts +37 -0
- package/dist/parser/types.d.ts +46 -0
- package/dist/parser/types.js +46 -0
- package/dist/parser/types.js.map +1 -0
- package/dist/parser/types.mjs +46 -0
- package/dist/parser/types.mjs.map +1 -0
- package/dist/pipeline/conditions.js +377 -0
- package/dist/pipeline/conditions.js.map +1 -0
- package/dist/pipeline/conditions.mjs +377 -0
- package/dist/pipeline/conditions.mjs.map +1 -0
- package/dist/pipeline/exclusive.d.ts +1 -0
- package/dist/pipeline/exclusive.js +231 -0
- package/dist/pipeline/exclusive.js.map +1 -0
- package/dist/pipeline/exclusive.mjs +231 -0
- package/dist/pipeline/exclusive.mjs.map +1 -0
- package/dist/pipeline/index.d.ts +53 -0
- package/dist/pipeline/index.js +641 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/index.mjs +635 -0
- package/dist/pipeline/index.mjs.map +1 -0
- package/dist/pipeline/materialize.js +821 -0
- package/dist/pipeline/materialize.js.map +1 -0
- package/dist/pipeline/materialize.mjs +821 -0
- package/dist/pipeline/materialize.mjs.map +1 -0
- package/dist/pipeline/parseStateKey.d.ts +1 -0
- package/dist/pipeline/parseStateKey.js +418 -0
- package/dist/pipeline/parseStateKey.js.map +1 -0
- package/dist/pipeline/parseStateKey.mjs +418 -0
- package/dist/pipeline/parseStateKey.mjs.map +1 -0
- package/dist/pipeline/simplify.js +557 -0
- package/dist/pipeline/simplify.js.map +1 -0
- package/dist/pipeline/simplify.mjs +557 -0
- package/dist/pipeline/simplify.mjs.map +1 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/okhsl-plugin.d.ts +35 -0
- package/dist/plugins/okhsl-plugin.js +371 -0
- package/dist/plugins/okhsl-plugin.js.map +1 -0
- package/dist/plugins/okhsl-plugin.mjs +345 -0
- package/dist/plugins/okhsl-plugin.mjs.map +1 -0
- package/dist/plugins/types.d.mts +49 -0
- package/dist/plugins/types.d.ts +69 -0
- package/dist/properties/index.js +158 -0
- package/dist/properties/index.js.map +1 -0
- package/dist/properties/index.mjs +141 -0
- package/dist/properties/index.mjs.map +1 -0
- package/dist/states/index.d.ts +45 -0
- package/dist/states/index.js +389 -0
- package/dist/states/index.js.map +1 -0
- package/dist/states/index.mjs +161 -0
- package/dist/states/index.mjs.map +1 -0
- package/dist/static/index.d.ts +5 -0
- package/dist/static/index.js +5 -0
- package/dist/static/tastyStatic.d.ts +46 -0
- package/dist/static/tastyStatic.js +31 -0
- package/dist/static/tastyStatic.js.map +1 -0
- package/dist/static/types.d.ts +49 -0
- package/dist/static/types.js +24 -0
- package/dist/static/types.js.map +1 -0
- package/dist/styles/align.d.ts +15 -0
- package/dist/styles/align.js +14 -0
- package/dist/styles/align.js.map +1 -0
- package/dist/styles/align.mjs +14 -0
- package/dist/styles/align.mjs.map +1 -0
- package/dist/styles/border.d.ts +25 -0
- package/dist/styles/border.js +114 -0
- package/dist/styles/border.js.map +1 -0
- package/dist/styles/border.mjs +114 -0
- package/dist/styles/border.mjs.map +1 -0
- package/dist/styles/color.d.ts +14 -0
- package/dist/styles/color.js +23 -0
- package/dist/styles/color.js.map +1 -0
- package/dist/styles/color.mjs +23 -0
- package/dist/styles/color.mjs.map +1 -0
- package/dist/styles/createStyle.js +77 -0
- package/dist/styles/createStyle.js.map +1 -0
- package/dist/styles/createStyle.mjs +77 -0
- package/dist/styles/createStyle.mjs.map +1 -0
- package/dist/styles/dimension.js +97 -0
- package/dist/styles/dimension.js.map +1 -0
- package/dist/styles/dimension.mjs +97 -0
- package/dist/styles/dimension.mjs.map +1 -0
- package/dist/styles/display.d.ts +37 -0
- package/dist/styles/display.js +67 -0
- package/dist/styles/display.js.map +1 -0
- package/dist/styles/display.mjs +67 -0
- package/dist/styles/display.mjs.map +1 -0
- package/dist/styles/fade.d.ts +15 -0
- package/dist/styles/fade.js +58 -0
- package/dist/styles/fade.js.map +1 -0
- package/dist/styles/fade.mjs +58 -0
- package/dist/styles/fade.mjs.map +1 -0
- package/dist/styles/fill.d.ts +44 -0
- package/dist/styles/fill.js +51 -0
- package/dist/styles/fill.js.map +1 -0
- package/dist/styles/fill.mjs +51 -0
- package/dist/styles/fill.mjs.map +1 -0
- package/dist/styles/flow.d.ts +16 -0
- package/dist/styles/flow.js +12 -0
- package/dist/styles/flow.js.map +1 -0
- package/dist/styles/flow.mjs +12 -0
- package/dist/styles/flow.mjs.map +1 -0
- package/dist/styles/gap.d.ts +31 -0
- package/dist/styles/gap.js +37 -0
- package/dist/styles/gap.js.map +1 -0
- package/dist/styles/gap.mjs +37 -0
- package/dist/styles/gap.mjs.map +1 -0
- package/dist/styles/height.d.ts +17 -0
- package/dist/styles/height.js +20 -0
- package/dist/styles/height.js.map +1 -0
- package/dist/styles/height.mjs +20 -0
- package/dist/styles/height.mjs.map +1 -0
- package/dist/styles/index.d.ts +2 -0
- package/dist/styles/index.js +9 -0
- package/dist/styles/index.js.map +1 -0
- package/dist/styles/index.mjs +9 -0
- package/dist/styles/index.mjs.map +1 -0
- package/dist/styles/inset.d.ts +50 -0
- package/dist/styles/inset.js +142 -0
- package/dist/styles/inset.js.map +1 -0
- package/dist/styles/inset.mjs +142 -0
- package/dist/styles/inset.mjs.map +1 -0
- package/dist/styles/justify.d.ts +15 -0
- package/dist/styles/justify.js +14 -0
- package/dist/styles/justify.js.map +1 -0
- package/dist/styles/justify.mjs +14 -0
- package/dist/styles/justify.mjs.map +1 -0
- package/dist/styles/list.d.ts +16 -0
- package/dist/styles/list.js +98 -0
- package/dist/styles/list.js.map +1 -0
- package/dist/styles/margin.d.ts +28 -0
- package/dist/styles/margin.js +96 -0
- package/dist/styles/margin.js.map +1 -0
- package/dist/styles/margin.mjs +96 -0
- package/dist/styles/margin.mjs.map +1 -0
- package/dist/styles/outline.d.ts +29 -0
- package/dist/styles/outline.js +65 -0
- package/dist/styles/outline.js.map +1 -0
- package/dist/styles/outline.mjs +65 -0
- package/dist/styles/outline.mjs.map +1 -0
- package/dist/styles/padding.d.ts +28 -0
- package/dist/styles/padding.js +96 -0
- package/dist/styles/padding.js.map +1 -0
- package/dist/styles/padding.mjs +96 -0
- package/dist/styles/padding.mjs.map +1 -0
- package/dist/styles/predefined.d.ts +74 -0
- package/dist/styles/predefined.js +241 -0
- package/dist/styles/predefined.js.map +1 -0
- package/dist/styles/predefined.mjs +232 -0
- package/dist/styles/predefined.mjs.map +1 -0
- package/dist/styles/preset.d.ts +47 -0
- package/dist/styles/preset.js +126 -0
- package/dist/styles/preset.js.map +1 -0
- package/dist/styles/preset.mjs +126 -0
- package/dist/styles/preset.mjs.map +1 -0
- package/dist/styles/radius.d.ts +14 -0
- package/dist/styles/radius.js +51 -0
- package/dist/styles/radius.js.map +1 -0
- package/dist/styles/radius.mjs +51 -0
- package/dist/styles/radius.mjs.map +1 -0
- package/dist/styles/scrollbar.d.ts +21 -0
- package/dist/styles/scrollbar.js +105 -0
- package/dist/styles/scrollbar.js.map +1 -0
- package/dist/styles/scrollbar.mjs +105 -0
- package/dist/styles/scrollbar.mjs.map +1 -0
- package/dist/styles/shadow.d.ts +14 -0
- package/dist/styles/shadow.js +24 -0
- package/dist/styles/shadow.js.map +1 -0
- package/dist/styles/shadow.mjs +24 -0
- package/dist/styles/shadow.mjs.map +1 -0
- package/dist/styles/styledScrollbar.d.ts +47 -0
- package/dist/styles/styledScrollbar.js +38 -0
- package/dist/styles/styledScrollbar.js.map +1 -0
- package/dist/styles/styledScrollbar.mjs +38 -0
- package/dist/styles/styledScrollbar.mjs.map +1 -0
- package/dist/styles/transition.d.ts +14 -0
- package/dist/styles/transition.js +138 -0
- package/dist/styles/transition.js.map +1 -0
- package/dist/styles/transition.mjs +138 -0
- package/dist/styles/transition.mjs.map +1 -0
- package/dist/styles/types.d.mts +492 -0
- package/dist/styles/types.d.ts +496 -0
- package/dist/styles/width.d.ts +17 -0
- package/dist/styles/width.js +20 -0
- package/dist/styles/width.js.map +1 -0
- package/dist/styles/width.mjs +20 -0
- package/dist/styles/width.mjs.map +1 -0
- package/dist/tasty.d.ts +983 -0
- package/dist/tasty.js +191 -0
- package/dist/tasty.js.map +1 -0
- package/dist/tokens/typography.d.ts +19 -0
- package/dist/tokens/typography.js +237 -0
- package/dist/tokens/typography.js.map +1 -0
- package/dist/types.d.ts +182 -0
- package/dist/utils/cache-wrapper.js +26 -0
- package/dist/utils/cache-wrapper.js.map +1 -0
- package/dist/utils/cache-wrapper.mjs +26 -0
- package/dist/utils/cache-wrapper.mjs.map +1 -0
- package/dist/utils/case-converter.js +8 -0
- package/dist/utils/case-converter.js.map +1 -0
- package/dist/utils/case-converter.mjs +8 -0
- package/dist/utils/case-converter.mjs.map +1 -0
- package/dist/utils/colors.d.ts +5 -0
- package/dist/utils/colors.js +9 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/dotize.d.ts +26 -0
- package/dist/utils/dotize.js +122 -0
- package/dist/utils/dotize.js.map +1 -0
- package/dist/utils/filter-base-props.d.ts +15 -0
- package/dist/utils/filter-base-props.js +45 -0
- package/dist/utils/filter-base-props.js.map +1 -0
- package/dist/utils/get-display-name.d.ts +7 -0
- package/dist/utils/get-display-name.js +10 -0
- package/dist/utils/get-display-name.js.map +1 -0
- package/dist/utils/hsl-to-rgb.js +38 -0
- package/dist/utils/hsl-to-rgb.js.map +1 -0
- package/dist/utils/hsl-to-rgb.mjs +38 -0
- package/dist/utils/hsl-to-rgb.mjs.map +1 -0
- package/dist/utils/is-dev-env.js +19 -0
- package/dist/utils/is-dev-env.js.map +1 -0
- package/dist/utils/is-dev-env.mjs +19 -0
- package/dist/utils/is-dev-env.mjs.map +1 -0
- package/dist/utils/merge-styles.d.ts +7 -0
- package/dist/utils/merge-styles.js +146 -0
- package/dist/utils/merge-styles.js.map +1 -0
- package/dist/utils/merge-styles.mjs +146 -0
- package/dist/utils/merge-styles.mjs.map +1 -0
- package/dist/utils/mod-attrs.d.ts +8 -0
- package/dist/utils/mod-attrs.js +21 -0
- package/dist/utils/mod-attrs.js.map +1 -0
- package/dist/utils/okhsl-to-rgb.js +296 -0
- package/dist/utils/okhsl-to-rgb.js.map +1 -0
- package/dist/utils/okhsl-to-rgb.mjs +296 -0
- package/dist/utils/okhsl-to-rgb.mjs.map +1 -0
- package/dist/utils/process-tokens.d.ts +31 -0
- package/dist/utils/process-tokens.js +171 -0
- package/dist/utils/process-tokens.js.map +1 -0
- package/dist/utils/process-tokens.mjs +28 -0
- package/dist/utils/process-tokens.mjs.map +1 -0
- package/dist/utils/resolve-recipes.d.ts +17 -0
- package/dist/utils/resolve-recipes.js +143 -0
- package/dist/utils/resolve-recipes.js.map +1 -0
- package/dist/utils/resolve-recipes.mjs +143 -0
- package/dist/utils/resolve-recipes.mjs.map +1 -0
- package/dist/utils/string.js +8 -0
- package/dist/utils/string.js.map +1 -0
- package/dist/utils/string.mjs +8 -0
- package/dist/utils/string.mjs.map +1 -0
- package/dist/utils/styles.d.mts +18 -0
- package/dist/utils/styles.d.ts +183 -0
- package/dist/utils/styles.js +585 -0
- package/dist/utils/styles.js.map +1 -0
- package/dist/utils/styles.mjs +346 -0
- package/dist/utils/styles.mjs.map +1 -0
- package/dist/utils/typography.d.ts +36 -0
- package/dist/utils/typography.js +53 -0
- package/dist/utils/typography.js.map +1 -0
- package/dist/utils/warnings.d.ts +16 -0
- package/dist/utils/warnings.js +16 -0
- package/dist/utils/warnings.js.map +1 -0
- package/dist/zero/babel.d.mts +108 -0
- package/dist/zero/babel.mjs +282 -0
- package/dist/zero/babel.mjs.map +1 -0
- package/dist/zero/index.d.mts +3 -0
- package/dist/zero/index.mjs +4 -0
- package/dist/zero/next.d.mts +60 -0
- package/dist/zero/next.mjs +78 -0
- package/dist/zero/next.mjs.map +1 -0
- package/package.json +127 -0
|
@@ -0,0 +1,714 @@
|
|
|
1
|
+
import { createStyle } from "../styles/createStyle.mjs";
|
|
2
|
+
import { STYLE_HANDLER_MAP } from "../styles/index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/injector/sheet-manager.ts
|
|
5
|
+
var SheetManager = class {
|
|
6
|
+
rootRegistries = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
config;
|
|
8
|
+
/** Dedicated style elements for raw CSS per root */
|
|
9
|
+
rawStyleElements = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
/** Tracking for raw CSS blocks per root */
|
|
11
|
+
rawCSSBlocks = /* @__PURE__ */ new WeakMap();
|
|
12
|
+
/** Counter for generating unique raw CSS IDs */
|
|
13
|
+
rawCSSCounter = 0;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get or create registry for a root (Document or ShadowRoot)
|
|
19
|
+
*/
|
|
20
|
+
getRegistry(root) {
|
|
21
|
+
let registry = this.rootRegistries.get(root);
|
|
22
|
+
if (!registry) {
|
|
23
|
+
const metrics = this.config.devMode ? {
|
|
24
|
+
hits: 0,
|
|
25
|
+
misses: 0,
|
|
26
|
+
bulkCleanups: 0,
|
|
27
|
+
totalInsertions: 0,
|
|
28
|
+
totalUnused: 0,
|
|
29
|
+
stylesCleanedUp: 0,
|
|
30
|
+
cleanupHistory: [],
|
|
31
|
+
startTime: Date.now()
|
|
32
|
+
} : void 0;
|
|
33
|
+
registry = {
|
|
34
|
+
sheets: [],
|
|
35
|
+
refCounts: /* @__PURE__ */ new Map(),
|
|
36
|
+
rules: /* @__PURE__ */ new Map(),
|
|
37
|
+
cacheKeyToClassName: /* @__PURE__ */ new Map(),
|
|
38
|
+
ruleTextSet: /* @__PURE__ */ new Set(),
|
|
39
|
+
bulkCleanupTimeout: null,
|
|
40
|
+
cleanupCheckTimeout: null,
|
|
41
|
+
metrics,
|
|
42
|
+
classCounter: 0,
|
|
43
|
+
keyframesCache: /* @__PURE__ */ new Map(),
|
|
44
|
+
keyframesNameToContent: /* @__PURE__ */ new Map(),
|
|
45
|
+
keyframesCounter: 0,
|
|
46
|
+
injectedProperties: /* @__PURE__ */ new Map(),
|
|
47
|
+
globalRules: /* @__PURE__ */ new Map()
|
|
48
|
+
};
|
|
49
|
+
this.rootRegistries.set(root, registry);
|
|
50
|
+
}
|
|
51
|
+
return registry;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create a new stylesheet for the registry
|
|
55
|
+
*/
|
|
56
|
+
createSheet(registry, root) {
|
|
57
|
+
const sheetInfo = {
|
|
58
|
+
sheet: this.createStyleElement(root),
|
|
59
|
+
ruleCount: 0,
|
|
60
|
+
holes: []
|
|
61
|
+
};
|
|
62
|
+
registry.sheets.push(sheetInfo);
|
|
63
|
+
return sheetInfo;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a style element and append to document
|
|
67
|
+
*/
|
|
68
|
+
createStyleElement(root) {
|
|
69
|
+
const style = root.createElement?.("style") || document.createElement("style");
|
|
70
|
+
if (this.config.nonce) style.nonce = this.config.nonce;
|
|
71
|
+
style.setAttribute("data-tasty", "");
|
|
72
|
+
if ("head" in root && root.head) root.head.appendChild(style);
|
|
73
|
+
else if ("appendChild" in root) root.appendChild(style);
|
|
74
|
+
else document.head.appendChild(style);
|
|
75
|
+
if (!style.isConnected && !this.config.forceTextInjection) console.error("SheetManager: Style element failed to connect to DOM!", {
|
|
76
|
+
parentNode: style.parentNode?.nodeName,
|
|
77
|
+
isConnected: style.isConnected
|
|
78
|
+
});
|
|
79
|
+
return style;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Insert CSS rules as a single block
|
|
83
|
+
*/
|
|
84
|
+
insertRule(registry, flattenedRules, className, root) {
|
|
85
|
+
let targetSheet = this.findAvailableSheet(registry, root);
|
|
86
|
+
if (!targetSheet) targetSheet = this.createSheet(registry, root);
|
|
87
|
+
const sheetIndex = registry.sheets.indexOf(targetSheet);
|
|
88
|
+
try {
|
|
89
|
+
const groupedRules = [];
|
|
90
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
91
|
+
const atKey = (at) => at && at.length ? at.join("|") : "";
|
|
92
|
+
flattenedRules.forEach((r) => {
|
|
93
|
+
const key = `${atKey(r.atRules)}||${r.selector}`;
|
|
94
|
+
const existing = groupMap.get(key);
|
|
95
|
+
if (existing) existing.declarations = existing.declarations ? `${existing.declarations} ${r.declarations}` : r.declarations;
|
|
96
|
+
else {
|
|
97
|
+
groupMap.set(key, {
|
|
98
|
+
idx: groupedRules.length,
|
|
99
|
+
selector: r.selector,
|
|
100
|
+
atRules: r.atRules,
|
|
101
|
+
declarations: r.declarations
|
|
102
|
+
});
|
|
103
|
+
groupedRules.push({ ...r });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
groupMap.forEach((val) => {
|
|
107
|
+
groupedRules[val.idx] = {
|
|
108
|
+
selector: val.selector,
|
|
109
|
+
atRules: val.atRules,
|
|
110
|
+
declarations: val.declarations
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
const insertedRuleTexts = [];
|
|
114
|
+
const insertedIndices = [];
|
|
115
|
+
let currentRuleIndex = this.findAvailableRuleIndex(targetSheet);
|
|
116
|
+
let firstInsertedIndex = null;
|
|
117
|
+
let lastInsertedIndex = null;
|
|
118
|
+
for (const rule of groupedRules) {
|
|
119
|
+
const declarations = rule.declarations;
|
|
120
|
+
const baseRule = `${rule.selector} { ${declarations} }`;
|
|
121
|
+
let fullRule = baseRule;
|
|
122
|
+
if (rule.atRules && rule.atRules.length > 0) fullRule = rule.atRules.reduce((css, atRule) => `${atRule} { ${css} }`, baseRule);
|
|
123
|
+
const styleElement = targetSheet.sheet;
|
|
124
|
+
const styleSheet = styleElement.sheet;
|
|
125
|
+
if (styleSheet && !this.config.forceTextInjection) {
|
|
126
|
+
const maxIndex = styleSheet.cssRules.length;
|
|
127
|
+
const atomicRuleIndex = this.findAvailableRuleIndex(targetSheet);
|
|
128
|
+
const safeIndex = Math.min(Math.max(0, atomicRuleIndex), maxIndex);
|
|
129
|
+
const splitSelectorsSafely = (selectorList) => {
|
|
130
|
+
const parts = [];
|
|
131
|
+
let buf = "";
|
|
132
|
+
let depthSq = 0;
|
|
133
|
+
let depthPar = 0;
|
|
134
|
+
let inStr = "";
|
|
135
|
+
for (let i = 0; i < selectorList.length; i++) {
|
|
136
|
+
const ch = selectorList[i];
|
|
137
|
+
if (inStr) {
|
|
138
|
+
if (ch === inStr && selectorList[i - 1] !== "\\") inStr = "";
|
|
139
|
+
buf += ch;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (ch === "\"" || ch === "'") {
|
|
143
|
+
inStr = ch;
|
|
144
|
+
buf += ch;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (ch === "[") depthSq++;
|
|
148
|
+
else if (ch === "]") depthSq = Math.max(0, depthSq - 1);
|
|
149
|
+
else if (ch === "(") depthPar++;
|
|
150
|
+
else if (ch === ")") depthPar = Math.max(0, depthPar - 1);
|
|
151
|
+
if (ch === "," && depthSq === 0 && depthPar === 0) {
|
|
152
|
+
const part = buf.trim();
|
|
153
|
+
if (part) parts.push(part);
|
|
154
|
+
buf = "";
|
|
155
|
+
} else buf += ch;
|
|
156
|
+
}
|
|
157
|
+
const tail = buf.trim();
|
|
158
|
+
if (tail) parts.push(tail);
|
|
159
|
+
return parts;
|
|
160
|
+
};
|
|
161
|
+
try {
|
|
162
|
+
styleSheet.insertRule(fullRule, safeIndex);
|
|
163
|
+
targetSheet.ruleCount++;
|
|
164
|
+
insertedIndices.push(safeIndex);
|
|
165
|
+
if (firstInsertedIndex == null) firstInsertedIndex = safeIndex;
|
|
166
|
+
lastInsertedIndex = safeIndex;
|
|
167
|
+
currentRuleIndex = safeIndex + 1;
|
|
168
|
+
} catch (e) {
|
|
169
|
+
const selectors = splitSelectorsSafely(rule.selector);
|
|
170
|
+
if (selectors.length > 1) {
|
|
171
|
+
let anyInserted = false;
|
|
172
|
+
for (const sel of selectors) {
|
|
173
|
+
const singleBase = `${sel} { ${declarations} }`;
|
|
174
|
+
let singleRule = singleBase;
|
|
175
|
+
if (rule.atRules && rule.atRules.length > 0) singleRule = rule.atRules.reduce((css, atRule) => `${atRule} { ${css} }`, singleBase);
|
|
176
|
+
try {
|
|
177
|
+
const maxIdx = styleSheet.cssRules.length;
|
|
178
|
+
const atomicIdx = this.findAvailableRuleIndex(targetSheet);
|
|
179
|
+
const idx = Math.min(Math.max(0, atomicIdx), maxIdx);
|
|
180
|
+
styleSheet.insertRule(singleRule, idx);
|
|
181
|
+
targetSheet.ruleCount++;
|
|
182
|
+
insertedIndices.push(idx);
|
|
183
|
+
if (firstInsertedIndex == null) firstInsertedIndex = idx;
|
|
184
|
+
lastInsertedIndex = idx;
|
|
185
|
+
currentRuleIndex = idx + 1;
|
|
186
|
+
anyInserted = true;
|
|
187
|
+
} catch (singleErr) {
|
|
188
|
+
if (process.env.NODE_ENV !== "production") console.warn("[tasty] Browser rejected CSS rule:", singleRule, singleErr);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (!anyInserted) {}
|
|
192
|
+
} else if (process.env.NODE_ENV !== "production") console.warn("[tasty] Browser rejected CSS rule:", fullRule, e);
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
const atomicRuleIndex = this.findAvailableRuleIndex(targetSheet);
|
|
196
|
+
styleElement.textContent = (styleElement.textContent || "") + "\n" + fullRule;
|
|
197
|
+
targetSheet.ruleCount++;
|
|
198
|
+
insertedIndices.push(atomicRuleIndex);
|
|
199
|
+
if (firstInsertedIndex == null) firstInsertedIndex = atomicRuleIndex;
|
|
200
|
+
lastInsertedIndex = atomicRuleIndex;
|
|
201
|
+
currentRuleIndex = atomicRuleIndex + 1;
|
|
202
|
+
}
|
|
203
|
+
if (!styleElement.parentNode && !this.config.forceTextInjection) console.error("SheetManager: Style element is NOT in DOM! This is the problem!", {
|
|
204
|
+
className,
|
|
205
|
+
ruleIndex: currentRuleIndex
|
|
206
|
+
});
|
|
207
|
+
if (this.config.devMode) {
|
|
208
|
+
insertedRuleTexts.push(fullRule);
|
|
209
|
+
try {
|
|
210
|
+
registry.ruleTextSet.add(fullRule);
|
|
211
|
+
} catch {}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (insertedIndices.length === 0) return null;
|
|
215
|
+
return {
|
|
216
|
+
className,
|
|
217
|
+
ruleIndex: firstInsertedIndex ?? 0,
|
|
218
|
+
sheetIndex,
|
|
219
|
+
cssText: this.config.devMode ? insertedRuleTexts : void 0,
|
|
220
|
+
endRuleIndex: lastInsertedIndex ?? firstInsertedIndex ?? 0,
|
|
221
|
+
indices: insertedIndices
|
|
222
|
+
};
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.warn("Failed to insert CSS rules:", error, {
|
|
225
|
+
flattenedRules,
|
|
226
|
+
className
|
|
227
|
+
});
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Insert global CSS rules
|
|
233
|
+
*/
|
|
234
|
+
insertGlobalRule(registry, flattenedRules, globalKey, root) {
|
|
235
|
+
const ruleInfo = this.insertRule(registry, flattenedRules, globalKey, root);
|
|
236
|
+
if (ruleInfo) registry.globalRules.set(globalKey, ruleInfo);
|
|
237
|
+
return ruleInfo;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Delete a global CSS rule by key
|
|
241
|
+
*/
|
|
242
|
+
deleteGlobalRule(registry, globalKey) {
|
|
243
|
+
const ruleInfo = registry.globalRules.get(globalKey);
|
|
244
|
+
if (!ruleInfo) return;
|
|
245
|
+
this.deleteRule(registry, ruleInfo);
|
|
246
|
+
registry.globalRules.delete(globalKey);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Adjust rule indices after deletion to account for shifting
|
|
250
|
+
*/
|
|
251
|
+
adjustIndicesAfterDeletion(registry, sheetIndex, startIdx, endIdx, deleteCount, deletedRuleInfo, deletedIndices) {
|
|
252
|
+
try {
|
|
253
|
+
const sortedDeleted = deletedIndices && deletedIndices.length > 0 ? [...deletedIndices].sort((a, b) => a - b) : null;
|
|
254
|
+
const countDeletedBefore = (sorted, idx) => {
|
|
255
|
+
let shift = 0;
|
|
256
|
+
for (const delIdx of sorted) if (delIdx < idx) shift++;
|
|
257
|
+
else break;
|
|
258
|
+
return shift;
|
|
259
|
+
};
|
|
260
|
+
const adjustRuleInfo = (info) => {
|
|
261
|
+
if (info === deletedRuleInfo) return;
|
|
262
|
+
if (info.sheetIndex !== sheetIndex) return;
|
|
263
|
+
if (!info.indices || info.indices.length === 0) return;
|
|
264
|
+
if (sortedDeleted) info.indices = info.indices.map((idx) => {
|
|
265
|
+
return idx - countDeletedBefore(sortedDeleted, idx);
|
|
266
|
+
});
|
|
267
|
+
else info.indices = info.indices.map((idx) => idx > endIdx ? Math.max(0, idx - deleteCount) : idx);
|
|
268
|
+
if (info.indices.length > 0) {
|
|
269
|
+
info.ruleIndex = Math.min(...info.indices);
|
|
270
|
+
info.endRuleIndex = Math.max(...info.indices);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
for (const info of registry.rules.values()) adjustRuleInfo(info);
|
|
274
|
+
for (const info of registry.globalRules.values()) adjustRuleInfo(info);
|
|
275
|
+
for (const entry of registry.keyframesCache.values()) {
|
|
276
|
+
const ki = entry.info;
|
|
277
|
+
if (ki.sheetIndex !== sheetIndex) continue;
|
|
278
|
+
if (sortedDeleted) {
|
|
279
|
+
const shift = countDeletedBefore(sortedDeleted, ki.ruleIndex);
|
|
280
|
+
if (shift > 0) ki.ruleIndex = Math.max(0, ki.ruleIndex - shift);
|
|
281
|
+
} else if (ki.ruleIndex > endIdx) ki.ruleIndex = Math.max(0, ki.ruleIndex - deleteCount);
|
|
282
|
+
}
|
|
283
|
+
} catch {}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Delete a CSS rule from the sheet
|
|
287
|
+
*/
|
|
288
|
+
deleteRule(registry, ruleInfo) {
|
|
289
|
+
const sheet = registry.sheets[ruleInfo.sheetIndex];
|
|
290
|
+
if (!sheet) return;
|
|
291
|
+
try {
|
|
292
|
+
const texts = this.config.devMode && Array.isArray(ruleInfo.cssText) ? ruleInfo.cssText.slice() : [];
|
|
293
|
+
const styleSheet = sheet.sheet.sheet;
|
|
294
|
+
if (styleSheet) {
|
|
295
|
+
const rules = styleSheet.cssRules;
|
|
296
|
+
if (ruleInfo.indices && ruleInfo.indices.length > 0) {
|
|
297
|
+
const sortedIndices = [...ruleInfo.indices].sort((a, b) => b - a);
|
|
298
|
+
const deletedIndices = [];
|
|
299
|
+
for (const idx of sortedIndices) if (idx >= 0 && idx < styleSheet.cssRules.length) try {
|
|
300
|
+
styleSheet.deleteRule(idx);
|
|
301
|
+
deletedIndices.push(idx);
|
|
302
|
+
} catch (e) {
|
|
303
|
+
console.warn(`Failed to delete rule at index ${idx}:`, e);
|
|
304
|
+
}
|
|
305
|
+
sheet.ruleCount = Math.max(0, sheet.ruleCount - deletedIndices.length);
|
|
306
|
+
if (deletedIndices.length > 0) this.adjustIndicesAfterDeletion(registry, ruleInfo.sheetIndex, Math.min(...deletedIndices), Math.max(...deletedIndices), deletedIndices.length, ruleInfo, deletedIndices);
|
|
307
|
+
} else {
|
|
308
|
+
const startIdx = Math.max(0, ruleInfo.ruleIndex);
|
|
309
|
+
const endIdx = Math.min(rules.length - 1, Number.isFinite(ruleInfo.endRuleIndex) ? ruleInfo.endRuleIndex : startIdx);
|
|
310
|
+
if (Number.isFinite(startIdx) && endIdx >= startIdx) {
|
|
311
|
+
const deleteCount = endIdx - startIdx + 1;
|
|
312
|
+
for (let idx = endIdx; idx >= startIdx; idx--) {
|
|
313
|
+
if (idx < 0 || idx >= styleSheet.cssRules.length) continue;
|
|
314
|
+
styleSheet.deleteRule(idx);
|
|
315
|
+
}
|
|
316
|
+
sheet.ruleCount = Math.max(0, sheet.ruleCount - deleteCount);
|
|
317
|
+
this.adjustIndicesAfterDeletion(registry, ruleInfo.sheetIndex, startIdx, endIdx, deleteCount, ruleInfo);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (this.config.devMode && texts.length) try {
|
|
322
|
+
for (const text of texts) registry.ruleTextSet.delete(text);
|
|
323
|
+
} catch {}
|
|
324
|
+
} catch (error) {
|
|
325
|
+
console.warn("Failed to delete CSS rule:", error);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Find a sheet with available space or return null
|
|
330
|
+
*/
|
|
331
|
+
findAvailableSheet(registry, _root) {
|
|
332
|
+
const maxRules = this.config.maxRulesPerSheet;
|
|
333
|
+
if (!maxRules) return registry.sheets[registry.sheets.length - 1] || null;
|
|
334
|
+
for (const sheet of registry.sheets) if (sheet.ruleCount < maxRules) return sheet;
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Find an available rule index in the sheet
|
|
339
|
+
*/
|
|
340
|
+
findAvailableRuleIndex(sheet) {
|
|
341
|
+
return sheet.ruleCount;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Schedule bulk cleanup of all unused styles (non-stacking)
|
|
345
|
+
*/
|
|
346
|
+
scheduleBulkCleanup(registry) {
|
|
347
|
+
if (registry.bulkCleanupTimeout) {
|
|
348
|
+
if (this.config.idleCleanup && typeof cancelIdleCallback !== "undefined") cancelIdleCallback(registry.bulkCleanupTimeout);
|
|
349
|
+
else clearTimeout(registry.bulkCleanupTimeout);
|
|
350
|
+
registry.bulkCleanupTimeout = null;
|
|
351
|
+
}
|
|
352
|
+
const performCleanup = () => {
|
|
353
|
+
this.performBulkCleanup(registry);
|
|
354
|
+
registry.bulkCleanupTimeout = null;
|
|
355
|
+
};
|
|
356
|
+
if (this.config.idleCleanup && typeof requestIdleCallback !== "undefined") registry.bulkCleanupTimeout = requestIdleCallback(performCleanup);
|
|
357
|
+
else {
|
|
358
|
+
const delay = this.config.bulkCleanupDelay || 5e3;
|
|
359
|
+
registry.bulkCleanupTimeout = setTimeout(performCleanup, delay);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Force cleanup of unused styles
|
|
364
|
+
*/
|
|
365
|
+
forceCleanup(registry) {
|
|
366
|
+
this.performBulkCleanup(registry, true);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Perform bulk cleanup of all unused styles
|
|
370
|
+
*/
|
|
371
|
+
performBulkCleanup(registry, cleanupAll = false) {
|
|
372
|
+
const cleanupStartTime = Date.now();
|
|
373
|
+
const unusedClassNames = Array.from(registry.refCounts.entries()).filter(([, refCount]) => refCount === 0).map(([className]) => className);
|
|
374
|
+
if (unusedClassNames.length === 0) return;
|
|
375
|
+
const candidates = unusedClassNames.map((className) => {
|
|
376
|
+
return {
|
|
377
|
+
className,
|
|
378
|
+
ruleInfo: registry.rules.get(className)
|
|
379
|
+
};
|
|
380
|
+
});
|
|
381
|
+
if (candidates.length === 0) return;
|
|
382
|
+
let selected = candidates;
|
|
383
|
+
if (!cleanupAll) {
|
|
384
|
+
const ratio = this.config.bulkCleanupBatchRatio ?? .5;
|
|
385
|
+
const limit = Math.max(1, Math.floor(candidates.length * Math.min(1, Math.max(0, ratio))));
|
|
386
|
+
selected = candidates.slice(0, limit);
|
|
387
|
+
}
|
|
388
|
+
let cleanedUpCount = 0;
|
|
389
|
+
let totalCssSize = 0;
|
|
390
|
+
let totalRulesDeleted = 0;
|
|
391
|
+
const rulesBySheet = /* @__PURE__ */ new Map();
|
|
392
|
+
for (const { className, ruleInfo } of selected) {
|
|
393
|
+
const sheetIndex = ruleInfo.sheetIndex;
|
|
394
|
+
if (this.config.devMode && Array.isArray(ruleInfo.cssText)) {
|
|
395
|
+
const cssSize = ruleInfo.cssText.reduce((total, css) => total + css.length, 0);
|
|
396
|
+
totalCssSize += cssSize;
|
|
397
|
+
totalRulesDeleted += ruleInfo.cssText.length;
|
|
398
|
+
}
|
|
399
|
+
if (!rulesBySheet.has(sheetIndex)) rulesBySheet.set(sheetIndex, []);
|
|
400
|
+
rulesBySheet.get(sheetIndex).push({
|
|
401
|
+
className,
|
|
402
|
+
ruleInfo
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
for (const [_sheetIndex, rulesInSheet] of rulesBySheet) {
|
|
406
|
+
rulesInSheet.sort((a, b) => b.ruleInfo.ruleIndex - a.ruleInfo.ruleIndex);
|
|
407
|
+
for (const { className, ruleInfo } of rulesInSheet) {
|
|
408
|
+
if ((registry.refCounts.get(className) || 0) > 0) continue;
|
|
409
|
+
if (registry.rules.get(className) !== ruleInfo) continue;
|
|
410
|
+
const sheetInfo = registry.sheets[ruleInfo.sheetIndex];
|
|
411
|
+
if (!sheetInfo || !sheetInfo.sheet) continue;
|
|
412
|
+
const styleSheet = sheetInfo.sheet.sheet;
|
|
413
|
+
if (!styleSheet) continue;
|
|
414
|
+
const maxRuleIndex = styleSheet.cssRules.length - 1;
|
|
415
|
+
const startIdx = ruleInfo.ruleIndex;
|
|
416
|
+
const endIdx = ruleInfo.endRuleIndex ?? ruleInfo.ruleIndex;
|
|
417
|
+
if (startIdx < 0 || endIdx > maxRuleIndex || startIdx > endIdx) continue;
|
|
418
|
+
this.deleteRule(registry, ruleInfo);
|
|
419
|
+
registry.rules.delete(className);
|
|
420
|
+
registry.refCounts.delete(className);
|
|
421
|
+
const keysToDelete = [];
|
|
422
|
+
for (const [key, mappedClassName] of registry.cacheKeyToClassName.entries()) if (mappedClassName === className) keysToDelete.push(key);
|
|
423
|
+
for (const key of keysToDelete) registry.cacheKeyToClassName.delete(key);
|
|
424
|
+
cleanedUpCount++;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (registry.metrics) {
|
|
428
|
+
registry.metrics.bulkCleanups++;
|
|
429
|
+
registry.metrics.stylesCleanedUp += cleanedUpCount;
|
|
430
|
+
registry.metrics.cleanupHistory.push({
|
|
431
|
+
timestamp: cleanupStartTime,
|
|
432
|
+
classesDeleted: cleanedUpCount,
|
|
433
|
+
cssSize: totalCssSize,
|
|
434
|
+
rulesDeleted: totalRulesDeleted
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Get total number of rules across all sheets
|
|
440
|
+
*/
|
|
441
|
+
getTotalRuleCount(registry) {
|
|
442
|
+
return registry.sheets.reduce((total, sheet) => total + sheet.ruleCount - sheet.holes.length, 0);
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Get CSS text from all sheets (for SSR)
|
|
446
|
+
*/
|
|
447
|
+
getCssText(registry) {
|
|
448
|
+
const cssChunks = [];
|
|
449
|
+
for (const sheet of registry.sheets) try {
|
|
450
|
+
const styleElement = sheet.sheet;
|
|
451
|
+
if (styleElement.textContent) cssChunks.push(styleElement.textContent);
|
|
452
|
+
else if (styleElement.sheet) {
|
|
453
|
+
const rules = Array.from(styleElement.sheet.cssRules);
|
|
454
|
+
cssChunks.push(rules.map((rule) => rule.cssText).join("\n"));
|
|
455
|
+
}
|
|
456
|
+
} catch (error) {
|
|
457
|
+
console.warn("Failed to read CSS from sheet:", error);
|
|
458
|
+
}
|
|
459
|
+
return cssChunks.join("\n");
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Get cache performance metrics
|
|
463
|
+
*/
|
|
464
|
+
getMetrics(registry) {
|
|
465
|
+
if (!registry.metrics) return null;
|
|
466
|
+
const unusedRulesCount = Array.from(registry.refCounts.values()).filter((count) => count === 0).length;
|
|
467
|
+
return {
|
|
468
|
+
...registry.metrics,
|
|
469
|
+
unusedHits: unusedRulesCount
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Reset cache performance metrics
|
|
474
|
+
*/
|
|
475
|
+
resetMetrics(registry) {
|
|
476
|
+
if (registry.metrics) registry.metrics = {
|
|
477
|
+
hits: 0,
|
|
478
|
+
misses: 0,
|
|
479
|
+
bulkCleanups: 0,
|
|
480
|
+
totalInsertions: 0,
|
|
481
|
+
totalUnused: 0,
|
|
482
|
+
stylesCleanedUp: 0,
|
|
483
|
+
cleanupHistory: [],
|
|
484
|
+
startTime: Date.now()
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Convert keyframes steps to CSS string
|
|
489
|
+
*/
|
|
490
|
+
stepsToCSS(steps) {
|
|
491
|
+
const rules = [];
|
|
492
|
+
for (const [key, value] of Object.entries(steps)) {
|
|
493
|
+
if (typeof value === "string") {
|
|
494
|
+
rules.push(`${key} { ${value.trim()} }`);
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
const styleMap = value || {};
|
|
498
|
+
const styleNames = Object.keys(styleMap).sort();
|
|
499
|
+
const handlerQueue = [];
|
|
500
|
+
const seenHandlers = /* @__PURE__ */ new Set();
|
|
501
|
+
styleNames.forEach((styleName) => {
|
|
502
|
+
let handlers = STYLE_HANDLER_MAP[styleName];
|
|
503
|
+
if (!handlers) handlers = STYLE_HANDLER_MAP[styleName] = [createStyle(styleName)];
|
|
504
|
+
handlers.forEach((handler) => {
|
|
505
|
+
if (!seenHandlers.has(handler)) {
|
|
506
|
+
seenHandlers.add(handler);
|
|
507
|
+
handlerQueue.push(handler);
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
const declarationPairs = [];
|
|
512
|
+
handlerQueue.forEach((handler) => {
|
|
513
|
+
const result = handler(handler.__lookupStyles.reduce((acc, name) => {
|
|
514
|
+
const v = styleMap[name];
|
|
515
|
+
if (v !== void 0) acc[name] = v;
|
|
516
|
+
return acc;
|
|
517
|
+
}, {}));
|
|
518
|
+
if (!result) return;
|
|
519
|
+
(Array.isArray(result) ? result : [result]).forEach((cssMap) => {
|
|
520
|
+
if (!cssMap || typeof cssMap !== "object") return;
|
|
521
|
+
const { $: _$, ...props } = cssMap;
|
|
522
|
+
Object.entries(props).forEach(([prop, val]) => {
|
|
523
|
+
if (val == null || val === "") return;
|
|
524
|
+
if (Array.isArray(val)) val.forEach((v) => {
|
|
525
|
+
if (v != null && v !== "") declarationPairs.push({
|
|
526
|
+
prop,
|
|
527
|
+
value: String(v)
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
else declarationPairs.push({
|
|
531
|
+
prop,
|
|
532
|
+
value: String(val)
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
const declarations = declarationPairs.map((d) => `${d.prop}: ${d.value}`).join("; ");
|
|
538
|
+
rules.push(`${key} { ${declarations.trim()} }`);
|
|
539
|
+
}
|
|
540
|
+
return rules.join(" ");
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Insert keyframes rule
|
|
544
|
+
*/
|
|
545
|
+
insertKeyframes(registry, steps, name, root) {
|
|
546
|
+
let targetSheet = this.findAvailableSheet(registry, root);
|
|
547
|
+
if (!targetSheet) targetSheet = this.createSheet(registry, root);
|
|
548
|
+
const ruleIndex = this.findAvailableRuleIndex(targetSheet);
|
|
549
|
+
const sheetIndex = registry.sheets.indexOf(targetSheet);
|
|
550
|
+
try {
|
|
551
|
+
const fullRule = `@keyframes ${name} { ${this.stepsToCSS(steps)} }`;
|
|
552
|
+
const styleElement = targetSheet.sheet;
|
|
553
|
+
const styleSheet = styleElement.sheet;
|
|
554
|
+
if (styleSheet && !this.config.forceTextInjection) {
|
|
555
|
+
const safeIndex = Math.min(Math.max(0, ruleIndex), styleSheet.cssRules.length);
|
|
556
|
+
styleSheet.insertRule(fullRule, safeIndex);
|
|
557
|
+
} else styleElement.textContent = (styleElement.textContent || "") + "\n" + fullRule;
|
|
558
|
+
targetSheet.ruleCount++;
|
|
559
|
+
return {
|
|
560
|
+
name,
|
|
561
|
+
ruleIndex,
|
|
562
|
+
sheetIndex,
|
|
563
|
+
cssText: this.config.devMode ? fullRule : void 0
|
|
564
|
+
};
|
|
565
|
+
} catch (error) {
|
|
566
|
+
console.warn("Failed to insert keyframes:", error);
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Delete keyframes rule
|
|
572
|
+
*/
|
|
573
|
+
deleteKeyframes(registry, info) {
|
|
574
|
+
const sheet = registry.sheets[info.sheetIndex];
|
|
575
|
+
if (!sheet) return;
|
|
576
|
+
try {
|
|
577
|
+
const styleSheet = sheet.sheet.sheet;
|
|
578
|
+
if (styleSheet) {
|
|
579
|
+
if (info.ruleIndex >= 0 && info.ruleIndex < styleSheet.cssRules.length) {
|
|
580
|
+
styleSheet.deleteRule(info.ruleIndex);
|
|
581
|
+
sheet.ruleCount = Math.max(0, sheet.ruleCount - 1);
|
|
582
|
+
this.adjustIndicesAfterDeletion(registry, info.sheetIndex, info.ruleIndex, info.ruleIndex, 1, {
|
|
583
|
+
className: "",
|
|
584
|
+
ruleIndex: info.ruleIndex,
|
|
585
|
+
sheetIndex: info.sheetIndex
|
|
586
|
+
}, [info.ruleIndex]);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
} catch (error) {
|
|
590
|
+
console.warn("Failed to delete keyframes:", error);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Schedule async cleanup check (non-stacking)
|
|
595
|
+
*/
|
|
596
|
+
checkCleanupNeeded(registry) {
|
|
597
|
+
if (registry.cleanupCheckTimeout) {
|
|
598
|
+
clearTimeout(registry.cleanupCheckTimeout);
|
|
599
|
+
registry.cleanupCheckTimeout = null;
|
|
600
|
+
}
|
|
601
|
+
registry.cleanupCheckTimeout = setTimeout(() => {
|
|
602
|
+
this.performCleanupCheck(registry);
|
|
603
|
+
registry.cleanupCheckTimeout = null;
|
|
604
|
+
}, 0);
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Perform the actual cleanup check (called asynchronously)
|
|
608
|
+
*/
|
|
609
|
+
performCleanupCheck(registry) {
|
|
610
|
+
if (Array.from(registry.refCounts.values()).filter((count) => count === 0).length >= (this.config.unusedStylesThreshold || 500)) this.scheduleBulkCleanup(registry);
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Clean up resources for a root
|
|
614
|
+
*/
|
|
615
|
+
cleanup(root) {
|
|
616
|
+
const registry = this.rootRegistries.get(root);
|
|
617
|
+
if (!registry) return;
|
|
618
|
+
if (registry.bulkCleanupTimeout) {
|
|
619
|
+
if (this.config.idleCleanup && typeof cancelIdleCallback !== "undefined") cancelIdleCallback(registry.bulkCleanupTimeout);
|
|
620
|
+
else clearTimeout(registry.bulkCleanupTimeout);
|
|
621
|
+
registry.bulkCleanupTimeout = null;
|
|
622
|
+
}
|
|
623
|
+
if (registry.cleanupCheckTimeout) {
|
|
624
|
+
clearTimeout(registry.cleanupCheckTimeout);
|
|
625
|
+
registry.cleanupCheckTimeout = null;
|
|
626
|
+
}
|
|
627
|
+
for (const sheet of registry.sheets) try {
|
|
628
|
+
const styleElement = sheet.sheet;
|
|
629
|
+
if (styleElement.parentNode) styleElement.parentNode.removeChild(styleElement);
|
|
630
|
+
} catch (error) {
|
|
631
|
+
console.warn("Failed to cleanup sheet:", error);
|
|
632
|
+
}
|
|
633
|
+
this.rootRegistries.delete(root);
|
|
634
|
+
const rawStyleElement = this.rawStyleElements.get(root);
|
|
635
|
+
if (rawStyleElement?.parentNode) rawStyleElement.parentNode.removeChild(rawStyleElement);
|
|
636
|
+
this.rawStyleElements.delete(root);
|
|
637
|
+
this.rawCSSBlocks.delete(root);
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Get or create a dedicated style element for raw CSS
|
|
641
|
+
* Raw CSS is kept separate from tasty-managed sheets to avoid index conflicts
|
|
642
|
+
*/
|
|
643
|
+
getOrCreateRawStyleElement(root) {
|
|
644
|
+
let styleElement = this.rawStyleElements.get(root);
|
|
645
|
+
if (!styleElement) {
|
|
646
|
+
styleElement = root.createElement?.("style") || document.createElement("style");
|
|
647
|
+
if (this.config.nonce) styleElement.nonce = this.config.nonce;
|
|
648
|
+
styleElement.setAttribute("data-tasty-raw", "");
|
|
649
|
+
if ("head" in root && root.head) root.head.appendChild(styleElement);
|
|
650
|
+
else if ("appendChild" in root) root.appendChild(styleElement);
|
|
651
|
+
else document.head.appendChild(styleElement);
|
|
652
|
+
this.rawStyleElements.set(root, styleElement);
|
|
653
|
+
this.rawCSSBlocks.set(root, /* @__PURE__ */ new Map());
|
|
654
|
+
}
|
|
655
|
+
return styleElement;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Inject raw CSS text directly without parsing
|
|
659
|
+
* Returns a dispose function to remove the injected CSS
|
|
660
|
+
*/
|
|
661
|
+
injectRawCSS(css, root) {
|
|
662
|
+
if (!css.trim()) return { dispose: () => {} };
|
|
663
|
+
const styleElement = this.getOrCreateRawStyleElement(root);
|
|
664
|
+
const blocksMap = this.rawCSSBlocks.get(root);
|
|
665
|
+
const id = `raw_${this.rawCSSCounter++}`;
|
|
666
|
+
const currentContent = styleElement.textContent || "";
|
|
667
|
+
const startOffset = currentContent.length;
|
|
668
|
+
const cssWithNewline = (currentContent ? "\n" : "") + css;
|
|
669
|
+
const endOffset = startOffset + cssWithNewline.length;
|
|
670
|
+
styleElement.textContent = currentContent + cssWithNewline;
|
|
671
|
+
const info = {
|
|
672
|
+
id,
|
|
673
|
+
css,
|
|
674
|
+
startOffset,
|
|
675
|
+
endOffset
|
|
676
|
+
};
|
|
677
|
+
blocksMap.set(id, info);
|
|
678
|
+
return { dispose: () => {
|
|
679
|
+
this.disposeRawCSS(id, root);
|
|
680
|
+
} };
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Remove a raw CSS block by ID
|
|
684
|
+
*/
|
|
685
|
+
disposeRawCSS(id, root) {
|
|
686
|
+
const styleElement = this.rawStyleElements.get(root);
|
|
687
|
+
const blocksMap = this.rawCSSBlocks.get(root);
|
|
688
|
+
if (!styleElement || !blocksMap) return;
|
|
689
|
+
if (!blocksMap.get(id)) return;
|
|
690
|
+
blocksMap.delete(id);
|
|
691
|
+
const remainingBlocks = Array.from(blocksMap.values());
|
|
692
|
+
if (remainingBlocks.length === 0) styleElement.textContent = "";
|
|
693
|
+
else {
|
|
694
|
+
remainingBlocks.sort((a, b) => a.startOffset - b.startOffset);
|
|
695
|
+
styleElement.textContent = remainingBlocks.map((block) => block.css).join("\n");
|
|
696
|
+
let offset = 0;
|
|
697
|
+
for (const block of remainingBlocks) {
|
|
698
|
+
block.startOffset = offset;
|
|
699
|
+
block.endOffset = offset + block.css.length;
|
|
700
|
+
offset = block.endOffset + 1;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Get the raw CSS content for SSR
|
|
706
|
+
*/
|
|
707
|
+
getRawCSSText(root) {
|
|
708
|
+
return this.rawStyleElements.get(root)?.textContent || "";
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
//#endregion
|
|
713
|
+
export { SheetManager };
|
|
714
|
+
//# sourceMappingURL=sheet-manager.mjs.map
|