f1ow 0.1.4 → 1.0.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 +94 -1
- package/dist/components/Canvas/AnnotationsOverlay.d.ts +34 -0
- package/dist/components/shapes/TextLabel.d.ts +16 -0
- package/dist/f1ow.js +12427 -7642
- package/dist/f1ow.umd.cjs +15861 -255
- package/dist/lib/FlowCanvasProps.d.ts +59 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/utils/camera.d.ts +1 -1
- package/dist/utils/connection.d.ts +26 -1
- package/dist/utils/dragSync.d.ts +50 -0
- package/dist/utils/elementRegistry.d.ts +146 -0
- package/dist/utils/labelMetrics.d.ts +49 -0
- package/package.json +107 -99
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { CanvasElement, ElementStyle, ToolType } from '../types';
|
|
2
2
|
import { ContextMenuItem } from '../components/ContextMenu/ContextMenu';
|
|
3
3
|
import { CollaborationConfig } from '../collaboration/types';
|
|
4
|
+
import { CustomElementConfig } from '../utils/elementRegistry';
|
|
5
|
+
import { RenderAnnotationFn } from '../components/Canvas/AnnotationsOverlay';
|
|
4
6
|
export type { ContextMenuItem };
|
|
5
7
|
/** Context passed to custom context menu renderers */
|
|
6
8
|
export interface ContextMenuContext {
|
|
@@ -68,6 +70,42 @@ export interface FlowCanvasProps {
|
|
|
68
70
|
readOnly?: boolean;
|
|
69
71
|
/** Additional CSS class for the root container */
|
|
70
72
|
className?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Render custom annotations, badges, or status indicators on top of canvas elements.
|
|
75
|
+
*
|
|
76
|
+
* The callback receives an `AnnotationContext` with:
|
|
77
|
+
* - `element` — the canvas element being annotated
|
|
78
|
+
* - `screenBounds` — pre-computed screen-space `{ x, y, width, height }`
|
|
79
|
+
* - `scale` — current viewport zoom level
|
|
80
|
+
*
|
|
81
|
+
* Return a React node to render, or `null` to skip.
|
|
82
|
+
* The node is positioned inside a `div` that matches the element's
|
|
83
|
+
* screen bounding box. Use `position: absolute` to place content
|
|
84
|
+
* relative to the element (e.g. `top: -10, right: -10` for a badge).
|
|
85
|
+
*
|
|
86
|
+
* **Important:** The entire overlay is `pointerEvents: 'none'`.
|
|
87
|
+
* Add `pointerEvents: 'auto'` on interactive nodes (buttons, badges).
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```tsx
|
|
91
|
+
* <FlowCanvas
|
|
92
|
+
* renderAnnotation={({ element, scale }) => {
|
|
93
|
+
* if (element.type !== 'rectangle') return null;
|
|
94
|
+
* return (
|
|
95
|
+
* <div style={{
|
|
96
|
+
* position: 'absolute', top: -10, right: -10,
|
|
97
|
+
* pointerEvents: 'auto',
|
|
98
|
+
* // Scale-aware badge sizing:
|
|
99
|
+
* transform: `scale(${1 / scale})`, transformOrigin: 'top right',
|
|
100
|
+
* }}>
|
|
101
|
+
* 🔴
|
|
102
|
+
* </div>
|
|
103
|
+
* );
|
|
104
|
+
* }}
|
|
105
|
+
* />
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
renderAnnotation?: RenderAnnotationFn;
|
|
71
109
|
/**
|
|
72
110
|
* Additional context menu items to append after the built-in items.
|
|
73
111
|
* Can be static items or a function that receives selection context.
|
|
@@ -84,6 +122,27 @@ export interface FlowCanvasProps {
|
|
|
84
122
|
* Pass a `CollaborationConfig` to connect, or `undefined`/`null` to disable.
|
|
85
123
|
*/
|
|
86
124
|
collaboration?: CollaborationConfig | null;
|
|
125
|
+
/**
|
|
126
|
+
* Register custom element types for this canvas instance.
|
|
127
|
+
*
|
|
128
|
+
* Each config is passed to `elementRegistry.register()` once on mount.
|
|
129
|
+
* Custom types go through the same validation pipeline as built-in types;
|
|
130
|
+
* the optional `validate` callback handles type-specific field checks.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```tsx
|
|
134
|
+
* <FlowCanvas
|
|
135
|
+
* customElementTypes={[{
|
|
136
|
+
* type: 'sticky-note',
|
|
137
|
+
* displayName: 'Sticky Note',
|
|
138
|
+
* validate: (el) =>
|
|
139
|
+
* typeof el.content === 'string' || 'content must be a string',
|
|
140
|
+
* defaults: { content: '', color: '#ffeb3b' },
|
|
141
|
+
* }]}
|
|
142
|
+
* />
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
customElementTypes?: CustomElementConfig[];
|
|
87
146
|
/**
|
|
88
147
|
* Configure Web Workers for background processing (elbow routing, SVG export).
|
|
89
148
|
*
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as FlowCanvas } from './FlowCanvas';
|
|
2
2
|
export type { FlowCanvasProps, FlowCanvasRef, FlowCanvasTheme, ContextMenuItem, ContextMenuContext, } from './FlowCanvasProps';
|
|
3
3
|
export { DEFAULT_THEME } from './FlowCanvasProps';
|
|
4
|
+
export type { AnnotationContext, AnnotationScreenBounds, RenderAnnotationFn, } from '../components/Canvas/AnnotationsOverlay';
|
|
4
5
|
export type { CanvasElement, RectangleElement, EllipseElement, DiamondElement, LineElement, ArrowElement, FreeDrawElement, TextElement, ImageElement, BaseElement, ElementStyle, ElementType, ToolType, Point, ViewportState, ConnectionAnchor, BoundElement, Binding, SnapTarget, Arrowhead, LineType, TextAlign, VerticalAlign, ImageScaleMode, ImageCrop, ElementMeta, CanvasOperation, } from '../types';
|
|
5
6
|
export { useCanvasStore } from '../store/useCanvasStore';
|
|
6
7
|
export { DEFAULT_STYLE, STROKE_COLORS, FILL_COLORS, STROKE_WIDTHS, TOOLS, ARROWHEAD_TYPES, LINE_TYPES, ROUGHNESS_CONFIGS } from '../constants';
|
|
@@ -9,6 +10,9 @@ export { distance, normalizeRect, rotatePoint, isPointInRect, getDiamondPoints,
|
|
|
9
10
|
export { exportToDataURL, downloadPNG, exportToJSON, downloadJSON, exportToSVG, downloadSVG } from '../utils/export';
|
|
10
11
|
export { drawArrowhead, arrowheadSize, flatToPoints } from '../utils/arrowheads';
|
|
11
12
|
export { computeCurveControlPoint, quadBezierAt, quadBezierTangent, curveArrowPrev, CURVE_RATIO } from '../utils/curve';
|
|
13
|
+
export { LABEL_PADDING_H, LABEL_PADDING_V, LABEL_CORNER, LABEL_LINE_HEIGHT, LABEL_MIN_WIDTH, measureLabelText, computePillSize } from '../utils/labelMetrics';
|
|
14
|
+
export { elementRegistry, registerCustomElement } from '../utils/elementRegistry';
|
|
15
|
+
export type { CustomElementConfig, ValidationResult } from '../utils/elementRegistry';
|
|
12
16
|
export { computeElbowPoints, computeElbowRoute, simplifyElbowPath, clearElbowRouteCache, directionFromFixedPoint, directionFromPoints, directionFromShapeToPoint, directionFromEdgePoint, getElbowPreferredDirection, } from '../utils/elbow';
|
|
13
17
|
export type { Direction } from '../utils/elbow';
|
|
14
18
|
export { getConnectionPoints, getEdgePoint, getEdgePointFromFixedPoint, computeFixedPoint, getAnchorPosition, findNearestSnapTarget, isConnectable, recomputeBoundPoints, findConnectorsForElement, addBoundElement, removeBoundElement, syncBoundElements, } from '../utils/connection';
|
package/dist/utils/camera.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ViewportState, CanvasElement } from '../types';
|
|
2
2
|
import { AABB } from './performance';
|
|
3
3
|
/** Predefined zoom steps for smooth discrete zooming */
|
|
4
|
-
export declare const ZOOM_STEPS: readonly [0.1, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4, 5];
|
|
4
|
+
export declare const ZOOM_STEPS: readonly [0.1, 0.25, 0.33, 0.5, 0.67, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3, 4, 5];
|
|
5
5
|
/** Default animation duration in ms */
|
|
6
6
|
export declare const DEFAULT_ANIMATION_DURATION = 280;
|
|
7
7
|
export interface ZoomAtPointOptions {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CanvasElement, Point, ConnectionAnchor, Binding, SnapTarget, ArrowElement, LineElement, BoundElement } from '../types';
|
|
1
|
+
import { CanvasElement, Point, ConnectionAnchor, Binding, SnapTarget, ArrowElement, LineElement, TextElement, BoundElement } 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 */
|
|
@@ -120,3 +120,28 @@ export declare function removeBoundElement(shape: CanvasElement, refId: string):
|
|
|
120
120
|
* @param updateElement Callback to persist the shape update
|
|
121
121
|
*/
|
|
122
122
|
export declare function syncBoundElements(connectorId: string, connectorType: 'arrow' | 'line', oldBinding: Binding | null, newBinding: Binding | null, elements: CanvasElement[], updateElement: (id: string, updates: Partial<CanvasElement>) => void): void;
|
|
123
|
+
/**
|
|
124
|
+
* Compute the midpoint position for a text label on a connector (arrow/line).
|
|
125
|
+
* Uses the connector's current points and lineType (sharp/curved/elbow)
|
|
126
|
+
* to find the visual midpoint, then centers the label around it.
|
|
127
|
+
*
|
|
128
|
+
* @param connector - The connector element (ArrowElement | LineElement)
|
|
129
|
+
* @param textWidth - Current label text width (px)
|
|
130
|
+
* @param textHeight - Current label text height (px)
|
|
131
|
+
* @returns `{ x, y }` in world coordinates for the text element.
|
|
132
|
+
*/
|
|
133
|
+
export declare function computeConnectorLabelPosition(connector: LineElement | ArrowElement, textWidth: number, textHeight: number): {
|
|
134
|
+
x: number;
|
|
135
|
+
y: number;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Sync bound text labels for a list of connector elements.
|
|
139
|
+
* Returns an array of text element updates to batch-apply.
|
|
140
|
+
*
|
|
141
|
+
* @param connectorIds - IDs of connectors whose labels need syncing
|
|
142
|
+
* @param elMap - O(1) element lookup map
|
|
143
|
+
*/
|
|
144
|
+
export declare function syncConnectorLabels(connectorIds: Iterable<string>, elMap: Map<string, CanvasElement>): Array<{
|
|
145
|
+
id: string;
|
|
146
|
+
updates: Partial<TextElement>;
|
|
147
|
+
}>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { CanvasElement } from '../types';
|
|
2
|
+
/** Shared padding between shape containers and their bound text. */
|
|
3
|
+
export declare const BOUND_TEXT_PADDING = 4;
|
|
4
|
+
/** Shape types that can contain bound text. */
|
|
5
|
+
export declare const CONTAINER_TYPES: ReadonlySet<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Compute the stored position for bound text inside a shape container.
|
|
8
|
+
*
|
|
9
|
+
* @param container The container shape (needs x, y, width, height)
|
|
10
|
+
* @param text The text element (needs height, optionally verticalAlign)
|
|
11
|
+
* @returns `{ x, y, width }` updates to apply on the text element
|
|
12
|
+
*/
|
|
13
|
+
export declare function computeBoundTextPosition(container: {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
}, text: {
|
|
19
|
+
height: number;
|
|
20
|
+
verticalAlign?: string;
|
|
21
|
+
}): {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
width: number;
|
|
25
|
+
};
|
|
26
|
+
export interface DragSyncResult {
|
|
27
|
+
/** Batched updates to apply to the store in a single write. */
|
|
28
|
+
updates: Array<{
|
|
29
|
+
id: string;
|
|
30
|
+
updates: Partial<CanvasElement>;
|
|
31
|
+
}>;
|
|
32
|
+
/** IDs of connectors that were recomputed (for dedup / further processing). */
|
|
33
|
+
processedConnectorIds: Set<string>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* After one or more elements are moved / resized, recompute:
|
|
37
|
+
*
|
|
38
|
+
* 1. Connector bound-points for all attached connectors
|
|
39
|
+
* 2. Bound text positions for shape containers
|
|
40
|
+
* 3. Connector-label positions (depend on updated connector geometry)
|
|
41
|
+
*
|
|
42
|
+
* Returns all updates as a flat array — the caller is responsible for
|
|
43
|
+
* applying them to the store (single `batchUpdateElements` call).
|
|
44
|
+
*
|
|
45
|
+
* @param movedIds IDs of elements that were moved / resized
|
|
46
|
+
* @param elements Current **full** element list (post position-write)
|
|
47
|
+
* @param skipIds Optional set of IDs to skip (e.g. group-internal
|
|
48
|
+
* elements that already moved together)
|
|
49
|
+
*/
|
|
50
|
+
export declare function syncAfterDrag(movedIds: Iterable<string>, elements: CanvasElement[], skipIds?: ReadonlySet<string>): DragSyncResult;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ─── Element Registry ────────────────────────────────────────────────────────
|
|
3
|
+
*
|
|
4
|
+
* A plugin/extension point that lets consumers register custom element types
|
|
5
|
+
* alongside the 8 built-in types. Every element passing through
|
|
6
|
+
* `addElement`, `updateElement`, or `setElements` is validated here first.
|
|
7
|
+
*
|
|
8
|
+
* Built-in types (rectangle | ellipse | diamond | line | arrow |
|
|
9
|
+
* freedraw | text | image) are pre-validated with field-level checks.
|
|
10
|
+
* Custom types only need to pass the common base checks; additional
|
|
11
|
+
* field validation is supplied via the `validate` callback.
|
|
12
|
+
*
|
|
13
|
+
* @example — register a custom type globally before rendering:
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { registerCustomElement } from 'f1ow';
|
|
16
|
+
*
|
|
17
|
+
* registerCustomElement({
|
|
18
|
+
* type: 'sticky-note',
|
|
19
|
+
* displayName: 'Sticky Note',
|
|
20
|
+
* validate: (el) => typeof el.content === 'string' || 'content must be a string',
|
|
21
|
+
* defaults: { content: '', color: '#ffeb3b' },
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @example — or pass directly to the component (registered on mount):
|
|
26
|
+
* ```tsx
|
|
27
|
+
* <FlowCanvas
|
|
28
|
+
* customElementTypes={[{
|
|
29
|
+
* type: 'sticky-note',
|
|
30
|
+
* validate: (el) => typeof el.content === 'string' || 'content must be a string',
|
|
31
|
+
* }]}
|
|
32
|
+
* />
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
/** Result of a validation call. */
|
|
36
|
+
export type ValidationResult = {
|
|
37
|
+
valid: true;
|
|
38
|
+
} | {
|
|
39
|
+
valid: false;
|
|
40
|
+
error: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Configuration object for a custom element type.
|
|
44
|
+
*
|
|
45
|
+
* @template T - Shape of the custom element's extra fields.
|
|
46
|
+
*/
|
|
47
|
+
export interface CustomElementConfig<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
48
|
+
/**
|
|
49
|
+
* Unique type identifier.
|
|
50
|
+
* Must not conflict with a built-in type unless `allowOverride` is `true`.
|
|
51
|
+
*/
|
|
52
|
+
type: string;
|
|
53
|
+
/** Human-readable name used in error/warning messages. Defaults to `type`. */
|
|
54
|
+
displayName?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Additional validator for type-specific fields.
|
|
57
|
+
* Called **after** base-field (id, x, y, width, height, rotation, style)
|
|
58
|
+
* validation passes.
|
|
59
|
+
*
|
|
60
|
+
* Return `true` if the element is valid, or a string describing the error.
|
|
61
|
+
*/
|
|
62
|
+
validate?: (element: Record<string, unknown>) => true | string;
|
|
63
|
+
/**
|
|
64
|
+
* Default field values merged into the element object when it is added via
|
|
65
|
+
* `addElement`. Fields already present on the element are NOT overwritten.
|
|
66
|
+
* Only applied to elements whose type matches this config.
|
|
67
|
+
*/
|
|
68
|
+
defaults?: Partial<T>;
|
|
69
|
+
/**
|
|
70
|
+
* Allow replacing an existing registration (built-in or custom).
|
|
71
|
+
* Useful when a consumer wants to tighten / relax built-in validation.
|
|
72
|
+
* Default: `false`.
|
|
73
|
+
*/
|
|
74
|
+
allowOverride?: boolean;
|
|
75
|
+
}
|
|
76
|
+
declare class ElementRegistryClass {
|
|
77
|
+
private customs;
|
|
78
|
+
/**
|
|
79
|
+
* Register a custom element type.
|
|
80
|
+
*
|
|
81
|
+
* @throws If the type already exists and `allowOverride` is not `true`.
|
|
82
|
+
*/
|
|
83
|
+
register(config: CustomElementConfig): void;
|
|
84
|
+
/** Returns `true` if the type is known (built-in or custom). */
|
|
85
|
+
isRegistered(type: string): boolean;
|
|
86
|
+
/** Retrieve the custom config for a type (undefined for built-in types). */
|
|
87
|
+
getCustomConfig(type: string): CustomElementConfig | undefined;
|
|
88
|
+
/** All registered type names, built-in first then custom. */
|
|
89
|
+
getRegisteredTypes(): string[];
|
|
90
|
+
/**
|
|
91
|
+
* Validate a full element before it enters the canvas store.
|
|
92
|
+
*
|
|
93
|
+
* Checks:
|
|
94
|
+
* 1. Non-null object with required base fields (id, type, x, y, w, h, rotation, style)
|
|
95
|
+
* 2. `type` is a known/registered type
|
|
96
|
+
* 3. Type-specific field checks for all 8 built-in types
|
|
97
|
+
* 4. Custom `validate` callback (custom types only)
|
|
98
|
+
*/
|
|
99
|
+
validateElement(element: unknown): ValidationResult;
|
|
100
|
+
/**
|
|
101
|
+
* Validate a partial update before it is applied to an existing element.
|
|
102
|
+
*
|
|
103
|
+
* Prevents overwriting immutable fields (`id` and `type`), and checks
|
|
104
|
+
* numeric fields for finiteness.
|
|
105
|
+
*/
|
|
106
|
+
validateUpdate(updates: Record<string, unknown>): ValidationResult;
|
|
107
|
+
/**
|
|
108
|
+
* Merge custom `defaults` into the element.
|
|
109
|
+
* Existing fields on the element take priority — defaults only fill gaps.
|
|
110
|
+
* Only active when the element's type has a custom config with `defaults`.
|
|
111
|
+
*/
|
|
112
|
+
applyDefaults<T extends {
|
|
113
|
+
type?: unknown;
|
|
114
|
+
}>(element: T): T;
|
|
115
|
+
private _validateStyle;
|
|
116
|
+
private _validateBuiltinFields;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The global element registry singleton.
|
|
120
|
+
*
|
|
121
|
+
* Pre-populated with field-level validators for all 8 built-in element types.
|
|
122
|
+
* Imported by the canvas store to gate every element mutation.
|
|
123
|
+
*
|
|
124
|
+
* Use `elementRegistry.register()` or the `registerCustomElement()` helper
|
|
125
|
+
* to add new element types before rendering `<FlowCanvas>`.
|
|
126
|
+
*/
|
|
127
|
+
export declare const elementRegistry: ElementRegistryClass;
|
|
128
|
+
/**
|
|
129
|
+
* Shorthand to register a custom element type on the global registry.
|
|
130
|
+
*
|
|
131
|
+
* Equivalent to `elementRegistry.register(config)`.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```ts
|
|
135
|
+
* import { registerCustomElement } from 'f1ow';
|
|
136
|
+
*
|
|
137
|
+
* registerCustomElement({
|
|
138
|
+
* type: 'sticky-note',
|
|
139
|
+
* displayName: 'Sticky Note',
|
|
140
|
+
* validate: (el) => typeof el.content === 'string' || 'content must be a string',
|
|
141
|
+
* defaults: { content: '', color: '#ffeb3b' },
|
|
142
|
+
* });
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export declare function registerCustomElement(config: CustomElementConfig): void;
|
|
146
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* labelMetrics.ts
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for connector label sizing — shared by both
|
|
5
|
+
* the Konva display path (TextShape render) and the DOM textarea editor.
|
|
6
|
+
*
|
|
7
|
+
* By measuring text with the same Canvas 2D API that Konva uses internally,
|
|
8
|
+
* both modes produce identical dimensions → no visual "jump" between
|
|
9
|
+
* display and editing.
|
|
10
|
+
*
|
|
11
|
+
* @see docs/CONNECTOR_LABEL_DESIGN.md
|
|
12
|
+
*/
|
|
13
|
+
/** Horizontal padding inside the pill background (px, canvas-space) */
|
|
14
|
+
export declare const LABEL_PADDING_H = 8;
|
|
15
|
+
/** Vertical padding inside the pill background (px, canvas-space) */
|
|
16
|
+
export declare const LABEL_PADDING_V = 4;
|
|
17
|
+
/** Corner radius of the pill background (px, canvas-space) */
|
|
18
|
+
export declare const LABEL_CORNER = 4;
|
|
19
|
+
/** Line-height multiplier — must match Konva <Text lineHeight> */
|
|
20
|
+
export declare const LABEL_LINE_HEIGHT = 1.18;
|
|
21
|
+
/** Minimum text content width to avoid zero-width pill */
|
|
22
|
+
export declare const LABEL_MIN_WIDTH = 10;
|
|
23
|
+
/**
|
|
24
|
+
* Measure text width/height using Canvas 2D — the same engine Konva uses.
|
|
25
|
+
*
|
|
26
|
+
* This function is the **single measurement source** for connector labels.
|
|
27
|
+
* Both the Konva `<Text>` node and the DOM `<textarea>` editor derive
|
|
28
|
+
* their dimensions from these numbers.
|
|
29
|
+
*
|
|
30
|
+
* @param text - The label string (single-line; newlines ignored)
|
|
31
|
+
* @param fontSize - Font size in canvas-space pixels
|
|
32
|
+
* @param fontFamily - CSS font-family string
|
|
33
|
+
* @returns `{ width, height }` in canvas-space pixels (not screen pixels)
|
|
34
|
+
*/
|
|
35
|
+
export declare function measureLabelText(text: string, fontSize: number, fontFamily: string): {
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Compute the full pill (background rect) dimensions for a connector label.
|
|
41
|
+
*
|
|
42
|
+
* @param textWidth - Measured text content width (from `measureLabelText`)
|
|
43
|
+
* @param textHeight - Measured text content height (from `measureLabelText`)
|
|
44
|
+
* @returns `{ width, height }` of the pill in canvas-space pixels
|
|
45
|
+
*/
|
|
46
|
+
export declare function computePillSize(textWidth: number, textHeight: number): {
|
|
47
|
+
width: number;
|
|
48
|
+
height: number;
|
|
49
|
+
};
|
package/package.json
CHANGED
|
@@ -1,99 +1,107 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "f1ow",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "Interactive canvas drawing toolkit built on KonvaJS — drop-in React component for diagrams, sketches & whiteboards",
|
|
6
|
-
"author": "Nuumz <info@nuumz.com>",
|
|
7
|
-
"homepage": "https://github.com/nuumz/f1ow-canvas#readme",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/nuumz/f1ow-canvas.git"
|
|
11
|
-
},
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/nuumz/f1ow-canvas/issues"
|
|
14
|
-
},
|
|
15
|
-
"main": "./dist/f1ow.umd.cjs",
|
|
16
|
-
"module": "./dist/f1ow.js",
|
|
17
|
-
"types": "./dist/lib/index.d.ts",
|
|
18
|
-
"exports": {
|
|
19
|
-
".": {
|
|
20
|
-
"types": "./dist/lib/index.d.ts",
|
|
21
|
-
"import": "./dist/f1ow.js",
|
|
22
|
-
"require": "./dist/f1ow.umd.cjs"
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
"files": [
|
|
26
|
-
"dist",
|
|
27
|
-
"LICENSE",
|
|
28
|
-
"README.md"
|
|
29
|
-
],
|
|
30
|
-
"sideEffects": false,
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"react
|
|
69
|
-
"react-
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
|
|
99
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "f1ow",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Interactive canvas drawing toolkit built on KonvaJS — drop-in React component for diagrams, sketches & whiteboards",
|
|
6
|
+
"author": "Nuumz <info@nuumz.com>",
|
|
7
|
+
"homepage": "https://github.com/nuumz/f1ow-canvas#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/nuumz/f1ow-canvas.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/nuumz/f1ow-canvas/issues"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/f1ow.umd.cjs",
|
|
16
|
+
"module": "./dist/f1ow.js",
|
|
17
|
+
"types": "./dist/lib/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/lib/index.d.ts",
|
|
21
|
+
"import": "./dist/f1ow.js",
|
|
22
|
+
"require": "./dist/f1ow.umd.cjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"LICENSE",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"sideEffects": false,
|
|
31
|
+
"scripts": {
|
|
32
|
+
"dev": "vite",
|
|
33
|
+
"build": "vite build",
|
|
34
|
+
"build:lib": "vite build --mode lib",
|
|
35
|
+
"preview": "vite preview",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"prepublishOnly": "npm run typecheck && npm run build:lib"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": ">=17.0.0",
|
|
41
|
+
"react-dom": ">=17.0.0",
|
|
42
|
+
"konva": ">=9.0.0",
|
|
43
|
+
"react-konva": ">=18.0.0",
|
|
44
|
+
"zustand": ">=5.0.0",
|
|
45
|
+
"yjs": ">=13.0.0",
|
|
46
|
+
"y-websocket": ">=2.0.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"konva": {
|
|
50
|
+
"optional": false
|
|
51
|
+
},
|
|
52
|
+
"react-konva": {
|
|
53
|
+
"optional": false
|
|
54
|
+
},
|
|
55
|
+
"zustand": {
|
|
56
|
+
"optional": false
|
|
57
|
+
},
|
|
58
|
+
"yjs": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
61
|
+
"y-websocket": {
|
|
62
|
+
"optional": true
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@types/node": "^25.2.1",
|
|
67
|
+
"@types/rbush": "^4.0.0",
|
|
68
|
+
"@types/react": "^18.3.18",
|
|
69
|
+
"@types/react-dom": "^18.3.5",
|
|
70
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
71
|
+
"konva": "^9.3.18",
|
|
72
|
+
"lucide-react": "^0.468.0",
|
|
73
|
+
"nanoid": "^5.0.9",
|
|
74
|
+
"rbush": "^4.0.1",
|
|
75
|
+
"react": "^18.3.1",
|
|
76
|
+
"react-dom": "^18.3.1",
|
|
77
|
+
"react-konva": "^18.2.10",
|
|
78
|
+
"typescript": "^5.7.3",
|
|
79
|
+
"vite": "^6.0.7",
|
|
80
|
+
"vite-plugin-dts": "^4.3.0",
|
|
81
|
+
"y-websocket": "^3.0.0",
|
|
82
|
+
"yjs": "^13.6.29",
|
|
83
|
+
"zustand": "^5.0.3"
|
|
84
|
+
},
|
|
85
|
+
"keywords": [
|
|
86
|
+
"canvas",
|
|
87
|
+
"drawing",
|
|
88
|
+
"konvajs",
|
|
89
|
+
"react",
|
|
90
|
+
"whiteboard",
|
|
91
|
+
"diagram",
|
|
92
|
+
"flowchart",
|
|
93
|
+
"react-component",
|
|
94
|
+
"konva",
|
|
95
|
+
"collaborative",
|
|
96
|
+
"vector",
|
|
97
|
+
"sketch"
|
|
98
|
+
],
|
|
99
|
+
"license": "MIT",
|
|
100
|
+
"pnpm": {
|
|
101
|
+
"overrides": {
|
|
102
|
+
"minimatch@9": "9.0.7",
|
|
103
|
+
"minimatch@10": "10.2.1",
|
|
104
|
+
"ajv": "8.18.0"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|