@xy-planning-network/trees 0.15.5-dev-1 → 0.16.0-dev-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xy-planning-network/trees",
3
- "version": "0.15.5-dev-1",
3
+ "version": "0.16.0-dev-1",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -435,7 +435,7 @@ onBeforeUnmount(() => {
435
435
  <div class="min-w-0 flex-1">
436
436
  <template v-if="item.kind === 'uploaded'">
437
437
  <span class="text-sm text-gray-800 [overflow-wrap:anywhere]">
438
- {{ item.file.filename }}
438
+ {{ item.file.name }}
439
439
  </span>
440
440
  <p class="mt-0.5 text-xs text-gray-600">Uploaded</p>
441
441
  </template>
@@ -468,7 +468,7 @@ onBeforeUnmount(() => {
468
468
  :href="item.file.url"
469
469
  target="_blank"
470
470
  rel="noopener noreferrer"
471
- :aria-label="`Open ${item.file.filename} in a new window`"
471
+ :aria-label="`Open ${item.file.name} in a new window`"
472
472
  >
473
473
  <ArrowTopRightOnSquareIcon class="h-5 w-5" aria-hidden="true" />
474
474
  </a>
@@ -493,9 +493,7 @@ onBeforeUnmount(() => {
493
493
  (item.kind === 'pending' && item.upload.status === 'uploading')
494
494
  "
495
495
  :aria-label="`Remove ${
496
- item.kind === 'uploaded'
497
- ? item.file.filename
498
- : item.upload.file.name
496
+ item.kind === 'uploaded' ? item.file.name : item.upload.file.name
499
497
  }`"
500
498
  @click="
501
499
  item.kind === 'uploaded'
@@ -1,9 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { useTable } from "@/composables/useTable"
3
- import { useBulkActions } from "@/composables/useBulkActions"
4
3
  import type {
5
4
  TableActions,
6
- TableBulkActions,
7
5
  TableColumns,
8
6
  TableRowsData,
9
7
  } from "@/composables/table"
@@ -13,44 +11,19 @@ import { toRef } from "vue"
13
11
  const props = withDefaults(
14
12
  defineProps<{
15
13
  tableActions?: TableActions<any>
16
- tableBulkActions?: TableBulkActions<any>
17
14
  tableColumns: TableColumns<any>
18
15
  tableData: TableRowsData
19
16
  }>(),
20
17
  {
21
18
  tableActions: () => ({ type: "dropdown", actions: [] }),
22
- tableBulkActions: () => ({ actions: [] }),
23
19
  }
24
20
  )
25
21
 
26
- const selected = defineModel<number[]>("selected", {
27
- required: false,
28
- default: [],
29
- })
30
-
31
- const {
32
- bulkActions,
33
- bulkSelectChecked,
34
- bulkSelectIndeterminate,
35
- bulkSelectOnChange,
36
- hasBulkActions,
37
- publicMethods,
38
- selectable,
39
- selectedOnPage,
40
- } = useBulkActions(
41
- toRef(props, "tableData"),
42
- toRef(props, "tableBulkActions"),
43
- selected
44
- )
45
-
46
22
  const { columns, hasActions, isEmptyCellValue, rows } = useTable(
47
23
  toRef(props, "tableData"),
48
24
  toRef(props, "tableColumns"),
49
- toRef(props, "tableActions"),
50
- publicMethods
25
+ toRef(props, "tableActions")
51
26
  )
52
-
53
- defineExpose(publicMethods)
54
27
  </script>
55
28
  <template>
56
29
  <div class="flex flex-col">
@@ -62,25 +35,6 @@ defineExpose(publicMethods)
62
35
  <table class="min-w-full divide-y divide-gray-200">
63
36
  <thead class="bg-gray-100">
64
37
  <tr>
65
- <th
66
- v-if="hasBulkActions"
67
- scope="col"
68
- class="pl-6 w-4 leading-none"
69
- >
70
- <input
71
- :class="[
72
- 'h-4 w-4 rounded cursor-pointer',
73
- 'disabled:bg-gray-100 disabled:border-gray-200 disabled:cursor-not-allowed disabled:opacity-100',
74
- 'checked:disabled:bg-xy-blue checked:disabled:border-xy-blue checked:disabled:opacity-50',
75
- 'border-gray-300 focus:ring-xy-blue-500',
76
- ]"
77
- :checked="bulkSelectChecked"
78
- :indeterminate="bulkSelectIndeterminate"
79
- type="checkbox"
80
- @change="bulkSelectOnChange"
81
- />
82
- </th>
83
-
84
38
  <th
85
39
  v-for="(col, idx) in columns"
86
40
  :key="idx"
@@ -96,23 +50,6 @@ defineExpose(publicMethods)
96
50
  class="px-6 py-3 text-xs font-medium tracking-wider text-gray-900 uppercase leading-4"
97
51
  />
98
52
  </tr>
99
-
100
- <tr v-if="hasBulkActions && selected.length > 0">
101
- <td colspan="100%" class="px-6 py-2.5 border-t bg-neutral-50">
102
- <div class="flex items-center gap-x-3">
103
- <div class="text-sm shrink-0">
104
- Selected
105
- <span class="font-medium">{{
106
- selectedOnPage.length
107
- }}</span>
108
- of
109
- <span class="font-medium">{{ selectable.length }}</span>
110
- </div>
111
-
112
- <ActionsButtonGroup :actions="bulkActions" />
113
- </div>
114
- </td>
115
- </tr>
116
53
  </thead>
117
54
  <tbody class="bg-white">
118
55
  <tr
@@ -120,21 +57,6 @@ defineExpose(publicMethods)
120
57
  :key="rowIdx"
121
58
  class="even:bg-gray-50"
122
59
  >
123
- <td v-if="hasBulkActions" class="pl-6 w-4 leading-none">
124
- <input
125
- v-model="selected"
126
- :class="[
127
- 'h-4 w-4 rounded cursor-pointer',
128
- 'disabled:bg-gray-100 disabled:border-gray-200 disabled:cursor-not-allowed disabled:opacity-100',
129
- 'checked:disabled:bg-xy-blue checked:disabled:border-xy-blue checked:disabled:opacity-50',
130
- 'border-gray-300 focus:ring-xy-blue-500',
131
- ]"
132
- :disabled="!selectable.includes(row.rowData?.id)"
133
- type="checkbox"
134
- :value="row.rowData?.id"
135
- />
136
- </td>
137
-
138
60
  <template v-for="(cell, cellIdx) in row.cells" :key="cellIdx">
139
61
  <component
140
62
  :is="'td'"
@@ -167,11 +89,7 @@ defineExpose(publicMethods)
167
89
 
168
90
  <tr v-if="rows.length === 0">
169
91
  <td
170
- :colspan="
171
- columns.length +
172
- (hasActions ? 1 : 0) +
173
- (hasBulkActions ? 1 : 0)
174
- "
92
+ :colspan="columns.length + (hasActions ? 1 : 0)"
175
93
  class="px-6 py-4 text-sm text-gray-700 whitespace-nowrap leading-5"
176
94
  >
177
95
  No items were found!
@@ -8,6 +8,7 @@ import {
8
8
  import DateRangePicker from "../forms/DateRangePicker.vue"
9
9
  import BaseAPI from "../../api/base"
10
10
  import type {
11
+ DynamicTableAPI,
11
12
  DynamicTableOptions,
12
13
  TableActions,
13
14
  TableBulkActions,
@@ -18,7 +19,6 @@ import { useAppFlasher } from "@/composables/useFlashes"
18
19
  import { TrailsRespPaged } from "@/api/client"
19
20
  import { DateRange, DateRangeProps } from "@/composables/date"
20
21
  import { useTable } from "@/composables/useTable"
21
- import { useBulkActions } from "@/composables/useBulkActions"
22
22
 
23
23
  const props = withDefaults(
24
24
  defineProps<{
@@ -141,25 +141,100 @@ const hasContent = computed((): boolean => {
141
141
  return rows.value.length ? true : false
142
142
  })
143
143
 
144
+ const clearSelections = () => {
145
+ selected.value = []
146
+ }
147
+
144
148
  const selected = defineModel<number[]>("selected", {
145
149
  required: false,
146
150
  default: [],
147
151
  })
148
152
 
149
- const {
150
- bulkActions,
151
- bulkSelectChecked,
152
- bulkSelectIndeterminate,
153
- bulkSelectOnChange,
154
- clearSelections,
155
- hasBulkActions,
156
- publicMethods,
157
- selectable,
158
- selectedOnPage,
159
- } = useBulkActions(tableData, toRef(props, "tableBulkActions"), selected, {
153
+ const selectedData = computed((): TableRowData[] => {
154
+ return tableData.value.filter((data) => {
155
+ return selected.value.includes(data?.id)
156
+ })
157
+ })
158
+
159
+ const selectedOnPage = computed(() => {
160
+ return selected.value.filter((id) => {
161
+ return selectable.value.includes(id)
162
+ })
163
+ })
164
+
165
+ const bulkActions = computed(() => {
166
+ return props.tableBulkActions.actions
167
+ .filter((action) => {
168
+ return action.show ?? true
169
+ })
170
+ .map((action) => {
171
+ return {
172
+ ...action,
173
+ disabled: selected.value.length === 0 || action.disabled,
174
+ onClick: (e?: Event) =>
175
+ action.onClick.apply(undefined, [
176
+ selected.value,
177
+ selectedData.value,
178
+ publicMethods,
179
+ e,
180
+ ]),
181
+ }
182
+ })
183
+ })
184
+
185
+ const hasBulkActions = computed(() => bulkActions.value.length > 0)
186
+
187
+ const selectable = computed(() => {
188
+ return tableData.value
189
+ .filter((row) => {
190
+ // NOTE(spk): table data must have an "id" key for bulk actions.
191
+ if (row.id === undefined) {
192
+ return false
193
+ }
194
+
195
+ if (props.tableBulkActions.isSelectable === undefined) {
196
+ return true
197
+ }
198
+
199
+ if (props.tableBulkActions.isSelectable(row)) {
200
+ return true
201
+ }
202
+
203
+ return false
204
+ })
205
+ .map((d) => d["id"])
206
+ })
207
+
208
+ const bulkSelectChecked = computed(
209
+ () =>
210
+ selectedOnPage.value.length > 0 &&
211
+ selectedOnPage.value.length === selectable.value.length
212
+ )
213
+
214
+ const bulkSelectIndeterminate = computed(
215
+ () =>
216
+ selectedOnPage.value.length > 0 &&
217
+ selectedOnPage.value.length < selectable.value.length
218
+ )
219
+
220
+ const bulkSelectOnChange = (e: Event) => {
221
+ const isChecked = (e.target as HTMLInputElement).checked
222
+
223
+ // set all records on current page to selection
224
+ if (isChecked) {
225
+ selected.value = selectable.value.map((id) => id)
226
+ return
227
+ }
228
+
229
+ clearSelections()
230
+ }
231
+
232
+ const publicMethods: DynamicTableAPI = {
233
+ clearSelection: clearSelections,
234
+ selectedData: selectedData,
160
235
  refresh: loadAndRender,
161
236
  reset: reloadTable,
162
- })
237
+ }
163
238
 
164
239
  const { columns, hasActions, isEmptyCellValue, rows } = useTable(
165
240
  tableData,
@@ -414,9 +489,7 @@ loadAndRender()
414
489
 
415
490
  <tr v-if="!hasContent">
416
491
  <td
417
- :colspan="
418
- columns.length + (hasActions ? 1 : 0) + (hasBulkActions ? 1 : 0)
419
- "
492
+ :colspan="columns.length + (hasActions ? 1 : 0)"
420
493
  class="px-6 py-4 text-sm text-gray-700 whitespace-nowrap leading-5"
421
494
  >
422
495
  No items were found!
@@ -50,7 +50,7 @@ export interface DateTimeInput extends Input {
50
50
  */
51
51
  export interface UploadedFile {
52
52
  id: number;
53
- filename: string;
53
+ name: string;
54
54
  url?: string;
55
55
  }
56
56
  export type FileUploadValue = UploadedFile | UploadedFile[] | null;
@@ -1,7 +1,6 @@
1
1
  import { Ref } from "vue";
2
2
  import { TableColumns, TableRowsData, TableActions, DynamicTableAPI } from "./table";
3
3
  import { ActionItemButton, ActionItemLink } from "../entry";
4
- export declare const tableAPIStub: DynamicTableAPI;
5
4
  export declare const useTable: (rowData: TableRowsData | Ref<TableRowsData>, cols: TableColumns | Ref<TableColumns>, acts: TableActions | Ref<TableActions>, exposedAPI?: DynamicTableAPI) => {
6
5
  columns: import("vue").ComputedRef<{
7
6
  alignment: string;
@@ -1,24 +1,10 @@
1
- import type { TableActions, TableBulkActions, TableColumns, TableRowsData } from "../../composables/table";
1
+ import type { TableActions, TableColumns, TableRowsData } from "../../composables/table";
2
2
  type __VLS_Props = {
3
3
  tableActions?: TableActions<any>;
4
- tableBulkActions?: TableBulkActions<any>;
5
4
  tableColumns: TableColumns<any>;
6
5
  tableData: TableRowsData;
7
6
  };
8
- type __VLS_PublicProps = {
9
- "selected"?: number[];
10
- } & __VLS_Props;
11
- declare const _default: import("vue").DefineComponent<__VLS_PublicProps, {
12
- clearSelection: () => void;
13
- refresh: () => void;
14
- reset: () => void;
15
- selectedData: import("vue").ComputedRef<import("../../composables/table").TableRowData[]>;
16
- }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
17
- "update:selected": (value: number[]) => any;
18
- }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
19
- "onUpdate:selected"?: ((value: number[]) => any) | undefined;
20
- }>, {
7
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
21
8
  tableActions: TableActions<any>;
22
- tableBulkActions: TableBulkActions<any>;
23
9
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, HTMLDivElement>;
24
10
  export default _default;
@@ -1,25 +0,0 @@
1
- import { type Ref } from "vue";
2
- import type { DynamicTableAPI, TableBulkActions, TableRowData } from "./table";
3
- interface UseBulkActionsOptions {
4
- refresh?: () => void;
5
- reset?: () => void;
6
- }
7
- export declare const useBulkActions: <T extends TableRowData>(tableData: Ref<T[]>, tableBulkActions: Ref<TableBulkActions<T>>, selected: Ref<number[]>, options?: UseBulkActionsOptions) => {
8
- bulkActions: import("vue").ComputedRef<{
9
- disabled: boolean | undefined;
10
- onClick: (e?: Event) => void;
11
- label: string;
12
- icon?: import("vue").RenderFunction | import("vue").FunctionalComponent<{}, {}, any, {}> | undefined;
13
- show?: boolean | undefined;
14
- }[]>;
15
- bulkSelectChecked: import("vue").ComputedRef<boolean>;
16
- bulkSelectIndeterminate: import("vue").ComputedRef<boolean>;
17
- bulkSelectOnChange: (e: Event) => void;
18
- clearSelections: () => void;
19
- hasBulkActions: import("vue").ComputedRef<boolean>;
20
- publicMethods: DynamicTableAPI<T>;
21
- selectable: import("vue").ComputedRef<any[]>;
22
- selectedData: import("vue").ComputedRef<T[]>;
23
- selectedOnPage: import("vue").ComputedRef<number[]>;
24
- };
25
- export {};