@visualli/react 0.1.6 → 0.2.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 +13 -5
- package/dist/index.cjs +1900 -2032
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +355 -97
- package/dist/index.d.ts +355 -97
- package/dist/index.js +2005 -2094
- package/dist/index.js.map +1 -1
- package/fonts/Caveat-Variable.ttf +0 -0
- package/licenses/visualli-design-system/LICENSE +9 -0
- package/licenses/visualli-design-system/NOTICE.md +6 -0
- package/package.json +9 -4
- package/src/VisualliCanvas.tsx +453 -408
- package/src/VisualliRenderer.tsx +90 -112
- package/src/components/A11yLayer.tsx +73 -0
- package/src/components/KonvaContainer.tsx +28 -237
- package/src/components/KonvaContainerLabelLayer.tsx +41 -0
- package/src/components/KonvaContainerLayer.tsx +34 -33
- package/src/components/KonvaEdge.tsx +25 -240
- package/src/components/KonvaEdgeLayer.tsx +69 -49
- package/src/components/KonvaNode.tsx +21 -156
- package/src/components/KonvaNodeLayer.tsx +102 -34
- package/src/components/KonvaStage.tsx +17 -3
- package/src/components/NavigationStack.tsx +16 -159
- package/src/components/Overlays.tsx +327 -0
- package/src/components/ZoomControls.tsx +3 -107
- package/src/components/useFrames.ts +30 -0
- package/src/context/VisualliContext.tsx +3 -3
- package/src/design/choreography.ts +157 -0
- package/src/design/containers.ts +150 -0
- package/src/design/design.ts +115 -0
- package/src/design/drawing.ts +303 -0
- package/src/design/measure.ts +34 -0
- package/src/design/runtime.ts +154 -0
- package/src/design/useDesign.ts +38 -0
- package/src/generated/specCss.ts +15 -0
- package/src/hooks/index.ts +0 -2
- package/src/hooks/useKonvaRenderer.ts +13 -18
- package/src/hooks/useLayerChoreography.ts +159 -0
- package/src/hooks/useViewportNodes.ts +0 -1
- package/src/index.ts +22 -22
- package/src/stores/stores.ts +2 -2
- package/src/stores/useViewportStore.ts +12 -2
- package/src/animations/index.ts +0 -2
- package/src/animations/konvaLayerTransition.ts +0 -223
- package/src/components/SketchyBoxKonva.tsx +0 -121
- package/src/config/blobShapes.ts +0 -204
- package/src/config/index.ts +0 -21
- package/src/config/textScaling.ts +0 -69
- package/src/hooks/useKonvaLayerTransition.ts +0 -221
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,38 @@
|
|
|
1
1
|
import React$1 from 'react';
|
|
2
|
-
import { VisualliDocument, FlatNode, VisualliLayer, NodeMap, ViewportState, IRenderConfigStore, ISelectionStore, MindMapConnection } from '@visualli/core';
|
|
3
|
-
export {
|
|
2
|
+
import { ThemeInput, Comfort, VisualliDocument, FlatNode, VisualliLayer, NodeMap, ViewportState, IRenderConfigStore, ISelectionStore, ThemeName, ResolvedComfort, Metrics, MindMapConnection, Hull, LabelSide, SemanticAnchor, IdeaMeasure } from '@visualli/core';
|
|
3
|
+
export { BLOB_SHAPES, Comfort, DESIGN_SYSTEM_VERSION, FitResult, IDEA, LABEL_GROWTH, METRICS, RINGS, THEME_NAMES, TOKENS, TOPICS, ThemeInput, ThemeName, TopicName, arrowPath, blobPath, blobRadius, calculateFitCenter, calculateFitView, calculateFitZoom, edgePath, getChildLayerForNode, getConnectionsForLayer, getLayerForNavigation, getTokens, ideaColor, ideaSize, ideaStyle, labelGrowth, resolveComfort, resolveTheme, shapeForLevel, topicStyle } from '@visualli/core';
|
|
4
4
|
import * as zustand from 'zustand';
|
|
5
5
|
import Konva from 'konva';
|
|
6
6
|
import * as konva_lib_Stage from 'konva/lib/Stage';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
interface DesignSystemAssets {
|
|
9
|
+
/**
|
|
10
|
+
* Where the bundled Caveat font file is served from (URL of the directory that
|
|
11
|
+
* contains `Caveat-Variable.ttf`). Defaults to the copy shipped inside the npm
|
|
12
|
+
* package, via jsDelivr.
|
|
13
|
+
*/
|
|
14
|
+
fontBaseUrl?: string;
|
|
15
|
+
/** Set false to skip the Google Fonts stylesheet (Kalam + Atkinson Hyperlegible), e.g. when self-hosting them. */
|
|
16
|
+
loadWebFonts?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Inject the spec CSS and font declarations once. Safe to call repeatedly and on the server (no-op).
|
|
20
|
+
* The returned promise settles when the web-font stylesheet has loaded (its @font-face rules must exist
|
|
21
|
+
* before document.fonts.load() can fetch anything).
|
|
22
|
+
*/
|
|
23
|
+
declare function ensureDesignSystemStyles(assets?: DesignSystemAssets): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Resolves once the canvas fonts are usable (or after `timeoutMs`, so an
|
|
26
|
+
* offline reader still gets a map in the fallback faces).
|
|
27
|
+
*/
|
|
28
|
+
declare function loadCanvasFonts(sheet?: Promise<void>, timeoutMs?: number): Promise<void>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Any of the 8 design-system themes ('light', 'dark', 'focus-light', 'focus-dark', 'colorsafe-light',
|
|
32
|
+
* 'colorsafe-dark', 'contrast-light', 'contrast-dark'), a family ('focus' | 'colorsafe' | 'contrast'),
|
|
33
|
+
* or 'auto' (follow the reader's colour scheme). 'light' | 'dark' | 'auto' are the pre-0.2 values and keep working.
|
|
34
|
+
*/
|
|
35
|
+
type VisualliTheme = ThemeInput;
|
|
9
36
|
interface VisualliRendererProps {
|
|
10
37
|
/**
|
|
11
38
|
* Raw JSONL string — the content of a .visualli file.
|
|
@@ -29,18 +56,35 @@ interface VisualliRendererProps {
|
|
|
29
56
|
*/
|
|
30
57
|
useWorker?: boolean;
|
|
31
58
|
/**
|
|
32
|
-
* Colour theme.
|
|
33
|
-
* - '
|
|
34
|
-
* - 'light' → always light background
|
|
35
|
-
* - 'auto' → follows the OS/browser prefers-color-scheme
|
|
59
|
+
* Colour theme (see VisualliTheme).
|
|
60
|
+
* - 'auto' follows prefers-color-scheme (and switches to high contrast under forced-colors)
|
|
36
61
|
* @default 'light'
|
|
37
62
|
*/
|
|
38
63
|
theme?: VisualliTheme;
|
|
64
|
+
/** Comfort settings: readable type, larger text, reduced motion ('system' follows the OS). */
|
|
65
|
+
comfort?: Comfort;
|
|
66
|
+
/** Switch to the high-contrast theme under forced-colors. @default true */
|
|
67
|
+
respectForcedColors?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Interaction layout: 'auto' follows the reader's input (touch -> bottom-sheet peek and larger
|
|
70
|
+
* controls, pointer -> floating peek on hover); force one with 'touch' or 'pointer'.
|
|
71
|
+
* @default 'auto'
|
|
72
|
+
*/
|
|
73
|
+
layout?: 'auto' | 'touch' | 'pointer';
|
|
74
|
+
/** Where the zoom / fit controls sit: the design system's 'bottom-right' (default) or the pre-0.2 'top-right'. */
|
|
75
|
+
/**
|
|
76
|
+
* The map is the page (an app such as Visualli's web app): it takes every touch gesture, so the browser never
|
|
77
|
+
* zooms or scrolls the page — the design system's `.vi-map.is-app` (`touch-action: none`). Leave it off when the
|
|
78
|
+
* map is embedded in a scrolling page: one finger then still scrolls the page, two fingers pinch the map.
|
|
79
|
+
*/
|
|
80
|
+
app?: boolean;
|
|
81
|
+
/** Where the zoom / fit controls sit: 'top-right' (default, the design system's placement) or 'bottom-right'. */
|
|
82
|
+
controlsPosition?: 'top-right' | 'bottom-right';
|
|
39
83
|
/**
|
|
40
84
|
* Enable chromatic immersion background effect.
|
|
41
85
|
* When true:
|
|
42
|
-
* - Root layer (level 0) shows
|
|
43
|
-
* - Child layers
|
|
86
|
+
* - Root layer (level 0) shows the plain canvas
|
|
87
|
+
* - Child layers are tinted with the parent idea's topic colour
|
|
44
88
|
* @default false
|
|
45
89
|
*/
|
|
46
90
|
chromaticImmersion?: boolean;
|
|
@@ -56,12 +100,16 @@ interface VisualliRendererProps {
|
|
|
56
100
|
* @default '100%'
|
|
57
101
|
*/
|
|
58
102
|
height?: string | number;
|
|
103
|
+
/** Directory URL the bundled Caveat font is served from (defaults to the copy in the npm package, via jsDelivr). */
|
|
104
|
+
fontBaseUrl?: DesignSystemAssets['fontBaseUrl'];
|
|
105
|
+
/** Set false when you load Kalam and Atkinson Hyperlegible yourself. */
|
|
106
|
+
loadWebFonts?: DesignSystemAssets['loadWebFonts'];
|
|
59
107
|
/** Additional CSS class on the root element. */
|
|
60
108
|
className?: string;
|
|
61
109
|
/** Additional inline styles merged onto the root element. */
|
|
62
110
|
style?: React$1.CSSProperties;
|
|
63
111
|
}
|
|
64
|
-
declare function VisualliRenderer({ visualliString, visualliFile, theme, width, height, useWorker, chromaticImmersion, className, style, }: VisualliRendererProps): React$1.JSX.Element;
|
|
112
|
+
declare function VisualliRenderer({ visualliString, visualliFile, theme, comfort, respectForcedColors, layout, controlsPosition, app, width, height, useWorker, chromaticImmersion, fontBaseUrl, loadWebFonts, className, style, }: VisualliRendererProps): React$1.JSX.Element;
|
|
65
113
|
|
|
66
114
|
interface VisualliCanvasProps {
|
|
67
115
|
preParsedVisualli?: VisualliDocument;
|
|
@@ -77,12 +125,51 @@ interface VisualliCanvasProps {
|
|
|
77
125
|
* Component handles all fetching and parsing automatically.
|
|
78
126
|
*/
|
|
79
127
|
visualliFile?: File | string;
|
|
128
|
+
/**
|
|
129
|
+
* Theme: one of the 8 design-system themes ('light', 'dark', 'focus-light', …), a family
|
|
130
|
+
* ('focus' | 'colorsafe' | 'contrast') or 'auto' (follow the reader). Default 'light'.
|
|
131
|
+
*/
|
|
132
|
+
theme?: ThemeInput;
|
|
133
|
+
/** @deprecated use `theme`. true -> 'dark', false -> 'light'. Kept for one release. */
|
|
80
134
|
isDark?: boolean;
|
|
135
|
+
/** Comfort settings: readable type, larger text, reduced motion. */
|
|
136
|
+
comfort?: Comfort;
|
|
137
|
+
/**
|
|
138
|
+
* How a layer arrives. 'gradual' (default): ideas bloom in one by one, then connectors draw
|
|
139
|
+
* (design-system motion). 'instant': everything fades in together, as with reduced motion.
|
|
140
|
+
*/
|
|
141
|
+
reveal?: 'gradual' | 'instant';
|
|
142
|
+
/** Switch to the high-contrast theme under forced-colors. Default true. */
|
|
143
|
+
respectForcedColors?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Interaction layout. 'auto' (default) follows the reader's input: touch devices get the design
|
|
146
|
+
* system's bottom-sheet peek and larger controls, pointer devices the floating peek on hover.
|
|
147
|
+
* Force one with 'touch' or 'pointer'.
|
|
148
|
+
*/
|
|
149
|
+
layout?: 'auto' | 'touch' | 'pointer';
|
|
150
|
+
/**
|
|
151
|
+
* The map is the page (an app such as Visualli's web app): it takes every touch gesture, so the browser never
|
|
152
|
+
* zooms or scrolls the page — the design system's `.vi-map.is-app` (`touch-action: none`). Leave it off when the
|
|
153
|
+
* map is embedded in a scrolling page: one finger then still scrolls the page, two fingers pinch the map.
|
|
154
|
+
*/
|
|
155
|
+
app?: boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Where the zoom / fit controls sit. Default 'top-right', the design system's placement (`.vi-map__ctrls`,
|
|
158
|
+
* opposite the depth trail). 'bottom-right' moves them to the bottom corner for hosts that need the top edge;
|
|
159
|
+
* there they rise above the touch peek sheet while it's open.
|
|
160
|
+
*/
|
|
161
|
+
controlsPosition?: 'top-right' | 'bottom-right';
|
|
162
|
+
/** Where the bundled Caveat font is served from (directory URL). Defaults to the copy in the npm package, via jsDelivr. */
|
|
163
|
+
fontBaseUrl?: DesignSystemAssets['fontBaseUrl'];
|
|
164
|
+
/** Set false when you load Kalam and Atkinson Hyperlegible yourself. */
|
|
165
|
+
loadWebFonts?: DesignSystemAssets['loadWebFonts'];
|
|
81
166
|
chromaticImmersion?: boolean;
|
|
82
167
|
onNodeClick?: (node: FlatNode) => void;
|
|
83
168
|
onLayerChange?: (layerId: string, layer: VisualliLayer) => void;
|
|
169
|
+
onNodeHover?: (nodeId: string | null) => void;
|
|
84
170
|
renderOverlay?: (params: {
|
|
85
171
|
isDark: boolean;
|
|
172
|
+
theme: string;
|
|
86
173
|
containerWidth: number;
|
|
87
174
|
containerHeight: number;
|
|
88
175
|
}) => React$1.ReactNode;
|
|
@@ -141,10 +228,15 @@ declare const useNodeStore: zustand.UseBoundStore<zustand.StoreApi<INodeStore>>;
|
|
|
141
228
|
interface IViewportStore extends ViewportState {
|
|
142
229
|
canvasWidth: number;
|
|
143
230
|
canvasHeight: number;
|
|
231
|
+
/** The layer's fit to view (scale and centre): zoom is shown and limited (VIEW) relative to it, as in the design system. */
|
|
232
|
+
fitScale: number;
|
|
233
|
+
fitCenterX: number;
|
|
234
|
+
fitCenterY: number;
|
|
144
235
|
pan: (deltaX: number, deltaY: number) => void;
|
|
145
236
|
zoom: (delta: number, pivotX?: number, pivotY?: number) => void;
|
|
146
237
|
setCenter: (x: number, y: number) => void;
|
|
147
238
|
setZoom: (level: number) => void;
|
|
239
|
+
setFit: (scale: number, centerX: number, centerY: number) => void;
|
|
148
240
|
updateCanvasSize: (width: number, height: number) => void;
|
|
149
241
|
getVisibleBounds: () => ViewportState['visibleBounds'];
|
|
150
242
|
worldToScreen: (x: number, y: number) => {
|
|
@@ -171,98 +263,107 @@ interface UseKonvaRendererReturn {
|
|
|
171
263
|
handleMouseDown: (e: Konva.KonvaEventObject<MouseEvent>) => void;
|
|
172
264
|
handleMouseMove: (e: Konva.KonvaEventObject<MouseEvent>) => void;
|
|
173
265
|
handleMouseUp: (e: Konva.KonvaEventObject<MouseEvent>) => void;
|
|
266
|
+
/** End a one-finger / mouse pan now (e.g. a second finger turns it into a pinch), keeping how far it moved. */
|
|
267
|
+
cancelPan: () => void;
|
|
174
268
|
canvasWidth: number;
|
|
175
269
|
canvasHeight: number;
|
|
176
270
|
}
|
|
177
|
-
declare function useKonvaRenderer({ containerRef,
|
|
271
|
+
declare function useKonvaRenderer({ containerRef, enabled, }: UseKonvaRendererOptions): UseKonvaRendererReturn;
|
|
178
272
|
|
|
273
|
+
/** A viewport to return to: centre and zoom. */
|
|
179
274
|
interface AnimatorViewport {
|
|
180
275
|
centerX: number;
|
|
181
276
|
centerY: number;
|
|
182
277
|
zoomLevel: number;
|
|
183
278
|
}
|
|
184
|
-
interface
|
|
185
|
-
x: number;
|
|
186
|
-
y: number;
|
|
187
|
-
width: number;
|
|
188
|
-
height: number;
|
|
189
|
-
}
|
|
190
|
-
interface TransitionCallbacks {
|
|
191
|
-
onUpdate: (state: {
|
|
192
|
-
viewport: AnimatorViewport;
|
|
193
|
-
opacity: number;
|
|
194
|
-
backgroundColor: string;
|
|
195
|
-
}) => void;
|
|
196
|
-
onComplete: () => void;
|
|
197
|
-
onPhaseChange?: (phase: string) => void;
|
|
198
|
-
}
|
|
199
|
-
declare class KonvaLayerTransitionAnimator {
|
|
200
|
-
private rafId;
|
|
201
|
-
private timers;
|
|
202
|
-
private _active;
|
|
203
|
-
get active(): boolean;
|
|
204
|
-
cancel(): void;
|
|
205
|
-
animateZoomIntoLayer(current: AnimatorViewport, targetNode: NodeBounds, childCenter: {
|
|
206
|
-
x: number;
|
|
207
|
-
y: number;
|
|
208
|
-
}, fromColor: string, toColor: string, cb: TransitionCallbacks, targetZoom?: number, canvasWidth?: number, canvasHeight?: number): void;
|
|
209
|
-
animateZoomOutToParent(current: AnimatorViewport, parent: AnimatorViewport, fromColor: string, toColor: string, cb: TransitionCallbacks): void;
|
|
210
|
-
private _complete;
|
|
211
|
-
}
|
|
212
|
-
declare const konvaLayerTransitionAnimator: KonvaLayerTransitionAnimator;
|
|
213
|
-
|
|
214
|
-
interface LayerTransitionOptions {
|
|
215
|
-
/** Ref to the Konva Stage for imperative position/scale updates each frame. */
|
|
279
|
+
interface LayerChoreographyOptions {
|
|
216
280
|
stageRef: React.RefObject<Konva.Stage | null>;
|
|
217
|
-
/**
|
|
281
|
+
/** The element around the Konva stage; the zoom, fade and settle play on it. */
|
|
218
282
|
canvasWrapperRef: React.RefObject<HTMLDivElement | null>;
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
/** Called when a zoom-out swap happens — use to update the nav stack. */
|
|
283
|
+
reducedMotion: boolean;
|
|
284
|
+
/** Switch the displayed layer to a child layer (the layers swap here). */
|
|
285
|
+
onSwapLayer: (childLayerId: string) => void;
|
|
286
|
+
/** Switch back to the parent layer (the layers swap here). */
|
|
224
287
|
onSwapBack: () => void;
|
|
225
|
-
/** Called
|
|
288
|
+
/** Called once the new layer has settled. */
|
|
226
289
|
onComplete: () => void;
|
|
227
|
-
/**
|
|
228
|
-
|
|
229
|
-
* When provided, the caller is responsible for moving the canvas content.
|
|
230
|
-
*/
|
|
231
|
-
onViewportFrame?: (vp: AnimatorViewport) => void;
|
|
232
|
-
/**
|
|
233
|
-
* Called once when the animation reaches its final viewport.
|
|
234
|
-
* When provided, replaces the default applyViewport call at completion.
|
|
235
|
-
*/
|
|
236
|
-
onViewportFinal?: (vp: AnimatorViewport) => void;
|
|
237
|
-
/**
|
|
238
|
-
* Called at phase-change points ('swap', 'zoom-back') in addition to the
|
|
239
|
-
* internal content-swap logic. Use to reset CSS transforms before Konva redraws.
|
|
240
|
-
*/
|
|
241
|
-
onPhaseChange?: (phase: string) => void;
|
|
242
|
-
/**
|
|
243
|
-
* Called with 'start' before the animator fires its first frame and with
|
|
244
|
-
* 'end' after onComplete. Use to set up / tear down GPU hints (willChange, etc.).
|
|
245
|
-
*/
|
|
246
|
-
onTransitionLifecycle?: (phase: 'start' | 'end') => void;
|
|
290
|
+
/** 'start' before anything moves, 'end' after the new layer has settled (pause hit-testing, GPU hints). */
|
|
291
|
+
onLifecycle?: (phase: 'start' | 'end') => void;
|
|
247
292
|
}
|
|
248
|
-
interface
|
|
249
|
-
|
|
250
|
-
|
|
293
|
+
interface LayerChoreography {
|
|
294
|
+
/** Step inside `targetNode` into the child layer. */
|
|
295
|
+
stepInside: (targetNode: FlatNode, childLayerId: string, childNodes: ReadonlyArray<FlatNode>) => void;
|
|
296
|
+
/** Back out to a layer whose fit viewport is `parent`. */
|
|
297
|
+
backOut: (parent: AnimatorViewport) => void;
|
|
298
|
+
/** The new layer is committed and drawing at its first frame: lift the veil and settle. Call after the swap's React commit. */
|
|
299
|
+
arrive: () => void;
|
|
251
300
|
isTransitioning: () => boolean;
|
|
252
301
|
}
|
|
253
|
-
declare function
|
|
302
|
+
declare function useLayerChoreography(o: LayerChoreographyOptions): LayerChoreography;
|
|
254
303
|
|
|
255
304
|
declare function useViewportNodes(nodes: FlatNode[], levelFilter?: number, skipCulling?: boolean,
|
|
256
305
|
/** When true, skip culling so dragged nodes are always visible and the
|
|
257
306
|
* spatial index (keyed on layout positions) is not consulted. */
|
|
258
307
|
isDragging?: boolean): FlatNode[];
|
|
259
308
|
|
|
260
|
-
interface
|
|
309
|
+
interface NodeShadow {
|
|
261
310
|
x: number;
|
|
262
311
|
y: number;
|
|
312
|
+
blur: number;
|
|
313
|
+
color: string;
|
|
314
|
+
}
|
|
315
|
+
interface Design {
|
|
316
|
+
theme: ThemeName;
|
|
317
|
+
comfort: ResolvedComfort;
|
|
318
|
+
tokens: Readonly<Record<string, string>>;
|
|
319
|
+
metrics: Metrics;
|
|
320
|
+
isDark: boolean;
|
|
321
|
+
/** CSS font stacks, already switched to the readable face when that comfort setting is on. */
|
|
322
|
+
fontHand: string;
|
|
323
|
+
fontNote: string;
|
|
324
|
+
fontUi: string;
|
|
325
|
+
/** Multiplier for label sizes (`--vi-label-scale`). */
|
|
326
|
+
labelScale: number;
|
|
327
|
+
/** Idea drop shadow for this theme; null when the theme turns it off (high contrast). */
|
|
328
|
+
nodeShadow: NodeShadow | null;
|
|
329
|
+
/** Attributes the spec CSS keys off; put them on the renderer's root element. */
|
|
330
|
+
attrs: Record<string, string>;
|
|
331
|
+
/** Canvas weight/size for connector labels (the readable face is smaller and bolder). */
|
|
332
|
+
edgeLabel: {
|
|
333
|
+
weight: number;
|
|
334
|
+
size: number;
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
declare function makeDesign(theme: ThemeName, comfortIn: ResolvedComfort): Design;
|
|
338
|
+
declare const DEFAULT_DESIGN: Design;
|
|
339
|
+
interface DesignProps {
|
|
340
|
+
/**
|
|
341
|
+
* One of the 8 design-system themes ('light', 'dark', 'focus-light', 'focus-dark',
|
|
342
|
+
* 'colorsafe-light', 'colorsafe-dark', 'contrast-light', 'contrast-dark'), a family
|
|
343
|
+
* ('focus' | 'colorsafe' | 'contrast') or 'auto' (follow the reader's colour scheme).
|
|
344
|
+
*/
|
|
345
|
+
theme?: ThemeInput;
|
|
346
|
+
/** @deprecated use `theme`. Kept for one release: true -> 'dark', false -> 'light'. */
|
|
347
|
+
isDark?: boolean;
|
|
348
|
+
/** Readable type, larger text, reduced motion. */
|
|
349
|
+
comfort?: Comfort;
|
|
350
|
+
/** Switch to the matching high-contrast theme under forced-colors (Windows high contrast etc.). Default true. */
|
|
351
|
+
respectForcedColors?: boolean;
|
|
263
352
|
}
|
|
264
|
-
|
|
265
|
-
declare function
|
|
353
|
+
/** Resolve props + reader environment (colour scheme, forced colours, reduced motion) to a Design. */
|
|
354
|
+
declare function resolveDesign(props: DesignProps, env: {
|
|
355
|
+
prefersDark: boolean;
|
|
356
|
+
forcedColors: boolean;
|
|
357
|
+
prefersReducedMotion: boolean;
|
|
358
|
+
}): Design;
|
|
359
|
+
|
|
360
|
+
/** The reader's current preferences. */
|
|
361
|
+
declare function useReaderEnv(): {
|
|
362
|
+
prefersDark: boolean;
|
|
363
|
+
forcedColors: boolean;
|
|
364
|
+
prefersReducedMotion: boolean;
|
|
365
|
+
};
|
|
366
|
+
declare function useDesign(props: DesignProps): Design;
|
|
266
367
|
|
|
267
368
|
interface KonvaStageProps {
|
|
268
369
|
children: React$1.ReactNode;
|
|
@@ -285,8 +386,10 @@ interface KonvaNodeProps {
|
|
|
285
386
|
isExternallyHovered?: boolean;
|
|
286
387
|
/** True while this node is being pressed/dragged. */
|
|
287
388
|
isExternallyPressed?: boolean;
|
|
288
|
-
|
|
389
|
+
isSelected?: boolean;
|
|
390
|
+
/** True while any node is being dragged — disables the drop shadow. */
|
|
289
391
|
isDragging?: boolean;
|
|
392
|
+
design?: Design;
|
|
290
393
|
}
|
|
291
394
|
declare const KonvaNode: React$1.NamedExoticComponent<KonvaNodeProps>;
|
|
292
395
|
|
|
@@ -294,42 +397,134 @@ interface KonvaEdgeProps {
|
|
|
294
397
|
sourceNode: FlatNode;
|
|
295
398
|
targetNode: FlatNode;
|
|
296
399
|
connection?: MindMapConnection;
|
|
400
|
+
/** @deprecated pass `design`. */
|
|
297
401
|
isDark?: boolean;
|
|
402
|
+
/** @deprecated connectors use the design system's edge colour; kept so existing callers compile. */
|
|
298
403
|
colorOverride?: string;
|
|
299
404
|
zoomLevel?: number;
|
|
405
|
+
design?: Design;
|
|
300
406
|
}
|
|
301
407
|
declare const KonvaEdge: React$1.NamedExoticComponent<KonvaEdgeProps>;
|
|
302
408
|
|
|
409
|
+
/** How an idea looks mid-arrival (multiplies its resting look). */
|
|
410
|
+
interface Arrival {
|
|
411
|
+
alpha: number;
|
|
412
|
+
scale: number;
|
|
413
|
+
dx: number;
|
|
414
|
+
dy: number;
|
|
415
|
+
}
|
|
416
|
+
/** How a connector looks mid-arrival: `draw` is the fraction of the line drawn, `alpha` its group's fade. */
|
|
417
|
+
interface EdgeArrival {
|
|
418
|
+
alpha: number;
|
|
419
|
+
draw: number;
|
|
420
|
+
}
|
|
421
|
+
/** The timeline of one layer's arrival. Shared by the idea layer and the connector layer. */
|
|
422
|
+
declare class RevealClock {
|
|
423
|
+
private t0;
|
|
424
|
+
private end;
|
|
425
|
+
private plan;
|
|
426
|
+
private reduced;
|
|
427
|
+
private center;
|
|
428
|
+
private order;
|
|
429
|
+
private listeners;
|
|
430
|
+
private timer;
|
|
431
|
+
/** Begin a layer's arrival. `reduced` (reduced motion or instant reveal): everything fades in together. */
|
|
432
|
+
start(nodes: ReadonlyArray<FlatNode>, edgeCount: number, reduced: boolean, now?: number): void;
|
|
433
|
+
/** Jump to the finished state (e.g. on unmount). */
|
|
434
|
+
stop(): void;
|
|
435
|
+
/** True while the layer is still arriving. */
|
|
436
|
+
active(now?: number): boolean;
|
|
437
|
+
/** Called with true when an arrival starts and false when it has finished. Returns the unsubscribe function. */
|
|
438
|
+
subscribe(fn: (running: boolean) => void): () => void;
|
|
439
|
+
private emit;
|
|
440
|
+
/** Fills `out` with idea `id`'s arrival look. Returns false when it has arrived (nothing to apply). */
|
|
441
|
+
node(id: string, x: number, y: number, now: number, out: Arrival): boolean;
|
|
442
|
+
/** Fills `out` with connector `i`'s arrival look. Returns false when it has arrived. */
|
|
443
|
+
edge(i: number, dashed: boolean, now: number, out: EdgeArrival): boolean;
|
|
444
|
+
}
|
|
445
|
+
|
|
303
446
|
interface KonvaNodeLayerProps {
|
|
304
447
|
nodes?: FlatNode[];
|
|
305
448
|
isTransitioning?: boolean;
|
|
306
449
|
isDragging?: boolean;
|
|
307
450
|
hoveredNodeId?: string | null;
|
|
308
451
|
pressedNodeId?: string | null;
|
|
452
|
+
selectedNodeId?: string | null;
|
|
453
|
+
/** Idea with keyboard focus (accessible layer). */
|
|
454
|
+
focusedNodeId?: string | null;
|
|
455
|
+
design?: Design;
|
|
456
|
+
/** The layer's arrival timeline (bloom). Omit for no arrival animation. */
|
|
457
|
+
clock?: RevealClock;
|
|
458
|
+
/** Touch layout (`.vi-map.is-touch`): the other ideas fade while one is peeked. */
|
|
459
|
+
touch?: boolean;
|
|
460
|
+
/** Idea whose peek (sheet) is open on touch. */
|
|
461
|
+
peekedNodeId?: string | null;
|
|
309
462
|
}
|
|
310
|
-
declare function KonvaNodeLayer({ nodes: propNodes,
|
|
463
|
+
declare function KonvaNodeLayer({ nodes: propNodes, isDragging, hoveredNodeId, pressedNodeId, selectedNodeId, focusedNodeId, design, clock, touch, peekedNodeId, }: KonvaNodeLayerProps): React$1.JSX.Element;
|
|
311
464
|
|
|
312
465
|
interface KonvaEdgeLayerProps {
|
|
313
466
|
nodes: FlatNode[];
|
|
314
467
|
connections: MindMapConnection[];
|
|
315
468
|
currentLevel?: number;
|
|
469
|
+
/** @deprecated pass `design`; kept so existing callers still compile. */
|
|
316
470
|
isDark?: boolean;
|
|
317
|
-
/** Pass true while
|
|
471
|
+
/** Pass true while an idea is being dragged (connectors are always drawn then). */
|
|
318
472
|
isDragging?: boolean;
|
|
473
|
+
design?: Design;
|
|
474
|
+
/** The layer's arrival timeline (connectors draw in after the ideas). Omit for no arrival animation. */
|
|
475
|
+
clock?: RevealClock;
|
|
319
476
|
}
|
|
320
|
-
declare function KonvaEdgeLayer({
|
|
477
|
+
declare function KonvaEdgeLayer({ connections, isDragging, design, clock }: KonvaEdgeLayerProps): React$1.JSX.Element;
|
|
321
478
|
|
|
322
479
|
interface KonvaContainerProps {
|
|
323
480
|
/** All nodes in this container group (already resolved from nodeMap). */
|
|
324
481
|
nodes: FlatNode[];
|
|
325
|
-
/**
|
|
482
|
+
/** The group's name, drawn as a pill on the hull. */
|
|
326
483
|
label?: string;
|
|
327
|
-
/**
|
|
484
|
+
/** @deprecated unused: the hull and name use the design system's container style. */
|
|
328
485
|
color?: string;
|
|
486
|
+
/** @deprecated pass `design`. */
|
|
329
487
|
isDark?: boolean;
|
|
488
|
+
zoomLevel?: number;
|
|
489
|
+
design?: Design;
|
|
330
490
|
}
|
|
331
491
|
declare const KonvaContainer: React$1.NamedExoticComponent<KonvaContainerProps>;
|
|
332
492
|
|
|
493
|
+
interface ContainerInput {
|
|
494
|
+
id: string;
|
|
495
|
+
label?: string;
|
|
496
|
+
nodeIds: string[];
|
|
497
|
+
}
|
|
498
|
+
interface ConnectionInput {
|
|
499
|
+
from: string;
|
|
500
|
+
to: string;
|
|
501
|
+
}
|
|
502
|
+
interface PlacedPill {
|
|
503
|
+
text: string;
|
|
504
|
+
x: number;
|
|
505
|
+
y: number;
|
|
506
|
+
side: LabelSide;
|
|
507
|
+
w: number;
|
|
508
|
+
h: number;
|
|
509
|
+
}
|
|
510
|
+
interface PlacedContainer {
|
|
511
|
+
id: string;
|
|
512
|
+
hull: Hull;
|
|
513
|
+
pill: PlacedPill | null;
|
|
514
|
+
}
|
|
515
|
+
/** The pill's box in world units for `text` (ellipsised past labelMaxWidth), with the text grown by `k`. */
|
|
516
|
+
declare function measurePill(text: string, d: Design, k: number, c?: CanvasRenderingContext2D | null): PlacedPill;
|
|
517
|
+
/**
|
|
518
|
+
* Hulls and name positions for a layer's containers, in file order (each name
|
|
519
|
+
* avoids the ones placed before it). Placement uses the names' size at 100%
|
|
520
|
+
* (k = 1), so they don't hop while zooming; they follow ideas that are dragged.
|
|
521
|
+
*/
|
|
522
|
+
declare function layoutContainers(containers: ReadonlyArray<ContainerInput>, nodes: ReadonlyMap<string, FlatNode>, connections: ReadonlyArray<ConnectionInput>, d: Design): PlacedContainer[];
|
|
523
|
+
/** The dashed hull (beneath connectors and ideas). */
|
|
524
|
+
declare function drawHull(c: CanvasRenderingContext2D, h: Hull, d: Design): void;
|
|
525
|
+
/** The name pill (above connectors and ideas), its text growing like idea labels when zoomed out (labelGrowth). */
|
|
526
|
+
declare function drawPill(c: CanvasRenderingContext2D, p: PlacedPill, d: Design, zoom: number): void;
|
|
527
|
+
|
|
333
528
|
interface ContainerGroup {
|
|
334
529
|
id: string;
|
|
335
530
|
label?: string;
|
|
@@ -337,39 +532,102 @@ interface ContainerGroup {
|
|
|
337
532
|
level: number;
|
|
338
533
|
}
|
|
339
534
|
interface KonvaContainerLayerProps {
|
|
340
|
-
/** Layout-snapshot nodes
|
|
535
|
+
/** Layout-snapshot nodes (kept for API compatibility). */
|
|
341
536
|
nodes: FlatNode[];
|
|
342
537
|
containers: ContainerGroup[];
|
|
538
|
+
/** The layer's connections: container names are placed clear of them. */
|
|
539
|
+
connections?: ConnectionInput[];
|
|
540
|
+
/** @deprecated pass `design`. */
|
|
541
|
+
isDark?: boolean;
|
|
542
|
+
design?: Design;
|
|
543
|
+
}
|
|
544
|
+
declare function KonvaContainerLayer({ containers, connections, design }: KonvaContainerLayerProps): React$1.JSX.Element | null;
|
|
545
|
+
|
|
546
|
+
interface KonvaContainerLabelLayerProps {
|
|
547
|
+
containers: ContainerGroup[];
|
|
548
|
+
connections?: ConnectionInput[];
|
|
549
|
+
design?: Design;
|
|
550
|
+
}
|
|
551
|
+
declare function KonvaContainerLabelLayer({ containers, connections, design }: KonvaContainerLabelLayerProps): React$1.JSX.Element | null;
|
|
552
|
+
|
|
553
|
+
interface ZoomControlsProps {
|
|
554
|
+
/** Re-fit the current layer into view. */
|
|
555
|
+
onFit?: () => void;
|
|
556
|
+
/** Touch layout: larger targets (the design system's `md` icon buttons). */
|
|
557
|
+
touch?: boolean;
|
|
558
|
+
/** @deprecated theme comes from the surrounding data-theme; kept so existing callers compile. */
|
|
343
559
|
isDark?: boolean;
|
|
344
560
|
}
|
|
345
|
-
declare
|
|
561
|
+
declare const ZoomControls: React$1.NamedExoticComponent<ZoomControlsProps>;
|
|
562
|
+
/** An idea's colour: its topic, or a custom colour drawn as given (FlatNode.topic / FlatNode.custom). */
|
|
563
|
+
type IdeaPaint = Pick<FlatNode, 'topic' | 'custom'>;
|
|
564
|
+
/** CSS fill + ring for an idea's colour, as the design system's topicColors: the active theme's topic properties, or
|
|
565
|
+
* the custom colour with its darker ring (the `edge` token when it has none). */
|
|
566
|
+
declare function paintVars(p: IdeaPaint): {
|
|
567
|
+
fill: string;
|
|
568
|
+
ring: string;
|
|
569
|
+
};
|
|
570
|
+
/** A depth trail entry: the idea stepped into (its title and colour); the first is the map (home glyph, its title as the accessible name). */
|
|
571
|
+
interface TrailEntry {
|
|
572
|
+
layerId: string;
|
|
573
|
+
label: string;
|
|
574
|
+
level: number;
|
|
575
|
+
paint: IdeaPaint;
|
|
576
|
+
}
|
|
577
|
+
interface DepthTrailProps {
|
|
578
|
+
stack: TrailEntry[];
|
|
579
|
+
onNavigateBack: (index: number) => void;
|
|
580
|
+
}
|
|
581
|
+
declare const DepthTrail: React$1.NamedExoticComponent<DepthTrailProps>;
|
|
582
|
+
/** Split `text` into plain runs and runs that match an anchor word (longest word wins, whole words only). */
|
|
583
|
+
declare function splitTerms(text: string, anchors: ReadonlyArray<SemanticAnchor>): Array<string | SemanticAnchor>;
|
|
584
|
+
declare const TermCard: ({ anchor, inSheet }: {
|
|
585
|
+
anchor: SemanticAnchor;
|
|
586
|
+
inSheet?: boolean;
|
|
587
|
+
}) => React$1.JSX.Element;
|
|
588
|
+
interface PeekCardProps {
|
|
589
|
+
node: FlatNode;
|
|
590
|
+
anchors: ReadonlyArray<SemanticAnchor>;
|
|
591
|
+
/** Present when the idea has a layer inside it. */
|
|
592
|
+
onStepInside?: () => void;
|
|
593
|
+
onClose?: () => void;
|
|
594
|
+
/** Replaces the plain summary text (extension point kept from earlier versions). */
|
|
595
|
+
renderContent?: (summary: string) => React$1.ReactNode;
|
|
596
|
+
}
|
|
597
|
+
declare const PeekCard: React$1.NamedExoticComponent<PeekCardProps>;
|
|
346
598
|
|
|
347
599
|
interface NavStackEntry {
|
|
348
600
|
layerId: string;
|
|
349
601
|
layer: VisualliLayer;
|
|
350
602
|
label: string;
|
|
603
|
+
/** Colour of the idea this layer opens from (the design system's TRAIL: the clicked idea's own colour); the first
|
|
604
|
+
* entry, the map's title, is TRAIL.rootTopic. */
|
|
605
|
+
paint?: IdeaPaint;
|
|
351
606
|
}
|
|
352
607
|
interface NavigationStackProps {
|
|
353
608
|
stack: NavStackEntry[];
|
|
354
609
|
onNavigateBack: (index: number) => void;
|
|
610
|
+
/** @deprecated theme comes from the surrounding data-theme. */
|
|
355
611
|
isDark?: boolean;
|
|
612
|
+
/** Override the trail's default offset from the top-left corner. */
|
|
356
613
|
top?: string;
|
|
357
614
|
left?: string;
|
|
358
615
|
}
|
|
359
616
|
declare const NavigationStack: React$1.NamedExoticComponent<NavigationStackProps>;
|
|
360
617
|
|
|
361
|
-
interface
|
|
362
|
-
|
|
618
|
+
interface A11yLayerProps {
|
|
619
|
+
nodes: FlatNode[];
|
|
620
|
+
/** Accessible name of the list, e.g. the layer title. */
|
|
621
|
+
label: string;
|
|
622
|
+
hasChildLayer: (nodeId: string) => boolean;
|
|
623
|
+
onActivate: (node: FlatNode) => void;
|
|
624
|
+
onFocusNode: (nodeId: string | null) => void;
|
|
625
|
+
/** Spoken when the layer changes. */
|
|
626
|
+
announcement?: string;
|
|
363
627
|
}
|
|
364
|
-
declare const
|
|
628
|
+
declare const A11yLayer: React$1.NamedExoticComponent<A11yLayerProps>;
|
|
365
629
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
fill: string;
|
|
369
|
-
stroke: string;
|
|
370
|
-
backStroke: string;
|
|
371
|
-
padding?: string;
|
|
372
|
-
}
|
|
373
|
-
declare const SketchyBoxKonva: React$1.FC<SketchyBoxKonvaProps>;
|
|
630
|
+
/** Width of a label in `d`'s idea face (cached per face, size, text and font load). */
|
|
631
|
+
declare function ideaMeasure(d: Pick<Design, 'fontHand' | 'comfort'>): IdeaMeasure;
|
|
374
632
|
|
|
375
|
-
export { type AnimatorViewport, type ContainerGroup, type INodeStore, type IViewportStore, KonvaContainer, KonvaContainerLayer, KonvaEdge, KonvaEdgeLayer, type KonvaEdgeProps,
|
|
633
|
+
export { A11yLayer, type AnimatorViewport, type ContainerGroup, DEFAULT_DESIGN, DepthTrail, type DepthTrailProps, type Design, type DesignProps, type DesignSystemAssets, type INodeStore, type IViewportStore, type IdeaPaint, KonvaContainer, KonvaContainerLabelLayer, KonvaContainerLayer, KonvaEdge, KonvaEdgeLayer, type KonvaEdgeProps, KonvaNode, KonvaNodeLayer, type KonvaNodeProps, KonvaStage, type KonvaStageProps, type LayerChoreography, type LayerChoreographyOptions, type NavStackEntry, NavigationStack, PeekCard, type PeekCardProps, type PlacedContainer, type PlacedPill, TermCard, type TrailEntry, type UseKonvaRendererOptions, type UseKonvaRendererReturn, VisualliCanvas, type VisualliCanvasProps, type VisualliContextValue, VisualliProvider, type VisualliProviderProps, VisualliRenderer, type VisualliRendererProps, type VisualliTheme, ZoomControls, drawHull, drawPill, ensureDesignSystemStyles, ideaMeasure, layoutContainers, loadCanvasFonts, makeDesign, measurePill, paintVars, resolveDesign, splitTerms, useDesign, useKonvaRenderer, useLayerChoreography, useNodeStore, useReaderEnv, useRenderConfigStore, useSelectionStore, useViewportNodes, useViewportStore, useVisualli };
|