hyperclayjs 1.13.0 → 1.14.1
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/README.md +9 -9
- package/package.json +1 -1
- package/src/core/optionVisibility.js +5 -1
- package/src/core/savePage.js +87 -19
- package/src/core/tailwindInject.js +2 -1
- package/src/dom-utilities/insertStyleTag.js +60 -22
- package/src/hyperclay.js +10 -4
- package/src/ui/theModal.js +13 -8
- package/src/utilities/cacheBust.js +4 -3
package/README.md
CHANGED
|
@@ -60,10 +60,10 @@ import 'hyperclayjs/presets/standard.js';
|
|
|
60
60
|
| autosave | 0.9KB | Auto-save on DOM changes |
|
|
61
61
|
| edit-mode | 1.8KB | Toggle edit mode on hyperclay on/off |
|
|
62
62
|
| edit-mode-helpers | 7.5KB | Admin-only functionality: [edit-mode-input], [edit-mode-resource], [edit-mode-onclick] |
|
|
63
|
-
| option-visibility | 5.
|
|
63
|
+
| option-visibility | 5.5KB | Dynamic show/hide based on ancestor state with option:attribute="value" |
|
|
64
64
|
| persist | 2.4KB | Persist input/select/textarea values to the DOM with [persist] attribute |
|
|
65
65
|
| save-core | 6.8KB | Basic save function only - hyperclay.savePage() |
|
|
66
|
-
| save-system |
|
|
66
|
+
| save-system | 9.6KB | CMD+S, [trigger-save] button, savestatus attribute |
|
|
67
67
|
| save-toast | 0.9KB | Toast notifications for save events |
|
|
68
68
|
| snapshot | 7.5KB | Source of truth for page state - captures DOM snapshots for save and sync |
|
|
69
69
|
| tailwind-inject | 0.4KB | Injects tailwind CSS link with cache-bust on save |
|
|
@@ -85,7 +85,7 @@ import 'hyperclayjs/presets/standard.js';
|
|
|
85
85
|
| Module | Size | Description |
|
|
86
86
|
|--------|------|-------------|
|
|
87
87
|
| dialogs | 7.7KB | ask(), consent(), tell(), snippet() dialog functions |
|
|
88
|
-
| the-modal |
|
|
88
|
+
| the-modal | 21KB | Full modal window creation system - window.theModal |
|
|
89
89
|
| toast | 7.9KB | Success/error message notifications, toast(msg, msgType) |
|
|
90
90
|
|
|
91
91
|
### Utilities (Core utilities (often auto-included))
|
|
@@ -106,7 +106,7 @@ import 'hyperclayjs/presets/standard.js';
|
|
|
106
106
|
| all-js | 14.4KB | Full DOM manipulation library |
|
|
107
107
|
| dom-ready | 0.4KB | DOM ready callback |
|
|
108
108
|
| form-data | 2KB | Extract form data as an object |
|
|
109
|
-
| style-injection |
|
|
109
|
+
| style-injection | 4KB | Dynamic stylesheet injection |
|
|
110
110
|
|
|
111
111
|
### String Utilities (String manipulation helpers)
|
|
112
112
|
|
|
@@ -132,17 +132,17 @@ import 'hyperclayjs/presets/standard.js';
|
|
|
132
132
|
|
|
133
133
|
## Presets
|
|
134
134
|
|
|
135
|
-
### Minimal (~
|
|
135
|
+
### Minimal (~40.6KB)
|
|
136
136
|
Essential features for basic editing
|
|
137
137
|
|
|
138
|
-
**Modules:** `save-core`, `save-system`, `edit-mode-helpers`, `toast`, `save-toast`, `export-to-window`
|
|
138
|
+
**Modules:** `save-core`, `snapshot`, `save-system`, `edit-mode-helpers`, `toast`, `save-toast`, `export-to-window`, `view-mode-excludes-edit-modules`
|
|
139
139
|
|
|
140
|
-
### Standard (~
|
|
140
|
+
### Standard (~60.1KB)
|
|
141
141
|
Standard feature set for most use cases
|
|
142
142
|
|
|
143
|
-
**Modules:** `save-core`, `save-system`, `edit-mode-helpers`, `persist`, `option-visibility`, `event-attrs`, `dom-helpers`, `toast`, `save-toast`, `export-to-window`
|
|
143
|
+
**Modules:** `save-core`, `snapshot`, `save-system`, `unsaved-warning`, `edit-mode-helpers`, `persist`, `option-visibility`, `event-attrs`, `dom-helpers`, `toast`, `save-toast`, `export-to-window`, `view-mode-excludes-edit-modules`
|
|
144
144
|
|
|
145
|
-
### Everything (~
|
|
145
|
+
### Everything (~182.3KB)
|
|
146
146
|
All available features
|
|
147
147
|
|
|
148
148
|
Includes all available modules across all categories.
|
package/package.json
CHANGED
|
@@ -118,7 +118,11 @@ const optionVisibility = {
|
|
|
118
118
|
try {
|
|
119
119
|
const attributes = this.findOptionAttributes();
|
|
120
120
|
const css = this.generateCSS(attributes);
|
|
121
|
-
|
|
121
|
+
// mutations-ignore: This style tag is regenerated on load. Without this,
|
|
122
|
+
// the mutation observer would detect it as a change, delaying the settled signal.
|
|
123
|
+
insertStyles(STYLE_NAME, css, (style) => {
|
|
124
|
+
style.setAttribute('mutations-ignore', '');
|
|
125
|
+
});
|
|
122
126
|
this.log(`Generated ${attributes.length} rules`);
|
|
123
127
|
} catch (error) {
|
|
124
128
|
console.error('[OptionVisibility:Layer] Error generating rules:', error);
|
package/src/core/savePage.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import throttle from "../utilities/throttle.js";
|
|
14
|
+
import Mutation from "../utilities/mutation.js";
|
|
14
15
|
import { isEditMode, isOwner } from "./isAdminOfCurrentResource.js";
|
|
15
16
|
import {
|
|
16
17
|
savePage as savePageCore,
|
|
@@ -19,6 +20,11 @@ import {
|
|
|
19
20
|
beforeSave
|
|
20
21
|
} from "./savePageCore.js";
|
|
21
22
|
|
|
23
|
+
// Reset savestatus to 'saved' in snapshots (each module cleans up its own attrs)
|
|
24
|
+
beforeSave(clone => {
|
|
25
|
+
clone.setAttribute('savestatus', 'saved');
|
|
26
|
+
});
|
|
27
|
+
|
|
22
28
|
// ============================================
|
|
23
29
|
// SAVE STATE MANAGEMENT
|
|
24
30
|
// ============================================
|
|
@@ -94,17 +100,6 @@ export function setUnsavedChanges(val) { unsavedChanges = val; }
|
|
|
94
100
|
export function getLastSavedContents() { return lastSavedContents; }
|
|
95
101
|
export function setLastSavedContents(val) { lastSavedContents = val; }
|
|
96
102
|
|
|
97
|
-
// Initialize lastSavedContents on page load to match what's on disk
|
|
98
|
-
// This prevents unnecessary save attempts when content hasn't changed
|
|
99
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
100
|
-
if (isEditMode) {
|
|
101
|
-
// Capture initial state immediately for comparison
|
|
102
|
-
lastSavedContents = getPageContents();
|
|
103
|
-
// Set initial save status to 'saved'
|
|
104
|
-
document.documentElement.setAttribute('savestatus', 'saved');
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
103
|
/**
|
|
109
104
|
* Save the current page with change detection and state management
|
|
110
105
|
*
|
|
@@ -185,14 +180,87 @@ const throttledSave = throttle(savePage, 1200);
|
|
|
185
180
|
// Baseline for autosave comparison
|
|
186
181
|
let baselineContents = '';
|
|
187
182
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
183
|
+
// ============================================
|
|
184
|
+
// BASELINE CAPTURE (Settled Signal)
|
|
185
|
+
// ============================================
|
|
186
|
+
//
|
|
187
|
+
// WHY SETTLED SIGNAL:
|
|
188
|
+
// Modules run on load and mutate the DOM (add styles, modify attributes).
|
|
189
|
+
// A fixed delay (e.g., 1500ms) is arbitrary and either too short (misses slow
|
|
190
|
+
// mutations) or too long (delays baseline). Instead, we wait for mutations to
|
|
191
|
+
// stop, meaning all modules have finished their setup work.
|
|
192
|
+
//
|
|
193
|
+
// WHY IMMEDIATE + CONDITIONAL UPDATE:
|
|
194
|
+
// We set baseline immediately as a safety net. If the user edits or saves
|
|
195
|
+
// before settle completes, we don't overwrite their work. The settled snapshot
|
|
196
|
+
// only replaces baseline if nothing changed (lastSavedContents === immediateContents).
|
|
197
|
+
|
|
198
|
+
const SETTLE_MS = 500; // Wait for no mutations for this long
|
|
199
|
+
const MAX_SETTLE_MS = 3000; // Max time to wait before forcing capture
|
|
200
|
+
|
|
201
|
+
function initBaselineCapture() {
|
|
202
|
+
if (!isEditMode) return;
|
|
203
|
+
|
|
204
|
+
let userEdited = false;
|
|
205
|
+
let settled = false;
|
|
206
|
+
let unsubscribeMutation = null;
|
|
207
|
+
|
|
208
|
+
// Take immediate snapshot and set as baseline right away
|
|
209
|
+
// This ensures saves during settle window work correctly
|
|
210
|
+
const immediateContents = getPageContents();
|
|
211
|
+
lastSavedContents = immediateContents;
|
|
212
|
+
baselineContents = immediateContents;
|
|
213
|
+
|
|
214
|
+
// Track user edits to avoid overwriting real changes
|
|
215
|
+
const userEditEvents = ['input', 'change', 'paste'];
|
|
216
|
+
const markUserEdited = (e) => {
|
|
217
|
+
const target = e.target;
|
|
218
|
+
const isEditable = target.isContentEditable ||
|
|
219
|
+
target.tagName === 'INPUT' ||
|
|
220
|
+
target.tagName === 'TEXTAREA' ||
|
|
221
|
+
target.tagName === 'SELECT';
|
|
222
|
+
if (isEditable) userEdited = true;
|
|
223
|
+
};
|
|
224
|
+
userEditEvents.forEach(evt => document.addEventListener(evt, markUserEdited, true));
|
|
225
|
+
|
|
226
|
+
// Called when mutations settle OR max timeout reached
|
|
227
|
+
const captureBaseline = () => {
|
|
228
|
+
if (settled) return;
|
|
229
|
+
settled = true;
|
|
230
|
+
|
|
231
|
+
// Cleanup listeners
|
|
232
|
+
if (unsubscribeMutation) unsubscribeMutation();
|
|
233
|
+
userEditEvents.forEach(evt => document.removeEventListener(evt, markUserEdited, true));
|
|
234
|
+
|
|
235
|
+
// Only update if no user edits AND no saves occurred during settle
|
|
236
|
+
// (if a save happened, lastSavedContents would differ from immediateContents)
|
|
237
|
+
if (!userEdited && lastSavedContents === immediateContents) {
|
|
238
|
+
const contents = getPageContents();
|
|
239
|
+
lastSavedContents = contents;
|
|
240
|
+
baselineContents = contents;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
document.documentElement.setAttribute('savestatus', 'saved');
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Start settle observer - fires when no mutations for SETTLE_MS
|
|
247
|
+
unsubscribeMutation = Mutation.onAnyChange(
|
|
248
|
+
{ debounce: SETTLE_MS, omitChangeDetails: true },
|
|
249
|
+
captureBaseline
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
// Max timeout fallback
|
|
253
|
+
setTimeout(() => {
|
|
254
|
+
if (!settled) captureBaseline();
|
|
255
|
+
}, MAX_SETTLE_MS);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Run when DOM is ready
|
|
259
|
+
if (document.readyState === 'loading') {
|
|
260
|
+
document.addEventListener('DOMContentLoaded', initBaselineCapture);
|
|
261
|
+
} else {
|
|
262
|
+
initBaselineCapture();
|
|
263
|
+
}
|
|
196
264
|
|
|
197
265
|
/**
|
|
198
266
|
* Save the page with throttling, for use with auto-save
|
|
@@ -5,9 +5,10 @@ function init() {
|
|
|
5
5
|
const currentResource = cookie.get('currentResource');
|
|
6
6
|
if (!currentResource) return;
|
|
7
7
|
|
|
8
|
-
const href = `/tailwindcss/${currentResource}`;
|
|
8
|
+
const href = `/tailwindcss/${currentResource}.css`;
|
|
9
9
|
insertStyles(href, (link) => {
|
|
10
10
|
link.setAttribute('onaftersave', 'cacheBust(this)');
|
|
11
|
+
link.setAttribute('mutations-ignore', '');
|
|
11
12
|
});
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -2,10 +2,20 @@
|
|
|
2
2
|
* Insert styles into the document (inline CSS or external stylesheet).
|
|
3
3
|
*
|
|
4
4
|
* With a persistent DOM (i.e. hyperclay), we need a way to update styles.
|
|
5
|
-
* This function
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
5
|
+
* This function reuses existing elements when possible:
|
|
6
|
+
* - Inline styles: matches by data-name, reuses if content matches
|
|
7
|
+
* - External stylesheets: matches by normalized full URL path
|
|
8
|
+
*
|
|
9
|
+
* This ensures:
|
|
10
|
+
* - No DOM churn: existing elements are reused when content/path matches
|
|
11
|
+
* - No duplicates: removes any duplicate style/link elements
|
|
12
|
+
* - Callback always runs: attributes can be updated on existing elements
|
|
13
|
+
*
|
|
14
|
+
* WHY REUSE IN-PLACE:
|
|
15
|
+
* In a persistent DOM (hyperclay), removing and re-adding elements changes their
|
|
16
|
+
* position and surrounding whitespace. This causes snapshot diffs even when content
|
|
17
|
+
* is identical, triggering false "unsaved changes" warnings. Reusing existing
|
|
18
|
+
* elements preserves DOM structure for stable snapshots.
|
|
9
19
|
*
|
|
10
20
|
* Usage:
|
|
11
21
|
* insertStyles('/path/to/file.css') // External stylesheet
|
|
@@ -18,15 +28,33 @@ function insertStyles(nameOrHref, cssOrCallback, callback) {
|
|
|
18
28
|
// Inline style: insertStyles('my-styles', '.foo { ... }', optionalCallback)
|
|
19
29
|
const name = nameOrHref;
|
|
20
30
|
const css = cssOrCallback;
|
|
21
|
-
const
|
|
31
|
+
const existingStyles = [...document.querySelectorAll(`style[data-name="${name}"]`)];
|
|
32
|
+
|
|
33
|
+
// If exact match exists, just update attributes via callback and return it
|
|
34
|
+
const exactMatch = existingStyles.find(el => el.textContent === css);
|
|
35
|
+
if (exactMatch) {
|
|
36
|
+
if (callback) callback(exactMatch);
|
|
37
|
+
// Remove any duplicates
|
|
38
|
+
existingStyles.filter(el => el !== exactMatch).forEach(el => el.remove());
|
|
39
|
+
return exactMatch;
|
|
40
|
+
}
|
|
22
41
|
|
|
23
|
-
|
|
24
|
-
style
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
// Update first existing style in-place, or create new one
|
|
43
|
+
let style;
|
|
44
|
+
if (existingStyles.length > 0) {
|
|
45
|
+
style = existingStyles[0];
|
|
46
|
+
style.textContent = css;
|
|
47
|
+
if (callback) callback(style);
|
|
48
|
+
// Remove duplicates
|
|
49
|
+
existingStyles.slice(1).forEach(el => el.remove());
|
|
50
|
+
} else {
|
|
51
|
+
style = document.createElement('style');
|
|
52
|
+
style.dataset.name = name;
|
|
53
|
+
style.textContent = css;
|
|
54
|
+
if (callback) callback(style);
|
|
55
|
+
document.head.appendChild(style);
|
|
56
|
+
}
|
|
28
57
|
|
|
29
|
-
oldStyles.forEach(el => el.remove());
|
|
30
58
|
return style;
|
|
31
59
|
}
|
|
32
60
|
|
|
@@ -34,25 +62,35 @@ function insertStyles(nameOrHref, cssOrCallback, callback) {
|
|
|
34
62
|
const href = nameOrHref;
|
|
35
63
|
const cb = typeof cssOrCallback === 'function' ? cssOrCallback : undefined;
|
|
36
64
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
65
|
+
// Normalize href to full URL for comparison
|
|
66
|
+
const normalizedHref = new URL(href, window.location.href).href;
|
|
67
|
+
|
|
68
|
+
// Find all links with matching normalized path
|
|
69
|
+
const existingLinks = [...document.querySelectorAll('link[rel="stylesheet"]')]
|
|
70
|
+
.filter(el => {
|
|
71
|
+
try {
|
|
72
|
+
return new URL(el.getAttribute('href'), window.location.href).href === normalizedHref;
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
44
77
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
78
|
+
// If match exists, just update attributes via callback and return it
|
|
79
|
+
if (existingLinks.length > 0) {
|
|
80
|
+
const link = existingLinks[0];
|
|
81
|
+
if (cb) cb(link);
|
|
82
|
+
// Remove any duplicates
|
|
83
|
+
existingLinks.slice(1).forEach(el => el.remove());
|
|
84
|
+
return link;
|
|
85
|
+
}
|
|
48
86
|
|
|
87
|
+
// Create new link element
|
|
49
88
|
const link = document.createElement('link');
|
|
50
89
|
link.rel = 'stylesheet';
|
|
51
90
|
link.href = href;
|
|
52
91
|
if (cb) cb(link);
|
|
53
92
|
document.head.appendChild(link);
|
|
54
93
|
|
|
55
|
-
oldLinks.forEach(el => el.remove());
|
|
56
94
|
return link;
|
|
57
95
|
}
|
|
58
96
|
|
package/src/hyperclay.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* HyperclayJS v1.
|
|
2
|
+
* HyperclayJS v1.14.1 - Minimal Browser-Native Loader
|
|
3
3
|
*
|
|
4
4
|
* Modules auto-init when imported (no separate init call needed).
|
|
5
5
|
* Include `export-to-window` feature to export to window.hyperclay.
|
|
@@ -73,11 +73,13 @@ const PRESETS = {
|
|
|
73
73
|
"description": "Essential features for basic editing",
|
|
74
74
|
"modules": [
|
|
75
75
|
"save-core",
|
|
76
|
+
"snapshot",
|
|
76
77
|
"save-system",
|
|
77
78
|
"edit-mode-helpers",
|
|
78
79
|
"toast",
|
|
79
80
|
"save-toast",
|
|
80
|
-
"export-to-window"
|
|
81
|
+
"export-to-window",
|
|
82
|
+
"view-mode-excludes-edit-modules"
|
|
81
83
|
]
|
|
82
84
|
},
|
|
83
85
|
"standard": {
|
|
@@ -85,7 +87,9 @@ const PRESETS = {
|
|
|
85
87
|
"description": "Standard feature set for most use cases",
|
|
86
88
|
"modules": [
|
|
87
89
|
"save-core",
|
|
90
|
+
"snapshot",
|
|
88
91
|
"save-system",
|
|
92
|
+
"unsaved-warning",
|
|
89
93
|
"edit-mode-helpers",
|
|
90
94
|
"persist",
|
|
91
95
|
"option-visibility",
|
|
@@ -93,7 +97,8 @@ const PRESETS = {
|
|
|
93
97
|
"dom-helpers",
|
|
94
98
|
"toast",
|
|
95
99
|
"save-toast",
|
|
96
|
-
"export-to-window"
|
|
100
|
+
"export-to-window",
|
|
101
|
+
"view-mode-excludes-edit-modules"
|
|
97
102
|
]
|
|
98
103
|
},
|
|
99
104
|
"everything": {
|
|
@@ -140,7 +145,8 @@ const PRESETS = {
|
|
|
140
145
|
"file-upload",
|
|
141
146
|
"live-sync",
|
|
142
147
|
"tailwind-inject",
|
|
143
|
-
"export-to-window"
|
|
148
|
+
"export-to-window",
|
|
149
|
+
"view-mode-excludes-edit-modules"
|
|
144
150
|
]
|
|
145
151
|
}
|
|
146
152
|
};
|
package/src/ui/theModal.js
CHANGED
|
@@ -166,8 +166,10 @@ const MicroModal = (() => {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
removeEventListeners () {
|
|
169
|
-
this.modal
|
|
170
|
-
|
|
169
|
+
if (this.modal) {
|
|
170
|
+
this.modal.removeEventListener('touchstart', this.onClick)
|
|
171
|
+
this.modal.removeEventListener('click', this.onClick)
|
|
172
|
+
}
|
|
171
173
|
document.removeEventListener('keydown', this.onKeydown)
|
|
172
174
|
}
|
|
173
175
|
|
|
@@ -303,7 +305,9 @@ const MicroModal = (() => {
|
|
|
303
305
|
}
|
|
304
306
|
|
|
305
307
|
const close = targetModal => {
|
|
308
|
+
if (!activeModal) return
|
|
306
309
|
targetModal ? activeModal.closeModalById(targetModal) : activeModal.closeModal()
|
|
310
|
+
activeModal = null
|
|
307
311
|
}
|
|
308
312
|
|
|
309
313
|
return { init, show, close }
|
|
@@ -364,6 +368,7 @@ const modalCss = `<style class="micromodal-css">
|
|
|
364
368
|
|
|
365
369
|
.micromodal__container {
|
|
366
370
|
position: relative;
|
|
371
|
+
max-width: 600px;
|
|
367
372
|
box-sizing: border-box;
|
|
368
373
|
overflow-y: auto;
|
|
369
374
|
padding: 26px 40px 40px 40px;
|
|
@@ -465,7 +470,7 @@ const modalCss = `<style class="micromodal-css">
|
|
|
465
470
|
background-color: #1D1F2F;
|
|
466
471
|
color: #E5E7EB;
|
|
467
472
|
font-family: inherit;
|
|
468
|
-
font-size:
|
|
473
|
+
font-size: inherit;
|
|
469
474
|
font-weight: bold;
|
|
470
475
|
}
|
|
471
476
|
|
|
@@ -495,7 +500,7 @@ const modalCss = `<style class="micromodal-css">
|
|
|
495
500
|
|
|
496
501
|
.micromodal .snippet-code-block pre {
|
|
497
502
|
color: white;
|
|
498
|
-
font-family:
|
|
503
|
+
font-family: var(--hyperclay-modal-code-font-family, var(--hyperclay-modal-font-family, monospace));
|
|
499
504
|
font-size: 0.875rem;
|
|
500
505
|
white-space: nowrap;
|
|
501
506
|
margin: 0;
|
|
@@ -540,21 +545,21 @@ const modalCss = `<style class="micromodal-css">
|
|
|
540
545
|
}
|
|
541
546
|
|
|
542
547
|
.micromodal .micromodal__tell-title {
|
|
543
|
-
font-size: 20px;
|
|
548
|
+
font-size: var(--hyperclay-modal-title-font-size, 20px);
|
|
544
549
|
font-weight: bold;
|
|
545
550
|
}
|
|
546
551
|
|
|
547
552
|
.micromodal .micromodal__tell-content {
|
|
548
|
-
font-size: 16px;
|
|
553
|
+
font-size: var(--hyperclay-modal-font-size, 16px);
|
|
549
554
|
font-weight: normal;
|
|
550
555
|
}
|
|
551
556
|
|
|
552
557
|
@media (min-width: 640px) {
|
|
553
558
|
.micromodal .micromodal__tell-title {
|
|
554
|
-
font-size: 22px;
|
|
559
|
+
font-size: var(--hyperclay-modal-title-font-size, 22px);
|
|
555
560
|
}
|
|
556
561
|
.micromodal .micromodal__tell-content {
|
|
557
|
-
font-size: 18px;
|
|
562
|
+
font-size: var(--hyperclay-modal-font-size, 18px);
|
|
558
563
|
}
|
|
559
564
|
}
|
|
560
565
|
</style>`;
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
// Cache-bust an element's href or src attribute by adding/updating a version query param
|
|
3
3
|
|
|
4
4
|
function cacheBust(el) {
|
|
5
|
-
const attr = el.href
|
|
6
|
-
const
|
|
5
|
+
const attr = el.hasAttribute('href') ? 'href' : 'src';
|
|
6
|
+
const currentValue = el.getAttribute(attr);
|
|
7
|
+
const url = new URL(currentValue, location.href);
|
|
7
8
|
url.searchParams.set('v', Date.now());
|
|
8
|
-
el
|
|
9
|
+
el.setAttribute(attr, url.href);
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
// Auto-export to window unless suppressed by loader
|