@bendyline/squisq-editor-react 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.
Files changed (186) hide show
  1. package/README.md +57 -10
  2. package/dist/index.d.ts +1114 -52
  3. package/dist/index.js +18446 -8050
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles/fa-brands-400-AHOAZHCU.woff2 +0 -0
  6. package/dist/styles/fa-regular-400-VRZYIBIZ.woff2 +0 -0
  7. package/dist/styles/fa-solid-900-MDEYK55F.woff2 +0 -0
  8. package/dist/styles/fa-v4compatibility-ETEVP6IB.woff2 +0 -0
  9. package/dist/styles/index.css +13867 -0
  10. package/package.json +15 -7
  11. package/src/BlockCardView.tsx +121 -0
  12. package/src/BlockPreviewPanel.tsx +69 -0
  13. package/src/BlockPropertiesPopover.tsx +191 -0
  14. package/src/EditorContext.tsx +165 -16
  15. package/src/EditorShell.tsx +265 -144
  16. package/src/FolderView.tsx +131 -0
  17. package/src/Icon.tsx +26 -0
  18. package/src/ImageEditor.tsx +69 -22
  19. package/src/OutlinePanel.tsx +64 -7
  20. package/src/PlainHtmlPreview.tsx +30 -3
  21. package/src/PreviewControls.tsx +491 -122
  22. package/src/PreviewPanel.tsx +15 -9
  23. package/src/RawEditor.tsx +179 -17
  24. package/src/RecorderEntry.tsx +9 -16
  25. package/src/TemplateAnnotation.ts +44 -0
  26. package/src/TemplatePicker.tsx +329 -54
  27. package/src/ThemeCustomizerPanel.tsx +30 -336
  28. package/src/ThemePicker.tsx +112 -3
  29. package/src/TimelineBlockPreview.tsx +37 -0
  30. package/src/TimelineTrack.tsx +671 -0
  31. package/src/Toolbar.tsx +544 -180
  32. package/src/Tooltip.tsx +22 -4
  33. package/src/TransitionPicker.tsx +351 -0
  34. package/src/VersionHistoryPanel.tsx +4 -16
  35. package/src/ViewMenuPanel.tsx +17 -14
  36. package/src/WysiwygEditor.tsx +161 -65
  37. package/src/__tests__/blockProperties.test.ts +92 -0
  38. package/src/__tests__/blockRange.test.ts +105 -0
  39. package/src/__tests__/buildPreviewDocTransition.test.ts +73 -0
  40. package/src/__tests__/codeContextSectionView.test.tsx +95 -0
  41. package/src/__tests__/codeContextZoneManager.test.ts +127 -0
  42. package/src/__tests__/createShapeLayer.test.ts +46 -0
  43. package/src/__tests__/diffContextSections.test.ts +39 -0
  44. package/src/__tests__/drawingShapeRoundTrip.test.ts +49 -0
  45. package/src/__tests__/editorShellCodeContext.test.tsx +86 -0
  46. package/src/__tests__/editorShellProps.test.tsx +96 -0
  47. package/src/__tests__/embeddedMedia.test.ts +48 -0
  48. package/src/__tests__/headingTransition.test.ts +138 -0
  49. package/src/__tests__/layoutChildRoundTrip.test.ts +71 -0
  50. package/src/__tests__/plainHtmlPreview.test.tsx +10 -8
  51. package/src/__tests__/previewControls.test.tsx +70 -0
  52. package/src/__tests__/recorderMediaInsert.test.ts +86 -0
  53. package/src/__tests__/templateAnnotationRoundTrip.test.ts +18 -0
  54. package/src/__tests__/templatePickerMetadata.test.ts +32 -0
  55. package/src/__tests__/timelineSource.test.ts +134 -0
  56. package/src/__tests__/tiptapBridge.test.ts +92 -0
  57. package/src/__tests__/tiptapBridgeConformance.test.ts +47 -0
  58. package/src/__tests__/tooltip.test.tsx +72 -0
  59. package/src/__tests__/transitionCatalog.test.ts +64 -0
  60. package/src/__tests__/useBlockNavigator.test.tsx +67 -0
  61. package/src/__tests__/useJsonEditorTokens.test.ts +59 -0
  62. package/src/__tests__/useMediaRecorder.test.ts +41 -0
  63. package/src/__tests__/useTimelineClock.test.ts +21 -0
  64. package/src/blockProperties.ts +88 -0
  65. package/src/blockRange.ts +132 -0
  66. package/src/buildPreviewDoc.ts +98 -9
  67. package/src/codeContext/CodeContextSectionView.tsx +124 -0
  68. package/src/codeContext/CodeContextZoneManager.ts +149 -0
  69. package/src/codeContext/CodeContextZones.tsx +121 -0
  70. package/src/codeContext/diffContextSections.ts +38 -0
  71. package/src/codeContext/types.ts +75 -0
  72. package/src/customTemplates/AddBin.tsx +126 -0
  73. package/src/customTemplates/CustomLayoutManager.tsx +233 -0
  74. package/src/customTemplates/CustomTemplateContext.tsx +182 -0
  75. package/src/customTemplates/LayerToolbar.tsx +580 -0
  76. package/src/customTemplates/ShapeGlyph.tsx +47 -0
  77. package/src/customTemplates/TemplateDesigner.tsx +430 -0
  78. package/src/customTemplates/__tests__/library.test.ts +88 -0
  79. package/src/customTemplates/__tests__/normalizePositions.test.ts +109 -0
  80. package/src/customTemplates/__tests__/shapeDefs.test.ts +49 -0
  81. package/src/customTemplates/__tests__/useMemoryLayerAdapter.test.ts +95 -0
  82. package/src/customTemplates/designer.css +673 -0
  83. package/src/customTemplates/index.ts +31 -0
  84. package/src/customTemplates/library.ts +97 -0
  85. package/src/customTemplates/normalizePositions.ts +75 -0
  86. package/src/customTemplates/shapeDefs.ts +131 -0
  87. package/src/customTemplates/thumbnail.tsx +63 -0
  88. package/src/customTemplates/tokenDefs.ts +60 -0
  89. package/src/customTemplates/useDocCustomTemplates.ts +52 -0
  90. package/src/customTemplates/useMemoryLayerAdapter.ts +123 -0
  91. package/src/customThemes/CustomThemeContext.tsx +179 -0
  92. package/src/customThemes/CustomThemeDialog.tsx +286 -0
  93. package/src/customThemes/__tests__/CustomThemeContext.test.tsx +64 -0
  94. package/src/customThemes/__tests__/CustomThemeDialog.test.tsx +47 -0
  95. package/src/customThemes/__tests__/customThemeLibrary.test.ts +51 -0
  96. package/src/customThemes/customThemeLibrary.ts +97 -0
  97. package/src/customThemes/index.ts +31 -0
  98. package/src/customThemes/themeControls.tsx +229 -0
  99. package/src/customThemes/themeDraft.ts +272 -0
  100. package/src/customThemes/useDocCustomThemes.ts +49 -0
  101. package/src/diagram/DiagramCanvas.tsx +240 -0
  102. package/src/diagram/DiagramExtension.ts +209 -0
  103. package/src/diagram/DiagramMaximizedOverlay.tsx +46 -0
  104. package/src/diagram/DiagramWidget.tsx +270 -0
  105. package/src/diagram/diagramCommands.ts +604 -0
  106. package/src/diagram/diagramConstants.ts +17 -0
  107. package/src/diagram/useDiagramData.ts +126 -0
  108. package/src/embeddedMedia.ts +78 -0
  109. package/src/frontmatter.ts +29 -0
  110. package/src/headingTransition.ts +231 -0
  111. package/src/imageEditor/CanvasSurface.tsx +383 -88
  112. package/src/imageEditor/PropertiesPanel.tsx +47 -1
  113. package/src/imageEditor/Toolbar.tsx +229 -16
  114. package/src/imageEditor/createShapeLayer.ts +280 -0
  115. package/src/imageEditor/icons.tsx +34 -114
  116. package/src/imageEditor/image-editor.css +54 -5
  117. package/src/imageEditor/state.ts +23 -3
  118. package/src/index.ts +109 -1
  119. package/src/jsonEditor/useJsonEditorTokens.ts +13 -43
  120. package/src/recorder/RecorderModal.tsx +120 -53
  121. package/src/recorder/RecorderPanel.tsx +2 -26
  122. package/src/recorder/hooks/useMediaRecorder.ts +17 -11
  123. package/src/recorder/insertMediaBlock.ts +30 -0
  124. package/src/resolveBlockVisual.ts +33 -0
  125. package/src/scene/Scene.tsx +540 -0
  126. package/src/scene/SceneBlockExtension.ts +198 -0
  127. package/src/scene/SceneBlockToolbar.tsx +201 -0
  128. package/src/scene/SceneBlockWidget.tsx +434 -0
  129. package/src/scene/ScenePropsBar.tsx +85 -0
  130. package/src/scene/SceneSelection.tsx +107 -0
  131. package/src/scene/SceneViewport.tsx +102 -0
  132. package/src/scene/ShapePalette.tsx +181 -0
  133. package/src/scene/__tests__/DiagramAdapter.test.ts +56 -0
  134. package/src/scene/__tests__/bezierEdit.test.ts +85 -0
  135. package/src/scene/__tests__/blockLayers.test.ts +57 -0
  136. package/src/scene/__tests__/shapeLayers.test.ts +106 -0
  137. package/src/scene/__tests__/useSceneHitTest.test.ts +90 -0
  138. package/src/scene/__tests__/useScenePanZoom.test.ts +103 -0
  139. package/src/scene/adapters/DiagramAdapter.ts +168 -0
  140. package/src/scene/adapters/DrawingAdapter.ts +415 -0
  141. package/src/scene/adapters/LayoutAdapter.ts +310 -0
  142. package/src/scene/adapters/blockLayers.ts +159 -0
  143. package/src/scene/commands/SceneCommand.ts +70 -0
  144. package/src/scene/commands/drawingCommands.ts +318 -0
  145. package/src/scene/commands/layoutCommands.ts +301 -0
  146. package/src/scene/hooks/useSceneHitTest.ts +105 -0
  147. package/src/scene/hooks/useScenePanZoom.ts +147 -0
  148. package/src/scene/hooks/useSceneSelection.ts +62 -0
  149. package/src/scene/index.ts +95 -0
  150. package/src/scene/layers/DiagramEdges.tsx +127 -0
  151. package/src/scene/layers/edgeGeometry.ts +77 -0
  152. package/src/scene/layers/nodeCard.tsx +145 -0
  153. package/src/scene/layers/renderLayer.tsx +70 -0
  154. package/src/scene/layers/shapeLayers.ts +201 -0
  155. package/src/scene/paths/bezierEdit.ts +208 -0
  156. package/src/scene/scene.css +649 -0
  157. package/src/scene/text/SceneTextOverlay.tsx +161 -0
  158. package/src/scene/text/sceneTextChannel.ts +40 -0
  159. package/src/scene/text/sceneTextConfig.ts +27 -0
  160. package/src/scene/text/sceneTiptap.ts +36 -0
  161. package/src/scene/text/useSceneTextEditing.ts +39 -0
  162. package/src/scene/tools/ConnectTool.ts +111 -0
  163. package/src/scene/tools/DrawingConnectTool.ts +161 -0
  164. package/src/scene/tools/PathTool.ts +158 -0
  165. package/src/scene/tools/PlaceTool.ts +47 -0
  166. package/src/scene/tools/SceneTool.ts +75 -0
  167. package/src/scene/tools/SelectTool.ts +284 -0
  168. package/src/scene/tools/ShapeTool.ts +144 -0
  169. package/src/scene/tools/TextTool.ts +72 -0
  170. package/src/scene/tools/TokenTool.ts +95 -0
  171. package/src/scene/tools/createDrawShapeTool.ts +82 -0
  172. package/src/styles/code-context.css +155 -0
  173. package/src/styles/diagram.css +183 -0
  174. package/src/styles/editor.css +1708 -150
  175. package/src/styles/folder-view.css +210 -0
  176. package/src/styles/image-edit-affordance.css +2 -2
  177. package/src/styles/index.css +5 -0
  178. package/src/timelineSource.ts +244 -0
  179. package/src/tiptapBridge.ts +115 -34
  180. package/src/tooltipPlacement.ts +13 -0
  181. package/src/transitionCatalog.ts +159 -0
  182. package/src/types/monaco-shims.d.ts +10 -0
  183. package/src/useBlockNavigator.ts +153 -0
  184. package/src/useMonacoLoader.ts +23 -1
  185. package/src/useTimelineClock.ts +76 -0
  186. package/src/utils/dropUtils.ts +1 -1
@@ -0,0 +1,649 @@
1
+ /*
2
+ * Squisq Scene engine — visual styles for the 2D editing surface.
3
+ *
4
+ * The Scene is a position:relative root with three children:
5
+ * 1. Optional toolbar (top-left)
6
+ * 2. SVG viewport (fills the root)
7
+ * 3. Optional maximize button (top-right)
8
+ *
9
+ * Colors lean on existing `--squisq-*` CSS variables so light/dark
10
+ * themes apply automatically.
11
+ */
12
+
13
+ .squisq-scene-root {
14
+ position: relative;
15
+ width: 100%;
16
+ height: 100%;
17
+ background: var(--squisq-surface, #ffffff);
18
+ border: 1px solid var(--squisq-border, #e2e8f0);
19
+ border-radius: 8px;
20
+ overflow: hidden;
21
+ }
22
+
23
+ .squisq-scene-viewport {
24
+ display: block;
25
+ width: 100%;
26
+ height: 100%;
27
+ touch-action: none;
28
+ background: transparent;
29
+ user-select: none;
30
+ outline: none;
31
+ }
32
+
33
+ .squisq-scene-viewport:focus,
34
+ .squisq-scene-viewport:focus-visible {
35
+ outline: none;
36
+ }
37
+
38
+ /* Custom URL-based cursors with a white halo around a dark stroke, so
39
+ the pointer stays visible regardless of canvas background or the
40
+ user's OS cursor scheme (Windows lets users render system cursors
41
+ in pure white, which makes the OS-stock keywords invisible on the
42
+ editor's light surface — mirrors the I-beam workaround in
43
+ editor.css). Each tool sets `data-cursor` on the SVG; the matching
44
+ selector picks the right URL with a keyword fallback when the URL
45
+ fails to load. */
46
+
47
+ /* Default arrow — used by SelectTool. Hotspot at the tip (3, 3). */
48
+ .squisq-scene-viewport[data-cursor='default'] {
49
+ cursor:
50
+ url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='22' viewBox='0 0 20 22'><path d='M3 3 L3 17 L7 13 L10 19 L12 18 L9 12 L15 12 Z' fill='%231f2937' stroke='white' stroke-width='1.5' stroke-linejoin='round'/></svg>")
51
+ 3 3,
52
+ default;
53
+ }
54
+
55
+ /* Crosshair — used by ConnectTool / PathTool / ShapeTool. Hotspot is
56
+ the cross center (11, 11). */
57
+ .squisq-scene-viewport[data-cursor='crosshair'] {
58
+ cursor:
59
+ url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='23' height='23' viewBox='0 0 23 23'><g fill='none' stroke-linecap='round'><path d='M11 1 L11 21 M1 11 L21 11' stroke='white' stroke-width='3.2'/><path d='M11 1 L11 21 M1 11 L21 11' stroke='%231f2937' stroke-width='1.4'/><circle cx='11' cy='11' r='2' fill='white' stroke='%231f2937' stroke-width='1'/></g></svg>")
60
+ 11 11,
61
+ crosshair;
62
+ }
63
+
64
+ /* Text I-beam — used by TextTool. Re-uses the same shape as
65
+ `.squisq-wysiwyg-editor` in editor.css so the look is consistent. */
66
+ .squisq-scene-viewport[data-cursor='text'] {
67
+ cursor:
68
+ url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='22' viewBox='0 0 16 22'><g fill='none' stroke-linecap='round'><path d='M5 3 L11 3 M5 19 L11 19 M8 3 L8 19' stroke='white' stroke-width='3.2'/><path d='M5 3 L11 3 M5 19 L11 19 M8 3 L8 19' stroke='%231f2937' stroke-width='1.4'/></g></svg>")
69
+ 8 11,
70
+ text;
71
+ }
72
+
73
+ .squisq-scene-dot {
74
+ fill: var(--squisq-text-muted, #94a3b8);
75
+ fill-opacity: 0.35;
76
+ }
77
+
78
+ /* ── Selection ─────────────────────────────────────────────── */
79
+
80
+ .squisq-scene-selection-outline {
81
+ fill: none;
82
+ stroke: #6366f1;
83
+ stroke-width: 1.5;
84
+ stroke-dasharray: 4 3;
85
+ vector-effect: non-scaling-stroke;
86
+ }
87
+
88
+ .squisq-scene-selection-handle {
89
+ fill: #ffffff;
90
+ stroke: #6366f1;
91
+ stroke-width: 1.5;
92
+ vector-effect: non-scaling-stroke;
93
+ }
94
+
95
+ /* ── Tool overlays ────────────────────────────────────────── */
96
+
97
+ .squisq-scene-marquee {
98
+ fill: rgba(99, 102, 241, 0.08);
99
+ stroke: #6366f1;
100
+ stroke-width: 1;
101
+ stroke-dasharray: 4 3;
102
+ vector-effect: non-scaling-stroke;
103
+ }
104
+
105
+ .squisq-scene-connect-preview {
106
+ fill: none;
107
+ stroke: #6366f1;
108
+ stroke-width: 2;
109
+ stroke-dasharray: 6 4;
110
+ vector-effect: non-scaling-stroke;
111
+ pointer-events: none;
112
+ }
113
+
114
+ /* ── Toolbar ──────────────────────────────────────────────── */
115
+
116
+ .squisq-scene-toolbar {
117
+ position: absolute;
118
+ top: 8px;
119
+ left: 8px;
120
+ z-index: 10;
121
+ display: flex;
122
+ flex-direction: row;
123
+ flex-wrap: wrap;
124
+ gap: 4px;
125
+ padding: 4px;
126
+ background: #ffffff;
127
+ border: 1px solid #cbd5e1;
128
+ border-radius: 6px;
129
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
130
+ max-width: calc(100% - 16px);
131
+ }
132
+
133
+ .squisq-scene-tool {
134
+ display: inline-flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ min-width: 28px;
138
+ height: 28px;
139
+ padding: 0 8px;
140
+ background: #ffffff;
141
+ border: 1px solid transparent;
142
+ border-radius: 4px;
143
+ color: #1e293b;
144
+ cursor: pointer;
145
+ font-size: 11px;
146
+ font-weight: 600;
147
+ line-height: 1;
148
+ white-space: nowrap;
149
+ }
150
+
151
+ .squisq-scene-tool:hover {
152
+ background: #f1f5f9;
153
+ border-color: #cbd5e1;
154
+ color: #1e293b;
155
+ }
156
+
157
+ .squisq-scene-tool:focus-visible {
158
+ outline: 2px solid #6366f1;
159
+ outline-offset: 1px;
160
+ }
161
+
162
+ .squisq-scene-tool--active {
163
+ background: #eef2ff;
164
+ border-color: #6366f1;
165
+ color: #4338ca;
166
+ }
167
+
168
+ .squisq-scene-tool--active:hover {
169
+ background: #e0e7ff;
170
+ border-color: #4f46e5;
171
+ color: #4338ca;
172
+ }
173
+
174
+ .squisq-scene-tool-label {
175
+ font-size: 11px;
176
+ font-weight: 600;
177
+ text-transform: uppercase;
178
+ letter-spacing: 0.04em;
179
+ color: inherit;
180
+ }
181
+
182
+ /* ── Block toolbar (above & outside the canvas) ───────────────
183
+ * Shared chrome for diagram / drawing / layout. A right-aligned row
184
+ * that sits above the canvas box (rendered by `SceneBlockToolbar`).
185
+ * Tool buttons reuse `.squisq-scene-tool`; actions use `.squisq-scene-action`. */
186
+ .squisq-scene-block-toolbar {
187
+ display: flex;
188
+ flex-direction: row;
189
+ flex-wrap: wrap;
190
+ align-items: center;
191
+ justify-content: flex-end;
192
+ gap: 8px;
193
+ margin-bottom: 6px;
194
+ min-height: 30px;
195
+ }
196
+
197
+ .squisq-scene-block-tools,
198
+ .squisq-scene-block-actions {
199
+ display: inline-flex;
200
+ flex-direction: row;
201
+ flex-wrap: wrap;
202
+ gap: 4px;
203
+ padding: 3px;
204
+ background: var(--squisq-surface, #ffffff);
205
+ border: 1px solid var(--squisq-border, #cbd5e1);
206
+ border-radius: 6px;
207
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
208
+ }
209
+
210
+ .squisq-scene-action {
211
+ display: inline-flex;
212
+ align-items: center;
213
+ gap: 4px;
214
+ height: 28px;
215
+ padding: 0 10px;
216
+ background: #ffffff;
217
+ border: 1px solid transparent;
218
+ border-radius: 4px;
219
+ color: #1e293b;
220
+ cursor: pointer;
221
+ font-size: 11px;
222
+ font-weight: 600;
223
+ line-height: 1;
224
+ white-space: nowrap;
225
+ }
226
+
227
+ .squisq-scene-action:hover:not(:disabled) {
228
+ background: #f1f5f9;
229
+ border-color: #cbd5e1;
230
+ }
231
+
232
+ .squisq-scene-action:focus-visible {
233
+ outline: 2px solid #6366f1;
234
+ outline-offset: 1px;
235
+ }
236
+
237
+ .squisq-scene-action:disabled {
238
+ opacity: 0.45;
239
+ cursor: default;
240
+ }
241
+
242
+ .squisq-scene-action-icon {
243
+ font-size: 13px;
244
+ line-height: 1;
245
+ }
246
+
247
+ .squisq-scene-action-label {
248
+ font-size: 11px;
249
+ font-weight: 600;
250
+ text-transform: uppercase;
251
+ letter-spacing: 0.04em;
252
+ }
253
+
254
+ .squisq-scene-action--danger {
255
+ color: #b91c1c;
256
+ }
257
+
258
+ .squisq-scene-action--danger:hover:not(:disabled) {
259
+ background: #fef2f2;
260
+ border-color: #fecaca;
261
+ color: #b91c1c;
262
+ }
263
+
264
+ /* Maximized overlay: a flex-filling canvas with the toolbar as a right-hand
265
+ column (full screen has room to reserve it). */
266
+ .squisq-scene-block-max {
267
+ display: flex;
268
+ flex-direction: row;
269
+ align-items: stretch;
270
+ gap: 12px;
271
+ width: 100%;
272
+ height: 100%;
273
+ padding: 12px;
274
+ }
275
+ .squisq-scene-block-max > .squisq-diagram-canvas,
276
+ .squisq-scene-block-max > .squisq-scene-stage {
277
+ flex: 1;
278
+ min-width: 0;
279
+ min-height: 0;
280
+ }
281
+
282
+ /* ── Side (gutter) contextual toolbar ─────────────────────────
283
+ The drawing/layout/diagram toolbar renders as a vertical ~180px column to
284
+ the RIGHT of the canvas instead of a horizontal bar above it, so it doesn't
285
+ reserve any vertical canvas space. Inline, it floats in the page's right
286
+ gutter (outside the content column); maximized, it's a normal right column. */
287
+ .squisq-scene-shell {
288
+ position: relative;
289
+ }
290
+
291
+ .squisq-scene-side-toolbar {
292
+ position: absolute;
293
+ top: 0;
294
+ left: 100%;
295
+ margin-left: 12px;
296
+ width: 180px;
297
+ }
298
+
299
+ .squisq-scene-block-max > .squisq-scene-side-toolbar {
300
+ position: static;
301
+ flex: 0 0 180px;
302
+ width: 180px;
303
+ overflow-y: auto;
304
+ }
305
+
306
+ /* Re-flow the (normally horizontal, right-aligned) toolbar into a top-aligned
307
+ vertical column whose button groups wrap within the 180px width. */
308
+ .squisq-scene-side-toolbar .squisq-scene-block-toolbar {
309
+ flex-direction: column;
310
+ align-items: stretch;
311
+ justify-content: flex-start;
312
+ width: 100%;
313
+ margin: 0;
314
+ }
315
+ .squisq-scene-side-toolbar .squisq-scene-block-tools,
316
+ .squisq-scene-side-toolbar .squisq-scene-block-actions,
317
+ .squisq-scene-side-toolbar .squisq-scene-block-props {
318
+ width: 100%;
319
+ }
320
+
321
+ /* In the gutter the Shape palette can't drop straight down (it'd run off the
322
+ page edge), so open it toward the canvas (to the left of the button). */
323
+ .squisq-scene-side-toolbar .squisq-scene-tool-popover-anchor .squisq-shape-palette {
324
+ top: 0;
325
+ left: auto;
326
+ right: calc(100% + 6px);
327
+ }
328
+
329
+ /* ── Maximize button ──────────────────────────────────────── */
330
+
331
+ .squisq-scene-maximize-btn {
332
+ position: absolute;
333
+ top: 8px;
334
+ right: 8px;
335
+ z-index: 10;
336
+ width: 32px;
337
+ height: 32px;
338
+ display: inline-flex;
339
+ align-items: center;
340
+ justify-content: center;
341
+ background: #ffffff;
342
+ border: 1px solid #cbd5e1;
343
+ border-radius: 6px;
344
+ cursor: pointer;
345
+ font-size: 16px;
346
+ line-height: 1;
347
+ color: #1e293b;
348
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
349
+ }
350
+
351
+ .squisq-scene-maximize-btn:hover {
352
+ background: #f1f5f9;
353
+ border-color: #94a3b8;
354
+ color: #0f172a;
355
+ }
356
+
357
+ /* ── Diagram node card (used by nodeCard.tsx) ─────────────── */
358
+
359
+ .squisq-scene-node-card {
360
+ fill: var(--squisq-surface, #ffffff);
361
+ stroke: var(--squisq-text, #1e293b);
362
+ stroke-width: 2;
363
+ vector-effect: non-scaling-stroke;
364
+ }
365
+
366
+ .squisq-scene-node-label {
367
+ fill: var(--squisq-text, #1e293b);
368
+ font-weight: 600;
369
+ font-size: 22px;
370
+ font-family:
371
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
372
+ user-select: none;
373
+ pointer-events: none;
374
+ }
375
+
376
+ .squisq-scene-node-handle {
377
+ fill: var(--squisq-text, #1e293b);
378
+ cursor: crosshair;
379
+ pointer-events: all;
380
+ }
381
+
382
+ .squisq-scene-node-handle:hover {
383
+ fill: #6366f1;
384
+ }
385
+
386
+ .squisq-scene-edge-path {
387
+ fill: none;
388
+ stroke: var(--squisq-text, #1e293b);
389
+ stroke-width: 2;
390
+ vector-effect: non-scaling-stroke;
391
+ }
392
+
393
+ .squisq-scene-edge-arrow {
394
+ fill: var(--squisq-text, #1e293b);
395
+ }
396
+
397
+ .squisq-scene-edge-marker-open {
398
+ fill: none;
399
+ stroke: var(--squisq-text, #1e293b);
400
+ stroke-width: 1.5;
401
+ }
402
+
403
+ .squisq-scene-edge-label {
404
+ fill: var(--squisq-text-muted, #64748b);
405
+ font-size: 14px;
406
+ font-family:
407
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
408
+ pointer-events: none;
409
+ user-select: none;
410
+ }
411
+
412
+ /* ── Drawing shape palette + properties panel ──── */
413
+
414
+ .squisq-scene-stage {
415
+ position: relative;
416
+ }
417
+
418
+ /* Anchor for a toolbar dropdown (the shape palette below the Shape tool). */
419
+ .squisq-scene-tool-popover-anchor {
420
+ position: relative;
421
+ display: inline-flex;
422
+ }
423
+
424
+ /* Shape palette — a light dropdown that pops DOWN from the Shape tool
425
+ button in the contextual toolbar. */
426
+ .squisq-shape-palette {
427
+ position: absolute;
428
+ top: calc(100% + 6px);
429
+ left: 0;
430
+ width: 320px;
431
+ max-height: 420px;
432
+ display: flex;
433
+ flex-direction: column;
434
+ background: #ffffff;
435
+ color: #1e293b;
436
+ border: 1px solid #e2e8f0;
437
+ border-radius: 8px;
438
+ box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
439
+ z-index: 30;
440
+ padding: 8px;
441
+ }
442
+
443
+ .squisq-shape-palette-search {
444
+ width: 100%;
445
+ box-sizing: border-box;
446
+ padding: 6px 8px;
447
+ margin-bottom: 6px;
448
+ background: #f8fafc;
449
+ color: inherit;
450
+ border: 1px solid #cbd5e1;
451
+ border-radius: 6px;
452
+ }
453
+
454
+ .squisq-shape-palette-scroll {
455
+ overflow-y: auto;
456
+ }
457
+
458
+ .squisq-shape-palette-heading {
459
+ font-size: 11px;
460
+ font-weight: 600;
461
+ opacity: 0.7;
462
+ margin: 8px 2px 4px;
463
+ text-transform: uppercase;
464
+ }
465
+
466
+ .squisq-shape-palette-grid {
467
+ display: grid;
468
+ grid-template-columns: repeat(6, 1fr);
469
+ gap: 2px;
470
+ }
471
+
472
+ .squisq-shape-palette-item {
473
+ display: flex;
474
+ align-items: center;
475
+ justify-content: center;
476
+ padding: 4px;
477
+ background: none;
478
+ border: 1px solid transparent;
479
+ border-radius: 6px;
480
+ cursor: pointer;
481
+ }
482
+
483
+ .squisq-shape-palette-item:hover {
484
+ background: #f1f5f9;
485
+ border-color: #e2e8f0;
486
+ }
487
+
488
+ .squisq-shape-thumb {
489
+ fill: none;
490
+ stroke: #334155;
491
+ stroke-width: 1.5;
492
+ }
493
+
494
+ .squisq-shape-thumb-line {
495
+ stroke: #334155;
496
+ stroke-width: 1.5;
497
+ }
498
+
499
+ .squisq-shape-thumb-text {
500
+ fill: #334155;
501
+ font-size: 22px;
502
+ font-weight: 700;
503
+ }
504
+
505
+ /* Per-selection style controls, inline in the contextual toolbar (Fill /
506
+ Stroke / Color swatches + connector dropdowns) — styled as a pill that
507
+ matches the tools/actions groups. */
508
+ .squisq-scene-block-props {
509
+ display: inline-flex;
510
+ flex-direction: row;
511
+ flex-wrap: wrap;
512
+ align-items: center;
513
+ gap: 8px;
514
+ padding: 3px 8px;
515
+ background: var(--squisq-surface, #ffffff);
516
+ border: 1px solid var(--squisq-border, #cbd5e1);
517
+ border-radius: 6px;
518
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
519
+ color: #1e293b;
520
+ font-size: 11px;
521
+ }
522
+
523
+ .squisq-scene-prop {
524
+ display: inline-flex;
525
+ align-items: center;
526
+ gap: 5px;
527
+ }
528
+
529
+ .squisq-scene-prop-label {
530
+ font-weight: 600;
531
+ text-transform: uppercase;
532
+ letter-spacing: 0.04em;
533
+ opacity: 0.7;
534
+ }
535
+
536
+ .squisq-scene-prop-color {
537
+ width: 26px;
538
+ height: 22px;
539
+ padding: 0;
540
+ background: none;
541
+ border: 1px solid #cbd5e1;
542
+ border-radius: 4px;
543
+ cursor: pointer;
544
+ }
545
+
546
+ .squisq-scene-prop-select {
547
+ background: #f8fafc;
548
+ color: inherit;
549
+ border: 1px solid #cbd5e1;
550
+ border-radius: 4px;
551
+ padding: 2px 4px;
552
+ font-size: 11px;
553
+ }
554
+
555
+ .squisq-scene-prop-clear {
556
+ font-size: 10px;
557
+ background: none;
558
+ border: 1px solid #cbd5e1;
559
+ color: inherit;
560
+ border-radius: 4px;
561
+ padding: 2px 5px;
562
+ cursor: pointer;
563
+ }
564
+
565
+ .squisq-scene-prop-clear:hover {
566
+ background: #f1f5f9;
567
+ }
568
+
569
+ /* ── Inline widget host (mirrors squisq-diagram-inline) ──── */
570
+
571
+ .squisq-scene-widget-host {
572
+ margin: 0.75rem 0 1.25rem;
573
+ }
574
+
575
+ .squisq-scene-inline {
576
+ position: relative;
577
+ width: 100%;
578
+ height: 420px;
579
+ border: 1px solid var(--squisq-border, #e2e8f0);
580
+ border-radius: 8px;
581
+ overflow: hidden;
582
+ background: var(--squisq-surface, #ffffff);
583
+ }
584
+
585
+ .squisq-scene-inline-placeholder {
586
+ height: 420px;
587
+ border: 1px dashed var(--squisq-border, #e2e8f0);
588
+ border-radius: 8px;
589
+ display: flex;
590
+ align-items: center;
591
+ justify-content: center;
592
+ color: var(--squisq-text-muted, #64748b);
593
+ font-size: 14px;
594
+ }
595
+
596
+ .squisq-scene-inline-placeholder::before {
597
+ content: 'Canvas open in full screen — press Esc to return';
598
+ }
599
+
600
+ /* Hide sub-headings that belong to a layout/drawing block — the canvas
601
+ owns their visual representation. */
602
+ [data-squisq-scene-child='true'] {
603
+ display: none;
604
+ }
605
+
606
+ /* ── Empty state ──────────────────────────────────────────── */
607
+
608
+ .squisq-scene-empty {
609
+ position: absolute;
610
+ inset: 0;
611
+ display: flex;
612
+ flex-direction: column;
613
+ align-items: center;
614
+ justify-content: center;
615
+ gap: 8px;
616
+ pointer-events: none;
617
+ text-align: center;
618
+ padding: 24px;
619
+ }
620
+
621
+ .squisq-scene-empty-title {
622
+ font-size: 14px;
623
+ font-weight: 600;
624
+ color: var(--squisq-text, #1e293b);
625
+ }
626
+
627
+ .squisq-scene-empty-hint {
628
+ font-size: 12px;
629
+ color: var(--squisq-text-muted, #64748b);
630
+ max-width: 320px;
631
+ line-height: 1.45;
632
+ }
633
+
634
+ .squisq-scene-empty-btn {
635
+ pointer-events: auto;
636
+ margin-top: 4px;
637
+ padding: 6px 12px;
638
+ font-size: 12px;
639
+ font-weight: 500;
640
+ color: #ffffff;
641
+ background: #6366f1;
642
+ border: none;
643
+ border-radius: 6px;
644
+ cursor: pointer;
645
+ }
646
+
647
+ .squisq-scene-empty-btn:hover {
648
+ background: #4f46e5;
649
+ }