@sellmate/design-system 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/dist/cjs/{component.table-CMqGfEui.js → component.table-qOFez3z3.js} +3 -0
  2. package/dist/cjs/design-system.cjs.js +1 -1
  3. package/dist/cjs/index.cjs.js +2 -2
  4. package/dist/cjs/loader.cjs.js +1 -1
  5. package/dist/cjs/sanitize-inline-html-BZCCwH_U.js +65 -0
  6. package/dist/cjs/sd-calendar_2.cjs.entry.js +9 -7
  7. package/dist/cjs/sd-callout.cjs.entry.js +152 -0
  8. package/dist/cjs/sd-card.cjs.entry.js +1 -1
  9. package/dist/cjs/sd-checkbox.cjs.entry.js +9 -4
  10. package/dist/cjs/sd-chip.cjs.entry.js +1 -1
  11. package/dist/cjs/sd-circle-progress.cjs.entry.js +2 -2
  12. package/dist/cjs/sd-confirm-modal_2.cjs.entry.js +4 -3
  13. package/dist/cjs/sd-date-picker_7.cjs.entry.js +9 -9
  14. package/dist/cjs/sd-date-range-picker-calendar.cjs.entry.js +1 -1
  15. package/dist/cjs/sd-dropdown-button.cjs.entry.js +6 -5
  16. package/dist/cjs/sd-field_3.cjs.entry.js +7 -7
  17. package/dist/cjs/sd-guide.cjs.entry.js +5 -4
  18. package/dist/cjs/sd-key-value-table.cjs.entry.js +2 -2
  19. package/dist/cjs/sd-linear-progress.cjs.entry.js +2 -2
  20. package/dist/cjs/sd-loading-container.cjs.entry.js +2 -2
  21. package/dist/cjs/sd-pagination_4.cjs.entry.js +28 -37
  22. package/dist/cjs/sd-popup.cjs.entry.js +6 -5
  23. package/dist/cjs/sd-portal.cjs.entry.js +1 -1
  24. package/dist/cjs/sd-select-list-item_2.cjs.entry.js +6 -6
  25. package/dist/cjs/sd-select_3.cjs.entry.js +8 -8
  26. package/dist/cjs/sd-switch.cjs.entry.js +1 -1
  27. package/dist/cjs/sd-table.cjs.entry.js +37 -36
  28. package/dist/cjs/{sd-table.config-BIpldZtw.js → sd-table.config-DqgNOdXO.js} +5 -3
  29. package/dist/cjs/sd-tabs.cjs.entry.js +1 -1
  30. package/dist/cjs/sd-tag.cjs.entry.js +4 -2
  31. package/dist/cjs/sd-td.cjs.entry.js +18 -9
  32. package/dist/cjs/sd-toast-container.cjs.entry.js +1 -1
  33. package/dist/cjs/sd-toast.cjs.entry.js +2 -2
  34. package/dist/cjs/sd-toggle.cjs.entry.js +1 -1
  35. package/dist/cjs/{system-VmZRYp6V.js → system-wrt-tcOq.js} +12 -1
  36. package/dist/collection/collection-manifest.json +2 -1
  37. package/dist/collection/components/sd-calendar/sd-calendar.css +5 -1
  38. package/dist/collection/components/sd-calendar/sd-calendar.js +26 -4
  39. package/dist/collection/components/sd-callout/sd-callout.config.js +45 -0
  40. package/dist/collection/components/sd-callout/sd-callout.css +87 -0
  41. package/dist/collection/components/sd-callout/sd-callout.js +114 -0
  42. package/dist/collection/components/sd-card/sd-card.js +1 -1
  43. package/dist/collection/components/sd-checkbox/sd-checkbox.js +9 -4
  44. package/dist/collection/components/sd-chip/sd-chip.js +1 -1
  45. package/dist/collection/components/sd-circle-progress/sd-circle-progress.js +1 -1
  46. package/dist/collection/components/sd-confirm-modal/sd-confirm-modal.js +3 -2
  47. package/dist/collection/components/sd-date-picker/sd-date-picker-trigger/sd-date-picker-trigger.js +2 -2
  48. package/dist/collection/components/sd-date-picker/sd-date-picker.js +2 -2
  49. package/dist/collection/components/sd-date-range-picker/sd-date-range-picker-calendar/sd-date-range-picker-calendar.js +1 -1
  50. package/dist/collection/components/sd-dropdown-button/sd-dropdown-button.js +5 -4
  51. package/dist/collection/components/sd-field/sd-field.js +4 -4
  52. package/dist/collection/components/sd-floating-portal/sd-floating-portal.js +1 -1
  53. package/dist/collection/components/sd-guide/sd-guide.js +4 -3
  54. package/dist/collection/components/sd-input/sd-input.js +2 -2
  55. package/dist/collection/components/sd-linear-progress/sd-linear-progress.js +1 -1
  56. package/dist/collection/components/sd-loading-container/sd-loading-container.js +2 -2
  57. package/dist/collection/components/sd-loading-modal/sd-loading-modal.js +1 -1
  58. package/dist/collection/components/sd-modal-container/sd-modal-container.js +8 -0
  59. package/dist/collection/components/sd-number-input/sd-number-input.js +4 -4
  60. package/dist/collection/components/sd-pagination/sd-pagination.js +3 -3
  61. package/dist/collection/components/sd-popup/sd-popup.config.js +3 -4
  62. package/dist/collection/components/sd-popup/sd-popup.js +4 -2
  63. package/dist/collection/components/sd-portal/sd-portal.js +1 -1
  64. package/dist/collection/components/sd-select/sd-select-list-item/sd-select-list-item.js +2 -2
  65. package/dist/collection/components/sd-select/sd-select-list-item-search/sd-select-list-item-search.js +4 -4
  66. package/dist/collection/components/sd-select/sd-select-listbox/sd-select-listbox.js +2 -2
  67. package/dist/collection/components/sd-select/sd-select-trigger/sd-select-trigger.js +2 -2
  68. package/dist/collection/components/sd-select/sd-select.js +4 -4
  69. package/dist/collection/components/sd-switch/sd-switch.js +1 -1
  70. package/dist/collection/components/sd-table/sd-table.js +35 -34
  71. package/dist/collection/components/sd-table/sd-tbody/sd-tbody.js +2 -2
  72. package/dist/collection/components/sd-table/sd-td/sd-td.js +18 -9
  73. package/dist/collection/components/sd-table/sd-thead/sd-thead.js +3 -3
  74. package/dist/collection/components/sd-table/sd-tr/sd-tr.css +6 -2
  75. package/dist/collection/components/sd-table/sd-tr/sd-tr.js +16 -25
  76. package/dist/collection/components/sd-tabs/sd-tabs.js +1 -1
  77. package/dist/collection/components/sd-tag/sd-tag.js +4 -2
  78. package/dist/collection/components/sd-textarea/sd-textarea.js +1 -1
  79. package/dist/collection/components/sd-toast/sd-toast.js +2 -2
  80. package/dist/collection/components/sd-toast-container/sd-toast-container.js +1 -1
  81. package/dist/collection/components/sd-toggle/sd-toggle.js +1 -1
  82. package/dist/collection/components/sd-tooltip/sd-tooltip.js +2 -2
  83. package/dist/collection/utils/html/sanitize-inline-html.js +61 -0
  84. package/dist/collection/utils/modal.js +2 -2
  85. package/dist/components/index.js +1 -1
  86. package/dist/components/{p-Da5i_Sa6.js → p-AO2RGdjH.js} +1 -1
  87. package/dist/components/{p-X-8I-A3g.js → p-B3sb3aIX.js} +1 -1
  88. package/dist/components/{p-CIUE4qr7.js → p-BGb86o0p.js} +1 -1
  89. package/dist/components/{p-C3fqSH7A.js → p-BLhu2So8.js} +1 -1
  90. package/dist/components/{p-INdVvadB.js → p-BSQsJHnV.js} +1 -1
  91. package/dist/components/{p-xX3QT-8K.js → p-BZCvsLRf.js} +1 -1
  92. package/dist/components/{p-BFC3Etk2.js → p-BqrZA_Nl.js} +1 -1
  93. package/dist/components/{p-DS7Ypvt5.js → p-C54v30vB.js} +1 -1
  94. package/dist/components/{p-DlREBZ-C.js → p-CJ-QHG0F.js} +1 -1
  95. package/dist/components/{p-kSfaCwf1.js → p-CbXb6ylI.js} +1 -1
  96. package/dist/components/{p-BRxXhFqt.js → p-CgYjGJEh.js} +1 -1
  97. package/dist/components/{p-CLxVZFEG.js → p-Co3H5873.js} +1 -1
  98. package/dist/components/{p-BRk9YZBe.js → p-Cvk-Luhs.js} +1 -1
  99. package/dist/components/{p-BeBiPTbd.js → p-D5inekTL.js} +1 -1
  100. package/dist/components/{p-Bs1Z5QtN.js → p-DChOBMCc.js} +1 -1
  101. package/dist/components/p-DGlmvjGc.js +1 -0
  102. package/dist/components/p-DQFHAKL_.js +1 -0
  103. package/dist/components/{p-CPuyhF6g.js → p-DUcbofDO.js} +1 -1
  104. package/dist/components/p-DZbc1mgp.js +1 -0
  105. package/dist/components/{p-t161LJqb.js → p-DeK3og10.js} +1 -1
  106. package/dist/components/{p-BjpbUGud.js → p-DmaopssQ.js} +1 -1
  107. package/dist/components/p-DopVneZA.js +1 -0
  108. package/dist/components/p-DrrsZftV.js +1 -0
  109. package/dist/components/{p-CpgTSxf0.js → p-DyZNk1VT.js} +1 -1
  110. package/dist/components/{p-oyZgWRnC.js → p-HK6Bwtz8.js} +1 -1
  111. package/dist/components/{p-Z5Vk33zf.js → p-IThoLpLs.js} +1 -1
  112. package/dist/components/{p-JlZdKw4C.js → p-J3eT660D.js} +1 -1
  113. package/dist/components/p-fpzgqVv1.js +1 -0
  114. package/dist/components/p-iCuIUhaK.js +1 -0
  115. package/dist/components/p-m_OtjUs1.js +1 -0
  116. package/dist/components/{p-BwPmM1Pm.js → p-uHITnW_J.js} +1 -1
  117. package/dist/components/{p-Cx_d5vsS.js → p-yH47DvUh.js} +1 -1
  118. package/dist/components/sd-barcode-input.js +1 -1
  119. package/dist/components/sd-calendar.js +1 -1
  120. package/dist/components/sd-callout.d.ts +11 -0
  121. package/dist/components/sd-callout.js +1 -0
  122. package/dist/components/sd-card.js +1 -1
  123. package/dist/components/sd-checkbox.js +1 -1
  124. package/dist/components/sd-chip.js +1 -1
  125. package/dist/components/sd-circle-progress.js +1 -1
  126. package/dist/components/sd-confirm-modal.js +1 -1
  127. package/dist/components/sd-date-picker-trigger.js +1 -1
  128. package/dist/components/sd-date-picker.js +1 -1
  129. package/dist/components/sd-date-range-picker-calendar.js +1 -1
  130. package/dist/components/sd-date-range-picker.js +1 -1
  131. package/dist/components/sd-dropdown-button.js +1 -1
  132. package/dist/components/sd-field.js +1 -1
  133. package/dist/components/sd-file-picker.js +1 -1
  134. package/dist/components/sd-floating-portal.js +1 -1
  135. package/dist/components/sd-guide.js +1 -1
  136. package/dist/components/sd-input.js +1 -1
  137. package/dist/components/sd-key-value-table.js +1 -1
  138. package/dist/components/sd-linear-progress.js +1 -1
  139. package/dist/components/sd-loading-container.js +1 -1
  140. package/dist/components/sd-loading-modal.js +1 -1
  141. package/dist/components/sd-modal-container.js +1 -1
  142. package/dist/components/sd-number-input.js +1 -1
  143. package/dist/components/sd-pagination.js +1 -1
  144. package/dist/components/sd-popover.js +1 -1
  145. package/dist/components/sd-popup.js +1 -1
  146. package/dist/components/sd-portal.js +1 -1
  147. package/dist/components/sd-select-list-item-search.js +1 -1
  148. package/dist/components/sd-select-list-item.js +1 -1
  149. package/dist/components/sd-select-listbox.js +1 -1
  150. package/dist/components/sd-select-trigger.js +1 -1
  151. package/dist/components/sd-select.js +1 -1
  152. package/dist/components/sd-switch.js +1 -1
  153. package/dist/components/sd-table.js +1 -1
  154. package/dist/components/sd-tabs.js +1 -1
  155. package/dist/components/sd-tag.js +1 -1
  156. package/dist/components/sd-tbody.js +1 -1
  157. package/dist/components/sd-td.js +1 -1
  158. package/dist/components/sd-textarea.js +1 -1
  159. package/dist/components/sd-thead.js +1 -1
  160. package/dist/components/sd-toast-container.js +1 -1
  161. package/dist/components/sd-toast.js +1 -1
  162. package/dist/components/sd-toggle.js +1 -1
  163. package/dist/components/sd-tooltip.js +1 -1
  164. package/dist/components/sd-tr.js +1 -1
  165. package/dist/design-system/design-system.esm.js +1 -1
  166. package/dist/design-system/index.esm.js +1 -1
  167. package/dist/design-system/{p-74bf0ed9.entry.js → p-06a6798d.entry.js} +1 -1
  168. package/dist/design-system/{p-e611dcd4.entry.js → p-0894c492.entry.js} +1 -1
  169. package/dist/design-system/p-14e30f67.entry.js +1 -0
  170. package/dist/design-system/{p-9b9bf9db.entry.js → p-1e530c87.entry.js} +1 -1
  171. package/dist/design-system/{p-84a94775.entry.js → p-2bdceecb.entry.js} +1 -1
  172. package/dist/design-system/{p-a98f9a29.entry.js → p-339cb954.entry.js} +1 -1
  173. package/dist/design-system/{p-a7ea1cf0.entry.js → p-352c68ae.entry.js} +1 -1
  174. package/dist/design-system/p-3d61e68f.entry.js +1 -0
  175. package/dist/design-system/{p-fe3ae346.entry.js → p-3f4a281f.entry.js} +1 -1
  176. package/dist/design-system/p-40bdbe5a.entry.js +1 -0
  177. package/dist/design-system/{p-481e6934.entry.js → p-435ae69e.entry.js} +1 -1
  178. package/dist/design-system/p-4473c051.entry.js +1 -0
  179. package/dist/design-system/p-61f4238b.entry.js +1 -0
  180. package/dist/design-system/p-786c72e9.entry.js +1 -0
  181. package/dist/design-system/{p-00854a0a.entry.js → p-78de36f2.entry.js} +1 -1
  182. package/dist/design-system/p-795bae4c.entry.js +1 -0
  183. package/dist/design-system/p-819e28fe.entry.js +1 -0
  184. package/dist/design-system/{p-32e2d71e.entry.js → p-843d4b16.entry.js} +1 -1
  185. package/dist/design-system/{p-cc97f4b4.entry.js → p-8ee990bd.entry.js} +1 -1
  186. package/dist/design-system/{p-fe0a5368.entry.js → p-9404ab06.entry.js} +1 -1
  187. package/dist/design-system/p-DGlmvjGc.js +1 -0
  188. package/dist/design-system/p-DQFHAKL_.js +1 -0
  189. package/dist/design-system/p-DZbc1mgp.js +1 -0
  190. package/dist/design-system/p-DopVneZA.js +1 -0
  191. package/dist/design-system/{p-e8e64511.entry.js → p-aac84d22.entry.js} +1 -1
  192. package/dist/design-system/{p-f7074386.entry.js → p-b868d747.entry.js} +1 -1
  193. package/dist/design-system/{p-3b8954d9.entry.js → p-b8e34533.entry.js} +1 -1
  194. package/dist/design-system/p-c3e4853c.entry.js +1 -0
  195. package/dist/design-system/{p-11b904a3.entry.js → p-d226bd61.entry.js} +1 -1
  196. package/dist/design-system/{p-dbeaeb31.entry.js → p-d3cc8538.entry.js} +1 -1
  197. package/dist/design-system/{p-ae117afa.entry.js → p-eae21a79.entry.js} +1 -1
  198. package/dist/design-system/{p-e23dac79.entry.js → p-fa670cc4.entry.js} +1 -1
  199. package/dist/esm/{component.table-BnfUIhUj.js → component.table-DQFHAKL_.js} +3 -0
  200. package/dist/esm/design-system.js +1 -1
  201. package/dist/esm/index.js +2 -2
  202. package/dist/esm/loader.js +1 -1
  203. package/dist/esm/sanitize-inline-html-DopVneZA.js +63 -0
  204. package/dist/esm/sd-calendar_2.entry.js +9 -7
  205. package/dist/esm/sd-callout.entry.js +150 -0
  206. package/dist/esm/sd-card.entry.js +1 -1
  207. package/dist/esm/sd-checkbox.entry.js +9 -4
  208. package/dist/esm/sd-chip.entry.js +1 -1
  209. package/dist/esm/sd-circle-progress.entry.js +2 -2
  210. package/dist/esm/sd-confirm-modal_2.entry.js +4 -3
  211. package/dist/esm/sd-date-picker_7.entry.js +9 -9
  212. package/dist/esm/sd-date-range-picker-calendar.entry.js +1 -1
  213. package/dist/esm/sd-dropdown-button.entry.js +6 -5
  214. package/dist/esm/sd-field_3.entry.js +7 -7
  215. package/dist/esm/sd-guide.entry.js +5 -4
  216. package/dist/esm/sd-key-value-table.entry.js +2 -2
  217. package/dist/esm/sd-linear-progress.entry.js +2 -2
  218. package/dist/esm/sd-loading-container.entry.js +2 -2
  219. package/dist/esm/sd-pagination_4.entry.js +28 -37
  220. package/dist/esm/sd-popup.entry.js +6 -5
  221. package/dist/esm/sd-portal.entry.js +1 -1
  222. package/dist/esm/sd-select-list-item_2.entry.js +6 -6
  223. package/dist/esm/sd-select_3.entry.js +8 -8
  224. package/dist/esm/sd-switch.entry.js +1 -1
  225. package/dist/esm/{sd-table.config-B-VgXXT7.js → sd-table.config-CFHtQ8LX.js} +5 -3
  226. package/dist/esm/sd-table.entry.js +37 -36
  227. package/dist/esm/sd-tabs.entry.js +1 -1
  228. package/dist/esm/sd-tag.entry.js +4 -2
  229. package/dist/esm/sd-td.entry.js +18 -9
  230. package/dist/esm/sd-toast-container.entry.js +1 -1
  231. package/dist/esm/sd-toast.entry.js +2 -2
  232. package/dist/esm/sd-toggle.entry.js +1 -1
  233. package/dist/esm/{system-GBlVDmy4.js → system-DGlmvjGc.js} +12 -1
  234. package/dist/types/components/sd-calendar/sd-calendar.d.ts +1 -0
  235. package/dist/types/components/sd-callout/sd-callout.config.d.ts +34 -0
  236. package/dist/types/components/sd-callout/sd-callout.d.ts +11 -0
  237. package/dist/types/components/sd-table/sd-table.d.ts +1 -1
  238. package/dist/types/components/sd-table/sd-td/sd-td.d.ts +2 -2
  239. package/dist/types/components/sd-table/sd-tr/sd-tr.d.ts +1 -2
  240. package/dist/types/components.d.ts +43 -0
  241. package/dist/types/utils/html/sanitize-inline-html.d.ts +1 -0
  242. package/hydrate/index.js +397 -150
  243. package/hydrate/index.mjs +397 -150
  244. package/package.json +1 -1
  245. package/dist/components/p-B8o25hOw.js +0 -1
  246. package/dist/components/p-BkWaPXXj.js +0 -1
  247. package/dist/components/p-BnfUIhUj.js +0 -1
  248. package/dist/components/p-CyObYB-g.js +0 -1
  249. package/dist/components/p-GBlVDmy4.js +0 -1
  250. package/dist/components/p-WAsath62.js +0 -1
  251. package/dist/components/p-mmdt-WnS.js +0 -1
  252. package/dist/design-system/p-563b6fc2.entry.js +0 -1
  253. package/dist/design-system/p-8f4ccae4.entry.js +0 -1
  254. package/dist/design-system/p-9f7f1b8b.entry.js +0 -1
  255. package/dist/design-system/p-BnfUIhUj.js +0 -1
  256. package/dist/design-system/p-GBlVDmy4.js +0 -1
  257. package/dist/design-system/p-a640e509.entry.js +0 -1
  258. package/dist/design-system/p-a97033a2.entry.js +0 -1
  259. package/dist/design-system/p-f721a6c6.entry.js +0 -1
  260. package/dist/design-system/p-fc5c4f85.entry.js +0 -1
  261. package/dist/design-system/p-ffaa4b5d.entry.js +0 -1
  262. package/dist/design-system/p-mmdt-WnS.js +0 -1
@@ -1,7 +1,7 @@
1
1
  import { h, Host, readTask, forceUpdate, } from "@stencil/core";
2
2
  import { nanoid } from "nanoid";
3
3
  import { TABLE_ID_ATTR, } from "./constants";
4
- import { TABLE_RADIUS, TABLE_BORDER, TABLE_BODY_TYPOGRAPHY, TABLE_BODY_LAYOUT } from "./sd-table.config";
4
+ import { TABLE_RADIUS, TABLE_BORDER, TABLE_BODY_TYPOGRAPHY, TABLE_BODY_LAYOUT, } from "./sd-table.config";
5
5
  export class SdTable {
6
6
  static DEFAULT_NO_DATA_LABEL = '데이터가 없습니다.';
7
7
  el;
@@ -31,7 +31,9 @@ export class SdTable {
31
31
  get effectiveRowHeight() {
32
32
  if (this.rowHeight != null)
33
33
  return this.rowHeight;
34
- return this.dense ? Number(TABLE_BODY_LAYOUT.dense.height) : Number(TABLE_BODY_LAYOUT.default.height);
34
+ return this.dense
35
+ ? Number(TABLE_BODY_LAYOUT.dense.height)
36
+ : Number(TABLE_BODY_LAYOUT.default.height);
35
37
  }
36
38
  virtualBuffer = 5;
37
39
  virtualEndThreshold = 10;
@@ -207,6 +209,10 @@ export class SdTable {
207
209
  if (this.pagination?.rowsPerPage != null) {
208
210
  this.innerRowsPerPage = this.pagination.rowsPerPage;
209
211
  }
212
+ // host element 에 자식 컴포넌트(sd-thead/sd-tbody/sd-tr) 가 직접 접근하는 internal sync helpers 를 monkey-patch.
213
+ // 28개 메서드 전체를 typed interface 로 노출하면 코드 비용이 크고, 어차피 internal 이라 외부 사용자가 호출하지 않는다.
214
+ // 정식 @Method 노출로 옮기는 작업은 별도 이슈로 분리.
215
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
210
216
  const el = this.el;
211
217
  el.isRowSelectedSync = this.isRowSelectedSync.bind(this);
212
218
  el.updateRowSelectSync = this.updateRowSelectSync.bind(this);
@@ -225,7 +231,6 @@ export class SdTable {
225
231
  el.unregisterSpanSync = this.unregisterSpanSync.bind(this);
226
232
  el.getSpanSync = this.getSpanSync.bind(this);
227
233
  el.isCoveredSync = this.isCoveredSync.bind(this);
228
- el.isVisualLastRowSync = this.isVisualLastRowSync.bind(this);
229
234
  el.registerSeparatorSync = this.registerSeparatorSync.bind(this);
230
235
  el.unregisterSeparatorSync = this.unregisterSeparatorSync.bind(this);
231
236
  el.isVisualLastRowBeforeSeparatorSync = this.isVisualLastRowBeforeSeparatorSync.bind(this);
@@ -236,6 +241,7 @@ export class SdTable {
236
241
  el.registerUseFrameSync = this.registerUseFrameSync.bind(this);
237
242
  el.unregisterUseFrameSync = this.unregisterUseFrameSync.bind(this);
238
243
  el.hasUseFrameInRowSync = this.hasUseFrameInRowSync.bind(this);
244
+ el.isCellUseFrameSync = this.isCellUseFrameSync.bind(this);
239
245
  if (Array.isArray(this.rows)) {
240
246
  this.rowCount = this.rows.length;
241
247
  this.pushRowsToChildren(this.rows);
@@ -313,10 +319,16 @@ export class SdTable {
313
319
  }
314
320
  });
315
321
  this.noDataContentResizeObserver.observe(target);
316
- const measured = Math.ceil(target.scrollHeight);
317
- this.noDataBodyHeight = Math.max(60, measured);
322
+ readTask(() => {
323
+ if (!this.noDataContentEl)
324
+ return;
325
+ const measured = Math.ceil(this.noDataContentEl.scrollHeight);
326
+ const next = Math.max(60, measured);
327
+ if (next !== this.noDataBodyHeight) {
328
+ this.noDataBodyHeight = next;
329
+ }
330
+ });
318
331
  }
319
- // light DOM(manual mode 자식)과 shadow DOM(autoThead/autoTbody fallback) 양쪽 모두에서 자식을 찾는다.
320
332
  queryChildEl(selector) {
321
333
  return (this.el.querySelector(selector) ??
322
334
  this.el.shadowRoot?.querySelector(selector) ??
@@ -344,12 +356,12 @@ export class SdTable {
344
356
  refreshChildrenSelection() {
345
357
  const thead = this.queryChildEl('sd-thead');
346
358
  thead?.refreshSelection?.();
347
- this.queryAllTr().forEach(tr => tr?.refreshSelection?.());
359
+ this.queryAllTr().forEach(tr => tr.refreshSelection?.());
348
360
  }
349
361
  refreshChildrenConfig() {
350
362
  const thead = this.queryChildEl('sd-thead');
351
363
  thead?.refreshConfig?.();
352
- this.queryAllTr().forEach(tr => tr?.refreshConfig?.());
364
+ this.queryAllTr().forEach(tr => tr.refreshConfig?.());
353
365
  }
354
366
  maybeEmitVirtualReachEnd(start, end) {
355
367
  const threshold = Math.max(1, this.virtualEndThreshold);
@@ -381,6 +393,7 @@ export class SdTable {
381
393
  this.vsEnd = end;
382
394
  const topHeight = start * this.effectiveRowHeight;
383
395
  const bottomHeight = Math.max(0, (this.rowCount - end) * this.effectiveRowHeight);
396
+ // setSpacersSync 는 sd-tbody 가 host element 에 monkey-patch 하는 internal sync helper.
384
397
  const tbody = this.queryChildEl('sd-tbody');
385
398
  tbody?.setSpacersSync?.(topHeight, bottomHeight);
386
399
  if (rangeChanged) {
@@ -438,6 +451,9 @@ export class SdTable {
438
451
  const fields = this.useFrameRegistry.get(rowKey);
439
452
  return fields != null && fields.size > 0;
440
453
  }
454
+ isCellUseFrameSync(rowKey, field) {
455
+ return this.useFrameRegistry.get(rowKey)?.has(field) ?? false;
456
+ }
441
457
  isRowSelectedSync(row) {
442
458
  return Array.from(this.innerSelected).some(r => r[this.rowKey ?? 'id'] === row[this.rowKey ?? 'id']);
443
459
  }
@@ -498,7 +514,7 @@ export class SdTable {
498
514
  this.updateRowsVisibility();
499
515
  }
500
516
  updateRowsVisibility() {
501
- this.queryAllTr().forEach(tr => tr?.updateVisibility?.());
517
+ this.queryAllTr().forEach(tr => tr.updateVisibility?.());
502
518
  }
503
519
  changeRowsPerPage(perPage) {
504
520
  const changedRowsPerPage = perPage != null && perPage !== '' ? Number(perPage) : 0;
@@ -537,7 +553,7 @@ export class SdTable {
537
553
  this.columnWidths = this.columnWidths.map((width, idx) => (idx === index ? newWidth : width));
538
554
  const thead = this.queryChildEl('sd-thead');
539
555
  thead?.setColumnWidths?.(this.columnWidths);
540
- this.queryAllTr().forEach(tr => tr?.setColumnWidths?.(this.columnWidths));
556
+ this.queryAllTr().forEach(tr => tr.setColumnWidths?.(this.columnWidths));
541
557
  const stickyRightCount = this.stickyColumn?.right || 0;
542
558
  const visibleColCount = this.columns.filter(c => c.visible !== false).length;
543
559
  const isRightStickyEdgeResizer = stickyRightCount > 0 && index === visibleColCount - stickyRightCount;
@@ -592,9 +608,8 @@ export class SdTable {
592
608
  // 경우가 있어, sd-tr의 @State (spansVersion)을 통해 재렌더를 강제한다.
593
609
  requestAllTrUpdate() {
594
610
  this.queryAllTr().forEach(tr => {
595
- const trAny = tr;
596
- if (typeof trAny.bumpSpansVersion === 'function') {
597
- trAny.bumpSpansVersion();
611
+ if (typeof tr.bumpSpansVersion === 'function') {
612
+ tr.bumpSpansVersion();
598
613
  }
599
614
  else {
600
615
  forceUpdate(tr);
@@ -709,7 +724,7 @@ export class SdTable {
709
724
  return false;
710
725
  }
711
726
  // rowspan을 반영한 셀의 시각적 하단 행 인덱스를 반환한다.
712
- // isVisualLastRowSync·isVisualLastRowBeforeSeparatorSync 공통 헬퍼.
727
+ // isVisualLastRowBeforeSeparatorSync 헬퍼.
713
728
  resolveVisualBottom(rowKey, field) {
714
729
  const myRowIdx = this.resolveRowIndex(rowKey);
715
730
  if (myRowIdx == null)
@@ -718,20 +733,6 @@ export class SdTable {
718
733
  const rs = Math.max(1, span?.rowspan ?? 1);
719
734
  return myRowIdx + rs - 1;
720
735
  }
721
- // 셀의 시각적 하단이 테이블(또는 현재 페이지)의 마지막 행인지 판정.
722
- // 마지막 행에 border-bottom: none을 적용하기 위함.
723
- isVisualLastRowSync(rowKey, field) {
724
- if (this.rowCount <= 0)
725
- return false;
726
- const visualBottom = this.resolveVisualBottom(rowKey, field);
727
- if (visualBottom == null)
728
- return false;
729
- const pageInfo = this.getPaginationInfoSync();
730
- const lastVisibleIdx = pageInfo
731
- ? Math.min(pageInfo.endIndex - 1, this.rowCount - 1)
732
- : this.rowCount - 1;
733
- return visualBottom === lastVisibleIdx;
734
- }
735
736
  registerSeparatorSync(prevRowKey) {
736
737
  const idx = this.resolveRowIndex(prevRowKey);
737
738
  if (idx != null)
@@ -848,25 +849,25 @@ export class SdTable {
848
849
  '--table-body-line-height': `${TABLE_BODY_TYPOGRAPHY.lineHeight}px`,
849
850
  '--table-body-text-decoration': TABLE_BODY_TYPOGRAPHY.textDecoration,
850
851
  };
851
- return (h(Host, { key: '02d716bdac3832710bf58d63741aeeb4b04d434b', style: hostStyle }, h("div", { key: '88faad346e032ca727375889aa0552a330f5799a', class: "sd-table__container", style: {
852
+ return (h(Host, { key: '9ee5b528b330f9edf406ff40ec089136c0807653', style: hostStyle }, h("div", { key: '9ac6cbba84b7ef7d0897474168748811fb15af92', class: "sd-table__container", style: {
852
853
  '--table-width': this.width,
853
854
  '--table-height': effectiveTableHeight,
854
855
  '--table-container-height': `calc(${effectiveTableHeight} - ${paginationHeight}px)`,
855
- } }, h("div", { key: '783934f349e0da5bab77cbb44cc12f0dfeb9ec71', class: {
856
+ } }, h("div", { key: '11f916debfd443e1d243bfa2335dbb0a3cb094bc', class: {
856
857
  'sd-table__wrapper': true,
857
858
  'sd-table__wrapper--radius-use-top': this.radius === 'useTop',
858
- } }, h("div", { key: 'd3a76ad0e853c6adf16df633c0e0b7f5bb580f24', class: {
859
+ } }, h("div", { key: '3cad3d86f731a3edc0d2b5a680bcaf6ad6be7399', class: {
859
860
  'sd-table__scroll-container': true,
860
861
  'sd-table__scroll-container--loading': this.isLoading,
861
862
  'sd-table__scroll-container--no-data': isNoData,
862
- } }, this.isLoading && (h("div", { key: 'cc77ce58ff0eebf3fc1d7dd9dbf11578f94d4dd1', class: "sd-table__loading", style: { top: `${this.loadingScrollTop}px` } }, h("sd-circle-progress", { key: 'bda7ed774342089a23d13b49a506b04527026275', indeterminate: true }))), isNoData && (h(h.Fragment, null, h("div", { key: 'f2ce89d0ae9eefe0f0f8509e477756cb74dbef86', class: "sd-table__no-data-header-overlay" }), h("div", { key: '84d739563123d0f0fc33166b1a6e80021ba06e1c', class: "sd-table__no-data" }, h("div", { key: '3507f718a25b79c44fdf283fb41356ab72f2a384', class: "sd-table__no-data-content", ref: el => {
863
+ } }, this.isLoading && (h("div", { key: '6f0aac84dcb3d9ca721ed82cd45214b3956d3f94', class: "sd-table__loading", style: { top: `${this.loadingScrollTop}px` } }, h("sd-circle-progress", { key: '8bb6b8025fceee6ef856efd9cafefe925fc95272', indeterminate: true }))), isNoData && (h(h.Fragment, null, h("div", { key: '69e6e22b68261832a299de470c8ca7f5a16205dd', class: "sd-table__no-data-header-overlay" }), h("div", { key: 'c797a2d41c752698bed1f034beefddc4bf8b951d', class: "sd-table__no-data" }, h("div", { key: '0f0306bc89b5d9046de2aec935822eab0c3ca36c', class: "sd-table__no-data-content", ref: el => {
863
864
  this.noDataContentEl = el;
864
865
  if (el)
865
866
  this.syncNoDataContentObserver();
866
- } }, h("slot", { key: '818129819b2ff4a6f9fc1224dc59a9aa5861296d', name: "no-data" }, h("span", { key: 'c03cfb713e6dadd5ab4c60d7d27fd502d7aa9348' }, this.resolvedNoDataLabel)))))), h("table", { key: '8864714a828069985bac6535bc40cbb043dfcb28', class: this.tableClasses }, this.autoThead ? (h("slot", { name: `${resolvedTableId}-head`, onSlotchange: this.handleStructureSlotChange }, h("sd-thead", { rows: this.rows ?? [] }))) : (h("slot", { name: `${resolvedTableId}-head`, onSlotchange: this.handleStructureSlotChange })), this.autoTbody ? (h("slot", { name: `${resolvedTableId}-body`, onSlotchange: this.handleStructureSlotChange }, h("sd-tbody", { rows: this.rows ?? [] }, this.renderAutoRows()))) : (h("slot", { name: `${resolvedTableId}-body`, onSlotchange: this.handleStructureSlotChange }))))), this.pagination &&
867
+ } }, h("slot", { key: '042671d4c65c4031a756da386ed010146c17f736', name: "no-data" }, h("span", { key: '5994f656dbea3fd1dea69c105907b188658f8c41' }, this.resolvedNoDataLabel)))))), h("table", { key: '16bb3a7c6b32e5312eda79015cd7d90bef37bdff', class: this.tableClasses }, this.autoThead ? (h("slot", { name: `${resolvedTableId}-head`, onSlotchange: this.handleStructureSlotChange }, h("sd-thead", { rows: this.rows ?? [] }))) : (h("slot", { name: `${resolvedTableId}-head`, onSlotchange: this.handleStructureSlotChange })), this.autoTbody ? (h("slot", { name: `${resolvedTableId}-body`, onSlotchange: this.handleStructureSlotChange }, h("sd-tbody", { rows: this.rows ?? [] }, this.renderAutoRows()))) : (h("slot", { name: `${resolvedTableId}-body`, onSlotchange: this.handleStructureSlotChange }))))), this.pagination &&
867
868
  this.pagination.rowsPerPage > 0 &&
868
869
  this.rowCount > 0 &&
869
- !this.useVirtualScroll && (h("div", { key: 'bdac4b4d551152ec7ee0cdc31bfb992748836928', class: "sd-table__pagination" }, h("sd-pagination", { key: '2c60fff7f8ac3a3bd22da2173b8a9187bb686ddf', currentPage: !this.useInternalPagination ? this.pagination.page : this.currentPage, lastPage: !this.useInternalPagination ? this.pagination.lastPage : this.lastPageNumber, onSdPageChange: (e) => this.changePage(e.detail) }), this.useRowsPerPageSelect && (h("sd-select", { key: '7a662f58e13c15e705341773570f899f503f12c0', value: this.useInternalPagination
870
+ !this.useVirtualScroll && (h("div", { key: '6c3ee5d93fb395154c4c42c914669af535c1a5bc', class: "sd-table__pagination" }, h("sd-pagination", { key: '46053012374e1255037706a8fa4d068dbc60f2d9', currentPage: !this.useInternalPagination ? this.pagination.page : this.currentPage, lastPage: !this.useInternalPagination ? this.pagination.lastPage : this.lastPageNumber, onSdPageChange: (e) => this.changePage(e.detail) }), this.useRowsPerPageSelect && (h("sd-select", { key: 'df04b19e857e823be8237148d84456d492575ce3', value: this.useInternalPagination
870
871
  ? this.innerRowsPerPage
871
872
  : this.pagination.rowsPerPage, options: this.rowsPerPageOption, width: "128px", emitValue: true, onSdUpdate: e => {
872
873
  if (!this.isRowsPerPageValue(e.detail))
@@ -45,9 +45,9 @@ export class SdTbody {
45
45
  }
46
46
  }
47
47
  render() {
48
- return (h(Host, { key: 'bdb686445ce324c6254891a385d6175c8cac06df', slot: `${this.tableId}-body` }, h("tbody", { key: '21a7772f0d43a358d9ae17459f0ff296324bfd82', class: { tbody: true } }, [
48
+ return (h(Host, { key: 'a3d0ee1c1820474e97e430ba91f48e12ee0e252d', slot: `${this.tableId}-body` }, h("tbody", { key: 'bbd5b9acf02150b146c9b25d07f2e7a9dd347921', class: { tbody: true } }, [
49
49
  this.topSpacerHeight > 0 && (h("tr", { key: "spacer-top", class: "tbody__spacer", style: { height: `${this.topSpacerHeight}px`, display: 'block' } })),
50
- h("slot", { key: 'e38d8fe5d67a91d3fa5a25be98195da104660005' }),
50
+ h("slot", { key: 'f0ec0aa4d7e7190fc93d96afe5591004174fff63' }),
51
51
  this.bottomSpacerHeight > 0 && (h("tr", { key: "spacer-bottom", class: "tbody__spacer", style: { height: `${this.bottomSpacerHeight}px`, display: 'block' } })),
52
52
  ])));
53
53
  }
@@ -19,11 +19,13 @@ export class SdTd {
19
19
  this.syncSlotName();
20
20
  this.syncSpanRegistration();
21
21
  this.syncCellClassRegistration(oldField);
22
+ this.syncUseFrameRegistration(oldField);
22
23
  }
23
24
  handleRowKeyChange(_newKey, oldKey) {
24
25
  this.syncSlotName();
25
26
  this.syncSpanRegistration();
26
27
  this.syncCellClassRegistration(undefined, oldKey);
28
+ this.syncUseFrameRegistration(undefined, oldKey);
27
29
  }
28
30
  handleSpanChange() {
29
31
  this.syncSpanRegistration();
@@ -34,15 +36,15 @@ export class SdTd {
34
36
  handleDividerChange() {
35
37
  this.syncCellClassRegistration();
36
38
  }
37
- handleUseFieldChange() {
38
- this.syncUseFieldRegistration();
39
+ handleUseFrameChange() {
40
+ this.syncUseFrameRegistration();
39
41
  this.requestParentTrUpdate();
40
42
  }
41
43
  componentWillLoad() {
42
44
  this.syncSlotName();
43
45
  this.syncSpanRegistration();
44
46
  this.syncCellClassRegistration();
45
- this.syncUseFieldRegistration();
47
+ this.syncUseFrameRegistration();
46
48
  // slot 타이밍 엇갈림 대응: 부모 sd-tr forceUpdate로 슬롯 재매칭
47
49
  const parentTr = this.el.parentElement;
48
50
  if (parentTr?.tagName?.toLowerCase() === 'sd-tr') {
@@ -53,7 +55,7 @@ export class SdTd {
53
55
  this.syncSlotName();
54
56
  this.syncSpanRegistration();
55
57
  this.syncCellClassRegistration();
56
- this.syncUseFieldRegistration();
58
+ this.syncUseFrameRegistration();
57
59
  }
58
60
  // React StrictMode에서는 disconnect/reconnect 사이클이 일어나면서
59
61
  // 동일 인스턴스의 componentWillLoad는 더 이상 호출되지 않는다.
@@ -61,7 +63,7 @@ export class SdTd {
61
63
  connectedCallback() {
62
64
  this.syncSpanRegistration();
63
65
  this.syncCellClassRegistration();
64
- this.syncUseFieldRegistration();
66
+ this.syncUseFrameRegistration();
65
67
  }
66
68
  disconnectedCallback() {
67
69
  const table = this.findTable();
@@ -118,9 +120,16 @@ export class SdTd {
118
120
  table.registerCellClassSync(String(this.rowKey), this.field, combinedClass);
119
121
  this.requestParentTrUpdate();
120
122
  }
121
- syncUseFieldRegistration() {
123
+ syncUseFrameRegistration(prevField, prevRowKey) {
122
124
  const table = this.findTable();
123
- if (!table || this.field === '' || this.rowKey == null)
125
+ if (!table)
126
+ return;
127
+ const oldField = prevField ?? this.field;
128
+ const oldRowKey = prevRowKey ?? (this.rowKey != null ? String(this.rowKey) : undefined);
129
+ if (oldField !== '' && oldRowKey != null) {
130
+ table.unregisterUseFrameSync?.(oldRowKey, oldField);
131
+ }
132
+ if (this.field === '' || this.rowKey == null)
124
133
  return;
125
134
  if (this.useFrame) {
126
135
  table.registerUseFrameSync?.(String(this.rowKey), this.field);
@@ -141,7 +150,7 @@ export class SdTd {
141
150
  }
142
151
  }
143
152
  render() {
144
- return (h(Host, { key: '7d51ea5f02ba2df099f4440be26c2f0be8a73a6b', class: { [`align-${this.align}`]: Boolean(this.align) } }, h("slot", { key: '9a6a634e2bcd206ec9099c6be738c3853d0cbebf' })));
153
+ return (h(Host, { key: '91c033a0c4c3a6c3c9b29c0be99912c5ac1283ee', class: { [`align-${this.align}`]: Boolean(this.align) } }, h("slot", { key: 'abfbc911c707012bc7d924e328ba07d71b96f9a9' })));
145
154
  }
146
155
  static get is() { return "sd-td"; }
147
156
  static get originalStyleUrls() {
@@ -357,7 +366,7 @@ export class SdTd {
357
366
  "methodName": "handleDividerChange"
358
367
  }, {
359
368
  "propName": "useFrame",
360
- "methodName": "handleUseFieldChange"
369
+ "methodName": "handleUseFrameChange"
361
370
  }];
362
371
  }
363
372
  }
@@ -157,16 +157,16 @@ export class SdThead {
157
157
  '--table-border-color': TABLE_BORDER.color,
158
158
  '--table-border-width': `${TABLE_BORDER.width}px`,
159
159
  };
160
- return (h(Host, { key: 'c2852fc7d6fe9e8116fabbbcc140f4db8319bfdc', slot: `${this.tableId}-head`, style: headStyle }, h("thead", { key: '970cb1c96145326f38b79636a72982b0e9c81fa0', class: {
160
+ return (h(Host, { key: '234ca55bb2507aef21df976066e5ce377c2e9e89', slot: `${this.tableId}-head`, style: headStyle }, h("thead", { key: 'fecd6b54f72a8643b663c3af1988eed60300d08d', class: {
161
161
  'thead': true,
162
162
  'thead--sticky': this._stickyHeader,
163
- } }, h("tr", { key: '839fb6e9fd68ef10dea1f1d470a6b3e707475a8d', class: "tr" }, this._selectable && (h("th", { key: 'd669372261627013bc1b39157139d180b3d1a6c1', class: {
163
+ } }, h("tr", { key: '21d56c50076d3340733b7fa0a8e569fec005e415', class: "tr" }, this._selectable && (h("th", { key: 'ace570ae2157ae63a21ec6ba60d8b8898dd0c33c', class: {
164
164
  'th': true,
165
165
  'th--selected': true,
166
166
  'sticky-left': true,
167
167
  'sticky-left-edge': stickyLeftCount === 0,
168
168
  'is-scrolled-left': stickyLeftCount === 0 && this._scrolledLeft,
169
- }, style: { '--sticky-left-offset': '0px' } }, h("sd-checkbox", { key: '6263984430b4aa53e6ac24fb0f6a6c05838a71d5', value: this.getIsAllChecked(), disabled: safeRows.length === 0, onSdUpdate: (e) => this.handleSelectAll(e.detail) }))), stickyLeftCols.map((col, idx) => (h("th", { key: col.name, class: {
169
+ }, style: { '--sticky-left-offset': '0px' } }, h("sd-checkbox", { key: '4b30536f427b9985355c4e22b6b532a3033306c0', value: this.getIsAllChecked(), disabled: safeRows.length === 0, onSdUpdate: (e) => this.handleSelectAll(e.detail) }))), stickyLeftCols.map((col, idx) => (h("th", { key: col.name, class: {
170
170
  'th': true,
171
171
  [`${col.thClass}`]: Boolean(col.thClass),
172
172
  'sticky-left': true,
@@ -14,6 +14,9 @@ sd-tr * {
14
14
  .tr--no-hover:hover .td {
15
15
  background-color: white;
16
16
  }
17
+ .tr--separator:hover .td {
18
+ background-color: var(--table-separator-color, #eeeeee);
19
+ }
17
20
 
18
21
  .td {
19
22
  display: table-cell;
@@ -118,8 +121,9 @@ sd-tr * {
118
121
  background-color: white;
119
122
  }
120
123
 
121
- .td.td--last-row {
122
- border-bottom: none;
124
+ .tr--separator:hover .td.sticky-left,
125
+ .tr--separator:hover .td.sticky-right {
126
+ background-color: var(--table-separator-color, #eeeeee);
123
127
  }
124
128
 
125
129
  .tr--separator .td--separator {
@@ -170,6 +170,13 @@ export class SdTr {
170
170
  const fieldName = typeof col.field === 'string' ? col.field : col.name;
171
171
  return this.tableEl.getCellClassSync(this.rowKey, fieldName);
172
172
  }
173
+ getFramePaddingStyle(field) {
174
+ if (!this._dense)
175
+ return undefined;
176
+ if (!(this.tableEl?.isCellUseFrameSync?.(this.rowKey, field) ?? false))
177
+ return undefined;
178
+ return { padding: `${TABLE_BODY_LAYOUT.framePadding}px` };
179
+ }
173
180
  expandCellClass(classStr) {
174
181
  if (classStr == null || classStr === '')
175
182
  return {};
@@ -178,20 +185,6 @@ export class SdTr {
178
185
  .filter(Boolean)
179
186
  .map(c => [c, true]));
180
187
  }
181
- isVisualLastRow(col) {
182
- if (!this.tableEl?.isVisualLastRowSync)
183
- return false;
184
- const fieldName = typeof col.field === 'string' ? col.field : col.name;
185
- return this.tableEl.isVisualLastRowSync(this.rowKey, fieldName);
186
- }
187
- // selectable td는 column 정보가 없으므로 빈 field로 평가한다.
188
- // 해당 위치는 rowspan을 등록할 수 없으므로 spanRegistry에 매칭이 없고,
189
- // 결과적으로 "내 row 자체가 시각적 마지막인지"가 판정된다.
190
- isVisualLastRowForSelfRow() {
191
- if (!this.tableEl?.isVisualLastRowSync)
192
- return false;
193
- return this.tableEl.isVisualLastRowSync(this.rowKey, '');
194
- }
195
188
  isVisualLastRowBeforeSeparator(col) {
196
189
  if (!this.tableEl?.isVisualLastRowBeforeSeparatorSync)
197
190
  return false;
@@ -212,12 +205,13 @@ export class SdTr {
212
205
  const hasRowspan = this.tableEl?.hasRowspanSync?.() ?? false;
213
206
  const isUseFrameRow = this.tableEl?.hasUseFrameInRowSync?.(this.rowKey) ?? false;
214
207
  const effectiveDense = this._dense && !isUseFrameRow;
215
- const bodyLayout = effectiveDense ? TABLE_BODY_LAYOUT.dense : TABLE_BODY_LAYOUT.default;
208
+ const rowLayoutY = effectiveDense ? TABLE_BODY_LAYOUT.dense : TABLE_BODY_LAYOUT.default;
209
+ const rowPaddingX = this._dense && isUseFrameRow ? TABLE_BODY_LAYOUT.paddingX : TABLE_BODY_LAYOUT.paddingX;
216
210
  const rowStyle = {
217
211
  'display': this.isVisible ? '' : 'none',
218
- '--table-body-height': `${bodyLayout.height}px`,
219
- '--table-body-padding-y': `${bodyLayout.paddingY}px`,
220
- '--table-body-padding-x': `${TABLE_BODY_LAYOUT.paddingX}px`,
212
+ '--table-body-height': `${rowLayoutY.height}px`,
213
+ '--table-body-padding-y': `${rowLayoutY.paddingY}px`,
214
+ '--table-body-padding-x': `${rowPaddingX}px`,
221
215
  '--table-body-font-family': TABLE_BODY_TYPOGRAPHY.fontFamily,
222
216
  '--table-body-font-weight': TABLE_BODY_TYPOGRAPHY.fontWeight,
223
217
  '--table-body-font-size': `${TABLE_BODY_TYPOGRAPHY.fontSize}px`,
@@ -235,7 +229,6 @@ export class SdTr {
235
229
  return (h(Host, { style: rowStyle }, h("tr", { class: { 'tr': true, 'tr--no-hover': hasRowspan } }, this._selectable && (h("td", { class: {
236
230
  'td': true,
237
231
  'td--selected': true,
238
- 'td--last-row': this.isVisualLastRowForSelfRow(),
239
232
  'td--before-separator': this.isVisualLastRowBeforeSeparatorForSelfRow(),
240
233
  'sticky-left': true,
241
234
  'sticky-left-edge': stickyLeftCount === 0,
@@ -243,19 +236,19 @@ export class SdTr {
243
236
  }, style: { '--sticky-left-offset': '0px' } }, h("sd-checkbox", { value: this.isSelected(), onSdUpdate: () => this.handleSelect() }))), stickyLeftCols.map((col, idx) => {
244
237
  if (this.isCovered(idx))
245
238
  return null;
239
+ const fieldName = typeof col.field === 'string' ? col.field : col.name;
246
240
  const span = this.getSpanFor(col);
247
241
  const sdCellClass = this.getCellClassFor(col);
248
242
  return (h("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
249
243
  'td': true,
250
244
  [`td--${col.align || 'left'}`]: true,
251
- 'td--last-row': this.isVisualLastRow(col),
252
245
  'td--before-separator': this.isVisualLastRowBeforeSeparator(col),
253
246
  'sticky-left': true,
254
247
  'sticky-left-edge': idx === stickyLeftCount - 1,
255
248
  'is-scrolled-left': idx === stickyLeftCount - 1 && this._scrolledLeft,
256
249
  [`${col.tdClass}`]: Boolean(col.tdClass),
257
250
  ...this.expandCellClass(sdCellClass),
258
- }, style: this.getStickyStyle(idx) }, h("slot", { name: `${this.tableId}-${typeof col.field === 'string' ? col.field : col.name}-${this.rowKey}` }, h("span", null, this.getCellValue(col)))));
251
+ }, style: { ...this.getStickyStyle(idx), ...this.getFramePaddingStyle(fieldName) } }, h("slot", { name: `${this.tableId}-${fieldName}-${this.rowKey}` }, h("span", null, this.getCellValue(col)))));
259
252
  }), middleCols.map((col, relativeIdx) => {
260
253
  const actualColIdx = stickyLeftCount + relativeIdx;
261
254
  if (this.isCovered(actualColIdx))
@@ -266,11 +259,10 @@ export class SdTr {
266
259
  return (h("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
267
260
  'td': true,
268
261
  [`td--${col.align || 'left'}`]: true,
269
- 'td--last-row': this.isVisualLastRow(col),
270
262
  'td--before-separator': this.isVisualLastRowBeforeSeparator(col),
271
263
  [`${col.tdClass}`]: Boolean(col.tdClass),
272
264
  ...this.expandCellClass(sdCellClass),
273
- }, style: this.getStickyStyle(actualColIdx) }, h("slot", { name: `${this.tableId}-${fieldName}-${this.rowKey}` }, h("span", null, this.getCellValue(col)))));
265
+ }, style: { ...this.getStickyStyle(actualColIdx), ...this.getFramePaddingStyle(fieldName) } }, h("slot", { name: `${this.tableId}-${fieldName}-${this.rowKey}` }, h("span", null, this.getCellValue(col)))));
274
266
  }), stickyRightCols.map((col, relativeIdx) => {
275
267
  const actualColIdx = this.visibleColumns.length - stickyRightCount + relativeIdx;
276
268
  if (this.isCovered(actualColIdx))
@@ -281,14 +273,13 @@ export class SdTr {
281
273
  return (h("td", { key: col.name, rowSpan: span?.rowspan, colSpan: span?.colspan, class: {
282
274
  'td': true,
283
275
  [`td--${col.align || 'left'}`]: true,
284
- 'td--last-row': this.isVisualLastRow(col),
285
276
  'td--before-separator': this.isVisualLastRowBeforeSeparator(col),
286
277
  'sticky-right': true,
287
278
  'sticky-right-edge': relativeIdx === 0,
288
279
  'is-scrolled-right': relativeIdx === 0 && this._scrolledRight,
289
280
  [`${col.tdClass}`]: Boolean(col.tdClass),
290
281
  ...this.expandCellClass(sdCellClass),
291
- }, style: this.getStickyStyle(actualColIdx) }, h("slot", { name: `${this.tableId}-${fieldName}-${this.rowKey}` }, h("span", null, this.getCellValue(col)))));
282
+ }, style: { ...this.getStickyStyle(actualColIdx), ...this.getFramePaddingStyle(fieldName) } }, h("slot", { name: `${this.tableId}-${fieldName}-${this.rowKey}` }, h("span", null, this.getCellValue(col)))));
292
283
  }))));
293
284
  }
294
285
  static get is() { return "sd-tr"; }
@@ -67,7 +67,7 @@ export class SdTabs {
67
67
  };
68
68
  }
69
69
  render() {
70
- return (h("div", { key: '880f1aa80c29f2d578ffe2d5e5e5e0c008c898d3', class: this.getContainerClasses(), style: this.buildCssVars() }, this.tabs.map((tab, index) => {
70
+ return (h("div", { key: '181916a72512a6802a06dc56fca418a806d18a0e', class: this.getContainerClasses(), style: this.buildCssVars() }, this.tabs.map((tab, index) => {
71
71
  const badgeName = this.getBadgeName(tab);
72
72
  return (h("div", { key: `tab-${index}`, role: "tab", tabindex: 0, "aria-selected": tab.value === this.value ? 'true' : 'false', class: this.getTabClasses(tab), "aria-label": tab.label || 'tab', onClick: () => this.handleTabClick(tab), onKeyDown: e => {
73
73
  if (e.key === 'Enter' || e.key === ' ') {
@@ -4,6 +4,8 @@ export class SdTag {
4
4
  name = 'square_sm_grey';
5
5
  label = '';
6
6
  icon;
7
+ // 아이콘이 좌측 배치되는 게 자연스러운 default. prop 이름 변경(isRight 등)은 public API breaking 이라 별도 이슈로 분리.
8
+ // eslint-disable-next-line stencil/ban-default-true
7
9
  isLeft = true;
8
10
  componentWillLoad() {
9
11
  this.name = this.name ?? 'square_sm_grey';
@@ -25,7 +27,7 @@ export class SdTag {
25
27
  render() {
26
28
  const config = this.resolvedConfig;
27
29
  const iconNode = this.renderIcon(config.icon, config.iconSize);
28
- return (h("span", { key: '57f3c3f9ad53059fabff205cb44ffa3d1da9a711', class: "sd-tag", style: {
30
+ return (h("span", { key: 'c8b8b88e2c83401bb9d3e05004b0517d7e4a3a6a', class: "sd-tag", style: {
29
31
  '--sd-tag-background': config.background,
30
32
  '--sd-tag-content': config.content,
31
33
  '--sd-tag-height': config.height,
@@ -35,7 +37,7 @@ export class SdTag {
35
37
  '--sd-tag-font-weight': config.fontWeight,
36
38
  '--sd-tag-line-height': config.lineHeight,
37
39
  '--sd-tag-radius': config.radius,
38
- }, "aria-label": this.label || 'tag' }, this.icon && this.isLeft && iconNode, h("span", { key: '3360f36d18f073cd24699b6b8db2e731fda351ac', class: "sd-tag__label" }, this.label), this.icon && !this.isLeft && iconNode));
40
+ }, "aria-label": this.label || 'tag' }, this.icon && this.isLeft && iconNode, h("span", { key: '67094b09ab1d7b7e865c9f6b8017f8c5c3f8274a', class: "sd-tag__label" }, this.label), this.icon && !this.isLeft && iconNode));
39
41
  }
40
42
  static get is() { return "sd-tag"; }
41
43
  static get originalStyleUrls() {
@@ -105,7 +105,7 @@ export class SdTextarea {
105
105
  '--sd-system-size-field-sm-height': 'auto',
106
106
  '--sd-system-radius-field-sm': `${TEXTAREA_TOKENS.radius}px`,
107
107
  };
108
- return (h("sd-field", { key: '404175c94949c2510082df905c53e97ab835369c', 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, readonly: this.readonly, 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 }, h("div", { key: 'ca92dfe613b2c006ecc4021bb2f07a2e4b04239a', class: "sd-textarea__content" }, h("textarea", { key: 'a6d2bbdb9c88766182728cf3eb30ce7691fb048f', 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 }))));
108
+ return (h("sd-field", { key: 'd877d2598cad84c2bf495e76e0cc1d087f52cc8e', 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, readonly: this.readonly, 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 }, h("div", { key: 'c4e864b958b806d4ecc293bd47375dabe0b9e825', class: "sd-textarea__content" }, h("textarea", { key: '8d12c0178392c07150f0fdde5bab4c0e91534efb', 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 }))));
109
109
  }
110
110
  static get is() { return "sd-textarea"; }
111
111
  static get originalStyleUrls() {
@@ -17,12 +17,12 @@ export class SdToast {
17
17
  const linkColor = typeConfig.linkColor ?? typeConfig.content;
18
18
  const useDefaultCloseIntent = ['default', 'caution', 'info'].includes(this.type);
19
19
  const buttonName = TOAST_BUTTON_NAME_BY_TYPE[this.type] ?? TOAST_BUTTON_NAME_BY_TYPE.default;
20
- return (h("div", { key: 'db3ffaf51dc96c39c05558017f25929c679a59df', style: {
20
+ return (h("div", { key: '82579581897d7845b95456ccb5e2a1745c84bcc5', style: {
21
21
  '--sd-toast-bg': typeConfig.bg,
22
22
  '--sd-toast-text': typeConfig.content,
23
23
  '--sd-toast-icon': iconColor,
24
24
  '--sd-toast-link': linkColor,
25
- } }, h("div", { key: '92344f5bb95b0d4787591207f2e017d7dd177091', class: "sd-toast", role: "status", "aria-live": "polite", "aria-atomic": "true" }, this.icon && (h("div", { key: '991db58b2cb019dd3a787e000e9d8813014bbb09', class: "sd-toast__icon" }, h("sd-icon", { key: '24d53cd77fdea82ec07663a8968493ec2b794751', name: this.icon, size: iconSize, color: iconColor }))), h("div", { key: '70cfad4ef389cca798be9baeac99bfc41efcc615', class: "sd-toast__content" }, h("span", { key: '5927023435b17dc25ee07630fc4ae4568aadd9b9', class: "sd-toast__message" }, this.message)), this.link && (h("a", { key: '410c024fd81ebcc78175c1855a86f590566d1a81', href: this.link, class: "sd-toast__link", target: "_blank", rel: "noopener noreferrer" }, this.linkLabel || this.link)), this.buttonLabel && (h("sd-button", { key: 'd85287e7ef796a11f850a0ce5cde87f5881fa5c9', class: "sd-toast__button", name: buttonName, label: this.buttonLabel, onSdClick: (event) => this.buttonClick.emit(event.detail) })), this.useClose && (h("sd-ghost-button", { key: '55a6bf6457bd89254f6eb01072d46a0edbb8b510', class: "sd-toast__close", icon: "close", intent: useDefaultCloseIntent ? 'default' : 'inverse', ariaLabel: "close", size: "xs", onClick: () => this.close.emit() })))));
25
+ } }, h("div", { key: '5f41392a25dee4e53917255453c97c2203940f21', class: "sd-toast", role: "status", "aria-live": "polite", "aria-atomic": "true" }, this.icon && (h("div", { key: '8f38f7c9842ec295510135589a63994011a856f4', class: "sd-toast__icon" }, h("sd-icon", { key: '62ef897ddfc3b47fe7b640d430d0baf95bdb5b51', name: this.icon, size: iconSize, color: iconColor }))), h("div", { key: 'f6db6cb9776cb41400c9a9052cdea94990245298', class: "sd-toast__content" }, h("span", { key: 'fbd7cdd72422e9ad08f99302b4dcd607d058926f', class: "sd-toast__message" }, this.message)), this.link && (h("a", { key: 'f599928ad9d0d7536086d7dd2d1ce65b429fd8f4', href: this.link, class: "sd-toast__link", target: "_blank", rel: "noopener noreferrer" }, this.linkLabel || this.link)), this.buttonLabel && (h("sd-button", { key: '2be68a412c4b6b9dac64dbd89447c4905fa7512f', class: "sd-toast__button", name: buttonName, label: this.buttonLabel, onSdClick: (event) => this.buttonClick.emit(event.detail) })), this.useClose && (h("sd-ghost-button", { key: '065030362b37383ee7ae31e9b8a771b160427cbe', class: "sd-toast__close", icon: "close", intent: useDefaultCloseIntent ? 'default' : 'inverse', ariaLabel: "close", size: "xs", onClick: () => this.close.emit() })))));
26
26
  }
27
27
  static get is() { return "sd-toast"; }
28
28
  static get originalStyleUrls() {
@@ -216,7 +216,7 @@ export class SdToastContainer {
216
216
  const activeToasts = toasts.filter(t => t.state !== 'exiting').reverse();
217
217
  const indexMap = new Map();
218
218
  activeToasts.forEach((t, i) => indexMap.set(t.id, i));
219
- return (h("div", { key: 'bc3c9591b6453eed7df462841e29784c29b3aeef', class: "sd-toast-container", style: this.getContainerStyles(), onMouseEnter: () => {
219
+ return (h("div", { key: 'c80d46b63f50591d4d92b810c0625701e4741e3a', class: "sd-toast-container", style: this.getContainerStyles(), onMouseEnter: () => {
220
220
  this.expanded = true;
221
221
  this.pauseTimers();
222
222
  }, onMouseLeave: () => {
@@ -45,7 +45,7 @@ export class SdToggle {
45
45
  '--sd-toggle-content-select': TOGGLE_COLORS.content.select,
46
46
  '--sd-toggle-content-disabled': TOGGLE_COLORS.content.disabled,
47
47
  };
48
- return (h("label", { key: 'b16577aa25863a9dc337314d9059328799c1cd1e', class: this.toggleClasses, style: cssVars, "aria-label": this.label || 'toggle' }, this.label, h("input", { key: '6130825b74df8a573f4e062671fd694508759e82', style: { display: 'none' }, type: "checkbox", onInput: this.handleChange })));
48
+ return (h("label", { key: 'c5c8b9448dabb6619e80fd55b11f94bf78706994', class: this.toggleClasses, style: cssVars, "aria-label": this.label || 'toggle' }, this.label, h("input", { key: 'bd43e7f286da217653461ec3128998c5f5a821d9', style: { display: 'none' }, type: "checkbox", onInput: this.handleChange })));
49
49
  }
50
50
  static get is() { return "sd-toggle"; }
51
51
  static get originalStyleUrls() {
@@ -84,14 +84,14 @@ export class SdTooltip {
84
84
  const hasLabel = this.label !== undefined && this.label !== '';
85
85
  const divTrigger = trigger === 'hover' ? hoverTrigger : hasLabel ? {} : { onClick: toggleTooltip };
86
86
  const buttonClickTrigger = trigger === 'click' && hasLabel ? { onSdClick: toggleTooltip } : {};
87
- return (h(Fragment, { key: 'ef33f9f183820d684f2805e40134a81f7149fc16' }, h("div", { key: 'dd931825c55b0ee748c7ef45f15be0d6de37ad23', class: `sd-tooltip-trigger ${this.sdClass !== undefined && this.sdClass !== '' ? this.sdClass : ''}`, ...divTrigger }, hasLabel ? (h("sd-button", { ref: el => (this.buttonEl = el), name: this.name ?? 'primary_sm', label: this.label, icon: icon, rightIcon: this.rightIcon, ariaLabel: this.ariaLabel, disabled: this.disabled, type: this.type ?? 'button', class: "sd-tooltip", ...buttonClickTrigger })) : (h("sd-icon", { ref: el => (this.buttonEl = el), name: icon, size: this.iconSize ?? 12, color: color, class: "sd-tooltip" }))), this.showTooltip && (h("sd-floating-portal", { key: '443dbbe8f0b9a66aaae9b8482a3f615d2d41e8ec', parentRef: this.buttonEl, onSdClose: this.handleClose, placement: placement, offset: this.tooltipOffset }, h("div", { key: '040bde0321b1fd35014db976aeaddc515d87c807', ref: el => (this.menuEl = el), class: {
87
+ return (h(Fragment, { key: 'c7ed53cfd1505b394353a9a37d0fe012cdf29217' }, h("div", { key: 'd31332c8717dd954bb1c79bb9d0fd974f74d6e73', class: `sd-tooltip-trigger ${this.sdClass !== undefined && this.sdClass !== '' ? this.sdClass : ''}`, ...divTrigger }, hasLabel ? (h("sd-button", { ref: el => (this.buttonEl = el), name: this.name ?? 'primary_sm', label: this.label, icon: icon, rightIcon: this.rightIcon, ariaLabel: this.ariaLabel, disabled: this.disabled, type: this.type ?? 'button', class: "sd-tooltip", ...buttonClickTrigger })) : (h("sd-icon", { ref: el => (this.buttonEl = el), name: icon, size: this.iconSize ?? 12, color: color, class: "sd-tooltip" }))), this.showTooltip && (h("sd-floating-portal", { key: 'a63971f2fa15e9ef8a6294a2284284e7d7154a8f', parentRef: this.buttonEl, onSdClose: this.handleClose, placement: placement, offset: this.tooltipOffset }, h("div", { key: 'dc3259612bf303b320fdc849bbb83f224f410737', ref: el => (this.menuEl = el), class: {
88
88
  'sd-floating-menu': true,
89
89
  [`sd-floating-menu--${tooltipType}`]: true,
90
90
  [`sd-floating-menu--${placement}`]: true,
91
91
  }, style: {
92
92
  '--sd-floating-bg': typeConfig.bg,
93
93
  '--sd-floating-content': typeConfig.content,
94
- }, onMouseEnter: () => this.show(), onMouseLeave: () => this.startHideTimer() }, h("i", { key: 'e802c09cc13ec3db29704197fa402588bf97d670', class: `sd-floating-menu__arrow sd-floating-menu__arrow--${placement}` }, h(TooltipArrow, { key: 'b698fbdba2cee74955f65ed7b04abeea8ccabee5' })), h("div", { key: '97e856c543a8cdb880daae9ed0e461f5fd0f2b44', class: "sd-floating-menu__content", innerHTML: this.slotContentHTML }))))));
94
+ }, onMouseEnter: () => this.show(), onMouseLeave: () => this.startHideTimer() }, h("i", { key: '8b3d132320c27710c9346f5313ee7c173df4275e', class: `sd-floating-menu__arrow sd-floating-menu__arrow--${placement}` }, h(TooltipArrow, { key: '66e90298fa62b7660e3d785abd024e9acae38fe3' })), h("div", { key: '115d0ee83abb2d9ca607759f009c47acd34196e2', class: "sd-floating-menu__content", innerHTML: this.slotContentHTML }))))));
95
95
  }
96
96
  static get is() { return "sd-tooltip"; }
97
97
  static get originalStyleUrls() {
@@ -0,0 +1,61 @@
1
+ const ALLOWED_INLINE_TAGS = new Set(['B', 'STRONG', 'I', 'EM', 'BR', 'SPAN']);
2
+ const DROP_CONTENT_TAGS = new Set([
3
+ 'SCRIPT',
4
+ 'STYLE',
5
+ 'IFRAME',
6
+ 'OBJECT',
7
+ 'EMBED',
8
+ 'META',
9
+ 'LINK',
10
+ 'BASE',
11
+ 'NOSCRIPT',
12
+ ]);
13
+ const escapeHtml = (value) => value
14
+ .replaceAll('&', '&amp;')
15
+ .replaceAll('<', '&lt;')
16
+ .replaceAll('>', '&gt;')
17
+ .replaceAll('"', '&quot;')
18
+ .replaceAll("'", '&#39;');
19
+ const createSanitizerTemplate = () => {
20
+ if (typeof document === 'undefined') {
21
+ return null;
22
+ }
23
+ return document.createElement('template');
24
+ };
25
+ const sanitizeNode = (node, doc) => {
26
+ if (node.nodeType === Node.COMMENT_NODE) {
27
+ node.remove();
28
+ return;
29
+ }
30
+ if (node.nodeType !== Node.ELEMENT_NODE) {
31
+ return;
32
+ }
33
+ const element = node;
34
+ const tagName = element.tagName;
35
+ if (DROP_CONTENT_TAGS.has(tagName)) {
36
+ element.remove();
37
+ return;
38
+ }
39
+ Array.from(element.childNodes).forEach(child => sanitizeNode(child, doc));
40
+ Array.from(element.attributes).forEach(attr => element.removeAttribute(attr.name));
41
+ if (ALLOWED_INLINE_TAGS.has(tagName)) {
42
+ return;
43
+ }
44
+ const parent = element.parentNode;
45
+ if (parent == null) {
46
+ return;
47
+ }
48
+ while (element.firstChild) {
49
+ parent.insertBefore(element.firstChild, element);
50
+ }
51
+ parent.removeChild(element);
52
+ };
53
+ export const sanitizeInlineHtml = (value) => {
54
+ const template = createSanitizerTemplate();
55
+ if (template == null) {
56
+ return escapeHtml(value);
57
+ }
58
+ template.innerHTML = value;
59
+ Array.from(template.content.childNodes).forEach(child => sanitizeNode(child, template.ownerDocument));
60
+ return template.innerHTML;
61
+ };