f1ow 1.0.0 → 1.1.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.
- package/README.md +9 -4
- package/dist/components/Canvas/ConnectionPoints.d.ts +2 -0
- package/dist/components/Canvas/TextHtmlOverlay.d.ts +12 -0
- package/dist/components/shapes/TextLabel.d.ts +1 -1
- package/dist/components/shapes/TextShape.d.ts +1 -0
- package/dist/f1ow-collaboration.js +3804 -0
- package/dist/f1ow.js +4580 -3179
- package/dist/f1ow.umd.cjs +5874 -3946
- package/dist/hooks/useFlowAnimation.d.ts +8 -0
- package/dist/lib/FlowCanvasProps.d.ts +31 -1
- package/dist/lib/collaboration.d.ts +10 -0
- package/dist/lib/index.d.ts +7 -10
- package/dist/store/CanvasStoreContext.d.ts +14 -0
- package/dist/store/useCanvasStore.d.ts +32 -0
- package/dist/syncBridge-CveP4QyQ.js +428 -0
- package/dist/types/index.d.ts +97 -1
- package/dist/utils/connection.d.ts +30 -2
- package/dist/utils/editable.d.ts +2 -0
- package/dist/utils/elbow.d.ts +41 -8
- package/dist/utils/labelMetrics.d.ts +21 -0
- package/dist/utils/markdown.d.ts +14 -0
- package/dist/utils/markdownEditing.d.ts +1 -0
- package/dist/utils/textBinding.d.ts +18 -0
- package/dist/utils/textStyleTargets.d.ts +6 -0
- package/dist/yjsProvider-mWrSFiNG.js +100 -0
- package/package.json +121 -107
package/dist/types/index.d.ts
CHANGED
|
@@ -2,6 +2,27 @@ export type ToolType = 'select' | 'hand' | 'rectangle' | 'ellipse' | 'diamond' |
|
|
|
2
2
|
export type ElementType = 'rectangle' | 'ellipse' | 'diamond' | 'line' | 'arrow' | 'freedraw' | 'text' | 'image';
|
|
3
3
|
export type Arrowhead = 'arrow' | 'triangle' | 'triangle_outline' | 'circle' | 'circle_outline' | 'diamond' | 'diamond_outline' | 'bar' | 'crowfoot_one' | 'crowfoot_many' | 'crowfoot_one_or_many';
|
|
4
4
|
export type LineType = 'sharp' | 'curved' | 'elbow';
|
|
5
|
+
/** Gradient definition for connector strokes */
|
|
6
|
+
export interface LineGradient {
|
|
7
|
+
/** Color stops: [offset (0-1), cssColor] */
|
|
8
|
+
stops: [number, string][];
|
|
9
|
+
/** Gradient follows the path direction */
|
|
10
|
+
type: 'along-path';
|
|
11
|
+
}
|
|
12
|
+
/** Tapered stroke: width varies from start to end */
|
|
13
|
+
export interface LineTaper {
|
|
14
|
+
startWidth: number;
|
|
15
|
+
endWidth: number;
|
|
16
|
+
}
|
|
17
|
+
/** Extended line style options for connectors */
|
|
18
|
+
export interface LineStyleExtension {
|
|
19
|
+
/** Gradient stroke along the connector path */
|
|
20
|
+
gradient?: LineGradient;
|
|
21
|
+
/** Tapered stroke width */
|
|
22
|
+
taper?: LineTaper;
|
|
23
|
+
/** Animated flow direction indicator (dash animation) */
|
|
24
|
+
flowAnimation?: boolean;
|
|
25
|
+
}
|
|
5
26
|
export type FreehandStyle = 'standard' | 'pen' | 'brush' | 'pencil';
|
|
6
27
|
export interface ElementStyle {
|
|
7
28
|
strokeColor: string;
|
|
@@ -27,6 +48,17 @@ export interface BaseElement {
|
|
|
27
48
|
isVisible: boolean;
|
|
28
49
|
/** Bidirectional refs: arrows/text bound to this element */
|
|
29
50
|
boundElements: BoundElement[] | null;
|
|
51
|
+
/**
|
|
52
|
+
* Custom ports defined on this element instance.
|
|
53
|
+
* Used for architecture diagrams where shapes have named I/O points.
|
|
54
|
+
*/
|
|
55
|
+
ports?: Port[];
|
|
56
|
+
/**
|
|
57
|
+
* Monotonic version counter — bumped on every geometry/port mutation.
|
|
58
|
+
* Used by binding system to detect stale worker results and cache invalidation.
|
|
59
|
+
* Auto-managed by the store; consumers should not set this directly.
|
|
60
|
+
*/
|
|
61
|
+
version: number;
|
|
30
62
|
/** Group hierarchy: element belongs to these groups (innermost first, outermost last) */
|
|
31
63
|
groupIds?: string[];
|
|
32
64
|
/**
|
|
@@ -123,6 +155,8 @@ export interface LineElement extends BaseElement {
|
|
|
123
155
|
curvature?: number;
|
|
124
156
|
startBinding: Binding | null;
|
|
125
157
|
endBinding: Binding | null;
|
|
158
|
+
/** Extended line style (gradient, taper, animation) */
|
|
159
|
+
lineStyle?: LineStyleExtension;
|
|
126
160
|
}
|
|
127
161
|
export interface ArrowElement extends BaseElement {
|
|
128
162
|
type: 'arrow';
|
|
@@ -141,6 +175,8 @@ export interface ArrowElement extends BaseElement {
|
|
|
141
175
|
curvature?: number;
|
|
142
176
|
startBinding: Binding | null;
|
|
143
177
|
endBinding: Binding | null;
|
|
178
|
+
/** Extended line style (gradient, taper, animation) */
|
|
179
|
+
lineStyle?: LineStyleExtension;
|
|
144
180
|
}
|
|
145
181
|
export interface FreeDrawElement extends BaseElement {
|
|
146
182
|
type: 'freedraw';
|
|
@@ -208,8 +244,23 @@ export interface SelectionBox {
|
|
|
208
244
|
width: number;
|
|
209
245
|
height: number;
|
|
210
246
|
}
|
|
247
|
+
/** Named anchor positions on a shape's bounding box (compass notation) */
|
|
248
|
+
export type AnchorId = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw' | 'center' | 'auto';
|
|
249
|
+
/** Custom port on an element — user-defined attachment point */
|
|
250
|
+
export interface Port {
|
|
251
|
+
/** Unique port identifier within the element */
|
|
252
|
+
id: string;
|
|
253
|
+
/** Normalized [0-1, 0-1] position on the element's bounding box */
|
|
254
|
+
ratio: [number, number];
|
|
255
|
+
/** Optional display label for the port */
|
|
256
|
+
label?: string;
|
|
257
|
+
/** Optional preferred edge (used for elbow routing direction) */
|
|
258
|
+
edge?: AnchorId;
|
|
259
|
+
}
|
|
260
|
+
/** How the binding target was determined */
|
|
261
|
+
export type SnapMode = 'anchor' | 'port' | 'edge' | 'center';
|
|
211
262
|
/**
|
|
212
|
-
* @deprecated Use
|
|
263
|
+
* @deprecated Use AnchorId instead. Kept for backward-compat exports.
|
|
213
264
|
*/
|
|
214
265
|
export type ConnectionAnchor = 'top' | 'bottom' | 'left' | 'right' | 'center';
|
|
215
266
|
/** Bidirectional reference stored on shapes to track bound connectors/text */
|
|
@@ -221,13 +272,30 @@ export type BoundElement = {
|
|
|
221
272
|
export interface Binding {
|
|
222
273
|
/** The element this end is connected to */
|
|
223
274
|
elementId: string;
|
|
275
|
+
/**
|
|
276
|
+
* Named anchor position. When set, takes precedence over fixedPoint.
|
|
277
|
+
* Resolves to a fixedPoint at bind time, but re-resolves after resize
|
|
278
|
+
* to maintain semantic meaning (e.g. "always top-center").
|
|
279
|
+
* 'auto' = let the system choose the nearest anchor.
|
|
280
|
+
*/
|
|
281
|
+
anchor?: AnchorId;
|
|
282
|
+
/** Custom port ID. When set, takes precedence over anchor and fixedPoint. */
|
|
283
|
+
portId?: string;
|
|
224
284
|
/**
|
|
225
285
|
* Continuous attachment ratio [0-1, 0-1] on target's bounding box.
|
|
226
286
|
* e.g. [0.5, 0] = top center, [1, 0.5] = right center, [0.3, 0.7] = arbitrary.
|
|
287
|
+
* Always populated — serves as resolved cache when anchor/port is set.
|
|
227
288
|
*/
|
|
228
289
|
fixedPoint: [number, number];
|
|
229
290
|
/** Gap between the edge of the shape and the arrow tip (px) */
|
|
230
291
|
gap: number;
|
|
292
|
+
/** How the binding target was determined */
|
|
293
|
+
snapMode: SnapMode;
|
|
294
|
+
/**
|
|
295
|
+
* Version of the target element at bind time.
|
|
296
|
+
* Used to detect stale bindings (e.g. worker results arriving after element changed).
|
|
297
|
+
*/
|
|
298
|
+
elementVersion: number;
|
|
231
299
|
/**
|
|
232
300
|
* Whether to bind to the exact fixedPoint position, or to the shape center.
|
|
233
301
|
* When false (default), the arrow connects from/to the shape's center,
|
|
@@ -250,6 +318,12 @@ export interface SnapTarget {
|
|
|
250
318
|
* - `false`: cursor is in the center zone → attaches to center for auto-routing
|
|
251
319
|
*/
|
|
252
320
|
isPrecise: boolean;
|
|
321
|
+
/** Named anchor if snapped to a cardinal position */
|
|
322
|
+
anchor?: AnchorId;
|
|
323
|
+
/** Custom port ID if snapped to a port */
|
|
324
|
+
portId?: string;
|
|
325
|
+
/** How the snap target was determined */
|
|
326
|
+
snapMode: SnapMode;
|
|
253
327
|
}
|
|
254
328
|
/** State for editing individual points of a line/arrow element */
|
|
255
329
|
export interface LinearEditState {
|
|
@@ -266,3 +340,25 @@ export interface LinearEditState {
|
|
|
266
340
|
/** Whether a point is currently being dragged */
|
|
267
341
|
isDraggingPoint: boolean;
|
|
268
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Consumer-facing configuration for the connection/binding system.
|
|
345
|
+
* Pass via `FlowCanvasProps.connectionConfig`.
|
|
346
|
+
*/
|
|
347
|
+
export interface ConnectionConfig {
|
|
348
|
+
/** Distance outside shape perimeter to activate edge snap (px). Default: 24 */
|
|
349
|
+
snapThreshold?: number;
|
|
350
|
+
/** Hysteresis margin to prevent edge/center mode flickering (px). Default: 6 */
|
|
351
|
+
hysteresisMargin?: number;
|
|
352
|
+
/** Clearance around shapes for elbow routing (px). Default: adaptive */
|
|
353
|
+
elbowMargin?: number;
|
|
354
|
+
/** Hit radius for port dots (px, before zoom compensation). Default: 8 */
|
|
355
|
+
portHitRadius?: number;
|
|
356
|
+
/** Minimum stub length for elbow route endpoints (px). Default: 36 */
|
|
357
|
+
stubLength?: number;
|
|
358
|
+
/** Whether to render custom ports on shapes. Default: true */
|
|
359
|
+
enablePorts?: boolean;
|
|
360
|
+
/** Default line style extension applied to new connectors */
|
|
361
|
+
defaultLineStyle?: LineStyleExtension;
|
|
362
|
+
/** Default line type for new arrows/lines. Default: 'sharp' */
|
|
363
|
+
defaultLineType?: LineType;
|
|
364
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CanvasElement, Point, ConnectionAnchor, Binding, SnapTarget, ArrowElement, LineElement, TextElement, BoundElement } from '../types';
|
|
1
|
+
import { CanvasElement, Point, ConnectionAnchor, Binding, SnapTarget, ArrowElement, LineElement, TextElement, BoundElement, AnchorId, SnapMode } from '../types';
|
|
2
2
|
/** Whether an element can be a connection target */
|
|
3
3
|
export declare function isConnectable(el: CanvasElement): boolean;
|
|
4
4
|
/** Get the 5 named anchor positions for a bounding-box shape */
|
|
@@ -7,6 +7,29 @@ export declare function getConnectionPoints(el: CanvasElement): Record<Connectio
|
|
|
7
7
|
* @deprecated Use fixedPoint-based getEdgePointFromFixedPoint() instead.
|
|
8
8
|
*/
|
|
9
9
|
export declare function getAnchorPosition(el: CanvasElement, anchor: ConnectionAnchor): Point;
|
|
10
|
+
/** Map a named AnchorId to its fixedPoint ratio on the bounding box */
|
|
11
|
+
export declare function anchorToFixedPoint(anchor: AnchorId): [number, number];
|
|
12
|
+
/** Find the nearest cardinal AnchorId for a given fixedPoint */
|
|
13
|
+
export declare function fixedPointToAnchor(fp: [number, number]): AnchorId;
|
|
14
|
+
/** Resolve a port's ratio to a fixedPoint on an element */
|
|
15
|
+
export declare function resolvePort(el: CanvasElement, portId: string): [number, number] | null;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the effective fixedPoint for a binding, respecting priority:
|
|
18
|
+
* portId > anchor > fixedPoint.
|
|
19
|
+
*
|
|
20
|
+
* Returns the resolved fixedPoint and the effective snapMode.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveBindingPoint(binding: Binding, element: CanvasElement): {
|
|
23
|
+
fixedPoint: [number, number];
|
|
24
|
+
snapMode: SnapMode;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Create a Binding from a SnapTarget result.
|
|
28
|
+
* Convenience helper for LinearTool and LinearElementHandles.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createBindingFromSnap(snap: SnapTarget, gap: number, elementVersion: number): Binding;
|
|
31
|
+
/** Check whether a binding's elementVersion matches the current element */
|
|
32
|
+
export declare function isBindingStale(binding: Binding, element: CanvasElement): boolean;
|
|
10
33
|
/**
|
|
11
34
|
* Compute the appropriate gap between a connector and a shape edge,
|
|
12
35
|
* based on both the connector's stroke width and a base offset.
|
|
@@ -21,8 +44,13 @@ export declare function computeFixedPoint(el: CanvasElement, worldPt: Point): [n
|
|
|
21
44
|
/**
|
|
22
45
|
* Convert a fixedPoint ratio back to a world-space target point,
|
|
23
46
|
* then compute the edge intersection from center to that target.
|
|
47
|
+
*
|
|
48
|
+
* @param toward Optional direction hint for center fixedPoint [0.5, 0.5].
|
|
49
|
+
* When the fixedPoint is exactly center, there's no meaningful
|
|
50
|
+
* direction — `toward` provides the other endpoint so we can
|
|
51
|
+
* compute a stable edge exit. Without it, returns the element center.
|
|
24
52
|
*/
|
|
25
|
-
export declare function getEdgePointFromFixedPoint(el: CanvasElement, fixedPoint: [number, number], gap?: number): Point;
|
|
53
|
+
export declare function getEdgePointFromFixedPoint(el: CanvasElement, fixedPoint: [number, number], gap?: number, toward?: Point): Point;
|
|
26
54
|
/**
|
|
27
55
|
* Given a shape and an external world-space point, compute the point on
|
|
28
56
|
* the shape's perimeter closest to `toward`.
|
package/dist/utils/elbow.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ interface BBox {
|
|
|
7
7
|
width: number;
|
|
8
8
|
height: number;
|
|
9
9
|
}
|
|
10
|
+
type BoxLike = Pick<BBox, 'x' | 'y' | 'width' | 'height'>;
|
|
10
11
|
/**
|
|
11
12
|
* Determine the preferred exit direction for elbow routing from a
|
|
12
13
|
* center (imprecise) binding.
|
|
@@ -21,8 +22,11 @@ interface BBox {
|
|
|
21
22
|
* shapes at their vertical center — visually too close to objects and
|
|
22
23
|
* often requiring more bends.
|
|
23
24
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
25
|
+
* When both endpoint shapes are known, prefer the axis with the smaller
|
|
26
|
+
* inter-shape gap (or the orthogonal axis with less overlap). This makes
|
|
27
|
+
* diagonal routes look more intentional than a pure center-to-center
|
|
28
|
+
* heuristic. If only a target point is known, fall back to the normalized
|
|
29
|
+
* center-delta heuristic with a slight vertical bias.
|
|
26
30
|
*
|
|
27
31
|
* This function should be used by BOTH:
|
|
28
32
|
* - The binding system (connection.ts) to compute edge points for
|
|
@@ -31,12 +35,7 @@ interface BBox {
|
|
|
31
35
|
*
|
|
32
36
|
* For PRECISE bindings, always use directionFromFixedPoint instead.
|
|
33
37
|
*/
|
|
34
|
-
export declare function getElbowPreferredDirection(shape:
|
|
35
|
-
x: number;
|
|
36
|
-
y: number;
|
|
37
|
-
width: number;
|
|
38
|
-
height: number;
|
|
39
|
-
}, targetPoint: Point): Direction;
|
|
38
|
+
export declare function getElbowPreferredDirection(shape: BoxLike, targetPoint: Point, targetShape?: BoxLike | null, targetBinding?: Binding | null): Direction;
|
|
40
39
|
/**
|
|
41
40
|
* Determine the exit/entry direction from a binding's fixedPoint.
|
|
42
41
|
* fixedPoint is [fx, fy] in [0-1, 0-1] on the target shape's bbox.
|
|
@@ -67,6 +66,34 @@ export declare function directionFromShapeToPoint(shape: BBox, targetPoint: Poin
|
|
|
67
66
|
* computed edge point from the binding system.
|
|
68
67
|
*/
|
|
69
68
|
export declare function directionFromEdgePoint(shape: BBox, edgePoint: Point): Direction;
|
|
69
|
+
export declare function selectElbowDirectionPair(args: {
|
|
70
|
+
startWorld: Point;
|
|
71
|
+
endWorld: Point;
|
|
72
|
+
startBinding: Binding | null;
|
|
73
|
+
endBinding: Binding | null;
|
|
74
|
+
startShape?: {
|
|
75
|
+
x: number;
|
|
76
|
+
y: number;
|
|
77
|
+
width: number;
|
|
78
|
+
height: number;
|
|
79
|
+
} | null;
|
|
80
|
+
endShape?: {
|
|
81
|
+
x: number;
|
|
82
|
+
y: number;
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
} | null;
|
|
86
|
+
intermediateObstacles?: Array<{
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
width: number;
|
|
90
|
+
height: number;
|
|
91
|
+
}>;
|
|
92
|
+
minStubLength?: number;
|
|
93
|
+
}): {
|
|
94
|
+
startDir: Direction;
|
|
95
|
+
endDir: Direction;
|
|
96
|
+
};
|
|
70
97
|
/**
|
|
71
98
|
* Compute an orthogonal route between two points using a multi-candidate
|
|
72
99
|
* grid-based shortest-path algorithm.
|
|
@@ -99,6 +126,12 @@ export declare function directionFromEdgePoint(shape: BBox, edgePoint: Point): D
|
|
|
99
126
|
export declare function computeElbowRoute(start: Point, end: Point, startDir: Direction, endDir: Direction, startBBox?: BBox | null, endBBox?: BBox | null, minStubLength?: number,
|
|
100
127
|
/** Additional obstacles (intermediate shapes) to avoid — already as BBox */
|
|
101
128
|
intermediateObstacles?: BBox[]): Point[];
|
|
129
|
+
export declare function collectElbowIntermediateObstacles(startWorld: Point, endWorld: Point, allElements: CanvasElement[], excludeIds: Set<string>): Array<{
|
|
130
|
+
x: number;
|
|
131
|
+
y: number;
|
|
132
|
+
width: number;
|
|
133
|
+
height: number;
|
|
134
|
+
}>;
|
|
102
135
|
/** Clear the route cache (call when elements change structurally) */
|
|
103
136
|
export declare function clearElbowRouteCache(): void;
|
|
104
137
|
export declare function computeElbowPoints(startWorld: Point, endWorld: Point, startBinding: Binding | null, endBinding: Binding | null, allElements: CanvasElement[], minStubLength?: number): number[];
|
|
@@ -36,6 +36,27 @@ export declare function measureLabelText(text: string, fontSize: number, fontFam
|
|
|
36
36
|
width: number;
|
|
37
37
|
height: number;
|
|
38
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Compute the CSS half-leading offset for a given font.
|
|
41
|
+
*
|
|
42
|
+
* Konva renders text with `textBaseline='top'` — the glyph top aligns
|
|
43
|
+
* with the node's y position (no leading above).
|
|
44
|
+
* CSS distributes leading equally above and below the content area
|
|
45
|
+
* within each line box. The half-leading is the space ABOVE the glyphs
|
|
46
|
+
* that CSS adds but Konva does not.
|
|
47
|
+
*
|
|
48
|
+
* To align a DOM textarea's visible text with Konva's rendered text,
|
|
49
|
+
* shift the textarea UP by this amount (in canvas-space pixels).
|
|
50
|
+
*
|
|
51
|
+
* Uses `fontBoundingBoxAscent/Descent` for accurate per-font measurement
|
|
52
|
+
* with a safe fallback for older browsers.
|
|
53
|
+
*
|
|
54
|
+
* @param fontSize - Font size in canvas-space pixels
|
|
55
|
+
* @param fontFamily - CSS font-family string
|
|
56
|
+
* @param lineHeight - Line-height multiplier (default: LABEL_LINE_HEIGHT)
|
|
57
|
+
* @returns Half-leading in canvas-space pixels (≥ 0)
|
|
58
|
+
*/
|
|
59
|
+
export declare function computeHalfLeading(fontSize: number, fontFamily: string, lineHeight?: number): number;
|
|
39
60
|
/**
|
|
40
61
|
* Compute the full pill (background rect) dimensions for a connector label.
|
|
41
62
|
*
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function htmlToPlainText(html: string): string;
|
|
2
|
+
/**
|
|
3
|
+
* Render markdown text to inline-styled HTML.
|
|
4
|
+
* Safe for use with `innerHTML` — raw HTML in the source is escaped.
|
|
5
|
+
*/
|
|
6
|
+
export declare function renderMarkdown(text: string): string;
|
|
7
|
+
export declare function markdownToPlainText(text: string): string;
|
|
8
|
+
/** CSS class name for the markdown overlay container */
|
|
9
|
+
export declare const MD_CLASS = "fc-md";
|
|
10
|
+
/**
|
|
11
|
+
* CSS rules for markdown-rendered content.
|
|
12
|
+
* Injected once via a <style> tag by the overlay component.
|
|
13
|
+
*/
|
|
14
|
+
export declare const MD_STYLES = "\n.fc-md { line-height: inherit; }\n.fc-md p { margin: 0; }\n.fc-md h1 { margin: 0; font-weight: bold; font-size: 1.5em; line-height: 1.3; }\n.fc-md h2 { margin: 0; font-weight: bold; font-size: 1.3em; line-height: 1.3; }\n.fc-md h3 { margin: 0; font-weight: bold; font-size: 1.15em; line-height: 1.3; }\n.fc-md h4, .fc-md h5, .fc-md h6 { margin: 0; font-weight: bold; font-size: 1em; }\n.fc-md strong { font-weight: bold; }\n.fc-md em { font-style: italic; }\n.fc-md del { text-decoration: line-through; }\n.fc-md code {\n background: rgba(0,0,0,0.06);\n padding: 0.1em 0.3em;\n border-radius: 3px;\n font-size: 0.9em;\n font-family: 'SF Mono', Monaco, Menlo, Consolas, monospace;\n}\n.fc-md pre {\n background: rgba(0,0,0,0.06);\n padding: 0.4em 0.6em;\n border-radius: 4px;\n font-size: 0.85em;\n overflow-x: auto;\n margin: 0.2em 0;\n}\n.fc-md pre code { background: none; padding: 0; font-size: inherit; }\n.fc-md ul, .fc-md ol { padding-left: 1.5em; margin: 0.15em 0; }\n.fc-md li { margin: 0; }\n.fc-md blockquote {\n border-left: 3px solid rgba(0,0,0,0.15);\n padding-left: 0.8em;\n margin: 0.2em 0;\n color: rgba(0,0,0,0.55);\n}\n.fc-md a { color: #4f8df7; text-decoration: underline; }\n.fc-md hr { border: none; border-top: 1px solid rgba(0,0,0,0.12); margin: 0.3em 0; }\n.fc-md img { max-width: 100%; }\n";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function serializeEditableHtmlToMarkdown(html: string): string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CanvasElement, ElementStyle, Point, TextElement } from '../types';
|
|
2
|
+
export type TextContainerElement = Extract<CanvasElement, {
|
|
3
|
+
type: 'rectangle' | 'ellipse' | 'diamond' | 'image';
|
|
4
|
+
}>;
|
|
5
|
+
export declare function isTextContainerElement(element: CanvasElement): element is TextContainerElement;
|
|
6
|
+
export declare function isPointInsideTextContainer(element: TextContainerElement, point: Point): boolean;
|
|
7
|
+
export declare function findTopmostTextContainerAtPoint(elements: CanvasElement[], point: Point): TextContainerElement | null;
|
|
8
|
+
/**
|
|
9
|
+
* Reorder elements so every bound text element is placed immediately
|
|
10
|
+
* after its container. This keeps a shape and its label at the same
|
|
11
|
+
* logical z-index — shapes stacked above the container occlude the
|
|
12
|
+
* label, and the label never leaks above unrelated foreground elements.
|
|
13
|
+
*
|
|
14
|
+
* Pure function — returns the input reference unchanged when no
|
|
15
|
+
* reordering is required so downstream memoization stays stable.
|
|
16
|
+
*/
|
|
17
|
+
export declare function orderBoundTextWithContainers(elements: CanvasElement[]): CanvasElement[];
|
|
18
|
+
export declare function createBoundTextElement(id: string, container: TextContainerElement, style: ElementStyle): TextElement;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CanvasElement } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve text element ids that should receive font style updates.
|
|
4
|
+
* Includes directly selected text elements and bound text from selected containers.
|
|
5
|
+
*/
|
|
6
|
+
export declare function collectTextStyleTargetIds(selectedIds: string[], elements: CanvasElement[]): string[];
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as Y from "yjs";
|
|
2
|
+
import { WebsocketProvider } from "y-websocket";
|
|
3
|
+
let _doc = null;
|
|
4
|
+
let _provider = null;
|
|
5
|
+
let _config = null;
|
|
6
|
+
let _statusListeners = /* @__PURE__ */ new Set();
|
|
7
|
+
function createCollaborationProvider(config) {
|
|
8
|
+
if (_provider) {
|
|
9
|
+
destroyCollaborationProvider();
|
|
10
|
+
}
|
|
11
|
+
_config = config;
|
|
12
|
+
_doc = new Y.Doc();
|
|
13
|
+
_provider = new WebsocketProvider(
|
|
14
|
+
config.serverUrl,
|
|
15
|
+
config.roomName,
|
|
16
|
+
_doc,
|
|
17
|
+
{
|
|
18
|
+
connect: true,
|
|
19
|
+
params: config.authToken ? { token: config.authToken } : void 0
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
_provider.awareness.setLocalState({
|
|
23
|
+
user: config.user,
|
|
24
|
+
cursor: null,
|
|
25
|
+
selectedIds: []
|
|
26
|
+
});
|
|
27
|
+
_provider.on("status", (event) => {
|
|
28
|
+
const status = event.status;
|
|
29
|
+
for (const listener of _statusListeners) {
|
|
30
|
+
listener(status);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return { doc: _doc, provider: _provider };
|
|
34
|
+
}
|
|
35
|
+
function destroyCollaborationProvider() {
|
|
36
|
+
if (_provider) {
|
|
37
|
+
_provider.awareness.setLocalState(null);
|
|
38
|
+
_provider.disconnect();
|
|
39
|
+
_provider.destroy();
|
|
40
|
+
_provider = null;
|
|
41
|
+
}
|
|
42
|
+
if (_doc) {
|
|
43
|
+
_doc.destroy();
|
|
44
|
+
_doc = null;
|
|
45
|
+
}
|
|
46
|
+
_config = null;
|
|
47
|
+
}
|
|
48
|
+
function getYDoc() {
|
|
49
|
+
return _doc;
|
|
50
|
+
}
|
|
51
|
+
function getYProvider() {
|
|
52
|
+
return _provider;
|
|
53
|
+
}
|
|
54
|
+
function getYElements() {
|
|
55
|
+
return _doc == null ? void 0 : _doc.getMap("elements");
|
|
56
|
+
}
|
|
57
|
+
function getCollaborationConfig() {
|
|
58
|
+
return _config;
|
|
59
|
+
}
|
|
60
|
+
function isCollaborationActive() {
|
|
61
|
+
return _provider !== null && _provider.wsconnected;
|
|
62
|
+
}
|
|
63
|
+
function onStatusChange(listener) {
|
|
64
|
+
_statusListeners.add(listener);
|
|
65
|
+
return () => {
|
|
66
|
+
_statusListeners.delete(listener);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function updateAwareness(update) {
|
|
70
|
+
if (!_provider) return;
|
|
71
|
+
const current = _provider.awareness.getLocalState();
|
|
72
|
+
_provider.awareness.setLocalState({
|
|
73
|
+
...current,
|
|
74
|
+
...update
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function getRemoteAwareness() {
|
|
78
|
+
if (!_provider) return /* @__PURE__ */ new Map();
|
|
79
|
+
const all = _provider.awareness.getStates();
|
|
80
|
+
const localId = _provider.awareness.clientID;
|
|
81
|
+
const remote = /* @__PURE__ */ new Map();
|
|
82
|
+
for (const [clientId, state] of all) {
|
|
83
|
+
if (clientId !== localId && state && state.user) {
|
|
84
|
+
remote.set(clientId, state);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return remote;
|
|
88
|
+
}
|
|
89
|
+
export {
|
|
90
|
+
createCollaborationProvider,
|
|
91
|
+
destroyCollaborationProvider,
|
|
92
|
+
getCollaborationConfig,
|
|
93
|
+
getRemoteAwareness,
|
|
94
|
+
getYDoc,
|
|
95
|
+
getYElements,
|
|
96
|
+
getYProvider,
|
|
97
|
+
isCollaborationActive,
|
|
98
|
+
onStatusChange,
|
|
99
|
+
updateAwareness
|
|
100
|
+
};
|