nudge-ui 0.2.2 → 0.2.3

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 (226) hide show
  1. package/README.md +164 -46
  2. package/dist/client.mjs +252 -61
  3. package/dist/css/value-semantics/colorSemantics.d.ts +4 -0
  4. package/dist/css/value-semantics/colorSemantics.js +17 -0
  5. package/dist/hosts/astro/astroRuntimeConfig.js +1 -0
  6. package/dist/hosts/astro/clientTransport.js +38 -32
  7. package/dist/hosts/astro/integration.js +5 -1
  8. package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
  9. package/dist/hosts/astro/markdownIdentity.js +81 -0
  10. package/dist/hosts/next/manifest.js +1 -1
  11. package/dist/hosts/next/sidecar.js +5 -1
  12. package/dist/hosts/static/manifest.js +1 -1
  13. package/dist/hosts/static/server.js +3 -0
  14. package/dist/hosts/vite/vite.d.ts +3 -0
  15. package/dist/hosts/vite/vite.js +24 -4
  16. package/dist/inspector/agent/McpConnectionDialog.js +13 -19
  17. package/dist/inspector/agent/activity.d.ts +18 -0
  18. package/dist/inspector/agent/activity.js +70 -0
  19. package/dist/inspector/agent/client.d.ts +2 -0
  20. package/dist/inspector/agent/client.js +29 -1
  21. package/dist/inspector/agent/connectionStatus.js +1 -1
  22. package/dist/inspector/agent/httpTransport.js +9 -2
  23. package/dist/inspector/agent/protocol.d.ts +6 -3
  24. package/dist/inspector/agent/protocol.js +1 -1
  25. package/dist/inspector/agent/verification.d.ts +11 -1
  26. package/dist/inspector/agent/verification.js +53 -25
  27. package/dist/inspector/canvas/AgentActivityOverlay.d.ts +13 -0
  28. package/dist/inspector/canvas/AgentActivityOverlay.js +111 -0
  29. package/dist/inspector/canvas/CanvasCard.d.ts +9 -2
  30. package/dist/inspector/canvas/CanvasCard.js +133 -38
  31. package/dist/inspector/canvas/CanvasElementOverlay.js +152 -16
  32. package/dist/inspector/canvas/CanvasToolIcons.d.ts +10 -0
  33. package/dist/inspector/canvas/CanvasToolIcons.js +20 -0
  34. package/dist/inspector/canvas/CanvasToolbar.js +8 -4
  35. package/dist/inspector/canvas/CanvasWorkspace.js +225 -57
  36. package/dist/inspector/canvas/StaleChangeIndicator.js +3 -13
  37. package/dist/inspector/canvas/agentPresentation.d.ts +8 -8
  38. package/dist/inspector/canvas/agentPresentation.js +64 -52
  39. package/dist/inspector/canvas/canvasGestures.d.ts +1 -1
  40. package/dist/inspector/canvas/canvasGestures.js +1 -1
  41. package/dist/inspector/canvas/canvasStore.d.ts +46 -82
  42. package/dist/inspector/canvas/canvasStore.js +251 -284
  43. package/dist/inspector/canvas/frameContent.d.ts +21 -0
  44. package/dist/inspector/canvas/frameContent.js +44 -0
  45. package/dist/inspector/canvas/frameProtocol.d.ts +21 -4
  46. package/dist/inspector/canvas/frameProtocol.js +3 -3
  47. package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -1
  48. package/dist/inspector/canvas/keyboardShortcuts.js +4 -4
  49. package/dist/inspector/canvas/layout.d.ts +52 -0
  50. package/dist/inspector/canvas/layout.js +106 -0
  51. package/dist/inspector/canvas/projection.d.ts +15 -5
  52. package/dist/inspector/canvas/projection.js +69 -13
  53. package/dist/inspector/canvas/rendererBootstrap.js +32 -4
  54. package/dist/inspector/canvas/rendererElementSelector.js +47 -6
  55. package/dist/inspector/canvas/rendererStylesheet.js +2 -2
  56. package/dist/inspector/canvas/resizeHandleScale.js +1 -1
  57. package/dist/inspector/canvas/sessionStore.d.ts +11 -26
  58. package/dist/inspector/canvas/sessionStore.js +43 -183
  59. package/dist/inspector/canvas/staleChangeDetector.js +9 -3
  60. package/dist/inspector/canvas/useCanvasLayoutAnimation.d.ts +5 -0
  61. package/dist/inspector/canvas/useCanvasLayoutAnimation.js +107 -0
  62. package/dist/inspector/canvas/viewStore.d.ts +38 -0
  63. package/dist/inspector/canvas/viewStore.js +104 -0
  64. package/dist/inspector/canvas/wheelPan.d.ts +8 -0
  65. package/dist/inspector/canvas/wheelPan.js +8 -0
  66. package/dist/inspector/changes/changesLog.d.ts +6 -5
  67. package/dist/inspector/changes/changesLog.js +40 -32
  68. package/dist/inspector/changes/draftChanges.d.ts +56 -0
  69. package/dist/inspector/changes/draftChanges.js +300 -0
  70. package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
  71. package/dist/inspector/changes/previewDiagnostics.js +11 -25
  72. package/dist/inspector/clientManifest.d.ts +1 -1
  73. package/dist/inspector/comments/CommentsOverlay.d.ts +2 -0
  74. package/dist/inspector/comments/CommentsOverlay.js +250 -0
  75. package/dist/inspector/comments/element.d.ts +6 -0
  76. package/dist/inspector/comments/element.js +47 -0
  77. package/dist/inspector/comments/store.d.ts +29 -0
  78. package/dist/inspector/comments/store.js +121 -0
  79. package/dist/inspector/comments/verification.d.ts +5 -0
  80. package/dist/inspector/comments/verification.js +52 -0
  81. package/dist/inspector/drafts/model.d.ts +35 -0
  82. package/dist/inspector/drafts/model.js +45 -0
  83. package/dist/inspector/drafts/store.d.ts +28 -0
  84. package/dist/inspector/drafts/store.js +231 -0
  85. package/dist/inspector/index.js +20 -27
  86. package/dist/inspector/inline-text/inlineTextEditor.js +7 -0
  87. package/dist/inspector/inspection/useBrowserCssInspection.js +15 -1
  88. package/dist/inspector/iterations/capture.d.ts +2 -0
  89. package/dist/inspector/iterations/capture.js +173 -0
  90. package/dist/inspector/iterations/client.d.ts +7 -0
  91. package/dist/inspector/iterations/client.js +52 -0
  92. package/dist/inspector/iterations/coordinator.d.ts +15 -0
  93. package/dist/inspector/iterations/coordinator.js +130 -0
  94. package/dist/inspector/iterations/prompt.d.ts +3 -0
  95. package/dist/inspector/iterations/prompt.js +26 -0
  96. package/dist/inspector/overlay/DomNavigator.js +21 -15
  97. package/dist/inspector/overlay/interactionStyles.js +3 -1
  98. package/dist/inspector/overlay/spacingGestures.d.ts +13 -1
  99. package/dist/inspector/overlay/spacingGestures.js +82 -5
  100. package/dist/inspector/projection/{workspaceProjection.d.ts → draftProjection.d.ts} +6 -6
  101. package/dist/inspector/projection/{workspaceProjection.js → draftProjection.js} +4 -4
  102. package/dist/inspector/projection/renderedInstance.d.ts +2 -1
  103. package/dist/inspector/projection/renderedInstance.js +9 -5
  104. package/dist/inspector/projection/structuralProjection.d.ts +2 -1
  105. package/dist/inspector/projection/structuralProjection.js +19 -15
  106. package/dist/inspector/projection/textProjection.d.ts +2 -1
  107. package/dist/inspector/projection/textProjection.js +8 -4
  108. package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
  109. package/dist/inspector/prompt/clipboardHandoff.d.ts +10 -18
  110. package/dist/inspector/prompt/clipboardHandoff.js +92 -143
  111. package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
  112. package/dist/inspector/prompt/generatePrompt.js +17 -16
  113. package/dist/inspector/runtime/runtimeConfig.d.ts +9 -0
  114. package/dist/inspector/runtime/runtimeConfig.js +24 -0
  115. package/dist/inspector/settings/SettingsDialog.js +21 -8
  116. package/dist/inspector/shell/AgentStatusButton.d.ts +11 -0
  117. package/dist/inspector/shell/AgentStatusButton.js +36 -0
  118. package/dist/inspector/shell/AppShell.js +4 -2
  119. package/dist/inspector/shell/ChangesLog.js +46 -26
  120. package/dist/inspector/shell/CopyPromptButton.js +138 -89
  121. package/dist/inspector/shell/EmptyState.js +9 -8
  122. package/dist/inspector/shell/InspectorShell.js +13 -21
  123. package/dist/inspector/shell/PeekOriginalButton.js +24 -23
  124. package/dist/inspector/shell/originalPreview.js +5 -5
  125. package/dist/inspector/shell/shortcuts.d.ts +3 -0
  126. package/dist/inspector/shell/shortcuts.js +11 -0
  127. package/dist/inspector/sketch/SketchEditor.js +14 -14
  128. package/dist/inspector/sketch/SketchEntryButton.js +1 -1
  129. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +3 -1
  130. package/dist/inspector/sketch/SketchFrameOverlay.js +11 -8
  131. package/dist/inspector/sketch/SketchLayersPanel.js +13 -5
  132. package/dist/inspector/sketch/SketchOverlay.js +7 -7
  133. package/dist/inspector/sketch/SketchWorkspace.js +18 -12
  134. package/dist/inspector/sketch/interaction.d.ts +1 -0
  135. package/dist/inspector/sketch/interaction.js +8 -4
  136. package/dist/inspector/sketch/model.d.ts +5 -0
  137. package/dist/inspector/sketch/model.js +6 -2
  138. package/dist/inspector/sketch/raster.d.ts +1 -2
  139. package/dist/inspector/sketch/raster.js +68 -4
  140. package/dist/inspector/styleEditors/BackgroundEditor.d.ts +4 -0
  141. package/dist/inspector/styleEditors/BackgroundEditor.js +195 -0
  142. package/dist/inspector/styleEditors/BorderEditor.js +49 -78
  143. package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -1
  144. package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +1 -2
  145. package/dist/inspector/styleEditors/BoxShadowEditor.js +132 -4
  146. package/dist/inspector/styleEditors/ColorPicker.d.ts +5 -1
  147. package/dist/inspector/styleEditors/ColorPicker.js +10 -4
  148. package/dist/inspector/styleEditors/GapField.js +3 -5
  149. package/dist/inspector/styleEditors/GridChildSection.d.ts +1 -1
  150. package/dist/inspector/styleEditors/GridChildSection.js +18 -9
  151. package/dist/inspector/styleEditors/GridPicker.d.ts +1 -1
  152. package/dist/inspector/styleEditors/GridPicker.js +8 -2
  153. package/dist/inspector/styleEditors/GridSection.js +1 -1
  154. package/dist/inspector/styleEditors/GridValueField.js +19 -14
  155. package/dist/inspector/styleEditors/ImageBackgroundEditor.d.ts +18 -0
  156. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +118 -0
  157. package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +2 -2
  158. package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +3 -3
  159. package/dist/inspector/styleEditors/LayoutComboField.js +6 -4
  160. package/dist/inspector/styleEditors/LayoutDropdown.js +6 -3
  161. package/dist/inspector/styleEditors/LayoutSection.js +32 -11
  162. package/dist/inspector/styleEditors/SpacingBox.js +7 -5
  163. package/dist/inspector/styleEditors/Typography.js +11 -3
  164. package/dist/inspector/styleEditors/backgroundLayers.d.ts +24 -0
  165. package/dist/inspector/styleEditors/backgroundLayers.js +51 -0
  166. package/dist/inspector/styleEditors/gradientValue.d.ts +17 -0
  167. package/dist/inspector/styleEditors/gradientValue.js +114 -0
  168. package/dist/inspector/styleEditors/inlineAuthored.d.ts +10 -0
  169. package/dist/inspector/styleEditors/inlineAuthored.js +114 -0
  170. package/dist/inspector/styleEditors/layoutValue.d.ts +0 -8
  171. package/dist/inspector/styleEditors/layoutValue.js +0 -42
  172. package/dist/inspector/styleEditors/nudgeValue.d.ts +2 -2
  173. package/dist/inspector/styleEditors/nudgeValue.js +36 -8
  174. package/dist/inspector/tokens/TokenField.d.ts +7 -0
  175. package/dist/inspector/tokens/TokenField.js +29 -21
  176. package/dist/inspector/tokens/TokenLabel.js +5 -14
  177. package/dist/inspector/tokens/editActions.d.ts +1 -1
  178. package/dist/inspector/tokens/editActions.js +1 -1
  179. package/dist/inspector/ui/AtRuleContext.js +4 -6
  180. package/dist/inspector/ui/Button.d.ts +6 -2
  181. package/dist/inspector/ui/Button.js +4 -3
  182. package/dist/inspector/ui/ControlSurface.d.ts +2 -2
  183. package/dist/inspector/ui/ControlSurface.js +4 -3
  184. package/dist/inspector/ui/InlineStyleWarning.d.ts +11 -0
  185. package/dist/inspector/ui/InlineStyleWarning.js +13 -0
  186. package/dist/inspector/ui/InspectorPopover.d.ts +2 -1
  187. package/dist/inspector/ui/InspectorPopover.js +4 -5
  188. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  189. package/dist/inspector/ui/PopoverListbox.js +8 -7
  190. package/dist/inspector/ui/SegmentedControl.d.ts +2 -1
  191. package/dist/inspector/ui/SegmentedControl.js +2 -2
  192. package/dist/inspector/ui/Select.d.ts +6 -1
  193. package/dist/inspector/ui/Select.js +7 -11
  194. package/dist/inspector/ui/SideValuesField.js +1 -1
  195. package/dist/inspector/ui/Tooltip.d.ts +26 -0
  196. package/dist/inspector/ui/Tooltip.js +32 -0
  197. package/dist/inspector/ui/classNames.d.ts +2 -0
  198. package/dist/inspector/ui/classNames.js +4 -0
  199. package/dist/inspector/ui/customCursors.d.ts +23 -0
  200. package/dist/inspector/ui/customCursors.js +122 -0
  201. package/dist/inspector/ui/dragCursor.d.ts +0 -2
  202. package/dist/inspector/ui/dragCursor.js +2 -10
  203. package/dist/inspector/ui/portalContainer.d.ts +2 -0
  204. package/dist/inspector/ui/portalContainer.js +6 -0
  205. package/dist/inspector/ui/styles.js +29 -21
  206. package/dist/inspector/workspace/commands.d.ts +9 -0
  207. package/dist/inspector/workspace/commands.js +82 -0
  208. package/dist/inspector/workspace/controller.d.ts +4 -0
  209. package/dist/inspector/workspace/controller.js +66 -0
  210. package/dist/inspector/workspace/handoff.d.ts +42 -0
  211. package/dist/inspector/workspace/handoff.js +115 -0
  212. package/dist/inspector/workspace/timeline.d.ts +30 -0
  213. package/dist/inspector/workspace/timeline.js +108 -0
  214. package/dist/internal/agent-protocol.d.ts +19 -2
  215. package/dist/internal/agent-protocol.js +13 -0
  216. package/dist/nudge-ui.mjs +558 -311
  217. package/dist/project/artifacts.d.ts +13 -0
  218. package/dist/project/artifacts.js +253 -0
  219. package/dist/transport/artifacts.d.ts +8 -0
  220. package/dist/transport/artifacts.js +9 -0
  221. package/dist/transport/editor.js +3 -1
  222. package/dist/transport/routes.d.ts +2 -0
  223. package/dist/transport/routes.js +2 -0
  224. package/package.json +6 -2
  225. package/dist/inspector/changes/workspaceChanges.d.ts +0 -47
  226. package/dist/inspector/changes/workspaceChanges.js +0 -265
@@ -0,0 +1,300 @@
1
+ import { canWriteWorkspace } from "../canvas/workspaceLease.js";
2
+ import { applicationTarget, targetKey } from "../drafts/model.js";
3
+ import { changeKey, mergeChange, sameEffectiveChanges, selectorForChange } from "./model.js";
4
+ import { isElementChange } from "./types.js";
5
+ import { recordEdit, replayTimeline, pruneDraftHistory, timelineStatus, subscribeTimeline, clearSessionUndoHistory, discardDraftHistory, } from "../workspace/timeline.js";
6
+ export { recordCanvasChange, discardCanvasHistory, discardDraftHistory, clearSessionUndoHistory, createChangeHistoryGroup, } from "../workspace/timeline.js";
7
+ const drafts = new Map();
8
+ const lockedDrafts = new Set();
9
+ const listeners = new Set();
10
+ const draftListeners = new Set();
11
+ /** Until a frame is activated, edits belong to the current page's draft. */
12
+ let activeDraftId = null;
13
+ function activeId() {
14
+ return activeDraftId ??= targetKey(applicationTarget());
15
+ }
16
+ function draftState(id = activeId()) {
17
+ let draft = drafts.get(id);
18
+ if (!draft) {
19
+ draft = { id, revision: 0, contents: { changes: [], structuralChanges: [] } };
20
+ drafts.set(id, draft);
21
+ }
22
+ return draft;
23
+ }
24
+ export function lockDraft(id) {
25
+ if (lockedDrafts.has(id))
26
+ throw new Error("This iteration is already saving.");
27
+ lockedDrafts.add(id);
28
+ return () => { lockedDrafts.delete(id); };
29
+ }
30
+ export function isDraftLocked(id) {
31
+ return id === undefined ? lockedDrafts.size > 0 : lockedDrafts.has(id);
32
+ }
33
+ export function canEditDraft(id = activeId()) {
34
+ return canWriteWorkspace() && !lockedDrafts.has(id);
35
+ }
36
+ export function setActiveDraft(id, activate) {
37
+ draftState(id).activate = activate;
38
+ if (activeId() === id)
39
+ return;
40
+ activeDraftId = id;
41
+ publishSelection();
42
+ }
43
+ let snapshot = null;
44
+ function cloneContents(value) {
45
+ return {
46
+ changes: value.changes.map((change) => cloneValue(change)),
47
+ structuralChanges: value.structuralChanges.map((change) => cloneValue(change)),
48
+ };
49
+ }
50
+ function cloneValue(value, key) {
51
+ if (key === "oldToken" || key === "newToken")
52
+ return value;
53
+ if (Array.isArray(value))
54
+ return value.map((item) => cloneValue(item));
55
+ if (value !== null && typeof value === "object") {
56
+ const clone = {};
57
+ for (const [key, child] of Object.entries(value)) {
58
+ clone[key] = cloneValue(child, key);
59
+ }
60
+ return clone;
61
+ }
62
+ return value;
63
+ }
64
+ function freezeValue(value, key) {
65
+ if (key === "oldToken" || key === "newToken")
66
+ return value;
67
+ if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
68
+ for (const [childKey, child] of Object.entries(value))
69
+ freezeValue(child, childKey);
70
+ Object.freeze(value);
71
+ }
72
+ return value;
73
+ }
74
+ function createSnapshot() {
75
+ const draft = draftState();
76
+ return Object.freeze({ draftId: draft.id, revision: draft.revision, ...draft.contents, ...timelineStatus() });
77
+ }
78
+ let notificationDepth = 0;
79
+ let notificationPending = false;
80
+ function mutate(operation) {
81
+ notificationDepth += 1;
82
+ try {
83
+ return operation();
84
+ }
85
+ finally {
86
+ notificationDepth -= 1;
87
+ if (notificationDepth === 0 && notificationPending) {
88
+ notificationPending = false;
89
+ publishSelection();
90
+ }
91
+ }
92
+ }
93
+ function publishSelection() {
94
+ if (notificationDepth > 0) {
95
+ notificationPending = true;
96
+ return;
97
+ }
98
+ snapshot = null;
99
+ for (const listener of listeners)
100
+ listener();
101
+ }
102
+ subscribeTimeline(publishSelection);
103
+ function replaceContents(draft, next) {
104
+ draft.contents = freezeValue(cloneContents(next));
105
+ draft.revision += 1;
106
+ for (const listener of draftListeners)
107
+ listener(draft.id);
108
+ publishSelection();
109
+ }
110
+ export function subscribeDraftChanges(listener) {
111
+ draftListeners.add(listener);
112
+ return () => draftListeners.delete(listener);
113
+ }
114
+ export function getDraftChanges(id) {
115
+ const draft = drafts.get(id);
116
+ return {
117
+ draftId: id,
118
+ revision: draft?.revision ?? 0,
119
+ changes: draft?.contents.changes ?? [],
120
+ structuralChanges: draft?.contents.structuralChanges ?? [],
121
+ ...timelineStatus(),
122
+ };
123
+ }
124
+ export function restoreDraftChanges(id, next, revision = 1) {
125
+ const draft = draftState(id);
126
+ draft.contents = freezeValue(cloneContents(next));
127
+ draft.revision = revision;
128
+ publishSelection();
129
+ }
130
+ function commit(next) {
131
+ if (!canEditDraft())
132
+ return false;
133
+ const draft = draftState();
134
+ const before = draft.contents;
135
+ mutate(() => {
136
+ replaceContents(draft, next);
137
+ recordEdit({ draftId: draft.id, activate: draft.activate, before, after: draft.contents }, sameDraftContents);
138
+ });
139
+ return true;
140
+ }
141
+ function getSnapshot() { return snapshot ??= createSnapshot(); }
142
+ function subscribe(listener) {
143
+ listeners.add(listener);
144
+ return () => listeners.delete(listener);
145
+ }
146
+ function commitChangeRecordsImpl(incoming) {
147
+ if (incoming.length === 0)
148
+ return "unchanged";
149
+ const contents = draftState().contents;
150
+ const changes = incoming.reduce((current, change) => mergeChange(current, change), [...contents.changes]);
151
+ if (sameEffectiveChanges([...contents.changes], changes))
152
+ return "unchanged";
153
+ return commit({ ...contents, changes }) ? "applied" : "blocked";
154
+ }
155
+ function revertChangeRecordImpl(change) {
156
+ const contents = draftState().contents;
157
+ const changes = contents.changes.filter((candidate) => changeKey(candidate) !== changeKey(change));
158
+ return changes.length !== contents.changes.length && commit({ ...contents, changes });
159
+ }
160
+ function discardChangeRecordsImpl(target) {
161
+ const contents = draftState().contents;
162
+ const changes = contents.changes.filter((change) => target.kind === "selector"
163
+ ? selectorForChange(change) !== target.selector
164
+ : !isElementChange(change) || change.instanceOverride?.id !== target.id);
165
+ return changes.length !== contents.changes.length && commit({ ...contents, changes });
166
+ }
167
+ function commitStructuralChangeImpl(change) {
168
+ const contents = draftState().contents;
169
+ if (contents.structuralChanges.some((candidate) => candidate.id === change.id))
170
+ return false;
171
+ return commit({ ...contents, structuralChanges: [...contents.structuralChanges, change] });
172
+ }
173
+ function revertStructuralChangeRecordImpl(changeId) {
174
+ const contents = draftState().contents;
175
+ const structuralChanges = contents.structuralChanges.filter((change) => change.id !== changeId);
176
+ return structuralChanges.length !== contents.structuralChanges.length && commit({ ...contents, structuralChanges });
177
+ }
178
+ export function reconcileDraftChanges(id, verifiedKeys, verifiedStructuralIds) {
179
+ if (!canEditDraft(id))
180
+ return 0;
181
+ const draft = draftState(id);
182
+ const retain = (value) => ({
183
+ changes: value.changes.filter((change) => !verifiedKeys.has(changeKey(change))),
184
+ structuralChanges: value.structuralChanges.filter((change) => !verifiedStructuralIds.has(change.id)),
185
+ });
186
+ const next = retain(draft.contents);
187
+ const removed = draft.contents.changes.length - next.changes.length + draft.contents.structuralChanges.length - next.structuralChanges.length;
188
+ if (removed === 0)
189
+ return 0;
190
+ mutate(() => {
191
+ replaceContents(draft, next);
192
+ pruneDraftHistory(id, retain, sameDraftContents);
193
+ });
194
+ return removed;
195
+ }
196
+ function reconcileActiveDraftChangesImpl(keys, ids) {
197
+ return reconcileDraftChanges(activeId(), keys, ids);
198
+ }
199
+ function sameDraftContents(left, right) {
200
+ return sameEffectiveChanges([...left.changes], [...right.changes])
201
+ && JSON.stringify(left.structuralChanges) === JSON.stringify(right.structuralChanges);
202
+ }
203
+ function replay(direction) {
204
+ if (isDraftLocked() || !canWriteWorkspace())
205
+ return false;
206
+ return mutate(() => replayTimeline(direction, (entry, next) => {
207
+ replaceContents(draftState(entry.draftId), next);
208
+ entry.activate?.();
209
+ if (!entry.activate)
210
+ setActiveDraft(entry.draftId);
211
+ }));
212
+ }
213
+ function restoreActiveDraftChangesImpl(next, preserveHistory = false) {
214
+ mutate(() => {
215
+ replaceContents(draftState(), next);
216
+ if (!preserveHistory)
217
+ clearSessionUndoHistory();
218
+ });
219
+ }
220
+ export function clearDraftChanges(id, expectedRevision) {
221
+ const draft = draftState(id);
222
+ if (!canEditDraft(id) || (expectedRevision !== undefined && draft.revision !== expectedRevision))
223
+ return false;
224
+ mutate(() => {
225
+ replaceContents(draft, { changes: [], structuralChanges: [] });
226
+ discardDraftHistory(id);
227
+ });
228
+ return true;
229
+ }
230
+ export function listDraftIds() {
231
+ return [...drafts.keys()];
232
+ }
233
+ /** Drops a draft whose content no longer exists, such as a deleted iteration. */
234
+ export function forgetDraft(id) {
235
+ if (!drafts.has(id) || lockedDrafts.has(id))
236
+ return;
237
+ discardDraftHistory(id);
238
+ drafts.delete(id);
239
+ for (const listener of draftListeners)
240
+ listener(id);
241
+ publishSelection();
242
+ }
243
+ function clearActiveDraftChangesImpl() { clearDraftChanges(activeId()); }
244
+ function resetDraftChangesImpl() {
245
+ drafts.clear();
246
+ lockedDrafts.clear();
247
+ activeDraftId = null;
248
+ clearSessionUndoHistory();
249
+ publishSelection();
250
+ }
251
+ export const draftChangeStore = {
252
+ getSnapshot, subscribe,
253
+ commitChangeRecords: commitChangeRecordsImpl,
254
+ revertChangeRecord: revertChangeRecordImpl,
255
+ discardChangeRecords: discardChangeRecordsImpl,
256
+ commitStructuralChange: commitStructuralChangeImpl,
257
+ revertStructuralChangeRecord: revertStructuralChangeRecordImpl,
258
+ reconcileActiveDraftChanges: reconcileActiveDraftChangesImpl,
259
+ undoChange: () => replay("undo"),
260
+ redoChange: () => replay("redo"),
261
+ restoreActiveDraftChanges: restoreActiveDraftChangesImpl,
262
+ clearActiveDraftChanges: clearActiveDraftChangesImpl,
263
+ };
264
+ export function getActiveDraftChanges() {
265
+ return draftChangeStore.getSnapshot();
266
+ }
267
+ export function subscribeActiveDraftChanges(listener) {
268
+ return draftChangeStore.subscribe(listener);
269
+ }
270
+ export function commitChangeRecords(incoming, project) {
271
+ const result = draftChangeStore.commitChangeRecords(incoming);
272
+ if (result === "applied")
273
+ project(draftChangeStore.getSnapshot());
274
+ return result;
275
+ }
276
+ export function commitStructuralChange(change, project) {
277
+ const changed = draftChangeStore.commitStructuralChange(change);
278
+ if (changed)
279
+ project(draftChangeStore.getSnapshot());
280
+ return changed;
281
+ }
282
+ export function undoChange(project) {
283
+ const changed = draftChangeStore.undoChange();
284
+ if (changed)
285
+ project(draftChangeStore.getSnapshot());
286
+ return changed;
287
+ }
288
+ export function redoChange(project) {
289
+ const changed = draftChangeStore.redoChange();
290
+ if (changed)
291
+ project(draftChangeStore.getSnapshot());
292
+ return changed;
293
+ }
294
+ export function restoreActiveDraftChanges(next, project) {
295
+ draftChangeStore.restoreActiveDraftChanges(next);
296
+ project(draftChangeStore.getSnapshot());
297
+ }
298
+ export function resetDraftChanges() {
299
+ resetDraftChangesImpl();
300
+ }
@@ -3,9 +3,11 @@ import type { PreviewResult } from "../projection/managedStylesheet.js";
3
3
  export interface PreviewDocument {
4
4
  readonly logicalDocument: string;
5
5
  readonly sessionId: string;
6
+ readonly draftId?: string;
6
7
  }
7
8
  export interface PreviewAttempt extends PreviewDocument {
8
- readonly workspaceRevision: number;
9
+ readonly draftId: string;
10
+ readonly draftRevision: number;
9
11
  readonly attempt: number;
10
12
  }
11
13
  export interface PreviewDiagnostic extends PreviewAttempt {
@@ -26,7 +28,7 @@ export declare function publishPreviewDiagnostic(attempt: PreviewAttempt, change
26
28
  export declare function clearPreviewDiagnostics(changeKeys?: Iterable<string>): void;
27
29
  /** Notifies consumers when verification state changes without a result. */
28
30
  export declare function notifyPreviewDiagnostics(): void;
29
- export declare function getPreviewDiagnostic(changeKey: string, logicalDocument?: string): PreviewDiagnostic | undefined;
31
+ export declare function getPreviewDiagnostic(changeKey: string, logicalDocument?: string, draftId?: string): PreviewDiagnostic | undefined;
30
32
  /**
31
33
  * Host-first read across live documents. The per-document store is observable
32
34
  * here so a Canvas-only conflict is not write-only; host remains the default
@@ -1,16 +1,15 @@
1
- import { getWorkspaceChanges, subscribeWorkspaceChanges } from "./workspaceChanges.js";
1
+ import { getActiveDraftChanges, getDraftChanges } from "./draftChanges.js";
2
2
  const HOST_DOCUMENT = {
3
3
  logicalDocument: "host",
4
4
  sessionId: "host-document",
5
5
  };
6
- let workspaceRevision = getWorkspaceChanges().revision;
7
6
  let activeSessions = new Map([[HOST_DOCUMENT.logicalDocument, HOST_DOCUMENT.sessionId]]);
8
7
  let attemptsBySession = new Map();
9
8
  let diagnostics = new Map();
10
9
  let diagnosticRevision = 0;
11
10
  const listeners = new Set();
12
11
  function storageKey(document, changeKey) {
13
- return `${document.logicalDocument}\u0000${document.sessionId}\u0000${changeKey}`;
12
+ return `${document.draftId ?? getActiveDraftChanges().draftId}\u0000${document.logicalDocument}\u0000${document.sessionId}\u0000${changeKey}`;
14
13
  }
15
14
  function sessionKey(document) {
16
15
  return `${document.logicalDocument}\u0000${document.sessionId}`;
@@ -26,23 +25,12 @@ function notify() {
26
25
  for (const listener of listeners)
27
26
  listener();
28
27
  }
29
- function syncWorkspaceRevision() {
30
- const nextRevision = getWorkspaceChanges().revision;
31
- if (nextRevision === workspaceRevision)
32
- return;
33
- // Track the revision so late publishes are rejected per key. Do not clear
34
- // here: a new commit must preserve earlier diagnostics until they are
35
- // re-verified, otherwise every edit deletes every other change's status.
36
- workspaceRevision = nextRevision;
37
- }
38
- subscribeWorkspaceChanges(syncWorkspaceRevision);
39
28
  /** Returns the stable host-document identity for this inspector lifetime. */
40
29
  export function getHostPreviewDocument() {
41
- return HOST_DOCUMENT;
30
+ return { ...HOST_DOCUMENT, draftId: getActiveDraftChanges().draftId };
42
31
  }
43
32
  /** Starts or replaces the live session for one logical document. */
44
33
  export function startPreviewDocumentSession(document) {
45
- syncWorkspaceRevision();
46
34
  const previousSession = activeSessions.get(document.logicalDocument);
47
35
  if (previousSession === document.sessionId)
48
36
  return;
@@ -76,9 +64,9 @@ export function invalidatePreviewDocumentSession(logicalDocument, sessionId) {
76
64
  notify();
77
65
  }
78
66
  /** Opens a verification attempt for the currently active document session. */
79
- export function beginPreviewAttempt(document, revision = getWorkspaceChanges().revision) {
80
- syncWorkspaceRevision();
81
- if (revision !== workspaceRevision || activeSessions.get(document.logicalDocument) !== document.sessionId) {
67
+ export function beginPreviewAttempt(document, revision = getDraftChanges(document.draftId ?? getActiveDraftChanges().draftId).revision) {
68
+ const draftId = document.draftId ?? getActiveDraftChanges().draftId;
69
+ if (revision !== getDraftChanges(draftId).revision || activeSessions.get(document.logicalDocument) !== document.sessionId) {
82
70
  return null;
83
71
  }
84
72
  const attempt = (attemptsBySession.get(sessionKey(document)) ?? 0) + 1;
@@ -87,12 +75,11 @@ export function beginPreviewAttempt(document, revision = getWorkspaceChanges().r
87
75
  // rejects late publishes per key; wiping would drop every other change's
88
76
  // status before it is re-verified (and drop all host status when Canvas
89
77
  // verification returns null).
90
- return { ...document, workspaceRevision: revision, attempt };
78
+ return { ...document, draftId, draftRevision: revision, attempt };
91
79
  }
92
80
  /** Publishes only a result from the active revision, session, and attempt. */
93
81
  export function publishPreviewDiagnostic(attempt, changeKey, result) {
94
- syncWorkspaceRevision();
95
- if (attempt.workspaceRevision !== workspaceRevision
82
+ if (attempt.draftRevision !== getDraftChanges(attempt.draftId).revision
96
83
  || activeSessions.get(attempt.logicalDocument) !== attempt.sessionId
97
84
  || attemptsBySession.get(sessionKey(attempt)) !== attempt.attempt) {
98
85
  return false;
@@ -101,7 +88,7 @@ export function publishPreviewDiagnostic(attempt, changeKey, result) {
101
88
  const previous = diagnostics.get(key);
102
89
  if (previous
103
90
  && previous.changeKey === changeKey
104
- && previous.workspaceRevision === attempt.workspaceRevision
91
+ && previous.draftRevision === attempt.draftRevision
105
92
  && previous.attempt === attempt.attempt
106
93
  && sameResult(previous.result, result)) {
107
94
  return true;
@@ -127,7 +114,7 @@ export function clearPreviewDiagnostics(changeKeys) {
127
114
  export function notifyPreviewDiagnostics() {
128
115
  notify();
129
116
  }
130
- export function getPreviewDiagnostic(changeKey, logicalDocument = HOST_DOCUMENT.logicalDocument) {
117
+ export function getPreviewDiagnostic(changeKey, logicalDocument = HOST_DOCUMENT.logicalDocument, draftId = getActiveDraftChanges().draftId) {
131
118
  // Pure getter: never sync or notify. It runs on the React render path via
132
119
  // StaleChangeIndicator, so side effects here would clear state mid-render.
133
120
  // Diagnostics survive workspace revisions until overwritten or explicitly
@@ -135,7 +122,7 @@ export function getPreviewDiagnostic(changeKey, logicalDocument = HOST_DOCUMENT.
135
122
  const sessionId = activeSessions.get(logicalDocument);
136
123
  if (!sessionId)
137
124
  return undefined;
138
- return diagnostics.get(storageKey({ logicalDocument, sessionId }, changeKey));
125
+ return diagnostics.get(storageKey({ logicalDocument, sessionId, draftId }, changeKey));
139
126
  }
140
127
  /**
141
128
  * Host-first read across live documents. The per-document store is observable
@@ -164,7 +151,6 @@ export function getPreviewDiagnosticRevision() {
164
151
  }
165
152
  /** Test and teardown reset; it does not alter canonical workspace state. */
166
153
  export function resetPreviewDiagnostics() {
167
- workspaceRevision = getWorkspaceChanges().revision;
168
154
  activeSessions = new Map([[HOST_DOCUMENT.logicalDocument, HOST_DOCUMENT.sessionId]]);
169
155
  attemptsBySession = new Map();
170
156
  diagnostics = new Map();
@@ -1,5 +1,5 @@
1
1
  import { type NudgeUiRuntimeConfig } from "./runtime/runtimeConfig.js";
2
- export type { NudgeUiRuntimeConfig } from "./runtime/runtimeConfig.js";
2
+ export type { NudgeUiRuntimeConfig, NudgeUiRuntimeFeatures } from "./runtime/runtimeConfig.js";
3
3
  export { detectStylingSystem } from "./runtime/runtimeConfig.js";
4
4
  /** Version of the host-to-inspector runtime manifest Interface. */
5
5
  export declare const NUDGE_UI_CLIENT_MANIFEST_VERSION = 1;
@@ -0,0 +1,2 @@
1
+ import { type ReactElement } from "react";
2
+ export declare function CommentsOverlay(): ReactElement | null;