@stonecrop/atable 0.2.5 → 0.2.6
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 +30 -15
- package/src/components/ATable.vue +6 -6
- package/src/components/index.ts +118 -0
- package/src/histoire.setup.ts +24 -0
- package/src/index.ts +20 -0
- package/src/shims-vue.d.ts +5 -0
- package/src/themes/default.css +59 -0
- package/dist/atable.js +0 -775
- package/dist/atable.js.map +0 -1
- package/dist/atable.umd.cjs +0 -2
- package/dist/atable.umd.cjs.map +0 -1
- package/dist/style.css +0 -1
package/package.json
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/atable",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Tyler Matteson",
|
|
8
|
+
"email": "tyler@agritheory.com"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/agritheory/stonecrop",
|
|
13
|
+
"directory": "atable"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/agritheory/stonecrop/issues"
|
|
17
|
+
},
|
|
6
18
|
"exports": {
|
|
7
19
|
".": {
|
|
8
20
|
"import": "./dist/atable.js",
|
|
@@ -12,45 +24,48 @@
|
|
|
12
24
|
},
|
|
13
25
|
"main": "dist/atable.js",
|
|
14
26
|
"module": "dist/atable.js",
|
|
27
|
+
"umd": "dist/atable.umd.cjs",
|
|
15
28
|
"types": "src/index",
|
|
16
29
|
"files": [
|
|
17
30
|
"dist/*",
|
|
18
|
-
"src
|
|
31
|
+
"src/*"
|
|
19
32
|
],
|
|
20
33
|
"dependencies": {
|
|
21
34
|
"uuid": "^9.0.0",
|
|
22
|
-
"vue": "^3.
|
|
23
|
-
"@stonecrop/
|
|
24
|
-
"@stonecrop/
|
|
35
|
+
"vue": "^3.4.23",
|
|
36
|
+
"@stonecrop/themes": "0.2.6",
|
|
37
|
+
"@stonecrop/utilities": "0.2.6"
|
|
25
38
|
},
|
|
26
39
|
"devDependencies": {
|
|
27
|
-
"@histoire/plugin-vue": "^0.
|
|
40
|
+
"@histoire/plugin-vue": "^0.17.17",
|
|
28
41
|
"@types/uuid": "^9.0.0",
|
|
29
42
|
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
|
30
43
|
"@typescript-eslint/parser": "^5.59.5",
|
|
31
|
-
"@vitejs/plugin-vue": "^
|
|
32
|
-
"@vitest/coverage-
|
|
33
|
-
"@vitest/ui": "^
|
|
44
|
+
"@vitejs/plugin-vue": "^5.0.4",
|
|
45
|
+
"@vitest/coverage-v8": "^1.5.0",
|
|
46
|
+
"@vitest/ui": "^1.5.0",
|
|
34
47
|
"@vue/test-utils": "^2.3.2",
|
|
35
48
|
"cypress": "^12.11.0",
|
|
36
49
|
"eslint": "^8.40.0",
|
|
37
50
|
"eslint-config-prettier": "^8.8.0",
|
|
38
51
|
"eslint-plugin-vue": "^9.11.1",
|
|
39
|
-
"histoire": "^0.
|
|
52
|
+
"histoire": "^0.17.17",
|
|
40
53
|
"jsdom": "^22.0.0",
|
|
41
54
|
"typescript": "^5.0.4",
|
|
42
|
-
"vite": "^
|
|
43
|
-
"vitest": "^
|
|
55
|
+
"vite": "^5.2.9",
|
|
56
|
+
"vitest": "^1.5.0",
|
|
44
57
|
"vue-router": "^4",
|
|
45
|
-
"@stonecrop/aform": "0.2.
|
|
58
|
+
"@stonecrop/aform": "0.2.6"
|
|
46
59
|
},
|
|
47
60
|
"peerDependencies": {
|
|
48
|
-
"@stonecrop/aform": "0.2.
|
|
61
|
+
"@stonecrop/aform": "0.2.6"
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
49
65
|
},
|
|
50
66
|
"engines": {
|
|
51
67
|
"node": ">=20.11.0"
|
|
52
68
|
},
|
|
53
|
-
"umd": "dist/atable.umd.cjs",
|
|
54
69
|
"scripts": {
|
|
55
70
|
"build": "tsc -b && vite build",
|
|
56
71
|
"dev": "vite",
|
|
@@ -91,7 +91,7 @@ provide(tableData.id, tableData)
|
|
|
91
91
|
|
|
92
92
|
watch(
|
|
93
93
|
() => tableData.rows,
|
|
94
|
-
|
|
94
|
+
newValue => {
|
|
95
95
|
emit('update:modelValue', newValue)
|
|
96
96
|
},
|
|
97
97
|
{ deep: true }
|
|
@@ -139,11 +139,11 @@ const formatCell = (event?: KeyboardEvent, column?: TableColumn, cellData?: any)
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
const moveCursorToEnd = (target: HTMLElement) => {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
142
|
+
// const moveCursorToEnd = (target: HTMLElement) => {
|
|
143
|
+
// target.focus()
|
|
144
|
+
// document.execCommand('selectAll', false, null)
|
|
145
|
+
// document.getSelection().collapseToEnd()
|
|
146
|
+
// }
|
|
147
147
|
|
|
148
148
|
const clickOutside = (event: MouseEvent) => {
|
|
149
149
|
if (!tableData.modal.parent?.contains(event.target as HTMLElement)) {
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { v4 } from 'uuid'
|
|
2
|
+
import { computed, reactive } from 'vue'
|
|
3
|
+
|
|
4
|
+
import type { TableDisplay, TableRow, TableColumn, TableConfig, TableModal } from '../../types'
|
|
5
|
+
|
|
6
|
+
export default class TableDataStore {
|
|
7
|
+
id: string
|
|
8
|
+
rows: TableRow[]
|
|
9
|
+
columns: TableColumn[]
|
|
10
|
+
config: TableConfig
|
|
11
|
+
table: { [key: string]: any }
|
|
12
|
+
display: TableDisplay[]
|
|
13
|
+
modal: TableModal
|
|
14
|
+
|
|
15
|
+
constructor(
|
|
16
|
+
id?: string,
|
|
17
|
+
columns?: TableColumn[],
|
|
18
|
+
rows?: TableRow[],
|
|
19
|
+
config?: TableConfig,
|
|
20
|
+
table?: { [key: string]: any },
|
|
21
|
+
display?: TableDisplay[]
|
|
22
|
+
) {
|
|
23
|
+
this.id = id || v4()
|
|
24
|
+
this.rows = rows
|
|
25
|
+
this.columns = reactive(columns)
|
|
26
|
+
this.config = reactive(config)
|
|
27
|
+
this.table = table || reactive(this.createTableObject())
|
|
28
|
+
this.display = this.createDisplayObject(display)
|
|
29
|
+
this.modal = reactive({ visible: false })
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
createTableObject() {
|
|
33
|
+
const table = {}
|
|
34
|
+
for (const [colIndex, column] of this.columns.entries()) {
|
|
35
|
+
for (const [rowIndex, row] of this.rows.entries()) {
|
|
36
|
+
table[`${colIndex}:${rowIndex}`] = row[column.name]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return table
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
createDisplayObject(display?: TableDisplay[]) {
|
|
43
|
+
const defaultDisplay: TableDisplay[] = [Object.assign({}, { modified: false })]
|
|
44
|
+
|
|
45
|
+
// TODO: (typing) what is the type of `display` here?
|
|
46
|
+
if (display) {
|
|
47
|
+
if ('0:0' in display) {
|
|
48
|
+
return display
|
|
49
|
+
}
|
|
50
|
+
// else if ('default' in display) {
|
|
51
|
+
// // TODO: (typing) what is the possible input here for 'default'?
|
|
52
|
+
// defaultDisplay = display.default
|
|
53
|
+
// }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// TODO: (typing) is this type correct for the parent set?
|
|
57
|
+
const parents = new Set<string | number>()
|
|
58
|
+
for (let rowIndex = this.rows.length - 1; rowIndex >= 0; rowIndex--) {
|
|
59
|
+
const row = this.rows[rowIndex]
|
|
60
|
+
if (row.parent) {
|
|
61
|
+
parents.add(row.parent)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
defaultDisplay[rowIndex] = {
|
|
65
|
+
childrenOpen: false,
|
|
66
|
+
expanded: false,
|
|
67
|
+
indent: row.indent || null,
|
|
68
|
+
isParent: parents.has(rowIndex),
|
|
69
|
+
isRoot: row.parent === null || row.parent === undefined,
|
|
70
|
+
modified: false,
|
|
71
|
+
open: row.parent === null || row.parent === undefined,
|
|
72
|
+
parent: row.parent,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return reactive(defaultDisplay)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get zeroColumn() {
|
|
80
|
+
return ['list', 'tree', 'list-expansion'].includes(this.config.view)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get numberedRowWidth() {
|
|
84
|
+
return computed(() => {
|
|
85
|
+
return String(Math.ceil(this.rows.length / 100) + 1) + 'ch'
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
cellData<T>(colIndex: number, rowIndex: number): T {
|
|
90
|
+
return this.table[`${colIndex}:${rowIndex}`]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
setCellData(rowIndex: number, colIndex: number, value: any) {
|
|
94
|
+
if (this.table[`${colIndex}:${rowIndex}`] !== value) {
|
|
95
|
+
this.display[rowIndex].modified = true
|
|
96
|
+
}
|
|
97
|
+
this.table[`${colIndex}:${rowIndex}`] = value
|
|
98
|
+
const col = this.columns[colIndex]
|
|
99
|
+
this.rows[rowIndex][col.name] = value
|
|
100
|
+
return this.table[`${colIndex}:${rowIndex}`]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
toggleRowExpand(rowIndex: number) {
|
|
104
|
+
if (this.config.view === 'tree') {
|
|
105
|
+
this.display[rowIndex].childrenOpen = !this.display[rowIndex].childrenOpen
|
|
106
|
+
for (let index = this.rows.length - 1; index >= 0; index--) {
|
|
107
|
+
if (this.display[index].parent === rowIndex) {
|
|
108
|
+
this.display[index].open = !this.display[index].open
|
|
109
|
+
if (this.display[index].childrenOpen) {
|
|
110
|
+
this.toggleRowExpand(index)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} else if (this.config.view === 'list-expansion') {
|
|
115
|
+
this.display[rowIndex].expanded = !this.display[rowIndex].expanded
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineSetupVue3 } from '@histoire/plugin-vue'
|
|
2
|
+
|
|
3
|
+
import ACell from '@/components/ACell.vue'
|
|
4
|
+
import AExpansionRow from '@/components/AExpansionRow.vue'
|
|
5
|
+
import ARow from '@/components/ARow.vue'
|
|
6
|
+
import ATable from '@/components/ATable.vue'
|
|
7
|
+
import ATableHeader from '@/components/ATableHeader.vue'
|
|
8
|
+
import ATableModal from '@/components/ATableModal.vue'
|
|
9
|
+
|
|
10
|
+
import { ADate, AForm, ANumericInput, ATextInput } from '@stonecrop/aform'
|
|
11
|
+
|
|
12
|
+
export const setupVue3 = defineSetupVue3(({ app }) => {
|
|
13
|
+
// TODO: (typing) add typing for ADate
|
|
14
|
+
app.component('ACell', ACell)
|
|
15
|
+
app.component('ADate', ADate)
|
|
16
|
+
app.component('AExpansionRow', AExpansionRow)
|
|
17
|
+
app.component('AForm', AForm)
|
|
18
|
+
app.component('ANumericInput', ANumericInput)
|
|
19
|
+
app.component('ARow', ARow)
|
|
20
|
+
app.component('ATable', ATable)
|
|
21
|
+
app.component('ATableHeader', ATableHeader)
|
|
22
|
+
app.component('ATableModal', ATableModal)
|
|
23
|
+
app.component('ATextInput', ATextInput)
|
|
24
|
+
})
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { App } from 'vue'
|
|
2
|
+
|
|
3
|
+
import ACell from '@/components/ACell.vue'
|
|
4
|
+
import AExpansionRow from '@/components/AExpansionRow.vue'
|
|
5
|
+
import ARow from '@/components/ARow.vue'
|
|
6
|
+
import ATable from '@/components/ATable.vue'
|
|
7
|
+
import ATableHeader from '@/components/ATableHeader.vue'
|
|
8
|
+
import ATableModal from '@/components/ATableModal.vue'
|
|
9
|
+
import TableDataStore from './components'
|
|
10
|
+
|
|
11
|
+
function install(app: App /* options */) {
|
|
12
|
+
app.component('ACell', ACell)
|
|
13
|
+
app.component('AExpansionRow', AExpansionRow)
|
|
14
|
+
app.component('ARow', ARow)
|
|
15
|
+
app.component('ATable', ATable)
|
|
16
|
+
app.component('ATableHeader', ATableHeader)
|
|
17
|
+
app.component('ATableModal', ATableModal)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { install, ACell, AExpansionRow, ARow, ATable, ATableHeader, ATableModal, TableDataStore }
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
/* THEME COLORS */
|
|
3
|
+
|
|
4
|
+
/* General Colors */
|
|
5
|
+
--primary-color: #0098c9; /* primary action color, default blue */
|
|
6
|
+
--primary-text-color: #ffffff; /* text color paired with primary color, default white */
|
|
7
|
+
--brand-color: #202a44; /* brand color, default navy */
|
|
8
|
+
|
|
9
|
+
/* Grays */
|
|
10
|
+
--gray-5: #f2f2f2;
|
|
11
|
+
--gray-10: #e6e6e6;
|
|
12
|
+
--gray-20: #cccccc;
|
|
13
|
+
--gray-50: #808080;
|
|
14
|
+
--gray-60: #666666;
|
|
15
|
+
--gray-80: #333333;
|
|
16
|
+
|
|
17
|
+
/* Table Colors */
|
|
18
|
+
--row-color-zebra-light: #eeeeee;
|
|
19
|
+
--row-color-zebra-dark: #dddddd;
|
|
20
|
+
--focus-cell-background: #ffffff;
|
|
21
|
+
--focus-cell-outline: #827553;
|
|
22
|
+
--cell-border-color: #ffffff;
|
|
23
|
+
--cell-text-color: #3a3c41;
|
|
24
|
+
--active-cell-background: #ffffff;
|
|
25
|
+
--active-cell-outline: #e6a92d;
|
|
26
|
+
--row-border-color: var(--gray-20);
|
|
27
|
+
--header-border-color: #ffffff;
|
|
28
|
+
--header-text-color: var(--gray-20);
|
|
29
|
+
--row-number-background-color: #ffffff;
|
|
30
|
+
|
|
31
|
+
/* Form Colors */
|
|
32
|
+
--input-border-color: var(--gray-20);
|
|
33
|
+
--input-label-color: var(--gray-80);
|
|
34
|
+
--input-active-border-color: var(--primary-color);
|
|
35
|
+
--input-active-label-color: var(--primary-color);
|
|
36
|
+
--required-border: #e63c28;
|
|
37
|
+
|
|
38
|
+
/* FONT */
|
|
39
|
+
--font-size: 11pt;
|
|
40
|
+
--font-family: Arimo, Arial, sans-serif;
|
|
41
|
+
--table-font-size: 11pt;
|
|
42
|
+
--atable-font-family: 'Arimo', sans-serif;
|
|
43
|
+
|
|
44
|
+
/* TABLE */
|
|
45
|
+
--atable-row-padding: 10px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
html,
|
|
49
|
+
body {
|
|
50
|
+
font-family: var(--atable-font-family);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.atable {
|
|
54
|
+
font-family: var(--atable-font-family);
|
|
55
|
+
-webkit-font-smoothing: antialiased;
|
|
56
|
+
-moz-osx-font-smoothing: grayscale;
|
|
57
|
+
font-size: var(--table-font-size);
|
|
58
|
+
border-collapse: collapse;
|
|
59
|
+
}
|