@visualli/react 0.1.7 → 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 -2033
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +354 -97
- package/dist/index.d.ts +354 -97
- package/dist/index.js +2005 -2095
- 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 +452 -409
- 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,13 +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;
|
|
84
169
|
onNodeHover?: (nodeId: string | null) => void;
|
|
85
170
|
renderOverlay?: (params: {
|
|
86
171
|
isDark: boolean;
|
|
172
|
+
theme: string;
|
|
87
173
|
containerWidth: number;
|
|
88
174
|
containerHeight: number;
|
|
89
175
|
}) => React$1.ReactNode;
|
|
@@ -142,10 +228,15 @@ declare const useNodeStore: zustand.UseBoundStore<zustand.StoreApi<INodeStore>>;
|
|
|
142
228
|
interface IViewportStore extends ViewportState {
|
|
143
229
|
canvasWidth: number;
|
|
144
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;
|
|
145
235
|
pan: (deltaX: number, deltaY: number) => void;
|
|
146
236
|
zoom: (delta: number, pivotX?: number, pivotY?: number) => void;
|
|
147
237
|
setCenter: (x: number, y: number) => void;
|
|
148
238
|
setZoom: (level: number) => void;
|
|
239
|
+
setFit: (scale: number, centerX: number, centerY: number) => void;
|
|
149
240
|
updateCanvasSize: (width: number, height: number) => void;
|
|
150
241
|
getVisibleBounds: () => ViewportState['visibleBounds'];
|
|
151
242
|
worldToScreen: (x: number, y: number) => {
|
|
@@ -172,98 +263,107 @@ interface UseKonvaRendererReturn {
|
|
|
172
263
|
handleMouseDown: (e: Konva.KonvaEventObject<MouseEvent>) => void;
|
|
173
264
|
handleMouseMove: (e: Konva.KonvaEventObject<MouseEvent>) => void;
|
|
174
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;
|
|
175
268
|
canvasWidth: number;
|
|
176
269
|
canvasHeight: number;
|
|
177
270
|
}
|
|
178
|
-
declare function useKonvaRenderer({ containerRef,
|
|
271
|
+
declare function useKonvaRenderer({ containerRef, enabled, }: UseKonvaRendererOptions): UseKonvaRendererReturn;
|
|
179
272
|
|
|
273
|
+
/** A viewport to return to: centre and zoom. */
|
|
180
274
|
interface AnimatorViewport {
|
|
181
275
|
centerX: number;
|
|
182
276
|
centerY: number;
|
|
183
277
|
zoomLevel: number;
|
|
184
278
|
}
|
|
185
|
-
interface
|
|
186
|
-
x: number;
|
|
187
|
-
y: number;
|
|
188
|
-
width: number;
|
|
189
|
-
height: number;
|
|
190
|
-
}
|
|
191
|
-
interface TransitionCallbacks {
|
|
192
|
-
onUpdate: (state: {
|
|
193
|
-
viewport: AnimatorViewport;
|
|
194
|
-
opacity: number;
|
|
195
|
-
backgroundColor: string;
|
|
196
|
-
}) => void;
|
|
197
|
-
onComplete: () => void;
|
|
198
|
-
onPhaseChange?: (phase: string) => void;
|
|
199
|
-
}
|
|
200
|
-
declare class KonvaLayerTransitionAnimator {
|
|
201
|
-
private rafId;
|
|
202
|
-
private timers;
|
|
203
|
-
private _active;
|
|
204
|
-
get active(): boolean;
|
|
205
|
-
cancel(): void;
|
|
206
|
-
animateZoomIntoLayer(current: AnimatorViewport, targetNode: NodeBounds, childCenter: {
|
|
207
|
-
x: number;
|
|
208
|
-
y: number;
|
|
209
|
-
}, fromColor: string, toColor: string, cb: TransitionCallbacks, targetZoom?: number, canvasWidth?: number, canvasHeight?: number): void;
|
|
210
|
-
animateZoomOutToParent(current: AnimatorViewport, parent: AnimatorViewport, fromColor: string, toColor: string, cb: TransitionCallbacks): void;
|
|
211
|
-
private _complete;
|
|
212
|
-
}
|
|
213
|
-
declare const konvaLayerTransitionAnimator: KonvaLayerTransitionAnimator;
|
|
214
|
-
|
|
215
|
-
interface LayerTransitionOptions {
|
|
216
|
-
/** Ref to the Konva Stage for imperative position/scale updates each frame. */
|
|
279
|
+
interface LayerChoreographyOptions {
|
|
217
280
|
stageRef: React.RefObject<Konva.Stage | null>;
|
|
218
|
-
/**
|
|
281
|
+
/** The element around the Konva stage; the zoom, fade and settle play on it. */
|
|
219
282
|
canvasWrapperRef: React.RefObject<HTMLDivElement | null>;
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
/** 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). */
|
|
225
287
|
onSwapBack: () => void;
|
|
226
|
-
/** Called
|
|
288
|
+
/** Called once the new layer has settled. */
|
|
227
289
|
onComplete: () => void;
|
|
228
|
-
/**
|
|
229
|
-
|
|
230
|
-
* When provided, the caller is responsible for moving the canvas content.
|
|
231
|
-
*/
|
|
232
|
-
onViewportFrame?: (vp: AnimatorViewport) => void;
|
|
233
|
-
/**
|
|
234
|
-
* Called once when the animation reaches its final viewport.
|
|
235
|
-
* When provided, replaces the default applyViewport call at completion.
|
|
236
|
-
*/
|
|
237
|
-
onViewportFinal?: (vp: AnimatorViewport) => void;
|
|
238
|
-
/**
|
|
239
|
-
* Called at phase-change points ('swap', 'zoom-back') in addition to the
|
|
240
|
-
* internal content-swap logic. Use to reset CSS transforms before Konva redraws.
|
|
241
|
-
*/
|
|
242
|
-
onPhaseChange?: (phase: string) => void;
|
|
243
|
-
/**
|
|
244
|
-
* Called with 'start' before the animator fires its first frame and with
|
|
245
|
-
* 'end' after onComplete. Use to set up / tear down GPU hints (willChange, etc.).
|
|
246
|
-
*/
|
|
247
|
-
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;
|
|
248
292
|
}
|
|
249
|
-
interface
|
|
250
|
-
|
|
251
|
-
|
|
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;
|
|
252
300
|
isTransitioning: () => boolean;
|
|
253
301
|
}
|
|
254
|
-
declare function
|
|
302
|
+
declare function useLayerChoreography(o: LayerChoreographyOptions): LayerChoreography;
|
|
255
303
|
|
|
256
304
|
declare function useViewportNodes(nodes: FlatNode[], levelFilter?: number, skipCulling?: boolean,
|
|
257
305
|
/** When true, skip culling so dragged nodes are always visible and the
|
|
258
306
|
* spatial index (keyed on layout positions) is not consulted. */
|
|
259
307
|
isDragging?: boolean): FlatNode[];
|
|
260
308
|
|
|
261
|
-
interface
|
|
309
|
+
interface NodeShadow {
|
|
262
310
|
x: number;
|
|
263
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;
|
|
264
352
|
}
|
|
265
|
-
|
|
266
|
-
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;
|
|
267
367
|
|
|
268
368
|
interface KonvaStageProps {
|
|
269
369
|
children: React$1.ReactNode;
|
|
@@ -286,8 +386,10 @@ interface KonvaNodeProps {
|
|
|
286
386
|
isExternallyHovered?: boolean;
|
|
287
387
|
/** True while this node is being pressed/dragged. */
|
|
288
388
|
isExternallyPressed?: boolean;
|
|
289
|
-
|
|
389
|
+
isSelected?: boolean;
|
|
390
|
+
/** True while any node is being dragged — disables the drop shadow. */
|
|
290
391
|
isDragging?: boolean;
|
|
392
|
+
design?: Design;
|
|
291
393
|
}
|
|
292
394
|
declare const KonvaNode: React$1.NamedExoticComponent<KonvaNodeProps>;
|
|
293
395
|
|
|
@@ -295,42 +397,134 @@ interface KonvaEdgeProps {
|
|
|
295
397
|
sourceNode: FlatNode;
|
|
296
398
|
targetNode: FlatNode;
|
|
297
399
|
connection?: MindMapConnection;
|
|
400
|
+
/** @deprecated pass `design`. */
|
|
298
401
|
isDark?: boolean;
|
|
402
|
+
/** @deprecated connectors use the design system's edge colour; kept so existing callers compile. */
|
|
299
403
|
colorOverride?: string;
|
|
300
404
|
zoomLevel?: number;
|
|
405
|
+
design?: Design;
|
|
301
406
|
}
|
|
302
407
|
declare const KonvaEdge: React$1.NamedExoticComponent<KonvaEdgeProps>;
|
|
303
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
|
+
|
|
304
446
|
interface KonvaNodeLayerProps {
|
|
305
447
|
nodes?: FlatNode[];
|
|
306
448
|
isTransitioning?: boolean;
|
|
307
449
|
isDragging?: boolean;
|
|
308
450
|
hoveredNodeId?: string | null;
|
|
309
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;
|
|
310
462
|
}
|
|
311
|
-
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;
|
|
312
464
|
|
|
313
465
|
interface KonvaEdgeLayerProps {
|
|
314
466
|
nodes: FlatNode[];
|
|
315
467
|
connections: MindMapConnection[];
|
|
316
468
|
currentLevel?: number;
|
|
469
|
+
/** @deprecated pass `design`; kept so existing callers still compile. */
|
|
317
470
|
isDark?: boolean;
|
|
318
|
-
/** Pass true while
|
|
471
|
+
/** Pass true while an idea is being dragged (connectors are always drawn then). */
|
|
319
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;
|
|
320
476
|
}
|
|
321
|
-
declare function KonvaEdgeLayer({
|
|
477
|
+
declare function KonvaEdgeLayer({ connections, isDragging, design, clock }: KonvaEdgeLayerProps): React$1.JSX.Element;
|
|
322
478
|
|
|
323
479
|
interface KonvaContainerProps {
|
|
324
480
|
/** All nodes in this container group (already resolved from nodeMap). */
|
|
325
481
|
nodes: FlatNode[];
|
|
326
|
-
/**
|
|
482
|
+
/** The group's name, drawn as a pill on the hull. */
|
|
327
483
|
label?: string;
|
|
328
|
-
/**
|
|
484
|
+
/** @deprecated unused: the hull and name use the design system's container style. */
|
|
329
485
|
color?: string;
|
|
486
|
+
/** @deprecated pass `design`. */
|
|
330
487
|
isDark?: boolean;
|
|
488
|
+
zoomLevel?: number;
|
|
489
|
+
design?: Design;
|
|
331
490
|
}
|
|
332
491
|
declare const KonvaContainer: React$1.NamedExoticComponent<KonvaContainerProps>;
|
|
333
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
|
+
|
|
334
528
|
interface ContainerGroup {
|
|
335
529
|
id: string;
|
|
336
530
|
label?: string;
|
|
@@ -338,39 +532,102 @@ interface ContainerGroup {
|
|
|
338
532
|
level: number;
|
|
339
533
|
}
|
|
340
534
|
interface KonvaContainerLayerProps {
|
|
341
|
-
/** Layout-snapshot nodes
|
|
535
|
+
/** Layout-snapshot nodes (kept for API compatibility). */
|
|
342
536
|
nodes: FlatNode[];
|
|
343
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. */
|
|
344
559
|
isDark?: boolean;
|
|
345
560
|
}
|
|
346
|
-
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>;
|
|
347
598
|
|
|
348
599
|
interface NavStackEntry {
|
|
349
600
|
layerId: string;
|
|
350
601
|
layer: VisualliLayer;
|
|
351
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;
|
|
352
606
|
}
|
|
353
607
|
interface NavigationStackProps {
|
|
354
608
|
stack: NavStackEntry[];
|
|
355
609
|
onNavigateBack: (index: number) => void;
|
|
610
|
+
/** @deprecated theme comes from the surrounding data-theme. */
|
|
356
611
|
isDark?: boolean;
|
|
612
|
+
/** Override the trail's default offset from the top-left corner. */
|
|
357
613
|
top?: string;
|
|
358
614
|
left?: string;
|
|
359
615
|
}
|
|
360
616
|
declare const NavigationStack: React$1.NamedExoticComponent<NavigationStackProps>;
|
|
361
617
|
|
|
362
|
-
interface
|
|
363
|
-
|
|
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;
|
|
364
627
|
}
|
|
365
|
-
declare const
|
|
628
|
+
declare const A11yLayer: React$1.NamedExoticComponent<A11yLayerProps>;
|
|
366
629
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
fill: string;
|
|
370
|
-
stroke: string;
|
|
371
|
-
backStroke: string;
|
|
372
|
-
padding?: string;
|
|
373
|
-
}
|
|
374
|
-
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;
|
|
375
632
|
|
|
376
|
-
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 };
|