@panphora/clayjs 1.5.3 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/THIRD-PARTY-NOTICES.md +6 -0
- package/dist/clay.standalone.js +15041 -10657
- package/package.json +9 -4
- package/src/core/conflict-download.js +91 -0
- package/src/core/conflict-notice.js +720 -0
- package/src/core/conflict-presentation.js +301 -0
- package/src/core/save-conflict-notice.js +2 -192
- package/src/core/save-core.js +35 -2
- package/src/core/save-feedback.js +6 -0
- package/src/core/save.js +157 -3
- package/src/core/snapshot.js +21 -0
- package/src/core/stale-host-notice.js +21 -24
- package/src/core/unsaved-warning.js +64 -16
- package/src/lib/content-dom.js +4 -2
- package/src/lib/dirty-gate.js +37 -1
- package/src/lib/unsaved-state.js +55 -0
- package/src/loader-logic.js +26 -15
- package/src/loader.js +10 -3
- package/src/plugins/ai-edit.js +489 -179
- package/src/plugins/cms.js +12 -0
- package/src/plugins/indicator.js +35 -16
- package/src/plugins/quickcrop.js +103 -0
- package/src/plugins/richclay.js +21 -0
- package/src/plugins/source.js +13 -6
- package/src/plugins/wire.js +4 -0
- package/src/sync/conflict-revert.js +1138 -0
- package/src/sync/conflicts.js +159 -0
- package/src/sync/live-sync.js +130 -109
- package/src/sync/presence.js +42 -36
- package/src/sync/section-notice.js +53 -28
- package/src/ui/bevel-controls.js +277 -0
- package/src/ui/bevel-dialog.js +112 -0
- package/src/ui/bevel.js +247 -0
- package/src/ui/dialogs.js +63 -86
- package/src/ui/index.js +22 -11
- package/src/ui/modal.js +80 -387
- package/src/ui/skins/cms-toggle.js +15 -0
- package/src/ui/skins/cms.js +4 -0
- package/src/ui/skins/quickcrop.js +4 -0
- package/src/ui/skins/richclay.js +4 -0
- package/src/ui/toast.js +116 -401
- package/src/ui/vendor-skin.js +65 -0
- package/src/vendor/hyper-morph.vendor.js +4 -4
- package/src/vendor/quickcrop.vendor.js +14 -8
- package/src/vendor/richclay.vendor.js +22 -41
package/src/loader-logic.js
CHANGED
|
@@ -16,7 +16,7 @@ export const CORE_WAVES = {
|
|
|
16
16
|
// transform registered after that made an untouched page read as unsaved.
|
|
17
17
|
"core/persist.js", "core/admin-attrs.js",
|
|
18
18
|
"core/save-core.js", "core/save.js",
|
|
19
|
-
"core/
|
|
19
|
+
"core/conflict-notice.js",
|
|
20
20
|
"core/unsaved-warning.js", "core/autosave.js",
|
|
21
21
|
"attrs/save-freeze.js", "attrs/onaftersave.js", "attrs/refetch-on-save.js",
|
|
22
22
|
"lib/cache-bust.js",
|
|
@@ -24,20 +24,21 @@ export const CORE_WAVES = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export const PLUGIN_PATHS = {
|
|
27
|
-
richclay: { path: "
|
|
27
|
+
richclay: { path: "plugins/richclay.js", editOnly: true, default: true },
|
|
28
28
|
indicator: { path: "plugins/indicator.js", editOnly: true, default: false },
|
|
29
29
|
sync: { path: "sync/live-sync.js", editOnly: false, default: false },
|
|
30
30
|
sortable: { path: "plugins/sortable.js", editOnly: true, default: false },
|
|
31
31
|
undo: { path: "plugins/undo.js", editOnly: true, default: false },
|
|
32
|
-
cms: { path: "
|
|
33
|
-
quickcrop: { path: "
|
|
32
|
+
cms: { path: "plugins/cms.js", editOnly: false, default: false },
|
|
33
|
+
quickcrop: { path: "plugins/quickcrop.js", editOnly: false, default: false },
|
|
34
34
|
// editOnly, because a file picker only ever appears in edit mode: the cms
|
|
35
35
|
// injects its own editing toggle there and clayjs's edit-mode signal is a
|
|
36
36
|
// superset of the cms's, so the plugin is present exactly when it can be used.
|
|
37
37
|
upload: { path: "plugins/upload.js", editOnly: true, default: false },
|
|
38
38
|
wire: { path: "plugins/wire.js", editOnly: false, default: false },
|
|
39
|
-
// Edit mode only: the AI comment box is an editing gesture
|
|
40
|
-
// dormant
|
|
39
|
+
// Edit mode only: the AI comment box is an editing gesture. Opt in with
|
|
40
|
+
// `plugins=ai-edit`; it stays dormant on any host that does not list a ready
|
|
41
|
+
// `ai-edit` helper.
|
|
41
42
|
"ai-edit": { path: "plugins/ai-edit.js", editOnly: true, default: false },
|
|
42
43
|
demo: { path: "plugins/demo.js", editOnly: false, default: false },
|
|
43
44
|
// Saves the file's own bytes back instead of a fresh serialization of the DOM.
|
|
@@ -68,7 +69,7 @@ export const MODULES = {
|
|
|
68
69
|
"core/snapshot.js": () => import("./core/snapshot.js"),
|
|
69
70
|
"core/save-core.js": () => import("./core/save-core.js"),
|
|
70
71
|
"core/save.js": () => import("./core/save.js"),
|
|
71
|
-
"core/
|
|
72
|
+
"core/conflict-notice.js": () => import("./core/conflict-notice.js"),
|
|
72
73
|
"core/unsaved-warning.js": () => import("./core/unsaved-warning.js"),
|
|
73
74
|
"core/persist.js": () => import("./core/persist.js"),
|
|
74
75
|
"core/admin-attrs.js": () => import("./core/admin-attrs.js"),
|
|
@@ -78,13 +79,13 @@ export const MODULES = {
|
|
|
78
79
|
"attrs/refetch-on-save.js": () => import("./attrs/refetch-on-save.js"),
|
|
79
80
|
"lib/cache-bust.js": () => import("./lib/cache-bust.js"),
|
|
80
81
|
"vendor/hyper-morph.vendor.js": () => import("./vendor/hyper-morph.vendor.js"),
|
|
81
|
-
"
|
|
82
|
+
"plugins/richclay.js": () => import("./plugins/richclay.js"),
|
|
82
83
|
"plugins/indicator.js": () => import("./plugins/indicator.js"),
|
|
83
84
|
"sync/live-sync.js": () => import("./sync/live-sync.js"),
|
|
84
85
|
"plugins/sortable.js": () => import("./plugins/sortable.js"),
|
|
85
86
|
"plugins/undo.js": () => import("./plugins/undo.js"),
|
|
86
|
-
"
|
|
87
|
-
"
|
|
87
|
+
"plugins/cms.js": () => import("./plugins/cms.js"),
|
|
88
|
+
"plugins/quickcrop.js": () => import("./plugins/quickcrop.js"),
|
|
88
89
|
"plugins/upload.js": () => import("./plugins/upload.js"),
|
|
89
90
|
"plugins/wire.js": () => import("./plugins/wire.js"),
|
|
90
91
|
"plugins/ai-edit.js": () => import("./plugins/ai-edit.js"),
|
|
@@ -114,6 +115,8 @@ const PLUGIN_ORDER = ["richclay", "indicator", "sortable", "undo", "quickcrop",
|
|
|
114
115
|
// enables. Reverting it is reverting this line.
|
|
115
116
|
// ai-edit reads `clay.wire.helpers()` and sends through `clay.wire.send`, so a page
|
|
116
117
|
// that asks for it has to have the wire. The wire loads first in the order above.
|
|
118
|
+
// It does not bring undo: hyper-undo takes Cmd+Z for the whole window, text fields
|
|
119
|
+
// included, which a page that never asked for it should not get by default.
|
|
117
120
|
const IMPLIES = { cms: ["quickcrop", "upload"], "ai-edit": ["wire"] };
|
|
118
121
|
|
|
119
122
|
function parseCsv(params, key, enabled, apply) {
|
|
@@ -134,17 +137,25 @@ export function resolveModules(params, isEditMode) {
|
|
|
134
137
|
const core = [...CORE_WAVES.always];
|
|
135
138
|
if (isEditMode) core.push(...CORE_WAVES.editOnly);
|
|
136
139
|
|
|
137
|
-
const
|
|
140
|
+
const explicit = new Set();
|
|
141
|
+
parseCsv(params, "plugins", explicit, (set, name) => set.add(name));
|
|
142
|
+
const excluded = new Set();
|
|
143
|
+
parseCsv(params, "exclude", excluded, (set, name) => set.add(name));
|
|
144
|
+
|
|
145
|
+
const enabled = new Set(explicit);
|
|
138
146
|
for (const [name, spec] of Object.entries(PLUGIN_PATHS)) {
|
|
139
147
|
if (spec.default) enabled.add(name);
|
|
140
148
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
//
|
|
149
|
+
// ai-edit cannot run without the wire, so excluding the wire excludes it too.
|
|
150
|
+
if (excluded.has("wire")) enabled.delete("ai-edit");
|
|
151
|
+
// A default-on plugin that this mode drops brings nothing with it. An explicitly
|
|
152
|
+
// asked for plugin still brings what it implies.
|
|
144
153
|
for (const name of [...enabled]) {
|
|
154
|
+
if (excluded.has(name)) continue;
|
|
155
|
+
if (!explicit.has(name) && PLUGIN_PATHS[name].editOnly && !isEditMode) continue;
|
|
145
156
|
for (const implied of IMPLIES[name] || []) enabled.add(implied);
|
|
146
157
|
}
|
|
147
|
-
|
|
158
|
+
for (const name of excluded) enabled.delete(name);
|
|
148
159
|
|
|
149
160
|
const plugins = [];
|
|
150
161
|
for (const name of PLUGIN_ORDER) {
|
package/src/loader.js
CHANGED
|
@@ -88,8 +88,14 @@ function assembleCore(loaded, { isEditMode, isOwner }, regionPolicy) {
|
|
|
88
88
|
const saveFn = save.savePage || save.default;
|
|
89
89
|
saveFn.force = save.savePageForce;
|
|
90
90
|
saveFn.overwrite = save.saveOverwritingConflict;
|
|
91
|
+
saveFn.flush = save.flushSave;
|
|
91
92
|
clay.save = saveFn;
|
|
92
93
|
}
|
|
94
|
+
// The close warning's own predicate, reachable without a capture. It falls back to
|
|
95
|
+
// false rather than to absent: the module is edit-only, and a document that cannot
|
|
96
|
+
// save has nothing unsaved. Older clayjs has no such member, and that is the answer
|
|
97
|
+
// a host feature-detects.
|
|
98
|
+
clay.hasUnsavedChanges = loaded["core/unsaved-warning.js"]?.hasUnsavedChanges ?? (() => false);
|
|
93
99
|
if (snapshot) {
|
|
94
100
|
clay.getHTML = snapshot.getPageContents;
|
|
95
101
|
clay.addDocumentTransform = snapshot.addDocumentTransform;
|
|
@@ -108,7 +114,8 @@ function attachPluginMember(path, mod) {
|
|
|
108
114
|
clay.undo = mod.undo || mod.default;
|
|
109
115
|
} else if (path === "sync/live-sync.js") {
|
|
110
116
|
clay.morph = mod.morph;
|
|
111
|
-
|
|
117
|
+
clay.conflicts = mod.conflicts;
|
|
118
|
+
} else if (path === "plugins/cms.js") {
|
|
112
119
|
clay.cms = mod.cms || mod.default;
|
|
113
120
|
} else if (path === "plugins/upload.js") {
|
|
114
121
|
clay.upload = mod.upload || mod.default;
|
|
@@ -118,9 +125,9 @@ function attachPluginMember(path, mod) {
|
|
|
118
125
|
clay.aiEdit = mod.aiEdit || mod.default;
|
|
119
126
|
} else if (path === "plugins/demo.js") {
|
|
120
127
|
clay.demo = mod.demo;
|
|
121
|
-
} else if (path === "
|
|
128
|
+
} else if (path === "plugins/richclay.js") {
|
|
122
129
|
clay.RichClay = mod.RichClay || mod.default;
|
|
123
|
-
} else if (path === "
|
|
130
|
+
} else if (path === "plugins/quickcrop.js") {
|
|
124
131
|
clay.quickcrop = mod.quickcrop || mod.default;
|
|
125
132
|
} else if (path === "plugins/source.js") {
|
|
126
133
|
clay.source = mod.source || mod.default;
|