fds-vue-core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # FDS Vue Core
2
+
3
+ A Vue 3 component library with FDS Core integration, built with TypeScript for excellent developer experience.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ yarn add fds-vue-core
9
+ ```
10
+
11
+ ## Peer Dependencies
12
+
13
+ Make sure you have the required peer dependencies installed:
14
+
15
+ ```bash
16
+ npm install vue@^3.5.0 fds-core@^3.8.0
17
+ ```
18
+
19
+ ## Styling
20
+
21
+ This library is **style-free** and designed to work with your existing CSS framework. The components use standard HTML classes that you can style with:
22
+
23
+ - **Tailwind CSS** (recommended)
24
+ - **CSS Modules**
25
+ - **Styled Components**
26
+ - **Any CSS framework**
27
+
28
+ The components will inherit your project's styling automatically.
29
+
30
+ ## Usage
31
+
32
+ ### Global Registration
33
+
34
+ ```typescript
35
+ import { createApp } from 'vue'
36
+ import FdsVueCore from 'fds-vue-core'
37
+
38
+ const app = createApp(App)
39
+ app.use(FdsVueCore)
40
+ app.mount('#app')
41
+ ```
42
+
43
+ ### Individual Component Import
44
+
45
+ ```typescript
46
+ import { FdsTreeView } from 'fds-vue-core'
47
+ import 'fds-vue-core/style.css'
48
+ ```
49
+
50
+ ## Components
51
+
52
+ ### FdsTreeView
53
+
54
+ A hierarchical tree view component with full TypeScript support.
55
+
56
+ #### Basic Usage
57
+
58
+ ```vue
59
+ <template>
60
+ <FdsTreeView
61
+ :nodes="treeData"
62
+ :nodeId="'root'"
63
+ :nodeExpandIcon="'arrowDown'"
64
+ :nodeCollapseIcon="'arrowUp'"
65
+ :indentation="20"
66
+ :showNodeDescription="true"
67
+ :showChildrenCount="true"
68
+ :showIndeterminate="true"
69
+ />
70
+ </template>
71
+
72
+ <script setup lang="ts">
73
+ import { FdsTreeView, type TreeNode } from 'fds-vue-core'
74
+
75
+ const treeData: TreeNode[] = [
76
+ {
77
+ nodeId: 'root-1',
78
+ title: 'Documents',
79
+ children: [
80
+ {
81
+ nodeId: 'doc-1',
82
+ title: 'Work',
83
+ children: [
84
+ {
85
+ nodeId: 'work-1',
86
+ title: 'Projects',
87
+ data: { type: 'folder', count: 5 }
88
+ }
89
+ ]
90
+ }
91
+ ]
92
+ }
93
+ ]
94
+ </script>
95
+ ```
96
+
97
+ #### TypeScript Support
98
+
99
+ The library provides full TypeScript support with comprehensive type definitions:
100
+
101
+ ```typescript
102
+ import type {
103
+ TreeNode,
104
+ TreeNodeArray,
105
+ TreeNodeItem,
106
+ TreeViewProps,
107
+ NodeId,
108
+ TreeViewEvents,
109
+ ComponentSize,
110
+ ComponentVariant
111
+ } from 'fds-vue-core'
112
+
113
+ // Typed tree data
114
+ interface ProjectData {
115
+ type: 'project'
116
+ status: 'active' | 'completed' | 'planning'
117
+ priority: number
118
+ }
119
+
120
+ const typedTreeData: TreeNode<ProjectData>[] = [
121
+ {
122
+ nodeId: 'proj-1',
123
+ title: 'My Project',
124
+ data: {
125
+ type: 'project',
126
+ status: 'active',
127
+ priority: 1
128
+ }
129
+ }
130
+ ]
131
+ ```
132
+
133
+ #### Props
134
+
135
+ | Prop | Type | Default | Description |
136
+ |------|------|---------|-------------|
137
+ | `nodes` | `TreeNode[]` | `[]` | Array of tree nodes |
138
+ | `nodeId` | `string` | - | Unique identifier for the current node |
139
+ | `nodeExpandIcon` | `string` | - | Icon name for expanded state |
140
+ | `nodeCollapseIcon` | `string` | - | Icon name for collapsed state |
141
+ | `indentation` | `number` | - | Indentation level in pixels |
142
+ | `showNodeDescription` | `boolean` | `false` | Show node descriptions |
143
+ | `showChildrenCount` | `boolean` | `false` | Show children count |
144
+ | `showIndeterminate` | `boolean` | `false` | Show indeterminate state for partial selections |
145
+
146
+ #### Events
147
+
148
+ | Event | Payload | Description |
149
+ |-------|---------|-------------|
150
+ | `node-select` | `TreeNode` | Fired when a node is selected |
151
+ | `node-expand` | `TreeNode` | Fired when a node is expanded |
152
+ | `node-collapse` | `TreeNode` | Fired when a node is collapsed |
153
+ | `selection-change` | `TreeNode[]` | Fired when selection changes |
154
+
155
+ ## Development
156
+
157
+ ```bash
158
+ # Install dependencies
159
+ npm install
160
+
161
+ # Start development server
162
+ npm run dev
163
+
164
+ # Build library
165
+ npm run build
166
+
167
+ # Type checking
168
+ npm run type-check
169
+
170
+ # Linting
171
+ npm run lint
172
+ ```
173
+
174
+ ## Building for Production
175
+
176
+ ```bash
177
+ npm run build
178
+ ```
179
+
180
+ This will generate:
181
+ - `dist/fds-vue-core.es.js` - ES module build
182
+ - `dist/fds-vue-core.cjs.js` - CommonJS build
183
+ - `dist/index.d.ts` - TypeScript declarations
184
+ - `dist/style.css` - Styles
185
+
186
+ ## TypeScript
187
+
188
+ This library is built with TypeScript and provides comprehensive type definitions. All components, props, events, and utilities are fully typed for excellent developer experience.
189
+
190
+ ## License
191
+
192
+ MIT
@@ -0,0 +1,3 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
3
+ //# sourceMappingURL=App.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.vue.d.ts","sourceRoot":"","sources":["../src/App.vue"],"names":[],"mappings":";AAwSA,wBACG"}
@@ -0,0 +1,12 @@
1
+ import type { TreeNode, TreeViewProps } from './types';
2
+ type Props<T = Record<string, unknown>> = TreeViewProps<T>;
3
+ type __VLS_Props = Props;
4
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
5
+ nodes: TreeNode<Record<string, unknown>>[];
6
+ depth: number;
7
+ showNodeDescription: boolean;
8
+ showChildrenCount: boolean;
9
+ expandChildrenOnSelect: boolean;
10
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
+ export default _default;
12
+ //# sourceMappingURL=FdsTreeView.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FdsTreeView.vue.d.ts","sourceRoot":"","sources":["../../../src/components/fds-tree-view/FdsTreeView.vue"],"names":[],"mappings":"AAyMA,OAAO,KAAK,EAAE,QAAQ,EAA+B,aAAa,EAAE,MAAM,SAAS,CAAA;AAEnF,KAAK,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,CAAA;AAE1D,KAAK,WAAW,GAAG,KAAK,CAAC;;;;;;;;AA2WzB,wBAGG"}
@@ -0,0 +1,18 @@
1
+ import type { TreeNode, NodeId } from './types';
2
+ declare const useTreeState: () => {
3
+ selectedNodes: import("vue").Reactive<Set<string>>;
4
+ selectedNodeObjects: import("vue").Reactive<TreeNode<Record<string, unknown>>[]>;
5
+ expandedNodes: import("vue").Reactive<Set<string>>;
6
+ clearSelection: () => void;
7
+ clearExpanded: () => void;
8
+ isSelected: (nodeId: NodeId) => boolean;
9
+ isExpanded: (nodeId: NodeId) => boolean;
10
+ select: (nodeObject: TreeNode) => void;
11
+ selectAllChildren: (node: TreeNode) => void;
12
+ deselect: (nodeId: NodeId) => void;
13
+ deselectAllChildren: (node: TreeNode) => void;
14
+ expand: (nodeId: NodeId) => import("vue").Reactive<Set<string>>;
15
+ collapse: (nodeId: NodeId) => boolean;
16
+ };
17
+ export default useTreeState;
18
+ //# sourceMappingURL=useTreeState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTreeState.d.ts","sourceRoot":"","sources":["../../../src/components/fds-tree-view/useTreeState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAE/C,QAAA,MAAM,YAAY;;;;;;yBAWY,MAAM;yBACN,MAAM;yBAEN,QAAQ;8BAKH,QAAQ;uBAaf,MAAM;gCAQG,QAAQ;qBAUnB,MAAM;uBACJ,MAAM;CAiBjC,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ const vue = require("vue");
4
+ const _hoisted_1 = { class: "bg-white-solid p-2 rounded-md" };
5
+ const _hoisted_2 = { class: "flex" };
6
+ const _hoisted_3 = ["name"];
7
+ const _hoisted_4 = { class: "pl-0 flex-1 flex items-center" };
8
+ const _hoisted_5 = ["id", "checked", "indeterminate"];
9
+ const _hoisted_6 = ["for"];
10
+ const _hoisted_7 = {
11
+ key: 0,
12
+ type: "default"
13
+ };
14
+ const _hoisted_8 = { key: 1 };
15
+ const _hoisted_9 = {
16
+ key: 0,
17
+ type: "meta",
18
+ class: "flex-1"
19
+ };
20
+ const _hoisted_10 = { key: 0 };
21
+ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
22
+ __name: "FdsTreeView",
23
+ props: {
24
+ nodes: { default: () => [] },
25
+ depth: { default: 0 },
26
+ nodeExpandIcon: {},
27
+ nodeCollapseIcon: {},
28
+ indentation: {},
29
+ nodeId: {},
30
+ data: {},
31
+ title: {},
32
+ showNodeDescription: { type: Boolean, default: false },
33
+ showChildrenCount: { type: Boolean, default: false },
34
+ expandChildrenOnSelect: { type: Boolean, default: false },
35
+ showIndeterminate: { type: Boolean }
36
+ },
37
+ setup(__props) {
38
+ const props = __props;
39
+ const treeState = vue.inject("treeState", null);
40
+ const selectedNodes = treeState?.selectedNodes ?? vue.reactive(/* @__PURE__ */ new Set());
41
+ const expandedNodes = treeState?.expandedNodes ?? vue.reactive(/* @__PURE__ */ new Set());
42
+ const indentValue = props.depth * props.indentation;
43
+ const indent = vue.computed(() => ({
44
+ display: "flex",
45
+ flexDirection: "row",
46
+ alignItems: "center",
47
+ transform: `translate(${indentValue}px)`
48
+ }));
49
+ const hasChildrenNodes = vue.computed(() => props.nodes.length > 0);
50
+ const isIndeterminate = vue.computed(() => {
51
+ if (!hasChildrenNodes.value) return false;
52
+ let selectedCount = 0;
53
+ const totalCount = props.nodes.length;
54
+ props.nodes.forEach((node) => {
55
+ if (selectedNodes.has(node.nodeId)) {
56
+ selectedCount++;
57
+ }
58
+ });
59
+ return selectedCount > 0 && selectedCount < totalCount;
60
+ });
61
+ const selectAllChildren = (node) => {
62
+ if (treeState?.selectAllChildren) {
63
+ treeState.selectAllChildren(node);
64
+ } else {
65
+ selectedNodes.add(node.nodeId);
66
+ if (node.children && node.children.length > 0) {
67
+ node.children.forEach(selectAllChildren);
68
+ }
69
+ }
70
+ expandAll(node);
71
+ };
72
+ const deselectAllChildren = (node) => {
73
+ if (treeState?.deselectAllChildren) {
74
+ treeState.deselectAllChildren(node);
75
+ } else {
76
+ selectedNodes.delete(node.nodeId);
77
+ if (node.children && node.children.length > 0) {
78
+ node.children.forEach(deselectAllChildren);
79
+ }
80
+ }
81
+ };
82
+ const expandAll = (node) => {
83
+ treeState?.expand(node.nodeId);
84
+ if (node.children && node.children.length > 0) {
85
+ node.children.forEach(expandAll);
86
+ }
87
+ };
88
+ const handleSelectNode = () => {
89
+ let node = findNodeById(props.nodes, props.nodeId);
90
+ if (!node && props.nodeId) {
91
+ node = {
92
+ nodeId: props.nodeId,
93
+ title: props.title,
94
+ children: props.nodes || [],
95
+ data: props.data
96
+ };
97
+ }
98
+ if (!node) return;
99
+ if (selectedNodes.has(props.nodeId)) {
100
+ deselectAllChildren(node);
101
+ } else {
102
+ selectAllChildren(node);
103
+ if (selectedNodes.has(props.nodeId) && !expandedNodes.has(props.nodeId)) {
104
+ handleExpandNode(props.nodeId);
105
+ }
106
+ }
107
+ };
108
+ const handleExpandNode = (nodeId) => {
109
+ if (treeState) {
110
+ if (treeState.isExpanded(nodeId)) {
111
+ treeState.collapse(nodeId);
112
+ } else {
113
+ if (!hasChildrenNodes.value) return;
114
+ treeState.expand(nodeId);
115
+ }
116
+ return;
117
+ }
118
+ if (expandedNodes.has(nodeId)) {
119
+ expandedNodes.delete(nodeId);
120
+ } else {
121
+ if (!hasChildrenNodes.value) return;
122
+ expandedNodes.add(nodeId);
123
+ }
124
+ };
125
+ const findNodeById = (nodes, nodeId) => {
126
+ for (const node of nodes) {
127
+ if (node.nodeId === nodeId) {
128
+ return node;
129
+ }
130
+ if (node.children) {
131
+ const found = findNodeById(node.children, nodeId);
132
+ if (found) return found;
133
+ }
134
+ }
135
+ return null;
136
+ };
137
+ const getNodeIcon = () => treeState?.isExpanded(props.nodeId) && hasChildrenNodes.value ? props.nodeCollapseIcon : props.nodeExpandIcon;
138
+ return (_ctx, _cache) => {
139
+ const _component_FdsTreeView = vue.resolveComponent("FdsTreeView", true);
140
+ return vue.openBlock(), vue.createElementBlock("div", null, [
141
+ vue.createElementVNode("div", _hoisted_1, [
142
+ vue.createElementVNode("div", {
143
+ style: vue.normalizeStyle(indent.value)
144
+ }, [
145
+ vue.createElementVNode("div", _hoisted_2, [
146
+ hasChildrenNodes.value ? (vue.openBlock(), vue.createElementBlock("fds-icon", {
147
+ key: 0,
148
+ onClick: _cache[0] || (_cache[0] = ($event) => handleExpandNode(props.nodeId)),
149
+ name: getNodeIcon(),
150
+ size: "24px",
151
+ class: "text-blue-500 mr-3",
152
+ style: { "margin-top": "3px" }
153
+ }, null, 8, _hoisted_3)) : vue.createCommentVNode("", true),
154
+ !hasChildrenNodes.value ? (vue.openBlock(), vue.createElementBlock("div", {
155
+ key: 1,
156
+ style: vue.normalizeStyle({ width: `${_ctx.indentation}px` })
157
+ }, null, 4)) : vue.createCommentVNode("", true),
158
+ vue.createElementVNode("fds-checkbox", _hoisted_4, [
159
+ vue.createElementVNode("input", {
160
+ id: `checkbox-${props.nodeId}`,
161
+ style: { "margin": "0px", "margin-top": "3px" },
162
+ type: "checkbox",
163
+ checked: vue.unref(treeState)?.isSelected(props.nodeId),
164
+ indeterminate: _ctx.showIndeterminate && isIndeterminate.value,
165
+ onChange: handleSelectNode
166
+ }, null, 40, _hoisted_5),
167
+ vue.createElementVNode("label", {
168
+ for: `checkbox-${props.nodeId}`,
169
+ class: "flex flex-col pl-0"
170
+ }, [
171
+ vue.createElementVNode("div", null, [
172
+ _ctx.title ? (vue.openBlock(), vue.createElementBlock("fds-text", _hoisted_7, vue.toDisplayString(_ctx.title), 1)) : vue.createCommentVNode("", true),
173
+ _ctx.showChildrenCount && hasChildrenNodes.value ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_8, " (+" + vue.toDisplayString(props.nodes.length) + ") ", 1)) : vue.createCommentVNode("", true)
174
+ ]),
175
+ _ctx.showNodeDescription ? (vue.openBlock(), vue.createElementBlock("fds-text", _hoisted_9, vue.toDisplayString(props.nodeId), 1)) : vue.createCommentVNode("", true)
176
+ ], 8, _hoisted_6)
177
+ ])
178
+ ])
179
+ ], 4)
180
+ ]),
181
+ vue.unref(expandedNodes).has(props.nodeId) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_10, [
182
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(props.nodes, (child) => {
183
+ return vue.openBlock(), vue.createBlock(_component_FdsTreeView, {
184
+ key: child.nodeId,
185
+ nodes: child.children || [],
186
+ title: child.title,
187
+ nodeId: child.nodeId,
188
+ data: child.data,
189
+ depth: props.depth + 1,
190
+ indentation: props.indentation,
191
+ nodeExpandIcon: props.nodeExpandIcon,
192
+ nodeCollapseIcon: props.nodeCollapseIcon,
193
+ showNodeDescription: _ctx.showNodeDescription,
194
+ showChildrenCount: _ctx.showChildrenCount,
195
+ expandChildrenOnSelect: _ctx.expandChildrenOnSelect,
196
+ showIndeterminate: _ctx.showIndeterminate
197
+ }, null, 8, ["nodes", "title", "nodeId", "data", "depth", "indentation", "nodeExpandIcon", "nodeCollapseIcon", "showNodeDescription", "showChildrenCount", "expandChildrenOnSelect", "showIndeterminate"]);
198
+ }), 128))
199
+ ])) : vue.createCommentVNode("", true)
200
+ ]);
201
+ };
202
+ }
203
+ });
204
+ const index = {
205
+ install(app) {
206
+ app.component("FdsTreeView", _sfc_main);
207
+ }
208
+ };
209
+ exports.FdsTreeView = _sfc_main;
210
+ exports.default = index;
211
+ //# sourceMappingURL=fds-vue-core.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fds-vue-core.cjs.js","sources":["../src/components/fds-tree-view/FdsTreeView.vue","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, inject, reactive } from 'vue'\nimport useTreeState from './useTreeState'\nimport type { TreeNode, TreeNodeArray, TreeNodeItem, TreeViewProps } from './types'\n\ntype Props<T = Record<string, unknown>> = TreeViewProps<T>\n\nconst props = withDefaults(defineProps<Props>(), {\n nodes: () => [],\n depth: 0,\n showNodeDescription: false,\n showChildrenCount: false,\n expandChildrenOnSelect: false,\n})\n\nconst treeState = inject<ReturnType<typeof useTreeState> | null>('treeState', null)\nconst selectedNodes = treeState?.selectedNodes ?? reactive(new Set())\nconst expandedNodes = treeState?.expandedNodes ?? reactive(new Set())\n\nconst indentValue = props.depth * props.indentation\n\nconst indent = computed(() => ({\n display: 'flex',\n flexDirection: 'row' as const,\n alignItems: 'center' as const,\n transform: `translate(${indentValue}px)`,\n}))\n\nconst hasChildrenNodes = computed(() => props.nodes.length > 0)\n\nconst isIndeterminate = computed(() => {\n if (!hasChildrenNodes.value) return false\n\n let selectedCount = 0\n const totalCount = props.nodes.length\n\n props.nodes.forEach((node) => {\n if (selectedNodes.has(node.nodeId)) {\n selectedCount++\n }\n })\n\n return selectedCount > 0 && selectedCount < totalCount\n})\n\nconst selectAllChildren = (node: TreeNodeItem) => {\n if (treeState?.selectAllChildren) {\n treeState.selectAllChildren(node)\n } else {\n selectedNodes.add(node.nodeId)\n if (node.children && node.children.length > 0) {\n node.children.forEach(selectAllChildren)\n }\n }\n expandAll(node)\n}\n\nconst deselectAllChildren = (node: TreeNodeItem) => {\n if (treeState?.deselectAllChildren) {\n treeState.deselectAllChildren(node)\n } else {\n selectedNodes.delete(node.nodeId)\n if (node.children && node.children.length > 0) {\n node.children.forEach(deselectAllChildren)\n }\n }\n}\n\nconst expandAll = (node: TreeNodeItem) => {\n treeState?.expand(node.nodeId)\n if (node.children && node.children.length > 0) {\n node.children.forEach(expandAll)\n }\n}\n\nconst handleSelectNode = () => {\n let node = findNodeById(props.nodes, props.nodeId)\n\n if (!node && props.nodeId) {\n node = {\n nodeId: props.nodeId,\n title: props.title,\n children: props.nodes || [],\n data: props.data,\n }\n }\n\n if (!node) return\n\n if (selectedNodes.has(props.nodeId)) {\n deselectAllChildren(node)\n } else {\n selectAllChildren(node)\n\n if (selectedNodes.has(props.nodeId) && !expandedNodes.has(props.nodeId)) {\n handleExpandNode(props.nodeId)\n }\n }\n}\n\nconst handleExpandNode = (nodeId: TreeNode['nodeId']) => {\n if (treeState) {\n if (treeState.isExpanded(nodeId)) {\n treeState.collapse(nodeId)\n } else {\n if (!hasChildrenNodes.value) return\n treeState.expand(nodeId)\n }\n return\n }\n\n if (expandedNodes.has(nodeId)) {\n expandedNodes.delete(nodeId)\n } else {\n if (!hasChildrenNodes.value) return\n expandedNodes.add(nodeId)\n }\n}\n\nconst findNodeById = (nodes: TreeNodeArray, nodeId: string): TreeNodeItem | null => {\n for (const node of nodes) {\n if (node.nodeId === nodeId) {\n return node\n }\n if (node.children) {\n const found = findNodeById(node.children, nodeId)\n if (found) return found\n }\n }\n return null\n}\n\nconst getNodeIcon = () =>\n treeState?.isExpanded(props.nodeId) && hasChildrenNodes.value\n ? props.nodeCollapseIcon\n : props.nodeExpandIcon\n</script>\n\n<template>\n <div>\n <div class=\"bg-white-solid p-2 rounded-md\">\n <div :style=\"indent\">\n <div class=\"flex\">\n <fds-icon\n v-if=\"hasChildrenNodes\"\n @click=\"handleExpandNode(props.nodeId)\"\n :name=\"getNodeIcon()\"\n size=\"24px\"\n class=\"text-blue-500 mr-3\"\n style=\"margin-top: 3px\"\n />\n <div v-if=\"!hasChildrenNodes\" :style=\"{ width: `${indentation}px` }\" />\n <fds-checkbox class=\"pl-0 flex-1 flex items-center\">\n <input\n :id=\"`checkbox-${props.nodeId}`\"\n style=\"margin: 0px; margin-top: 3px\"\n type=\"checkbox\"\n :checked=\"treeState?.isSelected(props.nodeId)\"\n :indeterminate=\"showIndeterminate && isIndeterminate\"\n @change=\"handleSelectNode\"\n />\n <label :for=\"`checkbox-${props.nodeId}`\" class=\"flex flex-col pl-0\">\n <div>\n <fds-text v-if=\"title\" type=\"default\">{{ title }}</fds-text>\n <span v-if=\"showChildrenCount && hasChildrenNodes\">\n (+{{ props.nodes.length }})\n </span>\n </div>\n <fds-text v-if=\"showNodeDescription\" type=\"meta\" class=\"flex-1\">\n {{ props.nodeId }}\n </fds-text>\n </label>\n </fds-checkbox>\n </div>\n </div>\n </div>\n\n <div v-if=\"expandedNodes.has(props.nodeId)\">\n <FdsTreeView\n v-for=\"child in props.nodes\"\n :key=\"child.nodeId\"\n :nodes=\"child.children || []\"\n :title=\"child.title\"\n :nodeId=\"child.nodeId\"\n :data=\"child.data\"\n :depth=\"props.depth + 1\"\n :indentation=\"props.indentation\"\n :nodeExpandIcon=\"props.nodeExpandIcon\"\n :nodeCollapseIcon=\"props.nodeCollapseIcon\"\n :showNodeDescription=\"showNodeDescription\"\n :showChildrenCount=\"showChildrenCount\"\n :expandChildrenOnSelect=\"expandChildrenOnSelect\"\n :showIndeterminate=\"showIndeterminate\"\n />\n </div>\n </div>\n</template>\n","import type { App } from 'vue'\n\n// Import all components\nimport FdsTreeView from './components/fds-tree-view/FdsTreeView.vue'\n\n// Export individual components\nexport { FdsTreeView }\n\n// Export component library plugin\nexport default {\n install(app: App) {\n // Register all components globally\n app.component('FdsTreeView', FdsTreeView)\n\n // You can add global properties here if needed\n // app.config.globalProperties.$fds = { ... }\n },\n}\n\n// Export all types for consumers\nexport * from './types'\n\n// Re-export component types for convenience\nexport type {\n TreeNode,\n TreeNodeArray,\n TreeNodeItem,\n TreeViewProps,\n NodeId,\n} from './components/fds-tree-view/types'\n"],"names":["inject","reactive","computed","_createElementBlock","_createElementVNode","indentation","_unref","showIndeterminate","title","_toDisplayString","showChildrenCount","showNodeDescription","_openBlock","_Fragment","_renderList","_createBlock","expandChildrenOnSelect","FdsTreeView"],"mappings":"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"}
@@ -0,0 +1,211 @@
1
+ import { defineComponent, inject, reactive, computed, resolveComponent, createElementBlock, openBlock, createElementVNode, createCommentVNode, normalizeStyle, unref, toDisplayString, Fragment, renderList, createBlock } from "vue";
2
+ const _hoisted_1 = { class: "bg-white-solid p-2 rounded-md" };
3
+ const _hoisted_2 = { class: "flex" };
4
+ const _hoisted_3 = ["name"];
5
+ const _hoisted_4 = { class: "pl-0 flex-1 flex items-center" };
6
+ const _hoisted_5 = ["id", "checked", "indeterminate"];
7
+ const _hoisted_6 = ["for"];
8
+ const _hoisted_7 = {
9
+ key: 0,
10
+ type: "default"
11
+ };
12
+ const _hoisted_8 = { key: 1 };
13
+ const _hoisted_9 = {
14
+ key: 0,
15
+ type: "meta",
16
+ class: "flex-1"
17
+ };
18
+ const _hoisted_10 = { key: 0 };
19
+ const _sfc_main = /* @__PURE__ */ defineComponent({
20
+ __name: "FdsTreeView",
21
+ props: {
22
+ nodes: { default: () => [] },
23
+ depth: { default: 0 },
24
+ nodeExpandIcon: {},
25
+ nodeCollapseIcon: {},
26
+ indentation: {},
27
+ nodeId: {},
28
+ data: {},
29
+ title: {},
30
+ showNodeDescription: { type: Boolean, default: false },
31
+ showChildrenCount: { type: Boolean, default: false },
32
+ expandChildrenOnSelect: { type: Boolean, default: false },
33
+ showIndeterminate: { type: Boolean }
34
+ },
35
+ setup(__props) {
36
+ const props = __props;
37
+ const treeState = inject("treeState", null);
38
+ const selectedNodes = treeState?.selectedNodes ?? reactive(/* @__PURE__ */ new Set());
39
+ const expandedNodes = treeState?.expandedNodes ?? reactive(/* @__PURE__ */ new Set());
40
+ const indentValue = props.depth * props.indentation;
41
+ const indent = computed(() => ({
42
+ display: "flex",
43
+ flexDirection: "row",
44
+ alignItems: "center",
45
+ transform: `translate(${indentValue}px)`
46
+ }));
47
+ const hasChildrenNodes = computed(() => props.nodes.length > 0);
48
+ const isIndeterminate = computed(() => {
49
+ if (!hasChildrenNodes.value) return false;
50
+ let selectedCount = 0;
51
+ const totalCount = props.nodes.length;
52
+ props.nodes.forEach((node) => {
53
+ if (selectedNodes.has(node.nodeId)) {
54
+ selectedCount++;
55
+ }
56
+ });
57
+ return selectedCount > 0 && selectedCount < totalCount;
58
+ });
59
+ const selectAllChildren = (node) => {
60
+ if (treeState?.selectAllChildren) {
61
+ treeState.selectAllChildren(node);
62
+ } else {
63
+ selectedNodes.add(node.nodeId);
64
+ if (node.children && node.children.length > 0) {
65
+ node.children.forEach(selectAllChildren);
66
+ }
67
+ }
68
+ expandAll(node);
69
+ };
70
+ const deselectAllChildren = (node) => {
71
+ if (treeState?.deselectAllChildren) {
72
+ treeState.deselectAllChildren(node);
73
+ } else {
74
+ selectedNodes.delete(node.nodeId);
75
+ if (node.children && node.children.length > 0) {
76
+ node.children.forEach(deselectAllChildren);
77
+ }
78
+ }
79
+ };
80
+ const expandAll = (node) => {
81
+ treeState?.expand(node.nodeId);
82
+ if (node.children && node.children.length > 0) {
83
+ node.children.forEach(expandAll);
84
+ }
85
+ };
86
+ const handleSelectNode = () => {
87
+ let node = findNodeById(props.nodes, props.nodeId);
88
+ if (!node && props.nodeId) {
89
+ node = {
90
+ nodeId: props.nodeId,
91
+ title: props.title,
92
+ children: props.nodes || [],
93
+ data: props.data
94
+ };
95
+ }
96
+ if (!node) return;
97
+ if (selectedNodes.has(props.nodeId)) {
98
+ deselectAllChildren(node);
99
+ } else {
100
+ selectAllChildren(node);
101
+ if (selectedNodes.has(props.nodeId) && !expandedNodes.has(props.nodeId)) {
102
+ handleExpandNode(props.nodeId);
103
+ }
104
+ }
105
+ };
106
+ const handleExpandNode = (nodeId) => {
107
+ if (treeState) {
108
+ if (treeState.isExpanded(nodeId)) {
109
+ treeState.collapse(nodeId);
110
+ } else {
111
+ if (!hasChildrenNodes.value) return;
112
+ treeState.expand(nodeId);
113
+ }
114
+ return;
115
+ }
116
+ if (expandedNodes.has(nodeId)) {
117
+ expandedNodes.delete(nodeId);
118
+ } else {
119
+ if (!hasChildrenNodes.value) return;
120
+ expandedNodes.add(nodeId);
121
+ }
122
+ };
123
+ const findNodeById = (nodes, nodeId) => {
124
+ for (const node of nodes) {
125
+ if (node.nodeId === nodeId) {
126
+ return node;
127
+ }
128
+ if (node.children) {
129
+ const found = findNodeById(node.children, nodeId);
130
+ if (found) return found;
131
+ }
132
+ }
133
+ return null;
134
+ };
135
+ const getNodeIcon = () => treeState?.isExpanded(props.nodeId) && hasChildrenNodes.value ? props.nodeCollapseIcon : props.nodeExpandIcon;
136
+ return (_ctx, _cache) => {
137
+ const _component_FdsTreeView = resolveComponent("FdsTreeView", true);
138
+ return openBlock(), createElementBlock("div", null, [
139
+ createElementVNode("div", _hoisted_1, [
140
+ createElementVNode("div", {
141
+ style: normalizeStyle(indent.value)
142
+ }, [
143
+ createElementVNode("div", _hoisted_2, [
144
+ hasChildrenNodes.value ? (openBlock(), createElementBlock("fds-icon", {
145
+ key: 0,
146
+ onClick: _cache[0] || (_cache[0] = ($event) => handleExpandNode(props.nodeId)),
147
+ name: getNodeIcon(),
148
+ size: "24px",
149
+ class: "text-blue-500 mr-3",
150
+ style: { "margin-top": "3px" }
151
+ }, null, 8, _hoisted_3)) : createCommentVNode("", true),
152
+ !hasChildrenNodes.value ? (openBlock(), createElementBlock("div", {
153
+ key: 1,
154
+ style: normalizeStyle({ width: `${_ctx.indentation}px` })
155
+ }, null, 4)) : createCommentVNode("", true),
156
+ createElementVNode("fds-checkbox", _hoisted_4, [
157
+ createElementVNode("input", {
158
+ id: `checkbox-${props.nodeId}`,
159
+ style: { "margin": "0px", "margin-top": "3px" },
160
+ type: "checkbox",
161
+ checked: unref(treeState)?.isSelected(props.nodeId),
162
+ indeterminate: _ctx.showIndeterminate && isIndeterminate.value,
163
+ onChange: handleSelectNode
164
+ }, null, 40, _hoisted_5),
165
+ createElementVNode("label", {
166
+ for: `checkbox-${props.nodeId}`,
167
+ class: "flex flex-col pl-0"
168
+ }, [
169
+ createElementVNode("div", null, [
170
+ _ctx.title ? (openBlock(), createElementBlock("fds-text", _hoisted_7, toDisplayString(_ctx.title), 1)) : createCommentVNode("", true),
171
+ _ctx.showChildrenCount && hasChildrenNodes.value ? (openBlock(), createElementBlock("span", _hoisted_8, " (+" + toDisplayString(props.nodes.length) + ") ", 1)) : createCommentVNode("", true)
172
+ ]),
173
+ _ctx.showNodeDescription ? (openBlock(), createElementBlock("fds-text", _hoisted_9, toDisplayString(props.nodeId), 1)) : createCommentVNode("", true)
174
+ ], 8, _hoisted_6)
175
+ ])
176
+ ])
177
+ ], 4)
178
+ ]),
179
+ unref(expandedNodes).has(props.nodeId) ? (openBlock(), createElementBlock("div", _hoisted_10, [
180
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.nodes, (child) => {
181
+ return openBlock(), createBlock(_component_FdsTreeView, {
182
+ key: child.nodeId,
183
+ nodes: child.children || [],
184
+ title: child.title,
185
+ nodeId: child.nodeId,
186
+ data: child.data,
187
+ depth: props.depth + 1,
188
+ indentation: props.indentation,
189
+ nodeExpandIcon: props.nodeExpandIcon,
190
+ nodeCollapseIcon: props.nodeCollapseIcon,
191
+ showNodeDescription: _ctx.showNodeDescription,
192
+ showChildrenCount: _ctx.showChildrenCount,
193
+ expandChildrenOnSelect: _ctx.expandChildrenOnSelect,
194
+ showIndeterminate: _ctx.showIndeterminate
195
+ }, null, 8, ["nodes", "title", "nodeId", "data", "depth", "indentation", "nodeExpandIcon", "nodeCollapseIcon", "showNodeDescription", "showChildrenCount", "expandChildrenOnSelect", "showIndeterminate"]);
196
+ }), 128))
197
+ ])) : createCommentVNode("", true)
198
+ ]);
199
+ };
200
+ }
201
+ });
202
+ const index = {
203
+ install(app) {
204
+ app.component("FdsTreeView", _sfc_main);
205
+ }
206
+ };
207
+ export {
208
+ _sfc_main as FdsTreeView,
209
+ index as default
210
+ };
211
+ //# sourceMappingURL=fds-vue-core.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fds-vue-core.es.js","sources":["../src/components/fds-tree-view/FdsTreeView.vue","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, inject, reactive } from 'vue'\nimport useTreeState from './useTreeState'\nimport type { TreeNode, TreeNodeArray, TreeNodeItem, TreeViewProps } from './types'\n\ntype Props<T = Record<string, unknown>> = TreeViewProps<T>\n\nconst props = withDefaults(defineProps<Props>(), {\n nodes: () => [],\n depth: 0,\n showNodeDescription: false,\n showChildrenCount: false,\n expandChildrenOnSelect: false,\n})\n\nconst treeState = inject<ReturnType<typeof useTreeState> | null>('treeState', null)\nconst selectedNodes = treeState?.selectedNodes ?? reactive(new Set())\nconst expandedNodes = treeState?.expandedNodes ?? reactive(new Set())\n\nconst indentValue = props.depth * props.indentation\n\nconst indent = computed(() => ({\n display: 'flex',\n flexDirection: 'row' as const,\n alignItems: 'center' as const,\n transform: `translate(${indentValue}px)`,\n}))\n\nconst hasChildrenNodes = computed(() => props.nodes.length > 0)\n\nconst isIndeterminate = computed(() => {\n if (!hasChildrenNodes.value) return false\n\n let selectedCount = 0\n const totalCount = props.nodes.length\n\n props.nodes.forEach((node) => {\n if (selectedNodes.has(node.nodeId)) {\n selectedCount++\n }\n })\n\n return selectedCount > 0 && selectedCount < totalCount\n})\n\nconst selectAllChildren = (node: TreeNodeItem) => {\n if (treeState?.selectAllChildren) {\n treeState.selectAllChildren(node)\n } else {\n selectedNodes.add(node.nodeId)\n if (node.children && node.children.length > 0) {\n node.children.forEach(selectAllChildren)\n }\n }\n expandAll(node)\n}\n\nconst deselectAllChildren = (node: TreeNodeItem) => {\n if (treeState?.deselectAllChildren) {\n treeState.deselectAllChildren(node)\n } else {\n selectedNodes.delete(node.nodeId)\n if (node.children && node.children.length > 0) {\n node.children.forEach(deselectAllChildren)\n }\n }\n}\n\nconst expandAll = (node: TreeNodeItem) => {\n treeState?.expand(node.nodeId)\n if (node.children && node.children.length > 0) {\n node.children.forEach(expandAll)\n }\n}\n\nconst handleSelectNode = () => {\n let node = findNodeById(props.nodes, props.nodeId)\n\n if (!node && props.nodeId) {\n node = {\n nodeId: props.nodeId,\n title: props.title,\n children: props.nodes || [],\n data: props.data,\n }\n }\n\n if (!node) return\n\n if (selectedNodes.has(props.nodeId)) {\n deselectAllChildren(node)\n } else {\n selectAllChildren(node)\n\n if (selectedNodes.has(props.nodeId) && !expandedNodes.has(props.nodeId)) {\n handleExpandNode(props.nodeId)\n }\n }\n}\n\nconst handleExpandNode = (nodeId: TreeNode['nodeId']) => {\n if (treeState) {\n if (treeState.isExpanded(nodeId)) {\n treeState.collapse(nodeId)\n } else {\n if (!hasChildrenNodes.value) return\n treeState.expand(nodeId)\n }\n return\n }\n\n if (expandedNodes.has(nodeId)) {\n expandedNodes.delete(nodeId)\n } else {\n if (!hasChildrenNodes.value) return\n expandedNodes.add(nodeId)\n }\n}\n\nconst findNodeById = (nodes: TreeNodeArray, nodeId: string): TreeNodeItem | null => {\n for (const node of nodes) {\n if (node.nodeId === nodeId) {\n return node\n }\n if (node.children) {\n const found = findNodeById(node.children, nodeId)\n if (found) return found\n }\n }\n return null\n}\n\nconst getNodeIcon = () =>\n treeState?.isExpanded(props.nodeId) && hasChildrenNodes.value\n ? props.nodeCollapseIcon\n : props.nodeExpandIcon\n</script>\n\n<template>\n <div>\n <div class=\"bg-white-solid p-2 rounded-md\">\n <div :style=\"indent\">\n <div class=\"flex\">\n <fds-icon\n v-if=\"hasChildrenNodes\"\n @click=\"handleExpandNode(props.nodeId)\"\n :name=\"getNodeIcon()\"\n size=\"24px\"\n class=\"text-blue-500 mr-3\"\n style=\"margin-top: 3px\"\n />\n <div v-if=\"!hasChildrenNodes\" :style=\"{ width: `${indentation}px` }\" />\n <fds-checkbox class=\"pl-0 flex-1 flex items-center\">\n <input\n :id=\"`checkbox-${props.nodeId}`\"\n style=\"margin: 0px; margin-top: 3px\"\n type=\"checkbox\"\n :checked=\"treeState?.isSelected(props.nodeId)\"\n :indeterminate=\"showIndeterminate && isIndeterminate\"\n @change=\"handleSelectNode\"\n />\n <label :for=\"`checkbox-${props.nodeId}`\" class=\"flex flex-col pl-0\">\n <div>\n <fds-text v-if=\"title\" type=\"default\">{{ title }}</fds-text>\n <span v-if=\"showChildrenCount && hasChildrenNodes\">\n (+{{ props.nodes.length }})\n </span>\n </div>\n <fds-text v-if=\"showNodeDescription\" type=\"meta\" class=\"flex-1\">\n {{ props.nodeId }}\n </fds-text>\n </label>\n </fds-checkbox>\n </div>\n </div>\n </div>\n\n <div v-if=\"expandedNodes.has(props.nodeId)\">\n <FdsTreeView\n v-for=\"child in props.nodes\"\n :key=\"child.nodeId\"\n :nodes=\"child.children || []\"\n :title=\"child.title\"\n :nodeId=\"child.nodeId\"\n :data=\"child.data\"\n :depth=\"props.depth + 1\"\n :indentation=\"props.indentation\"\n :nodeExpandIcon=\"props.nodeExpandIcon\"\n :nodeCollapseIcon=\"props.nodeCollapseIcon\"\n :showNodeDescription=\"showNodeDescription\"\n :showChildrenCount=\"showChildrenCount\"\n :expandChildrenOnSelect=\"expandChildrenOnSelect\"\n :showIndeterminate=\"showIndeterminate\"\n />\n </div>\n </div>\n</template>\n","import type { App } from 'vue'\n\n// Import all components\nimport FdsTreeView from './components/fds-tree-view/FdsTreeView.vue'\n\n// Export individual components\nexport { FdsTreeView }\n\n// Export component library plugin\nexport default {\n install(app: App) {\n // Register all components globally\n app.component('FdsTreeView', FdsTreeView)\n\n // You can add global properties here if needed\n // app.config.globalProperties.$fds = { ... }\n },\n}\n\n// Export all types for consumers\nexport * from './types'\n\n// Re-export component types for convenience\nexport type {\n TreeNode,\n TreeNodeArray,\n TreeNodeItem,\n TreeViewProps,\n NodeId,\n} from './components/fds-tree-view/types'\n"],"names":["_createElementBlock","_createElementVNode","indentation","_unref","showIndeterminate","title","_toDisplayString","showChildrenCount","showNodeDescription","_openBlock","_Fragment","_renderList","_createBlock","expandChildrenOnSelect","FdsTreeView"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,UAAM,QAAQ;AAQd,UAAM,YAAY,OAA+C,aAAa,IAAI;AAClF,UAAM,gBAAgB,WAAW,iBAAiB,SAAS,oBAAI,KAAK;AACpE,UAAM,gBAAgB,WAAW,iBAAiB,SAAS,oBAAI,KAAK;AAEpE,UAAM,cAAc,MAAM,QAAQ,MAAM;AAExC,UAAM,SAAS,SAAS,OAAO;AAAA,MAC7B,SAAS;AAAA,MACT,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,WAAW,aAAa,WAAW;AAAA,IAAA,EACnC;AAEF,UAAM,mBAAmB,SAAS,MAAM,MAAM,MAAM,SAAS,CAAC;AAE9D,UAAM,kBAAkB,SAAS,MAAM;AACrC,UAAI,CAAC,iBAAiB,MAAO,QAAO;AAEpC,UAAI,gBAAgB;AACpB,YAAM,aAAa,MAAM,MAAM;AAE/B,YAAM,MAAM,QAAQ,CAAC,SAAS;AAC5B,YAAI,cAAc,IAAI,KAAK,MAAM,GAAG;AAClC;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO,gBAAgB,KAAK,gBAAgB;AAAA,IAC9C,CAAC;AAED,UAAM,oBAAoB,CAAC,SAAuB;AAChD,UAAI,WAAW,mBAAmB;AAChC,kBAAU,kBAAkB,IAAI;AAAA,MAClC,OAAO;AACL,sBAAc,IAAI,KAAK,MAAM;AAC7B,YAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,eAAK,SAAS,QAAQ,iBAAiB;AAAA,QACzC;AAAA,MACF;AACA,gBAAU,IAAI;AAAA,IAChB;AAEA,UAAM,sBAAsB,CAAC,SAAuB;AAClD,UAAI,WAAW,qBAAqB;AAClC,kBAAU,oBAAoB,IAAI;AAAA,MACpC,OAAO;AACL,sBAAc,OAAO,KAAK,MAAM;AAChC,YAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,eAAK,SAAS,QAAQ,mBAAmB;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,CAAC,SAAuB;AACxC,iBAAW,OAAO,KAAK,MAAM;AAC7B,UAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,aAAK,SAAS,QAAQ,SAAS;AAAA,MACjC;AAAA,IACF;AAEA,UAAM,mBAAmB,MAAM;AAC7B,UAAI,OAAO,aAAa,MAAM,OAAO,MAAM,MAAM;AAEjD,UAAI,CAAC,QAAQ,MAAM,QAAQ;AACzB,eAAO;AAAA,UACL,QAAQ,MAAM;AAAA,UACd,OAAO,MAAM;AAAA,UACb,UAAU,MAAM,SAAS,CAAA;AAAA,UACzB,MAAM,MAAM;AAAA,QAAA;AAAA,MAEhB;AAEA,UAAI,CAAC,KAAM;AAEX,UAAI,cAAc,IAAI,MAAM,MAAM,GAAG;AACnC,4BAAoB,IAAI;AAAA,MAC1B,OAAO;AACL,0BAAkB,IAAI;AAEtB,YAAI,cAAc,IAAI,MAAM,MAAM,KAAK,CAAC,cAAc,IAAI,MAAM,MAAM,GAAG;AACvE,2BAAiB,MAAM,MAAM;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,mBAAmB,CAAC,WAA+B;AACvD,UAAI,WAAW;AACb,YAAI,UAAU,WAAW,MAAM,GAAG;AAChC,oBAAU,SAAS,MAAM;AAAA,QAC3B,OAAO;AACL,cAAI,CAAC,iBAAiB,MAAO;AAC7B,oBAAU,OAAO,MAAM;AAAA,QACzB;AACA;AAAA,MACF;AAEA,UAAI,cAAc,IAAI,MAAM,GAAG;AAC7B,sBAAc,OAAO,MAAM;AAAA,MAC7B,OAAO;AACL,YAAI,CAAC,iBAAiB,MAAO;AAC7B,sBAAc,IAAI,MAAM;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,eAAe,CAAC,OAAsB,WAAwC;AAClF,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,WAAW,QAAQ;AAC1B,iBAAO;AAAA,QACT;AACA,YAAI,KAAK,UAAU;AACjB,gBAAM,QAAQ,aAAa,KAAK,UAAU,MAAM;AAChD,cAAI,MAAO,QAAO;AAAA,QACpB;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,MAClB,WAAW,WAAW,MAAM,MAAM,KAAK,iBAAiB,QACpD,MAAM,mBACN,MAAM;;;0BAIVA,mBAwDM,OAAA,MAAA;AAAA,QAvDJC,mBAmCM,OAnCN,YAmCM;AAAA,UAlCJA,mBAiCM,OAAA;AAAA,YAjCA,sBAAO,OAAA,KAAM;AAAA,UAAA;YACjBA,mBA+BM,OA/BN,YA+BM;AAAA,cA7BI,iBAAA,sBADRD,mBAOE,YAAA;AAAA;gBALC,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAE,iBAAiB,MAAM,MAAM;AAAA,gBACpC,MAAM,YAAA;AAAA,gBACP,MAAK;AAAA,gBACL,OAAM;AAAA,gBACN,OAAA,EAAA,cAAA,MAAA;AAAA,cAAA;eAEU,iBAAA,sBAAZA,mBAAuE,OAAA;AAAA;gBAAxC,kCAAmBE,KAAAA,WAAW,MAAA;AAAA,cAAA;cAC7DD,mBAoBe,gBApBf,YAoBe;AAAA,gBAnBbA,mBAOE,SAAA;AAAA,kBANC,IAAE,YAAc,MAAM,MAAM;AAAA,kBAC7B,OAAA,EAAA,UAAA,OAAA,cAAA,MAAA;AAAA,kBACA,MAAK;AAAA,kBACJ,SAASE,MAAA,SAAA,GAAW,WAAW,MAAM,MAAM;AAAA,kBAC3C,eAAeC,KAAAA,qBAAqB,gBAAA;AAAA,kBACpC,UAAQ;AAAA,gBAAA;gBAEXH,mBAUQ,SAAA;AAAA,kBAVA,KAAG,YAAc,MAAM,MAAM;AAAA,kBAAI,OAAM;AAAA,gBAAA;kBAC7CA,mBAKM,OAAA,MAAA;AAAA,oBAJYI,KAAAA,sBAAhBL,mBAA4D,YAA5D,YAA4DM,gBAAnBD,KAAAA,KAAK,GAAA,CAAA;oBAClCE,KAAAA,qBAAqB,iBAAA,sBAAjCP,mBAEO,QAAA,YAF4C,QAC/CM,gBAAG,MAAM,MAAM,MAAM,IAAG,MAC5B,CAAA;;kBAEcE,KAAAA,uBAAhBC,UAAA,GAAAT,mBAEW,YAFX,YAEWM,gBADN,MAAM,MAAM,GAAA,CAAA;;;;;;QAQhBH,MAAA,aAAA,EAAc,IAAI,MAAM,MAAM,kBAAzCH,mBAiBM,OAAA,aAAA;AAAA,WAhBJS,UAAA,IAAA,GAAAT,mBAeEU,UAAA,MAAAC,WAdgB,MAAM,QAAf,UAAK;gCADdC,YAeE,wBAAA;AAAA,cAbC,KAAK,MAAM;AAAA,cACX,OAAO,MAAM,YAAQ,CAAA;AAAA,cACrB,OAAO,MAAM;AAAA,cACb,QAAQ,MAAM;AAAA,cACd,MAAM,MAAM;AAAA,cACZ,OAAO,MAAM,QAAK;AAAA,cAClB,aAAa,MAAM;AAAA,cACnB,gBAAgB,MAAM;AAAA,cACtB,kBAAkB,MAAM;AAAA,cACxB,qBAAqBJ,KAAAA;AAAAA,cACrB,mBAAmBD,KAAAA;AAAAA,cACnB,wBAAwBM,KAAAA;AAAAA,cACxB,mBAAmBT,KAAAA;AAAAA,YAAAA;;;;;;;ACvL5B,MAAA,QAAe;AAAA,EACb,QAAQ,KAAU;AAEhB,QAAI,UAAU,eAAeU,SAAW;AAAA,EAI1C;AACF;"}
@@ -0,0 +1,10 @@
1
+ import type { App } from 'vue';
2
+ import FdsTreeView from './components/fds-tree-view/FdsTreeView.vue';
3
+ export { FdsTreeView };
4
+ declare const _default: {
5
+ install(app: App): void;
6
+ };
7
+ export default _default;
8
+ export * from './types';
9
+ export type { TreeNode, TreeNodeArray, TreeNodeItem, TreeViewProps, NodeId, } from './components/fds-tree-view/types';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAG9B,OAAO,WAAW,MAAM,4CAA4C,CAAA;AAGpE,OAAO,EAAE,WAAW,EAAE,CAAA;;iBAIP,GAAG;;AADlB,wBAQC;AAGD,cAAc,SAAS,CAAA;AAGvB,YAAY,EACV,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,MAAM,GACP,MAAM,kCAAkC,CAAA"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import './style.css';
2
+ import 'fds-core/dist/fds-core/fds-core.css';
3
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAA;AAIpB,OAAO,qCAAqC,CAAA"}
@@ -0,0 +1,19 @@
1
+ import type { TreeNode, TreeNodeArray, TreeNodeItem, TreeViewProps, NodeId } from '../components/fds-tree-view/types';
2
+ export type { TreeNode, TreeNodeArray, TreeNodeItem, TreeViewProps, NodeId, };
3
+ export interface FdsTreeViewInstance {
4
+ [key: string]: unknown;
5
+ }
6
+ export interface FdsVueCoreConfig {
7
+ theme?: 'light' | 'dark';
8
+ locale?: string;
9
+ }
10
+ export interface TreeViewEvents {
11
+ 'node-select': (node: TreeNode) => void;
12
+ 'node-expand': (node: TreeNode) => void;
13
+ 'node-collapse': (node: TreeNode) => void;
14
+ 'selection-change': (selectedNodes: TreeNode[]) => void;
15
+ }
16
+ export type ComponentSize = 'small' | 'medium' | 'large';
17
+ export type ComponentVariant = 'default' | 'primary' | 'secondary' | 'danger';
18
+ export type { App } from 'vue';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,MAAM,EACP,MAAM,mCAAmC,CAAA;AAE1C,YAAY,EACV,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,MAAM,GACP,CAAA;AAGD,MAAM,WAAW,mBAAmB;IAIlC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;CAEhB;AAGD,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;IACvC,aAAa,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;IACvC,eAAe,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;IACzC,kBAAkB,EAAE,CAAC,aAAa,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAA;CACxD;AAGD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAA;AACxD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAA;AAG7E,YAAY,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "fds-vue-core",
3
+ "version": "1.0.0",
4
+ "description": "FDS Vue Core Component Library",
5
+ "type": "module",
6
+ "main": "./dist/fds-vue-core.cjs.js",
7
+ "module": "./dist/fds-vue-core.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/fds-vue-core.es.js",
13
+ "require": "./dist/fds-vue-core.cjs.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "keywords": [
20
+ "vue",
21
+ "vue3",
22
+ "components",
23
+ "library",
24
+ "fds"
25
+ ],
26
+ "engines": {
27
+ "node": "^20.19.0 || >=22.12.0"
28
+ },
29
+ "scripts": {
30
+ "serve": "vite",
31
+ "build": "vite build && npm run build:types",
32
+ "build:types": "vue-tsc --project tsconfig.build.json",
33
+ "preview": "vite preview",
34
+ "type-check": "vue-tsc --noEmit",
35
+ "lint": "eslint . --fix",
36
+ "format": "prettier --write src/",
37
+ "prepublishOnly": "npm run build"
38
+ },
39
+ "peerDependencies": {
40
+ "vue": "^3.5.0",
41
+ "fds-core": "^3.8.0"
42
+ },
43
+ "dependencies": {
44
+ "tailwindcss": "^4.1.13"
45
+ },
46
+ "devDependencies": {
47
+ "@tailwindcss/vite": "^4.1.13",
48
+ "@tsconfig/node22": "^22.0.2",
49
+ "@types/node": "^22.16.5",
50
+ "@vitejs/plugin-vue": "^6.0.1",
51
+ "@vue/eslint-config-prettier": "^10.2.0",
52
+ "@vue/eslint-config-typescript": "^14.6.0",
53
+ "@vue/tsconfig": "^0.7.0",
54
+ "eslint": "^9.31.0",
55
+ "eslint-plugin-vue": "~10.3.0",
56
+ "prettier": "3.6.2",
57
+ "typescript": "~5.8.0",
58
+ "vite": "^7.0.6",
59
+ "vite-plugin-dts": "^4.5.4",
60
+ "vite-plugin-vue-devtools": "^8.0.0",
61
+ "vue": "^3.5.18",
62
+ "vue-tsc": "^3.0.4"
63
+ }
64
+ }