@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,182 @@
1
+ /**
2
+ * CustomTemplateContext — exposes the merged set of doc-level + library
3
+ * custom templates to the rest of the editor (chiefly TemplatePicker
4
+ * and TemplateDesigner).
5
+ *
6
+ * The host wraps the editor in a provider, supplying:
7
+ * - `docTemplates`: the list currently sourced from the active doc's
8
+ * frontmatter (read from `Doc.customTemplates`).
9
+ * - `onDocTemplatesChange`: a callback the host uses to persist a
10
+ * change back into the doc (e.g. by updating the markdown source).
11
+ *
12
+ * Library templates come from `localStorage` via `library.ts` and are
13
+ * managed entirely within the context — the host doesn't see them.
14
+ *
15
+ * `applyTemplate(def)` is the bridge between the two pools: when a
16
+ * user picks a library template for a block, we copy its definition
17
+ * into the doc's customTemplates (if it isn't already there) so the
18
+ * doc remains self-sufficient for SSR / export. The block's annotation
19
+ * (`{[name]}`) is what actually selects the template at render time;
20
+ * this just ensures the registry merge has the definition.
21
+ */
22
+
23
+ import {
24
+ createContext,
25
+ useCallback,
26
+ useContext,
27
+ useEffect,
28
+ useMemo,
29
+ useState,
30
+ type ReactNode,
31
+ } from 'react';
32
+ import type { CustomTemplateDefinition } from '@bendyline/squisq/schemas';
33
+ import {
34
+ listLibraryTemplates,
35
+ saveLibraryTemplate as saveLibraryTemplateRaw,
36
+ deleteLibraryTemplate as deleteLibraryTemplateRaw,
37
+ } from './library';
38
+
39
+ export interface CustomTemplateContextValue {
40
+ /** Templates inlined into the current doc's frontmatter. */
41
+ docTemplates: CustomTemplateDefinition[];
42
+ /** Templates the user has saved to their browser-local library. */
43
+ libraryTemplates: CustomTemplateDefinition[];
44
+ /**
45
+ * Convenience: the union of doc + library, with library entries
46
+ * skipped when a doc template of the same name already exists.
47
+ * Used by the picker so a single "Custom" section covers both
48
+ * sources without duplicates.
49
+ */
50
+ allTemplates: CustomTemplateDefinition[];
51
+
52
+ /**
53
+ * Persist a template into the current doc. Replaces any existing
54
+ * entry with the same `name`. Triggers the host's
55
+ * `onDocTemplatesChange` so the doc's frontmatter ends up updated.
56
+ */
57
+ upsertDocTemplate: (def: CustomTemplateDefinition) => void;
58
+ /** Persist a template into the user's library (replaces by name). */
59
+ upsertLibraryTemplate: (def: CustomTemplateDefinition) => void;
60
+ /** Remove a doc-level template by name. */
61
+ removeDocTemplate: (name: string) => void;
62
+ /** Remove a library template by name. */
63
+ removeLibraryTemplate: (name: string) => void;
64
+ /**
65
+ * Apply a template to the current doc. If the template is already in
66
+ * the doc, this is a no-op. If it's only in the library, it's
67
+ * copied into the doc so SSR / export work. Returns the resolved
68
+ * definition so callers can also write the heading annotation.
69
+ */
70
+ applyTemplate: (def: CustomTemplateDefinition) => CustomTemplateDefinition;
71
+ }
72
+
73
+ const CustomTemplateContext = createContext<CustomTemplateContextValue | null>(null);
74
+
75
+ export interface CustomTemplateProviderProps {
76
+ /** The current doc's custom templates (from `Doc.customTemplates`). */
77
+ docTemplates: CustomTemplateDefinition[];
78
+ /**
79
+ * Callback the host uses to persist a new doc-template list back
80
+ * into the doc (e.g. by writing the encoded payload into the
81
+ * markdown's `squisq-custom-templates` frontmatter key).
82
+ */
83
+ onDocTemplatesChange: (next: CustomTemplateDefinition[]) => void;
84
+ children: ReactNode;
85
+ }
86
+
87
+ export function CustomTemplateProvider({
88
+ docTemplates,
89
+ onDocTemplatesChange,
90
+ children,
91
+ }: CustomTemplateProviderProps) {
92
+ const [libraryTemplates, setLibraryTemplates] = useState<CustomTemplateDefinition[]>(() =>
93
+ listLibraryTemplates(),
94
+ );
95
+
96
+ // Re-read the library when this provider mounts so cross-tab edits
97
+ // (or initial first-paint quirks) are picked up. We don't subscribe
98
+ // to localStorage events in v1 — opening the picker re-renders and
99
+ // re-reads, which is enough for the single-tab common case.
100
+ useEffect(() => {
101
+ setLibraryTemplates(listLibraryTemplates());
102
+ }, []);
103
+
104
+ const upsertDocTemplate = useCallback(
105
+ (def: CustomTemplateDefinition) => {
106
+ const existingIdx = docTemplates.findIndex((t) => t.name === def.name);
107
+ const next =
108
+ existingIdx >= 0
109
+ ? docTemplates.map((t, i) => (i === existingIdx ? def : t))
110
+ : [...docTemplates, def];
111
+ onDocTemplatesChange(next);
112
+ },
113
+ [docTemplates, onDocTemplatesChange],
114
+ );
115
+
116
+ const removeDocTemplate = useCallback(
117
+ (name: string) => {
118
+ const next = docTemplates.filter((t) => t.name !== name);
119
+ if (next.length !== docTemplates.length) onDocTemplatesChange(next);
120
+ },
121
+ [docTemplates, onDocTemplatesChange],
122
+ );
123
+
124
+ const upsertLibraryTemplate = useCallback((def: CustomTemplateDefinition) => {
125
+ setLibraryTemplates(saveLibraryTemplateRaw(def));
126
+ }, []);
127
+
128
+ const removeLibraryTemplate = useCallback((name: string) => {
129
+ setLibraryTemplates(deleteLibraryTemplateRaw(name));
130
+ }, []);
131
+
132
+ const applyTemplate = useCallback(
133
+ (def: CustomTemplateDefinition) => {
134
+ // If the doc already has this template (matching name), leave
135
+ // both alone — the existing entry might be a customized copy.
136
+ const inDoc = docTemplates.find((t) => t.name === def.name);
137
+ if (!inDoc) upsertDocTemplate(def);
138
+ return inDoc ?? def;
139
+ },
140
+ [docTemplates, upsertDocTemplate],
141
+ );
142
+
143
+ const allTemplates = useMemo(() => {
144
+ const seen = new Set(docTemplates.map((t) => t.name));
145
+ return [...docTemplates, ...libraryTemplates.filter((t) => !seen.has(t.name))];
146
+ }, [docTemplates, libraryTemplates]);
147
+
148
+ const value = useMemo<CustomTemplateContextValue>(
149
+ () => ({
150
+ docTemplates,
151
+ libraryTemplates,
152
+ allTemplates,
153
+ upsertDocTemplate,
154
+ upsertLibraryTemplate,
155
+ removeDocTemplate,
156
+ removeLibraryTemplate,
157
+ applyTemplate,
158
+ }),
159
+ [
160
+ docTemplates,
161
+ libraryTemplates,
162
+ allTemplates,
163
+ upsertDocTemplate,
164
+ upsertLibraryTemplate,
165
+ removeDocTemplate,
166
+ removeLibraryTemplate,
167
+ applyTemplate,
168
+ ],
169
+ );
170
+
171
+ return <CustomTemplateContext.Provider value={value}>{children}</CustomTemplateContext.Provider>;
172
+ }
173
+
174
+ /**
175
+ * Hook returning the current context. Returns null when no provider is
176
+ * mounted — callers can degrade to "no custom templates" rather than
177
+ * throwing, since the feature is optional.
178
+ */
179
+ // eslint-disable-next-line react-refresh/only-export-components -- hook is co-located with its provider by design; splitting it into its own module would fragment the context API for no runtime benefit
180
+ export function useCustomTemplates(): CustomTemplateContextValue | null {
181
+ return useContext(CustomTemplateContext);
182
+ }