hyperclayjs 1.2.0 → 1.3.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.
Files changed (40) hide show
  1. package/README.md +44 -57
  2. package/communication/behaviorCollector.js +8 -1
  3. package/communication/sendMessage.js +8 -2
  4. package/communication/uploadFile.js +8 -2
  5. package/core/adminSystem.js +3 -0
  6. package/core/autosave.js +95 -0
  7. package/core/editmodeSystem.js +10 -8
  8. package/core/enablePersistentFormInputValues.js +8 -1
  9. package/core/optionVisibilityRuleGenerator.js +9 -1
  10. package/core/savePage.js +28 -71
  11. package/core/savePageCore.js +7 -14
  12. package/custom-attributes/ajaxElements.js +4 -0
  13. package/custom-attributes/domHelpers.js +9 -0
  14. package/custom-attributes/events.js +3 -0
  15. package/custom-attributes/inputHelpers.js +3 -0
  16. package/custom-attributes/sortable.js +9 -1
  17. package/dom-utilities/All.js +4 -7
  18. package/dom-utilities/getDataFromForm.js +9 -2
  19. package/dom-utilities/insertStyleTag.js +9 -2
  20. package/dom-utilities/onDomReady.js +8 -2
  21. package/dom-utilities/onLoad.js +8 -2
  22. package/hyperclay.js +106 -692
  23. package/module-dependency-graph.json +175 -137
  24. package/package.json +3 -3
  25. package/string-utilities/copy-to-clipboard.js +3 -7
  26. package/string-utilities/emmet-html.js +8 -2
  27. package/string-utilities/query.js +8 -1
  28. package/string-utilities/slugify.js +4 -7
  29. package/ui/info.js +9 -1
  30. package/ui/prompts.js +19 -12
  31. package/ui/theModal.js +4 -4
  32. package/ui/toast-hyperclay.js +5 -9
  33. package/ui/toast.js +4 -7
  34. package/utilities/cookie.js +4 -7
  35. package/utilities/debounce.js +10 -4
  36. package/utilities/mutation.js +5 -0
  37. package/utilities/nearest.js +6 -1
  38. package/utilities/throttle.js +8 -2
  39. package/vendor/idiomorph.min.js +9 -1
  40. package/README.template.md +0 -276
package/hyperclay.js CHANGED
@@ -1,453 +1,67 @@
1
1
  /**
2
- * HyperclayJS v1.2.0 - Self-detecting module loader
3
- * Automatically loads requested features with dependency resolution
2
+ * HyperclayJS v1.3.1 - Minimal Browser-Native Loader
4
3
  *
5
- * USAGE:
4
+ * Modules self-export to window.hyperclay when imported.
5
+ * Modules auto-init when imported (no separate init call needed).
6
+ * Uses top-level await so subsequent module scripts automatically wait.
6
7
  *
7
8
  * <!-- Load with a preset -->
8
9
  * <script src="https://cdn.jsdelivr.net/npm/hyperclayjs@1/hyperclay.js?preset=minimal" type="module"></script>
9
- * <script src="https://cdn.jsdelivr.net/npm/hyperclayjs@1/hyperclay.js?preset=standard" type="module"></script>
10
- * <script src="https://cdn.jsdelivr.net/npm/hyperclayjs@1/hyperclay.js?preset=everything" type="module"></script>
11
- *
12
10
  * <!-- Load specific features -->
13
11
  * <script src="https://cdn.jsdelivr.net/npm/hyperclayjs@1/hyperclay.js?features=save,admin,toast" type="module"></script>
14
- *
15
- * <!-- Combine presets and features -->
16
- * <script src="https://cdn.jsdelivr.net/npm/hyperclayjs@1/hyperclay.js?preset=minimal&features=modals,ajax" type="module"></script>
17
- *
18
- * Available presets: minimal, standard, everything
19
- * See https://github.com/hyperclay/hyperclayjs for full list of features
12
+ * <!-- Load preset with exclusions -->
13
+ * <script src="https://cdn.jsdelivr.net/npm/hyperclayjs@1/hyperclay.js?preset=everything&exclude=tailwind-play,behavior-collector" type="module"></script>
20
14
  *
21
15
  * AUTO-GENERATED FILE - Do not edit directly
22
- * Generated from module-dependency-graph.json
23
16
  */
24
17
 
25
- (async function() {
26
- 'use strict';
27
-
28
- // Create a promise that resolves when hyperclay is ready
29
- let hyperclayReadyResolve;
30
- window.hyperclayReady = new Promise(resolve => {
31
- hyperclayReadyResolve = resolve;
32
- });
33
-
34
- // Initialize namespaces
35
- window.hyperclay = window.hyperclay || {};
36
-
37
- // Module dependency map - AUTO-GENERATED
38
- const moduleDependencies = {
39
- "save-core": {
40
- "path": "./core/savePageCore.js",
41
- "dependencies": [
42
- "cookie"
43
- ],
44
- "exports": {
45
- "savePage": [
46
- "hyperclay"
47
- ]
48
- }
49
- },
50
- "save": {
51
- "path": "./core/savePage.js",
52
- "dependencies": [
53
- "save-core",
54
- "toast",
55
- "toast-hyperclay",
56
- "mutation",
57
- "throttle"
58
- ],
59
- "exports": {
60
- "beforeSave": [
61
- "hyperclay"
62
- ],
63
- "savePage": [
64
- "hyperclay"
65
- ],
66
- "replacePageWith": [
67
- "hyperclay"
68
- ],
69
- "initHyperclaySaveButton": [
70
- "hyperclay"
71
- ],
72
- "initSaveKeyboardShortcut": [
73
- "hyperclay"
74
- ],
75
- "initSavePageOnChange": [
76
- "hyperclay"
77
- ]
78
- }
79
- },
80
- "admin": {
81
- "path": "./core/adminSystem.js",
82
- "dependencies": [
83
- "save",
84
- "dom-ready"
85
- ],
86
- "exports": {}
87
- },
88
- "persist": {
89
- "path": "./core/enablePersistentFormInputValues.js",
90
- "dependencies": [
91
- "save"
92
- ],
93
- "exports": {
94
- "enablePersistentFormInputValues": [
95
- "hyperclay"
96
- ]
97
- }
98
- },
99
- "options": {
100
- "path": "./core/optionVisibilityRuleGenerator.js",
101
- "dependencies": [
102
- "mutation"
103
- ],
104
- "exports": {
105
- "optionVisibilityRuleGenerator": [
106
- "window",
107
- "hyperclay"
108
- ]
109
- }
110
- },
111
- "editmode": {
112
- "path": "./core/editmodeSystem.js",
113
- "dependencies": [
114
- "save",
115
- "dom-ready"
116
- ],
117
- "exports": {
118
- "toggleEditMode": [
119
- "hyperclay"
120
- ],
121
- "isEditMode": [
122
- "hyperclay"
123
- ],
124
- "isOwner": [
125
- "hyperclay"
126
- ]
127
- }
128
- },
129
- "events": {
130
- "path": "./custom-attributes/events.js",
131
- "dependencies": [
132
- "mutation",
133
- "window-load"
134
- ],
135
- "exports": {}
136
- },
137
- "ajax": {
138
- "path": "./custom-attributes/ajaxElements.js",
139
- "dependencies": [
140
- "get-data-from-form"
141
- ],
142
- "exports": {}
143
- },
144
- "sortable": {
145
- "path": "./custom-attributes/sortable.js",
146
- "dependencies": [
147
- "mutation"
148
- ],
149
- "exports": {
150
- "Sortable": [
151
- "window",
152
- "hyperclay"
153
- ]
154
- }
155
- },
156
- "helpers": {
157
- "path": "./custom-attributes/domHelpers.js",
158
- "dependencies": [
159
- "nearest"
160
- ],
161
- "exports": {
162
- "initCustomAttributes": [
163
- "window",
164
- "hyperclay"
165
- ]
166
- }
167
- },
168
- "inputs": {
169
- "path": "./custom-attributes/inputHelpers.js",
170
- "dependencies": [],
171
- "exports": {}
172
- },
173
- "prompts": {
174
- "path": "./ui/prompts.js",
175
- "dependencies": [
176
- "dom-ready",
177
- "copy-to-clipboard",
178
- "modals",
179
- "toast",
180
- "toast-hyperclay"
181
- ],
182
- "exports": {
183
- "ask": [
184
- "window",
185
- "hyperclay"
186
- ],
187
- "consent": [
188
- "window",
189
- "hyperclay"
190
- ],
191
- "tell": [
192
- "window",
193
- "hyperclay"
194
- ],
195
- "snippet": [
196
- "hyperclay"
197
- ],
198
- "showApiKey": [
199
- "hyperclay"
200
- ]
201
- }
202
- },
203
- "toast": {
204
- "path": "./ui/toast.js",
205
- "dependencies": [],
206
- "exports": {
207
- "toast": [
208
- "window",
209
- "hyperclay"
210
- ]
211
- }
212
- },
213
- "toast-hyperclay": {
214
- "path": "./ui/toast-hyperclay.js",
215
- "dependencies": [
216
- "toast"
217
- ],
218
- "exports": {
219
- "toast": [
220
- "window",
221
- "hyperclay"
222
- ]
223
- }
224
- },
225
- "modals": {
226
- "path": "./ui/theModal.js",
227
- "dependencies": [],
228
- "exports": {
229
- "themodal": [
230
- "window",
231
- "hyperclay"
232
- ]
233
- }
234
- },
235
- "info": {
236
- "path": "./ui/info.js",
237
- "dependencies": [
238
- "dom-ready",
239
- "modals"
240
- ],
241
- "exports": {
242
- "info": [
243
- "window",
244
- "hyperclay"
245
- ]
246
- }
247
- },
248
- "tailwind-play": {
249
- "path": "./vendor/tailwind-play.js",
250
- "dependencies": [
251
- "style-injection"
252
- ],
253
- "exports": {}
254
- },
255
- "mutation": {
256
- "path": "./utilities/mutation.js",
257
- "dependencies": [],
258
- "exports": {
259
- "Mutation": [
260
- "window",
261
- "hyperclay"
262
- ]
263
- }
264
- },
265
- "nearest": {
266
- "path": "./utilities/nearest.js",
267
- "dependencies": [],
268
- "exports": {
269
- "nearest": [
270
- "window",
271
- "hyperclay"
272
- ]
273
- }
274
- },
275
- "cookie": {
276
- "path": "./utilities/cookie.js",
277
- "dependencies": [],
278
- "exports": {
279
- "cookie": [
280
- "window",
281
- "hyperclay"
282
- ]
283
- }
284
- },
285
- "throttle": {
286
- "path": "./utilities/throttle.js",
287
- "dependencies": [],
288
- "exports": {
289
- "throttle": [
290
- "hyperclay"
291
- ]
292
- }
293
- },
294
- "debounce": {
295
- "path": "./utilities/debounce.js",
296
- "dependencies": [],
297
- "exports": {
298
- "debounce": [
299
- "hyperclay"
300
- ]
301
- }
302
- },
303
- "dom-ready": {
304
- "path": "./dom-utilities/onDomReady.js",
305
- "dependencies": [],
306
- "exports": {
307
- "onDomReady": [
308
- "hyperclay"
309
- ]
310
- }
311
- },
312
- "window-load": {
313
- "path": "./dom-utilities/onLoad.js",
314
- "dependencies": [],
315
- "exports": {
316
- "onLoad": [
317
- "hyperclay"
318
- ]
319
- }
320
- },
321
- "alljs": {
322
- "path": "./dom-utilities/All.js",
323
- "dependencies": [],
324
- "exports": {
325
- "All": [
326
- "window",
327
- "hyperclay"
328
- ]
329
- }
330
- },
331
- "style-injection": {
332
- "path": "./dom-utilities/insertStyleTag.js",
333
- "dependencies": [],
334
- "exports": {
335
- "insertStyleTag": [
336
- "window",
337
- "hyperclay"
338
- ]
339
- }
340
- },
341
- "get-data-from-form": {
342
- "path": "./dom-utilities/getDataFromForm.js",
343
- "dependencies": [],
344
- "exports": {
345
- "getDataFromForm": [
346
- "window",
347
- "hyperclay"
348
- ]
349
- }
350
- },
351
- "idiomorph": {
352
- "path": "./vendor/idiomorph.min.js",
353
- "dependencies": [],
354
- "exports": {
355
- "Idiomorph": [
356
- "hyperclay"
357
- ]
358
- }
359
- },
360
- "slugify": {
361
- "path": "./string-utilities/slugify.js",
362
- "dependencies": [],
363
- "exports": {
364
- "slugify": [
365
- "window",
366
- "hyperclay"
367
- ]
368
- }
369
- },
370
- "emmet-html": {
371
- "path": "./string-utilities/emmet-html.js",
372
- "dependencies": [],
373
- "exports": {
374
- "emmet": [
375
- "hyperclay"
376
- ]
377
- }
378
- },
379
- "copy-to-clipboard": {
380
- "path": "./string-utilities/copy-to-clipboard.js",
381
- "dependencies": [],
382
- "exports": {
383
- "copyToClipboard": [
384
- "hyperclay"
385
- ]
386
- }
387
- },
388
- "query-parser": {
389
- "path": "./string-utilities/query.js",
390
- "dependencies": [],
391
- "exports": {
392
- "query": [
393
- "window",
394
- "hyperclay"
395
- ]
396
- }
397
- },
398
- "behavior-collector": {
399
- "path": "./communication/behaviorCollector.js",
400
- "dependencies": [],
401
- "exports": {
402
- "behaviorCollector": [
403
- "hyperclay"
404
- ]
405
- }
406
- },
407
- "send-message": {
408
- "path": "./communication/sendMessage.js",
409
- "dependencies": [
410
- "behavior-collector",
411
- "get-data-from-form",
412
- "toast",
413
- "toast-hyperclay"
414
- ],
415
- "exports": {
416
- "sendMessage": [
417
- "hyperclay"
418
- ]
419
- }
420
- },
421
- "file-upload": {
422
- "path": "./communication/uploadFile.js",
423
- "dependencies": [
424
- "copy-to-clipboard",
425
- "toast",
426
- "toast-hyperclay",
427
- "debounce"
428
- ],
429
- "exports": {
430
- "uploadFile": [
431
- "hyperclay"
432
- ],
433
- "createFile": [
434
- "hyperclay"
435
- ],
436
- "uploadFileBasic": [
437
- "hyperclay"
438
- ]
439
- }
440
- }
18
+ window.hyperclay = window.hyperclay || {};
19
+ window.hyperclayModules = window.hyperclayModules || {};
20
+
21
+ const MODULE_PATHS = {
22
+ "save-core": "./core/savePageCore.js",
23
+ "save-system": "./core/savePage.js",
24
+ "autosave": "./core/autosave.js",
25
+ "admin": "./core/adminSystem.js",
26
+ "persist": "./core/enablePersistentFormInputValues.js",
27
+ "option-visibility": "./core/optionVisibilityRuleGenerator.js",
28
+ "edit-mode": "./core/editmodeSystem.js",
29
+ "event-attrs": "./custom-attributes/events.js",
30
+ "ajax-elements": "./custom-attributes/ajaxElements.js",
31
+ "sortable": "./custom-attributes/sortable.js",
32
+ "dom-helpers": "./custom-attributes/domHelpers.js",
33
+ "input-helpers": "./custom-attributes/inputHelpers.js",
34
+ "dialogs": "./ui/prompts.js",
35
+ "toast": "./ui/toast.js",
36
+ "toast-hyperclay": "./ui/toast-hyperclay.js",
37
+ "modal": "./ui/theModal.js",
38
+ "tailwind-play": "./vendor/tailwind-play.js",
39
+ "mutation": "./utilities/mutation.js",
40
+ "nearest": "./utilities/nearest.js",
41
+ "cookie": "./utilities/cookie.js",
42
+ "throttle": "./utilities/throttle.js",
43
+ "debounce": "./utilities/debounce.js",
44
+ "dom-ready": "./dom-utilities/onDomReady.js",
45
+ "window-load": "./dom-utilities/onLoad.js",
46
+ "all-js": "./dom-utilities/All.js",
47
+ "style-injection": "./dom-utilities/insertStyleTag.js",
48
+ "form-data": "./dom-utilities/getDataFromForm.js",
49
+ "idiomorph": "./vendor/idiomorph.min.js",
50
+ "slugify": "./string-utilities/slugify.js",
51
+ "emmet": "./string-utilities/emmet-html.js",
52
+ "clipboard": "./string-utilities/copy-to-clipboard.js",
53
+ "query-params": "./string-utilities/query.js",
54
+ "behavior-collector": "./communication/behaviorCollector.js",
55
+ "send-message": "./communication/sendMessage.js",
56
+ "file-upload": "./communication/uploadFile.js"
441
57
  };
442
-
443
- // Preset configurations - AUTO-GENERATED
444
- const presets = {
58
+ const PRESETS = {
445
59
  "minimal": {
446
60
  "name": "Minimal",
447
61
  "description": "Essential features for basic editing",
448
62
  "modules": [
449
63
  "save-core",
450
- "save",
64
+ "save-system",
451
65
  "admin",
452
66
  "toast"
453
67
  ]
@@ -457,12 +71,12 @@
457
71
  "description": "Standard feature set for most use cases",
458
72
  "modules": [
459
73
  "save-core",
460
- "save",
74
+ "save-system",
461
75
  "admin",
462
76
  "persist",
463
- "ajax",
464
- "events",
465
- "helpers",
77
+ "option-visibility",
78
+ "event-attrs",
79
+ "dom-helpers",
466
80
  "toast"
467
81
  ]
468
82
  },
@@ -471,21 +85,21 @@
471
85
  "description": "All available features",
472
86
  "modules": [
473
87
  "save-core",
474
- "save",
88
+ "save-system",
89
+ "autosave",
475
90
  "admin",
476
91
  "persist",
477
- "options",
478
- "editmode",
479
- "events",
480
- "ajax",
92
+ "option-visibility",
93
+ "edit-mode",
94
+ "event-attrs",
95
+ "ajax-elements",
481
96
  "sortable",
482
- "helpers",
483
- "inputs",
484
- "prompts",
97
+ "dom-helpers",
98
+ "input-helpers",
99
+ "dialogs",
485
100
  "toast",
486
101
  "toast-hyperclay",
487
- "modals",
488
- "info",
102
+ "modal",
489
103
  "tailwind-play",
490
104
  "mutation",
491
105
  "nearest",
@@ -494,14 +108,14 @@
494
108
  "debounce",
495
109
  "dom-ready",
496
110
  "window-load",
497
- "alljs",
111
+ "all-js",
498
112
  "style-injection",
499
- "get-data-from-form",
113
+ "form-data",
500
114
  "idiomorph",
501
115
  "slugify",
502
- "emmet-html",
503
- "copy-to-clipboard",
504
- "query-parser",
116
+ "emmet",
117
+ "clipboard",
118
+ "query-params",
505
119
  "behavior-collector",
506
120
  "send-message",
507
121
  "file-upload"
@@ -509,251 +123,51 @@
509
123
  }
510
124
  };
511
125
 
512
- // Find our script tag
513
- const currentScript = document.currentScript ||
514
- Array.from(document.scripts).find(s =>
515
- s.src && (s.src.includes('hyperclay.js') || s.src.includes('hyperclay-starter-kit.js'))
516
- );
517
-
518
- if (!currentScript) {
519
- console.error('HyperclayJS: Could not find script tag');
520
- return;
521
- }
522
-
523
- // Parse URL parameters
524
- const scriptUrl = new URL(currentScript.src);
525
- const featuresParam = scriptUrl.searchParams.get('features');
526
- const presetParam = scriptUrl.searchParams.get('preset');
527
- const debugMode = scriptUrl.searchParams.get('debug') === 'true';
528
-
529
- // Determine requested features
530
- let requestedFeatures = [];
531
-
532
- if (presetParam && presets[presetParam]) {
533
- requestedFeatures = presets[presetParam].modules;
534
- if (debugMode) console.log(`HyperclayJS: Loading preset "${presetParam}"`);
535
- } else if (featuresParam) {
536
- requestedFeatures = featuresParam.split(',').map(f => f.trim());
537
- if (debugMode) console.log(`HyperclayJS: Loading features:`, requestedFeatures);
538
- } else {
539
- // Default to minimal preset
540
- requestedFeatures = presets.minimal.modules;
541
- if (debugMode) console.log('HyperclayJS: No features specified, loading minimal preset');
542
- }
543
-
544
- // Resolve all dependencies
545
- function resolveDependencies(features) {
546
- const resolved = new Set();
547
- const queue = [...features];
548
-
549
- while (queue.length > 0) {
550
- const feature = queue.shift();
551
-
552
- if (resolved.has(feature)) continue;
553
-
554
- const module = moduleDependencies[feature];
555
- if (!module) {
556
- console.warn(`HyperclayJS: Unknown feature "${feature}"`);
557
- continue;
558
- }
559
-
560
- // Add dependencies to queue
561
- if (module.dependencies && module.dependencies.length > 0) {
562
- module.dependencies.forEach(dep => {
563
- if (!resolved.has(dep)) {
564
- queue.push(dep);
565
- }
566
- });
567
- }
568
-
569
- // Mark this feature as resolved
570
- resolved.add(feature);
571
- }
572
-
573
- return Array.from(resolved);
574
- }
575
-
576
- // Topological sort for correct load order
577
- function topologicalSort(features) {
578
- const visited = new Set();
579
- const result = [];
580
-
581
- function visit(feature) {
582
- if (visited.has(feature)) return;
583
- visited.add(feature);
584
-
585
- const module = moduleDependencies[feature];
586
- if (module && module.dependencies) {
587
- module.dependencies.forEach(dep => {
588
- if (features.includes(dep)) {
589
- visit(dep);
590
- }
591
- });
592
- }
593
-
594
- result.push(feature);
595
- }
596
-
597
- features.forEach(feature => visit(feature));
598
- return result;
599
- }
600
-
601
- // Get base URL for module imports
602
- function getBaseUrl() {
603
- const scriptDir = scriptUrl.href.substring(0, scriptUrl.href.lastIndexOf('/'));
604
- return scriptDir;
605
- }
606
-
607
- // Load a module
608
- async function loadModule(feature, baseUrl) {
609
- const module = moduleDependencies[feature];
610
- if (!module) return null;
611
-
612
- const modulePath = `${baseUrl}/${module.path}`;
613
-
614
- try {
615
- if (debugMode) console.log(`HyperclayJS: Loading ${feature}...`);
616
- const loaded = await import(modulePath);
617
-
618
- // Auto-initialize if the module exports an init function
619
- if (loaded.init && typeof loaded.init === 'function') {
620
- loaded.init();
621
- }
622
-
623
- return loaded;
624
- } catch (error) {
625
- console.error(`HyperclayJS: Failed to load ${feature}:`, error);
626
- return null;
627
- }
628
- }
629
-
630
- // Main execution
631
- try {
632
- // Resolve all dependencies
633
- const allFeatures = resolveDependencies(requestedFeatures);
634
-
635
- // Sort in correct load order
636
- const loadOrder = topologicalSort(allFeatures);
637
-
638
- if (debugMode) console.log('HyperclayJS: Load order:', loadOrder);
639
-
640
- // Get base URL
641
- const baseUrl = getBaseUrl();
642
-
643
- // Track loaded modules
644
- const loadedModules = {};
645
-
646
- // Load modules in order
647
- for (const feature of loadOrder) {
648
- const module = await loadModule(feature, baseUrl);
649
- if (module) {
650
- loadedModules[feature] = module;
651
- }
652
- }
653
-
654
- // Store loaded modules globally for access
655
- window.hyperclayModules = loadedModules;
656
-
657
- // Attach exports to window based on module configuration
658
- for (const feature of loadOrder) {
659
- const module = loadedModules[feature];
660
- const moduleConfig = moduleDependencies[feature];
661
-
662
- if (!module || !moduleConfig.exports) continue;
663
-
664
- // For each export in the module's configuration
665
- for (const [exportName, locations] of Object.entries(moduleConfig.exports)) {
666
- // Try to get the export - check both named export and default export
667
- let exportValue = module[exportName];
668
-
669
- // If not found as named export, try default export
670
- if (!exportValue && module.default) {
671
- exportValue = module.default;
672
- }
673
-
674
- if (!exportValue) continue;
675
-
676
- // Attach to each configured location
677
- locations.forEach(location => {
678
- if (location === 'window') {
679
- window[exportName] = exportValue;
680
- } else if (location === 'hyperclay') {
681
- window.hyperclay[exportName] = exportValue;
682
- }
683
- });
684
- }
685
- }
126
+ // Parse URL (use import.meta.url for ES modules since document.currentScript is null)
127
+ const url = new URL(import.meta.url);
128
+ const preset = url.searchParams.get('preset');
129
+ const features = url.searchParams.get('features');
130
+ const exclude = url.searchParams.get('exclude');
131
+ const debug = url.searchParams.get('debug') === 'true';
132
+ const baseUrl = url.href.substring(0, url.href.lastIndexOf('/'));
133
+
134
+ // Get requested features
135
+ let requested = [];
136
+ if (preset && PRESETS[preset]) {
137
+ requested = [...PRESETS[preset].modules];
138
+ } else if (features) {
139
+ requested = features.split(',').map(f => f.trim());
140
+ } else {
141
+ requested = [...PRESETS.minimal.modules];
142
+ }
686
143
 
687
- // Create window.h alias
688
- window.h = window.hyperclay;
144
+ // Apply exclusions
145
+ if (exclude) {
146
+ const excluded = new Set(exclude.split(',').map(f => f.trim()));
147
+ requested = requested.filter(f => !excluded.has(f));
148
+ }
689
149
 
690
- // Fire custom event when loading is complete
691
- window.dispatchEvent(new CustomEvent('hyperclayReady', {
692
- detail: {
693
- features: loadOrder,
694
- modules: loadedModules
695
- }
696
- }));
150
+ // Modules that extend prototypes must load before modules that execute user code
151
+ const LOAD_FIRST = new Set(['dom-helpers', 'all-js']);
697
152
 
698
- // Resolve the ready promise
699
- if (hyperclayReadyResolve) {
700
- hyperclayReadyResolve(window.hyperclay);
701
- }
153
+ const loadModules = (modules) => Promise.all(modules.map(async feature => {
154
+ const path = MODULE_PATHS[feature];
155
+ if (!path) throw new Error(`Unknown feature: ${feature}`);
156
+ if (debug) console.log(`HyperclayJS: Loading ${feature}...`);
157
+ const module = await import(`${baseUrl}/${path}`);
158
+ window.hyperclayModules[feature] = module;
159
+ }));
702
160
 
703
- if (debugMode) {
704
- console.log('HyperclayJS: All modules loaded successfully');
161
+ if (debug) console.log('HyperclayJS: Loading features:', requested);
705
162
 
706
- // Show feature summary - AUTO-GENERATED
707
- const sizes = {
708
- "save-core": 5.9,
709
- "save": 4.9,
710
- "admin": 5.300000000000001,
711
- "persist": 2.2,
712
- "options": 4.4,
713
- "editmode": 1.4,
714
- "events": 3.5,
715
- "ajax": 2.7,
716
- "sortable": 117.89999999999999,
717
- "helpers": 5.4,
718
- "inputs": 1.2,
719
- "prompts": 7.7,
720
- "toast": 7.3,
721
- "toast-hyperclay": 8,
722
- "modals": 18.4,
723
- "info": 3.2,
724
- "tailwind-play": 362.3,
725
- "mutation": 12.8,
726
- "nearest": 3.2,
727
- "cookie": 1.3,
728
- "throttle": 0.6,
729
- "debounce": 0.2,
730
- "dom-ready": 0.2,
731
- "window-load": 0.2,
732
- "alljs": 13.9,
733
- "style-injection": 0.8,
734
- "get-data-from-form": 1.7,
735
- "idiomorph": 7.9,
736
- "slugify": 0.7,
737
- "emmet-html": 1.4,
738
- "copy-to-clipboard": 0.9,
739
- "query-parser": 0.1,
740
- "behavior-collector": 5.2,
741
- "send-message": 1.2,
742
- "file-upload": 10.4
743
- };
744
- const totalSize = loadOrder.reduce((sum, feature) => {
745
- return sum + (sizes[feature] || 0);
746
- }, 0);
163
+ // Load in waves: prototype extenders first, then everything else
164
+ const first = requested.filter(f => LOAD_FIRST.has(f));
165
+ const rest = requested.filter(f => !LOAD_FIRST.has(f));
747
166
 
748
- console.log(`HyperclayJS: Loaded ${loadOrder.length} modules (~${totalSize.toFixed(1)}KB)`);
749
- }
167
+ if (first.length) await loadModules(first);
168
+ if (rest.length) await loadModules(rest);
750
169
 
751
- } catch (error) {
752
- console.error('HyperclayJS: Fatal error during initialization:', error);
753
- }
754
- })();
170
+ // Create h alias
171
+ window.h = window.hyperclay;
755
172
 
756
- // Export for use in build tools
757
- if (typeof module !== 'undefined' && module.exports) {
758
- module.exports = { version: '1.0.0' };
759
- }
173
+ if (debug) console.log('HyperclayJS: Ready');