@stonecrop/atable 0.30.0 → 0.32.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,407 +0,0 @@
1
- <template>
2
- <td
3
- ref="actionsCell"
4
- class="atable-row-actions"
5
- :class="{ 'sticky-column': position === 'before-index', 'dropdown-active': dropdownOpen }">
6
- <!-- Dropdown mode -->
7
- <div v-if="showDropdown" class="row-actions-dropdown">
8
- <button
9
- ref="toggleButton"
10
- type="button"
11
- class="row-actions-toggle"
12
- :aria-expanded="dropdownOpen"
13
- aria-haspopup="true"
14
- @click.stop="toggleDropdown">
15
- <span class="dropdown-icon">⋮</span>
16
- </button>
17
- <div
18
- v-show="dropdownOpen"
19
- class="row-actions-menu"
20
- :class="{ 'menu-flipped': dropdownFlipped }"
21
- :style="menuStyle"
22
- role="menu">
23
- <button
24
- v-for="action in enabledActions"
25
- :key="action.type"
26
- type="button"
27
- class="row-action-menu-item"
28
- role="menuitem"
29
- :disabled="action.disabled"
30
- @click.stop="executeAction(action.type, $event)">
31
- <span class="action-icon" v-html="action.icon" />
32
- <span class="action-label">{{ action.label }}</span>
33
- </button>
34
- </div>
35
- </div>
36
-
37
- <!-- Icon mode -->
38
- <div v-else class="row-actions-icons">
39
- <button
40
- v-for="action in enabledActions"
41
- :key="action.type"
42
- type="button"
43
- class="row-action-btn"
44
- :title="action.label"
45
- :aria-label="action.label"
46
- :disabled="action.disabled"
47
- @click.stop="executeAction(action.type, $event)">
48
- <span class="action-icon" v-html="action.icon" />
49
- </button>
50
- </div>
51
- </td>
52
- </template>
53
-
54
- <script setup lang="ts">
55
- import { useResizeObserver, onClickOutside } from '@vueuse/core'
56
- import { computed, ref, useTemplateRef } from 'vue'
57
-
58
- import { actionIcons } from '../icons'
59
- import { createTableStore } from '../stores/table'
60
- import type { RowActionsConfig, RowActionType } from '../types'
61
-
62
- const props = defineProps<{
63
- rowIndex: number
64
- store: ReturnType<typeof createTableStore>
65
- config: RowActionsConfig
66
- position?: 'before-index' | 'after-index' | 'end'
67
- }>()
68
-
69
- const emit = defineEmits<{
70
- action: [type: RowActionType, rowIndex: number, event?: MouseEvent]
71
- }>()
72
-
73
- const actionsCellRef = useTemplateRef<HTMLTableCellElement>('actionsCell')
74
- const toggleButtonRef = useTemplateRef<HTMLButtonElement>('toggleButton')
75
- const cellWidth = ref(0)
76
- const dropdownOpen = ref(false)
77
- const dropdownFlipped = ref(false)
78
- const menuPosition = ref({ top: 0, left: 0 })
79
-
80
- // Default labels for actions
81
- const defaultLabels: Record<RowActionType, string> = {
82
- add: 'Add Record',
83
- delete: 'Delete Record',
84
- duplicate: 'Duplicate Record',
85
- insertAbove: 'Insert Above',
86
- insertBelow: 'Insert Below',
87
- move: 'Move Record',
88
- moveUp: 'Move Up',
89
- moveDown: 'Move Down',
90
- open: 'Open Record',
91
- }
92
-
93
- // Determine which actions are enabled
94
- const enabledActions = computed(() => {
95
- const actions: Array<{ type: RowActionType; label: string; icon: string; disabled: boolean }> = []
96
- const configActions = props.config.actions || {}
97
-
98
- const actionTypes: RowActionType[] = [
99
- 'open',
100
- 'moveUp',
101
- 'moveDown',
102
- 'duplicate',
103
- 'insertAbove',
104
- 'insertBelow',
105
- 'add',
106
- 'delete',
107
- 'move',
108
- ]
109
-
110
- for (const type of actionTypes) {
111
- const actionConfig = configActions[type]
112
-
113
- // Skip if explicitly disabled
114
- if (actionConfig === false) continue
115
-
116
- // Skip if not configured and we're being explicit
117
- if (actionConfig === undefined) continue
118
-
119
- let enabled = true
120
- let label = defaultLabels[type]
121
- let icon = actionIcons[type]
122
- let disabled = false
123
-
124
- if (typeof actionConfig === 'object') {
125
- enabled = actionConfig.enabled !== false
126
- label = actionConfig.label || label
127
- icon = actionConfig.icon || icon
128
- // Per-row predicate; reading store state here keeps this computed reactive to row changes.
129
- if (actionConfig.disabled) disabled = actionConfig.disabled(props.rowIndex, props.store)
130
- }
131
-
132
- if (enabled) {
133
- actions.push({ type, label, icon, disabled })
134
- }
135
- }
136
-
137
- return actions
138
- })
139
-
140
- // Determine if we should show dropdown mode
141
- const showDropdown = computed(() => {
142
- if (props.config.forceDropdown) return true
143
-
144
- const threshold = props.config.dropdownThreshold ?? 150
145
- if (threshold === 0) return false
146
-
147
- return cellWidth.value > 0 && cellWidth.value < threshold
148
- })
149
-
150
- // Compute menu style for fixed positioning
151
- const menuStyle = computed(() => {
152
- if (!dropdownOpen.value) return {}
153
-
154
- if (dropdownFlipped.value) {
155
- return {
156
- position: 'fixed' as const,
157
- bottom: `${window.innerHeight - menuPosition.value.top}px`,
158
- left: `${menuPosition.value.left}px`,
159
- top: 'auto',
160
- }
161
- }
162
- return {
163
- position: 'fixed' as const,
164
- top: `${menuPosition.value.top}px`,
165
- left: `${menuPosition.value.left}px`,
166
- }
167
- })
168
-
169
- // Track cell width for responsive behavior
170
- useResizeObserver(actionsCellRef, entries => {
171
- const entry = entries[0]
172
- if (entry) {
173
- cellWidth.value = entry.contentRect.width
174
- }
175
- })
176
-
177
- // Toggle dropdown menu
178
- const toggleDropdown = () => {
179
- if (!dropdownOpen.value) {
180
- // Opening - check if we need to flip
181
- checkDropdownPosition()
182
- }
183
- dropdownOpen.value = !dropdownOpen.value
184
- }
185
-
186
- // Check if dropdown should flip upward and calculate position
187
- const checkDropdownPosition = () => {
188
- if (!toggleButtonRef.value) return
189
-
190
- const buttonRect = toggleButtonRef.value.getBoundingClientRect()
191
- const viewportHeight = window.innerHeight
192
- const viewportWidth = window.innerWidth
193
- const estimatedMenuHeight = enabledActions.value.length * 40 + 16 // ~40px per item + padding
194
- const estimatedMenuWidth = 160 // matches min-width: 10rem
195
-
196
- // Check if menu would extend beyond viewport bottom
197
- const spaceBelow = viewportHeight - buttonRect.bottom
198
- const spaceAbove = buttonRect.top
199
-
200
- // Flip if not enough space below but enough space above
201
- dropdownFlipped.value = spaceBelow < estimatedMenuHeight && spaceAbove > estimatedMenuHeight
202
-
203
- // Horizontal: anchor the menu's left edge to the button, but right-align it to the button when
204
- // it would overflow the viewport's right edge (e.g. an end-positioned actions column).
205
- let left = buttonRect.left
206
- if (left + estimatedMenuWidth > viewportWidth) {
207
- left = Math.max(0, buttonRect.right - estimatedMenuWidth)
208
- }
209
-
210
- // Calculate fixed position
211
- menuPosition.value = {
212
- top: dropdownFlipped.value ? buttonRect.top : buttonRect.bottom,
213
- left,
214
- }
215
- }
216
-
217
- onClickOutside(actionsCellRef, () => {
218
- dropdownOpen.value = false
219
- })
220
-
221
- // Execute an action
222
- const executeAction = (actionType: RowActionType, event?: MouseEvent) => {
223
- dropdownOpen.value = false
224
-
225
- // Check for custom handler
226
- const actionConfig = props.config.actions?.[actionType]
227
- if (typeof actionConfig === 'object' && actionConfig.handler) {
228
- const result = actionConfig.handler(props.rowIndex, props.store)
229
- if (result === false) {
230
- // Handler returned false, don't proceed with default behavior
231
- return
232
- }
233
- }
234
-
235
- // Emit the action event for parent to handle
236
- emit('action', actionType, props.rowIndex, event)
237
- }
238
- </script>
239
-
240
- <style>
241
- .atable-row-actions {
242
- width: 2rem;
243
- min-width: 2rem;
244
- padding: 0 0.25rem;
245
- vertical-align: middle;
246
- white-space: nowrap;
247
- border-top: 1px solid var(--sc-row-border-color);
248
- background: white;
249
- user-select: none;
250
- position: relative;
251
- }
252
-
253
- .atable-row-actions.dropdown-active {
254
- z-index: 101;
255
- }
256
-
257
- .row-actions-icons {
258
- display: flex;
259
- gap: 0.25rem;
260
- align-items: center;
261
- justify-content: center;
262
- }
263
-
264
- .row-action-btn {
265
- display: inline-flex;
266
- align-items: center;
267
- justify-content: center;
268
- width: 1.5rem;
269
- height: 1.5rem;
270
- padding: 0.125rem;
271
- border: none;
272
- background: transparent;
273
- cursor: pointer;
274
- border-radius: 0.25rem;
275
- transition: background-color 0.15s ease;
276
- }
277
-
278
- .row-action-btn:hover {
279
- background-color: var(--sc-gray-10);
280
- }
281
-
282
- .row-action-btn:focus {
283
- outline: 2px solid var(--sc-focus-cell-outline);
284
- outline-offset: 1px;
285
- }
286
-
287
- .row-action-btn .action-icon {
288
- display: flex;
289
- align-items: center;
290
- justify-content: center;
291
- width: 1rem;
292
- height: 1rem;
293
- }
294
-
295
- .row-action-btn .action-icon :deep(svg) {
296
- width: 100%;
297
- height: 100%;
298
- }
299
-
300
- /* Dropdown mode styles */
301
- .row-actions-dropdown {
302
- position: relative;
303
- display: inline-block;
304
- }
305
- .row-actions-dropdown:has(button:focus) {
306
- outline: 2px solid var(--sc-focus-cell-outline);
307
- outline-offset: -2px;
308
- }
309
-
310
- .row-actions-toggle {
311
- display: inline-flex;
312
- align-items: center;
313
- justify-content: center;
314
- width: 1.5rem;
315
- height: 1.5rem;
316
- padding: 0;
317
- border: none;
318
- background: transparent;
319
- cursor: pointer;
320
- border-radius: 0.25rem;
321
- font-size: 1rem;
322
- font-weight: bold;
323
- transition: background-color 0.15s ease;
324
- }
325
-
326
- .row-actions-toggle:hover {
327
- background-color: var(--sc-gray-10);
328
- }
329
-
330
- .row-actions-toggle:focus {
331
- /* outline: 2px solid var(--sc-focus-cell-outline);
332
- outline-offset: 1px; */
333
- }
334
-
335
- .dropdown-icon {
336
- line-height: 1;
337
- }
338
-
339
- .row-actions-menu {
340
- position: fixed;
341
- z-index: 100;
342
- min-width: 10rem;
343
- padding: 0.25rem 0;
344
- background: white;
345
- border: 1px solid var(--sc-row-border-color);
346
- border-left: 4px solid var(--sc-row-border-color);
347
- border-radius: 0;
348
- }
349
-
350
- .row-actions-menu.menu-flipped {
351
- box-shadow:
352
- 0 -4px 6px -1px rgb(0 0 0 / 0.1),
353
- 0 -2px 4px -2px rgb(0 0 0 / 0.1);
354
- }
355
-
356
- .row-action-menu-item {
357
- display: flex;
358
- align-items: center;
359
- gap: 0.5rem;
360
- width: 100%;
361
- padding: 0.5rem 0.75rem;
362
- border: none;
363
- background: transparent;
364
- cursor: pointer;
365
- text-align: left;
366
- font-size: 0.875rem;
367
- transition: background-color 0.15s ease;
368
- }
369
-
370
- .row-action-menu-item:hover {
371
- background-color: var(--sc-gray-10);
372
- }
373
-
374
- .row-action-menu-item:focus {
375
- outline: none;
376
- background-color: var(--sc-gray-10);
377
- }
378
-
379
- .row-action-menu-item:disabled,
380
- .row-action-btn:disabled {
381
- opacity: 0.4;
382
- cursor: not-allowed;
383
- }
384
-
385
- .row-action-menu-item:disabled:hover,
386
- .row-action-btn:disabled:hover {
387
- background-color: transparent;
388
- }
389
-
390
- .row-action-menu-item .action-icon {
391
- display: flex;
392
- align-items: center;
393
- justify-content: center;
394
- width: 1rem;
395
- height: 1rem;
396
- flex-shrink: 0;
397
- }
398
-
399
- .row-action-menu-item .action-icon :deep(svg) {
400
- width: 100%;
401
- height: 100%;
402
- }
403
-
404
- .row-action-menu-item .action-label {
405
- flex: 1;
406
- }
407
- </style>