@stonecrop/atable 0.31.0 → 0.33.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 (79) hide show
  1. package/dist/assets/index.css +804 -1
  2. package/dist/atable.js +2809 -1944
  3. package/dist/atable.js.map +1 -1
  4. package/dist/src/components/ACell.vue.d.ts +17 -0
  5. package/dist/src/components/ACell.vue.d.ts.map +1 -0
  6. package/dist/src/components/AGanttCell.vue.d.ts +34 -0
  7. package/dist/src/components/AGanttCell.vue.d.ts.map +1 -0
  8. package/dist/src/components/AGanttConnection.vue.d.ts +13 -0
  9. package/dist/src/components/AGanttConnection.vue.d.ts.map +1 -0
  10. package/dist/src/components/ARow.vue.d.ts +2693 -0
  11. package/dist/src/components/ARow.vue.d.ts.map +1 -0
  12. package/dist/src/components/ARowActions.vue.d.ts +16 -0
  13. package/dist/src/components/ARowActions.vue.d.ts.map +1 -0
  14. package/dist/src/components/ATable.vue.d.ts +13358 -0
  15. package/dist/src/components/ATable.vue.d.ts.map +1 -0
  16. package/dist/src/components/ATableColumnFilter.vue.d.ts +11 -0
  17. package/dist/src/components/ATableColumnFilter.vue.d.ts.map +1 -0
  18. package/dist/src/components/ATableHeader.vue.d.ts +20 -0
  19. package/dist/src/components/ATableHeader.vue.d.ts.map +1 -0
  20. package/dist/src/components/ATableLoading.vue.d.ts +14 -0
  21. package/dist/src/components/ATableLoading.vue.d.ts.map +1 -0
  22. package/dist/src/components/ATableLoadingBar.vue.d.ts +14 -0
  23. package/dist/src/components/ATableLoadingBar.vue.d.ts.map +1 -0
  24. package/dist/src/components/ATableModal.vue.d.ts +18 -0
  25. package/dist/src/components/ATableModal.vue.d.ts.map +1 -0
  26. package/dist/src/components/ATablePaginationFooter.vue.d.ts +17 -0
  27. package/dist/src/components/ATablePaginationFooter.vue.d.ts.map +1 -0
  28. package/dist/src/icons/index.d.ts +14 -7
  29. package/dist/src/icons/index.d.ts.map +1 -1
  30. package/dist/{tsdoc-metadata.json → src/tsdoc-metadata.json} +1 -1
  31. package/dist/src/types/index.d.ts.map +1 -1
  32. package/package.json +35 -29
  33. package/dist/atable.d.ts +0 -3560
  34. package/dist/atable.tsbuildinfo +0 -1
  35. package/dist/icons/stonecrop-ui-icon-add.svg +0 -5
  36. package/dist/icons/stonecrop-ui-icon-delete.svg +0 -5
  37. package/dist/icons/stonecrop-ui-icon-duplicate.svg +0 -5
  38. package/dist/icons/stonecrop-ui-icon-insert-above.svg +0 -15
  39. package/dist/icons/stonecrop-ui-icon-insert-below.svg +0 -15
  40. package/dist/icons/stonecrop-ui-icon-move.svg +0 -4
  41. package/dist/icons/stonecrop-ui-icon-open.svg +0 -5
  42. package/dist/src/composables/table-pagination.js +0 -108
  43. package/dist/src/icons/index.js +0 -32
  44. package/dist/src/index.js +0 -33
  45. package/dist/src/linkSearchableText.js +0 -44
  46. package/dist/src/resolveFilterType.js +0 -27
  47. package/dist/src/schemaToColumns.js +0 -59
  48. package/dist/src/stores/table.js +0 -833
  49. package/dist/src/types/index.js +0 -0
  50. package/dist/src/utils.js +0 -39
  51. package/src/components/ACell.vue +0 -410
  52. package/src/components/AGanttCell.vue +0 -638
  53. package/src/components/AGanttConnection.vue +0 -164
  54. package/src/components/ARow.vue +0 -251
  55. package/src/components/ARowActions.vue +0 -407
  56. package/src/components/ATable.vue +0 -538
  57. package/src/components/ATableColumnFilter.vue +0 -216
  58. package/src/components/ATableHeader.vue +0 -141
  59. package/src/components/ATableLoading.vue +0 -86
  60. package/src/components/ATableLoadingBar.vue +0 -81
  61. package/src/components/ATableModal.vue +0 -52
  62. package/src/components/ATablePaginationFooter.vue +0 -100
  63. package/src/composables/table-pagination.ts +0 -172
  64. package/src/icons/index.ts +0 -38
  65. package/src/icons/stonecrop-ui-icon-add.svg +0 -5
  66. package/src/icons/stonecrop-ui-icon-delete.svg +0 -5
  67. package/src/icons/stonecrop-ui-icon-duplicate.svg +0 -5
  68. package/src/icons/stonecrop-ui-icon-insert-above.svg +0 -15
  69. package/src/icons/stonecrop-ui-icon-insert-below.svg +0 -15
  70. package/src/icons/stonecrop-ui-icon-move.svg +0 -4
  71. package/src/icons/stonecrop-ui-icon-open.svg +0 -5
  72. package/src/index.ts +0 -62
  73. package/src/linkSearchableText.ts +0 -42
  74. package/src/resolveFilterType.ts +0 -32
  75. package/src/schemaToColumns.ts +0 -67
  76. package/src/shims-vue.d.ts +0 -10
  77. package/src/stores/table.ts +0 -978
  78. package/src/types/index.ts +0 -794
  79. package/src/utils.ts +0 -40
@@ -1,172 +0,0 @@
1
- import type { GetRecordsOptions, GetRecordsResult } from '@stonecrop/schema'
2
- import { computed, nextTick, ref, toValue, watch, type MaybeRefOrGetter, type Ref } from 'vue'
3
-
4
- import type { TableRow } from '../types'
5
-
6
- /**
7
- * A table row after filter/sort, with its index in the held row list.
8
- * @public
9
- */
10
- export type FilteredTableRow = TableRow & { originalIndex: number }
11
-
12
- /**
13
- * Options for {@link useTablePagination}.
14
- * @public
15
- */
16
- export interface UseTablePaginationOptions {
17
- /** Rows after filter and sort — pagination is a window over this list, not part of filtering. */
18
- rows: MaybeRefOrGetter<FilteredTableRow[]>
19
- /** When set, slice the held rows into windows of this size. Omit to show the whole held list. */
20
- pageSize?: MaybeRefOrGetter<number | undefined>
21
- /** Fetch the next server page. Typed from schema so ATable need not import Stonecrop. */
22
- getRecords?: (options?: GetRecordsOptions) => Promise<GetRecordsResult>
23
- /** When this changes, refetch from offset 0. */
24
- sourceKey?: MaybeRefOrGetter<string | undefined>
25
- }
26
-
27
- /**
28
- * Pagination state and controls returned by {@link useTablePagination}.
29
- * @public
30
- */
31
- export interface TablePagination {
32
- visibleRows: Ref<FilteredTableRow[]>
33
- hasPrev: Ref<boolean>
34
- hasNext: Ref<boolean>
35
- /** Whether the server reported more records beyond what has been fetched. */
36
- hasMore: Ref<boolean>
37
- loading: Ref<boolean>
38
- next: () => Promise<void>
39
- prev: () => void
40
- /** Whether footer chrome should render. */
41
- showFooter: Ref<boolean>
42
- /** Whether another in-memory window exists before asking the server. */
43
- hasLocalNext: Ref<boolean>
44
- /** Rows currently held after filter/sort — useful for a completion summary. */
45
- loadedCount: Ref<number>
46
- /** True once the server reported a further page existed (multi-page fetch). */
47
- hasEverHadMore: Ref<boolean>
48
- }
49
-
50
- /**
51
- * Window rows after filter/sort, and optionally walk {@link @stonecrop/schema#GetRecordsOptions} for the next page.
52
- * Pagination is not a filter — pass already-filtered rows.
53
- * @public
54
- */
55
- export function useTablePagination(options: UseTablePaginationOptions): TablePagination {
56
- const heldRows = computed(() => toValue(options.rows))
57
- const pageSize = computed(() => toValue(options.pageSize))
58
- const sourceKey = computed(() => toValue(options.sourceKey))
59
-
60
- const windowIndex = ref(0)
61
- const loading = ref(false)
62
- const serverHasMore = ref(false)
63
- const hasEverHadMore = ref(false)
64
- const lastFetchOffset = ref(0)
65
- const lastPageLength = ref(0)
66
- const loadedCount = computed(() => heldRows.value.length)
67
-
68
- const effectivePageSize = computed(() => {
69
- const size = pageSize.value
70
- if (size != null && size > 0) {
71
- return size
72
- }
73
- // No pageSize: one window over everything held (server list or full child table).
74
- const count = heldRows.value.length
75
- return count > 0 ? count : 1
76
- })
77
-
78
- const windowCount = computed(() => Math.max(1, Math.ceil(heldRows.value.length / effectivePageSize.value)))
79
-
80
- const visibleRows = computed(() => {
81
- const start = windowIndex.value * effectivePageSize.value
82
- return heldRows.value.slice(start, start + effectivePageSize.value)
83
- })
84
-
85
- const hasLocalNext = computed(() => windowIndex.value < windowCount.value - 1)
86
- const hasPrev = computed(() => windowIndex.value > 0)
87
- const hasNext = computed(() => hasLocalNext.value || (Boolean(options.getRecords) && serverHasMore.value))
88
- const hasMore = computed(() => serverHasMore.value)
89
-
90
- const showFooter = computed(() => {
91
- if (options.getRecords) {
92
- // Keep the footer after the last "Load more" so completion is visible, not silent.
93
- return serverHasMore.value || hasPrev.value || loading.value || (hasEverHadMore.value && !serverHasMore.value)
94
- }
95
- const size = pageSize.value
96
- return size != null && size > 0 && heldRows.value.length > size
97
- })
98
-
99
- const resetWindow = () => {
100
- windowIndex.value = 0
101
- hasEverHadMore.value = false
102
- }
103
-
104
- const fetchFromServer = async (fetchOptions?: GetRecordsOptions) => {
105
- if (!options.getRecords) {
106
- return
107
- }
108
- loading.value = true
109
- try {
110
- const result = await options.getRecords(fetchOptions)
111
- serverHasMore.value = result.hasMore
112
- if (result.hasMore) {
113
- hasEverHadMore.value = true
114
- }
115
- lastFetchOffset.value = fetchOptions?.offset ?? 0
116
- lastPageLength.value = result.data.length
117
- } finally {
118
- loading.value = false
119
- }
120
- }
121
-
122
- watch(
123
- () => sourceKey.value,
124
- () => {
125
- resetWindow()
126
- if (options.getRecords) {
127
- void fetchFromServer()
128
- }
129
- },
130
- { immediate: true }
131
- )
132
-
133
- watch(heldRows, () => {
134
- // Shrinking the held set can leave the window past the end.
135
- if (windowIndex.value >= windowCount.value) {
136
- windowIndex.value = Math.max(0, windowCount.value - 1)
137
- }
138
- })
139
-
140
- const next = async () => {
141
- if (hasLocalNext.value) {
142
- windowIndex.value += 1
143
- return
144
- }
145
- if (options.getRecords && serverHasMore.value) {
146
- await fetchFromServer({ offset: lastFetchOffset.value + lastPageLength.value })
147
- await nextTick()
148
- // Parent/HST grows rows; show the newly appended tail.
149
- windowIndex.value = Math.max(0, windowCount.value - 1)
150
- }
151
- }
152
-
153
- const prev = () => {
154
- if (windowIndex.value > 0) {
155
- windowIndex.value -= 1
156
- }
157
- }
158
-
159
- return {
160
- visibleRows,
161
- hasPrev,
162
- hasNext,
163
- hasMore,
164
- loading,
165
- next,
166
- prev,
167
- showFooter,
168
- hasLocalNext,
169
- loadedCount,
170
- hasEverHadMore,
171
- }
172
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * Icon exports for ATable row actions.
3
- * Icons are exported as raw SVG strings for flexibility in rendering.
4
- * @packageDocumentation
5
- */
6
-
7
- import AddIcon from './stonecrop-ui-icon-add.svg?raw'
8
- import DeleteIcon from './stonecrop-ui-icon-delete.svg?raw'
9
- import DuplicateIcon from './stonecrop-ui-icon-duplicate.svg?raw'
10
- import InsertAboveIcon from './stonecrop-ui-icon-insert-above.svg?raw'
11
- import InsertBelowIcon from './stonecrop-ui-icon-insert-below.svg?raw'
12
- import MoveIcon from './stonecrop-ui-icon-move.svg?raw'
13
- import OpenIcon from './stonecrop-ui-icon-open.svg?raw'
14
-
15
- // Directional move icons are inline (no dedicated SVG asset): simple up/down chevrons.
16
- const MoveUpIcon =
17
- '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M8 13V3.5M4.5 7 8 3.5 11.5 7" stroke-linecap="round" stroke-linejoin="round"/></svg>'
18
- const MoveDownIcon =
19
- '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M8 3v9.5M4.5 9 8 12.5 11.5 9" stroke-linecap="round" stroke-linejoin="round"/></svg>'
20
-
21
- export { AddIcon, DeleteIcon, DuplicateIcon, InsertAboveIcon, InsertBelowIcon, MoveIcon, OpenIcon }
22
-
23
- /**
24
- * Map of action types to their default icons.
25
- *
26
- * @public
27
- */
28
- export const actionIcons: Record<string, string> = {
29
- add: AddIcon,
30
- delete: DeleteIcon,
31
- duplicate: DuplicateIcon,
32
- insertAbove: InsertAboveIcon,
33
- insertBelow: InsertBelowIcon,
34
- move: MoveIcon,
35
- moveUp: MoveUpIcon,
36
- moveDown: MoveDownIcon,
37
- open: OpenIcon,
38
- }
@@ -1,5 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
3
- <path d="M32,64C14.35,64,0,49.65,0,32S14.35,0,32,0s32,14.35,32,32-14.35,32-32,32ZM32,4c-15.44,0-28,12.56-28,28s12.56,28,28,28,28-12.56,28-28S47.44,4,32,4Z" style="fill: #000; stroke-width: 0px;"/>
4
- <polygon points="34 18 30 18 30 30 18 30 18 34 30 34 30 46 34 46 34 34 46 34 46 30 34 30 34 18" style="fill: #000; stroke-width: 0px;"/>
5
- </svg>
@@ -1,5 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
3
- <path d="M32,64C14.35,64,0,49.65,0,32S14.35,0,32,0s32,14.35,32,32-14.35,32-32,32ZM32,4c-15.44,0-28,12.56-28,28s12.56,28,28,28,28-12.56,28-28S47.44,4,32,4Z" style="fill: #000; stroke-width: 0px;"/>
4
- <polygon points="46.84 19.99 44.01 17.16 32 29.17 19.99 17.16 17.16 19.99 29.17 32 17.16 44.01 19.99 46.84 32 34.83 44.01 46.84 46.84 44.01 34.83 32 46.84 19.99" style="fill: #000; stroke-width: 0px;"/>
5
- </svg>
@@ -1,5 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70.67 70.67">
3
- <path d="M68.67,16.67h-14.67V2c0-1.1-.9-2-2-2H2C.9,0,0,.9,0,2v50c0,1.1.9,2,2,2h14.67v14.67c0,1.1.9,2,2,2h50c1.1,0,2-.9,2-2V18.67c0-1.1-.9-2-2-2ZM4,4h46v46H4V4ZM66.67,66.67H20.67v-12.67h31.33c1.1,0,2-.9,2-2v-31.33h12.67v46Z" style="fill: #000; stroke-width: 0px;"/>
4
- <polygon points="41 25 29 25 29 13 25 13 25 25 13 25 13 29 25 29 25 41 29 41 29 29 41 29 41 25" style="fill: #000; stroke-width: 0px;"/>
5
- </svg>
@@ -1,15 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 70.6 61.5">
3
- <path d="M68.6,45.8v13.7H2v-13.7h66.6M70.6,43.8H0v17.7h70.6v-17.7h0Z"/>
4
- <path d="M68.6,24.2v13.7H2v-13.7h66.6M70.6,22.2H0v17.7h70.6v-17.7h0Z"/>
5
- <g>
6
- <polygon points="70.6 2.5 68.6 2.5 68.6 2 68.1 2 68.1 0 70.6 0 70.6 2.5"/>
7
- <path d="M65.3,2h-2.9V0h2.9v2ZM59.6,2h-2.9V0h2.9v2ZM53.9,2h-2.9V0h2.9v2ZM48.2,2h-2.9V0h2.9v2ZM42.4,2h-2.9V0h2.9v2ZM36.7,2h-2.9V0h2.9v2ZM31,2h-2.9V0h2.9v2ZM25.3,2h-2.9V0h2.9v2ZM19.6,2h-2.9V0h2.9v2ZM13.9,2h-2.9V0h2.9v2ZM8.2,2h-2.9V0h2.9v2Z"/>
8
- <polygon points="2 2.5 0 2.5 0 0 2.5 0 2.5 2 2 2 2 2.5"/>
9
- <path d="M2,13.4H0v-2.7h2v2.7ZM2,8H0v-2.7h2v2.7Z"/>
10
- <polygon points="2.5 18.7 0 18.7 0 16.2 2 16.2 2 16.7 2.5 16.7 2.5 18.7"/>
11
- <path d="M65.3,18.7h-2.9v-2h2.9v2ZM59.6,18.7h-2.9v-2h2.9v2ZM53.9,18.7h-2.9v-2h2.9v2ZM48.2,18.7h-2.9v-2h2.9v2ZM42.4,18.7h-2.9v-2h2.9v2ZM36.7,18.7h-2.9v-2h2.9v2ZM31,18.7h-2.9v-2h2.9v2ZM25.3,18.7h-2.9v-2h2.9v2ZM19.6,18.7h-2.9v-2h2.9v2ZM13.9,18.7h-2.9v-2h2.9v2ZM8.2,18.7h-2.9v-2h2.9v2Z"/>
12
- <polygon points="70.6 18.7 68.1 18.7 68.1 16.7 68.6 16.7 68.6 16.2 70.6 16.2 70.6 18.7"/>
13
- <path d="M70.6,13.4h-2v-2.7h2v2.7ZM70.6,8h-2v-2.7h2v2.7Z"/>
14
- </g>
15
- </svg>
@@ -1,15 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 70.6 61.5">
3
- <g>
4
- <polygon points="70.6 45.3 68.6 45.3 68.6 44.8 68.1 44.8 68.1 42.8 70.6 42.8 70.6 45.3"/>
5
- <path d="M65.3,44.8h-2.9v-2h2.9v2ZM59.6,44.8h-2.9v-2h2.9v2ZM53.9,44.8h-2.9v-2h2.9v2ZM48.2,44.8h-2.9v-2h2.9v2ZM42.4,44.8h-2.9v-2h2.9v2ZM36.7,44.8h-2.9v-2h2.9v2ZM31,44.8h-2.9v-2h2.9v2ZM25.3,44.8h-2.9v-2h2.9v2ZM19.6,44.8h-2.9v-2h2.9v2ZM13.9,44.8h-2.9v-2h2.9v2ZM8.2,44.8h-2.9v-2h2.9v2Z"/>
6
- <polygon points="2 45.3 0 45.3 0 42.8 2.5 42.8 2.5 44.8 2 44.8 2 45.3"/>
7
- <path d="M2,56.3H0v-2.7h2v2.7ZM2,50.8H0v-2.7h2v2.7Z"/>
8
- <polygon points="2.5 61.5 0 61.5 0 59 2 59 2 59.5 2.5 59.5 2.5 61.5"/>
9
- <path d="M65.3,61.5h-2.9v-2h2.9v2ZM59.6,61.5h-2.9v-2h2.9v2ZM53.9,61.5h-2.9v-2h2.9v2ZM48.2,61.5h-2.9v-2h2.9v2ZM42.4,61.5h-2.9v-2h2.9v2ZM36.7,61.5h-2.9v-2h2.9v2ZM31,61.5h-2.9v-2h2.9v2ZM25.3,61.5h-2.9v-2h2.9v2ZM19.6,61.5h-2.9v-2h2.9v2ZM13.9,61.5h-2.9v-2h2.9v2ZM8.2,61.5h-2.9v-2h2.9v2Z"/>
10
- <polygon points="70.6 61.5 68.1 61.5 68.1 59.5 68.6 59.5 68.6 59 70.6 59 70.6 61.5"/>
11
- <path d="M70.6,56.3h-2v-2.7h2v2.7ZM70.6,50.8h-2v-2.7h2v2.7Z"/>
12
- </g>
13
- <path d="M68.6,23.7v13.7H2v-13.7h66.6M70.6,21.7H0v17.7h70.6v-17.7h0Z"/>
14
- <path d="M68.6,2v13.7H2V2h66.6M70.6,0H0v17.7h70.6V0h0Z"/>
15
- </svg>
@@ -1,4 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70.67 70.64">
3
- <path d="M70.08,33.9l-9.75-9.75-2.83,2.83,6.33,6.33h-26.51V6.81l6.33,6.33,2.83-2.83L36.75.56c-.75-.75-2.08-.75-2.83,0l-9.75,9.75,2.83,2.83,6.33-6.33v26.5H6.83l6.33-6.33-2.83-2.83L.59,33.9c-.38.38-.59.88-.59,1.41s.21,1.04.59,1.41l9.75,9.75,2.83-2.83-6.33-6.33h26.5v26.51l-6.33-6.33-2.83,2.83,9.75,9.75c.38.38.88.59,1.41.59s1.04-.21,1.41-.59l9.75-9.75-2.83-2.83-6.33,6.33v-26.51h26.51l-6.33,6.33,2.83,2.83,9.75-9.75c.38-.38.59-.88.59-1.41s-.21-1.04-.59-1.41Z" style="fill: #000; stroke-width: 0px;"/>
4
- </svg>
@@ -1,5 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
3
- <path d="M32,64C14.35,64,0,49.65,0,32S14.35,0,32,0s32,14.35,32,32-14.35,32-32,32ZM32,4c-15.44,0-28,12.56-28,28s12.56,28,28,28,28-12.56,28-28S47.44,4,32,4Z" style="fill: #000; stroke-width: 0px;"/>
4
- <polygon points="18,20 18,44 46,32" style="fill: #000; stroke-width: 0px;"/>
5
- </svg>
package/src/index.ts DELETED
@@ -1,62 +0,0 @@
1
- import { App } from 'vue'
2
-
3
- import ACell from './components/ACell.vue'
4
- import AGanttCell from './components/AGanttCell.vue'
5
- import ARow from './components/ARow.vue'
6
- import ARowActions from './components/ARowActions.vue'
7
- import ATable from './components/ATable.vue'
8
- import ATableHeader from './components/ATableHeader.vue'
9
- import ATableLoading from './components/ATableLoading.vue'
10
- import ATableLoadingBar from './components/ATableLoadingBar.vue'
11
- import ATableModal from './components/ATableModal.vue'
12
- import ATablePaginationFooter from './components/ATablePaginationFooter.vue'
13
- export { createTableStore } from './stores/table'
14
- export { useTablePagination } from './composables/table-pagination'
15
- export type { FilteredTableRow, TablePagination, UseTablePaginationOptions } from './composables/table-pagination'
16
- export type { FilterState, FilterStateRecord } from './stores/table'
17
- export type * from './types'
18
- export { schemaToColumns } from './schemaToColumns'
19
-
20
- // Icon exports
21
- export {
22
- AddIcon,
23
- DeleteIcon,
24
- DuplicateIcon,
25
- InsertAboveIcon,
26
- InsertBelowIcon,
27
- MoveIcon,
28
- OpenIcon,
29
- actionIcons,
30
- } from './icons'
31
-
32
- /**
33
- * Install all ATable components
34
- * @param app - Vue app instance
35
- * @public
36
- */
37
- function install(app: App /* options */) {
38
- app.component('ACell', ACell)
39
- app.component('AGanttCell', AGanttCell)
40
- app.component('ARow', ARow)
41
- app.component('ARowActions', ARowActions)
42
- app.component('ATable', ATable)
43
- app.component('ATableHeader', ATableHeader)
44
- app.component('ATableLoading', ATableLoading)
45
- app.component('ATableLoadingBar', ATableLoadingBar)
46
- app.component('ATableModal', ATableModal)
47
- app.component('ATablePaginationFooter', ATablePaginationFooter)
48
- }
49
-
50
- export {
51
- ACell,
52
- AGanttCell,
53
- ARow,
54
- ARowActions,
55
- ATable,
56
- ATableHeader,
57
- ATableLoading,
58
- ATableLoadingBar,
59
- ATableModal,
60
- ATablePaginationFooter,
61
- install,
62
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * Normalize a scalar cell value to a non-empty string, or nothing.
3
- *
4
- * Rejecting objects is what the haystack wants: a nested value has no single textual form, and
5
- * `String()` on one contributes `[object Object]`, which matches a search for "object" and nothing
6
- * a user would actually type.
7
- */
8
- function scalarText(value: unknown): string | undefined {
9
- if (value == null || typeof value === 'object') return undefined
10
- if (typeof value === 'string') return value === '' ? undefined : value
11
- if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {
12
- return String(value)
13
- }
14
- return undefined
15
- }
16
-
17
- /**
18
- * Build the substring-search haystack for a link column cell.
19
- * Server middleware enriches inline FKs to `{ id, displayText }`; search both.
20
- * @public
21
- */
22
- export function linkSearchableText(cellValue: unknown): string {
23
- if (cellValue == null || cellValue === '') return ''
24
-
25
- // `in` rather than an assertion to `Record<string, unknown>`: the assertion claims the value has
26
- // string keys of unknown type, which is narrower than `object` and so is a claim this function
27
- // cannot make about a cell it did not build.
28
- if (typeof cellValue === 'object') {
29
- const parts: string[] = []
30
- if ('id' in cellValue) {
31
- const id = scalarText(cellValue.id)
32
- if (id !== undefined) parts.push(id)
33
- }
34
- if ('displayText' in cellValue) {
35
- const displayText = scalarText(cellValue.displayText)
36
- if (displayText !== undefined) parts.push(displayText)
37
- }
38
- return parts.join(' ')
39
- }
40
-
41
- return scalarText(cellValue) ?? ''
42
- }
@@ -1,32 +0,0 @@
1
- import { componentCategory, type ComponentCategory } from '@stonecrop/schema'
2
-
3
- import type { TableColumn } from './types'
4
-
5
- /** Filter widget type derived from a component's semantic category. */
6
- export type ResolvedFilterType = 'text' | 'select' | 'number' | 'date' | 'dateRange' | 'checkbox' | 'component'
7
-
8
- const CATEGORY_FILTER: Record<ComponentCategory, Exclude<ResolvedFilterType, 'component'>> = {
9
- text: 'text',
10
- number: 'number',
11
- boolean: 'checkbox',
12
- date: 'date',
13
- datetime: 'dateRange',
14
- select: 'select',
15
- code: 'text',
16
- link: 'text',
17
- attach: 'text',
18
- quantity: 'number',
19
- currency: 'number',
20
- }
21
-
22
- /**
23
- * Resolve the filter widget and filter logic type for a column.
24
- * Explicit `filterType` wins; otherwise derive from the component category.
25
- * @public
26
- */
27
- export function resolveFilterType(column: Pick<TableColumn, 'filterType' | 'component'>): ResolvedFilterType {
28
- if (column.filterType) return column.filterType
29
- const category = componentCategory(column.component)
30
- if (category) return CATEGORY_FILTER[category]
31
- return 'text'
32
- }
@@ -1,67 +0,0 @@
1
- import { componentCategory } from '@stonecrop/schema'
2
- import type { ColumnSchema } from '@stonecrop/schema'
3
-
4
- import type { TableColumn } from './types'
5
- import { formatCurrency, formatQuantity } from './utils'
6
-
7
- /**
8
- * Convert an array of doctype field descriptors into ATable column definitions.
9
- *
10
- * Fields are excluded when:
11
- * - `hidden: true` — field should not be visible in any view
12
- * - no `component` — non-scalar entry (nested table or fieldset), no column equivalent
13
- *
14
- * `fieldname` is renamed to `name`; `hidden` is stripped. All other `ColumnSchema` properties
15
- * spread through automatically.
16
- *
17
- * For link fields (those carrying `doctype`) without an explicit `cellComponent`:
18
- * - `linkDoctype` is set from the field's `doctype` property (used by ACell's async resolver).
19
- * - A synchronous `format` function is added (unless the field already has one) that handles
20
- * both bare ID strings and pre-resolved `{ id, displayText }` objects.
21
- *
22
- * For quantity fields — those whose `component` carries the `'quantity'` category — without an
23
- * explicit `format`, a synchronous `format` is added that renders the `{ qty, uom }` value (see
24
- * `QuantityValue` in `@stonecrop/aform`) as `"<qty> <uom>"`.
25
- *
26
- * For currency fields — those whose `component` carries the `'currency'` category — without an
27
- * explicit `format`, a synchronous `format` is added that renders the `{ amount, currency }` value
28
- * (see `CurrencyValue` in `@stonecrop/aform`) as `"<amount> <currency>"`.
29
- *
30
- * @public
31
- */
32
- export function schemaToColumns(schema: ColumnSchema[]): TableColumn[] {
33
- return schema
34
- .filter(f => !f.hidden && f.component)
35
- .map(({ fieldname, hidden: _hidden, ...rest }) => {
36
- const col: TableColumn = Object.assign({ name: fieldname }, rest)
37
-
38
- // Link fields: store the linked doctype for async resolution by ACell, and add a sync
39
- // format that handles pre-resolved AFormLinkValue objects.
40
- if (rest.doctype && !rest.cellComponent) {
41
- col.linkDoctype = rest.doctype
42
-
43
- if (!rest.format) {
44
- col.format = (v: any): string => {
45
- if (v === null || v === undefined) return ''
46
- if (typeof v === 'object') {
47
- const display: unknown = v.displayText ?? v.id ?? ''
48
- return typeof display === 'string' || typeof display === 'number' ? String(display) : ''
49
- }
50
- return String(v)
51
- }
52
- }
53
- }
54
-
55
- // Quantity fields: render the composite { qty, uom } value as "<qty> <uom>".
56
- if (componentCategory(rest.component) === 'quantity' && !rest.format) {
57
- col.format = formatQuantity
58
- }
59
-
60
- // Currency fields: render the composite { amount, currency } value as "<amount> <currency>".
61
- if (componentCategory(rest.component) === 'currency' && !rest.format) {
62
- col.format = formatCurrency
63
- }
64
-
65
- return col
66
- })
67
- }
@@ -1,10 +0,0 @@
1
- declare module '*.vue' {
2
- import { ComponentOptions } from 'vue'
3
- const Component: ComponentOptions
4
- export default Component
5
- }
6
-
7
- declare module '*.svg?raw' {
8
- const content: string
9
- export default content
10
- }