@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 CHANGED
@@ -1,8 +1,20 @@
1
1
  {
2
2
  "name": "@stonecrop/atable",
3
- "version": "0.2.5",
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/**/*.vue"
31
+ "src/*"
19
32
  ],
20
33
  "dependencies": {
21
34
  "uuid": "^9.0.0",
22
- "vue": "^3.2.47",
23
- "@stonecrop/utilities": "0.2.5",
24
- "@stonecrop/themes": "0.2.5"
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.16.1",
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": "^4.2.1",
32
- "@vitest/coverage-c8": "^0.31.0",
33
- "@vitest/ui": "^0.31.0",
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.16.1",
52
+ "histoire": "^0.17.17",
40
53
  "jsdom": "^22.0.0",
41
54
  "typescript": "^5.0.4",
42
- "vite": "^4.3.5",
43
- "vitest": "^0.31.0",
55
+ "vite": "^5.2.9",
56
+ "vitest": "^1.5.0",
44
57
  "vue-router": "^4",
45
- "@stonecrop/aform": "0.2.5"
58
+ "@stonecrop/aform": "0.2.6"
46
59
  },
47
60
  "peerDependencies": {
48
- "@stonecrop/aform": "0.2.5"
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
- (newValue, oldValue) => {
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
- target.focus()
144
- document.execCommand('selectAll', false, null)
145
- document.getSelection().collapseToEnd()
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,5 @@
1
+ declare module '*.vue' {
2
+ import { ComponentOptions } from 'vue'
3
+ const Component: ComponentOptions
4
+ export default Component
5
+ }
@@ -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
+ }