@sellmate/design-system 1.21.0 → 1.22.0
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/cjs/design-system.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/sd-button_2.cjs.entry.js +4 -4
- package/dist/cjs/sd-chip-input.cjs.entry.js +41 -17
- package/dist/cjs/sd-pagination_4.cjs.entry.js +86 -7
- package/dist/collection/components/assets/CaretDown.js +1 -1
- package/dist/collection/components/assets/CaretLeft.js +1 -1
- package/dist/collection/components/assets/CaretRight.js +1 -1
- package/dist/collection/components/assets/CaretUp.js +1 -1
- package/dist/collection/components/sd-chip-input/sd-chip-input.css +5 -0
- package/dist/collection/components/sd-chip-input/sd-chip-input.js +40 -16
- package/dist/collection/components/sd-table/sd-table.stories.helpers.js +97 -0
- package/dist/collection/components/sd-table/sd-thead/sd-thead.css +21 -0
- package/dist/collection/components/sd-table/sd-thead/sd-thead.js +87 -7
- package/dist/components/{p-D4zy1T3V.js → p-58DLP3IW.js} +1 -1
- package/dist/components/{p-CcwzTAJC.js → p-B0myARGe.js} +1 -1
- package/dist/components/{p-CBDBmMmw.js → p-B12iH3Zk.js} +1 -1
- package/dist/components/{p-B5VNSTAf.js → p-B2bF2KlS.js} +1 -1
- package/dist/components/{p-C3mTIE8H.js → p-BXRgi3NZ.js} +1 -1
- package/dist/components/{p-DC5W8Uy1.js → p-Bm3NWPaP.js} +1 -1
- package/dist/components/{p-FA9fGvbL.js → p-BpQwjSB8.js} +1 -1
- package/dist/components/{p-BjSMh85k.js → p-BpjmheLG.js} +1 -1
- package/dist/components/{p-CTw1Deo8.js → p-Bric-SEs.js} +1 -1
- package/dist/components/{p-CZYTZeMe.js → p-BwTsP0Ak.js} +1 -1
- package/dist/components/p-CCO1WtEj.js +1 -0
- package/dist/components/{p-DPXOBYhf.js → p-CHxVi6l1.js} +1 -1
- package/dist/components/{p-Dz7VXmIA.js → p-Cdzn78dP.js} +1 -1
- package/dist/components/{p-YpyfqzoP.js → p-Cjf8PHEl.js} +1 -1
- package/dist/components/{p-l7TaS8q9.js → p-Co2ThnbG.js} +1 -1
- package/dist/components/{p-BrHnpCXR.js → p-CwSlRPMm.js} +1 -1
- package/dist/components/{p-CTxZT3Je.js → p-D7StBSjK.js} +1 -1
- package/dist/components/{p-Btj50AUe.js → p-DFbj6d3L.js} +1 -1
- package/dist/components/{p-Cugxp5lo.js → p-DlXBFtBO.js} +1 -1
- package/dist/components/{p-BIHVGo10.js → p-Du_qPqW-.js} +1 -1
- package/dist/components/{p-DJY7lCe4.js → p-DzAvlr8W.js} +1 -1
- package/dist/components/{p-4MIzxb0h.js → p-FrqOl9KZ.js} +1 -1
- package/dist/components/{p-BQQC-6k4.js → p-JMuxVcTW.js} +1 -1
- package/dist/components/{p-B76pFg6k.js → p-OjchKJGr.js} +1 -1
- package/dist/components/{p-DIc8C633.js → p-YCGkwgiM.js} +1 -1
- package/dist/components/{p-DZikCqcw.js → p-ZvP2Ce6J.js} +1 -1
- package/dist/components/p-kRH2GOb0.js +1 -0
- package/dist/components/{p-s_75vJTu.js → p-mcMbSkii.js} +1 -1
- package/dist/components/{p-DU0IkIvI.js → p-vPS2GNz3.js} +1 -1
- package/dist/components/sd-action-modal.js +1 -1
- package/dist/components/sd-barcode-input.js +1 -1
- package/dist/components/sd-button.js +1 -1
- package/dist/components/sd-calendar.js +1 -1
- package/dist/components/sd-callout.js +1 -1
- package/dist/components/sd-checkbox.js +1 -1
- package/dist/components/sd-chip-input.js +1 -1
- package/dist/components/sd-chip.js +1 -1
- package/dist/components/sd-confirm-modal.js +1 -1
- package/dist/components/sd-date-picker-trigger.js +1 -1
- package/dist/components/sd-date-picker.js +1 -1
- package/dist/components/sd-date-range-picker-calendar.js +1 -1
- package/dist/components/sd-date-range-picker.js +1 -1
- package/dist/components/sd-dropdown-button.js +1 -1
- package/dist/components/sd-field.js +1 -1
- package/dist/components/sd-file-picker.js +1 -1
- package/dist/components/sd-ghost-button.js +1 -1
- package/dist/components/sd-guide.js +1 -1
- package/dist/components/sd-icon.js +1 -1
- package/dist/components/sd-input.js +1 -1
- package/dist/components/sd-key-value-table.js +1 -1
- package/dist/components/sd-loading-modal.js +1 -1
- package/dist/components/sd-modal-container.js +1 -1
- package/dist/components/sd-number-input.js +1 -1
- package/dist/components/sd-pagination.js +1 -1
- package/dist/components/sd-popover.js +1 -1
- package/dist/components/sd-popup.js +1 -1
- package/dist/components/sd-select-list-item-search.js +1 -1
- package/dist/components/sd-select-list-item.js +1 -1
- package/dist/components/sd-select-listbox.js +1 -1
- package/dist/components/sd-select-trigger.js +1 -1
- package/dist/components/sd-select.js +1 -1
- package/dist/components/sd-table.js +1 -1
- package/dist/components/sd-tabs.js +1 -1
- package/dist/components/sd-tag.js +1 -1
- package/dist/components/sd-text-link.js +1 -1
- package/dist/components/sd-textarea.js +1 -1
- package/dist/components/sd-thead.js +1 -1
- package/dist/components/sd-toast-container.js +1 -1
- package/dist/components/sd-toast.js +1 -1
- package/dist/components/sd-tooltip.js +1 -1
- package/dist/components/sd-tr.js +1 -1
- package/dist/design-system/design-system.esm.js +1 -1
- package/dist/design-system/p-14447dd5.entry.js +1 -0
- package/dist/design-system/p-4bbc894b.entry.js +1 -0
- package/dist/design-system/p-e7d4b78e.entry.js +1 -0
- package/dist/esm/design-system.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/sd-button_2.entry.js +4 -4
- package/dist/esm/sd-chip-input.entry.js +41 -17
- package/dist/esm/sd-pagination_4.entry.js +86 -7
- package/dist/types/components/sd-table/constants.d.ts +1 -0
- package/dist/types/components/sd-table/sd-table.stories.helpers.d.ts +10 -0
- package/dist/types/components/sd-table/sd-thead/sd-thead.d.ts +8 -0
- package/hydrate/index.js +132 -28
- package/hydrate/index.mjs +132 -28
- package/package.json +1 -1
- package/dist/components/p-BVlg0BoC.js +0 -1
- package/dist/components/p-BzsHwLh6.js +0 -1
- package/dist/design-system/p-0f35cd21.entry.js +0 -1
- package/dist/design-system/p-4e44b45b.entry.js +0 -1
- package/dist/design-system/p-fe5b8eaa.entry.js +0 -1
|
@@ -234,7 +234,7 @@ const SdTbody = class {
|
|
|
234
234
|
};
|
|
235
235
|
SdTbody.style = sdTbodyCss();
|
|
236
236
|
|
|
237
|
-
const sdTheadCss = () => `sd-thead{display:contents}sd-thead *{box-sizing:border-box}.thead{display:table-header-group;height:var(--table-header-height, 36px)}.thead--sticky{position:sticky;top:0;z-index:120}.tr{display:table-row;width:100%}.th{display:table-cell;background:var(--table-header-bg, #F5FAFF);height:var(--table-header-height, 36px);padding:0 var(--table-header-padding-x, 16px);font-family:var(--table-header-font-family, inherit);font-weight:var(--table-header-font-weight, 500);font-size:var(--table-header-font-size, 12px);line-height:var(--table-header-line-height, 20px);text-decoration:var(--table-header-text-decoration, none);vertical-align:middle;border-bottom:var(--table-border-width, 1px) solid var(--table-border-color, #E1E1E1);-webkit-user-select:none;user-select:none;position:relative;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.th--selected{position:relative;width:var(--table-selectable-width, 48px) !important;max-width:var(--table-selectable-width, 48px) !important;min-width:var(--table-selectable-width, 48px) !important;text-align:center}.th--selected sd-checkbox label{position:relative}.th--selected sd-checkbox label:before{content:"";position:absolute;inset:-6px}.th.sticky-left{position:sticky;background-color:var(--table-header-bg, #F5FAFF);z-index:110 !important;left:var(--sticky-left-offset, 0)}.th.sticky-right{position:sticky;background-color:var(--table-header-bg, #F5FAFF);z-index:110 !important;right:var(--sticky-right-offset, 0)}.th.sticky-left-edge:after{content:"";position:absolute;top:0;left:100%;right:-20px;width:20px;height:100%;z-index:101 !important;box-shadow:inset 12px 0 20px -25px;opacity:0;pointer-events:none;transition:opacity 0.2s}.th.sticky-right-edge:after{content:"";position:absolute;top:0;left:-20px;width:20px;height:100%;z-index:101 !important;box-shadow:inset -12px 0 20px -25px;opacity:0;pointer-events:none;transition:opacity 0.2s}.th.sticky-left-edge.is-scrolled-left{overflow:visible}.th.sticky-left-edge.is-scrolled-left:after{opacity:1}.th.sticky-right-edge.is-scrolled-right{overflow:visible}.th.sticky-right-edge.is-scrolled-right:after{opacity:1}.th__content{display:flex;flex-flow:row nowrap;align-items:center;gap:var(--table-header-gap, 4px)}.th__content--left{justify-content:flex-start}.th__content--center{justify-content:center}.th__content--right{justify-content:flex-end}.th__content--label{white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.th__bar{position:absolute;top:50%;right:0;transform:translateY(-50%);width:var(--table-border-width, 1px);height:var(--table-header-resizer-height, 16px);z-index:3;background-color:var(--table-header-resizer-color, #CCCCCC)}.th__resizer{position:absolute;top:50%;right:0;transform:translateY(-50%);width:4px;height:var(--table-header-resizer-height, 16px);cursor:col-resize;z-index:3;border-left:var(--table-border-width, 1px) solid var(--table-header-resizer-color, #CCCCCC);border-right:var(--table-border-width, 1px) solid var(--table-header-resizer-color, #CCCCCC)}.th__resizer--left{right:auto;left:0}`;
|
|
237
|
+
const sdTheadCss = () => `sd-thead{display:contents}sd-thead *{box-sizing:border-box}.thead{display:table-header-group;height:var(--table-header-height, 36px)}.thead--sticky{position:sticky;top:0;z-index:120}.tr{display:table-row;width:100%}.th{display:table-cell;background:var(--table-header-bg, #F5FAFF);height:var(--table-header-height, 36px);padding:0 var(--table-header-padding-x, 16px);font-family:var(--table-header-font-family, inherit);font-weight:var(--table-header-font-weight, 500);font-size:var(--table-header-font-size, 12px);line-height:var(--table-header-line-height, 20px);text-decoration:var(--table-header-text-decoration, none);vertical-align:middle;border-bottom:var(--table-border-width, 1px) solid var(--table-border-color, #E1E1E1);-webkit-user-select:none;user-select:none;position:relative;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.th--selected{position:relative;width:var(--table-selectable-width, 48px) !important;max-width:var(--table-selectable-width, 48px) !important;min-width:var(--table-selectable-width, 48px) !important;text-align:center}.th--selected sd-checkbox label{position:relative}.th--selected sd-checkbox label:before{content:"";position:absolute;inset:-6px}.th.sticky-left{position:sticky;background-color:var(--table-header-bg, #F5FAFF);z-index:110 !important;left:var(--sticky-left-offset, 0)}.th.sticky-right{position:sticky;background-color:var(--table-header-bg, #F5FAFF);z-index:110 !important;right:var(--sticky-right-offset, 0)}.th.sticky-left-edge:after{content:"";position:absolute;top:0;left:100%;right:-20px;width:20px;height:100%;z-index:101 !important;box-shadow:inset 12px 0 20px -25px;opacity:0;pointer-events:none;transition:opacity 0.2s}.th.sticky-right-edge:after{content:"";position:absolute;top:0;left:-20px;width:20px;height:100%;z-index:101 !important;box-shadow:inset -12px 0 20px -25px;opacity:0;pointer-events:none;transition:opacity 0.2s}.th.sticky-left-edge.is-scrolled-left{overflow:visible}.th.sticky-left-edge.is-scrolled-left:after{opacity:1}.th.sticky-right-edge.is-scrolled-right{overflow:visible}.th.sticky-right-edge.is-scrolled-right:after{opacity:1}.th__content{display:flex;flex-flow:row nowrap;align-items:center;gap:var(--table-header-gap, 4px)}.th__content--left{justify-content:flex-start}.th__content--center{justify-content:center}.th__content--right{justify-content:flex-end}.th__content--label{white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.th__bar{position:absolute;top:50%;right:0;transform:translateY(-50%);width:var(--table-border-width, 1px);height:var(--table-header-resizer-height, 16px);z-index:3;background-color:var(--table-header-resizer-color, #CCCCCC)}.th__dropdown-trigger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:16px;height:16px;padding:0;border:none;background:transparent;cursor:pointer;color:inherit;border-radius:2px}.th__dropdown-trigger sd-icon{transition:transform 0.15s ease}.th__dropdown-trigger--open sd-icon{transform:rotate(180deg)}.th__resizer{position:absolute;top:50%;right:0;transform:translateY(-50%);width:4px;height:var(--table-header-resizer-height, 16px);cursor:col-resize;z-index:3;border-left:var(--table-border-width, 1px) solid var(--table-header-resizer-color, #CCCCCC);border-right:var(--table-border-width, 1px) solid var(--table-header-resizer-color, #CCCCCC)}.th__resizer--left{right:auto;left:0}`;
|
|
238
238
|
|
|
239
239
|
const SdThead = class {
|
|
240
240
|
constructor(hostRef) {
|
|
@@ -270,14 +270,29 @@ const SdThead = class {
|
|
|
270
270
|
_stickyHeader = false;
|
|
271
271
|
_scrolledLeft = false;
|
|
272
272
|
_scrolledRight = false;
|
|
273
|
+
dropdownOpenMap = {};
|
|
273
274
|
tableEl = null;
|
|
275
|
+
dropdownRefs = {};
|
|
276
|
+
dropdownThRefs = {};
|
|
277
|
+
dropdownPortals = {};
|
|
274
278
|
handleColumnsChange(newCols) {
|
|
275
279
|
if (Array.isArray(newCols) && (this.columnWidths ?? []).length === 0) {
|
|
276
280
|
this.columnWidths = newCols.map(c => (c.autoWidth ? 0 : parseInt(c.width || '120', 10)));
|
|
277
281
|
}
|
|
278
282
|
}
|
|
283
|
+
disconnectedCallback() {
|
|
284
|
+
const portals = this.dropdownPortals ?? {};
|
|
285
|
+
Object.values(portals).forEach(portal => {
|
|
286
|
+
if (portal?.parentNode != null)
|
|
287
|
+
portal.parentNode.removeChild(portal);
|
|
288
|
+
});
|
|
289
|
+
}
|
|
279
290
|
componentWillLoad() {
|
|
280
291
|
this.syncTableContext();
|
|
292
|
+
this.dropdownOpenMap = this.dropdownOpenMap ?? {};
|
|
293
|
+
this.dropdownRefs = this.dropdownRefs ?? {};
|
|
294
|
+
this.dropdownThRefs = this.dropdownThRefs ?? {};
|
|
295
|
+
this.dropdownPortals = this.dropdownPortals ?? {};
|
|
281
296
|
this.columnWidths = Array.isArray(this.columnWidths) ? this.columnWidths : [];
|
|
282
297
|
this.resolveConfig();
|
|
283
298
|
if ((this.columnWidths ?? []).length === 0) {
|
|
@@ -287,6 +302,36 @@ const SdThead = class {
|
|
|
287
302
|
componentDidLoad() {
|
|
288
303
|
this.syncTableContext();
|
|
289
304
|
this.resolveConfig();
|
|
305
|
+
this.initDropdownPortals();
|
|
306
|
+
}
|
|
307
|
+
// sd-portal을 body에 붙여 CSS transform 영향 없이 정확한 위치에 패널을 표시한다.
|
|
308
|
+
// <slot>을 render에 두지 않고 직접 DOM 이동(slot 속성 제거)으로 Stencil 슬롯 에뮬레이션 충돌을 피한다.
|
|
309
|
+
initDropdownPortals() {
|
|
310
|
+
const cols = this._columns ?? [];
|
|
311
|
+
const hasDropdownCols = cols.filter(c => c.hasDropdown === true);
|
|
312
|
+
if (hasDropdownCols.length === 0)
|
|
313
|
+
return;
|
|
314
|
+
for (const col of hasDropdownCols) {
|
|
315
|
+
const colName = col.name;
|
|
316
|
+
// 이미 포탈이 생성된 컬럼은 건너뜀 (refreshConfig 재호출 대비)
|
|
317
|
+
if ((this.dropdownPortals ?? {})[colName] != null)
|
|
318
|
+
continue;
|
|
319
|
+
const slotContent = this.el.querySelector(`[slot="dropdown-${colName}"]`);
|
|
320
|
+
if (slotContent == null)
|
|
321
|
+
continue;
|
|
322
|
+
// slot 속성 제거: Stencil 슬롯 에뮬레이션이 재배포하지 못하게 한다
|
|
323
|
+
slotContent.removeAttribute('slot');
|
|
324
|
+
const portal = document.createElement('sd-portal');
|
|
325
|
+
portal.parentRef = this.dropdownThRefs[colName] ?? null;
|
|
326
|
+
portal.open = false;
|
|
327
|
+
// 첫 open 전까지 포탈 호스트 자체를 숨긴다.
|
|
328
|
+
// moveSlotContent()가 open=true 시 children을 독립 wrapper div로 이동하므로 이후 동작에 영향 없음.
|
|
329
|
+
portal.style.display = 'none';
|
|
330
|
+
portal.addEventListener('sdClose', () => this.closeDropdown(colName));
|
|
331
|
+
portal.appendChild(slotContent);
|
|
332
|
+
document.body.appendChild(portal);
|
|
333
|
+
this.dropdownPortals[colName] = portal;
|
|
334
|
+
}
|
|
290
335
|
}
|
|
291
336
|
syncTableContext() {
|
|
292
337
|
// sd-table이 shadow:true이므로 fallback content로 렌더되면 closest가 경계를 못 넘는다.
|
|
@@ -329,6 +374,7 @@ const SdThead = class {
|
|
|
329
374
|
/** 테이블 설정을 다시 불러옵니다. */
|
|
330
375
|
async refreshConfig() {
|
|
331
376
|
this.resolveConfig();
|
|
377
|
+
this.initDropdownPortals();
|
|
332
378
|
}
|
|
333
379
|
/** 컬럼 너비를 업데이트합니다. */
|
|
334
380
|
async setColumnWidths(widths) {
|
|
@@ -373,6 +419,28 @@ const SdThead = class {
|
|
|
373
419
|
handleColumnSort = (col) => {
|
|
374
420
|
this.sdColumnSort.emit({ column: col });
|
|
375
421
|
};
|
|
422
|
+
toggleDropdown(name) {
|
|
423
|
+
const isOpen = this.dropdownOpenMap[name] !== true;
|
|
424
|
+
const portals = this.dropdownPortals ?? {};
|
|
425
|
+
const newMap = { ...this.dropdownOpenMap };
|
|
426
|
+
// _columns 기준으로 순회: portals가 비어도 dropdownOpenMap은 항상 갱신됨
|
|
427
|
+
for (const col of (this._columns ?? []).filter(c => c.hasDropdown === true)) {
|
|
428
|
+
const shouldBeOpen = col.name === name ? isOpen : false;
|
|
429
|
+
newMap[col.name] = shouldBeOpen;
|
|
430
|
+
const portal = portals[col.name];
|
|
431
|
+
if (portal != null)
|
|
432
|
+
portal.open = shouldBeOpen;
|
|
433
|
+
}
|
|
434
|
+
this.dropdownOpenMap = newMap;
|
|
435
|
+
}
|
|
436
|
+
closeDropdown(name) {
|
|
437
|
+
if (this.dropdownOpenMap[name] !== true)
|
|
438
|
+
return;
|
|
439
|
+
this.dropdownOpenMap = { ...this.dropdownOpenMap, [name]: false };
|
|
440
|
+
const portal = (this.dropdownPortals ?? {})[name];
|
|
441
|
+
if (portal != null)
|
|
442
|
+
portal.open = false;
|
|
443
|
+
}
|
|
376
444
|
handleSelectAll(checked) {
|
|
377
445
|
const nextChecked = !!checked;
|
|
378
446
|
const safeRows = Array.isArray(this.rows) ? this.rows : [];
|
|
@@ -389,6 +457,8 @@ const SdThead = class {
|
|
|
389
457
|
}
|
|
390
458
|
render() {
|
|
391
459
|
const safeRows = Array.isArray(this.rows) ? this.rows : [];
|
|
460
|
+
const dropdownOpenMap = this.dropdownOpenMap ?? {};
|
|
461
|
+
const dropdownRefs = this.dropdownRefs ?? {};
|
|
392
462
|
const stickyLeftCount = this._stickyColumn.left || 0;
|
|
393
463
|
const stickyRightCount = this._stickyColumn.right || 0;
|
|
394
464
|
const stickyLeftCols = this.visibleColumns.slice(0, stickyLeftCount);
|
|
@@ -410,22 +480,25 @@ const SdThead = class {
|
|
|
410
480
|
'--table-border-color': sdTable_config.TABLE_BORDER.color,
|
|
411
481
|
'--table-border-width': `${sdTable_config.TABLE_BORDER.width}px`,
|
|
412
482
|
};
|
|
413
|
-
return (index.h(index.Host, { key: '
|
|
483
|
+
return (index.h(index.Host, { key: '947f5e5b0e59e7e6f8a73e4fd44dbfa646cb630a', slot: `${this.tableId}-head`, style: headStyle }, index.h("thead", { key: '2e0ffbfe9d96528c6e0082d4883fa462a18831d6', class: {
|
|
414
484
|
'thead': true,
|
|
415
485
|
'thead--sticky': this._stickyHeader,
|
|
416
|
-
} }, index.h("tr", { key: '
|
|
486
|
+
} }, index.h("tr", { key: '5843a18e1548bc6546e447d4c9213375116af0e9', class: "tr" }, this._selectable && (index.h("th", { key: '914024ca35874747e39f1819337cd4ad1cbe733d', class: {
|
|
417
487
|
'th': true,
|
|
418
488
|
'th--selected': true,
|
|
419
489
|
'sticky-left': true,
|
|
420
490
|
'sticky-left-edge': stickyLeftCount === 0,
|
|
421
491
|
'is-scrolled-left': stickyLeftCount === 0 && this._scrolledLeft,
|
|
422
|
-
}, style: { '--sticky-left-offset': '0px' } }, index.h("sd-checkbox", { key: '
|
|
492
|
+
}, style: { '--sticky-left-offset': '0px' } }, index.h("sd-checkbox", { key: 'e07232f1f5fa02589573ddaae53ebdadbdb97674', value: this.getIsAllChecked(), disabled: safeRows.length === 0, onSdUpdate: (e) => this.handleSelectAll(e.detail) }), index.h("div", { key: '08b504cfd4f420e76e91d649eed28c7068517044', class: "th__bar" }))), stickyLeftCols.map((col, idx) => (index.h("th", { key: col.name, class: {
|
|
423
493
|
'th': true,
|
|
424
494
|
[`${col.thClass}`]: Boolean(col.thClass),
|
|
425
495
|
'sticky-left': true,
|
|
426
496
|
'sticky-left-edge': idx === stickyLeftCount - 1,
|
|
427
497
|
'is-scrolled-left': idx === stickyLeftCount - 1 && this._scrolledLeft,
|
|
428
|
-
}, style: { ...col.thStyle, ...this.getStickyStyle(idx) } }, index.h("div", { class: `th__content th__content--${col.align || 'left'}` }, index.h("div", { class: "th__content--label" }, col.label), col.icon && (index.h("sd-icon", { name: col.icon, size: "12", color: sdTable_config.resolveTableIconColor(col.icon, col.iconColor) })), col.sort && (index.h("sd-icon", { name: sdTable_config.resolveSortIconName(col.sort), size: "12", color: sdTable_config.resolveTableIconColor(sdTable_config.resolveSortIconName(col.sort), col.iconColor), onClick: () => this.handleColumnSort(col), style: { cursor: 'pointer' } })), col.tooltip && (index.h("sd-tooltip", { ...col.tooltipOptions }, index.h("div", { slot: "content" }, col.tooltip.map(text => (index.h("p", null, text))))))
|
|
498
|
+
}, style: { ...col.thStyle, ...this.getStickyStyle(idx) }, ref: col.hasDropdown === true ? (el => { this.dropdownThRefs[col.name] = el; }) : undefined }, index.h("div", { class: `th__content th__content--${col.align || 'left'}` }, index.h("div", { class: "th__content--label" }, col.label), col.icon && (index.h("sd-icon", { name: col.icon, size: "12", color: sdTable_config.resolveTableIconColor(col.icon, col.iconColor) })), col.sort && (index.h("sd-icon", { name: sdTable_config.resolveSortIconName(col.sort), size: "12", color: sdTable_config.resolveTableIconColor(sdTable_config.resolveSortIconName(col.sort), col.iconColor), onClick: () => this.handleColumnSort(col), style: { cursor: 'pointer' } })), col.tooltip && (index.h("sd-tooltip", { ...col.tooltipOptions }, index.h("div", { slot: "content" }, col.tooltip.map(text => (index.h("p", null, text)))))), col.hasDropdown === true && (index.h("button", { class: {
|
|
499
|
+
'th__dropdown-trigger': true,
|
|
500
|
+
'th__dropdown-trigger--open': dropdownOpenMap[col.name] === true,
|
|
501
|
+
}, ref: el => { dropdownRefs[col.name] = el; }, onClick: () => this.toggleDropdown(col.name), "aria-haspopup": "listbox", "aria-expanded": dropdownOpenMap[col.name] === true ? 'true' : 'false' }, index.h("sd-icon", { name: "chevronDown", size: "12" })))), this._resizable && idx !== lastColIdx && (
|
|
429
502
|
// column resize 는 마우스 드래그 전용 인터랙션이라 키보드 핸들러를 두지 않는다.
|
|
430
503
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
431
504
|
index.h("div", { class: "th__resizer", onMouseDown: (evt) => this.handleResize(idx, evt) }))))), middleCols.map((col, relativeIdx) => {
|
|
@@ -433,7 +506,10 @@ const SdThead = class {
|
|
|
433
506
|
return (index.h("th", { key: col.name, class: {
|
|
434
507
|
th: true,
|
|
435
508
|
[`${col.thClass}`]: Boolean(col.thClass),
|
|
436
|
-
}, style: { ...col.thStyle, ...this.getStickyStyle(actualColIdx) } }, index.h("div", { class: `th__content th__content--${col.align || 'left'}` }, index.h("div", { class: "th__content--label" }, col.label), col.icon && (index.h("sd-icon", { name: col.icon, size: "12", color: sdTable_config.resolveTableIconColor(col.icon, col.iconColor) })), col.sort && (index.h("sd-icon", { name: sdTable_config.resolveSortIconName(col.sort), size: "12", color: sdTable_config.resolveTableIconColor(sdTable_config.resolveSortIconName(col.sort), col.iconColor), onClick: () => this.handleColumnSort(col), style: { cursor: 'pointer' } })), col.tooltip && (index.h("sd-tooltip", { ...col.tooltipOptions }, index.h("div", { slot: "content" }, col.tooltip.map(text => (index.h("p", null, text))))))
|
|
509
|
+
}, style: { ...col.thStyle, ...this.getStickyStyle(actualColIdx) }, ref: col.hasDropdown === true ? (el => { this.dropdownThRefs[col.name] = el; }) : undefined }, index.h("div", { class: `th__content th__content--${col.align || 'left'}` }, index.h("div", { class: "th__content--label" }, col.label), col.icon && (index.h("sd-icon", { name: col.icon, size: "12", color: sdTable_config.resolveTableIconColor(col.icon, col.iconColor) })), col.sort && (index.h("sd-icon", { name: sdTable_config.resolveSortIconName(col.sort), size: "12", color: sdTable_config.resolveTableIconColor(sdTable_config.resolveSortIconName(col.sort), col.iconColor), onClick: () => this.handleColumnSort(col), style: { cursor: 'pointer' } })), col.tooltip && (index.h("sd-tooltip", { ...col.tooltipOptions }, index.h("div", { slot: "content" }, col.tooltip.map(text => (index.h("p", null, text)))))), col.hasDropdown === true && (index.h("button", { class: {
|
|
510
|
+
'th__dropdown-trigger': true,
|
|
511
|
+
'th__dropdown-trigger--open': this.dropdownOpenMap[col.name] === true,
|
|
512
|
+
}, ref: el => { this.dropdownRefs[col.name] = el; }, onClick: () => this.toggleDropdown(col.name), "aria-haspopup": "listbox", "aria-expanded": this.dropdownOpenMap[col.name] === true ? 'true' : 'false' }, index.h("sd-icon", { name: "chevronDown", size: "12" })))), this._resizable && actualColIdx !== lastColIdx && (
|
|
437
513
|
// column resize 는 마우스 드래그 전용 인터랙션이라 키보드 핸들러를 두지 않는다.
|
|
438
514
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
439
515
|
index.h("div", { class: "th__resizer", onMouseDown: (evt) => this.handleResize(actualColIdx, evt) }))));
|
|
@@ -445,7 +521,10 @@ const SdThead = class {
|
|
|
445
521
|
'sticky-right': true,
|
|
446
522
|
'sticky-right-edge': relativeIdx === 0,
|
|
447
523
|
'is-scrolled-right': relativeIdx === 0 && this._scrolledRight,
|
|
448
|
-
}, style: { ...col.thStyle, ...this.getStickyStyle(actualColIdx) } }, index.h("div", { class: `th__content th__content--${col.align || 'left'}` }, index.h("div", { class: "th__content--label" }, col.label), col.icon && (index.h("sd-icon", { name: col.icon, size: "12", color: sdTable_config.resolveTableIconColor(col.icon, col.iconColor) })), col.sort && (index.h("sd-icon", { name: sdTable_config.resolveSortIconName(col.sort), size: "12", color: sdTable_config.resolveTableIconColor(sdTable_config.resolveSortIconName(col.sort), col.iconColor), onClick: () => this.handleColumnSort(col), style: { cursor: 'pointer' } })), col.tooltip && (index.h("sd-tooltip", { ...col.tooltipOptions }, index.h("div", { slot: "content" }, col.tooltip.map(text => (index.h("p", null, text))))))
|
|
524
|
+
}, style: { ...col.thStyle, ...this.getStickyStyle(actualColIdx) }, ref: col.hasDropdown === true ? (el => { this.dropdownThRefs[col.name] = el; }) : undefined }, index.h("div", { class: `th__content th__content--${col.align || 'left'}` }, index.h("div", { class: "th__content--label" }, col.label), col.icon && (index.h("sd-icon", { name: col.icon, size: "12", color: sdTable_config.resolveTableIconColor(col.icon, col.iconColor) })), col.sort && (index.h("sd-icon", { name: sdTable_config.resolveSortIconName(col.sort), size: "12", color: sdTable_config.resolveTableIconColor(sdTable_config.resolveSortIconName(col.sort), col.iconColor), onClick: () => this.handleColumnSort(col), style: { cursor: 'pointer' } })), col.tooltip && (index.h("sd-tooltip", { ...col.tooltipOptions }, index.h("div", { slot: "content" }, col.tooltip.map(text => (index.h("p", null, text)))))), col.hasDropdown === true && (index.h("button", { class: {
|
|
525
|
+
'th__dropdown-trigger': true,
|
|
526
|
+
'th__dropdown-trigger--open': this.dropdownOpenMap[col.name] === true,
|
|
527
|
+
}, ref: el => { this.dropdownRefs[col.name] = el; }, onClick: () => this.toggleDropdown(col.name), "aria-haspopup": "listbox", "aria-expanded": this.dropdownOpenMap[col.name] === true ? 'true' : 'false' }, index.h("sd-icon", { name: "chevronDown", size: "12" })))), this._resizable && (
|
|
449
528
|
// column resize 는 마우스 드래그 전용 인터랙션이라 키보드 핸들러를 두지 않는다.
|
|
450
529
|
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
451
530
|
index.h("div", { class: "th__resizer th__resizer--left", onMouseDown: (evt) => this.handleResize(actualColIdx, evt, true) }))));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
2
|
export const CaretDown = (props) => {
|
|
3
3
|
const { size = 24, ...rest } = props;
|
|
4
|
-
return (h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...rest }, h("path", { d: "
|
|
4
|
+
return (h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...rest }, h("path", { d: "M19.2188 8.25C19.9555 8.25 20.2813 9.44246 19.7061 10.0342L12.4874 17.46C12.2028 17.7526 11.7974 17.7526 11.5127 17.46L4.294 10.0342C3.71879 9.44247 4.04461 8.25 4.7813 8.25H19.2188Z", fill: "currentColor" })));
|
|
5
5
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
2
|
export const CaretLeft = (props) => {
|
|
3
3
|
const { size = 24, ...rest } = props;
|
|
4
|
-
return (h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...rest }, h("path", { d: "
|
|
4
|
+
return (h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...rest }, h("path", { d: "M14.1423 4.29416C14.7698 3.71888 16.0358 4.04475 16.0358 4.78146V19.219C16.0358 19.9557 14.7698 20.2815 14.1423 19.7063L6.26827 12.4865C5.95813 12.2019 5.95791 11.7975 6.26827 11.5129L14.1423 4.29416Z", fill: "currentColor" })));
|
|
5
5
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
2
|
export const CaretRight = (props) => {
|
|
3
3
|
const { size = 24, ...rest } = props;
|
|
4
|
-
return (h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...rest }, h("path", { d: "
|
|
4
|
+
return (h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...rest }, h("path", { d: "M8.25 4.78127C8.25 4.04456 9.44248 3.71871 10.0342 4.29397L17.46 11.5127C17.7526 11.7973 17.7526 12.2027 17.46 12.4873L10.0342 19.7061C9.44249 20.2814 8.25 19.9555 8.25 19.2188V4.78127Z", fill: "currentColor" })));
|
|
5
5
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
2
|
export const CaretUp = (props) => {
|
|
3
3
|
const { size = 24, ...rest } = props;
|
|
4
|
-
return (h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...rest }, h("path", { d: "M11.
|
|
4
|
+
return (h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...rest }, h("path", { d: "M11.6252 6.44362C11.8583 6.27919 12.1422 6.27906 12.3752 6.44362L12.4865 6.5403L19.7063 13.9651C20.2815 14.5568 19.9557 15.7503 19.219 15.7503H4.78146C4.04475 15.7503 3.71888 14.5568 4.29416 13.9651L11.5129 6.5403L11.6252 6.44362Z", fill: "currentColor" })));
|
|
5
5
|
};
|
|
@@ -133,6 +133,11 @@ sd-chip-input .sd-chip-input__suggestion-item--active {
|
|
|
133
133
|
color: var(--sd-chip-input-suggestion-color-hover);
|
|
134
134
|
font-weight: var(--sd-chip-input-suggestion-font-weight-selected);
|
|
135
135
|
}
|
|
136
|
+
sd-chip-input .sd-chip-input__suggestion-item--selected {
|
|
137
|
+
cursor: default;
|
|
138
|
+
overflow: visible;
|
|
139
|
+
text-overflow: unset;
|
|
140
|
+
}
|
|
136
141
|
sd-chip-input .sd-chip-input__suggestions-empty {
|
|
137
142
|
padding: 12px;
|
|
138
143
|
text-align: center;
|
|
@@ -222,7 +222,9 @@ export class SdChipInput {
|
|
|
222
222
|
}
|
|
223
223
|
if (event.key === 'Enter' && this.activeSuggestionIndex >= 0) {
|
|
224
224
|
event.preventDefault();
|
|
225
|
-
|
|
225
|
+
const selectedItem = activeItems[this.activeSuggestionIndex];
|
|
226
|
+
if (!(this.internalValues ?? []).includes(selectedItem))
|
|
227
|
+
this.addChip(selectedItem);
|
|
226
228
|
return;
|
|
227
229
|
}
|
|
228
230
|
}
|
|
@@ -282,6 +284,10 @@ export class SdChipInput {
|
|
|
282
284
|
};
|
|
283
285
|
handleContainerClick = () => {
|
|
284
286
|
if (!this.disabled) {
|
|
287
|
+
// 이미 포커스된 상태에서 재클릭 시 handleFocus가 다시 실행되지 않으므로
|
|
288
|
+
// suppress 플래그를 여기서 직접 해제한다.
|
|
289
|
+
this.suppressRecommendations = false;
|
|
290
|
+
this.suppressSuggestions = false;
|
|
285
291
|
this.inputEl?.focus();
|
|
286
292
|
}
|
|
287
293
|
};
|
|
@@ -426,7 +432,7 @@ export class SdChipInput {
|
|
|
426
432
|
fontFamily: CHIP_INPUT_SUGGESTIONS.itemFontFamily,
|
|
427
433
|
color: CHIP_INPUT_SUGGESTIONS.emptyColor,
|
|
428
434
|
};
|
|
429
|
-
return (h("sd-field", { key: '
|
|
435
|
+
return (h("sd-field", { key: 'b72e33b6f204ebdf6791cc2f20d01bbb74a4203a', name: this.name, label: this.label, labelWidth: this.labelWidth, hint: this.hint, errorMessage: this.errorMessage, rules: [this.duplicateRule, ...(this.rules ?? [])], error: this.error, disabled: this.disabled, focused: this.focused, hovered: this.hovered, status: this.status, size: this.size, width: this.width, icon: this.icon, labelTooltip: this.labelTooltip, labelTooltipProps: this.labelTooltipProps, ref: el => (this.formField = el), style: cssVars, onMouseEnter: () => (this.hovered = true), onMouseLeave: () => (this.hovered = false) }, h("div", { key: '499114d06f4d375fed5575edd394c501f4d72691', class: "sd-chip-input", ref: el => (this.chipInputRef = el), onClick: this.handleContainerClick }, (this.internalValues ?? []).map((value, i) => (h("sd-chip", { key: i, value: value, error: this.getChipError(i), disabled: this.getChipDisabled(i), editable: false, onSdRemove: () => this.handleChipRemove(i) }))), !isMaxReached && (h("div", { key: '5910a2d0e0e9cbc472baa1d9c9c3fa07e89fbdcb', class: {
|
|
430
436
|
'sd-chip-input__field': true,
|
|
431
437
|
'sd-chip-input__field--filled': this.inputValue !== '',
|
|
432
438
|
'sd-chip-input__field--empty': this.inputValue === '' && this.internalValues.length > 0 && !this.focused,
|
|
@@ -434,20 +440,38 @@ export class SdChipInput {
|
|
|
434
440
|
? this.inputValue
|
|
435
441
|
: this.internalValues.length === 0
|
|
436
442
|
? this.placeholder
|
|
437
|
-
: '' }, h("input", { key: '
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
443
|
+
: '' }, h("input", { key: '3c1e75d691332b67a500a2d17030d5db191bdeb9', ref: el => (this.inputEl = el), class: "sd-chip-input__input", placeholder: this.internalValues.length === 0 ? this.placeholder : '', disabled: this.disabled, size: 1, onInput: this.handleInput, onKeyDown: this.handleKeyDown, onFocus: this.handleFocus, onBlur: this.handleBlur }))), showResetArea && (
|
|
444
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
445
|
+
h("div", { key: '4aa212280a928b88b85dffa3d453ea8f563e1fe0', class: "sd-chip-input__reset",
|
|
446
|
+
// 리셋 버튼 클릭 시 input blur → portal unmount → refocus → 새 portal mount로
|
|
447
|
+
// 두 wrapper가 body에 잠깐 겹치는 타이밍 이슈를 방지한다.
|
|
448
|
+
onMouseDown: e => e.preventDefault() }, this.inputValue === '' && h("span", { key: 'f7faa45b57d8e38dda8cc98119357f92d914fee4', class: "sd-chip-input__divider" }), this.maxCount != null && (h("span", { key: 'dfde4ea82558414614fb2d817f7bfa1fb5d4bf5f', class: "sd-chip-input__max-count" }, "\uCD5C\uB300 ", this.maxCount, "\uAC1C")), this.useReset && this.internalValues.length > 0 && (h("sd-text-link", { key: '9b43c82c1a5d425e5b187e92b4259e7d919491e3', icon: "reset", iconColor: CHIP_INPUT_RESET.iconColor, label: "\uC785\uB825 \uCD08\uAE30\uD654", underline: true, disabled: this.disabled, style: { '--sd-text-link-color': CHIP_INPUT_RESET.labelColor }, onSdClick: this.handleResetInput })))), showDropdown && (h("sd-portal", { key: 'aa205aacbbafcd8c3d9855268637e6da956d4a74', open: showDropdown, parentRef: this.chipInputRef ?? null, viewportPadding: SdChipInput.SUGGESTIONS_VIEWPORT_PADDING, onSdClose: this.closeSuggestions }, h("div", { key: '26814734f202da3a13e695ae1d0c913ea430b888', class: "sd-chip-input__suggestions", role: "listbox", style: suggestionBoxStyle }, isDropdownLoading && (h("div", { key: 'df80d11b79f67dc6cfe6503b258528efa3752265', class: "sd-chip-input__suggestions-empty", style: suggestionEmptyStyle }, "\uBD88\uB7EC\uC624\uB294 \uC911...")), dropdownItems.map((item, i) => {
|
|
449
|
+
const isSelected = (this.internalValues ?? []).includes(item);
|
|
450
|
+
const isActive = i === this.activeSuggestionIndex && !isSelected;
|
|
451
|
+
return (h("div", { key: item, class: {
|
|
452
|
+
'sd-chip-input__suggestion-item': true,
|
|
453
|
+
'sd-chip-input__suggestion-item--active': isActive,
|
|
454
|
+
'sd-chip-input__suggestion-item--selected': isSelected,
|
|
455
|
+
}, role: "option", tabIndex: -1, "aria-selected": isSelected || isActive, "aria-disabled": isSelected ? 'true' : undefined, style: isSelected
|
|
456
|
+
? {
|
|
457
|
+
...suggestionItemStyle,
|
|
458
|
+
color: '#0075FF',
|
|
459
|
+
fontWeight: CHIP_INPUT_SUGGESTIONS.itemFontWeightSelected,
|
|
460
|
+
cursor: 'default',
|
|
461
|
+
}
|
|
462
|
+
: isActive
|
|
463
|
+
? {
|
|
464
|
+
...suggestionItemStyle,
|
|
465
|
+
background: CHIP_INPUT_SUGGESTIONS.itemBgHover,
|
|
466
|
+
color: CHIP_INPUT_SUGGESTIONS.itemColorHover,
|
|
467
|
+
fontWeight: CHIP_INPUT_SUGGESTIONS.itemFontWeightSelected,
|
|
468
|
+
}
|
|
469
|
+
: suggestionItemStyle, onMouseDown: e => {
|
|
470
|
+
e.preventDefault();
|
|
471
|
+
if (!isSelected)
|
|
472
|
+
this.addChip(item);
|
|
473
|
+
} }, h("span", { style: { flex: '1' } }, item), isSelected && (h("sd-icon", { name: "check", size: "12", style: { color: '#0075FF', flexShrink: '0' } }))));
|
|
474
|
+
})))))));
|
|
451
475
|
}
|
|
452
476
|
static get is() { return "sd-chip-input"; }
|
|
453
477
|
static get originalStyleUrls() {
|
|
@@ -143,3 +143,100 @@ StoryVirtualTable = __decorate([
|
|
|
143
143
|
customElement('story-virtual-table')
|
|
144
144
|
], StoryVirtualTable);
|
|
145
145
|
export { StoryVirtualTable };
|
|
146
|
+
const DROPDOWN_STATUS_META = {
|
|
147
|
+
active: { bg: '#DCFCE7', color: '#166534', label: 'Active' },
|
|
148
|
+
reviewing: { bg: '#FEF3C7', color: '#92400E', label: 'Reviewing' },
|
|
149
|
+
archived: { bg: '#E2E8F0', color: '#475569', label: 'Archived' },
|
|
150
|
+
};
|
|
151
|
+
const DROPDOWN_SEED = [
|
|
152
|
+
{ id: 1, name: 'Avery Kim', role: 'Owner', region: 'Seoul', status: 'active' },
|
|
153
|
+
{ id: 2, name: 'Mina Park', role: 'Manager', region: 'Busan', status: 'reviewing' },
|
|
154
|
+
{ id: 3, name: 'Ethan Lee', role: 'Analyst', region: 'Incheon', status: 'archived' },
|
|
155
|
+
{ id: 4, name: 'Sora Choi', role: 'Owner', region: 'Daegu', status: 'active' },
|
|
156
|
+
{ id: 5, name: 'Jisoo Han', role: 'Manager', region: 'Daejeon', status: 'reviewing' },
|
|
157
|
+
{ id: 6, name: 'Noah Yoon', role: 'Analyst', region: 'Gwangju', status: 'active' },
|
|
158
|
+
{ id: 7, name: 'Iris Jung', role: 'Manager', region: 'Suwon', status: 'active' },
|
|
159
|
+
{ id: 8, name: 'Liam Seo', role: 'Owner', region: 'Ulsan', status: 'reviewing' },
|
|
160
|
+
];
|
|
161
|
+
const DROPDOWN_COLUMNS = [
|
|
162
|
+
{ name: 'name', label: 'Customer', field: 'name', autoWidth: true },
|
|
163
|
+
{ name: 'role', label: 'Role', field: 'role', align: 'center', width: '100px', hasDropdown: true },
|
|
164
|
+
{ name: 'region', label: 'Region', field: 'region', width: '100px' },
|
|
165
|
+
{ name: 'status', label: 'Status', field: 'status', align: 'center', width: '110px', hasDropdown: true },
|
|
166
|
+
];
|
|
167
|
+
const LISTBOX_STYLE = 'margin:0;padding:4px;list-style:none;min-width:140px;background:white;border:1px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 16px rgba(0,0,0,0.10);';
|
|
168
|
+
const ITEM_BASE_STYLE = 'padding:7px 12px;border-radius:6px;cursor:pointer;font-size:13px;';
|
|
169
|
+
let StoryDropdownTable = class StoryDropdownTable extends LitElement {
|
|
170
|
+
// Disable shadow DOM so Stencil's slot emulation can see and move
|
|
171
|
+
// the slotted <ul> nodes without Lit's ChildPart losing track of them.
|
|
172
|
+
createRenderRoot() { return this; }
|
|
173
|
+
constructor() {
|
|
174
|
+
super();
|
|
175
|
+
this.roleFilter = 'All';
|
|
176
|
+
this.statusFilter = 'All';
|
|
177
|
+
}
|
|
178
|
+
get displayRows() {
|
|
179
|
+
return DROPDOWN_SEED.filter(row => (this.roleFilter === 'All' || row.role === this.roleFilter) &&
|
|
180
|
+
(this.statusFilter === 'All' || row.status === this.statusFilter));
|
|
181
|
+
}
|
|
182
|
+
itemStyle(active) {
|
|
183
|
+
return `${ITEM_BASE_STYLE}background:${active ? '#f0f9ff' : 'transparent'};color:${active ? '#0369a1' : '#374151'};font-weight:${active ? '600' : '400'};`;
|
|
184
|
+
}
|
|
185
|
+
render() {
|
|
186
|
+
const rows = this.displayRows;
|
|
187
|
+
const roleOptions = ['All', 'Owner', 'Manager', 'Analyst'];
|
|
188
|
+
const statusOptions = ['All', 'active', 'reviewing', 'archived'];
|
|
189
|
+
return html `
|
|
190
|
+
<div style="display:flex;flex-direction:column;gap:12px;">
|
|
191
|
+
<div style="display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-size:14px;">
|
|
192
|
+
<span style="color:#64748b;">Active filters:</span>
|
|
193
|
+
${this.roleFilter !== 'All' ? html `<span style="border-radius:9999px;background:#ecfeff;padding:2px 12px;font-size:12px;font-weight:500;color:#0e7490;">Role: ${this.roleFilter}</span>` : nothing}
|
|
194
|
+
${this.statusFilter !== 'All' ? html `<span style="border-radius:9999px;background:#ecfeff;padding:2px 12px;font-size:12px;font-weight:500;color:#0e7490;">Status: ${DROPDOWN_STATUS_META[this.statusFilter]?.label}</span>` : nothing}
|
|
195
|
+
${this.roleFilter === 'All' && this.statusFilter === 'All' ? html `<span style="color:#94a3b8;">없음</span>` : nothing}
|
|
196
|
+
${this.roleFilter !== 'All' || this.statusFilter !== 'All' ? html `<button style="font-size:12px;color:#64748b;text-decoration:underline;background:none;border:none;cursor:pointer;" @click=${() => { this.roleFilter = 'All'; this.statusFilter = 'All'; }}>초기화</button>` : nothing}
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
<sd-table .columns=${DROPDOWN_COLUMNS} .rows=${rows} row-key="id" width="100%">
|
|
200
|
+
<sd-thead>
|
|
201
|
+
<ul slot="dropdown-role" style=${LISTBOX_STYLE}>
|
|
202
|
+
${roleOptions.map(opt => html `
|
|
203
|
+
<li style=${this.itemStyle(this.roleFilter === opt)} @click=${() => { this.roleFilter = opt; }}>${opt}</li>
|
|
204
|
+
`)}
|
|
205
|
+
</ul>
|
|
206
|
+
<ul slot="dropdown-status" style=${LISTBOX_STYLE}>
|
|
207
|
+
${statusOptions.map(opt => html `
|
|
208
|
+
<li style=${this.itemStyle(this.statusFilter === opt)} @click=${() => { this.statusFilter = opt; }}>
|
|
209
|
+
${opt === 'All' ? 'All' : DROPDOWN_STATUS_META[opt].label}
|
|
210
|
+
</li>
|
|
211
|
+
`)}
|
|
212
|
+
</ul>
|
|
213
|
+
</sd-thead>
|
|
214
|
+
<sd-tbody>
|
|
215
|
+
${repeat(rows, row => row.id, row => {
|
|
216
|
+
const meta = DROPDOWN_STATUS_META[row.status];
|
|
217
|
+
return html `
|
|
218
|
+
<sd-tr row-key=${String(row.id)} .row=${row}>
|
|
219
|
+
<sd-td field="status" row-key=${String(row.id)}>
|
|
220
|
+
<span style="display:inline-flex;min-width:88px;align-items:center;justify-content:center;border-radius:9999px;padding:4px 10px;font-size:12px;font-weight:600;background:${meta.bg};color:${meta.color};">
|
|
221
|
+
${meta.label}
|
|
222
|
+
</span>
|
|
223
|
+
</sd-td>
|
|
224
|
+
</sd-tr>
|
|
225
|
+
`;
|
|
226
|
+
})}
|
|
227
|
+
</sd-tbody>
|
|
228
|
+
</sd-table>
|
|
229
|
+
</div>
|
|
230
|
+
`;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
__decorate([
|
|
234
|
+
state()
|
|
235
|
+
], StoryDropdownTable.prototype, "roleFilter", void 0);
|
|
236
|
+
__decorate([
|
|
237
|
+
state()
|
|
238
|
+
], StoryDropdownTable.prototype, "statusFilter", void 0);
|
|
239
|
+
StoryDropdownTable = __decorate([
|
|
240
|
+
customElement('story-dropdown-table')
|
|
241
|
+
], StoryDropdownTable);
|
|
242
|
+
export { StoryDropdownTable };
|
|
@@ -143,6 +143,27 @@ sd-thead * {
|
|
|
143
143
|
background-color: var(--table-header-resizer-color, #CCCCCC);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
.th__dropdown-trigger {
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
justify-content: center;
|
|
150
|
+
flex-shrink: 0;
|
|
151
|
+
width: 16px;
|
|
152
|
+
height: 16px;
|
|
153
|
+
padding: 0;
|
|
154
|
+
border: none;
|
|
155
|
+
background: transparent;
|
|
156
|
+
cursor: pointer;
|
|
157
|
+
color: inherit;
|
|
158
|
+
border-radius: 2px;
|
|
159
|
+
}
|
|
160
|
+
.th__dropdown-trigger sd-icon {
|
|
161
|
+
transition: transform 0.15s ease;
|
|
162
|
+
}
|
|
163
|
+
.th__dropdown-trigger--open sd-icon {
|
|
164
|
+
transform: rotate(180deg);
|
|
165
|
+
}
|
|
166
|
+
|
|
146
167
|
.th__resizer {
|
|
147
168
|
position: absolute;
|
|
148
169
|
top: 50%;
|