@studio-west/component-sw 0.12.12 → 0.12.14

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.
@@ -1,5 +1,13 @@
1
1
  <template>
2
- <table class="sw-table">
2
+ <!-- Скрытый рендер слота: монтирует SwTableColumn, которые регистрируют себя через inject -->
3
+ <div style="display: none;" aria-hidden="true"><slot /></div>
4
+ <div
5
+ ref="wrapperRef"
6
+ class="sw-table-wrapper"
7
+ :class="{ 'fixed-active': isFixedActive }"
8
+ :style="wrapperStyle"
9
+ >
10
+ <table ref="tableRef" class="sw-table" :class="{ 'resizing': isResizing }">
3
11
  <thead>
4
12
  <tr v-for="(row, rowIndex) in headerRows" :key="rowIndex">
5
13
  <th
@@ -7,40 +15,43 @@
7
15
  :key="cell.key"
8
16
  :colspan="cell.colspan"
9
17
  :rowspan="cell.rowspan"
10
- :style="{ minWidth: cell.width, minHeight: cell.height }"
18
+ :class="getHeaderCellClass(cell)"
19
+ :style="getHeaderCellStyle(cell)"
20
+ @mouseenter="onHeaderEnter(cell)"
21
+ @mouseleave="onHeaderLeave"
11
22
  >
12
23
  {{ cell.label }}
24
+ <span
25
+ v-if="isResizableLeaf(cell)"
26
+ class="resize-handle"
27
+ @mousedown.prevent="startResize($event, cell)"
28
+ />
13
29
  </th>
14
30
  </tr>
15
31
  </thead>
16
32
  <tbody>
17
- <tr v-for="(row, rowIndex) in processedTableData" :key="rowIndex">
33
+ <tr
34
+ v-for="(row, rowIndex) in processedTableData"
35
+ :key="rowIndex"
36
+ @mouseenter="hoveredRowIndex = rowIndex"
37
+ @mouseleave="hoveredRowIndex = null"
38
+ >
18
39
  <td
19
40
  v-for="cell in row"
20
41
  :key="cell.key"
21
42
  :colspan="cell.colspan"
22
43
  :rowspan="cell.rowspan"
23
- :style="cell.style"
44
+ :class="getBodyCellClass(cell, rowIndex)"
45
+ :style="getBodyCellStyle(cell)"
24
46
  >
25
- <!-- Сначала пробуем именованный слот по prop -->
47
+ <!-- Именованный слот по prop колонки -->
26
48
  <slot
27
- v-if="slots[cell.prop]"
49
+ v-if="cell.prop && slots[cell.prop]"
28
50
  :name="cell.prop"
29
51
  :row="cell.originalRow"
30
52
  :$index="cell.rowIndex"
31
53
  :value="cell.label"
32
54
  />
33
- <!-- Затем пробуем слот default с данными конкретной ячейки -->
34
- <slot
35
- v-else-if="slots.default"
36
- name="default"
37
- :row="cell.originalRow"
38
- :$index="cell.rowIndex"
39
- :column="cell.prop"
40
- :value="cell.label"
41
- >
42
- {{ cell.label }}
43
- </slot>
44
55
  <!-- Fallback на простое значение -->
45
56
  <template v-else>
46
57
  {{ cell.label }}
@@ -49,63 +60,195 @@
49
60
  </tr>
50
61
  </tbody>
51
62
  </table>
63
+ </div>
52
64
  </template>
53
65
 
54
66
  <script setup>
55
- import { ref, useSlots, watch, onMounted, computed } from 'vue'
56
- import SwTableColumn from './SwTableColumn.vue'
67
+ import {
68
+ ref, useSlots, computed, watchEffect, provide, reactive,
69
+ onMounted, onUnmounted, nextTick, watch
70
+ } from 'vue'
57
71
 
58
72
  const props = defineProps({
59
- data: {
60
- type: Array,
61
- required: true
62
- }
73
+ data: { type: Array, required: true },
74
+ resizable: { type: Boolean, default: true },
75
+ maxWidth: { type: [String, Number], default: undefined }
63
76
  })
64
77
 
78
+ const emit = defineEmits(['column-resize'])
79
+
65
80
  const slots = useSlots()
66
- const columnTree = ref([])
67
- // Функция для построения дерева колонок
68
- function buildColumnTree(vnodes) {
69
- const result = []
81
+ const columnTree = reactive([])
82
+ const columnWidths = ref({})
83
+ const isResizing = ref(false)
84
+ const hoveredColIndices = ref(null)
85
+ const hoveredRowIndex = ref(null)
86
+ const wrapperRef = ref(null)
87
+ const tableRef = ref(null)
88
+ const isOverflowing = ref(false)
89
+ const isClient = typeof window !== 'undefined' && typeof document !== 'undefined'
90
+ let columnOrder = 0
91
+ let resizeObserver = null
70
92
 
71
- for (const vnode of vnodes) {
72
- // Handle fragments (from v-for)
73
- if (vnode.type === Symbol.for('v-fgt') || Array.isArray(vnode.children)) {
74
- const children = Array.isArray(vnode.children) ? vnode.children : []
75
- const childColumns = buildColumnTree(children)
76
- result.push(...childColumns)
77
- continue
78
- }
93
+ provide('swTableColumns', columnTree)
94
+ provide('swTableAllocColumnOrder', () => columnOrder++)
79
95
 
80
- // Check if this is a SwTableColumn component using multiple detection methods
81
- const isTableColumn =
82
- vnode.type === SwTableColumn ||
83
- (vnode.type.__name === 'SwTableColumn') ||
84
- (vnode.type.name === 'SwTableColumn') ||
85
- (typeof vnode.type === 'object' && vnode.type.name === 'AsyncComponentWrapper' && vnode.props?.prop !== undefined) ||
86
- (typeof vnode.type === 'object' && vnode.props?.prop !== undefined) ||
87
- (typeof vnode.type === 'object' && vnode.props?.label !== undefined)
88
-
89
- if (isTableColumn) {
90
- const column = {
91
- ...vnode.props,
92
- children: []
93
- }
94
-
95
- // Handle both function and array children
96
- let children = []
97
- if (typeof vnode.children?.default === 'function') {
98
- try {children = vnode.children.default()}
99
- catch (e) {console.warn('Error calling default slot:', e)}
100
- } else if (Array.isArray(vnode.children)) children = vnode.children
101
- if (children && children.length > 0) {
102
- const childColumns = buildColumnTree(children)
103
- if (childColumns.length > 0) column.children = childColumns
104
- }
105
- result.push(column)
96
+ function parseWidth(width) {
97
+ if (width == null || width === 'auto') return null
98
+ if (typeof width === 'number') return width
99
+ const parsed = parseInt(width, 10)
100
+ return Number.isNaN(parsed) ? null : parsed
101
+ }
102
+ function formatWidth(width) {
103
+ return width == null ? undefined : `${width}px`
104
+ }
105
+ function getColumnWidth(prop, defaultWidth) {
106
+ if (columnWidths.value[prop] != null) return columnWidths.value[prop]
107
+ return parseWidth(defaultWidth)
108
+ }
109
+ function getColumnWidthStyle(prop, defaultWidth) {
110
+ const width = getColumnWidth(prop, defaultWidth)
111
+ if (width == null) return {}
112
+ const formatted = formatWidth(width)
113
+ return { width: formatted, minWidth: formatted }
114
+ }
115
+ function getColumnPixelWidth(column) {
116
+ if (!column?.prop) return parseWidth(column?.width) ?? parseWidth(column?.minWidth) ?? 80
117
+ return getColumnWidth(column.prop, column.width)
118
+ ?? parseWidth(column.minWidth) ?? 80
119
+ }
120
+ function getLeftOffsetForColIndex(colIndex) {
121
+ let offset = 0
122
+ for (let i = 0; i < colIndex; i++) {
123
+ offset += getColumnPixelWidth(flatColumns.value[i])
124
+ }
125
+ return offset
126
+ }
127
+ function getRightOffsetForColIndex(colIndex) {
128
+ let offset = 0
129
+ const columns = flatColumns.value
130
+ for (let i = columns.length - 1; i > colIndex; i--) {
131
+ offset += getColumnPixelWidth(columns[i])
132
+ }
133
+ return offset
134
+ }
135
+ function getCellFixedSide(cell) {
136
+ if (cell.fixed) return cell.fixed
137
+ if (cell.prop) return flatColumns.value.find((col) => col.prop === cell.prop)?.fixed
138
+ if (!cell.colIndices?.length) return null
139
+ const sides = cell.colIndices.map((i) => flatColumns.value[i]?.fixed).filter(Boolean)
140
+ if (sides.length && sides.every((side) => side === 'left')) return 'left'
141
+ if (sides.length && sides.every((side) => side === 'right')) return 'right'
142
+ return null
143
+ }
144
+ function getFixedPositionStyle(cell, inHeader = false) {
145
+ const side = getCellFixedSide(cell)
146
+ if (!side) return {}
147
+ const startIndex = cell.colIndex ?? cell.colIndices[0]
148
+ const endIndex = cell.colIndex != null
149
+ ? cell.colIndex + (cell.colspan || 1) - 1
150
+ : cell.colIndices[cell.colIndices.length - 1]
151
+ const zBase = inHeader ? 100 : 0
152
+ if (side === 'left') {
153
+ return {
154
+ position: 'sticky',
155
+ left: `${getLeftOffsetForColIndex(startIndex)}px`,
156
+ zIndex: zBase + startIndex + 1
106
157
  }
107
158
  }
108
- return result
159
+ return {
160
+ position: 'sticky',
161
+ right: `${getRightOffsetForColIndex(endIndex)}px`,
162
+ zIndex: zBase + flatColumns.value.length - endIndex
163
+ }
164
+ }
165
+ function getHeaderCellStyle(cell) {
166
+ const style = { minHeight: cell.height && cell.height !== 'auto' ? cell.height : undefined}
167
+ if (cell.prop) Object.assign(style, getColumnWidthStyle(cell.prop, cell.width))
168
+ else if (cell.width && cell.width !== 'auto') style.minWidth = formatWidth(parseWidth(cell.width)) || cell.width
169
+ if (isFixedActive.value) Object.assign(style, getFixedPositionStyle(cell, true))
170
+ return style
171
+ }
172
+ function getBodyCellStyle(cell) {
173
+ const style = { ...cell.style }
174
+ if (isFixedActive.value) Object.assign(style, getFixedPositionStyle(cell))
175
+ return style
176
+ }
177
+ function isResizableLeaf(cell) {
178
+ if (!props.resizable || !cell.prop) return false
179
+ return cell.resizable !== false
180
+ }
181
+ function onHeaderEnter(cell) {hoveredColIndices.value = new Set(cell.colIndices)}
182
+ function onHeaderLeave() {hoveredColIndices.value = null}
183
+ function cellCoversHoveredColumn(cell) {
184
+ if (!hoveredColIndices.value) return false
185
+ const start = cell.colIndex
186
+ const end = start + (cell.colspan || 1) - 1
187
+ for (let i = start; i <= end; i++) {
188
+ if (hoveredColIndices.value.has(i)) return true
189
+ }
190
+ return false
191
+ }
192
+ function isRowHoveredForCell(cell, rowIndex) {
193
+ const hover = hoveredRowIndex.value
194
+ if (hover === null) return false
195
+ return rowIndex <= hover && hover < rowIndex + (cell.rowspan || 1)
196
+ }
197
+ function getFixedCellClass(cell) {
198
+ const side = getCellFixedSide(cell)
199
+ return {
200
+ 'fixed-left': isFixedActive.value && side === 'left',
201
+ 'fixed-right': isFixedActive.value && side === 'right'
202
+ }
203
+ }
204
+ function getBodyCellClass(cell, rowIndex) {
205
+ const colHover = cellCoversHoveredColumn(cell)
206
+ const rowHover = isRowHoveredForCell(cell, rowIndex)
207
+ return {
208
+ ...getFixedCellClass(cell),
209
+ 'col-hover': colHover && !rowHover,
210
+ 'row-hover': rowHover && !colHover
211
+ }
212
+ }
213
+ function getHeaderCellClass(cell) {
214
+ return {
215
+ ...getFixedCellClass(cell),
216
+ 'resizable': isResizableLeaf(cell),
217
+ 'col-hover': cellCoversHoveredColumn(cell)
218
+ }
219
+ }
220
+ function getMinResizeWidth(cell) {
221
+ return parseWidth(cell.minWidth) ?? 48
222
+ }
223
+ function startResize(event, cell) {
224
+ if (!isClient) return
225
+ const th = event.currentTarget.closest('th')
226
+ if (!th || !cell.prop) return
227
+ const prop = cell.prop
228
+ const startX = event.clientX
229
+ const startWidth = getColumnWidth(prop, cell.width) ?? th.offsetWidth
230
+ const minWidth = getMinResizeWidth(cell)
231
+ isResizing.value = true
232
+ document.body.style.cursor = 'col-resize'
233
+ document.body.style.userSelect = 'none'
234
+ const onMouseMove = (e) => {
235
+ const nextWidth = Math.max(minWidth, startWidth + (e.clientX - startX))
236
+ columnWidths.value = { ...columnWidths.value, [prop]: nextWidth }
237
+ }
238
+ const onMouseUp = () => {
239
+ document.removeEventListener('mousemove', onMouseMove)
240
+ document.removeEventListener('mouseup', onMouseUp)
241
+ document.body.style.cursor = ''
242
+ document.body.style.userSelect = ''
243
+ isResizing.value = false
244
+ emit('column-resize', { prop, width: columnWidths.value[prop] })
245
+ nextTick(updateOverflowState)
246
+ }
247
+ document.addEventListener('mousemove', onMouseMove)
248
+ document.addEventListener('mouseup', onMouseUp)
249
+ }
250
+ function sortColumns(columns) {
251
+ return [...columns].sort((a, b) => a.order - b.order)
109
252
  }
110
253
 
111
254
  // Получение максимальной глубины дерева
@@ -124,26 +267,27 @@ function getMaxDepth(columns) {
124
267
  // Преобразование дерева в строки для thead
125
268
  function buildHeaderRows(columns, depth) {
126
269
  const rows = Array.from({ length: depth }, () => [])
127
-
270
+ let leafColIndex = 0
128
271
  function processColumns(cols, rowIndex, parentKey = '') {
129
- for (let i = 0; i < cols.length; i++) {
130
- const col = cols[i]
272
+ const sortedCols = sortColumns(cols)
273
+ for (let i = 0; i < sortedCols.length; i++) {
274
+ const col = sortedCols[i]
131
275
  const key = parentKey ? `${parentKey}-${col.prop || i}` : (col.prop || i)
132
-
133
276
  if (col.children && col.children.length > 0) {
134
- // Это родительская колонка
277
+ const startIndex = leafColIndex
135
278
  const leafCount = countLeafColumns(col.children)
279
+ processColumns(col.children, rowIndex + 1, key)
136
280
  rows[rowIndex].push({
137
281
  key,
138
282
  label: col.label,
139
283
  colspan: leafCount,
140
284
  rowspan: 1,
141
285
  width: col.width,
142
- height: col.height
286
+ height: col.height,
287
+ colIndices: Array.from({ length: leafCount }, (_, j) => startIndex + j)
143
288
  })
144
- processColumns(col.children, rowIndex + 1, key)
145
289
  } else {
146
- // Это конечная колонка
290
+ const colIndex = leafColIndex++
147
291
  rows[rowIndex].push({
148
292
  key: col.prop,
149
293
  label: col.label,
@@ -151,7 +295,11 @@ function buildHeaderRows(columns, depth) {
151
295
  rowspan: depth - rowIndex,
152
296
  width: col.width,
153
297
  height: col.height,
154
- prop: col.prop
298
+ prop: col.prop,
299
+ resizable: col.resizable,
300
+ minWidth: col.minWidth,
301
+ colIndex,
302
+ colIndices: [colIndex]
155
303
  })
156
304
  }
157
305
  }
@@ -163,9 +311,8 @@ function buildHeaderRows(columns, depth) {
163
311
  // Подсчет количества листовых колонок
164
312
  function countLeafColumns(columns) {
165
313
  let count = 0
166
-
167
314
  function traverse(cols) {
168
- for (const col of cols) {
315
+ for (const col of sortColumns(cols)) {
169
316
  if (col.children && col.children.length > 0) traverse(col.children)
170
317
  else count++
171
318
  }
@@ -177,9 +324,8 @@ function countLeafColumns(columns) {
177
324
  // Извлечение плоского списка конечных колонок
178
325
  function extractLeafColumns(columns) {
179
326
  const result = []
180
-
181
327
  function traverse(cols) {
182
- for (const col of cols) {
328
+ for (const col of sortColumns(cols)) {
183
329
  if (col.children && col.children.length > 0) traverse(col.children)
184
330
  else result.push(col)
185
331
  }
@@ -190,17 +336,21 @@ function extractLeafColumns(columns) {
190
336
 
191
337
  // Обработка данных для tbody с поддержкой colspan
192
338
  function processBodyData(data, columns) {
339
+
193
340
  // Защита от undefined/null значений
194
341
  if (!data || !Array.isArray(data)) return []
195
342
  if (!columns || !Array.isArray(columns)) return []
343
+
196
344
  // Функция для получения значения по пути (например, "gant.0")
197
345
  function getValueByPath(obj, path) {
198
346
  if (!obj || !path) return undefined
347
+
199
348
  // Разбиваем путь по точкам
200
349
  const keys = path.split('.')
201
350
  let value = obj
202
351
  for (const key of keys) {
203
352
  if (value === null || value === undefined) return undefined
353
+
204
354
  // Пробуем обратиться как к свойству объекта или элементу массива
205
355
  value = value[key]
206
356
  }
@@ -211,9 +361,11 @@ function processBodyData(data, columns) {
211
361
  data.forEach((row, rowIndex) => {
212
362
  const processedRow = []
213
363
  columns.forEach((column, colIndex) => {
214
- const key = `${rowIndex}-${column.prop}`
364
+ const key = `${rowIndex}-${colIndex}`
365
+
215
366
  // Проверяем, не занята ли эта ячейка из-за rowspan/colspan
216
367
  if (cellMap.has(key)) return
368
+
217
369
  // Получаем значение по пути (поддержка "gant.0", "gant.1" и т.д.)
218
370
  const cellData = getValueByPath(row, column.prop)
219
371
  let cellValue = cellData
@@ -228,10 +380,16 @@ function processBodyData(data, columns) {
228
380
  rowspan = cellData.rowspan || 1
229
381
  style = cellData.style || {}
230
382
  }
383
+ style = {
384
+ ...style,
385
+ ...getColumnWidthStyle(column.prop, column.width)
386
+ }
231
387
  const cell = {
232
388
  key,
233
389
  label: cellValue,
234
390
  prop: column.prop,
391
+ fixed: column.fixed,
392
+ colIndex,
235
393
  colspan,
236
394
  rowspan,
237
395
  style,
@@ -243,46 +401,72 @@ function processBodyData(data, columns) {
243
401
  for (let r = 0; r < rowspan; r++) {
244
402
  for (let c = 0; c < colspan; c++) {
245
403
  if (r === 0 && c === 0) continue // Основная ячейка
246
- const cellKey = `${rowIndex + r}-${columns[colIndex + c]?.prop}`
247
- if (cellKey) cellMap.set(cellKey, true)
404
+ const cellKey = `${rowIndex + r}-${colIndex + c}`
405
+ cellMap.set(cellKey, true)
248
406
  }
249
407
  }
250
408
  })
251
-
252
409
  if (processedRow.length > 0) {
253
410
  processedRows.push(processedRow)
254
411
  }
255
412
  })
256
-
257
413
  return processedRows
258
414
  }
259
415
 
260
416
  // Вычисляемые свойства
261
- const maxDepth = computed(() => getMaxDepth(columnTree.value))
262
- const headerRows = computed(() => buildHeaderRows(columnTree.value, maxDepth.value))
263
- const flatColumns = computed(() => extractLeafColumns(columnTree.value))
417
+ const maxDepth = computed(() => getMaxDepth(columnTree))
418
+ const headerRows = computed(() => buildHeaderRows(columnTree, maxDepth.value))
419
+ const flatColumns = computed(() => extractLeafColumns(columnTree))
264
420
  const processedTableData = computed(() => processBodyData(props.data, flatColumns.value))
265
-
266
- // Сбор колонок из слотов
421
+ const hasFixedColumns = computed(() => flatColumns.value.some((col) => col.fixed))
422
+ const wrapperStyle = computed(() => {
423
+ if (props.maxWidth == null) return undefined
424
+ const width = typeof props.maxWidth === 'number'
425
+ ? `${props.maxWidth}px`
426
+ : props.maxWidth
427
+ return { maxWidth: width }
428
+ })
429
+ const isFixedActive = computed(() => (
430
+ props.maxWidth != null && hasFixedColumns.value && isOverflowing.value
431
+ ))
432
+ function updateOverflowState() {
433
+ if (!isClient) {
434
+ isOverflowing.value = false
435
+ return
436
+ }
437
+ const wrapper = wrapperRef.value
438
+ const table = tableRef.value
439
+ if (!wrapper || !table) {
440
+ isOverflowing.value = false
441
+ return
442
+ }
443
+ isOverflowing.value = table.scrollWidth > wrapper.clientWidth + 1
444
+ }
445
+ function initColumnWidths() {
446
+ const widths = {}
447
+ for (const column of flatColumns.value) {
448
+ const width = parseWidth(column.width)
449
+ if (column.prop && width != null) widths[column.prop] = width
450
+ }
451
+ columnWidths.value = widths
452
+ }
453
+ watchEffect(() => {
454
+ flatColumns.value
455
+ initColumnWidths()
456
+ })
457
+ watch(
458
+ [() => props.data, () => props.maxWidth, flatColumns, columnWidths, processedTableData],
459
+ () => nextTick(updateOverflowState)
460
+ )
267
461
  onMounted(() => {
268
- const columnVNodes = slots.default?.() || []
269
- console.log('Raw slot VNodes:', columnVNodes)
270
-
271
- // Filter out comment nodes and other non-component nodes
272
- const validVNodes = columnVNodes.filter(vnode => {
273
- console.log('VNode type:', vnode.type, 'props:', vnode.props)
274
- // Check for actual component types (not comments or text)
275
- const isComponent = vnode.type &&
276
- (typeof vnode.type === 'object' || typeof vnode.type === 'function')
277
- console.log('Is component:', isComponent)
278
- return isComponent
279
- })
280
-
281
- console.log('Valid VNodes:', validVNodes)
282
- columnTree.value = buildColumnTree(validVNodes)
283
- console.log('SwTable mounted - columnTree:', columnTree.value)
284
- console.log('SwTable mounted - flatColumns:', flatColumns.value)
285
- console.log('SwTable mounted - data:', props.data)
462
+ updateOverflowState()
463
+ if (!isClient || typeof ResizeObserver === 'undefined') return
464
+ resizeObserver = new ResizeObserver(() => updateOverflowState())
465
+ if (wrapperRef.value) resizeObserver.observe(wrapperRef.value)
466
+ if (tableRef.value) resizeObserver.observe(tableRef.value)
467
+ })
468
+ onUnmounted(() => {
469
+ resizeObserver?.disconnect()
470
+ resizeObserver = null
286
471
  })
287
-
288
472
  </script>
@@ -1,14 +1,14 @@
1
1
  <template>
2
- <div style="display: none;"></div>
2
+ <div style="display: none;"><slot /></div>
3
3
  </template>
4
4
 
5
5
  <script setup>
6
- import { defineProps } from 'vue'
6
+ import { inject, provide, onUnmounted, reactive, watch } from 'vue'
7
7
 
8
8
  const props = defineProps({
9
9
  prop: {
10
10
  type: String,
11
- required: true
11
+ default: undefined
12
12
  },
13
13
  label: {
14
14
  type: String,
@@ -21,6 +21,68 @@ const props = defineProps({
21
21
  height: {
22
22
  type: [String, Number],
23
23
  default: 'auto'
24
+ },
25
+ resizable: {
26
+ type: Boolean,
27
+ default: undefined
28
+ },
29
+ minWidth: {
30
+ type: [String, Number],
31
+ default: 48
32
+ },
33
+ fixed: {
34
+ type: String,
35
+ default: undefined,
36
+ validator: (value) => value == null || value === 'left' || value === 'right'
37
+ }
38
+ })
39
+
40
+ const tableColumns = inject('swTableColumns', null)
41
+ const parentColumn = inject('swTableParentColumn', null)
42
+ const allocColumnOrder = inject('swTableAllocColumnOrder', null)
43
+
44
+ const column = reactive({
45
+ order: allocColumnOrder?.() ?? 0,
46
+ prop: props.prop,
47
+ label: props.label,
48
+ width: props.width,
49
+ height: props.height,
50
+ resizable: props.resizable,
51
+ minWidth: props.minWidth,
52
+ fixed: props.fixed,
53
+ children: []
54
+ })
55
+
56
+ watch(() => props, (nextProps) => {
57
+ column.prop = nextProps.prop
58
+ column.label = nextProps.label
59
+ column.width = nextProps.width
60
+ column.height = nextProps.height
61
+ column.resizable = nextProps.resizable
62
+ column.minWidth = nextProps.minWidth
63
+ column.fixed = nextProps.fixed
64
+ }, { deep: true })
65
+
66
+ provide('swTableParentColumn', column)
67
+
68
+ function registerColumn() {
69
+ if (parentColumn) {
70
+ parentColumn.children.push(column)
71
+ } else if (tableColumns) {
72
+ tableColumns.push(column)
24
73
  }
74
+ }
75
+
76
+ function unregisterColumn() {
77
+ const list = parentColumn ? parentColumn.children : tableColumns
78
+ if (!list) return
79
+ const index = list.indexOf(column)
80
+ if (index > -1) list.splice(index, 1)
81
+ }
82
+
83
+ registerColumn()
84
+
85
+ onUnmounted(() => {
86
+ unregisterColumn()
25
87
  })
26
88
  </script>