@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.js CHANGED
@@ -9869,6 +9869,11 @@ class SdGhostButton {
9869
9869
  disabled = false;
9870
9870
  click;
9871
9871
  hasWarnedMissingAriaLabel = false;
9872
+ componentWillLoad() {
9873
+ this.size ??= 'sm';
9874
+ this.intent ??= 'default';
9875
+ this.ariaLabel ??= '';
9876
+ }
9872
9877
  handleClick = (event) => {
9873
9878
  if (this.disabled) {
9874
9879
  event.preventDefault();
@@ -9893,19 +9898,19 @@ class SdGhostButton {
9893
9898
  render() {
9894
9899
  const sizeConfig = GHOST_BUTTON_SIZES[this.size];
9895
9900
  const contentColor = this.disabled
9896
- ? GHOST_BUTTON_DISABLED_COLORS[this.intent ?? 'default']
9897
- : GHOST_BUTTON_CONTENT_COLORS[this.intent ?? 'default'];
9901
+ ? GHOST_BUTTON_DISABLED_COLORS[this.intent]
9902
+ : GHOST_BUTTON_CONTENT_COLORS[this.intent];
9898
9903
  const accessibleName = this.ariaLabel.trim() || undefined;
9899
- return (hAsync("button", { key: '34c5026b4819b624b19d1773bad413b689633c2a', class: {
9904
+ return (hAsync("button", { key: 'd7f6fcbed3526ffb8b90b205dbe2bbf55abf03a0', class: {
9900
9905
  'sd-ghost-button': true,
9901
9906
  'sd-ghost-button--disabled': this.disabled,
9902
9907
  }, type: "button", disabled: this.disabled, "aria-label": accessibleName, style: {
9903
9908
  '--sd-ghost-button-size': `${sizeConfig.size}px`,
9904
9909
  '--sd-ghost-button-radius': `${GHOST_BUTTON_RADIUS[this.size]}px`,
9905
- '--sd-ghost-button-hover-bg': GHOST_BUTTON_HOVER_BG_COLORS[this.intent ?? 'default'],
9910
+ '--sd-ghost-button-hover-bg': GHOST_BUTTON_HOVER_BG_COLORS[this.intent],
9906
9911
  '--sd-ghost-button-hover-opacity': GHOST_BUTTON_HOVER_OPACITY,
9907
9912
  '--sd-ghost-button-accent': GHOST_BUTTON_FOCUS_RING_COLOR,
9908
- }, onClick: this.handleClick }, hAsync("sd-icon", { key: '063f7cfabfdbf0f4f2f4c1a2c811e6c3734d941f', name: this.icon, size: sizeConfig.icon, color: contentColor })));
9913
+ }, onClick: this.handleClick }, hAsync("sd-icon", { key: '9efc3a3fbf7878a9a50b2efbf054b335d9cddfe0', name: this.icon, size: sizeConfig.icon, color: contentColor })));
9909
9914
  }
9910
9915
  static get style() { return sdGhostButtonCss(); }
9911
9916
  static get cmpMeta() { return {
@@ -11061,7 +11066,7 @@ class SdLoadingModal {
11061
11066
  '--sd-loading-modal-width': this.toCssSize(this.width) ?? `${LOADING_MODAL_LAYOUT.minWidth}px`,
11062
11067
  '--sd-loading-modal-height': this.toCssSize(this.height) ?? `${LOADING_MODAL_LAYOUT.minHeight}px`,
11063
11068
  };
11064
- 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 }))))));
11069
+ 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 }))))));
11065
11070
  }
11066
11071
  static get style() { return sdLoadingModalCss(); }
11067
11072
  static get cmpMeta() { return {
@@ -11189,10 +11194,8 @@ class SdModalContainer {
11189
11194
  }
11190
11195
  get el() { return getElement(this); }
11191
11196
  autoRemove = false;
11192
- entry;
11193
- isVisible = false;
11194
- backdropVisible = false;
11195
- layerRef;
11197
+ entries = [];
11198
+ layerRefs = new Map();
11196
11199
  async open(options, modalRef) {
11197
11200
  const id = `modal-${++modalIdCounter}`;
11198
11201
  const modalEl = this.createConfirmModal(id, options);
@@ -11203,6 +11206,7 @@ class SdModalContainer {
11203
11206
  modalRef,
11204
11207
  persistent: !!options.persistent,
11205
11208
  closing: false,
11209
+ backdropVisible: false,
11206
11210
  });
11207
11211
  return id;
11208
11212
  }
@@ -11216,6 +11220,7 @@ class SdModalContainer {
11216
11220
  modalRef,
11217
11221
  persistent: !!options.persistent,
11218
11222
  closing: false,
11223
+ backdropVisible: false,
11219
11224
  });
11220
11225
  return id;
11221
11226
  }
@@ -11230,91 +11235,93 @@ class SdModalContainer {
11230
11235
  modalRef,
11231
11236
  persistent: !!options.persistent,
11232
11237
  closing: false,
11238
+ backdropVisible: false,
11233
11239
  });
11234
11240
  return id;
11235
11241
  }
11236
11242
  componentDidRender() {
11237
- if (!this.entry || this.entry.closing || !this.layerRef)
11243
+ if (!Array.isArray(this.entries))
11238
11244
  return;
11239
- if (this.entry.modalEl.isConnected)
11240
- return;
11241
- const { id, modalEl } = this.entry;
11242
- this.layerRef.appendChild(modalEl);
11243
- this.waitForModalReady(modalEl).then(() => {
11244
- requestAnimationFrame(() => {
11245
- if (!this.entry || this.entry.id !== id || this.entry.closing || !modalEl.isConnected)
11246
- return;
11247
- this.backdropVisible = true;
11248
- modalEl.classList.add('sd-modal-container__modal--visible');
11245
+ for (const entry of this.entries) {
11246
+ if (entry.closing || entry.modalEl.isConnected)
11247
+ continue;
11248
+ const layerRef = this.layerRefs.get(entry.id);
11249
+ if (!layerRef)
11250
+ continue;
11251
+ const { id, modalEl } = entry;
11252
+ layerRef.appendChild(modalEl);
11253
+ this.waitForModalReady(modalEl).then(() => {
11254
+ requestAnimationFrame(() => {
11255
+ const current = this.entries.find(e => e.id === id);
11256
+ if (!current || current.closing || !modalEl.isConnected)
11257
+ return;
11258
+ this.entries = this.entries.map(e => e.id === id ? { ...e, backdropVisible: true } : e);
11259
+ modalEl.classList.add('sd-modal-container__modal--visible');
11260
+ });
11249
11261
  });
11250
- });
11262
+ }
11251
11263
  }
11252
11264
  disconnectedCallback() {
11253
- if (this.entry?.dismissTimerId)
11254
- clearTimeout(this.entry.dismissTimerId);
11255
- if (this.entry)
11256
- unregisterModal(this.entry.id);
11265
+ for (const entry of this.entries ?? []) {
11266
+ if (entry.dismissTimerId)
11267
+ clearTimeout(entry.dismissTimerId);
11268
+ unregisterModal(entry.id);
11269
+ }
11257
11270
  }
11258
11271
  async dismissById(id, reason) {
11259
- if (this.entry?.id !== id)
11272
+ const entry = this.entries.find(e => e.id === id);
11273
+ if (!entry)
11260
11274
  return;
11261
- this.requestDismiss(reason);
11275
+ this.requestDismiss(id, reason);
11262
11276
  }
11263
11277
  async update(id, props) {
11264
- if (!this.entry || this.entry.id !== id || this.entry.closing)
11278
+ const entry = this.entries.find(e => e.id === id && !e.closing);
11279
+ if (!entry)
11265
11280
  return;
11266
- const tag = this.entry.modalEl.tagName.toLowerCase();
11281
+ const tag = entry.modalEl.tagName.toLowerCase();
11267
11282
  if (tag === 'sd-loading-modal') {
11268
- this.applyLoadingProps(this.entry.modalEl, props);
11283
+ this.applyLoadingProps(entry.modalEl, props);
11269
11284
  return;
11270
11285
  }
11271
- this.applyProps(this.entry.modalEl, props);
11286
+ this.applyProps(entry.modalEl, props);
11272
11287
  }
11273
11288
  mountEntry(entry) {
11274
- if (this.entry) {
11275
- throw new Error('[sd-modal-container] This instance already manages an active modal.');
11276
- }
11277
- this.entry = entry;
11278
- this.backdropVisible = false;
11279
- this.isVisible = true;
11289
+ this.entries = [...(this.entries ?? []), entry];
11280
11290
  registerModal({
11281
11291
  id: entry.id,
11282
11292
  persistent: entry.persistent,
11283
- requestClose: () => this.dispatchClose(),
11293
+ requestClose: () => this.dispatchClose(entry.id),
11284
11294
  shake: () => this.shakeModal(entry.modalEl),
11285
11295
  setZIndex: zIndex => {
11286
11296
  this.el.style.setProperty('--sd-modal-container-z-index', String(zIndex));
11287
11297
  },
11288
11298
  });
11289
11299
  }
11290
- attachModalEventListeners(_id, modalEl) {
11291
- modalEl.addEventListener('sdOk', () => this.requestDismiss('confirm'));
11292
- modalEl.addEventListener('sdCancel', () => this.requestDismiss('cancel'));
11293
- modalEl.addEventListener('sdClose', () => this.requestDismiss('close'));
11300
+ attachModalEventListeners(id, modalEl) {
11301
+ modalEl.addEventListener('sdOk', () => this.requestDismiss(id, 'confirm'));
11302
+ modalEl.addEventListener('sdCancel', () => this.requestDismiss(id, 'cancel'));
11303
+ modalEl.addEventListener('sdClose', () => this.requestDismiss(id, 'close'));
11294
11304
  }
11295
- attachLoadingModalEventListeners(_id, modalEl) {
11305
+ attachLoadingModalEventListeners(id, modalEl) {
11296
11306
  modalEl.addEventListener('sdClick', () => {
11297
- this.entry?.modalRef._triggerClick?.();
11307
+ const entry = this.entries.find(e => e.id === id);
11308
+ entry?.modalRef._triggerClick?.();
11298
11309
  });
11299
11310
  }
11300
- dispatchClose() {
11301
- this.entry?.modalEl.dispatchEvent(new CustomEvent('sdClose'));
11311
+ dispatchClose(id) {
11312
+ const entry = this.entries.find(e => e.id === id);
11313
+ entry?.modalEl.dispatchEvent(new CustomEvent('sdClose'));
11302
11314
  }
11303
- requestDismiss(reason) {
11304
- const currentEntry = this.entry;
11315
+ requestDismiss(id, reason) {
11316
+ const currentEntry = this.entries.find(e => e.id === id);
11305
11317
  if (!currentEntry || currentEntry.closing)
11306
11318
  return;
11307
11319
  currentEntry.modalEl.classList.remove('sd-modal-container__modal--visible');
11308
11320
  const dismissTimerId = setTimeout(() => {
11309
- this.finalizeDismiss(currentEntry.id);
11321
+ this.finalizeDismiss(id);
11310
11322
  }, ANIMATION_DURATION);
11311
- setModalInteractive(currentEntry.id, false);
11312
- this.entry = {
11313
- ...currentEntry,
11314
- closing: true,
11315
- dismissTimerId,
11316
- };
11317
- this.backdropVisible = false;
11323
+ setModalInteractive(id, false);
11324
+ this.entries = (this.entries ?? []).map(e => e.id === id ? { ...e, closing: true, dismissTimerId, backdropVisible: false } : e);
11318
11325
  if (reason === 'confirm')
11319
11326
  currentEntry.modalRef._triggerOk();
11320
11327
  else if (reason === 'cancel')
@@ -11323,18 +11330,17 @@ class SdModalContainer {
11323
11330
  currentEntry.modalRef._triggerClose();
11324
11331
  }
11325
11332
  finalizeDismiss(id) {
11326
- const currentEntry = this.entry;
11327
- if (!currentEntry || currentEntry.id !== id)
11333
+ const currentEntry = this.entries.find(e => e.id === id);
11334
+ if (!currentEntry)
11328
11335
  return;
11329
11336
  if (currentEntry.dismissTimerId)
11330
11337
  clearTimeout(currentEntry.dismissTimerId);
11331
11338
  currentEntry.modalEl.remove();
11332
11339
  unregisterModal(id);
11333
11340
  currentEntry.modalRef._triggerDismissed();
11334
- this.entry = undefined;
11335
- this.backdropVisible = false;
11336
- this.isVisible = false;
11337
- if (this.autoRemove) {
11341
+ this.layerRefs.delete(id);
11342
+ this.entries = (this.entries ?? []).filter(e => e.id !== id);
11343
+ if (this.autoRemove && this.entries.length === 0) {
11338
11344
  this.el.remove();
11339
11345
  }
11340
11346
  }
@@ -11355,8 +11361,14 @@ class SdModalContainer {
11355
11361
  applyLoadingProps(el, options) {
11356
11362
  if (this.hasOwnProp(options, 'state'))
11357
11363
  this.setAttr(el, 'state', options.state);
11358
- if (this.hasOwnProp(options, 'message'))
11359
- this.setAttr(el, 'message', options.message);
11364
+ if (this.hasOwnProp(options, 'message')) {
11365
+ if (Array.isArray(options.message)) {
11366
+ el.message = options.message;
11367
+ }
11368
+ else {
11369
+ this.setAttr(el, 'message', options.message);
11370
+ }
11371
+ }
11360
11372
  if (this.hasOwnProp(options, 'useButton')) {
11361
11373
  if (options.useButton)
11362
11374
  el.setAttribute('use-button', '');
@@ -11402,11 +11414,11 @@ class SdModalContainer {
11402
11414
  if (this.hasOwnProp(options, 'tagContents'))
11403
11415
  el.tagContents = options.tagContents;
11404
11416
  }
11405
- handleBackdropClick = () => {
11406
- if (!this.entry || !isTopInteractiveModal(this.entry.id))
11417
+ handleBackdropClick(id) {
11418
+ if (!isTopInteractiveModal(id))
11407
11419
  return;
11408
- requestCloseForModal(this.entry.id);
11409
- };
11420
+ requestCloseForModal(id);
11421
+ }
11410
11422
  shakeModal(modalEl) {
11411
11423
  const cls = 'sd-modal-container__modal--shake';
11412
11424
  modalEl.classList.remove(cls);
@@ -11435,14 +11447,15 @@ class SdModalContainer {
11435
11447
  el.setAttribute(name, value);
11436
11448
  }
11437
11449
  render() {
11438
- if (!this.isVisible || !this.entry)
11450
+ if (!this.entries?.length)
11439
11451
  return null;
11440
- return (hAsync("div", { class: "sd-modal-container" }, hAsync("div", { class: "sd-modal-container__layer", "data-modal-id": this.entry.id, ref: el => {
11441
- this.layerRef = el;
11452
+ 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 => {
11453
+ if (el)
11454
+ this.layerRefs.set(entry.id, el);
11442
11455
  } }, hAsync("div", { class: {
11443
11456
  'sd-modal-container__backdrop': true,
11444
- 'sd-modal-container__backdrop--visible': this.backdropVisible,
11445
- }, onClick: this.handleBackdropClick }))));
11457
+ 'sd-modal-container__backdrop--visible': entry.backdropVisible,
11458
+ }, onClick: () => this.handleBackdropClick(entry.id) }))))));
11446
11459
  }
11447
11460
  static get style() { return sdModalContainerCss(); }
11448
11461
  static get cmpMeta() { return {
@@ -11450,9 +11463,7 @@ class SdModalContainer {
11450
11463
  "$tagName$": "sd-modal-container",
11451
11464
  "$members$": {
11452
11465
  "autoRemove": [4, "auto-remove"],
11453
- "entry": [32],
11454
- "isVisible": [32],
11455
- "backdropVisible": [32],
11466
+ "entries": [32],
11456
11467
  "open": [64],
11457
11468
  "openLoading": [64],
11458
11469
  "createCustom": [64],
@@ -12746,6 +12757,11 @@ class SdRadioButton {
12746
12757
  disabled = false;
12747
12758
  name;
12748
12759
  change;
12760
+ componentWillLoad() {
12761
+ this.size ??= 'sm';
12762
+ this.options ??= [];
12763
+ this.disabled ??= false;
12764
+ }
12749
12765
  handleRadioChange = (optionValue, optionDisabled) => {
12750
12766
  if (this.disabled || optionDisabled)
12751
12767
  return;
@@ -12806,7 +12822,7 @@ class SdRadioButton {
12806
12822
  '--sd-radio-button-content-select': RADIO_BUTTON_COLORS.content.select,
12807
12823
  '--sd-radio-button-content-disabled': RADIO_BUTTON_COLORS.content.disabled,
12808
12824
  };
12809
- return (hAsync("div", { key: '67c8e7ad03fb6ee4cabd06591e3e11e5d38914f0', class: this.getGroupClasses(), style: cssVars, role: "radiogroup", "aria-disabled": this.disabled.toString() }, this.options.map(option => {
12825
+ return (hAsync("div", { key: 'fbc0246d9cf615956121295e29bf8c702ee73edc', class: this.getGroupClasses(), style: cssVars, role: "radiogroup", "aria-disabled": this.disabled.toString() }, this.options.map(option => {
12810
12826
  const isSelected = this.isOptionSelected(option);
12811
12827
  const isDisabled = this.isOptionDisabled(option);
12812
12828
  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)));
@@ -14649,6 +14665,9 @@ class SdSelectV2 {
14649
14665
  labelTooltipProps = null;
14650
14666
  emitValue = false;
14651
14667
  width = '';
14668
+ useSearch = false;
14669
+ allSelectedLabel = '전체';
14670
+ useSelectAll = false;
14652
14671
  isOpen = false;
14653
14672
  isAnimatingOut = false;
14654
14673
  triggerWidth = '200px';
@@ -14690,6 +14709,12 @@ class SdSelectV2 {
14690
14709
  if (this.isMulti) {
14691
14710
  if (!Array.isArray(this.value) || this.value.length === 0)
14692
14711
  return '';
14712
+ const nonDisabledLeaves = this.getNonDisabledLeaves(this.options);
14713
+ const selected = this.getSelectedOptions();
14714
+ const allSelected = nonDisabledLeaves.length > 0 &&
14715
+ nonDisabledLeaves.every(leaf => selected.some(s => s.value === leaf.value));
14716
+ if (allSelected)
14717
+ return this.allSelectedLabel ?? '전체';
14693
14718
  const flat = this.flattenOptions(this.options);
14694
14719
  return this.value
14695
14720
  .map(item => {
@@ -14714,6 +14739,15 @@ class SdSelectV2 {
14714
14739
  flattenOptions(options) {
14715
14740
  return options.flatMap(o => (o.children ? this.flattenOptions(o.children) : [o]));
14716
14741
  }
14742
+ getNonDisabledLeaves(options) {
14743
+ return options.flatMap(o => {
14744
+ if (o.disabled)
14745
+ return [];
14746
+ if (o.children)
14747
+ return this.getNonDisabledLeaves(o.children);
14748
+ return [o];
14749
+ });
14750
+ }
14717
14751
  getSelectedOptions() {
14718
14752
  const val = this.value;
14719
14753
  if (!val || !Array.isArray(val))
@@ -14860,15 +14894,15 @@ class SdSelectV2 {
14860
14894
  this.closeDropdown();
14861
14895
  },
14862
14896
  };
14863
- 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: () => {
14897
+ 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: () => {
14864
14898
  this.hovered = true;
14865
14899
  }, onMouseLeave: () => {
14866
14900
  this.hovered = false;
14867
- } }, hAsync("div", { key: 'dba3a313b7e0171a441540877aacdc7d5c2e7f04', class: "sd-select-v2", ref: el => {
14901
+ } }, hAsync("div", { key: '42fa82a3c53804d9f90aadb0465d52fd9f4e446e', class: "sd-select-v2", ref: el => {
14868
14902
  this.triggerRef = el;
14869
- } }, hAsync("sd-select-v2-trigger", { key: '7790357558f174eb70b15ed72574f738b062c479', ref: el => {
14903
+ } }, hAsync("sd-select-v2-trigger", { key: 'c97ae1e67019b099eee72f829d554b9e0350af30', ref: el => {
14870
14904
  this.triggerComponentRef = el;
14871
- }, 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) })))));
14905
+ }, 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) })))));
14872
14906
  }
14873
14907
  static get watchers() { return {
14874
14908
  "isOpen": [{
@@ -14900,6 +14934,9 @@ class SdSelectV2 {
14900
14934
  "labelTooltipProps": [16],
14901
14935
  "emitValue": [4, "emit-value"],
14902
14936
  "width": [8],
14937
+ "useSearch": [4, "use-search"],
14938
+ "allSelectedLabel": [1, "all-selected-label"],
14939
+ "useSelectAll": [4, "use-select-all"],
14903
14940
  "name": [1],
14904
14941
  "isOpen": [32],
14905
14942
  "isAnimatingOut": [32],
@@ -15267,6 +15304,8 @@ class SdSelectV2Listbox {
15267
15304
  options = [];
15268
15305
  value = null;
15269
15306
  emitValue = false;
15307
+ useSearch = false;
15308
+ useSelectAll = false;
15270
15309
  triggerWidth = '200px';
15271
15310
  maxWidth = '640px';
15272
15311
  maxHeight = '260px';
@@ -15284,7 +15323,40 @@ class SdSelectV2Listbox {
15284
15323
  get isMulti() {
15285
15324
  return this.type === 'multi' || this.type === 'multi_depth';
15286
15325
  }
15326
+ static SELECT_ALL_OPTION = {
15327
+ value: '__select_all__',
15328
+ label: '전체',
15329
+ };
15330
+ get showSelectAll() {
15331
+ return this.useSelectAll && this.isMulti;
15332
+ }
15333
+ getAllNonDisabledLeaves() {
15334
+ const collect = (opts) => opts.flatMap(o => {
15335
+ if (o.disabled)
15336
+ return [];
15337
+ if (o.children)
15338
+ return collect(o.children);
15339
+ return [o];
15340
+ });
15341
+ return collect(this.options);
15342
+ }
15343
+ get selectAllState() {
15344
+ if (!this.showSelectAll)
15345
+ return false;
15346
+ const allLeaves = this.getAllNonDisabledLeaves();
15347
+ if (allLeaves.length === 0)
15348
+ return false;
15349
+ const selectedValues = this.getSelectedValues();
15350
+ const selectedCount = allLeaves.filter(l => selectedValues.has(l.value)).length;
15351
+ if (selectedCount === 0)
15352
+ return false;
15353
+ if (selectedCount === allLeaves.length)
15354
+ return true;
15355
+ return null;
15356
+ }
15287
15357
  get showSearch() {
15358
+ if (!this.useSearch)
15359
+ return false;
15288
15360
  const count = this.isDepth ? countLeaves(this.options) : this.options.length;
15289
15361
  return count >= SEARCH_THRESHOLD;
15290
15362
  }
@@ -15386,6 +15458,9 @@ class SdSelectV2Listbox {
15386
15458
  }
15387
15459
  get navigableOptions() {
15388
15460
  const items = [];
15461
+ if (this.showSelectAll) {
15462
+ items.push(SdSelectV2Listbox.SELECT_ALL_OPTION);
15463
+ }
15389
15464
  const walk = (opts) => {
15390
15465
  for (const opt of opts) {
15391
15466
  const isGroup = !!opt.children;
@@ -15399,6 +15474,22 @@ class SdSelectV2Listbox {
15399
15474
  walk(this.filteredOptions);
15400
15475
  return items;
15401
15476
  }
15477
+ isSelectAllOption(option) {
15478
+ return this.showSelectAll && option.value === SdSelectV2Listbox.SELECT_ALL_OPTION.value;
15479
+ }
15480
+ emitSelectAll() {
15481
+ if (!this.showSelectAll)
15482
+ return;
15483
+ const allLeaves = this.getAllNonDisabledLeaves();
15484
+ this.optionSelect.emit({
15485
+ option: { ...SdSelectV2Listbox.SELECT_ALL_OPTION, children: allLeaves },
15486
+ leaves: allLeaves,
15487
+ });
15488
+ }
15489
+ handleSelectAllClick = (e) => {
15490
+ e.stopPropagation();
15491
+ this.emitSelectAll();
15492
+ };
15402
15493
  isOptionFocused(option) {
15403
15494
  if (this.focusedIndex < 0)
15404
15495
  return false;
@@ -15471,7 +15562,13 @@ class SdSelectV2Listbox {
15471
15562
  return;
15472
15563
  e.preventDefault();
15473
15564
  e.stopPropagation();
15474
- this.emitOptionSelect(items[this.focusedIndex]);
15565
+ const focused = items[this.focusedIndex];
15566
+ if (this.isSelectAllOption(focused)) {
15567
+ this.emitSelectAll();
15568
+ }
15569
+ else {
15570
+ this.emitOptionSelect(focused);
15571
+ }
15475
15572
  }
15476
15573
  };
15477
15574
  /**
@@ -15550,9 +15647,9 @@ class SdSelectV2Listbox {
15550
15647
  '--listbox-max-height': this.maxHeight,
15551
15648
  '--listbox-radius': `${LIST_BOX_LAYOUT.radius}px`,
15552
15649
  };
15553
- 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 => {
15650
+ 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 => {
15554
15651
  this.listEl = el;
15555
- } }, 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) })))))));
15652
+ } }, 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) })))))));
15556
15653
  }
15557
15654
  static get watchers() { return {
15558
15655
  "searchKeyword": [{
@@ -15568,6 +15665,8 @@ class SdSelectV2Listbox {
15568
15665
  "options": [16],
15569
15666
  "value": [8],
15570
15667
  "emitValue": [4, "emit-value"],
15668
+ "useSearch": [4, "use-search"],
15669
+ "useSelectAll": [4, "use-select-all"],
15571
15670
  "triggerWidth": [1, "trigger-width"],
15572
15671
  "maxWidth": [1, "max-width"],
15573
15672
  "maxHeight": [1, "max-height"],
@@ -15631,13 +15730,13 @@ class SdSelectV2Trigger {
15631
15730
  ? SELECT_COLORS.icon.disabled
15632
15731
  : SELECT_COLORS.icon.default,
15633
15732
  };
15634
- return (hAsync("div", { key: '7c4f60c972c17b5954cbf0d0cc7ee38c8e6c16a3', ref: el => {
15733
+ return (hAsync("div", { key: 'ec8bf544b2878082a046fbe881afa2369709033f', ref: el => {
15635
15734
  this.triggerEl = el;
15636
15735
  }, tabindex: this.disabled ? -1 : 0, class: {
15637
15736
  'sd-select-v2-trigger': true,
15638
15737
  'sd-select-v2-trigger--open': this.isOpen,
15639
15738
  'sd-select-v2-trigger--disabled': this.disabled,
15640
- }, 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: {
15739
+ }, 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: {
15641
15740
  'sd-select-v2-trigger__icon': true,
15642
15741
  'sd-select-v2-trigger__icon--open': this.isOpen,
15643
15742
  } }))));
@@ -15759,7 +15858,7 @@ class SdSwitch {
15759
15858
  '--sd-switch-line-height': `${SWITCH_TYPOGRAPHY.lineHeight}px`,
15760
15859
  '--sd-switch-text-decoration': SWITCH_TYPOGRAPHY.textDecoration,
15761
15860
  };
15762
- 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)));
15861
+ 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)));
15763
15862
  }
15764
15863
  static get style() { return sdSwitchCss(); }
15765
15864
  static get cmpMeta() { return {
@@ -15803,7 +15902,7 @@ function nanoid(size = 21) {
15803
15902
 
15804
15903
  const TABLE_ID_ATTR = 'table-id';
15805
15904
 
15806
- 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%)}`;
15905
+ 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%)}`;
15807
15906
 
15808
15907
  class SdTable {
15809
15908
  constructor(hostRef) {
@@ -15859,11 +15958,17 @@ class SdTable {
15859
15958
  scrolledRight = false;
15860
15959
  rowCount = 0;
15861
15960
  loadingScrollTop = 0;
15961
+ // light DOM에 sd-thead / sd-tbody 자식이 없으면 sd-table이 직접 렌더해야 함을 알리는 플래그.
15962
+ // componentWillLoad에서 한 번 결정되며, 이후 동적 토글은 지원하지 않는다.
15963
+ autoThead = false;
15964
+ autoTbody = false;
15862
15965
  vsStart = 0;
15863
15966
  vsEnd = 0;
15864
15967
  lastReachEndNotifiedRowCount = -1;
15865
15968
  scrollContainer = null;
15866
15969
  onScroll;
15970
+ // 키: `${rowKey}::${field}` → { rowspan, colspan }
15971
+ spanRegistry = new Map();
15867
15972
  toFiniteNumber(value, fallback) {
15868
15973
  const n = typeof value === 'number' ? value : Number(value);
15869
15974
  return Number.isFinite(n) ? n : fallback;
@@ -15942,9 +16047,16 @@ class SdTable {
15942
16047
  this.innerRowsPerPage = newVal.rowsPerPage;
15943
16048
  }
15944
16049
  }
16050
+ detectChildren() {
16051
+ const hasThead = !!this.el.querySelector(':scope > sd-thead');
16052
+ const hasTbody = !!this.el.querySelector(':scope > sd-tbody');
16053
+ this.autoThead = !hasThead;
16054
+ this.autoTbody = !hasTbody;
16055
+ }
15945
16056
  componentWillLoad() {
15946
16057
  this.syncTableIdAttribute();
15947
16058
  this.handleNoDataLabelChange(this.noDataLabel);
16059
+ this.detectChildren();
15948
16060
  this.innerSelected = new Set(this.selected || []);
15949
16061
  this.columnWidths = (this.columns || []).map(c => parseInt(c.width || '120', 10));
15950
16062
  if (this.pagination?.page) {
@@ -15967,6 +16079,11 @@ class SdTable {
15967
16079
  el.getTableIdSync = () => this.getResolvedTableId();
15968
16080
  el.getVirtualScrollConfigSync = this.getVirtualScrollConfigSync.bind(this);
15969
16081
  el.calculateVisibleRange = this.calculateVisibleRange.bind(this);
16082
+ el.registerSpanSync = this.registerSpanSync.bind(this);
16083
+ el.unregisterSpanSync = this.unregisterSpanSync.bind(this);
16084
+ el.getSpanSync = this.getSpanSync.bind(this);
16085
+ el.isCoveredSync = this.isCoveredSync.bind(this);
16086
+ el.hasRowspanSync = this.hasRowspanSync.bind(this);
15970
16087
  if (Array.isArray(this.rows)) {
15971
16088
  this.rowCount = this.rows.length;
15972
16089
  this.pushRowsToChildren(this.rows);
@@ -16015,11 +16132,22 @@ class SdTable {
16015
16132
  this.scrollContainer.removeEventListener('scroll', this.onScroll);
16016
16133
  }
16017
16134
  }
16135
+ // light DOM(manual mode 자식)과 shadow DOM(autoThead/autoTbody fallback) 양쪽 모두에서 자식을 찾는다.
16136
+ queryChildEl(selector) {
16137
+ return (this.el.querySelector(selector) ??
16138
+ this.el.shadowRoot?.querySelector(selector) ??
16139
+ null);
16140
+ }
16141
+ queryAllTr() {
16142
+ const light = Array.from(this.el.querySelectorAll('sd-tr'));
16143
+ const shadow = Array.from(this.el.shadowRoot?.querySelectorAll('sd-tr') ?? []);
16144
+ return [...light, ...shadow];
16145
+ }
16018
16146
  pushRowsToChildren(rows) {
16019
- const tbody = this.el.querySelector('sd-tbody');
16147
+ const tbody = this.queryChildEl('sd-tbody');
16020
16148
  if (tbody)
16021
16149
  tbody.rows = rows;
16022
- const thead = this.el.querySelector('sd-thead');
16150
+ const thead = this.queryChildEl('sd-thead');
16023
16151
  if (thead)
16024
16152
  thead.rows = rows;
16025
16153
  }
@@ -16030,16 +16158,14 @@ class SdTable {
16030
16158
  this.refreshChildrenConfig();
16031
16159
  };
16032
16160
  refreshChildrenSelection() {
16033
- const thead = this.el.querySelector('sd-thead');
16034
- const rows = this.el.querySelectorAll('sd-tr');
16161
+ const thead = this.queryChildEl('sd-thead');
16035
16162
  thead?.refreshSelection?.();
16036
- rows.forEach(tr => tr?.refreshSelection?.());
16163
+ this.queryAllTr().forEach(tr => tr?.refreshSelection?.());
16037
16164
  }
16038
16165
  refreshChildrenConfig() {
16039
- const thead = this.el.querySelector('sd-thead');
16040
- const rows = this.el.querySelectorAll('sd-tr');
16166
+ const thead = this.queryChildEl('sd-thead');
16041
16167
  thead?.refreshConfig?.();
16042
- rows.forEach(tr => tr?.refreshConfig?.());
16168
+ this.queryAllTr().forEach(tr => tr?.refreshConfig?.());
16043
16169
  }
16044
16170
  maybeEmitVirtualReachEnd(start, end) {
16045
16171
  const threshold = Math.max(1, this.virtualEndThreshold);
@@ -16071,7 +16197,7 @@ class SdTable {
16071
16197
  this.vsEnd = end;
16072
16198
  const topHeight = start * this.rowHeight;
16073
16199
  const bottomHeight = Math.max(0, (this.rowCount - end) * this.rowHeight);
16074
- const tbody = this.el.querySelector('sd-tbody');
16200
+ const tbody = this.queryChildEl('sd-tbody');
16075
16201
  tbody?.setSpacersSync?.(topHeight, bottomHeight);
16076
16202
  if (rangeChanged) {
16077
16203
  this.sdVirtualUpdate.emit({
@@ -16163,8 +16289,7 @@ class SdTable {
16163
16289
  this.updateRowsVisibility();
16164
16290
  }
16165
16291
  updateRowsVisibility() {
16166
- const rows = this.el.querySelectorAll('sd-tr');
16167
- rows.forEach(tr => tr?.updateVisibility?.());
16292
+ this.queryAllTr().forEach(tr => tr?.updateVisibility?.());
16168
16293
  }
16169
16294
  changeRowsPerPage(perPage) {
16170
16295
  const changedRowsPerPage = perPage ? Number(perPage) : 0;
@@ -16201,10 +16326,9 @@ class SdTable {
16201
16326
  const delta = moveEvent.clientX - startX;
16202
16327
  const newWidth = Math.min(Math.max(startWidth + (reversed ? -delta : delta), minWidth), maxWidth);
16203
16328
  this.columnWidths = this.columnWidths.map((width, idx) => (idx === index ? newWidth : width));
16204
- const thead = this.el.querySelector('sd-thead');
16205
- const rows = this.el.querySelectorAll('sd-tr');
16329
+ const thead = this.queryChildEl('sd-thead');
16206
16330
  thead?.setColumnWidths?.(this.columnWidths);
16207
- rows.forEach(tr => tr?.setColumnWidths?.(this.columnWidths));
16331
+ this.queryAllTr().forEach(tr => tr?.setColumnWidths?.(this.columnWidths));
16208
16332
  const stickyRightCount = this.stickyColumn?.right || 0;
16209
16333
  const visibleColCount = this.columns.filter(c => c.visible !== false).length;
16210
16334
  const isRightStickyEdgeResizer = stickyRightCount > 0 && index === visibleColCount - stickyRightCount;
@@ -16241,6 +16365,109 @@ class SdTable {
16241
16365
  async getStickyStyle(colIdx) {
16242
16366
  return this.getStickyStyleSync(colIdx);
16243
16367
  }
16368
+ // ─── rowspan / colspan registry ─────────────────────────────────
16369
+ // sd-td가 mount/unmount 시 자기 (rowKey, field)와 span을 등록한다.
16370
+ // sd-tr는 render마다 isCoveredSync로 자신의 셀 위치가 다른 셀의 span에
16371
+ // 덮였는지 판정해 <td>를 그릴지 결정한다.
16372
+ spanKey(rowKey, field) {
16373
+ return `${rowKey}::${field}`;
16374
+ }
16375
+ // span 등록은 sd-td의 lifecycle에서 비동기적으로 일어나므로,
16376
+ // 등록/해제 직후 형제 sd-tr들이 새 레지스트리 상태로 다시 그려져야
16377
+ // 덮인 셀이 사라지거나 다시 나타난다.
16378
+ // forceUpdate는 React 래퍼 환경에서 prop 동기화 사이클과 부딪혀 누락되는
16379
+ // 경우가 있어, sd-tr의 @State (spansVersion)을 통해 재렌더를 강제한다.
16380
+ requestAllTrUpdate() {
16381
+ this.queryAllTr().forEach(tr => {
16382
+ const trAny = tr;
16383
+ if (typeof trAny.bumpSpansVersion === 'function') {
16384
+ trAny.bumpSpansVersion();
16385
+ }
16386
+ });
16387
+ }
16388
+ registerSpanSync(rowKey, field, rowspan, colspan) {
16389
+ if (rowKey == null || !field)
16390
+ return;
16391
+ const safeRowspan = Math.max(1, Math.floor(rowspan || 1));
16392
+ const safeColspan = Math.max(1, Math.floor(colspan || 1));
16393
+ const key = this.spanKey(rowKey, field);
16394
+ const prev = this.spanRegistry.get(key);
16395
+ if (safeRowspan === 1 && safeColspan === 1) {
16396
+ if (!prev)
16397
+ return;
16398
+ this.spanRegistry.delete(key);
16399
+ this.requestAllTrUpdate();
16400
+ return;
16401
+ }
16402
+ if (prev && prev.rowspan === safeRowspan && prev.colspan === safeColspan)
16403
+ return;
16404
+ this.spanRegistry.set(key, { rowspan: safeRowspan, colspan: safeColspan });
16405
+ this.requestAllTrUpdate();
16406
+ }
16407
+ unregisterSpanSync(rowKey, field) {
16408
+ if (rowKey == null || !field)
16409
+ return;
16410
+ const key = this.spanKey(rowKey, field);
16411
+ if (!this.spanRegistry.has(key))
16412
+ return;
16413
+ this.spanRegistry.delete(key);
16414
+ this.requestAllTrUpdate();
16415
+ }
16416
+ getSpanSync(rowKey, field) {
16417
+ return this.spanRegistry.get(this.spanKey(rowKey, field));
16418
+ }
16419
+ // 레지스트리에 rowspan>1 항목이 하나라도 있으면 true.
16420
+ // hover 동작을 끌지 결정하는 데 사용 — colspan만 있는 경우는 그대로 hover 유지.
16421
+ hasRowspanSync() {
16422
+ for (const span of this.spanRegistry.values()) {
16423
+ if (span.rowspan > 1)
16424
+ return true;
16425
+ }
16426
+ return false;
16427
+ }
16428
+ isCoveredSync(rowKey, colIdx, columns) {
16429
+ if (this.spanRegistry.size === 0)
16430
+ return false;
16431
+ const visibleCols = columns.filter(c => c.visible !== false);
16432
+ // 1. 같은 행 왼쪽 스캔 — colspan으로 이 위치를 덮는 셀이 있는가
16433
+ for (let i = 0; i < colIdx; i++) {
16434
+ const c = visibleCols[i];
16435
+ if (!c)
16436
+ continue;
16437
+ const field = typeof c.field === 'string' ? c.field : c.name;
16438
+ const span = this.spanRegistry.get(this.spanKey(rowKey, field));
16439
+ if (!span)
16440
+ continue;
16441
+ if (i + span.colspan > colIdx)
16442
+ return true;
16443
+ }
16444
+ // 2. 위쪽 행 스캔 — 숫자 변환 가능한 rowKey만 rowspan 평가
16445
+ const myRowIdx = Number(rowKey);
16446
+ if (!Number.isFinite(myRowIdx))
16447
+ return false;
16448
+ for (const [key, span] of this.spanRegistry) {
16449
+ if (span.rowspan <= 1)
16450
+ continue;
16451
+ const sepIdx = key.indexOf('::');
16452
+ if (sepIdx < 0)
16453
+ continue;
16454
+ const otherRowKey = key.slice(0, sepIdx);
16455
+ const otherField = key.slice(sepIdx + 2);
16456
+ const otherRowIdx = Number(otherRowKey);
16457
+ if (!Number.isFinite(otherRowIdx))
16458
+ continue;
16459
+ if (otherRowIdx >= myRowIdx)
16460
+ continue;
16461
+ if (otherRowIdx + span.rowspan <= myRowIdx)
16462
+ continue;
16463
+ const otherColIdx = visibleCols.findIndex(c => (typeof c.field === 'string' ? c.field : c.name) === otherField);
16464
+ if (otherColIdx < 0)
16465
+ continue;
16466
+ if (otherColIdx <= colIdx && otherColIdx + span.colspan > colIdx)
16467
+ return true;
16468
+ }
16469
+ return false;
16470
+ }
16244
16471
  setRowCountSync(count) {
16245
16472
  const safeCount = Math.max(0, Math.floor(this.toFiniteNumber(count, 0)));
16246
16473
  if (safeCount !== this.rowCount) {
@@ -16288,6 +16515,22 @@ class SdTable {
16288
16515
  return null;
16289
16516
  return { from: this.vsStart, to: this.vsEnd };
16290
16517
  }
16518
+ // autoTbody fallback에서 sd-table이 직접 sd-tr을 만들어내는 경로.
16519
+ // 가상 스크롤은 사용자가 직접 SdTbody+SdTr을 작성해야 하므로 빈 배열을 반환한다.
16520
+ renderAutoRows() {
16521
+ if (this.useVirtualScroll)
16522
+ return null;
16523
+ const allRows = this.rows ?? [];
16524
+ const pageInfo = this.getPaginationInfoSync();
16525
+ const startIdx = pageInfo?.startIndex ?? 0;
16526
+ const displayed = pageInfo
16527
+ ? allRows.slice(pageInfo.startIndex, pageInfo.endIndex)
16528
+ : allRows;
16529
+ return displayed.map((row, i) => {
16530
+ const absoluteIdx = startIdx + i;
16531
+ return (hAsync("sd-tr", { key: absoluteIdx, "row-key": String(absoluteIdx), row: row }));
16532
+ });
16533
+ }
16291
16534
  get tableClasses() {
16292
16535
  return [
16293
16536
  'sd-table',
@@ -16307,24 +16550,24 @@ class SdTable {
16307
16550
  }
16308
16551
  render() {
16309
16552
  const resolvedTableId = this.getResolvedTableId();
16310
- return (hAsync(Host, { key: '0b90643721a90b7bb59a6c31f6edeb313849b973' }, hAsync("div", { key: 'e55fe4f476dbea4888a168861e7e6d6951d7d489', class: "sd-table__container", style: {
16553
+ return (hAsync(Host, { key: 'd73cd690ad11ce92af37b6f32374f6f891c5b677' }, hAsync("div", { key: 'f51d23212885ad8121b9a4e895fb854f1e142bc4', class: "sd-table__container", style: {
16311
16554
  '--table-width': this.width,
16312
16555
  '--table-height': this.height,
16313
16556
  '--table-container-height': `calc(${this.height || '100%'} - ${this.pagination && this.rowCount > 0 && !this.useVirtualScroll ? 48 : 0}px)`,
16314
- } }, hAsync("div", { key: 'de18a900037a7b2f619dd22981c30ed76f5a8111', class: {
16557
+ } }, hAsync("div", { key: '84b1ba7b2220ff55304b9c19e59304ca2257cff0', class: {
16315
16558
  'sd-table__clip': true,
16316
16559
  'sd-table__clip--has-pagination': !!(this.pagination &&
16317
16560
  this.pagination.rowsPerPage > 0 &&
16318
16561
  this.rowCount > 0 &&
16319
16562
  !this.useVirtualScroll),
16320
- } }, hAsync("div", { key: '028e0982d415033adaf420ee6b953241c8f3dbec', class: {
16563
+ } }, hAsync("div", { key: 'c901eba67eae29515bf0b3edcc6632b2aacf0f80', class: {
16321
16564
  'sd-table__wrapper': true,
16322
16565
  'sd-table__wrapper--loading': this.isLoading,
16323
16566
  'sd-table__wrapper--no-data': this.rowCount === 0 && !this.isLoading,
16324
- } }, 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 &&
16567
+ } }, 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 &&
16325
16568
  this.pagination.rowsPerPage > 0 &&
16326
16569
  this.rowCount > 0 &&
16327
- !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
16570
+ !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
16328
16571
  ? this.innerRowsPerPage
16329
16572
  : this.pagination.rowsPerPage, options: this.rowsPerPageOption, width: "128px", emitValue: true, onSdUpdate: e => {
16330
16573
  if (!this.isRowsPerPageValue(e.detail))
@@ -16405,6 +16648,8 @@ class SdTable {
16405
16648
  "scrolledRight": [32],
16406
16649
  "rowCount": [32],
16407
16650
  "loadingScrollTop": [32],
16651
+ "autoThead": [32],
16652
+ "autoTbody": [32],
16408
16653
  "isRowSelected": [64],
16409
16654
  "updateRowSelect": [64],
16410
16655
  "toggleSelectAll": [64],
@@ -16605,7 +16850,7 @@ class SdTabs {
16605
16850
  };
16606
16851
  }
16607
16852
  render() {
16608
- return (hAsync("div", { key: '390edfad274caa06df38af9d04580015a1744a44', class: this.getContainerClasses(), style: this.buildCssVars() }, this.tabs.map((tab, index) => {
16853
+ return (hAsync("div", { key: '3698b7b43e74ff053d61d5ce696b987373fd27d6', class: this.getContainerClasses(), style: this.buildCssVars() }, this.tabs.map((tab, index) => {
16609
16854
  const badgeName = this.getBadgeName(tab);
16610
16855
  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() }))));
16611
16856
  })));
@@ -16801,7 +17046,7 @@ class SdTag {
16801
17046
  render() {
16802
17047
  const config = this.resolvedConfig;
16803
17048
  const iconNode = this.renderIcon(config.icon, config.iconSize);
16804
- return (hAsync("span", { key: 'da19900d267d2b2f000e1790133966a7976bcded', class: "sd-tag", style: {
17049
+ return (hAsync("span", { key: 'def10730670f37a62fa76b507f7f15a1b1f956fc', class: "sd-tag", style: {
16805
17050
  '--sd-tag-background': config.background,
16806
17051
  '--sd-tag-content': config.content,
16807
17052
  '--sd-tag-height': config.height,
@@ -16811,7 +17056,7 @@ class SdTag {
16811
17056
  '--sd-tag-font-weight': config.fontWeight,
16812
17057
  '--sd-tag-line-height': config.lineHeight,
16813
17058
  '--sd-tag-radius': config.radius,
16814
- }, "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));
17059
+ }, "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));
16815
17060
  }
16816
17061
  static get style() { return sdTagCss(); }
16817
17062
  static get cmpMeta() { return {
@@ -16862,7 +17107,12 @@ class SdTbody {
16862
17107
  this.syncTableContext();
16863
17108
  }
16864
17109
  syncTableContext() {
16865
- const table = this.el.closest('sd-table');
17110
+ // sd-table shadow:true이므로 fallback content로 렌더되면 closest가 경계를 못 넘는다.
17111
+ // 그 경우 getRootNode().host(=sd-table)로 폴백한다.
17112
+ const closest = this.el.closest('sd-table');
17113
+ const root = this.el.getRootNode();
17114
+ const fromShadow = root instanceof ShadowRoot ? root.host : null;
17115
+ const table = closest ?? fromShadow;
16866
17116
  this.tableEl = table;
16867
17117
  const fromMethod = table?.getTableIdSync?.();
16868
17118
  const fromAttr = table?.getAttribute(TABLE_ID_ATTR);
@@ -16875,7 +17125,7 @@ class SdTbody {
16875
17125
  }
16876
17126
  render() {
16877
17127
  const hasRows = this.rows.length > 0;
16878
- return (hAsync(Host, { key: 'e4c64dbf97185bbc6eaec4b883c65dc8ebd34ece', slot: `${this.tableId}-body` }, hAsync("tbody", { key: 'b2fb886684a5a6055d3af659bba75dd9bc801b73', class: { 'tbody': true, 'tbody--empty': !hasRows } }, hasRows ? ([
17128
+ return (hAsync(Host, { key: 'bc9fbd4f08f4d77da60b083dceef4e24e2fb5532', slot: `${this.tableId}-body` }, hAsync("tbody", { key: '81ef875cbc39f988021a211ede716a98d3ea30cd', class: { 'tbody': true, 'tbody--empty': !hasRows } }, hasRows ? ([
16879
17129
  this.topSpacerHeight > 0 && (hAsync("tr", { key: "spacer-top", class: "tbody__spacer", style: { height: `${this.topSpacerHeight}px`, display: 'block' } })),
16880
17130
  hAsync("slot", null),
16881
17131
  this.bottomSpacerHeight > 0 && (hAsync("tr", { key: "spacer-bottom", class: "tbody__spacer", style: { height: `${this.bottomSpacerHeight}px`, display: 'block' } })),
@@ -16912,20 +17162,63 @@ class SdTd {
16912
17162
  field;
16913
17163
  rowKey;
16914
17164
  align;
17165
+ rowspan;
17166
+ colspan;
16915
17167
  handleFieldChange() {
16916
17168
  this.syncSlotName();
17169
+ this.syncSpanRegistration();
16917
17170
  }
16918
17171
  handleRowKeyChange() {
16919
17172
  this.syncSlotName();
17173
+ this.syncSpanRegistration();
17174
+ }
17175
+ handleSpanChange() {
17176
+ this.syncSpanRegistration();
16920
17177
  }
16921
17178
  componentWillLoad() {
16922
17179
  this.syncSlotName();
17180
+ this.syncSpanRegistration();
16923
17181
  // slot 타이밍 엇갈림 대응: 부모 sd-tr forceUpdate로 슬롯 재매칭
16924
17182
  const parentTr = this.el.parentElement;
16925
17183
  if (parentTr?.tagName?.toLowerCase() === 'sd-tr') ;
16926
17184
  }
16927
17185
  componentDidLoad() {
16928
17186
  this.syncSlotName();
17187
+ this.syncSpanRegistration();
17188
+ }
17189
+ // React StrictMode에서는 disconnect/reconnect 사이클이 일어나면서
17190
+ // 동일 인스턴스의 componentWillLoad는 더 이상 호출되지 않는다.
17191
+ // 재연결 시점에도 등록 상태를 복구해야 rowspan/colspan이 유지된다.
17192
+ connectedCallback() {
17193
+ this.syncSpanRegistration();
17194
+ }
17195
+ disconnectedCallback() {
17196
+ const table = this.findTable();
17197
+ if (table?.unregisterSpanSync && this.field && this.rowKey != null) {
17198
+ table.unregisterSpanSync(String(this.rowKey), this.field);
17199
+ this.requestParentTrUpdate();
17200
+ }
17201
+ }
17202
+ findTable() {
17203
+ return this.el.closest('sd-table');
17204
+ }
17205
+ requestParentTrUpdate() {
17206
+ const parentTr = this.el.parentElement;
17207
+ if (parentTr?.tagName?.toLowerCase() !== 'sd-tr')
17208
+ return;
17209
+ const trAny = parentTr;
17210
+ if (typeof trAny.bumpSpansVersion === 'function') {
17211
+ trAny.bumpSpansVersion();
17212
+ }
17213
+ }
17214
+ syncSpanRegistration() {
17215
+ const table = this.findTable();
17216
+ if (!table?.registerSpanSync || !this.field || this.rowKey == null)
17217
+ return;
17218
+ const rs = Math.max(1, Math.floor(Number(this.rowspan) || 1));
17219
+ const cs = Math.max(1, Math.floor(Number(this.colspan) || 1));
17220
+ table.registerSpanSync(String(this.rowKey), this.field, rs, cs);
17221
+ this.requestParentTrUpdate();
16929
17222
  }
16930
17223
  syncSlotName() {
16931
17224
  const table = this.el.closest('sd-table');
@@ -16939,7 +17232,7 @@ class SdTd {
16939
17232
  }
16940
17233
  }
16941
17234
  render() {
16942
- return (hAsync(Host, { key: '672c967273dac405ed4a47fa5939463265075681', class: { [`align-${this.align}`]: Boolean(this.align) } }, hAsync("slot", { key: 'c15e572fdf4a8c68fff8b69b586dfbf9f01dce1b' })));
17235
+ return (hAsync(Host, { key: 'da9ce2edb986d4b3cf1a6e5f59030009f1288250', class: { [`align-${this.align}`]: Boolean(this.align) } }, hAsync("slot", { key: '8514071bd38c4f5b1997ae7239b8585a25f97ce0' })));
16943
17236
  }
16944
17237
  static get watchers() { return {
16945
17238
  "field": [{
@@ -16947,6 +17240,12 @@ class SdTd {
16947
17240
  }],
16948
17241
  "rowKey": [{
16949
17242
  "handleRowKeyChange": 0
17243
+ }],
17244
+ "rowspan": [{
17245
+ "handleSpanChange": 0
17246
+ }],
17247
+ "colspan": [{
17248
+ "handleSpanChange": 0
16950
17249
  }]
16951
17250
  }; }
16952
17251
  static get style() { return sdTdCss(); }
@@ -16956,7 +17255,9 @@ class SdTd {
16956
17255
  "$members$": {
16957
17256
  "field": [1],
16958
17257
  "rowKey": [1, "row-key"],
16959
- "align": [1]
17258
+ "align": [1],
17259
+ "rowspan": [2],
17260
+ "colspan": [2]
16960
17261
  },
16961
17262
  "$listeners$": undefined,
16962
17263
  "$lazyBundleId$": "-",
@@ -17035,16 +17336,16 @@ class SdTextLink {
17035
17336
  '--sd-text-link-text-decoration': typo.textDecoration,
17036
17337
  ...(this.disabled ? { '--sd-text-link-color': TEXT_LINK_COLORS.content.disabled } : {}),
17037
17338
  };
17038
- return (hAsync("span", { key: '1128254cddacf5869f320ce2b788b06646f27d7f', class: {
17339
+ return (hAsync("span", { key: '77c1aa4a4a6297af9431947b7146db2ddfad52b5', class: {
17039
17340
  'sd-text-link': true,
17040
17341
  'sd-text-link--disabled': this.disabled,
17041
- }, 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: {
17342
+ }, 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: {
17042
17343
  width: `${TEXT_LINK_LAYOUT.arrowFrame}px`,
17043
17344
  height: `${TEXT_LINK_LAYOUT.arrowFrame}px`,
17044
17345
  display: 'inline-flex',
17045
17346
  alignItems: 'center',
17046
17347
  justifyContent: 'center',
17047
- } }, hAsync("sd-icon", { key: '677c88823b02084449cd2dec83cc6bd27dfb8006', name: "chevronRight", size: TEXT_LINK_LAYOUT.arrowIconSize, color: arrowColor })))));
17348
+ } }, hAsync("sd-icon", { key: '2fa166ef60f6d1ee933450146bc667ee89dad2ce', name: "chevronRight", size: TEXT_LINK_LAYOUT.arrowIconSize, color: arrowColor })))));
17048
17349
  }
17049
17350
  static get style() { return sdTextLinkCss(); }
17050
17351
  static get cmpMeta() { return {
@@ -17191,7 +17492,7 @@ class SdTextarea {
17191
17492
  '--sd-system-size-field-sm-height': 'auto',
17192
17493
  '--sd-system-radius-field-sm': `${TEXTAREA_TOKENS.radius}px`,
17193
17494
  };
17194
- 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 }))));
17495
+ 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 }))));
17195
17496
  }
17196
17497
  static get watchers() { return {
17197
17498
  "value": [{
@@ -17288,7 +17589,12 @@ class SdThead {
17288
17589
  this.resolveConfig();
17289
17590
  }
17290
17591
  syncTableContext() {
17291
- const table = this.el.closest('sd-table');
17592
+ // sd-table shadow:true이므로 fallback content로 렌더되면 closest가 경계를 못 넘는다.
17593
+ // 그 경우 getRootNode().host(=sd-table)로 폴백한다.
17594
+ const closest = this.el.closest('sd-table');
17595
+ const root = this.el.getRootNode();
17596
+ const fromShadow = root instanceof ShadowRoot ? root.host : null;
17597
+ const table = closest ?? fromShadow;
17292
17598
  this.tableEl = table;
17293
17599
  const fromMethod = table?.getTableIdSync?.();
17294
17600
  const fromAttr = table?.getAttribute(TABLE_ID_ATTR);
@@ -17378,16 +17684,16 @@ class SdThead {
17378
17684
  const stickyLeftCols = this.visibleColumns.slice(0, stickyLeftCount);
17379
17685
  const middleCols = this.visibleColumns.slice(stickyLeftCount, this.visibleColumns.length - stickyRightCount);
17380
17686
  const stickyRightCols = this.visibleColumns.slice(this.visibleColumns.length - stickyRightCount);
17381
- return (hAsync(Host, { key: '2358499ef65d88005d03b1246604c0fd8eefdde1', slot: `${this.tableId}-head` }, hAsync("thead", { key: '49bb43a19aeb83f3a60367b26dbb6535ebcec743', class: {
17687
+ return (hAsync(Host, { key: '5aa1e38311b542d1a0b05b55abc7ef41927508bd', slot: `${this.tableId}-head` }, hAsync("thead", { key: '6d17753988ecd02d900d8a3bd7f2115b534b68a7', class: {
17382
17688
  'thead': true,
17383
17689
  'thead--sticky': this._stickyHeader,
17384
- } }, hAsync("tr", { key: 'cd6388d79e9a4a5d9edbbda05601abbbefcb1ff4', class: "tr" }, this._selectable && (hAsync("th", { key: 'fa09e82368d45e9fb1d32838ef44e609c698609d', class: {
17690
+ } }, hAsync("tr", { key: '9cc729603e126da2f9c8923fe29ece10c7750bb4', class: "tr" }, this._selectable && (hAsync("th", { key: '37b2bcfa77eaf4c44465684c49ae84d566acc18b', class: {
17385
17691
  'th': true,
17386
17692
  'th--selected': true,
17387
17693
  'sticky-left': true,
17388
17694
  'sticky-left-edge': stickyLeftCount === 0,
17389
17695
  'is-scrolled-left': stickyLeftCount === 0 && this._scrolledLeft,
17390
- }, 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: {
17696
+ }, 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: {
17391
17697
  'th': true,
17392
17698
  [`${col.thClass}`]: Boolean(col.thClass),
17393
17699
  'sticky-left': true,
@@ -17502,10 +17808,10 @@ class SdToast {
17502
17808
  render() {
17503
17809
  const typeConfig = TOAST_TYPE_CONFIG[this.type] ?? TOAST_TYPE_CONFIG.default;
17504
17810
  const iconSize = Number(TOAST_LAYOUT.iconSize);
17505
- return (hAsync("div", { key: 'd4b73e2503514143f5174bc8859baf0e59c2f8da', style: {
17811
+ return (hAsync("div", { key: '77954c9d285339cb48032eec5eca0dcbe308affc', style: {
17506
17812
  '--sd-toast-bg': typeConfig.bg,
17507
17813
  '--sd-toast-text': typeConfig.content,
17508
- } }, 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() })))));
17814
+ } }, 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() })))));
17509
17815
  }
17510
17816
  static get style() { return sdToastCss(); }
17511
17817
  static get cmpMeta() { return {
@@ -17757,7 +18063,7 @@ class SdToastContainer {
17757
18063
  const activeToasts = toasts.filter(t => t.state !== 'exiting').reverse();
17758
18064
  const indexMap = new Map();
17759
18065
  activeToasts.forEach((t, i) => indexMap.set(t.id, i));
17760
- return (hAsync("div", { key: '601c4c5aa55df02459866607ca7c59da53c2eda5', class: "sd-toast-container", style: this.getContainerStyles(), onMouseEnter: () => {
18066
+ return (hAsync("div", { key: '5057793be2d6ce213edc84d58f7273248646dc19', class: "sd-toast-container", style: this.getContainerStyles(), onMouseEnter: () => {
17761
18067
  this.expanded = true;
17762
18068
  this.pauseTimers();
17763
18069
  }, onMouseLeave: () => {
@@ -17915,7 +18221,7 @@ class SdToggle {
17915
18221
  '--sd-toggle-content-select': TOGGLE_COLORS.content.select,
17916
18222
  '--sd-toggle-content-disabled': TOGGLE_COLORS.content.disabled,
17917
18223
  };
17918
- 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 })));
18224
+ 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 })));
17919
18225
  }
17920
18226
  static get style() { return sdToggleCss(); }
17921
18227
  static get cmpMeta() { return {
@@ -18042,14 +18348,14 @@ class SdTooltip {
18042
18348
  const toggleTooltip = () => (this.showTooltip = !this.showTooltip);
18043
18349
  const divTrigger = trigger === 'hover' ? hoverTrigger : this.label ? {} : { onClick: toggleTooltip };
18044
18350
  const buttonClickTrigger = trigger === 'click' && this.label ? { onSdClick: toggleTooltip } : {};
18045
- 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: {
18351
+ 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: {
18046
18352
  'sd-floating-menu': true,
18047
18353
  [`sd-floating-menu--${tooltipType}`]: true,
18048
18354
  [`sd-floating-menu--${placement}`]: true,
18049
18355
  }, style: {
18050
18356
  '--sd-floating-bg': typeConfig.bg,
18051
18357
  '--sd-floating-content': typeConfig.content,
18052
- }, 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 }))))));
18358
+ }, 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 }))))));
18053
18359
  }
18054
18360
  static get style() { return sdTooltipCss(); }
18055
18361
  static get cmpMeta() { return {
@@ -18076,7 +18382,7 @@ class SdTooltip {
18076
18382
  }; }
18077
18383
  }
18078
18384
 
18079
- 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}`;
18385
+ 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}`;
18080
18386
 
18081
18387
  class SdTr {
18082
18388
  constructor(hostRef) {
@@ -18091,6 +18397,7 @@ class SdTr {
18091
18397
  tableId = '';
18092
18398
  columnWidths = [];
18093
18399
  isVisible = true;
18400
+ spansVersion = 0;
18094
18401
  _columns = [];
18095
18402
  _selectable = false;
18096
18403
  _stickyColumn = { left: 0, right: 0 };
@@ -18108,7 +18415,12 @@ class SdTr {
18108
18415
  this.syncTableContext();
18109
18416
  }
18110
18417
  syncTableContext() {
18111
- const table = this.el.closest('sd-table');
18418
+ // sd-table shadow:true이므로 fallback content로 렌더되면 closest가 경계를 못 넘는다.
18419
+ // 그 경우 getRootNode().host(=sd-table)로 폴백한다.
18420
+ const closest = this.el.closest('sd-table');
18421
+ const root = this.el.getRootNode();
18422
+ const fromShadow = root instanceof ShadowRoot ? root.host : null;
18423
+ const table = closest ?? fromShadow;
18112
18424
  this.tableEl = table;
18113
18425
  const fromMethod = table?.getTableIdSync?.();
18114
18426
  const fromAttr = table?.getAttribute(TABLE_ID_ATTR);
@@ -18133,6 +18445,9 @@ class SdTr {
18133
18445
  async refreshConfig() {
18134
18446
  this.resolveConfig();
18135
18447
  }
18448
+ async bumpSpansVersion() {
18449
+ this.spansVersion = this.spansVersion + 1;
18450
+ }
18136
18451
  async updateVisibility() {
18137
18452
  this.updateVisibilitySync();
18138
18453
  }
@@ -18198,37 +18513,60 @@ class SdTr {
18198
18513
  this.tableEl.updateRowSelectSync(this.row);
18199
18514
  }
18200
18515
  }
18516
+ getSpanFor(col) {
18517
+ if (!this.tableEl?.getSpanSync)
18518
+ return undefined;
18519
+ const fieldName = typeof col.field === 'string' ? col.field : col.name;
18520
+ return this.tableEl.getSpanSync(this.rowKey, fieldName);
18521
+ }
18522
+ isCovered(colIdx) {
18523
+ if (!this.tableEl?.isCoveredSync)
18524
+ return false;
18525
+ return this.tableEl.isCoveredSync(this.rowKey, colIdx, this._columns);
18526
+ }
18201
18527
  render() {
18202
18528
  const stickyLeftCount = this._stickyColumn.left || 0;
18203
18529
  const stickyRightCount = this._stickyColumn.right || 0;
18204
18530
  const stickyLeftCols = this.visibleColumns.slice(0, stickyLeftCount);
18205
18531
  const middleCols = this.visibleColumns.slice(stickyLeftCount, this.visibleColumns.length - stickyRightCount);
18206
18532
  const stickyRightCols = this.visibleColumns.slice(this.visibleColumns.length - stickyRightCount);
18207
- return (hAsync(Host, { key: 'd6259e5c87cce0fa70f1d849e11416ad69b0cac1', style: { display: this.isVisible ? '' : 'none' } }, hAsync("tr", { key: '90e36c39bede0e07fc1c4d90183a73ebc99b6ed8', class: "tr" }, this._selectable && (hAsync("td", { key: '601f1747063d8e73803304abc2cd767f420f359c', class: {
18533
+ const hasRowspan = this.tableEl?.hasRowspanSync?.() ?? false;
18534
+ 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: {
18208
18535
  'td': true,
18209
18536
  'td--selected': true,
18210
18537
  'sticky-left': true,
18211
18538
  'sticky-left-edge': stickyLeftCount === 0,
18212
18539
  'is-scrolled-left': stickyLeftCount === 0 && this._scrolledLeft,
18213
- }, 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: {
18214
- 'td': true,
18215
- [`td--${col.align || 'left'}`]: true,
18216
- 'sticky-left': true,
18217
- 'sticky-left-edge': idx === stickyLeftCount - 1,
18218
- 'is-scrolled-left': idx === stickyLeftCount - 1 && this._scrolledLeft,
18219
- [`${col.tdClass}`]: Boolean(col.tdClass),
18220
- }, 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) => {
18540
+ }, style: { '--sticky-left-offset': '0px' } }, hAsync("sd-checkbox", { key: '72bdbadc76dcb0682eb4de496e9abda692a0ea7e', value: this.isSelected(), onSdUpdate: () => this.handleSelect() }))), stickyLeftCols.map((col, idx) => {
18541
+ if (this.isCovered(idx))
18542
+ return null;
18543
+ const span = this.getSpanFor(col);
18544
+ return (hAsync("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
18545
+ 'td': true,
18546
+ [`td--${col.align || 'left'}`]: true,
18547
+ 'sticky-left': true,
18548
+ 'sticky-left-edge': idx === stickyLeftCount - 1,
18549
+ 'is-scrolled-left': idx === stickyLeftCount - 1 && this._scrolledLeft,
18550
+ [`${col.tdClass}`]: Boolean(col.tdClass),
18551
+ }, 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)))));
18552
+ }), middleCols.map((col, relativeIdx) => {
18221
18553
  const actualColIdx = stickyLeftCount + relativeIdx;
18554
+ if (this.isCovered(actualColIdx))
18555
+ return null;
18222
18556
  const fieldName = typeof col.field === 'string' ? col.field : col.name;
18223
- return (hAsync("td", { key: col.name, class: {
18557
+ const span = this.getSpanFor(col);
18558
+ return (hAsync("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
18224
18559
  td: true,
18225
18560
  [`td--${col.align || 'left'}`]: true,
18226
18561
  [`${col.tdClass}`]: Boolean(col.tdClass),
18227
18562
  }, style: this.getStickyStyle(actualColIdx) }, hAsync("slot", { name: `${this.tableId}-${fieldName}-${this.rowKey}` }, hAsync("span", null, this.getCellValue(col)))));
18228
18563
  }), stickyRightCols.map((col, relativeIdx) => {
18229
18564
  const actualColIdx = this.visibleColumns.length - stickyRightCount + relativeIdx;
18565
+ if (this.isCovered(actualColIdx))
18566
+ return null;
18230
18567
  const fieldName = typeof col.field === 'string' ? col.field : col.name;
18231
- return (hAsync("td", { key: col.name, class: {
18568
+ const span = this.getSpanFor(col);
18569
+ return (hAsync("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
18232
18570
  'td': true,
18233
18571
  [`td--${col.align || 'left'}`]: true,
18234
18572
  'sticky-right': true,
@@ -18251,12 +18589,14 @@ class SdTr {
18251
18589
  "tableId": [32],
18252
18590
  "columnWidths": [32],
18253
18591
  "isVisible": [32],
18592
+ "spansVersion": [32],
18254
18593
  "_columns": [32],
18255
18594
  "_selectable": [32],
18256
18595
  "_stickyColumn": [32],
18257
18596
  "_scrolledLeft": [32],
18258
18597
  "_scrolledRight": [32],
18259
18598
  "refreshConfig": [64],
18599
+ "bumpSpansVersion": [64],
18260
18600
  "updateVisibility": [64],
18261
18601
  "setColumnWidths": [64],
18262
18602
  "refreshSelection": [64]