quasar-ui-sellmate-ui-kit 3.14.9 → 3.14.11

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,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar-ui-sellmate-ui-kit",
3
- "version": "3.14.9",
3
+ "version": "3.14.11",
4
4
  "author": "Sellmate Dev Team <dev@sellmate.co.kr>",
5
5
  "description": "Sellmate UI Kit",
6
6
  "license": "MIT",
@@ -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.isStickyLeft || stickyColumn.isStickyRight,
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.isStickyLeft,
22
- 'sticky-right-table': stickyColumn.isStickyRight,
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>
@@ -166,11 +132,13 @@
166
132
  type: Boolean,
167
133
  default: false,
168
134
  },
135
+ useLastCellResizable: {
136
+ type: Boolean,
137
+ default: false,
138
+ },
169
139
  stickyColumn: {
170
140
  type: Object,
171
141
  default: () => ({
172
- isStickyLeft: false,
173
- isStickyRight: false,
174
142
  leftStickyCount: 0,
175
143
  rightStickyCount: 0,
176
144
  }),
@@ -299,12 +267,12 @@
299
267
  const tableElement = () => sTableRef.value.$el;
300
268
 
301
269
  if (props.resizable) {
302
- addResizable(sTableRef, props.stickyColumn);
270
+ addResizable(sTableRef, props.stickyColumn, props.useLastCellResizable);
303
271
  }
304
272
 
305
273
  const { count, direction: stickyDirection } = props.stickyColumn;
306
- const { isStickyLeft, isStickyRight } = props.stickyColumn;
307
- if (isStickyLeft || isStickyRight) {
274
+ const { leftStickyCount, rightStickyCount } = props.stickyColumn;
275
+ if (leftStickyCount > 0 || rightStickyCount > 0) {
308
276
  addStickyColumn(sTableRef, props.stickyColumn);
309
277
  observeScrollForStickyShadow(tableElement());
310
278
  }
@@ -379,7 +347,8 @@
379
347
  .q-table__middle {
380
348
  .q-table {
381
349
  overflow: auto;
382
- table-layout: fixed;
350
+ width: 100%;
351
+ table-layout: auto;
383
352
  tr {
384
353
  th,
385
354
  td {
@@ -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 = '4px';
13
+ div.style.width = `${HANDLE_WIDTH}px`;
9
14
  div.style.position = 'absolute';
10
15
  div.style.cursor = 'col-resize';
11
- div.style.backgroundColor = 'none';
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 = 2;
20
+ div.style.zIndex = HANDLE_Z_INDEX;
16
21
  div.style.userSelect = 'none';
17
- div.style.height = '16px';
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,148 @@ function detectStickyWidth(tableElement, isStickyLeft) {
46
50
  });
47
51
  }
48
52
 
49
- // Helper function to measure text width
50
- function getTextWidth(text, style) {
51
- const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement('canvas'));
52
- const context = canvas.getContext('2d');
53
- const font = style.font || `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;
54
- context.font = font;
55
- return context.measureText(text).width;
56
- }
57
-
58
- function setListeners(div, position, useSticky, restrictedColClass = '') {
59
- // resizable 속성을 사용할 때에 이벤트
60
- let curCol;
61
- let pageX;
62
- let curColWidth;
63
-
64
- const onMouseMove = e => {
65
- if (!curCol) return false;
66
-
67
- const isRestricted = curCol.classList.contains(restrictedColClass);
68
-
69
- const diffX = e.pageX - pageX;
70
- let calcWidth = '';
71
-
72
- const isStickyLeft = position === 'right';
73
-
74
- if (isStickyLeft) {
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
- curCol.style.width = `${calcWidth}px`;
89
- curCol.style.minWidth = `${calcWidth}px`;
90
- curCol.style.maxWidth = `${calcWidth}px`;
91
-
92
- if (useSticky && curCol) {
93
- const table = curCol.closest('table').parentElement;
94
- detectStickyWidth(table, position === 'right');
95
- }
96
-
97
- return true;
98
- };
99
-
100
- const onMouseUp = () => {
101
- curCol = undefined;
102
- pageX = undefined;
103
- curColWidth = undefined;
104
- document.removeEventListener('mousemove', onMouseMove);
105
- document.removeEventListener('mouseup', onMouseUp);
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
- const onMouseDown = e => {
109
- curCol = e.target.parentElement;
110
- pageX = e.pageX;
111
- curColWidth = curCol.offsetWidth;
112
- document.addEventListener('mousemove', onMouseMove, { passive: true });
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
- div.addEventListener('mousedown', onMouseDown, { passive: true });
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 appendResizableDiv(col, direction, useSticky, restrictedColClass = '') {
120
- const div = createDiv(direction);
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
- function getTableCols(tableEl) {
126
- const tableElement = tableEl.getElementsByTagName('table')[0];
127
- const firstRow = tableElement.getElementsByTagName('tr')[0];
128
- return firstRow ? Array.from(firstRow.children) : [];
129
- }
120
+ rows.forEach(row => {
121
+ const cells = Array.from(row.children);
122
+ const targetCell = cells[colIdx];
123
+ if (!targetCell) return;
130
124
 
131
- function addResizable(tableRef, stickyColumnsConfig = {}) {
132
- const cols = getTableCols(tableRef.value.$el);
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
- const leftStickyCount = stickyColumnsConfig.leftStickyCount || 0;
135
- const rightStickyCount = stickyColumnsConfig.rightStickyCount || 0;
132
+ function addResizable(tableRef, stickyColumnsConfig = {}, useLastCellResizable = false) {
133
+ const cols = getTableCols(tableRef.value.$el);
134
+ const leftStickyCount = stickyColumnsConfig.leftStickyCount || 0;
135
+ const rightStickyCount = stickyColumnsConfig.rightStickyCount || 0;
136
136
 
137
- cols.forEach((col, colIdx) => {
138
- const isLastCol = colIdx >= cols.length - 1;
139
- const isFirstCol = colIdx === 0;
140
137
  const isSelectTable = tableRef.value.$el.classList.contains('s-select-table');
141
138
 
142
- // 🔑 스티키 컬럼이라면 리사이즈 핸들 생성 금지
143
- const isLeftSticky = colIdx < leftStickyCount;
144
- const isRightSticky = colIdx >= cols.length - rightStickyCount;
139
+ cols.forEach((col, colIdx) => {
140
+ const isFirstCol = colIdx === 0;
141
+ const isLastCol = colIdx === cols.length - 1;
142
+ const isLeftSticky = colIdx < leftStickyCount;
143
+ const isRightSticky = colIdx >= cols.length - rightStickyCount;
145
144
 
146
- if (isLeftSticky || isRightSticky) {
147
- return; // 스티키 컬럼이면 appendResizableDiv 호출하지 않음
148
- }
145
+ // 🔑 스티키 컬럼이라면 리사이즈 핸들 생성 금지!! appendResizableDiv 호출하지 않음
146
+ if (isLeftSticky || isRightSticky) return;
147
+
148
+ const shouldAddResizable = (() => {
149
+ if (isSelectTable) {
150
+ if (useLastCellResizable && isLastCol) return true;
151
+ return !isFirstCol && !isLastCol;
152
+ }
153
+ return useLastCellResizable ? !isLastCol : true;
154
+ })();
149
155
 
150
- // 나머지 컬럼만 리사이즈 핸들 생성
151
- if (isSelectTable) {
152
- if (!isFirstCol && !isLastCol) {
156
+ if (shouldAddResizable) {
153
157
  appendResizableDiv(col, 'right', false);
154
158
  }
155
- } else if (!isLastCol) {
156
- appendResizableDiv(col, 'right', false);
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;
159
+ });
160
+ }
185
161
 
186
- const cols = getTableCols(tableRef.value.$el);
187
- const isSelectTable = tableRef.value.$el.classList.contains('s-select-table');
188
- const restrictedColClass = `sticky-col-${isSelectTable ? leftStickyCount : leftStickyCount - 1}`;
162
+ function addStickyColumn(tableRef, stickyColumnsConfig) {
163
+ const { leftStickyCount, rightStickyCount } = stickyColumnsConfig;
189
164
 
190
- // Left Sticky Columns
191
- if (isStickyLeft && leftStickyCount > 0) {
192
- // let i = isSelectTable ? 1 : 0; // Select Table일 경우 첫번째 컬럼은 스티키가 아님
193
- const count = isSelectTable ? leftStickyCount + 1 : leftStickyCount; // Select Table일 경우 +1
165
+ const cols = getTableCols(tableRef.value.$el);
166
+ const isSelectTable = tableRef.value.$el.classList.contains('s-select-table');
194
167
 
195
- for (let i = 0; i < count; i++) {
196
- applyStickyToColumn(tableRef.value.$el, i, true, '0px');
197
- if (isSelectTable && i > 0) {
198
- appendResizableDiv(cols[i], 'right', true, restrictedColClass); // 오른쪽에 리사이즈 핸들 추가
199
- if (i === count - 1) {
200
- restrictedMinWidth = cols[i].style.width.replace('px', ''); // 마지막 스티키 컬럼의 최소 너비 저장
201
- }
202
- } else {
203
- appendResizableDiv(cols[i], 'right', true, restrictedColClass); // 오른쪽에 리사이즈 핸들 추가
204
- if (i === count - 1) {
205
- restrictedMinWidth = cols[i].style.width.replace('px', ''); // 마지막 스티키 컬럼의 최소 너비 저장
168
+ // Left Sticky Columns
169
+ if (leftStickyCount > 0) {
170
+ // let i = isSelectTable ? 1 : 0; // Select Table일 경우 첫번째 컬럼은 스티키가 아님
171
+ const count = isSelectTable ? leftStickyCount + 1 : leftStickyCount; // Select Table일 경우 +1
172
+
173
+ for (let i = 0; i < count; i++) {
174
+ applyStickyToColumn(tableRef.value.$el, i, true, '0px');
175
+ if (isSelectTable && i > 0) {
176
+ appendResizableDiv(cols[i], 'right', true); // 오른쪽에 리사이즈 핸들 추가
177
+ } else {
178
+ appendResizableDiv(cols[i], 'right', true); // 오른쪽에 리사이즈 핸들 추가
206
179
  }
207
180
  }
181
+
182
+ detectStickyWidth(tableRef.value.$el, true); // 좌측 스티키 너비 재계산
208
183
  }
209
184
 
210
- detectStickyWidth(tableRef.value.$el, true); // 좌측 스티키 너비 재계산
211
- }
185
+ // Right Sticky Columns
186
+ if (rightStickyCount > 0) {
187
+ for (let i = cols.length - rightStickyCount; i < cols.length; i++) {
188
+ applyStickyToColumn(tableRef.value.$el, i, false, '0px');
189
+ appendResizableDiv(cols[i], 'left', true); // 왼쪽에 리사이즈 핸들 추가 (우측 스티키)
190
+ }
212
191
 
213
- // Right Sticky Columns
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); // 왼쪽에 리사이즈 핸들 추가 (우측 스티키)
192
+ detectStickyWidth(tableRef.value.$el, false); // 우측 스티키 너비 재계산
218
193
  }
219
-
220
- detectStickyWidth(tableRef.value.$el, false); // 우측 스티키 너비 재계산
221
194
  }
222
- }
223
-
224
- export function useResizable() {
225
195
  return {
226
196
  addResizable,
227
197
  addStickyColumn,