@sellmate/design-system 1.0.74 → 1.0.76

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 (182) hide show
  1. package/dist/cjs/design-system.cjs.js +1 -1
  2. package/dist/cjs/index.cjs.js +5 -0
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/sd-button_4.cjs.entry.js +2 -2
  5. package/dist/cjs/sd-confirm-modal_2.cjs.entry.js +1 -1
  6. package/dist/cjs/sd-ghost-button.cjs.entry.js +10 -5
  7. package/dist/cjs/sd-modal-container.cjs.entry.js +76 -68
  8. package/dist/cjs/sd-pagination_5.cjs.entry.js +889 -0
  9. package/dist/cjs/sd-radio-button.cjs.entry.js +6 -1
  10. package/dist/cjs/sd-select-v2-list-item_4.cjs.entry.js +65 -5
  11. package/dist/cjs/sd-switch.cjs.entry.js +1 -1
  12. package/dist/cjs/sd-table.cjs.entry.js +167 -20
  13. package/dist/cjs/sd-tabs.cjs.entry.js +1 -1
  14. package/dist/cjs/sd-tag.cjs.entry.js +2 -2
  15. package/dist/cjs/sd-td.cjs.entry.js +53 -1
  16. package/dist/cjs/sd-text-link.cjs.entry.js +3 -3
  17. package/dist/cjs/sd-textarea.cjs.entry.js +1 -1
  18. package/dist/cjs/sd-toast-container.cjs.entry.js +1 -1
  19. package/dist/cjs/sd-toast.cjs.entry.js +2 -2
  20. package/dist/cjs/sd-toggle.cjs.entry.js +1 -1
  21. package/dist/collection/components/sd-ghost-button/sd-ghost-button.js +10 -5
  22. package/dist/collection/components/sd-loading-modal/sd-loading-modal.js +3 -3
  23. package/dist/collection/components/sd-modal-container/sd-modal-container.js +77 -71
  24. package/dist/collection/components/sd-radio-button/sd-radio-button.js +6 -1
  25. package/dist/collection/components/sd-select-v2/sd-select-v2-listbox/sd-select-v2-listbox.js +103 -3
  26. package/dist/collection/components/sd-select-v2/sd-select-v2-trigger/sd-select-v2-trigger.js +2 -2
  27. package/dist/collection/components/sd-select-v2/sd-select-v2.js +82 -4
  28. package/dist/collection/components/sd-switch/sd-switch.js +1 -1
  29. package/dist/collection/components/sd-table/sd-table.css +1 -1
  30. package/dist/collection/components/sd-table/sd-table.js +170 -21
  31. package/dist/collection/components/sd-table/sd-tbody/sd-tbody.js +7 -2
  32. package/dist/collection/components/sd-table/sd-td/sd-td.js +91 -1
  33. package/dist/collection/components/sd-table/sd-thead/sd-thead.js +9 -4
  34. package/dist/collection/components/sd-table/sd-tr/sd-tr.css +8 -0
  35. package/dist/collection/components/sd-table/sd-tr/sd-tr.js +62 -12
  36. package/dist/collection/components/sd-tabs/sd-tabs.js +1 -1
  37. package/dist/collection/components/sd-tag/sd-tag.js +2 -2
  38. package/dist/collection/components/sd-text-link/sd-text-link.js +3 -3
  39. package/dist/collection/components/sd-textarea/sd-textarea.js +1 -1
  40. package/dist/collection/components/sd-toast/sd-toast.js +2 -2
  41. package/dist/collection/components/sd-toast-container/sd-toast-container.js +1 -1
  42. package/dist/collection/components/sd-toggle/sd-toggle.js +1 -1
  43. package/dist/collection/components/sd-tooltip/sd-tooltip.js +2 -2
  44. package/dist/collection/utils/modal.js +5 -0
  45. package/dist/components/index.js +1 -1
  46. package/dist/components/{p-BALOEavB.js → p-6AvsuYqF.js} +1 -1
  47. package/dist/components/{p-CTwEbxRN.js → p-6PsyRF61.js} +1 -1
  48. package/dist/components/{p-DEBakAhm.js → p-7DKZPPev.js} +1 -1
  49. package/dist/components/p-BBD_1E3n.js +1 -0
  50. package/dist/components/p-BQvugXhH.js +1 -0
  51. package/dist/components/p-BRfPoWUn.js +1 -0
  52. package/dist/components/{p-CHFGWh0m.js → p-C-BOe23n.js} +1 -1
  53. package/dist/components/p-C7h8lwnU.js +1 -0
  54. package/dist/components/{p-SDBnyM8D.js → p-CUg9NH6y.js} +1 -1
  55. package/dist/components/{p-C3dI7f7C.js → p-CgMyz4NQ.js} +1 -1
  56. package/dist/components/p-Csfj4h1A.js +1 -0
  57. package/dist/components/{p-Bp0B8tcl.js → p-DAC3TaZV.js} +1 -1
  58. package/dist/components/p-DQfNwvwx.js +1 -0
  59. package/dist/components/p-DfOYYI9m.js +1 -0
  60. package/dist/components/{p-H-9uoufd.js → p-d4UB2UF7.js} +1 -1
  61. package/dist/components/p-eEC3ITv0.js +1 -0
  62. package/dist/components/{p-CWEeXx2E.js → p-nVHDJc9g.js} +1 -1
  63. package/dist/components/{p-D8fG9Yt7.js → p-rnbt1m4L.js} +1 -1
  64. package/dist/components/sd-action-modal.js +1 -1
  65. package/dist/components/sd-barcode-input.js +1 -1
  66. package/dist/components/sd-chip.js +1 -1
  67. package/dist/components/sd-confirm-modal.js +1 -1
  68. package/dist/components/sd-date-picker-calendar.js +1 -1
  69. package/dist/components/sd-date-picker.js +1 -1
  70. package/dist/components/sd-date-range-picker-calendar.js +1 -1
  71. package/dist/components/sd-date-range-picker.js +1 -1
  72. package/dist/components/sd-field.js +1 -1
  73. package/dist/components/sd-file-picker.js +1 -1
  74. package/dist/components/sd-ghost-button.js +1 -1
  75. package/dist/components/sd-guide.js +1 -1
  76. package/dist/components/sd-input.js +1 -1
  77. package/dist/components/sd-loading-modal.js +1 -1
  78. package/dist/components/sd-modal-container.js +1 -1
  79. package/dist/components/sd-number-input.js +1 -1
  80. package/dist/components/sd-popover.js +1 -1
  81. package/dist/components/sd-radio-button.js +1 -1
  82. package/dist/components/sd-select-dropdown.js +1 -1
  83. package/dist/components/sd-select-group.js +1 -1
  84. package/dist/components/sd-select-multiple-group.js +1 -1
  85. package/dist/components/sd-select-multiple.js +1 -1
  86. package/dist/components/sd-select-search-input.js +1 -1
  87. package/dist/components/sd-select-v2-listbox.js +1 -1
  88. package/dist/components/sd-select-v2-trigger.js +1 -1
  89. package/dist/components/sd-select-v2.js +1 -1
  90. package/dist/components/sd-select.js +1 -1
  91. package/dist/components/sd-switch.js +1 -1
  92. package/dist/components/sd-table.js +1 -1
  93. package/dist/components/sd-tabs.js +1 -1
  94. package/dist/components/sd-tag.js +1 -1
  95. package/dist/components/sd-tbody.js +1 -1
  96. package/dist/components/sd-td.js +1 -1
  97. package/dist/components/sd-text-link.js +1 -1
  98. package/dist/components/sd-textarea.js +1 -1
  99. package/dist/components/sd-thead.js +1 -1
  100. package/dist/components/sd-toast-container.js +1 -1
  101. package/dist/components/sd-toast.js +1 -1
  102. package/dist/components/sd-toggle.js +1 -1
  103. package/dist/components/sd-tooltip.js +1 -1
  104. package/dist/components/sd-tr.js +1 -1
  105. package/dist/design-system/design-system.esm.js +1 -1
  106. package/dist/design-system/index.esm.js +1 -1
  107. package/dist/design-system/p-0e1b27cc.entry.js +1 -0
  108. package/dist/design-system/p-11029f6e.entry.js +1 -0
  109. package/dist/design-system/{p-cc62c180.entry.js → p-140b40ab.entry.js} +1 -1
  110. package/dist/design-system/p-34f7345b.entry.js +1 -0
  111. package/dist/design-system/p-363c9451.entry.js +1 -0
  112. package/dist/design-system/{p-fdcfaa7c.entry.js → p-506f2b68.entry.js} +1 -1
  113. package/dist/design-system/{p-8200b5f2.entry.js → p-531a6a82.entry.js} +1 -1
  114. package/dist/design-system/p-55b65a41.entry.js +1 -0
  115. package/dist/design-system/{p-d1dfa0e1.entry.js → p-68d0d67e.entry.js} +1 -1
  116. package/dist/design-system/p-7fe3a466.entry.js +1 -0
  117. package/dist/design-system/{p-05a1c092.entry.js → p-9466cd93.entry.js} +1 -1
  118. package/dist/design-system/{p-33bec0e3.entry.js → p-b683f2fe.entry.js} +1 -1
  119. package/dist/design-system/p-c521e731.entry.js +1 -0
  120. package/dist/design-system/p-c7bcb232.entry.js +1 -0
  121. package/dist/design-system/{p-16a15368.entry.js → p-c9eb70f5.entry.js} +1 -1
  122. package/dist/design-system/p-d1846df9.entry.js +1 -0
  123. package/dist/design-system/{p-2d154fe0.entry.js → p-fdb52620.entry.js} +1 -1
  124. package/dist/esm/design-system.js +1 -1
  125. package/dist/esm/index.js +5 -0
  126. package/dist/esm/loader.js +1 -1
  127. package/dist/esm/sd-button_4.entry.js +2 -2
  128. package/dist/esm/sd-confirm-modal_2.entry.js +1 -1
  129. package/dist/esm/sd-ghost-button.entry.js +10 -5
  130. package/dist/esm/sd-modal-container.entry.js +76 -68
  131. package/dist/esm/sd-pagination_5.entry.js +883 -0
  132. package/dist/esm/sd-radio-button.entry.js +6 -1
  133. package/dist/esm/sd-select-v2-list-item_4.entry.js +65 -5
  134. package/dist/esm/sd-switch.entry.js +1 -1
  135. package/dist/esm/sd-table.entry.js +168 -21
  136. package/dist/esm/sd-tabs.entry.js +1 -1
  137. package/dist/esm/sd-tag.entry.js +2 -2
  138. package/dist/esm/sd-td.entry.js +53 -1
  139. package/dist/esm/sd-text-link.entry.js +3 -3
  140. package/dist/esm/sd-textarea.entry.js +1 -1
  141. package/dist/esm/sd-toast-container.entry.js +1 -1
  142. package/dist/esm/sd-toast.entry.js +2 -2
  143. package/dist/esm/sd-toggle.entry.js +1 -1
  144. package/dist/types/components/sd-ghost-button/sd-ghost-button.d.ts +1 -0
  145. package/dist/types/components/sd-loading-modal/sd-loading-modal.d.ts +1 -1
  146. package/dist/types/components/sd-modal-container/sd-modal-container.config.d.ts +1 -1
  147. package/dist/types/components/sd-modal-container/sd-modal-container.d.ts +6 -4
  148. package/dist/types/components/sd-radio-button/sd-radio-button.d.ts +1 -0
  149. package/dist/types/components/sd-select-v2/sd-select-v2-listbox/sd-select-v2-listbox.d.ts +9 -0
  150. package/dist/types/components/sd-select-v2/sd-select-v2.d.ts +4 -0
  151. package/dist/types/components/sd-table/sd-table.d.ts +17 -0
  152. package/dist/types/components/sd-table/sd-td/sd-td.d.ts +8 -0
  153. package/dist/types/components/sd-table/sd-tr/sd-tr.d.ts +4 -0
  154. package/dist/types/components.d.ts +55 -3
  155. package/hydrate/index.js +482 -142
  156. package/hydrate/index.mjs +482 -142
  157. package/package.json +1 -1
  158. package/dist/cjs/sd-pagination_2.cjs.entry.js +0 -427
  159. package/dist/cjs/sd-tbody.cjs.entry.js +0 -66
  160. package/dist/cjs/sd-thead.cjs.entry.js +0 -179
  161. package/dist/cjs/sd-tr.cjs.entry.js +0 -171
  162. package/dist/components/p-Bbs5Ws0k.js +0 -1
  163. package/dist/components/p-Biplmgfa.js +0 -1
  164. package/dist/components/p-CgL8_FSD.js +0 -1
  165. package/dist/components/p-DuMkBStM.js +0 -1
  166. package/dist/components/p-vQDL-PZ8.js +0 -1
  167. package/dist/design-system/p-109a10e4.entry.js +0 -1
  168. package/dist/design-system/p-380198bc.entry.js +0 -1
  169. package/dist/design-system/p-6b537e2f.entry.js +0 -1
  170. package/dist/design-system/p-6e90fb80.entry.js +0 -1
  171. package/dist/design-system/p-7b77c65c.entry.js +0 -1
  172. package/dist/design-system/p-8f88bd67.entry.js +0 -1
  173. package/dist/design-system/p-ba5fea6f.entry.js +0 -1
  174. package/dist/design-system/p-be54d6bd.entry.js +0 -1
  175. package/dist/design-system/p-c3379a6e.entry.js +0 -1
  176. package/dist/design-system/p-dc07d618.entry.js +0 -1
  177. package/dist/design-system/p-ef09409c.entry.js +0 -1
  178. package/dist/design-system/p-f8237991.entry.js +0 -1
  179. package/dist/esm/sd-pagination_2.entry.js +0 -424
  180. package/dist/esm/sd-tbody.entry.js +0 -64
  181. package/dist/esm/sd-thead.entry.js +0 -177
  182. package/dist/esm/sd-tr.entry.js +0 -169
package/hydrate/index.mjs CHANGED
@@ -9867,6 +9867,11 @@ class SdGhostButton {
9867
9867
  disabled = false;
9868
9868
  click;
9869
9869
  hasWarnedMissingAriaLabel = false;
9870
+ componentWillLoad() {
9871
+ this.size ??= 'sm';
9872
+ this.intent ??= 'default';
9873
+ this.ariaLabel ??= '';
9874
+ }
9870
9875
  handleClick = (event) => {
9871
9876
  if (this.disabled) {
9872
9877
  event.preventDefault();
@@ -9891,19 +9896,19 @@ class SdGhostButton {
9891
9896
  render() {
9892
9897
  const sizeConfig = GHOST_BUTTON_SIZES[this.size];
9893
9898
  const contentColor = this.disabled
9894
- ? GHOST_BUTTON_DISABLED_COLORS[this.intent ?? 'default']
9895
- : GHOST_BUTTON_CONTENT_COLORS[this.intent ?? 'default'];
9899
+ ? GHOST_BUTTON_DISABLED_COLORS[this.intent]
9900
+ : GHOST_BUTTON_CONTENT_COLORS[this.intent];
9896
9901
  const accessibleName = this.ariaLabel.trim() || undefined;
9897
- return (hAsync("button", { key: '34c5026b4819b624b19d1773bad413b689633c2a', class: {
9902
+ return (hAsync("button", { key: 'd7f6fcbed3526ffb8b90b205dbe2bbf55abf03a0', class: {
9898
9903
  'sd-ghost-button': true,
9899
9904
  'sd-ghost-button--disabled': this.disabled,
9900
9905
  }, type: "button", disabled: this.disabled, "aria-label": accessibleName, style: {
9901
9906
  '--sd-ghost-button-size': `${sizeConfig.size}px`,
9902
9907
  '--sd-ghost-button-radius': `${GHOST_BUTTON_RADIUS[this.size]}px`,
9903
- '--sd-ghost-button-hover-bg': GHOST_BUTTON_HOVER_BG_COLORS[this.intent ?? 'default'],
9908
+ '--sd-ghost-button-hover-bg': GHOST_BUTTON_HOVER_BG_COLORS[this.intent],
9904
9909
  '--sd-ghost-button-hover-opacity': GHOST_BUTTON_HOVER_OPACITY,
9905
9910
  '--sd-ghost-button-accent': GHOST_BUTTON_FOCUS_RING_COLOR,
9906
- }, onClick: this.handleClick }, hAsync("sd-icon", { key: '063f7cfabfdbf0f4f2f4c1a2c811e6c3734d941f', name: this.icon, size: sizeConfig.icon, color: contentColor })));
9911
+ }, onClick: this.handleClick }, hAsync("sd-icon", { key: '9efc3a3fbf7878a9a50b2efbf054b335d9cddfe0', name: this.icon, size: sizeConfig.icon, color: contentColor })));
9907
9912
  }
9908
9913
  static get style() { return sdGhostButtonCss(); }
9909
9914
  static get cmpMeta() { return {
@@ -11059,7 +11064,7 @@ class SdLoadingModal {
11059
11064
  '--sd-loading-modal-width': this.toCssSize(this.width) ?? `${LOADING_MODAL_LAYOUT.minWidth}px`,
11060
11065
  '--sd-loading-modal-height': this.toCssSize(this.height) ?? `${LOADING_MODAL_LAYOUT.minHeight}px`,
11061
11066
  };
11062
- return (hAsync(Host, { key: '91fe223de0146ad3a631284728597d6dca312a7e', style: hostStyle }, hAsync("div", { key: 'e3284b3e8fd775b0128ae2e7495141d04d07eaa8', class: "sd-loading-modal" }, hAsync("div", { key: '4975a8e75f7cf983c54a015f25520c34aef855a5', class: "sd-loading-modal__content" }, this.state === 'loading' ? (hAsync("sd-circle-progress", { indeterminate: true })) : (hAsync("sd-icon", { class: "sd-loading-modal__icon", name: "warningOutline", size: LOADING_MODAL_LAYOUT.contentSize, color: LOADING_MODAL_COLORS.errorIcon }))), hAsync("p", { key: 'c3d09b0c957a0cf2097772499a91bb8f86f19e98', class: "sd-loading-modal__message" }, this.resolvedMessage), this.useButton && (hAsync("div", { key: 'c5c1fa02e3c7c3dd3747a1609dc1fa9aab70c61c', class: "sd-loading-modal__button" }, hAsync("sd-button-v2", { key: '849bdd00035bfa602ec814e55b585588f15871c6', name: LOADING_MODAL_BUTTON_PRESET, label: this.resolvedButtonLabel, onSdClick: this.handleClick }))))));
11067
+ return (hAsync(Host, { key: '3113deea33ae8f08ac631e53744c94dfc0ffe829', style: hostStyle }, hAsync("div", { key: 'd6afa60fe2cf83bd1afd707e8aa218d2c66d761b', class: "sd-loading-modal" }, hAsync("div", { key: 'be70c3adcbea4fca528f459ad7fbc33e82649073', class: "sd-loading-modal__content" }, this.state === 'loading' ? (hAsync("sd-circle-progress", { indeterminate: true })) : (hAsync("sd-icon", { class: "sd-loading-modal__icon", name: "warningOutline", size: LOADING_MODAL_LAYOUT.contentSize, color: LOADING_MODAL_COLORS.errorIcon }))), hAsync("div", { key: '9aa73a423423e093606e58796490be123e5fa52a', class: "sd-loading-modal__message-wrapper" }, Array.isArray(this.resolvedMessage) ? (this.resolvedMessage.map(message => (hAsync("p", { class: "sd-loading-modal__message" }, message)))) : (hAsync("p", { class: "sd-loading-modal__message" }, this.resolvedMessage))), this.useButton && (hAsync("div", { key: '59fd5cf61b53f1362974a7b92ad6e6319f141def', class: "sd-loading-modal__button" }, hAsync("sd-button-v2", { key: '9bfe53124cd1f8a3008d8a2ccc6ea9d8af5d62c2', name: LOADING_MODAL_BUTTON_PRESET, label: this.resolvedButtonLabel, onSdClick: this.handleClick }))))));
11063
11068
  }
11064
11069
  static get style() { return sdLoadingModalCss(); }
11065
11070
  static get cmpMeta() { return {
@@ -11187,10 +11192,8 @@ class SdModalContainer {
11187
11192
  }
11188
11193
  get el() { return getElement(this); }
11189
11194
  autoRemove = false;
11190
- entry;
11191
- isVisible = false;
11192
- backdropVisible = false;
11193
- layerRef;
11195
+ entries = [];
11196
+ layerRefs = new Map();
11194
11197
  async open(options, modalRef) {
11195
11198
  const id = `modal-${++modalIdCounter}`;
11196
11199
  const modalEl = this.createConfirmModal(id, options);
@@ -11201,6 +11204,7 @@ class SdModalContainer {
11201
11204
  modalRef,
11202
11205
  persistent: !!options.persistent,
11203
11206
  closing: false,
11207
+ backdropVisible: false,
11204
11208
  });
11205
11209
  return id;
11206
11210
  }
@@ -11214,6 +11218,7 @@ class SdModalContainer {
11214
11218
  modalRef,
11215
11219
  persistent: !!options.persistent,
11216
11220
  closing: false,
11221
+ backdropVisible: false,
11217
11222
  });
11218
11223
  return id;
11219
11224
  }
@@ -11228,91 +11233,93 @@ class SdModalContainer {
11228
11233
  modalRef,
11229
11234
  persistent: !!options.persistent,
11230
11235
  closing: false,
11236
+ backdropVisible: false,
11231
11237
  });
11232
11238
  return id;
11233
11239
  }
11234
11240
  componentDidRender() {
11235
- if (!this.entry || this.entry.closing || !this.layerRef)
11241
+ if (!Array.isArray(this.entries))
11236
11242
  return;
11237
- if (this.entry.modalEl.isConnected)
11238
- return;
11239
- const { id, modalEl } = this.entry;
11240
- this.layerRef.appendChild(modalEl);
11241
- this.waitForModalReady(modalEl).then(() => {
11242
- requestAnimationFrame(() => {
11243
- if (!this.entry || this.entry.id !== id || this.entry.closing || !modalEl.isConnected)
11244
- return;
11245
- this.backdropVisible = true;
11246
- modalEl.classList.add('sd-modal-container__modal--visible');
11243
+ for (const entry of this.entries) {
11244
+ if (entry.closing || entry.modalEl.isConnected)
11245
+ continue;
11246
+ const layerRef = this.layerRefs.get(entry.id);
11247
+ if (!layerRef)
11248
+ continue;
11249
+ const { id, modalEl } = entry;
11250
+ layerRef.appendChild(modalEl);
11251
+ this.waitForModalReady(modalEl).then(() => {
11252
+ requestAnimationFrame(() => {
11253
+ const current = this.entries.find(e => e.id === id);
11254
+ if (!current || current.closing || !modalEl.isConnected)
11255
+ return;
11256
+ this.entries = this.entries.map(e => e.id === id ? { ...e, backdropVisible: true } : e);
11257
+ modalEl.classList.add('sd-modal-container__modal--visible');
11258
+ });
11247
11259
  });
11248
- });
11260
+ }
11249
11261
  }
11250
11262
  disconnectedCallback() {
11251
- if (this.entry?.dismissTimerId)
11252
- clearTimeout(this.entry.dismissTimerId);
11253
- if (this.entry)
11254
- unregisterModal(this.entry.id);
11263
+ for (const entry of this.entries ?? []) {
11264
+ if (entry.dismissTimerId)
11265
+ clearTimeout(entry.dismissTimerId);
11266
+ unregisterModal(entry.id);
11267
+ }
11255
11268
  }
11256
11269
  async dismissById(id, reason) {
11257
- if (this.entry?.id !== id)
11270
+ const entry = this.entries.find(e => e.id === id);
11271
+ if (!entry)
11258
11272
  return;
11259
- this.requestDismiss(reason);
11273
+ this.requestDismiss(id, reason);
11260
11274
  }
11261
11275
  async update(id, props) {
11262
- if (!this.entry || this.entry.id !== id || this.entry.closing)
11276
+ const entry = this.entries.find(e => e.id === id && !e.closing);
11277
+ if (!entry)
11263
11278
  return;
11264
- const tag = this.entry.modalEl.tagName.toLowerCase();
11279
+ const tag = entry.modalEl.tagName.toLowerCase();
11265
11280
  if (tag === 'sd-loading-modal') {
11266
- this.applyLoadingProps(this.entry.modalEl, props);
11281
+ this.applyLoadingProps(entry.modalEl, props);
11267
11282
  return;
11268
11283
  }
11269
- this.applyProps(this.entry.modalEl, props);
11284
+ this.applyProps(entry.modalEl, props);
11270
11285
  }
11271
11286
  mountEntry(entry) {
11272
- if (this.entry) {
11273
- throw new Error('[sd-modal-container] This instance already manages an active modal.');
11274
- }
11275
- this.entry = entry;
11276
- this.backdropVisible = false;
11277
- this.isVisible = true;
11287
+ this.entries = [...(this.entries ?? []), entry];
11278
11288
  registerModal({
11279
11289
  id: entry.id,
11280
11290
  persistent: entry.persistent,
11281
- requestClose: () => this.dispatchClose(),
11291
+ requestClose: () => this.dispatchClose(entry.id),
11282
11292
  shake: () => this.shakeModal(entry.modalEl),
11283
11293
  setZIndex: zIndex => {
11284
11294
  this.el.style.setProperty('--sd-modal-container-z-index', String(zIndex));
11285
11295
  },
11286
11296
  });
11287
11297
  }
11288
- attachModalEventListeners(_id, modalEl) {
11289
- modalEl.addEventListener('sdOk', () => this.requestDismiss('confirm'));
11290
- modalEl.addEventListener('sdCancel', () => this.requestDismiss('cancel'));
11291
- modalEl.addEventListener('sdClose', () => this.requestDismiss('close'));
11298
+ attachModalEventListeners(id, modalEl) {
11299
+ modalEl.addEventListener('sdOk', () => this.requestDismiss(id, 'confirm'));
11300
+ modalEl.addEventListener('sdCancel', () => this.requestDismiss(id, 'cancel'));
11301
+ modalEl.addEventListener('sdClose', () => this.requestDismiss(id, 'close'));
11292
11302
  }
11293
- attachLoadingModalEventListeners(_id, modalEl) {
11303
+ attachLoadingModalEventListeners(id, modalEl) {
11294
11304
  modalEl.addEventListener('sdClick', () => {
11295
- this.entry?.modalRef._triggerClick?.();
11305
+ const entry = this.entries.find(e => e.id === id);
11306
+ entry?.modalRef._triggerClick?.();
11296
11307
  });
11297
11308
  }
11298
- dispatchClose() {
11299
- this.entry?.modalEl.dispatchEvent(new CustomEvent('sdClose'));
11309
+ dispatchClose(id) {
11310
+ const entry = this.entries.find(e => e.id === id);
11311
+ entry?.modalEl.dispatchEvent(new CustomEvent('sdClose'));
11300
11312
  }
11301
- requestDismiss(reason) {
11302
- const currentEntry = this.entry;
11313
+ requestDismiss(id, reason) {
11314
+ const currentEntry = this.entries.find(e => e.id === id);
11303
11315
  if (!currentEntry || currentEntry.closing)
11304
11316
  return;
11305
11317
  currentEntry.modalEl.classList.remove('sd-modal-container__modal--visible');
11306
11318
  const dismissTimerId = setTimeout(() => {
11307
- this.finalizeDismiss(currentEntry.id);
11319
+ this.finalizeDismiss(id);
11308
11320
  }, ANIMATION_DURATION);
11309
- setModalInteractive(currentEntry.id, false);
11310
- this.entry = {
11311
- ...currentEntry,
11312
- closing: true,
11313
- dismissTimerId,
11314
- };
11315
- this.backdropVisible = false;
11321
+ setModalInteractive(id, false);
11322
+ this.entries = (this.entries ?? []).map(e => e.id === id ? { ...e, closing: true, dismissTimerId, backdropVisible: false } : e);
11316
11323
  if (reason === 'confirm')
11317
11324
  currentEntry.modalRef._triggerOk();
11318
11325
  else if (reason === 'cancel')
@@ -11321,18 +11328,17 @@ class SdModalContainer {
11321
11328
  currentEntry.modalRef._triggerClose();
11322
11329
  }
11323
11330
  finalizeDismiss(id) {
11324
- const currentEntry = this.entry;
11325
- if (!currentEntry || currentEntry.id !== id)
11331
+ const currentEntry = this.entries.find(e => e.id === id);
11332
+ if (!currentEntry)
11326
11333
  return;
11327
11334
  if (currentEntry.dismissTimerId)
11328
11335
  clearTimeout(currentEntry.dismissTimerId);
11329
11336
  currentEntry.modalEl.remove();
11330
11337
  unregisterModal(id);
11331
11338
  currentEntry.modalRef._triggerDismissed();
11332
- this.entry = undefined;
11333
- this.backdropVisible = false;
11334
- this.isVisible = false;
11335
- if (this.autoRemove) {
11339
+ this.layerRefs.delete(id);
11340
+ this.entries = (this.entries ?? []).filter(e => e.id !== id);
11341
+ if (this.autoRemove && this.entries.length === 0) {
11336
11342
  this.el.remove();
11337
11343
  }
11338
11344
  }
@@ -11353,8 +11359,14 @@ class SdModalContainer {
11353
11359
  applyLoadingProps(el, options) {
11354
11360
  if (this.hasOwnProp(options, 'state'))
11355
11361
  this.setAttr(el, 'state', options.state);
11356
- if (this.hasOwnProp(options, 'message'))
11357
- this.setAttr(el, 'message', options.message);
11362
+ if (this.hasOwnProp(options, 'message')) {
11363
+ if (Array.isArray(options.message)) {
11364
+ el.message = options.message;
11365
+ }
11366
+ else {
11367
+ this.setAttr(el, 'message', options.message);
11368
+ }
11369
+ }
11358
11370
  if (this.hasOwnProp(options, 'useButton')) {
11359
11371
  if (options.useButton)
11360
11372
  el.setAttribute('use-button', '');
@@ -11400,11 +11412,11 @@ class SdModalContainer {
11400
11412
  if (this.hasOwnProp(options, 'tagContents'))
11401
11413
  el.tagContents = options.tagContents;
11402
11414
  }
11403
- handleBackdropClick = () => {
11404
- if (!this.entry || !isTopInteractiveModal(this.entry.id))
11415
+ handleBackdropClick(id) {
11416
+ if (!isTopInteractiveModal(id))
11405
11417
  return;
11406
- requestCloseForModal(this.entry.id);
11407
- };
11418
+ requestCloseForModal(id);
11419
+ }
11408
11420
  shakeModal(modalEl) {
11409
11421
  const cls = 'sd-modal-container__modal--shake';
11410
11422
  modalEl.classList.remove(cls);
@@ -11433,14 +11445,15 @@ class SdModalContainer {
11433
11445
  el.setAttribute(name, value);
11434
11446
  }
11435
11447
  render() {
11436
- if (!this.isVisible || !this.entry)
11448
+ if (!this.entries?.length)
11437
11449
  return null;
11438
- return (hAsync("div", { class: "sd-modal-container" }, hAsync("div", { class: "sd-modal-container__layer", "data-modal-id": this.entry.id, ref: el => {
11439
- this.layerRef = el;
11450
+ return (hAsync("div", { class: "sd-modal-container" }, this.entries.map((entry, index) => (hAsync("div", { key: entry.id, class: "sd-modal-container__layer", style: { zIndex: String(index + 1) }, "data-modal-id": entry.id, ref: el => {
11451
+ if (el)
11452
+ this.layerRefs.set(entry.id, el);
11440
11453
  } }, hAsync("div", { class: {
11441
11454
  'sd-modal-container__backdrop': true,
11442
- 'sd-modal-container__backdrop--visible': this.backdropVisible,
11443
- }, onClick: this.handleBackdropClick }))));
11455
+ 'sd-modal-container__backdrop--visible': entry.backdropVisible,
11456
+ }, onClick: () => this.handleBackdropClick(entry.id) }))))));
11444
11457
  }
11445
11458
  static get style() { return sdModalContainerCss(); }
11446
11459
  static get cmpMeta() { return {
@@ -11448,9 +11461,7 @@ class SdModalContainer {
11448
11461
  "$tagName$": "sd-modal-container",
11449
11462
  "$members$": {
11450
11463
  "autoRemove": [4, "auto-remove"],
11451
- "entry": [32],
11452
- "isVisible": [32],
11453
- "backdropVisible": [32],
11464
+ "entries": [32],
11454
11465
  "open": [64],
11455
11466
  "openLoading": [64],
11456
11467
  "createCustom": [64],
@@ -12744,6 +12755,11 @@ class SdRadioButton {
12744
12755
  disabled = false;
12745
12756
  name;
12746
12757
  change;
12758
+ componentWillLoad() {
12759
+ this.size ??= 'sm';
12760
+ this.options ??= [];
12761
+ this.disabled ??= false;
12762
+ }
12747
12763
  handleRadioChange = (optionValue, optionDisabled) => {
12748
12764
  if (this.disabled || optionDisabled)
12749
12765
  return;
@@ -12804,7 +12820,7 @@ class SdRadioButton {
12804
12820
  '--sd-radio-button-content-select': RADIO_BUTTON_COLORS.content.select,
12805
12821
  '--sd-radio-button-content-disabled': RADIO_BUTTON_COLORS.content.disabled,
12806
12822
  };
12807
- return (hAsync("div", { key: '67c8e7ad03fb6ee4cabd06591e3e11e5d38914f0', class: this.getGroupClasses(), style: cssVars, role: "radiogroup", "aria-disabled": this.disabled.toString() }, this.options.map(option => {
12823
+ return (hAsync("div", { key: 'fbc0246d9cf615956121295e29bf8c702ee73edc', class: this.getGroupClasses(), style: cssVars, role: "radiogroup", "aria-disabled": this.disabled.toString() }, this.options.map(option => {
12808
12824
  const isSelected = this.isOptionSelected(option);
12809
12825
  const isDisabled = this.isOptionDisabled(option);
12810
12826
  return (hAsync("label", { key: `radio-${option.value}`, class: this.getButtonClasses(option), "aria-label": option.label || 'radio option', "data-label": option.label }, hAsync("input", { type: "radio", name: this.groupName, value: option.value.toString(), checked: isSelected, disabled: isDisabled, onInput: () => this.handleRadioChange(option.value, option.disabled) }), option.label && hAsync("span", { class: "sd-radio-button__label" }, option.label)));
@@ -14647,6 +14663,9 @@ class SdSelectV2 {
14647
14663
  labelTooltipProps = null;
14648
14664
  emitValue = false;
14649
14665
  width = '';
14666
+ useSearch = false;
14667
+ allSelectedLabel = '전체';
14668
+ useSelectAll = false;
14650
14669
  isOpen = false;
14651
14670
  isAnimatingOut = false;
14652
14671
  triggerWidth = '200px';
@@ -14688,6 +14707,12 @@ class SdSelectV2 {
14688
14707
  if (this.isMulti) {
14689
14708
  if (!Array.isArray(this.value) || this.value.length === 0)
14690
14709
  return '';
14710
+ const nonDisabledLeaves = this.getNonDisabledLeaves(this.options);
14711
+ const selected = this.getSelectedOptions();
14712
+ const allSelected = nonDisabledLeaves.length > 0 &&
14713
+ nonDisabledLeaves.every(leaf => selected.some(s => s.value === leaf.value));
14714
+ if (allSelected)
14715
+ return this.allSelectedLabel ?? '전체';
14691
14716
  const flat = this.flattenOptions(this.options);
14692
14717
  return this.value
14693
14718
  .map(item => {
@@ -14712,6 +14737,15 @@ class SdSelectV2 {
14712
14737
  flattenOptions(options) {
14713
14738
  return options.flatMap(o => (o.children ? this.flattenOptions(o.children) : [o]));
14714
14739
  }
14740
+ getNonDisabledLeaves(options) {
14741
+ return options.flatMap(o => {
14742
+ if (o.disabled)
14743
+ return [];
14744
+ if (o.children)
14745
+ return this.getNonDisabledLeaves(o.children);
14746
+ return [o];
14747
+ });
14748
+ }
14715
14749
  getSelectedOptions() {
14716
14750
  const val = this.value;
14717
14751
  if (!val || !Array.isArray(val))
@@ -14858,15 +14892,15 @@ class SdSelectV2 {
14858
14892
  this.closeDropdown();
14859
14893
  },
14860
14894
  };
14861
- return (hAsync("sd-field", { key: '76b432c04fa0f9fca70e63e9c7d16ed768fc9dd1', name: this.name, label: this.label, labelWidth: this.labelWidth, addonLabel: this.addonLabel, addonAlign: this.addonAlign, hint: this.hint, errorMessage: this.errorMessage, width: this.width, rules: this.rules, error: this.error, disabled: this.disabled, focused: this.focused, hovered: this.hovered, icon: this.icon, labelTooltip: this.labelTooltip, labelTooltipProps: this.labelTooltipProps, onMouseEnter: () => {
14895
+ return (hAsync("sd-field", { key: '62bb998e1d455a3792001da4849ba867c60cdd9f', name: this.name, label: this.label, labelWidth: this.labelWidth, addonLabel: this.addonLabel, addonAlign: this.addonAlign, hint: this.hint, errorMessage: this.errorMessage, width: this.width, rules: this.rules, error: this.error, disabled: this.disabled, focused: this.focused, hovered: this.hovered, icon: this.icon, labelTooltip: this.labelTooltip, labelTooltipProps: this.labelTooltipProps, onMouseEnter: () => {
14862
14896
  this.hovered = true;
14863
14897
  }, onMouseLeave: () => {
14864
14898
  this.hovered = false;
14865
- } }, hAsync("div", { key: 'dba3a313b7e0171a441540877aacdc7d5c2e7f04', class: "sd-select-v2", ref: el => {
14899
+ } }, hAsync("div", { key: '42fa82a3c53804d9f90aadb0465d52fd9f4e446e', class: "sd-select-v2", ref: el => {
14866
14900
  this.triggerRef = el;
14867
- } }, hAsync("sd-select-v2-trigger", { key: '7790357558f174eb70b15ed72574f738b062c479', ref: el => {
14901
+ } }, hAsync("sd-select-v2-trigger", { key: 'c97ae1e67019b099eee72f829d554b9e0350af30', ref: el => {
14868
14902
  this.triggerComponentRef = el;
14869
- }, displayText: this.displayText, placeholder: this.placeholder, disabled: this.disabled, isOpen: this.isOpen, onSdTriggerClick: this.handleTriggerClick, onSdTriggerFocus: this.handleTriggerFocus, onSdTriggerBlur: this.handleTriggerBlur })), (this.isOpen || this.isAnimatingOut) && (hAsync("sd-portal", { key: '672f3583b24e363b74d184d13866ee19a78b04d9', ...portalProps }, hAsync("sd-select-v2-listbox", { key: 'f71d95ad06c74356e4d5ce94da7e720c002390b6', type: this.type, options: this.options, value: this.value, emitValue: this.emitValue, triggerWidth: this.triggerWidth, maxWidth: this.resolvedMaxDropdownWidth, maxHeight: this.resolvedDropdownHeight, onSdOptionSelect: event => this.handleOptionSelect(event.detail) })))));
14903
+ }, displayText: this.displayText, placeholder: this.placeholder, disabled: this.disabled, isOpen: this.isOpen, onSdTriggerClick: this.handleTriggerClick, onSdTriggerFocus: this.handleTriggerFocus, onSdTriggerBlur: this.handleTriggerBlur })), (this.isOpen || this.isAnimatingOut) && (hAsync("sd-portal", { key: '5018c8bf4c60a13541f0872149d12b92f164ca96', ...portalProps }, hAsync("sd-select-v2-listbox", { key: 'b7222f7649a8f096f085840a3dd97b7aa069152c', type: this.type, options: this.options, value: this.value, emitValue: this.emitValue, useSearch: this.useSearch, useSelectAll: this.useSelectAll, triggerWidth: this.triggerWidth, maxWidth: this.resolvedMaxDropdownWidth, maxHeight: this.resolvedDropdownHeight, onSdOptionSelect: event => this.handleOptionSelect(event.detail) })))));
14870
14904
  }
14871
14905
  static get watchers() { return {
14872
14906
  "isOpen": [{
@@ -14898,6 +14932,9 @@ class SdSelectV2 {
14898
14932
  "labelTooltipProps": [16],
14899
14933
  "emitValue": [4, "emit-value"],
14900
14934
  "width": [8],
14935
+ "useSearch": [4, "use-search"],
14936
+ "allSelectedLabel": [1, "all-selected-label"],
14937
+ "useSelectAll": [4, "use-select-all"],
14901
14938
  "name": [1],
14902
14939
  "isOpen": [32],
14903
14940
  "isAnimatingOut": [32],
@@ -15265,6 +15302,8 @@ class SdSelectV2Listbox {
15265
15302
  options = [];
15266
15303
  value = null;
15267
15304
  emitValue = false;
15305
+ useSearch = false;
15306
+ useSelectAll = false;
15268
15307
  triggerWidth = '200px';
15269
15308
  maxWidth = '640px';
15270
15309
  maxHeight = '260px';
@@ -15282,7 +15321,40 @@ class SdSelectV2Listbox {
15282
15321
  get isMulti() {
15283
15322
  return this.type === 'multi' || this.type === 'multi_depth';
15284
15323
  }
15324
+ static SELECT_ALL_OPTION = {
15325
+ value: '__select_all__',
15326
+ label: '전체',
15327
+ };
15328
+ get showSelectAll() {
15329
+ return this.useSelectAll && this.isMulti;
15330
+ }
15331
+ getAllNonDisabledLeaves() {
15332
+ const collect = (opts) => opts.flatMap(o => {
15333
+ if (o.disabled)
15334
+ return [];
15335
+ if (o.children)
15336
+ return collect(o.children);
15337
+ return [o];
15338
+ });
15339
+ return collect(this.options);
15340
+ }
15341
+ get selectAllState() {
15342
+ if (!this.showSelectAll)
15343
+ return false;
15344
+ const allLeaves = this.getAllNonDisabledLeaves();
15345
+ if (allLeaves.length === 0)
15346
+ return false;
15347
+ const selectedValues = this.getSelectedValues();
15348
+ const selectedCount = allLeaves.filter(l => selectedValues.has(l.value)).length;
15349
+ if (selectedCount === 0)
15350
+ return false;
15351
+ if (selectedCount === allLeaves.length)
15352
+ return true;
15353
+ return null;
15354
+ }
15285
15355
  get showSearch() {
15356
+ if (!this.useSearch)
15357
+ return false;
15286
15358
  const count = this.isDepth ? countLeaves(this.options) : this.options.length;
15287
15359
  return count >= SEARCH_THRESHOLD;
15288
15360
  }
@@ -15384,6 +15456,9 @@ class SdSelectV2Listbox {
15384
15456
  }
15385
15457
  get navigableOptions() {
15386
15458
  const items = [];
15459
+ if (this.showSelectAll) {
15460
+ items.push(SdSelectV2Listbox.SELECT_ALL_OPTION);
15461
+ }
15387
15462
  const walk = (opts) => {
15388
15463
  for (const opt of opts) {
15389
15464
  const isGroup = !!opt.children;
@@ -15397,6 +15472,22 @@ class SdSelectV2Listbox {
15397
15472
  walk(this.filteredOptions);
15398
15473
  return items;
15399
15474
  }
15475
+ isSelectAllOption(option) {
15476
+ return this.showSelectAll && option.value === SdSelectV2Listbox.SELECT_ALL_OPTION.value;
15477
+ }
15478
+ emitSelectAll() {
15479
+ if (!this.showSelectAll)
15480
+ return;
15481
+ const allLeaves = this.getAllNonDisabledLeaves();
15482
+ this.optionSelect.emit({
15483
+ option: { ...SdSelectV2Listbox.SELECT_ALL_OPTION, children: allLeaves },
15484
+ leaves: allLeaves,
15485
+ });
15486
+ }
15487
+ handleSelectAllClick = (e) => {
15488
+ e.stopPropagation();
15489
+ this.emitSelectAll();
15490
+ };
15400
15491
  isOptionFocused(option) {
15401
15492
  if (this.focusedIndex < 0)
15402
15493
  return false;
@@ -15469,7 +15560,13 @@ class SdSelectV2Listbox {
15469
15560
  return;
15470
15561
  e.preventDefault();
15471
15562
  e.stopPropagation();
15472
- this.emitOptionSelect(items[this.focusedIndex]);
15563
+ const focused = items[this.focusedIndex];
15564
+ if (this.isSelectAllOption(focused)) {
15565
+ this.emitSelectAll();
15566
+ }
15567
+ else {
15568
+ this.emitOptionSelect(focused);
15569
+ }
15473
15570
  }
15474
15571
  };
15475
15572
  /**
@@ -15548,9 +15645,9 @@ class SdSelectV2Listbox {
15548
15645
  '--listbox-max-height': this.maxHeight,
15549
15646
  '--listbox-radius': `${LIST_BOX_LAYOUT.radius}px`,
15550
15647
  };
15551
- return (hAsync("div", { key: 'd4d80ebd565436cd929961a2f9ce50adf92c124b', class: "sd-select-v2-listbox", style: cssVars }, this.showSearch && (hAsync("sd-select-v2-list-item-search", { key: 'bd549975fe6187aa7e77e718c8d2ba4a6d6e33de', isScrolled: this.isScrolled, onSdSearchFilter: this.handleSearchFilter })), hAsync("div", { key: '4ac6a1512781942fef3e42d6ca32762962df1836', class: "sd-select-v2-listbox__list", onScroll: this.handleScroll, ref: el => {
15648
+ return (hAsync("div", { key: '34efe12dfb3829dd7024eb473d0bb6460ad07e61', class: "sd-select-v2-listbox", style: cssVars }, this.showSearch && (hAsync("sd-select-v2-list-item-search", { key: 'd59a97386213e93f905a817b7c3242d1fb5d5035', isScrolled: this.isScrolled, onSdSearchFilter: this.handleSearchFilter })), hAsync("div", { key: '0feb6763afe5ac661de85df2c1a3683e56b17035', class: "sd-select-v2-listbox__list", onScroll: this.handleScroll, ref: el => {
15552
15649
  this.listEl = el;
15553
- } }, this.isEmpty ? (hAsync("div", { class: "sd-select-v2-listbox__empty" }, EMPTY_MESSAGE)) : this.isDepth ? (this.renderOptions(this.filteredOptions)) : (this.filteredOptions.map(option => (hAsync("sd-select-v2-list-item", { option: option, depth: 1, isSelected: this.isOptionSelected(option), isFocused: this.isOptionFocused(option), useCheckbox: this.isMulti, onSdListItemClick: this.handleOptionClick, onMouseEnter: () => this.handleOptionHover(option) })))))));
15650
+ } }, this.showSelectAll && (hAsync("sd-select-v2-list-item", { key: 'b4a765ddfadd39808baafd925d0cd2fcdab78800', option: SdSelectV2Listbox.SELECT_ALL_OPTION, depth: 1, isSelected: this.selectAllState, isFocused: this.isOptionFocused(SdSelectV2Listbox.SELECT_ALL_OPTION), useCheckbox: true, onSdListItemClick: this.handleSelectAllClick, onMouseEnter: () => this.handleOptionHover(SdSelectV2Listbox.SELECT_ALL_OPTION) })), this.isEmpty ? (hAsync("div", { class: "sd-select-v2-listbox__empty" }, EMPTY_MESSAGE)) : this.isDepth ? (this.renderOptions(this.filteredOptions)) : (this.filteredOptions.map(option => (hAsync("sd-select-v2-list-item", { option: option, depth: 1, isSelected: this.isOptionSelected(option), isFocused: this.isOptionFocused(option), useCheckbox: this.isMulti, onSdListItemClick: this.handleOptionClick, onMouseEnter: () => this.handleOptionHover(option) })))))));
15554
15651
  }
15555
15652
  static get watchers() { return {
15556
15653
  "searchKeyword": [{
@@ -15566,6 +15663,8 @@ class SdSelectV2Listbox {
15566
15663
  "options": [16],
15567
15664
  "value": [8],
15568
15665
  "emitValue": [4, "emit-value"],
15666
+ "useSearch": [4, "use-search"],
15667
+ "useSelectAll": [4, "use-select-all"],
15569
15668
  "triggerWidth": [1, "trigger-width"],
15570
15669
  "maxWidth": [1, "max-width"],
15571
15670
  "maxHeight": [1, "max-height"],
@@ -15629,13 +15728,13 @@ class SdSelectV2Trigger {
15629
15728
  ? SELECT_COLORS.icon.disabled
15630
15729
  : SELECT_COLORS.icon.default,
15631
15730
  };
15632
- return (hAsync("div", { key: '7c4f60c972c17b5954cbf0d0cc7ee38c8e6c16a3', ref: el => {
15731
+ return (hAsync("div", { key: 'ec8bf544b2878082a046fbe881afa2369709033f', ref: el => {
15633
15732
  this.triggerEl = el;
15634
15733
  }, tabindex: this.disabled ? -1 : 0, class: {
15635
15734
  'sd-select-v2-trigger': true,
15636
15735
  'sd-select-v2-trigger--open': this.isOpen,
15637
15736
  'sd-select-v2-trigger--disabled': this.disabled,
15638
- }, style: cssVars, onClick: this.handleClick, onFocus: this.handleFocus, onBlur: this.handleBlur }, hAsync("div", { key: 'de5f5a44626fce29c5a83cf0a14dd03352d40b57', class: "sd-select-v2-trigger__content" }, hAsync("span", { key: 'a36a013e9ef359160c2b9d24b42ee6f228aca302', class: "sd-select-v2-trigger__text" }, hasValue ? this.displayText : this.placeholder), hAsync("sd-icon", { key: '4bfcfce96fbe2008517ee26d7802d4492292faa5', name: "chevronDown", size: 12, color: "var(--trigger-icon-color)", class: {
15737
+ }, style: cssVars, onClick: this.handleClick, onFocus: this.handleFocus, onBlur: this.handleBlur }, hAsync("div", { key: '1a6a5cf66208aa5a996e788886ff593ec0830d51', class: "sd-select-v2-trigger__content" }, hAsync("span", { key: 'bd905f9149f3842e5e169e1a6086b33164b0ab66', class: "sd-select-v2-trigger__text" }, hasValue ? this.displayText : this.placeholder), hAsync("sd-icon", { key: 'cc487e430f42fdd61540e265a9e5bb01e9045a58', name: "chevronDown", size: 12, color: "var(--trigger-icon-color)", class: {
15639
15738
  'sd-select-v2-trigger__icon': true,
15640
15739
  'sd-select-v2-trigger__icon--open': this.isOpen,
15641
15740
  } }))));
@@ -15757,7 +15856,7 @@ class SdSwitch {
15757
15856
  '--sd-switch-line-height': `${SWITCH_TYPOGRAPHY.lineHeight}px`,
15758
15857
  '--sd-switch-text-decoration': SWITCH_TYPOGRAPHY.textDecoration,
15759
15858
  };
15760
- return (hAsync("label", { key: 'ac6a35d06ddd04bc94369014ff586766dd745bbb', "aria-label": this.label || 'switch', class: this.switchClasses, style: cssVars }, hAsync("input", { key: '9ebc810e93c9dfa3bf7407f279dadbada579196e', type: "checkbox", checked: this.value, disabled: this.disabled, onInput: this.handleChange }), hAsync("div", { key: '7add76be99645d6434e95305f6318fac7da0de57', class: "sd-switch__track" }, hAsync("div", { key: 'ed90778aa4dcd6f0853029579c36cfdb8640afcf', class: "sd-switch__knob" })), this.label && hAsync("span", { key: '70e3ddf819e77da4c693a4853ddb7f392381964e', class: "sd-switch__label" }, this.label)));
15859
+ return (hAsync("label", { key: '469c012285d3c8a33792a460e74d8566c384efe8', "aria-label": this.label || 'switch', class: this.switchClasses, style: cssVars }, hAsync("input", { key: '9678e3325339a47e3e2d81ce3cd752c86ed0f906', type: "checkbox", checked: this.value, disabled: this.disabled, onInput: this.handleChange }), hAsync("div", { key: '47348914869f5215957a652cfcf3a11807a0216f', class: "sd-switch__track" }, hAsync("div", { key: '0676260c42e6b79acec710f0f9ba72f01a3a7c18', class: "sd-switch__knob" })), this.label && hAsync("span", { key: 'b92597092795bff38d2acf0cff76f9c381435438', class: "sd-switch__label" }, this.label)));
15761
15860
  }
15762
15861
  static get style() { return sdSwitchCss(); }
15763
15862
  static get cmpMeta() { return {
@@ -15801,7 +15900,7 @@ function nanoid(size = 21) {
15801
15900
 
15802
15901
  const TABLE_ID_ATTR = 'table-id';
15803
15902
 
15804
- const sdTableCss = () => `sd-table,:host{display:block;width:100%;max-width:100%;min-width:0}sd-table *,:host *{box-sizing:border-box}.sd-table__container{height:var(--table-height, auto);width:var(--table-width, 100%);max-width:100%;min-width:0;color:#222222;display:flex;flex-direction:column}.sd-table__clip{width:100%;min-width:0;height:var(--table-container-height, 400px);border:1px solid #E1E1E1;border-radius:8px;overflow:hidden}.sd-table__clip--has-pagination{border-radius:8px 8px 0 0}.sd-table__wrapper{width:100%;height:100%;display:flex;flex-direction:column;position:relative;font-size:12px;overflow:auto;background:#FFFFFF}.sd-table__wrapper--loading{overflow:hidden !important;pointer-events:none}.sd-table__wrapper--no-data{overflow:hidden;pointer-events:none}.sd-table__no-data{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:12px;color:#888888;pointer-events:none;z-index:200;background:rgba(255, 255, 255, 0.6)}.sd-table__loading{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(255, 255, 255, 0.6);z-index:200;display:flex;align-items:center;justify-content:center;pointer-events:none}.sd-table{background-color:white;display:table;width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.sd-table--selectable sd-thead,.sd-table--selectable sd-tbody{--selectable:true}.sd-table--sticky-header sd-thead thead{position:sticky;top:0;z-index:120}.sd-table--sticky-column sd-thead,.sd-table--sticky-column sd-tbody{--sticky-column:true}.sd-table--scrolled-left sd-thead,.sd-table--scrolled-left sd-tbody{--scrolled-left:true}.sd-table--scrolled-right sd-thead,.sd-table--scrolled-right sd-tbody{--scrolled-right:true}.sd-table--resizable sd-thead{--resizable:true}.sd-table--no-data sd-thead{opacity:0.4}.sd-table__pagination{position:relative;background:#F9F9F9;height:48px;display:flex;align-items:center;justify-content:center;border:1px solid #E1E1E1;border-top:none;border-radius:0 0 8px 8px}.sd-table__pagination sd-select-v2{position:absolute;right:10px;top:50%;transform:translateY(-50%)}`;
15903
+ const sdTableCss = () => `sd-table,:host{display:block;width:100%;max-width:100%;min-width:0}sd-table *,:host *{box-sizing:border-box}.sd-table__container{height:var(--table-height, 100%);width:var(--table-width, 100%);max-width:100%;min-width:0;color:#222222;display:flex;flex-direction:column}.sd-table__clip{width:100%;min-width:0;height:var(--table-container-height, 400px);border:1px solid #E1E1E1;border-radius:8px;overflow:hidden}.sd-table__clip--has-pagination{border-radius:8px 8px 0 0}.sd-table__wrapper{width:100%;height:100%;display:flex;flex-direction:column;position:relative;font-size:12px;overflow:auto;background:#FFFFFF}.sd-table__wrapper--loading{overflow:hidden !important;pointer-events:none}.sd-table__wrapper--no-data{overflow:hidden;pointer-events:none}.sd-table__no-data{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:12px;color:#888888;pointer-events:none;z-index:200;background:rgba(255, 255, 255, 0.6)}.sd-table__loading{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(255, 255, 255, 0.6);z-index:200;display:flex;align-items:center;justify-content:center;pointer-events:none}.sd-table{background-color:white;display:table;width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.sd-table--selectable sd-thead,.sd-table--selectable sd-tbody{--selectable:true}.sd-table--sticky-header sd-thead thead{position:sticky;top:0;z-index:120}.sd-table--sticky-column sd-thead,.sd-table--sticky-column sd-tbody{--sticky-column:true}.sd-table--scrolled-left sd-thead,.sd-table--scrolled-left sd-tbody{--scrolled-left:true}.sd-table--scrolled-right sd-thead,.sd-table--scrolled-right sd-tbody{--scrolled-right:true}.sd-table--resizable sd-thead{--resizable:true}.sd-table--no-data sd-thead{opacity:0.4}.sd-table__pagination{position:relative;background:#F9F9F9;height:48px;display:flex;align-items:center;justify-content:center;border:1px solid #E1E1E1;border-top:none;border-radius:0 0 8px 8px}.sd-table__pagination sd-select-v2{position:absolute;right:10px;top:50%;transform:translateY(-50%)}`;
15805
15904
 
15806
15905
  class SdTable {
15807
15906
  constructor(hostRef) {
@@ -15857,11 +15956,17 @@ class SdTable {
15857
15956
  scrolledRight = false;
15858
15957
  rowCount = 0;
15859
15958
  loadingScrollTop = 0;
15959
+ // light DOM에 sd-thead / sd-tbody 자식이 없으면 sd-table이 직접 렌더해야 함을 알리는 플래그.
15960
+ // componentWillLoad에서 한 번 결정되며, 이후 동적 토글은 지원하지 않는다.
15961
+ autoThead = false;
15962
+ autoTbody = false;
15860
15963
  vsStart = 0;
15861
15964
  vsEnd = 0;
15862
15965
  lastReachEndNotifiedRowCount = -1;
15863
15966
  scrollContainer = null;
15864
15967
  onScroll;
15968
+ // 키: `${rowKey}::${field}` → { rowspan, colspan }
15969
+ spanRegistry = new Map();
15865
15970
  toFiniteNumber(value, fallback) {
15866
15971
  const n = typeof value === 'number' ? value : Number(value);
15867
15972
  return Number.isFinite(n) ? n : fallback;
@@ -15940,9 +16045,16 @@ class SdTable {
15940
16045
  this.innerRowsPerPage = newVal.rowsPerPage;
15941
16046
  }
15942
16047
  }
16048
+ detectChildren() {
16049
+ const hasThead = !!this.el.querySelector(':scope > sd-thead');
16050
+ const hasTbody = !!this.el.querySelector(':scope > sd-tbody');
16051
+ this.autoThead = !hasThead;
16052
+ this.autoTbody = !hasTbody;
16053
+ }
15943
16054
  componentWillLoad() {
15944
16055
  this.syncTableIdAttribute();
15945
16056
  this.handleNoDataLabelChange(this.noDataLabel);
16057
+ this.detectChildren();
15946
16058
  this.innerSelected = new Set(this.selected || []);
15947
16059
  this.columnWidths = (this.columns || []).map(c => parseInt(c.width || '120', 10));
15948
16060
  if (this.pagination?.page) {
@@ -15965,6 +16077,11 @@ class SdTable {
15965
16077
  el.getTableIdSync = () => this.getResolvedTableId();
15966
16078
  el.getVirtualScrollConfigSync = this.getVirtualScrollConfigSync.bind(this);
15967
16079
  el.calculateVisibleRange = this.calculateVisibleRange.bind(this);
16080
+ el.registerSpanSync = this.registerSpanSync.bind(this);
16081
+ el.unregisterSpanSync = this.unregisterSpanSync.bind(this);
16082
+ el.getSpanSync = this.getSpanSync.bind(this);
16083
+ el.isCoveredSync = this.isCoveredSync.bind(this);
16084
+ el.hasRowspanSync = this.hasRowspanSync.bind(this);
15968
16085
  if (Array.isArray(this.rows)) {
15969
16086
  this.rowCount = this.rows.length;
15970
16087
  this.pushRowsToChildren(this.rows);
@@ -16013,11 +16130,22 @@ class SdTable {
16013
16130
  this.scrollContainer.removeEventListener('scroll', this.onScroll);
16014
16131
  }
16015
16132
  }
16133
+ // light DOM(manual mode 자식)과 shadow DOM(autoThead/autoTbody fallback) 양쪽 모두에서 자식을 찾는다.
16134
+ queryChildEl(selector) {
16135
+ return (this.el.querySelector(selector) ??
16136
+ this.el.shadowRoot?.querySelector(selector) ??
16137
+ null);
16138
+ }
16139
+ queryAllTr() {
16140
+ const light = Array.from(this.el.querySelectorAll('sd-tr'));
16141
+ const shadow = Array.from(this.el.shadowRoot?.querySelectorAll('sd-tr') ?? []);
16142
+ return [...light, ...shadow];
16143
+ }
16016
16144
  pushRowsToChildren(rows) {
16017
- const tbody = this.el.querySelector('sd-tbody');
16145
+ const tbody = this.queryChildEl('sd-tbody');
16018
16146
  if (tbody)
16019
16147
  tbody.rows = rows;
16020
- const thead = this.el.querySelector('sd-thead');
16148
+ const thead = this.queryChildEl('sd-thead');
16021
16149
  if (thead)
16022
16150
  thead.rows = rows;
16023
16151
  }
@@ -16028,16 +16156,14 @@ class SdTable {
16028
16156
  this.refreshChildrenConfig();
16029
16157
  };
16030
16158
  refreshChildrenSelection() {
16031
- const thead = this.el.querySelector('sd-thead');
16032
- const rows = this.el.querySelectorAll('sd-tr');
16159
+ const thead = this.queryChildEl('sd-thead');
16033
16160
  thead?.refreshSelection?.();
16034
- rows.forEach(tr => tr?.refreshSelection?.());
16161
+ this.queryAllTr().forEach(tr => tr?.refreshSelection?.());
16035
16162
  }
16036
16163
  refreshChildrenConfig() {
16037
- const thead = this.el.querySelector('sd-thead');
16038
- const rows = this.el.querySelectorAll('sd-tr');
16164
+ const thead = this.queryChildEl('sd-thead');
16039
16165
  thead?.refreshConfig?.();
16040
- rows.forEach(tr => tr?.refreshConfig?.());
16166
+ this.queryAllTr().forEach(tr => tr?.refreshConfig?.());
16041
16167
  }
16042
16168
  maybeEmitVirtualReachEnd(start, end) {
16043
16169
  const threshold = Math.max(1, this.virtualEndThreshold);
@@ -16069,7 +16195,7 @@ class SdTable {
16069
16195
  this.vsEnd = end;
16070
16196
  const topHeight = start * this.rowHeight;
16071
16197
  const bottomHeight = Math.max(0, (this.rowCount - end) * this.rowHeight);
16072
- const tbody = this.el.querySelector('sd-tbody');
16198
+ const tbody = this.queryChildEl('sd-tbody');
16073
16199
  tbody?.setSpacersSync?.(topHeight, bottomHeight);
16074
16200
  if (rangeChanged) {
16075
16201
  this.sdVirtualUpdate.emit({
@@ -16161,8 +16287,7 @@ class SdTable {
16161
16287
  this.updateRowsVisibility();
16162
16288
  }
16163
16289
  updateRowsVisibility() {
16164
- const rows = this.el.querySelectorAll('sd-tr');
16165
- rows.forEach(tr => tr?.updateVisibility?.());
16290
+ this.queryAllTr().forEach(tr => tr?.updateVisibility?.());
16166
16291
  }
16167
16292
  changeRowsPerPage(perPage) {
16168
16293
  const changedRowsPerPage = perPage ? Number(perPage) : 0;
@@ -16199,10 +16324,9 @@ class SdTable {
16199
16324
  const delta = moveEvent.clientX - startX;
16200
16325
  const newWidth = Math.min(Math.max(startWidth + (reversed ? -delta : delta), minWidth), maxWidth);
16201
16326
  this.columnWidths = this.columnWidths.map((width, idx) => (idx === index ? newWidth : width));
16202
- const thead = this.el.querySelector('sd-thead');
16203
- const rows = this.el.querySelectorAll('sd-tr');
16327
+ const thead = this.queryChildEl('sd-thead');
16204
16328
  thead?.setColumnWidths?.(this.columnWidths);
16205
- rows.forEach(tr => tr?.setColumnWidths?.(this.columnWidths));
16329
+ this.queryAllTr().forEach(tr => tr?.setColumnWidths?.(this.columnWidths));
16206
16330
  const stickyRightCount = this.stickyColumn?.right || 0;
16207
16331
  const visibleColCount = this.columns.filter(c => c.visible !== false).length;
16208
16332
  const isRightStickyEdgeResizer = stickyRightCount > 0 && index === visibleColCount - stickyRightCount;
@@ -16239,6 +16363,109 @@ class SdTable {
16239
16363
  async getStickyStyle(colIdx) {
16240
16364
  return this.getStickyStyleSync(colIdx);
16241
16365
  }
16366
+ // ─── rowspan / colspan registry ─────────────────────────────────
16367
+ // sd-td가 mount/unmount 시 자기 (rowKey, field)와 span을 등록한다.
16368
+ // sd-tr는 render마다 isCoveredSync로 자신의 셀 위치가 다른 셀의 span에
16369
+ // 덮였는지 판정해 <td>를 그릴지 결정한다.
16370
+ spanKey(rowKey, field) {
16371
+ return `${rowKey}::${field}`;
16372
+ }
16373
+ // span 등록은 sd-td의 lifecycle에서 비동기적으로 일어나므로,
16374
+ // 등록/해제 직후 형제 sd-tr들이 새 레지스트리 상태로 다시 그려져야
16375
+ // 덮인 셀이 사라지거나 다시 나타난다.
16376
+ // forceUpdate는 React 래퍼 환경에서 prop 동기화 사이클과 부딪혀 누락되는
16377
+ // 경우가 있어, sd-tr의 @State (spansVersion)을 통해 재렌더를 강제한다.
16378
+ requestAllTrUpdate() {
16379
+ this.queryAllTr().forEach(tr => {
16380
+ const trAny = tr;
16381
+ if (typeof trAny.bumpSpansVersion === 'function') {
16382
+ trAny.bumpSpansVersion();
16383
+ }
16384
+ });
16385
+ }
16386
+ registerSpanSync(rowKey, field, rowspan, colspan) {
16387
+ if (rowKey == null || !field)
16388
+ return;
16389
+ const safeRowspan = Math.max(1, Math.floor(rowspan || 1));
16390
+ const safeColspan = Math.max(1, Math.floor(colspan || 1));
16391
+ const key = this.spanKey(rowKey, field);
16392
+ const prev = this.spanRegistry.get(key);
16393
+ if (safeRowspan === 1 && safeColspan === 1) {
16394
+ if (!prev)
16395
+ return;
16396
+ this.spanRegistry.delete(key);
16397
+ this.requestAllTrUpdate();
16398
+ return;
16399
+ }
16400
+ if (prev && prev.rowspan === safeRowspan && prev.colspan === safeColspan)
16401
+ return;
16402
+ this.spanRegistry.set(key, { rowspan: safeRowspan, colspan: safeColspan });
16403
+ this.requestAllTrUpdate();
16404
+ }
16405
+ unregisterSpanSync(rowKey, field) {
16406
+ if (rowKey == null || !field)
16407
+ return;
16408
+ const key = this.spanKey(rowKey, field);
16409
+ if (!this.spanRegistry.has(key))
16410
+ return;
16411
+ this.spanRegistry.delete(key);
16412
+ this.requestAllTrUpdate();
16413
+ }
16414
+ getSpanSync(rowKey, field) {
16415
+ return this.spanRegistry.get(this.spanKey(rowKey, field));
16416
+ }
16417
+ // 레지스트리에 rowspan>1 항목이 하나라도 있으면 true.
16418
+ // hover 동작을 끌지 결정하는 데 사용 — colspan만 있는 경우는 그대로 hover 유지.
16419
+ hasRowspanSync() {
16420
+ for (const span of this.spanRegistry.values()) {
16421
+ if (span.rowspan > 1)
16422
+ return true;
16423
+ }
16424
+ return false;
16425
+ }
16426
+ isCoveredSync(rowKey, colIdx, columns) {
16427
+ if (this.spanRegistry.size === 0)
16428
+ return false;
16429
+ const visibleCols = columns.filter(c => c.visible !== false);
16430
+ // 1. 같은 행 왼쪽 스캔 — colspan으로 이 위치를 덮는 셀이 있는가
16431
+ for (let i = 0; i < colIdx; i++) {
16432
+ const c = visibleCols[i];
16433
+ if (!c)
16434
+ continue;
16435
+ const field = typeof c.field === 'string' ? c.field : c.name;
16436
+ const span = this.spanRegistry.get(this.spanKey(rowKey, field));
16437
+ if (!span)
16438
+ continue;
16439
+ if (i + span.colspan > colIdx)
16440
+ return true;
16441
+ }
16442
+ // 2. 위쪽 행 스캔 — 숫자 변환 가능한 rowKey만 rowspan 평가
16443
+ const myRowIdx = Number(rowKey);
16444
+ if (!Number.isFinite(myRowIdx))
16445
+ return false;
16446
+ for (const [key, span] of this.spanRegistry) {
16447
+ if (span.rowspan <= 1)
16448
+ continue;
16449
+ const sepIdx = key.indexOf('::');
16450
+ if (sepIdx < 0)
16451
+ continue;
16452
+ const otherRowKey = key.slice(0, sepIdx);
16453
+ const otherField = key.slice(sepIdx + 2);
16454
+ const otherRowIdx = Number(otherRowKey);
16455
+ if (!Number.isFinite(otherRowIdx))
16456
+ continue;
16457
+ if (otherRowIdx >= myRowIdx)
16458
+ continue;
16459
+ if (otherRowIdx + span.rowspan <= myRowIdx)
16460
+ continue;
16461
+ const otherColIdx = visibleCols.findIndex(c => (typeof c.field === 'string' ? c.field : c.name) === otherField);
16462
+ if (otherColIdx < 0)
16463
+ continue;
16464
+ if (otherColIdx <= colIdx && otherColIdx + span.colspan > colIdx)
16465
+ return true;
16466
+ }
16467
+ return false;
16468
+ }
16242
16469
  setRowCountSync(count) {
16243
16470
  const safeCount = Math.max(0, Math.floor(this.toFiniteNumber(count, 0)));
16244
16471
  if (safeCount !== this.rowCount) {
@@ -16286,6 +16513,22 @@ class SdTable {
16286
16513
  return null;
16287
16514
  return { from: this.vsStart, to: this.vsEnd };
16288
16515
  }
16516
+ // autoTbody fallback에서 sd-table이 직접 sd-tr을 만들어내는 경로.
16517
+ // 가상 스크롤은 사용자가 직접 SdTbody+SdTr을 작성해야 하므로 빈 배열을 반환한다.
16518
+ renderAutoRows() {
16519
+ if (this.useVirtualScroll)
16520
+ return null;
16521
+ const allRows = this.rows ?? [];
16522
+ const pageInfo = this.getPaginationInfoSync();
16523
+ const startIdx = pageInfo?.startIndex ?? 0;
16524
+ const displayed = pageInfo
16525
+ ? allRows.slice(pageInfo.startIndex, pageInfo.endIndex)
16526
+ : allRows;
16527
+ return displayed.map((row, i) => {
16528
+ const absoluteIdx = startIdx + i;
16529
+ return (hAsync("sd-tr", { key: absoluteIdx, "row-key": String(absoluteIdx), row: row }));
16530
+ });
16531
+ }
16289
16532
  get tableClasses() {
16290
16533
  return [
16291
16534
  'sd-table',
@@ -16305,24 +16548,24 @@ class SdTable {
16305
16548
  }
16306
16549
  render() {
16307
16550
  const resolvedTableId = this.getResolvedTableId();
16308
- return (hAsync(Host, { key: '0b90643721a90b7bb59a6c31f6edeb313849b973' }, hAsync("div", { key: 'e55fe4f476dbea4888a168861e7e6d6951d7d489', class: "sd-table__container", style: {
16551
+ return (hAsync(Host, { key: 'd73cd690ad11ce92af37b6f32374f6f891c5b677' }, hAsync("div", { key: 'f51d23212885ad8121b9a4e895fb854f1e142bc4', class: "sd-table__container", style: {
16309
16552
  '--table-width': this.width,
16310
16553
  '--table-height': this.height,
16311
16554
  '--table-container-height': `calc(${this.height || '100%'} - ${this.pagination && this.rowCount > 0 && !this.useVirtualScroll ? 48 : 0}px)`,
16312
- } }, hAsync("div", { key: 'de18a900037a7b2f619dd22981c30ed76f5a8111', class: {
16555
+ } }, hAsync("div", { key: '84b1ba7b2220ff55304b9c19e59304ca2257cff0', class: {
16313
16556
  'sd-table__clip': true,
16314
16557
  'sd-table__clip--has-pagination': !!(this.pagination &&
16315
16558
  this.pagination.rowsPerPage > 0 &&
16316
16559
  this.rowCount > 0 &&
16317
16560
  !this.useVirtualScroll),
16318
- } }, hAsync("div", { key: '028e0982d415033adaf420ee6b953241c8f3dbec', class: {
16561
+ } }, hAsync("div", { key: 'c901eba67eae29515bf0b3edcc6632b2aacf0f80', class: {
16319
16562
  'sd-table__wrapper': true,
16320
16563
  'sd-table__wrapper--loading': this.isLoading,
16321
16564
  'sd-table__wrapper--no-data': this.rowCount === 0 && !this.isLoading,
16322
- } }, this.isLoading && (hAsync("div", { key: '8c9110c9c2c26cddbbed8e1f2782ecfaafd3679c', class: "sd-table__loading", style: { top: `${this.loadingScrollTop}px` } }, hAsync("sd-circle-progress", { key: '51b61f91b0ecebf63fe3e65b94012963f0375e5c', indeterminate: true }))), this.rowCount === 0 && !this.isLoading && (hAsync("div", { key: '0a7a45049014869b8164b081a251218d3c814e87', class: "sd-table__no-data" }, hAsync("slot", { key: 'd4b6219e5dcaaa22be3360f7f0f05a8b32533890', name: "no-data" }, hAsync("span", { key: 'c76848aad8a1d3967f3cd239090e97266e46ab3e' }, this.resolvedNoDataLabel)))), hAsync("table", { key: '2b560d112402549c7043b337d944b0de88c3ba0e', class: this.tableClasses }, hAsync("slot", { key: '1c4583148df6a585f389c1bed0426fa4a3cb4899', name: `${resolvedTableId}-head`, onSlotchange: this.handleStructureSlotChange }), hAsync("slot", { key: 'a5d983106de61c829f9cbeb541d1908fee48468c', name: `${resolvedTableId}-body`, onSlotchange: this.handleStructureSlotChange })))), this.pagination &&
16565
+ } }, this.isLoading && (hAsync("div", { key: '35a237d0203b2479dbdb77ac42c918a9375bdfd3', class: "sd-table__loading", style: { top: `${this.loadingScrollTop}px` } }, hAsync("sd-circle-progress", { key: '21a29981c1cdbd679f46abd2e7de7794c9ebbca9', indeterminate: true }))), this.rowCount === 0 && !this.isLoading && (hAsync("div", { key: '07ad28bc6e7556cfe229fc1e952410f388424a7f', class: "sd-table__no-data" }, hAsync("slot", { key: 'bf21e60f5b86614587b704bea2965b9467c7f467', name: "no-data" }, hAsync("span", { key: 'f3d012d12e9189545b0cef52250502d46cb9a764' }, this.resolvedNoDataLabel)))), hAsync("table", { key: '655d3dc017c6445ec454faef0e5e9837b7ee0013', class: this.tableClasses }, this.autoThead ? (hAsync("slot", { name: `${resolvedTableId}-head`, onSlotchange: this.handleStructureSlotChange }, hAsync("sd-thead", { rows: this.rows ?? [] }))) : (hAsync("slot", { name: `${resolvedTableId}-head`, onSlotchange: this.handleStructureSlotChange })), this.autoTbody ? (hAsync("slot", { name: `${resolvedTableId}-body`, onSlotchange: this.handleStructureSlotChange }, hAsync("sd-tbody", { rows: this.rows ?? [] }, this.renderAutoRows()))) : (hAsync("slot", { name: `${resolvedTableId}-body`, onSlotchange: this.handleStructureSlotChange }))))), this.pagination &&
16323
16566
  this.pagination.rowsPerPage > 0 &&
16324
16567
  this.rowCount > 0 &&
16325
- !this.useVirtualScroll && (hAsync("div", { key: '004355d84e2cfc2fd38a9d4811f14fd66dc5c21b', class: "sd-table__pagination" }, hAsync("sd-pagination", { key: '463586c7e57782a7989962f73cb3d4e8c04f5bce', currentPage: !this.useInternalPagination ? this.pagination.page : this.currentPage, lastPage: !this.useInternalPagination ? this.pagination.lastPage : this.lastPageNumber, onSdPageChange: (e) => this.changePage(e.detail) }), this.useRowsPerPageSelect && (hAsync("sd-select-v2", { key: '1f26de447da63ef0c4a24ffb49666a0687db9991', value: this.useInternalPagination
16568
+ !this.useVirtualScroll && (hAsync("div", { key: '7ab0b30a0c0e0a197b0f79c6b07ef5614d5d2879', class: "sd-table__pagination" }, hAsync("sd-pagination", { key: '71d44bba5a82f4d8f7c067e525db15fe9a36c305', currentPage: !this.useInternalPagination ? this.pagination.page : this.currentPage, lastPage: !this.useInternalPagination ? this.pagination.lastPage : this.lastPageNumber, onSdPageChange: (e) => this.changePage(e.detail) }), this.useRowsPerPageSelect && (hAsync("sd-select-v2", { key: 'a9ab33347db0714da188f658a2ca1902502db690', value: this.useInternalPagination
16326
16569
  ? this.innerRowsPerPage
16327
16570
  : this.pagination.rowsPerPage, options: this.rowsPerPageOption, width: "128px", emitValue: true, onSdUpdate: e => {
16328
16571
  if (!this.isRowsPerPageValue(e.detail))
@@ -16403,6 +16646,8 @@ class SdTable {
16403
16646
  "scrolledRight": [32],
16404
16647
  "rowCount": [32],
16405
16648
  "loadingScrollTop": [32],
16649
+ "autoThead": [32],
16650
+ "autoTbody": [32],
16406
16651
  "isRowSelected": [64],
16407
16652
  "updateRowSelect": [64],
16408
16653
  "toggleSelectAll": [64],
@@ -16603,7 +16848,7 @@ class SdTabs {
16603
16848
  };
16604
16849
  }
16605
16850
  render() {
16606
- return (hAsync("div", { key: '390edfad274caa06df38af9d04580015a1744a44', class: this.getContainerClasses(), style: this.buildCssVars() }, this.tabs.map((tab, index) => {
16851
+ return (hAsync("div", { key: '3698b7b43e74ff053d61d5ce696b987373fd27d6', class: this.getContainerClasses(), style: this.buildCssVars() }, this.tabs.map((tab, index) => {
16607
16852
  const badgeName = this.getBadgeName(tab);
16608
16853
  return (hAsync("div", { key: `tab-${index}`, class: this.getTabClasses(tab), "aria-label": tab.label || 'tab', onClick: () => this.handleTabClick(tab) }, hAsync("span", { "data-label": tab.label, class: "sd-tabs__label" }, tab.label), tab.badge !== undefined && tab.badge !== null && tab.badge !== '' && (hAsync("sd-tag", { name: badgeName, label: tab.badge.toString() }))));
16609
16854
  })));
@@ -16799,7 +17044,7 @@ class SdTag {
16799
17044
  render() {
16800
17045
  const config = this.resolvedConfig;
16801
17046
  const iconNode = this.renderIcon(config.icon, config.iconSize);
16802
- return (hAsync("span", { key: 'da19900d267d2b2f000e1790133966a7976bcded', class: "sd-tag", style: {
17047
+ return (hAsync("span", { key: 'def10730670f37a62fa76b507f7f15a1b1f956fc', class: "sd-tag", style: {
16803
17048
  '--sd-tag-background': config.background,
16804
17049
  '--sd-tag-content': config.content,
16805
17050
  '--sd-tag-height': config.height,
@@ -16809,7 +17054,7 @@ class SdTag {
16809
17054
  '--sd-tag-font-weight': config.fontWeight,
16810
17055
  '--sd-tag-line-height': config.lineHeight,
16811
17056
  '--sd-tag-radius': config.radius,
16812
- }, "aria-label": this.label || 'tag' }, this.icon && this.isLeft && iconNode, hAsync("span", { key: 'e426021988395058367872ac23658586b2895764', class: "sd-tag__label" }, this.label), this.icon && !this.isLeft && iconNode));
17057
+ }, "aria-label": this.label || 'tag' }, this.icon && this.isLeft && iconNode, hAsync("span", { key: '32082536736e20074263632aa29f36bc7709db39', class: "sd-tag__label" }, this.label), this.icon && !this.isLeft && iconNode));
16813
17058
  }
16814
17059
  static get style() { return sdTagCss(); }
16815
17060
  static get cmpMeta() { return {
@@ -16860,7 +17105,12 @@ class SdTbody {
16860
17105
  this.syncTableContext();
16861
17106
  }
16862
17107
  syncTableContext() {
16863
- const table = this.el.closest('sd-table');
17108
+ // sd-table shadow:true이므로 fallback content로 렌더되면 closest가 경계를 못 넘는다.
17109
+ // 그 경우 getRootNode().host(=sd-table)로 폴백한다.
17110
+ const closest = this.el.closest('sd-table');
17111
+ const root = this.el.getRootNode();
17112
+ const fromShadow = root instanceof ShadowRoot ? root.host : null;
17113
+ const table = closest ?? fromShadow;
16864
17114
  this.tableEl = table;
16865
17115
  const fromMethod = table?.getTableIdSync?.();
16866
17116
  const fromAttr = table?.getAttribute(TABLE_ID_ATTR);
@@ -16873,7 +17123,7 @@ class SdTbody {
16873
17123
  }
16874
17124
  render() {
16875
17125
  const hasRows = this.rows.length > 0;
16876
- return (hAsync(Host, { key: 'e4c64dbf97185bbc6eaec4b883c65dc8ebd34ece', slot: `${this.tableId}-body` }, hAsync("tbody", { key: 'b2fb886684a5a6055d3af659bba75dd9bc801b73', class: { 'tbody': true, 'tbody--empty': !hasRows } }, hasRows ? ([
17126
+ return (hAsync(Host, { key: 'bc9fbd4f08f4d77da60b083dceef4e24e2fb5532', slot: `${this.tableId}-body` }, hAsync("tbody", { key: '81ef875cbc39f988021a211ede716a98d3ea30cd', class: { 'tbody': true, 'tbody--empty': !hasRows } }, hasRows ? ([
16877
17127
  this.topSpacerHeight > 0 && (hAsync("tr", { key: "spacer-top", class: "tbody__spacer", style: { height: `${this.topSpacerHeight}px`, display: 'block' } })),
16878
17128
  hAsync("slot", null),
16879
17129
  this.bottomSpacerHeight > 0 && (hAsync("tr", { key: "spacer-bottom", class: "tbody__spacer", style: { height: `${this.bottomSpacerHeight}px`, display: 'block' } })),
@@ -16910,20 +17160,63 @@ class SdTd {
16910
17160
  field;
16911
17161
  rowKey;
16912
17162
  align;
17163
+ rowspan;
17164
+ colspan;
16913
17165
  handleFieldChange() {
16914
17166
  this.syncSlotName();
17167
+ this.syncSpanRegistration();
16915
17168
  }
16916
17169
  handleRowKeyChange() {
16917
17170
  this.syncSlotName();
17171
+ this.syncSpanRegistration();
17172
+ }
17173
+ handleSpanChange() {
17174
+ this.syncSpanRegistration();
16918
17175
  }
16919
17176
  componentWillLoad() {
16920
17177
  this.syncSlotName();
17178
+ this.syncSpanRegistration();
16921
17179
  // slot 타이밍 엇갈림 대응: 부모 sd-tr forceUpdate로 슬롯 재매칭
16922
17180
  const parentTr = this.el.parentElement;
16923
17181
  if (parentTr?.tagName?.toLowerCase() === 'sd-tr') ;
16924
17182
  }
16925
17183
  componentDidLoad() {
16926
17184
  this.syncSlotName();
17185
+ this.syncSpanRegistration();
17186
+ }
17187
+ // React StrictMode에서는 disconnect/reconnect 사이클이 일어나면서
17188
+ // 동일 인스턴스의 componentWillLoad는 더 이상 호출되지 않는다.
17189
+ // 재연결 시점에도 등록 상태를 복구해야 rowspan/colspan이 유지된다.
17190
+ connectedCallback() {
17191
+ this.syncSpanRegistration();
17192
+ }
17193
+ disconnectedCallback() {
17194
+ const table = this.findTable();
17195
+ if (table?.unregisterSpanSync && this.field && this.rowKey != null) {
17196
+ table.unregisterSpanSync(String(this.rowKey), this.field);
17197
+ this.requestParentTrUpdate();
17198
+ }
17199
+ }
17200
+ findTable() {
17201
+ return this.el.closest('sd-table');
17202
+ }
17203
+ requestParentTrUpdate() {
17204
+ const parentTr = this.el.parentElement;
17205
+ if (parentTr?.tagName?.toLowerCase() !== 'sd-tr')
17206
+ return;
17207
+ const trAny = parentTr;
17208
+ if (typeof trAny.bumpSpansVersion === 'function') {
17209
+ trAny.bumpSpansVersion();
17210
+ }
17211
+ }
17212
+ syncSpanRegistration() {
17213
+ const table = this.findTable();
17214
+ if (!table?.registerSpanSync || !this.field || this.rowKey == null)
17215
+ return;
17216
+ const rs = Math.max(1, Math.floor(Number(this.rowspan) || 1));
17217
+ const cs = Math.max(1, Math.floor(Number(this.colspan) || 1));
17218
+ table.registerSpanSync(String(this.rowKey), this.field, rs, cs);
17219
+ this.requestParentTrUpdate();
16927
17220
  }
16928
17221
  syncSlotName() {
16929
17222
  const table = this.el.closest('sd-table');
@@ -16937,7 +17230,7 @@ class SdTd {
16937
17230
  }
16938
17231
  }
16939
17232
  render() {
16940
- return (hAsync(Host, { key: '672c967273dac405ed4a47fa5939463265075681', class: { [`align-${this.align}`]: Boolean(this.align) } }, hAsync("slot", { key: 'c15e572fdf4a8c68fff8b69b586dfbf9f01dce1b' })));
17233
+ return (hAsync(Host, { key: 'da9ce2edb986d4b3cf1a6e5f59030009f1288250', class: { [`align-${this.align}`]: Boolean(this.align) } }, hAsync("slot", { key: '8514071bd38c4f5b1997ae7239b8585a25f97ce0' })));
16941
17234
  }
16942
17235
  static get watchers() { return {
16943
17236
  "field": [{
@@ -16945,6 +17238,12 @@ class SdTd {
16945
17238
  }],
16946
17239
  "rowKey": [{
16947
17240
  "handleRowKeyChange": 0
17241
+ }],
17242
+ "rowspan": [{
17243
+ "handleSpanChange": 0
17244
+ }],
17245
+ "colspan": [{
17246
+ "handleSpanChange": 0
16948
17247
  }]
16949
17248
  }; }
16950
17249
  static get style() { return sdTdCss(); }
@@ -16954,7 +17253,9 @@ class SdTd {
16954
17253
  "$members$": {
16955
17254
  "field": [1],
16956
17255
  "rowKey": [1, "row-key"],
16957
- "align": [1]
17256
+ "align": [1],
17257
+ "rowspan": [2],
17258
+ "colspan": [2]
16958
17259
  },
16959
17260
  "$listeners$": undefined,
16960
17261
  "$lazyBundleId$": "-",
@@ -17033,16 +17334,16 @@ class SdTextLink {
17033
17334
  '--sd-text-link-text-decoration': typo.textDecoration,
17034
17335
  ...(this.disabled ? { '--sd-text-link-color': TEXT_LINK_COLORS.content.disabled } : {}),
17035
17336
  };
17036
- return (hAsync("span", { key: '1128254cddacf5869f320ce2b788b06646f27d7f', class: {
17337
+ return (hAsync("span", { key: '77c1aa4a4a6297af9431947b7146db2ddfad52b5', class: {
17037
17338
  'sd-text-link': true,
17038
17339
  'sd-text-link--disabled': this.disabled,
17039
- }, style: cssVars, onClick: this.handleClick }, this.icon && (hAsync("sd-icon", { key: '52c069d637a2ccf9cd4e7bd1ab3a62ea981d2e1e', name: this.icon, size: TEXT_LINK_LAYOUT.iconSize, color: iconColor, class: "sd-text-link__icon" })), hAsync("span", { key: '99a09359c75c2eb6c2e2ef6b9e3b87d92c3f7810', class: labelClassName }, this.label), this.useArrow && (hAsync("span", { key: 'c7e77454d9d002c0e043dc71a418c65ecd60cff5', class: "sd-text-link__arrow", style: {
17340
+ }, style: cssVars, onClick: this.handleClick }, this.icon && (hAsync("sd-icon", { key: '6f760b3c7e0adccd2aa08cb662cca90a3d3a227b', name: this.icon, size: TEXT_LINK_LAYOUT.iconSize, color: iconColor, class: "sd-text-link__icon" })), hAsync("span", { key: '3ff017970956d8e5cb72b4d6e26d33aaf0551e76', class: labelClassName }, this.label), this.useArrow && (hAsync("span", { key: '8332cbe3b2283ce866044e55804e35338569a38f', class: "sd-text-link__arrow", style: {
17040
17341
  width: `${TEXT_LINK_LAYOUT.arrowFrame}px`,
17041
17342
  height: `${TEXT_LINK_LAYOUT.arrowFrame}px`,
17042
17343
  display: 'inline-flex',
17043
17344
  alignItems: 'center',
17044
17345
  justifyContent: 'center',
17045
- } }, hAsync("sd-icon", { key: '677c88823b02084449cd2dec83cc6bd27dfb8006', name: "chevronRight", size: TEXT_LINK_LAYOUT.arrowIconSize, color: arrowColor })))));
17346
+ } }, hAsync("sd-icon", { key: '2fa166ef60f6d1ee933450146bc667ee89dad2ce', name: "chevronRight", size: TEXT_LINK_LAYOUT.arrowIconSize, color: arrowColor })))));
17046
17347
  }
17047
17348
  static get style() { return sdTextLinkCss(); }
17048
17349
  static get cmpMeta() { return {
@@ -17189,7 +17490,7 @@ class SdTextarea {
17189
17490
  '--sd-system-size-field-sm-height': 'auto',
17190
17491
  '--sd-system-radius-field-sm': `${TEXTAREA_TOKENS.radius}px`,
17191
17492
  };
17192
- return (hAsync("sd-field", { key: '345a70f335ee103a4e45c75e17559359beec01c9', name: this.name, label: this.label, labelWidth: this.labelWidth, addonLabel: this.addonLabel, addonAlign: this.addonAlign, hint: this.hint, errorMessage: this.errorMessage, width: this.width, rules: this.rules, error: this.error, disabled: this.disabled, focused: this.focused, hovered: this.hovered, status: this.status, icon: this.icon, labelTooltip: this.labelTooltip, labelTooltipProps: this.labelTooltipProps, ref: el => (this.formField = el), onMouseEnter: () => (this.hovered = true), onMouseLeave: () => (this.hovered = false), style: cssVars }, hAsync("div", { key: 'dc09d61d06f3cefb15dce980e293a266fdf3d79d', class: "sd-textarea__content" }, hAsync("textarea", { key: '085de248d7376e0d19d3588bc836bd5ad17cb335', name: this.name, ref: el => (this.nativeEl = el), class: `sd-textarea__native ${this.textareaClass}`, value: this.internalValue || '', placeholder: this.placeholder, disabled: this.disabled, readOnly: this.readonly, autofocus: this.autoFocus, maxLength: this.maxLength, rows: this.rows, spellcheck: this.spellcheck, onInput: this.handleInput, onFocus: event => this.handleFocus('focus', event), onBlur: event => this.handleFocus('blur', event), style: this.textareaStyle }))));
17493
+ return (hAsync("sd-field", { key: 'a77834af45e2ca7abaa019d18b6108a51f0cf4ae', name: this.name, label: this.label, labelWidth: this.labelWidth, addonLabel: this.addonLabel, addonAlign: this.addonAlign, hint: this.hint, errorMessage: this.errorMessage, width: this.width, rules: this.rules, error: this.error, disabled: this.disabled, focused: this.focused, hovered: this.hovered, status: this.status, icon: this.icon, labelTooltip: this.labelTooltip, labelTooltipProps: this.labelTooltipProps, ref: el => (this.formField = el), onMouseEnter: () => (this.hovered = true), onMouseLeave: () => (this.hovered = false), style: cssVars }, hAsync("div", { key: '2cbc8ef4febeab89eb336cb29d34abdbf9f2f080', class: "sd-textarea__content" }, hAsync("textarea", { key: '3b09e30b4e42affc7f03fb8a354387b57e5ee0fe', name: this.name, ref: el => (this.nativeEl = el), class: `sd-textarea__native ${this.textareaClass}`, value: this.internalValue || '', placeholder: this.placeholder, disabled: this.disabled, readOnly: this.readonly, autofocus: this.autoFocus, maxLength: this.maxLength, rows: this.rows, spellcheck: this.spellcheck, onInput: this.handleInput, onFocus: event => this.handleFocus('focus', event), onBlur: event => this.handleFocus('blur', event), style: this.textareaStyle }))));
17193
17494
  }
17194
17495
  static get watchers() { return {
17195
17496
  "value": [{
@@ -17286,7 +17587,12 @@ class SdThead {
17286
17587
  this.resolveConfig();
17287
17588
  }
17288
17589
  syncTableContext() {
17289
- const table = this.el.closest('sd-table');
17590
+ // sd-table shadow:true이므로 fallback content로 렌더되면 closest가 경계를 못 넘는다.
17591
+ // 그 경우 getRootNode().host(=sd-table)로 폴백한다.
17592
+ const closest = this.el.closest('sd-table');
17593
+ const root = this.el.getRootNode();
17594
+ const fromShadow = root instanceof ShadowRoot ? root.host : null;
17595
+ const table = closest ?? fromShadow;
17290
17596
  this.tableEl = table;
17291
17597
  const fromMethod = table?.getTableIdSync?.();
17292
17598
  const fromAttr = table?.getAttribute(TABLE_ID_ATTR);
@@ -17376,16 +17682,16 @@ class SdThead {
17376
17682
  const stickyLeftCols = this.visibleColumns.slice(0, stickyLeftCount);
17377
17683
  const middleCols = this.visibleColumns.slice(stickyLeftCount, this.visibleColumns.length - stickyRightCount);
17378
17684
  const stickyRightCols = this.visibleColumns.slice(this.visibleColumns.length - stickyRightCount);
17379
- return (hAsync(Host, { key: '2358499ef65d88005d03b1246604c0fd8eefdde1', slot: `${this.tableId}-head` }, hAsync("thead", { key: '49bb43a19aeb83f3a60367b26dbb6535ebcec743', class: {
17685
+ return (hAsync(Host, { key: '5aa1e38311b542d1a0b05b55abc7ef41927508bd', slot: `${this.tableId}-head` }, hAsync("thead", { key: '6d17753988ecd02d900d8a3bd7f2115b534b68a7', class: {
17380
17686
  'thead': true,
17381
17687
  'thead--sticky': this._stickyHeader,
17382
- } }, hAsync("tr", { key: 'cd6388d79e9a4a5d9edbbda05601abbbefcb1ff4', class: "tr" }, this._selectable && (hAsync("th", { key: 'fa09e82368d45e9fb1d32838ef44e609c698609d', class: {
17688
+ } }, hAsync("tr", { key: '9cc729603e126da2f9c8923fe29ece10c7750bb4', class: "tr" }, this._selectable && (hAsync("th", { key: '37b2bcfa77eaf4c44465684c49ae84d566acc18b', class: {
17383
17689
  'th': true,
17384
17690
  'th--selected': true,
17385
17691
  'sticky-left': true,
17386
17692
  'sticky-left-edge': stickyLeftCount === 0,
17387
17693
  'is-scrolled-left': stickyLeftCount === 0 && this._scrolledLeft,
17388
- }, style: { '--sticky-left-offset': '0px' } }, hAsync("sd-checkbox", { key: '5ab4861aecfac9495101363d5bd809d077c7dbc3', value: this.getIsAllChecked(), disabled: !safeRows.length, onSdUpdate: (e) => this.handleSelectAll(e.detail) }))), stickyLeftCols.map((col, idx) => (hAsync("th", { key: col.name, class: {
17694
+ }, style: { '--sticky-left-offset': '0px' } }, hAsync("sd-checkbox", { key: '4284894821640ee1bdbd12b1759efb01e6c06488', value: this.getIsAllChecked(), disabled: !safeRows.length, onSdUpdate: (e) => this.handleSelectAll(e.detail) }))), stickyLeftCols.map((col, idx) => (hAsync("th", { key: col.name, class: {
17389
17695
  'th': true,
17390
17696
  [`${col.thClass}`]: Boolean(col.thClass),
17391
17697
  'sticky-left': true,
@@ -17500,10 +17806,10 @@ class SdToast {
17500
17806
  render() {
17501
17807
  const typeConfig = TOAST_TYPE_CONFIG[this.type] ?? TOAST_TYPE_CONFIG.default;
17502
17808
  const iconSize = Number(TOAST_LAYOUT.iconSize);
17503
- return (hAsync("div", { key: 'd4b73e2503514143f5174bc8859baf0e59c2f8da', style: {
17809
+ return (hAsync("div", { key: '77954c9d285339cb48032eec5eca0dcbe308affc', style: {
17504
17810
  '--sd-toast-bg': typeConfig.bg,
17505
17811
  '--sd-toast-text': typeConfig.content,
17506
- } }, hAsync("div", { key: '7334daee691fb03a1005c2afac64033554489046', class: "sd-toast", role: "status", "aria-live": "polite", "aria-atomic": "true" }, this.icon && (hAsync("div", { key: '297ada835b0710bf43a936b02e53b0873b7f4af3', class: "sd-toast__icon" }, hAsync("sd-icon", { key: 'b5bc4716df28231dc7af15db63595ae9044189b5', name: this.icon, size: iconSize, color: typeConfig.content }))), hAsync("div", { key: 'd0239c8f8b495fbdaedad0f65a6d0a0edfaada60', class: "sd-toast__content" }, hAsync("span", { key: 'dc70d403673bb8f99cfd91393054a86bf17e5ac2', class: "sd-toast__message" }, this.message)), this.link && (hAsync("a", { key: '1a76bcee482720693b501d3a13c54e720bbe44fc', href: this.link, class: "sd-toast__link", target: "_blank", rel: "noopener noreferrer" }, this.linkLabel || this.link)), this.useClose && (hAsync("sd-ghost-button", { key: 'a8dc3c15cabf5ca4e075e75c4fb2744dd5da4fa0', class: "sd-toast__close", icon: "close", intent: this.type === 'caution' ? 'default' : 'inverse', ariaLabel: "close", size: "xs", onClick: () => this.close.emit() })))));
17812
+ } }, hAsync("div", { key: '73c792f19982140f91397a3ec7d6e22914ca316f', class: "sd-toast", role: "status", "aria-live": "polite", "aria-atomic": "true" }, this.icon && (hAsync("div", { key: 'cc140bfd043b0d0cd6a7697053f736dac707f86b', class: "sd-toast__icon" }, hAsync("sd-icon", { key: '85f38036cd39cb4d0f4a43ef0d307ef9faa03eb1', name: this.icon, size: iconSize, color: typeConfig.content }))), hAsync("div", { key: '4d36e34a9ccac80fc2ed01f33b1e2aa80d70c78b', class: "sd-toast__content" }, hAsync("span", { key: '9105d37004bbde90e8a7118ca5a58a6e4d6953f5', class: "sd-toast__message" }, this.message)), this.link && (hAsync("a", { key: 'fdaabae7d8efb6540ce770cc5783b286789cdb3c', href: this.link, class: "sd-toast__link", target: "_blank", rel: "noopener noreferrer" }, this.linkLabel || this.link)), this.useClose && (hAsync("sd-ghost-button", { key: 'c5985e50041b8f3e8c77e142fd06afaf0537de47', class: "sd-toast__close", icon: "close", intent: this.type === 'caution' ? 'default' : 'inverse', ariaLabel: "close", size: "xs", onClick: () => this.close.emit() })))));
17507
17813
  }
17508
17814
  static get style() { return sdToastCss(); }
17509
17815
  static get cmpMeta() { return {
@@ -17755,7 +18061,7 @@ class SdToastContainer {
17755
18061
  const activeToasts = toasts.filter(t => t.state !== 'exiting').reverse();
17756
18062
  const indexMap = new Map();
17757
18063
  activeToasts.forEach((t, i) => indexMap.set(t.id, i));
17758
- return (hAsync("div", { key: '601c4c5aa55df02459866607ca7c59da53c2eda5', class: "sd-toast-container", style: this.getContainerStyles(), onMouseEnter: () => {
18064
+ return (hAsync("div", { key: '5057793be2d6ce213edc84d58f7273248646dc19', class: "sd-toast-container", style: this.getContainerStyles(), onMouseEnter: () => {
17759
18065
  this.expanded = true;
17760
18066
  this.pauseTimers();
17761
18067
  }, onMouseLeave: () => {
@@ -17913,7 +18219,7 @@ class SdToggle {
17913
18219
  '--sd-toggle-content-select': TOGGLE_COLORS.content.select,
17914
18220
  '--sd-toggle-content-disabled': TOGGLE_COLORS.content.disabled,
17915
18221
  };
17916
- return (hAsync("label", { key: 'fe56ffe876ccc859536ca74703e0870ad97e1668', class: this.toggleClasses, style: cssVars, "aria-label": this.label || 'toggle' }, this.label, hAsync("input", { key: 'f473fd71c03d0e4e3e8fb354753d769033f148f2', style: { display: 'none' }, type: "checkbox", onInput: this.handleChange })));
18222
+ return (hAsync("label", { key: 'e9bb126d92605cdd3a88ff1840aa79a4b66c7cf8', class: this.toggleClasses, style: cssVars, "aria-label": this.label || 'toggle' }, this.label, hAsync("input", { key: '41c18a29c10ae91b84ecd6d2619a40ab99f5d151', style: { display: 'none' }, type: "checkbox", onInput: this.handleChange })));
17917
18223
  }
17918
18224
  static get style() { return sdToggleCss(); }
17919
18225
  static get cmpMeta() { return {
@@ -18040,14 +18346,14 @@ class SdTooltip {
18040
18346
  const toggleTooltip = () => (this.showTooltip = !this.showTooltip);
18041
18347
  const divTrigger = trigger === 'hover' ? hoverTrigger : this.label ? {} : { onClick: toggleTooltip };
18042
18348
  const buttonClickTrigger = trigger === 'click' && this.label ? { onSdClick: toggleTooltip } : {};
18043
- return (hAsync(Fragment, { key: 'e0211f8c80222e357d278c81582baf40ef47a8a6' }, hAsync("div", { key: '9747aa6130dbf0d7e29bbe2d7222c22c8001c6a5', class: `sd-tooltip-trigger ${this.sdClass || ''}`, ...divTrigger }, this.label ? (hAsync("sd-button", { ref: el => (this.buttonEl = el), label: this.label, icon: icon, size: this.buttonSize ?? 'sm', color: color, variant: this.buttonVariant ?? 'primary', class: "sd-tooltip", ...buttonClickTrigger })) : (hAsync("sd-icon", { ref: el => (this.buttonEl = el), name: icon, size: this.iconSize ?? 12, color: color, class: "sd-tooltip" }))), this.showTooltip && (hAsync("sd-floating-portal", { key: '7f3e8e2758ef78ca1765bd7e4ec8d6849698ff88', parentRef: this.buttonEl, onSdClose: this.handleClose.bind(this), placement: placement, offset: this.tooltipOffset }, hAsync("div", { key: '86a3a006bdcee86f16da7ebea04ff267a7f029b9', ref: el => (this.menuEl = el), class: {
18349
+ return (hAsync(Fragment, { key: 'b5368ef5aced50890707aeb99c82de5784e7acf1' }, hAsync("div", { key: 'aeac6276d7e36e315093770d03671d83b339137a', class: `sd-tooltip-trigger ${this.sdClass || ''}`, ...divTrigger }, this.label ? (hAsync("sd-button", { ref: el => (this.buttonEl = el), label: this.label, icon: icon, size: this.buttonSize ?? 'sm', color: color, variant: this.buttonVariant ?? 'primary', class: "sd-tooltip", ...buttonClickTrigger })) : (hAsync("sd-icon", { ref: el => (this.buttonEl = el), name: icon, size: this.iconSize ?? 12, color: color, class: "sd-tooltip" }))), this.showTooltip && (hAsync("sd-floating-portal", { key: '7e24c9f16d326f787a7441753ae138e08ebe3f78', parentRef: this.buttonEl, onSdClose: this.handleClose.bind(this), placement: placement, offset: this.tooltipOffset }, hAsync("div", { key: '4681dfcb409ec7b072be6bf82bd42c5ebce29100', ref: el => (this.menuEl = el), class: {
18044
18350
  'sd-floating-menu': true,
18045
18351
  [`sd-floating-menu--${tooltipType}`]: true,
18046
18352
  [`sd-floating-menu--${placement}`]: true,
18047
18353
  }, style: {
18048
18354
  '--sd-floating-bg': typeConfig.bg,
18049
18355
  '--sd-floating-content': typeConfig.content,
18050
- }, onMouseEnter: () => this.show(), onMouseLeave: () => this.startHideTimer() }, hAsync("i", { key: '50268080023fc252774a7fb564bdbf6c007c115e', class: `sd-floating-menu__arrow sd-floating-menu__arrow--${placement}` }, hAsync(TooltipArrow, { key: '28b2948d9570157c6c40e7738498266ca8c8ec64' })), hAsync("div", { key: 'e2057da013a2700e8614f1e8d8e5164aec8efb18', class: "sd-floating-menu__content", innerHTML: this.slotContentHTML }))))));
18356
+ }, onMouseEnter: () => this.show(), onMouseLeave: () => this.startHideTimer() }, hAsync("i", { key: 'e74368ffeabb85d4d4257e4695b1979c8f63495d', class: `sd-floating-menu__arrow sd-floating-menu__arrow--${placement}` }, hAsync(TooltipArrow, { key: 'e4f5b3031eb0cabcadf9fd0f564f6adf4515c14f' })), hAsync("div", { key: '3399759f60874f2f8a5ebf3e2c618dab94289aec', class: "sd-floating-menu__content", innerHTML: this.slotContentHTML }))))));
18051
18357
  }
18052
18358
  static get style() { return sdTooltipCss(); }
18053
18359
  static get cmpMeta() { return {
@@ -18074,7 +18380,7 @@ class SdTooltip {
18074
18380
  }; }
18075
18381
  }
18076
18382
 
18077
- const sdTrCss = () => `sd-tr{display:contents}sd-tr *{box-sizing:border-box}.tr{display:table-row}.tr:hover .td{background-color:#F9F9F9}.td{display:table-cell;height:44px;padding:0 16px;border-bottom:1px solid #E1E1E1;background:white;vertical-align:middle;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.td--left{text-align:left}.td--center{text-align:center}.td--right{text-align:right}.td--selected{position:relative;width:52px !important;max-width:52px !important;min-width:52px !important;padding:0 10px 0 24px;text-align:left}.td--selected sd-checkbox label{position:relative}.td--selected sd-checkbox label:before{content:"";position:absolute;inset:-6px}.td.sticky-left{position:sticky;background-color:white;z-index:100 !important;left:var(--sticky-left-offset, 0)}.td.sticky-right{position:sticky;background-color:white;z-index:100 !important;right:var(--sticky-right-offset, 0)}.td.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}.td.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}.td.sticky-left-edge.is-scrolled-left{overflow:visible}.td.sticky-left-edge.is-scrolled-left:after{opacity:1}.td.sticky-right-edge.is-scrolled-right{overflow:visible}.td.sticky-right-edge.is-scrolled-right:after{opacity:1}.tr:hover .td.sticky-left,.tr:hover .td.sticky-right{background-color:#F9F9F9}`;
18383
+ const sdTrCss = () => `sd-tr{display:contents}sd-tr *{box-sizing:border-box}.tr{display:table-row}.tr:hover .td{background-color:#F9F9F9}.tr--no-hover:hover .td{background-color:white}.td{display:table-cell;height:44px;padding:0 16px;border-bottom:1px solid #E1E1E1;background:white;vertical-align:middle;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.td--left{text-align:left}.td--center{text-align:center}.td--right{text-align:right}.td--selected{position:relative;width:52px !important;max-width:52px !important;min-width:52px !important;padding:0 10px 0 24px;text-align:left}.td--selected sd-checkbox label{position:relative}.td--selected sd-checkbox label:before{content:"";position:absolute;inset:-6px}.td.sticky-left{position:sticky;background-color:white;z-index:100 !important;left:var(--sticky-left-offset, 0)}.td.sticky-right{position:sticky;background-color:white;z-index:100 !important;right:var(--sticky-right-offset, 0)}.td.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}.td.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}.td.sticky-left-edge.is-scrolled-left{overflow:visible}.td.sticky-left-edge.is-scrolled-left:after{opacity:1}.td.sticky-right-edge.is-scrolled-right{overflow:visible}.td.sticky-right-edge.is-scrolled-right:after{opacity:1}.tr:hover .td.sticky-left,.tr:hover .td.sticky-right{background-color:#F9F9F9}.tr--no-hover:hover .td.sticky-left,.tr--no-hover:hover .td.sticky-right{background-color:white}`;
18078
18384
 
18079
18385
  class SdTr {
18080
18386
  constructor(hostRef) {
@@ -18089,6 +18395,7 @@ class SdTr {
18089
18395
  tableId = '';
18090
18396
  columnWidths = [];
18091
18397
  isVisible = true;
18398
+ spansVersion = 0;
18092
18399
  _columns = [];
18093
18400
  _selectable = false;
18094
18401
  _stickyColumn = { left: 0, right: 0 };
@@ -18106,7 +18413,12 @@ class SdTr {
18106
18413
  this.syncTableContext();
18107
18414
  }
18108
18415
  syncTableContext() {
18109
- const table = this.el.closest('sd-table');
18416
+ // sd-table shadow:true이므로 fallback content로 렌더되면 closest가 경계를 못 넘는다.
18417
+ // 그 경우 getRootNode().host(=sd-table)로 폴백한다.
18418
+ const closest = this.el.closest('sd-table');
18419
+ const root = this.el.getRootNode();
18420
+ const fromShadow = root instanceof ShadowRoot ? root.host : null;
18421
+ const table = closest ?? fromShadow;
18110
18422
  this.tableEl = table;
18111
18423
  const fromMethod = table?.getTableIdSync?.();
18112
18424
  const fromAttr = table?.getAttribute(TABLE_ID_ATTR);
@@ -18131,6 +18443,9 @@ class SdTr {
18131
18443
  async refreshConfig() {
18132
18444
  this.resolveConfig();
18133
18445
  }
18446
+ async bumpSpansVersion() {
18447
+ this.spansVersion = this.spansVersion + 1;
18448
+ }
18134
18449
  async updateVisibility() {
18135
18450
  this.updateVisibilitySync();
18136
18451
  }
@@ -18196,37 +18511,60 @@ class SdTr {
18196
18511
  this.tableEl.updateRowSelectSync(this.row);
18197
18512
  }
18198
18513
  }
18514
+ getSpanFor(col) {
18515
+ if (!this.tableEl?.getSpanSync)
18516
+ return undefined;
18517
+ const fieldName = typeof col.field === 'string' ? col.field : col.name;
18518
+ return this.tableEl.getSpanSync(this.rowKey, fieldName);
18519
+ }
18520
+ isCovered(colIdx) {
18521
+ if (!this.tableEl?.isCoveredSync)
18522
+ return false;
18523
+ return this.tableEl.isCoveredSync(this.rowKey, colIdx, this._columns);
18524
+ }
18199
18525
  render() {
18200
18526
  const stickyLeftCount = this._stickyColumn.left || 0;
18201
18527
  const stickyRightCount = this._stickyColumn.right || 0;
18202
18528
  const stickyLeftCols = this.visibleColumns.slice(0, stickyLeftCount);
18203
18529
  const middleCols = this.visibleColumns.slice(stickyLeftCount, this.visibleColumns.length - stickyRightCount);
18204
18530
  const stickyRightCols = this.visibleColumns.slice(this.visibleColumns.length - stickyRightCount);
18205
- return (hAsync(Host, { key: 'd6259e5c87cce0fa70f1d849e11416ad69b0cac1', style: { display: this.isVisible ? '' : 'none' } }, hAsync("tr", { key: '90e36c39bede0e07fc1c4d90183a73ebc99b6ed8', class: "tr" }, this._selectable && (hAsync("td", { key: '601f1747063d8e73803304abc2cd767f420f359c', class: {
18531
+ const hasRowspan = this.tableEl?.hasRowspanSync?.() ?? false;
18532
+ return (hAsync(Host, { key: 'e8d387043d3384daffb5d548176b469a91264225', style: { display: this.isVisible ? '' : 'none' } }, hAsync("tr", { key: '1d579819497a6186941b0c80c916a83c48dfcc0d', class: { 'tr': true, 'tr--no-hover': hasRowspan } }, this._selectable && (hAsync("td", { key: '1a8ab44a8c65926eb9a7bd9e9224d0eed55ecfb1', class: {
18206
18533
  'td': true,
18207
18534
  'td--selected': true,
18208
18535
  'sticky-left': true,
18209
18536
  'sticky-left-edge': stickyLeftCount === 0,
18210
18537
  'is-scrolled-left': stickyLeftCount === 0 && this._scrolledLeft,
18211
- }, style: { '--sticky-left-offset': '0px' } }, hAsync("sd-checkbox", { key: '97068a623d3b7876c7e6392e3f5ed81cfc60d592', value: this.isSelected(), onSdUpdate: () => this.handleSelect() }))), stickyLeftCols.map((col, idx) => (hAsync("td", { key: col.name, class: {
18212
- 'td': true,
18213
- [`td--${col.align || 'left'}`]: true,
18214
- 'sticky-left': true,
18215
- 'sticky-left-edge': idx === stickyLeftCount - 1,
18216
- 'is-scrolled-left': idx === stickyLeftCount - 1 && this._scrolledLeft,
18217
- [`${col.tdClass}`]: Boolean(col.tdClass),
18218
- }, style: this.getStickyStyle(idx) }, hAsync("slot", { name: `${this.tableId}-${typeof col.field === 'string' ? col.field : col.name}-${this.rowKey}` }, hAsync("span", null, this.getCellValue(col)))))), middleCols.map((col, relativeIdx) => {
18538
+ }, style: { '--sticky-left-offset': '0px' } }, hAsync("sd-checkbox", { key: '72bdbadc76dcb0682eb4de496e9abda692a0ea7e', value: this.isSelected(), onSdUpdate: () => this.handleSelect() }))), stickyLeftCols.map((col, idx) => {
18539
+ if (this.isCovered(idx))
18540
+ return null;
18541
+ const span = this.getSpanFor(col);
18542
+ return (hAsync("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
18543
+ 'td': true,
18544
+ [`td--${col.align || 'left'}`]: true,
18545
+ 'sticky-left': true,
18546
+ 'sticky-left-edge': idx === stickyLeftCount - 1,
18547
+ 'is-scrolled-left': idx === stickyLeftCount - 1 && this._scrolledLeft,
18548
+ [`${col.tdClass}`]: Boolean(col.tdClass),
18549
+ }, style: this.getStickyStyle(idx) }, hAsync("slot", { name: `${this.tableId}-${typeof col.field === 'string' ? col.field : col.name}-${this.rowKey}` }, hAsync("span", null, this.getCellValue(col)))));
18550
+ }), middleCols.map((col, relativeIdx) => {
18219
18551
  const actualColIdx = stickyLeftCount + relativeIdx;
18552
+ if (this.isCovered(actualColIdx))
18553
+ return null;
18220
18554
  const fieldName = typeof col.field === 'string' ? col.field : col.name;
18221
- return (hAsync("td", { key: col.name, class: {
18555
+ const span = this.getSpanFor(col);
18556
+ return (hAsync("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
18222
18557
  td: true,
18223
18558
  [`td--${col.align || 'left'}`]: true,
18224
18559
  [`${col.tdClass}`]: Boolean(col.tdClass),
18225
18560
  }, style: this.getStickyStyle(actualColIdx) }, hAsync("slot", { name: `${this.tableId}-${fieldName}-${this.rowKey}` }, hAsync("span", null, this.getCellValue(col)))));
18226
18561
  }), stickyRightCols.map((col, relativeIdx) => {
18227
18562
  const actualColIdx = this.visibleColumns.length - stickyRightCount + relativeIdx;
18563
+ if (this.isCovered(actualColIdx))
18564
+ return null;
18228
18565
  const fieldName = typeof col.field === 'string' ? col.field : col.name;
18229
- return (hAsync("td", { key: col.name, class: {
18566
+ const span = this.getSpanFor(col);
18567
+ return (hAsync("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
18230
18568
  'td': true,
18231
18569
  [`td--${col.align || 'left'}`]: true,
18232
18570
  'sticky-right': true,
@@ -18249,12 +18587,14 @@ class SdTr {
18249
18587
  "tableId": [32],
18250
18588
  "columnWidths": [32],
18251
18589
  "isVisible": [32],
18590
+ "spansVersion": [32],
18252
18591
  "_columns": [32],
18253
18592
  "_selectable": [32],
18254
18593
  "_stickyColumn": [32],
18255
18594
  "_scrolledLeft": [32],
18256
18595
  "_scrolledRight": [32],
18257
18596
  "refreshConfig": [64],
18597
+ "bumpSpansVersion": [64],
18258
18598
  "updateVisibility": [64],
18259
18599
  "setColumnWidths": [64],
18260
18600
  "refreshSelection": [64]