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.
- package/README.md +44 -59
- package/communication/behaviorCollector.js +8 -1
- package/communication/sendMessage.js +8 -2
- package/communication/uploadFile.js +8 -2
- package/core/adminSystem.js +3 -0
- package/core/autosave.js +95 -0
- package/core/editmodeSystem.js +10 -8
- package/core/enablePersistentFormInputValues.js +8 -1
- package/core/optionVisibilityRuleGenerator.js +9 -1
- package/core/savePage.js +28 -71
- package/core/savePageCore.js +7 -14
- package/custom-attributes/ajaxElements.js +4 -0
- package/custom-attributes/domHelpers.js +9 -0
- package/custom-attributes/events.js +3 -0
- package/custom-attributes/inputHelpers.js +3 -0
- package/custom-attributes/sortable.js +9 -1
- package/dom-utilities/All.js +4 -7
- package/dom-utilities/getDataFromForm.js +9 -2
- package/dom-utilities/insertStyleTag.js +9 -2
- package/dom-utilities/onDomReady.js +8 -2
- package/dom-utilities/onLoad.js +8 -2
- package/hyperclay.js +109 -673
- package/module-dependency-graph.json +193 -137
- package/package.json +3 -3
- package/string-utilities/copy-to-clipboard.js +3 -7
- package/string-utilities/emmet-html.js +8 -2
- package/string-utilities/query.js +8 -1
- package/string-utilities/slugify.js +4 -7
- package/ui/info.js +9 -1
- package/ui/prompts.js +19 -12
- package/ui/theModal.js +4 -4
- package/ui/toast-hyperclay.js +21 -0
- package/ui/toast.js +4 -7
- package/utilities/cookie.js +4 -7
- package/utilities/debounce.js +10 -4
- package/utilities/mutation.js +5 -0
- package/utilities/nearest.js +6 -1
- package/utilities/throttle.js +8 -2
- package/vendor/idiomorph.min.js +9 -1
- package/README.template.md +0 -276
package/README.md
CHANGED
|
@@ -52,89 +52,87 @@ import 'hyperclayjs/presets/standard.js';
|
|
|
52
52
|
|
|
53
53
|
| Module | Size | Description |
|
|
54
54
|
|--------|------|-------------|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
55
|
+
| admin | 5.4KB | Hides admin inputs, scripts, contenteditable, onclick for regular viewers |
|
|
56
|
+
| autosave | 2.4KB | Auto-save on DOM changes, unsaved changes warning |
|
|
57
|
+
| edit-mode | 1.7KB | Toggle edit mode on/off |
|
|
58
|
+
| option-visibility | 4.7KB | Dynamic show/hide based on ancestor state with option:attribute="value" |
|
|
59
|
+
| persist | 2.4KB | Persist form values to the DOM with [persist] attribute |
|
|
60
|
+
| save-core | 5.8KB | Basic save function only - hyperclay.savePage() |
|
|
61
|
+
| save-system | 4.1KB | Manual save: keyboard shortcut (CMD+S), save button, change tracking |
|
|
61
62
|
|
|
62
63
|
### Custom Attributes (HTML enhancements)
|
|
63
64
|
|
|
64
65
|
| Module | Size | Description |
|
|
65
66
|
|--------|------|-------------|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
67
|
+
| ajax-elements | 2.8KB | [ajax-form], [ajax-button] for async form submissions |
|
|
68
|
+
| dom-helpers | 5.6KB | el.nearest, el.val, el.text, el.exec, el.cycle |
|
|
69
|
+
| event-attrs | 3.6KB | [onclickaway], [onclone], [onpagemutation], [onrender] |
|
|
70
|
+
| input-helpers | 1.2KB | [prevent-enter], [autosize] for textareas |
|
|
71
|
+
| sortable | 118.1KB | Drag-drop sorting with [sortable] - includes Sortable.js vendor library |
|
|
71
72
|
|
|
72
73
|
### UI Components (User interface elements)
|
|
73
74
|
|
|
74
75
|
| Module | Size | Description |
|
|
75
76
|
|--------|------|-------------|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
| Toast Notifications | 7.3KB | Success/error message notifications - toast(msg, msgType) |
|
|
77
|
+
| dialogs | 11.2KB | ask(), consent(), tell(), info(), snippet() functions |
|
|
78
|
+
| modal | 18.5KB | Full modal window creation system - window.theModal |
|
|
79
|
+
| tailwind-play | 362.3KB | Live Tailwind CSS editing - no need for a build system |
|
|
80
|
+
| toast | 7.3KB | Success/error message notifications - toast(msg, msgType) |
|
|
81
81
|
|
|
82
82
|
### Utilities (Core utilities (often auto-included))
|
|
83
83
|
|
|
84
84
|
| Module | Size | Description |
|
|
85
85
|
|--------|------|-------------|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
86
|
+
| cookie | 1.3KB | Cookie management (often auto-included) |
|
|
87
|
+
| debounce | 0.4KB | Function debouncing |
|
|
88
|
+
| mutation | 12.9KB | DOM mutation observation (often auto-included) |
|
|
89
|
+
| nearest | 3.3KB | Find nearest elements (often auto-included) |
|
|
90
|
+
| throttle | 0.7KB | Function throttling |
|
|
91
91
|
|
|
92
92
|
### DOM Utilities (DOM manipulation helpers)
|
|
93
93
|
|
|
94
94
|
| Module | Size | Description |
|
|
95
95
|
|--------|------|-------------|
|
|
96
|
-
|
|
|
97
|
-
|
|
|
98
|
-
|
|
|
99
|
-
|
|
|
100
|
-
| Window Load | 0.2KB | Window load callback |
|
|
96
|
+
| all-js | 13.9KB | Full DOM manipulation library |
|
|
97
|
+
| dom-ready | 0.3KB | DOM ready callback |
|
|
98
|
+
| form-data | 1.9KB | Extract form data as an object |
|
|
99
|
+
| style-injection | 1KB | Dynamic stylesheet injection |
|
|
101
100
|
|
|
102
101
|
### String Utilities (String manipulation helpers)
|
|
103
102
|
|
|
104
103
|
| Module | Size | Description |
|
|
105
104
|
|--------|------|-------------|
|
|
106
|
-
|
|
|
107
|
-
|
|
|
108
|
-
|
|
|
109
|
-
|
|
|
105
|
+
| clipboard | 0.8KB | Clipboard utility |
|
|
106
|
+
| emmet | 1.5KB | Emmet-like HTML generation |
|
|
107
|
+
| query-params | 0.2KB | Parse URL search params |
|
|
108
|
+
| slugify | 0.6KB | URL-friendly slug generator |
|
|
110
109
|
|
|
111
110
|
### Communication & Files (File handling and messaging)
|
|
112
111
|
|
|
113
112
|
| Module | Size | Description |
|
|
114
113
|
|--------|------|-------------|
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
| Send Message to App Owner | 1.2KB | Message sending utility |
|
|
114
|
+
| file-upload | 10.6KB | File upload with progress |
|
|
115
|
+
| send-message | 1.3KB | Message sending utility |
|
|
118
116
|
|
|
119
117
|
### Vendor Libraries (Third-party libraries)
|
|
120
118
|
|
|
121
119
|
| Module | Size | Description |
|
|
122
120
|
|--------|------|-------------|
|
|
123
|
-
|
|
|
121
|
+
| idiomorph | 8.1KB | Efficient DOM morphing library |
|
|
124
122
|
|
|
125
123
|
## Presets
|
|
126
124
|
|
|
127
|
-
### Minimal (~
|
|
125
|
+
### Minimal (~22.6KB)
|
|
128
126
|
Essential features for basic editing
|
|
129
127
|
|
|
130
|
-
**Modules:** `save-core`, `save`, `admin`, `toast`
|
|
128
|
+
**Modules:** `save-core`, `save-system`, `admin`, `toast`
|
|
131
129
|
|
|
132
|
-
### Standard (~
|
|
130
|
+
### Standard (~38.9KB)
|
|
133
131
|
Standard feature set for most use cases
|
|
134
132
|
|
|
135
|
-
**Modules:** `save-core`, `save`, `admin`, `persist`, `
|
|
133
|
+
**Modules:** `save-core`, `save-system`, `admin`, `persist`, `option-visibility`, `event-attrs`, `dom-helpers`, `toast`
|
|
136
134
|
|
|
137
|
-
### Everything (~
|
|
135
|
+
### Everything (~629.5KB)
|
|
138
136
|
All available features
|
|
139
137
|
|
|
140
138
|
Includes all available modules across all categories.
|
|
@@ -214,12 +212,12 @@ The configurator dynamically loads this file to always show accurate information
|
|
|
214
212
|
|
|
215
213
|
## Browser Support
|
|
216
214
|
|
|
217
|
-
- Chrome
|
|
218
|
-
- Firefox
|
|
219
|
-
- Safari
|
|
220
|
-
- Edge
|
|
215
|
+
- Chrome 89+
|
|
216
|
+
- Firefox 89+
|
|
217
|
+
- Safari 15.4+
|
|
218
|
+
- Edge 89+
|
|
221
219
|
|
|
222
|
-
|
|
220
|
+
The loader uses top-level await, which means any `<script type="module">` placed after it will automatically wait for HyperclayJS to finish loading. No ready events or promises needed.
|
|
223
221
|
|
|
224
222
|
## API Examples
|
|
225
223
|
|
|
@@ -229,9 +227,6 @@ All features use modern JavaScript (ES2020+). For older browser support, use a t
|
|
|
229
227
|
// Manually save the page
|
|
230
228
|
hyperclay.savePage();
|
|
231
229
|
|
|
232
|
-
// Initialize auto-save
|
|
233
|
-
hyperclay.initSavePageOnChange();
|
|
234
|
-
|
|
235
230
|
// Add save button
|
|
236
231
|
hyperclay.initHyperclaySaveButton(); // Looks for [trigger-save]
|
|
237
232
|
|
|
@@ -308,18 +303,8 @@ export default function myFeature() {
|
|
|
308
303
|
// Feature implementation
|
|
309
304
|
}
|
|
310
305
|
|
|
311
|
-
//
|
|
312
|
-
|
|
313
|
-
if (typeof window !== 'undefined') {
|
|
314
|
-
// Auto-initialize on import
|
|
315
|
-
myFeature();
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Auto-run if needed
|
|
320
|
-
if (typeof window !== 'undefined') {
|
|
321
|
-
init();
|
|
322
|
-
}
|
|
306
|
+
// Auto-init when module is imported
|
|
307
|
+
myFeature();
|
|
323
308
|
```
|
|
324
309
|
|
|
325
310
|
## Migration from Monolithic Script
|
|
@@ -222,9 +222,16 @@ const behaviorCollector = (() => {
|
|
|
222
222
|
};
|
|
223
223
|
})();
|
|
224
224
|
|
|
225
|
+
// Self-export to hyperclay only
|
|
226
|
+
window.hyperclay = window.hyperclay || {};
|
|
227
|
+
window.hyperclay.behaviorCollector = behaviorCollector;
|
|
228
|
+
|
|
225
229
|
export default behaviorCollector;
|
|
226
230
|
|
|
227
231
|
// Auto-initialize - start collecting behavior data
|
|
228
232
|
export function init() {
|
|
229
233
|
behaviorCollector.init();
|
|
230
|
-
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Auto-init when module is imported
|
|
237
|
+
init();
|
|
@@ -2,7 +2,7 @@ import behaviorCollector from "./behaviorCollector.js";
|
|
|
2
2
|
import getDataFromForm from "../dom-utilities/getDataFromForm.js";
|
|
3
3
|
import toast from "../ui/toast.js";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
function sendMessage(eventOrObj, successMessage = "Successfully sent", callback) {
|
|
6
6
|
let form;
|
|
7
7
|
let data;
|
|
8
8
|
|
|
@@ -45,4 +45,10 @@ export default function sendMessage(eventOrObj, successMessage = "Successfully s
|
|
|
45
45
|
toast(`Failed to send message: ${error}`);
|
|
46
46
|
throw error;
|
|
47
47
|
});
|
|
48
|
-
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Self-export to hyperclay only
|
|
51
|
+
window.hyperclay = window.hyperclay || {};
|
|
52
|
+
window.hyperclay.sendMessage = sendMessage;
|
|
53
|
+
|
|
54
|
+
export default sendMessage;
|
|
@@ -322,7 +322,7 @@ function detectContentType(content) {
|
|
|
322
322
|
// CSV pattern
|
|
323
323
|
{ type: "csv", mime: "text/csv", regex: /^[^,\n]+(,[^,\n]+)+/ },
|
|
324
324
|
// Markdown pattern
|
|
325
|
-
{
|
|
325
|
+
{
|
|
326
326
|
type: "md",
|
|
327
327
|
mime: "text/markdown",
|
|
328
328
|
regex: /#\S+\s+\S+|```[\s\S]*```/
|
|
@@ -345,4 +345,10 @@ function detectContentType(content) {
|
|
|
345
345
|
|
|
346
346
|
// Default to plain text
|
|
347
347
|
return { type: "txt", mime: "text/plain", extension: ".txt" };
|
|
348
|
-
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Self-export to hyperclay only
|
|
351
|
+
window.hyperclay = window.hyperclay || {};
|
|
352
|
+
window.hyperclay.uploadFile = uploadFile;
|
|
353
|
+
window.hyperclay.createFile = createFile;
|
|
354
|
+
window.hyperclay.uploadFileBasic = uploadFileBasic;
|
package/core/adminSystem.js
CHANGED
package/core/autosave.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-save system for Hyperclay
|
|
3
|
+
*
|
|
4
|
+
* Automatically saves page on DOM changes with throttling.
|
|
5
|
+
* Warns before leaving page with unsaved changes.
|
|
6
|
+
*
|
|
7
|
+
* Requires the 'save' module to be loaded first.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import toast from "../ui/toast.js";
|
|
11
|
+
import throttle from "../utilities/throttle.js";
|
|
12
|
+
import Mutation from "../utilities/mutation.js";
|
|
13
|
+
import { isEditMode, isOwner } from "./isAdminOfCurrentResource.js";
|
|
14
|
+
import { getPageContents } from "./savePageCore.js";
|
|
15
|
+
import {
|
|
16
|
+
savePage,
|
|
17
|
+
getUnsavedChanges,
|
|
18
|
+
setUnsavedChanges,
|
|
19
|
+
getLastSavedContents
|
|
20
|
+
} from "./savePage.js";
|
|
21
|
+
|
|
22
|
+
let baselineContents = '';
|
|
23
|
+
|
|
24
|
+
// Capture baseline after setup mutations settle
|
|
25
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
26
|
+
if (isEditMode) {
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
baselineContents = getPageContents();
|
|
29
|
+
}, 1500);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Throttled version of savePage for auto-save
|
|
35
|
+
*/
|
|
36
|
+
const throttledSave = throttle(savePage, 1200);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Save the page with throttling, for use with auto-save
|
|
40
|
+
* Checks both baseline and last saved content to prevent saves from initial setup
|
|
41
|
+
*
|
|
42
|
+
* @param {Function} callback - Optional callback
|
|
43
|
+
*/
|
|
44
|
+
export function savePageThrottled(callback = () => {}) {
|
|
45
|
+
if (!isEditMode) return;
|
|
46
|
+
|
|
47
|
+
const currentContents = getPageContents();
|
|
48
|
+
// For autosave: check both that content changed from baseline AND from last save
|
|
49
|
+
// This prevents saves from initial setup mutations
|
|
50
|
+
if (currentContents !== baselineContents && currentContents !== getLastSavedContents()) {
|
|
51
|
+
setUnsavedChanges(true);
|
|
52
|
+
throttledSave(callback);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Initialize auto-save on DOM changes
|
|
58
|
+
* Uses debounced mutation observer
|
|
59
|
+
*/
|
|
60
|
+
export function initSavePageOnChange() {
|
|
61
|
+
Mutation.onAnyChange({
|
|
62
|
+
debounce: 3333,
|
|
63
|
+
omitChangeDetails: true
|
|
64
|
+
}, () => {
|
|
65
|
+
savePageThrottled(({msg, msgType} = {}) => {
|
|
66
|
+
if (msg) toast(msg, msgType);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Warn before leaving page with unsaved changes
|
|
73
|
+
*/
|
|
74
|
+
window.addEventListener('beforeunload', (event) => {
|
|
75
|
+
if (getUnsavedChanges() && isOwner) {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
event.returnValue = '';
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
function init() {
|
|
82
|
+
if (!isEditMode) return;
|
|
83
|
+
initSavePageOnChange();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Self-export to hyperclay
|
|
87
|
+
window.hyperclay = window.hyperclay || {};
|
|
88
|
+
window.hyperclay.savePageThrottled = savePageThrottled;
|
|
89
|
+
window.hyperclay.initSavePageOnChange = initSavePageOnChange;
|
|
90
|
+
|
|
91
|
+
// Auto-init when module is imported
|
|
92
|
+
init();
|
|
93
|
+
|
|
94
|
+
export { init, savePageThrottled, initSavePageOnChange };
|
|
95
|
+
export default init;
|
package/core/editmodeSystem.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
// Edit mode system - combines editmode toggle with page type setting
|
|
2
2
|
import { toggleEditMode } from './editmode.js';
|
|
3
|
+
import { isEditMode, isOwner } from './isAdminOfCurrentResource.js';
|
|
3
4
|
import { init as initPageType } from './setPageTypeOnDocumentElement.js';
|
|
4
5
|
|
|
5
6
|
function init() {
|
|
6
7
|
initPageType();
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
// Self-export to hyperclay only
|
|
11
|
+
window.hyperclay = window.hyperclay || {};
|
|
12
|
+
window.hyperclay.toggleEditMode = toggleEditMode;
|
|
13
|
+
window.hyperclay.isEditMode = isEditMode;
|
|
14
|
+
window.hyperclay.isOwner = isOwner;
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
// Auto-init when module is imported
|
|
17
|
+
init();
|
|
16
18
|
|
|
17
|
-
export { init,
|
|
18
|
-
export default { init,
|
|
19
|
+
export { init, toggleEditMode, isEditMode, isOwner };
|
|
20
|
+
export default { init, toggleEditMode, isEditMode, isOwner };
|
|
@@ -59,4 +59,11 @@ export default function enablePersistentFormInputValues(filterBySelector = "[per
|
|
|
59
59
|
// Auto-initialize with default selector
|
|
60
60
|
export function init() {
|
|
61
61
|
enablePersistentFormInputValues("[persist]");
|
|
62
|
-
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Self-export to hyperclay only
|
|
65
|
+
window.hyperclay = window.hyperclay || {};
|
|
66
|
+
window.hyperclay.enablePersistentFormInputValues = enablePersistentFormInputValues;
|
|
67
|
+
|
|
68
|
+
// Auto-init when module is imported
|
|
69
|
+
init();
|
|
@@ -152,9 +152,17 @@ const optionVisibilityRuleGenerator = {
|
|
|
152
152
|
},
|
|
153
153
|
};
|
|
154
154
|
|
|
155
|
+
// Self-export to window and hyperclay
|
|
156
|
+
window.optionVisibilityRuleGenerator = optionVisibilityRuleGenerator;
|
|
157
|
+
window.hyperclay = window.hyperclay || {};
|
|
158
|
+
window.hyperclay.optionVisibilityRuleGenerator = optionVisibilityRuleGenerator;
|
|
159
|
+
|
|
155
160
|
export default optionVisibilityRuleGenerator;
|
|
156
161
|
|
|
157
162
|
// Auto-initialize
|
|
158
163
|
export function init() {
|
|
159
164
|
optionVisibilityRuleGenerator.start();
|
|
160
|
-
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Auto-init when module is imported
|
|
168
|
+
init();
|
package/core/savePage.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Save system for Hyperclay
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Manual save with change detection, toast notifications,
|
|
5
|
+
* keyboard shortcuts, and save button support.
|
|
6
|
+
*
|
|
7
|
+
* For auto-save on DOM changes, also load the 'autosave' module.
|
|
6
8
|
*
|
|
7
9
|
* Built on top of savePageCore.js
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
import toast from "../ui/toast.js";
|
|
11
|
-
import throttle from "../utilities/throttle.js";
|
|
12
|
-
import Mutation from "../utilities/mutation.js";
|
|
13
13
|
import { isEditMode, isOwner } from "./isAdminOfCurrentResource.js";
|
|
14
14
|
import {
|
|
15
15
|
savePage as savePageCore,
|
|
@@ -20,9 +20,17 @@ import {
|
|
|
20
20
|
// Re-export beforeSave from core for backward compatibility
|
|
21
21
|
export { beforeSave } from "./savePageCore.js";
|
|
22
22
|
|
|
23
|
+
// Re-export getPageContents for autosave module
|
|
24
|
+
export { getPageContents } from "./savePageCore.js";
|
|
25
|
+
|
|
23
26
|
let unsavedChanges = false;
|
|
24
27
|
let lastSavedContents = '';
|
|
25
|
-
|
|
28
|
+
|
|
29
|
+
// State accessors for autosave module
|
|
30
|
+
export function getUnsavedChanges() { return unsavedChanges; }
|
|
31
|
+
export function setUnsavedChanges(val) { unsavedChanges = val; }
|
|
32
|
+
export function getLastSavedContents() { return lastSavedContents; }
|
|
33
|
+
export function setLastSavedContents(val) { lastSavedContents = val; }
|
|
26
34
|
|
|
27
35
|
// Initialize lastSavedContents on page load to match what's on disk
|
|
28
36
|
// This prevents unnecessary save attempts when content hasn't changed
|
|
@@ -30,11 +38,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
30
38
|
if (isEditMode) {
|
|
31
39
|
// Capture initial state immediately for comparison
|
|
32
40
|
lastSavedContents = getPageContents();
|
|
33
|
-
|
|
34
|
-
// Also capture baseline after setup for autosave detection
|
|
35
|
-
setTimeout(() => {
|
|
36
|
-
baselineContents = getPageContents();
|
|
37
|
-
}, 1500);
|
|
38
41
|
}
|
|
39
42
|
});
|
|
40
43
|
|
|
@@ -72,29 +75,6 @@ export function savePage(callback = () => {}) {
|
|
|
72
75
|
});
|
|
73
76
|
}
|
|
74
77
|
|
|
75
|
-
/**
|
|
76
|
-
* Throttled version of savePage for auto-save
|
|
77
|
-
*/
|
|
78
|
-
const throttledSave = throttle(savePage, 1200);
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Save the page with throttling, for use with auto-save
|
|
82
|
-
* Checks both baseline and last saved content to prevent saves from initial setup
|
|
83
|
-
*
|
|
84
|
-
* @param {Function} callback - Optional callback
|
|
85
|
-
*/
|
|
86
|
-
export function savePageThrottled(callback = () => {}) {
|
|
87
|
-
if (!isEditMode) return;
|
|
88
|
-
|
|
89
|
-
const currentContents = getPageContents();
|
|
90
|
-
// For autosave: check both that content changed from baseline AND from last save
|
|
91
|
-
// This prevents saves from initial setup mutations
|
|
92
|
-
if (currentContents !== baselineContents && currentContents !== lastSavedContents) {
|
|
93
|
-
unsavedChanges = true;
|
|
94
|
-
throttledSave(callback);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
78
|
/**
|
|
99
79
|
* Fetch HTML from a URL and save it, then reload
|
|
100
80
|
* Shows toast notifications
|
|
@@ -148,49 +128,26 @@ export function initHyperclaySaveButton() {
|
|
|
148
128
|
}
|
|
149
129
|
|
|
150
130
|
/**
|
|
151
|
-
* Initialize
|
|
152
|
-
*
|
|
153
|
-
*/
|
|
154
|
-
export function initSavePageOnChange() {
|
|
155
|
-
Mutation.onAnyChange({
|
|
156
|
-
debounce: 3333,
|
|
157
|
-
omitChangeDetails: true
|
|
158
|
-
}, () => {
|
|
159
|
-
savePageThrottled(({msg, msgType} = {}) => {
|
|
160
|
-
if (msg) toast(msg, msgType);
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Warn before leaving page with unsaved changes
|
|
167
|
-
*/
|
|
168
|
-
window.addEventListener('beforeunload', (event) => {
|
|
169
|
-
if (unsavedChanges && isOwner) {
|
|
170
|
-
event.preventDefault();
|
|
171
|
-
event.returnValue = '';
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Initialize the full save system
|
|
131
|
+
* Initialize the save system (keyboard shortcut and save button)
|
|
132
|
+
* For auto-save, also load the 'autosave' module
|
|
177
133
|
*/
|
|
178
134
|
export function init() {
|
|
179
135
|
if (!isEditMode) return;
|
|
180
136
|
|
|
181
137
|
initSaveKeyboardShortcut();
|
|
182
138
|
initHyperclaySaveButton();
|
|
183
|
-
initSavePageOnChange();
|
|
184
139
|
}
|
|
185
140
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
141
|
+
// Self-export to hyperclay only
|
|
142
|
+
window.hyperclay = window.hyperclay || {};
|
|
143
|
+
window.hyperclay.savePage = savePage;
|
|
144
|
+
window.hyperclay.beforeSave = beforeSave;
|
|
145
|
+
window.hyperclay.replacePageWith = replacePageWith;
|
|
146
|
+
window.hyperclay.initHyperclaySaveButton = initHyperclaySaveButton;
|
|
147
|
+
window.hyperclay.initSaveKeyboardShortcut = initSaveKeyboardShortcut;
|
|
193
148
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
149
|
+
// Auto-init when module is imported
|
|
150
|
+
init();
|
|
151
|
+
|
|
152
|
+
export { savePage, replacePageWith, initSaveKeyboardShortcut, initHyperclaySaveButton, init };
|
|
153
|
+
export default savePage;
|
package/core/savePageCore.js
CHANGED
|
@@ -220,17 +220,10 @@ export function replacePageWith(url, callback = () => {}) {
|
|
|
220
220
|
});
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
window.hyperclay.savePage = savePage;
|
|
232
|
-
window.hyperclay.saveHtml = saveHtml;
|
|
233
|
-
window.hyperclay.replacePageWith = replacePageWith;
|
|
234
|
-
window.hyperclay.beforeSave = beforeSave;
|
|
235
|
-
window.hyperclay.getPageContents = getPageContents;
|
|
236
|
-
}
|
|
223
|
+
// Self-export to hyperclay only
|
|
224
|
+
window.hyperclay = window.hyperclay || {};
|
|
225
|
+
window.hyperclay.savePage = savePage;
|
|
226
|
+
window.hyperclay.saveHtml = saveHtml;
|
|
227
|
+
window.hyperclay.replacePageWith = replacePageWith;
|
|
228
|
+
window.hyperclay.beforeSave = beforeSave;
|
|
229
|
+
window.hyperclay.getPageContents = getPageContents;
|
|
@@ -171,5 +171,14 @@ function init () {
|
|
|
171
171
|
};
|
|
172
172
|
|
|
173
173
|
}
|
|
174
|
+
|
|
175
|
+
// Self-export to window and hyperclay
|
|
176
|
+
window.initCustomAttributes = init;
|
|
177
|
+
window.hyperclay = window.hyperclay || {};
|
|
178
|
+
window.hyperclay.initCustomAttributes = init;
|
|
179
|
+
|
|
180
|
+
// Auto-init when module is imported
|
|
181
|
+
init();
|
|
182
|
+
|
|
174
183
|
export { init };
|
|
175
184
|
export default init;
|
|
@@ -72,5 +72,13 @@ function init () {
|
|
|
72
72
|
// ❌ onElementAdded(newElem => makeSortable(newElem.closest('[sortable]')))
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
export
|
|
75
|
+
// Self-export to window and hyperclay
|
|
76
|
+
window.Sortable = Sortable;
|
|
77
|
+
window.hyperclay = window.hyperclay || {};
|
|
78
|
+
window.hyperclay.Sortable = Sortable;
|
|
79
|
+
|
|
80
|
+
// Auto-init when module is imported
|
|
81
|
+
init();
|
|
82
|
+
|
|
83
|
+
export { init, Sortable };
|
|
76
84
|
export default init;
|
package/dom-utilities/All.js
CHANGED
|
@@ -403,12 +403,9 @@ const All = new Proxy(function (selectorOrElements, contextSelector) {
|
|
|
403
403
|
// Install default plugins
|
|
404
404
|
All.use(defaultPlugins);
|
|
405
405
|
|
|
406
|
-
//
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}
|
|
411
|
-
window.hyperclay.All = All;
|
|
412
|
-
}
|
|
406
|
+
// Self-export to window and hyperclay
|
|
407
|
+
window.All = All;
|
|
408
|
+
window.hyperclay = window.hyperclay || {};
|
|
409
|
+
window.hyperclay.All = All;
|
|
413
410
|
|
|
414
411
|
export default All;
|