stickyflow 0.3.0 → 0.5.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 (65) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +51 -5
  3. package/dist/binding/index.cjs +34 -0
  4. package/dist/binding/index.cjs.map +1 -0
  5. package/dist/binding/index.d.cts +11 -0
  6. package/dist/binding/index.d.ts +11 -0
  7. package/dist/binding/index.js +5 -0
  8. package/dist/binding/index.js.map +1 -0
  9. package/dist/{chunk-XEN5QIIJ.js → chunk-7VW2XKVB.js} +3 -3
  10. package/dist/{chunk-XEN5QIIJ.js.map → chunk-7VW2XKVB.js.map} +1 -1
  11. package/dist/chunk-BODZN3ZI.js +1182 -0
  12. package/dist/chunk-BODZN3ZI.js.map +1 -0
  13. package/dist/{chunk-CSXQD3ON.js → chunk-G7NRK5AG.js} +1128 -1081
  14. package/dist/chunk-G7NRK5AG.js.map +1 -0
  15. package/dist/{chunk-BYMIYXP5.js → chunk-IEHE6WVN.js} +197 -19
  16. package/dist/chunk-IEHE6WVN.js.map +1 -0
  17. package/dist/{chunk-HFOGKSNU.cjs → chunk-L3VJXZFD.cjs} +15 -15
  18. package/dist/{chunk-HFOGKSNU.cjs.map → chunk-L3VJXZFD.cjs.map} +1 -1
  19. package/dist/{chunk-65IVT4GK.js → chunk-LTGF5OHP.js} +1008 -631
  20. package/dist/chunk-LTGF5OHP.js.map +1 -0
  21. package/dist/chunk-TWDLOXRM.cjs +1189 -0
  22. package/dist/chunk-TWDLOXRM.cjs.map +1 -0
  23. package/dist/{chunk-UXDWH2JC.cjs → chunk-VK3T6O5Z.cjs} +1165 -1118
  24. package/dist/chunk-VK3T6O5Z.cjs.map +1 -0
  25. package/dist/{chunk-CXL254BT.cjs → chunk-XY2GZUHC.cjs} +204 -18
  26. package/dist/chunk-XY2GZUHC.cjs.map +1 -0
  27. package/dist/{chunk-DDCTNLLD.cjs → chunk-ZMLQIMJK.cjs} +1504 -1128
  28. package/dist/chunk-ZMLQIMJK.cjs.map +1 -0
  29. package/dist/index.cjs +53 -1013
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +22 -14
  32. package/dist/index.d.ts +22 -14
  33. package/dist/index.js +6 -993
  34. package/dist/index.js.map +1 -1
  35. package/dist/interaction/index.cjs +474 -305
  36. package/dist/interaction/index.cjs.map +1 -1
  37. package/dist/interaction/index.d.cts +11 -3
  38. package/dist/interaction/index.d.ts +11 -3
  39. package/dist/interaction/index.js +255 -87
  40. package/dist/interaction/index.js.map +1 -1
  41. package/dist/{render-C5X74hds.d.cts → render-CgX_y15a.d.cts} +193 -116
  42. package/dist/{render-C5X74hds.d.ts → render-CgX_y15a.d.ts} +193 -116
  43. package/dist/runtime-DnUxca3Y.d.ts +10 -0
  44. package/dist/runtime-reWgr7MP.d.cts +10 -0
  45. package/dist/{runtimeTypes-D8hPZ62T.d.ts → runtimeTypes-CEBGueYM.d.ts} +10 -5
  46. package/dist/{runtimeTypes-yTSAvtCn.d.cts → runtimeTypes-D60w6nyF.d.cts} +10 -5
  47. package/dist/stickyflow-diagram.global.js +35 -35
  48. package/dist/stickyflow-diagram.global.js.map +1 -1
  49. package/dist/{types-BDKDf4zr.d.cts → types-DYLC_lsk.d.ts} +3 -2
  50. package/dist/{types-CdgGdtoD.d.ts → types-DvhMpqrL.d.cts} +3 -2
  51. package/dist/viewer/index.cjs +9 -9
  52. package/dist/viewer/index.d.cts +4 -4
  53. package/dist/viewer/index.d.ts +4 -4
  54. package/dist/viewer/index.js +4 -4
  55. package/dist/web-component/index.cjs +6 -6
  56. package/dist/web-component/index.d.cts +2 -2
  57. package/dist/web-component/index.d.ts +2 -2
  58. package/dist/web-component/index.js +4 -4
  59. package/package.json +6 -1
  60. package/dist/chunk-65IVT4GK.js.map +0 -1
  61. package/dist/chunk-BYMIYXP5.js.map +0 -1
  62. package/dist/chunk-CSXQD3ON.js.map +0 -1
  63. package/dist/chunk-CXL254BT.cjs.map +0 -1
  64. package/dist/chunk-DDCTNLLD.cjs.map +0 -1
  65. package/dist/chunk-UXDWH2JC.cjs.map +0 -1
@@ -1,5 +1,5 @@
1
- import { O as OwnerRef, E as Emitter$1, V as Viewer, U as Unsubscribe } from '../types-BDKDf4zr.cjs';
2
- import { E as Side, I as IsometricFace } from '../render-C5X74hds.cjs';
1
+ import { O as OwnerRef, E as Emitter$1, V as Viewer, U as Unsubscribe } from '../types-DvhMpqrL.cjs';
2
+ import { Y as Side, I as IsometricFace } from '../render-CgX_y15a.cjs';
3
3
 
4
4
  interface TextChangeEvent {
5
5
  owner: OwnerRef;
@@ -226,6 +226,14 @@ declare function applyPathPointChange(sfl: string, event: PathPointChangeEvent):
226
226
 
227
227
  declare function applyPropertyChange(sfl: string, event: PropertyChangeEvent): string;
228
228
 
229
+ interface QuickDuplicateOptions {
230
+ shapeId: string;
231
+ linkId: string;
232
+ gap?: number;
233
+ }
234
+
235
+ declare function applyQuickDuplicateChange(sfl: string, event: QuickDuplicateEvent, options: QuickDuplicateOptions): string;
236
+
229
237
  declare function applyResizeChange(sfl: string, event: ResizeChangeEvent): string;
230
238
 
231
239
  declare function applySankeyNodeMoveChange(sfl: string, event: SankeyNodeMoveEvent): string;
@@ -271,4 +279,4 @@ interface EditingOptions {
271
279
  }
272
280
  declare function bindEditing(viewer: Viewer, options?: EditingOptions): Interaction;
273
281
 
274
- export { type ChartValueChangeEvent, type ColorEditHandle, type ColorPickerTheme, type ColorPickerThemeOption, type ColorPopoverHandle, type ColorPopoverOptions, type DeleteEvent, type EditableRules, type EditingOptions, type InsertCanvasObjectOptions, type InsertConnectionOptions, type InsertLinkOptions, type InsertPathOptions, type Interaction, type InteractionEventMap, type InteractionEventName, type IsometricQuickDuplicateDirection, type LinkReconnectEvent, type LinkSegmentChangeEvent, type LinkToEvent, type MoveChangeEvent, type PathDrawCompleteEvent, type PathDrawOptions, type PathPoint, type PathPointChangeEvent, type PickerValue, type PropertyChangeEvent, type PropertyEditingHandle, type PropertyEditingOptions, type PropertyValue, type QuickDuplicateEvent, type RemoveCanvasObjectOptions, type ResizeChangeEvent, type SankeyNodeMoveEvent, type SankeyNodeRenameEvent, type TextChangeEvent, Unsubscribe, applyChartValueChange, applyLinkReconnectChange, applyLinkSegmentChange, applyMoveChange, applyPathPointChange, applyPropertyChange, applyResizeChange, applySankeyNodeMoveChange, applySankeyNodeRenameChange, applyTextChange, bindEditing, bindPropertyEditing, cssBackground, formatPickerValue, insertCanvasObject, insertConnection, insertLink, insertPath, openColorPopover, readGradientValue, removeCanvasObject, removeLink, resolveTheme, seedFrom };
282
+ export { type ChartValueChangeEvent, type ColorEditHandle, type ColorPickerTheme, type ColorPickerThemeOption, type ColorPopoverHandle, type ColorPopoverOptions, type DeleteEvent, type EditableRules, type EditingOptions, type InsertCanvasObjectOptions, type InsertConnectionOptions, type InsertLinkOptions, type InsertPathOptions, type Interaction, type InteractionEventMap, type InteractionEventName, type IsometricQuickDuplicateDirection, type LinkReconnectEvent, type LinkSegmentChangeEvent, type LinkToEvent, type MoveChangeEvent, type PathDrawCompleteEvent, type PathDrawOptions, type PathPoint, type PathPointChangeEvent, type PickerValue, type PropertyChangeEvent, type PropertyEditingHandle, type PropertyEditingOptions, type PropertyValue, type QuickDuplicateEvent, type QuickDuplicateOptions, type RemoveCanvasObjectOptions, type ResizeChangeEvent, type SankeyNodeMoveEvent, type SankeyNodeRenameEvent, type TextChangeEvent, Unsubscribe, applyChartValueChange, applyLinkReconnectChange, applyLinkSegmentChange, applyMoveChange, applyPathPointChange, applyPropertyChange, applyQuickDuplicateChange, applyResizeChange, applySankeyNodeMoveChange, applySankeyNodeRenameChange, applyTextChange, bindEditing, bindPropertyEditing, cssBackground, formatPickerValue, insertCanvasObject, insertConnection, insertLink, insertPath, openColorPopover, readGradientValue, removeCanvasObject, removeLink, resolveTheme, seedFrom };
@@ -1,5 +1,5 @@
1
- import { O as OwnerRef, E as Emitter$1, V as Viewer, U as Unsubscribe } from '../types-CdgGdtoD.js';
2
- import { E as Side, I as IsometricFace } from '../render-C5X74hds.js';
1
+ import { O as OwnerRef, E as Emitter$1, V as Viewer, U as Unsubscribe } from '../types-DYLC_lsk.js';
2
+ import { Y as Side, I as IsometricFace } from '../render-CgX_y15a.js';
3
3
 
4
4
  interface TextChangeEvent {
5
5
  owner: OwnerRef;
@@ -226,6 +226,14 @@ declare function applyPathPointChange(sfl: string, event: PathPointChangeEvent):
226
226
 
227
227
  declare function applyPropertyChange(sfl: string, event: PropertyChangeEvent): string;
228
228
 
229
+ interface QuickDuplicateOptions {
230
+ shapeId: string;
231
+ linkId: string;
232
+ gap?: number;
233
+ }
234
+
235
+ declare function applyQuickDuplicateChange(sfl: string, event: QuickDuplicateEvent, options: QuickDuplicateOptions): string;
236
+
229
237
  declare function applyResizeChange(sfl: string, event: ResizeChangeEvent): string;
230
238
 
231
239
  declare function applySankeyNodeMoveChange(sfl: string, event: SankeyNodeMoveEvent): string;
@@ -271,4 +279,4 @@ interface EditingOptions {
271
279
  }
272
280
  declare function bindEditing(viewer: Viewer, options?: EditingOptions): Interaction;
273
281
 
274
- export { type ChartValueChangeEvent, type ColorEditHandle, type ColorPickerTheme, type ColorPickerThemeOption, type ColorPopoverHandle, type ColorPopoverOptions, type DeleteEvent, type EditableRules, type EditingOptions, type InsertCanvasObjectOptions, type InsertConnectionOptions, type InsertLinkOptions, type InsertPathOptions, type Interaction, type InteractionEventMap, type InteractionEventName, type IsometricQuickDuplicateDirection, type LinkReconnectEvent, type LinkSegmentChangeEvent, type LinkToEvent, type MoveChangeEvent, type PathDrawCompleteEvent, type PathDrawOptions, type PathPoint, type PathPointChangeEvent, type PickerValue, type PropertyChangeEvent, type PropertyEditingHandle, type PropertyEditingOptions, type PropertyValue, type QuickDuplicateEvent, type RemoveCanvasObjectOptions, type ResizeChangeEvent, type SankeyNodeMoveEvent, type SankeyNodeRenameEvent, type TextChangeEvent, Unsubscribe, applyChartValueChange, applyLinkReconnectChange, applyLinkSegmentChange, applyMoveChange, applyPathPointChange, applyPropertyChange, applyResizeChange, applySankeyNodeMoveChange, applySankeyNodeRenameChange, applyTextChange, bindEditing, bindPropertyEditing, cssBackground, formatPickerValue, insertCanvasObject, insertConnection, insertLink, insertPath, openColorPopover, readGradientValue, removeCanvasObject, removeLink, resolveTheme, seedFrom };
282
+ export { type ChartValueChangeEvent, type ColorEditHandle, type ColorPickerTheme, type ColorPickerThemeOption, type ColorPopoverHandle, type ColorPopoverOptions, type DeleteEvent, type EditableRules, type EditingOptions, type InsertCanvasObjectOptions, type InsertConnectionOptions, type InsertLinkOptions, type InsertPathOptions, type Interaction, type InteractionEventMap, type InteractionEventName, type IsometricQuickDuplicateDirection, type LinkReconnectEvent, type LinkSegmentChangeEvent, type LinkToEvent, type MoveChangeEvent, type PathDrawCompleteEvent, type PathDrawOptions, type PathPoint, type PathPointChangeEvent, type PickerValue, type PropertyChangeEvent, type PropertyEditingHandle, type PropertyEditingOptions, type PropertyValue, type QuickDuplicateEvent, type QuickDuplicateOptions, type RemoveCanvasObjectOptions, type ResizeChangeEvent, type SankeyNodeMoveEvent, type SankeyNodeRenameEvent, type TextChangeEvent, Unsubscribe, applyChartValueChange, applyLinkReconnectChange, applyLinkSegmentChange, applyMoveChange, applyPathPointChange, applyPropertyChange, applyQuickDuplicateChange, applyResizeChange, applySankeyNodeMoveChange, applySankeyNodeRenameChange, applyTextChange, bindEditing, bindPropertyEditing, cssBackground, formatPickerValue, insertCanvasObject, insertConnection, insertLink, insertPath, openColorPopover, readGradientValue, removeCanvasObject, removeLink, resolveTheme, seedFrom };
@@ -1,5 +1,5 @@
1
- import { screenRectOf, Emitter, resolveOwner, isCameraGesture, pointerUserPoint, clearAlignmentGuides, updateAlignmentGuides, pxPerUnit, findOwnerNode, isPrimary, SVG_NAMESPACE, isTextLabel, findSnapCandidateBounds, symbolDeclaredBounds, updateQuickDuplicateBubbles, isometricGeometryOf, ISO_HALO_ATTR, ISO_DUPLICATE_BUBBLES_ATTR, updateHalo, axisArrowPlacements, updateAxisArrowGroup, PATH_HALO_ATTR, findAllOwnerNodes, findIsometricApexCandidates, DERIVED_HEIGHT_ROLES, resizeHandlePositions, pathGeometryOf } from '../chunk-XEN5QIIJ.js';
2
- import { sflToCanvasState, tokenizeSource, roundedOrthogonalPathData, seriesLabelOffsetXProp, seriesLabelOffsetYProp, radarVertexPoint, freeformPathData, CORNER_RADIUS_ATTR, AXIS_COS, isometricFaces, roundedPolygonPath, isometricTopFaceCenter, calculateLinkRoute, pointAtPort, roundedBarPath, barShapePath, formatBarLabel, LABEL_WIDTH, LEADER_INSET, clipSegmentToRect, AXIS_SIN, radarValueAtPoint, radarSeriesPath, estimateTextWidth, wrapText, personLabelArea, isometricFaceCenter, PATH_POINT_INDEX_ATTR, linePathData, barLabelSize, BAR_LABEL, pillPath, getLineMidpoint, labelGapDash, pillCornerRadius, SQUARE_CORNER_ATTR, cornersRoundedRectPath, localShapePath, relativeOffsetOnRectangleSide, edgePointToward, SYMBOL_POINTS_ATTR, SYMBOL_TENSION_ATTR } from '../chunk-BYMIYXP5.js';
1
+ import { screenRectOf, Emitter, resolveOwner, isCameraGesture, pointerUserPoint, clearAlignmentGuides, updateAlignmentGuides, pxPerUnit, findOwnerNode, isPrimary, SVG_NAMESPACE, isTextLabel, findSnapCandidateBounds, symbolDeclaredBounds, updateQuickDuplicateBubbles, isometricGeometryOf, ISO_HALO_ATTR, ISO_DUPLICATE_BUBBLES_ATTR, updateHalo, axisArrowPlacements, updateAxisArrowGroup, PATH_HALO_ATTR, findAllOwnerNodes, findIsometricApexCandidates, DERIVED_HEIGHT_ROLES, resizeHandlePositions, pathGeometryOf } from '../chunk-7VW2XKVB.js';
2
+ import { sflToCanvasState, isIsometricObject, tokenizeSource, roundedOrthogonalPathData, seriesLabelOffsetXProp, seriesLabelOffsetYProp, radarVertexPoint, AXIS_SIN, AXIS_COS, freeformPathData, CORNER_RADIUS_ATTR, isometricFaces, roundedPolygonPath, isometricTopFaceCenter, calculateLinkRoute, pointAtPort, roundedBarPath, barShapePath, formatBarLabel, LABEL_WIDTH, LEADER_INSET, clipSegmentToRect, radarValueAtPoint, radarSeriesPath, estimateTextWidth, wrapText, personLabelArea, isometricFaceCenter, PATH_POINT_INDEX_ATTR, linePathData, barLabelSize, BAR_LABEL, pillPath, getLineMidpoint, labelGapDash, pillCornerRadius, SQUARE_CORNER_ATTR, cornersRoundedRectPath, localShapePath, relativeOffsetOnRectangleSide, edgePointToward, SYMBOL_POINTS_ATTR, SYMBOL_TENSION_ATTR } from '../chunk-IEHE6WVN.js';
3
3
 
4
4
  // src/runtime/interaction/chartValue/coordinates.ts
5
5
  function pointerUserY(svg, event) {
@@ -6392,7 +6392,7 @@ function braceDelta(masked) {
6392
6392
  }
6393
6393
 
6394
6394
  // src/runtime/interaction/sflPatch/scan/blocks.ts
6395
- var OWNER_HEADER = /^\s*(Entity|Shape|Text|Container|Chart|Path|Link|Isometric|Widget|Connection|Shader)\s+([A-Za-z_][A-Za-z0-9_]*)\b/;
6395
+ var OWNER_HEADER = /^\s*(Entity|Shape|Text|Container|Chart|Path|Link|Isometric|Widget|Component|Connection|Shader)\s+([A-Za-z_][A-Za-z0-9_]*)\b/;
6396
6396
  var VALID_IDENT = /^[A-Za-z_][A-Za-z0-9_]*$/;
6397
6397
  function blockEndIn(masked, startLine) {
6398
6398
  let depth = 0;
@@ -7286,6 +7286,257 @@ function shouldQuote(current, quote, indexed) {
7286
7286
  return indexed && trimmed === "none";
7287
7287
  }
7288
7288
 
7289
+ // src/runtime/interaction/sflPatch/connectionPatch/blockText.ts
7290
+ function buildConnectionBlock(options, baseIndent) {
7291
+ const bodyIndent = `${baseIndent} `;
7292
+ const block = [
7293
+ `${baseIndent}Connection ${options.id} {`,
7294
+ `${bodyIndent}from: ${options.fromId}`,
7295
+ `${bodyIndent}to: ${options.toId}`,
7296
+ `${bodyIndent}fromFace: "${options.fromFace}"`,
7297
+ `${bodyIndent}toFace: "${options.toFace}"`
7298
+ ];
7299
+ if (options.body) {
7300
+ block.push(...indentBlock(options.body, bodyIndent));
7301
+ }
7302
+ block.push(`${baseIndent}}`);
7303
+ return block;
7304
+ }
7305
+
7306
+ // src/runtime/interaction/sflPatch/connectionPatch/insertionTarget.ts
7307
+ function resolveConnectionInsertionTarget(sfl, lines, options) {
7308
+ if (!VALID_IDENT.test(options.id) || nameExists(lines, options.id)) {
7309
+ return null;
7310
+ }
7311
+ const canvasObjects = sflToCanvasState(sfl).canvasObjects;
7312
+ const hasSource = canvasObjects.some((canvasObject) => canvasObject.id === options.fromId);
7313
+ const hasTarget = canvasObjects.some((canvasObject) => canvasObject.id === options.toId);
7314
+ if (!hasSource || !hasTarget) {
7315
+ return null;
7316
+ }
7317
+ return findFirstBlockOfKind(lines, "Model");
7318
+ }
7319
+
7320
+ // src/runtime/interaction/sflPatch/connectionPatch/insert.ts
7321
+ function insertConnection(sfl, options) {
7322
+ const lines = sfl.split("\n");
7323
+ const modelRange = resolveConnectionInsertionTarget(sfl, lines, options);
7324
+ if (!modelRange) {
7325
+ return sfl;
7326
+ }
7327
+ insertBlockLines(lines, modelRange, (baseIndent) => buildConnectionBlock(options, baseIndent));
7328
+ return lines.join("\n");
7329
+ }
7330
+
7331
+ // src/runtime/interaction/sflPatch/changes/quickDuplicate/styleBlock.ts
7332
+ var QUOTED_KEYS = /* @__PURE__ */ new Set(["fill", "stroke", "textColor", "fontFamily", "shadow", "labelBackground"]);
7333
+ function styleLine(key, value) {
7334
+ return QUOTED_KEYS.has(key) ? ` ${key}: "${value.replace(/"/g, '\\"')}"` : ` ${key}: ${value}`;
7335
+ }
7336
+ function styleBlock(props, keys, leading = []) {
7337
+ const copied = keys.flatMap((key) => {
7338
+ const value = props?.[key];
7339
+ return value === void 0 ? [] : [styleLine(key, value)];
7340
+ });
7341
+ const lines = [...leading, ...copied];
7342
+ return lines.length > 0 ? `style {
7343
+ ${lines.join("\n")}
7344
+ }` : void 0;
7345
+ }
7346
+
7347
+ // src/runtime/interaction/sflPatch/changes/quickDuplicate/isometricDuplicate.ts
7348
+ var ISOMETRIC_GAP = 40;
7349
+ var ISOMETRIC_STYLE_KEYS = [
7350
+ "fill",
7351
+ "stroke",
7352
+ "strokeWidth",
7353
+ "cornerRadius",
7354
+ "shadow",
7355
+ "labelOffsetX",
7356
+ "labelOffsetY",
7357
+ "labelBackground"
7358
+ ];
7359
+ var TOUCHING_FACES = {
7360
+ "iso-width-pos": { fromFace: "right", toFace: "left" },
7361
+ "iso-width-neg": { fromFace: "left", toFace: "right" },
7362
+ "iso-depth-pos": { fromFace: "front", toFace: "back" },
7363
+ "iso-depth-neg": { fromFace: "back", toFace: "front" },
7364
+ "iso-height-pos": { fromFace: "bottom", toFace: "top" },
7365
+ "iso-height-neg": { fromFace: "top", toFace: "bottom" }
7366
+ };
7367
+ function isIsometricDirection2(direction) {
7368
+ return direction.startsWith("iso-");
7369
+ }
7370
+ function isometricOffset(direction, object, gap) {
7371
+ const { width, height } = object;
7372
+ const { depth } = object.isometric;
7373
+ switch (direction) {
7374
+ case "iso-width-pos":
7375
+ return { dx: (width + gap) * AXIS_COS, dy: (width + gap) * AXIS_SIN };
7376
+ case "iso-width-neg":
7377
+ return { dx: -(width + gap) * AXIS_COS, dy: -(width + gap) * AXIS_SIN };
7378
+ case "iso-depth-pos":
7379
+ return { dx: -(depth + gap) * AXIS_COS, dy: (depth + gap) * AXIS_SIN };
7380
+ case "iso-depth-neg":
7381
+ return { dx: (depth + gap) * AXIS_COS, dy: -(depth + gap) * AXIS_SIN };
7382
+ case "iso-height-pos":
7383
+ return { dx: 0, dy: height + gap };
7384
+ case "iso-height-neg":
7385
+ return { dx: 0, dy: -(height + gap) };
7386
+ }
7387
+ }
7388
+ function copyStyle(object, direction) {
7389
+ if (!direction.startsWith("iso-height-")) {
7390
+ return styleBlock(object.props, ISOMETRIC_STYLE_KEYS);
7391
+ }
7392
+ return styleBlock(
7393
+ object.props,
7394
+ ISOMETRIC_STYLE_KEYS.filter((key) => key !== "shadow"),
7395
+ [' shadow: "off"']
7396
+ );
7397
+ }
7398
+ function copyOf(object, direction, options) {
7399
+ const { dx, dy } = isometricOffset(direction, object, options.gap ?? ISOMETRIC_GAP);
7400
+ return {
7401
+ id: options.shapeId,
7402
+ kind: "isometric",
7403
+ text: object.text ?? "",
7404
+ x: object.x + dx,
7405
+ y: object.y + dy,
7406
+ width: object.width,
7407
+ height: object.height,
7408
+ depth: object.isometric.depth,
7409
+ parentId: object.parentFrameId,
7410
+ body: copyStyle(object, direction)
7411
+ };
7412
+ }
7413
+ function duplicateIsometricObject(sfl, object, direction, options) {
7414
+ const withCopy = insertCanvasObject(sfl, copyOf(object, direction, options));
7415
+ return insertConnection(withCopy, {
7416
+ id: options.linkId,
7417
+ fromId: object.id,
7418
+ toId: options.shapeId,
7419
+ ...TOUCHING_FACES[direction]
7420
+ });
7421
+ }
7422
+
7423
+ // src/runtime/interaction/sflPatch/linkPatch/blockText.ts
7424
+ function buildLinkBlock(options, baseIndent) {
7425
+ const bodyIndent = `${baseIndent} `;
7426
+ const from = formatLinkEndpoint({ id: options.fromId, side: options.fromSide, fraction: options.fromFraction });
7427
+ const to = formatLinkEndpoint({ id: options.toId, side: options.toSide, fraction: options.toFraction });
7428
+ const block = [`${baseIndent}Link ${options.id} {`, `${bodyIndent}from: ${from}`, `${bodyIndent}to: ${to}`];
7429
+ if (options.text !== void 0) {
7430
+ block.push(`${bodyIndent}text: "${escapeSflString(options.text)}"`);
7431
+ }
7432
+ if (options.body) {
7433
+ block.push(...indentBlock(options.body, bodyIndent));
7434
+ }
7435
+ block.push(`${baseIndent}}`);
7436
+ return block;
7437
+ }
7438
+
7439
+ // src/runtime/interaction/sflPatch/linkPatch/insertionTarget.ts
7440
+ function resolveLinkInsertionTarget(sfl, lines, options) {
7441
+ if (!VALID_IDENT.test(options.id) || nameExists(lines, options.id)) {
7442
+ return null;
7443
+ }
7444
+ const canvasObjects = sflToCanvasState(sfl).canvasObjects;
7445
+ const hasSource = canvasObjects.some((canvasObject) => canvasObject.id === options.fromId);
7446
+ const hasTarget = canvasObjects.some((canvasObject) => canvasObject.id === options.toId);
7447
+ if (!hasSource || !hasTarget) {
7448
+ return null;
7449
+ }
7450
+ return findFirstBlockOfKind(lines, "Model");
7451
+ }
7452
+
7453
+ // src/runtime/interaction/sflPatch/linkPatch/insert.ts
7454
+ function insertLink(sfl, options) {
7455
+ const lines = sfl.split("\n");
7456
+ const modelRange = resolveLinkInsertionTarget(sfl, lines, options);
7457
+ if (!modelRange) {
7458
+ return sfl;
7459
+ }
7460
+ insertBlockLines(lines, modelRange, (baseIndent) => buildLinkBlock(options, baseIndent));
7461
+ return lines.join("\n");
7462
+ }
7463
+
7464
+ // src/runtime/interaction/sflPatch/changes/quickDuplicate/shapeDuplicate.ts
7465
+ var SHAPE_GAP = 200;
7466
+ var OPPOSITE_SIDE = { top: "bottom", right: "left", bottom: "top", left: "right" };
7467
+ var SHAPE_STYLE_KEYS = [
7468
+ "fill",
7469
+ "stroke",
7470
+ "strokeWidth",
7471
+ "strokeStyle",
7472
+ "textColor",
7473
+ "fontSize",
7474
+ "fontFamily",
7475
+ "cornerRadius",
7476
+ "opacity",
7477
+ "shadow"
7478
+ ];
7479
+ var LINK_STYLE_KEYS = ["stroke", "strokeWidth", "strokeStyle", "markerStart", "markerEnd", "route"];
7480
+ function shapeOffset(side, object, gap) {
7481
+ switch (side) {
7482
+ case "top":
7483
+ return { dx: 0, dy: -(object.height + gap) };
7484
+ case "bottom":
7485
+ return { dx: 0, dy: object.height + gap };
7486
+ case "left":
7487
+ return { dx: -(object.width + gap), dy: 0 };
7488
+ case "right":
7489
+ return { dx: object.width + gap, dy: 0 };
7490
+ }
7491
+ }
7492
+ function copyOf2(object, side, options) {
7493
+ const { dx, dy } = shapeOffset(side, object, options.gap ?? SHAPE_GAP);
7494
+ const shape = object.shapeType ? [` shape: ${object.shapeType}`] : [];
7495
+ return {
7496
+ id: options.shapeId,
7497
+ kind: "shape",
7498
+ text: object.text ?? "",
7499
+ x: object.x + dx,
7500
+ y: object.y + dy,
7501
+ width: object.width,
7502
+ height: object.height,
7503
+ parentId: object.parentFrameId,
7504
+ body: styleBlock(object.props, SHAPE_STYLE_KEYS, shape)
7505
+ };
7506
+ }
7507
+ function linkStyleReference(links, objectId) {
7508
+ return links.find((link) => link.fromId === objectId) ?? links[0];
7509
+ }
7510
+ function linkToCopy(object, links, side, options) {
7511
+ return {
7512
+ id: options.linkId,
7513
+ fromId: object.id,
7514
+ toId: options.shapeId,
7515
+ fromSide: side,
7516
+ toSide: OPPOSITE_SIDE[side],
7517
+ body: styleBlock(linkStyleReference(links, object.id)?.props, LINK_STYLE_KEYS)
7518
+ };
7519
+ }
7520
+ function duplicateShape(sfl, input) {
7521
+ const { object, links, side, options } = input;
7522
+ const withCopy = insertCanvasObject(sfl, copyOf2(object, side, options));
7523
+ return insertLink(withCopy, linkToCopy(object, links, side, options));
7524
+ }
7525
+
7526
+ // src/runtime/interaction/sflPatch/changes/quickDuplicateChange.ts
7527
+ function applyQuickDuplicateChange(sfl, event, options) {
7528
+ const state = sflToCanvasState(sfl);
7529
+ const object = state.canvasObjects.find((candidate) => candidate.id === event.owner.id);
7530
+ if (!object) {
7531
+ return sfl;
7532
+ }
7533
+ const { direction } = event;
7534
+ if (isIsometricDirection2(direction)) {
7535
+ return isIsometricObject(object) ? duplicateIsometricObject(sfl, object, direction, options) : sfl;
7536
+ }
7537
+ return isIsometricObject(object) ? sfl : duplicateShape(sfl, { object, links: state.links, side: direction, options });
7538
+ }
7539
+
7289
7540
  // src/runtime/interaction/sflPatch/changes/resizeChange.ts
7290
7541
  function applyResizeChange(sfl, event) {
7291
7542
  const state = sflToCanvasState(sfl);
@@ -7410,89 +7661,6 @@ function applyTextChange(sfl, event) {
7410
7661
  return lines.join("\n");
7411
7662
  }
7412
7663
 
7413
- // src/runtime/interaction/sflPatch/connectionPatch/blockText.ts
7414
- function buildConnectionBlock(options, baseIndent) {
7415
- const bodyIndent = `${baseIndent} `;
7416
- const block = [
7417
- `${baseIndent}Connection ${options.id} {`,
7418
- `${bodyIndent}from: ${options.fromId}`,
7419
- `${bodyIndent}to: ${options.toId}`,
7420
- `${bodyIndent}fromFace: "${options.fromFace}"`,
7421
- `${bodyIndent}toFace: "${options.toFace}"`
7422
- ];
7423
- if (options.body) {
7424
- block.push(...indentBlock(options.body, bodyIndent));
7425
- }
7426
- block.push(`${baseIndent}}`);
7427
- return block;
7428
- }
7429
-
7430
- // src/runtime/interaction/sflPatch/connectionPatch/insertionTarget.ts
7431
- function resolveConnectionInsertionTarget(sfl, lines, options) {
7432
- if (!VALID_IDENT.test(options.id) || nameExists(lines, options.id)) {
7433
- return null;
7434
- }
7435
- const canvasObjects = sflToCanvasState(sfl).canvasObjects;
7436
- const hasSource = canvasObjects.some((canvasObject) => canvasObject.id === options.fromId);
7437
- const hasTarget = canvasObjects.some((canvasObject) => canvasObject.id === options.toId);
7438
- if (!hasSource || !hasTarget) {
7439
- return null;
7440
- }
7441
- return findFirstBlockOfKind(lines, "Model");
7442
- }
7443
-
7444
- // src/runtime/interaction/sflPatch/connectionPatch/insert.ts
7445
- function insertConnection(sfl, options) {
7446
- const lines = sfl.split("\n");
7447
- const modelRange = resolveConnectionInsertionTarget(sfl, lines, options);
7448
- if (!modelRange) {
7449
- return sfl;
7450
- }
7451
- insertBlockLines(lines, modelRange, (baseIndent) => buildConnectionBlock(options, baseIndent));
7452
- return lines.join("\n");
7453
- }
7454
-
7455
- // src/runtime/interaction/sflPatch/linkPatch/blockText.ts
7456
- function buildLinkBlock(options, baseIndent) {
7457
- const bodyIndent = `${baseIndent} `;
7458
- const from = formatLinkEndpoint({ id: options.fromId, side: options.fromSide, fraction: options.fromFraction });
7459
- const to = formatLinkEndpoint({ id: options.toId, side: options.toSide, fraction: options.toFraction });
7460
- const block = [`${baseIndent}Link ${options.id} {`, `${bodyIndent}from: ${from}`, `${bodyIndent}to: ${to}`];
7461
- if (options.text !== void 0) {
7462
- block.push(`${bodyIndent}text: "${escapeSflString(options.text)}"`);
7463
- }
7464
- if (options.body) {
7465
- block.push(...indentBlock(options.body, bodyIndent));
7466
- }
7467
- block.push(`${baseIndent}}`);
7468
- return block;
7469
- }
7470
-
7471
- // src/runtime/interaction/sflPatch/linkPatch/insertionTarget.ts
7472
- function resolveLinkInsertionTarget(sfl, lines, options) {
7473
- if (!VALID_IDENT.test(options.id) || nameExists(lines, options.id)) {
7474
- return null;
7475
- }
7476
- const canvasObjects = sflToCanvasState(sfl).canvasObjects;
7477
- const hasSource = canvasObjects.some((canvasObject) => canvasObject.id === options.fromId);
7478
- const hasTarget = canvasObjects.some((canvasObject) => canvasObject.id === options.toId);
7479
- if (!hasSource || !hasTarget) {
7480
- return null;
7481
- }
7482
- return findFirstBlockOfKind(lines, "Model");
7483
- }
7484
-
7485
- // src/runtime/interaction/sflPatch/linkPatch/insert.ts
7486
- function insertLink(sfl, options) {
7487
- const lines = sfl.split("\n");
7488
- const modelRange = resolveLinkInsertionTarget(sfl, lines, options);
7489
- if (!modelRange) {
7490
- return sfl;
7491
- }
7492
- insertBlockLines(lines, modelRange, (baseIndent) => buildLinkBlock(options, baseIndent));
7493
- return lines.join("\n");
7494
- }
7495
-
7496
7664
  // src/runtime/interaction/sflPatch/linkPatch/remove.ts
7497
7665
  function removeLink(sfl, id) {
7498
7666
  const lines = sfl.split("\n");
@@ -7557,6 +7725,6 @@ function bindEditing(viewer, options = {}) {
7557
7725
  };
7558
7726
  }
7559
7727
 
7560
- export { applyChartValueChange, applyLinkReconnectChange, applyLinkSegmentChange, applyMoveChange, applyPathPointChange, applyPropertyChange, applyResizeChange, applySankeyNodeMoveChange, applySankeyNodeRenameChange, applyTextChange, bindEditing, bindPropertyEditing, cssBackground, formatPickerValue, insertCanvasObject, insertConnection, insertLink, insertPath, openColorPopover, readGradientValue, removeCanvasObject, removeLink, resolveTheme, seedFrom };
7728
+ export { applyChartValueChange, applyLinkReconnectChange, applyLinkSegmentChange, applyMoveChange, applyPathPointChange, applyPropertyChange, applyQuickDuplicateChange, applyResizeChange, applySankeyNodeMoveChange, applySankeyNodeRenameChange, applyTextChange, bindEditing, bindPropertyEditing, cssBackground, formatPickerValue, insertCanvasObject, insertConnection, insertLink, insertPath, openColorPopover, readGradientValue, removeCanvasObject, removeLink, resolveTheme, seedFrom };
7561
7729
  //# sourceMappingURL=index.js.map
7562
7730
  //# sourceMappingURL=index.js.map