@xen-orchestra/web-core 0.35.0 → 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.
Files changed (118) hide show
  1. package/lib/components/console/VtsRemoteConsole.vue +1 -1
  2. package/lib/components/copy-button/VtsCopyButton.vue +1 -1
  3. package/lib/components/layout/VtsLayoutSidebar.vue +1 -1
  4. package/lib/components/quick-info-card/VtsQuickInfoCard.vue +1 -1
  5. package/lib/components/relative-time/VtsRelativeTime.vue +2 -3
  6. package/lib/components/select/VtsSelect.vue +1 -1
  7. package/lib/components/state-hero/VtsStateHero.vue +20 -10
  8. package/lib/components/table/VtsRow.vue +26 -0
  9. package/lib/components/table/VtsTable.vue +99 -42
  10. package/lib/components/table/cells/VtsCollapsedListCell.vue +59 -0
  11. package/lib/components/table/cells/VtsHeaderCell.vue +31 -0
  12. package/lib/components/table/cells/VtsLinkCell.vue +33 -0
  13. package/lib/components/table/cells/VtsNumberCell.vue +21 -0
  14. package/lib/components/{size-progress-cell/VtsSizeProgressCell.vue → table/cells/VtsProgressBarCell.vue} +8 -5
  15. package/lib/components/table/cells/VtsStatusCell.vue +69 -0
  16. package/lib/components/table/cells/VtsTagCell.vue +24 -0
  17. package/lib/components/table/cells/VtsTextCell.vue +32 -0
  18. package/lib/components/table/cells/VtsTruncatedTextCell.vue +64 -0
  19. package/lib/components/task/VtsQuickTaskButton.vue +1 -1
  20. package/lib/components/tree/VtsTreeLine.vue +1 -1
  21. package/lib/components/ui/alert/UiAlert.vue +1 -1
  22. package/lib/components/ui/button/UiButton.vue +4 -2
  23. package/lib/components/ui/button-icon/UiButtonIcon.vue +12 -11
  24. package/lib/components/ui/column-header/UiColumnHeader.vue +22 -0
  25. package/lib/components/ui/info/UiInfo.vue +5 -1
  26. package/lib/components/ui/input/UiInput.vue +3 -2
  27. package/lib/components/ui/link/UiLink.vue +5 -0
  28. package/lib/components/ui/log-entry-viewer/UiLogEntryViewer.vue +1 -1
  29. package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +2 -2
  30. package/lib/components/ui/table-cell/UiTableCell.vue +41 -0
  31. package/lib/components/ui/table-pagination/PaginationButton.vue +1 -1
  32. package/lib/components/ui/toaster/UiToaster.vue +1 -1
  33. package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +6 -2
  34. package/lib/composables/pagination.composable.ts +16 -1
  35. package/lib/composables/relative-time.composable.ts +8 -61
  36. package/lib/composables/table-state.composable.ts +56 -0
  37. package/lib/composables/tree-filter.composable.ts +2 -2
  38. package/lib/icons/fa-icons.ts +2 -0
  39. package/lib/icons/object-icons.ts +1 -1
  40. package/lib/locales/en.json +23 -0
  41. package/lib/locales/fr.json +23 -0
  42. package/lib/packages/form-select/use-form-select-controller.ts +1 -0
  43. package/lib/packages/remote-resource/define-remote-resource.ts +4 -4
  44. package/lib/packages/table/README.md +53 -308
  45. package/lib/packages/table/define-column.ts +7 -0
  46. package/lib/packages/table/define-columns.ts +104 -50
  47. package/lib/packages/table/index.ts +3 -11
  48. package/lib/packages/table/types.ts +10 -0
  49. package/lib/{composables/tree.composable.md → packages/tree/README.md} +28 -23
  50. package/lib/{composables → packages}/tree/branch-definition.ts +9 -4
  51. package/lib/{composables → packages}/tree/branch.ts +15 -20
  52. package/lib/{composables → packages}/tree/build-nodes.ts +5 -5
  53. package/lib/{composables → packages}/tree/define-branch.ts +8 -4
  54. package/lib/{composables → packages}/tree/define-leaf.ts +8 -3
  55. package/lib/{composables → packages}/tree/define-tree.ts +10 -5
  56. package/lib/{composables → packages}/tree/leaf-definition.ts +1 -1
  57. package/lib/{composables → packages}/tree/leaf.ts +3 -3
  58. package/lib/{composables → packages}/tree/tree-node-base.ts +18 -3
  59. package/lib/{composables → packages}/tree/tree-node-definition-base.ts +4 -2
  60. package/lib/{composables → packages}/tree/types.ts +11 -9
  61. package/lib/{composables/tree.composable.ts → packages/tree/use-tree.ts} +24 -11
  62. package/lib/tables/column-definitions/address-column.ts +4 -0
  63. package/lib/tables/column-definitions/button-column.ts +35 -0
  64. package/lib/tables/column-definitions/button-icon-column.ts +30 -0
  65. package/lib/tables/column-definitions/collapsed-list-column.ts +12 -0
  66. package/lib/tables/column-definitions/date-column.ts +34 -0
  67. package/lib/tables/column-definitions/info-column.ts +12 -0
  68. package/lib/tables/column-definitions/input-column.ts +32 -0
  69. package/lib/tables/column-definitions/link-column.ts +14 -0
  70. package/lib/tables/column-definitions/literal-column.ts +9 -0
  71. package/lib/tables/column-definitions/number-column.ts +10 -0
  72. package/lib/tables/column-definitions/percent-column.ts +15 -0
  73. package/lib/tables/column-definitions/progress-bar-column.ts +10 -0
  74. package/lib/tables/column-definitions/select-column.ts +12 -0
  75. package/lib/tables/column-definitions/select-item-column.ts +8 -0
  76. package/lib/tables/column-definitions/status-column.ts +16 -0
  77. package/lib/tables/column-definitions/tag-column.ts +11 -0
  78. package/lib/tables/column-definitions/text-column.ts +11 -0
  79. package/lib/tables/column-definitions/truncated-text-column.ts +10 -0
  80. package/lib/tables/column-sets/backup-issue-columns.ts +15 -0
  81. package/lib/tables/column-sets/backup-job-columns.ts +23 -0
  82. package/lib/tables/column-sets/backup-job-schedule-columns.ts +21 -0
  83. package/lib/tables/column-sets/backup-log-columns.ts +19 -0
  84. package/lib/tables/column-sets/host-columns.ts +19 -0
  85. package/lib/tables/column-sets/network-columns.ts +22 -0
  86. package/lib/tables/column-sets/new-vm-network-columns.ts +24 -0
  87. package/lib/tables/column-sets/new-vm-sr-columns.ts +33 -0
  88. package/lib/tables/column-sets/patch-columns.ts +13 -0
  89. package/lib/tables/column-sets/pif-columns.ts +23 -0
  90. package/lib/tables/column-sets/server-columns.ts +18 -0
  91. package/lib/tables/column-sets/sr-columns.ts +20 -0
  92. package/lib/tables/column-sets/vdi-columns.ts +21 -0
  93. package/lib/tables/column-sets/vif-columns.ts +23 -0
  94. package/lib/tables/column-sets/vm-columns.ts +21 -0
  95. package/lib/tables/helpers/render-body-cell.ts +4 -0
  96. package/lib/tables/helpers/render-head-cell.ts +6 -0
  97. package/lib/tables/helpers/render-loading-cell.ts +5 -0
  98. package/lib/tables/types.ts +7 -0
  99. package/lib/utils/size.util.ts +5 -9
  100. package/package.json +1 -1
  101. package/lib/components/data-table/VtsDataTable.vue +0 -70
  102. package/lib/components/table/ColumnTitle.vue +0 -152
  103. package/lib/packages/table/apply-extensions.ts +0 -26
  104. package/lib/packages/table/define-renderer/define-table-cell-renderer.ts +0 -27
  105. package/lib/packages/table/define-renderer/define-table-renderer.ts +0 -47
  106. package/lib/packages/table/define-renderer/define-table-row-renderer.ts +0 -29
  107. package/lib/packages/table/define-renderer/define-table-section-renderer.ts +0 -29
  108. package/lib/packages/table/define-table/define-multi-source-table.ts +0 -39
  109. package/lib/packages/table/define-table/define-table.ts +0 -13
  110. package/lib/packages/table/define-table/define-typed-table.ts +0 -18
  111. package/lib/packages/table/transform-sources.ts +0 -13
  112. package/lib/packages/table/types/extensions.ts +0 -16
  113. package/lib/packages/table/types/index.ts +0 -47
  114. package/lib/packages/table/types/table-cell.ts +0 -18
  115. package/lib/packages/table/types/table-row.ts +0 -20
  116. package/lib/packages/table/types/table-section.ts +0 -19
  117. package/lib/packages/table/types/table.ts +0 -28
  118. package/lib/types/button.type.ts +0 -3
@@ -1,62 +1,116 @@
1
- import type { TableCellVNode } from '.'
2
- import { reactive, computed } from 'vue'
3
-
4
- export function defineColumns<
5
- TSource,
6
- TColumns extends Record<
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
- const columnNames = Object.keys(config).filter(key => config[key] !== undefined) as TColumnName[]
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
- const hiddenColumnNames = reactive(new Set()) as Set<TColumnName>
36
+ const allColumns = setup(...args)
31
37
 
32
- const visibleColumnNames = computed(() => columnNames.filter(name => !hiddenColumnNames.has(name)))
38
+ const availableColumns = objectOmit(allColumns, config.exclude ?? []) as $TAvailableColumns
33
39
 
34
- const visibleColumns = computed(() => visibleColumnNames.value.map(name => config[name]!))
40
+ const hiddenColumnIds = ref(new Set()) as Ref<Set<$TAvailableColumnId>>
35
41
 
36
- const visibleColumnsCount = computed(() => visibleColumnNames.value.length)
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
- type GetHeaderCells = THeaderArg extends undefined
39
- ? (arg?: THeaderArg) => TableCellVNode[]
40
- : (arg: THeaderArg) => TableCellVNode[]
49
+ const colspan = computed(() => visibleColumnIds.value.length)
41
50
 
42
- type GetBodyCells = TBodyArg extends undefined
43
- ? (source: TSource, arg?: TBodyArg) => TableCellVNode[]
44
- : (source: TSource, arg: TBodyArg) => TableCellVNode[]
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
- return {
47
- getHeaderCells: ((arg?: THeaderArg) =>
48
- visibleColumns.value.map(column => column.header(arg as THeaderArg))) as GetHeaderCells,
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
- getBodyCells: ((source: TSource, arg?: TBodyArg) =>
51
- visibleColumns.value.map(column => column.body(source, arg as TBodyArg))) as GetBodyCells,
69
+ return () =>
70
+ visibleColumnIds.value.map(columnId => {
71
+ const { renderHead } = availableColumns[columnId]
52
72
 
53
- toggleColumn: (name: TColumnName, forcedValue = !hiddenColumnNames.has(name)) => {
54
- if (forcedValue) {
55
- hiddenColumnNames.add(name)
56
- } else {
57
- hiddenColumnNames.delete(name)
58
- }
59
- },
60
- visibleColumnsCount,
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 * from './apply-extensions'
2
- export * from './define-renderer/define-table-cell-renderer'
3
- export * from './define-renderer/define-table-row-renderer'
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 => defineTree(family.members, member => defineTree(member.animals)))
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/composables/tree/tree-node-definition-base'
2
- import type { TreeNodeDefinition, TreeNodeOptions } from '@core/composables/tree/types'
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(data: TData, options: TreeNodeOptions<TData, TDiscriminator>, children: TChildDefinition[]) {
13
- super(data, options)
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/composables/tree/tree-node-base'
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?.isExpanded === false) {
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 isExpanded() {
63
- return this.context.expandedIds.has(this.id) || this.passesFilterDownwards || this.passesFilterUpwards
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
- expanded: this.isExpanded,
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
- toggleExpand(forcedValue?: boolean, recursive?: boolean) {
105
- const nextExpanded = forcedValue ?? !this.isExpanded
99
+ toggleCollapse(forcedValue?: boolean, recursive?: boolean) {
100
+ const nextCollapsed = forcedValue ?? !this.isCollapsed
106
101
 
107
- if (nextExpanded) {
108
- this.context.expandedIds.add(this.id)
102
+ if (nextCollapsed) {
103
+ this.context.collapsedIds.add(this.id)
109
104
  } else {
110
- this.context.expandedIds.delete(this.id)
105
+ this.context.collapsedIds.delete(this.id)
111
106
  }
112
107
 
113
- const shouldPropagate = recursive ?? !nextExpanded
108
+ const shouldPropagate = recursive ?? nextCollapsed
114
109
 
115
110
  if (shouldPropagate) {
116
111
  this.rawChildren.forEach(child => {
117
112
  if (child.isBranch) {
118
- child.toggleExpand(nextExpanded, recursive)
113
+ child.toggleCollapse(nextCollapsed, recursive)
119
114
  }
120
115
  })
121
116
  }
@@ -1,6 +1,6 @@
1
- import { Branch } from '@core/composables/tree/branch'
2
- import { Leaf } from '@core/composables/tree/leaf'
3
- import type { DefinitionToTreeNode, TreeContext, TreeNode, TreeNodeDefinition } from '@core/composables/tree/types'
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/composables/tree/branch-definition'
2
- import type { Identifiable, Labeled, TreeNodeDefinition, TreeNodeOptions } from '@core/composables/tree/types'
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/composables/tree/leaf-definition'
2
- import type { Identifiable, Labeled, TreeNodeOptions } from '@core/composables/tree/types'
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/composables/tree/branch-definition'
2
- import { LeafDefinition } from '@core/composables/tree/leaf-definition'
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/composables/tree/types'
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/composables/tree/tree-node-definition-base'
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/composables/tree/tree-node-base'
2
- import type { LeafStatuses } from '@core/composables/tree/types'
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?.isExpanded === false) {
16
+ if (this.parent?.isCollapsed === true) {
17
17
  return true
18
18
  }
19
19