@xen-orchestra/web-core 0.35.1 → 0.36.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/lib/components/console/VtsRemoteConsole.vue +1 -1
- package/lib/components/copy-button/VtsCopyButton.vue +1 -1
- package/lib/components/layout/VtsLayoutSidebar.vue +1 -1
- package/lib/components/quick-info-card/VtsQuickInfoCard.vue +1 -1
- package/lib/components/relative-time/VtsRelativeTime.vue +2 -3
- package/lib/components/select/VtsSelect.vue +1 -1
- package/lib/components/state-hero/VtsStateHero.vue +20 -10
- package/lib/components/table/VtsRow.vue +26 -0
- package/lib/components/table/VtsTable.vue +99 -42
- package/lib/components/table/cells/VtsCollapsedListCell.vue +59 -0
- package/lib/components/table/cells/VtsHeaderCell.vue +31 -0
- package/lib/components/table/cells/VtsLinkCell.vue +33 -0
- package/lib/components/table/cells/VtsNumberCell.vue +21 -0
- package/lib/components/{size-progress-cell/VtsSizeProgressCell.vue → table/cells/VtsProgressBarCell.vue} +8 -5
- package/lib/components/table/cells/VtsStatusCell.vue +69 -0
- package/lib/components/table/cells/VtsTagCell.vue +24 -0
- package/lib/components/table/cells/VtsTextCell.vue +32 -0
- package/lib/components/table/cells/VtsTruncatedTextCell.vue +64 -0
- package/lib/components/task/VtsQuickTaskButton.vue +1 -1
- package/lib/components/tree/VtsTreeLine.vue +1 -1
- package/lib/components/ui/alert/UiAlert.vue +1 -1
- package/lib/components/ui/button/UiButton.vue +4 -2
- package/lib/components/ui/button-icon/UiButtonIcon.vue +12 -11
- package/lib/components/ui/column-header/UiColumnHeader.vue +22 -0
- package/lib/components/ui/info/UiInfo.vue +5 -1
- package/lib/components/ui/input/UiInput.vue +3 -2
- package/lib/components/ui/link/UiLink.vue +5 -0
- package/lib/components/ui/log-entry-viewer/UiLogEntryViewer.vue +1 -1
- package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +2 -2
- package/lib/components/ui/table-cell/UiTableCell.vue +41 -0
- package/lib/components/ui/table-pagination/PaginationButton.vue +1 -1
- package/lib/components/ui/toaster/UiToaster.vue +1 -1
- package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +6 -2
- package/lib/composables/pagination.composable.ts +16 -1
- package/lib/composables/relative-time.composable.ts +8 -61
- package/lib/composables/table-state.composable.ts +56 -0
- package/lib/composables/tree-filter.composable.ts +2 -2
- package/lib/icons/fa-icons.ts +2 -0
- package/lib/icons/object-icons.ts +1 -1
- package/lib/locales/en.json +23 -0
- package/lib/locales/fr.json +23 -0
- package/lib/packages/form-select/use-form-select-controller.ts +1 -0
- package/lib/packages/table/README.md +53 -308
- package/lib/packages/table/define-column.ts +7 -0
- package/lib/packages/table/define-columns.ts +104 -50
- package/lib/packages/table/index.ts +3 -11
- package/lib/packages/table/types.ts +10 -0
- package/lib/{composables/tree.composable.md → packages/tree/README.md} +28 -23
- package/lib/{composables → packages}/tree/branch-definition.ts +9 -4
- package/lib/{composables → packages}/tree/branch.ts +15 -20
- package/lib/{composables → packages}/tree/build-nodes.ts +5 -5
- package/lib/{composables → packages}/tree/define-branch.ts +8 -4
- package/lib/{composables → packages}/tree/define-leaf.ts +8 -3
- package/lib/{composables → packages}/tree/define-tree.ts +10 -5
- package/lib/{composables → packages}/tree/leaf-definition.ts +1 -1
- package/lib/{composables → packages}/tree/leaf.ts +3 -3
- package/lib/{composables → packages}/tree/tree-node-base.ts +18 -3
- package/lib/{composables → packages}/tree/tree-node-definition-base.ts +4 -2
- package/lib/{composables → packages}/tree/types.ts +11 -9
- package/lib/{composables/tree.composable.ts → packages/tree/use-tree.ts} +24 -11
- package/lib/tables/column-definitions/address-column.ts +4 -0
- package/lib/tables/column-definitions/button-column.ts +35 -0
- package/lib/tables/column-definitions/button-icon-column.ts +30 -0
- package/lib/tables/column-definitions/collapsed-list-column.ts +12 -0
- package/lib/tables/column-definitions/date-column.ts +34 -0
- package/lib/tables/column-definitions/info-column.ts +12 -0
- package/lib/tables/column-definitions/input-column.ts +32 -0
- package/lib/tables/column-definitions/link-column.ts +14 -0
- package/lib/tables/column-definitions/literal-column.ts +9 -0
- package/lib/tables/column-definitions/number-column.ts +10 -0
- package/lib/tables/column-definitions/percent-column.ts +15 -0
- package/lib/tables/column-definitions/progress-bar-column.ts +10 -0
- package/lib/tables/column-definitions/select-column.ts +12 -0
- package/lib/tables/column-definitions/select-item-column.ts +8 -0
- package/lib/tables/column-definitions/status-column.ts +16 -0
- package/lib/tables/column-definitions/tag-column.ts +11 -0
- package/lib/tables/column-definitions/text-column.ts +11 -0
- package/lib/tables/column-definitions/truncated-text-column.ts +10 -0
- package/lib/tables/column-sets/backup-issue-columns.ts +15 -0
- package/lib/tables/column-sets/backup-job-columns.ts +23 -0
- package/lib/tables/column-sets/backup-job-schedule-columns.ts +21 -0
- package/lib/tables/column-sets/backup-log-columns.ts +19 -0
- package/lib/tables/column-sets/host-columns.ts +19 -0
- package/lib/tables/column-sets/network-columns.ts +22 -0
- package/lib/tables/column-sets/new-vm-network-columns.ts +24 -0
- package/lib/tables/column-sets/new-vm-sr-columns.ts +33 -0
- package/lib/tables/column-sets/patch-columns.ts +13 -0
- package/lib/tables/column-sets/pif-columns.ts +23 -0
- package/lib/tables/column-sets/server-columns.ts +18 -0
- package/lib/tables/column-sets/sr-columns.ts +20 -0
- package/lib/tables/column-sets/vdi-columns.ts +21 -0
- package/lib/tables/column-sets/vif-columns.ts +23 -0
- package/lib/tables/column-sets/vm-columns.ts +21 -0
- package/lib/tables/helpers/render-body-cell.ts +4 -0
- package/lib/tables/helpers/render-head-cell.ts +6 -0
- package/lib/tables/helpers/render-loading-cell.ts +5 -0
- package/lib/tables/types.ts +7 -0
- package/lib/utils/size.util.ts +5 -9
- package/package.json +1 -1
- package/lib/components/data-table/VtsDataTable.vue +0 -70
- package/lib/components/table/ColumnTitle.vue +0 -152
- package/lib/packages/table/apply-extensions.ts +0 -26
- package/lib/packages/table/define-renderer/define-table-cell-renderer.ts +0 -27
- package/lib/packages/table/define-renderer/define-table-renderer.ts +0 -47
- package/lib/packages/table/define-renderer/define-table-row-renderer.ts +0 -29
- package/lib/packages/table/define-renderer/define-table-section-renderer.ts +0 -29
- package/lib/packages/table/define-table/define-multi-source-table.ts +0 -39
- package/lib/packages/table/define-table/define-table.ts +0 -13
- package/lib/packages/table/define-table/define-typed-table.ts +0 -18
- package/lib/packages/table/transform-sources.ts +0 -13
- package/lib/packages/table/types/extensions.ts +0 -16
- package/lib/packages/table/types/index.ts +0 -47
- package/lib/packages/table/types/table-cell.ts +0 -18
- package/lib/packages/table/types/table-row.ts +0 -20
- package/lib/packages/table/types/table-section.ts +0 -19
- package/lib/packages/table/types/table.ts +0 -28
- package/lib/types/button.type.ts +0 -3
|
@@ -1,62 +1,116 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
string,
|
|
8
|
-
| {
|
|
9
|
-
header: (arg: THeaderArg) => TableCellVNode
|
|
10
|
-
body: (source: TSource, arg: TBodyArg) => TableCellVNode
|
|
11
|
-
}
|
|
12
|
-
| undefined
|
|
13
|
-
>,
|
|
14
|
-
TColumnName extends Extract<keyof TColumns, string>,
|
|
15
|
-
THeaderArg = undefined,
|
|
16
|
-
TBodyArg = undefined,
|
|
17
|
-
>(
|
|
18
|
-
config: TColumns &
|
|
19
|
-
Record<
|
|
20
|
-
string,
|
|
21
|
-
| {
|
|
22
|
-
header: (arg: THeaderArg) => TableCellVNode
|
|
23
|
-
body: (source: TSource, arg: TBodyArg) => TableCellVNode
|
|
24
|
-
}
|
|
25
|
-
| undefined
|
|
26
|
-
>
|
|
1
|
+
import type { AreAllPropertiesOptional, Columns } from '@core/packages/table/types.ts'
|
|
2
|
+
import { objectOmit } from '@vueuse/shared'
|
|
3
|
+
import { computed, defineComponent, Fragment, h, ref, type Component, type Ref, type VNode } from 'vue'
|
|
4
|
+
|
|
5
|
+
export function defineColumns<TSetupArgs extends any[], TColumns extends Columns>(
|
|
6
|
+
setup: (...args: TSetupArgs) => TColumns
|
|
27
7
|
) {
|
|
28
|
-
|
|
8
|
+
function useColumns<
|
|
9
|
+
THeadRenderers extends {
|
|
10
|
+
[K in keyof TColumns as [] extends Parameters<TColumns[K]['renderHead']> ? K : never]?: (
|
|
11
|
+
renderer: TColumns[K]['renderHead']
|
|
12
|
+
) => VNode
|
|
13
|
+
} & {
|
|
14
|
+
[K in keyof TColumns as [] extends Parameters<TColumns[K]['renderHead']> ? never : K]: (
|
|
15
|
+
renderer: TColumns[K]['renderHead']
|
|
16
|
+
) => VNode
|
|
17
|
+
},
|
|
18
|
+
TBodyRenderers extends {
|
|
19
|
+
[K in keyof TColumns]: (renderer: TColumns[K]['renderBody']) => VNode
|
|
20
|
+
},
|
|
21
|
+
THeadItem,
|
|
22
|
+
TBodyItem,
|
|
23
|
+
TExcludedId extends keyof TColumns = never,
|
|
24
|
+
>(
|
|
25
|
+
config: {
|
|
26
|
+
exclude?: TExcludedId[]
|
|
27
|
+
body: (item: TBodyItem) => Omit<TBodyRenderers, TExcludedId>
|
|
28
|
+
} & (AreAllPropertiesOptional<Omit<THeadRenderers, TExcludedId>> extends true
|
|
29
|
+
? { head?: (item: THeadItem) => Omit<THeadRenderers, TExcludedId> }
|
|
30
|
+
: { head: (item: THeadItem) => Omit<THeadRenderers, TExcludedId> }),
|
|
31
|
+
...args: TSetupArgs
|
|
32
|
+
) {
|
|
33
|
+
type $TAvailableColumns = Omit<TColumns, TExcludedId>
|
|
34
|
+
type $TAvailableColumnId = keyof $TAvailableColumns
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
const allColumns = setup(...args)
|
|
31
37
|
|
|
32
|
-
|
|
38
|
+
const availableColumns = objectOmit(allColumns, config.exclude ?? []) as $TAvailableColumns
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
const hiddenColumnIds = ref(new Set()) as Ref<Set<$TAvailableColumnId>>
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
const visibleColumnIds = computed(
|
|
43
|
+
() =>
|
|
44
|
+
Object.keys(availableColumns).filter(
|
|
45
|
+
id => !hiddenColumnIds.value.has(id as $TAvailableColumnId)
|
|
46
|
+
) as $TAvailableColumnId[]
|
|
47
|
+
)
|
|
37
48
|
|
|
38
|
-
|
|
39
|
-
? (arg?: THeaderArg) => TableCellVNode[]
|
|
40
|
-
: (arg: THeaderArg) => TableCellVNode[]
|
|
49
|
+
const colspan = computed(() => visibleColumnIds.value.length)
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
function toggle(columnId: $TAvailableColumnId, visible: boolean = hiddenColumnIds.value.has(columnId)) {
|
|
52
|
+
if (visible) {
|
|
53
|
+
hiddenColumnIds.value.delete(columnId)
|
|
54
|
+
} else {
|
|
55
|
+
hiddenColumnIds.value.add(columnId)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
45
58
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
const HeadCells = defineComponent({
|
|
60
|
+
props: {
|
|
61
|
+
item: {
|
|
62
|
+
type: Object as () => THeadItem,
|
|
63
|
+
required: false,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
setup(props) {
|
|
67
|
+
const headCellRenderers = config.head?.(props.item as THeadItem) ?? ({} as THeadRenderers)
|
|
49
68
|
|
|
50
|
-
|
|
51
|
-
|
|
69
|
+
return () =>
|
|
70
|
+
visibleColumnIds.value.map(columnId => {
|
|
71
|
+
const { renderHead } = availableColumns[columnId]
|
|
52
72
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
73
|
+
const headCellRenderer = headCellRenderers[columnId as keyof typeof headCellRenderers]
|
|
74
|
+
|
|
75
|
+
return h(Fragment, { key: columnId }, [headCellRenderer ? headCellRenderer(renderHead) : renderHead()])
|
|
76
|
+
})
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const BodyCells = defineComponent({
|
|
81
|
+
props: {
|
|
82
|
+
item: {
|
|
83
|
+
type: Object as () => TBodyItem,
|
|
84
|
+
required: true,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
setup(props) {
|
|
88
|
+
const bodyCellRenderers = config.body(props.item as TBodyItem) ?? ({} as TBodyRenderers)
|
|
89
|
+
|
|
90
|
+
return () =>
|
|
91
|
+
visibleColumnIds.value.map(columnId => {
|
|
92
|
+
const { renderBody } = availableColumns[columnId]
|
|
93
|
+
|
|
94
|
+
const bodyCellRenderer = bodyCellRenderers[columnId as keyof typeof bodyCellRenderers]
|
|
95
|
+
|
|
96
|
+
return h(Fragment, { key: columnId }, [bodyCellRenderer ? bodyCellRenderer(renderBody) : renderBody()])
|
|
97
|
+
})
|
|
98
|
+
},
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
HeadCells: HeadCells as Component<
|
|
103
|
+
[THeadItem] extends [undefined]
|
|
104
|
+
? Record<string, never>
|
|
105
|
+
: undefined extends THeadItem
|
|
106
|
+
? { item?: THeadItem }
|
|
107
|
+
: { item: THeadItem }
|
|
108
|
+
>,
|
|
109
|
+
BodyCells: BodyCells as Component<{ item: TBodyItem }>,
|
|
110
|
+
toggle,
|
|
111
|
+
colspan,
|
|
112
|
+
}
|
|
61
113
|
}
|
|
114
|
+
|
|
115
|
+
return useColumns
|
|
62
116
|
}
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export * from './define-columns'
|
|
5
|
-
export * from './define-table/define-multi-source-table'
|
|
6
|
-
export * from './define-table/define-table'
|
|
7
|
-
export * from './define-renderer/define-table-renderer'
|
|
8
|
-
export * from './define-renderer/define-table-section-renderer'
|
|
9
|
-
export * from './define-table/define-typed-table'
|
|
10
|
-
export * from './transform-sources'
|
|
11
|
-
export * from './types'
|
|
1
|
+
export { defineColumn } from './define-column.ts'
|
|
2
|
+
export { defineColumns } from './define-columns.ts'
|
|
3
|
+
export type { ColumnRenderer, Columns } from './types.ts'
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type VNode } from 'vue'
|
|
2
|
+
|
|
3
|
+
export type ColumnRenderer<THeadArgs extends any[], TBodyArgs extends any[]> = {
|
|
4
|
+
renderHead: (...args: THeadArgs) => VNode
|
|
5
|
+
renderBody: (...args: TBodyArgs) => VNode
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type Columns = Record<string, ColumnRenderer<any, any>>
|
|
9
|
+
|
|
10
|
+
export type AreAllPropertiesOptional<T> = Record<string, never> extends T ? true : false
|
|
@@ -50,12 +50,13 @@ This option allows you to customize the label of the selected nodes.
|
|
|
50
50
|
## `LeafDefinition`
|
|
51
51
|
|
|
52
52
|
```ts
|
|
53
|
-
new LeafDefinition(data)
|
|
54
|
-
new LeafDefinition(data, options)
|
|
53
|
+
new LeafDefinition(treeId, data)
|
|
54
|
+
new LeafDefinition(treeId, data, options)
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
| | Required | Type | Default | |
|
|
58
58
|
| ----------------------- | :------------------: | ---------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
59
|
+
| `treeId` | ✓ | `string` | | identifier for tree this node belongs to |
|
|
59
60
|
| `data` | ✓ | `TData` | | data to be stored in the node |
|
|
60
61
|
| `options.discriminator` | | `string` | `undefined` | discriminator for the node when you mix different data types (see Discriminator below) |
|
|
61
62
|
| `options.predicate` | | `(node: TreeNode) => boolean \| undefined` | `undefined` | filter function (see Filtering below) |
|
|
@@ -66,7 +67,7 @@ new LeafDefinition(data, options)
|
|
|
66
67
|
### Example
|
|
67
68
|
|
|
68
69
|
```ts
|
|
69
|
-
const definition = new LeafDefinition({ id: 1, label: 'John Doe', age: 30 })
|
|
70
|
+
const definition = new LeafDefinition('users', { id: 1, label: 'John Doe', age: 30 })
|
|
70
71
|
```
|
|
71
72
|
|
|
72
73
|
## `BranchDefinition`
|
|
@@ -74,8 +75,8 @@ const definition = new LeafDefinition({ id: 1, label: 'John Doe', age: 30 })
|
|
|
74
75
|
A `BranchDefinition` is very similar to a `LeafDefinition`, but it contains a collection of children definitions.
|
|
75
76
|
|
|
76
77
|
```ts
|
|
77
|
-
new BranchDefinition(data, children)
|
|
78
|
-
new BranchDefinition(data, options, children)
|
|
78
|
+
new BranchDefinition(treeId, data, children)
|
|
79
|
+
new BranchDefinition(treeId, data, options, children)
|
|
79
80
|
```
|
|
80
81
|
|
|
81
82
|
| | | Type | Default | |
|
|
@@ -86,9 +87,9 @@ new BranchDefinition(data, options, children)
|
|
|
86
87
|
### Example
|
|
87
88
|
|
|
88
89
|
```ts
|
|
89
|
-
const definition = new BranchDefinition({ id: 'smithes', name: 'The Smithes' }, [
|
|
90
|
-
new LeafDefinition({ id: 'jd-1', name: 'John Smith', age: 30 }),
|
|
91
|
-
new LeafDefinition({ id: 'jd-2', name: 'Jane Smith', age: 28 }),
|
|
90
|
+
const definition = new BranchDefinition('users', { id: 'smithes', name: 'The Smithes' }, [
|
|
91
|
+
new LeafDefinition('users', { id: 'jd-1', name: 'John Smith', age: 30 }),
|
|
92
|
+
new LeafDefinition('users', { id: 'jd-2', name: 'Jane Smith', age: 28 }),
|
|
92
93
|
])
|
|
93
94
|
```
|
|
94
95
|
|
|
@@ -101,8 +102,8 @@ mix different types of nodes at the same collection depth.
|
|
|
101
102
|
|
|
102
103
|
```ts
|
|
103
104
|
const definitions = [
|
|
104
|
-
new LeafDefinition({ id: 'jd-1', label: 'John Doe', age: 30 }),
|
|
105
|
-
new LeafDefinition({ id: 'rx-1', label: 'Rex', breed: 'Golden Retriever' }),
|
|
105
|
+
new LeafDefinition('family', { id: 'jd-1', label: 'John Doe', age: 30 }),
|
|
106
|
+
new LeafDefinition('family', { id: 'rx-1', label: 'Rex', breed: 'Golden Retriever' }),
|
|
106
107
|
]
|
|
107
108
|
|
|
108
109
|
const { nodes } = useTree(definitions)
|
|
@@ -116,8 +117,8 @@ nodes.value.forEach(node => {
|
|
|
116
117
|
|
|
117
118
|
```ts
|
|
118
119
|
const definitions = [
|
|
119
|
-
new LeafDefinition({ id: 'jd-1', label: 'John Doe', age: 30 }, { discriminator: 'person' }),
|
|
120
|
-
new LeafDefinition({ id: 'rx-1', label: 'Rex', breed: 'Golden Retriever' }, { discriminator: 'animal' }),
|
|
120
|
+
new LeafDefinition('family', { id: 'jd-1', label: 'John Doe', age: 30 }, { discriminator: 'person' }),
|
|
121
|
+
new LeafDefinition('family', { id: 'rx-1', label: 'Rex', breed: 'Golden Retriever' }, { discriminator: 'animal' }),
|
|
121
122
|
]
|
|
122
123
|
|
|
123
124
|
const { nodes } = useTree(definitions)
|
|
@@ -138,8 +139,8 @@ the `isBranch` property will serve the same purpose.
|
|
|
138
139
|
|
|
139
140
|
```ts
|
|
140
141
|
const definitions = [
|
|
141
|
-
new LeafDefinition({ id: 'jd-1', label: 'John Doe', age: 30 }),
|
|
142
|
-
new BranchDefinition({ id: 'dogs', label: 'Dogs', legs: 4 }, [
|
|
142
|
+
new LeafDefinition('family', { id: 'jd-1', label: 'John Doe', age: 30 }),
|
|
143
|
+
new BranchDefinition('family', { id: 'dogs', label: 'Dogs', legs: 4 }, [
|
|
143
144
|
/* ... */
|
|
144
145
|
]),
|
|
145
146
|
]
|
|
@@ -254,7 +255,9 @@ const families = [
|
|
|
254
255
|
You can use the `defineTree` helper this way:
|
|
255
256
|
|
|
256
257
|
```ts
|
|
257
|
-
const definitions = defineTree(families, family =>
|
|
258
|
+
const definitions = defineTree('family', families, family =>
|
|
259
|
+
defineTree('member', family.members, member => defineTree('animal', member.animals))
|
|
260
|
+
)
|
|
258
261
|
```
|
|
259
262
|
|
|
260
263
|
This is the equivalent of the following code:
|
|
@@ -263,12 +266,14 @@ This is the equivalent of the following code:
|
|
|
263
266
|
const definitions = families.map(
|
|
264
267
|
family =>
|
|
265
268
|
new BranchDefinition(
|
|
269
|
+
'family',
|
|
266
270
|
family,
|
|
267
271
|
family.members.map(
|
|
268
272
|
member =>
|
|
269
273
|
new BranchDefinition(
|
|
274
|
+
'member',
|
|
270
275
|
member,
|
|
271
|
-
member.animals.map(animal => new LeafDefinition(animal))
|
|
276
|
+
member.animals.map('animal', animal => new LeafDefinition(animal))
|
|
272
277
|
)
|
|
273
278
|
)
|
|
274
279
|
)
|
|
@@ -287,12 +292,12 @@ const entries = [
|
|
|
287
292
|
{ uuid: 'jd-2', name: 'Jane Doe' },
|
|
288
293
|
]
|
|
289
294
|
|
|
290
|
-
const definitionsA = defineTree(entries, {
|
|
295
|
+
const definitionsA = defineTree('user', entries, {
|
|
291
296
|
getId: 'uuid',
|
|
292
297
|
getLabel: 'name',
|
|
293
298
|
})
|
|
294
299
|
|
|
295
|
-
const definitionsB = defineTree(entries, {
|
|
300
|
+
const definitionsB = defineTree('user', entries, {
|
|
296
301
|
getId: entry => entry.uuid,
|
|
297
302
|
getLabel: entry => entry.name,
|
|
298
303
|
})
|
|
@@ -394,8 +399,8 @@ Here are the rules to determine whether a node is visible or not.
|
|
|
394
399
|
</template>
|
|
395
400
|
|
|
396
401
|
<script lang="ts" setup>
|
|
397
|
-
const familyDefinitions = defineTree(families, ({ members }) =>
|
|
398
|
-
defineTree(members, ({ animals }) => defineTree(animals))
|
|
402
|
+
const familyDefinitions = defineTree('family', families, ({ members }) =>
|
|
403
|
+
defineTree('member', members, ({ animals }) => defineTree('animal', animals))
|
|
399
404
|
)
|
|
400
405
|
|
|
401
406
|
const { nodes } = useTree(familyDefinitions)
|
|
@@ -448,7 +453,7 @@ Here are the rules to determine whether a node is visible or not.
|
|
|
448
453
|
</template>
|
|
449
454
|
|
|
450
455
|
<script lang="ts" setup>
|
|
451
|
-
const definitions = defineTree(families, ({ members }) => defineTree(members))
|
|
456
|
+
const definitions = defineTree('family', families, ({ members }) => defineTree('member', members))
|
|
452
457
|
|
|
453
458
|
const { nodes } = useTree(definitions, { allowMultiSelect: true })
|
|
454
459
|
</script>
|
|
@@ -517,8 +522,8 @@ Here are the rules to determine whether a node is visible or not.
|
|
|
517
522
|
return !filterValue ? undefined : label.toLocaleLowerCase().includes(filterValue)
|
|
518
523
|
}
|
|
519
524
|
|
|
520
|
-
const definitions = defineTree(families, { predicate }, ({ members }) =>
|
|
521
|
-
defineTree(members, { predicate }, ({ animals }) => defineTree(animals, { predicate }))
|
|
525
|
+
const definitions = defineTree('family', families, { predicate }, ({ members }) =>
|
|
526
|
+
defineTree('member', members, { predicate }, ({ animals }) => defineTree('animal', animals, { predicate }))
|
|
522
527
|
)
|
|
523
528
|
|
|
524
529
|
const { nodes } = useTree(definitions, { expand: false })
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TreeNodeDefinitionBase } from '@core/
|
|
2
|
-
import type { TreeNodeDefinition, TreeNodeOptions } from '@core/
|
|
1
|
+
import { TreeNodeDefinitionBase } from '@core/packages/tree/tree-node-definition-base'
|
|
2
|
+
import type { TreeNodeDefinition, TreeNodeOptions } from '@core/packages/tree/types'
|
|
3
3
|
|
|
4
4
|
export class BranchDefinition<
|
|
5
5
|
TData extends object = any,
|
|
@@ -9,8 +9,13 @@ export class BranchDefinition<
|
|
|
9
9
|
readonly isBranch = true
|
|
10
10
|
children: TChildDefinition[]
|
|
11
11
|
|
|
12
|
-
constructor(
|
|
13
|
-
|
|
12
|
+
constructor(
|
|
13
|
+
treeId: string,
|
|
14
|
+
data: TData,
|
|
15
|
+
options: TreeNodeOptions<TData, TDiscriminator>,
|
|
16
|
+
children: TChildDefinition[]
|
|
17
|
+
) {
|
|
18
|
+
super(treeId, data, options)
|
|
14
19
|
|
|
15
20
|
this.children = children
|
|
16
21
|
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import { TreeNodeBase } from '@core/
|
|
2
|
-
import type {
|
|
3
|
-
BranchStatuses,
|
|
4
|
-
ChildTreeGetter,
|
|
5
|
-
TreeContext,
|
|
6
|
-
TreeNode,
|
|
7
|
-
TreeNodeOptions,
|
|
8
|
-
} from '@core/composables/tree/types'
|
|
1
|
+
import { TreeNodeBase } from '@core/packages/tree/tree-node-base'
|
|
2
|
+
import type { BranchStatuses, ChildTreeGetter, TreeContext, TreeNode, TreeNodeOptions } from '@core/packages/tree/types'
|
|
9
3
|
|
|
10
4
|
export class Branch<
|
|
11
5
|
TData extends object = any,
|
|
@@ -16,6 +10,7 @@ export class Branch<
|
|
|
16
10
|
readonly rawChildren: TChildNode[]
|
|
17
11
|
|
|
18
12
|
constructor(
|
|
13
|
+
treeId: string,
|
|
19
14
|
data: TData,
|
|
20
15
|
parent: Branch | undefined,
|
|
21
16
|
context: TreeContext,
|
|
@@ -23,7 +18,7 @@ export class Branch<
|
|
|
23
18
|
options: TreeNodeOptions<TData, TDiscriminator> | undefined,
|
|
24
19
|
getChildTree: ChildTreeGetter<TData, TChildNode, TDiscriminator>
|
|
25
20
|
) {
|
|
26
|
-
super(data, parent, context, depth, options)
|
|
21
|
+
super(treeId, data, parent, context, depth, options)
|
|
27
22
|
this.rawChildren = getChildTree(this)
|
|
28
23
|
}
|
|
29
24
|
|
|
@@ -48,7 +43,7 @@ export class Branch<
|
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
get isExcluded() {
|
|
51
|
-
if (this.parent?.
|
|
46
|
+
if (this.parent?.isCollapsed === true) {
|
|
52
47
|
return true
|
|
53
48
|
}
|
|
54
49
|
|
|
@@ -59,8 +54,8 @@ export class Branch<
|
|
|
59
54
|
return this.failsFilterDownwards
|
|
60
55
|
}
|
|
61
56
|
|
|
62
|
-
get
|
|
63
|
-
return this.context.
|
|
57
|
+
get isCollapsed() {
|
|
58
|
+
return this.context.collapsedIds.has(this.id)
|
|
64
59
|
}
|
|
65
60
|
|
|
66
61
|
get areChildrenFullySelected(): boolean {
|
|
@@ -92,7 +87,7 @@ export class Branch<
|
|
|
92
87
|
matches: this.passesFilter === true,
|
|
93
88
|
'selected-partial': this.context.allowMultiSelect && this.areChildrenPartiallySelected,
|
|
94
89
|
'selected-full': this.context.allowMultiSelect && this.areChildrenFullySelected,
|
|
95
|
-
|
|
90
|
+
collapsed: this.isCollapsed,
|
|
96
91
|
}
|
|
97
92
|
}
|
|
98
93
|
|
|
@@ -101,21 +96,21 @@ export class Branch<
|
|
|
101
96
|
return this.areChildrenFullySelected ? 'all' : this.areChildrenPartiallySelected ? 'some' : 'none'
|
|
102
97
|
}
|
|
103
98
|
|
|
104
|
-
|
|
105
|
-
const
|
|
99
|
+
toggleCollapse(forcedValue?: boolean, recursive?: boolean) {
|
|
100
|
+
const nextCollapsed = forcedValue ?? !this.isCollapsed
|
|
106
101
|
|
|
107
|
-
if (
|
|
108
|
-
this.context.
|
|
102
|
+
if (nextCollapsed) {
|
|
103
|
+
this.context.collapsedIds.add(this.id)
|
|
109
104
|
} else {
|
|
110
|
-
this.context.
|
|
105
|
+
this.context.collapsedIds.delete(this.id)
|
|
111
106
|
}
|
|
112
107
|
|
|
113
|
-
const shouldPropagate = recursive ??
|
|
108
|
+
const shouldPropagate = recursive ?? nextCollapsed
|
|
114
109
|
|
|
115
110
|
if (shouldPropagate) {
|
|
116
111
|
this.rawChildren.forEach(child => {
|
|
117
112
|
if (child.isBranch) {
|
|
118
|
-
child.
|
|
113
|
+
child.toggleCollapse(nextCollapsed, recursive)
|
|
119
114
|
}
|
|
120
115
|
})
|
|
121
116
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Branch } from '@core/
|
|
2
|
-
import { Leaf } from '@core/
|
|
3
|
-
import type { DefinitionToTreeNode, TreeContext, TreeNode, TreeNodeDefinition } from '@core/
|
|
1
|
+
import { Branch } from '@core/packages/tree/branch'
|
|
2
|
+
import { Leaf } from '@core/packages/tree/leaf'
|
|
3
|
+
import type { DefinitionToTreeNode, TreeContext, TreeNode, TreeNodeDefinition } from '@core/packages/tree/types'
|
|
4
4
|
|
|
5
5
|
export function buildNodes<TDefinition extends TreeNodeDefinition, TTreeNode extends DefinitionToTreeNode<TDefinition>>(
|
|
6
6
|
definitions: TDefinition[],
|
|
@@ -9,10 +9,10 @@ export function buildNodes<TDefinition extends TreeNodeDefinition, TTreeNode ext
|
|
|
9
9
|
function create(definitions: TreeNodeDefinition[], parent: Branch | undefined, depth: number): TreeNode[] {
|
|
10
10
|
return definitions.map(definition =>
|
|
11
11
|
definition.isBranch
|
|
12
|
-
? new Branch(definition.data, parent, context, depth, definition.options, thisBranch =>
|
|
12
|
+
? new Branch(definition.treeId, definition.data, parent, context, depth, definition.options, thisBranch =>
|
|
13
13
|
create(definition.children, thisBranch, depth + 1)
|
|
14
14
|
)
|
|
15
|
-
: new Leaf(definition.data, parent, context, depth, definition.options)
|
|
15
|
+
: new Leaf(definition.treeId, definition.data, parent, context, depth, definition.options)
|
|
16
16
|
)
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import { BranchDefinition } from '@core/
|
|
2
|
-
import type { Identifiable, Labeled, TreeNodeDefinition, TreeNodeOptions } from '@core/
|
|
1
|
+
import { BranchDefinition } from '@core/packages/tree/branch-definition'
|
|
2
|
+
import type { Identifiable, Labeled, TreeNodeDefinition, TreeNodeOptions } from '@core/packages/tree/types'
|
|
3
3
|
|
|
4
4
|
export function defineBranch<
|
|
5
5
|
TData extends Identifiable & Labeled,
|
|
6
6
|
TChildDefinition extends TreeNodeDefinition,
|
|
7
7
|
const TDiscriminator,
|
|
8
|
-
>(data: TData, children: TChildDefinition[]): BranchDefinition<TData, TChildDefinition, TDiscriminator>
|
|
8
|
+
>(treeId: string, data: TData, children: TChildDefinition[]): BranchDefinition<TData, TChildDefinition, TDiscriminator>
|
|
9
|
+
|
|
9
10
|
export function defineBranch<TData extends object, TChildDefinition extends TreeNodeDefinition, const TDiscriminator>(
|
|
11
|
+
treeId: string,
|
|
10
12
|
data: TData,
|
|
11
13
|
options: TreeNodeOptions<TData, TDiscriminator>,
|
|
12
14
|
children: TChildDefinition[]
|
|
13
15
|
): BranchDefinition<TData, TChildDefinition, TDiscriminator>
|
|
16
|
+
|
|
14
17
|
export function defineBranch<TData extends object, TChildDefinition extends TreeNodeDefinition, const TDiscriminator>(
|
|
18
|
+
treeId: string,
|
|
15
19
|
data: TData,
|
|
16
20
|
optionsOrChildren: TreeNodeOptions<TData, TDiscriminator> | TChildDefinition[],
|
|
17
21
|
childrenOrNone?: TChildDefinition[]
|
|
@@ -19,5 +23,5 @@ export function defineBranch<TData extends object, TChildDefinition extends Tree
|
|
|
19
23
|
const options = Array.isArray(optionsOrChildren) ? ({} as TreeNodeOptions<TData, TDiscriminator>) : optionsOrChildren
|
|
20
24
|
const children = Array.isArray(optionsOrChildren) ? optionsOrChildren : childrenOrNone!
|
|
21
25
|
|
|
22
|
-
return new BranchDefinition(data, options, children)
|
|
26
|
+
return new BranchDefinition(treeId, data, options, children)
|
|
23
27
|
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import { LeafDefinition } from '@core/
|
|
2
|
-
import type { Identifiable, Labeled, TreeNodeOptions } from '@core/
|
|
1
|
+
import { LeafDefinition } from '@core/packages/tree/leaf-definition'
|
|
2
|
+
import type { Identifiable, Labeled, TreeNodeOptions } from '@core/packages/tree/types'
|
|
3
3
|
|
|
4
4
|
export function defineLeaf<TData extends Identifiable & Labeled, const TDiscriminator>(
|
|
5
|
+
treeId: string,
|
|
5
6
|
data: TData
|
|
6
7
|
): LeafDefinition<TData, TDiscriminator>
|
|
8
|
+
|
|
7
9
|
export function defineLeaf<TData extends object, const TDiscriminator>(
|
|
10
|
+
treeId: string,
|
|
8
11
|
data: TData,
|
|
9
12
|
options: TreeNodeOptions<TData, TDiscriminator>
|
|
10
13
|
): LeafDefinition<TData, TDiscriminator>
|
|
14
|
+
|
|
11
15
|
export function defineLeaf<TData extends object, const TDiscriminator>(
|
|
16
|
+
treeId: string,
|
|
12
17
|
data: TData,
|
|
13
18
|
options?: TreeNodeOptions<TData, TDiscriminator>
|
|
14
19
|
): LeafDefinition<TData, TDiscriminator> {
|
|
15
|
-
return new LeafDefinition(data, options ?? ({} as TreeNodeOptions<TData, TDiscriminator>))
|
|
20
|
+
return new LeafDefinition(treeId, data, options ?? ({} as TreeNodeOptions<TData, TDiscriminator>))
|
|
16
21
|
}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import { BranchDefinition } from '@core/
|
|
2
|
-
import { LeafDefinition } from '@core/
|
|
1
|
+
import { BranchDefinition } from '@core/packages/tree/branch-definition'
|
|
2
|
+
import { LeafDefinition } from '@core/packages/tree/leaf-definition'
|
|
3
3
|
import type {
|
|
4
4
|
ChildTreeDefinitionGetter,
|
|
5
5
|
Identifiable,
|
|
6
6
|
Labeled,
|
|
7
7
|
TreeNodeDefinition,
|
|
8
8
|
TreeNodeOptions,
|
|
9
|
-
} from '@core/
|
|
9
|
+
} from '@core/packages/tree/types'
|
|
10
10
|
|
|
11
11
|
// Overload 1: Leaf with no options
|
|
12
12
|
export function defineTree<TData extends Identifiable & Labeled, const TDiscriminator = any>(
|
|
13
|
+
treeId: string,
|
|
13
14
|
entries: TData[]
|
|
14
15
|
): LeafDefinition<TData, TDiscriminator>[]
|
|
15
16
|
|
|
16
17
|
// Overload 2: Leaf with options
|
|
17
18
|
export function defineTree<TData extends object, const TDiscriminator = any>(
|
|
19
|
+
treeId: string,
|
|
18
20
|
entries: TData[],
|
|
19
21
|
options: TreeNodeOptions<TData, TDiscriminator>
|
|
20
22
|
): LeafDefinition<TData, TDiscriminator>[]
|
|
@@ -25,6 +27,7 @@ export function defineTree<
|
|
|
25
27
|
TChildDefinition extends TreeNodeDefinition,
|
|
26
28
|
const TDiscriminator = any,
|
|
27
29
|
>(
|
|
30
|
+
treeId: string,
|
|
28
31
|
entries: TData[],
|
|
29
32
|
getChildTree: ChildTreeDefinitionGetter<TData, TChildDefinition>
|
|
30
33
|
): BranchDefinition<TData, TChildDefinition, TDiscriminator>[]
|
|
@@ -35,6 +38,7 @@ export function defineTree<
|
|
|
35
38
|
TChildDefinition extends TreeNodeDefinition = TreeNodeDefinition,
|
|
36
39
|
const TDiscriminator = any,
|
|
37
40
|
>(
|
|
41
|
+
treeId: string,
|
|
38
42
|
entries: TData[],
|
|
39
43
|
options: TreeNodeOptions<TData, TDiscriminator>,
|
|
40
44
|
getChildTree: ChildTreeDefinitionGetter<TData, TChildDefinition>
|
|
@@ -46,6 +50,7 @@ export function defineTree<
|
|
|
46
50
|
TChildDefinition extends TreeNodeDefinition = TreeNodeDefinition,
|
|
47
51
|
const TDiscriminator = any,
|
|
48
52
|
>(
|
|
53
|
+
treeId: string,
|
|
49
54
|
entries: TData[],
|
|
50
55
|
optionsOrGetChildTree?: TreeNodeOptions<TData, TDiscriminator> | ChildTreeDefinitionGetter<TData, TChildDefinition>,
|
|
51
56
|
getChildTreeOrNone?: ChildTreeDefinitionGetter<TData, TChildDefinition>
|
|
@@ -58,8 +63,8 @@ export function defineTree<
|
|
|
58
63
|
const getChildTree = typeof optionsOrGetChildTree === 'function' ? optionsOrGetChildTree : getChildTreeOrNone
|
|
59
64
|
|
|
60
65
|
if (getChildTree !== undefined) {
|
|
61
|
-
return entries.map(data => new BranchDefinition(data, options, getChildTree(data)))
|
|
66
|
+
return entries.map(data => new BranchDefinition(treeId, data, options, getChildTree(data)))
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
return entries.map(data => new LeafDefinition(data, options))
|
|
69
|
+
return entries.map(data => new LeafDefinition(treeId, data, options))
|
|
65
70
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TreeNodeDefinitionBase } from '@core/
|
|
1
|
+
import { TreeNodeDefinitionBase } from '@core/packages/tree/tree-node-definition-base'
|
|
2
2
|
|
|
3
3
|
export class LeafDefinition<TData extends object = any, const TDiscriminator = any> extends TreeNodeDefinitionBase<
|
|
4
4
|
TData,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TreeNodeBase } from '@core/
|
|
2
|
-
import type { LeafStatuses } from '@core/
|
|
1
|
+
import { TreeNodeBase } from '@core/packages/tree/tree-node-base'
|
|
2
|
+
import type { LeafStatuses } from '@core/packages/tree/types'
|
|
3
3
|
|
|
4
4
|
export class Leaf<TData extends object = any, const TDiscriminator = any> extends TreeNodeBase<TData, TDiscriminator> {
|
|
5
5
|
readonly isBranch = false
|
|
@@ -13,7 +13,7 @@ export class Leaf<TData extends object = any, const TDiscriminator = any> extend
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
get isExcluded() {
|
|
16
|
-
if (this.parent?.
|
|
16
|
+
if (this.parent?.isCollapsed === true) {
|
|
17
17
|
return true
|
|
18
18
|
}
|
|
19
19
|
|