@sondor-technology/sondor-components 1.0.9 → 1.0.10

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 (431) hide show
  1. package/dist/components/accordion/accordion.constants.d.ts +5 -0
  2. package/dist/components/accordion/accordion.constants.d.ts.map +1 -0
  3. package/dist/components/accordion/accordion.constants.js +3 -0
  4. package/dist/components/accordion/accordion.constants.js.map +1 -0
  5. package/dist/components/accordion/accordion.d.ts +29 -0
  6. package/dist/components/accordion/accordion.d.ts.map +1 -0
  7. package/dist/components/accordion/accordion.js +226 -0
  8. package/dist/components/accordion/accordion.js.map +1 -0
  9. package/dist/components/alert/alert.constants.d.ts +2 -0
  10. package/dist/components/alert/alert.constants.d.ts.map +1 -1
  11. package/dist/components/alert/alert.d.ts +50 -2
  12. package/dist/components/alert/alert.d.ts.map +1 -1
  13. package/dist/components/alert/alert.js +285 -16
  14. package/dist/components/alert/alert.js.map +1 -1
  15. package/dist/components/avatar/avatar.d.ts +20 -0
  16. package/dist/components/avatar/avatar.d.ts.map +1 -0
  17. package/dist/components/avatar/avatar.js +100 -0
  18. package/dist/components/avatar/avatar.js.map +1 -0
  19. package/dist/components/back-to-top/back-to-top.d.ts +29 -0
  20. package/dist/components/back-to-top/back-to-top.d.ts.map +1 -0
  21. package/dist/components/back-to-top/back-to-top.js +149 -0
  22. package/dist/components/back-to-top/back-to-top.js.map +1 -0
  23. package/dist/components/bar-chart/bar-chart.d.ts +42 -0
  24. package/dist/components/bar-chart/bar-chart.d.ts.map +1 -0
  25. package/dist/components/bar-chart/bar-chart.js +298 -0
  26. package/dist/components/bar-chart/bar-chart.js.map +1 -0
  27. package/dist/components/breadcrumb/breadcrumb.js +2 -2
  28. package/dist/components/button/button.d.ts +1 -0
  29. package/dist/components/button/button.d.ts.map +1 -1
  30. package/dist/components/button/button.js +8 -8
  31. package/dist/components/button/button.js.map +1 -1
  32. package/dist/components/button-group/button-group.js +4 -4
  33. package/dist/components/calendar/calendar.d.ts.map +1 -1
  34. package/dist/components/calendar/calendar.js +11 -9
  35. package/dist/components/calendar/calendar.js.map +1 -1
  36. package/dist/components/chart/chart-base.d.ts +59 -0
  37. package/dist/components/chart/chart-base.d.ts.map +1 -0
  38. package/dist/components/chart/chart-base.js +261 -0
  39. package/dist/components/chart/chart-base.js.map +1 -0
  40. package/dist/components/chart/chart.utils.d.ts +27 -0
  41. package/dist/components/chart/chart.utils.d.ts.map +1 -0
  42. package/dist/components/chart/chart.utils.js +117 -0
  43. package/dist/components/chart/chart.utils.js.map +1 -0
  44. package/dist/components/code-block/code-block.d.ts +5 -0
  45. package/dist/components/code-block/code-block.d.ts.map +1 -1
  46. package/dist/components/code-block/code-block.js +34 -24
  47. package/dist/components/code-block/code-block.js.map +1 -1
  48. package/dist/components/consent/consent.d.ts +63 -0
  49. package/dist/components/consent/consent.d.ts.map +1 -0
  50. package/dist/components/consent/consent.js +327 -0
  51. package/dist/components/consent/consent.js.map +1 -0
  52. package/dist/components/consent/consent.utils.d.ts +36 -0
  53. package/dist/components/consent/consent.utils.d.ts.map +1 -0
  54. package/dist/components/consent/consent.utils.js +82 -0
  55. package/dist/components/consent/consent.utils.js.map +1 -0
  56. package/dist/components/contact/contact.d.ts +22 -0
  57. package/dist/components/contact/contact.d.ts.map +1 -0
  58. package/dist/components/contact/contact.js +83 -0
  59. package/dist/components/contact/contact.js.map +1 -0
  60. package/dist/components/container/container.d.ts +20 -0
  61. package/dist/components/container/container.d.ts.map +1 -0
  62. package/dist/components/container/container.js +68 -0
  63. package/dist/components/container/container.js.map +1 -0
  64. package/dist/components/content-card/content-card.js +4 -4
  65. package/dist/components/context-menu/context-menu.d.ts +89 -0
  66. package/dist/components/context-menu/context-menu.d.ts.map +1 -0
  67. package/dist/components/context-menu/context-menu.js +414 -0
  68. package/dist/components/context-menu/context-menu.js.map +1 -0
  69. package/dist/components/cron-builder/cron-builder.d.ts.map +1 -1
  70. package/dist/components/cron-builder/cron-builder.js +13 -11
  71. package/dist/components/cron-builder/cron-builder.js.map +1 -1
  72. package/dist/components/cta/cta.d.ts +20 -0
  73. package/dist/components/cta/cta.d.ts.map +1 -0
  74. package/dist/components/cta/cta.js +64 -0
  75. package/dist/components/cta/cta.js.map +1 -0
  76. package/dist/components/drawer/drawer.js +6 -6
  77. package/dist/components/faq/faq-item.d.ts +22 -0
  78. package/dist/components/faq/faq-item.d.ts.map +1 -0
  79. package/dist/components/faq/faq-item.js +117 -0
  80. package/dist/components/faq/faq-item.js.map +1 -0
  81. package/dist/components/faq/faq.d.ts +18 -0
  82. package/dist/components/faq/faq.d.ts.map +1 -0
  83. package/dist/components/faq/faq.js +38 -0
  84. package/dist/components/faq/faq.js.map +1 -0
  85. package/dist/components/feature-grid/feature-grid.d.ts +22 -0
  86. package/dist/components/feature-grid/feature-grid.d.ts.map +1 -0
  87. package/dist/components/feature-grid/feature-grid.js +55 -0
  88. package/dist/components/feature-grid/feature-grid.js.map +1 -0
  89. package/dist/components/feature-grid/feature.d.ts +18 -0
  90. package/dist/components/feature-grid/feature.d.ts.map +1 -0
  91. package/dist/components/feature-grid/feature.js +91 -0
  92. package/dist/components/feature-grid/feature.js.map +1 -0
  93. package/dist/components/field/field.js +2 -2
  94. package/dist/components/footer/footer.js +4 -4
  95. package/dist/components/form/form-reset.d.ts +7 -0
  96. package/dist/components/form/form-reset.d.ts.map +1 -0
  97. package/dist/components/form/form-reset.js +47 -0
  98. package/dist/components/form/form-reset.js.map +1 -0
  99. package/dist/components/form/form.d.ts +5 -0
  100. package/dist/components/form/form.d.ts.map +1 -1
  101. package/dist/components/form/form.js +17 -3
  102. package/dist/components/form/form.js.map +1 -1
  103. package/dist/components/grid/grid.d.ts +5 -0
  104. package/dist/components/grid/grid.d.ts.map +1 -1
  105. package/dist/components/grid/grid.js +86 -4
  106. package/dist/components/grid/grid.js.map +1 -1
  107. package/dist/components/heat-map/heat-map.d.ts +39 -0
  108. package/dist/components/heat-map/heat-map.d.ts.map +1 -0
  109. package/dist/components/heat-map/heat-map.js +306 -0
  110. package/dist/components/heat-map/heat-map.js.map +1 -0
  111. package/dist/components/hero/hero.d.ts +26 -0
  112. package/dist/components/hero/hero.d.ts.map +1 -0
  113. package/dist/components/hero/hero.js +132 -0
  114. package/dist/components/hero/hero.js.map +1 -0
  115. package/dist/components/icon/icon-paths.d.ts +84 -0
  116. package/dist/components/icon/icon-paths.d.ts.map +1 -1
  117. package/dist/components/icon/icon-paths.js +89 -0
  118. package/dist/components/icon/icon-paths.js.map +1 -1
  119. package/dist/components/icon/icon.d.ts +2 -0
  120. package/dist/components/icon/icon.d.ts.map +1 -1
  121. package/dist/components/icon/icon.js +10 -1
  122. package/dist/components/icon/icon.js.map +1 -1
  123. package/dist/components/image/image.d.ts +31 -0
  124. package/dist/components/image/image.d.ts.map +1 -0
  125. package/dist/components/image/image.js +179 -0
  126. package/dist/components/image/image.js.map +1 -0
  127. package/dist/components/input/input.js +4 -4
  128. package/dist/components/lazy/lazy.d.ts +34 -0
  129. package/dist/components/lazy/lazy.d.ts.map +1 -0
  130. package/dist/components/lazy/lazy.js +104 -0
  131. package/dist/components/lazy/lazy.js.map +1 -0
  132. package/dist/components/line-chart/line-chart.d.ts +37 -0
  133. package/dist/components/line-chart/line-chart.d.ts.map +1 -0
  134. package/dist/components/line-chart/line-chart.js +271 -0
  135. package/dist/components/line-chart/line-chart.js.map +1 -0
  136. package/dist/components/list/list-item.d.ts +45 -0
  137. package/dist/components/list/list-item.d.ts.map +1 -0
  138. package/dist/components/list/list-item.js +263 -0
  139. package/dist/components/list/list-item.js.map +1 -0
  140. package/dist/components/list/list.d.ts +50 -0
  141. package/dist/components/list/list.d.ts.map +1 -0
  142. package/dist/components/list/list.js +161 -0
  143. package/dist/components/list/list.js.map +1 -0
  144. package/dist/components/logo-cloud/logo-cloud.d.ts +19 -0
  145. package/dist/components/logo-cloud/logo-cloud.d.ts.map +1 -0
  146. package/dist/components/logo-cloud/logo-cloud.js +66 -0
  147. package/dist/components/logo-cloud/logo-cloud.js.map +1 -0
  148. package/dist/components/modal/modal.d.ts +12 -0
  149. package/dist/components/modal/modal.d.ts.map +1 -1
  150. package/dist/components/modal/modal.js +40 -11
  151. package/dist/components/modal/modal.js.map +1 -1
  152. package/dist/components/page-layout/page-layout.js +8 -8
  153. package/dist/components/pagination/pagination.d.ts +15 -0
  154. package/dist/components/pagination/pagination.d.ts.map +1 -0
  155. package/dist/components/pagination/pagination.js +126 -0
  156. package/dist/components/pagination/pagination.js.map +1 -0
  157. package/dist/components/pagination/pagination.utils.d.ts +3 -0
  158. package/dist/components/pagination/pagination.utils.d.ts.map +1 -0
  159. package/dist/components/pagination/pagination.utils.js +19 -0
  160. package/dist/components/pagination/pagination.utils.js.map +1 -0
  161. package/dist/components/pie-chart/pie-chart.d.ts +33 -0
  162. package/dist/components/pie-chart/pie-chart.d.ts.map +1 -0
  163. package/dist/components/pie-chart/pie-chart.js +233 -0
  164. package/dist/components/pie-chart/pie-chart.js.map +1 -0
  165. package/dist/components/pin-input/pin-input.js +4 -4
  166. package/dist/components/popover/popover.d.ts.map +1 -1
  167. package/dist/components/popover/popover.js +1 -3
  168. package/dist/components/popover/popover.js.map +1 -1
  169. package/dist/components/post-list/post-card.d.ts +16 -0
  170. package/dist/components/post-list/post-card.d.ts.map +1 -0
  171. package/dist/components/post-list/post-card.js +22 -0
  172. package/dist/components/post-list/post-card.js.map +1 -0
  173. package/dist/components/post-list/post-list.d.ts +17 -0
  174. package/dist/components/post-list/post-list.d.ts.map +1 -0
  175. package/dist/components/post-list/post-list.js +23 -0
  176. package/dist/components/post-list/post-list.js.map +1 -0
  177. package/dist/components/pricing/pricing-tier.d.ts +23 -0
  178. package/dist/components/pricing/pricing-tier.d.ts.map +1 -0
  179. package/dist/components/pricing/pricing-tier.js +144 -0
  180. package/dist/components/pricing/pricing-tier.js.map +1 -0
  181. package/dist/components/pricing/pricing.d.ts +18 -0
  182. package/dist/components/pricing/pricing.d.ts.map +1 -0
  183. package/dist/components/pricing/pricing.js +38 -0
  184. package/dist/components/pricing/pricing.js.map +1 -0
  185. package/dist/components/progress/progress.d.ts +17 -0
  186. package/dist/components/progress/progress.d.ts.map +1 -0
  187. package/dist/components/progress/progress.js +109 -0
  188. package/dist/components/progress/progress.js.map +1 -0
  189. package/dist/components/project-grid/project-card.d.ts +17 -0
  190. package/dist/components/project-grid/project-card.d.ts.map +1 -0
  191. package/dist/components/project-grid/project-card.js +23 -0
  192. package/dist/components/project-grid/project-card.js.map +1 -0
  193. package/dist/components/project-grid/project-grid.d.ts +17 -0
  194. package/dist/components/project-grid/project-grid.d.ts.map +1 -0
  195. package/dist/components/project-grid/project-grid.js +23 -0
  196. package/dist/components/project-grid/project-grid.js.map +1 -0
  197. package/dist/components/radio/radio.js +1 -1
  198. package/dist/components/reveal/reveal.constants.d.ts +10 -0
  199. package/dist/components/reveal/reveal.constants.d.ts.map +1 -0
  200. package/dist/components/reveal/reveal.constants.js +11 -0
  201. package/dist/components/reveal/reveal.constants.js.map +1 -0
  202. package/dist/components/reveal/reveal.d.ts +64 -0
  203. package/dist/components/reveal/reveal.d.ts.map +1 -0
  204. package/dist/components/reveal/reveal.js +352 -0
  205. package/dist/components/reveal/reveal.js.map +1 -0
  206. package/dist/components/scroll-progress/scroll-progress.d.ts +32 -0
  207. package/dist/components/scroll-progress/scroll-progress.d.ts.map +1 -0
  208. package/dist/components/scroll-progress/scroll-progress.js +120 -0
  209. package/dist/components/scroll-progress/scroll-progress.js.map +1 -0
  210. package/dist/components/section/card-row.d.ts +30 -0
  211. package/dist/components/section/card-row.d.ts.map +1 -0
  212. package/dist/components/section/card-row.js +174 -0
  213. package/dist/components/section/card-row.js.map +1 -0
  214. package/dist/components/section/card.d.ts +27 -0
  215. package/dist/components/section/card.d.ts.map +1 -0
  216. package/dist/components/section/card.js +205 -0
  217. package/dist/components/section/card.js.map +1 -0
  218. package/dist/components/section/row-item.d.ts +22 -0
  219. package/dist/components/section/row-item.d.ts.map +1 -0
  220. package/dist/components/section/row-item.js +53 -0
  221. package/dist/components/section/row-item.js.map +1 -0
  222. package/dist/components/section/section.d.ts +70 -0
  223. package/dist/components/section/section.d.ts.map +1 -0
  224. package/dist/components/section/section.js +240 -0
  225. package/dist/components/section/section.js.map +1 -0
  226. package/dist/components/select/select.js +3 -3
  227. package/dist/components/series-nav/series-nav.d.ts +29 -0
  228. package/dist/components/series-nav/series-nav.d.ts.map +1 -0
  229. package/dist/components/series-nav/series-nav.js +178 -0
  230. package/dist/components/series-nav/series-nav.js.map +1 -0
  231. package/dist/components/site-header/site-header.d.ts +51 -0
  232. package/dist/components/site-header/site-header.d.ts.map +1 -0
  233. package/dist/components/site-header/site-header.js +296 -0
  234. package/dist/components/site-header/site-header.js.map +1 -0
  235. package/dist/components/skeleton/skeleton.js +7 -7
  236. package/dist/components/sparkline/sparkline.d.ts +19 -0
  237. package/dist/components/sparkline/sparkline.d.ts.map +1 -0
  238. package/dist/components/sparkline/sparkline.js +99 -0
  239. package/dist/components/sparkline/sparkline.js.map +1 -0
  240. package/dist/components/spinner/spinner.d.ts +13 -0
  241. package/dist/components/spinner/spinner.d.ts.map +1 -0
  242. package/dist/components/spinner/spinner.js +65 -0
  243. package/dist/components/spinner/spinner.js.map +1 -0
  244. package/dist/components/split/split.d.ts +23 -0
  245. package/dist/components/split/split.d.ts.map +1 -0
  246. package/dist/components/split/split.js +104 -0
  247. package/dist/components/split/split.js.map +1 -0
  248. package/dist/components/stack/stack.d.ts +21 -0
  249. package/dist/components/stack/stack.d.ts.map +1 -0
  250. package/dist/components/stack/stack.js +102 -0
  251. package/dist/components/stack/stack.js.map +1 -0
  252. package/dist/components/stat-card/stat-card.d.ts +35 -0
  253. package/dist/components/stat-card/stat-card.d.ts.map +1 -0
  254. package/dist/components/stat-card/stat-card.js +199 -0
  255. package/dist/components/stat-card/stat-card.js.map +1 -0
  256. package/dist/components/stats/stat.d.ts +16 -0
  257. package/dist/components/stats/stat.d.ts.map +1 -0
  258. package/dist/components/stats/stat.js +51 -0
  259. package/dist/components/stats/stat.js.map +1 -0
  260. package/dist/components/stats/stats.d.ts +19 -0
  261. package/dist/components/stats/stats.d.ts.map +1 -0
  262. package/dist/components/stats/stats.js +45 -0
  263. package/dist/components/stats/stats.js.map +1 -0
  264. package/dist/components/switch/switch.js +2 -2
  265. package/dist/components/table/data-table.d.ts +115 -27
  266. package/dist/components/table/data-table.d.ts.map +1 -1
  267. package/dist/components/table/data-table.js +1012 -411
  268. package/dist/components/table/data-table.js.map +1 -1
  269. package/dist/components/table/data-table.utils.d.ts +81 -0
  270. package/dist/components/table/data-table.utils.d.ts.map +1 -0
  271. package/dist/components/table/data-table.utils.js +208 -0
  272. package/dist/components/table/data-table.utils.js.map +1 -0
  273. package/dist/components/table/table.d.ts +28 -0
  274. package/dist/components/table/table.d.ts.map +1 -1
  275. package/dist/components/table/table.js +161 -33
  276. package/dist/components/table/table.js.map +1 -1
  277. package/dist/components/team/person.d.ts +19 -0
  278. package/dist/components/team/person.d.ts.map +1 -0
  279. package/dist/components/team/person.js +123 -0
  280. package/dist/components/team/person.js.map +1 -0
  281. package/dist/components/team/team.d.ts +18 -0
  282. package/dist/components/team/team.d.ts.map +1 -0
  283. package/dist/components/team/team.js +36 -0
  284. package/dist/components/team/team.js.map +1 -0
  285. package/dist/components/testimonials/testimonial.d.ts +18 -0
  286. package/dist/components/testimonials/testimonial.d.ts.map +1 -0
  287. package/dist/components/testimonials/testimonial.js +115 -0
  288. package/dist/components/testimonials/testimonial.js.map +1 -0
  289. package/dist/components/testimonials/testimonials.d.ts +18 -0
  290. package/dist/components/testimonials/testimonials.d.ts.map +1 -0
  291. package/dist/components/testimonials/testimonials.js +36 -0
  292. package/dist/components/testimonials/testimonials.js.map +1 -0
  293. package/dist/components/textarea/textarea.js +3 -3
  294. package/dist/components/theme-toggle/theme-toggle.js +1 -1
  295. package/dist/components/time-picker/time-picker.js +3 -3
  296. package/dist/components/timeline/timeline-item.d.ts +18 -0
  297. package/dist/components/timeline/timeline-item.d.ts.map +1 -0
  298. package/dist/components/timeline/timeline-item.js +102 -0
  299. package/dist/components/timeline/timeline-item.js.map +1 -0
  300. package/dist/components/timeline/timeline.d.ts +18 -0
  301. package/dist/components/timeline/timeline.d.ts.map +1 -0
  302. package/dist/components/timeline/timeline.js +30 -0
  303. package/dist/components/timeline/timeline.js.map +1 -0
  304. package/dist/components/toast/toast.d.ts +33 -0
  305. package/dist/components/toast/toast.d.ts.map +1 -0
  306. package/dist/components/toast/toast.js +147 -0
  307. package/dist/components/toast/toast.js.map +1 -0
  308. package/dist/components/toggle-group/toggle-button.d.ts +2 -0
  309. package/dist/components/toggle-group/toggle-button.d.ts.map +1 -1
  310. package/dist/components/toggle-group/toggle-button.js +12 -4
  311. package/dist/components/toggle-group/toggle-button.js.map +1 -1
  312. package/dist/components/toggle-group/toggle-group.js +4 -4
  313. package/dist/components/tooltip/tooltip.js +21 -21
  314. package/dist/components/vertical-nav/vertical-nav-group.js +3 -3
  315. package/dist/components/vertical-nav/vertical-nav-item.js +4 -4
  316. package/dist/components/video-embed/video-embed.d.ts +37 -0
  317. package/dist/components/video-embed/video-embed.d.ts.map +1 -0
  318. package/dist/components/video-embed/video-embed.js +183 -0
  319. package/dist/components/video-embed/video-embed.js.map +1 -0
  320. package/dist/index.d.ts +107 -0
  321. package/dist/index.d.ts.map +1 -0
  322. package/dist/index.js +104 -0
  323. package/dist/index.js.map +1 -0
  324. package/dist/styles/index.css +205 -2
  325. package/dist/styles/reset.d.ts.map +1 -1
  326. package/dist/styles/reset.js +5 -0
  327. package/dist/styles/reset.js.map +1 -1
  328. package/package.json +210 -7
  329. package/src/components/accordion/accordion.constants.ts +5 -0
  330. package/src/components/accordion/accordion.ts +209 -0
  331. package/src/components/alert/alert.constants.ts +3 -0
  332. package/src/components/alert/alert.ts +284 -17
  333. package/src/components/avatar/avatar.ts +84 -0
  334. package/src/components/back-to-top/back-to-top.ts +140 -0
  335. package/src/components/bar-chart/bar-chart.ts +295 -0
  336. package/src/components/breadcrumb/breadcrumb.ts +2 -2
  337. package/src/components/button/button.ts +9 -8
  338. package/src/components/button-group/button-group.ts +4 -4
  339. package/src/components/calendar/calendar.ts +12 -9
  340. package/src/components/chart/chart-base.ts +275 -0
  341. package/src/components/chart/chart.utils.ts +140 -0
  342. package/src/components/code-block/code-block.ts +35 -24
  343. package/src/components/consent/consent.ts +312 -0
  344. package/src/components/consent/consent.utils.ts +110 -0
  345. package/src/components/contact/contact.ts +83 -0
  346. package/src/components/container/container.ts +60 -0
  347. package/src/components/content-card/content-card.ts +4 -4
  348. package/src/components/context-menu/context-menu.ts +426 -0
  349. package/src/components/cron-builder/cron-builder.ts +21 -18
  350. package/src/components/cta/cta.ts +64 -0
  351. package/src/components/drawer/drawer.ts +6 -6
  352. package/src/components/faq/faq-item.ts +110 -0
  353. package/src/components/faq/faq.ts +40 -0
  354. package/src/components/feature-grid/feature-grid.ts +52 -0
  355. package/src/components/feature-grid/feature.ts +84 -0
  356. package/src/components/field/field.ts +2 -2
  357. package/src/components/footer/footer.ts +4 -4
  358. package/src/components/form/form-reset.ts +45 -0
  359. package/src/components/form/form.ts +17 -3
  360. package/src/components/grid/grid.ts +73 -4
  361. package/src/components/heat-map/heat-map.ts +292 -0
  362. package/src/components/hero/hero.ts +132 -0
  363. package/src/components/icon/icon-paths.ts +92 -1
  364. package/src/components/icon/icon.ts +8 -1
  365. package/src/components/image/image.ts +165 -0
  366. package/src/components/input/input.ts +4 -4
  367. package/src/components/lazy/lazy.ts +94 -0
  368. package/src/components/line-chart/line-chart.ts +271 -0
  369. package/src/components/list/list-item.ts +225 -0
  370. package/src/components/list/list.ts +157 -0
  371. package/src/components/logo-cloud/logo-cloud.ts +65 -0
  372. package/src/components/modal/modal.ts +37 -11
  373. package/src/components/page-layout/page-layout.ts +8 -8
  374. package/src/components/pagination/pagination.ts +120 -0
  375. package/src/components/pagination/pagination.utils.ts +14 -0
  376. package/src/components/pie-chart/pie-chart.ts +230 -0
  377. package/src/components/pin-input/pin-input.ts +4 -4
  378. package/src/components/popover/popover.ts +1 -3
  379. package/src/components/post-list/post-card.ts +18 -0
  380. package/src/components/post-list/post-list.ts +19 -0
  381. package/src/components/pricing/pricing-tier.ts +132 -0
  382. package/src/components/pricing/pricing.ts +39 -0
  383. package/src/components/progress/progress.ts +95 -0
  384. package/src/components/project-grid/project-card.ts +19 -0
  385. package/src/components/project-grid/project-grid.ts +19 -0
  386. package/src/components/radio/radio.ts +1 -1
  387. package/src/components/reveal/reveal.constants.ts +20 -0
  388. package/src/components/reveal/reveal.ts +344 -0
  389. package/src/components/scroll-progress/scroll-progress.ts +119 -0
  390. package/src/components/section/card-row.ts +152 -0
  391. package/src/components/section/card.ts +197 -0
  392. package/src/components/section/row-item.ts +38 -0
  393. package/src/components/section/section.ts +232 -0
  394. package/src/components/select/select.ts +3 -3
  395. package/src/components/series-nav/series-nav.ts +164 -0
  396. package/src/components/site-header/site-header.ts +276 -0
  397. package/src/components/skeleton/skeleton.ts +7 -7
  398. package/src/components/sparkline/sparkline.ts +83 -0
  399. package/src/components/spinner/spinner.ts +55 -0
  400. package/src/components/split/split.ts +106 -0
  401. package/src/components/stack/stack.ts +88 -0
  402. package/src/components/stat-card/stat-card.ts +179 -0
  403. package/src/components/stats/stat.ts +49 -0
  404. package/src/components/stats/stats.ts +47 -0
  405. package/src/components/switch/switch.ts +2 -2
  406. package/src/components/table/data-table.ts +1015 -425
  407. package/src/components/table/data-table.utils.ts +276 -0
  408. package/src/components/table/table.ts +168 -38
  409. package/src/components/team/person.ts +113 -0
  410. package/src/components/team/team.ts +37 -0
  411. package/src/components/testimonials/testimonial.ts +108 -0
  412. package/src/components/testimonials/testimonials.ts +37 -0
  413. package/src/components/textarea/textarea.ts +3 -3
  414. package/src/components/theme-toggle/theme-toggle.ts +1 -1
  415. package/src/components/time-picker/time-picker.ts +3 -3
  416. package/src/components/timeline/timeline-item.ts +100 -0
  417. package/src/components/timeline/timeline.ts +31 -0
  418. package/src/components/toast/toast.ts +153 -0
  419. package/src/components/toggle-group/toggle-button.ts +9 -4
  420. package/src/components/toggle-group/toggle-group.ts +4 -4
  421. package/src/components/tooltip/tooltip.ts +21 -21
  422. package/src/components/vertical-nav/vertical-nav-group.ts +3 -3
  423. package/src/components/vertical-nav/vertical-nav-item.ts +4 -4
  424. package/src/components/video-embed/video-embed.ts +162 -0
  425. package/src/index.ts +108 -0
  426. package/src/styles/globals.css +63 -0
  427. package/src/styles/index.css +3 -1
  428. package/src/styles/prose.css +154 -0
  429. package/src/styles/reset.ts +5 -0
  430. package/src/styles/theme.css +53 -1
  431. package/src/styles/typography.css +1 -0
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Pure data helpers for st-data-table (search, filter, sort, paginate). They have no DOM or Lit
3
+ * dependencies so they can be unit tested and reused for server-side logic.
4
+ */
5
+
6
+ export type FilterType = "text" | "number" | "select" | "boolean";
7
+ export type SortDirection = "asc" | "desc";
8
+
9
+ export type FilterOperator =
10
+ | "contains"
11
+ | "notContains"
12
+ | "equals"
13
+ | "startsWith"
14
+ | "endsWith"
15
+ | "eq"
16
+ | "neq"
17
+ | "gt"
18
+ | "gte"
19
+ | "lt"
20
+ | "lte"
21
+ | "is"
22
+ | "isNot"
23
+ | "isTrue"
24
+ | "isFalse";
25
+
26
+ export interface FilterOption {
27
+ label: string;
28
+ value: string;
29
+ }
30
+
31
+ export interface DataTableColumn {
32
+ header: string;
33
+ key: string;
34
+ /** Click the header to sort. Shift+click adds the column to a multi-column sort. */
35
+ sortable?: boolean;
36
+ hidden?: boolean;
37
+ /** Adds the column to the filter builder with this value type. */
38
+ filter?: FilterType;
39
+ /** Choices for `select` filters. Derived from the data when omitted. */
40
+ options?: FilterOption[];
41
+ /** Set to false to exclude the column from the search box. */
42
+ searchable?: boolean;
43
+ align?: "start" | "center" | "end";
44
+ /** Any CSS width, e.g. "8rem". */
45
+ width?: string;
46
+ /** Underlying value used for search, filter and sort when it differs from `row[key]`. */
47
+ value?: (row: any) => unknown;
48
+ /** Custom cell content (JavaScript only). */
49
+ render?: (row: any) => unknown;
50
+ }
51
+
52
+ export interface SortConfig {
53
+ key: string;
54
+ direction: SortDirection;
55
+ }
56
+
57
+ export interface DataFilter {
58
+ key: string;
59
+ op: FilterOperator;
60
+ value?: string;
61
+ }
62
+
63
+ export interface OperatorInfo {
64
+ op: FilterOperator;
65
+ label: string;
66
+ /** False for operators that take no value, such as `isTrue`. */
67
+ needsValue: boolean;
68
+ }
69
+
70
+ const OPERATORS: Record<FilterType, OperatorInfo[]> = {
71
+ text: [
72
+ {op: "contains", label: "contains", needsValue: true},
73
+ {op: "notContains", label: "does not contain", needsValue: true},
74
+ {op: "equals", label: "equals", needsValue: true},
75
+ {op: "startsWith", label: "starts with", needsValue: true},
76
+ {op: "endsWith", label: "ends with", needsValue: true},
77
+ ],
78
+ number: [
79
+ {op: "eq", label: "=", needsValue: true},
80
+ {op: "neq", label: "≠", needsValue: true},
81
+ {op: "gt", label: ">", needsValue: true},
82
+ {op: "gte", label: "≥", needsValue: true},
83
+ {op: "lt", label: "<", needsValue: true},
84
+ {op: "lte", label: "≤", needsValue: true},
85
+ ],
86
+ select: [
87
+ {op: "is", label: "is", needsValue: true},
88
+ {op: "isNot", label: "is not", needsValue: true},
89
+ ],
90
+ boolean: [
91
+ {op: "isTrue", label: "is yes", needsValue: false},
92
+ {op: "isFalse", label: "is no", needsValue: false},
93
+ ],
94
+ };
95
+
96
+ export const operatorsFor = (type: FilterType): OperatorInfo[] => OPERATORS[type];
97
+
98
+ export const defaultOperator = (type: FilterType): FilterOperator => OPERATORS[type][0].op;
99
+
100
+ const operatorInfo = (type: FilterType, op: FilterOperator) =>
101
+ OPERATORS[type].find((o) => o.op === op);
102
+
103
+ /** Reads the comparable value for a column: its `value` accessor, else `row[key]`. */
104
+ export const cellValue = (row: any, column: Pick<DataTableColumn, "key" | "value">): unknown =>
105
+ column.value ? column.value(row) : row?.[column.key];
106
+
107
+ const isBlank = (v: unknown) => v === null || v === undefined || v === "";
108
+
109
+ const toText = (v: unknown) => (v === null || v === undefined ? "" : String(v)).toLowerCase();
110
+
111
+ /** A filter is applied only once it has everything it needs (e.g. a value for "contains"). */
112
+ export function isFilterComplete(filter: DataFilter, columns: DataTableColumn[]): boolean {
113
+ const column = columns.find((c) => c.key === filter.key);
114
+ if (!column?.filter) return false;
115
+ const info = operatorInfo(column.filter, filter.op);
116
+ if (!info) return false;
117
+ return !info.needsValue || (filter.value ?? "").trim() !== "";
118
+ }
119
+
120
+ function matches(filter: DataFilter, type: FilterType, raw: unknown): boolean {
121
+ const value = (filter.value ?? "").trim();
122
+ switch (type) {
123
+ case "text": {
124
+ const cell = toText(raw);
125
+ const needle = value.toLowerCase();
126
+ if (filter.op === "contains") return cell.includes(needle);
127
+ if (filter.op === "notContains") return !cell.includes(needle);
128
+ if (filter.op === "equals") return cell === needle;
129
+ if (filter.op === "startsWith") return cell.startsWith(needle);
130
+ if (filter.op === "endsWith") return cell.endsWith(needle);
131
+ return true;
132
+ }
133
+ case "number": {
134
+ if (isBlank(raw)) return false;
135
+ const cell = Number(raw);
136
+ const target = Number(value);
137
+ if (Number.isNaN(cell) || Number.isNaN(target)) return false;
138
+ if (filter.op === "eq") return cell === target;
139
+ if (filter.op === "neq") return cell !== target;
140
+ if (filter.op === "gt") return cell > target;
141
+ if (filter.op === "gte") return cell >= target;
142
+ if (filter.op === "lt") return cell < target;
143
+ if (filter.op === "lte") return cell <= target;
144
+ return true;
145
+ }
146
+ case "select": {
147
+ const same = String(raw ?? "") === value;
148
+ return filter.op === "isNot" ? !same : same;
149
+ }
150
+ case "boolean": {
151
+ const truthy = raw === true || toText(raw) === "true" || toText(raw) === "yes";
152
+ return filter.op === "isFalse" ? !truthy : truthy;
153
+ }
154
+ }
155
+ }
156
+
157
+ /** Keeps rows that satisfy every complete filter (AND), across any number of columns. */
158
+ export function applyFilters<T>(rows: T[], filters: DataFilter[], columns: DataTableColumn[]): T[] {
159
+ const active = filters.filter((f) => isFilterComplete(f, columns));
160
+ if (!active.length) return rows;
161
+ const byKey = new Map(columns.map((c) => [c.key, c]));
162
+ return rows.filter((row) =>
163
+ active.every((f) => {
164
+ const column = byKey.get(f.key)!;
165
+ return matches(f, column.filter!, cellValue(row, column));
166
+ }),
167
+ );
168
+ }
169
+
170
+ /** Every whitespace separated term must appear in at least one searchable column. */
171
+ export function searchRows<T>(rows: T[], query: string, columns: DataTableColumn[]): T[] {
172
+ const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
173
+ if (!terms.length) return rows;
174
+ const searchable = columns.filter((c) => c.searchable !== false);
175
+ return rows.filter((row) => {
176
+ const haystack = searchable.map((c) => toText(cellValue(row, c)));
177
+ return terms.every((term) => haystack.some((cell) => cell.includes(term)));
178
+ });
179
+ }
180
+
181
+ const collator = new Intl.Collator(undefined, {numeric: true, sensitivity: "base"});
182
+
183
+ /** Compares two cell values: numbers numerically, dates by time, everything else naturally. */
184
+ export function compareValues(a: unknown, b: unknown): number {
185
+ if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
186
+ if (typeof a === "number" && typeof b === "number") return a - b;
187
+ if (typeof a === "boolean" && typeof b === "boolean") return Number(a) - Number(b);
188
+ return collator.compare(String(a), String(b));
189
+ }
190
+
191
+ /** Stable multi-column sort. Empty values always sort last, whichever the direction. */
192
+ export function sortRows<T>(rows: T[], sorts: SortConfig[], columns: DataTableColumn[]): T[] {
193
+ const active = sorts.filter((s) => columns.some((c) => c.key === s.key));
194
+ if (!active.length) return rows;
195
+ const byKey = new Map(columns.map((c) => [c.key, c]));
196
+ return rows
197
+ .map((row, index) => ({row, index}))
198
+ .sort((x, y) => {
199
+ for (const s of active) {
200
+ const column = byKey.get(s.key)!;
201
+ const a = cellValue(x.row, column);
202
+ const b = cellValue(y.row, column);
203
+ const aBlank = isBlank(a);
204
+ const bBlank = isBlank(b);
205
+ if (aBlank || bBlank) {
206
+ if (aBlank && bBlank) continue;
207
+ return aBlank ? 1 : -1;
208
+ }
209
+ const result = compareValues(a, b);
210
+ if (result !== 0) return s.direction === "asc" ? result : -result;
211
+ }
212
+ return x.index - y.index;
213
+ })
214
+ .map(({row}) => row);
215
+ }
216
+
217
+ /**
218
+ * Advances a column through none -> asc -> desc -> none. With `additive` (Shift+click) other
219
+ * sorted columns are kept so users can sort by several columns; otherwise they are replaced.
220
+ */
221
+ export function nextSort(current: SortConfig[], key: string, additive: boolean): SortConfig[] {
222
+ const existing = current.find((s) => s.key === key);
223
+ const direction: SortDirection | null = !existing ? "asc" : existing.direction === "asc" ? "desc" : null;
224
+ const others = additive ? current.filter((s) => s.key !== key) : [];
225
+ if (!direction) return additive ? current.filter((s) => s.key !== key) : [];
226
+ if (additive && existing) return current.map((s) => (s.key === key ? {key, direction} : s));
227
+ return [...others, {key, direction}];
228
+ }
229
+
230
+ export interface PageSlice<T> {
231
+ rows: T[];
232
+ page: number;
233
+ totalPages: number;
234
+ total: number;
235
+ /** 1-based index of the first and last row on the page (0 when empty). */
236
+ from: number;
237
+ to: number;
238
+ }
239
+
240
+ /** Slices one page and clamps `page` into range. */
241
+ export function paginate<T>(rows: T[], page: number, pageSize: number): PageSlice<T> {
242
+ const size = Math.max(1, pageSize);
243
+ const totalPages = Math.max(1, Math.ceil(rows.length / size));
244
+ const current = Math.min(Math.max(1, page), totalPages);
245
+ const start = (current - 1) * size;
246
+ const slice = rows.slice(start, start + size);
247
+ return {
248
+ rows: slice,
249
+ page: current,
250
+ totalPages,
251
+ total: rows.length,
252
+ from: slice.length ? start + 1 : 0,
253
+ to: start + slice.length,
254
+ };
255
+ }
256
+
257
+ /** Distinct values of a column, as options for a select filter. */
258
+ export function deriveOptions(rows: any[], column: DataTableColumn): FilterOption[] {
259
+ const seen = new Set<string>();
260
+ for (const row of rows) {
261
+ const v = cellValue(row, column);
262
+ if (!isBlank(v)) seen.add(String(v));
263
+ }
264
+ return [...seen].sort(collator.compare).map((value) => ({label: value, value}));
265
+ }
266
+
267
+ /** Human readable summary of a filter, e.g. "Status is Active". */
268
+ export function describeFilter(filter: DataFilter, columns: DataTableColumn[]): string {
269
+ const column = columns.find((c) => c.key === filter.key);
270
+ if (!column?.filter) return filter.key;
271
+ const info = operatorInfo(column.filter, filter.op);
272
+ const value = column.filter === "select"
273
+ ? (column.options?.find((o) => o.value === filter.value)?.label ?? filter.value ?? "")
274
+ : (filter.value ?? "");
275
+ return [column.header, info?.label ?? filter.op, info?.needsValue ? value : ""].filter(Boolean).join(" ");
276
+ }
@@ -1,14 +1,31 @@
1
- import {LitElement, html, css} from "lit";
1
+ import {LitElement, html, css, nothing} from "lit";
2
2
  import {customElement, property} from "lit/decorators.js";
3
+ import {classMap} from "lit/directives/class-map.js";
4
+ import {ifDefined} from "lit/directives/if-defined.js";
3
5
  import {resetStyles} from "../../styles/reset.js";
6
+ import "../skeleton/skeleton.js";
4
7
 
5
8
  export type TableMode = "horizontal" | "vertical";
9
+ export type TableAlign = "start" | "center" | "end";
6
10
 
7
11
  export interface TableColumn {
8
12
  header: string;
9
13
  key: string;
14
+ /** Horizontal alignment of the column. Numbers usually read best with "end". */
15
+ align?: TableAlign;
16
+ /** Any CSS width, e.g. "8rem" or "20%". */
17
+ width?: string;
18
+ /** Custom cell content (JavaScript only). Return text or a Lit template. */
19
+ render?: (row: Record<string, any>, index: number) => unknown;
10
20
  }
11
21
 
22
+ const SKELETON_ROWS = 3;
23
+
24
+ /**
25
+ * Lightweight data table. Use `st-data-table` when you need sorting, search or pagination.
26
+ *
27
+ * Events: `st-row-click` (detail: the row object) when `clickable-rows` is set.
28
+ */
12
29
  @customElement("st-table")
13
30
  export class StTable extends LitElement {
14
31
  @property({type: Array}) columns: TableColumn[] = [];
@@ -18,6 +35,17 @@ export class StTable extends LitElement {
18
35
  @property({type: Boolean, reflect: true}) striped = false;
19
36
  @property({type: Boolean, reflect: true}) hoverable = false;
20
37
  @property({type: Boolean, reflect: true}) dense = false;
38
+ /** Keeps the header visible while the body scrolls. Set a height with `--st-table-max-height`. */
39
+ @property({type: Boolean, reflect: true, attribute: "sticky-header"}) stickyHeader = false;
40
+ /** Shows placeholder rows and sets `aria-busy`. */
41
+ @property({type: Boolean, reflect: true}) loading = false;
42
+ /** Makes rows focusable and emits `st-row-click` on click, Enter or Space. */
43
+ @property({type: Boolean, reflect: true, attribute: "clickable-rows"}) clickableRows = false;
44
+
45
+ /** Describes the table to assistive technology (and visually, unless `caption-hidden`). */
46
+ @property({type: String}) caption = "";
47
+ @property({type: Boolean, reflect: true, attribute: "caption-hidden"}) captionHidden = false;
48
+ @property({type: String, attribute: "empty-text"}) emptyText = "No data available.";
21
49
 
22
50
  static styles = [
23
51
  resetStyles,
@@ -29,20 +57,40 @@ export class StTable extends LitElement {
29
57
 
30
58
  .table-wrapper {
31
59
  width: 100%;
32
- overflow-x: auto;
60
+ overflow: auto;
33
61
  -webkit-overflow-scrolling: touch;
62
+ max-height: var(--st-table-max-height, none);
34
63
  }
35
64
 
36
65
  table {
37
66
  width: 100%;
38
67
  border-collapse: collapse;
39
68
  text-align: left;
40
- font-size: var(--st-font-size-base, 1rem);
69
+ font-size: var(--st-font-size-base);
70
+ color: var(--st-color-text);
71
+ }
72
+
73
+ caption {
74
+ padding: var(--st-spacing-sm) var(--st-spacing-lg);
75
+ text-align: left;
76
+ font-weight: var(--st-font-weight-medium);
41
77
  color: var(--st-color-text);
42
78
  }
43
79
 
80
+ :host([caption-hidden]) caption {
81
+ position: absolute;
82
+ width: 1px;
83
+ height: 1px;
84
+ padding: 0;
85
+ margin: -1px;
86
+ overflow: hidden;
87
+ clip: rect(0, 0, 0, 0);
88
+ white-space: nowrap;
89
+ border: 0;
90
+ }
91
+
44
92
  th {
45
- font-weight: 600;
93
+ font-weight: var(--st-font-weight-semibold);
46
94
  padding: var(--st-spacing-md) var(--st-spacing-lg);
47
95
  border-bottom: 2px solid var(--st-color-border);
48
96
  color: var(--st-color-text-muted);
@@ -54,18 +102,42 @@ export class StTable extends LitElement {
54
102
  border-bottom: 1px solid var(--st-color-border);
55
103
  }
56
104
 
105
+ .align-center {
106
+ text-align: center;
107
+ }
108
+ .align-end {
109
+ text-align: end;
110
+ }
111
+
57
112
  /* Modifiers */
58
113
  :host([dense]) th,
59
114
  :host([dense]) td {
60
115
  padding: var(--st-spacing-sm) var(--st-spacing-md);
61
116
  }
62
117
 
118
+ :host([sticky-header]) th {
119
+ position: sticky;
120
+ top: 0;
121
+ z-index: 1;
122
+ background-color: var(--st-color-bg);
123
+ }
124
+
63
125
  :host([striped]) tbody tr:nth-of-type(odd) {
64
- background-color: var(--st-color-surface-muted, #f8fafc);
126
+ background-color: var(--st-color-surface-muted);
127
+ }
128
+
129
+ :host([hoverable]) tbody tr:hover,
130
+ tbody tr.clickable:hover {
131
+ background-color: var(--st-color-surface-hover);
65
132
  }
66
133
 
67
- :host([hoverable]) tbody tr:hover {
68
- background-color: var(--st-color-surface-hover, #f1f5f9);
134
+ tbody tr.clickable {
135
+ cursor: pointer;
136
+ }
137
+
138
+ tbody tr.clickable:focus-visible {
139
+ outline: 2px solid var(--st-color-primary);
140
+ outline-offset: -2px;
69
141
  }
70
142
 
71
143
  /* ==========================================================
@@ -115,7 +187,7 @@ export class StTable extends LitElement {
115
187
  /* Inject the header name on the left */
116
188
  :host([mode="vertical"]) td::before {
117
189
  content: attr(data-label);
118
- font-weight: 600;
190
+ font-weight: var(--st-font-weight-semibold);
119
191
  text-align: left;
120
192
  padding-right: var(--st-spacing-md);
121
193
  color: var(--st-color-text-muted);
@@ -123,46 +195,104 @@ export class StTable extends LitElement {
123
195
 
124
196
  .empty-state {
125
197
  text-align: center;
126
- padding: 2rem !important;
198
+ padding: var(--st-spacing-xl) !important;
127
199
  color: var(--st-color-text-muted);
128
200
  font-style: italic;
129
201
  }
130
202
  `,
131
203
  ];
132
204
 
205
+ private _alignClass(col: TableColumn) {
206
+ return classMap({"align-center": col.align === "center", "align-end": col.align === "end"});
207
+ }
208
+
209
+ private _onRowClick(row: Record<string, any>) {
210
+ if (!this.clickableRows) return;
211
+ this.dispatchEvent(
212
+ new CustomEvent("st-row-click", {detail: row, bubbles: true, composed: true}),
213
+ );
214
+ }
215
+
216
+ private _onRowKeydown(e: KeyboardEvent, row: Record<string, any>) {
217
+ if (!this.clickableRows || (e.key !== "Enter" && e.key !== " ")) return;
218
+ e.preventDefault();
219
+ this._onRowClick(row);
220
+ }
221
+
222
+ private _renderBody() {
223
+ const span = Math.max(this.columns.length, 1);
224
+ if (this.loading) {
225
+ return Array.from(
226
+ {length: SKELETON_ROWS},
227
+ () => html`
228
+ <tr role="row">
229
+ ${this.columns.map(
230
+ () => html`
231
+ <td role="cell"><st-skeleton variant="text" width="70%"></st-skeleton></td>
232
+ `,
233
+ )}
234
+ </tr>
235
+ `,
236
+ );
237
+ }
238
+ if (this.data.length === 0) {
239
+ return html`
240
+ <tr role="row">
241
+ <td role="cell" colspan=${span} class="empty-state">${this.emptyText}</td>
242
+ </tr>
243
+ `;
244
+ }
245
+ return this.data.map(
246
+ (row, index) => html`
247
+ <tr
248
+ role="row"
249
+ class=${classMap({clickable: this.clickableRows})}
250
+ tabindex=${ifDefined(this.clickableRows ? "0" : undefined)}
251
+ @click=${() => this._onRowClick(row)}
252
+ @keydown=${(e: KeyboardEvent) => this._onRowKeydown(e, row)}
253
+ >
254
+ ${this.columns.map(
255
+ (col) => html`
256
+ <td role="cell" class=${this._alignClass(col)} data-label=${col.header}>
257
+ ${col.render ? col.render(row, index) : (row[col.key] ?? "")}
258
+ </td>
259
+ `,
260
+ )}
261
+ </tr>
262
+ `,
263
+ );
264
+ }
265
+
266
+ private _renderHead() {
267
+ return html`
268
+ <thead role="rowgroup">
269
+ <tr role="row">
270
+ ${this.columns.map(
271
+ (col) => html`
272
+ <th
273
+ role="columnheader"
274
+ scope="col"
275
+ class=${this._alignClass(col)}
276
+ style=${ifDefined(col.width ? `width:${col.width}` : undefined)}
277
+ >
278
+ ${col.header}
279
+ </th>
280
+ `,
281
+ )}
282
+ </tr>
283
+ </thead>
284
+ `;
285
+ }
286
+
133
287
  render() {
134
288
  return html`
135
289
  <div class="table-wrapper">
136
- <!-- 🚀 FIX: Explicit ARIA roles map to preserve semantics when CSS 'display' changes -->
137
- <table role="table">
138
- <thead role="rowgroup">
139
- <tr role="row">
140
- ${this.columns.map(
141
- (col) => html`<th role="columnheader" scope="col">${col.header}</th>`,
142
- )}
143
- </tr>
144
- </thead>
290
+ <!-- Explicit ARIA roles preserve semantics when CSS 'display' changes in vertical mode -->
291
+ <table role="table" aria-busy=${this.loading ? "true" : "false"}>
292
+ ${this.caption ? html`<caption>${this.caption}</caption>` : nothing}
293
+ ${this.columns.length ? this._renderHead() : nothing}
145
294
  <tbody role="rowgroup">
146
- ${this.data.length === 0
147
- ? html`
148
- <tr role="row">
149
- <td role="cell" colspan=${this.columns.length} class="empty-state">
150
- No data available.
151
- </td>
152
- </tr>
153
- `
154
- : this.data.map(
155
- (row) => html`
156
- <tr role="row">
157
- ${this.columns.map(
158
- // 🚀 FIX: Nullish coalescing prevents printing "undefined" for sparse data objects
159
- (col) => html`
160
- <td role="cell" data-label=${col.header}>${row[col.key] ?? ""}</td>
161
- `,
162
- )}
163
- </tr>
164
- `,
165
- )}
295
+ ${this._renderBody()}
166
296
  </tbody>
167
297
  </table>
168
298
  </div>
@@ -0,0 +1,113 @@
1
+ import {html, css} from "lit";
2
+ import {customElement, state} from "lit/decorators.js";
3
+ import {resetStyles} from "../../styles/reset.js";
4
+ import {StRowItem} from "../section/row-item.js";
5
+
6
+ /**
7
+ * One team member inside `st-team`.
8
+ *
9
+ * Slots: `photo` (an `img`, hidden when empty), `name` (a real heading such as `<h3>`), `role`,
10
+ * the default slot (a short bio) and `links` (social or contact links).
11
+ */
12
+ @customElement("st-person")
13
+ export class StPerson extends StRowItem {
14
+ @state() private _hasPhoto = false;
15
+ @state() private _hasLinks = false;
16
+
17
+ static styles = [
18
+ resetStyles,
19
+ css`
20
+ :host {
21
+ display: block;
22
+ text-align: center;
23
+ }
24
+
25
+ .person {
26
+ display: grid;
27
+ justify-items: center;
28
+ gap: var(--st-spacing-xs);
29
+ }
30
+
31
+ .photo {
32
+ display: block;
33
+ overflow: hidden;
34
+ width: 7rem;
35
+ height: 7rem;
36
+ margin-bottom: var(--st-spacing-sm);
37
+ border-radius: 50%;
38
+ background: var(--st-color-surface-muted);
39
+ }
40
+
41
+ .photo[hidden] {
42
+ display: none;
43
+ }
44
+
45
+ .photo ::slotted(img) {
46
+ width: 100%;
47
+ height: 100%;
48
+ object-fit: cover;
49
+ }
50
+
51
+ ::slotted([slot="name"]) {
52
+ margin: 0 !important;
53
+ font-size: var(--st-font-size-lg) !important;
54
+ }
55
+
56
+ ::slotted([slot="role"]) {
57
+ display: block;
58
+ color: var(--st-color-primary-text);
59
+ font-size: var(--st-font-size-sm);
60
+ font-weight: var(--st-font-weight-bold);
61
+ }
62
+
63
+ .bio {
64
+ color: var(--st-color-text-muted);
65
+ font-size: var(--st-font-size-sm);
66
+ }
67
+
68
+ .bio ::slotted(*) {
69
+ margin: 0;
70
+ }
71
+
72
+ .links {
73
+ display: flex;
74
+ flex-wrap: wrap;
75
+ justify-content: center;
76
+ gap: var(--st-spacing-md);
77
+ margin-top: var(--st-spacing-sm);
78
+ }
79
+
80
+ .links[hidden] {
81
+ display: none;
82
+ }
83
+ `,
84
+ ];
85
+
86
+ render() {
87
+ return this.frame(html`
88
+ <div class="person">
89
+ <span class="photo" ?hidden=${!this._hasPhoto}>
90
+ <slot
91
+ name="photo"
92
+ @slotchange=${(e: Event) => (this._hasPhoto = (e.target as HTMLSlotElement).assignedNodes().length > 0)}
93
+ ></slot>
94
+ </span>
95
+ <slot name="name"></slot>
96
+ <slot name="role"></slot>
97
+ <div class="bio"><slot></slot></div>
98
+ <div class="links" ?hidden=${!this._hasLinks}>
99
+ <slot
100
+ name="links"
101
+ @slotchange=${(e: Event) => (this._hasLinks = (e.target as HTMLSlotElement).assignedNodes().length > 0)}
102
+ ></slot>
103
+ </div>
104
+ </div>
105
+ `);
106
+ }
107
+ }
108
+
109
+ declare global {
110
+ interface HTMLElementTagNameMap {
111
+ "st-person": StPerson;
112
+ }
113
+ }