flow-mindmap 0.1.0-beta.1
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/LICENSE +201 -0
- package/README.md +288 -0
- package/dist/components/DataPanel.vue.d.ts +10 -0
- package/dist/components/Drawer.vue.d.ts +33 -0
- package/dist/components/Icon.vue.d.ts +7 -0
- package/dist/components/MarkdownPanel.vue.d.ts +12 -0
- package/dist/components/MindMap.vue.d.ts +60 -0
- package/dist/components/NodeContextMenu.vue.d.ts +46 -0
- package/dist/components/NotePanel.vue.d.ts +20 -0
- package/dist/components/Outline.vue.d.ts +45 -0
- package/dist/components/SettingsPanel.vue.d.ts +30 -0
- package/dist/composables/useHistory.d.ts +19 -0
- package/dist/composables/useKeyboard.d.ts +32 -0
- package/dist/composables/usePanZoom.d.ts +35 -0
- package/dist/core/layout.d.ts +98 -0
- package/dist/core/palettes.d.ts +43 -0
- package/dist/entry.d.ts +11 -0
- package/dist/flow-mindmap.js +1849 -0
- package/dist/flow-mindmap.umd.cjs +1 -0
- package/dist/style.css +1 -0
- package/dist/tree.d.ts +68 -0
- package/dist/types.d.ts +215 -0
- package/package.json +70 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MindMapNode } from '../types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
/** The currently selected node. `null` means nothing is
|
|
4
|
+
* selected; the panel renders an empty-state in that case. */
|
|
5
|
+
selectedNode: MindMapNode | null;
|
|
6
|
+
/** Disable all edit controls (read-only mode). */
|
|
7
|
+
readonly?: boolean;
|
|
8
|
+
/** Bumped by the parent (App.vue) on each select change. The
|
|
9
|
+
* panel uses this as a "focus the textarea" signal so the
|
|
10
|
+
* user can start typing immediately after picking a node. */
|
|
11
|
+
focusTick?: number;
|
|
12
|
+
};
|
|
13
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
14
|
+
apply: (text: string) => any;
|
|
15
|
+
remove: () => any;
|
|
16
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
|
+
onApply?: ((text: string) => any) | undefined;
|
|
18
|
+
onRemove?: (() => any) | undefined;
|
|
19
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
export default _default;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { MindMapNode } from '../types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
/** Root of the mind map. */
|
|
4
|
+
data: MindMapNode;
|
|
5
|
+
/** Highlight the node with this id (the one selected on the main canvas). */
|
|
6
|
+
selectedId?: string | null;
|
|
7
|
+
/** When true, hide a node's children in the outline. */
|
|
8
|
+
collapsedIds?: Set<string>;
|
|
9
|
+
/** Read-only — disables editing / add / drag. Default false. */
|
|
10
|
+
readonly?: boolean;
|
|
11
|
+
};
|
|
12
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
13
|
+
select: (node: MindMapNode) => any;
|
|
14
|
+
edit: (payload: {
|
|
15
|
+
id: string;
|
|
16
|
+
text: string;
|
|
17
|
+
}) => any;
|
|
18
|
+
toggleCollapse: (id: string) => any;
|
|
19
|
+
addChild: (id: string) => any;
|
|
20
|
+
addSibling: (id: string) => any;
|
|
21
|
+
move: (payload: {
|
|
22
|
+
srcId: string;
|
|
23
|
+
targetId: string;
|
|
24
|
+
position: "before" | "after" | "child";
|
|
25
|
+
}) => any;
|
|
26
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
27
|
+
onSelect?: ((node: MindMapNode) => any) | undefined;
|
|
28
|
+
onEdit?: ((payload: {
|
|
29
|
+
id: string;
|
|
30
|
+
text: string;
|
|
31
|
+
}) => any) | undefined;
|
|
32
|
+
onToggleCollapse?: ((id: string) => any) | undefined;
|
|
33
|
+
onAddChild?: ((id: string) => any) | undefined;
|
|
34
|
+
onAddSibling?: ((id: string) => any) | undefined;
|
|
35
|
+
onMove?: ((payload: {
|
|
36
|
+
srcId: string;
|
|
37
|
+
targetId: string;
|
|
38
|
+
position: "before" | "after" | "child";
|
|
39
|
+
}) => any) | undefined;
|
|
40
|
+
}>, {
|
|
41
|
+
readonly: boolean;
|
|
42
|
+
selectedId: string | null;
|
|
43
|
+
collapsedIds: Set<string>;
|
|
44
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
45
|
+
export default _default;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MindMapSettings } from '../types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
settings: MindMapSettings;
|
|
4
|
+
/** true when a node is selected — the per-node panel is shown too. */
|
|
5
|
+
hasSelection: boolean;
|
|
6
|
+
selectedNodeText?: string;
|
|
7
|
+
};
|
|
8
|
+
/** Style overrides for a single node. Stored externally (App.vue
|
|
9
|
+
* holds the map) so the per-node state is preserved across
|
|
10
|
+
* selection changes. */
|
|
11
|
+
export interface NodeStyle {
|
|
12
|
+
/** Background colour. undefined = fall back to theme/branch. */
|
|
13
|
+
bg?: string;
|
|
14
|
+
/** Text colour. */
|
|
15
|
+
textColor?: string;
|
|
16
|
+
/** Border colour. */
|
|
17
|
+
borderColor?: string;
|
|
18
|
+
/** Font weight: 400 / 600. undefined = inherit. */
|
|
19
|
+
fontWeight?: 400 | 600;
|
|
20
|
+
}
|
|
21
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
22
|
+
reset: () => any;
|
|
23
|
+
"update:settings": (s: Partial<MindMapSettings>) => any;
|
|
24
|
+
"update:nodeStyle": (s: Partial<NodeStyle>) => any;
|
|
25
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
26
|
+
onReset?: (() => any) | undefined;
|
|
27
|
+
"onUpdate:settings"?: ((s: Partial<MindMapSettings>) => any) | undefined;
|
|
28
|
+
"onUpdate:nodeStyle"?: ((s: Partial<NodeStyle>) => any) | undefined;
|
|
29
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
|
+
export default _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MindMapNode } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Linear undo/redo history for the mind map.
|
|
4
|
+
*
|
|
5
|
+
* Each entry stores the data tree (full JSON snapshot).
|
|
6
|
+
* Snapshots are deep-cloned JSON strings (one string per state). The
|
|
7
|
+
* timeline is bounded so a long session doesn't grow without limit.
|
|
8
|
+
*/
|
|
9
|
+
export interface HistoryState {
|
|
10
|
+
data: MindMapNode;
|
|
11
|
+
}
|
|
12
|
+
export declare function useHistory(maxSize?: number): {
|
|
13
|
+
canUndo: () => boolean;
|
|
14
|
+
canRedo: () => boolean;
|
|
15
|
+
record: (snapshot: HistoryState) => void;
|
|
16
|
+
undo: () => HistoryState | null;
|
|
17
|
+
redo: () => HistoryState | null;
|
|
18
|
+
reset: () => void;
|
|
19
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface KeyboardOptions {
|
|
2
|
+
isEditing: () => boolean;
|
|
3
|
+
isReadonly: () => boolean;
|
|
4
|
+
getSelectedId: () => string | null;
|
|
5
|
+
getRootId: () => string;
|
|
6
|
+
/**
|
|
7
|
+
* Called when Tab/Enter fires and no node is selected — defaults the
|
|
8
|
+
* action to the root node so the user can build a tree from scratch
|
|
9
|
+
* without first clicking something.
|
|
10
|
+
*/
|
|
11
|
+
defaultTargetId?: () => string;
|
|
12
|
+
onAddChild: (id: string) => void;
|
|
13
|
+
onAddSibling: (id: string) => void;
|
|
14
|
+
onAddSiblingBefore: (id: string) => void;
|
|
15
|
+
onRemove: (id: string) => void;
|
|
16
|
+
onStartEdit: (id: string) => void;
|
|
17
|
+
onClearSelection: () => void;
|
|
18
|
+
onDuplicate: (id: string) => void;
|
|
19
|
+
onUndo: () => void;
|
|
20
|
+
onRedo: () => void;
|
|
21
|
+
/**
|
|
22
|
+
* Move selection to a neighbour. Returns the new selected id (or null
|
|
23
|
+
* if no neighbour exists in that direction).
|
|
24
|
+
* dx = -1 → select first child
|
|
25
|
+
* dx = +1 → select parent
|
|
26
|
+
* dy = -1 → select previous sibling
|
|
27
|
+
* dy = +1 → select next sibling
|
|
28
|
+
*/
|
|
29
|
+
onNavigate: (dx: number, dy: number) => void;
|
|
30
|
+
onSelectRoot: () => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function useKeyboard(opts: KeyboardOptions): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
export interface PanZoomOptions {
|
|
3
|
+
minScale?: number;
|
|
4
|
+
maxScale?: number;
|
|
5
|
+
step?: number;
|
|
6
|
+
getContainer: () => HTMLElement | null;
|
|
7
|
+
}
|
|
8
|
+
export interface MarqueeRect {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function usePanZoom(opts: PanZoomOptions): {
|
|
15
|
+
scale: Ref<number, number>;
|
|
16
|
+
offsetX: Ref<number, number>;
|
|
17
|
+
offsetY: Ref<number, number>;
|
|
18
|
+
isPanning: Ref<boolean, boolean>;
|
|
19
|
+
onWheel: (e: WheelEvent) => void;
|
|
20
|
+
zoomIn: () => void;
|
|
21
|
+
zoomOut: () => void;
|
|
22
|
+
startPan: (e: PointerEvent | MouseEvent) => void;
|
|
23
|
+
startMarquee: (worldX: number, worldY: number) => void;
|
|
24
|
+
updateMarquee: (worldX: number, worldY: number) => void;
|
|
25
|
+
isMarquee: Ref<boolean, boolean>;
|
|
26
|
+
marquee: {
|
|
27
|
+
x: number;
|
|
28
|
+
y: number;
|
|
29
|
+
width: number;
|
|
30
|
+
height: number;
|
|
31
|
+
};
|
|
32
|
+
marqueeVersion: Ref<number, number>;
|
|
33
|
+
setOnMarqueeEnd: (cb: (() => void) | null) => void;
|
|
34
|
+
resetView: (layoutWidth: number, layoutHeight: number, rootY: number, padding?: number) => void;
|
|
35
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export interface LayoutNode {
|
|
2
|
+
id: string;
|
|
3
|
+
text: string;
|
|
4
|
+
depth: number;
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
/** Font size to render this node's text at, in px. */
|
|
10
|
+
fontSize: number;
|
|
11
|
+
isRoot: boolean;
|
|
12
|
+
collapsed?: boolean;
|
|
13
|
+
side: 1 | -1;
|
|
14
|
+
/**
|
|
15
|
+
* Direction this node's children fan out in: 'right' (default for
|
|
16
|
+
* mindmap right side / tree), 'left' (mindmap left side), or 'down'
|
|
17
|
+
* (org mode).
|
|
18
|
+
*/
|
|
19
|
+
_dir: 'right' | 'left' | 'down';
|
|
20
|
+
/** Direction this node's children fan out in, as a signed scalar
|
|
21
|
+
* (1 = right, -1 = left). Mirrors `_dir` for callers that need
|
|
22
|
+
* a number. Kept in sync by applyDoLayout and forceRight — when
|
|
23
|
+
* the height-based balancer moves a child to the opposite side,
|
|
24
|
+
* the whole subtree gets its `side` / `_dir` / `_dirRight`
|
|
25
|
+
* re-stamped so descendants fan the right way. */
|
|
26
|
+
_dirRight: 1 | -1;
|
|
27
|
+
/** Layout-only: vertical extent of this node's subtree (post-order
|
|
28
|
+
* walk result, read by layoutHorizontal). Not for public use. */
|
|
29
|
+
_subtreeH: number;
|
|
30
|
+
/** Layout-only: horizontal extent of this node's subtree (read by
|
|
31
|
+
* layoutVertical / org mode). Not for public use. */
|
|
32
|
+
_subtreeW: number;
|
|
33
|
+
/** Optional embedded image (mirrored from MindMapNode.image).
|
|
34
|
+
* The renderer uses src/width/height; naturalW/H lock the
|
|
35
|
+
* resize aspect ratio. */
|
|
36
|
+
image?: MindMapImage;
|
|
37
|
+
/** Mirrored from MindMapNode.link. Read by the renderer to
|
|
38
|
+
* show a link icon next to the text. */
|
|
39
|
+
link?: {
|
|
40
|
+
url: string;
|
|
41
|
+
};
|
|
42
|
+
/** Mirrored from MindMapNode.note. Read by the renderer to
|
|
43
|
+
* show a note icon next to the text. */
|
|
44
|
+
note?: {
|
|
45
|
+
text: string;
|
|
46
|
+
};
|
|
47
|
+
children: LayoutNode[];
|
|
48
|
+
parent: LayoutNode | null;
|
|
49
|
+
}
|
|
50
|
+
import type { MindMapNode, MindMapImage } from '../types';
|
|
51
|
+
declare function heightAt(depth: number): number;
|
|
52
|
+
declare function fontAt(depth: number): number;
|
|
53
|
+
export type LayoutMode = 'mindmap' | 'tree' | 'org';
|
|
54
|
+
export interface LayoutOptions {
|
|
55
|
+
mode?: LayoutMode;
|
|
56
|
+
/** @deprecated kept for API compat; ignored in 1.html-style layout. */
|
|
57
|
+
balanced?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* When true, layout() leaves each LayoutNode's existing x/y in
|
|
60
|
+
* place — it still does the doLayout split / redirect / stack
|
|
61
|
+
* walk, but skips writing to child.x / child.y. Used after a
|
|
62
|
+
* drag: we commit the offset into the data tree, clear the
|
|
63
|
+
* per-node offset map, then re-run layout with this flag so
|
|
64
|
+
* the dragged node (and its subtree) stay where the user put
|
|
65
|
+
* them. The root is still forced to (0, 0) — to put the
|
|
66
|
+
* dragged node at a new position, the surrounding tree moves
|
|
67
|
+
* relative to it. New nodes added later get the algorithmic
|
|
68
|
+
* position since their LayoutNode has x = 0, y = 0.
|
|
69
|
+
*/
|
|
70
|
+
preservePositions?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export declare function layout(root: MindMapNode, options?: LayoutOptions): {
|
|
73
|
+
root: LayoutNode;
|
|
74
|
+
width: number;
|
|
75
|
+
height: number;
|
|
76
|
+
vbX: number;
|
|
77
|
+
vbY: number;
|
|
78
|
+
vbW: number;
|
|
79
|
+
vbH: number;
|
|
80
|
+
};
|
|
81
|
+
export declare const LAYOUT: {
|
|
82
|
+
/** Legacy single-size values for callers that still expect them. */
|
|
83
|
+
NODE_W: number;
|
|
84
|
+
NODE_H: number;
|
|
85
|
+
NODE_FONTS: number[];
|
|
86
|
+
NODE_HEIGHTS: number[];
|
|
87
|
+
NODE_MIN_W: number[];
|
|
88
|
+
NODE_PAD_H: number[];
|
|
89
|
+
NODE_FONT_WEIGHTS: number[];
|
|
90
|
+
H_GAP: number;
|
|
91
|
+
V_GAP: number;
|
|
92
|
+
SIDE_PADDING: number;
|
|
93
|
+
heightAt: typeof heightAt;
|
|
94
|
+
fontAt: typeof fontAt;
|
|
95
|
+
/** Clear the text-measurement cache (call after font load). */
|
|
96
|
+
clearMeasureCache: () => void;
|
|
97
|
+
};
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface BranchPalette {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
/** Hex colors cycled across top-level branches, in display order. */
|
|
5
|
+
colors: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare const BUILTIN_PALETTES: readonly BranchPalette[];
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a palette by id from a combined list of built-ins and
|
|
10
|
+
* user-defined custom palettes. Falls back to the default palette
|
|
11
|
+
* if `id` is missing or points at a deleted custom palette. Pure
|
|
12
|
+
* — no DOM, no reactive deps — so it can be called from a computed
|
|
13
|
+
* or a watch.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolvePalette(id: string, customPalettes?: readonly BranchPalette[]): BranchPalette;
|
|
16
|
+
/**
|
|
17
|
+
* Parse a free-form text blob into a cleaned color array. Accepts:
|
|
18
|
+
*
|
|
19
|
+
* 1. **Hex codes** — `#rgb` / `#rgba` / `#rrggbb` / `#rrggbbaa`,
|
|
20
|
+
* with or without the leading `#`. The alpha channel on
|
|
21
|
+
* 4- or 8-digit hex is silently dropped.
|
|
22
|
+
* 2. **`rgb()` / `rgba()` functions** — `rgb(255, 99, 71)`,
|
|
23
|
+
* `rgba(255,99,71,0.5)`. Whitespace and percentage values
|
|
24
|
+
* are both accepted (matches CSS rules). Alpha dropped.
|
|
25
|
+
* 3. **CSS named colors** — the 30 most common (`red`, `tomato`,
|
|
26
|
+
* `coral`, `teal`, …). A small curated set keeps the parser
|
|
27
|
+
* from silently accepting typos that look color-ish
|
|
28
|
+
* (`tan`, `peru` are in; `chartreuse1` is not).
|
|
29
|
+
* 4. **JSON / JS array** — `['#f87171', 'red']`,
|
|
30
|
+
* `["#f87171","rgb(0,0,255)"]`, even a single-line
|
|
31
|
+
* `["red","blue"]`. Bracket and quote chars are tolerated
|
|
32
|
+
* so a copy-pasted `[…]` round-trips cleanly.
|
|
33
|
+
* 5. **Any-delimiter blob** — the parser scans the raw text for
|
|
34
|
+
* color-shaped substrings rather than splitting on commas,
|
|
35
|
+
* so a user can paste `rgb(255, 0, 0), #0f0, blue` and every
|
|
36
|
+
* piece lands.
|
|
37
|
+
*
|
|
38
|
+
* Malformed tokens are dropped silently (consistent with the
|
|
39
|
+
* rest of the canvas's "paste messy text" UX). Returns at most
|
|
40
|
+
* `maxColors` entries; output is lowercased `#rrggbb` for stable
|
|
41
|
+
* dedup and direct comparison with `BUILTIN_PALETTES`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function parsePaletteInput(text: string, maxColors?: number): string[];
|
package/dist/entry.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import MindMap from './components/MindMap.vue';
|
|
2
|
+
import type { App } from 'vue';
|
|
3
|
+
import type { MindMapNode, MindMapOptions, MindMapTheme, MindMapExpose } from './types';
|
|
4
|
+
import { uid, clone, findNode, findParent, removeNode, addChild, addSibling } from './tree';
|
|
5
|
+
export type { MindMapNode, MindMapOptions, MindMapTheme, MindMapExpose };
|
|
6
|
+
export { MindMap };
|
|
7
|
+
export { uid, clone, findNode, findParent, removeNode, addChild, addSibling };
|
|
8
|
+
declare const plugin: {
|
|
9
|
+
install(app: App): void;
|
|
10
|
+
};
|
|
11
|
+
export default plugin;
|