@stonecrop/atable 0.2.39 → 0.2.40
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.js +482 -465
- package/dist/atable.js.map +1 -1
- package/dist/atable.umd.cjs +1 -1
- package/dist/atable.umd.cjs.map +1 -1
- package/dist/src/types/index.d.ts +1 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -3
- package/src/components/ACell.vue +8 -6
- package/src/components/AExpansionRow.vue +0 -3
- package/src/components/ARow.vue +8 -4
- package/src/components/ATable.vue +44 -3
- package/src/components/ATableHeader.vue +10 -3
- package/src/types/index.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,cAAc,CAAA;AAEzC,MAAM,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IAEZ,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,cAAc,CAAA;AAEzC,MAAM,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IAEZ,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACxC,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,WAAW,KAAK,MAAM,CAAC,CAAA;IAC7D,wBAAwB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE9C,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,MAAM,CAAC,CAAA;IACjE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACzB,GAAG,EAAE,QAAQ,CAAA;IACb,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAAA;IACzC,SAAS,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACpC,CAAA"}
|
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"
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=Arimo:ital,wght@0,400..700;1,400..700&display=swap";: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);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;overflow:hidden;text-overflow:ellipsis;order:1}.atable__cell span{overflow:hidden;text-overflow:ellipsis}.atable__cell:focus,.atable__cell:focus-within{background-color:var(--focus-cell-background);outline-width:2px;outline-style:solid;outline-offset:-1px;outline-color:var(--focus-cell-outline);box-shadow:none;min-height:1.15em;max-height:1.15em;overflow:hidden;box-sizing:border-box}.table-row{border-top:1px solid var(--row-border-color);height:var(--atable-row-height);display:flex;background-color:#fff}.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:30px;text-overflow:ellipsis;overflow:hidden}.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:30px;padding-right:1em;padding-left:0;box-sizing:border-box}.atable-header-row{display:flex}.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;order:1;box-sizing:border-box}#header-index{box-sizing:content-box}.atable th:focus{outline:none}.amodal{z-index:100;position:absolute;background-color:var(--row-color-zebra-dark)}.sticky-index{position:sticky;left:0;z-index:1;order:0}.sticky-column,th.sticky-column,td.sticky-column,th.sticky-index,td.sticky-index{position:sticky;z-index:1;order:0;background:#fff}.sticky-column-edge,.atable th.sticky-column-edge{border-right:1px solid var(--row-border-color);border-right-width:1px}.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.40",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": {
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@vueuse/core": "^11.1.0",
|
|
36
36
|
"uuid": "^10.0.0",
|
|
37
37
|
"vue": "^3.5.6",
|
|
38
|
-
"@stonecrop/utilities": "0.2.
|
|
39
|
-
"@stonecrop/themes": "0.2.
|
|
38
|
+
"@stonecrop/utilities": "0.2.40",
|
|
39
|
+
"@stonecrop/themes": "0.2.40"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@microsoft/api-documenter": "^7.25.3",
|
package/src/components/ACell.vue
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
ref="cell"
|
|
4
4
|
:data-colindex="colIndex"
|
|
5
5
|
:data-rowindex="rowIndex"
|
|
6
|
-
:data-editable="
|
|
7
|
-
:contenteditable="
|
|
6
|
+
:data-editable="column.edit"
|
|
7
|
+
:contenteditable="column.edit"
|
|
8
8
|
:tabindex="tabIndex"
|
|
9
9
|
:spellcheck="false"
|
|
10
10
|
:style="cellStyle"
|
|
@@ -14,12 +14,13 @@
|
|
|
14
14
|
@input="onChange"
|
|
15
15
|
@click="handleInput"
|
|
16
16
|
@mousedown="handleInput"
|
|
17
|
-
class="atable__cell"
|
|
17
|
+
class="atable__cell"
|
|
18
|
+
:class="pinned ? 'sticky-column' : ''">
|
|
18
19
|
<component
|
|
19
|
-
v-if="
|
|
20
|
-
:is="
|
|
20
|
+
v-if="column.cellComponent"
|
|
21
|
+
:is="column.cellComponent"
|
|
21
22
|
:value="displayValue"
|
|
22
|
-
v-bind="
|
|
23
|
+
v-bind="column.cellComponentProps">
|
|
23
24
|
</component>
|
|
24
25
|
<span v-else>{{ displayValue }}</span>
|
|
25
26
|
</td>
|
|
@@ -44,6 +45,7 @@ const {
|
|
|
44
45
|
tableid: string
|
|
45
46
|
addNavigation?: boolean | KeypressHandlers
|
|
46
47
|
tabIndex?: number
|
|
48
|
+
pinned?: boolean
|
|
47
49
|
}>()
|
|
48
50
|
|
|
49
51
|
const tableData = inject<TableDataStore>(tableid)
|
|
@@ -17,16 +17,13 @@ import { type KeypressHandlers, useKeyboardNav } from '@stonecrop/utilities'
|
|
|
17
17
|
import { computed, inject, useTemplateRef } from 'vue'
|
|
18
18
|
|
|
19
19
|
import TableDataStore from '.'
|
|
20
|
-
import type { TableRow } from '@/types'
|
|
21
20
|
|
|
22
21
|
const {
|
|
23
|
-
row,
|
|
24
22
|
rowIndex,
|
|
25
23
|
tableid,
|
|
26
24
|
tabIndex = -1,
|
|
27
25
|
addNavigation,
|
|
28
26
|
} = defineProps<{
|
|
29
|
-
row: TableRow
|
|
30
27
|
rowIndex: number
|
|
31
28
|
tableid: string
|
|
32
29
|
tabIndex?: number
|
package/src/components/ARow.vue
CHANGED
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
<tr ref="rowEl" :tabindex="tabIndex" v-show="isRowVisible" class="table-row">
|
|
3
3
|
<!-- render numbered/tree view index -->
|
|
4
4
|
<slot name="index">
|
|
5
|
-
<td
|
|
5
|
+
<td
|
|
6
|
+
v-if="tableData.config.view === 'list'"
|
|
7
|
+
:tabIndex="-1"
|
|
8
|
+
class="list-index"
|
|
9
|
+
:class="hasPinnedColumns ? 'sticky-index' : ''">
|
|
6
10
|
{{ rowIndex + 1 }}
|
|
7
11
|
</td>
|
|
8
12
|
<td
|
|
9
13
|
v-else-if="tableData.config.view === 'tree'"
|
|
10
14
|
:tabIndex="-1"
|
|
11
15
|
class="tree-index"
|
|
16
|
+
:class="hasPinnedColumns ? 'sticky-index' : ''"
|
|
12
17
|
@click="toggleRowExpand(rowIndex)">
|
|
13
18
|
{{ rowExpandSymbol }}
|
|
14
19
|
</td>
|
|
@@ -24,16 +29,13 @@ import { type KeypressHandlers, useKeyboardNav, defaultKeypressHandlers } from '
|
|
|
24
29
|
import { computed, inject, useTemplateRef } from 'vue'
|
|
25
30
|
|
|
26
31
|
import TableDataStore from '.'
|
|
27
|
-
import type { TableRow } from '@/types'
|
|
28
32
|
|
|
29
33
|
const {
|
|
30
|
-
row,
|
|
31
34
|
rowIndex,
|
|
32
35
|
tableid,
|
|
33
36
|
tabIndex = -1,
|
|
34
37
|
addNavigation = false, // default to allowing cell navigation
|
|
35
38
|
} = defineProps<{
|
|
36
|
-
row: TableRow
|
|
37
39
|
rowIndex: number
|
|
38
40
|
tableid: string
|
|
39
41
|
tabIndex?: number
|
|
@@ -43,6 +45,8 @@ const {
|
|
|
43
45
|
const tableData = inject<TableDataStore>(tableid)
|
|
44
46
|
const rowRef = useTemplateRef<HTMLTableRowElement>('rowEl')
|
|
45
47
|
|
|
48
|
+
const hasPinnedColumns = computed(() => tableData.columns.some(col => col.pinned))
|
|
49
|
+
|
|
46
50
|
const isRowVisible = computed(() => {
|
|
47
51
|
return tableData.config.view !== 'tree' || tableData.display[rowIndex].isRoot || tableData.display[rowIndex].open
|
|
48
52
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<table
|
|
3
|
+
ref="table"
|
|
3
4
|
class="atable"
|
|
4
5
|
:style="{ width: tableData.config.fullWidth ? '100%' : 'auto' }"
|
|
5
6
|
v-on-click-outside="closeModal">
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
:tableid="tableData.id"
|
|
22
23
|
:col="col"
|
|
23
24
|
spellcheck="false"
|
|
25
|
+
:pinned="col.pinned"
|
|
24
26
|
:rowIndex="rowIndex"
|
|
25
27
|
:colIndex="colIndex + (tableData.zeroColumn ? 0 : -1)"
|
|
26
28
|
:component="col.cellComponent"
|
|
@@ -61,7 +63,7 @@
|
|
|
61
63
|
|
|
62
64
|
<script setup lang="ts">
|
|
63
65
|
import { vOnClickOutside } from '@vueuse/components'
|
|
64
|
-
import { nextTick, provide, watch } from 'vue'
|
|
66
|
+
import { nextTick, provide, watch, onMounted, useTemplateRef } from 'vue'
|
|
65
67
|
|
|
66
68
|
import TableDataStore from '.'
|
|
67
69
|
import ACell from '@/components/ACell.vue'
|
|
@@ -76,18 +78,17 @@ const {
|
|
|
76
78
|
columns,
|
|
77
79
|
rows = [],
|
|
78
80
|
config = new Object(),
|
|
79
|
-
tableid,
|
|
80
81
|
} = defineProps<{
|
|
81
82
|
id?: string
|
|
82
83
|
modelValue: TableRow[]
|
|
83
84
|
columns: TableColumn[]
|
|
84
85
|
rows?: TableRow[]
|
|
85
86
|
config?: TableConfig
|
|
86
|
-
tableid?: string
|
|
87
87
|
}>()
|
|
88
88
|
|
|
89
89
|
const emit = defineEmits(['update:modelValue'])
|
|
90
90
|
|
|
91
|
+
const tableRef = useTemplateRef<HTMLTableElement>('table')
|
|
91
92
|
const rowsValue = modelValue ? modelValue : rows
|
|
92
93
|
const tableData = new TableDataStore(id, columns, rowsValue, config)
|
|
93
94
|
provide(tableData.id, tableData)
|
|
@@ -100,6 +101,46 @@ watch(
|
|
|
100
101
|
{ deep: true }
|
|
101
102
|
)
|
|
102
103
|
|
|
104
|
+
onMounted(() => {
|
|
105
|
+
assignStickyCellWidths()
|
|
106
|
+
|
|
107
|
+
// in tree view, a mutation observer is needed to capture and adjust expanded rows
|
|
108
|
+
if (tableData.config.view === 'tree') {
|
|
109
|
+
const observer = new MutationObserver(() => assignStickyCellWidths())
|
|
110
|
+
observer.observe(tableRef.value, { childList: true, subtree: true })
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const assignStickyCellWidths = () => {
|
|
115
|
+
const table = tableRef.value
|
|
116
|
+
|
|
117
|
+
// set header cell width to match sticky cells' width
|
|
118
|
+
const headerCells = Array.from(table.rows[0].cells)
|
|
119
|
+
for (const [index, headerCell] of headerCells.entries()) {
|
|
120
|
+
const rowCell = table.rows[1].cells[index]
|
|
121
|
+
headerCell.style.width = `${rowCell.offsetWidth}px`
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// pin cells in row that are sticky
|
|
125
|
+
for (const row of table.rows) {
|
|
126
|
+
let totalWidth = 0
|
|
127
|
+
const columns: HTMLTableCellElement[] = []
|
|
128
|
+
|
|
129
|
+
for (const column of row.cells) {
|
|
130
|
+
if (column.classList.contains('sticky-column') || column.classList.contains('sticky-index')) {
|
|
131
|
+
column.style.left = `${totalWidth}px`
|
|
132
|
+
totalWidth += column.offsetWidth
|
|
133
|
+
columns.push(column)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (columns.length > 0) {
|
|
138
|
+
const lastColumn = columns[columns.length - 1]
|
|
139
|
+
lastColumn.classList.add('sticky-column-edge')
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
103
144
|
// const formatCell = (event?: KeyboardEvent, column?: TableColumn, cellData?: any) => {
|
|
104
145
|
// let colIndex: number
|
|
105
146
|
// const target = event?.target as HTMLTableCellElement
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<thead id="resizable" v-if="columns.length">
|
|
3
3
|
<tr class="atable-header-row" tabindex="-1">
|
|
4
|
-
<th v-if="tableData.zeroColumn" id="header-index" />
|
|
5
|
-
<th
|
|
4
|
+
<th v-if="tableData.zeroColumn" id="header-index" :class="hasPinnedColumns ? 'sticky-index' : ''" />
|
|
5
|
+
<th
|
|
6
|
+
v-for="(column, colKey) in columns"
|
|
7
|
+
:key="column.name"
|
|
8
|
+
tabindex="-1"
|
|
9
|
+
:style="getHeaderCellStyle(column)"
|
|
10
|
+
:class="column.pinned ? 'sticky-column' : ''">
|
|
6
11
|
<slot>{{ column.label || String.fromCharCode(colKey + 97).toUpperCase() }}</slot>
|
|
7
12
|
</th>
|
|
8
13
|
</tr>
|
|
@@ -10,7 +15,7 @@
|
|
|
10
15
|
</template>
|
|
11
16
|
|
|
12
17
|
<script setup lang="ts">
|
|
13
|
-
import { CSSProperties, inject } from 'vue'
|
|
18
|
+
import { CSSProperties, inject, computed } from 'vue'
|
|
14
19
|
|
|
15
20
|
import TableDataStore from '.'
|
|
16
21
|
import type { TableColumn } from '@/types'
|
|
@@ -19,6 +24,8 @@ const { columns, tableid } = defineProps<{ columns: TableColumn[]; tableid?: str
|
|
|
19
24
|
|
|
20
25
|
const tableData = inject<TableDataStore>(tableid)
|
|
21
26
|
|
|
27
|
+
const hasPinnedColumns = computed(() => tableData.columns.some(col => col.pinned))
|
|
28
|
+
|
|
22
29
|
const getHeaderCellStyle = (column: TableColumn): CSSProperties => ({
|
|
23
30
|
minWidth: column.width || '40ch',
|
|
24
31
|
textAlign: column.align || 'center',
|