quasar-ui-sellmate-ui-kit 3.14.9 → 3.14.10
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/dist/index.common.js +2 -2
- package/dist/index.css +1 -1
- package/dist/index.esm.js +2 -2
- package/dist/index.min.css +1 -1
- package/dist/index.rtl.css +1 -1
- package/dist/index.rtl.min.css +1 -1
- package/dist/index.umd.js +141 -197
- package/dist/index.umd.min.js +2 -2
- package/package.json +1 -1
- package/src/components/STable.vue +7 -43
- package/src/composables/table/use-resizable.js +126 -159
package/package.json
CHANGED
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
:class="{
|
|
14
14
|
's-select-table': $attrs.selection && $attrs.selection !== 'none',
|
|
15
15
|
'resizable-table': resizable,
|
|
16
|
-
'sticky-column-table': stickyColumn.
|
|
16
|
+
'sticky-column-table': stickyColumn.leftStickyCount > 0 || stickyColumn.rightStickyCount > 0,
|
|
17
17
|
'sticky-resizable-table': stickyResizable,
|
|
18
18
|
'sticky-header': stickyHeader,
|
|
19
19
|
'before-search': !rows.length,
|
|
20
20
|
's-table__hover': !noHover,
|
|
21
|
-
'sticky-left-table': stickyColumn.
|
|
22
|
-
'sticky-right-table': stickyColumn.
|
|
21
|
+
'sticky-left-table': stickyColumn.leftStickyCount > 0,
|
|
22
|
+
'sticky-right-table': stickyColumn.rightStickyCount > 0,
|
|
23
23
|
}"
|
|
24
24
|
@selection="updateSelected"
|
|
25
25
|
ref="sTableRef"
|
|
@@ -44,24 +44,7 @@
|
|
|
44
44
|
</template>
|
|
45
45
|
|
|
46
46
|
<template v-for="(column, index) in columns" :key="index" #[`body-cell-${column.name}`]="props">
|
|
47
|
-
<q-td
|
|
48
|
-
v-if="navigator"
|
|
49
|
-
:class="{
|
|
50
|
-
focused: isFocused(props),
|
|
51
|
-
'text-center': props.col.align === 'center',
|
|
52
|
-
'text-right': props.col.align === 'right',
|
|
53
|
-
[typeof props.col.classes === 'function'
|
|
54
|
-
? props.col.classes(props.row)
|
|
55
|
-
: props.col.classes]: true,
|
|
56
|
-
[typeof props.row.class === 'function'
|
|
57
|
-
? props.row.class(props.row)
|
|
58
|
-
: typeof props.row.class === 'string'
|
|
59
|
-
? props.row.class
|
|
60
|
-
: '']: true,
|
|
61
|
-
}"
|
|
62
|
-
:style="props.col.style"
|
|
63
|
-
@click.stop="focusCell(props)"
|
|
64
|
-
>
|
|
47
|
+
<q-td v-if="navigator" :props="props" @click.stop="focusCell(props)">
|
|
65
48
|
<slot :name="`body-cell-${column.name}-content`" v-bind="props">
|
|
66
49
|
<s-input
|
|
67
50
|
ref="inputRef"
|
|
@@ -82,24 +65,7 @@
|
|
|
82
65
|
</span>
|
|
83
66
|
</slot>
|
|
84
67
|
</q-td>
|
|
85
|
-
<q-td
|
|
86
|
-
v-else
|
|
87
|
-
v-bind="props"
|
|
88
|
-
auto-width
|
|
89
|
-
:class="{
|
|
90
|
-
'text-center': props.col.align === 'center',
|
|
91
|
-
'text-right': props.col.align === 'right',
|
|
92
|
-
[typeof props.col.classes === 'function'
|
|
93
|
-
? props.col.classes(props.row)
|
|
94
|
-
: props.col.classes]: true,
|
|
95
|
-
[typeof props.row.class === 'function'
|
|
96
|
-
? props.row.class(props.row)
|
|
97
|
-
: typeof props.row.class === 'string'
|
|
98
|
-
? props.row.class
|
|
99
|
-
: '']: true,
|
|
100
|
-
}"
|
|
101
|
-
:style="props.col.style"
|
|
102
|
-
>
|
|
68
|
+
<q-td v-else :props="props" auto-width>
|
|
103
69
|
<slot :name="`body-cell-${column.name}-content`" v-bind="props">
|
|
104
70
|
{{ props.value }}
|
|
105
71
|
</slot>
|
|
@@ -169,8 +135,6 @@
|
|
|
169
135
|
stickyColumn: {
|
|
170
136
|
type: Object,
|
|
171
137
|
default: () => ({
|
|
172
|
-
isStickyLeft: false,
|
|
173
|
-
isStickyRight: false,
|
|
174
138
|
leftStickyCount: 0,
|
|
175
139
|
rightStickyCount: 0,
|
|
176
140
|
}),
|
|
@@ -303,8 +267,8 @@
|
|
|
303
267
|
}
|
|
304
268
|
|
|
305
269
|
const { count, direction: stickyDirection } = props.stickyColumn;
|
|
306
|
-
const {
|
|
307
|
-
if (
|
|
270
|
+
const { leftStickyCount, rightStickyCount } = props.stickyColumn;
|
|
271
|
+
if (leftStickyCount > 0 || rightStickyCount > 0) {
|
|
308
272
|
addStickyColumn(sTableRef, props.stickyColumn);
|
|
309
273
|
observeScrollForStickyShadow(tableElement());
|
|
310
274
|
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
const MIN_COL_WIDTH = 40; // 최소 너비 제한
|
|
2
|
+
const HANDLE_WIDTH = 4; // 리사이즈 핸들의 너비
|
|
3
|
+
const HANDLE_HEIGHT = 16; // 리사이즈 핸들의 높이
|
|
4
|
+
const HANDLE_Z_INDEX = 2; // 리사이즈 핸들의 z-index
|
|
5
|
+
|
|
1
6
|
function createDiv(val) {
|
|
2
7
|
// 기존의 resizable div 코드
|
|
3
8
|
const div = document.createElement('div');
|
|
@@ -5,23 +10,22 @@ function createDiv(val) {
|
|
|
5
10
|
div.style.top = '10px';
|
|
6
11
|
if (val === 'right') div.style.right = 0;
|
|
7
12
|
if (val === 'left') div.style.left = 0;
|
|
8
|
-
div.style.width =
|
|
13
|
+
div.style.width = `${HANDLE_WIDTH}px`;
|
|
9
14
|
div.style.position = 'absolute';
|
|
10
15
|
div.style.cursor = 'col-resize';
|
|
11
|
-
div.style.backgroundColor = '
|
|
16
|
+
div.style.backgroundColor = 'transparent';
|
|
12
17
|
div.style.border = '1px solid #CCCCCC';
|
|
13
18
|
div.style.borderTop = 'none';
|
|
14
19
|
div.style.borderBottom = 'none';
|
|
15
|
-
div.style.zIndex =
|
|
20
|
+
div.style.zIndex = HANDLE_Z_INDEX;
|
|
16
21
|
div.style.userSelect = 'none';
|
|
17
|
-
div.style.height =
|
|
22
|
+
div.style.height = `${HANDLE_HEIGHT}px`;
|
|
18
23
|
return div;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
// TODO: 전역이 아니라 컴포넌트 단위로 제한된 최소 너비를 설정할 수 있도록 개선
|
|
22
|
-
let restrictedMinWidth;
|
|
23
|
-
|
|
24
26
|
function detectStickyWidth(tableElement, isStickyLeft) {
|
|
27
|
+
if (!tableElement) return;
|
|
28
|
+
|
|
25
29
|
const tableRow = Array.from(tableElement.getElementsByTagName('tr'));
|
|
26
30
|
const theadRow = tableRow[0];
|
|
27
31
|
const stickyTh = Array.from(theadRow.querySelectorAll('.sticky-cell'));
|
|
@@ -46,182 +50,145 @@ function detectStickyWidth(tableElement, isStickyLeft) {
|
|
|
46
50
|
});
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (isRestricted && curColWidth + diffX <= restrictedMinWidth) {
|
|
76
|
-
calcWidth = restrictedMinWidth; // 제한된 컬럼은 최소 너비로 설정
|
|
77
|
-
} else {
|
|
78
|
-
calcWidth = curColWidth + diffX;
|
|
53
|
+
export function useResizable() {
|
|
54
|
+
function setListeners(div, position, useSticky) {
|
|
55
|
+
// resizable 속성을 사용할 때에 이벤트
|
|
56
|
+
let curCol;
|
|
57
|
+
let pageX;
|
|
58
|
+
let curColWidth;
|
|
59
|
+
|
|
60
|
+
const onMouseMove = e => {
|
|
61
|
+
if (!curCol) return false;
|
|
62
|
+
|
|
63
|
+
const diffX = e.pageX - pageX;
|
|
64
|
+
const isStickyLeft = position === 'right';
|
|
65
|
+
let calcWidth = isStickyLeft ? curColWidth + diffX : curColWidth - diffX;
|
|
66
|
+
|
|
67
|
+
const computedStyles = window.getComputedStyle(curCol);
|
|
68
|
+
const min = parseInt(computedStyles.minWidth || `${MIN_COL_WIDTH}`, 10);
|
|
69
|
+
const max = parseInt(
|
|
70
|
+
computedStyles.maxWidth === 'none' ? '9999' : computedStyles.maxWidth || '9999',
|
|
71
|
+
10,
|
|
72
|
+
);
|
|
73
|
+
calcWidth = Math.max(min, Math.min(calcWidth, max));
|
|
74
|
+
curCol.style.width = `${calcWidth}px`;
|
|
75
|
+
|
|
76
|
+
if (useSticky && curCol) {
|
|
77
|
+
const table = curCol.closest('table').parentElement;
|
|
78
|
+
detectStickyWidth(table, position === 'right');
|
|
79
79
|
}
|
|
80
|
-
} else {
|
|
81
|
-
calcWidth = curColWidth - diffX;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (calcWidth < 40) {
|
|
85
|
-
calcWidth = 40; // 최소 너비 제한
|
|
86
|
-
}
|
|
87
80
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
81
|
+
return true;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const onMouseUp = () => {
|
|
85
|
+
curCol = undefined;
|
|
86
|
+
pageX = undefined;
|
|
87
|
+
curColWidth = undefined;
|
|
88
|
+
document.removeEventListener('mousemove', onMouseMove);
|
|
89
|
+
document.removeEventListener('mouseup', onMouseUp);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const onMouseDown = e => {
|
|
93
|
+
curCol = e.target.parentElement;
|
|
94
|
+
pageX = e.pageX;
|
|
95
|
+
curColWidth = curCol.offsetWidth;
|
|
96
|
+
document.addEventListener('mousemove', onMouseMove, { passive: true });
|
|
97
|
+
document.addEventListener('mouseup', onMouseUp, { passive: true });
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
div.addEventListener('mousedown', onMouseDown, { passive: true });
|
|
101
|
+
}
|
|
107
102
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
document.addEventListener('mouseup', onMouseUp, { passive: true });
|
|
114
|
-
};
|
|
103
|
+
function appendResizableDiv(col, direction, useSticky) {
|
|
104
|
+
const div = createDiv(direction);
|
|
105
|
+
col.appendChild(div);
|
|
106
|
+
setListeners(div, direction, useSticky);
|
|
107
|
+
}
|
|
115
108
|
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
function getTableCols(tableEl) {
|
|
110
|
+
if (!tableEl) return [];
|
|
111
|
+
const tableElement = tableEl.getElementsByTagName('table')[0];
|
|
112
|
+
if (!tableElement) return [];
|
|
113
|
+
const firstRow = tableElement.getElementsByTagName('tr')[0];
|
|
114
|
+
return firstRow ? Array.from(firstRow.children) : [];
|
|
115
|
+
}
|
|
118
116
|
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
col.appendChild(div);
|
|
122
|
-
setListeners(div, direction, useSticky, restrictedColClass);
|
|
123
|
-
}
|
|
117
|
+
function applyStickyToColumn(tableEl, colIdx, isLeft, offsetPx) {
|
|
118
|
+
const rows = Array.from(tableEl.querySelectorAll('tr'));
|
|
124
119
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
120
|
+
rows.forEach(row => {
|
|
121
|
+
const cells = Array.from(row.children);
|
|
122
|
+
const targetCell = cells[colIdx];
|
|
123
|
+
if (!targetCell) return;
|
|
130
124
|
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
targetCell.classList.add('sticky-cell');
|
|
126
|
+
targetCell.classList.add(isLeft ? 'left' : 'right');
|
|
127
|
+
targetCell.style.position = 'sticky';
|
|
128
|
+
targetCell.style[isLeft ? 'left' : 'right'] = offsetPx;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
133
131
|
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
function addResizable(tableRef, stickyColumnsConfig = {}) {
|
|
133
|
+
const cols = getTableCols(tableRef.value.$el);
|
|
134
|
+
const leftStickyCount = stickyColumnsConfig.leftStickyCount || 0;
|
|
135
|
+
const rightStickyCount = stickyColumnsConfig.rightStickyCount || 0;
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const isSelectTable = tableRef.value.$el.classList.contains('s-select-table');
|
|
137
|
+
cols.forEach((col, colIdx) => {
|
|
138
|
+
const isFirstCol = colIdx === 0;
|
|
139
|
+
const isSelectTable = tableRef.value.$el.classList.contains('s-select-table');
|
|
141
140
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
// 🔑 스티키 컬럼이라면 리사이즈 핸들 생성 금지
|
|
142
|
+
const isLeftSticky = colIdx < leftStickyCount;
|
|
143
|
+
const isRightSticky = colIdx >= cols.length - rightStickyCount;
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
145
|
+
// 스티키 컬럼이면 appendResizableDiv 호출하지 않음
|
|
146
|
+
if (isLeftSticky || isRightSticky) return;
|
|
149
147
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
// 나머지 컬럼만 리사이즈 핸들 생성
|
|
149
|
+
if (isSelectTable) {
|
|
150
|
+
if (!isFirstCol) {
|
|
151
|
+
appendResizableDiv(col, 'right', false);
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
153
154
|
appendResizableDiv(col, 'right', false);
|
|
154
155
|
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function applyStickyToColumn(tableEl, colIdx, isLeft, offsetPx) {
|
|
162
|
-
const rows = Array.from(tableEl.querySelectorAll('tr'));
|
|
163
|
-
|
|
164
|
-
rows.forEach(row => {
|
|
165
|
-
const cells = Array.from(row.children);
|
|
166
|
-
const targetCell = cells[colIdx];
|
|
167
|
-
if (!targetCell) return;
|
|
168
|
-
|
|
169
|
-
targetCell.classList.add('sticky-cell');
|
|
170
|
-
targetCell.classList.add(isLeft ? 'left' : 'right');
|
|
171
|
-
targetCell.classList.add(`sticky-col-${colIdx}`);
|
|
172
|
-
|
|
173
|
-
targetCell.style.position = 'sticky';
|
|
174
|
-
|
|
175
|
-
if (isLeft) {
|
|
176
|
-
targetCell.style.left = offsetPx;
|
|
177
|
-
} else {
|
|
178
|
-
targetCell.style.right = offsetPx;
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function addStickyColumn(tableRef, stickyColumnsConfig) {
|
|
184
|
-
const { isStickyLeft, isStickyRight, leftStickyCount, rightStickyCount } = stickyColumnsConfig;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
185
158
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const restrictedColClass = `sticky-col-${isSelectTable ? leftStickyCount : leftStickyCount - 1}`;
|
|
159
|
+
function addStickyColumn(tableRef, stickyColumnsConfig) {
|
|
160
|
+
const { leftStickyCount, rightStickyCount } = stickyColumnsConfig;
|
|
189
161
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// let i = isSelectTable ? 1 : 0; // Select Table일 경우 첫번째 컬럼은 스티키가 아님
|
|
193
|
-
const count = isSelectTable ? leftStickyCount + 1 : leftStickyCount; // Select Table일 경우 +1
|
|
162
|
+
const cols = getTableCols(tableRef.value.$el);
|
|
163
|
+
const isSelectTable = tableRef.value.$el.classList.contains('s-select-table');
|
|
194
164
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
165
|
+
// Left Sticky Columns
|
|
166
|
+
if (leftStickyCount > 0) {
|
|
167
|
+
// let i = isSelectTable ? 1 : 0; // Select Table일 경우 첫번째 컬럼은 스티키가 아님
|
|
168
|
+
const count = isSelectTable ? leftStickyCount + 1 : leftStickyCount; // Select Table일 경우 +1
|
|
169
|
+
|
|
170
|
+
for (let i = 0; i < count; i++) {
|
|
171
|
+
applyStickyToColumn(tableRef.value.$el, i, true, '0px');
|
|
172
|
+
if (isSelectTable && i > 0) {
|
|
173
|
+
appendResizableDiv(cols[i], 'right', true); // 오른쪽에 리사이즈 핸들 추가
|
|
174
|
+
} else {
|
|
175
|
+
appendResizableDiv(cols[i], 'right', true); // 오른쪽에 리사이즈 핸들 추가
|
|
206
176
|
}
|
|
207
177
|
}
|
|
178
|
+
|
|
179
|
+
detectStickyWidth(tableRef.value.$el, true); // 좌측 스티키 너비 재계산
|
|
208
180
|
}
|
|
209
181
|
|
|
210
|
-
|
|
211
|
-
|
|
182
|
+
// Right Sticky Columns
|
|
183
|
+
if (rightStickyCount > 0) {
|
|
184
|
+
for (let i = cols.length - rightStickyCount; i < cols.length; i++) {
|
|
185
|
+
applyStickyToColumn(tableRef.value.$el, i, false, '0px');
|
|
186
|
+
appendResizableDiv(cols[i], 'left', true); // 왼쪽에 리사이즈 핸들 추가 (우측 스티키)
|
|
187
|
+
}
|
|
212
188
|
|
|
213
|
-
|
|
214
|
-
if (isStickyRight && rightStickyCount > 0) {
|
|
215
|
-
for (let i = cols.length - rightStickyCount; i < cols.length; i++) {
|
|
216
|
-
applyStickyToColumn(tableRef.value.$el, i, false, '0px');
|
|
217
|
-
appendResizableDiv(cols[i], 'left', true); // 왼쪽에 리사이즈 핸들 추가 (우측 스티키)
|
|
189
|
+
detectStickyWidth(tableRef.value.$el, false); // 우측 스티키 너비 재계산
|
|
218
190
|
}
|
|
219
|
-
|
|
220
|
-
detectStickyWidth(tableRef.value.$el, false); // 우측 스티키 너비 재계산
|
|
221
191
|
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export function useResizable() {
|
|
225
192
|
return {
|
|
226
193
|
addResizable,
|
|
227
194
|
addStickyColumn,
|