@dineug/erd-editor 3.7.0 → 3.9.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 (111) hide show
  1. package/README.md +1 -1
  2. package/dist/components/erd/automatic-table-placement/AutomaticTablePlacement.d.ts +0 -15
  3. package/dist/components/erd/automatic-table-placement/runElkPlacement.d.ts +11 -0
  4. package/dist/components/erd/canvas/CanvasScene.d.ts +3 -3
  5. package/dist/components/erd/canvas/column-drag-ghost/ColumnDragGhost.d.ts +10 -0
  6. package/dist/components/erd/canvas/column-drag-ghost/columnDragPointer.d.ts +28 -0
  7. package/dist/components/erd/canvas/entityDrag.d.ts +5 -4
  8. package/dist/components/erd/canvas/highlightTransition.d.ts +35 -0
  9. package/dist/components/erd/canvas/memo/useMoveMemo.d.ts +3 -1
  10. package/dist/components/erd/canvas/mixColor.d.ts +7 -0
  11. package/dist/components/erd/canvas/relationship-group/RelationshipGroup.d.ts +2 -0
  12. package/dist/components/erd/canvas/relationship-group/relationship/Relationship.d.ts +2 -0
  13. package/dist/components/erd/canvas/relationship-group/relationship/Relationship.template.d.ts +3 -3
  14. package/dist/components/erd/canvas/sceneHit.d.ts +7 -6
  15. package/dist/components/erd/canvas/sceneTokens.d.ts +58 -6
  16. package/dist/components/erd/canvas/table/Table.d.ts +7 -0
  17. package/dist/components/erd/canvas/table/cellLayout.d.ts +50 -20
  18. package/dist/components/erd/canvas/table/colorEdge.d.ts +10 -0
  19. package/dist/components/erd/canvas/table/column/Column.d.ts +35 -0
  20. package/dist/components/erd/canvas/table/goToErd.d.ts +18 -0
  21. package/dist/components/erd/canvas/table/useMoveTable.d.ts +3 -1
  22. package/dist/components/erd/canvas/table/useViewPin.d.ts +19 -0
  23. package/dist/components/erd/canvas/useMoveEntity.d.ts +15 -2
  24. package/dist/components/erd/content-compass/ContentCompass.d.ts +1 -1
  25. package/dist/components/erd/content-compass/compassGeometry.d.ts +27 -4
  26. package/dist/components/erd/diff-viewer/diff.d.ts +9 -2
  27. package/dist/components/erd/diff-viewer/diffContext.d.ts +9 -0
  28. package/dist/components/erd/floating-toolbar/FloatingToolbar.d.ts +3 -3
  29. package/dist/components/erd/floating-toolbar/FloatingToolbar.styles.d.ts +3 -0
  30. package/dist/components/erd/floating-toolbar/ToolbarCompass.template.d.ts +14 -0
  31. package/dist/components/erd/minimap/MinimapScene.d.ts +1 -1
  32. package/dist/components/erd/minimap/minimapGeometry.d.ts +4 -3
  33. package/dist/components/flowCenters.d.ts +10 -0
  34. package/dist/components/primitives/context-menu/context-menu-content/ContextMenuContent.d.ts +2 -0
  35. package/dist/components/primitives/context-menu/context-menu-content/fitMenu.d.ts +20 -0
  36. package/dist/components/primitives/icon/icons.d.ts +5 -2
  37. package/dist/components/sceneSourceContext.d.ts +10 -0
  38. package/dist/components/table-view/Table.styles.d.ts +6 -1
  39. package/dist/components/table-view/column/useColumnCell.d.ts +5 -0
  40. package/dist/components/theme-builder/ThemeBuilder.styles.d.ts +5 -0
  41. package/dist/components/visualization/Visualization.d.ts +3 -4
  42. package/dist/components/visualization/Visualization.styles.d.ts +4 -1
  43. package/dist/components/visualization/VisualizationFlow.d.ts +10 -0
  44. package/dist/components/visualization/VisualizationGraph.d.ts +10 -0
  45. package/dist/components/visualization/captureDrag.d.ts +14 -0
  46. package/dist/components/visualization/flowLayout.d.ts +29 -0
  47. package/dist/components/visualization/graphViewHandle.d.ts +33 -0
  48. package/dist/components/visualization/particles/ParticleLayer.d.ts +10 -0
  49. package/dist/components/visualization/particles/particleEdges.d.ts +15 -0
  50. package/dist/components/visualization/particles/particleLoop.d.ts +28 -0
  51. package/dist/components/visualization/particles/particlePath.d.ts +83 -0
  52. package/dist/components/visualization/useViewGestures.d.ts +24 -0
  53. package/dist/components/visualization/visualization-toolbar/VisualizationToolbar.d.ts +10 -0
  54. package/dist/components/visualization/visualization-toolbar/VisualizationToolbar.styles.d.ts +4 -0
  55. package/dist/components/visualization/visualizationView.d.ts +29 -5
  56. package/dist/components/visualization/zoomVisualization.d.ts +20 -0
  57. package/dist/constants/layout.d.ts +74 -1
  58. package/dist/constants/tablePlacement.d.ts +4 -3
  59. package/dist/constants/zoom.d.ts +7 -0
  60. package/dist/engine/actions.d.ts +6 -0
  61. package/dist/engine/index.js +12 -12
  62. package/dist/engine/modules/editor/actions.d.ts +60 -2
  63. package/dist/engine/modules/editor/atom.actions.d.ts +136 -0
  64. package/dist/engine/modules/editor/generator.actions.d.ts +19 -6
  65. package/dist/engine/modules/editor/state.d.ts +41 -0
  66. package/dist/engine/modules/editor/view.actions.d.ts +270 -0
  67. package/dist/engine/modules/editor/view.d.ts +28 -0
  68. package/dist/engine/modules/editor/view.generator.actions.d.ts +24 -0
  69. package/dist/engine/modules/settings/atom.actions.d.ts +17 -3
  70. package/dist/engine/modules/settings/generator.actions.d.ts +21 -4
  71. package/dist/engine/rx-operators/viewActionRedirect.d.ts +10 -0
  72. package/dist/engine/rx-operators/viewIgnoreFilter.d.ts +10 -0
  73. package/dist/engine/rx-store.d.ts +1 -0
  74. package/dist/engine/tag.d.ts +2 -0
  75. package/dist/erd-editor.umd.js +365 -314
  76. package/dist/hooks/usePinchZoom.d.ts +27 -0
  77. package/dist/index.js +6750 -5202
  78. package/dist/konva/scene/columnDropTarget.d.ts +12 -4
  79. package/dist/konva/scene/contentBounds.d.ts +12 -5
  80. package/dist/konva/scene/fitZoom.d.ts +16 -0
  81. package/dist/konva/scene/metrics.d.ts +6 -5
  82. package/dist/konva/scene/viewFreeze.d.ts +10 -7
  83. package/dist/konva/scene/viewLayout.d.ts +94 -0
  84. package/dist/konva/scene/viewport.d.ts +23 -4
  85. package/dist/{schemaGCService--wGet5O7.js → schemaGCService-CFiz1xOG.js} +3725 -3132
  86. package/dist/services/elk-layout/elkGraph.d.ts +40 -1
  87. package/dist/services/elk-layout/elkLayoutOptions.d.ts +22 -1
  88. package/dist/services/elk-layout/elkLayoutService.d.ts +5 -1
  89. package/dist/services/elk-layout/index.d.ts +10 -4
  90. package/dist/styles/elevation.styles.d.ts +7 -0
  91. package/dist/themes/radix-ui-theme.config.d.ts +12 -0
  92. package/dist/themes/tokens.d.ts +7 -0
  93. package/dist/utils/calcTable.d.ts +23 -1
  94. package/dist/utils/clickGesture.d.ts +19 -0
  95. package/dist/utils/domEvent.d.ts +8 -0
  96. package/dist/utils/draw-relationship/bezier.d.ts +32 -0
  97. package/dist/utils/draw-relationship/calc.d.ts +6 -1
  98. package/dist/utils/draw-relationship/geometrySource.d.ts +9 -0
  99. package/dist/utils/draw-relationship/incremental.d.ts +7 -1
  100. package/dist/utils/draw-relationship/index.d.ts +37 -11
  101. package/dist/utils/draw-relationship/pathFinding.d.ts +2 -1
  102. package/dist/utils/draw-relationship/route.d.ts +5 -3
  103. package/dist/utils/draw-relationship/sort.d.ts +2 -1
  104. package/dist/utils/draw-relationship/stub.d.ts +9 -4
  105. package/dist/utils/emitter.d.ts +4 -0
  106. package/dist/utils/keyboard-shortcut/index.d.ts +2 -1
  107. package/dist/utils/pinch.d.ts +34 -0
  108. package/dist/utils/validation.d.ts +1 -0
  109. package/dist/workers/elkLayout.shared-worker.js +1 -1
  110. package/dist/workers/exportPng.shared-worker.js +26 -26
  111. package/package.json +3 -3
@@ -1,9 +1,29 @@
1
1
  import { RootState } from '../../engine/state';
2
+ import { GeometrySource } from '../../utils/draw-relationship/geometrySource';
2
3
  import { ElkPlacement } from './elkLayoutOptions';
3
4
  export type ElkLayoutNode = {
4
5
  id: string;
5
6
  width: number;
6
7
  height: number;
8
+ /**
9
+ * Where the source already draws this table, normalized into node widths.
10
+ * Only a placement whose strategies read a hint is sent one, and a view that
11
+ * has not placed the table yet hints from where the document draws it.
12
+ */
13
+ x?: number;
14
+ y?: number;
15
+ /** What is laid out inside this node, which is what makes it a group rather than a table. */
16
+ children?: ElkLayoutNode[];
17
+ };
18
+ /**
19
+ * Which tables a request covers and what it measures them by. The source picks
20
+ * both the sizes and the hints, and grouping packs the tables no relationship
21
+ * reaches into one box instead of scattering them through the layers.
22
+ */
23
+ export type ElkLayoutRequestOptions = {
24
+ tableIds?: string[];
25
+ source?: GeometrySource;
26
+ groupUnrelated?: boolean;
7
27
  };
8
28
  export type ElkLayoutEdge = {
9
29
  source: string;
@@ -31,7 +51,17 @@ export type ElkLayoutPoint = {
31
51
  x: number;
32
52
  y: number;
33
53
  };
34
- export declare function createElkLayoutRequest(state: RootState, placement: ElkPlacement): ElkLayoutRequest;
54
+ /**
55
+ * What ELK is asked to place, at the sizes the source draws. Nodes carry a
56
+ * hint of where they already stand where the placement reads one, and grouping
57
+ * folds the tables no relationship reaches into one packed box.
58
+ *
59
+ * @example
60
+ * createElkLayoutRequest(state, TablePlacement.viewLayered, { source: 'flow' });
61
+ */
62
+ export declare function createElkLayoutRequest(state: RootState, placement: ElkPlacement, { tableIds, source, groupUnrelated, }?: ElkLayoutRequestOptions): ElkLayoutRequest;
63
+ /** Every table in a node list, which is every node the group nodes do not hold. */
64
+ export declare function flattenElkNodes(nodes: ElkLayoutNode[]): ElkLayoutNode[];
35
65
  /**
36
66
  * Where each table lands, over the middle of what the document already draws.
37
67
  * ELK lays every graph out from its own origin, so a document placed twice
@@ -41,4 +71,13 @@ export declare function createElkLayoutRequest(state: RootState, placement: ElkP
41
71
  * onChange(toTablePoints(store.state, request, await createElkLayout(request)));
42
72
  */
43
73
  export declare function toTablePoints(state: RootState, { nodes }: ElkLayoutRequest, points: ElkLayoutPoint[]): ElkLayoutPoint[];
74
+ /**
75
+ * Where each table lands in a view, whose coordinates start at its own corner.
76
+ * A view shares nothing with the document, so unlike a placement of the
77
+ * document this reads no content rect and centres the layout on nothing.
78
+ *
79
+ * @example
80
+ * dispatch(viewSetLayout({ positions: toViewPoints(request, points) }));
81
+ */
82
+ export declare function toViewPoints({ nodes }: ElkLayoutRequest, points: ElkLayoutPoint[]): ElkLayoutPoint[];
44
83
  //# sourceMappingURL=elkGraph.d.ts.map
@@ -10,12 +10,33 @@ export declare function isElkPlacement(placement: TablePlacement): placement is
10
10
  */
11
11
  export declare function usesPorts(placement: ElkPlacement): boolean;
12
12
  /**
13
- * What ELK is told, for the placement the author picked.
13
+ * Whether the placement reads the coordinate hint a node can carry. Only the
14
+ * views' preset layers and places interactively; the rest derive both from the
15
+ * edges alone, and a hint sent with one of those would be paid for and ignored.
16
+ */
17
+ export declare function usesCoordinateHints(placement: ElkPlacement): boolean;
18
+ /**
19
+ * The box the tables joined to nothing are gathered in, told what the
20
+ * reference tells its own and nothing besides: the ratio, under the layered
21
+ * algorithm around it, which stands them in one column. ELK places the box like any node.
22
+ */
23
+ export declare const GROUP_NODE_OPTIONS: LayoutOptions;
24
+ /**
25
+ * What ELK is told, for the placement it was asked for.
14
26
  *
15
27
  * @example
16
28
  * const graph = { id: 'root', layoutOptions: elkLayoutOptions(placement) };
17
29
  */
18
30
  export declare function elkLayoutOptions(placement: ElkPlacement): LayoutOptions;
31
+ /**
32
+ * What every node in a layout is told, before the ports a placement may add.
33
+ * Only the views' preset says anything at this level, so the rest hand ELK a
34
+ * bare box and let the algorithm's own defaults decide.
35
+ *
36
+ * @example
37
+ * const layoutOptions = elkNodeLayoutOptions(placement);
38
+ */
39
+ export declare function elkNodeLayoutOptions(placement: ElkPlacement): LayoutOptions | null;
19
40
  /**
20
41
  * Every algorithm the placements name. ELK registers the metadata of these and
21
42
  * no others, so it is read off the options rather than listed: a placement
@@ -2,7 +2,11 @@ import { ElkNode, ElkPort } from 'elkjs/lib/elk-api';
2
2
  import { ElkLayoutEdge, ElkLayoutPoint, ElkLayoutRequest } from './elkGraph';
3
3
  /** One port per relationship endpoint, grouped by the table it sits on. */
4
4
  export declare function portsByNode(edges: ElkLayoutEdge[]): Map<string, ElkPort[]>;
5
- /** The graph ELK is handed, which is flat: an ERD nests no table in another. */
5
+ /**
6
+ * The graph ELK is handed. An ERD nests no table in another, so the one node
7
+ * that ever holds children is the group a request packs its unrelated tables
8
+ * into, and every edge stays at the root whatever level its ends sit on.
9
+ */
6
10
  export declare function toElkGraph({ placement, nodes, edges, }: ElkLayoutRequest): ElkNode;
7
11
  /**
8
12
  * Places tables by an ELK algorithm, off the thread that asked for it. What
@@ -1,13 +1,19 @@
1
1
  import { ElkLayoutPoint, ElkLayoutRequest } from './elkGraph';
2
- export { createElkLayoutRequest, type ElkLayoutPoint, type ElkLayoutRequest, toTablePoints, } from './elkGraph';
2
+ export { createElkLayoutRequest, type ElkLayoutPoint, type ElkLayoutRequest, toTablePoints, toViewPoints, } from './elkGraph';
3
3
  export { type ElkPlacement, isElkPlacement } from './elkLayoutOptions';
4
4
  /**
5
- * Where every table goes under the placement the author picked. ELK runs on a
5
+ * How long a placement runs, the worker's own start included, before the wait
6
+ * is worth saying out loud. Under it the answer reads as immediate and a
7
+ * message that appears and goes is worse than none; over it the editor looks stuck.
8
+ */
9
+ export declare const SLOW_LAYOUT_MS = 6000;
10
+ /**
11
+ * Where every table goes under the placement it was asked for. ELK runs on a
6
12
  * worker and only there, because laying a large schema out holds a thread for
7
13
  * long enough to stop the editor drawing.
8
14
  *
9
15
  * @example
10
- * const points = await createElkLayout(createElkLayoutRequest(state, placement));
16
+ * const points = await createElkLayout(request, () => emitter.emit(toast));
11
17
  */
12
- export declare function createElkLayout(request: ElkLayoutRequest): Promise<ElkLayoutPoint[]>;
18
+ export declare function createElkLayout(request: ElkLayoutRequest, onSlow?: () => void): Promise<ElkLayoutPoint[]>;
13
19
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The shadow a panel floating over the canvas casts, the pair radix gives its
3
+ * dropdowns and dialogs. A light panel reads pasted on without it, its border
4
+ * sitting only a few luminance points off the ground behind.
5
+ */
6
+ export declare const floatingShadow: import('@dineug/r-html').CSSTemplateLiterals;
7
+ //# sourceMappingURL=elevation.styles.d.ts.map
@@ -1,3 +1,15 @@
1
1
  import { Theme } from './tokens';
2
2
  export declare const ThemeConfig: Theme;
3
+ /**
4
+ * What the gray, gold and bronze accents take instead: their low steps sit on
5
+ * the gray-4 hover, so a selected row stays on gray-6 and a hovered one eases
6
+ * back to gray-5, as gray-7 would take gray-11 text in light down to 3.76:1.
7
+ */
8
+ export declare const NeutralAccentThemeConfig: Partial<Theme>;
9
+ /**
10
+ * What the light appearance takes instead: its gray 1 to 3 sit too close to lift
11
+ * a table off the canvas, and a step 9 key or line reads under 3:1 on them, so
12
+ * the boxes go white with a gray-8 edge and the keys drop to step 11.
13
+ */
14
+ export declare const LightThemeConfig: Partial<Theme>;
3
15
  //# sourceMappingURL=radix-ui-theme.config.d.ts.map
@@ -26,14 +26,21 @@ export type Theme = {
26
26
  canvasBackground: string;
27
27
  canvasBoundaryBackground: string;
28
28
  tableBackground: string;
29
+ tableHeaderBackground: string;
29
30
  tableSelect: string;
30
31
  tableBorder: string;
32
+ tableShadow: string;
31
33
  memoBackground: string;
32
34
  memoSelect: string;
33
35
  memoBorder: string;
36
+ memoShadow: string;
34
37
  columnSelect: string;
38
+ columnSelectHover: string;
35
39
  columnHover: string;
36
40
  relationshipHover: string;
41
+ visualizationLink: string;
42
+ visualizationColumn: string;
43
+ visualizationRelationship: string;
37
44
  toolbarBackground: string;
38
45
  contextMenuBackground: string;
39
46
  contextMenuSelect: string;
@@ -1,6 +1,7 @@
1
1
  import { EngineContext } from '../engine/context';
2
2
  import { RootState } from '../engine/state';
3
3
  import { Table } from '../internal-types';
4
+ import { GeometrySource } from './draw-relationship/geometrySource';
4
5
  export declare function getWidthGeneration(): number;
5
6
  /**
6
7
  * Invalidates every cached table size. Called from recalculateTableWidth,
@@ -19,6 +20,27 @@ export type ColumnWidth = {
19
20
  autoIncrement: number;
20
21
  unique: number;
21
22
  };
22
- export declare function calcTableHeight(table: Table): number;
23
+ /**
24
+ * The width a view draws a table at: the header name, or the key badge with
25
+ * the widest name and type among the rows given, whichever is wider. The rows
26
+ * are the caller's to name, and the show bits and the column order are the document's, read by no view.
27
+ */
28
+ export declare function calcViewTableWidths(table: Table, state: RootState, columnIds: string[]): ColumnWidth;
29
+ /**
30
+ * The width a view header's name takes. Every ui width was measured at the size
31
+ * and weight the rows are drawn in, and a header is drawn larger and heavier,
32
+ * so the measured width is scaled by both rather than measured a second time.
33
+ */
34
+ export declare function viewHeaderNameWidth(widthName: number): number;
35
+ /** The header band a source draws above its rows, each at its own line height. */
36
+ export declare function tableHeaderHeight(source?: GeometrySource): number;
37
+ /**
38
+ * The height of one row a source draws. The document row is sized around the
39
+ * input box an editor opens in it and the view row around a line of read only
40
+ * text, so the two are independent numbers.
41
+ */
42
+ export declare function tableRowHeight(source?: GeometrySource): number;
43
+ /** The box height for the rows given, every row of the table unless a view shows fewer. */
44
+ export declare function calcTableHeight(table: Table, rowCount?: number, source?: GeometrySource): number;
23
45
  export declare function recalculateTableWidth({ doc: { tableIds }, collections }: RootState, { toWidth }: EngineContext): void;
24
46
  //# sourceMappingURL=calcTable.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { Point } from '../internal-types';
2
+ /** How far a press may travel before its release reads as a drag rather than a click, in screen pixels. */
3
+ export declare const CLICK_SLOP = 4;
4
+ /** Where a pointer event landed: the mouse, or the touch it began with or lifted. */
5
+ export declare function pointOf(evt: Event): Point | null;
6
+ /** Whether a release landed near enough to the press to read as a click rather than a drag. */
7
+ export declare function isClick(from: Point, to: Point): boolean;
8
+ /** A press with the main button and no modifier, the only one a view reads as a click. */
9
+ export declare function isPlainPress(evt: MouseEvent | TouchEvent): boolean;
10
+ /**
11
+ * Calls back once the press given is released as a click. The release is read
12
+ * off the window rather than off the node pressed, since the scene rebuilds
13
+ * that node before the lift, and a press with no point to measure reads as nothing.
14
+ *
15
+ * @example
16
+ * onClickRelease(event.evt, () => setViewPinnedTable(store.state, id, kind));
17
+ */
18
+ export declare function onClickRelease(evt: Event, done: () => void): void;
19
+ //# sourceMappingURL=clickGesture.d.ts.map
@@ -4,6 +4,14 @@ export declare function onStop(event: Event): void;
4
4
  export declare function onStopImmediate(event: Event): void;
5
5
  export declare function isMouseEvent(event: Event): event is MouseEvent;
6
6
  export declare function isTouchEvent(event: Event): event is TouchEvent;
7
+ /** A touch that puts a finger down beside another: a pinch, never a press of its own. */
8
+ export declare function isMultiTouch(event: Event): boolean;
9
+ /**
10
+ * The editor root, which is where a pan has to take the selection off: the top
11
+ * toolbar is a sibling of the scene that pans, so suppressing it any lower
12
+ * leaves a drag that reaches the toolbar free to select its text.
13
+ */
14
+ export declare function editorRootOf(el: HTMLElement): HTMLElement;
7
15
  /**
8
16
  * Takes selection off an element for the length of a gesture and hands back the
9
17
  * undo. A press allowed to start one lets the browser promote the drag to a
@@ -0,0 +1,32 @@
1
+ import { Point } from '../../internal-types';
2
+ /**
3
+ * How far a control point is pushed out, relative to the gap it spans. The
4
+ * reference draws every edge with xyflow's default curvature, and these two
5
+ * numbers are what put its control points where they sit.
6
+ */
7
+ export declare const VIEW_CURVATURE = 0.25;
8
+ /**
9
+ * How many straight chords one view connector's curve is flattened into. Over
10
+ * the run a view lays out, the widest gap between a chord and the true curve
11
+ * stays under the half pixel every geometry reader here works to.
12
+ */
13
+ export declare const VIEW_BEZIER_SEGMENTS = 24;
14
+ /**
15
+ * How far a control point reaches past its own end where the other end lies
16
+ * behind it. The only branch that leaves the box the two ends make, so a
17
+ * culling test carrying this much covers the whole curve.
18
+ */
19
+ export declare function curveReach(gap: number): number;
20
+ /**
21
+ * The two control points of the curve between a connector's turning points.
22
+ * Each leaves straight out of its own end, so the stub run meets the curve
23
+ * without a corner and the whole turn is carried between them.
24
+ */
25
+ export declare function bezierControls(from: Point, fromOutward: Point, to: Point, toOutward: Point): [Point, Point];
26
+ /**
27
+ * That curve as a polyline. Flattening it here is what keeps every reader
28
+ * downstream working on straight segments: the path serialiser, the hit path,
29
+ * the particle measurement and the route box all stay as they were.
30
+ */
31
+ export declare function bezierPolyline(from: Point, fromOutward: Point, to: Point, toOutward: Point, segments?: number): Point[];
32
+ //# sourceMappingURL=bezier.d.ts.map
@@ -1,7 +1,12 @@
1
1
  import { RootState } from '../../engine/state';
2
2
  import { Point, Table } from '../../internal-types';
3
3
  import { ObjectPoint } from '.';
4
- export declare function tableToObjectPoint(state: RootState, table: Table): ObjectPoint;
4
+ import { GeometrySource } from './geometrySource';
5
+ /**
6
+ * The box and the four edge midpoints the sort anchors against, at the point
7
+ * and the size the source given draws the table at.
8
+ */
9
+ export declare function tableToObjectPoint(state: RootState, table: Table, source?: GeometrySource): ObjectPoint;
5
10
  export declare function euclideanDistance(a: Point, b: Point): number;
6
11
  export declare function manhattanDistance(a: Point, b: Point): number;
7
12
  //# sourceMappingURL=calc.d.ts.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Which coordinate system a geometry reader works in: the document, or the
3
+ * view named by its kind. One mode that picks the coordinates, the shown set
4
+ * and the sort channel at once, so a view never redraws the document under it.
5
+ */
6
+ export type GeometrySource = 'document' | 'flow';
7
+ /** The sources that are views, which is also the kind of the view slot each reads. */
8
+ export type ViewSource = Exclude<GeometrySource, 'document'>;
9
+ //# sourceMappingURL=geometrySource.d.ts.map
@@ -1,5 +1,6 @@
1
1
  import { RootState } from '../../engine/state';
2
2
  import { Point } from '../../internal-types';
3
+ import { GeometrySource } from './geometrySource';
3
4
  import { Obstacles } from './route';
4
5
  export type DirtyBox = {
5
6
  left: number;
@@ -31,7 +32,12 @@ export type SortCache = {
31
32
  boxes: Map<string, DirtyBox>;
32
33
  entries: Map<string, RouteEntry>;
33
34
  };
34
- export declare function getSortCache(state: RootState): SortCache;
35
+ /**
36
+ * What the last sort of one source over one store left for the next, a cache
37
+ * per source because the document's boxes and a view's are different layouts
38
+ * of the same tables, and a diff across them would re-route everything each turn.
39
+ */
40
+ export declare function getSortCache(state: RootState, source?: GeometrySource): SortCache;
35
41
  export declare function boundsOfPoints(points: Point[]): DirtyBox;
36
42
  /**
37
43
  * Whether a moved table can change a route. The bounding box rather than the
@@ -1,4 +1,5 @@
1
- import { Point, Relationship, ValuesType } from '../../internal-types';
1
+ import { Point, Relationship, RelationshipPoint, ValuesType } from '../../internal-types';
2
+ import { GeometrySource } from './geometrySource';
2
3
  export declare const DirectionName: {
3
4
  readonly left: "left";
4
5
  readonly right: "right";
@@ -135,11 +136,26 @@ export declare const ANCHOR_EDGE_INSET = 12;
135
136
  * shorter run it touches, so a short run keeps its right angle.
136
137
  */
137
138
  export declare const ROUTE_CHAMFER = 8;
138
- export declare function setStubSlots(relationship: Relationship, slots: readonly [number, number]): void;
139
+ /** One end of a connector as the geometry reads it: which table, where on it, and which way out. */
140
+ export type Anchor = Pick<RelationshipPoint, 'x' | 'y' | 'direction'> & {
141
+ tableId: string;
142
+ };
143
+ export type Anchors = {
144
+ start: Anchor;
145
+ end: Anchor;
146
+ };
147
+ export declare function copyAnchor({ tableId, x, y, direction }: Anchor): Anchor;
148
+ /**
149
+ * Forgets what a source's sorts wrote for these connectors, so a reader sees a
150
+ * source that never sorted them. Per connector, never the whole channel: the
151
+ * channels and their epochs are module-wide, and a page may host two stores.
152
+ */
153
+ export declare function clearSortChannel(relationships: Iterable<Relationship>, source?: GeometrySource): void;
154
+ export declare function setStubSlots(relationship: Relationship, slots: readonly [number, number], source?: GeometrySource): void;
139
155
  /** Falls back to slot zero, which reproduces the pre-stagger geometry. */
140
- export declare function getStubSlots(relationship: Relationship): readonly [number, number];
141
- export declare function setRoute(relationship: Relationship, points: Point[]): void;
142
- export declare function getRoute(relationship: Relationship): Point[] | undefined;
156
+ export declare function getStubSlots(relationship: Relationship, source?: GeometrySource): readonly [number, number];
157
+ export declare function setRoute(relationship: Relationship, points: Point[], source?: GeometrySource): void;
158
+ export declare function getRoute(relationship: Relationship, source?: GeometrySource): Point[] | undefined;
143
159
  /**
144
160
  * How far a connector reaches past its anchor, whichever decoration is furthest
145
161
  * out. The ring shares a centre with the second tick, so its outer edge and the
@@ -158,16 +174,26 @@ export type BBox = {
158
174
  width: number;
159
175
  height: number;
160
176
  };
177
+ /** Opens a sort on one source, retiring every route box that source's previous sort wrote. */
178
+ export declare function nextSortEpoch(source?: GeometrySource): void;
179
+ /**
180
+ * Where a connector's two ends sit, for a reader outside the sort. The
181
+ * document keeps them on the entity, where its sort wrote them; a view keeps
182
+ * its own in its channel, and one it has not sorted yet reads the document's.
183
+ */
184
+ export declare function getAnchors(relationship: Relationship, source?: GeometrySource): Anchors;
161
185
  /**
162
- * Opens a sort, retiring every route box the previous one wrote. Identity
163
- * outlives a sort, so the stamp a route carries is what separates a box for the
164
- * current routes from one the next sort has already replaced.
186
+ * Where a sort leaves a connector's two ends: on the entity for the document,
187
+ * the one derived geometry written to it, and in the channel for a view, which
188
+ * writes nothing to the document. Copied, so the channel never aliases a caller's object.
165
189
  */
166
- export declare function nextSortEpoch(): void;
190
+ export declare function setAnchors(relationship: Relationship, { start, end }: Anchors, source?: GeometrySource): void;
191
+ /** How thick a connector is drawn in the source given, markers and all. */
192
+ export declare function relationshipStrokeWidth(source?: GeometrySource): number;
167
193
  /**
168
194
  * Everywhere a relationship can be drawn, for a culling test that must not lose
169
- * a connector whose anchors are on screen and whose route is not. Without a
195
+ * a connector whose anchors are on screen and whose drawn run is not. Without a
170
196
  * route from this sort the stub ends are unknown, so the padding carries them.
171
197
  */
172
- export declare function getRouteBBox(relationship: Relationship, strokeWidth?: number): BBox;
198
+ export declare function getRouteBBox(relationship: Relationship, strokeWidth?: number, source?: GeometrySource): BBox;
173
199
  //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import { Point, Relationship } from '../../internal-types';
2
2
  import { RelationshipPath } from '.';
3
- export declare function getRelationshipPath(relationship: Relationship): RelationshipPath;
3
+ import { GeometrySource } from './geometrySource';
4
+ export declare function getRelationshipPath(relationship: Relationship, source?: GeometrySource): RelationshipPath;
4
5
  /**
5
6
  * The routing polyline as one d, so a connector is a single element whatever the
6
7
  * router and the corner cuts made of it. The segments are contiguous by
@@ -1,5 +1,6 @@
1
1
  import { RootState } from '../../engine/state';
2
2
  import { Point } from '../../internal-types';
3
+ import { GeometrySource } from './geometrySource';
3
4
  export type Obstacles = {
4
5
  ids: string[];
5
6
  left: Float64Array;
@@ -8,10 +9,11 @@ export type Obstacles = {
8
9
  bottom: Float64Array;
9
10
  };
10
11
  /**
11
- * Every table in the document, not only those carrying a relationship: a table
12
- * with no relationships at all still blocks the view.
12
+ * Every table the source shows, not only those carrying a relationship: a
13
+ * table with no relationships at all still blocks the view. For a view that is
14
+ * the tables it places, at the points it places them.
13
15
  */
14
- export declare function collectObstacles(state: RootState): Obstacles;
16
+ export declare function collectObstacles(state: RootState, source?: GeometrySource): Obstacles;
15
17
  /** Liang–Barsky, with no divisions until a slab actually clips. */
16
18
  export declare function segmentHitsBox(ax: number, ay: number, bx: number, by: number, left: number, top: number, right: number, bottom: number): boolean;
17
19
  /**
@@ -1,3 +1,4 @@
1
1
  import { RootState } from '../../engine/state';
2
- export declare function relationshipSort(state: RootState): void;
2
+ import { GeometrySource } from './geometrySource';
3
+ export declare function relationshipSort(state: RootState, source?: GeometrySource): void;
3
4
  //# sourceMappingURL=sort.d.ts.map
@@ -1,4 +1,5 @@
1
- import { Point, Relationship } from '../../internal-types';
1
+ import { Point } from '../../internal-types';
2
+ import { Anchor, Anchors } from '.';
2
3
  /**
3
4
  * Slot zero keeps the historical PATH_END_HEIGHT, so a relationship that never
4
5
  * went through relationshipSort draws exactly as it did before.
@@ -9,7 +10,7 @@ export declare function stubFor(slot: number): number;
9
10
  * null when they do not. Only this arrangement can collapse: a gap of twice the
10
11
  * stub puts both turning points on one spot, and a smaller gap inverts the path.
11
12
  */
12
- export declare function facingGap(start: Relationship['start'], end: Relationship['end']): number | null;
13
+ export declare function facingGap(start: Anchor, end: Anchor): number | null;
13
14
  /**
14
15
  * Below roughly 2 * MIN_STUB the two cardinality decorations already overlap
15
16
  * each other, which no stub length can fix; the clamp stops short of making it
@@ -27,8 +28,12 @@ export type StubEnds = {
27
28
  export declare function isHorizontal(direction: number): direction is 1 | 2;
28
29
  /** +1 when the anchor's outward normal points right or down. */
29
30
  export declare function outwardSign(direction: number): 1 | -1;
30
- /** The two points a route has to join, given the anchors and their slots. */
31
- export declare function stubEnds(relationship: Relationship): StubEnds;
31
+ /**
32
+ * The two points a route has to join, given the anchors and the slot each end
33
+ * took. Both come from the sort in hand rather than a channel, so the document
34
+ * and a view route from what they just placed and never from each other.
35
+ */
36
+ export declare function stubEnds({ start, end }: Anchors, [startSlot, endSlot]: readonly [number, number]): StubEnds;
32
37
  /**
33
38
  * Where the guide line begins — the short run between the cardinality
34
39
  * decorations and the routed polyline.
@@ -2,6 +2,7 @@ import { Action, AnyAction, DOMTemplateLiterals } from '@dineug/r-html';
2
2
  import { TablePlacement } from '../constants/tablePlacement';
3
3
  import { ValuesType } from '../internal-types';
4
4
  import { ThemeOptions } from '../themes/radix-ui-theme';
5
+ import { GeometrySource } from './draw-relationship/geometrySource';
5
6
  declare const InternalActionType: {
6
7
  readonly openColorPicker: "openColorPicker";
7
8
  readonly closeColorPicker: "closeColorPicker";
@@ -62,6 +63,7 @@ type InternalActionMap = {
62
63
  [InternalActionType.dragSelectStart]: {
63
64
  x: number;
64
65
  y: number;
66
+ source: GeometrySource;
65
67
  };
66
68
  };
67
69
  type ListenerRecord = {
@@ -197,9 +199,11 @@ export declare const dragSelectStartAction: {
197
199
  (payload: {
198
200
  x: number;
199
201
  y: number;
202
+ source: GeometrySource;
200
203
  }): AnyAction<{
201
204
  x: number;
202
205
  y: number;
206
+ source: GeometrySource;
203
207
  }>;
204
208
  toString(): string;
205
209
  type: string;
@@ -24,6 +24,7 @@ export declare const KeyBindingName: {
24
24
  readonly relationshipOneOnly: "relationshipOneOnly";
25
25
  readonly relationshipOneN: "relationshipOneN";
26
26
  readonly tableProperties: "tableProperties";
27
+ readonly focusView: "focusView";
27
28
  readonly zoomIn: "zoomIn";
28
29
  readonly zoomOut: "zoomOut";
29
30
  readonly zoomReset: "zoomReset";
@@ -31,7 +32,7 @@ export declare const KeyBindingName: {
31
32
  readonly zenMode: "zenMode";
32
33
  };
33
34
  export type KeyBindingName = ValuesType<typeof KeyBindingName>;
34
- export declare const KeyBindingNameList: ("undo" | "redo" | "selectAllColumn" | "search" | "stop" | "edit" | "addMemo" | "addTable" | "removeTable" | "addColumn" | "removeColumn" | "primaryKey" | "selectAllTable" | "relationshipZeroOne" | "relationshipZeroN" | "relationshipOneOnly" | "relationshipOneN" | "tableProperties" | "zoomIn" | "zoomOut" | "zoomReset" | "handTool" | "zenMode")[];
35
+ export declare const KeyBindingNameList: ("undo" | "redo" | "selectAllColumn" | "search" | "stop" | "edit" | "addMemo" | "addTable" | "removeTable" | "addColumn" | "removeColumn" | "primaryKey" | "selectAllTable" | "relationshipZeroOne" | "relationshipZeroN" | "relationshipOneOnly" | "relationshipOneN" | "tableProperties" | "focusView" | "zoomIn" | "zoomOut" | "zoomReset" | "handTool" | "zenMode")[];
35
36
  export type KeyBindingMap = Record<KeyBindingName, ShortcutOption[]>;
36
37
  export declare const createKeyBindingMap: () => KeyBindingMap;
37
38
  export declare function shortcutToTuple(shortcut?: string): KeyBindingPress[];
@@ -0,0 +1,34 @@
1
+ import { Subscription } from 'rxjs';
2
+ import { Point } from '../internal-types';
3
+ /**
4
+ * Whether a wheel is a trackpad pinch, which a browser sends as a ctrl wheel.
5
+ * On Apple devices the zoom chord is the command key, so every ctrl wheel is
6
+ * one; elsewhere ctrl is the chord too, and only a wheel short of a notch is.
7
+ */
8
+ export declare function isPinchWheel(event: WheelEvent): boolean;
9
+ /** How much a pinch wheel scales the zoom: the scale the browser encoded in it. */
10
+ export declare function pinchWheelScale({ deltaY }: WheelEvent): number;
11
+ /** Where a pinch stands: how far it has scaled since it began, and its centre now. */
12
+ export type Pinch = {
13
+ scale: number;
14
+ center: Point;
15
+ };
16
+ /**
17
+ * What a scene makes of a pinch beginning at the point given, in its own box:
18
+ * the step to take on every move after, or null to let the pinch go by.
19
+ */
20
+ export type PinchStart = (center: Point) => ((pinch: Pinch) => void) | null;
21
+ /**
22
+ * The pinches a scene box takes besides the wheel: two fingers on a touch
23
+ * screen, and Safari's trackpad pinch, which reaches a page as gesture events.
24
+ * iOS sends both for one pinch, so the fingers win and the gestures stand down.
25
+ *
26
+ * @example
27
+ * const pinch = createPinch(() => root.value, center => step);
28
+ * onMounted(() => addUnsubscribe(pinch.listen()));
29
+ */
30
+ export declare function createPinch(box: () => HTMLElement, start: PinchStart): {
31
+ handleTouchstart: (event: MouseEvent | TouchEvent) => boolean;
32
+ listen: () => Subscription;
33
+ };
34
+ //# sourceMappingURL=pinch.d.ts.map
@@ -1,4 +1,5 @@
1
1
  export declare const toNumString: (value: string) => string;
2
+ export declare const zoomInRange: (value: number) => number;
2
3
  export declare const maxWidthCommentInRange: (value: number) => number;
3
4
  export declare function canvasSizeInRange(size: number | string): number;
4
5
  export declare function zoomLevelInRange(zoom: number): number;
@@ -1 +1 @@
1
- import*as e from"comlink";typeof document>`u`&&Reflect.set(globalThis,`document`,{});const t={force:`force`,layeredHorizontal:`layeredHorizontal`,layeredVertical:`layeredVertical`,flow:`flow`};t.force;function n(e){return e!==t.force}function r(e){return e===t.flow}const i={"elk.spacing.nodeNode":`80`,"elk.separateConnectedComponents":`true`,"elk.spacing.componentComponent":`160`},a=e=>({...i,"elk.algorithm":`layered`,"elk.direction":e,"elk.layered.spacing.nodeNodeBetweenLayers":`160`,"elk.layered.cycleBreaking.strategy":`DEPTH_FIRST`});function o(e){switch(e){case t.layeredHorizontal:return a(`RIGHT`);case t.layeredVertical:return a(`DOWN`);case t.flow:return{...a(`RIGHT`),"elk.layered.nodePlacement.strategy":`SIMPLE`,"elk.layered.spacing.edgeNodeBetweenLayers":`80`}}}const s=[...new Set(Object.values(t).filter(n).map(e=>o(e)[`elk.algorithm`]))],c=`EAST`,l=e=>`edge-${e}-source`,u=e=>`edge-${e}-target`;function d(e,t){return e.side===t.side?e.side===c?e.row-t.row:t.row-e.row:e.side===c?-1:1}function f(e){let t=new Map,n=(e,n)=>{let r=t.get(e);r?r.push(n):t.set(e,[n])};return e.forEach((e,t)=>{n(e.source,{id:l(t),row:e.sourceRow,side:c}),n(e.target,{id:u(t),row:e.targetRow,side:`WEST`})}),new Map([...t].map(([e,t])=>[e,t.sort(d).map(({id:e,side:t})=>({id:e,width:8,height:8,layoutOptions:{"elk.port.side":t}}))]))}function p({placement:e,nodes:t,edges:n}){let i=r(e)?f(n):null;return{id:`root`,layoutOptions:o(e),children:t.map(({id:e,width:t,height:n})=>({id:e,width:t,height:n,...i?{layoutOptions:{"elk.portConstraints":`FIXED_ORDER`},ports:i.get(e)??[]}:{}})),edges:n.map(({source:e,target:t},n)=>({id:`edge-${n}`,sources:[i?l(n):e],targets:[i?u(n):t]}))}}let m=null;function h(){return m??=import(`elkjs/lib/elk.bundled.js`).then(({default:e})=>new e({algorithms:s})),m}const g=new class{async ready(){return await h(),!0}async layout(e){return((await(await h()).layout(p(e))).children??[]).map(({id:e,x:t,y:n})=>({id:e,x:t??0,y:n??0}))}};self.onconnect=t=>{let n=t.ports[0];e.expose(g,n)};
1
+ import*as e from"comlink";typeof document>`u`&&Reflect.set(globalThis,`document`,{});const t={force:`force`,layeredHorizontal:`layeredHorizontal`,layeredVertical:`layeredVertical`,flow:`flow`,viewLayered:`viewLayered`};t.force;function n(e){return e!==t.force}function r(e){return e===t.flow}const i={"elk.algorithm":`layered`,"elk.layered.spacing.baseValue":`40`,"elk.spacing.componentComponent":`80`,"elk.layered.spacing.edgeNodeBetweenLayers":`120`,"elk.layered.considerModelOrder.strategy":`PREFER_EDGES`,"elk.layered.crossingMinimization.forceNodeModelOrder":`true`,"elk.layered.mergeEdges":`true`,"elk.layered.nodePlacement.strategy":`INTERACTIVE`,"elk.layered.layering.strategy":`INTERACTIVE`},a={"elk.alignment":`LEFT`},o={"elk.aspectRatio":`0.5625`},s={"elk.spacing.nodeNode":`80`,"elk.separateConnectedComponents":`true`,"elk.spacing.componentComponent":`160`},c=e=>({...s,"elk.algorithm":`layered`,"elk.direction":e,"elk.layered.spacing.nodeNodeBetweenLayers":`160`,"elk.layered.cycleBreaking.strategy":`DEPTH_FIRST`});function l(e){switch(e){case t.layeredHorizontal:return c(`RIGHT`);case t.layeredVertical:return c(`DOWN`);case t.flow:return{...c(`RIGHT`),"elk.layered.nodePlacement.strategy":`SIMPLE`,"elk.layered.spacing.edgeNodeBetweenLayers":`80`};case t.viewLayered:return{...i}}}function u(e){return e===t.viewLayered?{...a}:null}const d=[...new Set(Object.values(t).filter(n).map(e=>l(e)[`elk.algorithm`]))],f=`EAST`,p=e=>`edge-${e}-source`,m=e=>`edge-${e}-target`;function h(e,t){return e.side===t.side?e.side===f?e.row-t.row:t.row-e.row:e.side===f?-1:1}function g(e){let t=new Map,n=(e,n)=>{let r=t.get(e);r?r.push(n):t.set(e,[n])};return e.forEach((e,t)=>{n(e.source,{id:p(t),row:e.sourceRow,side:f}),n(e.target,{id:m(t),row:e.targetRow,side:`WEST`})}),new Map([...t].map(([e,t])=>[e,t.sort(h).map(({id:e,side:t})=>({id:e,width:8,height:8,layoutOptions:{"elk.port.side":t}}))]))}function _({placement:e,nodes:t,edges:n}){let i=r(e)?g(n):null;return{id:`root`,layoutOptions:l(e),children:t.map(t=>v(t,e,i)),edges:n.map(({source:e,target:t},n)=>({id:`edge-${n}`,sources:[i?p(n):e],targets:[i?m(n):t]}))}}function v({id:e,width:t,height:n,x:r,y:i,children:a},s,c){if(a?.length)return{id:e,width:t,height:n,layoutOptions:{...o},children:a.map(e=>v(e,s,c))};let l={...u(s),...c?{"elk.portConstraints":`FIXED_ORDER`}:{}};return{id:e,width:t,height:n,...r===void 0?{}:{x:r},...i===void 0?{}:{y:i},...Object.keys(l).length?{layoutOptions:l}:{},...c?{ports:c.get(e)??[]}:{}}}function y(e,t,n){return e.flatMap(({id:e,x:r,y:i,children:a})=>{let o=t+(r??0),s=n+(i??0);return a?.length?y(a,o,s):[{id:e,x:o,y:s}]})}let b=null;function x(){return b??=import(`elkjs/lib/elk.bundled.js`).then(({default:e})=>new e({algorithms:d})),b}const S=new class{async ready(){return await x(),!0}async layout(e){return y((await(await x()).layout(_(e))).children??[],0,0)}};self.onconnect=t=>{let n=t.ports[0];e.expose(S,n)};