@jasonshimmy/custom-elements-runtime 3.3.0 → 3.5.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.
Files changed (106) hide show
  1. package/README.md +28 -7
  2. package/dist/css-utils-Bn-dO44e.js +203 -0
  3. package/dist/{css-utils-CC43BbEy.js.map → css-utils-Bn-dO44e.js.map} +1 -1
  4. package/dist/{css-utils-CC43BbEy.js → css-utils-CFeP8SK1.cjs} +5 -71
  5. package/dist/{css-utils-mgjmH8qX.cjs.map → css-utils-CFeP8SK1.cjs.map} +1 -1
  6. package/dist/custom-elements-runtime.cjs.js +3 -4
  7. package/dist/custom-elements-runtime.cjs.js.map +1 -1
  8. package/dist/custom-elements-runtime.colors.cjs.js +1 -2
  9. package/dist/custom-elements-runtime.colors.cjs.js.map +1 -1
  10. package/dist/custom-elements-runtime.colors.es.js +277 -277
  11. package/dist/custom-elements-runtime.colors.es.js.map +1 -1
  12. package/dist/custom-elements-runtime.directive-enhancements.cjs.js +1 -2
  13. package/dist/custom-elements-runtime.directive-enhancements.cjs.js.map +1 -1
  14. package/dist/custom-elements-runtime.directive-enhancements.es.js +106 -122
  15. package/dist/custom-elements-runtime.directive-enhancements.es.js.map +1 -1
  16. package/dist/custom-elements-runtime.directives.cjs.js +1 -2
  17. package/dist/custom-elements-runtime.directives.cjs.js.map +1 -1
  18. package/dist/custom-elements-runtime.directives.es.js +60 -65
  19. package/dist/custom-elements-runtime.directives.es.js.map +1 -1
  20. package/dist/custom-elements-runtime.dom-jit-css.cjs.js +1 -7
  21. package/dist/custom-elements-runtime.dom-jit-css.cjs.js.map +1 -1
  22. package/dist/custom-elements-runtime.dom-jit-css.es.js +103 -115
  23. package/dist/custom-elements-runtime.dom-jit-css.es.js.map +1 -1
  24. package/dist/custom-elements-runtime.es.js +206 -253
  25. package/dist/custom-elements-runtime.es.js.map +1 -1
  26. package/dist/custom-elements-runtime.event-bus.cjs.js +1 -2
  27. package/dist/custom-elements-runtime.event-bus.cjs.js.map +1 -1
  28. package/dist/custom-elements-runtime.event-bus.es.js +102 -108
  29. package/dist/custom-elements-runtime.event-bus.es.js.map +1 -1
  30. package/dist/custom-elements-runtime.jit-css.cjs.js +1 -2
  31. package/dist/custom-elements-runtime.jit-css.cjs.js.map +1 -1
  32. package/dist/custom-elements-runtime.jit-css.es.js +14 -32
  33. package/dist/custom-elements-runtime.jit-css.es.js.map +1 -1
  34. package/dist/custom-elements-runtime.router.cjs.js +20 -21
  35. package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
  36. package/dist/custom-elements-runtime.router.es.js +866 -926
  37. package/dist/custom-elements-runtime.router.es.js.map +1 -1
  38. package/dist/custom-elements-runtime.ssr-middleware.cjs.js +3 -4
  39. package/dist/custom-elements-runtime.ssr-middleware.cjs.js.map +1 -1
  40. package/dist/custom-elements-runtime.ssr-middleware.es.js +67 -73
  41. package/dist/custom-elements-runtime.ssr-middleware.es.js.map +1 -1
  42. package/dist/custom-elements-runtime.ssr.cjs.js +1 -1
  43. package/dist/custom-elements-runtime.ssr.es.js +3 -13
  44. package/dist/custom-elements-runtime.store.cjs.js +1 -2
  45. package/dist/custom-elements-runtime.store.cjs.js.map +1 -1
  46. package/dist/custom-elements-runtime.store.es.js +32 -33
  47. package/dist/custom-elements-runtime.store.es.js.map +1 -1
  48. package/dist/custom-elements-runtime.transitions.cjs.js +1 -2
  49. package/dist/custom-elements-runtime.transitions.cjs.js.map +1 -1
  50. package/dist/custom-elements-runtime.transitions.es.js +200 -210
  51. package/dist/custom-elements-runtime.transitions.es.js.map +1 -1
  52. package/dist/custom-elements-runtime.vite-plugin.cjs.js +4 -2
  53. package/dist/custom-elements-runtime.vite-plugin.cjs.js.map +1 -1
  54. package/dist/custom-elements-runtime.vite-plugin.es.js +155 -78
  55. package/dist/custom-elements-runtime.vite-plugin.es.js.map +1 -1
  56. package/dist/helpers-DcEpRwq5.cjs +5 -0
  57. package/dist/helpers-DcEpRwq5.cjs.map +1 -0
  58. package/dist/helpers-tJgb4Qve.js +693 -0
  59. package/dist/helpers-tJgb4Qve.js.map +1 -0
  60. package/dist/hooks-CEUnvtsA.js +407 -0
  61. package/dist/hooks-CEUnvtsA.js.map +1 -0
  62. package/dist/hooks-CNfugc95.cjs +2 -0
  63. package/dist/hooks-CNfugc95.cjs.map +1 -0
  64. package/dist/logger-DIJ0UH3R.js +36 -0
  65. package/dist/{logger-L25axmB-.js.map → logger-DIJ0UH3R.js.map} +1 -1
  66. package/dist/logger-Dkht1dCX.cjs +2 -0
  67. package/dist/{logger-BYIN7ysT.cjs.map → logger-Dkht1dCX.cjs.map} +1 -1
  68. package/dist/namespace-helpers-CIUkG8Mn.js +56 -0
  69. package/dist/{namespace-helpers-BucDdgz_.js.map → namespace-helpers-CIUkG8Mn.js.map} +1 -1
  70. package/dist/namespace-helpers-yYIb7INq.cjs +2 -0
  71. package/dist/{namespace-helpers-Bf7rm9JV.cjs.map → namespace-helpers-yYIb7INq.cjs.map} +1 -1
  72. package/dist/runtime/tag-utils.d.ts +11 -0
  73. package/dist/ssr-BpYy9XlW.js +170 -0
  74. package/dist/{ssr-B3lxl1vr.js.map → ssr-BpYy9XlW.js.map} +1 -1
  75. package/dist/ssr-CFabTOyi.cjs +4 -0
  76. package/dist/{ssr-DtD9e5iA.cjs.map → ssr-CFabTOyi.cjs.map} +1 -1
  77. package/dist/ssr.d.ts +33 -0
  78. package/dist/style-A8l3aQ52.cjs +55 -0
  79. package/dist/{style-Bjn8zDiZ.cjs.map → style-A8l3aQ52.cjs.map} +1 -1
  80. package/dist/style-DSSoCbC9.js +1877 -0
  81. package/dist/{style-DuDoj_xK.js.map → style-DSSoCbC9.js.map} +1 -1
  82. package/dist/tag-utils-CoSXTr1F.js +10 -0
  83. package/dist/tag-utils-CoSXTr1F.js.map +1 -0
  84. package/dist/tag-utils-XJ3dkcPQ.cjs +2 -0
  85. package/dist/tag-utils-XJ3dkcPQ.cjs.map +1 -0
  86. package/dist/template-compiler-B4B_jAPN.cjs +19 -0
  87. package/dist/{template-compiler-BB4JJdqk.cjs.map → template-compiler-B4B_jAPN.cjs.map} +1 -1
  88. package/dist/template-compiler-C3h8_vbE.js +3044 -0
  89. package/dist/{template-compiler-Cs5axmn4.js.map → template-compiler-C3h8_vbE.js.map} +1 -1
  90. package/dist/vite-plugin.d.ts +96 -2
  91. package/package.json +8 -8
  92. package/dist/css-utils-mgjmH8qX.cjs +0 -577
  93. package/dist/hooks-_3xP4G2N.js +0 -1189
  94. package/dist/hooks-_3xP4G2N.js.map +0 -1
  95. package/dist/hooks-fYQgZk2g.cjs +0 -7
  96. package/dist/hooks-fYQgZk2g.cjs.map +0 -1
  97. package/dist/logger-BYIN7ysT.cjs +0 -3
  98. package/dist/logger-L25axmB-.js +0 -41
  99. package/dist/namespace-helpers-Bf7rm9JV.cjs +0 -3
  100. package/dist/namespace-helpers-BucDdgz_.js +0 -61
  101. package/dist/ssr-B3lxl1vr.js +0 -165
  102. package/dist/ssr-DtD9e5iA.cjs +0 -5
  103. package/dist/style-Bjn8zDiZ.cjs +0 -56
  104. package/dist/style-DuDoj_xK.js +0 -1972
  105. package/dist/template-compiler-BB4JJdqk.cjs +0 -23
  106. package/dist/template-compiler-Cs5axmn4.js +0 -3236
@@ -1,76 +1,71 @@
1
- var u = "", i = 0, f = [];
2
- function y() {
3
- u = "", i = 0, f.length = 0;
1
+ //#region src/lib/directives.ts
2
+ var e = "", t = 0, n = [];
3
+ function r() {
4
+ e = "", t = 0, n.length = 0;
4
5
  }
5
- function $() {
6
- return i++;
7
- }
8
- function s(n) {
9
- const e = i++;
10
- return n !== void 0 ? n : u ? `${u}.${e}` : `when-block-${e}`;
6
+ function i() {
7
+ return t++;
11
8
  }
12
9
  function a(n) {
13
- f.push([u, i]), u = n, i = 0;
10
+ let r = t++;
11
+ return n === void 0 ? e ? `${e}.${r}` : `when-block-${r}` : n;
12
+ }
13
+ function o(r) {
14
+ n.push([e, t]), e = r, t = 0;
14
15
  }
15
- function p() {
16
- const n = f[f.length - 1];
17
- n && (f.length--, [u, i] = n);
16
+ function s() {
17
+ let r = n[n.length - 1];
18
+ r && (n.length--, [e, t] = r);
18
19
  }
19
- function d(n, e, t) {
20
- const r = s(t);
21
- if (typeof e != "function") return c(n ? e : [], r);
22
- if (!n) return c([], r);
23
- a(r);
24
- const o = e();
25
- return p(), c(o, r);
20
+ function c(e, t, n) {
21
+ let r = a(n);
22
+ if (typeof t != "function") return d(e ? t : [], r);
23
+ if (!e) return d([], r);
24
+ o(r);
25
+ let i = t();
26
+ return s(), d(i, r);
26
27
  }
27
- function v(n, e) {
28
- return n.map((t, r) => {
29
- const o = typeof t == "object" ? t?.key ?? t?.id ?? `idx-${r}` : String(t);
30
- return c(e(t, r), `each-${o}`);
31
- });
28
+ function l(e, t) {
29
+ return e.map((e, n) => {
30
+ let r = typeof e == "object" ? e?.key ?? e?.id ?? `idx-${n}` : String(e);
31
+ return d(t(e, n), `each-${r}`);
32
+ });
32
33
  }
33
- function x() {
34
- const n = [];
35
- return {
36
- when(e, t) {
37
- return n.push([e, t]), this;
38
- },
39
- otherwise(e) {
40
- return n.push([!0, e]), this;
41
- },
42
- done() {
43
- const e = `match-${s()}`;
44
- for (let t = 0; t < n.length; t++) {
45
- const [r, o] = n[t];
46
- if (r) {
47
- const h = `${e}-branch-${t}`;
48
- if (typeof o == "function") {
49
- a(h);
50
- const l = o();
51
- return p(), [c(l, h)];
52
- }
53
- return [c(o, h)];
54
- }
55
- }
56
- return [c([], `${e}-empty`)];
57
- }
58
- };
34
+ function u() {
35
+ let e = [];
36
+ return {
37
+ when(t, n) {
38
+ return e.push([t, n]), this;
39
+ },
40
+ otherwise(t) {
41
+ return e.push([!0, t]), this;
42
+ },
43
+ done() {
44
+ let t = `match-${a()}`;
45
+ for (let n = 0; n < e.length; n++) {
46
+ let [r, i] = e[n];
47
+ if (r) {
48
+ let e = `${t}-branch-${n}`;
49
+ if (typeof i == "function") {
50
+ o(e);
51
+ let t = i();
52
+ return s(), [d(t, e)];
53
+ }
54
+ return [d(i, e)];
55
+ }
56
+ }
57
+ return [d([], `${t}-empty`)];
58
+ }
59
+ };
59
60
  }
60
- function c(n, e) {
61
- return {
62
- tag: "#anchor",
63
- key: e,
64
- children: n ? Array.isArray(n) ? n.filter((t) => t != null) : [n].filter((t) => t != null) : []
65
- };
61
+ function d(e, t) {
62
+ return {
63
+ tag: "#anchor",
64
+ key: t,
65
+ children: e ? Array.isArray(e) ? e.filter((e) => e != null) : [e].filter((e) => e != null) : []
66
+ };
66
67
  }
67
- export {
68
- c as anchorBlock,
69
- v as each,
70
- x as match,
71
- $ as nextDirectiveIndex,
72
- y as resetWhenCounter,
73
- d as when
74
- };
68
+ //#endregion
69
+ export { d as anchorBlock, l as each, u as match, i as nextDirectiveIndex, r as resetWhenCounter, c as when };
75
70
 
76
71
  //# sourceMappingURL=custom-elements-runtime.directives.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-elements-runtime.directives.es.js","names":[],"sources":["../src/lib/directives.ts"],"sourcesContent":["import type { VNode } from './runtime/types';\n\n// ── Per-render directive scope tracking ─────────────────────────────────────\n//\n// A FLAT counter (index++) breaks when a when() factory itself contains more\n// when() calls: those inner calls consume counter slots, causing SUBSEQUENT\n// SIBLING when() calls to get a different index depending on whether the factory\n// ran. For example:\n//\n// when(A, () => { when(B); when(C); }) // ← factory may or may not run\n// when(D) // ← index shifts when factory runs\n//\n// The fix: each when() call claims its own slot (stable regardless of whether\n// the factory runs), then ENTERS a new child scope for the factory. Inner\n// when() calls consume indices in that child scope, never bleeding into the\n// sibling counter of the outer scope.\n//\n// Key format: root sibling 0 → \"when-block-0\"\n// child of \"when-block-0\" at pos 1 → \"when-block-0.1\"\n// grandchild → \"when-block-0.1.0\" etc.\n\n/** Current scope's parent prefix (empty string = root scope). */\nlet _scopeParent = '';\n/** Next sibling index inside the current scope. */\nlet _scopeIndex = 0;\n/** Stack of [parentPrefix, siblingIndex] for nested scopes. */\nconst _scopeStack: Array<readonly [string, number]> = [];\n\n/**\n * Reset all scope state at the start of each component render pass.\n * Called automatically by the component renderer — not needed in user code.\n * @internal\n */\nexport function resetWhenCounter(): void {\n _scopeParent = '';\n _scopeIndex = 0;\n _scopeStack.length = 0;\n}\n\n/**\n * Claim the next directive call index within the current scope.\n * Used by directive-enhancements.ts for non-when() directives (switchOnLength,\n * switchOnPromise, etc.) that need a stable unique number per call site.\n * @internal\n */\nexport function nextDirectiveIndex(): number {\n return _scopeIndex++;\n}\n\n/** Claim the next slot in the current scope and return its anchor key. */\nfunction claimKey(explicitKey?: string): string {\n const idx = _scopeIndex++;\n if (explicitKey !== undefined) return explicitKey;\n return _scopeParent ? `${_scopeParent}.${idx}` : `when-block-${idx}`;\n}\n\n/** Push a new child scope keyed under `anchorKey`. */\nfunction enterScope(anchorKey: string): void {\n _scopeStack.push([_scopeParent, _scopeIndex] as const);\n _scopeParent = anchorKey;\n _scopeIndex = 0;\n}\n\n/** Pop back to the parent scope. */\nfunction exitScope(): void {\n const top = _scopeStack[_scopeStack.length - 1];\n if (top) {\n _scopeStack.length--;\n [_scopeParent, _scopeIndex] = top;\n }\n}\n\n/* --- When --- */\nexport function when(\n cond: boolean,\n children: VNode | VNode[],\n key?: string,\n): VNode;\nexport function when(\n cond: boolean,\n factory: () => VNode | VNode[],\n key?: string,\n): VNode;\nexport function when(\n cond: boolean,\n childrenOrFactory: VNode | VNode[] | (() => VNode | VNode[]),\n key?: string,\n): VNode {\n // Claim this call's position BEFORE potentially entering a child scope.\n // This guarantees sibling when() calls always get the same index regardless\n // of whether a factory executes and how many when() calls it contains.\n const anchorKey = claimKey(key);\n\n if (typeof childrenOrFactory !== 'function') {\n return anchorBlock(cond ? childrenOrFactory : [], anchorKey);\n }\n\n if (!cond) {\n return anchorBlock([], anchorKey);\n }\n\n // Run the factory in a child scope so its inner when() calls don't\n // affect the sibling counter of the outer scope.\n enterScope(anchorKey);\n const children = childrenOrFactory();\n exitScope();\n return anchorBlock(children, anchorKey);\n}\n\n/* --- Each --- */\nexport function each<\n T extends string | number | boolean | { id?: string | number; key?: string },\n>(list: T[], render: (item: T, index: number) => VNode | VNode[]): VNode[] {\n return list.map((item, i) => {\n // For primitives, use value as key; for objects, prefer key/id\n const itemKey =\n typeof item === 'object'\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `idx-${i}`)\n : String(item);\n return anchorBlock(render(item, i), `each-${itemKey}`);\n });\n}\n\n/* --- match --- */\ntype Branch = [\n condition: unknown,\n content: VNode | VNode[] | (() => VNode | VNode[]),\n];\n\nexport function match() {\n const branches: Branch[] = [];\n return {\n when(cond: unknown, content: VNode | VNode[] | (() => VNode | VNode[])) {\n branches.push([cond, content]);\n return this;\n },\n otherwise(content: VNode | VNode[]) {\n branches.push([true, content]);\n return this;\n },\n done() {\n const matchKey = `match-${claimKey()}`;\n for (let idx = 0; idx < branches.length; idx++) {\n const [cond, content] = branches[idx];\n if (cond) {\n const branchKey = `${matchKey}-branch-${idx}`;\n if (typeof content === 'function') {\n enterScope(branchKey);\n const payload = (content as () => VNode | VNode[])();\n exitScope();\n return [anchorBlock(payload, branchKey)];\n }\n return [anchorBlock(content, branchKey)];\n }\n }\n return [anchorBlock([], `${matchKey}-empty`)];\n },\n };\n}\n\n/**\n * Create a stable anchor block with consistent boundaries.\n * Always has start/end boundaries.\n */\nexport function anchorBlock(\n children: VNode | VNode[] | null | undefined,\n anchorKey: string,\n): VNode {\n // Normalize children to array, filtering out only null/undefined values.\n // Preserve meaningful falsy values such as 0, false, and empty string.\n const childArray = !children\n ? []\n : Array.isArray(children)\n ? children.filter((c) => c !== null && c !== undefined)\n : [children].filter((c) => c !== null && c !== undefined);\n\n return {\n tag: '#anchor',\n key: anchorKey,\n children: childArray,\n };\n}\n"],"mappings":"AAsBA,IAAI,IAAe,IAEf,IAAc,GAEZ,IAAgD,CAAA;AAOtD,SAAgB,IAAyB;AACvC,EAAA,IAAe,IACf,IAAc,GACd,EAAY,SAAS;;AASvB,SAAgB,IAA6B;AAC3C,SAAO;;AAIT,SAAS,EAAS,GAA8B;AAC9C,QAAM,IAAM;AACZ,SAAI,MAAgB,SAAkB,IAC/B,IAAe,GAAG,CAAA,IAAgB,CAAA,KAAQ,cAAc,CAAA;;AAIjE,SAAS,EAAW,GAAyB;AAC3C,EAAA,EAAY,KAAK,CAAC,GAAc,CAAA,CAAY,GAC5C,IAAe,GACf,IAAc;;AAIhB,SAAS,IAAkB;AACzB,QAAM,IAAM,EAAY,EAAY,SAAS,CAAA;AAC7C,EAAI,MACF,EAAY,UACZ,CAAC,GAAc,CAAA,IAAe;;AAelC,SAAgB,EACd,GACA,GACA,GACO;AAIP,QAAM,IAAY,EAAS,CAAA;AAE3B,MAAI,OAAO,KAAsB,WAC/B,QAAO,EAAY,IAAO,IAAoB,CAAA,GAAI,CAAA;AAGpD,MAAI,CAAC,EACH,QAAO,EAAY,CAAA,GAAI,CAAA;AAKzB,EAAA,EAAW,CAAA;AACX,QAAM,IAAW,EAAA;AACjB,SAAA,EAAA,GACO,EAAY,GAAU,CAAA;;AAI/B,SAAgB,EAEd,GAAW,GAA8D;AACzE,SAAO,EAAK,IAAA,CAAK,GAAM,MAAM;AAE3B,UAAM,IACJ,OAAO,KAAS,WACV,GAAkC,OACnC,GAAkC,MACnC,OAAO,CAAA,KACP,OAAO,CAAA;AACb,WAAO,EAAY,EAAO,GAAM,CAAA,GAAI,QAAQ,CAAA,EAAA;AAAA;;AAUhD,SAAgB,IAAQ;AACtB,QAAM,IAAqB,CAAA;AAC3B,SAAO;AAAA,IACL,KAAK,GAAe,GAAoD;AACtE,aAAA,EAAS,KAAK,CAAC,GAAM,CAAA,CAAQ,GACtB;AAAA;IAET,UAAU,GAA0B;AAClC,aAAA,EAAS,KAAK,CAAC,IAAM,CAAA,CAAQ,GACtB;AAAA;IAET,OAAO;AACL,YAAM,IAAW,SAAS,EAAA,CAAU;AACpC,eAAS,IAAM,GAAG,IAAM,EAAS,QAAQ,KAAO;AAC9C,cAAM,CAAC,GAAM,CAAA,IAAW,EAAS,CAAA;AACjC,YAAI,GAAM;AACR,gBAAM,IAAY,GAAG,CAAA,WAAmB,CAAA;AACxC,cAAI,OAAO,KAAY,YAAY;AACjC,YAAA,EAAW,CAAA;AACX,kBAAM,IAAW,EAAA;AACjB,mBAAA,EAAA,GACO,CAAC,EAAY,GAAS,CAAA,CAAU;AAAA;AAEzC,iBAAO,CAAC,EAAY,GAAS,CAAA,CAAU;AAAA;;AAG3C,aAAO,CAAC,EAAY,CAAA,GAAI,GAAG,CAAA,QAAS,CAAQ;AAAA;;;AASlD,SAAgB,EACd,GACA,GACO;AASP,SAAO;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,UATkB,IAEhB,MAAM,QAAQ,CAAA,IACZ,EAAS,OAAA,CAAQ,MAAM,KAAM,IAAc,IAC3C,CAAC,CAAA,EAAU,OAAA,CAAQ,MAAM,KAAM,IAAc,IAH/C,CAAA;AAAA"}
1
+ {"version":3,"file":"custom-elements-runtime.directives.es.js","names":[],"sources":["../src/lib/directives.ts"],"sourcesContent":["import type { VNode } from './runtime/types';\n\n// ── Per-render directive scope tracking ─────────────────────────────────────\n//\n// A FLAT counter (index++) breaks when a when() factory itself contains more\n// when() calls: those inner calls consume counter slots, causing SUBSEQUENT\n// SIBLING when() calls to get a different index depending on whether the factory\n// ran. For example:\n//\n// when(A, () => { when(B); when(C); }) // ← factory may or may not run\n// when(D) // ← index shifts when factory runs\n//\n// The fix: each when() call claims its own slot (stable regardless of whether\n// the factory runs), then ENTERS a new child scope for the factory. Inner\n// when() calls consume indices in that child scope, never bleeding into the\n// sibling counter of the outer scope.\n//\n// Key format: root sibling 0 → \"when-block-0\"\n// child of \"when-block-0\" at pos 1 → \"when-block-0.1\"\n// grandchild → \"when-block-0.1.0\" etc.\n\n/** Current scope's parent prefix (empty string = root scope). */\nlet _scopeParent = '';\n/** Next sibling index inside the current scope. */\nlet _scopeIndex = 0;\n/** Stack of [parentPrefix, siblingIndex] for nested scopes. */\nconst _scopeStack: Array<readonly [string, number]> = [];\n\n/**\n * Reset all scope state at the start of each component render pass.\n * Called automatically by the component renderer — not needed in user code.\n * @internal\n */\nexport function resetWhenCounter(): void {\n _scopeParent = '';\n _scopeIndex = 0;\n _scopeStack.length = 0;\n}\n\n/**\n * Claim the next directive call index within the current scope.\n * Used by directive-enhancements.ts for non-when() directives (switchOnLength,\n * switchOnPromise, etc.) that need a stable unique number per call site.\n * @internal\n */\nexport function nextDirectiveIndex(): number {\n return _scopeIndex++;\n}\n\n/** Claim the next slot in the current scope and return its anchor key. */\nfunction claimKey(explicitKey?: string): string {\n const idx = _scopeIndex++;\n if (explicitKey !== undefined) return explicitKey;\n return _scopeParent ? `${_scopeParent}.${idx}` : `when-block-${idx}`;\n}\n\n/** Push a new child scope keyed under `anchorKey`. */\nfunction enterScope(anchorKey: string): void {\n _scopeStack.push([_scopeParent, _scopeIndex] as const);\n _scopeParent = anchorKey;\n _scopeIndex = 0;\n}\n\n/** Pop back to the parent scope. */\nfunction exitScope(): void {\n const top = _scopeStack[_scopeStack.length - 1];\n if (top) {\n _scopeStack.length--;\n [_scopeParent, _scopeIndex] = top;\n }\n}\n\n/* --- When --- */\nexport function when(\n cond: boolean,\n children: VNode | VNode[],\n key?: string,\n): VNode;\nexport function when(\n cond: boolean,\n factory: () => VNode | VNode[],\n key?: string,\n): VNode;\nexport function when(\n cond: boolean,\n childrenOrFactory: VNode | VNode[] | (() => VNode | VNode[]),\n key?: string,\n): VNode {\n // Claim this call's position BEFORE potentially entering a child scope.\n // This guarantees sibling when() calls always get the same index regardless\n // of whether a factory executes and how many when() calls it contains.\n const anchorKey = claimKey(key);\n\n if (typeof childrenOrFactory !== 'function') {\n return anchorBlock(cond ? childrenOrFactory : [], anchorKey);\n }\n\n if (!cond) {\n return anchorBlock([], anchorKey);\n }\n\n // Run the factory in a child scope so its inner when() calls don't\n // affect the sibling counter of the outer scope.\n enterScope(anchorKey);\n const children = childrenOrFactory();\n exitScope();\n return anchorBlock(children, anchorKey);\n}\n\n/* --- Each --- */\nexport function each<\n T extends string | number | boolean | { id?: string | number; key?: string },\n>(list: T[], render: (item: T, index: number) => VNode | VNode[]): VNode[] {\n return list.map((item, i) => {\n // For primitives, use value as key; for objects, prefer key/id\n const itemKey =\n typeof item === 'object'\n ? ((item as Record<string, unknown>)?.key ??\n (item as Record<string, unknown>)?.id ??\n `idx-${i}`)\n : String(item);\n return anchorBlock(render(item, i), `each-${itemKey}`);\n });\n}\n\n/* --- match --- */\ntype Branch = [\n condition: unknown,\n content: VNode | VNode[] | (() => VNode | VNode[]),\n];\n\nexport function match() {\n const branches: Branch[] = [];\n return {\n when(cond: unknown, content: VNode | VNode[] | (() => VNode | VNode[])) {\n branches.push([cond, content]);\n return this;\n },\n otherwise(content: VNode | VNode[]) {\n branches.push([true, content]);\n return this;\n },\n done() {\n const matchKey = `match-${claimKey()}`;\n for (let idx = 0; idx < branches.length; idx++) {\n const [cond, content] = branches[idx];\n if (cond) {\n const branchKey = `${matchKey}-branch-${idx}`;\n if (typeof content === 'function') {\n enterScope(branchKey);\n const payload = (content as () => VNode | VNode[])();\n exitScope();\n return [anchorBlock(payload, branchKey)];\n }\n return [anchorBlock(content, branchKey)];\n }\n }\n return [anchorBlock([], `${matchKey}-empty`)];\n },\n };\n}\n\n/**\n * Create a stable anchor block with consistent boundaries.\n * Always has start/end boundaries.\n */\nexport function anchorBlock(\n children: VNode | VNode[] | null | undefined,\n anchorKey: string,\n): VNode {\n // Normalize children to array, filtering out only null/undefined values.\n // Preserve meaningful falsy values such as 0, false, and empty string.\n const childArray = !children\n ? []\n : Array.isArray(children)\n ? children.filter((c) => c !== null && c !== undefined)\n : [children].filter((c) => c !== null && c !== undefined);\n\n return {\n tag: '#anchor',\n key: anchorKey,\n children: childArray,\n };\n}\n"],"mappings":";AAsBA,IAAI,IAAe,IAEf,IAAc,GAEZ,IAAgD,EAAE;AAOxD,SAAgB,IAAyB;AAGvC,CAFA,IAAe,IACf,IAAc,GACd,EAAY,SAAS;;AASvB,SAAgB,IAA6B;AAC3C,QAAO;;AAIT,SAAS,EAAS,GAA8B;CAC9C,IAAM,IAAM;AAEZ,QADI,MAAgB,KAAA,IACb,IAAe,GAAG,EAAa,GAAG,MAAQ,cAAc,MADzB;;AAKxC,SAAS,EAAW,GAAyB;AAG3C,CAFA,EAAY,KAAK,CAAC,GAAc,EAAY,CAAU,EACtD,IAAe,GACf,IAAc;;AAIhB,SAAS,IAAkB;CACzB,IAAM,IAAM,EAAY,EAAY,SAAS;AAC7C,CAAI,MACF,EAAY,UACZ,CAAC,GAAc,KAAe;;AAelC,SAAgB,EACd,GACA,GACA,GACO;CAIP,IAAM,IAAY,EAAS,EAAI;AAE/B,KAAI,OAAO,KAAsB,WAC/B,QAAO,EAAY,IAAO,IAAoB,EAAE,EAAE,EAAU;AAG9D,KAAI,CAAC,EACH,QAAO,EAAY,EAAE,EAAE,EAAU;AAKnC,GAAW,EAAU;CACrB,IAAM,IAAW,GAAmB;AAEpC,QADA,GAAW,EACJ,EAAY,GAAU,EAAU;;AAIzC,SAAgB,EAEd,GAAW,GAA8D;AACzE,QAAO,EAAK,KAAK,GAAM,MAAM;EAE3B,IAAM,IACJ,OAAO,KAAS,WACV,GAAkC,OACnC,GAAkC,MACnC,OAAO,MACP,OAAO,EAAK;AAClB,SAAO,EAAY,EAAO,GAAM,EAAE,EAAE,QAAQ,IAAU;GACtD;;AASJ,SAAgB,IAAQ;CACtB,IAAM,IAAqB,EAAE;AAC7B,QAAO;EACL,KAAK,GAAe,GAAoD;AAEtE,UADA,EAAS,KAAK,CAAC,GAAM,EAAQ,CAAC,EACvB;;EAET,UAAU,GAA0B;AAElC,UADA,EAAS,KAAK,CAAC,IAAM,EAAQ,CAAC,EACvB;;EAET,OAAO;GACL,IAAM,IAAW,SAAS,GAAU;AACpC,QAAK,IAAI,IAAM,GAAG,IAAM,EAAS,QAAQ,KAAO;IAC9C,IAAM,CAAC,GAAM,KAAW,EAAS;AACjC,QAAI,GAAM;KACR,IAAM,IAAY,GAAG,EAAS,UAAU;AACxC,SAAI,OAAO,KAAY,YAAY;AACjC,QAAW,EAAU;MACrB,IAAM,IAAW,GAAmC;AAEpD,aADA,GAAW,EACJ,CAAC,EAAY,GAAS,EAAU,CAAC;;AAE1C,YAAO,CAAC,EAAY,GAAS,EAAU,CAAC;;;AAG5C,UAAO,CAAC,EAAY,EAAE,EAAE,GAAG,EAAS,QAAQ,CAAC;;EAEhD;;AAOH,SAAgB,EACd,GACA,GACO;AASP,QAAO;EACL,KAAK;EACL,KAAK;EACL,UATkB,IAEhB,MAAM,QAAQ,EAAS,GACrB,EAAS,QAAQ,MAAM,KAAM,KAAwB,GACrD,CAAC,EAAS,CAAC,QAAQ,MAAM,KAAM,KAAwB,GAHzD,EAAE;EASL"}
@@ -1,8 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("./style-Bjn8zDiZ.cjs");function R(w={}){const{root:s,styleId:y="cer-dom-jit-css",...b}=w;Object.keys(b).length>0&&E.enableJITCSS(b);const a=new Set;let d="",n=null,l=null,h=!1,c=null,u=new Set,f=!1,S=!1,r=null;function j(){if(!(typeof document>"u")){if(r=s instanceof ShadowRoot?s:document,typeof CSSStyleSheet<"u"&&"replaceSync"in CSSStyleSheet.prototype&&r.adoptedStyleSheets!==void 0)try{l=new CSSStyleSheet,r.adoptedStyleSheets=[...r.adoptedStyleSheets,l],h=!0;return}catch{}s instanceof ShadowRoot?(n=document.createElement("style"),n.id=y,s.appendChild(n)):(n=document.getElementById(y),n||(n=document.createElement("style"),n.id=y,(document.head??document.documentElement).appendChild(n)))}}function v(e){if(e){if(d+=`
2
- ${e}`,h&&l)try{l.replaceSync(`@layer cer-utilities {
3
- ${d}
4
- }`);return}catch{}n&&(n.textContent=`@layer cer-utilities {
5
- ${d}
6
- }`)}}function O(e){const t=e.getAttribute("class");return t?t.split(/\s+/).filter(Boolean):[]}function m(){f||(f=!0,queueMicrotask(M))}function M(){if(f=!1,u.size===0)return;const e=[];for(const o of u)a.has(o)||(a.add(o),e.push(o));if(u=new Set,e.length===0)return;const t=E.jitCSS(`<div class="${e.join(" ")}"></div>`);t&&v(t)}function p(e){for(const t of O(e))u.add(t)}function g(e){const t=document.createTreeWalker(e instanceof Document?document.body:e,NodeFilter.SHOW_ELEMENT);let o=t.currentNode;for(;o;)o instanceof Element&&p(o),o=t.nextNode();m()}function T(){if(s)return s;if(typeof document<"u"){const e=document.querySelectorAll("[data-jitcss]");return e.length>0&&e.length===1?e[0]:document.body}return null}function N(e){const t=e.getAttribute("data-jitcss");return t==="self"?"self":t==="global"?"global":"container"}function I(){if(S)return;S=!0,j();const e=T();if(!e)return;const t=e instanceof Element&&e.hasAttribute("data-jitcss")?N(e):"container",o=t==="global"?document.body:e;t==="self"&&o instanceof Element?(p(o),m()):g(o),c=new MutationObserver(D=>{for(const i of D)if(i.type==="attributes"&&i.attributeName==="class")i.target instanceof Element&&p(i.target);else if(i.type==="childList"){for(const C of i.addedNodes)if(C instanceof Element){if(t==="self")continue;g(C)}}m()}),c.observe(o,{subtree:t!=="self",attributes:!0,attributeFilter:["class"],childList:t!=="self",characterData:!1})}function A(){if(S){if(S=!1,c&&(c.disconnect(),c=null),h&&l){try{const e=r??document;e.adoptedStyleSheets=e.adoptedStyleSheets.filter(t=>t!==l)}catch{}l=null}n&&(n.remove(),n=null),a.clear(),u.clear(),d="",f=!1,r=null}}return{mount:I,destroy:A,get processedCount(){return a.size}}}exports.createDOMJITCSS=R;
7
-
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./style-A8l3aQ52.cjs`);function t(t={}){let{root:n,styleId:r=`cer-dom-jit-css`,...i}=t;Object.keys(i).length>0&&e.i(i);let a=new Set,o=``,s=null,c=null,l=!1,u=null,d=new Set,f=!1,p=!1,m=null;function h(){if(!(typeof document>`u`)){if(m=n instanceof ShadowRoot?n:document,typeof CSSStyleSheet<`u`&&`replaceSync`in CSSStyleSheet.prototype&&m.adoptedStyleSheets!==void 0)try{c=new CSSStyleSheet,m.adoptedStyleSheets=[...m.adoptedStyleSheets,c],l=!0;return}catch{}n instanceof ShadowRoot?(s=document.createElement(`style`),s.id=r,n.appendChild(s)):(s=document.getElementById(r),s||(s=document.createElement(`style`),s.id=r,(document.head??document.documentElement).appendChild(s)))}}function g(e){if(e){if(o+=`\n${e}`,l&&c)try{c.replaceSync(`@layer cer-utilities {\n${o}\n}`);return}catch{}s&&(s.textContent=`@layer cer-utilities {\n${o}\n}`)}}function _(e){let t=e.getAttribute(`class`);return t?t.split(/\s+/).filter(Boolean):[]}function v(){f||(f=!0,queueMicrotask(y))}function y(){if(f=!1,d.size===0)return;let t=[];for(let e of d)a.has(e)||(a.add(e),t.push(e));if(d=new Set,t.length===0)return;let n=e.l(`<div class="${t.join(` `)}"></div>`);n&&g(n)}function b(e){for(let t of _(e))d.add(t)}function x(e){let t=document.createTreeWalker(e instanceof Document?document.body:e,NodeFilter.SHOW_ELEMENT),n=t.currentNode;for(;n;)n instanceof Element&&b(n),n=t.nextNode();v()}function S(){if(n)return n;if(typeof document<`u`){let e=document.querySelectorAll(`[data-jitcss]`);return e.length>0&&e.length===1?e[0]:document.body}return null}function C(e){let t=e.getAttribute(`data-jitcss`);return t===`self`?`self`:t===`global`?`global`:`container`}function w(){if(p)return;p=!0,h();let e=S();if(!e)return;let t=e instanceof Element&&e.hasAttribute(`data-jitcss`)?C(e):`container`,n=t===`global`?document.body:e;t===`self`&&n instanceof Element?(b(n),v()):x(n),u=new MutationObserver(e=>{for(let n of e)if(n.type===`attributes`&&n.attributeName===`class`)n.target instanceof Element&&b(n.target);else if(n.type===`childList`){for(let e of n.addedNodes)if(e instanceof Element){if(t===`self`)continue;x(e)}}v()}),u.observe(n,{subtree:t!==`self`,attributes:!0,attributeFilter:[`class`],childList:t!==`self`,characterData:!1})}function T(){if(p){if(p=!1,u&&=(u.disconnect(),null),l&&c){try{let e=m??document;e.adoptedStyleSheets=e.adoptedStyleSheets.filter(e=>e!==c)}catch{}c=null}s&&=(s.remove(),null),a.clear(),d.clear(),o=``,f=!1,m=null}}return{mount:w,destroy:T,get processedCount(){return a.size}}}exports.createDOMJITCSS=t;
8
2
  //# sourceMappingURL=custom-elements-runtime.dom-jit-css.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-elements-runtime.dom-jit-css.cjs.js","names":[],"sources":["../src/lib/dom-jit-css.ts"],"sourcesContent":["/**\n * Non-Shadow DOM JIT CSS runtime scanner.\n *\n * Watches real DOM elements for class changes and injects utility CSS into\n * a shared `<style>` element (or constructable stylesheet) in the host document.\n *\n * @example\n * ```ts\n * import { createDOMJITCSS } from '@jasonshimmy/custom-elements-runtime/dom-jit-css';\n *\n * // Watch the full document body\n * const jit = createDOMJITCSS();\n * jit.mount();\n *\n * // Watch a specific container element\n * const jit = createDOMJITCSS({ root: document.getElementById('app')! });\n * jit.mount();\n *\n * // Tear down when no longer needed\n * jit.destroy();\n * ```\n *\n * ## `data-jitcss` attribute semantics\n *\n * | Attribute value | Behaviour |\n * | ------------------------------------------------------ | ----------------------------------------------------------------- |\n * | `data-jitcss` (no value) or `data-jitcss=\"container\"` | Scopes the observer to that element and its subtree |\n * | `data-jitcss=\"self\"` | Only processes classes on that exact element, not descendants |\n * | `data-jitcss=\"global\"` | Observer covers `document.body` (useful on `<html>` or `<body>`) |\n *\n * When `createDOMJITCSS()` is called with no `root`, it auto-detects all\n * `[data-jitcss]` elements and registers an observer for each.\n */\n\nimport { jitCSS, enableJITCSS, type JITCSSOptions } from './runtime/style';\n\n/**\n * Options for `createDOMJITCSS()`.\n */\nexport interface DOMJITCSSOptions extends JITCSSOptions {\n /**\n * The root element to observe. Defaults to auto-detecting `[data-jitcss]`\n * elements, then falling back to `document.body`.\n */\n root?: Element | ShadowRoot | null;\n /**\n * ID of the `<style>` element injected into the document head.\n * Defaults to `'cer-dom-jit-css'`.\n */\n styleId?: string;\n}\n\n/** Public handle returned by `createDOMJITCSS()`. */\nexport interface DOMJITCSSHandle {\n /** Start observing the DOM and injecting utility CSS. */\n mount(): void;\n /** Stop observing and remove the injected stylesheet. */\n destroy(): void;\n /** Get the number of unique classes processed so far. */\n readonly processedCount: number;\n}\n\n/**\n * Create a DOM JIT CSS instance that watches class attribute changes and\n * injects CSS utility rules into the document.\n *\n * @param options - Configuration options.\n * @returns A handle with `mount()` and `destroy()` methods.\n */\nexport function createDOMJITCSS(\n options: DOMJITCSSOptions = {},\n): DOMJITCSSHandle {\n const {\n root: rootOption,\n styleId = 'cer-dom-jit-css',\n ...jitOptions\n } = options;\n\n // Apply JIT CSS options (e.g. extendedColors, customColors) globally\n if (Object.keys(jitOptions).length > 0) {\n enableJITCSS(jitOptions);\n }\n\n // Monotonically growing set of processed class names.\n // We never shrink this — rules remain valid even if classes are removed.\n const processedClasses = new Set<string>();\n // CSS text that has been injected. Grown incrementally.\n let injectedCSS = '';\n\n let styleEl: HTMLStyleElement | null = null;\n let adoptedSheet: CSSStyleSheet | null = null;\n let useAdoptedSheet = false;\n let observer: MutationObserver | null = null;\n let pendingClasses = new Set<string>();\n let flushScheduled = false;\n let isMounted = false;\n // The target for adoptedStyleSheets / <style> injection. Set during mount().\n // When rootOption is a ShadowRoot the sheet is scoped to that shadow tree;\n // otherwise styles are adopted by the host document.\n let adoptionTarget: Document | ShadowRoot | null = null;\n\n function injectStylesheet(): void {\n if (typeof document === 'undefined') return;\n\n // Scope stylesheet injection to the shadow root when one was supplied,\n // so the generated utility classes do not leak into the host document.\n adoptionTarget = rootOption instanceof ShadowRoot ? rootOption : document;\n\n // Try constructable stylesheets first (faster incremental updates)\n if (\n typeof CSSStyleSheet !== 'undefined' &&\n 'replaceSync' in CSSStyleSheet.prototype &&\n adoptionTarget.adoptedStyleSheets !== undefined\n ) {\n try {\n adoptedSheet = new CSSStyleSheet();\n adoptionTarget.adoptedStyleSheets = [\n ...adoptionTarget.adoptedStyleSheets,\n adoptedSheet,\n ];\n useAdoptedSheet = true;\n return;\n } catch {\n // Fall through to style element\n }\n }\n\n // Fallback: a plain <style> element.\n // For a ShadowRoot target, append directly inside the shadow tree.\n // ShadowRoot has no getElementById(), so we always create a fresh element.\n if (rootOption instanceof ShadowRoot) {\n styleEl = document.createElement('style');\n styleEl.id = styleId;\n rootOption.appendChild(styleEl);\n } else {\n styleEl = document.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = styleId;\n (document.head ?? document.documentElement).appendChild(styleEl);\n }\n }\n }\n\n function applyNewCSS(css: string): void {\n if (!css) return;\n injectedCSS += `\\n${css}`;\n if (useAdoptedSheet && adoptedSheet) {\n try {\n // Replace the entire sheet with the accumulated CSS wrapped in a single\n // @layer block. replaceSync handles nested at-rules (@media, @container,\n // @supports) correctly — the previous insertRule approach used a flat\n // regex that stripped at-rule wrappers, causing dark: and responsive\n // variants to apply unconditionally.\n adoptedSheet.replaceSync(`@layer cer-utilities {\\n${injectedCSS}\\n}`);\n return;\n } catch {\n // Fall through to style element\n }\n }\n if (styleEl) {\n // Wrap everything in a single @layer block for the <style> fallback path\n styleEl.textContent = `@layer cer-utilities {\\n${injectedCSS}\\n}`;\n }\n }\n\n function extractClasses(el: Element): string[] {\n const cls = el.getAttribute('class');\n if (!cls) return [];\n return cls.split(/\\s+/).filter(Boolean);\n }\n\n function scheduleFlush(): void {\n if (flushScheduled) return;\n flushScheduled = true;\n queueMicrotask(flushPending);\n }\n\n function flushPending(): void {\n flushScheduled = false;\n if (pendingClasses.size === 0) return;\n\n // Compute delta — only process classes we haven't seen before\n const newClasses: string[] = [];\n for (const cls of pendingClasses) {\n if (!processedClasses.has(cls)) {\n processedClasses.add(cls);\n newClasses.push(cls);\n }\n }\n pendingClasses = new Set<string>();\n\n if (newClasses.length === 0) return;\n\n // Build a minimal HTML string containing only the new class names so\n // the jitCSS engine parses only the delta (not the full DOM).\n const fakeHTML = `<div class=\"${newClasses.join(' ')}\"></div>`;\n const newCSS = jitCSS(fakeHTML);\n if (newCSS) {\n applyNewCSS(newCSS);\n }\n }\n\n function addClassesFromElement(el: Element): void {\n for (const cls of extractClasses(el)) {\n pendingClasses.add(cls);\n }\n }\n\n function scanSubtree(root: Element | Document | ShadowRoot): void {\n // Use TreeWalker for maximum performance on initial scan\n const walker = document.createTreeWalker(\n root instanceof Document ? document.body : (root as Node),\n NodeFilter.SHOW_ELEMENT,\n );\n let node: Node | null = walker.currentNode;\n while (node) {\n if (node instanceof Element) {\n addClassesFromElement(node);\n }\n node = walker.nextNode();\n }\n scheduleFlush();\n }\n\n function getObserverRoot(): Element | ShadowRoot | null {\n if (rootOption) {\n // Return the ShadowRoot directly so the MutationObserver observes inside\n // the shadow tree. Previously we returned rootOption.host which caused the\n // observer to watch the light DOM of the host element instead.\n return rootOption;\n }\n\n // Auto-detect [data-jitcss] elements\n if (typeof document !== 'undefined') {\n const scoped = document.querySelectorAll('[data-jitcss]');\n if (scoped.length > 0) {\n // Use the first scoped element; if multiple, observe body\n return scoped.length === 1 ? (scoped[0] as Element) : document.body;\n }\n return document.body;\n }\n\n return null;\n }\n\n function getDataJITCSSMode(el: Element): 'container' | 'self' | 'global' {\n const val = el.getAttribute('data-jitcss');\n if (val === 'self') return 'self';\n if (val === 'global') return 'global';\n return 'container';\n }\n\n function mount(): void {\n if (isMounted) return;\n isMounted = true;\n\n injectStylesheet();\n\n const observerRoot = getObserverRoot();\n if (!observerRoot) return;\n\n // ShadowRoot does not inherit hasAttribute() from Element; guard with an\n // instanceof check so passing a ShadowRoot as root does not throw.\n const mode =\n observerRoot instanceof Element &&\n observerRoot.hasAttribute('data-jitcss')\n ? getDataJITCSSMode(observerRoot)\n : 'container';\n const actualRoot = mode === 'global' ? document.body : observerRoot;\n\n // Initial scan\n if (mode === 'self' && actualRoot instanceof Element) {\n addClassesFromElement(actualRoot);\n scheduleFlush();\n } else {\n scanSubtree(actualRoot);\n }\n\n // Set up MutationObserver\n observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'class'\n ) {\n if (mutation.target instanceof Element) {\n addClassesFromElement(mutation.target);\n }\n } else if (mutation.type === 'childList') {\n for (const node of mutation.addedNodes) {\n if (node instanceof Element) {\n if (mode === 'self') continue; // Only own classes in self mode\n // scanSubtree already processes the root element as its first\n // walker node, so a separate addClassesFromElement call here\n // would process the same element twice.\n scanSubtree(node);\n }\n }\n }\n }\n scheduleFlush();\n });\n\n observer.observe(actualRoot, {\n subtree: mode !== 'self',\n attributes: true,\n attributeFilter: ['class'],\n childList: mode !== 'self',\n characterData: false,\n });\n }\n\n function destroy(): void {\n if (!isMounted) return;\n isMounted = false;\n\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n\n // Remove injected styles\n if (useAdoptedSheet && adoptedSheet) {\n try {\n const target = adoptionTarget ?? document;\n target.adoptedStyleSheets = target.adoptedStyleSheets.filter(\n (s) => s !== adoptedSheet,\n );\n } catch {\n // ignore\n }\n adoptedSheet = null;\n }\n\n if (styleEl) {\n styleEl.remove();\n styleEl = null;\n }\n\n processedClasses.clear();\n pendingClasses.clear();\n injectedCSS = '';\n flushScheduled = false;\n adoptionTarget = null;\n }\n\n return {\n mount,\n destroy,\n get processedCount() {\n return processedClasses.size;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"custom-elements-runtime.dom-jit-css.cjs.js","names":[],"sources":["../src/lib/dom-jit-css.ts"],"sourcesContent":["/**\n * Non-Shadow DOM JIT CSS runtime scanner.\n *\n * Watches real DOM elements for class changes and injects utility CSS into\n * a shared `<style>` element (or constructable stylesheet) in the host document.\n *\n * @example\n * ```ts\n * import { createDOMJITCSS } from '@jasonshimmy/custom-elements-runtime/dom-jit-css';\n *\n * // Watch the full document body\n * const jit = createDOMJITCSS();\n * jit.mount();\n *\n * // Watch a specific container element\n * const jit = createDOMJITCSS({ root: document.getElementById('app')! });\n * jit.mount();\n *\n * // Tear down when no longer needed\n * jit.destroy();\n * ```\n *\n * ## `data-jitcss` attribute semantics\n *\n * | Attribute value | Behaviour |\n * | ------------------------------------------------------ | ----------------------------------------------------------------- |\n * | `data-jitcss` (no value) or `data-jitcss=\"container\"` | Scopes the observer to that element and its subtree |\n * | `data-jitcss=\"self\"` | Only processes classes on that exact element, not descendants |\n * | `data-jitcss=\"global\"` | Observer covers `document.body` (useful on `<html>` or `<body>`) |\n *\n * When `createDOMJITCSS()` is called with no `root`, it auto-detects all\n * `[data-jitcss]` elements and registers an observer for each.\n */\n\nimport { jitCSS, enableJITCSS, type JITCSSOptions } from './runtime/style';\n\n/**\n * Options for `createDOMJITCSS()`.\n */\nexport interface DOMJITCSSOptions extends JITCSSOptions {\n /**\n * The root element to observe. Defaults to auto-detecting `[data-jitcss]`\n * elements, then falling back to `document.body`.\n */\n root?: Element | ShadowRoot | null;\n /**\n * ID of the `<style>` element injected into the document head.\n * Defaults to `'cer-dom-jit-css'`.\n */\n styleId?: string;\n}\n\n/** Public handle returned by `createDOMJITCSS()`. */\nexport interface DOMJITCSSHandle {\n /** Start observing the DOM and injecting utility CSS. */\n mount(): void;\n /** Stop observing and remove the injected stylesheet. */\n destroy(): void;\n /** Get the number of unique classes processed so far. */\n readonly processedCount: number;\n}\n\n/**\n * Create a DOM JIT CSS instance that watches class attribute changes and\n * injects CSS utility rules into the document.\n *\n * @param options - Configuration options.\n * @returns A handle with `mount()` and `destroy()` methods.\n */\nexport function createDOMJITCSS(\n options: DOMJITCSSOptions = {},\n): DOMJITCSSHandle {\n const {\n root: rootOption,\n styleId = 'cer-dom-jit-css',\n ...jitOptions\n } = options;\n\n // Apply JIT CSS options (e.g. extendedColors, customColors) globally\n if (Object.keys(jitOptions).length > 0) {\n enableJITCSS(jitOptions);\n }\n\n // Monotonically growing set of processed class names.\n // We never shrink this — rules remain valid even if classes are removed.\n const processedClasses = new Set<string>();\n // CSS text that has been injected. Grown incrementally.\n let injectedCSS = '';\n\n let styleEl: HTMLStyleElement | null = null;\n let adoptedSheet: CSSStyleSheet | null = null;\n let useAdoptedSheet = false;\n let observer: MutationObserver | null = null;\n let pendingClasses = new Set<string>();\n let flushScheduled = false;\n let isMounted = false;\n // The target for adoptedStyleSheets / <style> injection. Set during mount().\n // When rootOption is a ShadowRoot the sheet is scoped to that shadow tree;\n // otherwise styles are adopted by the host document.\n let adoptionTarget: Document | ShadowRoot | null = null;\n\n function injectStylesheet(): void {\n if (typeof document === 'undefined') return;\n\n // Scope stylesheet injection to the shadow root when one was supplied,\n // so the generated utility classes do not leak into the host document.\n adoptionTarget = rootOption instanceof ShadowRoot ? rootOption : document;\n\n // Try constructable stylesheets first (faster incremental updates)\n if (\n typeof CSSStyleSheet !== 'undefined' &&\n 'replaceSync' in CSSStyleSheet.prototype &&\n adoptionTarget.adoptedStyleSheets !== undefined\n ) {\n try {\n adoptedSheet = new CSSStyleSheet();\n adoptionTarget.adoptedStyleSheets = [\n ...adoptionTarget.adoptedStyleSheets,\n adoptedSheet,\n ];\n useAdoptedSheet = true;\n return;\n } catch {\n // Fall through to style element\n }\n }\n\n // Fallback: a plain <style> element.\n // For a ShadowRoot target, append directly inside the shadow tree.\n // ShadowRoot has no getElementById(), so we always create a fresh element.\n if (rootOption instanceof ShadowRoot) {\n styleEl = document.createElement('style');\n styleEl.id = styleId;\n rootOption.appendChild(styleEl);\n } else {\n styleEl = document.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = styleId;\n (document.head ?? document.documentElement).appendChild(styleEl);\n }\n }\n }\n\n function applyNewCSS(css: string): void {\n if (!css) return;\n injectedCSS += `\\n${css}`;\n if (useAdoptedSheet && adoptedSheet) {\n try {\n // Replace the entire sheet with the accumulated CSS wrapped in a single\n // @layer block. replaceSync handles nested at-rules (@media, @container,\n // @supports) correctly — the previous insertRule approach used a flat\n // regex that stripped at-rule wrappers, causing dark: and responsive\n // variants to apply unconditionally.\n adoptedSheet.replaceSync(`@layer cer-utilities {\\n${injectedCSS}\\n}`);\n return;\n } catch {\n // Fall through to style element\n }\n }\n if (styleEl) {\n // Wrap everything in a single @layer block for the <style> fallback path\n styleEl.textContent = `@layer cer-utilities {\\n${injectedCSS}\\n}`;\n }\n }\n\n function extractClasses(el: Element): string[] {\n const cls = el.getAttribute('class');\n if (!cls) return [];\n return cls.split(/\\s+/).filter(Boolean);\n }\n\n function scheduleFlush(): void {\n if (flushScheduled) return;\n flushScheduled = true;\n queueMicrotask(flushPending);\n }\n\n function flushPending(): void {\n flushScheduled = false;\n if (pendingClasses.size === 0) return;\n\n // Compute delta — only process classes we haven't seen before\n const newClasses: string[] = [];\n for (const cls of pendingClasses) {\n if (!processedClasses.has(cls)) {\n processedClasses.add(cls);\n newClasses.push(cls);\n }\n }\n pendingClasses = new Set<string>();\n\n if (newClasses.length === 0) return;\n\n // Build a minimal HTML string containing only the new class names so\n // the jitCSS engine parses only the delta (not the full DOM).\n const fakeHTML = `<div class=\"${newClasses.join(' ')}\"></div>`;\n const newCSS = jitCSS(fakeHTML);\n if (newCSS) {\n applyNewCSS(newCSS);\n }\n }\n\n function addClassesFromElement(el: Element): void {\n for (const cls of extractClasses(el)) {\n pendingClasses.add(cls);\n }\n }\n\n function scanSubtree(root: Element | Document | ShadowRoot): void {\n // Use TreeWalker for maximum performance on initial scan\n const walker = document.createTreeWalker(\n root instanceof Document ? document.body : (root as Node),\n NodeFilter.SHOW_ELEMENT,\n );\n let node: Node | null = walker.currentNode;\n while (node) {\n if (node instanceof Element) {\n addClassesFromElement(node);\n }\n node = walker.nextNode();\n }\n scheduleFlush();\n }\n\n function getObserverRoot(): Element | ShadowRoot | null {\n if (rootOption) {\n // Return the ShadowRoot directly so the MutationObserver observes inside\n // the shadow tree. Previously we returned rootOption.host which caused the\n // observer to watch the light DOM of the host element instead.\n return rootOption;\n }\n\n // Auto-detect [data-jitcss] elements\n if (typeof document !== 'undefined') {\n const scoped = document.querySelectorAll('[data-jitcss]');\n if (scoped.length > 0) {\n // Use the first scoped element; if multiple, observe body\n return scoped.length === 1 ? (scoped[0] as Element) : document.body;\n }\n return document.body;\n }\n\n return null;\n }\n\n function getDataJITCSSMode(el: Element): 'container' | 'self' | 'global' {\n const val = el.getAttribute('data-jitcss');\n if (val === 'self') return 'self';\n if (val === 'global') return 'global';\n return 'container';\n }\n\n function mount(): void {\n if (isMounted) return;\n isMounted = true;\n\n injectStylesheet();\n\n const observerRoot = getObserverRoot();\n if (!observerRoot) return;\n\n // ShadowRoot does not inherit hasAttribute() from Element; guard with an\n // instanceof check so passing a ShadowRoot as root does not throw.\n const mode =\n observerRoot instanceof Element &&\n observerRoot.hasAttribute('data-jitcss')\n ? getDataJITCSSMode(observerRoot)\n : 'container';\n const actualRoot = mode === 'global' ? document.body : observerRoot;\n\n // Initial scan\n if (mode === 'self' && actualRoot instanceof Element) {\n addClassesFromElement(actualRoot);\n scheduleFlush();\n } else {\n scanSubtree(actualRoot);\n }\n\n // Set up MutationObserver\n observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'class'\n ) {\n if (mutation.target instanceof Element) {\n addClassesFromElement(mutation.target);\n }\n } else if (mutation.type === 'childList') {\n for (const node of mutation.addedNodes) {\n if (node instanceof Element) {\n if (mode === 'self') continue; // Only own classes in self mode\n // scanSubtree already processes the root element as its first\n // walker node, so a separate addClassesFromElement call here\n // would process the same element twice.\n scanSubtree(node);\n }\n }\n }\n }\n scheduleFlush();\n });\n\n observer.observe(actualRoot, {\n subtree: mode !== 'self',\n attributes: true,\n attributeFilter: ['class'],\n childList: mode !== 'self',\n characterData: false,\n });\n }\n\n function destroy(): void {\n if (!isMounted) return;\n isMounted = false;\n\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n\n // Remove injected styles\n if (useAdoptedSheet && adoptedSheet) {\n try {\n const target = adoptionTarget ?? document;\n target.adoptedStyleSheets = target.adoptedStyleSheets.filter(\n (s) => s !== adoptedSheet,\n );\n } catch {\n // ignore\n }\n adoptedSheet = null;\n }\n\n if (styleEl) {\n styleEl.remove();\n styleEl = null;\n }\n\n processedClasses.clear();\n pendingClasses.clear();\n injectedCSS = '';\n flushScheduled = false;\n adoptionTarget = null;\n }\n\n return {\n mount,\n destroy,\n get processedCount() {\n return processedClasses.size;\n },\n };\n}\n"],"mappings":"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"}
@@ -1,118 +1,106 @@
1
- import { i as R, l as k } from "./style-DuDoj_xK.js";
2
- function D(E = {}) {
3
- const { root: s, styleId: m = "cer-dom-jit-css", ...b } = E;
4
- Object.keys(b).length > 0 && R(b);
5
- const u = /* @__PURE__ */ new Set();
6
- let d = "", n = null, l = null, h = !1, c = null, a = /* @__PURE__ */ new Set(), f = !1, S = !1, r = null;
7
- function w() {
8
- if (!(typeof document > "u")) {
9
- if (r = s instanceof ShadowRoot ? s : document, typeof CSSStyleSheet < "u" && "replaceSync" in CSSStyleSheet.prototype && r.adoptedStyleSheets !== void 0) try {
10
- l = new CSSStyleSheet(), r.adoptedStyleSheets = [...r.adoptedStyleSheets, l], h = !0;
11
- return;
12
- } catch {
13
- }
14
- s instanceof ShadowRoot ? (n = document.createElement("style"), n.id = m, s.appendChild(n)) : (n = document.getElementById(m), n || (n = document.createElement("style"), n.id = m, (document.head ?? document.documentElement).appendChild(n)));
15
- }
16
- }
17
- function j(e) {
18
- if (e) {
19
- if (d += `
20
- ${e}`, h && l) try {
21
- l.replaceSync(`@layer cer-utilities {
22
- ${d}
23
- }`);
24
- return;
25
- } catch {
26
- }
27
- n && (n.textContent = `@layer cer-utilities {
28
- ${d}
29
- }`);
30
- }
31
- }
32
- function v(e) {
33
- const t = e.getAttribute("class");
34
- return t ? t.split(/\s+/).filter(Boolean) : [];
35
- }
36
- function y() {
37
- f || (f = !0, queueMicrotask(N));
38
- }
39
- function N() {
40
- if (f = !1, a.size === 0) return;
41
- const e = [];
42
- for (const o of a) u.has(o) || (u.add(o), e.push(o));
43
- if (a = /* @__PURE__ */ new Set(), e.length === 0) return;
44
- const t = k(`<div class="${e.join(" ")}"></div>`);
45
- t && j(t);
46
- }
47
- function p(e) {
48
- for (const t of v(e)) a.add(t);
49
- }
50
- function g(e) {
51
- const t = document.createTreeWalker(e instanceof Document ? document.body : e, NodeFilter.SHOW_ELEMENT);
52
- let o = t.currentNode;
53
- for (; o; )
54
- o instanceof Element && p(o), o = t.nextNode();
55
- y();
56
- }
57
- function O() {
58
- if (s) return s;
59
- if (typeof document < "u") {
60
- const e = document.querySelectorAll("[data-jitcss]");
61
- return e.length > 0 && e.length === 1 ? e[0] : document.body;
62
- }
63
- return null;
64
- }
65
- function M(e) {
66
- const t = e.getAttribute("data-jitcss");
67
- return t === "self" ? "self" : t === "global" ? "global" : "container";
68
- }
69
- function T() {
70
- if (S) return;
71
- S = !0, w();
72
- const e = O();
73
- if (!e) return;
74
- const t = e instanceof Element && e.hasAttribute("data-jitcss") ? M(e) : "container", o = t === "global" ? document.body : e;
75
- t === "self" && o instanceof Element ? (p(o), y()) : g(o), c = new MutationObserver((I) => {
76
- for (const i of I) if (i.type === "attributes" && i.attributeName === "class")
77
- i.target instanceof Element && p(i.target);
78
- else if (i.type === "childList") {
79
- for (const C of i.addedNodes) if (C instanceof Element) {
80
- if (t === "self") continue;
81
- g(C);
82
- }
83
- }
84
- y();
85
- }), c.observe(o, {
86
- subtree: t !== "self",
87
- attributes: !0,
88
- attributeFilter: ["class"],
89
- childList: t !== "self",
90
- characterData: !1
91
- });
92
- }
93
- function A() {
94
- if (S) {
95
- if (S = !1, c && (c.disconnect(), c = null), h && l) {
96
- try {
97
- const e = r ?? document;
98
- e.adoptedStyleSheets = e.adoptedStyleSheets.filter((t) => t !== l);
99
- } catch {
100
- }
101
- l = null;
102
- }
103
- n && (n.remove(), n = null), u.clear(), a.clear(), d = "", f = !1, r = null;
104
- }
105
- }
106
- return {
107
- mount: T,
108
- destroy: A,
109
- get processedCount() {
110
- return u.size;
111
- }
112
- };
1
+ import { i as e, l as t } from "./style-DSSoCbC9.js";
2
+ //#region src/lib/dom-jit-css.ts
3
+ function n(n = {}) {
4
+ let { root: r, styleId: i = "cer-dom-jit-css", ...a } = n;
5
+ Object.keys(a).length > 0 && e(a);
6
+ let o = /* @__PURE__ */ new Set(), s = "", c = null, l = null, u = !1, d = null, f = /* @__PURE__ */ new Set(), p = !1, m = !1, h = null;
7
+ function g() {
8
+ if (!(typeof document > "u")) {
9
+ if (h = r instanceof ShadowRoot ? r : document, typeof CSSStyleSheet < "u" && "replaceSync" in CSSStyleSheet.prototype && h.adoptedStyleSheets !== void 0) try {
10
+ l = new CSSStyleSheet(), h.adoptedStyleSheets = [...h.adoptedStyleSheets, l], u = !0;
11
+ return;
12
+ } catch {}
13
+ r instanceof ShadowRoot ? (c = document.createElement("style"), c.id = i, r.appendChild(c)) : (c = document.getElementById(i), c || (c = document.createElement("style"), c.id = i, (document.head ?? document.documentElement).appendChild(c)));
14
+ }
15
+ }
16
+ function _(e) {
17
+ if (e) {
18
+ if (s += `\n${e}`, u && l) try {
19
+ l.replaceSync(`@layer cer-utilities {\n${s}\n}`);
20
+ return;
21
+ } catch {}
22
+ c && (c.textContent = `@layer cer-utilities {\n${s}\n}`);
23
+ }
24
+ }
25
+ function v(e) {
26
+ let t = e.getAttribute("class");
27
+ return t ? t.split(/\s+/).filter(Boolean) : [];
28
+ }
29
+ function y() {
30
+ p || (p = !0, queueMicrotask(b));
31
+ }
32
+ function b() {
33
+ if (p = !1, f.size === 0) return;
34
+ let e = [];
35
+ for (let t of f) o.has(t) || (o.add(t), e.push(t));
36
+ if (f = /* @__PURE__ */ new Set(), e.length === 0) return;
37
+ let n = t(`<div class="${e.join(" ")}"></div>`);
38
+ n && _(n);
39
+ }
40
+ function x(e) {
41
+ for (let t of v(e)) f.add(t);
42
+ }
43
+ function S(e) {
44
+ let t = document.createTreeWalker(e instanceof Document ? document.body : e, NodeFilter.SHOW_ELEMENT), n = t.currentNode;
45
+ for (; n;) n instanceof Element && x(n), n = t.nextNode();
46
+ y();
47
+ }
48
+ function C() {
49
+ if (r) return r;
50
+ if (typeof document < "u") {
51
+ let e = document.querySelectorAll("[data-jitcss]");
52
+ return e.length > 0 && e.length === 1 ? e[0] : document.body;
53
+ }
54
+ return null;
55
+ }
56
+ function w(e) {
57
+ let t = e.getAttribute("data-jitcss");
58
+ return t === "self" ? "self" : t === "global" ? "global" : "container";
59
+ }
60
+ function T() {
61
+ if (m) return;
62
+ m = !0, g();
63
+ let e = C();
64
+ if (!e) return;
65
+ let t = e instanceof Element && e.hasAttribute("data-jitcss") ? w(e) : "container", n = t === "global" ? document.body : e;
66
+ t === "self" && n instanceof Element ? (x(n), y()) : S(n), d = new MutationObserver((e) => {
67
+ for (let n of e) if (n.type === "attributes" && n.attributeName === "class") n.target instanceof Element && x(n.target);
68
+ else if (n.type === "childList") {
69
+ for (let e of n.addedNodes) if (e instanceof Element) {
70
+ if (t === "self") continue;
71
+ S(e);
72
+ }
73
+ }
74
+ y();
75
+ }), d.observe(n, {
76
+ subtree: t !== "self",
77
+ attributes: !0,
78
+ attributeFilter: ["class"],
79
+ childList: t !== "self",
80
+ characterData: !1
81
+ });
82
+ }
83
+ function E() {
84
+ if (m) {
85
+ if (m = !1, d &&= (d.disconnect(), null), u && l) {
86
+ try {
87
+ let e = h ?? document;
88
+ e.adoptedStyleSheets = e.adoptedStyleSheets.filter((e) => e !== l);
89
+ } catch {}
90
+ l = null;
91
+ }
92
+ c &&= (c.remove(), null), o.clear(), f.clear(), s = "", p = !1, h = null;
93
+ }
94
+ }
95
+ return {
96
+ mount: T,
97
+ destroy: E,
98
+ get processedCount() {
99
+ return o.size;
100
+ }
101
+ };
113
102
  }
114
- export {
115
- D as createDOMJITCSS
116
- };
103
+ //#endregion
104
+ export { n as createDOMJITCSS };
117
105
 
118
106
  //# sourceMappingURL=custom-elements-runtime.dom-jit-css.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-elements-runtime.dom-jit-css.es.js","names":[],"sources":["../src/lib/dom-jit-css.ts"],"sourcesContent":["/**\n * Non-Shadow DOM JIT CSS runtime scanner.\n *\n * Watches real DOM elements for class changes and injects utility CSS into\n * a shared `<style>` element (or constructable stylesheet) in the host document.\n *\n * @example\n * ```ts\n * import { createDOMJITCSS } from '@jasonshimmy/custom-elements-runtime/dom-jit-css';\n *\n * // Watch the full document body\n * const jit = createDOMJITCSS();\n * jit.mount();\n *\n * // Watch a specific container element\n * const jit = createDOMJITCSS({ root: document.getElementById('app')! });\n * jit.mount();\n *\n * // Tear down when no longer needed\n * jit.destroy();\n * ```\n *\n * ## `data-jitcss` attribute semantics\n *\n * | Attribute value | Behaviour |\n * | ------------------------------------------------------ | ----------------------------------------------------------------- |\n * | `data-jitcss` (no value) or `data-jitcss=\"container\"` | Scopes the observer to that element and its subtree |\n * | `data-jitcss=\"self\"` | Only processes classes on that exact element, not descendants |\n * | `data-jitcss=\"global\"` | Observer covers `document.body` (useful on `<html>` or `<body>`) |\n *\n * When `createDOMJITCSS()` is called with no `root`, it auto-detects all\n * `[data-jitcss]` elements and registers an observer for each.\n */\n\nimport { jitCSS, enableJITCSS, type JITCSSOptions } from './runtime/style';\n\n/**\n * Options for `createDOMJITCSS()`.\n */\nexport interface DOMJITCSSOptions extends JITCSSOptions {\n /**\n * The root element to observe. Defaults to auto-detecting `[data-jitcss]`\n * elements, then falling back to `document.body`.\n */\n root?: Element | ShadowRoot | null;\n /**\n * ID of the `<style>` element injected into the document head.\n * Defaults to `'cer-dom-jit-css'`.\n */\n styleId?: string;\n}\n\n/** Public handle returned by `createDOMJITCSS()`. */\nexport interface DOMJITCSSHandle {\n /** Start observing the DOM and injecting utility CSS. */\n mount(): void;\n /** Stop observing and remove the injected stylesheet. */\n destroy(): void;\n /** Get the number of unique classes processed so far. */\n readonly processedCount: number;\n}\n\n/**\n * Create a DOM JIT CSS instance that watches class attribute changes and\n * injects CSS utility rules into the document.\n *\n * @param options - Configuration options.\n * @returns A handle with `mount()` and `destroy()` methods.\n */\nexport function createDOMJITCSS(\n options: DOMJITCSSOptions = {},\n): DOMJITCSSHandle {\n const {\n root: rootOption,\n styleId = 'cer-dom-jit-css',\n ...jitOptions\n } = options;\n\n // Apply JIT CSS options (e.g. extendedColors, customColors) globally\n if (Object.keys(jitOptions).length > 0) {\n enableJITCSS(jitOptions);\n }\n\n // Monotonically growing set of processed class names.\n // We never shrink this — rules remain valid even if classes are removed.\n const processedClasses = new Set<string>();\n // CSS text that has been injected. Grown incrementally.\n let injectedCSS = '';\n\n let styleEl: HTMLStyleElement | null = null;\n let adoptedSheet: CSSStyleSheet | null = null;\n let useAdoptedSheet = false;\n let observer: MutationObserver | null = null;\n let pendingClasses = new Set<string>();\n let flushScheduled = false;\n let isMounted = false;\n // The target for adoptedStyleSheets / <style> injection. Set during mount().\n // When rootOption is a ShadowRoot the sheet is scoped to that shadow tree;\n // otherwise styles are adopted by the host document.\n let adoptionTarget: Document | ShadowRoot | null = null;\n\n function injectStylesheet(): void {\n if (typeof document === 'undefined') return;\n\n // Scope stylesheet injection to the shadow root when one was supplied,\n // so the generated utility classes do not leak into the host document.\n adoptionTarget = rootOption instanceof ShadowRoot ? rootOption : document;\n\n // Try constructable stylesheets first (faster incremental updates)\n if (\n typeof CSSStyleSheet !== 'undefined' &&\n 'replaceSync' in CSSStyleSheet.prototype &&\n adoptionTarget.adoptedStyleSheets !== undefined\n ) {\n try {\n adoptedSheet = new CSSStyleSheet();\n adoptionTarget.adoptedStyleSheets = [\n ...adoptionTarget.adoptedStyleSheets,\n adoptedSheet,\n ];\n useAdoptedSheet = true;\n return;\n } catch {\n // Fall through to style element\n }\n }\n\n // Fallback: a plain <style> element.\n // For a ShadowRoot target, append directly inside the shadow tree.\n // ShadowRoot has no getElementById(), so we always create a fresh element.\n if (rootOption instanceof ShadowRoot) {\n styleEl = document.createElement('style');\n styleEl.id = styleId;\n rootOption.appendChild(styleEl);\n } else {\n styleEl = document.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = styleId;\n (document.head ?? document.documentElement).appendChild(styleEl);\n }\n }\n }\n\n function applyNewCSS(css: string): void {\n if (!css) return;\n injectedCSS += `\\n${css}`;\n if (useAdoptedSheet && adoptedSheet) {\n try {\n // Replace the entire sheet with the accumulated CSS wrapped in a single\n // @layer block. replaceSync handles nested at-rules (@media, @container,\n // @supports) correctly — the previous insertRule approach used a flat\n // regex that stripped at-rule wrappers, causing dark: and responsive\n // variants to apply unconditionally.\n adoptedSheet.replaceSync(`@layer cer-utilities {\\n${injectedCSS}\\n}`);\n return;\n } catch {\n // Fall through to style element\n }\n }\n if (styleEl) {\n // Wrap everything in a single @layer block for the <style> fallback path\n styleEl.textContent = `@layer cer-utilities {\\n${injectedCSS}\\n}`;\n }\n }\n\n function extractClasses(el: Element): string[] {\n const cls = el.getAttribute('class');\n if (!cls) return [];\n return cls.split(/\\s+/).filter(Boolean);\n }\n\n function scheduleFlush(): void {\n if (flushScheduled) return;\n flushScheduled = true;\n queueMicrotask(flushPending);\n }\n\n function flushPending(): void {\n flushScheduled = false;\n if (pendingClasses.size === 0) return;\n\n // Compute delta — only process classes we haven't seen before\n const newClasses: string[] = [];\n for (const cls of pendingClasses) {\n if (!processedClasses.has(cls)) {\n processedClasses.add(cls);\n newClasses.push(cls);\n }\n }\n pendingClasses = new Set<string>();\n\n if (newClasses.length === 0) return;\n\n // Build a minimal HTML string containing only the new class names so\n // the jitCSS engine parses only the delta (not the full DOM).\n const fakeHTML = `<div class=\"${newClasses.join(' ')}\"></div>`;\n const newCSS = jitCSS(fakeHTML);\n if (newCSS) {\n applyNewCSS(newCSS);\n }\n }\n\n function addClassesFromElement(el: Element): void {\n for (const cls of extractClasses(el)) {\n pendingClasses.add(cls);\n }\n }\n\n function scanSubtree(root: Element | Document | ShadowRoot): void {\n // Use TreeWalker for maximum performance on initial scan\n const walker = document.createTreeWalker(\n root instanceof Document ? document.body : (root as Node),\n NodeFilter.SHOW_ELEMENT,\n );\n let node: Node | null = walker.currentNode;\n while (node) {\n if (node instanceof Element) {\n addClassesFromElement(node);\n }\n node = walker.nextNode();\n }\n scheduleFlush();\n }\n\n function getObserverRoot(): Element | ShadowRoot | null {\n if (rootOption) {\n // Return the ShadowRoot directly so the MutationObserver observes inside\n // the shadow tree. Previously we returned rootOption.host which caused the\n // observer to watch the light DOM of the host element instead.\n return rootOption;\n }\n\n // Auto-detect [data-jitcss] elements\n if (typeof document !== 'undefined') {\n const scoped = document.querySelectorAll('[data-jitcss]');\n if (scoped.length > 0) {\n // Use the first scoped element; if multiple, observe body\n return scoped.length === 1 ? (scoped[0] as Element) : document.body;\n }\n return document.body;\n }\n\n return null;\n }\n\n function getDataJITCSSMode(el: Element): 'container' | 'self' | 'global' {\n const val = el.getAttribute('data-jitcss');\n if (val === 'self') return 'self';\n if (val === 'global') return 'global';\n return 'container';\n }\n\n function mount(): void {\n if (isMounted) return;\n isMounted = true;\n\n injectStylesheet();\n\n const observerRoot = getObserverRoot();\n if (!observerRoot) return;\n\n // ShadowRoot does not inherit hasAttribute() from Element; guard with an\n // instanceof check so passing a ShadowRoot as root does not throw.\n const mode =\n observerRoot instanceof Element &&\n observerRoot.hasAttribute('data-jitcss')\n ? getDataJITCSSMode(observerRoot)\n : 'container';\n const actualRoot = mode === 'global' ? document.body : observerRoot;\n\n // Initial scan\n if (mode === 'self' && actualRoot instanceof Element) {\n addClassesFromElement(actualRoot);\n scheduleFlush();\n } else {\n scanSubtree(actualRoot);\n }\n\n // Set up MutationObserver\n observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'class'\n ) {\n if (mutation.target instanceof Element) {\n addClassesFromElement(mutation.target);\n }\n } else if (mutation.type === 'childList') {\n for (const node of mutation.addedNodes) {\n if (node instanceof Element) {\n if (mode === 'self') continue; // Only own classes in self mode\n // scanSubtree already processes the root element as its first\n // walker node, so a separate addClassesFromElement call here\n // would process the same element twice.\n scanSubtree(node);\n }\n }\n }\n }\n scheduleFlush();\n });\n\n observer.observe(actualRoot, {\n subtree: mode !== 'self',\n attributes: true,\n attributeFilter: ['class'],\n childList: mode !== 'self',\n characterData: false,\n });\n }\n\n function destroy(): void {\n if (!isMounted) return;\n isMounted = false;\n\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n\n // Remove injected styles\n if (useAdoptedSheet && adoptedSheet) {\n try {\n const target = adoptionTarget ?? document;\n target.adoptedStyleSheets = target.adoptedStyleSheets.filter(\n (s) => s !== adoptedSheet,\n );\n } catch {\n // ignore\n }\n adoptedSheet = null;\n }\n\n if (styleEl) {\n styleEl.remove();\n styleEl = null;\n }\n\n processedClasses.clear();\n pendingClasses.clear();\n injectedCSS = '';\n flushScheduled = false;\n adoptionTarget = null;\n }\n\n return {\n mount,\n destroy,\n get processedCount() {\n return processedClasses.size;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"custom-elements-runtime.dom-jit-css.es.js","names":[],"sources":["../src/lib/dom-jit-css.ts"],"sourcesContent":["/**\n * Non-Shadow DOM JIT CSS runtime scanner.\n *\n * Watches real DOM elements for class changes and injects utility CSS into\n * a shared `<style>` element (or constructable stylesheet) in the host document.\n *\n * @example\n * ```ts\n * import { createDOMJITCSS } from '@jasonshimmy/custom-elements-runtime/dom-jit-css';\n *\n * // Watch the full document body\n * const jit = createDOMJITCSS();\n * jit.mount();\n *\n * // Watch a specific container element\n * const jit = createDOMJITCSS({ root: document.getElementById('app')! });\n * jit.mount();\n *\n * // Tear down when no longer needed\n * jit.destroy();\n * ```\n *\n * ## `data-jitcss` attribute semantics\n *\n * | Attribute value | Behaviour |\n * | ------------------------------------------------------ | ----------------------------------------------------------------- |\n * | `data-jitcss` (no value) or `data-jitcss=\"container\"` | Scopes the observer to that element and its subtree |\n * | `data-jitcss=\"self\"` | Only processes classes on that exact element, not descendants |\n * | `data-jitcss=\"global\"` | Observer covers `document.body` (useful on `<html>` or `<body>`) |\n *\n * When `createDOMJITCSS()` is called with no `root`, it auto-detects all\n * `[data-jitcss]` elements and registers an observer for each.\n */\n\nimport { jitCSS, enableJITCSS, type JITCSSOptions } from './runtime/style';\n\n/**\n * Options for `createDOMJITCSS()`.\n */\nexport interface DOMJITCSSOptions extends JITCSSOptions {\n /**\n * The root element to observe. Defaults to auto-detecting `[data-jitcss]`\n * elements, then falling back to `document.body`.\n */\n root?: Element | ShadowRoot | null;\n /**\n * ID of the `<style>` element injected into the document head.\n * Defaults to `'cer-dom-jit-css'`.\n */\n styleId?: string;\n}\n\n/** Public handle returned by `createDOMJITCSS()`. */\nexport interface DOMJITCSSHandle {\n /** Start observing the DOM and injecting utility CSS. */\n mount(): void;\n /** Stop observing and remove the injected stylesheet. */\n destroy(): void;\n /** Get the number of unique classes processed so far. */\n readonly processedCount: number;\n}\n\n/**\n * Create a DOM JIT CSS instance that watches class attribute changes and\n * injects CSS utility rules into the document.\n *\n * @param options - Configuration options.\n * @returns A handle with `mount()` and `destroy()` methods.\n */\nexport function createDOMJITCSS(\n options: DOMJITCSSOptions = {},\n): DOMJITCSSHandle {\n const {\n root: rootOption,\n styleId = 'cer-dom-jit-css',\n ...jitOptions\n } = options;\n\n // Apply JIT CSS options (e.g. extendedColors, customColors) globally\n if (Object.keys(jitOptions).length > 0) {\n enableJITCSS(jitOptions);\n }\n\n // Monotonically growing set of processed class names.\n // We never shrink this — rules remain valid even if classes are removed.\n const processedClasses = new Set<string>();\n // CSS text that has been injected. Grown incrementally.\n let injectedCSS = '';\n\n let styleEl: HTMLStyleElement | null = null;\n let adoptedSheet: CSSStyleSheet | null = null;\n let useAdoptedSheet = false;\n let observer: MutationObserver | null = null;\n let pendingClasses = new Set<string>();\n let flushScheduled = false;\n let isMounted = false;\n // The target for adoptedStyleSheets / <style> injection. Set during mount().\n // When rootOption is a ShadowRoot the sheet is scoped to that shadow tree;\n // otherwise styles are adopted by the host document.\n let adoptionTarget: Document | ShadowRoot | null = null;\n\n function injectStylesheet(): void {\n if (typeof document === 'undefined') return;\n\n // Scope stylesheet injection to the shadow root when one was supplied,\n // so the generated utility classes do not leak into the host document.\n adoptionTarget = rootOption instanceof ShadowRoot ? rootOption : document;\n\n // Try constructable stylesheets first (faster incremental updates)\n if (\n typeof CSSStyleSheet !== 'undefined' &&\n 'replaceSync' in CSSStyleSheet.prototype &&\n adoptionTarget.adoptedStyleSheets !== undefined\n ) {\n try {\n adoptedSheet = new CSSStyleSheet();\n adoptionTarget.adoptedStyleSheets = [\n ...adoptionTarget.adoptedStyleSheets,\n adoptedSheet,\n ];\n useAdoptedSheet = true;\n return;\n } catch {\n // Fall through to style element\n }\n }\n\n // Fallback: a plain <style> element.\n // For a ShadowRoot target, append directly inside the shadow tree.\n // ShadowRoot has no getElementById(), so we always create a fresh element.\n if (rootOption instanceof ShadowRoot) {\n styleEl = document.createElement('style');\n styleEl.id = styleId;\n rootOption.appendChild(styleEl);\n } else {\n styleEl = document.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = styleId;\n (document.head ?? document.documentElement).appendChild(styleEl);\n }\n }\n }\n\n function applyNewCSS(css: string): void {\n if (!css) return;\n injectedCSS += `\\n${css}`;\n if (useAdoptedSheet && adoptedSheet) {\n try {\n // Replace the entire sheet with the accumulated CSS wrapped in a single\n // @layer block. replaceSync handles nested at-rules (@media, @container,\n // @supports) correctly — the previous insertRule approach used a flat\n // regex that stripped at-rule wrappers, causing dark: and responsive\n // variants to apply unconditionally.\n adoptedSheet.replaceSync(`@layer cer-utilities {\\n${injectedCSS}\\n}`);\n return;\n } catch {\n // Fall through to style element\n }\n }\n if (styleEl) {\n // Wrap everything in a single @layer block for the <style> fallback path\n styleEl.textContent = `@layer cer-utilities {\\n${injectedCSS}\\n}`;\n }\n }\n\n function extractClasses(el: Element): string[] {\n const cls = el.getAttribute('class');\n if (!cls) return [];\n return cls.split(/\\s+/).filter(Boolean);\n }\n\n function scheduleFlush(): void {\n if (flushScheduled) return;\n flushScheduled = true;\n queueMicrotask(flushPending);\n }\n\n function flushPending(): void {\n flushScheduled = false;\n if (pendingClasses.size === 0) return;\n\n // Compute delta — only process classes we haven't seen before\n const newClasses: string[] = [];\n for (const cls of pendingClasses) {\n if (!processedClasses.has(cls)) {\n processedClasses.add(cls);\n newClasses.push(cls);\n }\n }\n pendingClasses = new Set<string>();\n\n if (newClasses.length === 0) return;\n\n // Build a minimal HTML string containing only the new class names so\n // the jitCSS engine parses only the delta (not the full DOM).\n const fakeHTML = `<div class=\"${newClasses.join(' ')}\"></div>`;\n const newCSS = jitCSS(fakeHTML);\n if (newCSS) {\n applyNewCSS(newCSS);\n }\n }\n\n function addClassesFromElement(el: Element): void {\n for (const cls of extractClasses(el)) {\n pendingClasses.add(cls);\n }\n }\n\n function scanSubtree(root: Element | Document | ShadowRoot): void {\n // Use TreeWalker for maximum performance on initial scan\n const walker = document.createTreeWalker(\n root instanceof Document ? document.body : (root as Node),\n NodeFilter.SHOW_ELEMENT,\n );\n let node: Node | null = walker.currentNode;\n while (node) {\n if (node instanceof Element) {\n addClassesFromElement(node);\n }\n node = walker.nextNode();\n }\n scheduleFlush();\n }\n\n function getObserverRoot(): Element | ShadowRoot | null {\n if (rootOption) {\n // Return the ShadowRoot directly so the MutationObserver observes inside\n // the shadow tree. Previously we returned rootOption.host which caused the\n // observer to watch the light DOM of the host element instead.\n return rootOption;\n }\n\n // Auto-detect [data-jitcss] elements\n if (typeof document !== 'undefined') {\n const scoped = document.querySelectorAll('[data-jitcss]');\n if (scoped.length > 0) {\n // Use the first scoped element; if multiple, observe body\n return scoped.length === 1 ? (scoped[0] as Element) : document.body;\n }\n return document.body;\n }\n\n return null;\n }\n\n function getDataJITCSSMode(el: Element): 'container' | 'self' | 'global' {\n const val = el.getAttribute('data-jitcss');\n if (val === 'self') return 'self';\n if (val === 'global') return 'global';\n return 'container';\n }\n\n function mount(): void {\n if (isMounted) return;\n isMounted = true;\n\n injectStylesheet();\n\n const observerRoot = getObserverRoot();\n if (!observerRoot) return;\n\n // ShadowRoot does not inherit hasAttribute() from Element; guard with an\n // instanceof check so passing a ShadowRoot as root does not throw.\n const mode =\n observerRoot instanceof Element &&\n observerRoot.hasAttribute('data-jitcss')\n ? getDataJITCSSMode(observerRoot)\n : 'container';\n const actualRoot = mode === 'global' ? document.body : observerRoot;\n\n // Initial scan\n if (mode === 'self' && actualRoot instanceof Element) {\n addClassesFromElement(actualRoot);\n scheduleFlush();\n } else {\n scanSubtree(actualRoot);\n }\n\n // Set up MutationObserver\n observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (\n mutation.type === 'attributes' &&\n mutation.attributeName === 'class'\n ) {\n if (mutation.target instanceof Element) {\n addClassesFromElement(mutation.target);\n }\n } else if (mutation.type === 'childList') {\n for (const node of mutation.addedNodes) {\n if (node instanceof Element) {\n if (mode === 'self') continue; // Only own classes in self mode\n // scanSubtree already processes the root element as its first\n // walker node, so a separate addClassesFromElement call here\n // would process the same element twice.\n scanSubtree(node);\n }\n }\n }\n }\n scheduleFlush();\n });\n\n observer.observe(actualRoot, {\n subtree: mode !== 'self',\n attributes: true,\n attributeFilter: ['class'],\n childList: mode !== 'self',\n characterData: false,\n });\n }\n\n function destroy(): void {\n if (!isMounted) return;\n isMounted = false;\n\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n\n // Remove injected styles\n if (useAdoptedSheet && adoptedSheet) {\n try {\n const target = adoptionTarget ?? document;\n target.adoptedStyleSheets = target.adoptedStyleSheets.filter(\n (s) => s !== adoptedSheet,\n );\n } catch {\n // ignore\n }\n adoptedSheet = null;\n }\n\n if (styleEl) {\n styleEl.remove();\n styleEl = null;\n }\n\n processedClasses.clear();\n pendingClasses.clear();\n injectedCSS = '';\n flushScheduled = false;\n adoptionTarget = null;\n }\n\n return {\n mount,\n destroy,\n get processedCount() {\n return processedClasses.size;\n },\n };\n}\n"],"mappings":"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"}