webcake-ui-kit 1.2.0 → 1.2.2

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.
Files changed (68) hide show
  1. package/package.json +8 -2
  2. package/src/components/checkbox/Checkbox.vue +1 -1
  3. package/src/components/drawer/Drawer.vue +261 -0
  4. package/src/components/drawer/drawer.css +162 -0
  5. package/src/components/dropdown/Dropdown.vue +15 -9
  6. package/src/components/hover-card/HoverCard.vue +159 -0
  7. package/src/components/hover-card/hover-card.css +10 -0
  8. package/src/components/input-counter/InputCounter.vue +250 -0
  9. package/src/components/input-counter/input-counter.css +209 -0
  10. package/src/components/menu/Menu.vue +4 -2
  11. package/src/components/popover/Popover.vue +144 -0
  12. package/src/components/popover/popover.css +3 -0
  13. package/src/components/select/Select.vue +10 -2
  14. package/src/components/select/select.css +12 -4
  15. package/src/components/select-option/SelectOption.vue +8 -2
  16. package/src/components/table-v2/ColumnDragHandle.vue +103 -0
  17. package/src/components/table-v2/Table.vue +304 -0
  18. package/src/components/table-v2/TableColGroup.vue +55 -0
  19. package/src/components/table-v2/TableEmpty.vue +10 -0
  20. package/src/components/table-v2/TableLoading.vue +25 -0
  21. package/src/components/table-v2/TableResizeObserver.vue +91 -0
  22. package/src/components/table-v2/TableWrapper.vue +207 -0
  23. package/src/components/table-v2/body/DragPreview.vue +65 -0
  24. package/src/components/table-v2/body/MeasureCell.vue +42 -0
  25. package/src/components/table-v2/body/TableBody.vue +133 -0
  26. package/src/components/table-v2/body/TableCell.vue +114 -0
  27. package/src/components/table-v2/body/TableRow.vue +73 -0
  28. package/src/components/table-v2/composables/useColumns.js +19 -0
  29. package/src/components/table-v2/composables/useSorter.js +12 -0
  30. package/src/components/table-v2/composables/useSticky.js +31 -0
  31. package/src/components/table-v2/constants.js +2 -0
  32. package/src/components/table-v2/context/createTableContext.js +80 -0
  33. package/src/components/table-v2/header/TableHeader.vue +15 -0
  34. package/src/components/table-v2/header/TableHeaderCell.vue +89 -0
  35. package/src/components/table-v2/header/TableHeaderRow.vue +107 -0
  36. package/src/components/table-v2/style/table-body.css +0 -0
  37. package/src/components/table-v2/style/table-header.css +0 -0
  38. package/src/components/table-v2/style/table-loading.css +19 -0
  39. package/src/components/table-v2/style/table-wrapper.css +287 -0
  40. package/src/components/table-v2/style/table.css +5 -0
  41. package/src/icons/BoxShadow.vue +35 -0
  42. package/src/icons/Carousel.vue +34 -0
  43. package/src/icons/CloudSync2.vue +42 -0
  44. package/src/icons/CornerBottomLeft.vue +26 -0
  45. package/src/icons/CornerBottomRight.vue +26 -0
  46. package/src/icons/CornerTopLeft.vue +26 -0
  47. package/src/icons/CornerTopRight.vue +26 -0
  48. package/src/icons/DistanceRight.vue +30 -0
  49. package/src/icons/DistanceTop.vue +30 -0
  50. package/src/icons/DropShadow.vue +35 -0
  51. package/src/icons/Fire.vue +26 -0
  52. package/src/icons/GlobeAccess.vue +32 -0
  53. package/src/icons/InnerShadow.vue +33 -0
  54. package/src/icons/Livestream.vue +54 -0
  55. package/src/icons/PaddingBottom.vue +30 -0
  56. package/src/icons/PaddingLeft.vue +30 -0
  57. package/src/icons/PaddingRight.vue +30 -0
  58. package/src/icons/PaddingTop.vue +30 -0
  59. package/src/icons/SkewHeight.vue +32 -0
  60. package/src/icons/SkewWidth.vue +32 -0
  61. package/src/icons/SquareDashedBottomSolid.vue +26 -0
  62. package/src/icons/SquareDashedLeftSolid.vue +26 -0
  63. package/src/icons/SquareDashedRightSolid.vue +26 -0
  64. package/src/icons/StrokeLine.vue +23 -0
  65. package/src/icons/Topline.vue +26 -0
  66. package/src/icons/index.js +25 -0
  67. package/src/index.js +5 -0
  68. package/src/utils/common.js +34 -0
@@ -0,0 +1,207 @@
1
+ <template>
2
+ <div
3
+ class="ui-table-v2__wrapper"
4
+ :class="{
5
+ 'ui-table-v2__wrapper--ping-left': isPingedLeft,
6
+ 'ui-table-v2__wrapper--ping-right': isPingedRight
7
+ }"
8
+ >
9
+ <DragPreview v-if="hasDraggable" ref="dragPreview">
10
+ <template #bodyCell="slotData">
11
+ <slot name="bodyCell" v-bind="slotData"></slot>
12
+ </template>
13
+ </DragPreview>
14
+
15
+ <!-- Case 3: scroll.y — header và body là 2 table riêng để sticky header -->
16
+ <template v-if="hasScrollY && !isEmpty">
17
+ <div ref="headerRef" class="ui-table-v2__header-hold" style="overflow: hidden">
18
+ <table :class="tableClass" :style="fixedTableStyle">
19
+ <TableColGroup :is-header="true" />
20
+ <TableHeader />
21
+ </table>
22
+ </div>
23
+ <div ref="bodyRef" class="ui-table-v2__body-hold" :style="bodyHoldStyle" @scroll="handleBodyScroll">
24
+ <table :class="tableClass" :style="fixedTableStyle">
25
+ <TableColGroup />
26
+ <TableBody :measureColumnWidth="hasScrollY || hasScrollX || hasSticky">
27
+ <template #bodyCell="slotData">
28
+ <slot name="bodyCell" v-bind="slotData"></slot>
29
+ </template>
30
+ <template #empty>
31
+ <slot name="empty"></slot>
32
+ </template>
33
+ </TableBody>
34
+ </table>
35
+ </div>
36
+ </template>
37
+
38
+ <!-- Case 1 & 2: một table duy nhất -->
39
+ <div v-else class="ui-table-v2__content" ref="bodyRef" :style="contentStyle" @scroll="handleBodyScroll">
40
+ <table :class="tableClass" :style="tableStyle">
41
+ <TableColGroup />
42
+ <TableHeader />
43
+ <TableBody :measureColumnWidth="hasScrollY || hasScrollX || hasSticky" :is-empty="isEmpty">
44
+ <template #bodyCell="slotData">
45
+ <slot name="bodyCell" v-bind="slotData"></slot>
46
+ </template>
47
+ <template #empty>
48
+ <slot name="empty"></slot>
49
+ </template>
50
+ </TableBody>
51
+ </table>
52
+ </div>
53
+ </div>
54
+ </template>
55
+
56
+ <script>
57
+ import TableColGroup from './TableColGroup.vue'
58
+ import TableHeader from './header/TableHeader.vue'
59
+ import TableBody from './body/TableBody.vue'
60
+ import DragPreview from './body/DragPreview.vue'
61
+ import { toCssSize, getTargetScrollBarSize } from '../../utils/common'
62
+
63
+ export default {
64
+ name: 'TableV2Wrapper',
65
+
66
+ data: () => {
67
+ return {
68
+ toCssSize,
69
+ getTargetScrollBarSize,
70
+ isPingedLeft: false,
71
+ isPingedRight: false
72
+ }
73
+ },
74
+
75
+ components: { TableColGroup, TableHeader, TableBody, DragPreview },
76
+
77
+ inject: ['tableContext'],
78
+
79
+ computed: {
80
+ scroll: function () {
81
+ return this.tableContext.layout.scroll
82
+ },
83
+
84
+ minHeight: function () {
85
+ return this.tableContext.layout.height
86
+ },
87
+
88
+ isEmpty() {
89
+ return this.tableContext.data.display.length === 0
90
+ },
91
+
92
+ hasScrollY: function () {
93
+ // has fix header
94
+ return !!(this.scroll && this.scroll.y)
95
+ },
96
+
97
+ hasScrollX: function () {
98
+ // has horizontal scroll
99
+ return !!(this.scroll && this.scroll.x)
100
+ },
101
+
102
+ hasSticky: function () {
103
+ // has sticky column
104
+ const leftOffsets = this.tableContext.sticky.leftOffsets
105
+ const rightOffsets = this.tableContext.sticky.rightOffsets
106
+ return Object.keys(leftOffsets).length > 0 || Object.keys(rightOffsets).length > 0
107
+ },
108
+
109
+ hasDraggable() {
110
+ return !!(this.tableContext.draggable && this.tableContext.draggable.enabled)
111
+ },
112
+
113
+ tableClass: function () {
114
+ return {
115
+ 'ui-table-v2__table': true,
116
+ 'ui-table-v2__table--bordered': this.tableContext.layout.bordered
117
+ }
118
+ },
119
+
120
+ // Case 1 & 2 — wrapper có overflow-x khi scroll.x
121
+ contentStyle: function () {
122
+ return this.hasScrollX ? { overflow: 'auto hidden' } : {}
123
+ },
124
+
125
+ // Case 1 & 2 — table style
126
+ tableStyle: function () {
127
+ if (this.hasScrollX && !this.isEmpty) {
128
+ return {
129
+ tableLayout: 'fixed',
130
+ width: this.toCssSize(this.scroll.x),
131
+ minWidth: '100%'
132
+ }
133
+ }
134
+ return { tableLayout: 'auto' }
135
+ },
136
+
137
+ // Case 3 — cả header table và body table dùng chung style này
138
+ fixedTableStyle: function () {
139
+ return {
140
+ tableLayout: 'fixed',
141
+ width: this.scroll && this.scroll.x ? this.toCssSize(this.scroll.x) : undefined,
142
+ minWidth: '100%'
143
+ }
144
+ },
145
+
146
+ // Case 3 — body scroll container
147
+ bodyHoldStyle: function () {
148
+ const rowHeight = this.tableContext.layout.headerHeight
149
+ const deduct = `${this.toCssSize(rowHeight)}`
150
+
151
+ var style = {
152
+ overflowY: 'auto',
153
+ maxHeight: `calc(${this.toCssSize(this.scroll.y)} - ${deduct})`,
154
+ minHeight: this.minHeight > 0 ? `calc(${this.toCssSize(this.minHeight)} - ${deduct})` : undefined
155
+ }
156
+ if (this.hasScrollX) {
157
+ style.overflowX = 'auto'
158
+ }
159
+ return style
160
+ }
161
+ },
162
+ methods: {
163
+ handleBodyScroll(e) {
164
+ const { scrollLeft, scrollWidth, clientWidth } = e.currentTarget
165
+ if (this.$refs.headerRef) {
166
+ this.$refs.headerRef.scrollLeft = scrollLeft
167
+ }
168
+
169
+ this.isPingedLeft = scrollLeft > 0
170
+ this.isPingedRight = scrollLeft < scrollWidth - clientWidth
171
+ },
172
+ updateScrollState() {
173
+ console.log('update')
174
+ if (this.$refs.bodyRef) {
175
+ const { width } = getTargetScrollBarSize(this.$refs.bodyRef)
176
+ this.tableContext.layout.scrollBarWidth = width == 'auto' ? '0px' : width
177
+
178
+ const { scrollWidth, clientWidth, scrollLeft } = this.$refs.bodyRef
179
+ this.isPingedLeft = scrollLeft > 0
180
+ this.isPingedRight = scrollLeft < scrollWidth - clientWidth
181
+ }
182
+ }
183
+ },
184
+
185
+ watch: {
186
+ 'tableContext.data.display.length': function () {
187
+ this.$nextTick(() => {
188
+ this.updateScrollState()
189
+ })
190
+ },
191
+ hasScrollY(val) {
192
+ console.log('hasScrollY', val)
193
+ }
194
+ },
195
+
196
+ mounted: function () {
197
+ const self = this
198
+ this.tableContext.draggable.getPreviewEl = function () {
199
+ return self.$refs.dragPreview && self.$refs.dragPreview.$el
200
+ }
201
+
202
+ this.updateScrollState()
203
+ }
204
+ }
205
+ </script>
206
+
207
+ <style src="./style/table-wrapper.css" scoped></style>
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <table
3
+ class="ui-table-v2__drag-preview"
4
+ aria-hidden="true"
5
+ :style="{ width: containerWidth ? containerWidth + 'px' : '100%', tableLayout: 'fixed' }"
6
+ >
7
+ <tbody class="ui-table-v2__body">
8
+ <tr class="ui-table-v2__row" v-if="record">
9
+ <td v-for="col in columns" :key="col.key">
10
+ <div v-if="col.type === DRAGGABLE_COLUMN" class="wrapper-option">
11
+ <span class="drag-handle">
12
+ <WkiGripVertical :size="16" />
13
+ </span>
14
+ </div>
15
+ <div v-else-if="col.type === SELECTION_COLUMN" class="wrapper-option" />
16
+ <slot v-else name="bodyCell" :column="col" :text="record && record[col.dataIndex]" :record="record">
17
+ <span>{{ record && record[col.dataIndex] }}</span>
18
+ </slot>
19
+ </td>
20
+ </tr>
21
+ </tbody>
22
+ </table>
23
+ </template>
24
+
25
+ <script>
26
+ import { WkiGripVertical } from '../../../icons'
27
+ import { SELECTION_COLUMN, DRAGGABLE_COLUMN } from '../constants.js'
28
+
29
+ export default {
30
+ name: 'TableV2DragPreview',
31
+ components: { WkiGripVertical },
32
+ inject: ['tableContext'],
33
+ data: function () {
34
+ return {
35
+ SELECTION_COLUMN: SELECTION_COLUMN,
36
+ DRAGGABLE_COLUMN: DRAGGABLE_COLUMN
37
+ }
38
+ },
39
+ computed: {
40
+ record: function () {
41
+ return this.tableContext.draggable.draggingRecord
42
+ },
43
+ columns: function () {
44
+ return this.tableContext.columns.flat
45
+ },
46
+ containerWidth: function () {
47
+ return this.tableContext.layout.containerWidth
48
+ }
49
+ }
50
+ }
51
+ </script>
52
+
53
+ <style scoped>
54
+ .ui-table-v2__drag-preview {
55
+ position: fixed;
56
+ top: -10000px;
57
+ left: -10000px;
58
+ pointer-events: none;
59
+ border-collapse: separate;
60
+ border-spacing: 0;
61
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
62
+ border-radius: 4px;
63
+ overflow: hidden;
64
+ }
65
+ </style>
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <TableResizeObserver @resize="handleCellResize">
3
+ <td ref="cellRef" :style="{ padding: '0', border: '0', height: '0' }">
4
+ <div :style="{ height: 0, overflow: 'hidden' }">&nbsp;</div>
5
+ </td>
6
+ </TableResizeObserver>
7
+ </template>
8
+
9
+ <script>
10
+ import TableResizeObserver from '../TableResizeObserver.vue'
11
+ import { DRAGGABLE_COLUMN, SELECTION_COLUMN } from '../constants.js'
12
+ export default {
13
+ name: 'MeasureCell',
14
+ components: { TableResizeObserver },
15
+ props: {
16
+ measureColumnWidth: {
17
+ type: Boolean,
18
+ default: false
19
+ },
20
+ colKey: {
21
+ type: String,
22
+ required: true
23
+ }
24
+ },
25
+ inject: ['tableContext'],
26
+
27
+ methods: {
28
+ handleCellResize({ offsetWidth }) {
29
+ if (this.colKey === DRAGGABLE_COLUMN || this.colKey === SELECTION_COLUMN) {
30
+ return
31
+ }
32
+ this.tableContext.actions.resize(this.colKey, offsetWidth)
33
+ }
34
+ },
35
+
36
+ mounted() {
37
+ if (this.$refs.cellRef) {
38
+ this.handleCellResize({ offsetWidth: this.$refs.cellRef.offsetWidth })
39
+ }
40
+ }
41
+ }
42
+ </script>
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <tbody class="ui-table-v2__body">
3
+ <template v-if="measureColumnWidth">
4
+ <tr aria-hidden="true" class="ui-table-v2__measure-row" :style="{ height: '0', fontSize: '0' }">
5
+ <MeasureCell v-for="(column, colIndex) in tableContext.columns.flat" :key="colIndex" :colKey="column.key" />
6
+ </tr>
7
+ </template>
8
+
9
+ <template v-if="isEmpty">
10
+ <tr class="ui-table-v2__row">
11
+ <td colspan="100">
12
+ <div class="ui-table-v2__row-empty ui-table-v2__empty" :style="emptyStyle">
13
+ <slot name="empty">
14
+ <div class="wrapper-img">
15
+ <img
16
+ src="https://content.pancake.vn/web-media-262/2e/2a/0c/96/c2b58ae9f06c4dc2a3b83016e56d5b4132ff40637862ba23435e43a0-w:224-h:224-l:3927-t:image/png.png"
17
+ />
18
+ </div>
19
+ <span class="wk-paragraph-small">{{ emptyText }}</span>
20
+ </slot>
21
+ </div>
22
+ </td>
23
+ </tr>
24
+ </template>
25
+
26
+ <TableRow
27
+ v-for="(record, rowIndex) in tableContext.data.display"
28
+ :key="record[tableContext.layout.rowKey]"
29
+ :record="record"
30
+ :row-index="rowIndex"
31
+ :is-last-item="rowIndex == tableContext.data.display.length - 1"
32
+ >
33
+ <template #bodyCell="slotData">
34
+ <slot name="bodyCell" v-bind="slotData"></slot>
35
+ </template>
36
+ </TableRow>
37
+ </tbody>
38
+ </template>
39
+
40
+ <script>
41
+ import Sortable from 'sortablejs'
42
+ import TableRow from './TableRow.vue'
43
+ import MeasureCell from './MeasureCell.vue'
44
+
45
+ export default {
46
+ name: 'TableV2Body',
47
+ components: { TableRow, MeasureCell },
48
+ props: {
49
+ measureColumnWidth: {
50
+ type: Boolean,
51
+ default: false
52
+ },
53
+ isEmpty: {
54
+ type: Boolean,
55
+ default: false
56
+ }
57
+ },
58
+ inject: ['tableContext'],
59
+ watch: {
60
+ 'tableContext.draggable.enabled': function (val) {
61
+ val ? this._initSortable() : this._destroySortable()
62
+ },
63
+ 'tableContext.draggable.enableAnimationFlip': function () {
64
+ if (this.tableContext.draggable.enabled) this._initSortable()
65
+ }
66
+ },
67
+ mounted: function () {
68
+ if (this.tableContext.draggable.enabled) {
69
+ this._initSortable()
70
+ }
71
+ },
72
+ computed: {
73
+ emptyText() {
74
+ return this.tableContext.data.emptyText || 'Không có dữ liệu'
75
+ },
76
+ emptyStyle() {
77
+ const { height, rowHeight } = this.tableContext.layout
78
+ if (!height) return {}
79
+ return { minHeight: `calc(${height}px - ${rowHeight}px)` }
80
+ }
81
+ },
82
+ beforeUnmount: function () {
83
+ this._destroySortable()
84
+ },
85
+ // eslint-disable-next-line vue/no-deprecated-destroyed-lifecycle, vue/no-dupe-keys
86
+ beforeDestroy: function () {
87
+ this._destroySortable()
88
+ },
89
+ methods: {
90
+ _initSortable: function () {
91
+ this._destroySortable()
92
+ const self = this
93
+ const offset = this.measureColumnWidth ? 1 : 0
94
+ this._sortable = Sortable.create(this.$el, {
95
+ handle: '.drag-handle',
96
+ draggable: '.ui-table-v2__row',
97
+ animation: this.tableContext.draggable.enableAnimationFlip ? 150 : 0,
98
+ onChoose: function (evt) {
99
+ const rowIndex = evt.oldIndex - offset
100
+ self.tableContext.draggable.draggingRecord = self.tableContext.data.display[rowIndex] || null
101
+ },
102
+ setData: function (dataTransfer, dragEl) {
103
+ let previewEl =
104
+ typeof self.tableContext.draggable.getPreviewEl === 'function'
105
+ ? self.tableContext.draggable.getPreviewEl()
106
+ : null
107
+ if (!previewEl) return
108
+ dataTransfer.setDragImage(previewEl, 0, previewEl.offsetHeight / 2)
109
+ },
110
+ onEnd: function (evt) {
111
+ self.tableContext.draggable.draggingRecord = null
112
+ // Revert SortableJS DOM move — Vue owns the DOM
113
+ evt.from.insertBefore(evt.item, evt.from.children[evt.oldIndex] || null)
114
+ const oldIndex = evt.oldIndex - offset
115
+ const newIndex = evt.newIndex - offset
116
+ if (oldIndex === newIndex) return
117
+ if (typeof self.tableContext.actions.reorder === 'function') {
118
+ self.tableContext.actions.reorder(oldIndex, newIndex)
119
+ }
120
+ }
121
+ })
122
+ },
123
+ _destroySortable: function () {
124
+ if (this._sortable) {
125
+ this._sortable.destroy()
126
+ this._sortable = null
127
+ }
128
+ }
129
+ }
130
+ }
131
+ </script>
132
+
133
+ <style src="../style/table-body.css" scoped></style>
@@ -0,0 +1,114 @@
1
+ <template>
2
+ <td
3
+ :class="[
4
+ 'ui-table-v2__cell',
5
+ isSelectionCol && 'ui-table-v2__cell--selection',
6
+ isSelectionCol && 'ui-table-v2__header-cell--selection',
7
+ column.fixed && `ui-table-v2__cell--fixed-${column.fixed}`,
8
+ isLastFixedLeft && 'ui-table-v2__cell--fixed-left__last',
9
+ isFirstFixedRight && 'ui-table-v2__cell--fixed-right__first'
10
+ ]"
11
+ :style="cellStyle"
12
+ >
13
+ <div v-if="isSelectionCol" class="wrapper-option">
14
+ <Checkbox :checked="isSelected" :model-value="isSelected" @change="onToggle" />
15
+ </div>
16
+
17
+ <div v-else-if="isDraggableCol" class="wrapper-option">
18
+ <span class="drag-handle">
19
+ <WkiGripVertical :size="16" />
20
+ </span>
21
+ </div>
22
+
23
+ <slot
24
+ v-if="!isSelectionCol && !isDraggableCol"
25
+ name="bodyCell"
26
+ :column="column"
27
+ :text="record[column.dataIndex]"
28
+ :record="record"
29
+ >
30
+ <span :class="[column.ellipsis && 'ui-table-v2__cell--ellipsis']">
31
+ {{ record[column.dataIndex] }}
32
+ </span>
33
+ </slot>
34
+ </td>
35
+ </template>
36
+
37
+ <script>
38
+ import Checkbox from '../../checkbox/Checkbox.vue'
39
+ import { SELECTION_COLUMN, DRAGGABLE_COLUMN } from '../constants.js'
40
+ import { toCssSize } from '../../../utils/common.js'
41
+ import { WkiGripVertical } from '../../../icons'
42
+
43
+ export default {
44
+ name: 'TableV2Cell',
45
+ components: { Checkbox, WkiGripVertical },
46
+ inject: ['tableContext'],
47
+ props: {
48
+ column: { type: Object, required: true },
49
+ record: { type: Object, required: true },
50
+ offset: { type: [Number, String], default: 0 }
51
+ },
52
+ computed: {
53
+ isSelectionCol: function () {
54
+ return this.column.type === SELECTION_COLUMN
55
+ },
56
+ isDraggableCol: function () {
57
+ return this.column.type === DRAGGABLE_COLUMN
58
+ },
59
+ isLastFixedLeft: function () {
60
+ if (this.column.fixed !== 'left') return false
61
+ const cols = this.tableContext.columns.flat
62
+ let lastKey = null
63
+ for (let i = 0; i < cols.length; i++) {
64
+ if (cols[i].fixed === 'left') lastKey = cols[i].key
65
+ }
66
+ return lastKey === this.column.key
67
+ },
68
+ isFirstFixedRight: function () {
69
+ if (this.column.fixed !== 'right') return false
70
+ const cols = this.tableContext.columns.flat
71
+ for (let i = 0; i < cols.length; i++) {
72
+ if (cols[i].fixed === 'right') return cols[i].key === this.column.key
73
+ }
74
+ return false
75
+ },
76
+ isSelected: function () {
77
+ var key = this.record[this.tableContext.layout.rowKey]
78
+ return this.tableContext.selection.selectedRowKeys.indexOf(key) !== -1
79
+ },
80
+ cellStyle: function () {
81
+ const res = { textAlign: this.column.align }
82
+ if (this.column.fixed) {
83
+ res.position = 'sticky'
84
+ if (this.column.fixed === 'left') {
85
+ res.left = toCssSize(this.offset)
86
+ } else if (this.column.fixed === 'right') {
87
+ res.right = toCssSize(this.offset)
88
+ }
89
+ }
90
+ return res
91
+ }
92
+ },
93
+ methods: {
94
+ onToggle: function (checked, nativeEvent) {
95
+ const key = this.record[this.tableContext.layout.rowKey]
96
+ const keys = [...this.tableContext.selection.selectedRowKeys]
97
+ const idx = keys.indexOf(key)
98
+
99
+ if (checked && idx === -1) {
100
+ keys.push(key)
101
+ } else if (!checked && idx !== -1) {
102
+ keys.splice(idx, 1)
103
+ }
104
+
105
+ this.tableContext.actions.select(keys, {
106
+ type: 'row',
107
+ record: this.record,
108
+ selected: checked,
109
+ nativeEvent: nativeEvent
110
+ })
111
+ }
112
+ }
113
+ }
114
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <tr
3
+ v-bind="customAttrs"
4
+ v-on="customListeners"
5
+ :class="[
6
+ 'ui-table-v2__row',
7
+ isLastItem && 'ui-table-v2__row--last',
8
+ isSelected && 'ui-table-v2__row--selected',
9
+ customAttrs.class
10
+ ]"
11
+ :style="rowStyle"
12
+ >
13
+ <TableCell
14
+ v-for="column in tableContext.columns.flat"
15
+ :key="column.key"
16
+ :column="column"
17
+ :record="record"
18
+ :offset="column.fixed === 'left' ? leftStickyOffsets[column.key] : rightStickyOffsets[column.key]"
19
+ >
20
+ <template #bodyCell="slotData">
21
+ <slot name="bodyCell" v-bind="slotData"></slot>
22
+ </template>
23
+ </TableCell>
24
+ </tr>
25
+ </template>
26
+
27
+ <script>
28
+ import TableCell from './TableCell.vue'
29
+ import { splitProps } from '../../../utils/common.js'
30
+
31
+ export default {
32
+ name: 'TableV2Row',
33
+ components: { TableCell },
34
+ inject: ['tableContext'],
35
+ props: {
36
+ record: { type: Object, required: true },
37
+ rowIndex: { type: Number, required: true },
38
+ isLastItem: { type: Boolean, default: false }
39
+ },
40
+
41
+ computed: {
42
+ rowStyle() {
43
+ return { height: this.tableContext.layout.rowHeight + 'px' }
44
+ },
45
+
46
+ isSelected: function () {
47
+ var key = this.record[this.tableContext.layout.rowKey]
48
+ return this.tableContext.selection.selectedRowKeys.indexOf(key) !== -1
49
+ },
50
+
51
+ leftStickyOffsets() {
52
+ return this.tableContext.sticky.leftOffsets
53
+ },
54
+
55
+ rightStickyOffsets() {
56
+ return this.tableContext.sticky.rightOffsets
57
+ },
58
+
59
+ customProps: function () {
60
+ var fn = this.tableContext.rows.customRow
61
+ return typeof fn === 'function' ? fn(this.record, this.rowIndex) || {} : {}
62
+ },
63
+
64
+ customAttrs: function () {
65
+ return splitProps(this.customProps).attrs
66
+ },
67
+
68
+ customListeners: function () {
69
+ return splitProps(this.customProps).listeners
70
+ }
71
+ }
72
+ }
73
+ </script>
@@ -0,0 +1,19 @@
1
+ export function flattenColumns(columns) {
2
+ return (columns || []).map(function (col, i) {
3
+ return {
4
+ key: col.key || col.dataIndex || String(i),
5
+ type: col.type || null,
6
+ dataIndex: col.dataIndex || '',
7
+ title: col.title || '',
8
+ width: col.width || null,
9
+ align: col.align == 'left' ? null : col.align,
10
+ fixed: col.fixed || null,
11
+ ellipsis: col.ellipsis || false,
12
+ customCell: col.customCell || null,
13
+ customHeaderCell: col.customHeaderCell || null,
14
+ minWidth: col.minWidth || 50,
15
+ maxWidth: col.maxWidth || Infinity,
16
+ resizable: col.resizable || false
17
+ }
18
+ })
19
+ }
@@ -0,0 +1,12 @@
1
+ export function sortData(source, columnKey, order) {
2
+ if (!columnKey || !order) return source
3
+ var arr = source.slice()
4
+ arr.sort(function (a, b) {
5
+ var av = a[columnKey]
6
+ var bv = b[columnKey]
7
+ if (av === bv) return 0
8
+ var asc = av < bv ? -1 : 1
9
+ return order === 'ascend' ? asc : -asc
10
+ })
11
+ return arr
12
+ }
@@ -0,0 +1,31 @@
1
+ export function computeOffsets(columns, columnWidths) {
2
+ var left = {}
3
+ var right = {}
4
+ var leftAcc = 0
5
+ var rightAcc = 0
6
+
7
+ for (var i = 0; i < columns.length; i++) {
8
+ var col = columns[i]
9
+ if (col.fixed === 'left') {
10
+ left[col.key] = leftAcc
11
+ leftAcc += columnWidths.get(col.key) || parseWidth(col.width) || 0
12
+ }
13
+ }
14
+
15
+ for (var j = columns.length - 1; j >= 0; j--) {
16
+ var colR = columns[j]
17
+ if (colR.fixed === 'right') {
18
+ right[colR.key] = rightAcc
19
+ rightAcc += columnWidths.get(colR.key) || parseWidth(colR.width) || 0
20
+ }
21
+ }
22
+
23
+ return { left: left, right: right }
24
+ }
25
+
26
+ function parseWidth(width) {
27
+ if (!width) return 0
28
+ if (typeof width === 'number') return width
29
+ var n = parseInt(width, 10)
30
+ return isNaN(n) ? 0 : n
31
+ }