nuxt-ui-elements-pro 0.1.6 → 0.1.7

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.
Files changed (52) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +103 -3
  3. package/dist/runtime/components/EventCalendar.d.vue.ts +84 -3
  4. package/dist/runtime/components/EventCalendar.vue +129 -12
  5. package/dist/runtime/components/EventCalendar.vue.d.ts +84 -3
  6. package/dist/runtime/components/OrgChart.d.vue.ts +191 -0
  7. package/dist/runtime/components/OrgChart.vue +290 -0
  8. package/dist/runtime/components/OrgChart.vue.d.ts +191 -0
  9. package/dist/runtime/components/{EventCalendarHeader.d.vue.ts → event-calendar/EventCalendarHeader.d.vue.ts} +20 -1
  10. package/dist/runtime/components/event-calendar/EventCalendarHeader.vue +55 -0
  11. package/dist/runtime/components/{EventCalendarHeader.vue.d.ts → event-calendar/EventCalendarHeader.vue.d.ts} +20 -1
  12. package/dist/runtime/components/{EventCalendarListView.d.vue.ts → event-calendar/EventCalendarListView.d.vue.ts} +1 -1
  13. package/dist/runtime/components/{EventCalendarListView.vue → event-calendar/EventCalendarListView.vue} +1 -1
  14. package/dist/runtime/components/{EventCalendarListView.vue.d.ts → event-calendar/EventCalendarListView.vue.d.ts} +1 -1
  15. package/dist/runtime/components/{EventCalendarMonthView.d.vue.ts → event-calendar/EventCalendarMonthView.d.vue.ts} +1 -1
  16. package/dist/runtime/components/{EventCalendarMonthView.vue → event-calendar/EventCalendarMonthView.vue} +1 -1
  17. package/dist/runtime/components/{EventCalendarMonthView.vue.d.ts → event-calendar/EventCalendarMonthView.vue.d.ts} +1 -1
  18. package/dist/runtime/components/{EventCalendarTimeGrid.d.vue.ts → event-calendar/EventCalendarTimeGrid.d.vue.ts} +1 -1
  19. package/dist/runtime/components/{EventCalendarTimeGrid.vue → event-calendar/EventCalendarTimeGrid.vue} +1 -1
  20. package/dist/runtime/components/{EventCalendarTimeGrid.vue.d.ts → event-calendar/EventCalendarTimeGrid.vue.d.ts} +1 -1
  21. package/dist/runtime/components/org-chart/OrgChartConnectors.d.vue.ts +15 -0
  22. package/dist/runtime/components/org-chart/OrgChartConnectors.vue +29 -0
  23. package/dist/runtime/components/org-chart/OrgChartConnectors.vue.d.ts +15 -0
  24. package/dist/runtime/components/org-chart/OrgChartControls.d.vue.ts +19 -0
  25. package/dist/runtime/components/org-chart/OrgChartControls.vue +25 -0
  26. package/dist/runtime/components/org-chart/OrgChartControls.vue.d.ts +19 -0
  27. package/dist/runtime/components/org-chart/OrgChartNode.d.vue.ts +30 -0
  28. package/dist/runtime/components/org-chart/OrgChartNode.vue +129 -0
  29. package/dist/runtime/components/org-chart/OrgChartNode.vue.d.ts +30 -0
  30. package/dist/runtime/composables/useOrgChart.d.ts +42 -0
  31. package/dist/runtime/composables/useOrgChart.js +154 -0
  32. package/dist/runtime/composables/useOrgChartContext.d.ts +8 -0
  33. package/dist/runtime/composables/useOrgChartContext.js +11 -0
  34. package/dist/runtime/composables/useOrgChartDragDrop.d.ts +20 -0
  35. package/dist/runtime/composables/useOrgChartDragDrop.js +67 -0
  36. package/dist/runtime/composables/useOrgChartKeyboard.d.ts +16 -0
  37. package/dist/runtime/composables/useOrgChartKeyboard.js +101 -0
  38. package/dist/runtime/composables/useOrgChartSearch.d.ts +16 -0
  39. package/dist/runtime/composables/useOrgChartSearch.js +62 -0
  40. package/dist/runtime/composables/useOrgChartZoom.d.ts +26 -0
  41. package/dist/runtime/composables/useOrgChartZoom.js +101 -0
  42. package/dist/runtime/index.d.ts +1 -0
  43. package/dist/runtime/index.js +1 -0
  44. package/dist/runtime/types/event-calendar.d.ts +1 -0
  45. package/dist/runtime/types/index.d.ts +2 -4
  46. package/dist/runtime/types/index.js +2 -4
  47. package/dist/runtime/types/org-chart.d.ts +181 -0
  48. package/dist/runtime/types/org-chart.js +0 -0
  49. package/dist/runtime/utils/org-chart.d.ts +55 -0
  50. package/dist/runtime/utils/org-chart.js +367 -0
  51. package/package.json +1 -1
  52. package/dist/runtime/components/EventCalendarHeader.vue +0 -48
@@ -0,0 +1,181 @@
1
+ import type { ComputedRef, Ref } from "vue";
2
+ /** A single node in the org chart flat data */
3
+ export interface OrgChartNode {
4
+ /** Unique identifier */
5
+ id: string | number;
6
+ /** Parent node ID. `null` for the root node. */
7
+ parentId: string | number | null;
8
+ /** Display name */
9
+ name: string;
10
+ /** Optional secondary text (e.g., job title) */
11
+ title?: string;
12
+ /** Avatar image URL */
13
+ avatar?: string;
14
+ /** Icon name (e.g., `i-lucide-user`) */
15
+ icon?: string;
16
+ /** Nuxt UI color override for this node */
17
+ color?: string;
18
+ /** Arbitrary user-defined metadata passed through to slots */
19
+ metadata?: Record<string, unknown>;
20
+ }
21
+ /** Layout direction */
22
+ export type OrgChartDirection = "vertical" | "horizontal" | "bottom-up" | "right-to-left";
23
+ /** Connector line style */
24
+ export type OrgChartConnectorStyle = "right-angle" | "curved" | "straight";
25
+ /** Selection mode */
26
+ export type OrgChartSelectionMode = "none" | "single" | "multiple";
27
+ /** Tree node with computed relationships and layout position */
28
+ export interface OrgChartTreeNode {
29
+ /** Original flat node data */
30
+ data: OrgChartNode;
31
+ /** Parent tree node (null for root) */
32
+ parent: OrgChartTreeNode | null;
33
+ /** Direct children */
34
+ children: OrgChartTreeNode[];
35
+ /** Depth in the tree (root = 0) */
36
+ depth: number;
37
+ /** 0-based index among siblings */
38
+ indexInSiblings: number;
39
+ /** Total sibling count */
40
+ siblingCount: number;
41
+ /** Count of all descendants */
42
+ descendantCount: number;
43
+ /** Layout x position (top-left of node) */
44
+ x: number;
45
+ /** Layout y position (top-left of node) */
46
+ y: number;
47
+ }
48
+ /** Connector line segment between parent and child */
49
+ export interface OrgChartConnector {
50
+ /** Parent node ID */
51
+ fromId: string | number;
52
+ /** Child node ID */
53
+ toId: string | number;
54
+ /** SVG path data string (d attribute) */
55
+ path: string;
56
+ }
57
+ /** Non-hierarchical connection between any two nodes (e.g., dotted-line reporting) */
58
+ export interface OrgChartConnection {
59
+ /** Unique identifier for this connection */
60
+ id: string | number;
61
+ /** Source node ID */
62
+ fromId: string | number;
63
+ /** Target node ID */
64
+ toId: string | number;
65
+ /** Optional label displayed on the connection */
66
+ label?: string;
67
+ /** Line style @defaultValue 'dashed' */
68
+ style?: "dashed" | "dotted" | "solid";
69
+ /** Nuxt UI color for this connection */
70
+ color?: string;
71
+ /** Arbitrary metadata passed through to slots */
72
+ metadata?: Record<string, unknown>;
73
+ }
74
+ /** Computed connection path for rendering */
75
+ export interface OrgChartConnectionPath {
76
+ /** Original connection data */
77
+ connection: OrgChartConnection;
78
+ /** SVG path data string */
79
+ path: string;
80
+ /** Label position (midpoint of path) */
81
+ labelX: number;
82
+ labelY: number;
83
+ }
84
+ /** Computed layout result */
85
+ export interface OrgChartLayout {
86
+ /** All visible tree nodes with x, y positions */
87
+ nodes: OrgChartTreeNode[];
88
+ /** All connector paths (hierarchical parent-child) */
89
+ connectors: OrgChartConnector[];
90
+ /** Non-hierarchical connection paths */
91
+ connectionPaths: OrgChartConnectionPath[];
92
+ /** Total width of the layout (px) */
93
+ width: number;
94
+ /** Total height of the layout (px) */
95
+ height: number;
96
+ }
97
+ export interface OrgChartLayoutConfig {
98
+ /** Horizontal gap between sibling nodes (px) @defaultValue 40 */
99
+ siblingGap?: number;
100
+ /** Vertical gap between levels (px) @defaultValue 60 */
101
+ levelGap?: number;
102
+ /** Node width (px) @defaultValue 200 */
103
+ nodeWidth?: number;
104
+ /** Node height (px) @defaultValue 80 */
105
+ nodeHeight?: number;
106
+ /** Corner radius for right-angle connectors (px). Set to 0 for sharp corners. @defaultValue 8 */
107
+ connectorRadius?: number;
108
+ }
109
+ export type ResolvedLayoutConfig = Required<OrgChartLayoutConfig>;
110
+ export interface OrgChartZoomConfig {
111
+ /** Enable zoom/pan @defaultValue false */
112
+ enabled?: boolean;
113
+ /** Minimum zoom scale @defaultValue 0.25 */
114
+ min?: number;
115
+ /** Maximum zoom scale @defaultValue 2 */
116
+ max?: number;
117
+ /** Initial zoom scale @defaultValue 1 */
118
+ initial?: number;
119
+ /** Zoom step per scroll tick @defaultValue 0.1 */
120
+ step?: number;
121
+ /** Show zoom controls overlay @defaultValue true */
122
+ controls?: boolean;
123
+ }
124
+ export type ResolvedZoomConfig = Required<OrgChartZoomConfig>;
125
+ export interface OrgChartContext {
126
+ tree: ComputedRef<OrgChartTreeNode | null>;
127
+ layout: ComputedRef<OrgChartLayout>;
128
+ flatVisibleNodes: ComputedRef<OrgChartTreeNode[]>;
129
+ nodeMap: ComputedRef<Map<string | number, OrgChartTreeNode>>;
130
+ direction: ComputedRef<OrgChartDirection>;
131
+ connectorStyle: ComputedRef<OrgChartConnectorStyle>;
132
+ selectionMode: ComputedRef<OrgChartSelectionMode>;
133
+ compact: ComputedRef<boolean>;
134
+ animated: ComputedRef<boolean>;
135
+ draggable: ComputedRef<boolean>;
136
+ layoutConfig: ComputedRef<ResolvedLayoutConfig>;
137
+ zoomConfig: ComputedRef<ResolvedZoomConfig>;
138
+ expandedIds: Ref<Set<string | number>>;
139
+ selectedIds: Ref<Set<string | number>>;
140
+ focusedId: Ref<string | number | null>;
141
+ searchQuery: ComputedRef<string>;
142
+ matchedIds: ComputedRef<Set<string | number>>;
143
+ isMatched: (id: string | number) => boolean;
144
+ isDimmed: (id: string | number) => boolean;
145
+ isExpanded: (id: string | number) => boolean;
146
+ isSelected: (id: string | number) => boolean;
147
+ isFocused: (id: string | number) => boolean;
148
+ getDescendantCount: (id: string | number) => number;
149
+ getNode: (id: string | number) => OrgChartTreeNode | undefined;
150
+ getChildren: (id: string | number) => OrgChartTreeNode[];
151
+ getAncestors: (id: string | number) => OrgChartTreeNode[];
152
+ toggleExpand: (id: string | number) => void;
153
+ expandAll: () => void;
154
+ collapseAll: () => void;
155
+ selectNode: (id: string | number) => void;
156
+ deselectNode: (id: string | number) => void;
157
+ scrollToNode: (id: string | number) => void;
158
+ fitToView: () => void;
159
+ handleNodeClick: (node: OrgChartTreeNode, e: Event) => void;
160
+ onKeydown: (e: KeyboardEvent) => void;
161
+ draggedNodeId: Ref<string | number | null>;
162
+ dropTargetId: Ref<string | number | null>;
163
+ onDragStart: (nodeId: string | number, e: DragEvent) => void;
164
+ onDragOver: (nodeId: string | number, e: DragEvent) => void;
165
+ onDragLeave: (e: DragEvent) => void;
166
+ onDrop: (nodeId: string | number, e: DragEvent) => void;
167
+ onDragEnd: (e: DragEvent) => void;
168
+ connectionPaths: ComputedRef<OrgChartConnectionPath[]>;
169
+ handleConnectionClick: (connection: OrgChartConnection, e: Event) => void;
170
+ ui: ComputedRef<any>;
171
+ propUi: ComputedRef<any>;
172
+ scale: Ref<number>;
173
+ translateX: Ref<number>;
174
+ translateY: Ref<number>;
175
+ transformStyle: ComputedRef<Record<string, string>>;
176
+ zoomIn: () => void;
177
+ zoomOut: () => void;
178
+ zoomReset: () => void;
179
+ onWheel: (e: WheelEvent) => void;
180
+ onPointerDown: (e: PointerEvent) => void;
181
+ }
File without changes
@@ -0,0 +1,55 @@
1
+ import type { OrgChartNode, OrgChartTreeNode, OrgChartConnector, OrgChartConnection, OrgChartConnectionPath, OrgChartLayout, OrgChartDirection, OrgChartConnectorStyle, ResolvedLayoutConfig } from "../types/org-chart.js";
2
+ /**
3
+ * Build a tree from a flat node list.
4
+ * Validates exactly one root (parentId === null). Returns null for empty input.
5
+ */
6
+ export declare function buildTree(nodes: OrgChartNode[]): OrgChartTreeNode | null;
7
+ /**
8
+ * Compute full layout for the tree.
9
+ * Returns positioned nodes, connector paths, and total dimensions.
10
+ */
11
+ export declare function computeLayout(root: OrgChartTreeNode, config: ResolvedLayoutConfig, direction: OrgChartDirection, expandedIds: Set<string | number>): OrgChartLayout;
12
+ /** Overloaded layout that also accepts connector style */
13
+ export declare function computeFullLayout(root: OrgChartTreeNode, config: ResolvedLayoutConfig, direction: OrgChartDirection, connectorStyle: OrgChartConnectorStyle, expandedIds: Set<string | number>, connections?: OrgChartConnection[]): OrgChartLayout;
14
+ /**
15
+ * Compute SVG path data for connectors between parent-child pairs.
16
+ */
17
+ export declare function computeConnectors(nodes: OrgChartTreeNode[], config: ResolvedLayoutConfig, direction: OrgChartDirection, style: OrgChartConnectorStyle): OrgChartConnector[];
18
+ /**
19
+ * Compute SVG paths for non-hierarchical connections between arbitrary nodes.
20
+ * These are rendered as curved bezier paths offset from the straight line to
21
+ * avoid overlapping with hierarchical connectors.
22
+ */
23
+ export declare function computeConnectionPaths(nodes: OrgChartTreeNode[], config: ResolvedLayoutConfig, direction: OrgChartDirection, connections: OrgChartConnection[]): OrgChartConnectionPath[];
24
+ /**
25
+ * Flatten visible tree in DFS order, skipping collapsed subtrees.
26
+ * The root is always included.
27
+ */
28
+ export declare function flattenVisibleTree(root: OrgChartTreeNode, expandedIds: Set<string | number>): OrgChartTreeNode[];
29
+ /**
30
+ * Get ancestors of a node (from immediate parent to root).
31
+ */
32
+ export declare function getAncestors(nodeId: string | number, nodeMap: Map<string | number, OrgChartTreeNode>): OrgChartTreeNode[];
33
+ /**
34
+ * Get all descendants of a node (DFS, not including the node itself).
35
+ */
36
+ export declare function getDescendants(node: OrgChartTreeNode): OrgChartTreeNode[];
37
+ /**
38
+ * Collect all node IDs in the tree.
39
+ */
40
+ export declare function getAllNodeIds(root: OrgChartTreeNode): Set<string | number>;
41
+ /**
42
+ * Build a Map from node ID to OrgChartTreeNode for O(1) lookups.
43
+ */
44
+ export declare function buildNodeMap(root: OrgChartTreeNode): Map<string | number, OrgChartTreeNode>;
45
+ /** Default layout config values */
46
+ export declare const DEFAULT_LAYOUT_CONFIG: ResolvedLayoutConfig;
47
+ /** Default zoom config values */
48
+ export declare const DEFAULT_ZOOM_CONFIG: {
49
+ readonly enabled: false;
50
+ readonly min: 0.25;
51
+ readonly max: 2;
52
+ readonly initial: 1;
53
+ readonly step: 0.1;
54
+ readonly controls: true;
55
+ };
@@ -0,0 +1,367 @@
1
+ export function buildTree(nodes) {
2
+ if (nodes.length === 0) return null;
3
+ const ROOT_KEY = Symbol("root");
4
+ const childrenMap = /* @__PURE__ */ new Map();
5
+ for (const node of nodes) {
6
+ const key = node.parentId === null ? ROOT_KEY : node.parentId;
7
+ const list = childrenMap.get(key);
8
+ if (list) list.push(node);
9
+ else childrenMap.set(key, [node]);
10
+ }
11
+ const roots = childrenMap.get(ROOT_KEY);
12
+ if (!roots || roots.length === 0) {
13
+ throw new Error("[OrgChart] No root node found (parentId === null).");
14
+ }
15
+ if (roots.length > 1) {
16
+ throw new Error(`[OrgChart] Multiple root nodes found: ${roots.map((r) => r.id).join(", ")}. Only one root is supported.`);
17
+ }
18
+ function build(data, parent, depth, indexInSiblings, siblingCount) {
19
+ const node = {
20
+ data,
21
+ parent,
22
+ children: [],
23
+ depth,
24
+ indexInSiblings,
25
+ siblingCount,
26
+ descendantCount: 0,
27
+ x: 0,
28
+ y: 0
29
+ };
30
+ const childData = childrenMap.get(data.id) ?? [];
31
+ node.children = childData.map((child, i) => build(child, node, depth + 1, i, childData.length));
32
+ node.descendantCount = node.children.reduce((sum, c) => sum + 1 + c.descendantCount, 0);
33
+ return node;
34
+ }
35
+ return build(roots[0], null, 0, 0, 1);
36
+ }
37
+ function buildLayoutTree(root, expandedIds) {
38
+ const children = expandedIds.has(root.data.id) ? root.children.map((c) => buildLayoutTree(c, expandedIds)) : [];
39
+ return { treeNode: root, children, prelim: 0, mod: 0, x: 0 };
40
+ }
41
+ function layoutChildren(node, siblingGap, nodeWidth) {
42
+ if (node.children.length === 0) return;
43
+ let nextX = 0;
44
+ for (const child of node.children) {
45
+ child.prelim = nextX;
46
+ layoutChildren(child, siblingGap, nodeWidth);
47
+ nextX = getRightContour(child, child.prelim) + nodeWidth + siblingGap;
48
+ }
49
+ const first = node.children[0];
50
+ const last = node.children[node.children.length - 1];
51
+ const mid = (first.prelim + last.prelim) / 2;
52
+ node.mod = mid;
53
+ }
54
+ function getRightContour(node, offset) {
55
+ let max = offset;
56
+ for (const child of node.children) {
57
+ max = Math.max(max, getRightContour(child, offset + child.prelim));
58
+ }
59
+ return max;
60
+ }
61
+ function isVerticalFlow(direction) {
62
+ return direction === "vertical" || direction === "bottom-up";
63
+ }
64
+ function assignPositions(root, config, direction) {
65
+ const vertical = isVerticalFlow(direction);
66
+ layoutChildren(root, config.siblingGap, vertical ? config.nodeWidth : config.nodeHeight);
67
+ function absolutePositions(node, offsetX, depth) {
68
+ const absX = offsetX + node.prelim;
69
+ if (vertical) {
70
+ node.treeNode.x = absX;
71
+ node.treeNode.y = depth * (config.nodeHeight + config.levelGap);
72
+ } else {
73
+ node.treeNode.x = depth * (config.nodeWidth + config.levelGap);
74
+ node.treeNode.y = absX;
75
+ }
76
+ for (const child of node.children) {
77
+ absolutePositions(child, absX - node.mod, depth + 1);
78
+ }
79
+ }
80
+ absolutePositions(root, 0, 0);
81
+ }
82
+ function normalizePositions(nodes, padding = 20) {
83
+ if (nodes.length === 0) return;
84
+ let minX = Infinity;
85
+ let minY = Infinity;
86
+ for (const n of nodes) {
87
+ if (n.x < minX) minX = n.x;
88
+ if (n.y < minY) minY = n.y;
89
+ }
90
+ const dx = padding - minX;
91
+ const dy = padding - minY;
92
+ for (const n of nodes) {
93
+ n.x += dx;
94
+ n.y += dy;
95
+ }
96
+ }
97
+ export function computeLayout(root, config, direction, expandedIds) {
98
+ const layoutRoot = buildLayoutTree(root, expandedIds);
99
+ assignPositions(layoutRoot, config, direction);
100
+ const nodes = flattenAll(layoutRoot);
101
+ const treeNodes = nodes.map((ln) => ln.treeNode);
102
+ if (direction === "bottom-up") {
103
+ flipVertical(treeNodes, config);
104
+ } else if (direction === "right-to-left") {
105
+ flipHorizontal(treeNodes, config);
106
+ }
107
+ normalizePositions(treeNodes);
108
+ const connectors = computeConnectors(treeNodes, config, direction, "right-angle");
109
+ const w = config.nodeWidth;
110
+ const h = config.nodeHeight;
111
+ let maxX = 0;
112
+ let maxY = 0;
113
+ for (const n of treeNodes) {
114
+ if (n.x + w > maxX) maxX = n.x + w;
115
+ if (n.y + h > maxY) maxY = n.y + h;
116
+ }
117
+ return {
118
+ nodes: treeNodes,
119
+ connectors,
120
+ connectionPaths: [],
121
+ width: maxX + 20,
122
+ height: maxY + 20
123
+ };
124
+ }
125
+ function flipVertical(nodes, config) {
126
+ if (nodes.length === 0) return;
127
+ let maxY = 0;
128
+ for (const n of nodes) {
129
+ const bottom = n.y + config.nodeHeight;
130
+ if (bottom > maxY) maxY = bottom;
131
+ }
132
+ for (const n of nodes) {
133
+ n.y = maxY - n.y - config.nodeHeight;
134
+ }
135
+ }
136
+ function flipHorizontal(nodes, config) {
137
+ if (nodes.length === 0) return;
138
+ let maxX = 0;
139
+ for (const n of nodes) {
140
+ const right = n.x + config.nodeWidth;
141
+ if (right > maxX) maxX = right;
142
+ }
143
+ for (const n of nodes) {
144
+ n.x = maxX - n.x - config.nodeWidth;
145
+ }
146
+ }
147
+ export function computeFullLayout(root, config, direction, connectorStyle, expandedIds, connections) {
148
+ const layoutRoot = buildLayoutTree(root, expandedIds);
149
+ assignPositions(layoutRoot, config, direction);
150
+ const nodes = flattenAll(layoutRoot);
151
+ const treeNodes = nodes.map((ln) => ln.treeNode);
152
+ if (direction === "bottom-up") {
153
+ flipVertical(treeNodes, config);
154
+ } else if (direction === "right-to-left") {
155
+ flipHorizontal(treeNodes, config);
156
+ }
157
+ normalizePositions(treeNodes);
158
+ const connectors = computeConnectors(treeNodes, config, direction, connectorStyle);
159
+ const connectionPaths = connections && connections.length > 0 ? computeConnectionPaths(treeNodes, config, direction, connections) : [];
160
+ let maxX = 0;
161
+ let maxY = 0;
162
+ for (const n of treeNodes) {
163
+ const right = n.x + config.nodeWidth;
164
+ const bottom = n.y + config.nodeHeight;
165
+ if (right > maxX) maxX = right;
166
+ if (bottom > maxY) maxY = bottom;
167
+ }
168
+ return {
169
+ nodes: treeNodes,
170
+ connectors,
171
+ connectionPaths,
172
+ width: maxX + 20,
173
+ height: maxY + 20
174
+ };
175
+ }
176
+ function flattenAll(node) {
177
+ const result = [node];
178
+ for (const child of node.children) {
179
+ result.push(...flattenAll(child));
180
+ }
181
+ return result;
182
+ }
183
+ function getConnectorEndpoints(parent, child, config, direction) {
184
+ switch (direction) {
185
+ case "vertical":
186
+ return {
187
+ px: parent.x + config.nodeWidth / 2,
188
+ py: parent.y + config.nodeHeight,
189
+ cx: child.x + config.nodeWidth / 2,
190
+ cy: child.y
191
+ };
192
+ case "bottom-up":
193
+ return {
194
+ px: parent.x + config.nodeWidth / 2,
195
+ py: parent.y,
196
+ cx: child.x + config.nodeWidth / 2,
197
+ cy: child.y + config.nodeHeight
198
+ };
199
+ case "horizontal":
200
+ return {
201
+ px: parent.x + config.nodeWidth,
202
+ py: parent.y + config.nodeHeight / 2,
203
+ cx: child.x,
204
+ cy: child.y + config.nodeHeight / 2
205
+ };
206
+ case "right-to-left":
207
+ return {
208
+ px: parent.x,
209
+ py: parent.y + config.nodeHeight / 2,
210
+ cx: child.x + config.nodeWidth,
211
+ cy: child.y + config.nodeHeight / 2
212
+ };
213
+ }
214
+ }
215
+ export function computeConnectors(nodes, config, direction, style) {
216
+ const nodeMap = /* @__PURE__ */ new Map();
217
+ for (const n of nodes) nodeMap.set(n.data.id, n);
218
+ const connectors = [];
219
+ for (const node of nodes) {
220
+ if (!node.parent) continue;
221
+ const parent = nodeMap.get(node.parent.data.id);
222
+ if (!parent) continue;
223
+ const { px, py, cx, cy } = getConnectorEndpoints(parent, node, config, direction);
224
+ const path = buildConnectorPath(px, py, cx, cy, style, isVerticalFlow(direction), config.connectorRadius);
225
+ connectors.push({
226
+ fromId: parent.data.id,
227
+ toId: node.data.id,
228
+ path
229
+ });
230
+ }
231
+ return connectors;
232
+ }
233
+ function buildConnectorPath(px, py, cx, cy, style, vertical, radius = 0) {
234
+ if (style === "straight") {
235
+ return `M ${px} ${py} L ${cx} ${cy}`;
236
+ }
237
+ if (style === "curved") {
238
+ if (vertical) {
239
+ const midY = py + (cy - py) / 2;
240
+ return `M ${px} ${py} C ${px} ${midY}, ${cx} ${midY}, ${cx} ${cy}`;
241
+ }
242
+ const midX2 = px + (cx - px) / 2;
243
+ return `M ${px} ${py} C ${midX2} ${py}, ${midX2} ${cy}, ${cx} ${cy}`;
244
+ }
245
+ if (vertical) {
246
+ const midY = py + (cy - py) / 2;
247
+ if (radius <= 0 || px === cx) {
248
+ return `M ${px} ${py} L ${px} ${midY} L ${cx} ${midY} L ${cx} ${cy}`;
249
+ }
250
+ const r2 = Math.min(radius, Math.abs(cy - py) / 4, Math.abs(cx - px) / 2);
251
+ const dx = cx > px ? r2 : -r2;
252
+ const dy1 = midY > py ? r2 : -r2;
253
+ const dy2 = cy > midY ? r2 : -r2;
254
+ return [
255
+ `M ${px} ${py}`,
256
+ `L ${px} ${midY - dy1}`,
257
+ `Q ${px} ${midY}, ${px + dx} ${midY}`,
258
+ `L ${cx - dx} ${midY}`,
259
+ `Q ${cx} ${midY}, ${cx} ${midY + dy2}`,
260
+ `L ${cx} ${cy}`
261
+ ].join(" ");
262
+ }
263
+ const midX = px + (cx - px) / 2;
264
+ if (radius <= 0 || py === cy) {
265
+ return `M ${px} ${py} L ${midX} ${py} L ${midX} ${cy} L ${cx} ${cy}`;
266
+ }
267
+ const r = Math.min(radius, Math.abs(cx - px) / 4, Math.abs(cy - py) / 2);
268
+ const dx1 = midX > px ? r : -r;
269
+ const dx2 = cx > midX ? r : -r;
270
+ const dy = cy > py ? r : -r;
271
+ return [
272
+ `M ${px} ${py}`,
273
+ `L ${midX - dx1} ${py}`,
274
+ `Q ${midX} ${py}, ${midX} ${py + dy}`,
275
+ `L ${midX} ${cy - dy}`,
276
+ `Q ${midX} ${cy}, ${midX + dx2} ${cy}`,
277
+ `L ${cx} ${cy}`
278
+ ].join(" ");
279
+ }
280
+ export function computeConnectionPaths(nodes, config, direction, connections) {
281
+ const nodeMap = /* @__PURE__ */ new Map();
282
+ for (const n of nodes) nodeMap.set(n.data.id, n);
283
+ const result = [];
284
+ for (const conn of connections) {
285
+ const from = nodeMap.get(conn.fromId);
286
+ const to = nodeMap.get(conn.toId);
287
+ if (!from || !to) continue;
288
+ const fromCx = from.x + config.nodeWidth / 2;
289
+ const fromCy = from.y + config.nodeHeight / 2;
290
+ const toCx = to.x + config.nodeWidth / 2;
291
+ const toCy = to.y + config.nodeHeight / 2;
292
+ const dx = toCx - fromCx;
293
+ const dy = toCy - fromCy;
294
+ const dist = Math.sqrt(dx * dx + dy * dy);
295
+ const offset = Math.min(dist * 0.3, 80);
296
+ const nx = dist > 0 ? -dy / dist : 0;
297
+ const ny = dist > 0 ? dx / dist : 1;
298
+ const cpX = (fromCx + toCx) / 2 + nx * offset;
299
+ const cpY = (fromCy + toCy) / 2 + ny * offset;
300
+ const path = `M ${fromCx} ${fromCy} Q ${cpX} ${cpY}, ${toCx} ${toCy}`;
301
+ const labelX = (fromCx + 2 * cpX + toCx) / 4;
302
+ const labelY = (fromCy + 2 * cpY + toCy) / 4;
303
+ result.push({ connection: conn, path, labelX, labelY });
304
+ }
305
+ return result;
306
+ }
307
+ export function flattenVisibleTree(root, expandedIds) {
308
+ const result = [root];
309
+ if (expandedIds.has(root.data.id)) {
310
+ for (const child of root.children) {
311
+ result.push(...flattenVisibleTree(child, expandedIds));
312
+ }
313
+ }
314
+ return result;
315
+ }
316
+ export function getAncestors(nodeId, nodeMap) {
317
+ const result = [];
318
+ let current = nodeMap.get(nodeId);
319
+ if (!current) return result;
320
+ current = current.parent ?? void 0;
321
+ while (current) {
322
+ result.push(current);
323
+ current = current.parent ?? void 0;
324
+ }
325
+ return result;
326
+ }
327
+ export function getDescendants(node) {
328
+ const result = [];
329
+ for (const child of node.children) {
330
+ result.push(child);
331
+ result.push(...getDescendants(child));
332
+ }
333
+ return result;
334
+ }
335
+ export function getAllNodeIds(root) {
336
+ const ids = /* @__PURE__ */ new Set();
337
+ function walk(node) {
338
+ ids.add(node.data.id);
339
+ for (const child of node.children) walk(child);
340
+ }
341
+ walk(root);
342
+ return ids;
343
+ }
344
+ export function buildNodeMap(root) {
345
+ const map = /* @__PURE__ */ new Map();
346
+ function walk(node) {
347
+ map.set(node.data.id, node);
348
+ for (const child of node.children) walk(child);
349
+ }
350
+ walk(root);
351
+ return map;
352
+ }
353
+ export const DEFAULT_LAYOUT_CONFIG = {
354
+ siblingGap: 40,
355
+ levelGap: 60,
356
+ nodeWidth: 200,
357
+ nodeHeight: 80,
358
+ connectorRadius: 8
359
+ };
360
+ export const DEFAULT_ZOOM_CONFIG = {
361
+ enabled: false,
362
+ min: 0.25,
363
+ max: 2,
364
+ initial: 1,
365
+ step: 0.1,
366
+ controls: true
367
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-ui-elements-pro",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Pro components for nuxt-ui-elements",
5
5
  "license": "UNLICENSED",
6
6
  "files": [
@@ -1,48 +0,0 @@
1
- <script>
2
- import { Primitive } from "reka-ui";
3
- import { useEventCalendarContext } from "../composables/useEventCalendarContext";
4
- </script>
5
-
6
- <script setup>
7
- const props = defineProps({
8
- as: { type: null, required: false }
9
- });
10
- defineSlots();
11
- const ctx = useEventCalendarContext();
12
- </script>
13
-
14
- <template>
15
- <Primitive :as="props.as ?? 'div'" data-slot="header" :class="ctx.ui.value.header({ class: ctx.propUi.value?.header })">
16
- <slot
17
- :title="ctx.headerTitle.value"
18
- :prev="ctx.goToPrev"
19
- :next="ctx.goToNext"
20
- :today="ctx.goToToday"
21
- :current-date="ctx.displayDate.value"
22
- :view="ctx.view.value"
23
- :set-view="ctx.setView">
24
- <span data-slot="headerTitle" :class="ctx.ui.value.headerTitle({ class: ctx.propUi.value?.headerTitle })" aria-live="polite" aria-atomic="true">
25
- {{ ctx.headerTitle.value }}
26
- </span>
27
-
28
- <div data-slot="headerActions" :class="ctx.ui.value.headerActions({ class: ctx.propUi.value?.headerActions })">
29
- <div data-slot="viewSwitcher" role="group" aria-label="Calendar view" :class="ctx.ui.value.viewSwitcher({ class: ctx.propUi.value?.viewSwitcher })">
30
- <UButton
31
- v-for="v in ['month', 'week', 'day', 'list']"
32
- :key="v"
33
- :label="v"
34
- size="xs"
35
- :color="ctx.view.value === v ? ctx.color.value : 'neutral'"
36
- :variant="ctx.view.value === v ? 'subtle' : 'ghost'"
37
- :aria-pressed="ctx.view.value === v"
38
- class="capitalize"
39
- @click="ctx.setView(v)" />
40
- </div>
41
-
42
- <UButton icon="i-lucide-chevron-left" color="neutral" variant="ghost" size="xs" square :aria-label="`Previous ${ctx.view.value}`" @click="ctx.goToPrev" />
43
- <UButton label="Today" color="neutral" variant="ghost" size="xs" aria-label="Go to today" @click="ctx.goToToday" />
44
- <UButton icon="i-lucide-chevron-right" color="neutral" variant="ghost" size="xs" square :aria-label="`Next ${ctx.view.value}`" @click="ctx.goToNext" />
45
- </div>
46
- </slot>
47
- </Primitive>
48
- </template>