canopycms 0.1.0 → 0.2.0-int.119
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/CHANGELOG.md +144 -41
- package/dist/api/assets.d.ts +27 -7
- package/dist/api/assets.js +98 -37
- package/dist/api/client.d.ts +5 -3
- package/dist/api/client.js +7 -3
- package/dist/api/index.d.ts +1 -1
- package/dist/assets/asset-prefixes.d.ts +4 -1
- package/dist/assets/asset-prefixes.js +3 -1
- package/dist/assets/finalize.js +14 -1
- package/dist/assets/keys.d.ts +4 -1
- package/dist/assets/keys.js +4 -1
- package/dist/assets/store-local.d.ts +18 -9
- package/dist/assets/store-local.js +58 -26
- package/dist/assets/store-s3.d.ts +19 -4
- package/dist/assets/store-s3.js +56 -13
- package/dist/assets/types.d.ts +26 -2
- package/dist/cli/cli.js +112 -34
- package/dist/editor/BranchManager.js +2 -1
- package/dist/editor/CommentsPanel.js +67 -29
- package/dist/editor/Editor.d.ts +3 -0
- package/dist/editor/Editor.js +58 -36
- package/dist/editor/EntryNavigator.d.ts +8 -1
- package/dist/editor/EntryNavigator.js +31 -16
- package/dist/editor/FormHeader.d.ts +2 -1
- package/dist/editor/FormHeader.js +9 -5
- package/dist/editor/FormRenderer.d.ts +7 -2
- package/dist/editor/FormRenderer.js +51 -16
- package/dist/editor/PreviewFrame.d.ts +11 -2
- package/dist/editor/PreviewFrame.js +20 -4
- package/dist/editor/PreviewPane.d.ts +15 -1
- package/dist/editor/PreviewPane.js +55 -8
- package/dist/editor/PreviewToolbarTools.d.ts +8 -0
- package/dist/editor/PreviewToolbarTools.js +9 -1
- package/dist/editor/branch-status.d.ts +6 -0
- package/dist/editor/branch-status.js +10 -0
- package/dist/editor/comments/BranchComments.d.ts +2 -4
- package/dist/editor/comments/BranchComments.js +7 -11
- package/dist/editor/comments/ThreadCarousel.d.ts +2 -8
- package/dist/editor/comments/ThreadCarousel.js +4 -49
- package/dist/editor/comments/ThreadReplyControls.js +5 -2
- package/dist/editor/components/BranchLockBanner.d.ts +2 -0
- package/dist/editor/components/BranchLockBanner.js +6 -2
- package/dist/editor/components/BranchPill.d.ts +5 -4
- package/dist/editor/components/BranchPill.js +6 -8
- package/dist/editor/components/BranchesDrawer.js +3 -3
- package/dist/editor/components/EditorHeader.d.ts +2 -6
- package/dist/editor/components/EditorHeader.js +29 -28
- package/dist/editor/components/EditorRail.d.ts +3 -4
- package/dist/editor/components/EditorRail.js +3 -4
- package/dist/editor/components/EntryBreadcrumb.d.ts +9 -10
- package/dist/editor/components/EntryBreadcrumb.js +8 -11
- package/dist/editor/components/QuickOpenPalette.d.ts +7 -1
- package/dist/editor/components/QuickOpenPalette.js +6 -1
- package/dist/editor/components/RenameEntryModal.d.ts +6 -1
- package/dist/editor/components/RenameEntryModal.js +20 -5
- package/dist/editor/components/SaveSplitButton.d.ts +3 -2
- package/dist/editor/components/SaveSplitButton.js +25 -12
- package/dist/editor/components/StagedChangesDrawer.d.ts +0 -1
- package/dist/editor/components/StagedChangesDrawer.js +5 -4
- package/dist/editor/components/UndoToastMessage.d.ts +6 -5
- package/dist/editor/components/UndoToastMessage.js +6 -4
- package/dist/editor/components/UnsavedMark.d.ts +9 -0
- package/dist/editor/components/UnsavedMark.js +20 -0
- package/dist/editor/components/UserBadge.js +13 -11
- package/dist/editor/copy.d.ts +4 -0
- package/dist/editor/copy.js +4 -0
- package/dist/editor/editor-utils.d.ts +49 -9
- package/dist/editor/editor-utils.js +117 -16
- package/dist/editor/entry-search.d.ts +4 -2
- package/dist/editor/entry-search.js +2 -3
- package/dist/editor/fields/FieldLabel.d.ts +1 -1
- package/dist/editor/fields/ObjectField.d.ts +13 -2
- package/dist/editor/fields/ObjectField.js +38 -9
- package/dist/editor/fields/entry-link/EntryLinkContext.d.ts +2 -0
- package/dist/editor/fields/entry-link/InsertEntryLink.js +3 -1
- package/dist/editor/group-manager/index.js +1 -1
- package/dist/editor/hooks/useEditorLayout.d.ts +4 -0
- package/dist/editor/hooks/useEditorLayout.js +5 -0
- package/dist/editor/hooks/useEntryManager.d.ts +2 -0
- package/dist/editor/hooks/useEntryManager.js +10 -8
- package/dist/editor/media/AssetCard.d.ts +6 -3
- package/dist/editor/media/AssetCard.js +20 -7
- package/dist/editor/media/AssetListRow.d.ts +9 -4
- package/dist/editor/media/AssetListRow.js +14 -7
- package/dist/editor/media/MediaLibrary.js +5 -4
- package/dist/editor/media/MediaLibraryBody.d.ts +1 -1
- package/dist/editor/media/MediaLibraryBody.js +65 -37
- package/dist/editor/media/useAssetLibrary.d.ts +6 -3
- package/dist/editor/media/useAssetLibrary.js +17 -10
- package/dist/editor/pane-header.d.ts +6 -0
- package/dist/editor/pane-header.js +6 -0
- package/dist/editor/permission-manager/index.js +1 -1
- package/dist/editor/preview-bridge.d.ts +16 -0
- package/dist/editor/preview-bridge.js +12 -3
- package/dist/editor/preview-path.d.ts +11 -4
- package/dist/editor/preview-path.js +62 -19
- package/dist/editor/shell/ActivityRail.d.ts +1 -3
- package/dist/editor/shell/ActivityRail.js +3 -3
- package/dist/editor/shell/EditorShell.d.ts +15 -0
- package/dist/editor/shell/EditorShell.js +17 -1
- package/dist/editor/shell/OverlayHeader.d.ts +19 -0
- package/dist/editor/shell/OverlayHeader.js +15 -0
- package/dist/editor/shell/PaneLayout.d.ts +6 -1
- package/dist/editor/shell/PaneLayout.js +68 -13
- package/dist/editor/shell/SidePanelHost.d.ts +8 -6
- package/dist/editor/shell/SidePanelHost.js +70 -33
- package/dist/editor/shell/TopBar.js +2 -1
- package/dist/editor/theme.js +2 -0
- package/dist/editor/undo-removal.d.ts +19 -10
- package/dist/editor/undo-removal.js +44 -16
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import equal from 'fast-deep-equal';
|
|
2
|
+
import { ITEM_KEY, isItemKey } from '../item-keys.js';
|
|
2
3
|
import { isPlainRecord } from '../validation/field-traversal.js';
|
|
3
4
|
import { normalizeCanopyPath, parseCanopyPath } from './canopy-path.js';
|
|
5
|
+
const itemKeyAt = (list, index) => {
|
|
6
|
+
const item = list[index];
|
|
7
|
+
const key = isPlainRecord(item) ? item[ITEM_KEY] : undefined;
|
|
8
|
+
return isItemKey(key) ? key : undefined;
|
|
9
|
+
};
|
|
4
10
|
const findField = (fields, name) => {
|
|
5
11
|
for (const field of fields) {
|
|
6
12
|
if (field.type === 'group') {
|
|
@@ -22,8 +28,8 @@ const resolvePath = (fields, value, path) => {
|
|
|
22
28
|
let scope = fields;
|
|
23
29
|
let node = value;
|
|
24
30
|
const out = [];
|
|
25
|
-
const
|
|
26
|
-
const anchor = (list, index) =>
|
|
31
|
+
const lists = [];
|
|
32
|
+
const anchor = (list, index) => lists.push({ list, index });
|
|
27
33
|
let i = 0;
|
|
28
34
|
while (i < path.length) {
|
|
29
35
|
const name = path[i];
|
|
@@ -34,7 +40,7 @@ const resolvePath = (fields, value, path) => {
|
|
|
34
40
|
node = isPlainRecord(node) ? node[name] : undefined;
|
|
35
41
|
i += 1;
|
|
36
42
|
if (i === path.length)
|
|
37
|
-
return { path: out,
|
|
43
|
+
return { path: out, lists };
|
|
38
44
|
const index = path[i];
|
|
39
45
|
if (field.type === 'block') {
|
|
40
46
|
const block = typeof index === 'number' && Array.isArray(node) ? node[index] : undefined;
|
|
@@ -65,7 +71,7 @@ const resolvePath = (fields, value, path) => {
|
|
|
65
71
|
return undefined;
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
|
-
return { path: out,
|
|
74
|
+
return { path: out, lists };
|
|
69
75
|
};
|
|
70
76
|
const getAt = (root, path) => path.reduce((node, segment) => {
|
|
71
77
|
if (typeof segment === 'number')
|
|
@@ -89,9 +95,15 @@ const sameContent = (a, b) => equal(JSON.parse(JSON.stringify(a ?? null)), JSON.
|
|
|
89
95
|
const removalPath = (removal) => removal.kind === 'list-item' ? removal.listPath : removal.path;
|
|
90
96
|
const anchorsHold = (then, now) => then === undefined ||
|
|
91
97
|
(then.length === now.length &&
|
|
92
|
-
then.every((anchor, i) =>
|
|
98
|
+
then.every((anchor, i) => {
|
|
99
|
+
const { list, index } = now[i];
|
|
100
|
+
if (anchor.index !== index)
|
|
101
|
+
return false;
|
|
102
|
+
if (anchor.key !== undefined)
|
|
103
|
+
return itemKeyAt(list, index) === anchor.key;
|
|
93
104
|
// By content as stored, so the server's copy of the same items still holds.
|
|
94
|
-
sameContent(anchor.siblings,
|
|
105
|
+
return sameContent(anchor.siblings, list.filter((_, j) => j !== index));
|
|
106
|
+
}));
|
|
95
107
|
/**
|
|
96
108
|
* The canopy path `restoreRemoval` puts a removal back at: a list item returns to its old index,
|
|
97
109
|
* or to the list's end when the list is now shorter than that.
|
|
@@ -105,17 +117,17 @@ export function restoredFieldPath(fields, value, removal) {
|
|
|
105
117
|
}
|
|
106
118
|
/** The enclosing lists of a removal in `value`, taken before the removal applies; see `anchors`. */
|
|
107
119
|
export function removalAnchors(fields, value, removal) {
|
|
108
|
-
return resolvePath(fields, value, removalPath(removal))?.
|
|
120
|
+
return resolvePath(fields, value, removalPath(removal))?.lists.map(({ list, index }) => {
|
|
121
|
+
const key = itemKeyAt(list, index);
|
|
122
|
+
return key !== undefined
|
|
123
|
+
? { index, key }
|
|
124
|
+
: { index, siblings: list.filter((_, j) => j !== index) };
|
|
125
|
+
});
|
|
109
126
|
}
|
|
110
|
-
/**
|
|
111
|
-
|
|
112
|
-
* enclosing list has changed, the item is already there, or the image field has been filled.
|
|
113
|
-
* Edits made after the removal are kept, because it changes only the one list or field, in the
|
|
114
|
-
* value as it is now.
|
|
115
|
-
*/
|
|
116
|
-
export function restoreRemoval(fields, value, removal) {
|
|
127
|
+
/** Where and what `restoreRemoval` writes, or undefined when it can't; see there. */
|
|
128
|
+
const planRestore = (fields, value, removal) => {
|
|
117
129
|
const resolved = resolvePath(fields, value, removalPath(removal));
|
|
118
|
-
if (!resolved || !anchorsHold(removal.anchors, resolved.
|
|
130
|
+
if (!resolved || !anchorsHold(removal.anchors, resolved.lists))
|
|
119
131
|
return undefined;
|
|
120
132
|
const { path } = resolved;
|
|
121
133
|
// An enclosing object cleared since would come back holding only this.
|
|
@@ -139,9 +151,25 @@ export function restoreRemoval(fields, value, removal) {
|
|
|
139
151
|
return undefined;
|
|
140
152
|
next = removal.value;
|
|
141
153
|
}
|
|
142
|
-
|
|
154
|
+
return { path, next };
|
|
155
|
+
};
|
|
156
|
+
/** Whether `restoreRemoval` would put the removal back, without building the restored value. */
|
|
157
|
+
export const canRestoreRemoval = (fields, value, removal) => planRestore(fields, value, removal) !== undefined;
|
|
158
|
+
/**
|
|
159
|
+
* `value` with a removal put back, or undefined when it can't be: the list or field is gone,
|
|
160
|
+
* another item holds an enclosing index, the item is already there, or the image field or object
|
|
161
|
+
* has been filled. Edits made after the removal are kept, because it changes only the one list or
|
|
162
|
+
* field, in the value as it is now.
|
|
163
|
+
*/
|
|
164
|
+
export function restoreRemoval(fields, value, removal) {
|
|
165
|
+
const plan = planRestore(fields, value, removal);
|
|
166
|
+
const restored = plan ? setAt(value, plan.path, plan.next) : undefined;
|
|
143
167
|
return isPlainRecord(restored) ? restored : undefined;
|
|
144
168
|
}
|
|
169
|
+
/** Where a removal's moved threads went, said with its Undo; undefined when none moved. */
|
|
170
|
+
export const movedThreadsNote = (count) => count > 0
|
|
171
|
+
? `Its ${count === 1 ? 'comment thread' : `${count} comment threads`} moved to "Comment on this entry".`
|
|
172
|
+
: undefined;
|
|
145
173
|
/**
|
|
146
174
|
* How many open field threads a removal at `path` moves to the entry: those inside it keyed to an
|
|
147
175
|
* item at or below it. One keyed only above stays on its field, which a Clear leaves in place.
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CANOPYCMS_VERSION = "0.
|
|
1
|
+
export declare const CANOPYCMS_VERSION = "0.2.0-int.119";
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Generated by scripts/bump-version.mjs, its only writer. The package builds with plain
|
|
2
2
|
// tsc (rootDir: src), so src/ cannot import ../package.json; version.test.ts keeps the two equal.
|
|
3
|
-
export const CANOPYCMS_VERSION = '0.
|
|
3
|
+
export const CANOPYCMS_VERSION = '0.2.0-int.119';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"//": "@codemirror/language, @lezer/highlight: workaround — @mdxeditor/editor uses cm6-theme-basic-light which peer-requires these but mdxeditor doesn't declare them as dependencies",
|
|
3
3
|
"name": "canopycms",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-int.119",
|
|
5
5
|
"description": "CanopyCMS core package: schema-driven content, branch-aware editing, and editor UI for Next.js.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|