@mosetta/editor 0.0.0-stage → 0.0.29

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 (115) hide show
  1. package/CHANGELOG.md +190 -0
  2. package/LICENSE +21 -0
  3. package/README.md +10 -2
  4. package/mosetta.json +6 -0
  5. package/package.json +35 -3
  6. package/prefabs/workbench/prefab.json +11 -0
  7. package/prefabs/workbench/versions/1.json +120 -0
  8. package/prefabs/workbench/versions/2.json +13 -0
  9. package/prefabs/workbench/versions/3.json +19 -0
  10. package/prefabs/workbench/versions/4.json +29 -0
  11. package/prefabs/workbench/versions/5.json +29 -0
  12. package/tiles/canvas/canvas.component.tsx +2038 -0
  13. package/tiles/canvas/canvas.css +973 -0
  14. package/tiles/canvas/canvasTools.ts +66 -0
  15. package/tiles/canvas/chromeNodes.ts +35 -0
  16. package/tiles/canvas/ghosts.ts +33 -0
  17. package/tiles/canvas/insertPopover.tsx +56 -0
  18. package/tiles/canvas/popoverPlacement.ts +104 -0
  19. package/tiles/canvas/popoverSize.ts +87 -0
  20. package/tiles/canvas/providerChrome.tsx +191 -0
  21. package/tiles/canvas/scrollWatch.ts +43 -0
  22. package/tiles/canvas/settingsPopover.tsx +257 -0
  23. package/tiles/canvas/settingsTabs.ts +78 -0
  24. package/tiles/canvas/toolPanel.tsx +86 -0
  25. package/tiles/content/autoBind.ts +61 -0
  26. package/tiles/content/blockPage.css +390 -0
  27. package/tiles/content/blockPage.tsx +379 -0
  28. package/tiles/content/blockPicker.css +215 -0
  29. package/tiles/content/blockPicker.tsx +501 -0
  30. package/tiles/content/blockUpgrades.ts +145 -0
  31. package/tiles/content/blockVariants.ts +185 -0
  32. package/tiles/content/blockVocabulary.ts +77 -0
  33. package/tiles/content/catalogVersions.ts +106 -0
  34. package/tiles/content/componentPreview.css +82 -0
  35. package/tiles/content/componentPreview.tsx +249 -0
  36. package/tiles/content/content.server.ts +593 -0
  37. package/tiles/content/contentCommon.ts +133 -0
  38. package/tiles/content/disconnected.ts +56 -0
  39. package/tiles/content/distributions.css +256 -0
  40. package/tiles/content/distributions.tsx +271 -0
  41. package/tiles/content/editingAutosave.ts +125 -0
  42. package/tiles/content/editingClipboard.ts +185 -0
  43. package/tiles/content/editingConflicts.ts +223 -0
  44. package/tiles/content/editingHotkeys.ts +59 -0
  45. package/tiles/content/editingNotices.ts +105 -0
  46. package/tiles/content/formRoot.ts +18 -0
  47. package/tiles/content/fuzzySearch.ts +121 -0
  48. package/tiles/content/mediaUpload.ts +55 -0
  49. package/tiles/content/moduleSiblings.ts +9 -0
  50. package/tiles/content/mountedTree.ts +136 -0
  51. package/tiles/content/nodeSettings.css +483 -0
  52. package/tiles/content/nodeSettings.tsx +963 -0
  53. package/tiles/content/pasteText.ts +131 -0
  54. package/tiles/content/prefabFields.tsx +158 -0
  55. package/tiles/content/prefabParts.ts +105 -0
  56. package/tiles/content/previewEnvironment.ts +46 -0
  57. package/tiles/content/projectConfig.ts +46 -0
  58. package/tiles/content/projectPrefabs.ts +57 -0
  59. package/tiles/content/publishModal.css +109 -0
  60. package/tiles/content/publishModal.tsx +92 -0
  61. package/tiles/content/refsEditing.ts +412 -0
  62. package/tiles/content/scaledStage.ts +63 -0
  63. package/tiles/content/searchField.css +32 -0
  64. package/tiles/content/searchField.tsx +32 -0
  65. package/tiles/content/settingsDraft.ts +178 -0
  66. package/tiles/content/settingsIssues.tsx +124 -0
  67. package/tiles/content/themeScope.ts +72 -0
  68. package/tiles/content/themeVariables.ts +47 -0
  69. package/tiles/content/tooltipPlacement.ts +17 -0
  70. package/tiles/content/tooltips.tsx +131 -0
  71. package/tiles/content/treeMounter.ts +33 -0
  72. package/tiles/content/updatesModal.css +124 -0
  73. package/tiles/content/updatesModal.tsx +110 -0
  74. package/tiles/content/useCtrlHeld.ts +24 -0
  75. package/tiles/content/useEditingSession.ts +115 -0
  76. package/tiles/content/useMountedTree.ts +47 -0
  77. package/tiles/content/workbenchScale.css +27 -0
  78. package/tiles/hostFallback/hostFallback.component.tsx +32 -0
  79. package/tiles/hostFallback/hostFallback.css +12 -0
  80. package/tiles/hostFallback/hostFallback.editor.tsx +10 -0
  81. package/tiles/page/page.component.tsx +7 -0
  82. package/tiles/page/page.script.tsx +5 -0
  83. package/tiles/pageModules/pageModules.component.tsx +740 -0
  84. package/tiles/pageModules/pageModules.css +383 -0
  85. package/tiles/pageModules/pageModules.icon.svg +1 -0
  86. package/tiles/pageModules/servedPage.ts +465 -0
  87. package/tiles/pagesPanel/pagesPanel.component.tsx +1645 -0
  88. package/tiles/pagesPanel/pagesPanel.css +713 -0
  89. package/tiles/pagesPanel/pagesPanel.editor.tsx +23 -0
  90. package/tiles/pagesPanel/pagesSearch.ts +194 -0
  91. package/tiles/pagesPanel/routeTree.ts +98 -0
  92. package/tiles/previewBridge/landing.ts +66 -0
  93. package/tiles/previewBridge/previewAgent.ts +457 -0
  94. package/tiles/previewBridge/previewBridge.component.tsx +137 -0
  95. package/tiles/previewBridge/previewBridge.editor.tsx +10 -0
  96. package/tiles/previewBridge/previewBridgeCommon.ts +172 -0
  97. package/tiles/previewBridge/standIn.ts +22 -0
  98. package/tiles/treeView/treeView.component.tsx +514 -0
  99. package/tiles/treeView/treeView.css +303 -0
  100. package/tiles/treeView/treeView.editor.tsx +12 -0
  101. package/tiles/workbench/assistant.css +401 -0
  102. package/tiles/workbench/assistant.tsx +516 -0
  103. package/tiles/workbench/assistantChat.ts +165 -0
  104. package/tiles/workbench/dictation.ts +354 -0
  105. package/tiles/workbench/projectInfo.ts +72 -0
  106. package/tiles/workbench/recent.ts +67 -0
  107. package/tiles/workbench/workbench.component.tsx +476 -0
  108. package/tiles/workbench/workbench.css +376 -0
  109. package/tiles/workbench/workbenchAddress.ts +202 -0
  110. package/tiles/workbench/workspace.ts +775 -0
  111. package/tiles/workbenchEditor/workbenchEditor.component.tsx +461 -0
  112. package/tiles/workbenchEditor/workbenchEditor.css +370 -0
  113. package/tiles/workbenchHome/workbenchHome.component.tsx +196 -0
  114. package/tiles/workbenchHome/workbenchHome.css +271 -0
  115. package/tsconfig.json +3 -0
@@ -0,0 +1,172 @@
1
+ // The editor ↔ preview contract. Shared by the two halves that speak it: the agent module riding
2
+ // inside the canvas iframe (previewBridge.component.tsx) and the overlay drawing on top of that
3
+ // iframe (modules/canvas).
4
+ //
5
+ // TRANSPORT — a MessageChannel, not bare window.postMessage in both directions. The agent
6
+ // announces itself to whoever embeds it (a greeting carrying nothing but "a mosetta preview is
7
+ // here"), and the editor answers by handing over one end of a fresh channel. From then on the
8
+ // port IS the permission to talk: nothing to forge, no origin to re-check on every message, and
9
+ // the same code works once previews move to a tenant's own subdomain.
10
+ //
11
+ // COORDINATES — every box is viewport-relative, measured inside the iframe. The iframe element in
12
+ // the editor spans exactly that viewport, so the overlay draws the numbers as they arrive: no
13
+ // scroll arithmetic, and no way for the two sides to disagree about the origin of the axes.
14
+ import type { ITileReference, IBlueprint } from '@mosetta/core';
15
+
16
+ /** bumped when the shape below changes incompatibly — an older agent is ignored, not crashed */
17
+ export const PREVIEW_PROTOCOL_VERSION = 1;
18
+
19
+ /** the agent's module name — the one thing about it that is a constant */
20
+ const PREVIEW_BRIDGE_NAME = 'previewBridge';
21
+
22
+ /**
23
+ * The agent's full id, derived from ANY reference of the same editor build (in practice: the
24
+ * canvas's own, through useComponent). Namespace and version are shared — only the name differs —
25
+ * so the agent that rides into the preview is exactly the build that will talk to it, and the two
26
+ * halves of the protocol can never drift apart in version.
27
+ *
28
+ * The editor naming its own module is also what keeps the render runtime free of any knowledge
29
+ * about the editor: it is told which entity to attach, it does not go looking for one.
30
+ */
31
+ export function previewBridgeIdOf({ namespace, version }: ITileReference): string {
32
+ return `_ns_${namespace}_t_component_n_${PREVIEW_BRIDGE_NAME}_v_${version}`;
33
+ }
34
+
35
+ /**
36
+ * The id of the LANDING SPACE: a little emptiness the agent puts into its own copy of the page
37
+ * where a block is about to go, so the overlay can frame the very spot (`landing` below). Outside
38
+ * the `node-<n>` space the editor hands out, like the agent's own node; no document ever holds it.
39
+ */
40
+ export const LANDING_NODE_ID = '__mosettaLanding';
41
+
42
+ /** what a stand-in (standIn.ts) carries: the reference of the block it stands for */
43
+ export const STAND_IN_ATTRIBUTE = 'data-mosetta-stand-in';
44
+
45
+ /** where a block is about to go: the node, its slot, the position among that slot's children */
46
+ export interface ILandingPlace {
47
+ readonly parentId: string;
48
+ readonly slot: string;
49
+ readonly index: number;
50
+ }
51
+
52
+ /** the agent's greeting (window-level, iframe → embedder) */
53
+ export const PREVIEW_HELLO = 'mosetta:preview-hello';
54
+
55
+ /** the editor's answer (window-level, embedder → iframe), carrying the channel port */
56
+ export const PREVIEW_PORT = 'mosetta:preview-port';
57
+
58
+ export interface IPreviewHello {
59
+ readonly mosetta: typeof PREVIEW_HELLO;
60
+ readonly protocol: number;
61
+ }
62
+
63
+ export interface IPreviewPortOffer {
64
+ readonly mosetta: typeof PREVIEW_PORT;
65
+ readonly protocol: number;
66
+ }
67
+
68
+ export function isPreviewHello(data: unknown): data is IPreviewHello {
69
+ const message = data as IPreviewHello | null;
70
+ return !!message && message.mosetta === PREVIEW_HELLO && message.protocol === PREVIEW_PROTOCOL_VERSION;
71
+ }
72
+
73
+ export function isPreviewPortOffer(data: unknown): data is IPreviewPortOffer {
74
+ const message = data as IPreviewPortOffer | null;
75
+ return !!message && message.mosetta === PREVIEW_PORT && message.protocol === PREVIEW_PROTOCOL_VERSION;
76
+ }
77
+
78
+ /** where a tree node landed on screen; `depth` breaks ties when boxes nest exactly */
79
+ export interface INodeBox {
80
+ readonly id: string;
81
+ readonly reference: string;
82
+ readonly depth: number;
83
+ readonly x: number;
84
+ readonly y: number;
85
+ readonly width: number;
86
+ readonly height: number;
87
+ }
88
+
89
+ export interface IPreviewViewport {
90
+ readonly width: number;
91
+ readonly height: number;
92
+ }
93
+
94
+ /**
95
+ * A place a block can go, as the preview currently renders it: the module opened this slot, and
96
+ * this is where the next child would land. `area` is the box of whatever encloses the marker —
97
+ * for an empty slot that is the region to highlight, since a bare insertion point has no size.
98
+ */
99
+ export interface ISlotBox {
100
+ readonly ownerId: string;
101
+ readonly slot: string;
102
+ readonly max: number | 'many';
103
+ readonly min: number;
104
+ readonly filled: number;
105
+ readonly x: number;
106
+ readonly y: number;
107
+ readonly area: { readonly x: number; readonly y: number; readonly width: number; readonly height: number } | null;
108
+ }
109
+
110
+ /** agent → editor */
111
+ export type TPreviewEvent
112
+ = | {
113
+ readonly t: 'geometry';
114
+ readonly boxes: readonly INodeBox[];
115
+ readonly slots: readonly ISlotBox[];
116
+ /**
117
+ * The PREFAB nodes the realm shows EXPANDED right now (by node id): a live tree can only
118
+ * re-expand a prefab from blocks already rendered, so a prefab node absent here needs the
119
+ * server's render — the editor rebuilds the frame instead of pushing the tree. An agent that
120
+ * does not say (older) leaves the editor to its own guess.
121
+ */
122
+ readonly units?: readonly string[];
123
+ /**
124
+ * The PREFABS' own blocks, each under its expanded id (`<prefabNode>/<block>`) — `boxes`
125
+ * carries a prefab as ONE box, their union, under the prefab node; these are for the editor to
126
+ * frame one of them, picked to be seen (read-only). Outlets are left out: they are the page's
127
+ * place, not the prefab's block.
128
+ */
129
+ readonly parts?: readonly INodeBox[];
130
+ readonly viewport: IPreviewViewport;
131
+ /** where the page stood when this was measured — the baseline for every 'scroll' after it */
132
+ readonly scroll: { readonly x: number; readonly y: number };
133
+ }
134
+ // Scrolling the page moves everything by the same amount and changes no layout, so it is
135
+ // reported as a POSITION, not as new geometry: the editor slides its whole overlay by the
136
+ // difference. Re-measuring every block on every scroll event is what put the outlines a
137
+ // visible step behind the page.
138
+ | { readonly t: 'scroll'; readonly x: number; readonly y: number }
139
+ // ctrl carries Ctrl-or-Cmd from the source event: keyboard focus may live in EITHER realm, so
140
+ // the editor cannot read the modifier itself for events born inside the preview
141
+ // `nodeId` names a block of the PAGE — a prefab's block reads as its prefab node; `part` adds
142
+ // which of the prefab's own blocks it was (`<prefabNode>/<block>`), null on the page's own
143
+ | { readonly t: 'hover'; readonly nodeId: string | null; readonly part?: string | null; readonly ctrl?: boolean }
144
+ | { readonly t: 'pick'; readonly nodeId: string | null; readonly part?: string | null; readonly ctrl?: boolean }
145
+ /**
146
+ * Where the pointer is over the page, at most once a frame while armed: the overlay offers a
147
+ * place on the side of the selected block the pointer is on. Viewport coordinates, with the
148
+ * page's scroll at that moment — the editor reads them against the measurement's own baseline.
149
+ */
150
+ | { readonly t: 'pointer'; readonly x: number; readonly y: number; readonly scroll: { readonly x: number; readonly y: number } };
151
+
152
+ /** editor → agent */
153
+ export type TPreviewCommand
154
+ // suppression of the application's own click handling, so a click means "select this block"
155
+ // instead of following a link. Off = the preview behaves like the live page.
156
+ = | { readonly t: 'armed'; readonly armed: boolean }
157
+ | { readonly t: 'measure' }
158
+ | { readonly t: 'reveal'; readonly nodeId: string }
159
+ /** the views the editor chose for reference providers (i18n: the language being edited) */
160
+ | { readonly t: 'views'; readonly views: Readonly<Record<string, unknown>> }
161
+ /**
162
+ * The tree as the editor now holds it, rendered in place of the one the preview booted with.
163
+ * Only ever sent while the MODULE SET is unchanged: a block of a type this realm never loaded
164
+ * cannot appear by re-rendering, and that case rebuilds the frame instead.
165
+ */
166
+ | { readonly t: 'page'; readonly page: IBlueprint }
167
+ /**
168
+ * Make room where a block is about to go — or take the room away (null). The agent splices its
169
+ * landing space into the tree it renders (and into every tree that arrives while the place
170
+ * stands); the measurement after reports it like any node, under LANDING_NODE_ID.
171
+ */
172
+ | { readonly t: 'landing'; readonly at: ILandingPlace | null };
@@ -0,0 +1,22 @@
1
+ // The STAND-IN in the preview's own copy of the page: where a block of a distribution the project
2
+ // disconnected stands, the agent shows a placeholder of its own module instead (ADR-0059). The site
3
+ // renders nothing there; the editor shows the author what it leaves out, under the block's very id,
4
+ // so the overlay frames it, a click selects it and the tree's ✕ takes it away. The server's editable
5
+ // preview does the same to the first render (editorStandIn in @mosetta/server) — this keeps every
6
+ // tree the editor sends after it alike. Pure tree surgery, like the landing space.
7
+ import type { IBlueprint } from '@mosetta/core';
8
+ import { withoutDistributions } from '@mosetta/content/units';
9
+ import type { IBlueprintNodeDoc } from '@mosetta/content/units';
10
+
11
+ /** the page with a stand-in for every block of the `disconnected` distributions, or the very page */
12
+ export function withStandIns(page: IBlueprint, disconnected: readonly string[], agentReference: string): IBlueprint {
13
+ if (!disconnected.length) return page;
14
+ return withoutDistributions(page as unknown as IBlueprintNodeDoc, disconnected, (node) => ({
15
+ id: node.id,
16
+ reference: agentReference,
17
+ ...(node.slot !== undefined ? { slot: node.slot } : {}),
18
+ settings: { standIn: node.reference },
19
+ children: [],
20
+ ssr: false,
21
+ })) as unknown as IBlueprint;
22
+ }