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.
Files changed (113) hide show
  1. package/CHANGELOG.md +144 -41
  2. package/dist/api/assets.d.ts +27 -7
  3. package/dist/api/assets.js +98 -37
  4. package/dist/api/client.d.ts +5 -3
  5. package/dist/api/client.js +7 -3
  6. package/dist/api/index.d.ts +1 -1
  7. package/dist/assets/asset-prefixes.d.ts +4 -1
  8. package/dist/assets/asset-prefixes.js +3 -1
  9. package/dist/assets/finalize.js +14 -1
  10. package/dist/assets/keys.d.ts +4 -1
  11. package/dist/assets/keys.js +4 -1
  12. package/dist/assets/store-local.d.ts +18 -9
  13. package/dist/assets/store-local.js +58 -26
  14. package/dist/assets/store-s3.d.ts +19 -4
  15. package/dist/assets/store-s3.js +56 -13
  16. package/dist/assets/types.d.ts +26 -2
  17. package/dist/cli/cli.js +112 -34
  18. package/dist/editor/BranchManager.js +2 -1
  19. package/dist/editor/CommentsPanel.js +67 -29
  20. package/dist/editor/Editor.d.ts +3 -0
  21. package/dist/editor/Editor.js +58 -36
  22. package/dist/editor/EntryNavigator.d.ts +8 -1
  23. package/dist/editor/EntryNavigator.js +31 -16
  24. package/dist/editor/FormHeader.d.ts +2 -1
  25. package/dist/editor/FormHeader.js +9 -5
  26. package/dist/editor/FormRenderer.d.ts +7 -2
  27. package/dist/editor/FormRenderer.js +51 -16
  28. package/dist/editor/PreviewFrame.d.ts +11 -2
  29. package/dist/editor/PreviewFrame.js +20 -4
  30. package/dist/editor/PreviewPane.d.ts +15 -1
  31. package/dist/editor/PreviewPane.js +55 -8
  32. package/dist/editor/PreviewToolbarTools.d.ts +8 -0
  33. package/dist/editor/PreviewToolbarTools.js +9 -1
  34. package/dist/editor/branch-status.d.ts +6 -0
  35. package/dist/editor/branch-status.js +10 -0
  36. package/dist/editor/comments/BranchComments.d.ts +2 -4
  37. package/dist/editor/comments/BranchComments.js +7 -11
  38. package/dist/editor/comments/ThreadCarousel.d.ts +2 -8
  39. package/dist/editor/comments/ThreadCarousel.js +4 -49
  40. package/dist/editor/comments/ThreadReplyControls.js +5 -2
  41. package/dist/editor/components/BranchLockBanner.d.ts +2 -0
  42. package/dist/editor/components/BranchLockBanner.js +6 -2
  43. package/dist/editor/components/BranchPill.d.ts +5 -4
  44. package/dist/editor/components/BranchPill.js +6 -8
  45. package/dist/editor/components/BranchesDrawer.js +3 -3
  46. package/dist/editor/components/EditorHeader.d.ts +2 -6
  47. package/dist/editor/components/EditorHeader.js +29 -28
  48. package/dist/editor/components/EditorRail.d.ts +3 -4
  49. package/dist/editor/components/EditorRail.js +3 -4
  50. package/dist/editor/components/EntryBreadcrumb.d.ts +9 -10
  51. package/dist/editor/components/EntryBreadcrumb.js +8 -11
  52. package/dist/editor/components/QuickOpenPalette.d.ts +7 -1
  53. package/dist/editor/components/QuickOpenPalette.js +6 -1
  54. package/dist/editor/components/RenameEntryModal.d.ts +6 -1
  55. package/dist/editor/components/RenameEntryModal.js +20 -5
  56. package/dist/editor/components/SaveSplitButton.d.ts +3 -2
  57. package/dist/editor/components/SaveSplitButton.js +25 -12
  58. package/dist/editor/components/StagedChangesDrawer.d.ts +0 -1
  59. package/dist/editor/components/StagedChangesDrawer.js +5 -4
  60. package/dist/editor/components/UndoToastMessage.d.ts +6 -5
  61. package/dist/editor/components/UndoToastMessage.js +6 -4
  62. package/dist/editor/components/UnsavedMark.d.ts +9 -0
  63. package/dist/editor/components/UnsavedMark.js +20 -0
  64. package/dist/editor/components/UserBadge.js +13 -11
  65. package/dist/editor/copy.d.ts +4 -0
  66. package/dist/editor/copy.js +4 -0
  67. package/dist/editor/editor-utils.d.ts +49 -9
  68. package/dist/editor/editor-utils.js +117 -16
  69. package/dist/editor/entry-search.d.ts +4 -2
  70. package/dist/editor/entry-search.js +2 -3
  71. package/dist/editor/fields/FieldLabel.d.ts +1 -1
  72. package/dist/editor/fields/ObjectField.d.ts +13 -2
  73. package/dist/editor/fields/ObjectField.js +38 -9
  74. package/dist/editor/fields/entry-link/EntryLinkContext.d.ts +2 -0
  75. package/dist/editor/fields/entry-link/InsertEntryLink.js +3 -1
  76. package/dist/editor/group-manager/index.js +1 -1
  77. package/dist/editor/hooks/useEditorLayout.d.ts +4 -0
  78. package/dist/editor/hooks/useEditorLayout.js +5 -0
  79. package/dist/editor/hooks/useEntryManager.d.ts +2 -0
  80. package/dist/editor/hooks/useEntryManager.js +10 -8
  81. package/dist/editor/media/AssetCard.d.ts +6 -3
  82. package/dist/editor/media/AssetCard.js +20 -7
  83. package/dist/editor/media/AssetListRow.d.ts +9 -4
  84. package/dist/editor/media/AssetListRow.js +14 -7
  85. package/dist/editor/media/MediaLibrary.js +5 -4
  86. package/dist/editor/media/MediaLibraryBody.d.ts +1 -1
  87. package/dist/editor/media/MediaLibraryBody.js +65 -37
  88. package/dist/editor/media/useAssetLibrary.d.ts +6 -3
  89. package/dist/editor/media/useAssetLibrary.js +17 -10
  90. package/dist/editor/pane-header.d.ts +6 -0
  91. package/dist/editor/pane-header.js +6 -0
  92. package/dist/editor/permission-manager/index.js +1 -1
  93. package/dist/editor/preview-bridge.d.ts +16 -0
  94. package/dist/editor/preview-bridge.js +12 -3
  95. package/dist/editor/preview-path.d.ts +11 -4
  96. package/dist/editor/preview-path.js +62 -19
  97. package/dist/editor/shell/ActivityRail.d.ts +1 -3
  98. package/dist/editor/shell/ActivityRail.js +3 -3
  99. package/dist/editor/shell/EditorShell.d.ts +15 -0
  100. package/dist/editor/shell/EditorShell.js +17 -1
  101. package/dist/editor/shell/OverlayHeader.d.ts +19 -0
  102. package/dist/editor/shell/OverlayHeader.js +15 -0
  103. package/dist/editor/shell/PaneLayout.d.ts +6 -1
  104. package/dist/editor/shell/PaneLayout.js +68 -13
  105. package/dist/editor/shell/SidePanelHost.d.ts +8 -6
  106. package/dist/editor/shell/SidePanelHost.js +70 -33
  107. package/dist/editor/shell/TopBar.js +2 -1
  108. package/dist/editor/theme.js +2 -0
  109. package/dist/editor/undo-removal.d.ts +19 -10
  110. package/dist/editor/undo-removal.js +44 -16
  111. package/dist/version.d.ts +1 -1
  112. package/dist/version.js +1 -1
  113. 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 anchors = [];
26
- const anchor = (list, index) => anchors.push({ index, siblings: list.filter((_, i) => i !== 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, anchors };
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, anchors };
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) => anchor.index === now[i].index &&
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, now[i].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))?.anchors;
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
- * `value` with a removal put back, or undefined when it can't be: the list or field is gone, an
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.anchors))
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
- const restored = setAt(value, path, next);
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.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.1.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.1.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": {