@oh-just-another/react-ui 0.57.0

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/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +54 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/bottom-sheet.d.ts +26 -0
  6. package/dist/bottom-sheet.d.ts.map +1 -0
  7. package/dist/bottom-sheet.js +87 -0
  8. package/dist/bottom-sheet.js.map +1 -0
  9. package/dist/button-group.d.ts +14 -0
  10. package/dist/button-group.d.ts.map +1 -0
  11. package/dist/button-group.js +3 -0
  12. package/dist/button-group.js.map +1 -0
  13. package/dist/color-palette.d.ts +34 -0
  14. package/dist/color-palette.d.ts.map +1 -0
  15. package/dist/color-palette.js +77 -0
  16. package/dist/color-palette.js.map +1 -0
  17. package/dist/color-swatch-picker.d.ts +29 -0
  18. package/dist/color-swatch-picker.d.ts.map +1 -0
  19. package/dist/color-swatch-picker.js +56 -0
  20. package/dist/color-swatch-picker.js.map +1 -0
  21. package/dist/command-palette.d.ts +13 -0
  22. package/dist/command-palette.d.ts.map +1 -0
  23. package/dist/command-palette.js +146 -0
  24. package/dist/command-palette.js.map +1 -0
  25. package/dist/comments-panel.d.ts +27 -0
  26. package/dist/comments-panel.d.ts.map +1 -0
  27. package/dist/comments-panel.js +139 -0
  28. package/dist/comments-panel.js.map +1 -0
  29. package/dist/constants.d.ts +112 -0
  30. package/dist/constants.d.ts.map +1 -0
  31. package/dist/constants.js +119 -0
  32. package/dist/constants.js.map +1 -0
  33. package/dist/context-menu-controller.d.ts +41 -0
  34. package/dist/context-menu-controller.d.ts.map +1 -0
  35. package/dist/context-menu-controller.js +26 -0
  36. package/dist/context-menu-controller.js.map +1 -0
  37. package/dist/context-menu.d.ts +53 -0
  38. package/dist/context-menu.d.ts.map +1 -0
  39. package/dist/context-menu.js +333 -0
  40. package/dist/context-menu.js.map +1 -0
  41. package/dist/context.d.ts +44 -0
  42. package/dist/context.d.ts.map +1 -0
  43. package/dist/context.js +95 -0
  44. package/dist/context.js.map +1 -0
  45. package/dist/diagram-bars.d.ts +21 -0
  46. package/dist/diagram-bars.d.ts.map +1 -0
  47. package/dist/diagram-bars.js +4 -0
  48. package/dist/diagram-bars.js.map +1 -0
  49. package/dist/diagram-canvas.d.ts +39 -0
  50. package/dist/diagram-canvas.d.ts.map +1 -0
  51. package/dist/diagram-canvas.js +9 -0
  52. package/dist/diagram-canvas.js.map +1 -0
  53. package/dist/diagram-root.d.ts +70 -0
  54. package/dist/diagram-root.d.ts.map +1 -0
  55. package/dist/diagram-root.js +180 -0
  56. package/dist/diagram-root.js.map +1 -0
  57. package/dist/diff-panel.d.ts +25 -0
  58. package/dist/diff-panel.d.ts.map +1 -0
  59. package/dist/diff-panel.js +77 -0
  60. package/dist/diff-panel.js.map +1 -0
  61. package/dist/edge-style-panel.d.ts +19 -0
  62. package/dist/edge-style-panel.d.ts.map +1 -0
  63. package/dist/edge-style-panel.js +120 -0
  64. package/dist/edge-style-panel.js.map +1 -0
  65. package/dist/frame-name-editor-overlay.d.ts +13 -0
  66. package/dist/frame-name-editor-overlay.d.ts.map +1 -0
  67. package/dist/frame-name-editor-overlay.js +84 -0
  68. package/dist/frame-name-editor-overlay.js.map +1 -0
  69. package/dist/frame-panel.d.ts +19 -0
  70. package/dist/frame-panel.d.ts.map +1 -0
  71. package/dist/frame-panel.js +66 -0
  72. package/dist/frame-panel.js.map +1 -0
  73. package/dist/help-button.d.ts +16 -0
  74. package/dist/help-button.d.ts.map +1 -0
  75. package/dist/help-button.js +14 -0
  76. package/dist/help-button.js.map +1 -0
  77. package/dist/help-dialog.d.ts +56 -0
  78. package/dist/help-dialog.d.ts.map +1 -0
  79. package/dist/help-dialog.js +142 -0
  80. package/dist/help-dialog.js.map +1 -0
  81. package/dist/hooks.d.ts +54 -0
  82. package/dist/hooks.d.ts.map +1 -0
  83. package/dist/hooks.js +85 -0
  84. package/dist/hooks.js.map +1 -0
  85. package/dist/icon-button.d.ts +28 -0
  86. package/dist/icon-button.d.ts.map +1 -0
  87. package/dist/icon-button.js +14 -0
  88. package/dist/icon-button.js.map +1 -0
  89. package/dist/index.d.ts +45 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +46 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/layer-panel.d.ts +13 -0
  94. package/dist/layer-panel.d.ts.map +1 -0
  95. package/dist/layer-panel.js +109 -0
  96. package/dist/layer-panel.js.map +1 -0
  97. package/dist/library-panel.d.ts +33 -0
  98. package/dist/library-panel.d.ts.map +1 -0
  99. package/dist/library-panel.js +37 -0
  100. package/dist/library-panel.js.map +1 -0
  101. package/dist/link-caption-editor.d.ts +8 -0
  102. package/dist/link-caption-editor.d.ts.map +1 -0
  103. package/dist/link-caption-editor.js +65 -0
  104. package/dist/link-caption-editor.js.map +1 -0
  105. package/dist/link-drop-shape-menu.d.ts +12 -0
  106. package/dist/link-drop-shape-menu.d.ts.map +1 -0
  107. package/dist/link-drop-shape-menu.js +55 -0
  108. package/dist/link-drop-shape-menu.js.map +1 -0
  109. package/dist/link-hover-popup.d.ts +2 -0
  110. package/dist/link-hover-popup.d.ts.map +1 -0
  111. package/dist/link-hover-popup.js +96 -0
  112. package/dist/link-hover-popup.js.map +1 -0
  113. package/dist/main-menu.d.ts +67 -0
  114. package/dist/main-menu.d.ts.map +1 -0
  115. package/dist/main-menu.js +243 -0
  116. package/dist/main-menu.js.map +1 -0
  117. package/dist/markdown.d.ts +10 -0
  118. package/dist/markdown.d.ts.map +1 -0
  119. package/dist/markdown.js +131 -0
  120. package/dist/markdown.js.map +1 -0
  121. package/dist/merge-dialog.d.ts +22 -0
  122. package/dist/merge-dialog.d.ts.map +1 -0
  123. package/dist/merge-dialog.js +46 -0
  124. package/dist/merge-dialog.js.map +1 -0
  125. package/dist/modal.d.ts +19 -0
  126. package/dist/modal.d.ts.map +1 -0
  127. package/dist/modal.js +87 -0
  128. package/dist/modal.js.map +1 -0
  129. package/dist/palette.d.ts +73 -0
  130. package/dist/palette.d.ts.map +1 -0
  131. package/dist/palette.js +330 -0
  132. package/dist/palette.js.map +1 -0
  133. package/dist/popover.d.ts +33 -0
  134. package/dist/popover.d.ts.map +1 -0
  135. package/dist/popover.js +107 -0
  136. package/dist/popover.js.map +1 -0
  137. package/dist/property-panel.d.ts +32 -0
  138. package/dist/property-panel.d.ts.map +1 -0
  139. package/dist/property-panel.js +728 -0
  140. package/dist/property-panel.js.map +1 -0
  141. package/dist/reset-to-content-button.d.ts +10 -0
  142. package/dist/reset-to-content-button.d.ts.map +1 -0
  143. package/dist/reset-to-content-button.js +62 -0
  144. package/dist/reset-to-content-button.js.map +1 -0
  145. package/dist/segmented-control.d.ts +23 -0
  146. package/dist/segmented-control.d.ts.map +1 -0
  147. package/dist/segmented-control.js +5 -0
  148. package/dist/segmented-control.js.map +1 -0
  149. package/dist/selection-floating-panel.d.ts +56 -0
  150. package/dist/selection-floating-panel.d.ts.map +1 -0
  151. package/dist/selection-floating-panel.js +251 -0
  152. package/dist/selection-floating-panel.js.map +1 -0
  153. package/dist/sidebar.d.ts +31 -0
  154. package/dist/sidebar.d.ts.map +1 -0
  155. package/dist/sidebar.js +66 -0
  156. package/dist/sidebar.js.map +1 -0
  157. package/dist/slider.d.ts +20 -0
  158. package/dist/slider.d.ts.map +1 -0
  159. package/dist/slider.js +9 -0
  160. package/dist/slider.js.map +1 -0
  161. package/dist/text-editor-overlay.d.ts +16 -0
  162. package/dist/text-editor-overlay.d.ts.map +1 -0
  163. package/dist/text-editor-overlay.js +112 -0
  164. package/dist/text-editor-overlay.js.map +1 -0
  165. package/dist/toast.d.ts +34 -0
  166. package/dist/toast.d.ts.map +1 -0
  167. package/dist/toast.js +89 -0
  168. package/dist/toast.js.map +1 -0
  169. package/dist/toolbar.d.ts +149 -0
  170. package/dist/toolbar.d.ts.map +1 -0
  171. package/dist/toolbar.js +282 -0
  172. package/dist/toolbar.js.map +1 -0
  173. package/dist/tooltip.d.ts +21 -0
  174. package/dist/tooltip.d.ts.map +1 -0
  175. package/dist/tooltip.js +217 -0
  176. package/dist/tooltip.js.map +1 -0
  177. package/dist/ui-layer.d.ts +22 -0
  178. package/dist/ui-layer.d.ts.map +1 -0
  179. package/dist/ui-layer.js +3 -0
  180. package/dist/ui-layer.js.map +1 -0
  181. package/dist/versioning.d.ts +32 -0
  182. package/dist/versioning.d.ts.map +1 -0
  183. package/dist/versioning.js +206 -0
  184. package/dist/versioning.js.map +1 -0
  185. package/package.json +81 -0
  186. package/src/styles.css +1502 -0
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState } from "react";
3
+ import { mergeBranchHeads, resolveConflict, } from "@oh-just-another/versioning";
4
+ import { Modal } from "./modal.js";
5
+ export const MergeDialog = ({ store, sourceVersionId, targetVersionId, onApply, onCancel, style, }) => {
6
+ const report = useMemo(() => mergeBranchHeads(store, sourceVersionId, targetVersionId), [store, sourceVersionId, targetVersionId]);
7
+ const [picks, setPicks] = useState(new Map());
8
+ const pickFor = (c) => picks.get(conflictKey(c)) ?? defaultPick(c);
9
+ const setPick = (c, pick) => {
10
+ const next = new Map(picks);
11
+ next.set(conflictKey(c), pick);
12
+ setPicks(next);
13
+ };
14
+ const onApplyClick = () => {
15
+ let merged = report.mergedScene;
16
+ for (const c of report.conflicts) {
17
+ const pick = pickFor(c);
18
+ if (pick === "both")
19
+ continue; // host handles duplication
20
+ merged = resolveConflict(merged, c, pick);
21
+ }
22
+ onApply(merged);
23
+ };
24
+ return (_jsxs(Modal, { open: true, onClose: onCancel, title: "Merge branches", style: {
25
+ width: 480,
26
+ maxHeight: "80vh",
27
+ display: "flex",
28
+ flexDirection: "column",
29
+ ...style,
30
+ }, children: [_jsxs("header", { style: { padding: 12, borderBottom: "1px solid var(--border, #2a2a2a)" }, children: [_jsx("h2", { style: { margin: 0, fontSize: 14 }, children: "Merge branches" }), _jsxs("p", { style: { margin: "4px 0 0", fontSize: 11, opacity: 0.7 }, children: ["Auto-applied ", report.applied.length, " change", report.applied.length === 1 ? "" : "s", ".", " ", report.conflicts.length, " conflict", report.conflicts.length === 1 ? "" : "s", " need resolution."] })] }), _jsx("div", { style: { flex: 1, overflowY: "auto", padding: 12 }, children: report.conflicts.length === 0 ? (_jsx("p", { style: { margin: 0, opacity: 0.7 }, children: "No conflicts \u2014 ready to apply." })) : (report.conflicts.map((c) => (_jsx(ConflictRow, { conflict: c, pick: pickFor(c), onPick: (p) => { setPick(c, p); } }, conflictKey(c))))) }), _jsxs("footer", { style: {
31
+ display: "flex",
32
+ gap: 8,
33
+ justifyContent: "flex-end",
34
+ padding: 12,
35
+ borderTop: "1px solid var(--border, #2a2a2a)",
36
+ }, children: [_jsx("button", { type: "button", onClick: onCancel, children: "Cancel" }), _jsx("button", { type: "button", onClick: onApplyClick, children: "Apply" })] })] }));
37
+ };
38
+ const ConflictRow = ({ conflict, pick, onPick, }) => (_jsxs("div", { style: {
39
+ marginBottom: 12,
40
+ padding: 8,
41
+ border: "1px solid var(--border, #2a2a2a)",
42
+ borderRadius: 4,
43
+ }, children: [_jsxs("div", { style: { fontSize: 11, opacity: 0.7, marginBottom: 4 }, children: [conflict.kind, " \u2022 ", String(conflict.id)] }), _jsx("div", { style: { display: "flex", gap: 8 }, children: ["source", "target", "both"].map((side) => (_jsxs("label", { style: { display: "flex", alignItems: "center", gap: 4, fontSize: 12 }, children: [_jsx("input", { type: "radio", checked: pick === side, onChange: () => { onPick(side); }, name: `pick-${String(conflict.id)}` }), side] }, side))) })] }));
44
+ const conflictKey = (c) => `${c.kind}:${String(c.id)}`;
45
+ const defaultPick = (c) => c.source !== null ? "source" : c.target !== null ? "target" : "source";
46
+ //# sourceMappingURL=merge-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-dialog.js","sourceRoot":"","sources":["../src/merge-dialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAsB,MAAM,OAAO,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,eAAe,GAMhB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAqBnC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAC1B,KAAK,EACL,eAAe,EACf,eAAe,EACf,OAAO,EACP,QAAQ,EACR,KAAK,GACY,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,eAAe,CAAC,EAC/D,CAAC,KAAK,EAAE,eAAe,EAAE,eAAe,CAAC,CAC1C,CAAC;IACF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAA0C,IAAI,GAAG,EAAE,CAAC,CAAC;IAEvF,MAAM,OAAO,GAAG,CAAC,CAAgB,EAAsB,EAAE,CACvD,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;IAE9C,MAAM,OAAO,GAAG,CAAC,CAAgB,EAAE,IAAwB,EAAQ,EAAE;QACnE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,GAAS,EAAE;QAC9B,IAAI,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,IAAI,KAAK,MAAM;gBAAE,SAAS,CAAC,2BAA2B;YAC1D,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,KAAK,IACJ,IAAI,QACJ,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAC,gBAAgB,EACtB,KAAK,EAAE;YACL,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,MAAM;YACjB,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,QAAQ;YACvB,GAAG,KAAK;SACT,aAED,kBAAQ,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,kCAAkC,EAAE,aAC9E,aAAI,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,+BAAqB,EAC3D,aAAG,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,8BAC3C,MAAM,CAAC,OAAO,CAAC,MAAM,aAAS,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAG,GAAG,EACvF,MAAM,CAAC,SAAS,CAAC,MAAM,eAAW,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,yBAEzE,IACG,EACT,cAAK,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,YACpD,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC/B,YAAG,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,oDAAoC,CAC1E,CAAC,CAAC,CAAC,CACF,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAC1B,KAAC,WAAW,IAEV,QAAQ,EAAE,CAAC,EACX,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAH5B,WAAW,CAAC,CAAC,CAAC,CAInB,CACH,CAAC,CACH,GACG,EACN,kBACE,KAAK,EAAE;oBACL,OAAO,EAAE,MAAM;oBACf,GAAG,EAAE,CAAC;oBACN,cAAc,EAAE,UAAU;oBAC1B,OAAO,EAAE,EAAE;oBACX,SAAS,EAAE,kCAAkC;iBAC9C,aAED,iBAAQ,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,QAAQ,uBAE9B,EACT,iBAAQ,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,YAAY,sBAElC,IACF,IACH,CACT,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,EACnB,QAAQ,EACR,IAAI,EACJ,MAAM,GAKP,EAAE,EAAE,CAAC,CACJ,eACE,KAAK,EAAE;QACL,YAAY,EAAE,EAAE;QAChB,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,kCAAkC;QAC1C,YAAY,EAAE,CAAC;KAChB,aAED,eAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,EAAE,aACxD,QAAQ,CAAC,IAAI,cAAK,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAClC,EACN,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,YACnC,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACrD,iBAEE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,aAEtE,gBACE,IAAI,EAAC,OAAO,EACZ,OAAO,EAAE,IAAI,KAAK,IAAI,EACtB,QAAQ,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EACjC,IAAI,EAAE,QAAQ,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,GACnC,EACD,IAAI,KATA,IAAI,CAUH,CACT,CAAC,GACE,IACF,CACP,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,CAAgB,EAAU,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAE9E,MAAM,WAAW,GAAG,CAAC,CAAgB,EAAsB,EAAE,CAC3D,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type CSSProperties, type ReactNode } from "react";
2
+ /**
3
+ * Base modal / dialog primitive. Renders a backdrop plus a
4
+ * focus-trapped centered box; closes on Esc and click-outside (the
5
+ * latter optional via `dismissOnBackdrop=false`).
6
+ */
7
+ export interface ModalProps {
8
+ readonly open: boolean;
9
+ readonly onClose: () => void;
10
+ /** Accessible label for the dialog. Defaults to "Dialog". */
11
+ readonly title?: string;
12
+ readonly children: ReactNode;
13
+ /** Click on the backdrop dismisses the modal. Default `true`. */
14
+ readonly dismissOnBackdrop?: boolean;
15
+ readonly className?: string;
16
+ readonly style?: CSSProperties;
17
+ }
18
+ export declare const Modal: ({ open, onClose, title, children, dismissOnBackdrop, className, style, }: ModalProps) => import("react/jsx-runtime").JSX.Element | null;
19
+ //# sourceMappingURL=modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../src/modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,iEAAiE;IACjE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,eAAO,MAAM,KAAK,GAAI,0EAQnB,UAAU,mDAqGZ,CAAC"}
package/dist/modal.js ADDED
@@ -0,0 +1,87 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef, } from "react";
3
+ export const Modal = ({ open, onClose, title = "Dialog", children, dismissOnBackdrop = true, className, style, }) => {
4
+ const dialogRef = useRef(null);
5
+ const previouslyFocusedRef = useRef(null);
6
+ // Esc + restore focus on close.
7
+ useEffect(() => {
8
+ if (!open)
9
+ return undefined;
10
+ previouslyFocusedRef.current = document.activeElement;
11
+ const onKey = (ev) => {
12
+ if (ev.key === "Escape") {
13
+ ev.preventDefault();
14
+ onClose();
15
+ }
16
+ };
17
+ window.addEventListener("keydown", onKey);
18
+ // Focus the first focusable inside the dialog (or the box itself).
19
+ const ref = dialogRef.current;
20
+ if (ref) {
21
+ const focusable = ref.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
22
+ (focusable ?? ref).focus();
23
+ }
24
+ return () => {
25
+ window.removeEventListener("keydown", onKey);
26
+ previouslyFocusedRef.current?.focus();
27
+ };
28
+ }, [open, onClose]);
29
+ // Tab cycle stays inside dialog.
30
+ useEffect(() => {
31
+ if (!open)
32
+ return undefined;
33
+ const onKey = (ev) => {
34
+ if (ev.key !== "Tab")
35
+ return;
36
+ const ref = dialogRef.current;
37
+ if (!ref)
38
+ return;
39
+ const focusables = ref.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])');
40
+ if (focusables.length === 0)
41
+ return;
42
+ const first = focusables[0];
43
+ const last = focusables[focusables.length - 1];
44
+ if (first === undefined || last === undefined)
45
+ return;
46
+ const active = document.activeElement;
47
+ if (ev.shiftKey && active === first) {
48
+ ev.preventDefault();
49
+ last.focus();
50
+ }
51
+ else if (!ev.shiftKey && active === last) {
52
+ ev.preventDefault();
53
+ first.focus();
54
+ }
55
+ };
56
+ window.addEventListener("keydown", onKey, true);
57
+ return () => { window.removeEventListener("keydown", onKey, true); };
58
+ }, [open]);
59
+ if (!open)
60
+ return null;
61
+ const overlay = {
62
+ position: "fixed",
63
+ inset: 0,
64
+ background: "rgba(0, 0, 0, 0.55)",
65
+ display: "flex",
66
+ alignItems: "center",
67
+ justifyContent: "center",
68
+ zIndex: 1000,
69
+ };
70
+ const box = {
71
+ background: "var(--panel, #1a1a1a)",
72
+ color: "var(--text, #ddd)",
73
+ border: "1px solid var(--border, #2a2a2a)",
74
+ borderRadius: 8,
75
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.45)",
76
+ maxWidth: "calc(100vw - 64px)",
77
+ maxHeight: "calc(100vh - 64px)",
78
+ overflow: "auto",
79
+ outline: "none",
80
+ ...style,
81
+ };
82
+ return (_jsx("div", { role: "dialog", "aria-modal": "true", "aria-label": title, style: overlay, onClick: (ev) => {
83
+ if (dismissOnBackdrop && ev.target === ev.currentTarget)
84
+ onClose();
85
+ }, children: _jsx("div", { ref: dialogRef, tabIndex: -1, className: className, style: box, onClick: (ev) => { ev.stopPropagation(); }, children: children }) }));
86
+ };
87
+ //# sourceMappingURL=modal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modal.js","sourceRoot":"","sources":["../src/modal.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { type CSSProperties, type DragEvent } from "react";
2
+ import { type Category, type Template, type TemplateRegistry } from "@oh-just-another/templates";
3
+ /**
4
+ * Draggable shape palette. Defaults to the global `defaultRegistry`; pass a
5
+ * custom one if your host needs isolated registries (e.g. plugin sandbox).
6
+ *
7
+ * Templates are grouped into collapsible sections by `Category` — no tab
8
+ * switching, so the user sees everything at once and scrolls vertically.
9
+ * Each section header doubles as a collapse toggle.
10
+ *
11
+ * Drop semantics: an HTML5 drag is started with a `templateId` payload; the
12
+ * canvas (or any other drop-target) reads it and calls
13
+ * `editor.addElement(template.factory(...))`. Most hosts wire that in
14
+ * `<DiagramCanvas>` itself.
15
+ */
16
+ export interface PaletteProps {
17
+ readonly registry?: TemplateRegistry;
18
+ /** Order of category sections; only those present in the registry render. */
19
+ readonly categories?: readonly Category[];
20
+ /** Categories that start collapsed. Defaults to none. */
21
+ readonly collapsedByDefault?: readonly Category[];
22
+ /**
23
+ * Live search query — when set, the palette flattens (no category
24
+ * sections) and shows every template whose `name` / `category` /
25
+ * `tags` matches. Owned by the host so the input lives in the
26
+ * panel header above the palette body.
27
+ */
28
+ readonly searchQuery?: string;
29
+ /**
30
+ * Item layout: `"grid"` (default) packs 2-up square tiles; `"list"`
31
+ * is a compact single-column list of icon + name rows. Grouping by
32
+ * category is identical in both.
33
+ */
34
+ readonly layout?: "grid" | "list";
35
+ readonly style?: CSSProperties;
36
+ readonly className?: string;
37
+ }
38
+ export declare const Palette: ({ registry, categories, collapsedByDefault, searchQuery, layout, style, className, }: PaletteProps) => import("react/jsx-runtime").JSX.Element;
39
+ /** Currently-dragged palette template, or `null` when nothing is in flight. */
40
+ export declare const getActivePaletteDrag: () => Template | null;
41
+ /** Subscribe to active-drag changes. Returns unsubscribe. */
42
+ export declare const subscribePaletteDrag: (fn: () => void) => (() => void);
43
+ /** Hook variant of `subscribePaletteDrag` — returns the current drag template. */
44
+ export declare const usePaletteDrag: () => Template | null;
45
+ /**
46
+ * Drag-to-place handlers for a canvas element. Wires the full preview
47
+ * UX: as soon as the cursor enters the canvas with a palette drag in
48
+ * flight, the template's default shape appears centred under the
49
+ * cursor; dragover updates the position; drop commits as a single
50
+ * history entry; dragleave / Escape cancels (no history).
51
+ *
52
+ * Returns props that should spread onto the canvas wrapper element:
53
+ *
54
+ * ```tsx
55
+ * const placement = usePalettePlacement();
56
+ * <section {...placement}>...</section>
57
+ * ```
58
+ */
59
+ export declare const usePalettePlacement: () => {
60
+ onDragEnter: (ev: DragEvent<HTMLElement>) => void;
61
+ onDragOver: (ev: DragEvent<HTMLElement>) => void;
62
+ onDragLeave: (ev: DragEvent<HTMLElement>) => void;
63
+ onDrop: (ev: DragEvent<HTMLElement>) => void;
64
+ };
65
+ /**
66
+ * Convenience wrapper to drop a palette item onto a host element. Hosts that
67
+ * are not using `<DiagramCanvas>` can wire this themselves; the bundled
68
+ * canvas component installs an equivalent handler automatically.
69
+ *
70
+ * Drops only — no live preview (use `usePalettePlacement` for that).
71
+ */
72
+ export declare const usePaletteDropHandler: () => (ev: DragEvent<HTMLElement>) => void;
73
+ //# sourceMappingURL=palette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../src/palette.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwC,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIjG,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAC;AAKpC;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IACrC,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC1C,yDAAyD;IACzD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IAClD;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAID,eAAO,MAAM,OAAO,GAAI,sFAQrB,YAAY,4CAqEd,CAAC;AAwDF,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,QAAO,QAAQ,GAAG,IAAkB,CAAC;AAEtE,6DAA6D;AAC7D,eAAO,MAAM,oBAAoB,GAAI,IAAI,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAKhE,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,cAAc,QAAO,QAAQ,GAAG,IAU5C,CAAC;AA4FF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB;sBAgEV,SAAS,CAAC,WAAW,CAAC,KAAG,IAAI;qBAa9B,SAAS,CAAC,WAAW,CAAC,KAAG,IAAI;sBAe5B,SAAS,CAAC,WAAW,CAAC,KAAG,IAAI;iBASlC,SAAS,CAAC,WAAW,CAAC,KAAG,IAAI;CAiC7C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,SAExB,IAAI,SAAS,CAAC,WAAW,CAAC,SAyBnC,CAAC"}
@@ -0,0 +1,330 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from "react";
3
+ import { ChevronDown, ChevronRight } from "lucide-react";
4
+ import { DEFAULT_LAYER_ID, orderForTop } from "@oh-just-another/scene";
5
+ import { elementId } from "@oh-just-another/types";
6
+ import { defaultRegistry, matchesTemplateSearch, } from "@oh-just-another/templates";
7
+ import { walkDataTransfer } from "@oh-just-another/state";
8
+ import { useDiagramOptional } from "./hooks.js";
9
+ import { PALETTE_ITEM_SIZE } from "./constants.js";
10
+ const DEFAULT_CATEGORIES = ["basic", "layout", "flowchart", "custom", "rich"];
11
+ export const Palette = ({ registry = defaultRegistry, categories = DEFAULT_CATEGORIES, collapsedByDefault = [], searchQuery, layout = "grid", style, className, }) => {
12
+ const itemsClass = layout === "list" ? "du-palette-list" : "du-palette-grid";
13
+ const present = useMemo(() => new Set(registry.categories()), [registry]);
14
+ const visibleCategories = useMemo(() => categories.filter((c) => present.has(c)), [categories, present]);
15
+ const sections = useMemo(() => visibleCategories.map((cat) => ({ category: cat, items: registry.byCategory(cat) })), [registry, visibleCategories]);
16
+ const [collapsed, setCollapsed] = useState(() => new Set(collapsedByDefault));
17
+ const toggle = (cat) => {
18
+ setCollapsed((prev) => {
19
+ const next = new Set(prev);
20
+ if (next.has(cat))
21
+ next.delete(cat);
22
+ else
23
+ next.add(cat);
24
+ return next;
25
+ });
26
+ };
27
+ // Flat-search mode: when a query is active, dissolve category
28
+ // sections and show every match in one grid. Empty query → normal
29
+ // sectioned view.
30
+ const trimmedQuery = searchQuery?.trim() ?? "";
31
+ const flatMatches = useMemo(() => {
32
+ if (!trimmedQuery)
33
+ return [];
34
+ const out = [];
35
+ for (const { items } of sections) {
36
+ for (const t of items) {
37
+ if (matchesTemplateSearch(t, trimmedQuery))
38
+ out.push(t);
39
+ }
40
+ }
41
+ return out;
42
+ }, [sections, trimmedQuery]);
43
+ return (_jsx("aside", { className: `du-palette ${className ?? ""}`.trim(), style: style, children: _jsx("div", { className: "du-palette-body", children: trimmedQuery ? (flatMatches.length === 0 ? (_jsxs("div", { className: "du-palette-empty", children: ["No templates match \u201C", trimmedQuery, "\u201D"] })) : (_jsx("div", { className: itemsClass, children: flatMatches.map((template) => (_jsx(PaletteItem, { template: template }, template.id))) }))) : (sections.map(({ category, items }) => (_jsx(CategorySection, { category: category, items: items, itemsClass: itemsClass, collapsed: collapsed.has(category), onToggle: () => {
44
+ toggle(category);
45
+ } }, category)))) }) }));
46
+ };
47
+ const CategorySection = ({ category, items, itemsClass, collapsed, onToggle, }) => {
48
+ if (items.length === 0)
49
+ return null;
50
+ return (_jsxs("section", { className: "du-palette-section", children: [_jsxs("button", { type: "button", onClick: onToggle, "aria-expanded": !collapsed, className: "du-palette-category", children: [_jsx("span", { children: category }), _jsx("span", { className: "du-palette-category-caret", "aria-hidden": true, children: collapsed ? (_jsx(ChevronRight, { size: 12, strokeWidth: 1.75 })) : (_jsx(ChevronDown, { size: 12, strokeWidth: 1.75 })) })] }), collapsed ? null : (_jsx("div", { className: itemsClass, children: items.map((template) => (_jsx(PaletteItem, { template: template }, template.id))) }))] }));
51
+ };
52
+ // Module-level state — the canvas needs to know which template is
53
+ // being dragged so it can spin up a live placement preview. HTML5 DnD
54
+ // hides dataTransfer.getData() during dragover (security), so we use a
55
+ // pub/sub for the active drag instead.
56
+ let activeDrag = null;
57
+ const dragListeners = new Set();
58
+ const setActiveDrag = (tmpl) => {
59
+ if (activeDrag === tmpl)
60
+ return;
61
+ activeDrag = tmpl;
62
+ for (const fn of dragListeners)
63
+ fn();
64
+ };
65
+ /** Currently-dragged palette template, or `null` when nothing is in flight. */
66
+ export const getActivePaletteDrag = () => activeDrag;
67
+ /** Subscribe to active-drag changes. Returns unsubscribe. */
68
+ export const subscribePaletteDrag = (fn) => {
69
+ dragListeners.add(fn);
70
+ return () => {
71
+ dragListeners.delete(fn);
72
+ };
73
+ };
74
+ /** Hook variant of `subscribePaletteDrag` — returns the current drag template. */
75
+ export const usePaletteDrag = () => {
76
+ const [tmpl, setTmpl] = useState(activeDrag);
77
+ useEffect(() => subscribePaletteDrag(() => {
78
+ setTmpl(activeDrag);
79
+ }), []);
80
+ return tmpl;
81
+ };
82
+ // Fake drag image so the browser doesn't paint its default ghost of
83
+ // the palette item — the actual shape rendered on canvas via
84
+ // `beginPlacement` is the only thing the user should see following
85
+ // the cursor.
86
+ //
87
+ // An in-DOM div with a single near-transparent pixel of content
88
+ // (background-color: rgba(0,0,0,0.01)) and a real width/height is
89
+ // accepted by browsers as a valid drag image while rendering
90
+ // effectively nothing.
91
+ let emptyDragImage = null;
92
+ const getEmptyDragImage = () => {
93
+ if (typeof document === "undefined")
94
+ return null;
95
+ if (emptyDragImage && document.body.contains(emptyDragImage))
96
+ return emptyDragImage;
97
+ const div = document.createElement("div");
98
+ div.setAttribute("aria-hidden", "true");
99
+ // Off-screen position keeps it out of layout. 1×1 size and a barely-
100
+ // visible background satisfy the browser's "non-trivial drag image"
101
+ // check without showing anything to the user.
102
+ div.style.cssText =
103
+ "position:fixed;top:-1000px;left:-1000px;width:1px;height:1px;background:rgba(0,0,0,0.01)";
104
+ document.body.appendChild(div);
105
+ emptyDragImage = div;
106
+ return div;
107
+ };
108
+ const PaletteItem = ({ template }) => {
109
+ const editor = useDiagramOptional();
110
+ const onDragStart = (ev) => {
111
+ ev.dataTransfer.setData("application/x-template-id", template.id);
112
+ ev.dataTransfer.effectAllowed = "copy";
113
+ // Hide the browser's default ghost. The canvas renders the real
114
+ // shape via beginPlacement.
115
+ const ghost = getEmptyDragImage();
116
+ if (ghost)
117
+ ev.dataTransfer.setDragImage(ghost, 0, 0);
118
+ setActiveDrag(template);
119
+ };
120
+ const onDragEnd = () => {
121
+ setActiveDrag(null);
122
+ };
123
+ // Tap-to-place: HTML5 drag-and-drop doesn't fire on touch. On
124
+ // coarse-pointer devices a tap drops the template's default shape at
125
+ // the viewport centre (one undo step), then selects it for the user
126
+ // to move. Desktop keeps drag-to-position — the click is a no-op there.
127
+ const onClick = () => {
128
+ if (!editor)
129
+ return;
130
+ if (typeof window !== "undefined" && !window.matchMedia("(pointer: coarse)").matches)
131
+ return;
132
+ const host = editor.hostElement;
133
+ const rect = host.getBoundingClientRect();
134
+ const center = editor.screenToWorld({ x: rect.width / 2, y: rect.height / 2 });
135
+ const id = elementId(`shape-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`);
136
+ const shape = template.factory({
137
+ id,
138
+ layerId: DEFAULT_LAYER_ID,
139
+ position: center,
140
+ order: orderForTop([...editor.scene.elements.values()]
141
+ .filter((s) => s.layerId === DEFAULT_LAYER_ID)
142
+ .map((s) => s.order)),
143
+ });
144
+ const placement = editor.beginPlacement(shape);
145
+ placement.update(center);
146
+ placement.commit();
147
+ };
148
+ return (_jsxs("div", { role: "button", draggable: true, title: template.name, onDragStart: onDragStart, onDragEnd: onDragEnd, onClick: onClick, className: "du-palette-item", children: [_jsx("span", { className: "du-palette-item-icon", style: { width: PALETTE_ITEM_SIZE, height: PALETTE_ITEM_SIZE },
149
+ // Icons are trusted SVG markup defined in the registry by template
150
+ // authors — same source of truth as the canvas renderer uses.
151
+ dangerouslySetInnerHTML: { __html: template.icon } }), _jsx("span", { className: "du-palette-item-label", children: template.name })] }));
152
+ };
153
+ /**
154
+ * Drag-to-place handlers for a canvas element. Wires the full preview
155
+ * UX: as soon as the cursor enters the canvas with a palette drag in
156
+ * flight, the template's default shape appears centred under the
157
+ * cursor; dragover updates the position; drop commits as a single
158
+ * history entry; dragleave / Escape cancels (no history).
159
+ *
160
+ * Returns props that should spread onto the canvas wrapper element:
161
+ *
162
+ * ```tsx
163
+ * const placement = usePalettePlacement();
164
+ * <section {...placement}>...</section>
165
+ * ```
166
+ */
167
+ export const usePalettePlacement = () => {
168
+ const editor = useDiagramOptional();
169
+ const placementRef = useRef(null);
170
+ // Escape cancels — only listens when a placement is active.
171
+ useEffect(() => {
172
+ const onKey = (ev) => {
173
+ if (ev.key !== "Escape" || !placementRef.current)
174
+ return;
175
+ placementRef.current.cancel();
176
+ placementRef.current = null;
177
+ };
178
+ window.addEventListener("keydown", onKey);
179
+ return () => {
180
+ window.removeEventListener("keydown", onKey);
181
+ };
182
+ }, []);
183
+ // If the drag ends outside any canvas — clean up.
184
+ useEffect(() => subscribePaletteDrag(() => {
185
+ if (activeDrag === null && placementRef.current) {
186
+ placementRef.current.cancel();
187
+ placementRef.current = null;
188
+ }
189
+ }), []);
190
+ const ensurePlacement = (ev) => {
191
+ if (placementRef.current || !editor || !activeDrag)
192
+ return false;
193
+ const template = activeDrag;
194
+ const rect = ev.currentTarget.getBoundingClientRect();
195
+ const screenPoint = { x: ev.clientX - rect.left, y: ev.clientY - rect.top };
196
+ const worldPoint = editor.screenToWorld(screenPoint);
197
+ const id = elementId(`shape-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`);
198
+ const shape = template.factory({
199
+ id,
200
+ layerId: DEFAULT_LAYER_ID,
201
+ position: worldPoint, // temporary; placement.update will recenter
202
+ order: orderForTop([...editor.scene.elements.values()]
203
+ .filter((s) => s.layerId === DEFAULT_LAYER_ID)
204
+ .map((s) => s.order)),
205
+ });
206
+ placementRef.current = editor.beginPlacement(shape);
207
+ placementRef.current.update(worldPoint);
208
+ return true;
209
+ };
210
+ const cursorWorld = (ev) => {
211
+ if (!editor)
212
+ return null;
213
+ const rect = ev.currentTarget.getBoundingClientRect();
214
+ return editor.screenToWorld({ x: ev.clientX - rect.left, y: ev.clientY - rect.top });
215
+ };
216
+ return {
217
+ onDragEnter: (ev) => {
218
+ const types = ev.dataTransfer.types;
219
+ const isTemplate = types.includes("application/x-template-id");
220
+ const isFile = types.includes("Files");
221
+ // Accept both palette template drags and OS file drops. Without
222
+ // preventDefault'ing for file drops the browser falls back to its
223
+ // default behaviour (open the file in the current tab, losing the scene).
224
+ if (!isTemplate && !isFile)
225
+ return;
226
+ ev.preventDefault();
227
+ // Drag-preview overlay only applies to template drags — files
228
+ // get inserted at drop time, not previewed.
229
+ if (isTemplate)
230
+ ensurePlacement(ev);
231
+ },
232
+ onDragOver: (ev) => {
233
+ const types = ev.dataTransfer.types;
234
+ const isTemplate = types.includes("application/x-template-id");
235
+ const isFile = types.includes("Files");
236
+ if (!isTemplate && !isFile)
237
+ return;
238
+ ev.preventDefault();
239
+ ev.dataTransfer.dropEffect = "copy";
240
+ if (isTemplate) {
241
+ if (!placementRef.current) {
242
+ ensurePlacement(ev);
243
+ }
244
+ const world = cursorWorld(ev);
245
+ if (world && placementRef.current)
246
+ placementRef.current.update(world);
247
+ }
248
+ },
249
+ onDragLeave: (ev) => {
250
+ // dragleave fires for every child element too — only act when the
251
+ // pointer truly left the current target.
252
+ if (ev.currentTarget.contains(ev.relatedTarget))
253
+ return;
254
+ if (placementRef.current) {
255
+ placementRef.current.cancel();
256
+ placementRef.current = null;
257
+ }
258
+ },
259
+ onDrop: (ev) => {
260
+ ev.preventDefault();
261
+ // Palette-template drop has priority — that's the active drag
262
+ // started by `<Palette>` items.
263
+ if (placementRef.current) {
264
+ const world = cursorWorld(ev);
265
+ if (world)
266
+ placementRef.current.update(world);
267
+ placementRef.current.commit();
268
+ placementRef.current = null;
269
+ return;
270
+ }
271
+ // Otherwise treat it as a file drop from the OS / browser.
272
+ const dt = ev.dataTransfer;
273
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- DOM DataTransfer is typed non-null but is null outside drag contexts
274
+ if (!dt)
275
+ return;
276
+ const world = cursorWorld(ev);
277
+ const target = world ?? { x: 0, y: 0 };
278
+ if (!editor)
279
+ return;
280
+ // Walk recursively — descends folders via `webkitGetAsEntry`
281
+ // when available, falls back to the flat `files` list otherwise.
282
+ // Each yielded leaf file is dispatched independently; one bad
283
+ // sub-folder doesn't stop the rest.
284
+ void (async () => {
285
+ for await (const file of walkDataTransfer(dt, {
286
+ onError: (path, err) => {
287
+ console.warn(`[file-drop] failed at ${path}:`, err);
288
+ },
289
+ })) {
290
+ void editor.dispatchFileDrop(file, target);
291
+ }
292
+ })();
293
+ },
294
+ };
295
+ };
296
+ /**
297
+ * Convenience wrapper to drop a palette item onto a host element. Hosts that
298
+ * are not using `<DiagramCanvas>` can wire this themselves; the bundled
299
+ * canvas component installs an equivalent handler automatically.
300
+ *
301
+ * Drops only — no live preview (use `usePalettePlacement` for that).
302
+ */
303
+ export const usePaletteDropHandler = () => {
304
+ const editor = useDiagramOptional();
305
+ return (ev) => {
306
+ ev.preventDefault();
307
+ if (!editor)
308
+ return; // surface not mounted yet
309
+ const templateId = ev.dataTransfer.getData("application/x-template-id");
310
+ if (!templateId)
311
+ return;
312
+ const template = defaultRegistry.get(templateId);
313
+ if (!template)
314
+ return;
315
+ const rect = ev.currentTarget.getBoundingClientRect();
316
+ const screenPoint = { x: ev.clientX - rect.left, y: ev.clientY - rect.top };
317
+ const worldPoint = editor.screenToWorld(screenPoint);
318
+ const id = elementId(`shape-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`);
319
+ const shape = template.factory({
320
+ id,
321
+ layerId: DEFAULT_LAYER_ID,
322
+ position: worldPoint,
323
+ order: orderForTop([...editor.scene.elements.values()]
324
+ .filter((s) => s.layerId === DEFAULT_LAYER_ID)
325
+ .map((s) => s.order)),
326
+ });
327
+ editor.addElement(shape);
328
+ };
329
+ };
330
+ //# sourceMappingURL=palette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.js","sourceRoot":"","sources":["../src/palette.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { type Placement } from "@floating-ui/dom";
2
+ import { type ReactElement, type ReactNode } from "react";
3
+ /**
4
+ * Floating popover primitive. Wraps a trigger element and renders its
5
+ * children into a portal whose position is computed via
6
+ * `@floating-ui/dom` (offset + flip + shift). Closed by default;
7
+ * clicking the trigger toggles; clicking outside or pressing Esc
8
+ * closes.
9
+ *
10
+ * Used inside `<SelectionFloatingPanel>` for sub-controls that don't
11
+ * fit inline (color picker, corner radius slider, opacity slider).
12
+ * Uses the DOM-only `@floating-ui/dom` API plus a small outside-click
13
+ * hook rather than `@floating-ui/react`.
14
+ */
15
+ export interface PopoverProps {
16
+ /** Element that opens the popover when clicked. Must accept a ref. */
17
+ readonly trigger: ReactElement;
18
+ /** Content rendered inside the popover. */
19
+ readonly children: ReactNode;
20
+ /** Preferred placement; flip middleware will try fallbacks. Default `"bottom-start"`. */
21
+ readonly placement?: Placement;
22
+ /** Distance in px between trigger and popover. Default `6`. */
23
+ readonly offset?: number;
24
+ /** Optional className for the floating panel chrome. */
25
+ readonly className?: string;
26
+ /** Controlled-open state. If omitted, popover manages its own state. */
27
+ readonly open?: boolean;
28
+ readonly onOpenChange?: (open: boolean) => void;
29
+ /** ARIA label for the popover region. */
30
+ readonly ariaLabel?: string;
31
+ }
32
+ export declare const Popover: ({ trigger, children, placement, offset: gap, className, open: openProp, onOpenChange, ariaLabel, }: PopoverProps) => import("react/jsx-runtime").JSX.Element;
33
+ //# sourceMappingURL=popover.d.ts.map