@stonecrop/atable 0.4.36 → 0.4.37

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.
@@ -281,7 +281,7 @@ export const createTableStore = (initData) => {
281
281
  }
282
282
  else if (typeof format === 'string') {
283
283
  // parse format function from string
284
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
284
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval, @typescript-eslint/no-unsafe-call
285
285
  const formatFn = Function(`"use strict";return (${format})`)();
286
286
  return formatFn(value, { table: table.value, row, column });
287
287
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/atable",
3
- "version": "0.4.36",
3
+ "version": "0.4.37",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": {
@@ -38,31 +38,31 @@
38
38
  "**/*.css"
39
39
  ],
40
40
  "dependencies": {
41
- "@vueuse/components": "^13.6.0",
42
- "@vueuse/core": "^13.6.0",
41
+ "@vueuse/components": "^14.0.0",
42
+ "@vueuse/core": "^14.0.0",
43
43
  "pinia": "^3.0.3",
44
44
  "vue": "^3.5.22",
45
- "@stonecrop/themes": "0.4.36",
46
- "@stonecrop/utilities": "0.4.36"
45
+ "@stonecrop/themes": "0.4.37",
46
+ "@stonecrop/utilities": "0.4.37"
47
47
  },
48
48
  "devDependencies": {
49
- "@microsoft/api-documenter": "^7.26.31",
50
- "@rushstack/heft": "^0.74.2",
51
- "@typescript-eslint/eslint-plugin": "^7.18.0",
52
- "@typescript-eslint/parser": "^7.18.0",
49
+ "@eslint/js": "^9.38.0",
50
+ "@microsoft/api-documenter": "^7.27.3",
51
+ "@rushstack/heft": "^1.1.3",
53
52
  "@vitejs/plugin-vue": "^6.0.1",
54
- "@vitest/coverage-istanbul": "^3.2.4",
55
- "@vitest/ui": "^3.2.4",
53
+ "@vitest/coverage-istanbul": "^4.0.5",
54
+ "@vitest/ui": "^4.0.5",
56
55
  "@vue/test-utils": "^2.4.6",
57
- "cypress": "^14.5.3",
58
- "eslint-config-prettier": "^8.10.0",
59
- "eslint-plugin-vue": "^9.33.0",
60
- "eslint": "^8.57.1",
61
- "jsdom": "^26.1.0",
56
+ "eslint-config-prettier": "^10.1.8",
57
+ "eslint-plugin-vue": "^10.5.1",
58
+ "eslint": "^9.38.0",
59
+ "globals": "^16.4.0",
60
+ "jsdom": "^27.1.0",
62
61
  "typescript": "^5.9.3",
62
+ "typescript-eslint": "^8.46.2",
63
63
  "vite-plugin-lib-inject-css": "^2.2.2",
64
64
  "vite": "^7.1.1",
65
- "vitest": "^3.2.4",
65
+ "vitest": "^4.0.5",
66
66
  "vue-router": "^4.6.3",
67
67
  "stonecrop-rig": "0.2.22"
68
68
  },
@@ -78,7 +78,7 @@
78
78
  "build": "heft build && vite build && rushx docs",
79
79
  "dev": "vite",
80
80
  "docs": "cd ../common/autoinstallers/doc-tools && node generate-docs.mjs atable",
81
- "lint": "eslint . --ext .ts,.vue",
81
+ "lint": "eslint .",
82
82
  "preview": "vite preview",
83
83
  "test": "vitest run --coverage.enabled false",
84
84
  "test:watch": "vitest watch",
@@ -8,15 +8,15 @@
8
8
  :tabindex="tabIndex"
9
9
  :spellcheck="false"
10
10
  :style="cellStyle"
11
+ class="atable-cell"
12
+ :class="cellClasses"
11
13
  @focus="onFocus"
12
14
  @paste="updateCellData"
13
15
  @input="debouncedUpdateCellData"
14
- @click="onCellClick"
15
- class="atable-cell"
16
- :class="cellClasses">
16
+ @click="onCellClick">
17
17
  <component
18
- v-if="column.cellComponent"
19
18
  :is="column.cellComponent"
19
+ v-if="column.cellComponent"
20
20
  :value="displayValue"
21
21
  v-bind="column.cellComponentProps" />
22
22
  <span v-else-if="isHtmlValue" v-html="displayValue" />
@@ -173,7 +173,7 @@ const selectAllText = () => {
173
173
  selection.removeAllRanges()
174
174
  selection.addRange(range)
175
175
  }
176
- } catch (error) {
176
+ } catch {
177
177
  // Fallback for environments where Range API is not fully supported
178
178
  // This is expected in some test environments
179
179
  }
@@ -202,7 +202,7 @@ const saveCursorPosition = () => {
202
202
  return preCaretRange.toString().length
203
203
  }
204
204
  }
205
- } catch (error) {
205
+ } catch {
206
206
  // Fallback for environments where Selection API is not fully supported
207
207
  }
208
208
  return 0
@@ -227,7 +227,7 @@ const restoreCursorPosition = (position: number) => {
227
227
 
228
228
  while ((node = walker.nextNode())) {
229
229
  const textNode = node as Text
230
- const nextCharIndex = charIndex + textNode.textContent!.length
230
+ const nextCharIndex = charIndex + textNode.textContent.length
231
231
 
232
232
  if (position <= nextCharIndex) {
233
233
  range = document.createRange()
@@ -244,7 +244,7 @@ const restoreCursorPosition = (position: number) => {
244
244
  selection.removeAllRanges()
245
245
  selection.addRange(range)
246
246
  }
247
- } catch (error) {
247
+ } catch {
248
248
  // Fallback for environments where DOM APIs are not fully supported
249
249
  }
250
250
  }
@@ -266,7 +266,7 @@ const updateCellData = (payload: Event) => {
266
266
  if (column.format) {
267
267
  cellModified.value = target.textContent !== store.getFormattedValue(colIndex, rowIndex, originalData)
268
268
  // TODO: need to setup reverse format function?
269
- store.setCellText(colIndex, rowIndex, target.textContent!)
269
+ store.setCellText(colIndex, rowIndex, target.textContent)
270
270
  } else {
271
271
  cellModified.value = target.textContent !== originalData
272
272
  store.setCellData(colIndex, rowIndex, target.textContent)
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <tr v-bind="$attrs" ref="rowEl" :tabindex="tabIndex" class="expandable-row">
3
- <td :tabIndex="-1" @click="store.toggleRowExpand(rowIndex)" class="row-index">
3
+ <td :tabIndex="-1" class="row-index" @click="store.toggleRowExpand(rowIndex)">
4
4
  {{ rowExpandSymbol }}
5
5
  </td>
6
6
  <slot name="row" />
@@ -13,7 +13,7 @@
13
13
  </template>
14
14
 
15
15
  <script setup lang="ts">
16
- import { type KeypressHandlers, useKeyboardNav } from '@stonecrop/utilities'
16
+ import { defaultKeypressHandlers, type KeypressHandlers, useKeyboardNav } from '@stonecrop/utilities'
17
17
  import { computed, useTemplateRef } from 'vue'
18
18
 
19
19
  import { createTableStore } from '../stores/table'
@@ -22,7 +22,7 @@ const {
22
22
  rowIndex,
23
23
  store,
24
24
  tabIndex = -1,
25
- addNavigation,
25
+ addNavigation = defaultKeypressHandlers,
26
26
  } = defineProps<{
27
27
  rowIndex: number
28
28
  store: ReturnType<typeof createTableStore>
@@ -75,9 +75,9 @@ const {
75
75
  rowIndex,
76
76
  colIndex,
77
77
  start = 0,
78
- end,
78
+ end = 0,
79
79
  colspan = 1,
80
- label,
80
+ label = '',
81
81
  color = '#cccccc',
82
82
  } = defineProps<{
83
83
  store: ReturnType<typeof createTableStore>
@@ -100,12 +100,12 @@ const barColor = ref(color.length >= 6 ? color : '#cccccc')
100
100
  const barId = `gantt-bar-row-${rowIndex}-col-${colIndex}`
101
101
 
102
102
  // Template refs
103
- const containerRef = useTemplateRef('container')
104
- const barRef = useTemplateRef('bar')
105
- const leftResizeHandleRef = useTemplateRef('leftResizeHandle')
106
- const rightResizeHandleRef = useTemplateRef('rightResizeHandle')
107
- const leftConnectionHandleRef = useTemplateRef('leftConnectionHandle')
108
- const rightConnectionHandleRef = useTemplateRef('rightConnectionHandle')
103
+ const containerRef = useTemplateRef<HTMLDivElement>('container')
104
+ const barRef = useTemplateRef<HTMLDivElement>('bar')
105
+ const leftResizeHandleRef = useTemplateRef<HTMLDivElement>('leftResizeHandle')
106
+ const rightResizeHandleRef = useTemplateRef<HTMLDivElement>('rightResizeHandle')
107
+ const leftConnectionHandleRef = useTemplateRef<HTMLDivElement>('leftConnectionHandle')
108
+ const rightConnectionHandleRef = useTemplateRef<HTMLDivElement>('rightConnectionHandle')
109
109
 
110
110
  // Position tracking
111
111
  const { width: totalBarWidth } = useElementBounding(containerRef)
@@ -40,13 +40,13 @@
40
40
  <!-- Visible connection path -->
41
41
  <path
42
42
  v-for="connection in visibleConnections"
43
+ :id="connection.id"
43
44
  :key="connection.id"
44
45
  :d="getPathData(connection)"
45
46
  :stroke="connection.style?.color || '#666'"
46
47
  :stroke-width="connection.style?.width || 2"
47
48
  fill="none"
48
49
  marker-mid="url(#arrowhead-marker)"
49
- :id="connection.id"
50
50
  class="connection-path animated-path"
51
51
  @dblclick="handleConnectionDelete(connection)" />
52
52
  </svg>
@@ -78,7 +78,7 @@ const visibleConnections = computed(() => {
78
78
  })
79
79
  })
80
80
 
81
- const getPathData = (connection: ConnectionPath, isMarker: Boolean = false) => {
81
+ const getPathData = (connection: ConnectionPath) => {
82
82
  const fromHandle = store.connectionHandles.find(
83
83
  handle => handle.barId === connection.from.barId && handle.side === connection.from.side
84
84
  )
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <tr ref="rowEl" :tabindex="tabIndex" v-show="isRowVisible" class="atable-row">
2
+ <tr v-show="isRowVisible" ref="rowEl" :tabindex="tabIndex" class="atable-row">
3
3
  <!-- render numbered/tree view index; skip render for uncounted lists -->
4
- <slot name="index" v-if="store.config.view !== 'uncounted'">
4
+ <slot v-if="store.config.view !== 'uncounted'" name="index">
5
5
  <td
6
6
  v-if="store.config.view === 'list'"
7
7
  :tabIndex="-1"
@@ -3,31 +3,31 @@
3
3
  <!-- Main table view -->
4
4
  <table
5
5
  ref="table"
6
+ v-on-click-outside="store.closeModal"
6
7
  class="atable"
7
8
  :style="{
8
9
  width: store.config.fullWidth ? '100%' : 'auto',
9
- }"
10
- v-on-click-outside="store.closeModal">
10
+ }">
11
11
  <slot name="header" :data="store">
12
12
  <ATableHeader :columns="store.columns" :store="store" />
13
13
  </slot>
14
14
 
15
15
  <tbody>
16
16
  <slot name="body" :data="store">
17
- <ARow v-for="(row, rowIndex) in store.rows" :key="row.id" :row="row" :rowIndex="rowIndex" :store="store">
17
+ <ARow v-for="(row, rowIndex) in store.rows" :key="row.id" :row="row" :row-index="rowIndex" :store="store">
18
18
  <template v-for="(column, colIndex) in getProcessedColumnsForRow(row)" :key="column.name">
19
19
  <component
20
- v-if="column.isGantt"
21
20
  :is="column.ganttComponent || 'AGanttCell'"
21
+ v-if="column.isGantt"
22
22
  :store="store"
23
- :columnsCount="store.columns.length - pinnedColumnCount"
23
+ :columns-count="store.columns.length - pinnedColumnCount"
24
24
  :color="row.gantt?.color"
25
25
  :start="row.gantt?.startIndex"
26
26
  :end="row.gantt?.endIndex"
27
27
  :colspan="column.colspan"
28
28
  :pinned="column.pinned"
29
- :rowIndex="rowIndex"
30
- :colIndex="column.originalIndex ?? colIndex"
29
+ :row-index="rowIndex"
30
+ :col-index="column.originalIndex ?? colIndex"
31
31
  :style="{
32
32
  textAlign: column?.align || 'center',
33
33
  minWidth: column?.width || '40ch',
@@ -35,12 +35,12 @@
35
35
  }"
36
36
  @connection:create="handleConnectionCreate" />
37
37
  <component
38
- v-else
39
38
  :is="column.cellComponent || 'ACell'"
39
+ v-else
40
40
  :store="store"
41
41
  :pinned="column.pinned"
42
- :rowIndex="rowIndex"
43
- :colIndex="colIndex"
42
+ :row-index="rowIndex"
43
+ :col-index="colIndex"
44
44
  :style="{
45
45
  textAlign: column?.align || 'center',
46
46
  width: store.config.fullWidth ? 'auto' : null,
@@ -58,10 +58,10 @@
58
58
  <ATableModal v-show="store.modal.visible" :store="store">
59
59
  <template #default>
60
60
  <component
61
- :key="`${store.modal.rowIndex}:${store.modal.colIndex}`"
62
61
  :is="store.modal.component"
63
- :colIndex="store.modal.colIndex"
64
- :rowIndex="store.modal.rowIndex"
62
+ :key="`${store.modal.rowIndex}:${store.modal.colIndex}`"
63
+ :col-index="store.modal.colIndex"
64
+ :row-index="store.modal.rowIndex"
65
65
  :store="store"
66
66
  v-bind="store.modal.componentProps" />
67
67
  </template>
@@ -92,7 +92,7 @@ import type { ConnectionEvent, ConnectionPath, GanttDragEvent, TableColumn, Tabl
92
92
  const rows = defineModel<TableRow[]>('rows', { required: true })
93
93
  const columns = defineModel<TableColumn[]>('columns', { required: true })
94
94
 
95
- const { id, config = new Object() } = defineProps<{
95
+ const { id = '', config = new Object() } = defineProps<{
96
96
  id?: string
97
97
  config?: TableConfig
98
98
  }>()
@@ -12,8 +12,8 @@
12
12
  class="list-index" />
13
13
  <th
14
14
  v-for="(column, colKey) in columns"
15
- v-resize-observer="onResize"
16
15
  :key="column.name"
16
+ v-resize-observer="onResize"
17
17
  :data-colindex="colKey"
18
18
  tabindex="-1"
19
19
  :style="store.getHeaderCellStyle(column)"
@@ -1,12 +1,12 @@
1
1
  <template>
2
- <div class="amodal" ref="amodal" tabindex="-1" @click.stop @input.stop :style="amodalStyles">
2
+ <div ref="amodal" class="amodal" tabindex="-1" :style="amodalStyles" @click.stop @input.stop>
3
3
  <slot />
4
4
  </div>
5
5
  </template>
6
6
 
7
7
  <script setup lang="ts">
8
8
  import { useElementBounding } from '@vueuse/core'
9
- import { useTemplateRef, computed } from 'vue'
9
+ import { useTemplateRef, computed, type StyleValue } from 'vue'
10
10
 
11
11
  import { createTableStore } from '../stores/table'
12
12
 
@@ -15,11 +15,12 @@ const { store } = defineProps<{ store: ReturnType<typeof createTableStore> }>()
15
15
  const amodalRef = useTemplateRef('amodal')
16
16
  const { width: modalWidth, height: modalHeight } = useElementBounding(amodalRef)
17
17
 
18
- const amodalStyles = computed(() => {
18
+ const amodalStyles = computed((): StyleValue => {
19
19
  if (!(store.modal.height && store.modal.width && store.modal.left && store.modal.bottom)) return
20
20
 
21
- // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
22
- const table = store.modal.cell?.closest('table')!
21
+ const table = store.modal.cell?.closest('table')
22
+ if (!table) return {}
23
+
23
24
  const maxHeight = table.offsetHeight || 0
24
25
  const maxWidth = table.offsetWidth || 0
25
26
 
@@ -351,7 +351,7 @@ export const createTableStore = (initData: {
351
351
  return format(value, { table: table.value, row, column })
352
352
  } else if (typeof format === 'string') {
353
353
  // parse format function from string
354
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
354
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval, @typescript-eslint/no-unsafe-call
355
355
  const formatFn: (value: any, context?: CellContext) => string = Function(`"use strict";return (${format})`)()
356
356
  return formatFn(value, { table: table.value, row, column })
357
357
  }