@symbo.ls/scratch 3.8.6 → 3.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/set.js CHANGED
@@ -101,14 +101,37 @@ const setEach = (factoryName, props) => {
101
101
  const changeGlobalTheme = (newTheme) => {
102
102
  const CONFIG = (0, import_factory.getActiveConfig)();
103
103
  CONFIG.globalTheme = newTheme;
104
+ if (typeof document !== "undefined" && newTheme && newTheme !== "auto") {
105
+ document.documentElement.setAttribute("data-theme", newTheme);
106
+ }
104
107
  for (const key in CONFIG.CSS_VARS) {
105
108
  if (key.startsWith("--theme-")) delete CONFIG.CSS_VARS[key];
106
109
  }
107
110
  for (const key in CONFIG.CSS_MEDIA_VARS) {
108
111
  delete CONFIG.CSS_MEDIA_VARS[key];
109
112
  }
110
- if (CONFIG.theme) {
111
- setEach("theme", CONFIG.theme);
113
+ const source = CONFIG._originalTheme || CONFIG.theme;
114
+ if (source) {
115
+ const fresh = JSON.parse(JSON.stringify(source));
116
+ CONFIG.theme = fresh;
117
+ setEach("theme", fresh);
118
+ }
119
+ if (typeof document !== "undefined" && CONFIG.CSS_VARS) {
120
+ const sheets = document.styleSheets;
121
+ for (let i = 0; i < sheets.length; i++) {
122
+ try {
123
+ const rules = sheets[i].cssRules;
124
+ for (let j = 0; j < rules.length; j++) {
125
+ if (rules[j].selectorText === ":root") {
126
+ for (const key in CONFIG.CSS_VARS) {
127
+ rules[j].style.setProperty(key, CONFIG.CSS_VARS[key]);
128
+ }
129
+ return CONFIG;
130
+ }
131
+ }
132
+ } catch (e) {
133
+ }
134
+ }
112
135
  }
113
136
  return CONFIG;
114
137
  };
@@ -155,6 +178,9 @@ const set = (recivedConfig, options = SET_OPTIONS) => {
155
178
  CONFIG.SEMANTIC_ICONS = CONFIG.semantic_icons;
156
179
  }
157
180
  if (CONFIG.verbose) console.log(CONFIG);
181
+ if (typeof document !== "undefined" && CONFIG.globalTheme && CONFIG.globalTheme !== "auto") {
182
+ document.documentElement.setAttribute("data-theme", CONFIG.globalTheme);
183
+ }
158
184
  if (!CONFIG.__svg_cache) CONFIG.__svg_cache = {};
159
185
  const keys = Object.keys(config);
160
186
  const keySet = new Set(keys);
@@ -164,6 +190,9 @@ const set = (recivedConfig, options = SET_OPTIONS) => {
164
190
  (0, import_utils.deepMerge)(config[lower], config[key]);
165
191
  }
166
192
  });
193
+ if (config.theme && !CONFIG._originalTheme) {
194
+ CONFIG._originalTheme = JSON.parse(JSON.stringify(config.theme));
195
+ }
167
196
  keys.map((key) => {
168
197
  const lower = key.toLowerCase();
169
198
  if (lower !== key && keySet.has(lower)) return;
@@ -60,9 +60,9 @@ const appendSvgIconsSprite = (LIBRARY, options = DEF_OPTIONS) => {
60
60
  for (const key in LIBRARY) lib[key] = CONFIG.icons[key];
61
61
  appendSVG(lib, options);
62
62
  };
63
- const createSVGSpriteElement = (options = { isRoot: true }) => {
64
- if (!import_utils.document || !import_utils.document.createElementNS) return;
65
- const svgElem = import_utils.document.createElementNS("http://www.w3.org/2000/svg", "svg");
63
+ const createSVGSpriteElement = (doc, options = { isRoot: true }) => {
64
+ if (!doc || !doc.createElementNS) return;
65
+ const svgElem = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
66
66
  if (options.isRoot) {
67
67
  svgElem.setAttribute("aria-hidden", "true");
68
68
  svgElem.setAttribute("width", "0");
@@ -83,15 +83,24 @@ const appendSVG = (lib, options = DEF_OPTIONS) => {
83
83
  }
84
84
  const exists = doc.querySelector("#svgSprite");
85
85
  const SVGsprite = (0, import_utils2.generateSprite)(lib);
86
+ const spriteHtml = `<svg aria-hidden="true" width="0" height="0" style="position:absolute" id="svgSprite">${SVGsprite}</svg>`;
86
87
  if (exists) {
87
- const tempSVG = createSVGSpriteElement({ isRoot: false });
88
- tempSVG.innerHTML = SVGsprite;
89
- exists.append(...tempSVG.children);
88
+ if (doc.body.insertAdjacentHTML) {
89
+ exists.insertAdjacentHTML("beforeend", SVGsprite);
90
+ } else {
91
+ const tempSVG = createSVGSpriteElement(doc, { isRoot: false });
92
+ tempSVG.innerHTML = SVGsprite;
93
+ exists.append(...tempSVG.children);
94
+ }
90
95
  } else {
91
- const svgSpriteDOM = createSVGSpriteElement();
92
- if (svgSpriteDOM && svgSpriteDOM.nodeType) {
93
- svgSpriteDOM.innerHTML = SVGsprite;
94
- doc.body.prepend(svgSpriteDOM);
96
+ if (doc.body.insertAdjacentHTML) {
97
+ doc.body.insertAdjacentHTML("afterbegin", spriteHtml);
98
+ } else {
99
+ const svgSpriteDOM = createSVGSpriteElement(doc);
100
+ if (svgSpriteDOM && svgSpriteDOM.nodeType) {
101
+ svgSpriteDOM.innerHTML = SVGsprite;
102
+ doc.body.prepend(svgSpriteDOM);
103
+ }
95
104
  }
96
105
  }
97
106
  };
package/dist/esm/set.js CHANGED
@@ -88,14 +88,37 @@ const setEach = (factoryName, props) => {
88
88
  const changeGlobalTheme = (newTheme) => {
89
89
  const CONFIG = getActiveConfig();
90
90
  CONFIG.globalTheme = newTheme;
91
+ if (typeof document !== "undefined" && newTheme && newTheme !== "auto") {
92
+ document.documentElement.setAttribute("data-theme", newTheme);
93
+ }
91
94
  for (const key in CONFIG.CSS_VARS) {
92
95
  if (key.startsWith("--theme-")) delete CONFIG.CSS_VARS[key];
93
96
  }
94
97
  for (const key in CONFIG.CSS_MEDIA_VARS) {
95
98
  delete CONFIG.CSS_MEDIA_VARS[key];
96
99
  }
97
- if (CONFIG.theme) {
98
- setEach("theme", CONFIG.theme);
100
+ const source = CONFIG._originalTheme || CONFIG.theme;
101
+ if (source) {
102
+ const fresh = JSON.parse(JSON.stringify(source));
103
+ CONFIG.theme = fresh;
104
+ setEach("theme", fresh);
105
+ }
106
+ if (typeof document !== "undefined" && CONFIG.CSS_VARS) {
107
+ const sheets = document.styleSheets;
108
+ for (let i = 0; i < sheets.length; i++) {
109
+ try {
110
+ const rules = sheets[i].cssRules;
111
+ for (let j = 0; j < rules.length; j++) {
112
+ if (rules[j].selectorText === ":root") {
113
+ for (const key in CONFIG.CSS_VARS) {
114
+ rules[j].style.setProperty(key, CONFIG.CSS_VARS[key]);
115
+ }
116
+ return CONFIG;
117
+ }
118
+ }
119
+ } catch (e) {
120
+ }
121
+ }
99
122
  }
100
123
  return CONFIG;
101
124
  };
@@ -142,6 +165,9 @@ const set = (recivedConfig, options = SET_OPTIONS) => {
142
165
  CONFIG.SEMANTIC_ICONS = CONFIG.semantic_icons;
143
166
  }
144
167
  if (CONFIG.verbose) console.log(CONFIG);
168
+ if (typeof document !== "undefined" && CONFIG.globalTheme && CONFIG.globalTheme !== "auto") {
169
+ document.documentElement.setAttribute("data-theme", CONFIG.globalTheme);
170
+ }
145
171
  if (!CONFIG.__svg_cache) CONFIG.__svg_cache = {};
146
172
  const keys = Object.keys(config);
147
173
  const keySet = new Set(keys);
@@ -151,6 +177,9 @@ const set = (recivedConfig, options = SET_OPTIONS) => {
151
177
  deepMerge(config[lower], config[key]);
152
178
  }
153
179
  });
180
+ if (config.theme && !CONFIG._originalTheme) {
181
+ CONFIG._originalTheme = JSON.parse(JSON.stringify(config.theme));
182
+ }
154
183
  keys.map((key) => {
155
184
  const lower = key.toLowerCase();
156
185
  if (lower !== key && keySet.has(lower)) return;
@@ -34,9 +34,9 @@ const appendSvgIconsSprite = (LIBRARY, options = DEF_OPTIONS) => {
34
34
  for (const key in LIBRARY) lib[key] = CONFIG.icons[key];
35
35
  appendSVG(lib, options);
36
36
  };
37
- const createSVGSpriteElement = (options = { isRoot: true }) => {
38
- if (!document || !document.createElementNS) return;
39
- const svgElem = document.createElementNS("http://www.w3.org/2000/svg", "svg");
37
+ const createSVGSpriteElement = (doc, options = { isRoot: true }) => {
38
+ if (!doc || !doc.createElementNS) return;
39
+ const svgElem = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
40
40
  if (options.isRoot) {
41
41
  svgElem.setAttribute("aria-hidden", "true");
42
42
  svgElem.setAttribute("width", "0");
@@ -57,15 +57,24 @@ const appendSVG = (lib, options = DEF_OPTIONS) => {
57
57
  }
58
58
  const exists = doc.querySelector("#svgSprite");
59
59
  const SVGsprite = generateSprite(lib);
60
+ const spriteHtml = `<svg aria-hidden="true" width="0" height="0" style="position:absolute" id="svgSprite">${SVGsprite}</svg>`;
60
61
  if (exists) {
61
- const tempSVG = createSVGSpriteElement({ isRoot: false });
62
- tempSVG.innerHTML = SVGsprite;
63
- exists.append(...tempSVG.children);
62
+ if (doc.body.insertAdjacentHTML) {
63
+ exists.insertAdjacentHTML("beforeend", SVGsprite);
64
+ } else {
65
+ const tempSVG = createSVGSpriteElement(doc, { isRoot: false });
66
+ tempSVG.innerHTML = SVGsprite;
67
+ exists.append(...tempSVG.children);
68
+ }
64
69
  } else {
65
- const svgSpriteDOM = createSVGSpriteElement();
66
- if (svgSpriteDOM && svgSpriteDOM.nodeType) {
67
- svgSpriteDOM.innerHTML = SVGsprite;
68
- doc.body.prepend(svgSpriteDOM);
70
+ if (doc.body.insertAdjacentHTML) {
71
+ doc.body.insertAdjacentHTML("afterbegin", spriteHtml);
72
+ } else {
73
+ const svgSpriteDOM = createSVGSpriteElement(doc);
74
+ if (svgSpriteDOM && svgSpriteDOM.nodeType) {
75
+ svgSpriteDOM.innerHTML = SVGsprite;
76
+ doc.body.prepend(svgSpriteDOM);
77
+ }
69
78
  }
70
79
  }
71
80
  };
@@ -182,6 +182,7 @@ var SmblsScratch = (() => {
182
182
  exec = (param, element, state, context) => {
183
183
  if (isFunction(param)) {
184
184
  if (!element) return;
185
+ if (typeof param.call !== "function") return param;
185
186
  const result = param.call(
186
187
  element,
187
188
  element,
@@ -2709,9 +2710,9 @@ var SmblsScratch = (() => {
2709
2710
  for (const key in LIBRARY) lib[key] = CONFIG2.icons[key];
2710
2711
  appendSVG(lib, options);
2711
2712
  };
2712
- var createSVGSpriteElement = (options = { isRoot: true }) => {
2713
- if (!document2 || !document2.createElementNS) return;
2714
- const svgElem = document2.createElementNS("http://www.w3.org/2000/svg", "svg");
2713
+ var createSVGSpriteElement = (doc, options = { isRoot: true }) => {
2714
+ if (!doc || !doc.createElementNS) return;
2715
+ const svgElem = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
2715
2716
  if (options.isRoot) {
2716
2717
  svgElem.setAttribute("aria-hidden", "true");
2717
2718
  svgElem.setAttribute("width", "0");
@@ -2732,15 +2733,24 @@ var SmblsScratch = (() => {
2732
2733
  }
2733
2734
  const exists = doc.querySelector("#svgSprite");
2734
2735
  const SVGsprite = generateSprite(lib);
2736
+ const spriteHtml = `<svg aria-hidden="true" width="0" height="0" style="position:absolute" id="svgSprite">${SVGsprite}</svg>`;
2735
2737
  if (exists) {
2736
- const tempSVG = createSVGSpriteElement({ isRoot: false });
2737
- tempSVG.innerHTML = SVGsprite;
2738
- exists.append(...tempSVG.children);
2738
+ if (doc.body.insertAdjacentHTML) {
2739
+ exists.insertAdjacentHTML("beforeend", SVGsprite);
2740
+ } else {
2741
+ const tempSVG = createSVGSpriteElement(doc, { isRoot: false });
2742
+ tempSVG.innerHTML = SVGsprite;
2743
+ exists.append(...tempSVG.children);
2744
+ }
2739
2745
  } else {
2740
- const svgSpriteDOM = createSVGSpriteElement();
2741
- if (svgSpriteDOM && svgSpriteDOM.nodeType) {
2742
- svgSpriteDOM.innerHTML = SVGsprite;
2743
- doc.body.prepend(svgSpriteDOM);
2746
+ if (doc.body.insertAdjacentHTML) {
2747
+ doc.body.insertAdjacentHTML("afterbegin", spriteHtml);
2748
+ } else {
2749
+ const svgSpriteDOM = createSVGSpriteElement(doc);
2750
+ if (svgSpriteDOM && svgSpriteDOM.nodeType) {
2751
+ svgSpriteDOM.innerHTML = SVGsprite;
2752
+ doc.body.prepend(svgSpriteDOM);
2753
+ }
2744
2754
  }
2745
2755
  }
2746
2756
  };
@@ -3067,14 +3077,37 @@ var SmblsScratch = (() => {
3067
3077
  var changeGlobalTheme = (newTheme) => {
3068
3078
  const CONFIG2 = getActiveConfig();
3069
3079
  CONFIG2.globalTheme = newTheme;
3080
+ if (typeof document !== "undefined" && newTheme && newTheme !== "auto") {
3081
+ document.documentElement.setAttribute("data-theme", newTheme);
3082
+ }
3070
3083
  for (const key in CONFIG2.CSS_VARS) {
3071
3084
  if (key.startsWith("--theme-")) delete CONFIG2.CSS_VARS[key];
3072
3085
  }
3073
3086
  for (const key in CONFIG2.CSS_MEDIA_VARS) {
3074
3087
  delete CONFIG2.CSS_MEDIA_VARS[key];
3075
3088
  }
3076
- if (CONFIG2.theme) {
3077
- setEach("theme", CONFIG2.theme);
3089
+ const source = CONFIG2._originalTheme || CONFIG2.theme;
3090
+ if (source) {
3091
+ const fresh = JSON.parse(JSON.stringify(source));
3092
+ CONFIG2.theme = fresh;
3093
+ setEach("theme", fresh);
3094
+ }
3095
+ if (typeof document !== "undefined" && CONFIG2.CSS_VARS) {
3096
+ const sheets = document.styleSheets;
3097
+ for (let i = 0; i < sheets.length; i++) {
3098
+ try {
3099
+ const rules = sheets[i].cssRules;
3100
+ for (let j = 0; j < rules.length; j++) {
3101
+ if (rules[j].selectorText === ":root") {
3102
+ for (const key in CONFIG2.CSS_VARS) {
3103
+ rules[j].style.setProperty(key, CONFIG2.CSS_VARS[key]);
3104
+ }
3105
+ return CONFIG2;
3106
+ }
3107
+ }
3108
+ } catch (e) {
3109
+ }
3110
+ }
3078
3111
  }
3079
3112
  return CONFIG2;
3080
3113
  };
@@ -3121,6 +3154,9 @@ var SmblsScratch = (() => {
3121
3154
  CONFIG2.SEMANTIC_ICONS = CONFIG2.semantic_icons;
3122
3155
  }
3123
3156
  if (CONFIG2.verbose) console.log(CONFIG2);
3157
+ if (typeof document !== "undefined" && CONFIG2.globalTheme && CONFIG2.globalTheme !== "auto") {
3158
+ document.documentElement.setAttribute("data-theme", CONFIG2.globalTheme);
3159
+ }
3124
3160
  if (!CONFIG2.__svg_cache) CONFIG2.__svg_cache = {};
3125
3161
  const keys = Object.keys(config);
3126
3162
  const keySet = new Set(keys);
@@ -3130,6 +3166,9 @@ var SmblsScratch = (() => {
3130
3166
  deepMerge(config[lower], config[key]);
3131
3167
  }
3132
3168
  });
3169
+ if (config.theme && !CONFIG2._originalTheme) {
3170
+ CONFIG2._originalTheme = JSON.parse(JSON.stringify(config.theme));
3171
+ }
3133
3172
  keys.map((key) => {
3134
3173
  const lower = key.toLowerCase();
3135
3174
  if (lower !== key && keySet.has(lower)) return;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@symbo.ls/scratch",
3
3
  "description": "Φ / CSS framework and methodology.",
4
4
  "author": "symbo.ls",
5
- "version": "3.8.6",
5
+ "version": "3.8.8",
6
6
  "files": [
7
7
  "dist",
8
8
  "*.js",
@@ -33,8 +33,8 @@
33
33
  "prepublish": "npm run build && npm run copy:package:cjs"
34
34
  },
35
35
  "dependencies": {
36
- "@domql/utils": "^3.8.6",
37
- "@symbo.ls/smbls-utils": "^3.8.6",
36
+ "@domql/utils": "^3.8.8",
37
+ "@symbo.ls/smbls-utils": "^3.8.8",
38
38
  "color-contrast-checker": "^1.5.0"
39
39
  },
40
40
  "gitHead": "9fc1b79b41cdc725ca6b24aec64920a599634681",
package/src/set.js CHANGED
@@ -109,6 +109,11 @@ export const changeGlobalTheme = (newTheme) => {
109
109
  const CONFIG = getActiveConfig()
110
110
  CONFIG.globalTheme = newTheme
111
111
 
112
+ // Set data-theme attribute on document element for CSS selector-based theming
113
+ if (typeof document !== 'undefined' && newTheme && newTheme !== 'auto') {
114
+ document.documentElement.setAttribute('data-theme', newTheme)
115
+ }
116
+
112
117
  // Clear theme-related CSS vars
113
118
  for (const key in CONFIG.CSS_VARS) {
114
119
  if (key.startsWith('--theme-')) delete CONFIG.CSS_VARS[key]
@@ -119,9 +124,31 @@ export const changeGlobalTheme = (newTheme) => {
119
124
  delete CONFIG.CSS_MEDIA_VARS[key]
120
125
  }
121
126
 
122
- // Re-process all themes with the new globalTheme
123
- if (CONFIG.theme) {
124
- setEach('theme', CONFIG.theme)
127
+ // Re-process themes from original definitions (not mutated processed ones)
128
+ const source = CONFIG._originalTheme || CONFIG.theme
129
+ if (source) {
130
+ // Deep clone to avoid re-mutating the originals
131
+ const fresh = JSON.parse(JSON.stringify(source))
132
+ CONFIG.theme = fresh
133
+ setEach('theme', fresh)
134
+ }
135
+
136
+ // Apply updated CSS vars to the existing :root stylesheet rule
137
+ if (typeof document !== 'undefined' && CONFIG.CSS_VARS) {
138
+ const sheets = document.styleSheets
139
+ for (let i = 0; i < sheets.length; i++) {
140
+ try {
141
+ const rules = sheets[i].cssRules
142
+ for (let j = 0; j < rules.length; j++) {
143
+ if (rules[j].selectorText === ':root') {
144
+ for (const key in CONFIG.CSS_VARS) {
145
+ rules[j].style.setProperty(key, CONFIG.CSS_VARS[key])
146
+ }
147
+ return CONFIG
148
+ }
149
+ }
150
+ } catch (e) { /* cross-origin stylesheet */ }
151
+ }
125
152
  }
126
153
 
127
154
  return CONFIG
@@ -174,6 +201,11 @@ export const set = (recivedConfig, options = SET_OPTIONS) => {
174
201
  }
175
202
  if (CONFIG.verbose) console.log(CONFIG)
176
203
 
204
+ // Set data-theme attribute on document for CSS selector-based theming
205
+ if (typeof document !== 'undefined' && CONFIG.globalTheme && CONFIG.globalTheme !== 'auto') {
206
+ document.documentElement.setAttribute('data-theme', CONFIG.globalTheme)
207
+ }
208
+
177
209
  if (!CONFIG.__svg_cache) CONFIG.__svg_cache = {}
178
210
 
179
211
  const keys = Object.keys(config)
@@ -187,6 +219,11 @@ export const set = (recivedConfig, options = SET_OPTIONS) => {
187
219
  }
188
220
  })
189
221
 
222
+ // Store original theme definitions before processing mutates them
223
+ if (config.theme && !CONFIG._originalTheme) {
224
+ CONFIG._originalTheme = JSON.parse(JSON.stringify(config.theme))
225
+ }
226
+
190
227
  // Process only lowercase keys (skip UPPERCASE when lowercase equivalent exists)
191
228
  keys.map((key) => {
192
229
  const lower = key.toLowerCase()
package/src/system/svg.js CHANGED
@@ -44,9 +44,9 @@ export const appendSvgIconsSprite = (LIBRARY, options = DEF_OPTIONS) => {
44
44
  appendSVG(lib, options)
45
45
  }
46
46
 
47
- const createSVGSpriteElement = (options = { isRoot: true }) => {
48
- if (!document || !document.createElementNS) return
49
- const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
47
+ const createSVGSpriteElement = (doc, options = { isRoot: true }) => {
48
+ if (!doc || !doc.createElementNS) return
49
+ const svgElem = doc.createElementNS('http://www.w3.org/2000/svg', 'svg')
50
50
  if (options.isRoot) {
51
51
  svgElem.setAttribute('aria-hidden', 'true')
52
52
  svgElem.setAttribute('width', '0')
@@ -71,16 +71,25 @@ const appendSVG = (lib, options = DEF_OPTIONS) => {
71
71
  const exists = doc.querySelector('#svgSprite')
72
72
  const SVGsprite = generateSprite(lib)
73
73
 
74
+ const spriteHtml = `<svg aria-hidden="true" width="0" height="0" style="position:absolute" id="svgSprite">${SVGsprite}</svg>`
75
+
74
76
  if (exists) {
75
- const tempSVG = createSVGSpriteElement({ isRoot: false })
76
- // const svgSpriteWithoutRoot = doc.createElement('template')
77
- tempSVG.innerHTML = SVGsprite
78
- exists.append(...tempSVG.children)
77
+ if (doc.body.insertAdjacentHTML) {
78
+ exists.insertAdjacentHTML('beforeend', SVGsprite)
79
+ } else {
80
+ const tempSVG = createSVGSpriteElement(doc, { isRoot: false })
81
+ tempSVG.innerHTML = SVGsprite
82
+ exists.append(...tempSVG.children)
83
+ }
79
84
  } else {
80
- const svgSpriteDOM = createSVGSpriteElement()
81
- if (svgSpriteDOM && svgSpriteDOM.nodeType) {
82
- svgSpriteDOM.innerHTML = SVGsprite
83
- doc.body.prepend(svgSpriteDOM)
85
+ if (doc.body.insertAdjacentHTML) {
86
+ doc.body.insertAdjacentHTML('afterbegin', spriteHtml)
87
+ } else {
88
+ const svgSpriteDOM = createSVGSpriteElement(doc)
89
+ if (svgSpriteDOM && svgSpriteDOM.nodeType) {
90
+ svgSpriteDOM.innerHTML = SVGsprite
91
+ doc.body.prepend(svgSpriteDOM)
92
+ }
84
93
  }
85
94
  }
86
95
  }