hyperclayjs 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,9 +63,10 @@ import 'hyperclayjs/presets/standard.js';
63
63
  | option-visibility | 5.3KB | 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 | 7.1KB | Manual save: keyboard shortcut (CMD+S), save button, change tracking |
66
+ | save-system | 7.1KB | 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
+ | tailwind-inject | 0.4KB | Injects tailwind CSS link with cache-bust on save |
69
70
  | unsaved-warning | 0.8KB | Warn before leaving page with unsaved changes |
70
71
 
71
72
  ### Custom Attributes (HTML enhancements)
@@ -105,7 +106,7 @@ import 'hyperclayjs/presets/standard.js';
105
106
  | all-js | 14.4KB | Full DOM manipulation library |
106
107
  | dom-ready | 0.4KB | DOM ready callback |
107
108
  | form-data | 2KB | Extract form data as an object |
108
- | style-injection | 1.9KB | Dynamic stylesheet injection |
109
+ | style-injection | 2.4KB | Dynamic stylesheet injection |
109
110
 
110
111
  ### String Utilities (String manipulation helpers)
111
112
 
@@ -120,7 +121,7 @@ import 'hyperclayjs/presets/standard.js';
120
121
  | Module | Size | Description |
121
122
  |--------|------|-------------|
122
123
  | file-upload | 10.7KB | File upload with progress |
123
- | live-sync | 12KB | Real-time DOM sync across browsers and with file system |
124
+ | live-sync | 12.7KB | Real-time DOM sync across browsers |
124
125
  | send-message | 1.3KB | Message sending utility |
125
126
 
126
127
  ### Vendor Libraries (Third-party libraries)
@@ -141,7 +142,7 @@ Standard feature set for most use cases
141
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
144
 
144
- ### Everything (~176.5KB)
145
+ ### Everything (~178.1KB)
145
146
  All available features
146
147
 
147
148
  Includes all available modules across all categories.
@@ -230,7 +231,7 @@ The project uses Madge to automatically analyze dependencies and generate rich m
230
231
  npm run generate:deps
231
232
  ```
232
233
 
233
- This creates `module-dependency-graph.json` with:
234
+ This creates `module-dependency-graph.generated.json` with:
234
235
  - Complete dependency tree
235
236
  - Actual file sizes
236
237
  - Category assignments
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperclayjs",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "Modular JavaScript library for building interactive HTML applications with Hyperclay",
5
5
  "type": "module",
6
6
  "main": "src/hyperclay.js",
@@ -228,26 +228,34 @@ class LiveSync {
228
228
 
229
229
  /**
230
230
  * Listen for snapshot-ready events from the save system.
231
- * This replaces DOM observation we sync when save happens.
231
+ * Receives the full cloned documentElement and extracts head/body.
232
232
  */
233
233
  listenForSnapshots() {
234
- this._snapshotHandler = (event) => {
234
+ this._snapshotHandler = async (event) => {
235
235
  if (this.isPaused) return;
236
236
 
237
- const { body } = event.detail;
238
- if (!body) return;
237
+ const { documentElement } = event.detail;
238
+ if (!documentElement) return;
239
239
 
240
- this.sendBody(body);
240
+ // Extract head and body directly from cloned element
241
+ const head = documentElement.querySelector('head')?.innerHTML || '';
242
+ const body = documentElement.querySelector('body')?.innerHTML || '';
243
+
244
+ // Compute headHash using SHA-256 (async)
245
+ const headHash = await this.computeHeadHash(head);
246
+
247
+ // Send update even if body is empty (allows clearing content)
248
+ this.sendUpdate(body, headHash);
241
249
  };
242
250
 
243
251
  document.addEventListener('hyperclay:snapshot-ready', this._snapshotHandler);
244
252
  }
245
253
 
246
254
  /**
247
- * Send body HTML to the server (debounced)
255
+ * Send body and headHash to the server (debounced)
248
256
  * Only updates lastBodyHtml after successful save
249
257
  */
250
- sendBody(body) {
258
+ sendUpdate(body, headHash) {
251
259
  clearTimeout(this.debounceTimer);
252
260
 
253
261
  this.debounceTimer = setTimeout(() => {
@@ -256,9 +264,8 @@ class LiveSync {
256
264
 
257
265
  console.log('[LiveSync] Sending update');
258
266
 
259
- // Compute head hash to send to server (for hosted mode)
260
- const headHash = this.computeHeadHash();
261
- this.lastHeadHash = headHash; // Track local head changes
267
+ // Track local head changes
268
+ this.lastHeadHash = headHash;
262
269
 
263
270
  fetch('/live-sync/save', {
264
271
  method: 'POST',
@@ -286,21 +293,30 @@ class LiveSync {
286
293
  }
287
294
 
288
295
  /**
289
- * Compute MD5-like hash of head content (first 8 hex chars)
290
- * Uses a simple string hash since we don't have crypto in browser
296
+ * Compute SHA-256 hash of head content (first 16 hex chars)
297
+ * Uses SubtleCrypto API (async)
298
+ * @param {string} head - Head innerHTML
299
+ * @returns {Promise<string|null>} 16-char hex hash or null if unavailable
291
300
  */
292
- computeHeadHash() {
293
- const head = document.head?.innerHTML;
301
+ async computeHeadHash(head) {
294
302
  if (!head) return null;
295
303
 
296
- // Simple hash function (djb2)
297
- let hash = 5381;
298
- for (let i = 0; i < head.length; i++) {
299
- hash = ((hash << 5) + hash) + head.charCodeAt(i);
300
- hash = hash & hash; // Convert to 32bit integer
304
+ // SubtleCrypto requires secure context (HTTPS or localhost)
305
+ if (!crypto?.subtle?.digest) {
306
+ console.warn('[LiveSync] SHA-256 unavailable (non-secure context), skipping headHash');
307
+ return null;
308
+ }
309
+
310
+ try {
311
+ const encoder = new TextEncoder();
312
+ const data = encoder.encode(head);
313
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
314
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
315
+ return hashArray.map(b => b.toString(16).padStart(2, '0')).join('').slice(0, 16);
316
+ } catch (e) {
317
+ console.warn('[LiveSync] SHA-256 hash failed, skipping headHash:', e);
318
+ return null;
301
319
  }
302
- // Convert to hex and take first 8 chars
303
- return Math.abs(hash).toString(16).padStart(8, '0').slice(0, 8);
304
320
  }
305
321
 
306
322
  /**
@@ -128,10 +128,10 @@ export function captureForSave({ emitForSync = true } = {}) {
128
128
  const clone = captureSnapshot();
129
129
 
130
130
  // Emit for live-sync before stripping admin elements
131
+ // Sends full cloned documentElement so live-sync can extract head and body
131
132
  if (emitForSync) {
132
- const bodyForSync = clone.querySelector('body').innerHTML;
133
133
  document.dispatchEvent(new CustomEvent('hyperclay:snapshot-ready', {
134
- detail: { body: bodyForSync }
134
+ detail: { documentElement: clone }
135
135
  }));
136
136
  }
137
137
 
@@ -0,0 +1,14 @@
1
+ import { insertStyles } from '../dom-utilities/insertStyleTag.js';
2
+ import cookie from '../utilities/cookie.js';
3
+
4
+ function init() {
5
+ const currentResource = cookie.get('currentResource');
6
+ if (!currentResource) return;
7
+
8
+ const href = `/tailwindcss/${currentResource}`;
9
+ insertStyles(href, (link) => {
10
+ link.setAttribute('onaftersave', 'cacheBust(this)');
11
+ });
12
+ }
13
+
14
+ init();
@@ -6,24 +6,33 @@
6
6
  * duplicates. This ensures:
7
7
  * - No flickering: new styles are applied before old ones are removed
8
8
  * - Always upgrades: we default to the new styles/approach
9
+ *
10
+ * Usage:
11
+ * insertStyles('/path/to/file.css') // External stylesheet
12
+ * insertStyles('/path/to/file.css', (link) => { ... }) // With callback
13
+ * insertStyles('my-styles', '.foo { ... }') // Inline CSS
14
+ * insertStyles('my-styles', '.foo { ... }', (style) => { ... }) // With callback
9
15
  */
10
- function insertStyles(nameOrHref, css) {
11
- if (css !== undefined) {
12
- // Inline style: insertStyles('my-styles', '.foo { ... }')
16
+ function insertStyles(nameOrHref, cssOrCallback, callback) {
17
+ if (typeof cssOrCallback === 'string') {
18
+ // Inline style: insertStyles('my-styles', '.foo { ... }', optionalCallback)
13
19
  const name = nameOrHref;
20
+ const css = cssOrCallback;
14
21
  const oldStyles = document.querySelectorAll(`style[data-name="${name}"]`);
15
22
 
16
23
  const style = document.createElement('style');
17
24
  style.dataset.name = name;
18
25
  style.textContent = css;
26
+ if (callback) callback(style);
19
27
  document.head.appendChild(style);
20
28
 
21
29
  oldStyles.forEach(el => el.remove());
22
30
  return style;
23
31
  }
24
32
 
25
- // External stylesheet: insertStyles('/path/to/file.css')
33
+ // External stylesheet: insertStyles('/path/to/file.css', optionalCallback)
26
34
  const href = nameOrHref;
35
+ const cb = typeof cssOrCallback === 'function' ? cssOrCallback : undefined;
27
36
 
28
37
  let identifier;
29
38
  try {
@@ -40,6 +49,7 @@ function insertStyles(nameOrHref, css) {
40
49
  const link = document.createElement('link');
41
50
  link.rel = 'stylesheet';
42
51
  link.href = href;
52
+ if (cb) cb(link);
43
53
  document.head.appendChild(link);
44
54
 
45
55
  oldLinks.forEach(el => el.remove());
package/src/hyperclay.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * HyperclayJS v1.9.0 - Minimal Browser-Native Loader
2
+ * HyperclayJS v1.11.0 - 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.
@@ -64,6 +64,7 @@ const MODULE_PATHS = {
64
64
  "send-message": "./communication/sendMessage.js",
65
65
  "file-upload": "./communication/uploadFile.js",
66
66
  "live-sync": "./communication/live-sync.js",
67
+ "tailwind-inject": "./core/tailwindInject.js",
67
68
  "export-to-window": "./core/exportToWindow.js"
68
69
  };
69
70
  const PRESETS = {
@@ -138,10 +139,27 @@ const PRESETS = {
138
139
  "send-message",
139
140
  "file-upload",
140
141
  "live-sync",
142
+ "tailwind-inject",
141
143
  "export-to-window"
142
144
  ]
143
145
  }
144
146
  };
147
+ const EDIT_MODE_ONLY = new Set([
148
+ "save-core",
149
+ "save-system",
150
+ "autosave",
151
+ "unsaved-warning",
152
+ "save-toast",
153
+ "edit-mode-helpers",
154
+ "persist",
155
+ "snapshot",
156
+ "sortable",
157
+ "onaftersave",
158
+ "cache-bust",
159
+ "file-upload",
160
+ "live-sync",
161
+ "tailwind-inject"
162
+ ]);
145
163
 
146
164
  // Parse URL (use import.meta.url for ES modules since document.currentScript is null)
147
165
  const url = new URL(import.meta.url);
@@ -167,6 +185,17 @@ if (exclude) {
167
185
  requested = requested.filter(f => !excluded.has(f));
168
186
  }
169
187
 
188
+ // view-mode-excludes-edit-modules: skip edit-only modules when not in edit mode
189
+ const viewModeExcludesEdit = requested.includes('view-mode-excludes-edit-modules');
190
+ if (viewModeExcludesEdit) {
191
+ requested = requested.filter(f => f !== 'view-mode-excludes-edit-modules');
192
+ const { isEditMode } = await import('./core/isAdminOfCurrentResource.js');
193
+ if (!isEditMode) {
194
+ requested = requested.filter(f => !EDIT_MODE_ONLY.has(f));
195
+ if (debug) console.log('HyperclayJS: View mode - excluding edit-only modules');
196
+ }
197
+ }
198
+
170
199
  // Modules that extend prototypes must load before modules that execute user code
171
200
  const LOAD_FIRST = new Set(['dom-helpers', 'all-js']);
172
201
 
@@ -1,953 +0,0 @@
1
- {
2
- "rawDependencies": {
3
- "communication/behaviorCollector.js": [],
4
- "communication/live-sync.js": [],
5
- "communication/sendMessage.js": [
6
- "communication/behaviorCollector.js",
7
- "dom-utilities/getDataFromForm.js",
8
- "ui/toast.js"
9
- ],
10
- "communication/uploadFile.js": [
11
- "string-utilities/copy-to-clipboard.js",
12
- "ui/toast.js",
13
- "utilities/debounce.js"
14
- ],
15
- "core/adminContenteditable.js": [
16
- "core/isAdminOfCurrentResource.js",
17
- "core/savePage.js",
18
- "dom-utilities/onDomReady.js"
19
- ],
20
- "core/adminInputs.js": [
21
- "core/isAdminOfCurrentResource.js",
22
- "core/savePage.js",
23
- "dom-utilities/onDomReady.js"
24
- ],
25
- "core/adminOnClick.js": [
26
- "core/isAdminOfCurrentResource.js",
27
- "core/savePage.js",
28
- "dom-utilities/onDomReady.js"
29
- ],
30
- "core/adminResources.js": [
31
- "core/isAdminOfCurrentResource.js",
32
- "core/savePage.js",
33
- "dom-utilities/onDomReady.js"
34
- ],
35
- "core/adminSystem.js": [
36
- "core/adminContenteditable.js",
37
- "core/adminInputs.js",
38
- "core/adminOnClick.js",
39
- "core/adminResources.js"
40
- ],
41
- "core/autosave.js": [
42
- "core/isAdminOfCurrentResource.js",
43
- "core/savePage.js",
44
- "utilities/mutation.js"
45
- ],
46
- "core/editmode.js": [
47
- "core/isAdminOfCurrentResource.js"
48
- ],
49
- "core/editmodeSystem.js": [
50
- "core/editmode.js",
51
- "core/isAdminOfCurrentResource.js",
52
- "core/setPageTypeOnDocumentElement.js"
53
- ],
54
- "core/enablePersistentFormInputValues.js": [
55
- "core/snapshot.js"
56
- ],
57
- "core/exportToWindow.js": [],
58
- "core/isAdminOfCurrentResource.js": [
59
- "string-utilities/query.js",
60
- "utilities/cookie.js"
61
- ],
62
- "core/optionVisibility.js": [
63
- "dom-utilities/insertStyleTag.js",
64
- "utilities/mutation.js"
65
- ],
66
- "core/savePage.js": [
67
- "core/isAdminOfCurrentResource.js",
68
- "core/savePageCore.js",
69
- "utilities/throttle.js"
70
- ],
71
- "core/savePageCore.js": [
72
- "core/isAdminOfCurrentResource.js",
73
- "core/snapshot.js",
74
- "utilities/cookie.js"
75
- ],
76
- "core/saveToast.js": [
77
- "core/isAdminOfCurrentResource.js",
78
- "ui/toast.js"
79
- ],
80
- "core/setPageTypeOnDocumentElement.js": [
81
- "core/isAdminOfCurrentResource.js",
82
- "core/savePage.js",
83
- "dom-utilities/onDomReady.js"
84
- ],
85
- "core/snapshot.js": [],
86
- "core/unsavedWarning.js": [
87
- "core/isAdminOfCurrentResource.js",
88
- "core/savePage.js"
89
- ],
90
- "custom-attributes/ajaxElements.js": [
91
- "dom-utilities/getDataFromForm.js"
92
- ],
93
- "custom-attributes/autosize.js": [],
94
- "custom-attributes/domHelpers.js": [
95
- "utilities/nearest.js",
96
- "utilities/pipe.js"
97
- ],
98
- "custom-attributes/events.js": [
99
- "custom-attributes/onclickaway.js",
100
- "custom-attributes/onclone.js",
101
- "custom-attributes/onmutation.js",
102
- "custom-attributes/onpagemutation.js",
103
- "custom-attributes/onrender.js"
104
- ],
105
- "custom-attributes/inputHelpers.js": [
106
- "custom-attributes/autosize.js",
107
- "custom-attributes/preventEnter.js"
108
- ],
109
- "custom-attributes/onaftersave.js": [],
110
- "custom-attributes/onclickaway.js": [],
111
- "custom-attributes/onclone.js": [],
112
- "custom-attributes/onmutation.js": [
113
- "utilities/mutation.js"
114
- ],
115
- "custom-attributes/onpagemutation.js": [
116
- "utilities/mutation.js"
117
- ],
118
- "custom-attributes/onrender.js": [
119
- "dom-utilities/onLoad.js",
120
- "utilities/mutation.js"
121
- ],
122
- "custom-attributes/preventEnter.js": [],
123
- "custom-attributes/sortable.js": [
124
- "core/isAdminOfCurrentResource.js",
125
- "utilities/loadVendorScript.js",
126
- "utilities/mutation.js"
127
- ],
128
- "dom-utilities/All.js": [],
129
- "dom-utilities/getDataFromForm.js": [],
130
- "dom-utilities/insertStyleTag.js": [],
131
- "dom-utilities/onDomReady.js": [],
132
- "dom-utilities/onLoad.js": [],
133
- "hyperclay.js": [],
134
- "string-utilities/copy-to-clipboard.js": [],
135
- "string-utilities/query.js": [],
136
- "string-utilities/slugify.js": [],
137
- "ui/prompts.js": [
138
- "dom-utilities/onDomReady.js",
139
- "string-utilities/copy-to-clipboard.js",
140
- "ui/theModal.js",
141
- "ui/toast.js"
142
- ],
143
- "ui/theModal.js": [],
144
- "ui/toast-hyperclay.js": [
145
- "ui/toast.js"
146
- ],
147
- "ui/toast.js": [],
148
- "utilities/cacheBust.js": [],
149
- "utilities/cookie.js": [],
150
- "utilities/debounce.js": [],
151
- "utilities/loadVendorScript.js": [],
152
- "utilities/mutation.js": [],
153
- "utilities/nearest.js": [],
154
- "utilities/pipe.js": [],
155
- "utilities/throttle.js": [],
156
- "vendor/Sortable.vendor.js": [],
157
- "vendor/idiomorph.min.js": []
158
- },
159
- "modules": {
160
- "save-core": {
161
- "name": "save-core",
162
- "category": "core",
163
- "size": 6.8,
164
- "files": [
165
- "core/savePageCore.js"
166
- ],
167
- "description": "Basic save function only - hyperclay.savePage()",
168
- "exports": {
169
- "savePage": [
170
- "hyperclay"
171
- ]
172
- }
173
- },
174
- "save-system": {
175
- "name": "save-system",
176
- "category": "core",
177
- "size": 7.1,
178
- "files": [
179
- "core/savePage.js"
180
- ],
181
- "description": "Manual save: keyboard shortcut (CMD+S), save button, change tracking",
182
- "exports": {
183
- "beforeSave": [
184
- "hyperclay"
185
- ],
186
- "savePage": [
187
- "hyperclay"
188
- ],
189
- "savePageThrottled": [
190
- "hyperclay"
191
- ],
192
- "replacePageWith": [
193
- "hyperclay"
194
- ]
195
- }
196
- },
197
- "autosave": {
198
- "name": "autosave",
199
- "category": "core",
200
- "size": 0.9,
201
- "files": [
202
- "core/autosave.js"
203
- ],
204
- "description": "Auto-save on DOM changes",
205
- "exports": {}
206
- },
207
- "unsaved-warning": {
208
- "name": "unsaved-warning",
209
- "category": "core",
210
- "size": 0.8,
211
- "files": [
212
- "core/unsavedWarning.js"
213
- ],
214
- "description": "Warn before leaving page with unsaved changes",
215
- "exports": {}
216
- },
217
- "save-toast": {
218
- "name": "save-toast",
219
- "category": "core",
220
- "size": 0.9,
221
- "files": [
222
- "core/saveToast.js"
223
- ],
224
- "description": "Toast notifications for save events",
225
- "exports": {}
226
- },
227
- "edit-mode-helpers": {
228
- "name": "edit-mode-helpers",
229
- "category": "core",
230
- "size": 7.500000000000001,
231
- "files": [
232
- "core/adminSystem.js",
233
- "core/adminContenteditable.js",
234
- "core/adminInputs.js",
235
- "core/adminOnClick.js",
236
- "core/adminResources.js"
237
- ],
238
- "description": "Admin-only functionality: [edit-mode-input], [edit-mode-resource], [edit-mode-onclick]",
239
- "exports": {}
240
- },
241
- "persist": {
242
- "name": "persist",
243
- "category": "core",
244
- "size": 2.4,
245
- "files": [
246
- "core/enablePersistentFormInputValues.js"
247
- ],
248
- "description": "Persist input/select/textarea values to the DOM with [persist] attribute",
249
- "exports": {}
250
- },
251
- "snapshot": {
252
- "name": "snapshot",
253
- "category": "core",
254
- "size": 7.5,
255
- "files": [
256
- "core/snapshot.js"
257
- ],
258
- "description": "Source of truth for page state - captures DOM snapshots for save and sync",
259
- "exports": {
260
- "captureSnapshot": [
261
- "hyperclay"
262
- ],
263
- "captureForSave": [
264
- "hyperclay"
265
- ],
266
- "captureBodyForSync": [
267
- "hyperclay"
268
- ],
269
- "onSnapshot": [
270
- "hyperclay"
271
- ],
272
- "onPrepareForSave": [
273
- "hyperclay"
274
- ],
275
- "beforeSave": [
276
- "hyperclay"
277
- ],
278
- "getPageContents": [
279
- "hyperclay"
280
- ]
281
- }
282
- },
283
- "option-visibility": {
284
- "name": "option-visibility",
285
- "category": "core",
286
- "size": 5.3,
287
- "files": [
288
- "core/optionVisibility.js"
289
- ],
290
- "description": "Dynamic show/hide based on ancestor state with option:attribute=\"value\"",
291
- "exports": {}
292
- },
293
- "edit-mode": {
294
- "name": "edit-mode",
295
- "category": "core",
296
- "size": 1.8,
297
- "files": [
298
- "core/editmodeSystem.js",
299
- "core/editmode.js",
300
- "core/setPageTypeOnDocumentElement.js"
301
- ],
302
- "description": "Toggle edit mode on hyperclay on/off",
303
- "exports": {
304
- "toggleEditMode": [
305
- "hyperclay"
306
- ],
307
- "isEditMode": [
308
- "hyperclay"
309
- ],
310
- "isOwner": [
311
- "hyperclay"
312
- ]
313
- }
314
- },
315
- "event-attrs": {
316
- "name": "event-attrs",
317
- "category": "custom-attributes",
318
- "size": 4.1000000000000005,
319
- "files": [
320
- "custom-attributes/events.js",
321
- "custom-attributes/onclickaway.js",
322
- "custom-attributes/onclone.js",
323
- "custom-attributes/onpagemutation.js",
324
- "custom-attributes/onrender.js"
325
- ],
326
- "description": "[onclickaway], [onclone], [onpagemutation], [onrender]",
327
- "exports": {}
328
- },
329
- "ajax-elements": {
330
- "name": "ajax-elements",
331
- "category": "custom-attributes",
332
- "size": 2.6,
333
- "files": [
334
- "custom-attributes/ajaxElements.js"
335
- ],
336
- "description": "[ajax-form], [ajax-button] for async form submissions",
337
- "exports": {}
338
- },
339
- "sortable": {
340
- "name": "sortable",
341
- "category": "custom-attributes",
342
- "size": 3.4,
343
- "files": [
344
- "custom-attributes/sortable.js"
345
- ],
346
- "description": "Drag-drop sorting with [sortable], lazy-loads ~118KB Sortable.js in edit mode",
347
- "exports": {}
348
- },
349
- "dom-helpers": {
350
- "name": "dom-helpers",
351
- "category": "custom-attributes",
352
- "size": 6.2,
353
- "files": [
354
- "custom-attributes/domHelpers.js"
355
- ],
356
- "description": "el.nearest, el.val, el.text, el.exec, el.cycle",
357
- "exports": {}
358
- },
359
- "input-helpers": {
360
- "name": "input-helpers",
361
- "category": "custom-attributes",
362
- "size": 1.2,
363
- "files": [
364
- "custom-attributes/inputHelpers.js",
365
- "custom-attributes/preventEnter.js",
366
- "custom-attributes/autosize.js"
367
- ],
368
- "description": "[prevent-enter], [autosize] for textareas",
369
- "exports": {}
370
- },
371
- "onaftersave": {
372
- "name": "onaftersave",
373
- "category": "custom-attributes",
374
- "size": 1,
375
- "files": [
376
- "custom-attributes/onaftersave.js"
377
- ],
378
- "description": "[onaftersave] attribute - run JS when save status changes",
379
- "exports": {}
380
- },
381
- "dialogs": {
382
- "name": "dialogs",
383
- "category": "ui",
384
- "size": 7.7,
385
- "files": [
386
- "ui/prompts.js"
387
- ],
388
- "description": "ask(), consent(), tell(), snippet() dialog functions",
389
- "exports": {
390
- "ask": [
391
- "window",
392
- "hyperclay"
393
- ],
394
- "consent": [
395
- "window",
396
- "hyperclay"
397
- ],
398
- "tell": [
399
- "window",
400
- "hyperclay"
401
- ],
402
- "snippet": [
403
- "window",
404
- "hyperclay"
405
- ]
406
- }
407
- },
408
- "toast": {
409
- "name": "toast",
410
- "category": "ui",
411
- "size": 7.7,
412
- "files": [
413
- "ui/toast.js"
414
- ],
415
- "description": "Success/error message notifications, toast(msg, msgType)",
416
- "exports": {
417
- "toast": [
418
- "window",
419
- "hyperclay"
420
- ]
421
- }
422
- },
423
- "toast-hyperclay": {
424
- "name": "toast-hyperclay",
425
- "category": "ui",
426
- "size": 1,
427
- "files": [
428
- "ui/toast-hyperclay.js"
429
- ],
430
- "description": "toastHyperclay() with legacy Hyperclay platform styling (hidden feature)",
431
- "exports": {
432
- "toastHyperclay": [
433
- "window",
434
- "hyperclay"
435
- ]
436
- }
437
- },
438
- "the-modal": {
439
- "name": "the-modal",
440
- "category": "ui",
441
- "size": 21.8,
442
- "files": [
443
- "ui/theModal.js"
444
- ],
445
- "description": "Full modal window creation system - window.theModal",
446
- "exports": {
447
- "themodal": [
448
- "window",
449
- "hyperclay"
450
- ]
451
- }
452
- },
453
- "mutation": {
454
- "name": "mutation",
455
- "category": "utilities",
456
- "size": 13,
457
- "files": [
458
- "utilities/mutation.js"
459
- ],
460
- "description": "DOM mutation observation (often auto-included)",
461
- "exports": {
462
- "Mutation": [
463
- "window",
464
- "hyperclay"
465
- ]
466
- }
467
- },
468
- "nearest": {
469
- "name": "nearest",
470
- "category": "utilities",
471
- "size": 3.4,
472
- "files": [
473
- "utilities/nearest.js"
474
- ],
475
- "description": "Find nearest elements (often auto-included)",
476
- "exports": {
477
- "nearest": [
478
- "window",
479
- "hyperclay"
480
- ]
481
- }
482
- },
483
- "cookie": {
484
- "name": "cookie",
485
- "category": "utilities",
486
- "size": 1.4,
487
- "files": [
488
- "utilities/cookie.js"
489
- ],
490
- "description": "Cookie management (often auto-included)",
491
- "exports": {
492
- "cookie": [
493
- "window",
494
- "hyperclay"
495
- ]
496
- }
497
- },
498
- "throttle": {
499
- "name": "throttle",
500
- "category": "utilities",
501
- "size": 0.8,
502
- "files": [
503
- "utilities/throttle.js"
504
- ],
505
- "description": "Function throttling",
506
- "exports": {
507
- "throttle": [
508
- "hyperclay"
509
- ]
510
- }
511
- },
512
- "debounce": {
513
- "name": "debounce",
514
- "category": "utilities",
515
- "size": 0.4,
516
- "files": [
517
- "utilities/debounce.js"
518
- ],
519
- "description": "Function debouncing",
520
- "exports": {
521
- "debounce": [
522
- "hyperclay"
523
- ]
524
- }
525
- },
526
- "cache-bust": {
527
- "name": "cache-bust",
528
- "category": "utilities",
529
- "size": 0.6,
530
- "files": [
531
- "utilities/cacheBust.js"
532
- ],
533
- "description": "Cache-bust href/src attributes",
534
- "exports": {
535
- "cacheBust": [
536
- "window",
537
- "hyperclay"
538
- ]
539
- }
540
- },
541
- "dom-ready": {
542
- "name": "dom-ready",
543
- "category": "dom-utilities",
544
- "size": 0.4,
545
- "files": [
546
- "dom-utilities/onDomReady.js"
547
- ],
548
- "description": "DOM ready callback",
549
- "exports": {
550
- "onDomReady": [
551
- "hyperclay"
552
- ]
553
- }
554
- },
555
- "window-load": {
556
- "name": "window-load",
557
- "category": "dom-utilities",
558
- "size": 0.4,
559
- "files": [
560
- "dom-utilities/onLoad.js"
561
- ],
562
- "description": "Window load callback",
563
- "exports": {
564
- "onLoad": [
565
- "hyperclay"
566
- ]
567
- }
568
- },
569
- "all-js": {
570
- "name": "all-js",
571
- "category": "dom-utilities",
572
- "size": 14.4,
573
- "files": [
574
- "dom-utilities/All.js"
575
- ],
576
- "description": "Full DOM manipulation library",
577
- "exports": {
578
- "All": [
579
- "window",
580
- "hyperclay"
581
- ]
582
- }
583
- },
584
- "style-injection": {
585
- "name": "style-injection",
586
- "category": "dom-utilities",
587
- "size": 1.9,
588
- "files": [
589
- "dom-utilities/insertStyleTag.js"
590
- ],
591
- "description": "Dynamic stylesheet injection",
592
- "exports": {
593
- "insertStyles": [
594
- "window",
595
- "hyperclay"
596
- ],
597
- "insertStyleTag": [
598
- "window",
599
- "hyperclay"
600
- ]
601
- }
602
- },
603
- "form-data": {
604
- "name": "form-data",
605
- "category": "dom-utilities",
606
- "size": 2,
607
- "files": [
608
- "dom-utilities/getDataFromForm.js"
609
- ],
610
- "description": "Extract form data as an object",
611
- "exports": {
612
- "getDataFromForm": [
613
- "window",
614
- "hyperclay"
615
- ]
616
- }
617
- },
618
- "idiomorph": {
619
- "name": "idiomorph",
620
- "category": "vendor",
621
- "size": 8.3,
622
- "files": [
623
- "vendor/idiomorph.min.js"
624
- ],
625
- "description": "Efficient DOM morphing library",
626
- "exports": {
627
- "Idiomorph": [
628
- "hyperclay"
629
- ]
630
- }
631
- },
632
- "slugify": {
633
- "name": "slugify",
634
- "category": "string-utilities",
635
- "size": 0.7,
636
- "files": [
637
- "string-utilities/slugify.js"
638
- ],
639
- "description": "URL-friendly slug generator",
640
- "exports": {
641
- "slugify": [
642
- "window",
643
- "hyperclay"
644
- ]
645
- }
646
- },
647
- "copy-to-clipboard": {
648
- "name": "copy-to-clipboard",
649
- "category": "string-utilities",
650
- "size": 0.9,
651
- "files": [
652
- "string-utilities/copy-to-clipboard.js"
653
- ],
654
- "description": "Clipboard utility",
655
- "exports": {
656
- "copyToClipboard": [
657
- "hyperclay"
658
- ]
659
- }
660
- },
661
- "query-params": {
662
- "name": "query-params",
663
- "category": "string-utilities",
664
- "size": 0.3,
665
- "files": [
666
- "string-utilities/query.js"
667
- ],
668
- "description": "Parse URL search params",
669
- "exports": {
670
- "query": [
671
- "window",
672
- "hyperclay"
673
- ]
674
- }
675
- },
676
- "behavior-collector": {
677
- "name": "behavior-collector",
678
- "category": "communication",
679
- "size": 5.5,
680
- "files": [
681
- "communication/behaviorCollector.js"
682
- ],
683
- "description": "Tracks user interactions (mouse, scroll, keyboard)",
684
- "exports": {
685
- "behaviorCollector": [
686
- "hyperclay"
687
- ]
688
- }
689
- },
690
- "send-message": {
691
- "name": "send-message",
692
- "category": "communication",
693
- "size": 1.3,
694
- "files": [
695
- "communication/sendMessage.js"
696
- ],
697
- "description": "Message sending utility",
698
- "exports": {
699
- "sendMessage": [
700
- "hyperclay"
701
- ]
702
- }
703
- },
704
- "file-upload": {
705
- "name": "file-upload",
706
- "category": "communication",
707
- "size": 10.7,
708
- "files": [
709
- "communication/uploadFile.js"
710
- ],
711
- "description": "File upload with progress",
712
- "exports": {
713
- "uploadFile": [
714
- "hyperclay"
715
- ],
716
- "createFile": [
717
- "hyperclay"
718
- ],
719
- "uploadFileBasic": [
720
- "hyperclay"
721
- ]
722
- }
723
- },
724
- "live-sync": {
725
- "name": "live-sync",
726
- "category": "communication",
727
- "size": 12,
728
- "files": [
729
- "communication/live-sync.js"
730
- ],
731
- "description": "Real-time DOM sync across browsers and with file system",
732
- "exports": {
733
- "liveSync": [
734
- "hyperclay"
735
- ]
736
- }
737
- },
738
- "export-to-window": {
739
- "name": "export-to-window",
740
- "category": "core",
741
- "size": 0.4,
742
- "files": [
743
- "core/exportToWindow.js"
744
- ],
745
- "description": "Export all modules to window.hyperclay and window globals",
746
- "exports": {}
747
- }
748
- },
749
- "modulePaths": {
750
- "save-core": "./core/savePageCore.js",
751
- "save-system": "./core/savePage.js",
752
- "autosave": "./core/autosave.js",
753
- "unsaved-warning": "./core/unsavedWarning.js",
754
- "save-toast": "./core/saveToast.js",
755
- "edit-mode-helpers": "./core/adminSystem.js",
756
- "persist": "./core/enablePersistentFormInputValues.js",
757
- "snapshot": "./core/snapshot.js",
758
- "option-visibility": "./core/optionVisibility.js",
759
- "edit-mode": "./core/editmodeSystem.js",
760
- "event-attrs": "./custom-attributes/events.js",
761
- "ajax-elements": "./custom-attributes/ajaxElements.js",
762
- "sortable": "./custom-attributes/sortable.js",
763
- "dom-helpers": "./custom-attributes/domHelpers.js",
764
- "input-helpers": "./custom-attributes/inputHelpers.js",
765
- "onaftersave": "./custom-attributes/onaftersave.js",
766
- "dialogs": "./ui/prompts.js",
767
- "toast": "./ui/toast.js",
768
- "toast-hyperclay": "./ui/toast-hyperclay.js",
769
- "the-modal": "./ui/theModal.js",
770
- "mutation": "./utilities/mutation.js",
771
- "nearest": "./utilities/nearest.js",
772
- "cookie": "./utilities/cookie.js",
773
- "throttle": "./utilities/throttle.js",
774
- "debounce": "./utilities/debounce.js",
775
- "cache-bust": "./utilities/cacheBust.js",
776
- "dom-ready": "./dom-utilities/onDomReady.js",
777
- "window-load": "./dom-utilities/onLoad.js",
778
- "all-js": "./dom-utilities/All.js",
779
- "style-injection": "./dom-utilities/insertStyleTag.js",
780
- "form-data": "./dom-utilities/getDataFromForm.js",
781
- "idiomorph": "./vendor/idiomorph.min.js",
782
- "slugify": "./string-utilities/slugify.js",
783
- "copy-to-clipboard": "./string-utilities/copy-to-clipboard.js",
784
- "query-params": "./string-utilities/query.js",
785
- "behavior-collector": "./communication/behaviorCollector.js",
786
- "send-message": "./communication/sendMessage.js",
787
- "file-upload": "./communication/uploadFile.js",
788
- "live-sync": "./communication/live-sync.js",
789
- "export-to-window": "./core/exportToWindow.js"
790
- },
791
- "categories": {
792
- "core": {
793
- "name": "Core Features",
794
- "description": "Essential functionality",
795
- "modules": [
796
- "save-core",
797
- "save-system",
798
- "autosave",
799
- "unsaved-warning",
800
- "save-toast",
801
- "edit-mode-helpers",
802
- "persist",
803
- "snapshot",
804
- "option-visibility",
805
- "edit-mode"
806
- ]
807
- },
808
- "custom-attributes": {
809
- "name": "Custom Attributes",
810
- "description": "HTML enhancements",
811
- "modules": [
812
- "event-attrs",
813
- "ajax-elements",
814
- "sortable",
815
- "dom-helpers",
816
- "input-helpers",
817
- "onaftersave"
818
- ]
819
- },
820
- "ui": {
821
- "name": "UI Components",
822
- "description": "User interface elements",
823
- "modules": [
824
- "dialogs",
825
- "toast",
826
- "the-modal"
827
- ]
828
- },
829
- "utilities": {
830
- "name": "Utilities",
831
- "description": "Core utilities (often auto-included)",
832
- "modules": [
833
- "mutation",
834
- "nearest",
835
- "cookie",
836
- "throttle",
837
- "debounce",
838
- "cache-bust"
839
- ]
840
- },
841
- "dom-utilities": {
842
- "name": "DOM Utilities",
843
- "description": "DOM manipulation helpers",
844
- "modules": [
845
- "dom-ready",
846
- "all-js",
847
- "style-injection",
848
- "form-data"
849
- ]
850
- },
851
- "string-utilities": {
852
- "name": "String Utilities",
853
- "description": "String manipulation helpers",
854
- "modules": [
855
- "slugify",
856
- "copy-to-clipboard",
857
- "query-params"
858
- ]
859
- },
860
- "communication": {
861
- "name": "Communication & Files",
862
- "description": "File handling and messaging",
863
- "modules": [
864
- "send-message",
865
- "file-upload",
866
- "live-sync"
867
- ]
868
- },
869
- "vendor": {
870
- "name": "Vendor Libraries",
871
- "description": "Third-party libraries",
872
- "modules": [
873
- "idiomorph"
874
- ]
875
- }
876
- },
877
- "presets": {
878
- "minimal": {
879
- "name": "Minimal",
880
- "description": "Essential features for basic editing",
881
- "modules": [
882
- "save-core",
883
- "save-system",
884
- "edit-mode-helpers",
885
- "toast",
886
- "save-toast",
887
- "export-to-window"
888
- ]
889
- },
890
- "standard": {
891
- "name": "Standard",
892
- "description": "Standard feature set for most use cases",
893
- "modules": [
894
- "save-core",
895
- "save-system",
896
- "edit-mode-helpers",
897
- "persist",
898
- "option-visibility",
899
- "event-attrs",
900
- "dom-helpers",
901
- "toast",
902
- "save-toast",
903
- "export-to-window"
904
- ]
905
- },
906
- "everything": {
907
- "name": "Everything",
908
- "description": "All available features",
909
- "modules": [
910
- "save-core",
911
- "save-system",
912
- "autosave",
913
- "unsaved-warning",
914
- "save-toast",
915
- "edit-mode-helpers",
916
- "persist",
917
- "snapshot",
918
- "option-visibility",
919
- "edit-mode",
920
- "event-attrs",
921
- "ajax-elements",
922
- "sortable",
923
- "dom-helpers",
924
- "input-helpers",
925
- "onaftersave",
926
- "dialogs",
927
- "toast",
928
- "toast-hyperclay",
929
- "the-modal",
930
- "mutation",
931
- "nearest",
932
- "cookie",
933
- "throttle",
934
- "debounce",
935
- "cache-bust",
936
- "dom-ready",
937
- "window-load",
938
- "all-js",
939
- "style-injection",
940
- "form-data",
941
- "idiomorph",
942
- "slugify",
943
- "copy-to-clipboard",
944
- "query-params",
945
- "behavior-collector",
946
- "send-message",
947
- "file-upload",
948
- "live-sync",
949
- "export-to-window"
950
- ]
951
- }
952
- }
953
- }