@tumaet/apollon 4.7.0 → 4.8.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 (34) hide show
  1. package/README.md +2 -2
  2. package/dist/assets/style.css +1 -1
  3. package/dist/export.d.ts +73 -0
  4. package/dist/export.js +219 -0
  5. package/dist/exportStyles-Wcc8N8Xj.js +5 -0
  6. package/dist/fontStack-DOtVH2j8.js +5 -0
  7. package/dist/index.d.ts +19 -0
  8. package/dist/index.js +11295 -11167
  9. package/dist/internals.d.ts +36 -1
  10. package/dist/internals.js +12 -11
  11. package/dist/react/components/AlignmentGuides.d.ts +1 -1
  12. package/dist/react/components/DraggableGhost.d.ts +5 -0
  13. package/dist/react/constants.d.ts +10 -0
  14. package/dist/react/export/exportErrors.d.ts +10 -0
  15. package/dist/react/export/index.d.ts +13 -0
  16. package/dist/react/export/normalizeExportSvg.d.ts +16 -0
  17. package/dist/react/export/preProcessSvgForPdf.d.ts +20 -0
  18. package/dist/react/export/svgToPdf.d.ts +17 -0
  19. package/dist/react/export/svgToPng.d.ts +38 -0
  20. package/dist/react/exportStyles-CH2hautV.js +6 -0
  21. package/dist/react/hooks/useRemoteDraggingNodes.d.ts +20 -0
  22. package/dist/react/react.js +7237 -7009
  23. package/dist/react/store/diagramStore.d.ts +17 -1
  24. package/dist/react/sync/perfCounters.d.ts +6 -0
  25. package/dist/react/sync/ydoc.d.ts +2 -0
  26. package/dist/react/sync/yjsSync.d.ts +3 -2
  27. package/dist/react/typings.d.ts +17 -0
  28. package/dist/react/utils/collaboration.d.ts +10 -1
  29. package/dist/react/utils/exportUtils.d.ts +0 -130
  30. package/dist/react/utils/paletteLayout.d.ts +66 -0
  31. package/dist/{yjsSync-aPxjWNdZ.js → yjsSync-CqmgRwRE.js} +6800 -6701
  32. package/package.json +15 -1
  33. package/dist/exportStyles-Xk-Vm7Ul.js +0 -5
  34. package/dist/react/exportStyles-DZCHk5mK.js +0 -6
@@ -174,6 +174,7 @@ declare type CollaborationState = {
174
174
  viewport?: CollaborationViewport | null;
175
175
  followingClientId?: number | null;
176
176
  selectedElementId?: string | null;
177
+ draggingNodes?: DraggingNode[] | null;
177
178
  };
178
179
 
179
180
  declare type CollaborationUser = {
@@ -411,8 +412,24 @@ declare type DiagramStore = {
411
412
  canUndo: boolean;
412
413
  canRedo: boolean;
413
414
  undoManager: Y.UndoManager | null;
415
+ collaborationEnabled: boolean;
414
416
  previewMode: boolean;
415
417
  setDiagramId: (diagramId: string) => void;
418
+ setCollaborationEnabled: (enabled: boolean) => void;
419
+ /**
420
+ * Inject the sink that forwards transient drag/resize frames onto the
421
+ * ephemeral awareness channel (wired by `YjsSync` for every editor). Kept as
422
+ * runtime wiring rather than diagram state so a `reset()` never clears it.
423
+ * The broadcast itself is gated by `collaborationEnabled`, not by this sink;
424
+ * `null` (headless, where no `YjsSync` runs) just leaves it unwired.
425
+ */
426
+ setDraggingNodesPublisher: (publisher: ((draggingNodes: DraggingNode[] | null) => void) | null) => void;
427
+ /**
428
+ * Clear the peers' live-drag overlay once a gesture's settled value is
429
+ * committed. Called from `onNodeDragStop` (after the doc write) and on
430
+ * collaboration teardown; a no-op when nothing is being broadcast.
431
+ */
432
+ endTransientNodeBroadcast: () => void;
416
433
  setNodes: (payload: Node_2[] | ((nodes: Node_2[]) => Node_2[])) => void;
417
434
  setEdges: (payload: Edge[] | ((edges: Edge[]) => Edge[])) => void;
418
435
  setNodesAndEdges: (nodes: Node_2[], edges: Edge[]) => void;
@@ -445,6 +462,23 @@ declare type DiagramStore = {
445
462
  setPreviewMode: (active: boolean) => void;
446
463
  };
447
464
 
465
+ /**
466
+ * One node a peer is actively dragging or resizing. Broadcast over the
467
+ * ephemeral awareness channel — never written to the Yjs document — so peers
468
+ * can render the in-progress gesture live without growing the CRDT or entering
469
+ * anyone's undo history. The settled position/size is committed once on
470
+ * drop/release through the document like any other edit.
471
+ */
472
+ declare type DraggingNode = {
473
+ id: string;
474
+ position: {
475
+ x: number;
476
+ y: number;
477
+ };
478
+ width?: number | null;
479
+ height?: number | null;
480
+ };
481
+
448
482
  declare type ExtendedEdgeProps = EdgeProps<Edge<CustomEdgeProps>> & {
449
483
  markerEnd?: string;
450
484
  markerPadding?: number;
@@ -849,6 +883,7 @@ export declare class YjsSync {
849
883
  setLocalAwarenessViewport: (viewport: CollaborationViewport | null) => void;
850
884
  setLocalAwarenessFollowing: (followingClientId: number | null) => void;
851
885
  setLocalAwarenessSelectedElement: (selectedElementId: string | null) => void;
886
+ setLocalAwarenessDraggingNodes: (draggingNodes: DraggingNode[] | null) => void;
852
887
  setLocalAwarenessState: (state: Partial<CollaborationState>) => void;
853
888
  subscribeToAwarenessChanges: (callback: (states: Map<number, CollaborationState>) => void) => () => void;
854
889
  getAwarenessStates: () => Map<number, CollaborationState>;
@@ -870,7 +905,7 @@ export declare class YjsSync {
870
905
  /**
871
906
  * Convert Base64 string to Uint8Array
872
907
  */
873
- private base64ToUint8;
908
+ static base64ToUint8(base64: string): Uint8Array;
874
909
  }
875
910
 
876
911
  export { }
package/dist/internals.js CHANGED
@@ -1,6 +1,6 @@
1
- import { W as n, aE as r } from "./yjsSync-aPxjWNdZ.js";
2
- import { ab as p, aU as i, aV as u, aW as S, aX as g, aY as T, aZ as b, bo as F, bp as l, bq as v } from "./yjsSync-aPxjWNdZ.js";
3
- function V(t = new n()) {
1
+ import { U as n, aB as r } from "./yjsSync-CqmgRwRE.js";
2
+ import { a8 as m, aR as g, aS as p, aT as u, aU as S, aV as T, aW as b, bl as l, bm as F, bn as v } from "./yjsSync-CqmgRwRE.js";
3
+ function d(t = new n()) {
4
4
  const e = () => {
5
5
  }, a = {
6
6
  getState: () => ({
@@ -8,6 +8,7 @@ function V(t = new n()) {
8
8
  updateEdgesFromYjs: e,
9
9
  updateAssessmentFromYjs: e,
10
10
  updateUndoRedoState: e,
11
+ setDraggingNodesPublisher: e,
11
12
  undoManager: null
12
13
  // Other DiagramStore fields are typed but never accessed by
13
14
  // YjsSync; cast through `unknown` keeps the helper from
@@ -30,16 +31,16 @@ function V(t = new n()) {
30
31
  };
31
32
  }
32
33
  export {
33
- p as MessageType,
34
+ m as MessageType,
34
35
  r as YjsSync,
35
- i as convertV2ToV4,
36
- u as convertV3EdgeTypeToV4,
37
- S as convertV3HandleToV4,
38
- g as convertV3MessagesToV4,
36
+ g as convertV2ToV4,
37
+ p as convertV3EdgeTypeToV4,
38
+ u as convertV3HandleToV4,
39
+ S as convertV3MessagesToV4,
39
40
  T as convertV3NodeTypeToV4,
40
41
  b as convertV3ToV4,
41
- V as createHeadlessSync,
42
- F as isV2Format,
43
- l as isV3Format,
42
+ d as createHeadlessSync,
43
+ l as isV2Format,
44
+ F as isV3Format,
44
45
  v as isV4Format
45
46
  };
@@ -1 +1 @@
1
- export declare const AlignmentGuides: () => import("react").JSX.Element | null;
1
+ export declare const AlignmentGuides: () => import("react").JSX.Element;
@@ -3,6 +3,11 @@ import { DropElementConfig } from '../constants';
3
3
  interface DraggableGhostProps {
4
4
  children: React.ReactNode;
5
5
  dropElementConfig: DropElementConfig;
6
+ /**
7
+ * Visual scale of the palette preview.
8
+ * Used to convert pointer offsets into node-placement offsets.
9
+ */
10
+ previewScale?: number;
6
11
  }
7
12
  export declare const DraggableGhost: React.FC<DraggableGhostProps>;
8
13
  export {};
@@ -39,6 +39,16 @@ export declare const LAYOUT: Readonly<{
39
39
  readonly STEREOTYPE_LINE_HEIGHT: 15;
40
40
  readonly STEREOTYPE_NAME_GAP: 4;
41
41
  }>;
42
+ /**
43
+ * Treat narrow portrait viewports and short phone-landscape viewports as
44
+ * mobile. The portrait bound stops just below 768px so iPads (768px portrait)
45
+ * keep the regular desktop layout; the second clause catches phones in
46
+ * landscape, where the short height distinguishes them from tablets.
47
+ *
48
+ * NOTE: mirrored in standalone/webapp/src/constants/responsive.ts (the webapp
49
+ * can't import the library's curated public surface). Keep both in sync.
50
+ */
51
+ export declare const MOBILE_VIEW_QUERY = "(max-width: 767.95px), (max-width: 950px) and (max-height: 500px)";
42
52
  export declare const INTERFACE: Readonly<{
43
53
  readonly SIZE: 30;
44
54
  readonly RADIUS: number;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Typed error for the raster (PNG) export path so callers can show an
3
+ * actionable "diagram too large" message instead of the silent 0-byte file the
4
+ * old canvas path produced (#667).
5
+ */
6
+ export declare class RasterTooLargeError extends Error {
7
+ readonly canvasWidth: number;
8
+ readonly canvasHeight: number;
9
+ constructor(message: string, canvasWidth: number, canvasHeight: number);
10
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `@tumaet/apollon/export` — reliable browser raster/vector export of a
3
+ * compat-mode Apollon SVG. PNG via resvg (wasm); PDF via svg2pdf.js on jsPDF.
4
+ * Both fix the canvas-area-cap silent failure of the old client path (#667).
5
+ *
6
+ * The heavy renderers (`@resvg/resvg-wasm`, `jspdf`, `svg2pdf.js`) are optional
7
+ * dependencies, loaded lazily, so importing the editor never pulls them in.
8
+ */
9
+ export { svgToPng, computeAppliedScale } from './svgToPng';
10
+ export type { SvgToPngOptions, SvgToPngResult } from './svgToPng';
11
+ export { svgToPdf } from './svgToPdf';
12
+ export type { SvgToPdfOptions } from './svgToPdf';
13
+ export { RasterTooLargeError } from './exportErrors';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Drop `font-style="italic"` from every element of an export SVG.
3
+ *
4
+ * Apollon emits italic for abstract-class headers, but the editor itself ships
5
+ * only upright Inter (Regular + Bold) — on screen the slant is the browser's
6
+ * *synthetic* oblique, and text width is measured with the upright metrics.
7
+ * The raster (resvg) and PDF (jsPDF) paths carry the same two upright faces, so
8
+ * a real italic face would change advance widths and break the editor↔export
9
+ * determinism guarantee (and risk overflowing label boxes). We therefore render
10
+ * abstract names upright by design — matching the server export — and strip the
11
+ * attribute so the SVG no longer *claims* an italic it doesn't deliver. Abstract
12
+ * classes stay distinguishable by their «Abstract» stereotype label.
13
+ *
14
+ * Mutates `root` in place.
15
+ */
16
+ export declare function normalizeExportSvg(root: Element): void;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Adapt a compat-mode Apollon SVG to the three svg2pdf.js limitations that the
3
+ * library's own compat passes (in exportUtils.ts) do NOT already cover.
4
+ * Relative font-sizes, `tspan` `dy` and `dominant-baseline` are resolved
5
+ * upstream by `getSVG`, so they are intentionally absent here.
6
+ *
7
+ * 1. Nested `<svg>` clips its content despite `overflow="visible"` — svg2pdf
8
+ * treats the intrinsic size as a clip rect. Apollon wraps each node in
9
+ * `<svg width viewBox>`; replace those with `<g>` (layout-equivalent since
10
+ * the viewBox is always `0 0 w h`), translating any non-zero origin.
11
+ * 2. A `<text>` with 2+ `<tspan>` children renders with wrong glyph widths in
12
+ * svg2pdf; split it into independent `<text>` elements. Each tspan already
13
+ * carries an absolute `y` (resolved by `resolveTspanDy`).
14
+ * 3. svg2pdf looks up `font-family` as a literal string, so the CSS list
15
+ * `"Inter, system-ui, …"` misses the registered "Inter" and falls back to a
16
+ * standard font; collapse any Inter-led list to plain `"Inter"`.
17
+ *
18
+ * Mutates `root` in place and returns it.
19
+ */
20
+ export declare function preProcessSvgForPdf(root: Element): Element;
@@ -0,0 +1,17 @@
1
+ export type SvgToPdfOptions = {
2
+ /** Document title metadata; does not affect layout. */
3
+ title?: string;
4
+ /**
5
+ * Inter Regular + Bold as ttf/otf bytes, for hosts without `fetch` of the
6
+ * bundled `?url` font asset (e.g. tests, headless Node). Defaults to the
7
+ * bundled Inter.
8
+ */
9
+ fonts?: {
10
+ regular: Uint8Array;
11
+ bold: Uint8Array;
12
+ };
13
+ };
14
+ export declare function svgToPdf(svg: string, clip: {
15
+ width: number;
16
+ height: number;
17
+ }, opts?: SvgToPdfOptions): Promise<Blob>;
@@ -0,0 +1,38 @@
1
+ export type SvgToPngOptions = {
2
+ /** Multiplier applied to the diagram clip dimensions. Default 1.5. */
3
+ scale?: number;
4
+ /** CSS colour (e.g. "#ffffff") or null for transparent. Default null. */
5
+ background?: string | null;
6
+ /** Override the 75 MP area budget. */
7
+ maxAreaPx?: number;
8
+ /** Override the 16,384 px per-side cap. */
9
+ maxDimensionPx?: number;
10
+ /**
11
+ * The `@resvg/resvg-wasm` binary, as anything resvg's `initWasm` accepts.
12
+ * Required: where the wasm lives is the host bundler's concern, not the
13
+ * library's (resvg-wasm doesn't export it under a portable URL specifier).
14
+ * In Vite:
15
+ * `import url from "@resvg/resvg-wasm/index_bg.wasm?url"`
16
+ * `svgToPng(svg, clip, { wasmInput: fetch(url) })`
17
+ */
18
+ wasmInput?: WebAssembly.Module | BufferSource | Response | Promise<Response>;
19
+ /** Font buffers (ttf/otf) to use instead of the bundled Inter. */
20
+ fontBuffers?: Uint8Array[];
21
+ };
22
+ export type SvgToPngResult = {
23
+ blob: Blob;
24
+ /** The scale actually used — below the requested one when clamped. */
25
+ appliedScale: number;
26
+ clamped: boolean;
27
+ width: number;
28
+ height: number;
29
+ };
30
+ /**
31
+ * Largest scale that fits both the area budget and the per-side cap. Pure, so
32
+ * the clamp can be unit-tested without booting wasm.
33
+ */
34
+ export declare function computeAppliedScale(width: number, height: number, requestedScale: number, maxAreaPx: number, maxDimensionPx: number): number;
35
+ export declare function svgToPng(svg: string, clip: {
36
+ width: number;
37
+ height: number;
38
+ }, opts?: SvgToPngOptions): Promise<SvgToPngResult>;
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ const o = ".react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgb(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-border-default: 1px solid #bbb;--xy-node-border-selected-default: 1px solid #555;--xy-handle-background-color-default: #333;--xy-selection-background-color-default: rgba(150, 150, 180, .1);--xy-selection-border-default: 1px dotted rgba(155, 155, 155, .8);--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgb(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #777;--xy-background-pattern-lines-color-default: #777;--xy-background-pattern-cross-color-default: #777;--xy-node-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color, var(--xy-background-color-props, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default))}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.center{left:50%;transform:translate(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{border:var(--xy-node-border, var(--xy-node-border-default));color:var(--xy-node-color, var(--xy-node-color-default))}.react-flow__node-input.selected,.react-flow__node-input:focus,.react-flow__node-input:focus-visible,.react-flow__node-default.selected,.react-flow__node-default:focus,.react-flow__node-default:focus-visible,.react-flow__node-output.selected,.react-flow__node-output:focus,.react-flow__node-output:focus-visible,.react-flow__node-group.selected,.react-flow__node-group:focus,.react-flow__node-group:focus-visible{outline:none;border:var(--xy-node-border-selected, var(--xy-node-border-selected-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:4px;height:4px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));transform:translate(-50%,-50%)}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}", e = ':root{--safe-area-inset-top: env(safe-area-inset-top, 0px);--safe-area-inset-right: env(safe-area-inset-right, 0px);--safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);--safe-area-inset-left: env(safe-area-inset-left, 0px)}.react-flow{--panel-background: var(--apollon-background, #fff);--panel-shadow: 0 0 4px 0 var(--apollon-background-variant, #f8f9fa);--text: var(--apollon-primary-contrast, #000);--xy-edge-stroke: var(--apollon-primary-contrast, #000);--xy-edge-stroke-width: 2px;--xy-minimap-mask-background-color-props: #00000020;--xy-controls-button-background-color: var(--apollon-background, #fff)}.apollon-editor{background-color:var(--apollon-background, #fff);color:var(--apollon-primary-contrast, #000);isolation:isolate}.apollon-canvas{position:relative;flex:1;min-width:0;height:100%;overflow:hidden}.apollon-collaboration-presence-bar{position:absolute;top:10px;right:10px;display:flex;align-items:center;z-index:10002;pointer-events:auto}.apollon-collaboration-presence-bar [role=button]:focus-visible{outline:2px solid var(--apollon-primary, #3e8acc);outline-offset:2px}.apollon-collaboration-follower-badge{position:absolute;bottom:-4px;left:-4px;min-width:14px;height:14px;padding:0 3px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;border-radius:10px;border:2px solid;background-color:var(--apollon-background, #fff);color:var(--apollon-primary-contrast, #000);font-size:8px;font-weight:700}.apollon-collaboration-follow-frame{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;z-index:10001}.apollon-collaboration-follow-banner{position:absolute;top:16px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:8px;max-width:min(calc(100% - 32px),420px);padding:6px 6px 6px 14px;border-radius:999px;border:1px solid;background-color:var(--apollon-background, #fff);color:var(--apollon-primary-contrast, #000);box-shadow:0 2px 12px color-mix(in srgb,var(--apollon-primary-contrast, #000) 22%,transparent);font-size:13px;font-weight:500;white-space:nowrap;z-index:10004;pointer-events:auto;animation:apollon-collaboration-follow-banner-in .16s ease-out}@keyframes apollon-collaboration-follow-banner-in{0%{opacity:0;transform:translate(-50%,-8px)}to{opacity:1;transform:translate(-50%)}}@media(prefers-reduced-motion:reduce){.apollon-collaboration-follow-banner{animation:none}}.apollon-collaboration-follow-banner-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}.apollon-collaboration-follow-banner-text{overflow:hidden;text-overflow:ellipsis}.apollon-collaboration-follow-banner-stop{flex-shrink:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;cursor:pointer;border-radius:999px;padding:3px 12px;font:inherit;font-weight:600;background-color:var(--apollon-primary-contrast, #000);color:var(--apollon-background, #fff)}.apollon-collaboration-follow-banner-stop:hover{opacity:.85}.apollon-collaboration-follow-banner-stop:focus-visible{outline:2px solid var(--apollon-primary, #3e8acc);outline-offset:2px}.apollon-collaboration-cursors{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;pointer-events:none;z-index:10003}.apollon-collaboration-cursor{position:absolute}.apollon-collaboration-cursor-label{margin-top:4px;padding:2px 6px;font-size:12px;border-radius:6px;color:#fff;white-space:nowrap}.react-flow__node.apollon-collaboration-highlighted{box-shadow:0 0 0 4px var(--apollon-collaboration-highlight-color),0 0 16px 3px var(--apollon-collaboration-highlight-color)!important;border-color:var(--apollon-collaboration-highlight-color)!important}.react-flow__edge.apollon-collaboration-highlighted path{stroke:var(--apollon-collaboration-highlight-color)!important;stroke-width:4.5px!important;filter:drop-shadow(0 0 4px var(--apollon-collaboration-highlight-color))}.apollon-palette{box-sizing:border-box;position:absolute;top:10px;left:calc(10px + var(--safe-area-inset-left, 0px));z-index:10000;max-height:calc(100% - 84px - var(--safe-area-inset-bottom, 0px));display:flex;flex-direction:column;gap:8px;align-items:center;padding:6px;overflow-y:auto;overscroll-behavior:contain;background:var(--apollon-background, #fff);color:var(--apollon-primary-contrast, #000);border:1px solid var(--apollon-gray, #e9ecef);border-radius:6px;box-shadow:0 2px 8px #0000002e}.apollon-palette__entries{display:grid;justify-content:center}.apollon-palette__entry{display:flex;align-items:center;justify-content:center;cursor:grab;border-radius:4px;transition:background-color .12s ease}.apollon-palette__entry:hover{background:var(--apollon-background-variant, #f8f9fa)}.apollon-palette__entry:active{cursor:grabbing}.apollon-palette__view-switch{width:100%;display:flex;flex-direction:column;gap:4px}.apollon-palette__view-button{border-radius:6px;border:1px solid var(--apollon-primary-contrast, #000);background:transparent;color:var(--apollon-primary-contrast, #000);padding:6px 8px;cursor:pointer;font-weight:600;white-space:nowrap;font-size:12px}.apollon-palette__view-button--active{background:var(--apollon-primary, #3e8acc);color:var(--apollon-background, #fff)}.apollon-palette__hint{box-sizing:border-box;width:100%;max-width:160px;padding:4px;font-size:11px;line-height:1.4}@media(max-width:950px)and (max-height:500px){.react-flow__panel.bottom.left{margin-left:calc(10px + var(--safe-area-inset-left, 0px));margin-bottom:calc(10px + var(--safe-area-inset-bottom, 0px))}.react-flow__panel.bottom.right{margin-right:calc(10px + var(--safe-area-inset-right, 0px));margin-bottom:calc(10px + var(--safe-area-inset-bottom, 0px))}.apollon-collaboration-presence-bar{right:calc(10px + var(--safe-area-inset-right, 0px))}}.react-flow__controls-button{background:none;border-bottom:none}.react-flow__panel,.react-flow__node-toolbar{background-color:var(--panel-background);box-shadow:var(--panel-shadow);border-radius:8px;padding:8px}.react-flow svg{display:block}.react-flow__node-toolbar{display:flex;gap:8px}.react-flow__controls-button,.react-flow__controls-button:hover{background:var(--panel-background);border-bottom:none}.react-flow__controls-button>svg{fill:var(--text)}.react-flow__handle{opacity:0;background-color:transparent}.react-flow__handle.apollon-arc-handle:before{content:"";position:absolute;background-color:var(--apollon-primary, #3e8acc);opacity:.4;box-sizing:border-box;pointer-events:all;cursor:crosshair;--arc-long: calc(28px * var(--arc-scale, 1));--arc-short: calc(14px * var(--arc-scale, 1));--arc-radius: calc(14px * var(--arc-scale, 1))}.react-flow__handle.apollon-arc-handle--top:before{width:var(--arc-long);height:var(--arc-short);left:50%;top:50%;transform:translate(-50%,-100%);border-radius:var(--arc-radius) var(--arc-radius) 0 0}.react-flow__handle.apollon-arc-handle--right:before{width:var(--arc-short);height:var(--arc-long);left:50%;top:50%;transform:translateY(-50%);border-radius:0 var(--arc-radius) var(--arc-radius) 0}.react-flow__handle.apollon-arc-handle--bottom:before{width:var(--arc-long);height:var(--arc-short);left:50%;top:50%;transform:translate(-50%);border-radius:0 0 var(--arc-radius) var(--arc-radius)}.react-flow__handle.apollon-arc-handle--left:before{width:var(--arc-short);height:var(--arc-long);left:50%;top:50%;transform:translate(-100%,-50%);border-radius:var(--arc-radius) 0 0 var(--arc-radius)}.react-flow__resize-control line{z-index:9}.react-flow__resize-control.handle{z-index:20}.react-flow__resize-control{opacity:0;pointer-events:none;transition:opacity .12s ease}.react-flow__node:hover .react-flow__resize-control,.react-flow__node.selected .react-flow__resize-control{opacity:1;pointer-events:all}.react-flow__node:hover .react-flow__handle,.react-flow__node.selected .react-flow__handle{opacity:1;background-color:transparent;pointer-events:all;cursor:crosshair}.apollon-editor--connection-guidance .react-flow__handle.apollon-arc-handle:before{opacity:0;pointer-events:none}.apollon-editor--connection-guidance .react-flow__node:has(.apollon-connection-guidance-source),.apollon-editor--connection-guidance .react-flow__node:has(.react-flow__handle.connectionindicator.connectingto){z-index:10001!important}.apollon-editor--connection-guidance .react-flow__handle.connectionindicator{opacity:1!important;width:10px!important;height:10px!important;border-radius:999px;border:2px solid var(--apollon-primary, #3e8acc);background-color:var(--apollon-background, #fff);box-sizing:border-box}.apollon-editor--connection-guidance .react-flow__handle.connectionindicator.connectingfrom,.apollon-editor--connection-guidance .react-flow__handle.apollon-connection-guidance-source{opacity:0!important;pointer-events:none!important;border-color:transparent!important;background-color:transparent!important}.apollon-editor--connection-guidance .react-flow__handle.connectionindicator.valid{background-color:var(--apollon-primary, #3e8acc)!important}.edge-bend-handle{opacity:0;stroke:none;fill:color-mix(in srgb,var(--apollon-primary, #3e8acc) 34%,var(--apollon-background, #fff));transition:fill .12s ease,opacity .12s ease;vector-effect:non-scaling-stroke}.edge-endpoint-handle{fill:transparent;stroke:transparent;stroke-width:0;cursor:move;vector-effect:non-scaling-stroke}.edge-endpoint-handle--disabled{cursor:default}.react-flow__edge:hover .edge-bend-handle,.react-flow__edge.selected .edge-bend-handle{opacity:1;fill:var(--apollon-primary, #3e8acc)}.react-flow__edge:hover .edge-bend-handle:hover,.react-flow__edge.selected .edge-bend-handle:hover{fill:color-mix(in srgb,var(--apollon-primary, #3e8acc) 70%,#000)}.react-flow__edge:hover .edge-overlay,.react-flow__edge:hover .edge-marker-highlight{opacity:0}.react-flow__edge.selected .edge-overlay{opacity:0;pointer-events:none}.react-flow__edge.selected .edge-marker-highlight{opacity:0}.react-flow__edge:hover .react-flow__edge-path,.react-flow__edge:hover [data-inline-marker]{stroke:color-mix(in srgb,var(--apollon-primary, #3e8acc) 70%,#000)!important}.react-flow__edge:hover [data-inline-marker-filled=true]{fill:color-mix(in srgb,var(--apollon-primary, #3e8acc) 70%,#000)!important}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selected [data-inline-marker]{stroke:var(--apollon-primary, #3e8acc)!important}.react-flow__edge.selected [data-inline-marker-filled=true]{fill:var(--apollon-primary, #3e8acc)!important}.react-flow__node:hover,.react-flow__node.selected{opacity:.9;box-shadow:0 0 0 2px var(--apollon-primary, #3e8acc);border-radius:4px}.apollon-interactive-selection{--apollon-interactive-selection-color: var( --apollon-interactive-selection, #f39c12 )}.apollon-interactive-selection--selected [stroke]:not([stroke=none]){stroke:var(--apollon-interactive-selection-color)}.apollon-interactive-selection--selected .react-flow__edge-path{stroke-width:3px}.apollon-interactive-selection--selected .edge-overlay,.apollon-interactive-selection--selected .edge-marker-highlight{opacity:.45;stroke:var(--apollon-interactive-selection-color);stroke-width:15px}.react-flow__edges{z-index:9999}.react-flow__node{z-index:9998}svg.react-flow__connectionline{z-index:10000}.react-flow__connection-path{stroke:var(--xy-edge-stroke);stroke-width:var(--xy-edge-stroke-width);opacity:.5}.react-flow__minimap-mask{fill:"#f2f2f2";opacity:.6}.prevent-select{-webkit-user-select:none;-ms-user-select:none;user-select:none}.control-button{background-color:var(--apollon-background, #fff);border:1px solid var(--apollon-gray-variant, #495057);border-radius:8px;padding:6px 8px;cursor:pointer;opacity:1;display:flex;align-items:center;justify-content:center;min-width:32px;height:32px;font-size:14px;font-weight:700;transition:background-color .2s ease}.control-button:hover:not(.disabled){background-color:var(--apollon-background-variant, #f8f9fa)}.control-button.disabled{cursor:not-allowed;opacity:.5}.control-button.disabled:hover{background-color:var(--apollon-background, #fff)}.horizontally-not-resizable .react-flow__resize-control.top.line:hover,.horizontally-not-resizable .react-flow__resize-control.bottom.line:hover,.vertically-not-resizable .react-flow__resize-control.right.line:hover,.vertically-not-resizable .react-flow__resize-control.left.line:hover{cursor:grab}.apollon-editor .MuiSelect-select,.apollon-editor .MuiFormLabel-root{color:var(--apollon-primary-contrast, #000)!important}.apollon-editor .MuiOutlinedInput-notchedOutline{border-color:var(--apollon-primary-contrast, #000)!important}.apollon-editor .MuiSvgIcon-root{color:var(--apollon-primary-contrast, #000)!important}.scroll-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background-color:var(--apollon-grid, rgba(36, 39, 36, .1));-webkit-backdrop-filter:blur(.5px);backdrop-filter:blur(.5px);z-index:10;cursor:not-allowed;animation:fadeIn .2s ease-in-out;display:flex;align-items:center;justify-content:center;pointer-events:auto}.scroll-overlay-hint{position:absolute;bottom:40px;left:50%;transform:translate(-50%);z-index:11}.scroll-overlay-hint-content{background-color:var(--apollon-background, #fff);border:2px solid var(--apollon-primary, #3e8acc);border-radius:8px;padding:16px 24px;box-shadow:0 4px 12px var(--apollon-grid, rgba(36, 39, 36, .1));display:flex;align-items:center;justify-content:center}.scroll-overlay-hint-text{margin:0;color:var(--apollon-primary, #3e8acc);font-weight:600;font-size:14px;text-align:center}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}', r = `${o}
3
+ ${e}`;
4
+ export {
5
+ r as EXPORT_LAYOUT_CSS
6
+ };
@@ -0,0 +1,20 @@
1
+ import { Node } from '@xyflow/react';
2
+ import { CollaborationAwarenessApi } from '../components/collaboration/CollaborationLayer';
3
+ import { DraggingNode } from '../typings';
4
+ /**
5
+ * Live positions/sizes of nodes that *remote* peers are currently dragging or
6
+ * resizing, keyed by node id. These travel over the ephemeral awareness channel
7
+ * (never the Yjs document — see `diagramStore.onNodesChange`), so this hook is
8
+ * the read side of the live remote drag: it mirrors awareness into React state
9
+ * that `applyDraggingOverlay` overlays onto the rendered nodes.
10
+ */
11
+ export type RemoteDraggingOverlay = Map<string, DraggingNode>;
12
+ export declare const useRemoteDraggingNodes: (awareness: CollaborationAwarenessApi, active: boolean) => RemoteDraggingOverlay;
13
+ /**
14
+ * Overlay remote live-drag positions/sizes onto the rendered nodes. Returns the
15
+ * same array reference when there is nothing to overlay so React Flow skips the
16
+ * update. Behaviourally identical to the old per-frame document write — it
17
+ * moves the node in the controlled `nodes` prop — so connected edges follow
18
+ * exactly as before; the difference is only the (ephemeral) source.
19
+ */
20
+ export declare const applyDraggingOverlay: (nodes: Node[], overlay: RemoteDraggingOverlay) => Node[];