hyperclayjs 1.1.2 → 1.3.0

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