@stonecrop/atable 0.2.32 → 0.2.34
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/dist/atable/src/tsdoc-metadata.json +1 -1
- package/dist/atable.js +591 -605
- package/dist/atable.js.map +1 -1
- package/dist/atable.umd.cjs +1 -1
- package/dist/atable.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +8 -8
- package/src/components/ACell.vue +47 -47
- package/src/components/AExpansionRow.vue +24 -23
- package/src/components/ARow.vue +23 -27
- package/src/components/ATable.vue +18 -17
- package/src/components/ATableHeader.vue +3 -7
- package/src/components/ATableModal.vue +3 -3
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@import"https://fonts.googleapis.com/css2?family=Arimo:ital,wght@0,400..700;1,400..700&display=swap";.list-index{color:var(--header-text-color);font-weight:700;padding-left:var(--atable-row-padding);padding-right:1em;text-align:center;-webkit-user-select:none;user-select:none;width:var(--
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=Arimo:ital,wght@0,400..700;1,400..700&display=swap";.list-index{color:var(--header-text-color);font-weight:700;padding-left:var(--atable-row-padding);padding-right:1em;text-align:center;-webkit-user-select:none;user-select:none;width:var(--20b4541e);max-width:var(--20b4541e)}.atable #header-index{width:var(--20b4541e);max-width:var(--20b4541e)}.list-index{color:var(--header-text-color);font-weight:700;padding-left:var(--atable-row-padding);padding-right:1em;text-align:center;-webkit-user-select:none;user-select:none;width:var(--d266282a);max-width:var(--d266282a)}.atable #header-index{width:var(--d266282a);max-width:var(--d266282a)}.list-index{color:var(--header-text-color);font-weight:700;padding-left:var(--atable-row-padding);padding-right:1em;text-align:center;-webkit-user-select:none;user-select:none;width:var(--aa18a430);max-width:var(--aa18a430)}.atable #header-index{width:var(--aa18a430);max-width:var(--aa18a430)}.list-index{color:var(--header-text-color);font-weight:700;padding-left:var(--atable-row-padding);padding-right:1em;text-align:center;-webkit-user-select:none;user-select:none;width:var(--0fa106da);max-width:var(--0fa106da)}.atable #header-index{width:var(--0fa106da);max-width:var(--0fa106da)}.list-index{color:var(--header-text-color);font-weight:700;padding-left:var(--atable-row-padding);padding-right:1em;text-align:center;-webkit-user-select:none;user-select:none;width:var(--59561aac);max-width:var(--59561aac)}.atable #header-index{width:var(--59561aac);max-width:var(--59561aac)}:root{--primary-color: #0098c9;--primary-text-color: #ffffff;--brand-color: #202a44;--gray-5: #f2f2f2;--gray-10: #e6e6e6;--gray-20: #cccccc;--gray-50: #808080;--gray-60: #666666;--gray-80: #333333;--brand-danger: #e63c28;--brand-success: #155724;--row-color-zebra-light: #eeeeee;--row-color-zebra-dark: #dddddd;--focus-cell-background: #ffffff;--focus-cell-outline: #000000;--cell-border-color: #ffffff;--cell-text-color: #3a3c41;--active-cell-background: #ffffff;--active-cell-outline: #e6a92d;--row-border-color: var(--gray-20);--header-border-color: #ffffff;--header-text-color: var(--gray-20);--row-number-background-color: #ffffff;--input-border-color: var(--gray-20);--input-label-color: var(--gray-60);--input-active-border-color: #000000;--input-active-label-color: #000000;--required-border: #e63c28;--font-size: 10px;--font-family: Arimo, Arial, sans-serif;--table-font-size: 16px;--atable-font-family: "Arimo", sans-serif;--atable-row-padding: 0px;--atable-row-height: 1.5em;--btn-color: white;--btn-border: #cccccc;--btn-hover: #f2f2f2;--btn-label-color: black}.aform{display:flex;flex-wrap:wrap;gap:1rem;padding:1rem;border:1px solid var(--gray-5);border-left:4px solid var(--gray-5);margin-bottom:1rem;max-width:100%}@media screen and (max-width:400px){.aform{flex-direction:column}}.aform__form-element{border:1px solid transparent;padding:0;margin:0;position:relative;box-sizing:border-box;flex-grow:1;min-width:100px}.aform__input-field{outline:1px solid transparent;border:1px solid var(--input-border-color);font-size:1rem;padding:.5rem .25rem .25rem .5rem;margin:0;border-radius:0;box-sizing:border-box;width:100%;position:relative;color:var(--cell-text-color)}.aform__field-label{color:var(--input-label-color);display:inline-block;position:absolute;padding:0 .25rem;margin:0rem;z-index:2;font-size:.7rem;font-weight:300;letter-spacing:.05rem;width:auto;box-sizing:border-box;background:#fff;margin:0;border:1px solid var(--input-border-color);grid-row:1;top:0;left:10px;border:none;transform:translateY(-50%)}p.error{display:block;display:inline-block;display:none;padding:0rem 0rem 0rem .5rem;margin:.5rem 0 .25rem 0rem;border:1px solid transparent;width:100%;width:auto;color:var(--brand-danger);font-size:.8rem;position:absolute;right:0;top:0;background:#fff;padding:.25rem;transform:translate(-1rem,-50%);margin:0}.aform__input-field:focus{border:1px solid var(--input-active-border-color)}.aform__input-field:focus+.aform__field-label{color:var(--input-active-label-color)}.aform__checkbox{cursor:pointer;width:auto;margin-top:0;display:block}.aform__checkbox:checked{accent-color:var(--primary-color);border:1px solid black}.aform__checkbox-container{width:100%;display:inline-block;text-align:left}.aform__checkbox-container input{width:auto}.aform__checkbox-container:hover+.aform__field-label{color:var(--input-active-label-color)}.aform-primary-action{font-size:100%;text-align:center;min-height:2em;padding:.25rem 1rem;border:1px solid var(--primary-color);color:var(--primary-text-color);background-color:var(--primary-color);outline:2px solid var(--primary-text-color);transition:outline-offset .2s ease;font-size:var(--font-size);margin:.5ch}.aform-primary-action:hover,.aform-primary-action:active{outline:2px solid var(--primary-text-color);outline-offset:-4px;transition:outline-offset .2s ease}tr:focus{background-color:#add8e6;outline:auto}.aform__form-btn{padding:.5rem 2rem;width:auto;border:1px solid var(--input-border-color);color:var(--input-label-color);cursor:pointer;background-color:#fff}.aform__form-btn:disabled{background-color:var(--gray-5)}.aform__file-attach{padding:1rem;display:flex;flex-wrap:wrap;gap:1rem;flex-direction:row;justify-content:center;align-items:center;border:1px dashed var(--input-border-color);width:100%}@media screen and (max-width:400px){.aform__file-attach>.aform__form-btn{width:100%}}.aform__file-attach-feedback{color:var(--input-label-color);width:100%;padding:.5rem;text-align:center;align-self:center}.aform__file-attach-feedback>li{list-style:none;font-style:italic}.aform__file-attach-feedback>p{margin-top:0}.atable{font-family:var(--atable-font-family);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:var(--table-font-size);border-collapse:collapse}.row-index{color:var(--header-text-color);font-weight:700;text-align:center;-webkit-user-select:none;user-select:none;width:2ch}.expandable-row{border-top:1px solid var(--row-border-color);height:var(--atable-row-height);border-left:4px solid var(--row-border-color)}.expanded-row{border-bottom:1px solid var(--row-border-color);border-top:1px solid var(--row-border-color)}.expanded-row-content{border-bottom:1px solid var(--row-border-color);border-top:1px solid var(--row-border-color);padding:1.5rem}.atable__cell{border-radius:0;box-sizing:border-box;margin:0;outline:none;box-shadow:none;color:var(--cell-text-color);text-overflow:ellipsis;overflow:hidden;padding-left:.5ch!important;padding-right:.5ch;padding-top:var(--atable-row-padding);padding-bottom:var(--atable-row-padding);border-spacing:0px;border-collapse:collapse}.atable__cell:focus,.atable__cell:focus-within{background-color:var(--focus-cell-background);outline-width:2px;outline-style:solid;outline-color:var(--focus-cell-outline);box-shadow:none;min-height:1.15em;max-height:1.15em;overflow:hidden}.table-row{border-top:1px solid var(--row-border-color);height:var(--atable-row-height)}.list-index{color:var(--header-text-color);font-weight:700;padding-left:var(--atable-row-padding);padding-right:1em;text-align:center;-webkit-user-select:none;user-select:none;width:var(--2c1c9089);max-width:var(--2c1c9089)}.tree-index{color:var(--header-text-color);font-weight:700;text-align:center;-webkit-user-select:none;user-select:none;width:2ch}.atable #header-index{width:var(--2c1c9089);max-width:var(--2c1c9089)}.atable th{border-width:0px;border-style:solid;border-radius:0;padding-left:.5ch;padding-right:.5ch;padding-top:var(--atable-row-padding);padding-bottom:var(--atable-row-padding);color:var(--gray-60);height:var(--atable-row-height);font-weight:300;letter-spacing:.05rem}.atable th:focus{outline:none}.amodal{z-index:100;position:absolute;background-color:var(--row-color-zebra-dark)}.login-container{width:100%;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;font-family:var(--font-family)}.account-container{width:100%;margin-left:auto;margin-top:.5rem;margin-right:auto;display:flex;flex-direction:column;justify-content:center}.account-header{display:flex;flex-direction:column;text-align:center;margin-top:.5rem}#account-title{font-size:1.5rem;line-height:2rem;font-weight:600;letter-spacing:-.025em;margin:0}#account-subtitle{font-size:.875rem;line-height:1.25rem;margin:1rem}.login-form-container{display:grid;gap:.5rem}.login-form-element{display:grid;margin:.5rem 0;position:relative}.login-field{padding:.5rem .25rem .25rem .5rem;outline:1px solid transparent;border:1px solid var(--input-border-color);border-radius:.25rem}.login-field:focus{border:1px solid black}.btn{background-color:var(--btn-color);color:var(--btn-label-color);border:1px solid var(--btn-border);margin:.5rem 0;padding:.25rem;position:relative;cursor:pointer}.btn:hover{background-color:var(--btn-hover)}.btn:disabled{background-color:light-dark(rgba(239,239,239,.3),rgba(59,59,59,.3));color:light-dark(rgb(84,84,84),rgb(170,170,170))}.disabled{opacity:.5}.loading-icon{animation:spin 1s linear infinite forwards;display:inline-block;margin-right:.2rem;line-height:0;font-size:1rem;position:relative;top:.2rem}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/atable",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.34",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": {
|
|
@@ -32,19 +32,19 @@
|
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@vueuse/components": "^10.11.0",
|
|
35
|
-
"@vueuse/core": "^
|
|
35
|
+
"@vueuse/core": "^11.1.0",
|
|
36
36
|
"uuid": "^10.0.0",
|
|
37
|
-
"vue": "^3.
|
|
38
|
-
"@stonecrop/utilities": "0.2.
|
|
39
|
-
"@stonecrop/themes": "0.2.
|
|
37
|
+
"vue": "^3.5.6",
|
|
38
|
+
"@stonecrop/utilities": "0.2.34",
|
|
39
|
+
"@stonecrop/themes": "0.2.34"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@microsoft/api-documenter": "^7.25.3",
|
|
43
|
-
"@rushstack/heft": "^0.
|
|
43
|
+
"@rushstack/heft": "^0.67.2",
|
|
44
44
|
"@types/uuid": "^10.0.0",
|
|
45
45
|
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
|
46
46
|
"@typescript-eslint/parser": "^7.14.1",
|
|
47
|
-
"@vitejs/plugin-vue": "^5.
|
|
47
|
+
"@vitejs/plugin-vue": "^5.1.3",
|
|
48
48
|
"@vitest/coverage-istanbul": "^2.1.1",
|
|
49
49
|
"@vitest/ui": "^2.1.1",
|
|
50
50
|
"@vue/test-utils": "^2.4.6",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"eslint": "^8.40.0",
|
|
55
55
|
"jsdom": "^25.0.0",
|
|
56
56
|
"typescript": "^5.5.2",
|
|
57
|
-
"vite": "^5.
|
|
57
|
+
"vite": "^5.4.5",
|
|
58
58
|
"vitest": "^2.1.1",
|
|
59
59
|
"vue-router": "^4.4.0",
|
|
60
60
|
"stonecrop-rig": "0.2.22"
|
package/src/components/ACell.vue
CHANGED
|
@@ -27,36 +27,36 @@
|
|
|
27
27
|
|
|
28
28
|
<script setup lang="ts">
|
|
29
29
|
import { KeypressHandlers, defaultKeypressHandlers, useKeyboardNav } from '@stonecrop/utilities'
|
|
30
|
-
import { computed, CSSProperties, inject, ref } from 'vue'
|
|
30
|
+
import { computed, CSSProperties, inject, ref, useTemplateRef } from 'vue'
|
|
31
31
|
|
|
32
32
|
import TableDataStore from '.'
|
|
33
33
|
import type { CellFormatContext } from '@/types'
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
const tableData = inject<TableDataStore>(
|
|
50
|
-
const
|
|
35
|
+
const {
|
|
36
|
+
colIndex,
|
|
37
|
+
rowIndex,
|
|
38
|
+
tableid,
|
|
39
|
+
addNavigation = true,
|
|
40
|
+
tabIndex = 0,
|
|
41
|
+
} = defineProps<{
|
|
42
|
+
colIndex: number
|
|
43
|
+
rowIndex: number
|
|
44
|
+
tableid: string
|
|
45
|
+
addNavigation?: boolean | KeypressHandlers
|
|
46
|
+
tabIndex?: number
|
|
47
|
+
}>()
|
|
48
|
+
|
|
49
|
+
const tableData = inject<TableDataStore>(tableid)
|
|
50
|
+
const cellRef = useTemplateRef<HTMLTableCellElement>('cell')
|
|
51
51
|
const currentData = ref('')
|
|
52
52
|
const cellModified = ref(false)
|
|
53
53
|
|
|
54
54
|
const displayValue = computed(() => {
|
|
55
|
-
const data = tableData.cellData<any>(
|
|
56
|
-
if (tableData.columns[
|
|
55
|
+
const data = tableData.cellData<any>(colIndex, rowIndex)
|
|
56
|
+
if (tableData.columns[colIndex].format) {
|
|
57
57
|
const table = tableData.table
|
|
58
|
-
const row = tableData.rows[
|
|
59
|
-
const column = tableData.columns[
|
|
58
|
+
const row = tableData.rows[rowIndex]
|
|
59
|
+
const column = tableData.columns[colIndex]
|
|
60
60
|
const format = column.format
|
|
61
61
|
|
|
62
62
|
if (typeof format === 'function') {
|
|
@@ -75,26 +75,26 @@ const displayValue = computed(() => {
|
|
|
75
75
|
})
|
|
76
76
|
|
|
77
77
|
const handleInput = () => {
|
|
78
|
-
if (tableData.columns[
|
|
78
|
+
if (tableData.columns[colIndex].mask) {
|
|
79
79
|
// TODO: add masking to cell values
|
|
80
|
-
// tableData.columns[
|
|
80
|
+
// tableData.columns[colIndex].mask(event)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
if (tableData.columns[
|
|
84
|
-
const domRect =
|
|
83
|
+
if (tableData.columns[colIndex].modalComponent) {
|
|
84
|
+
const domRect = cellRef.value.getBoundingClientRect()
|
|
85
85
|
tableData.modal.visible = true
|
|
86
|
-
tableData.modal.colIndex =
|
|
87
|
-
tableData.modal.rowIndex =
|
|
88
|
-
tableData.modal.parent =
|
|
86
|
+
tableData.modal.colIndex = colIndex
|
|
87
|
+
tableData.modal.rowIndex = rowIndex
|
|
88
|
+
tableData.modal.parent = cellRef.value
|
|
89
89
|
tableData.modal.top = domRect.top + domRect.height
|
|
90
90
|
tableData.modal.left = domRect.left
|
|
91
91
|
tableData.modal.width = cellWidth.value
|
|
92
|
-
tableData.modal.component = tableData.columns[
|
|
93
|
-
tableData.modal.componentProps = tableData.columns[
|
|
92
|
+
tableData.modal.component = tableData.columns[colIndex].modalComponent
|
|
93
|
+
tableData.modal.componentProps = tableData.columns[colIndex].modalComponentProps
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
if (
|
|
97
|
+
if (addNavigation) {
|
|
98
98
|
let handlers = {
|
|
99
99
|
...defaultKeypressHandlers,
|
|
100
100
|
...{
|
|
@@ -106,16 +106,16 @@ if (props.addNavigation) {
|
|
|
106
106
|
},
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
if (typeof
|
|
109
|
+
if (typeof addNavigation === 'object') {
|
|
110
110
|
handlers = {
|
|
111
111
|
...handlers,
|
|
112
|
-
...
|
|
112
|
+
...addNavigation,
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
useKeyboardNav([
|
|
117
117
|
{
|
|
118
|
-
selectors:
|
|
118
|
+
selectors: cellRef,
|
|
119
119
|
handlers: handlers,
|
|
120
120
|
},
|
|
121
121
|
])
|
|
@@ -124,36 +124,36 @@ if (props.addNavigation) {
|
|
|
124
124
|
// const updateData = (event: Event) => {
|
|
125
125
|
// if (event) {
|
|
126
126
|
// // custom components need to handle their own updateData, this is the default
|
|
127
|
-
// if (!tableData.columns[
|
|
128
|
-
// tableData.setCellData(
|
|
127
|
+
// if (!tableData.columns[colIndex].component) {
|
|
128
|
+
// tableData.setCellData(rowIndex, colIndex, cell.value.innerHTML)
|
|
129
129
|
// }
|
|
130
130
|
// cellModified.value = true
|
|
131
131
|
// }
|
|
132
132
|
// }
|
|
133
133
|
|
|
134
134
|
const textAlign = computed(() => {
|
|
135
|
-
return tableData.columns[
|
|
135
|
+
return tableData.columns[colIndex].align || 'center'
|
|
136
136
|
})
|
|
137
137
|
|
|
138
138
|
const cellWidth = computed(() => {
|
|
139
|
-
return tableData.columns[
|
|
139
|
+
return tableData.columns[colIndex].width || '40ch'
|
|
140
140
|
})
|
|
141
141
|
|
|
142
142
|
const onFocus = () => {
|
|
143
|
-
if (
|
|
144
|
-
currentData.value =
|
|
143
|
+
if (cellRef.value) {
|
|
144
|
+
currentData.value = cellRef.value.textContent
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
const onChange = () => {
|
|
149
|
-
if (
|
|
150
|
-
if (
|
|
151
|
-
currentData.value =
|
|
152
|
-
|
|
149
|
+
if (cellRef.value) {
|
|
150
|
+
if (cellRef.value.textContent !== currentData.value) {
|
|
151
|
+
currentData.value = cellRef.value.textContent
|
|
152
|
+
cellRef.value.dispatchEvent(new Event('change'))
|
|
153
153
|
cellModified.value = true // set display instead
|
|
154
|
-
if (!tableData.columns[
|
|
154
|
+
if (!tableData.columns[colIndex].format) {
|
|
155
155
|
// TODO: need to setup reverse format function
|
|
156
|
-
tableData.setCellData(
|
|
156
|
+
tableData.setCellData(rowIndex, colIndex, currentData.value)
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
}
|
|
@@ -172,7 +172,7 @@ const cellStyle: CSSProperties = {
|
|
|
172
172
|
width: cellWidth.value,
|
|
173
173
|
backgroundColor: !cellModified.value ? 'inherit' : 'var(--cell-modified-color)',
|
|
174
174
|
fontWeight: !cellModified.value ? 'inherit' : 'bold',
|
|
175
|
-
paddingLeft: getIndent(
|
|
175
|
+
paddingLeft: getIndent(colIndex, tableData.display[rowIndex]?.indent),
|
|
176
176
|
}
|
|
177
177
|
</script>
|
|
178
178
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
</td>
|
|
6
6
|
<slot name="row" />
|
|
7
7
|
</tr>
|
|
8
|
-
<tr v-if="tableData.display[
|
|
8
|
+
<tr v-if="tableData.display[rowIndex].expanded" ref="rowExpanded" :tabindex="tabIndex" class="expanded-row">
|
|
9
9
|
<td :tabIndex="-1" :colspan="tableData.columns.length + 1" class="expanded-row-content">
|
|
10
10
|
<slot name="content" />
|
|
11
11
|
</td>
|
|
@@ -14,48 +14,49 @@
|
|
|
14
14
|
|
|
15
15
|
<script setup lang="ts">
|
|
16
16
|
import { type KeypressHandlers, useKeyboardNav } from '@stonecrop/utilities'
|
|
17
|
-
import { computed, inject,
|
|
17
|
+
import { computed, inject, useTemplateRef } from 'vue'
|
|
18
18
|
|
|
19
19
|
import TableDataStore from '.'
|
|
20
20
|
import type { TableRow } from '@/types'
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
const {
|
|
23
|
+
row,
|
|
24
|
+
rowIndex,
|
|
25
|
+
tableid,
|
|
26
|
+
tabIndex = -1,
|
|
27
|
+
addNavigation,
|
|
28
|
+
} = defineProps<{
|
|
29
|
+
row: TableRow
|
|
30
|
+
rowIndex: number
|
|
31
|
+
tableid: string
|
|
32
|
+
tabIndex?: number
|
|
33
|
+
addNavigation?: boolean | KeypressHandlers
|
|
34
|
+
}>()
|
|
34
35
|
|
|
35
|
-
const tableData = inject<TableDataStore>(
|
|
36
|
-
const
|
|
37
|
-
const
|
|
36
|
+
const tableData = inject<TableDataStore>(tableid)
|
|
37
|
+
const rowRef = useTemplateRef<HTMLTableRowElement>('rowEl')
|
|
38
|
+
// const expandedRowRef = useTemplateRef<HTMLDivElement>('rowExpanded')
|
|
38
39
|
|
|
39
40
|
const rowExpandSymbol = computed(() => {
|
|
40
|
-
return tableData.display[
|
|
41
|
+
return tableData.display[rowIndex].expanded ? '▼' : '►'
|
|
41
42
|
})
|
|
42
43
|
|
|
43
|
-
if (
|
|
44
|
+
if (addNavigation) {
|
|
44
45
|
const handlers: KeypressHandlers = {
|
|
45
46
|
'keydown.control.g': (event: KeyboardEvent) => {
|
|
46
47
|
event.stopPropagation()
|
|
47
48
|
event.preventDefault()
|
|
48
|
-
tableData.toggleRowExpand(
|
|
49
|
+
tableData.toggleRowExpand(rowIndex)
|
|
49
50
|
},
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
if (typeof
|
|
53
|
-
Object.assign(handlers,
|
|
53
|
+
if (typeof addNavigation === 'object') {
|
|
54
|
+
Object.assign(handlers, addNavigation)
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
useKeyboardNav([
|
|
57
58
|
{
|
|
58
|
-
selectors:
|
|
59
|
+
selectors: rowRef,
|
|
59
60
|
handlers: handlers,
|
|
60
61
|
},
|
|
61
62
|
])
|
package/src/components/ARow.vue
CHANGED
|
@@ -21,34 +21,30 @@
|
|
|
21
21
|
|
|
22
22
|
<script setup lang="ts">
|
|
23
23
|
import { type KeypressHandlers, useKeyboardNav, defaultKeypressHandlers } from '@stonecrop/utilities'
|
|
24
|
-
import { computed, inject,
|
|
24
|
+
import { computed, inject, useTemplateRef } from 'vue'
|
|
25
25
|
|
|
26
26
|
import TableDataStore from '.'
|
|
27
27
|
import type { TableRow } from '@/types'
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
29
|
+
const {
|
|
30
|
+
row,
|
|
31
|
+
rowIndex,
|
|
32
|
+
tableid,
|
|
33
|
+
tabIndex = -1,
|
|
34
|
+
addNavigation = false, // default to allowing cell navigation
|
|
35
|
+
} = defineProps<{
|
|
36
|
+
row: TableRow
|
|
37
|
+
rowIndex: number
|
|
38
|
+
tableid: string
|
|
39
|
+
tabIndex?: number
|
|
40
|
+
addNavigation?: boolean | KeypressHandlers
|
|
41
|
+
}>()
|
|
42
42
|
|
|
43
|
-
const tableData = inject<TableDataStore>(
|
|
44
|
-
const
|
|
43
|
+
const tableData = inject<TableDataStore>(tableid)
|
|
44
|
+
const rowRef = useTemplateRef<HTMLTableRowElement>('rowEl')
|
|
45
45
|
|
|
46
46
|
const isRowVisible = computed(() => {
|
|
47
|
-
return
|
|
48
|
-
tableData.config.view !== 'tree' ||
|
|
49
|
-
tableData.display[props.rowIndex].isRoot ||
|
|
50
|
-
tableData.display[props.rowIndex].open
|
|
51
|
-
)
|
|
47
|
+
return tableData.config.view !== 'tree' || tableData.display[rowIndex].isRoot || tableData.display[rowIndex].open
|
|
52
48
|
})
|
|
53
49
|
|
|
54
50
|
const rowExpandSymbol = computed(() => {
|
|
@@ -56,8 +52,8 @@ const rowExpandSymbol = computed(() => {
|
|
|
56
52
|
return ''
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
if (tableData.display[
|
|
60
|
-
return tableData.display[
|
|
55
|
+
if (tableData.display[rowIndex].isRoot || tableData.display[rowIndex].isParent) {
|
|
56
|
+
return tableData.display[rowIndex].childrenOpen ? '-' : '+'
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
return ''
|
|
@@ -67,19 +63,19 @@ const toggleRowExpand = (rowIndex: number) => {
|
|
|
67
63
|
tableData.toggleRowExpand(rowIndex)
|
|
68
64
|
}
|
|
69
65
|
|
|
70
|
-
if (
|
|
66
|
+
if (addNavigation) {
|
|
71
67
|
let handlers = defaultKeypressHandlers
|
|
72
68
|
|
|
73
|
-
if (typeof
|
|
69
|
+
if (typeof addNavigation === 'object') {
|
|
74
70
|
handlers = {
|
|
75
71
|
...handlers,
|
|
76
|
-
...
|
|
72
|
+
...addNavigation,
|
|
77
73
|
}
|
|
78
74
|
}
|
|
79
75
|
|
|
80
76
|
useKeyboardNav([
|
|
81
77
|
{
|
|
82
|
-
selectors:
|
|
78
|
+
selectors: rowRef,
|
|
83
79
|
handlers: handlers,
|
|
84
80
|
},
|
|
85
81
|
])
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
:style="{ width: tableData.config.fullWidth ? '100%' : 'auto' }"
|
|
5
5
|
v-on-click-outside="closeModal">
|
|
6
6
|
<slot name="header" :data="tableData">
|
|
7
|
-
<ATableHeader :columns="tableData.columns" :
|
|
7
|
+
<ATableHeader :columns="tableData.columns" :tableid="tableData.id" />
|
|
8
8
|
</slot>
|
|
9
9
|
|
|
10
10
|
<tbody>
|
|
@@ -70,25 +70,26 @@ import ATableHeader from '@/components/ATableHeader.vue'
|
|
|
70
70
|
import ATableModal from '@/components/ATableModal.vue'
|
|
71
71
|
import type { TableColumn, TableConfig, TableRow } from '@/types'
|
|
72
72
|
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
73
|
+
const {
|
|
74
|
+
id,
|
|
75
|
+
modelValue,
|
|
76
|
+
columns,
|
|
77
|
+
rows = [],
|
|
78
|
+
config = new Object(),
|
|
79
|
+
tableid,
|
|
80
|
+
} = defineProps<{
|
|
81
|
+
id?: string
|
|
82
|
+
modelValue: TableRow[]
|
|
83
|
+
columns: TableColumn[]
|
|
84
|
+
rows?: TableRow[]
|
|
85
|
+
config?: TableConfig
|
|
86
|
+
tableid?: string
|
|
87
|
+
}>()
|
|
87
88
|
|
|
88
89
|
const emit = defineEmits(['update:modelValue'])
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
const rowsValue = modelValue ? modelValue : rows
|
|
92
|
+
const tableData = new TableDataStore(id, columns, rowsValue, config)
|
|
92
93
|
provide(tableData.id, tableData)
|
|
93
94
|
|
|
94
95
|
watch(
|
|
@@ -13,15 +13,11 @@
|
|
|
13
13
|
import { CSSProperties, inject } from 'vue'
|
|
14
14
|
|
|
15
15
|
import TableDataStore from '.'
|
|
16
|
-
import type { TableColumn
|
|
16
|
+
import type { TableColumn } from '@/types'
|
|
17
17
|
|
|
18
|
-
const
|
|
19
|
-
columns: TableColumn[]
|
|
20
|
-
config?: TableConfig
|
|
21
|
-
tableid?: string
|
|
22
|
-
}>()
|
|
18
|
+
const { columns, tableid } = defineProps<{ columns: TableColumn[]; tableid?: string }>()
|
|
23
19
|
|
|
24
|
-
const tableData = inject<TableDataStore>(
|
|
20
|
+
const tableData = inject<TableDataStore>(tableid)
|
|
25
21
|
|
|
26
22
|
const getHeaderCellStyle = (column: TableColumn): CSSProperties => ({
|
|
27
23
|
minWidth: column.width || '40ch',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div class="amodal" tabindex="-1" @click="handleInput" @input="handleInput">
|
|
3
3
|
<slot />
|
|
4
4
|
</div>
|
|
5
5
|
</template>
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
|
|
10
10
|
// import TableDataStore from '.'
|
|
11
11
|
|
|
12
|
-
/* const
|
|
12
|
+
/* const { colIndex, rowIndex, tableid } = */ defineProps<{
|
|
13
13
|
colIndex?: number
|
|
14
14
|
rowIndex?: number
|
|
15
15
|
tableid?: string
|
|
16
16
|
}>()
|
|
17
17
|
|
|
18
|
-
// const tableData = inject<TableDataStore>(
|
|
18
|
+
// const tableData = inject<TableDataStore>(tableid)
|
|
19
19
|
// const cellBackgroundColor = computed(() => {
|
|
20
20
|
// if (tableData.modal.parent) {
|
|
21
21
|
// let computedstyle = window.getComputedStyle(tableData.modal.parent)
|