@phcdevworks/spectre-components 1.20.0 → 1.21.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 (350) hide show
  1. package/README.md +672 -49
  2. package/dist/accordion-item.cjs +540 -0
  3. package/dist/accordion-item.cjs.map +1 -0
  4. package/dist/accordion-item.d.cts +59 -0
  5. package/dist/accordion-item.d.ts +59 -0
  6. package/dist/accordion-item.js +537 -0
  7. package/dist/accordion-item.js.map +1 -0
  8. package/dist/accordion.cjs +468 -0
  9. package/dist/accordion.cjs.map +1 -0
  10. package/dist/accordion.d.cts +38 -0
  11. package/dist/accordion.d.ts +38 -0
  12. package/dist/accordion.js +465 -0
  13. package/dist/accordion.js.map +1 -0
  14. package/dist/alert.cjs +166 -65
  15. package/dist/alert.cjs.map +1 -1
  16. package/dist/alert.d.cts +41 -8
  17. package/dist/alert.d.ts +41 -8
  18. package/dist/alert.js +168 -67
  19. package/dist/alert.js.map +1 -1
  20. package/dist/avatar.cjs +27 -1
  21. package/dist/avatar.cjs.map +1 -1
  22. package/dist/avatar.d.cts +19 -3
  23. package/dist/avatar.d.ts +19 -3
  24. package/dist/avatar.js +27 -1
  25. package/dist/avatar.js.map +1 -1
  26. package/dist/badge.cjs +35 -2
  27. package/dist/badge.cjs.map +1 -1
  28. package/dist/badge.d.cts +31 -3
  29. package/dist/badge.d.ts +31 -3
  30. package/dist/badge.js +35 -2
  31. package/dist/badge.js.map +1 -1
  32. package/dist/breadcrumb.cjs +464 -0
  33. package/dist/breadcrumb.cjs.map +1 -0
  34. package/dist/breadcrumb.d.cts +32 -0
  35. package/dist/breadcrumb.d.ts +32 -0
  36. package/dist/breadcrumb.js +461 -0
  37. package/dist/breadcrumb.js.map +1 -0
  38. package/dist/button.cjs +32 -2
  39. package/dist/button.cjs.map +1 -1
  40. package/dist/button.d.cts +19 -3
  41. package/dist/button.d.ts +19 -3
  42. package/dist/button.js +32 -2
  43. package/dist/button.js.map +1 -1
  44. package/dist/card-bleed.cjs +458 -0
  45. package/dist/card-bleed.cjs.map +1 -0
  46. package/dist/card-bleed.d.cts +37 -0
  47. package/dist/card-bleed.d.ts +37 -0
  48. package/dist/card-bleed.js +455 -0
  49. package/dist/card-bleed.js.map +1 -0
  50. package/dist/card.cjs +27 -1
  51. package/dist/card.cjs.map +1 -1
  52. package/dist/card.d.cts +19 -3
  53. package/dist/card.d.ts +19 -3
  54. package/dist/card.js +27 -1
  55. package/dist/card.js.map +1 -1
  56. package/dist/carousel.cjs +655 -0
  57. package/dist/carousel.cjs.map +1 -0
  58. package/dist/carousel.d.cts +79 -0
  59. package/dist/carousel.d.ts +79 -0
  60. package/dist/carousel.js +652 -0
  61. package/dist/carousel.js.map +1 -0
  62. package/dist/checkbox.cjs +3 -1
  63. package/dist/checkbox.cjs.map +1 -1
  64. package/dist/checkbox.js +3 -1
  65. package/dist/checkbox.js.map +1 -1
  66. package/dist/choice-card.cjs +524 -0
  67. package/dist/choice-card.cjs.map +1 -0
  68. package/dist/choice-card.d.cts +81 -0
  69. package/dist/choice-card.d.ts +81 -0
  70. package/dist/choice-card.js +521 -0
  71. package/dist/choice-card.js.map +1 -0
  72. package/dist/container.cjs +23 -6
  73. package/dist/container.cjs.map +1 -1
  74. package/dist/container.d.cts +9 -3
  75. package/dist/container.d.ts +9 -3
  76. package/dist/container.js +23 -7
  77. package/dist/container.js.map +1 -1
  78. package/dist/datepicker.cjs +580 -0
  79. package/dist/datepicker.cjs.map +1 -0
  80. package/dist/datepicker.d.cts +78 -0
  81. package/dist/datepicker.d.ts +78 -0
  82. package/dist/datepicker.js +577 -0
  83. package/dist/datepicker.js.map +1 -0
  84. package/dist/dom-CX9bgbcQ.d.cts +3 -0
  85. package/dist/dom-CX9bgbcQ.d.ts +3 -0
  86. package/dist/dropdown.cjs +24 -0
  87. package/dist/dropdown.cjs.map +1 -1
  88. package/dist/dropdown.d.cts +3 -2
  89. package/dist/dropdown.d.ts +3 -2
  90. package/dist/dropdown.js +25 -1
  91. package/dist/dropdown.js.map +1 -1
  92. package/dist/external-auth-button.cjs +494 -0
  93. package/dist/external-auth-button.cjs.map +1 -0
  94. package/dist/external-auth-button.d.cts +71 -0
  95. package/dist/external-auth-button.d.ts +71 -0
  96. package/dist/external-auth-button.js +491 -0
  97. package/dist/external-auth-button.js.map +1 -0
  98. package/dist/fieldset.cjs +3 -1
  99. package/dist/fieldset.cjs.map +1 -1
  100. package/dist/fieldset.js +3 -1
  101. package/dist/fieldset.js.map +1 -1
  102. package/dist/file-input.cjs +371 -0
  103. package/dist/file-input.cjs.map +1 -0
  104. package/dist/file-input.d.cts +96 -0
  105. package/dist/file-input.d.ts +96 -0
  106. package/dist/file-input.js +367 -0
  107. package/dist/file-input.js.map +1 -0
  108. package/dist/footer-chip.cjs +22 -2
  109. package/dist/footer-chip.cjs.map +1 -1
  110. package/dist/footer-chip.d.cts +12 -1
  111. package/dist/footer-chip.d.ts +12 -1
  112. package/dist/footer-chip.js +22 -2
  113. package/dist/footer-chip.js.map +1 -1
  114. package/dist/footer-link.cjs +19 -1
  115. package/dist/footer-link.cjs.map +1 -1
  116. package/dist/footer-link.d.cts +12 -1
  117. package/dist/footer-link.d.ts +12 -1
  118. package/dist/footer-link.js +19 -1
  119. package/dist/footer-link.js.map +1 -1
  120. package/dist/footer.cjs +30 -1
  121. package/dist/footer.cjs.map +1 -1
  122. package/dist/footer.d.cts +2 -1
  123. package/dist/footer.d.ts +2 -1
  124. package/dist/footer.js +31 -2
  125. package/dist/footer.js.map +1 -1
  126. package/dist/{form-DpPtizpY.d.cts → form-CVO7mlDa.d.cts} +38 -9
  127. package/dist/{form-DpPtizpY.d.ts → form-CVO7mlDa.d.ts} +38 -9
  128. package/dist/grid.cjs +35 -1
  129. package/dist/grid.cjs.map +1 -1
  130. package/dist/grid.d.cts +9 -3
  131. package/dist/grid.d.ts +9 -3
  132. package/dist/grid.js +35 -2
  133. package/dist/grid.js.map +1 -1
  134. package/dist/icon-box.cjs +27 -1
  135. package/dist/icon-box.cjs.map +1 -1
  136. package/dist/icon-box.d.cts +19 -3
  137. package/dist/icon-box.d.ts +19 -3
  138. package/dist/icon-box.js +27 -1
  139. package/dist/icon-box.js.map +1 -1
  140. package/dist/index.cjs +3654 -107
  141. package/dist/index.cjs.map +1 -1
  142. package/dist/index.d.cts +26 -1
  143. package/dist/index.d.ts +26 -1
  144. package/dist/index.js +3594 -110
  145. package/dist/index.js.map +1 -1
  146. package/dist/input-group.cjs +471 -0
  147. package/dist/input-group.cjs.map +1 -0
  148. package/dist/input-group.d.cts +31 -0
  149. package/dist/input-group.d.ts +31 -0
  150. package/dist/input-group.js +468 -0
  151. package/dist/input-group.js.map +1 -0
  152. package/dist/input.cjs +96 -4
  153. package/dist/input.cjs.map +1 -1
  154. package/dist/input.d.cts +45 -6
  155. package/dist/input.d.ts +45 -6
  156. package/dist/input.js +98 -6
  157. package/dist/input.js.map +1 -1
  158. package/dist/label.cjs +3 -1
  159. package/dist/label.cjs.map +1 -1
  160. package/dist/label.js +3 -1
  161. package/dist/label.js.map +1 -1
  162. package/dist/list-group-item.cjs +367 -0
  163. package/dist/list-group-item.cjs.map +1 -0
  164. package/dist/list-group-item.d.cts +73 -0
  165. package/dist/list-group-item.d.ts +73 -0
  166. package/dist/list-group-item.js +364 -0
  167. package/dist/list-group-item.js.map +1 -0
  168. package/dist/list-group.cjs +610 -0
  169. package/dist/list-group.cjs.map +1 -0
  170. package/dist/list-group.d.cts +58 -0
  171. package/dist/list-group.d.ts +58 -0
  172. package/dist/list-group.js +607 -0
  173. package/dist/list-group.js.map +1 -0
  174. package/dist/modal.cjs +38 -35
  175. package/dist/modal.cjs.map +1 -1
  176. package/dist/modal.d.cts +1 -3
  177. package/dist/modal.d.ts +1 -3
  178. package/dist/modal.js +38 -35
  179. package/dist/modal.js.map +1 -1
  180. package/dist/nav-item.cjs +107 -4
  181. package/dist/nav-item.cjs.map +1 -1
  182. package/dist/nav-item.d.cts +52 -2
  183. package/dist/nav-item.d.ts +52 -2
  184. package/dist/nav-item.js +108 -5
  185. package/dist/nav-item.js.map +1 -1
  186. package/dist/nav.cjs +25 -1
  187. package/dist/nav.cjs.map +1 -1
  188. package/dist/nav.d.cts +2 -1
  189. package/dist/nav.d.ts +2 -1
  190. package/dist/nav.js +26 -2
  191. package/dist/nav.js.map +1 -1
  192. package/dist/offcanvas.cjs +621 -0
  193. package/dist/offcanvas.cjs.map +1 -0
  194. package/dist/offcanvas.d.cts +61 -0
  195. package/dist/offcanvas.d.ts +61 -0
  196. package/dist/offcanvas.js +617 -0
  197. package/dist/offcanvas.js.map +1 -0
  198. package/dist/pagination.cjs +452 -0
  199. package/dist/pagination.cjs.map +1 -0
  200. package/dist/pagination.d.cts +69 -0
  201. package/dist/pagination.d.ts +69 -0
  202. package/dist/pagination.js +448 -0
  203. package/dist/pagination.js.map +1 -0
  204. package/dist/popover.cjs +534 -0
  205. package/dist/popover.cjs.map +1 -0
  206. package/dist/popover.d.cts +59 -0
  207. package/dist/popover.d.ts +59 -0
  208. package/dist/popover.js +530 -0
  209. package/dist/popover.js.map +1 -0
  210. package/dist/pricing-card.cjs +121 -64
  211. package/dist/pricing-card.cjs.map +1 -1
  212. package/dist/pricing-card.d.cts +21 -7
  213. package/dist/pricing-card.d.ts +21 -7
  214. package/dist/pricing-card.js +122 -65
  215. package/dist/pricing-card.js.map +1 -1
  216. package/dist/progress.cjs +403 -0
  217. package/dist/progress.cjs.map +1 -0
  218. package/dist/progress.d.cts +70 -0
  219. package/dist/progress.d.ts +70 -0
  220. package/dist/progress.js +398 -0
  221. package/dist/progress.js.map +1 -0
  222. package/dist/prose.cjs +425 -0
  223. package/dist/prose.cjs.map +1 -0
  224. package/dist/prose.d.cts +21 -0
  225. package/dist/prose.d.ts +21 -0
  226. package/dist/prose.js +422 -0
  227. package/dist/prose.js.map +1 -0
  228. package/dist/radio.cjs +3 -1
  229. package/dist/radio.cjs.map +1 -1
  230. package/dist/radio.js +3 -1
  231. package/dist/radio.js.map +1 -1
  232. package/dist/range.cjs +381 -0
  233. package/dist/range.cjs.map +1 -0
  234. package/dist/range.d.cts +76 -0
  235. package/dist/range.d.ts +76 -0
  236. package/dist/range.js +378 -0
  237. package/dist/range.js.map +1 -0
  238. package/dist/rating.cjs +33 -0
  239. package/dist/rating.cjs.map +1 -1
  240. package/dist/rating.d.cts +38 -3
  241. package/dist/rating.d.ts +38 -3
  242. package/dist/rating.js +33 -0
  243. package/dist/rating.js.map +1 -1
  244. package/dist/section.cjs +27 -3
  245. package/dist/section.cjs.map +1 -1
  246. package/dist/section.d.cts +16 -1
  247. package/dist/section.d.ts +16 -1
  248. package/dist/section.js +27 -4
  249. package/dist/section.js.map +1 -1
  250. package/dist/select.cjs +6 -1
  251. package/dist/select.cjs.map +1 -1
  252. package/dist/select.d.cts +7 -1
  253. package/dist/select.d.ts +7 -1
  254. package/dist/select.js +6 -1
  255. package/dist/select.js.map +1 -1
  256. package/dist/sidebar-link.cjs +19 -1
  257. package/dist/sidebar-link.cjs.map +1 -1
  258. package/dist/sidebar-link.d.cts +13 -2
  259. package/dist/sidebar-link.d.ts +13 -2
  260. package/dist/sidebar-link.js +19 -1
  261. package/dist/sidebar-link.js.map +1 -1
  262. package/dist/sidebar-toggle.cjs +3 -1
  263. package/dist/sidebar-toggle.cjs.map +1 -1
  264. package/dist/sidebar-toggle.js +3 -1
  265. package/dist/sidebar-toggle.js.map +1 -1
  266. package/dist/sidebar.cjs +33 -1
  267. package/dist/sidebar.cjs.map +1 -1
  268. package/dist/sidebar.d.cts +1 -0
  269. package/dist/sidebar.d.ts +1 -0
  270. package/dist/sidebar.js +34 -2
  271. package/dist/sidebar.js.map +1 -1
  272. package/dist/spinner.cjs +2 -1
  273. package/dist/spinner.cjs.map +1 -1
  274. package/dist/spinner.d.cts +2 -2
  275. package/dist/spinner.d.ts +2 -2
  276. package/dist/spinner.js +2 -1
  277. package/dist/spinner.js.map +1 -1
  278. package/dist/stack.cjs +4 -2
  279. package/dist/stack.cjs.map +1 -1
  280. package/dist/stack.d.cts +2 -2
  281. package/dist/stack.d.ts +2 -2
  282. package/dist/stack.js +4 -2
  283. package/dist/stack.js.map +1 -1
  284. package/dist/states-Bgzwu_XZ.d.cts +9 -0
  285. package/dist/states-Bgzwu_XZ.d.ts +9 -0
  286. package/dist/stepper.cjs +495 -0
  287. package/dist/stepper.cjs.map +1 -0
  288. package/dist/stepper.d.cts +40 -0
  289. package/dist/stepper.d.ts +40 -0
  290. package/dist/stepper.js +491 -0
  291. package/dist/stepper.js.map +1 -0
  292. package/dist/switch.cjs +492 -0
  293. package/dist/switch.cjs.map +1 -0
  294. package/dist/switch.d.cts +82 -0
  295. package/dist/switch.d.ts +82 -0
  296. package/dist/switch.js +488 -0
  297. package/dist/switch.js.map +1 -0
  298. package/dist/tab-panel.cjs +465 -0
  299. package/dist/tab-panel.cjs.map +1 -0
  300. package/dist/tab-panel.d.cts +48 -0
  301. package/dist/tab-panel.d.ts +48 -0
  302. package/dist/tab-panel.js +462 -0
  303. package/dist/tab-panel.js.map +1 -0
  304. package/dist/table.cjs +506 -0
  305. package/dist/table.cjs.map +1 -0
  306. package/dist/table.d.cts +54 -0
  307. package/dist/table.d.ts +54 -0
  308. package/dist/table.js +501 -0
  309. package/dist/table.js.map +1 -0
  310. package/dist/tabs.cjs +596 -0
  311. package/dist/tabs.cjs.map +1 -0
  312. package/dist/tabs.d.cts +65 -0
  313. package/dist/tabs.d.ts +65 -0
  314. package/dist/tabs.js +592 -0
  315. package/dist/tabs.js.map +1 -0
  316. package/dist/tag.cjs +27 -1
  317. package/dist/tag.cjs.map +1 -1
  318. package/dist/tag.d.cts +19 -3
  319. package/dist/tag.d.ts +19 -3
  320. package/dist/tag.js +27 -1
  321. package/dist/tag.js.map +1 -1
  322. package/dist/testimonial.cjs +130 -64
  323. package/dist/testimonial.cjs.map +1 -1
  324. package/dist/testimonial.d.cts +23 -8
  325. package/dist/testimonial.d.ts +23 -8
  326. package/dist/testimonial.js +131 -65
  327. package/dist/testimonial.js.map +1 -1
  328. package/dist/text.cjs +65 -6
  329. package/dist/text.cjs.map +1 -1
  330. package/dist/text.d.cts +24 -3
  331. package/dist/text.d.ts +24 -3
  332. package/dist/text.js +64 -8
  333. package/dist/text.js.map +1 -1
  334. package/dist/textarea.cjs +3 -0
  335. package/dist/textarea.cjs.map +1 -1
  336. package/dist/textarea.d.cts +7 -1
  337. package/dist/textarea.d.ts +7 -1
  338. package/dist/textarea.js +3 -0
  339. package/dist/textarea.js.map +1 -1
  340. package/dist/toast.cjs +2 -1
  341. package/dist/toast.cjs.map +1 -1
  342. package/dist/toast.d.cts +2 -2
  343. package/dist/toast.d.ts +2 -2
  344. package/dist/toast.js +2 -1
  345. package/dist/toast.js.map +1 -1
  346. package/dist/tooltip.cjs.map +1 -1
  347. package/dist/tooltip.d.cts +2 -2
  348. package/dist/tooltip.d.ts +2 -2
  349. package/dist/tooltip.js.map +1 -1
  350. package/package.json +126 -11
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
- import { getButtonClasses, getInputLabelClasses, getInputClasses, getTextareaClasses, getSelectClasses, getCheckboxClasses, getRadioClasses, getLabelClasses, getFieldsetLegendClasses, getFieldsetClasses, getBadgeClasses, getCardClasses, getIconBoxClasses, getRatingClasses, getRatingStarClasses, getRatingStarsClasses, getRatingTextClasses, getTestimonialClasses, getAlertClasses, getAvatarClasses, getSpinnerClasses, getTagClasses, getPricingCardClasses, getContainerClasses, getGridClasses, getSectionClasses, getStackClasses, getDropdownClasses, getDropdownMenuClasses, getFooterClasses, getFooterChipClasses, getFooterLinkClasses, getModalOverlayClasses, getModalClasses, getNavClasses, getNavLinkClasses, getSidebarClasses, getSidebarToggleClasses, getSidebarBackdropClasses, getSidebarLinkClasses, getToastClasses, getToastIconClasses, getTooltipClasses, getTextClasses } from '@phcdevworks/spectre-ui';
2
- import { LitElement, html, nothing } from 'lit';
1
+ import { getButtonClasses, getInputLabelClasses, getInputClasses, getInputErrorMessageClasses, getInputHelperTextClasses, getInputWrapperClasses, getTextareaClasses, getSelectClasses, getCheckboxClasses, getRadioClasses, getLabelClasses, getFieldsetLegendClasses, getFieldsetClasses, getBadgeClasses, getCardClasses, getIconBoxClasses, getRatingClasses, getRatingStarClasses, getRatingStarsClasses, getRatingTextClasses, getTestimonialClasses, getTestimonialAuthorClasses, getTestimonialAuthorInfoClasses, getTestimonialAuthorNameClasses, getTestimonialAuthorTitleClasses, getTestimonialQuoteClasses, getAlertClasses, getAlertIconClasses, getAlertDismissClasses, getAvatarClasses, getSpinnerClasses, getTagClasses, getPricingCardClasses, getPricingCardBadgeClasses, getPricingCardPriceContainerClasses, getPricingCardPriceClasses, getPricingCardDescriptionClasses, getContainerClasses, getGridClasses, getSectionClasses, getStackClasses, getDropdownItemClasses, getDropdownHeaderClasses, getDropdownDividerClasses, getDropdownClasses, getDropdownMenuClasses, getFooterClasses, getFooterTextClasses, getFooterMutedClasses, getFooterLinksClasses, getFooterHeadingClasses, getFooterDividerClasses, getFooterChipClasses, getFooterLinkClasses, getModalOverlayClasses, getModalClasses, getNavClasses, getNavLinksClasses, getNavLinkClasses, getSidebarClasses, getSidebarHeaderClasses, getSidebarGroupClasses, getSidebarGroupSummaryClasses, getSidebarToggleClasses, getSidebarBackdropClasses, getSidebarLinkClasses, getToastClasses, getToastIconClasses, getTooltipClasses, getLeadClasses, getDisplayClasses, getHeadingClasses, getTextClasses, getTabsClasses, getTabsListClasses, getTabsItemClasses, getTabsPanelClasses, getAccordionClasses, getAccordionItemClasses, getAccordionHeaderClasses, getAccordionIconClasses, getAccordionPanelClasses, getBreadcrumbLinkClasses, getBreadcrumbClasses, getBreadcrumbItemClasses, getBreadcrumbSeparatorClasses, getListGroupItemTextClasses, getListGroupItemHeadingClasses, getListGroupClasses, getListGroupItemClasses, getOffcanvasBackdropClasses, getOffcanvasClasses, getOffcanvasHeaderClasses, getOffcanvasBodyClasses, getOffcanvasFooterClasses, getCarouselCaptionClasses, getCarouselClasses, getCarouselViewportClasses, getCarouselSlideClasses, getCarouselControlClasses, getCarouselIndicatorsClasses, getCarouselIndicatorClasses, getTableClasses, getTableRowClasses, getTableWrapperClasses, getPaginationItemClasses, getPaginationClasses, getPaginationEllipsisClasses, getStepperClasses, getStepperStepClasses, getStepperIndicatorClasses, getStepperLabelClasses, getCardBleedClasses, getProgressLabelClasses, getProgressClasses, getProgressBarClasses, getSwitchClasses, getRangeClasses, getFileInputClasses, getExternalAuthButtonClasses, getExternalAuthButtonIconClasses, getChoiceCardClasses, getInputGroupAddonClasses, getInputGroupClasses, getPopoverClasses, getPopoverArrowClasses, getPopoverHeaderClasses, getPopoverBodyClasses, getDayClasses, getDatepickerClasses, getDatepickerHeaderClasses, getDatepickerGridClasses, getDatepickerWeekdayClasses, getProseClasses } from '@phcdevworks/spectre-ui';
2
+ import { svg, LitElement, html, nothing } from 'lit';
3
3
  import { ifDefined } from 'lit/directives/if-defined.js';
4
4
  import { live } from 'lit/directives/live.js';
5
5
  import { literal, html as html$1 } from 'lit/static-html.js';
6
+ import { styleMap } from 'lit/directives/style-map.js';
6
7
 
7
8
  // src/utils/form.ts
8
9
  var spectreInputSizes = ["sm", "md", "lg"];
@@ -17,7 +18,11 @@ var spectreButtonVariants = [
17
18
  "success",
18
19
  "cta",
19
20
  "accent",
20
- "inverse"
21
+ "inverse",
22
+ "warning",
23
+ "link",
24
+ "light",
25
+ "dark"
21
26
  ];
22
27
  function isButtonVariant(value) {
23
28
  return spectreButtonVariants.includes(value);
@@ -55,7 +60,8 @@ var spectreBadgeVariants = [
55
60
  "outline",
56
61
  "accent",
57
62
  "cta",
58
- "inverse"
63
+ "inverse",
64
+ "brand"
59
65
  ];
60
66
  function isBadgeVariant(value) {
61
67
  return spectreBadgeVariants.includes(value);
@@ -65,7 +71,8 @@ var spectreAlertVariants = [
65
71
  "success",
66
72
  "warning",
67
73
  "danger",
68
- "neutral"
74
+ "neutral",
75
+ "brand"
69
76
  ];
70
77
  function isAlertVariant(value) {
71
78
  return spectreAlertVariants.includes(value);
@@ -137,7 +144,8 @@ var spectreSpinnerVariants = [
137
144
  "info",
138
145
  "neutral",
139
146
  "accent",
140
- "cta"
147
+ "cta",
148
+ "inverse"
141
149
  ];
142
150
  function isSpinnerVariant(value) {
143
151
  return spectreSpinnerVariants.includes(value);
@@ -167,7 +175,7 @@ var spectreAvatarShapes = ["circle", "square"];
167
175
  function isAvatarShape(value) {
168
176
  return spectreAvatarShapes.includes(value);
169
177
  }
170
- var spectreContainerMaxWidths = ["prose"];
178
+ var spectreContainerMaxWidths = ["none", "prose", "wide"];
171
179
  function isContainerMaxWidth(value) {
172
180
  return spectreContainerMaxWidths.includes(
173
181
  value
@@ -322,7 +330,7 @@ var spectreStackDirections = ["vertical", "horizontal"];
322
330
  function isStackDirection(value) {
323
331
  return spectreStackDirections.includes(value);
324
332
  }
325
- var spectreStackBases = ["sidebar"];
333
+ var spectreStackBases = ["none", "sidebar"];
326
334
  function isStackBasis(value) {
327
335
  return spectreStackBases.includes(value);
328
336
  }
@@ -353,7 +361,8 @@ var spectreToastVariants = [
353
361
  "info",
354
362
  "success",
355
363
  "warning",
356
- "danger"
364
+ "danger",
365
+ "neutral"
357
366
  ];
358
367
  function isToastVariant(value) {
359
368
  return spectreToastVariants.includes(value);
@@ -397,7 +406,12 @@ var spectreTextVariants = [
397
406
  "meta",
398
407
  "brand",
399
408
  "onInverse",
400
- "onInverseMuted"
409
+ "onInverseMuted",
410
+ "onSurface",
411
+ "onSurfaceMuted",
412
+ "onSurfaceSubtle",
413
+ "onSurfaceMeta",
414
+ "onSurfaceBrand"
401
415
  ];
402
416
  function isTextVariant(value) {
403
417
  return spectreTextVariants.includes(value);
@@ -428,6 +442,114 @@ var spectreTextTransforms = [
428
442
  function isTextTransform(value) {
429
443
  return spectreTextTransforms.includes(value);
430
444
  }
445
+ var spectreTabsVariants = ["line", "pill"];
446
+ function isTabsVariant(value) {
447
+ return spectreTabsVariants.includes(value);
448
+ }
449
+ var spectreOffcanvasPlacements = [
450
+ "start",
451
+ "end",
452
+ "top",
453
+ "bottom"
454
+ ];
455
+ function isOffcanvasPlacement(value) {
456
+ return spectreOffcanvasPlacements.includes(
457
+ value
458
+ );
459
+ }
460
+ var spectreTableSizes = ["sm", "md"];
461
+ function isTableSize(value) {
462
+ return spectreTableSizes.includes(value);
463
+ }
464
+ var spectreStepperOrientations = ["horizontal", "vertical"];
465
+ function isStepperOrientation(value) {
466
+ return spectreStepperOrientations.includes(
467
+ value
468
+ );
469
+ }
470
+ var spectreSpacingScale = ["sm", "md", "lg"];
471
+ function isSpacingStep(value) {
472
+ return spectreSpacingScale.includes(value);
473
+ }
474
+ var spectreGridColStarts = [
475
+ 1,
476
+ 2,
477
+ 3,
478
+ 4,
479
+ 5,
480
+ 6,
481
+ 7,
482
+ 8,
483
+ 9,
484
+ 10,
485
+ 11,
486
+ 12
487
+ ];
488
+ function isGridColStart(value) {
489
+ return spectreGridColStarts.includes(value);
490
+ }
491
+ function isGridColStartOptions(value) {
492
+ if (typeof value !== "object" || value === null) {
493
+ return false;
494
+ }
495
+ const candidate = value;
496
+ return (candidate.base === void 0 || isGridColStart(candidate.base)) && (candidate.md === void 0 || isGridColStart(candidate.md)) && (candidate.lg === void 0 || isGridColStart(candidate.lg));
497
+ }
498
+ var spectrePopoverPlacements = [
499
+ "top",
500
+ "bottom",
501
+ "left",
502
+ "right"
503
+ ];
504
+ function isPopoverPlacement(value) {
505
+ return spectrePopoverPlacements.includes(
506
+ value
507
+ );
508
+ }
509
+ var spectreProgressVariants = [
510
+ "brand",
511
+ "neutral",
512
+ "info",
513
+ "success",
514
+ "warning",
515
+ "danger"
516
+ ];
517
+ function isProgressVariant(value) {
518
+ return spectreProgressVariants.includes(
519
+ value
520
+ );
521
+ }
522
+ var spectreTextPresets = ["heading", "display", "lead"];
523
+ function isTextPreset(value) {
524
+ return spectreTextPresets.includes(value);
525
+ }
526
+ var spectreHeadingLevels = [
527
+ "h1",
528
+ "h2",
529
+ "h3",
530
+ "h4",
531
+ "h5",
532
+ "h6"
533
+ ];
534
+ function isHeadingLevel(value) {
535
+ return spectreHeadingLevels.includes(value);
536
+ }
537
+ var spectreDisplayLevels = [1, 2, 3, 4, 5, 6];
538
+ function isDisplayLevel(value) {
539
+ return spectreDisplayLevels.includes(value);
540
+ }
541
+ var spectreTableRowVariants = [
542
+ "neutral",
543
+ "info",
544
+ "success",
545
+ "warning",
546
+ "danger"
547
+ ];
548
+ function isTableRowVariant(value) {
549
+ return spectreTableRowVariants.includes(
550
+ value
551
+ );
552
+ }
431
553
  function normalizeInt(value, fallback, min = 0) {
432
554
  if (value == null || typeof value !== "number" || !Number.isInteger(value) || value < min) {
433
555
  return fallback;
@@ -716,6 +838,22 @@ function hasMeaningfulContent(nodes) {
716
838
  return false;
717
839
  });
718
840
  }
841
+ var idCounter = 0;
842
+ function createUniqueId(prefix) {
843
+ idCounter += 1;
844
+ return `${prefix}-${idCounter}`;
845
+ }
846
+ function replaceClasses(element, previous, next) {
847
+ const nextTokens = next.split(/\s+/).filter(Boolean);
848
+ previous.split(/\s+/).filter((token) => token && !nextTokens.includes(token)).forEach((token) => element.classList.remove(token));
849
+ element.classList.add(...nextTokens);
850
+ }
851
+ var spectreKindKey = /* @__PURE__ */ Symbol.for(
852
+ "phcdevworks.spectre-components.kind"
853
+ );
854
+ function isSpectreKind(node, kind) {
855
+ return node[spectreKindKey] === kind;
856
+ }
719
857
 
720
858
  // src/utils/projectable.ts
721
859
  var SpectreProjectableElement = class extends SpectreBaseElement {
@@ -751,7 +889,9 @@ var SpectreProjectableElement = class extends SpectreBaseElement {
751
889
  nextProjectedContent.push(node);
752
890
  }
753
891
  });
754
- const hasChanged = nextProjectedContent.length !== this.projectedContent.length || nextProjectedContent.some((node, index) => node !== this.projectedContent[index]);
892
+ const hasChanged = nextProjectedContent.length !== this.projectedContent.length || nextProjectedContent.some(
893
+ (node, index) => node !== this.projectedContent[index]
894
+ );
755
895
  if (hasChanged) {
756
896
  this.projectedContent = nextProjectedContent;
757
897
  }
@@ -781,9 +921,31 @@ var SpectreProjectableElement = class extends SpectreBaseElement {
781
921
  this.contentObserver = void 0;
782
922
  }
783
923
  };
924
+
925
+ // src/utils/states.ts
926
+ var hoverFocusStateProperties = {
927
+ focused: { type: Boolean, reflect: true },
928
+ hovered: { type: Boolean, reflect: true }
929
+ };
930
+ var interactionStateProperties = {
931
+ ...hoverFocusStateProperties,
932
+ active: { type: Boolean, reflect: true }
933
+ };
934
+ function hoverFocusStates(element) {
935
+ return {
936
+ focused: element.focused ?? false,
937
+ hovered: element.hovered ?? false
938
+ };
939
+ }
940
+ function interactionStates(element) {
941
+ return { ...hoverFocusStates(element), active: element.active ?? false };
942
+ }
784
943
  var SpectreButtonElement = class extends SpectreProjectableElement {
785
944
  constructor() {
786
945
  super(...arguments);
946
+ this.active = false;
947
+ this.focused = false;
948
+ this.hovered = false;
787
949
  this.compact = false;
788
950
  this.disabled = false;
789
951
  this.fullWidth = false;
@@ -867,6 +1029,7 @@ var SpectreButtonElement = class extends SpectreProjectableElement {
867
1029
  }
868
1030
  get buttonClasses() {
869
1031
  const recipeClasses = getButtonClasses({
1032
+ ...interactionStates(this),
870
1033
  compact: this.compact ?? false,
871
1034
  disabled: this.isDisabled,
872
1035
  fullWidth: this.fullWidth ?? false,
@@ -946,6 +1109,7 @@ var SpectreButtonElement = class extends SpectreProjectableElement {
946
1109
  }
947
1110
  };
948
1111
  SpectreButtonElement.properties = {
1112
+ ...interactionStateProperties,
949
1113
  compact: { type: Boolean, reflect: true },
950
1114
  disabled: { type: Boolean, reflect: true },
951
1115
  form: { type: String },
@@ -976,6 +1140,9 @@ function defineSpectreButton(tagName = "sp-button") {
976
1140
  var SpectreInputElement = class extends SpectreBaseElement {
977
1141
  constructor() {
978
1142
  super(...arguments);
1143
+ this.active = false;
1144
+ this.focused = false;
1145
+ this.hovered = false;
979
1146
  this.disabled = false;
980
1147
  this.fullWidth = false;
981
1148
  this.invalid = false;
@@ -987,6 +1154,10 @@ var SpectreInputElement = class extends SpectreBaseElement {
987
1154
  this.success = false;
988
1155
  this.type = "text";
989
1156
  this.value = "";
1157
+ this.errorMessage = void 0;
1158
+ this.helperText = void 0;
1159
+ this.label = void 0;
1160
+ this.generatedId = createUniqueId("sp-input");
990
1161
  }
991
1162
  get autocapitalize() {
992
1163
  return super.autocapitalize;
@@ -1061,12 +1232,30 @@ var SpectreInputElement = class extends SpectreBaseElement {
1061
1232
  }
1062
1233
  get inputClasses() {
1063
1234
  return getInputClasses({
1235
+ ...interactionStates(this),
1064
1236
  fullWidth: this.fullWidth ?? false,
1065
1237
  pill: this.pill ?? false,
1066
1238
  size: this.size,
1067
- state: this.isDisabled ? this.disabled ? "disabled" : "loading" : this.invalid ? "error" : this.success ? "success" : "default"
1239
+ state: this.isDisabled ? this.disabled ? "disabled" : "loading" : this.invalid || this.errorMessage ? "error" : this.success ? "success" : "default"
1068
1240
  });
1069
1241
  }
1242
+ get inputId() {
1243
+ return this.id || this.generatedId;
1244
+ }
1245
+ get hasFieldChrome() {
1246
+ return Boolean(this.label || this.helperText || this.errorMessage);
1247
+ }
1248
+ // An error message replaces the helper text while it is shown.
1249
+ get messageId() {
1250
+ if (this.errorMessage) {
1251
+ return `${this.inputId}-error`;
1252
+ }
1253
+ return this.helperText ? `${this.inputId}-helper` : void 0;
1254
+ }
1255
+ get describedBy() {
1256
+ const ids = [this.forwardedAriaDescribedBy, this.messageId].filter(Boolean);
1257
+ return ids.length > 0 ? ids.join(" ") : void 0;
1258
+ }
1070
1259
  get nativeInput() {
1071
1260
  return this.querySelector("[data-sp-input-native]");
1072
1261
  }
@@ -1084,11 +1273,48 @@ var SpectreInputElement = class extends SpectreBaseElement {
1084
1273
  blur() {
1085
1274
  this.nativeInput?.blur();
1086
1275
  }
1276
+ renderMessage() {
1277
+ if (this.errorMessage) {
1278
+ return html`<p
1279
+ aria-atomic="true"
1280
+ aria-live="polite"
1281
+ class="${getInputErrorMessageClasses()}"
1282
+ id="${this.inputId}-error"
1283
+ >
1284
+ ${this.errorMessage}
1285
+ </p>`;
1286
+ }
1287
+ if (this.helperText) {
1288
+ return html`<p
1289
+ class="${getInputHelperTextClasses({ disabled: this.isDisabled })}"
1290
+ id="${this.inputId}-helper"
1291
+ >
1292
+ ${this.helperText}
1293
+ </p>`;
1294
+ }
1295
+ return nothing;
1296
+ }
1297
+ // Without a label or message the native input renders alone, as before.
1087
1298
  render() {
1299
+ if (!this.hasFieldChrome) {
1300
+ return this.renderInput();
1301
+ }
1302
+ return html`<div class="${getInputWrapperClasses()}" data-sp-input-wrapper>
1303
+ ${this.label ? html`<label
1304
+ class="${getInputLabelClasses({ disabled: this.isDisabled })}"
1305
+ for="${this.inputId}"
1306
+ >${this.label}</label
1307
+ >` : nothing}
1308
+ ${this.renderInput()} ${this.renderMessage()}
1309
+ </div>`;
1310
+ }
1311
+ renderInput() {
1088
1312
  return html`<input
1089
1313
  aria-busy="${this.loading ? "true" : "false"}"
1090
- aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
1091
- aria-invalid="${ifDefined(this.invalid ? "true" : void 0)}"
1314
+ aria-describedby="${ifDefined(this.describedBy)}"
1315
+ aria-invalid="${ifDefined(
1316
+ this.invalid || this.errorMessage ? "true" : void 0
1317
+ )}"
1092
1318
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
1093
1319
  aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
1094
1320
  autocapitalize="${ifDefined(this.autocapitalize || void 0)}"
@@ -1101,7 +1327,7 @@ var SpectreInputElement = class extends SpectreBaseElement {
1101
1327
  form="${ifDefined(this.form || void 0)}"
1102
1328
  ?readonly="${this.readonly}"
1103
1329
  ?required="${this.required}"
1104
- id="${ifDefined(this.id || void 0)}"
1330
+ id="${ifDefined(this.hasFieldChrome ? this.inputId : this.id || void 0)}"
1105
1331
  inputmode="${ifDefined(this.inputmode || void 0)}"
1106
1332
  list="${ifDefined(this.list || void 0)}"
1107
1333
  max="${ifDefined(this.max || void 0)}"
@@ -1122,9 +1348,13 @@ var SpectreInputElement = class extends SpectreBaseElement {
1122
1348
  }
1123
1349
  };
1124
1350
  SpectreInputElement.properties = {
1351
+ ...interactionStateProperties,
1125
1352
  autocomplete: { type: String, reflect: true },
1126
1353
  disabled: { type: Boolean, reflect: true },
1127
1354
  enterkeyhint: { type: String, reflect: true },
1355
+ errorMessage: { attribute: "error-message", type: String },
1356
+ helperText: { attribute: "helper-text", type: String },
1357
+ label: { type: String },
1128
1358
  form: { type: String },
1129
1359
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
1130
1360
  inputmode: { type: String, reflect: true },
@@ -1159,6 +1389,7 @@ var DEFAULT_ROWS = 2;
1159
1389
  var SpectreTextareaElement = class extends SpectreBaseElement {
1160
1390
  constructor() {
1161
1391
  super(...arguments);
1392
+ this.focused = false;
1162
1393
  this.disabled = false;
1163
1394
  this.fullWidth = false;
1164
1395
  this.invalid = false;
@@ -1244,6 +1475,7 @@ var SpectreTextareaElement = class extends SpectreBaseElement {
1244
1475
  }
1245
1476
  get textareaClasses() {
1246
1477
  return getTextareaClasses({
1478
+ focused: this.focused ?? false,
1247
1479
  fullWidth: this.fullWidth ?? false,
1248
1480
  pill: this.pill ?? false,
1249
1481
  size: this.size,
@@ -1302,6 +1534,7 @@ var SpectreTextareaElement = class extends SpectreBaseElement {
1302
1534
  }
1303
1535
  };
1304
1536
  SpectreTextareaElement.properties = {
1537
+ focused: { type: Boolean, reflect: true },
1305
1538
  autocomplete: { type: String, reflect: true },
1306
1539
  disabled: { type: Boolean, reflect: true },
1307
1540
  enterkeyhint: { type: String, reflect: true },
@@ -1333,6 +1566,7 @@ function defineSpectreTextarea(tagName = "sp-textarea") {
1333
1566
  var SpectreSelectElement = class extends SpectreProjectableElement {
1334
1567
  constructor() {
1335
1568
  super(...arguments);
1569
+ this.focused = false;
1336
1570
  this.disabled = false;
1337
1571
  this.fullWidth = false;
1338
1572
  this.invalid = false;
@@ -1438,6 +1672,7 @@ var SpectreSelectElement = class extends SpectreProjectableElement {
1438
1672
  }
1439
1673
  get selectClasses() {
1440
1674
  return getSelectClasses({
1675
+ focused: this.focused ?? false,
1441
1676
  fullWidth: this.fullWidth ?? false,
1442
1677
  pill: this.pill ?? false,
1443
1678
  size: this.size,
@@ -1488,6 +1723,7 @@ var SpectreSelectElement = class extends SpectreProjectableElement {
1488
1723
  }
1489
1724
  };
1490
1725
  SpectreSelectElement.properties = {
1726
+ focused: { type: Boolean, reflect: true },
1491
1727
  autocomplete: { type: String, reflect: true },
1492
1728
  disabled: { type: Boolean, reflect: true },
1493
1729
  form: { type: String },
@@ -1998,6 +2234,11 @@ function defineSpectreFieldset(tagName = "sp-fieldset") {
1998
2234
  var SpectreBadgeElement = class extends SpectreProjectableElement {
1999
2235
  constructor() {
2000
2236
  super(...arguments);
2237
+ this.dot = false;
2238
+ this.interactive = false;
2239
+ this.active = false;
2240
+ this.focused = false;
2241
+ this.hovered = false;
2001
2242
  this.accentRail = void 0;
2002
2243
  this.accentRailColor = void 0;
2003
2244
  this.disabled = false;
@@ -2054,6 +2295,9 @@ var SpectreBadgeElement = class extends SpectreProjectableElement {
2054
2295
  }
2055
2296
  get badgeClasses() {
2056
2297
  const recipeClasses = getBadgeClasses({
2298
+ dot: this.dot ?? false,
2299
+ interactive: this.interactive ?? false,
2300
+ ...interactionStates(this),
2057
2301
  ...this.accentRail !== void 0 && {
2058
2302
  accentRail: this.accentRail
2059
2303
  },
@@ -2086,6 +2330,9 @@ var SpectreBadgeElement = class extends SpectreProjectableElement {
2086
2330
  }
2087
2331
  };
2088
2332
  SpectreBadgeElement.properties = {
2333
+ dot: { type: Boolean, reflect: true },
2334
+ interactive: { type: Boolean, reflect: true },
2335
+ ...interactionStateProperties,
2089
2336
  accentRail: { attribute: "accent-rail", type: String, reflect: true },
2090
2337
  accentRailColor: {
2091
2338
  attribute: "accent-rail-color",
@@ -2130,6 +2377,9 @@ var paddedConverter = {
2130
2377
  var SpectreCardElement = class extends SpectreProjectableElement {
2131
2378
  constructor() {
2132
2379
  super(...arguments);
2380
+ this.active = false;
2381
+ this.focused = false;
2382
+ this.hovered = false;
2133
2383
  this.accent = void 0;
2134
2384
  this.accentColor = void 0;
2135
2385
  this.disabled = false;
@@ -2190,6 +2440,7 @@ var SpectreCardElement = class extends SpectreProjectableElement {
2190
2440
  }
2191
2441
  get cardClasses() {
2192
2442
  const recipeClasses = getCardClasses({
2443
+ ...interactionStates(this),
2193
2444
  ...this.accent !== void 0 && {
2194
2445
  accent: this.accent
2195
2446
  },
@@ -2223,6 +2474,7 @@ var SpectreCardElement = class extends SpectreProjectableElement {
2223
2474
  }
2224
2475
  };
2225
2476
  SpectreCardElement.properties = {
2477
+ ...interactionStateProperties,
2226
2478
  accent: { type: String, reflect: true },
2227
2479
  accentColor: { attribute: "accent-color", type: String, reflect: true },
2228
2480
  disabled: { type: Boolean, reflect: true },
@@ -2244,6 +2496,9 @@ function defineSpectreCard(tagName = "sp-card") {
2244
2496
  var SpectreIconBoxElement = class extends SpectreProjectableElement {
2245
2497
  constructor() {
2246
2498
  super(...arguments);
2499
+ this.active = false;
2500
+ this.focused = false;
2501
+ this.hovered = false;
2247
2502
  this.disabled = false;
2248
2503
  this.fullWidth = false;
2249
2504
  this.interactive = false;
@@ -2299,6 +2554,7 @@ var SpectreIconBoxElement = class extends SpectreProjectableElement {
2299
2554
  }
2300
2555
  get iconBoxClasses() {
2301
2556
  return getIconBoxClasses({
2557
+ ...interactionStates(this),
2302
2558
  disabled: this.isDisabled,
2303
2559
  fullWidth: this.fullWidth ?? false,
2304
2560
  interactive: this.interactive ?? false,
@@ -2325,6 +2581,7 @@ var SpectreIconBoxElement = class extends SpectreProjectableElement {
2325
2581
  }
2326
2582
  };
2327
2583
  SpectreIconBoxElement.properties = {
2584
+ ...interactionStateProperties,
2328
2585
  disabled: { type: Boolean, reflect: true },
2329
2586
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
2330
2587
  interactive: { type: Boolean, reflect: true },
@@ -2344,6 +2601,12 @@ function defineSpectreIconBox(tagName = "sp-icon-box") {
2344
2601
  var SpectreRatingElement = class extends SpectreBaseElement {
2345
2602
  constructor() {
2346
2603
  super(...arguments);
2604
+ this.fullWidth = false;
2605
+ this.pill = false;
2606
+ this.interactive = false;
2607
+ this.active = false;
2608
+ this.focused = false;
2609
+ this.hovered = false;
2347
2610
  this.disabled = false;
2348
2611
  this.loading = false;
2349
2612
  this.max = 5;
@@ -2383,6 +2646,10 @@ var SpectreRatingElement = class extends SpectreBaseElement {
2383
2646
  }
2384
2647
  get ratingClasses() {
2385
2648
  return getRatingClasses({
2649
+ fullWidth: this.fullWidth ?? false,
2650
+ pill: this.pill ?? false,
2651
+ interactive: this.interactive ?? false,
2652
+ ...interactionStates(this),
2386
2653
  disabled: this.isDisabled,
2387
2654
  loading: this.loading ?? false,
2388
2655
  size: this.size
@@ -2432,6 +2699,10 @@ var SpectreRatingElement = class extends SpectreBaseElement {
2432
2699
  }
2433
2700
  };
2434
2701
  SpectreRatingElement.properties = {
2702
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
2703
+ pill: { type: Boolean, reflect: true },
2704
+ interactive: { type: Boolean, reflect: true },
2705
+ ...interactionStateProperties,
2435
2706
  disabled: { type: Boolean, reflect: true },
2436
2707
  label: { type: String, reflect: true },
2437
2708
  loading: { type: Boolean, reflect: true },
@@ -2447,9 +2718,105 @@ function defineSpectreRating(tagName = "sp-rating") {
2447
2718
  customElements.define(tagName, SpectreRatingElement);
2448
2719
  return SpectreRatingElement;
2449
2720
  }
2450
- var SpectreTestimonialElement = class extends SpectreProjectableElement {
2721
+
2722
+ // src/utils/projection.ts
2723
+ function slotOf(node) {
2724
+ if (node.nodeType !== Node.ELEMENT_NODE) {
2725
+ return void 0;
2726
+ }
2727
+ return node.getAttribute("slot") ?? void 0;
2728
+ }
2729
+ var ProjectionController = class {
2730
+ constructor(host, internalAttributes) {
2731
+ this.host = host;
2732
+ this.internalAttributes = internalAttributes;
2733
+ this.projected = [];
2734
+ host.addController(this);
2735
+ }
2736
+ hostConnected() {
2737
+ this.sync();
2738
+ this.observe();
2739
+ }
2740
+ hostDisconnected() {
2741
+ this.disconnect();
2742
+ }
2743
+ hostUpdate() {
2744
+ this.sync();
2745
+ this.disconnect();
2746
+ }
2747
+ hostUpdated() {
2748
+ this.observe();
2749
+ }
2750
+ // Every projected node in authored order, regardless of slot.
2751
+ all() {
2752
+ return [...this.projected];
2753
+ }
2754
+ // Omitting `slot` returns the nodes without a slot attribute.
2755
+ nodes(slot) {
2756
+ return this.projected.filter((node) => slotOf(node) === slot);
2757
+ }
2758
+ elements(slot) {
2759
+ return this.nodes(slot).filter(
2760
+ (node) => node.nodeType === Node.ELEMENT_NODE
2761
+ );
2762
+ }
2763
+ has(slot) {
2764
+ return hasMeaningfulContent(this.nodes(slot));
2765
+ }
2766
+ isInternalNode(node) {
2767
+ return node.nodeType === Node.ELEMENT_NODE && this.internalAttributes.some(
2768
+ (name) => node.hasAttribute(name)
2769
+ );
2770
+ }
2771
+ isProjectable(node) {
2772
+ if (node.nodeType === Node.COMMENT_NODE || this.isInternalNode(node)) {
2773
+ return false;
2774
+ }
2775
+ if (node.nodeType === Node.TEXT_NODE && this.hostHasRendered) {
2776
+ return Boolean(node.textContent?.trim());
2777
+ }
2778
+ return true;
2779
+ }
2780
+ get hostHasRendered() {
2781
+ return this.host.hasUpdated;
2782
+ }
2783
+ sync() {
2784
+ const next = [
2785
+ .../* @__PURE__ */ new Set([
2786
+ ...this.projected.filter((node) => this.host.contains(node)),
2787
+ ...Array.from(this.host.childNodes).filter(
2788
+ (node) => this.isProjectable(node)
2789
+ )
2790
+ ])
2791
+ ];
2792
+ const changed = next.length !== this.projected.length || next.some((node, index) => node !== this.projected[index]);
2793
+ if (changed) {
2794
+ this.projected = next;
2795
+ }
2796
+ return changed;
2797
+ }
2798
+ observe() {
2799
+ if (this.observer || !this.host.isConnected) {
2800
+ return;
2801
+ }
2802
+ this.observer = new MutationObserver(() => {
2803
+ if (this.sync()) {
2804
+ this.host.requestUpdate();
2805
+ }
2806
+ });
2807
+ this.observer.observe(this.host, { childList: true });
2808
+ }
2809
+ disconnect() {
2810
+ this.observer?.disconnect();
2811
+ this.observer = void 0;
2812
+ }
2813
+ };
2814
+ var SpectreTestimonialElement = class extends SpectreBaseElement {
2451
2815
  constructor() {
2452
2816
  super(...arguments);
2817
+ this.active = false;
2818
+ this.focused = false;
2819
+ this.hovered = false;
2453
2820
  this.accent = void 0;
2454
2821
  this.accentColor = void 0;
2455
2822
  this.disabled = false;
@@ -2457,6 +2824,9 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2457
2824
  this.interactive = false;
2458
2825
  this.loading = false;
2459
2826
  this.variant = "elevated";
2827
+ this.projection = new ProjectionController(this, [
2828
+ "data-sp-testimonial-native"
2829
+ ]);
2460
2830
  }
2461
2831
  get id() {
2462
2832
  return super.id;
@@ -2470,16 +2840,6 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2470
2840
  set title(value) {
2471
2841
  super.title = value;
2472
2842
  }
2473
- getContentContainer() {
2474
- return this.querySelector("[data-sp-testimonial-native]");
2475
- }
2476
- isInternalNode(node) {
2477
- if (node.nodeType !== Node.ELEMENT_NODE) {
2478
- return false;
2479
- }
2480
- const el = node;
2481
- return el.hasAttribute("data-sp-testimonial-native");
2482
- }
2483
2843
  willUpdate(changedProperties) {
2484
2844
  if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
2485
2845
  this.accent = void 0;
@@ -2505,6 +2865,7 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2505
2865
  }
2506
2866
  get testimonialClasses() {
2507
2867
  return getTestimonialClasses({
2868
+ ...interactionStates(this),
2508
2869
  ...this.accent !== void 0 && {
2509
2870
  accent: this.accent
2510
2871
  },
@@ -2518,6 +2879,24 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2518
2879
  variant: this.variant
2519
2880
  });
2520
2881
  }
2882
+ renderAuthor() {
2883
+ const hasName = this.projection.has("author-name");
2884
+ const hasTitle = this.projection.has("author-title");
2885
+ if (!this.projection.has("author-image") && !hasName && !hasTitle) {
2886
+ return nothing;
2887
+ }
2888
+ return html`<div class="${getTestimonialAuthorClasses()}">
2889
+ ${this.projection.nodes("author-image")}
2890
+ ${hasName || hasTitle ? html`<div class="${getTestimonialAuthorInfoClasses()}">
2891
+ ${hasName ? html`<div class="${getTestimonialAuthorNameClasses()}">
2892
+ ${this.projection.nodes("author-name")}
2893
+ </div>` : nothing}
2894
+ ${hasTitle ? html`<div class="${getTestimonialAuthorTitleClasses()}">
2895
+ ${this.projection.nodes("author-title")}
2896
+ </div>` : nothing}
2897
+ </div>` : nothing}
2898
+ </div>`;
2899
+ }
2521
2900
  render() {
2522
2901
  return html`<div
2523
2902
  aria-busy="${this.loading ? "true" : "false"}"
@@ -2530,11 +2909,15 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2530
2909
  role="${ifDefined(this.hasForwardedLabel ? "group" : void 0)}"
2531
2910
  title="${ifDefined(this.title || void 0)}"
2532
2911
  >
2533
- ${this.hasProjectedContent ? this.projectedContent : nothing}
2912
+ ${this.projection.has("quote") ? html`<div class="${getTestimonialQuoteClasses()}">
2913
+ ${this.projection.nodes("quote")}
2914
+ </div>` : nothing}
2915
+ ${this.projection.nodes()} ${this.renderAuthor()}
2534
2916
  </div>`;
2535
2917
  }
2536
2918
  };
2537
2919
  SpectreTestimonialElement.properties = {
2920
+ ...interactionStateProperties,
2538
2921
  accent: { type: String, reflect: true },
2539
2922
  accentColor: { attribute: "accent-color", type: String, reflect: true },
2540
2923
  disabled: { type: Boolean, reflect: true },
@@ -2551,15 +2934,46 @@ function defineSpectreTestimonial(tagName = "sp-testimonial") {
2551
2934
  customElements.define(tagName, SpectreTestimonialElement);
2552
2935
  return SpectreTestimonialElement;
2553
2936
  }
2554
- var SpectreAlertElement = class extends SpectreProjectableElement {
2937
+ var paths = {
2938
+ check: svg`<path d="M3 8.5l3 3 7-7" />`,
2939
+ chevronDown: svg`<path d="M4 6l4 4 4-4" />`,
2940
+ chevronLeft: svg`<path d="M10 4l-4 4 4 4" />`,
2941
+ chevronRight: svg`<path d="M6 4l4 4-4 4" />`,
2942
+ close: svg`<path d="M4 4l8 8M12 4l-8 8" />`
2943
+ };
2944
+ function renderIcon(name, sizeClass = "sp-icon-sm") {
2945
+ return html`<svg
2946
+ aria-hidden="true"
2947
+ class="${sizeClass}"
2948
+ fill="none"
2949
+ focusable="false"
2950
+ stroke="currentColor"
2951
+ stroke-linecap="round"
2952
+ stroke-linejoin="round"
2953
+ stroke-width="2"
2954
+ viewBox="0 0 16 16"
2955
+ >
2956
+ ${paths[name]}
2957
+ </svg>`;
2958
+ }
2959
+ var SpectreAlertElement = class extends SpectreBaseElement {
2555
2960
  constructor() {
2556
2961
  super(...arguments);
2962
+ this.interactive = false;
2963
+ this.active = false;
2964
+ this.focused = false;
2965
+ this.hovered = false;
2966
+ this.dismissLabel = "Dismiss";
2557
2967
  this.dismissed = false;
2968
+ this.dismissible = false;
2558
2969
  this.disabled = false;
2559
2970
  this.fullWidth = false;
2560
2971
  this.loading = false;
2561
2972
  this.size = "md";
2562
2973
  this.variant = "info";
2974
+ this.projection = new ProjectionController(this, [
2975
+ "data-sp-alert-native"
2976
+ ]);
2563
2977
  }
2564
2978
  get id() {
2565
2979
  return super.id;
@@ -2573,20 +2987,16 @@ var SpectreAlertElement = class extends SpectreProjectableElement {
2573
2987
  set title(value) {
2574
2988
  super.title = value;
2575
2989
  }
2576
- getContentContainer() {
2577
- return this.querySelector("[data-sp-alert-native]");
2578
- }
2579
- isInternalNode(node) {
2580
- if (node.nodeType !== Node.ELEMENT_NODE) {
2581
- return false;
2582
- }
2583
- const el = node;
2584
- return el.hasAttribute("data-sp-alert-native");
2585
- }
2586
2990
  willUpdate(changedProperties) {
2991
+ if (changedProperties.has("dismissLabel") && !this.dismissLabel) {
2992
+ this.dismissLabel = "Dismiss";
2993
+ }
2587
2994
  if (changedProperties.has("dismissed") && this.dismissed == null) {
2588
2995
  this.dismissed = false;
2589
2996
  }
2997
+ if (changedProperties.has("dismissible") && this.dismissible == null) {
2998
+ this.dismissible = false;
2999
+ }
2590
3000
  if (changedProperties.has("disabled") && this.disabled == null) {
2591
3001
  this.disabled = false;
2592
3002
  }
@@ -2603,10 +3013,20 @@ var SpectreAlertElement = class extends SpectreProjectableElement {
2603
3013
  this.size = "md";
2604
3014
  }
2605
3015
  }
3016
+ dismiss() {
3017
+ if (this.dismissed) {
3018
+ return;
3019
+ }
3020
+ this.dismissed = true;
3021
+ this.dispatchEvent(new CustomEvent("sp-dismiss", { bubbles: true }));
3022
+ }
2606
3023
  get alertClasses() {
2607
3024
  return getAlertClasses({
3025
+ interactive: this.interactive ?? false,
3026
+ ...interactionStates(this),
2608
3027
  disabled: this.isDisabled,
2609
3028
  dismissed: this.dismissed ?? false,
3029
+ dismissible: this.dismissible ?? false,
2610
3030
  fullWidth: this.fullWidth ?? false,
2611
3031
  loading: this.loading ?? false,
2612
3032
  size: this.size,
@@ -2625,12 +3045,28 @@ var SpectreAlertElement = class extends SpectreProjectableElement {
2625
3045
  role="alert"
2626
3046
  title="${ifDefined(this.title || void 0)}"
2627
3047
  >
2628
- ${this.hasProjectedContent ? this.projectedContent : nothing}
3048
+ ${this.projection.has("icon") ? html`<span class="${getAlertIconClasses()}"
3049
+ >${this.projection.nodes("icon")}</span
3050
+ >` : nothing}
3051
+ ${this.projection.has() ? this.projection.nodes() : nothing}
3052
+ ${this.dismissible ? html`<button
3053
+ aria-label="${this.dismissLabel ?? "Dismiss"}"
3054
+ class="${getAlertDismissClasses()}"
3055
+ data-sp-alert-dismiss
3056
+ type="button"
3057
+ @click="${() => this.dismiss()}"
3058
+ >
3059
+ ${renderIcon("close")}
3060
+ </button>` : nothing}
2629
3061
  </div>`;
2630
3062
  }
2631
3063
  };
2632
3064
  SpectreAlertElement.properties = {
3065
+ interactive: { type: Boolean, reflect: true },
3066
+ ...interactionStateProperties,
3067
+ dismissLabel: { attribute: "dismiss-label", type: String },
2633
3068
  dismissed: { type: Boolean, reflect: true },
3069
+ dismissible: { type: Boolean, reflect: true },
2634
3070
  disabled: { type: Boolean, reflect: true },
2635
3071
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
2636
3072
  loading: { type: Boolean, reflect: true },
@@ -2648,6 +3084,9 @@ function defineSpectreAlert(tagName = "sp-alert") {
2648
3084
  var SpectreAvatarElement = class extends SpectreProjectableElement {
2649
3085
  constructor() {
2650
3086
  super(...arguments);
3087
+ this.active = false;
3088
+ this.focused = false;
3089
+ this.hovered = false;
2651
3090
  this.disabled = false;
2652
3091
  this.fullWidth = false;
2653
3092
  this.interactive = false;
@@ -2703,6 +3142,7 @@ var SpectreAvatarElement = class extends SpectreProjectableElement {
2703
3142
  }
2704
3143
  get avatarClasses() {
2705
3144
  return getAvatarClasses({
3145
+ ...interactionStates(this),
2706
3146
  disabled: this.isDisabled,
2707
3147
  fullWidth: this.fullWidth ?? false,
2708
3148
  interactive: this.interactive ?? false,
@@ -2729,6 +3169,7 @@ var SpectreAvatarElement = class extends SpectreProjectableElement {
2729
3169
  }
2730
3170
  };
2731
3171
  SpectreAvatarElement.properties = {
3172
+ ...interactionStateProperties,
2732
3173
  disabled: { type: Boolean, reflect: true },
2733
3174
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
2734
3175
  interactive: { type: Boolean, reflect: true },
@@ -2820,6 +3261,9 @@ function defineSpectreSpinner(tagName = "sp-spinner") {
2820
3261
  var SpectreTagElement = class extends SpectreProjectableElement {
2821
3262
  constructor() {
2822
3263
  super(...arguments);
3264
+ this.active = false;
3265
+ this.focused = false;
3266
+ this.hovered = false;
2823
3267
  this.dismissible = false;
2824
3268
  this.disabled = false;
2825
3269
  this.fullWidth = false;
@@ -2879,6 +3323,7 @@ var SpectreTagElement = class extends SpectreProjectableElement {
2879
3323
  }
2880
3324
  get tagClasses() {
2881
3325
  return getTagClasses({
3326
+ ...interactionStates(this),
2882
3327
  disabled: this.isDisabled,
2883
3328
  dismissible: this.dismissible ?? false,
2884
3329
  fullWidth: this.fullWidth ?? false,
@@ -2906,6 +3351,7 @@ var SpectreTagElement = class extends SpectreProjectableElement {
2906
3351
  }
2907
3352
  };
2908
3353
  SpectreTagElement.properties = {
3354
+ ...interactionStateProperties,
2909
3355
  dismissible: { type: Boolean, reflect: true },
2910
3356
  disabled: { type: Boolean, reflect: true },
2911
3357
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
@@ -2923,9 +3369,12 @@ function defineSpectreTag(tagName = "sp-tag") {
2923
3369
  customElements.define(tagName, SpectreTagElement);
2924
3370
  return SpectreTagElement;
2925
3371
  }
2926
- var SpectrePricingCardElement = class extends SpectreProjectableElement {
3372
+ var SpectrePricingCardElement = class extends SpectreBaseElement {
2927
3373
  constructor() {
2928
3374
  super(...arguments);
3375
+ this.active = false;
3376
+ this.focused = false;
3377
+ this.hovered = false;
2929
3378
  this.accent = void 0;
2930
3379
  this.accentColor = void 0;
2931
3380
  this.disabled = false;
@@ -2933,6 +3382,9 @@ var SpectrePricingCardElement = class extends SpectreProjectableElement {
2933
3382
  this.fullHeight = false;
2934
3383
  this.interactive = false;
2935
3384
  this.loading = false;
3385
+ this.projection = new ProjectionController(this, [
3386
+ "data-sp-pricing-card-native"
3387
+ ]);
2936
3388
  }
2937
3389
  get id() {
2938
3390
  return super.id;
@@ -2946,16 +3398,6 @@ var SpectrePricingCardElement = class extends SpectreProjectableElement {
2946
3398
  set title(value) {
2947
3399
  super.title = value;
2948
3400
  }
2949
- getContentContainer() {
2950
- return this.querySelector("[data-sp-pricing-card-native]");
2951
- }
2952
- isInternalNode(node) {
2953
- if (node.nodeType !== Node.ELEMENT_NODE) {
2954
- return false;
2955
- }
2956
- const el = node;
2957
- return el.hasAttribute("data-sp-pricing-card-native");
2958
- }
2959
3401
  willUpdate(changedProperties) {
2960
3402
  if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
2961
3403
  this.accent = void 0;
@@ -2981,6 +3423,7 @@ var SpectrePricingCardElement = class extends SpectreProjectableElement {
2981
3423
  }
2982
3424
  get pricingCardClasses() {
2983
3425
  return getPricingCardClasses({
3426
+ ...interactionStates(this),
2984
3427
  ...this.accent !== void 0 && {
2985
3428
  accent: this.accent
2986
3429
  },
@@ -3006,11 +3449,24 @@ var SpectrePricingCardElement = class extends SpectreProjectableElement {
3006
3449
  role="${ifDefined(this.hasForwardedLabel ? "group" : void 0)}"
3007
3450
  title="${ifDefined(this.title || void 0)}"
3008
3451
  >
3009
- ${this.hasProjectedContent ? this.projectedContent : nothing}
3452
+ ${this.projection.nodes("header")}
3453
+ ${this.projection.has("badge") ? html`<div class="${getPricingCardBadgeClasses()}">
3454
+ ${this.projection.nodes("badge")}
3455
+ </div>` : nothing}
3456
+ ${this.projection.has("price") ? html`<div class="${getPricingCardPriceContainerClasses()}">
3457
+ <div class="${getPricingCardPriceClasses()}">
3458
+ ${this.projection.nodes("price")}
3459
+ </div>
3460
+ </div>` : nothing}
3461
+ ${this.projection.has("description") ? html`<div class="${getPricingCardDescriptionClasses()}">
3462
+ ${this.projection.nodes("description")}
3463
+ </div>` : nothing}
3464
+ ${this.projection.nodes()} ${this.projection.nodes("footer")}
3010
3465
  </div>`;
3011
3466
  }
3012
3467
  };
3013
3468
  SpectrePricingCardElement.properties = {
3469
+ ...interactionStateProperties,
3014
3470
  accent: { type: String, reflect: true },
3015
3471
  accentColor: { attribute: "accent-color", type: String, reflect: true },
3016
3472
  disabled: { type: Boolean, reflect: true },
@@ -3032,6 +3488,7 @@ var SpectreContainerElement = class extends SpectreProjectableElement {
3032
3488
  super(...arguments);
3033
3489
  this.innerClass = void 0;
3034
3490
  this.maxWidth = void 0;
3491
+ this.padding = void 0;
3035
3492
  }
3036
3493
  get id() {
3037
3494
  return super.id;
@@ -3046,9 +3503,9 @@ var SpectreContainerElement = class extends SpectreProjectableElement {
3046
3503
  super.title = value;
3047
3504
  }
3048
3505
  connectedCallback() {
3049
- var _a;
3506
+ var _a5;
3050
3507
  super.connectedCallback();
3051
- (_a = this.style).display || (_a.display = "block");
3508
+ (_a5 = this.style).display || (_a5.display = "block");
3052
3509
  }
3053
3510
  getContentContainer() {
3054
3511
  return this.querySelector("[data-sp-container-native]");
@@ -3064,11 +3521,19 @@ var SpectreContainerElement = class extends SpectreProjectableElement {
3064
3521
  if (changedProperties.has("maxWidth") && this.maxWidth != null && !isContainerMaxWidth(this.maxWidth)) {
3065
3522
  this.maxWidth = void 0;
3066
3523
  }
3524
+ if (changedProperties.has("padding") && this.padding != null && !isSpacingStep(this.padding)) {
3525
+ this.padding = void 0;
3526
+ }
3067
3527
  }
3068
3528
  get containerClasses() {
3069
- const recipeClasses = getContainerClasses(
3070
- this.maxWidth != null ? { maxWidth: this.maxWidth } : {}
3071
- );
3529
+ const recipeClasses = getContainerClasses({
3530
+ ...this.maxWidth != null && {
3531
+ maxWidth: this.maxWidth
3532
+ },
3533
+ ...this.padding != null && {
3534
+ padding: this.padding
3535
+ }
3536
+ });
3072
3537
  const utilityClasses = sanitizeUtilityClasses(this.innerClass);
3073
3538
  return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
3074
3539
  }
@@ -3088,7 +3553,8 @@ var SpectreContainerElement = class extends SpectreProjectableElement {
3088
3553
  };
3089
3554
  SpectreContainerElement.properties = {
3090
3555
  innerClass: { attribute: "inner-class", type: String },
3091
- maxWidth: { attribute: "max-width", type: String, reflect: true }
3556
+ maxWidth: { attribute: "max-width", type: String, reflect: true },
3557
+ padding: { type: String, reflect: true }
3092
3558
  };
3093
3559
  function defineSpectreContainer(tagName = "sp-container") {
3094
3560
  const existingElement = customElements.get(tagName);
@@ -3165,7 +3631,7 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3165
3631
  super.removeAttribute(qualifiedName);
3166
3632
  }
3167
3633
  connectedCallback() {
3168
- var _a;
3634
+ var _a5;
3169
3635
  const initialRole = HTMLElement.prototype.getAttribute.call(this, "role");
3170
3636
  if (initialRole !== null) {
3171
3637
  HTMLElement.prototype.removeAttribute.call(this, "role");
@@ -3174,7 +3640,7 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3174
3640
  if (initialRole !== null) {
3175
3641
  this.role = initialRole;
3176
3642
  }
3177
- (_a = this.style).display || (_a.display = "block");
3643
+ (_a5 = this.style).display || (_a5.display = "block");
3178
3644
  }
3179
3645
  getContentContainer() {
3180
3646
  return this.querySelector("[data-sp-grid-native]");
@@ -3209,6 +3675,9 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3209
3675
  if (changedProperties.has("offset") && this.offset !== void 0 && !isGridOffset(this.offset) && !isGridOffsetOptions(this.offset)) {
3210
3676
  this.offset = void 0;
3211
3677
  }
3678
+ if (changedProperties.has("colStart") && this.colStart !== void 0 && !isGridColStart(this.colStart) && !isGridColStartOptions(this.colStart)) {
3679
+ this.colStart = void 0;
3680
+ }
3212
3681
  if (changedProperties.has("rowSpan") && this.rowSpan !== void 0 && !isGridSpan(this.rowSpan) && !isGridSpanOptions(this.rowSpan)) {
3213
3682
  this.rowSpan = void 0;
3214
3683
  }
@@ -3243,6 +3712,9 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3243
3712
  ...this.offset !== void 0 && {
3244
3713
  offset: this.offset
3245
3714
  },
3715
+ ...this.colStart !== void 0 && {
3716
+ colStart: this.colStart
3717
+ },
3246
3718
  ...this.rowSpan !== void 0 && {
3247
3719
  rowSpan: this.rowSpan
3248
3720
  },
@@ -3282,6 +3754,7 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3282
3754
  };
3283
3755
  SpectreGridElement.properties = {
3284
3756
  align: { type: String, reflect: true },
3757
+ colStart: { attribute: "col-start", type: Object },
3285
3758
  columns: { type: Number, reflect: true },
3286
3759
  columnGap: { attribute: "column-gap", type: String, reflect: true },
3287
3760
  explicitTemplate: { attribute: "explicit-template", type: Object },
@@ -3307,7 +3780,9 @@ function defineSpectreGrid(tagName = "sp-grid") {
3307
3780
  var SpectreSectionElement = class extends SpectreProjectableElement {
3308
3781
  constructor() {
3309
3782
  super(...arguments);
3783
+ this.gap = void 0;
3310
3784
  this.innerClass = void 0;
3785
+ this.spacing = void 0;
3311
3786
  }
3312
3787
  get id() {
3313
3788
  return super.id;
@@ -3322,9 +3797,9 @@ var SpectreSectionElement = class extends SpectreProjectableElement {
3322
3797
  super.title = value;
3323
3798
  }
3324
3799
  connectedCallback() {
3325
- var _a;
3800
+ var _a5;
3326
3801
  super.connectedCallback();
3327
- (_a = this.style).display || (_a.display = "block");
3802
+ (_a5 = this.style).display || (_a5.display = "block");
3328
3803
  }
3329
3804
  getContentContainer() {
3330
3805
  return this.querySelector("[data-sp-section-native]");
@@ -3336,8 +3811,21 @@ var SpectreSectionElement = class extends SpectreProjectableElement {
3336
3811
  const el = node;
3337
3812
  return el.hasAttribute("data-sp-section-native");
3338
3813
  }
3814
+ willUpdate(changedProperties) {
3815
+ if (changedProperties.has("gap") && this.gap != null && !isSpacingStep(this.gap)) {
3816
+ this.gap = void 0;
3817
+ }
3818
+ if (changedProperties.has("spacing") && this.spacing != null && !isSpacingStep(this.spacing)) {
3819
+ this.spacing = void 0;
3820
+ }
3821
+ }
3339
3822
  get sectionClasses() {
3340
- const recipeClasses = getSectionClasses({});
3823
+ const recipeClasses = getSectionClasses({
3824
+ ...this.gap != null && { gap: this.gap },
3825
+ ...this.spacing != null && {
3826
+ spacing: this.spacing
3827
+ }
3828
+ });
3341
3829
  const utilityClasses = sanitizeUtilityClasses(this.innerClass);
3342
3830
  return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
3343
3831
  }
@@ -3356,7 +3844,9 @@ var SpectreSectionElement = class extends SpectreProjectableElement {
3356
3844
  }
3357
3845
  };
3358
3846
  SpectreSectionElement.properties = {
3359
- innerClass: { attribute: "inner-class", type: String }
3847
+ gap: { type: String, reflect: true },
3848
+ innerClass: { attribute: "inner-class", type: String },
3849
+ spacing: { type: String, reflect: true }
3360
3850
  };
3361
3851
  function defineSpectreSection(tagName = "sp-section") {
3362
3852
  const existingElement = customElements.get(tagName);
@@ -3388,9 +3878,9 @@ var SpectreStackElement = class extends SpectreProjectableElement {
3388
3878
  super.title = value;
3389
3879
  }
3390
3880
  connectedCallback() {
3391
- var _a;
3881
+ var _a5;
3392
3882
  super.connectedCallback();
3393
- (_a = this.style).display || (_a.display = "block");
3883
+ (_a5 = this.style).display || (_a5.display = "block");
3394
3884
  }
3395
3885
  getContentContainer() {
3396
3886
  return this.querySelector("[data-sp-stack-native]");
@@ -3455,6 +3945,22 @@ function defineSpectreStack(tagName = "sp-stack") {
3455
3945
  customElements.define(tagName, SpectreStackElement);
3456
3946
  return SpectreStackElement;
3457
3947
  }
3948
+
3949
+ // src/utils/parts.ts
3950
+ function applyPartClasses(elements, parts) {
3951
+ for (const element of elements) {
3952
+ const part = element.getAttribute("slot");
3953
+ const classes = part ? parts[part] : void 0;
3954
+ if (classes) {
3955
+ element.classList.add(...classes.split(/\s+/).filter(Boolean));
3956
+ }
3957
+ }
3958
+ }
3959
+ function childElements(nodes) {
3960
+ return nodes.filter(
3961
+ (node) => node.nodeType === Node.ELEMENT_NODE
3962
+ );
3963
+ }
3458
3964
  var SpectreDropdownElement = class extends SpectreBaseElement {
3459
3965
  constructor() {
3460
3966
  super(...arguments);
@@ -3595,6 +4101,14 @@ var SpectreDropdownElement = class extends SpectreBaseElement {
3595
4101
  this.viewport = false;
3596
4102
  }
3597
4103
  }
4104
+ updated(changedProperties) {
4105
+ super.updated(changedProperties);
4106
+ applyPartClasses(childElements(this.menuContent), {
4107
+ divider: getDropdownDividerClasses(),
4108
+ header: getDropdownHeaderClasses(),
4109
+ item: getDropdownItemClasses()
4110
+ });
4111
+ }
3598
4112
  get triggerElement() {
3599
4113
  return this.querySelector("[data-sp-dropdown-trigger]");
3600
4114
  }
@@ -3704,9 +4218,9 @@ var SpectreFooterElement = class extends SpectreProjectableElement {
3704
4218
  super.title = value;
3705
4219
  }
3706
4220
  connectedCallback() {
3707
- var _a;
4221
+ var _a5;
3708
4222
  super.connectedCallback();
3709
- (_a = this.style).display || (_a.display = "block");
4223
+ (_a5 = this.style).display || (_a5.display = "block");
3710
4224
  }
3711
4225
  getContentContainer() {
3712
4226
  return this.querySelector("[data-sp-footer-native]");
@@ -3746,6 +4260,22 @@ var SpectreFooterElement = class extends SpectreProjectableElement {
3746
4260
  const utilityClasses = sanitizeUtilityClasses(this.innerClass);
3747
4261
  return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
3748
4262
  }
4263
+ // Footer parts usually sit inside authored columns, so markers are matched
4264
+ // at any depth.
4265
+ updated(changedProperties) {
4266
+ super.updated(changedProperties);
4267
+ const native = this.querySelector("[data-sp-footer-native]");
4268
+ if (!native) {
4269
+ return;
4270
+ }
4271
+ applyPartClasses(native.querySelectorAll("[slot]"), {
4272
+ divider: getFooterDividerClasses(),
4273
+ heading: getFooterHeadingClasses(),
4274
+ links: getFooterLinksClasses(),
4275
+ muted: getFooterMutedClasses(),
4276
+ text: getFooterTextClasses()
4277
+ });
4278
+ }
3749
4279
  render() {
3750
4280
  return html`<footer
3751
4281
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
@@ -3776,6 +4306,8 @@ function defineSpectreFooter(tagName = "sp-footer") {
3776
4306
  var SpectreFooterChipElement = class extends SpectreProjectableElement {
3777
4307
  constructor() {
3778
4308
  super(...arguments);
4309
+ this.focused = false;
4310
+ this.hovered = false;
3779
4311
  this.disabled = false;
3780
4312
  }
3781
4313
  get id() {
@@ -3806,7 +4338,10 @@ var SpectreFooterChipElement = class extends SpectreProjectableElement {
3806
4338
  }
3807
4339
  }
3808
4340
  get footerChipClasses() {
3809
- return getFooterChipClasses({ disabled: this.disabled ?? false });
4341
+ return getFooterChipClasses({
4342
+ ...hoverFocusStates(this),
4343
+ disabled: this.disabled ?? false
4344
+ });
3810
4345
  }
3811
4346
  render() {
3812
4347
  return html`<span
@@ -3822,6 +4357,7 @@ var SpectreFooterChipElement = class extends SpectreProjectableElement {
3822
4357
  }
3823
4358
  };
3824
4359
  SpectreFooterChipElement.properties = {
4360
+ ...hoverFocusStateProperties,
3825
4361
  disabled: { type: Boolean, reflect: true }
3826
4362
  };
3827
4363
  function defineSpectreFooterChip(tagName = "sp-footer-chip") {
@@ -3835,6 +4371,8 @@ function defineSpectreFooterChip(tagName = "sp-footer-chip") {
3835
4371
  var SpectreFooterLinkElement = class extends SpectreProjectableElement {
3836
4372
  constructor() {
3837
4373
  super(...arguments);
4374
+ this.focused = false;
4375
+ this.hovered = false;
3838
4376
  this.active = false;
3839
4377
  this.disabled = false;
3840
4378
  this.href = void 0;
@@ -3871,6 +4409,7 @@ var SpectreFooterLinkElement = class extends SpectreProjectableElement {
3871
4409
  }
3872
4410
  get footerLinkClasses() {
3873
4411
  return getFooterLinkClasses({
4412
+ ...hoverFocusStates(this),
3874
4413
  active: this.active ?? false,
3875
4414
  disabled: this.disabled ?? false
3876
4415
  });
@@ -3892,6 +4431,7 @@ var SpectreFooterLinkElement = class extends SpectreProjectableElement {
3892
4431
  }
3893
4432
  };
3894
4433
  SpectreFooterLinkElement.properties = {
4434
+ ...hoverFocusStateProperties,
3895
4435
  active: { type: Boolean, reflect: true },
3896
4436
  disabled: { type: Boolean, reflect: true },
3897
4437
  href: { type: String }
@@ -3904,6 +4444,8 @@ function defineSpectreFooterLink(tagName = "sp-footer-link") {
3904
4444
  customElements.define(tagName, SpectreFooterLinkElement);
3905
4445
  return SpectreFooterLinkElement;
3906
4446
  }
4447
+
4448
+ // src/utils/focus.ts
3907
4449
  var FOCUSABLE_SELECTOR = [
3908
4450
  "a[href]",
3909
4451
  "button:not([disabled])",
@@ -3912,6 +4454,29 @@ var FOCUSABLE_SELECTOR = [
3912
4454
  "textarea:not([disabled])",
3913
4455
  '[tabindex]:not([tabindex="-1"])'
3914
4456
  ].join(",");
4457
+ function getFocusableElements(root) {
4458
+ if (!root) {
4459
+ return [];
4460
+ }
4461
+ return Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR));
4462
+ }
4463
+ function trapFocus(event, root) {
4464
+ const focusable = getFocusableElements(root);
4465
+ if (focusable.length === 0) {
4466
+ event.preventDefault();
4467
+ return;
4468
+ }
4469
+ const first = focusable[0];
4470
+ const last = focusable[focusable.length - 1];
4471
+ const active = document.activeElement;
4472
+ if (event.shiftKey && active === first) {
4473
+ event.preventDefault();
4474
+ last?.focus();
4475
+ } else if (!event.shiftKey && active === last) {
4476
+ event.preventDefault();
4477
+ first?.focus();
4478
+ }
4479
+ }
3915
4480
  var SpectreModalElement = class extends SpectreProjectableElement {
3916
4481
  constructor() {
3917
4482
  super(...arguments);
@@ -3929,7 +4494,7 @@ var SpectreModalElement = class extends SpectreProjectableElement {
3929
4494
  return;
3930
4495
  }
3931
4496
  if (event.key === "Tab") {
3932
- this.trapFocus(event);
4497
+ trapFocus(event, this.modalElement);
3933
4498
  }
3934
4499
  };
3935
4500
  }
@@ -3993,36 +4558,12 @@ var SpectreModalElement = class extends SpectreProjectableElement {
3993
4558
  get modalElement() {
3994
4559
  return this.querySelector("[data-sp-modal-native]");
3995
4560
  }
3996
- get focusableElements() {
3997
- const modal = this.modalElement;
3998
- if (!modal) {
3999
- return [];
4000
- }
4001
- return Array.from(modal.querySelectorAll(FOCUSABLE_SELECTOR));
4002
- }
4003
4561
  focusFirstElement() {
4004
- const [first] = this.focusableElements;
4562
+ const [first] = getFocusableElements(this.modalElement);
4005
4563
  (first ?? this.modalElement)?.focus();
4006
4564
  }
4007
- trapFocus(event) {
4008
- const focusable = this.focusableElements;
4009
- if (focusable.length === 0) {
4010
- event.preventDefault();
4011
- return;
4012
- }
4013
- const first = focusable[0];
4014
- const last = focusable[focusable.length - 1];
4015
- const active = document.activeElement;
4016
- if (event.shiftKey && active === first) {
4017
- event.preventDefault();
4018
- last?.focus();
4019
- } else if (!event.shiftKey && active === last) {
4020
- event.preventDefault();
4021
- first?.focus();
4022
- }
4023
- }
4024
- close() {
4025
- if (!this.open) {
4565
+ close() {
4566
+ if (!this.open) {
4026
4567
  return;
4027
4568
  }
4028
4569
  this.open = false;
@@ -4111,9 +4652,9 @@ var SpectreNavElement = class extends SpectreProjectableElement {
4111
4652
  super.title = value;
4112
4653
  }
4113
4654
  connectedCallback() {
4114
- var _a;
4655
+ var _a5;
4115
4656
  super.connectedCallback();
4116
- (_a = this.style).display || (_a.display = "block");
4657
+ (_a5 = this.style).display || (_a5.display = "block");
4117
4658
  }
4118
4659
  getContentContainer() {
4119
4660
  return this.querySelector("[data-sp-nav-native]");
@@ -4161,6 +4702,12 @@ var SpectreNavElement = class extends SpectreProjectableElement {
4161
4702
  const utilityClasses = sanitizeUtilityClasses(this.innerClass);
4162
4703
  return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
4163
4704
  }
4705
+ updated(changedProperties) {
4706
+ super.updated(changedProperties);
4707
+ applyPartClasses(childElements(this.projectedContent), {
4708
+ links: getNavLinksClasses()
4709
+ });
4710
+ }
4164
4711
  render() {
4165
4712
  return html`<nav
4166
4713
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
@@ -4193,12 +4740,20 @@ function defineSpectreNav(tagName = "sp-nav") {
4193
4740
  var SpectreNavItemElement = class extends SpectreBaseElement {
4194
4741
  constructor() {
4195
4742
  super(...arguments);
4743
+ this.focused = false;
4744
+ this.hovered = false;
4745
+ this.accent = void 0;
4746
+ this.accentColor = void 0;
4747
+ this.active = false;
4748
+ this.disabled = false;
4196
4749
  this.dropdown = false;
4750
+ this.fullWidth = false;
4197
4751
  this.href = void 0;
4198
4752
  this.label = void 0;
4199
4753
  this.mega = false;
4200
4754
  this.open = false;
4201
4755
  this.placement = "bottom-start";
4756
+ this.viewport = false;
4202
4757
  this.triggerContent = [];
4203
4758
  this.menuContent = [];
4204
4759
  this.handleDocumentClick = (event) => {
@@ -4296,6 +4851,24 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4296
4851
  this.contentObserver = void 0;
4297
4852
  }
4298
4853
  willUpdate(changedProperties) {
4854
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
4855
+ this.accent = void 0;
4856
+ }
4857
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
4858
+ this.accentColor = void 0;
4859
+ }
4860
+ if (changedProperties.has("active") && this.active == null) {
4861
+ this.active = false;
4862
+ }
4863
+ if (changedProperties.has("disabled") && this.disabled == null) {
4864
+ this.disabled = false;
4865
+ }
4866
+ if (changedProperties.has("fullWidth") && this.fullWidth == null) {
4867
+ this.fullWidth = false;
4868
+ }
4869
+ if (changedProperties.has("viewport") && this.viewport == null) {
4870
+ this.viewport = false;
4871
+ }
4299
4872
  if (changedProperties.has("dropdown") && this.dropdown == null) {
4300
4873
  this.dropdown = false;
4301
4874
  }
@@ -4309,6 +4882,14 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4309
4882
  this.placement = "bottom-start";
4310
4883
  }
4311
4884
  }
4885
+ updated(changedProperties) {
4886
+ super.updated(changedProperties);
4887
+ applyPartClasses(childElements(this.menuContent), {
4888
+ divider: getDropdownDividerClasses(),
4889
+ header: getDropdownHeaderClasses(),
4890
+ item: getDropdownItemClasses()
4891
+ });
4892
+ }
4312
4893
  get triggerElement() {
4313
4894
  return this.querySelector("[data-sp-nav-item-trigger]");
4314
4895
  }
@@ -4334,23 +4915,40 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4334
4915
  this.dispatchEvent(new CustomEvent("sp-close", { bubbles: true }));
4335
4916
  }
4336
4917
  get wrapperClasses() {
4337
- return getDropdownClasses({ mega: this.mega ?? false });
4918
+ return getDropdownClasses({
4919
+ fullWidth: this.fullWidth ?? false,
4920
+ mega: this.mega ?? false,
4921
+ viewport: this.viewport ?? false
4922
+ });
4338
4923
  }
4339
4924
  get menuClasses() {
4340
4925
  return getDropdownMenuClasses({
4926
+ ...this.accent !== void 0 && {
4927
+ accent: this.accent
4928
+ },
4929
+ ...this.accentColor !== void 0 && {
4930
+ accentColor: this.accentColor
4931
+ },
4341
4932
  mega: this.mega ?? false,
4933
+ viewport: this.viewport ?? false,
4342
4934
  open: this.open ?? false,
4343
4935
  placement: this.placement
4344
4936
  });
4345
4937
  }
4346
4938
  get navLinkClasses() {
4347
- return getNavLinkClasses();
4939
+ return getNavLinkClasses({
4940
+ ...hoverFocusStates(this),
4941
+ active: this.active ?? false,
4942
+ disabled: this.disabled ?? false
4943
+ });
4348
4944
  }
4349
4945
  renderLink() {
4350
4946
  return html`<a
4947
+ aria-current="${ifDefined(this.active ? "page" : void 0)}"
4948
+ aria-disabled="${ifDefined(this.disabled ? "true" : void 0)}"
4351
4949
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
4352
4950
  class="${this.navLinkClasses}"
4353
- href="${ifDefined(this.href)}"
4951
+ href="${ifDefined(this.disabled ? void 0 : this.href)}"
4354
4952
  id="${ifDefined(this.id || void 0)}"
4355
4953
  title="${ifDefined(this.title || void 0)}"
4356
4954
  >${this.hasMenuContent ? this.menuContent : this.label}</a
@@ -4368,6 +4966,7 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4368
4966
  aria-label="${ifDefined(this.forwardedAriaLabel ?? this.label)}"
4369
4967
  class="${this.navLinkClasses}"
4370
4968
  data-sp-nav-item-trigger
4969
+ ?disabled="${this.disabled ?? false}"
4371
4970
  type="button"
4372
4971
  @click="${() => this.toggle()}"
4373
4972
  >
@@ -4383,12 +4982,19 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4383
4982
  }
4384
4983
  };
4385
4984
  SpectreNavItemElement.properties = {
4985
+ ...hoverFocusStateProperties,
4986
+ accent: { type: String, reflect: true },
4987
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
4988
+ active: { type: Boolean, reflect: true },
4989
+ disabled: { type: Boolean, reflect: true },
4386
4990
  dropdown: { type: Boolean, reflect: true },
4991
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
4387
4992
  href: { type: String },
4388
4993
  label: { type: String },
4389
4994
  mega: { type: Boolean, reflect: true },
4390
4995
  open: { type: Boolean, reflect: true },
4391
- placement: { type: String, reflect: true }
4996
+ placement: { type: String, reflect: true },
4997
+ viewport: { type: Boolean, reflect: true }
4392
4998
  };
4393
4999
  function defineSpectreNavItem(tagName = "sp-nav-item") {
4394
5000
  const existingElement = customElements.get(tagName);
@@ -4491,6 +5097,20 @@ var SpectreSidebarElement = class extends SpectreProjectableElement {
4491
5097
  get sidebarClasses() {
4492
5098
  return getSidebarClasses({ bordered: this.bordered ?? false });
4493
5099
  }
5100
+ updated(changedProperties) {
5101
+ super.updated(changedProperties);
5102
+ const elements = childElements(this.projectedContent);
5103
+ applyPartClasses(elements, {
5104
+ group: getSidebarGroupClasses(),
5105
+ header: getSidebarHeaderClasses()
5106
+ });
5107
+ elements.filter((element) => element.getAttribute("slot") === "group").forEach((group) => {
5108
+ const summary = group.querySelector(":scope > summary");
5109
+ summary?.classList.add(
5110
+ ...getSidebarGroupSummaryClasses().split(/\s+/).filter(Boolean)
5111
+ );
5112
+ });
5113
+ }
4494
5114
  render() {
4495
5115
  return html`${this.hideToggle ? nothing : html`<button
4496
5116
  aria-expanded="${this.open ? "true" : "false"}"
@@ -4535,6 +5155,8 @@ function defineSpectreSidebar(tagName = "sp-sidebar") {
4535
5155
  var SpectreSidebarLinkElement = class extends SpectreProjectableElement {
4536
5156
  constructor() {
4537
5157
  super(...arguments);
5158
+ this.focused = false;
5159
+ this.hovered = false;
4538
5160
  this.active = false;
4539
5161
  this.disabled = false;
4540
5162
  this.href = void 0;
@@ -4575,6 +5197,7 @@ var SpectreSidebarLinkElement = class extends SpectreProjectableElement {
4575
5197
  }
4576
5198
  get sidebarLinkClasses() {
4577
5199
  return getSidebarLinkClasses({
5200
+ ...hoverFocusStates(this),
4578
5201
  active: this.active ?? false,
4579
5202
  disabled: this.disabled ?? false,
4580
5203
  level: this.level
@@ -4597,6 +5220,7 @@ var SpectreSidebarLinkElement = class extends SpectreProjectableElement {
4597
5220
  }
4598
5221
  };
4599
5222
  SpectreSidebarLinkElement.properties = {
5223
+ ...hoverFocusStateProperties,
4600
5224
  active: { type: Boolean, reflect: true },
4601
5225
  disabled: { type: Boolean, reflect: true },
4602
5226
  href: { type: String },
@@ -4972,12 +5596,12 @@ var SpectreTooltipElement = class extends SpectreBaseElement {
4972
5596
  return hasMeaningfulContent(this.tooltipContent);
4973
5597
  }
4974
5598
  connectedCallback() {
4975
- var _a, _b;
5599
+ var _a5, _b5;
4976
5600
  super.connectedCallback();
4977
5601
  this.syncProjectedContent();
4978
5602
  this.startContentObserver();
4979
- (_a = this.style).position || (_a.position = "relative");
4980
- (_b = this.style).display || (_b.display = "inline-block");
5603
+ (_a5 = this.style).position || (_a5.position = "relative");
5604
+ (_b5 = this.style).display || (_b5.display = "inline-block");
4981
5605
  }
4982
5606
  disconnectedCallback() {
4983
5607
  this.stopContentObserver();
@@ -5092,11 +5716,23 @@ var LEVEL_TAGS = {
5092
5716
  var SpectreTextElement = class extends SpectreProjectableElement {
5093
5717
  constructor() {
5094
5718
  super(...arguments);
5719
+ this.displayLevel = void 0;
5720
+ this.headingLevel = void 0;
5095
5721
  this.level = "p";
5722
+ this.preset = void 0;
5096
5723
  this.size = "md";
5097
5724
  this.variant = "default";
5098
5725
  }
5099
5726
  willUpdate(changedProperties) {
5727
+ if (changedProperties.has("displayLevel") && this.displayLevel != null && !isDisplayLevel(this.displayLevel)) {
5728
+ this.displayLevel = void 0;
5729
+ }
5730
+ if (changedProperties.has("headingLevel") && this.headingLevel != null && !isHeadingLevel(this.headingLevel)) {
5731
+ this.headingLevel = void 0;
5732
+ }
5733
+ if (changedProperties.has("preset") && this.preset != null && !isTextPreset(this.preset)) {
5734
+ this.preset = void 0;
5735
+ }
5100
5736
  if (changedProperties.has("family") && !isTextFamily(this.family)) {
5101
5737
  this.family = void 0;
5102
5738
  }
@@ -5135,19 +5771,34 @@ var SpectreTextElement = class extends SpectreProjectableElement {
5135
5771
  const el = node;
5136
5772
  return el.hasAttribute("data-sp-text-native");
5137
5773
  }
5138
- render() {
5139
- const tag = LEVEL_TAGS[this.level ?? "p"];
5140
- const textClasses = getTextClasses({
5774
+ // A typography preset replaces the text recipe: each sets its own size,
5775
+ // weight, and color.
5776
+ get textClasses() {
5777
+ const level = this.level ?? "p";
5778
+ switch (this.preset) {
5779
+ case "heading":
5780
+ return getHeadingClasses({
5781
+ level: this.headingLevel ?? (isHeadingLevel(level) ? level : "h2")
5782
+ });
5783
+ case "display":
5784
+ return getDisplayClasses({ level: this.displayLevel ?? 1 });
5785
+ case "lead":
5786
+ return getLeadClasses();
5787
+ }
5788
+ return getTextClasses({
5141
5789
  ...this.family !== void 0 && { family: this.family },
5142
5790
  size: this.size ?? "md",
5143
5791
  ...this.transform !== void 0 && { transform: this.transform },
5144
5792
  variant: this.variant ?? "default"
5145
5793
  });
5794
+ }
5795
+ render() {
5796
+ const tag = LEVEL_TAGS[this.level ?? "p"];
5146
5797
  return html$1`<${tag}
5147
5798
  aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
5148
5799
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
5149
5800
  aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
5150
- class="${textClasses}"
5801
+ class="${this.textClasses}"
5151
5802
  data-sp-text-native
5152
5803
  id="${ifDefined(this.id || void 0)}"
5153
5804
  title="${ifDefined(this.title || void 0)}"
@@ -5155,8 +5806,11 @@ var SpectreTextElement = class extends SpectreProjectableElement {
5155
5806
  }
5156
5807
  };
5157
5808
  SpectreTextElement.properties = {
5809
+ displayLevel: { attribute: "display-level", type: Number, reflect: true },
5158
5810
  family: { type: String, reflect: true },
5811
+ headingLevel: { attribute: "heading-level", type: String, reflect: true },
5159
5812
  level: { type: String, reflect: true },
5813
+ preset: { type: String, reflect: true },
5160
5814
  size: { type: String, reflect: true },
5161
5815
  transform: { type: String, reflect: true },
5162
5816
  variant: { type: String, reflect: true }
@@ -5169,6 +5823,2813 @@ function defineSpectreText(tagName = "sp-text") {
5169
5823
  customElements.define(tagName, SpectreTextElement);
5170
5824
  return SpectreTextElement;
5171
5825
  }
5826
+ var SpectreTabsElement = class extends SpectreBaseElement {
5827
+ constructor() {
5828
+ super(...arguments);
5829
+ this.fullWidth = false;
5830
+ this.selectedIndex = 0;
5831
+ this.variant = "line";
5832
+ this.vertical = false;
5833
+ this.baseId = createUniqueId("sp-tabs");
5834
+ this.projection = new ProjectionController(this, [
5835
+ "data-sp-tabs-native"
5836
+ ]);
5837
+ this.handlePanelChange = (event) => {
5838
+ event.stopPropagation();
5839
+ this.requestUpdate();
5840
+ };
5841
+ this.handleKeydown = async (event) => {
5842
+ const enabled = this.panels.map((panel, index) => panel.disabled ? -1 : index).filter((index) => index >= 0);
5843
+ if (enabled.length === 0) {
5844
+ return;
5845
+ }
5846
+ const position = enabled.indexOf(this.activeIndex);
5847
+ const previousKey = this.vertical ? "ArrowUp" : "ArrowLeft";
5848
+ const nextKey = this.vertical ? "ArrowDown" : "ArrowRight";
5849
+ let target;
5850
+ switch (event.key) {
5851
+ case previousKey:
5852
+ target = enabled[(position - 1 + enabled.length) % enabled.length];
5853
+ break;
5854
+ case nextKey:
5855
+ target = enabled[(position + 1) % enabled.length];
5856
+ break;
5857
+ case "Home":
5858
+ target = enabled[0];
5859
+ break;
5860
+ case "End":
5861
+ target = enabled[enabled.length - 1];
5862
+ break;
5863
+ default:
5864
+ return;
5865
+ }
5866
+ if (target === void 0) {
5867
+ return;
5868
+ }
5869
+ event.preventDefault();
5870
+ this.select(target);
5871
+ await this.updateComplete;
5872
+ this.tabButtons[target]?.focus();
5873
+ };
5874
+ }
5875
+ get id() {
5876
+ return super.id;
5877
+ }
5878
+ set id(value) {
5879
+ super.id = value;
5880
+ }
5881
+ get title() {
5882
+ return super.title;
5883
+ }
5884
+ set title(value) {
5885
+ super.title = value;
5886
+ }
5887
+ connectedCallback() {
5888
+ var _a5;
5889
+ super.connectedCallback();
5890
+ (_a5 = this.style).display || (_a5.display = "block");
5891
+ this.addEventListener("sp-tab-panel-change", this.handlePanelChange);
5892
+ }
5893
+ disconnectedCallback() {
5894
+ this.removeEventListener("sp-tab-panel-change", this.handlePanelChange);
5895
+ super.disconnectedCallback();
5896
+ }
5897
+ willUpdate(changedProperties) {
5898
+ if (changedProperties.has("fullWidth") && this.fullWidth == null) {
5899
+ this.fullWidth = false;
5900
+ }
5901
+ if (changedProperties.has("selectedIndex")) {
5902
+ this.selectedIndex = normalizeInt(this.selectedIndex, 0);
5903
+ }
5904
+ if (changedProperties.has("variant") && (this.variant == null || !isTabsVariant(this.variant))) {
5905
+ this.variant = "line";
5906
+ }
5907
+ if (changedProperties.has("vertical") && this.vertical == null) {
5908
+ this.vertical = false;
5909
+ }
5910
+ }
5911
+ updated(changedProperties) {
5912
+ super.updated(changedProperties);
5913
+ const activeIndex = this.activeIndex;
5914
+ this.panels.forEach((panel, index) => {
5915
+ panel.selected = index === activeIndex;
5916
+ panel.tabId = this.tabId(index);
5917
+ });
5918
+ }
5919
+ get panels() {
5920
+ return this.projection.elements().filter(
5921
+ (element) => isSpectreKind(element, "tab-panel")
5922
+ );
5923
+ }
5924
+ // Falls back to the first enabled panel when the requested one is missing
5925
+ // or disabled; -1 when every panel is disabled.
5926
+ get activeIndex() {
5927
+ const panels = this.panels;
5928
+ const index = this.selectedIndex ?? 0;
5929
+ if (panels[index] && !panels[index].disabled) {
5930
+ return index;
5931
+ }
5932
+ return panels.findIndex((panel) => !panel.disabled);
5933
+ }
5934
+ tabId(index) {
5935
+ return `${this.baseId}-tab-${index}`;
5936
+ }
5937
+ get tabButtons() {
5938
+ return Array.from(
5939
+ this.querySelectorAll("[data-sp-tabs-tab]")
5940
+ ).filter(
5941
+ (button) => button.closest("[data-sp-tabs-native]") === this.native
5942
+ );
5943
+ }
5944
+ get native() {
5945
+ return this.querySelector("[data-sp-tabs-native]");
5946
+ }
5947
+ select(index) {
5948
+ const panel = this.panels[index];
5949
+ if (!panel || panel.disabled || index === this.activeIndex) {
5950
+ return;
5951
+ }
5952
+ this.selectedIndex = index;
5953
+ this.dispatchEvent(
5954
+ new CustomEvent("sp-change", { bubbles: true, detail: { index } })
5955
+ );
5956
+ }
5957
+ get tabsClasses() {
5958
+ return getTabsClasses({
5959
+ fullWidth: this.fullWidth ?? false,
5960
+ variant: this.variant,
5961
+ vertical: this.vertical ?? false
5962
+ });
5963
+ }
5964
+ render() {
5965
+ const panels = this.panels;
5966
+ const activeIndex = this.activeIndex;
5967
+ return html`<div
5968
+ class="${this.tabsClasses}"
5969
+ data-sp-tabs-native
5970
+ id="${ifDefined(this.id || void 0)}"
5971
+ title="${ifDefined(this.title || void 0)}"
5972
+ >
5973
+ <div
5974
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
5975
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
5976
+ aria-orientation="${ifDefined(this.vertical ? "vertical" : void 0)}"
5977
+ class="${getTabsListClasses()}"
5978
+ role="tablist"
5979
+ @keydown="${this.handleKeydown}"
5980
+ >
5981
+ ${panels.map((panel, index) => {
5982
+ const active = index === activeIndex;
5983
+ return html`<button
5984
+ aria-controls="${panel.panelId}"
5985
+ aria-selected="${active ? "true" : "false"}"
5986
+ class="${getTabsItemClasses({
5987
+ active,
5988
+ disabled: panel.disabled ?? false
5989
+ })}"
5990
+ data-sp-tabs-tab
5991
+ ?disabled="${panel.disabled ?? false}"
5992
+ id="${this.tabId(index)}"
5993
+ role="tab"
5994
+ tabindex="${active ? "0" : "-1"}"
5995
+ type="button"
5996
+ @click="${() => this.select(index)}"
5997
+ >
5998
+ ${panel.label ?? ""}
5999
+ </button>`;
6000
+ })}
6001
+ </div>
6002
+ ${this.projection.nodes()}
6003
+ </div>`;
6004
+ }
6005
+ };
6006
+ SpectreTabsElement.properties = {
6007
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
6008
+ selectedIndex: { attribute: "selected-index", type: Number, reflect: true },
6009
+ variant: { type: String, reflect: true },
6010
+ vertical: { type: Boolean, reflect: true }
6011
+ };
6012
+ function defineSpectreTabs(tagName = "sp-tabs") {
6013
+ const existingElement = customElements.get(tagName);
6014
+ if (existingElement) {
6015
+ return existingElement;
6016
+ }
6017
+ customElements.define(tagName, SpectreTabsElement);
6018
+ return SpectreTabsElement;
6019
+ }
6020
+ var _a, _b;
6021
+ var SpectreTabPanelElement = class extends (_b = SpectreBaseElement, _a = spectreKindKey, _b) {
6022
+ constructor() {
6023
+ super(...arguments);
6024
+ this[_a] = "tab-panel";
6025
+ this.disabled = false;
6026
+ this.label = void 0;
6027
+ // Owned by the parent `sp-tabs`, which sets it from its `selectedIndex`.
6028
+ this.selected = false;
6029
+ this.tabId = void 0;
6030
+ this.generatedId = createUniqueId("sp-tab-panel");
6031
+ this.projection = new ProjectionController(this, [
6032
+ "data-sp-tab-panel-native"
6033
+ ]);
6034
+ }
6035
+ get id() {
6036
+ return super.id;
6037
+ }
6038
+ set id(value) {
6039
+ super.id = value;
6040
+ }
6041
+ get title() {
6042
+ return super.title;
6043
+ }
6044
+ set title(value) {
6045
+ super.title = value;
6046
+ }
6047
+ get panelId() {
6048
+ return this.id || this.generatedId;
6049
+ }
6050
+ connectedCallback() {
6051
+ var _a5;
6052
+ super.connectedCallback();
6053
+ (_a5 = this.style).display || (_a5.display = "contents");
6054
+ }
6055
+ willUpdate(changedProperties) {
6056
+ if (changedProperties.has("disabled") && this.disabled == null) {
6057
+ this.disabled = false;
6058
+ }
6059
+ }
6060
+ updated(changedProperties) {
6061
+ super.updated(changedProperties);
6062
+ if (changedProperties.has("label") || changedProperties.has("disabled")) {
6063
+ this.dispatchEvent(
6064
+ new CustomEvent("sp-tab-panel-change", { bubbles: true })
6065
+ );
6066
+ }
6067
+ }
6068
+ render() {
6069
+ return html`<div
6070
+ aria-labelledby="${ifDefined(this.tabId)}"
6071
+ class="${getTabsPanelClasses()}"
6072
+ data-sp-tab-panel-native
6073
+ ?hidden="${!this.selected}"
6074
+ id="${this.panelId}"
6075
+ role="tabpanel"
6076
+ tabindex="0"
6077
+ title="${ifDefined(this.title || void 0)}"
6078
+ >
6079
+ ${this.projection.nodes()}
6080
+ </div>`;
6081
+ }
6082
+ };
6083
+ SpectreTabPanelElement.properties = {
6084
+ disabled: { type: Boolean, reflect: true },
6085
+ label: { type: String },
6086
+ selected: { type: Boolean, reflect: true },
6087
+ tabId: { attribute: false }
6088
+ };
6089
+ function defineSpectreTabPanel(tagName = "sp-tab-panel") {
6090
+ const existingElement = customElements.get(tagName);
6091
+ if (existingElement) {
6092
+ return existingElement;
6093
+ }
6094
+ customElements.define(tagName, SpectreTabPanelElement);
6095
+ return SpectreTabPanelElement;
6096
+ }
6097
+ var SpectreAccordionElement = class extends SpectreBaseElement {
6098
+ constructor() {
6099
+ super(...arguments);
6100
+ this.flush = false;
6101
+ this.multiple = false;
6102
+ this.projection = new ProjectionController(this, [
6103
+ "data-sp-accordion-native"
6104
+ ]);
6105
+ this.handleItemOpen = (event) => {
6106
+ if (this.multiple) {
6107
+ return;
6108
+ }
6109
+ const items = this.items;
6110
+ const opened = items.find((item) => item === event.target);
6111
+ if (!opened) {
6112
+ return;
6113
+ }
6114
+ items.forEach((item) => {
6115
+ if (item !== opened) {
6116
+ item.open = false;
6117
+ }
6118
+ });
6119
+ };
6120
+ }
6121
+ get id() {
6122
+ return super.id;
6123
+ }
6124
+ set id(value) {
6125
+ super.id = value;
6126
+ }
6127
+ get title() {
6128
+ return super.title;
6129
+ }
6130
+ set title(value) {
6131
+ super.title = value;
6132
+ }
6133
+ connectedCallback() {
6134
+ var _a5;
6135
+ super.connectedCallback();
6136
+ (_a5 = this.style).display || (_a5.display = "block");
6137
+ this.addEventListener("sp-open", this.handleItemOpen);
6138
+ }
6139
+ disconnectedCallback() {
6140
+ this.removeEventListener("sp-open", this.handleItemOpen);
6141
+ super.disconnectedCallback();
6142
+ }
6143
+ willUpdate(changedProperties) {
6144
+ if (changedProperties.has("flush") && this.flush == null) {
6145
+ this.flush = false;
6146
+ }
6147
+ if (changedProperties.has("multiple") && this.multiple == null) {
6148
+ this.multiple = false;
6149
+ }
6150
+ }
6151
+ get items() {
6152
+ return this.projection.elements().filter(
6153
+ (element) => isSpectreKind(element, "accordion-item")
6154
+ );
6155
+ }
6156
+ render() {
6157
+ return html`<div
6158
+ class="${getAccordionClasses({ flush: this.flush ?? false })}"
6159
+ data-sp-accordion-native
6160
+ id="${ifDefined(this.id || void 0)}"
6161
+ title="${ifDefined(this.title || void 0)}"
6162
+ >
6163
+ ${this.projection.nodes()}
6164
+ </div>`;
6165
+ }
6166
+ };
6167
+ SpectreAccordionElement.properties = {
6168
+ flush: { type: Boolean, reflect: true },
6169
+ multiple: { type: Boolean, reflect: true }
6170
+ };
6171
+ function defineSpectreAccordion(tagName = "sp-accordion") {
6172
+ const existingElement = customElements.get(tagName);
6173
+ if (existingElement) {
6174
+ return existingElement;
6175
+ }
6176
+ customElements.define(tagName, SpectreAccordionElement);
6177
+ return SpectreAccordionElement;
6178
+ }
6179
+ var _a2, _b2;
6180
+ var SpectreAccordionItemElement = class extends (_b2 = SpectreBaseElement, _a2 = spectreKindKey, _b2) {
6181
+ constructor() {
6182
+ super(...arguments);
6183
+ this[_a2] = "accordion-item";
6184
+ this.focused = false;
6185
+ this.hovered = false;
6186
+ this.disabled = false;
6187
+ this.label = void 0;
6188
+ this.open = false;
6189
+ this.generatedId = createUniqueId("sp-accordion-item");
6190
+ this.appliedHostClasses = "";
6191
+ this.projection = new ProjectionController(this, [
6192
+ "data-sp-accordion-item-header",
6193
+ "data-sp-accordion-item-panel"
6194
+ ]);
6195
+ }
6196
+ get id() {
6197
+ return super.id;
6198
+ }
6199
+ set id(value) {
6200
+ super.id = value;
6201
+ }
6202
+ get title() {
6203
+ return super.title;
6204
+ }
6205
+ set title(value) {
6206
+ super.title = value;
6207
+ }
6208
+ connectedCallback() {
6209
+ var _a5;
6210
+ super.connectedCallback();
6211
+ (_a5 = this.style).display || (_a5.display = "block");
6212
+ }
6213
+ willUpdate(changedProperties) {
6214
+ if (changedProperties.has("disabled") && this.disabled == null) {
6215
+ this.disabled = false;
6216
+ }
6217
+ if (changedProperties.has("open") && this.open == null) {
6218
+ this.open = false;
6219
+ }
6220
+ const hostClasses = getAccordionItemClasses({
6221
+ disabled: this.disabled ?? false,
6222
+ expanded: this.open ?? false
6223
+ });
6224
+ replaceClasses(this, this.appliedHostClasses, hostClasses);
6225
+ this.appliedHostClasses = hostClasses;
6226
+ }
6227
+ get headerId() {
6228
+ return this.id || `${this.generatedId}-header`;
6229
+ }
6230
+ get panelId() {
6231
+ return `${this.generatedId}-panel`;
6232
+ }
6233
+ toggle() {
6234
+ if (this.disabled) {
6235
+ return;
6236
+ }
6237
+ this.open = !this.open;
6238
+ this.dispatchEvent(
6239
+ new CustomEvent(this.open ? "sp-open" : "sp-close", { bubbles: true })
6240
+ );
6241
+ }
6242
+ render() {
6243
+ const expanded = this.open ?? false;
6244
+ const disabled = this.disabled ?? false;
6245
+ return html`<button
6246
+ aria-controls="${this.panelId}"
6247
+ aria-expanded="${expanded ? "true" : "false"}"
6248
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
6249
+ class="${getAccordionHeaderClasses({
6250
+ ...hoverFocusStates(this),
6251
+ disabled,
6252
+ expanded
6253
+ })}"
6254
+ data-sp-accordion-item-header
6255
+ ?disabled="${disabled}"
6256
+ id="${this.headerId}"
6257
+ title="${ifDefined(this.title || void 0)}"
6258
+ type="button"
6259
+ @click="${() => this.toggle()}"
6260
+ >
6261
+ ${this.projection.has("header") ? this.projection.nodes("header") : this.label ?? ""}
6262
+ <span class="${getAccordionIconClasses({ expanded })}"
6263
+ >${renderIcon("chevronDown")}</span
6264
+ >
6265
+ </button>
6266
+ <div
6267
+ aria-labelledby="${this.headerId}"
6268
+ class="${getAccordionPanelClasses({ expanded })}"
6269
+ data-sp-accordion-item-panel
6270
+ ?hidden="${!expanded}"
6271
+ id="${this.panelId}"
6272
+ role="region"
6273
+ >
6274
+ ${this.projection.nodes()}
6275
+ </div>`;
6276
+ }
6277
+ };
6278
+ SpectreAccordionItemElement.properties = {
6279
+ ...hoverFocusStateProperties,
6280
+ disabled: { type: Boolean, reflect: true },
6281
+ label: { type: String },
6282
+ open: { type: Boolean, reflect: true }
6283
+ };
6284
+ function defineSpectreAccordionItem(tagName = "sp-accordion-item") {
6285
+ const existingElement = customElements.get(tagName);
6286
+ if (existingElement) {
6287
+ return existingElement;
6288
+ }
6289
+ customElements.define(tagName, SpectreAccordionItemElement);
6290
+ return SpectreAccordionItemElement;
6291
+ }
6292
+ var SpectreBreadcrumbElement = class extends SpectreBaseElement {
6293
+ constructor() {
6294
+ super(...arguments);
6295
+ this.separator = void 0;
6296
+ this.projection = new ProjectionController(this, [
6297
+ "data-sp-breadcrumb-native"
6298
+ ]);
6299
+ }
6300
+ get id() {
6301
+ return super.id;
6302
+ }
6303
+ set id(value) {
6304
+ super.id = value;
6305
+ }
6306
+ get title() {
6307
+ return super.title;
6308
+ }
6309
+ set title(value) {
6310
+ super.title = value;
6311
+ }
6312
+ connectedCallback() {
6313
+ var _a5;
6314
+ super.connectedCallback();
6315
+ (_a5 = this.style).display || (_a5.display = "block");
6316
+ }
6317
+ updated(changedProperties) {
6318
+ super.updated(changedProperties);
6319
+ const linkClasses = getBreadcrumbLinkClasses();
6320
+ this.crumbs.forEach((crumb) => {
6321
+ if (crumb instanceof HTMLAnchorElement) {
6322
+ crumb.classList.add(linkClasses);
6323
+ }
6324
+ });
6325
+ }
6326
+ get crumbs() {
6327
+ return this.projection.nodes().filter((node) => hasMeaningfulContent([node]));
6328
+ }
6329
+ get navLabel() {
6330
+ if (this.forwardedAriaLabel) {
6331
+ return this.forwardedAriaLabel;
6332
+ }
6333
+ return this.forwardedAriaLabelledBy ? void 0 : "Breadcrumb";
6334
+ }
6335
+ render() {
6336
+ const crumbs = this.crumbs;
6337
+ const separator = this.separator?.trim();
6338
+ return html`<nav
6339
+ aria-label="${ifDefined(this.navLabel)}"
6340
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
6341
+ data-sp-breadcrumb-native
6342
+ id="${ifDefined(this.id || void 0)}"
6343
+ title="${ifDefined(this.title || void 0)}"
6344
+ >
6345
+ <ol
6346
+ class="${getBreadcrumbClasses({ customSeparator: Boolean(separator) })}"
6347
+ >
6348
+ ${crumbs.map((crumb, index) => {
6349
+ const current = index === crumbs.length - 1;
6350
+ return html`<li
6351
+ aria-current="${ifDefined(current ? "page" : void 0)}"
6352
+ class="${getBreadcrumbItemClasses({ current })}"
6353
+ >
6354
+ ${separator && index > 0 ? html`<span
6355
+ aria-hidden="true"
6356
+ class="${getBreadcrumbSeparatorClasses()}"
6357
+ >${separator}</span
6358
+ >` : nothing}${crumb}
6359
+ </li>`;
6360
+ })}
6361
+ </ol>
6362
+ </nav>`;
6363
+ }
6364
+ };
6365
+ SpectreBreadcrumbElement.properties = {
6366
+ separator: { type: String }
6367
+ };
6368
+ function defineSpectreBreadcrumb(tagName = "sp-breadcrumb") {
6369
+ const existingElement = customElements.get(tagName);
6370
+ if (existingElement) {
6371
+ return existingElement;
6372
+ }
6373
+ customElements.define(tagName, SpectreBreadcrumbElement);
6374
+ return SpectreBreadcrumbElement;
6375
+ }
6376
+ function isInteractiveItem(item) {
6377
+ return Boolean(item.href) || (item.interactive ?? false);
6378
+ }
6379
+ var SpectreListGroupElement = class extends SpectreBaseElement {
6380
+ constructor() {
6381
+ super(...arguments);
6382
+ this.accent = void 0;
6383
+ this.accentColor = void 0;
6384
+ this.flush = false;
6385
+ this.horizontal = false;
6386
+ this.projection = new ProjectionController(this, [
6387
+ "data-sp-list-group-native"
6388
+ ]);
6389
+ this.handleItemChange = (event) => {
6390
+ event.stopPropagation();
6391
+ this.requestUpdate();
6392
+ };
6393
+ }
6394
+ get id() {
6395
+ return super.id;
6396
+ }
6397
+ set id(value) {
6398
+ super.id = value;
6399
+ }
6400
+ get title() {
6401
+ return super.title;
6402
+ }
6403
+ set title(value) {
6404
+ super.title = value;
6405
+ }
6406
+ connectedCallback() {
6407
+ var _a5;
6408
+ super.connectedCallback();
6409
+ (_a5 = this.style).display || (_a5.display = "block");
6410
+ this.addEventListener("sp-list-group-item-change", this.handleItemChange);
6411
+ }
6412
+ disconnectedCallback() {
6413
+ this.removeEventListener("sp-list-group-item-change", this.handleItemChange);
6414
+ super.disconnectedCallback();
6415
+ }
6416
+ willUpdate(changedProperties) {
6417
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
6418
+ this.accent = void 0;
6419
+ }
6420
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
6421
+ this.accentColor = void 0;
6422
+ }
6423
+ if (changedProperties.has("flush") && this.flush == null) {
6424
+ this.flush = false;
6425
+ }
6426
+ if (changedProperties.has("horizontal") && this.horizontal == null) {
6427
+ this.horizontal = false;
6428
+ }
6429
+ }
6430
+ updated(changedProperties) {
6431
+ super.updated(changedProperties);
6432
+ this.items.forEach((item) => {
6433
+ applyPartClasses(item.children, {
6434
+ heading: getListGroupItemHeadingClasses(),
6435
+ text: getListGroupItemTextClasses()
6436
+ });
6437
+ });
6438
+ }
6439
+ get items() {
6440
+ return this.projection.elements().filter(
6441
+ (element) => isSpectreKind(element, "list-group-item")
6442
+ );
6443
+ }
6444
+ get listClasses() {
6445
+ return getListGroupClasses({
6446
+ ...this.accent !== void 0 && {
6447
+ accent: this.accent
6448
+ },
6449
+ ...this.accentColor !== void 0 && {
6450
+ accentColor: this.accentColor
6451
+ },
6452
+ flush: this.flush ?? false,
6453
+ horizontal: this.horizontal ?? false
6454
+ });
6455
+ }
6456
+ itemClasses(item) {
6457
+ return getListGroupItemClasses({
6458
+ ...hoverFocusStates(item),
6459
+ active: item.active ?? false,
6460
+ disabled: item.disabled ?? false,
6461
+ interactive: isInteractiveItem(item),
6462
+ selected: item.selected ?? false
6463
+ });
6464
+ }
6465
+ select(item) {
6466
+ item.dispatchEvent(new CustomEvent("sp-select", { bubbles: true }));
6467
+ }
6468
+ renderRow(item) {
6469
+ const classes = this.itemClasses(item);
6470
+ const current = item.active ? "true" : void 0;
6471
+ const disabled = item.disabled ?? false;
6472
+ const id = item.id || void 0;
6473
+ const label = item.ariaLabel?.trim() || void 0;
6474
+ const title = item.title || void 0;
6475
+ if (item.href) {
6476
+ return html`<a
6477
+ aria-current="${ifDefined(current)}"
6478
+ aria-disabled="${ifDefined(disabled ? "true" : void 0)}"
6479
+ aria-label="${ifDefined(label)}"
6480
+ class="${classes}"
6481
+ data-sp-list-group-row
6482
+ href="${ifDefined(disabled ? void 0 : item.href)}"
6483
+ id="${ifDefined(id)}"
6484
+ target="${ifDefined(item.target)}"
6485
+ title="${ifDefined(title)}"
6486
+ @click="${() => this.select(item)}"
6487
+ >${item}</a
6488
+ >`;
6489
+ }
6490
+ if (item.interactive) {
6491
+ return html`<button
6492
+ aria-current="${ifDefined(current)}"
6493
+ aria-label="${ifDefined(label)}"
6494
+ class="${classes}"
6495
+ data-sp-list-group-row
6496
+ ?disabled="${disabled}"
6497
+ id="${ifDefined(id)}"
6498
+ title="${ifDefined(title)}"
6499
+ type="button"
6500
+ @click="${() => this.select(item)}"
6501
+ >
6502
+ ${item}
6503
+ </button>`;
6504
+ }
6505
+ return html`<div
6506
+ aria-current="${ifDefined(current)}"
6507
+ aria-label="${ifDefined(label)}"
6508
+ class="${classes}"
6509
+ data-sp-list-group-row
6510
+ id="${ifDefined(id)}"
6511
+ title="${ifDefined(title)}"
6512
+ >
6513
+ ${item}
6514
+ </div>`;
6515
+ }
6516
+ render() {
6517
+ const items = this.items;
6518
+ if (!items.some(isInteractiveItem)) {
6519
+ return html`<ul
6520
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
6521
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
6522
+ class="${this.listClasses}"
6523
+ data-sp-list-group-native
6524
+ id="${ifDefined(this.id || void 0)}"
6525
+ title="${ifDefined(this.title || void 0)}"
6526
+ >
6527
+ ${items.map(
6528
+ (item) => html`<li
6529
+ aria-current="${ifDefined(item.active ? "true" : void 0)}"
6530
+ aria-label="${ifDefined(item.ariaLabel?.trim() || void 0)}"
6531
+ class="${this.itemClasses(item)}"
6532
+ data-sp-list-group-row
6533
+ id="${ifDefined(item.id || void 0)}"
6534
+ title="${ifDefined(item.title || void 0)}"
6535
+ >
6536
+ ${item}
6537
+ </li>`
6538
+ )}
6539
+ </ul>`;
6540
+ }
6541
+ return html`<div
6542
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
6543
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
6544
+ class="${this.listClasses}"
6545
+ data-sp-list-group-native
6546
+ id="${ifDefined(this.id || void 0)}"
6547
+ title="${ifDefined(this.title || void 0)}"
6548
+ >
6549
+ ${items.map((item) => this.renderRow(item))}
6550
+ </div>`;
6551
+ }
6552
+ };
6553
+ SpectreListGroupElement.properties = {
6554
+ accent: { type: String, reflect: true },
6555
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
6556
+ flush: { type: Boolean, reflect: true },
6557
+ horizontal: { type: Boolean, reflect: true }
6558
+ };
6559
+ function defineSpectreListGroup(tagName = "sp-list-group") {
6560
+ const existingElement = customElements.get(tagName);
6561
+ if (existingElement) {
6562
+ return existingElement;
6563
+ }
6564
+ customElements.define(tagName, SpectreListGroupElement);
6565
+ return SpectreListGroupElement;
6566
+ }
6567
+ var _a3, _b3;
6568
+ var SpectreListGroupItemElement = class extends (_b3 = SpectreBaseElement, _a3 = spectreKindKey, _b3) {
6569
+ constructor() {
6570
+ super(...arguments);
6571
+ this[_a3] = "list-group-item";
6572
+ this.focused = false;
6573
+ this.hovered = false;
6574
+ this.active = false;
6575
+ this.disabled = false;
6576
+ this.href = void 0;
6577
+ this.interactive = false;
6578
+ this.selected = false;
6579
+ this.target = void 0;
6580
+ }
6581
+ get id() {
6582
+ return super.id;
6583
+ }
6584
+ set id(value) {
6585
+ super.id = value;
6586
+ }
6587
+ get title() {
6588
+ return super.title;
6589
+ }
6590
+ set title(value) {
6591
+ super.title = value;
6592
+ }
6593
+ connectedCallback() {
6594
+ var _a5;
6595
+ super.connectedCallback();
6596
+ (_a5 = this.style).display || (_a5.display = "contents");
6597
+ this.contentObserver = new MutationObserver(() => this.notifyParent());
6598
+ this.contentObserver.observe(this, { childList: true });
6599
+ }
6600
+ disconnectedCallback() {
6601
+ this.contentObserver?.disconnect();
6602
+ this.contentObserver = void 0;
6603
+ super.disconnectedCallback();
6604
+ }
6605
+ notifyParent() {
6606
+ this.dispatchEvent(
6607
+ new CustomEvent("sp-list-group-item-change", { bubbles: true })
6608
+ );
6609
+ }
6610
+ willUpdate(changedProperties) {
6611
+ if (changedProperties.has("active") && this.active == null) {
6612
+ this.active = false;
6613
+ }
6614
+ if (changedProperties.has("disabled") && this.disabled == null) {
6615
+ this.disabled = false;
6616
+ }
6617
+ if (changedProperties.has("interactive") && this.interactive == null) {
6618
+ this.interactive = false;
6619
+ }
6620
+ if (changedProperties.has("selected") && this.selected == null) {
6621
+ this.selected = false;
6622
+ }
6623
+ }
6624
+ updated(changedProperties) {
6625
+ super.updated(changedProperties);
6626
+ this.notifyParent();
6627
+ }
6628
+ render() {
6629
+ return nothing;
6630
+ }
6631
+ };
6632
+ SpectreListGroupItemElement.properties = {
6633
+ ...hoverFocusStateProperties,
6634
+ active: { type: Boolean, reflect: true },
6635
+ disabled: { type: Boolean, reflect: true },
6636
+ href: { type: String },
6637
+ interactive: { type: Boolean, reflect: true },
6638
+ selected: { type: Boolean, reflect: true },
6639
+ target: { type: String }
6640
+ };
6641
+ function defineSpectreListGroupItem(tagName = "sp-list-group-item") {
6642
+ const existingElement = customElements.get(tagName);
6643
+ if (existingElement) {
6644
+ return existingElement;
6645
+ }
6646
+ customElements.define(tagName, SpectreListGroupItemElement);
6647
+ return SpectreListGroupItemElement;
6648
+ }
6649
+ var SpectreOffcanvasElement = class extends SpectreBaseElement {
6650
+ constructor() {
6651
+ super(...arguments);
6652
+ this.closeLabel = "Close";
6653
+ this.label = void 0;
6654
+ this.open = false;
6655
+ this.placement = "start";
6656
+ this.previouslyFocusedElement = null;
6657
+ this.titleId = `${createUniqueId("sp-offcanvas")}-title`;
6658
+ this.projection = new ProjectionController(this, [
6659
+ "data-sp-offcanvas-backdrop",
6660
+ "data-sp-offcanvas-native"
6661
+ ]);
6662
+ this.handleDocumentKeydown = (event) => {
6663
+ if (!this.open) {
6664
+ return;
6665
+ }
6666
+ if (event.key === "Escape") {
6667
+ this.close();
6668
+ } else if (event.key === "Tab") {
6669
+ trapFocus(event, this.panelElement);
6670
+ }
6671
+ };
6672
+ }
6673
+ get id() {
6674
+ return super.id;
6675
+ }
6676
+ set id(value) {
6677
+ super.id = value;
6678
+ }
6679
+ get title() {
6680
+ return super.title;
6681
+ }
6682
+ set title(value) {
6683
+ super.title = value;
6684
+ }
6685
+ connectedCallback() {
6686
+ super.connectedCallback();
6687
+ document.addEventListener("keydown", this.handleDocumentKeydown);
6688
+ }
6689
+ disconnectedCallback() {
6690
+ document.removeEventListener("keydown", this.handleDocumentKeydown);
6691
+ super.disconnectedCallback();
6692
+ }
6693
+ willUpdate(changedProperties) {
6694
+ if (changedProperties.has("closeLabel") && !this.closeLabel) {
6695
+ this.closeLabel = "Close";
6696
+ }
6697
+ if (changedProperties.has("open") && this.open == null) {
6698
+ this.open = false;
6699
+ }
6700
+ if (changedProperties.has("placement") && (this.placement == null || !isOffcanvasPlacement(this.placement))) {
6701
+ this.placement = "start";
6702
+ }
6703
+ }
6704
+ updated(changedProperties) {
6705
+ super.updated(changedProperties);
6706
+ if (!changedProperties.has("open")) {
6707
+ return;
6708
+ }
6709
+ if (this.open) {
6710
+ this.previouslyFocusedElement = document.activeElement;
6711
+ this.focusPanel();
6712
+ } else if (this.previouslyFocusedElement) {
6713
+ this.previouslyFocusedElement.focus();
6714
+ this.previouslyFocusedElement = null;
6715
+ }
6716
+ }
6717
+ get panelElement() {
6718
+ return this.querySelector("[data-sp-offcanvas-native]");
6719
+ }
6720
+ // The panel's `visibility` transitions in from `hidden`, so it cannot take
6721
+ // focus until the slide-in finishes unless motion is disabled.
6722
+ focusPanel() {
6723
+ const panel = this.panelElement;
6724
+ const focusFirst = () => {
6725
+ const [first] = getFocusableElements(panel);
6726
+ (first ?? panel)?.focus();
6727
+ };
6728
+ focusFirst();
6729
+ if (panel && !panel.contains(document.activeElement)) {
6730
+ panel.addEventListener(
6731
+ "transitionend",
6732
+ () => {
6733
+ if (this.open) {
6734
+ focusFirst();
6735
+ }
6736
+ },
6737
+ { once: true }
6738
+ );
6739
+ }
6740
+ }
6741
+ close() {
6742
+ if (!this.open) {
6743
+ return;
6744
+ }
6745
+ this.open = false;
6746
+ this.dispatchEvent(new CustomEvent("sp-close", { bubbles: true }));
6747
+ }
6748
+ get hasHeading() {
6749
+ return this.projection.has("header") || Boolean(this.label);
6750
+ }
6751
+ get labelledBy() {
6752
+ if (this.forwardedAriaLabelledBy) {
6753
+ return this.forwardedAriaLabelledBy;
6754
+ }
6755
+ return this.hasHeading && !this.forwardedAriaLabel ? this.titleId : void 0;
6756
+ }
6757
+ render() {
6758
+ const open = this.open ?? false;
6759
+ return html`<div
6760
+ aria-hidden="true"
6761
+ class="${getOffcanvasBackdropClasses({ open })}"
6762
+ data-sp-offcanvas-backdrop
6763
+ @click="${() => this.close()}"
6764
+ ></div>
6765
+ <div
6766
+ aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
6767
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
6768
+ aria-labelledby="${ifDefined(this.labelledBy)}"
6769
+ aria-modal="true"
6770
+ class="${getOffcanvasClasses({
6771
+ open,
6772
+ placement: this.placement
6773
+ })}"
6774
+ data-sp-offcanvas-native
6775
+ id="${ifDefined(this.id || void 0)}"
6776
+ ?inert="${!open}"
6777
+ role="dialog"
6778
+ tabindex="-1"
6779
+ title="${ifDefined(this.title || void 0)}"
6780
+ >
6781
+ <div class="${getOffcanvasHeaderClasses()}">
6782
+ <div id="${ifDefined(this.hasHeading ? this.titleId : void 0)}">
6783
+ ${this.projection.has("header") ? this.projection.nodes("header") : this.label ?? nothing}
6784
+ </div>
6785
+ <button
6786
+ aria-label="${this.closeLabel ?? "Close"}"
6787
+ class="${getButtonClasses({ size: "sm", variant: "ghost" })}"
6788
+ data-sp-offcanvas-close
6789
+ type="button"
6790
+ @click="${() => this.close()}"
6791
+ >
6792
+ ${renderIcon("close")}
6793
+ </button>
6794
+ </div>
6795
+ <div class="${getOffcanvasBodyClasses()}">
6796
+ ${this.projection.nodes()}
6797
+ </div>
6798
+ ${this.projection.has("footer") ? html`<div class="${getOffcanvasFooterClasses()}">
6799
+ ${this.projection.nodes("footer")}
6800
+ </div>` : nothing}
6801
+ </div>`;
6802
+ }
6803
+ };
6804
+ SpectreOffcanvasElement.properties = {
6805
+ closeLabel: { attribute: "close-label", type: String },
6806
+ label: { type: String },
6807
+ open: { type: Boolean, reflect: true },
6808
+ placement: { type: String, reflect: true }
6809
+ };
6810
+ function defineSpectreOffcanvas(tagName = "sp-offcanvas") {
6811
+ const existingElement = customElements.get(tagName);
6812
+ if (existingElement) {
6813
+ return existingElement;
6814
+ }
6815
+ customElements.define(tagName, SpectreOffcanvasElement);
6816
+ return SpectreOffcanvasElement;
6817
+ }
6818
+ var SpectreCarouselElement = class extends SpectreBaseElement {
6819
+ constructor() {
6820
+ super(...arguments);
6821
+ this.fade = false;
6822
+ this.hideControls = false;
6823
+ this.hideIndicators = false;
6824
+ this.index = 0;
6825
+ this.loop = false;
6826
+ this.nextLabel = "Next slide";
6827
+ this.previousLabel = "Previous slide";
6828
+ this.indexFromScroll = false;
6829
+ this.projection = new ProjectionController(this, [
6830
+ "data-sp-carousel-native"
6831
+ ]);
6832
+ this.handleKeydown = (event) => {
6833
+ if (event.key === "ArrowLeft") {
6834
+ event.preventDefault();
6835
+ this.goTo(this.activeIndex - 1);
6836
+ } else if (event.key === "ArrowRight") {
6837
+ event.preventDefault();
6838
+ this.goTo(this.activeIndex + 1);
6839
+ }
6840
+ };
6841
+ // Native swipes and scroll-snap move the viewport directly; follow them so
6842
+ // the indicators and controls stay in sync.
6843
+ this.handleScroll = (event) => {
6844
+ const viewport = event.currentTarget;
6845
+ if (this.fade || viewport.clientWidth === 0) {
6846
+ return;
6847
+ }
6848
+ const target = Math.round(viewport.scrollLeft / viewport.clientWidth);
6849
+ if (target === this.activeIndex || target >= this.slides.length) {
6850
+ return;
6851
+ }
6852
+ this.indexFromScroll = true;
6853
+ this.index = target;
6854
+ this.dispatchEvent(
6855
+ new CustomEvent("sp-change", { bubbles: true, detail: { index: target } })
6856
+ );
6857
+ };
6858
+ }
6859
+ get id() {
6860
+ return super.id;
6861
+ }
6862
+ set id(value) {
6863
+ super.id = value;
6864
+ }
6865
+ get title() {
6866
+ return super.title;
6867
+ }
6868
+ set title(value) {
6869
+ super.title = value;
6870
+ }
6871
+ connectedCallback() {
6872
+ var _a5;
6873
+ super.connectedCallback();
6874
+ (_a5 = this.style).display || (_a5.display = "block");
6875
+ }
6876
+ willUpdate(changedProperties) {
6877
+ if (changedProperties.has("fade") && this.fade == null) {
6878
+ this.fade = false;
6879
+ }
6880
+ if (changedProperties.has("hideControls") && this.hideControls == null) {
6881
+ this.hideControls = false;
6882
+ }
6883
+ if (changedProperties.has("hideIndicators") && this.hideIndicators == null) {
6884
+ this.hideIndicators = false;
6885
+ }
6886
+ if (changedProperties.has("index")) {
6887
+ this.index = normalizeInt(this.index, 0);
6888
+ }
6889
+ if (changedProperties.has("loop") && this.loop == null) {
6890
+ this.loop = false;
6891
+ }
6892
+ if (changedProperties.has("nextLabel") && !this.nextLabel) {
6893
+ this.nextLabel = "Next slide";
6894
+ }
6895
+ if (changedProperties.has("previousLabel") && !this.previousLabel) {
6896
+ this.previousLabel = "Previous slide";
6897
+ }
6898
+ }
6899
+ updated(changedProperties) {
6900
+ super.updated(changedProperties);
6901
+ this.slides.forEach((slide2) => {
6902
+ applyPartClasses(slide2.querySelectorAll("[slot]"), {
6903
+ caption: getCarouselCaptionClasses()
6904
+ });
6905
+ });
6906
+ const scrolledByUser = this.indexFromScroll;
6907
+ this.indexFromScroll = false;
6908
+ if (this.fade || scrolledByUser || !changedProperties.has("index")) {
6909
+ return;
6910
+ }
6911
+ const slide = this.slideWrappers[this.activeIndex];
6912
+ if (slide && typeof this.viewport?.scrollTo === "function") {
6913
+ this.viewport.scrollTo({ left: slide.offsetLeft });
6914
+ }
6915
+ }
6916
+ get slides() {
6917
+ return this.projection.elements();
6918
+ }
6919
+ get activeIndex() {
6920
+ const last = this.slides.length - 1;
6921
+ return Math.max(0, Math.min(this.index ?? 0, last));
6922
+ }
6923
+ get viewport() {
6924
+ return this.querySelector("[data-sp-carousel-viewport]");
6925
+ }
6926
+ get slideWrappers() {
6927
+ const viewport = this.viewport;
6928
+ if (!viewport) {
6929
+ return [];
6930
+ }
6931
+ return Array.from(viewport.children).filter(
6932
+ (child) => child.hasAttribute("data-sp-carousel-slide")
6933
+ );
6934
+ }
6935
+ goTo(target) {
6936
+ const count = this.slides.length;
6937
+ if (count === 0) {
6938
+ return;
6939
+ }
6940
+ let next = target;
6941
+ if (this.loop) {
6942
+ next = (target % count + count) % count;
6943
+ } else if (target < 0 || target >= count) {
6944
+ return;
6945
+ }
6946
+ if (next === this.activeIndex) {
6947
+ return;
6948
+ }
6949
+ this.index = next;
6950
+ this.dispatchEvent(
6951
+ new CustomEvent("sp-change", { bubbles: true, detail: { index: next } })
6952
+ );
6953
+ }
6954
+ get regionLabel() {
6955
+ if (this.forwardedAriaLabel) {
6956
+ return this.forwardedAriaLabel;
6957
+ }
6958
+ return this.forwardedAriaLabelledBy ? void 0 : "Carousel";
6959
+ }
6960
+ render() {
6961
+ const slides = this.slides;
6962
+ const count = slides.length;
6963
+ const active = this.activeIndex;
6964
+ const loop = this.loop ?? false;
6965
+ return html`<div
6966
+ aria-label="${ifDefined(this.regionLabel)}"
6967
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
6968
+ aria-roledescription="carousel"
6969
+ class="${getCarouselClasses({ fade: this.fade ?? false })}"
6970
+ data-sp-carousel-native
6971
+ id="${ifDefined(this.id || void 0)}"
6972
+ role="region"
6973
+ title="${ifDefined(this.title || void 0)}"
6974
+ @keydown="${this.handleKeydown}"
6975
+ >
6976
+ <div
6977
+ aria-live="polite"
6978
+ class="${getCarouselViewportClasses()}"
6979
+ data-sp-carousel-viewport
6980
+ @scroll="${this.handleScroll}"
6981
+ >
6982
+ ${slides.map(
6983
+ (slide, index) => html`<div
6984
+ aria-label="${index + 1} of ${count}"
6985
+ aria-roledescription="slide"
6986
+ class="${getCarouselSlideClasses({ active: index === active })}"
6987
+ data-sp-carousel-slide
6988
+ role="group"
6989
+ >
6990
+ ${slide}
6991
+ </div>`
6992
+ )}
6993
+ </div>
6994
+ ${!this.hideControls && count > 1 ? html`<button
6995
+ aria-label="${this.previousLabel ?? "Previous slide"}"
6996
+ class="${getCarouselControlClasses({ direction: "prev" })}"
6997
+ data-sp-carousel-prev
6998
+ ?disabled="${!loop && active === 0}"
6999
+ type="button"
7000
+ @click="${() => this.goTo(active - 1)}"
7001
+ >
7002
+ ${renderIcon("chevronLeft", "sp-icon-md")}
7003
+ </button>
7004
+ <button
7005
+ aria-label="${this.nextLabel ?? "Next slide"}"
7006
+ class="${getCarouselControlClasses({ direction: "next" })}"
7007
+ data-sp-carousel-next
7008
+ ?disabled="${!loop && active === count - 1}"
7009
+ type="button"
7010
+ @click="${() => this.goTo(active + 1)}"
7011
+ >
7012
+ ${renderIcon("chevronRight", "sp-icon-md")}
7013
+ </button>` : nothing}
7014
+ ${!this.hideIndicators && count > 1 ? html`<div class="${getCarouselIndicatorsClasses()}">
7015
+ ${slides.map(
7016
+ (_, index) => html`<button
7017
+ aria-current="${ifDefined(
7018
+ index === active ? "true" : void 0
7019
+ )}"
7020
+ aria-label="Go to slide ${index + 1}"
7021
+ class="${getCarouselIndicatorClasses({
7022
+ active: index === active
7023
+ })}"
7024
+ data-sp-carousel-indicator
7025
+ type="button"
7026
+ @click="${() => this.goTo(index)}"
7027
+ ></button>`
7028
+ )}
7029
+ </div>` : nothing}
7030
+ </div>`;
7031
+ }
7032
+ };
7033
+ SpectreCarouselElement.properties = {
7034
+ fade: { type: Boolean, reflect: true },
7035
+ hideControls: { attribute: "hide-controls", type: Boolean, reflect: true },
7036
+ hideIndicators: {
7037
+ attribute: "hide-indicators",
7038
+ type: Boolean,
7039
+ reflect: true
7040
+ },
7041
+ index: { type: Number, reflect: true },
7042
+ loop: { type: Boolean, reflect: true },
7043
+ nextLabel: { attribute: "next-label", type: String },
7044
+ previousLabel: { attribute: "previous-label", type: String }
7045
+ };
7046
+ function defineSpectreCarousel(tagName = "sp-carousel") {
7047
+ const existingElement = customElements.get(tagName);
7048
+ if (existingElement) {
7049
+ return existingElement;
7050
+ }
7051
+ customElements.define(tagName, SpectreCarouselElement);
7052
+ return SpectreCarouselElement;
7053
+ }
7054
+ var SpectreTableElement = class extends SpectreBaseElement {
7055
+ constructor() {
7056
+ super(...arguments);
7057
+ this.bordered = false;
7058
+ this.hoverable = false;
7059
+ this.size = "md";
7060
+ this.striped = false;
7061
+ this.appliedTableClasses = /* @__PURE__ */ new WeakMap();
7062
+ this.projection = new ProjectionController(this, [
7063
+ "data-sp-table-native"
7064
+ ]);
7065
+ }
7066
+ get id() {
7067
+ return super.id;
7068
+ }
7069
+ set id(value) {
7070
+ super.id = value;
7071
+ }
7072
+ get title() {
7073
+ return super.title;
7074
+ }
7075
+ set title(value) {
7076
+ super.title = value;
7077
+ }
7078
+ connectedCallback() {
7079
+ var _a5;
7080
+ super.connectedCallback();
7081
+ (_a5 = this.style).display || (_a5.display = "block");
7082
+ }
7083
+ willUpdate(changedProperties) {
7084
+ if (changedProperties.has("bordered") && this.bordered == null) {
7085
+ this.bordered = false;
7086
+ }
7087
+ if (changedProperties.has("hoverable") && this.hoverable == null) {
7088
+ this.hoverable = false;
7089
+ }
7090
+ if (changedProperties.has("size") && (this.size == null || !isTableSize(this.size))) {
7091
+ this.size = "md";
7092
+ }
7093
+ if (changedProperties.has("striped") && this.striped == null) {
7094
+ this.striped = false;
7095
+ }
7096
+ }
7097
+ // The authored <table> is styled in place: the HTML parser drops table
7098
+ // parts that are not inside a <table>, so the component cannot render one.
7099
+ updated(changedProperties) {
7100
+ super.updated(changedProperties);
7101
+ const classes = getTableClasses({
7102
+ bordered: this.bordered ?? false,
7103
+ hoverable: this.hoverable ?? false,
7104
+ size: this.size,
7105
+ striped: this.striped ?? false
7106
+ });
7107
+ this.projection.elements().filter((element) => element instanceof HTMLTableElement).forEach((table) => {
7108
+ replaceClasses(
7109
+ table,
7110
+ this.appliedTableClasses.get(table) ?? "",
7111
+ classes
7112
+ );
7113
+ this.appliedTableClasses.set(table, classes);
7114
+ table.querySelectorAll("tr").forEach((row) => this.styleRow(row));
7115
+ });
7116
+ }
7117
+ // Contextual rows opt in with `data-variant`; `aria-selected` is styled by
7118
+ // the recipe CSS directly.
7119
+ styleRow(row) {
7120
+ const variant = row.dataset.variant;
7121
+ const classes = isTableRowVariant(variant) ? getTableRowClasses({ variant }) : "";
7122
+ replaceClasses(row, this.appliedTableClasses.get(row) ?? "", classes);
7123
+ this.appliedTableClasses.set(row, classes);
7124
+ }
7125
+ render() {
7126
+ const labelled = Boolean(
7127
+ this.forwardedAriaLabel || this.forwardedAriaLabelledBy
7128
+ );
7129
+ return html`<div
7130
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7131
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
7132
+ class="${getTableWrapperClasses()}"
7133
+ data-sp-table-native
7134
+ id="${ifDefined(this.id || void 0)}"
7135
+ role="${ifDefined(labelled ? "region" : void 0)}"
7136
+ tabindex="${ifDefined(labelled ? "0" : void 0)}"
7137
+ title="${ifDefined(this.title || void 0)}"
7138
+ >
7139
+ ${this.projection.nodes()}
7140
+ </div>`;
7141
+ }
7142
+ };
7143
+ SpectreTableElement.properties = {
7144
+ bordered: { type: Boolean, reflect: true },
7145
+ hoverable: { type: Boolean, reflect: true },
7146
+ size: { type: String, reflect: true },
7147
+ striped: { type: Boolean, reflect: true }
7148
+ };
7149
+ function defineSpectreTable(tagName = "sp-table") {
7150
+ const existingElement = customElements.get(tagName);
7151
+ if (existingElement) {
7152
+ return existingElement;
7153
+ }
7154
+ customElements.define(tagName, SpectreTableElement);
7155
+ return SpectreTableElement;
7156
+ }
7157
+ function pageRange(page, total, siblings) {
7158
+ const pages = (from, to) => Array.from({ length: to - from + 1 }, (_, index) => from + index);
7159
+ if (total <= siblings * 2 + 5) {
7160
+ return pages(1, total);
7161
+ }
7162
+ const left = Math.max(page - siblings, 1);
7163
+ const right = Math.min(page + siblings, total);
7164
+ const leftGap = left > 3;
7165
+ const rightGap = right < total - 2;
7166
+ const edgeCount = siblings * 2 + 3;
7167
+ if (!leftGap) {
7168
+ return [...pages(1, edgeCount), "ellipsis", total];
7169
+ }
7170
+ if (!rightGap) {
7171
+ return [1, "ellipsis", ...pages(total - edgeCount + 1, total)];
7172
+ }
7173
+ return [1, "ellipsis", ...pages(left, right), "ellipsis", total];
7174
+ }
7175
+ var SpectrePaginationElement = class extends SpectreBaseElement {
7176
+ constructor() {
7177
+ super(...arguments);
7178
+ this.hrefTemplate = void 0;
7179
+ this.nextLabel = "Next";
7180
+ this.page = 1;
7181
+ this.previousLabel = "Previous";
7182
+ this.siblings = 1;
7183
+ this.size = "md";
7184
+ this.total = 1;
7185
+ }
7186
+ get id() {
7187
+ return super.id;
7188
+ }
7189
+ set id(value) {
7190
+ super.id = value;
7191
+ }
7192
+ get title() {
7193
+ return super.title;
7194
+ }
7195
+ set title(value) {
7196
+ super.title = value;
7197
+ }
7198
+ connectedCallback() {
7199
+ var _a5;
7200
+ super.connectedCallback();
7201
+ (_a5 = this.style).display || (_a5.display = "block");
7202
+ }
7203
+ willUpdate(changedProperties) {
7204
+ if (changedProperties.has("total")) {
7205
+ this.total = normalizeInt(this.total, 1, 1);
7206
+ }
7207
+ if (changedProperties.has("page") || changedProperties.has("total")) {
7208
+ const page = normalizeInt(this.page, 1, 1) ?? 1;
7209
+ this.page = Math.min(page, this.total ?? 1);
7210
+ }
7211
+ if (changedProperties.has("siblings")) {
7212
+ this.siblings = normalizeInt(this.siblings, 1);
7213
+ }
7214
+ if (changedProperties.has("size") && (this.size == null || !isInputSize(this.size))) {
7215
+ this.size = "md";
7216
+ }
7217
+ if (changedProperties.has("previousLabel") && !this.previousLabel) {
7218
+ this.previousLabel = "Previous";
7219
+ }
7220
+ if (changedProperties.has("nextLabel") && !this.nextLabel) {
7221
+ this.nextLabel = "Next";
7222
+ }
7223
+ }
7224
+ get navLabel() {
7225
+ if (this.forwardedAriaLabel) {
7226
+ return this.forwardedAriaLabel;
7227
+ }
7228
+ return this.forwardedAriaLabelledBy ? void 0 : "Pagination";
7229
+ }
7230
+ goTo(target) {
7231
+ if (target === this.page || target < 1 || target > (this.total ?? 1)) {
7232
+ return;
7233
+ }
7234
+ this.page = target;
7235
+ this.dispatchEvent(
7236
+ new CustomEvent("sp-change", { bubbles: true, detail: { page: target } })
7237
+ );
7238
+ }
7239
+ renderItem(target, content, { active = false, disabled = false, label }) {
7240
+ const classes = getPaginationItemClasses({ active, disabled });
7241
+ const current = active ? "page" : void 0;
7242
+ if (this.hrefTemplate) {
7243
+ if (disabled) {
7244
+ return html`<a aria-disabled="true" class="${classes}">${content}</a>`;
7245
+ }
7246
+ return html`<a
7247
+ aria-current="${ifDefined(current)}"
7248
+ aria-label="${ifDefined(label)}"
7249
+ class="${classes}"
7250
+ href="${this.hrefTemplate.split("{page}").join(String(target))}"
7251
+ @click="${() => this.goTo(target)}"
7252
+ >${content}</a
7253
+ >`;
7254
+ }
7255
+ return html`<button
7256
+ aria-current="${ifDefined(current)}"
7257
+ aria-label="${ifDefined(label)}"
7258
+ class="${classes}"
7259
+ ?disabled="${disabled}"
7260
+ type="button"
7261
+ @click="${() => this.goTo(target)}"
7262
+ >
7263
+ ${content}
7264
+ </button>`;
7265
+ }
7266
+ render() {
7267
+ const page = this.page ?? 1;
7268
+ const total = this.total ?? 1;
7269
+ return html`<nav
7270
+ aria-label="${ifDefined(this.navLabel)}"
7271
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
7272
+ data-sp-pagination-native
7273
+ id="${ifDefined(this.id || void 0)}"
7274
+ title="${ifDefined(this.title || void 0)}"
7275
+ >
7276
+ <ul
7277
+ class="${getPaginationClasses({ size: this.size })}"
7278
+ >
7279
+ <li>
7280
+ ${this.renderItem(page - 1, this.previousLabel ?? "Previous", {
7281
+ disabled: page <= 1
7282
+ })}
7283
+ </li>
7284
+ ${pageRange(page, total, this.siblings ?? 1).map(
7285
+ (entry) => entry === "ellipsis" ? html`<li>
7286
+ <span
7287
+ aria-hidden="true"
7288
+ class="${getPaginationEllipsisClasses()}"
7289
+ >…</span
7290
+ >
7291
+ </li>` : html`<li>
7292
+ ${this.renderItem(entry, entry, {
7293
+ active: entry === page,
7294
+ label: `Page ${entry}`
7295
+ })}
7296
+ </li>`
7297
+ )}
7298
+ <li>
7299
+ ${this.renderItem(page + 1, this.nextLabel ?? "Next", {
7300
+ disabled: page >= total
7301
+ })}
7302
+ </li>
7303
+ </ul>
7304
+ </nav>`;
7305
+ }
7306
+ };
7307
+ SpectrePaginationElement.properties = {
7308
+ hrefTemplate: { attribute: "href-template", type: String },
7309
+ nextLabel: { attribute: "next-label", type: String },
7310
+ page: { type: Number, reflect: true },
7311
+ previousLabel: { attribute: "previous-label", type: String },
7312
+ siblings: { type: Number },
7313
+ size: { type: String, reflect: true },
7314
+ total: { type: Number, reflect: true }
7315
+ };
7316
+ function defineSpectrePagination(tagName = "sp-pagination") {
7317
+ const existingElement = customElements.get(tagName);
7318
+ if (existingElement) {
7319
+ return existingElement;
7320
+ }
7321
+ customElements.define(tagName, SpectrePaginationElement);
7322
+ return SpectrePaginationElement;
7323
+ }
7324
+ var SpectreStepperElement = class extends SpectreBaseElement {
7325
+ constructor() {
7326
+ super(...arguments);
7327
+ this.current = 0;
7328
+ this.orientation = "horizontal";
7329
+ this.projection = new ProjectionController(this, [
7330
+ "data-sp-stepper-native"
7331
+ ]);
7332
+ }
7333
+ get id() {
7334
+ return super.id;
7335
+ }
7336
+ set id(value) {
7337
+ super.id = value;
7338
+ }
7339
+ get title() {
7340
+ return super.title;
7341
+ }
7342
+ set title(value) {
7343
+ super.title = value;
7344
+ }
7345
+ connectedCallback() {
7346
+ var _a5;
7347
+ super.connectedCallback();
7348
+ (_a5 = this.style).display || (_a5.display = "block");
7349
+ }
7350
+ willUpdate(changedProperties) {
7351
+ if (changedProperties.has("current")) {
7352
+ this.current = normalizeInt(this.current, 0);
7353
+ }
7354
+ if (changedProperties.has("orientation") && (this.orientation == null || !isStepperOrientation(this.orientation))) {
7355
+ this.orientation = "horizontal";
7356
+ }
7357
+ }
7358
+ stateFor(index) {
7359
+ const current = this.current ?? 0;
7360
+ if (index < current) {
7361
+ return "done";
7362
+ }
7363
+ return index === current ? "active" : "pending";
7364
+ }
7365
+ render() {
7366
+ return html`<ol
7367
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7368
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
7369
+ class="${getStepperClasses({
7370
+ orientation: this.orientation
7371
+ })}"
7372
+ data-sp-stepper-native
7373
+ id="${ifDefined(this.id || void 0)}"
7374
+ title="${ifDefined(this.title || void 0)}"
7375
+ >
7376
+ ${this.projection.elements().map((step, index) => {
7377
+ const state = this.stateFor(index);
7378
+ return html`<li
7379
+ aria-current="${ifDefined(state === "active" ? "step" : void 0)}"
7380
+ class="${getStepperStepClasses({ state })}"
7381
+ data-state="${state}"
7382
+ >
7383
+ <span aria-hidden="true" class="${getStepperIndicatorClasses()}"
7384
+ >${state === "done" ? renderIcon("check") : index + 1}</span
7385
+ >
7386
+ <span class="${getStepperLabelClasses()}">${step}</span>
7387
+ </li>`;
7388
+ })}
7389
+ </ol>`;
7390
+ }
7391
+ };
7392
+ SpectreStepperElement.properties = {
7393
+ current: { type: Number, reflect: true },
7394
+ orientation: { type: String, reflect: true }
7395
+ };
7396
+ function defineSpectreStepper(tagName = "sp-stepper") {
7397
+ const existingElement = customElements.get(tagName);
7398
+ if (existingElement) {
7399
+ return existingElement;
7400
+ }
7401
+ customElements.define(tagName, SpectreStepperElement);
7402
+ return SpectreStepperElement;
7403
+ }
7404
+ var SpectreCardBleedElement = class extends SpectreBaseElement {
7405
+ constructor() {
7406
+ super(...arguments);
7407
+ this.edges = void 0;
7408
+ this.padded = void 0;
7409
+ this.projection = new ProjectionController(this, [
7410
+ "data-sp-card-bleed-native"
7411
+ ]);
7412
+ }
7413
+ get id() {
7414
+ return super.id;
7415
+ }
7416
+ set id(value) {
7417
+ super.id = value;
7418
+ }
7419
+ get title() {
7420
+ return super.title;
7421
+ }
7422
+ set title(value) {
7423
+ super.title = value;
7424
+ }
7425
+ connectedCallback() {
7426
+ var _a5;
7427
+ super.connectedCallback();
7428
+ (_a5 = this.style).display || (_a5.display = "block");
7429
+ }
7430
+ willUpdate(changedProperties) {
7431
+ if (changedProperties.has("padded") && this.padded != null) {
7432
+ const padded = this.padded;
7433
+ this.padded = padded === "" ? "md" : isSpacingStep(padded) ? padded : void 0;
7434
+ }
7435
+ }
7436
+ // `edges` is a space-separated list of edges, or `all`.
7437
+ get bleedEdges() {
7438
+ const tokens = (this.edges ?? "").split(/\s+/).filter(Boolean);
7439
+ if (tokens.includes("all")) {
7440
+ return "all";
7441
+ }
7442
+ return tokens.filter(
7443
+ (token) => isAccentEdge(token)
7444
+ );
7445
+ }
7446
+ render() {
7447
+ return html`<div
7448
+ class="${getCardBleedClasses({
7449
+ edges: this.bleedEdges,
7450
+ ...this.padded != null && {
7451
+ padded: this.padded
7452
+ }
7453
+ })}"
7454
+ data-sp-card-bleed-native
7455
+ id="${ifDefined(this.id || void 0)}"
7456
+ title="${ifDefined(this.title || void 0)}"
7457
+ >
7458
+ ${this.projection.nodes()}
7459
+ </div>`;
7460
+ }
7461
+ };
7462
+ SpectreCardBleedElement.properties = {
7463
+ edges: { type: String, reflect: true },
7464
+ padded: { type: String, reflect: true }
7465
+ };
7466
+ function defineSpectreCardBleed(tagName = "sp-card-bleed") {
7467
+ const existingElement = customElements.get(tagName);
7468
+ if (existingElement) {
7469
+ return existingElement;
7470
+ }
7471
+ customElements.define(tagName, SpectreCardBleedElement);
7472
+ return SpectreCardBleedElement;
7473
+ }
7474
+ var SpectreProseElement = class extends SpectreBaseElement {
7475
+ constructor() {
7476
+ super(...arguments);
7477
+ this.projection = new ProjectionController(this, [
7478
+ "data-sp-prose-native"
7479
+ ]);
7480
+ }
7481
+ get id() {
7482
+ return super.id;
7483
+ }
7484
+ set id(value) {
7485
+ super.id = value;
7486
+ }
7487
+ get title() {
7488
+ return super.title;
7489
+ }
7490
+ set title(value) {
7491
+ super.title = value;
7492
+ }
7493
+ connectedCallback() {
7494
+ var _a5;
7495
+ super.connectedCallback();
7496
+ (_a5 = this.style).display || (_a5.display = "block");
7497
+ }
7498
+ render() {
7499
+ return html`<div
7500
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7501
+ class="${getProseClasses()}"
7502
+ data-sp-prose-native
7503
+ id="${ifDefined(this.id || void 0)}"
7504
+ role="${ifDefined(this.forwardedAriaLabel ? "region" : void 0)}"
7505
+ title="${ifDefined(this.title || void 0)}"
7506
+ >
7507
+ ${this.projection.nodes()}
7508
+ </div>`;
7509
+ }
7510
+ };
7511
+ function defineSpectreProse(tagName = "sp-prose") {
7512
+ const existingElement = customElements.get(tagName);
7513
+ if (existingElement) {
7514
+ return existingElement;
7515
+ }
7516
+ customElements.define(tagName, SpectreProseElement);
7517
+ return SpectreProseElement;
7518
+ }
7519
+ var SpectreProgressElement = class extends SpectreBaseElement {
7520
+ constructor() {
7521
+ super(...arguments);
7522
+ this.indeterminate = false;
7523
+ this.label = void 0;
7524
+ this.max = 100;
7525
+ this.size = "md";
7526
+ this.value = 0;
7527
+ this.valueText = void 0;
7528
+ this.variant = "brand";
7529
+ this.labelId = `${createUniqueId("sp-progress")}-label`;
7530
+ }
7531
+ get id() {
7532
+ return super.id;
7533
+ }
7534
+ set id(value) {
7535
+ super.id = value;
7536
+ }
7537
+ get title() {
7538
+ return super.title;
7539
+ }
7540
+ set title(value) {
7541
+ super.title = value;
7542
+ }
7543
+ connectedCallback() {
7544
+ var _a5;
7545
+ super.connectedCallback();
7546
+ (_a5 = this.style).display || (_a5.display = "block");
7547
+ }
7548
+ willUpdate(changedProperties) {
7549
+ if (changedProperties.has("indeterminate") && this.indeterminate == null) {
7550
+ this.indeterminate = false;
7551
+ }
7552
+ if (changedProperties.has("max") && (typeof this.max !== "number" || !(this.max > 0))) {
7553
+ this.max = 100;
7554
+ }
7555
+ if (changedProperties.has("value") || changedProperties.has("max")) {
7556
+ const value = typeof this.value === "number" ? this.value : 0;
7557
+ this.value = Math.min(Math.max(value, 0), this.max ?? 100);
7558
+ }
7559
+ if (changedProperties.has("size") && (this.size == null || !isInputSize(this.size))) {
7560
+ this.size = "md";
7561
+ }
7562
+ if (changedProperties.has("variant") && (this.variant == null || !isProgressVariant(this.variant))) {
7563
+ this.variant = "brand";
7564
+ }
7565
+ }
7566
+ get percent() {
7567
+ return (this.value ?? 0) / (this.max ?? 100) * 100;
7568
+ }
7569
+ get labelledBy() {
7570
+ if (this.forwardedAriaLabelledBy) {
7571
+ return this.forwardedAriaLabelledBy;
7572
+ }
7573
+ return this.label && !this.forwardedAriaLabel ? this.labelId : void 0;
7574
+ }
7575
+ render() {
7576
+ const indeterminate = this.indeterminate ?? false;
7577
+ return html`${this.label ? html`<span class="${getProgressLabelClasses()}" id="${this.labelId}"
7578
+ >${this.label}</span
7579
+ >` : nothing}
7580
+ <div
7581
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7582
+ aria-labelledby="${ifDefined(this.labelledBy)}"
7583
+ aria-valuemax="${this.max ?? 100}"
7584
+ aria-valuemin="0"
7585
+ aria-valuenow="${ifDefined(indeterminate ? void 0 : this.value)}"
7586
+ aria-valuetext="${ifDefined(this.valueText || void 0)}"
7587
+ class="${getProgressClasses({ size: this.size })}"
7588
+ data-sp-progress-native
7589
+ id="${ifDefined(this.id || void 0)}"
7590
+ role="progressbar"
7591
+ title="${ifDefined(this.title || void 0)}"
7592
+ >
7593
+ <div
7594
+ class="${getProgressBarClasses({
7595
+ indeterminate,
7596
+ variant: this.variant
7597
+ })}"
7598
+ data-sp-progress-bar
7599
+ style="${styleMap(indeterminate ? {} : { width: `${this.percent}%` })}"
7600
+ ></div>
7601
+ </div>`;
7602
+ }
7603
+ };
7604
+ SpectreProgressElement.properties = {
7605
+ indeterminate: { type: Boolean, reflect: true },
7606
+ label: { type: String },
7607
+ max: { type: Number, reflect: true },
7608
+ size: { type: String, reflect: true },
7609
+ value: { type: Number, reflect: true },
7610
+ valueText: { attribute: "value-text", type: String },
7611
+ variant: { type: String, reflect: true }
7612
+ };
7613
+ function defineSpectreProgress(tagName = "sp-progress") {
7614
+ const existingElement = customElements.get(tagName);
7615
+ if (existingElement) {
7616
+ return existingElement;
7617
+ }
7618
+ customElements.define(tagName, SpectreProgressElement);
7619
+ return SpectreProgressElement;
7620
+ }
7621
+ var SpectreSwitchElement = class extends SpectreBaseElement {
7622
+ constructor() {
7623
+ super(...arguments);
7624
+ this.checked = false;
7625
+ this.disabled = false;
7626
+ this.focused = false;
7627
+ this.form = void 0;
7628
+ this.label = void 0;
7629
+ this.name = void 0;
7630
+ this.required = false;
7631
+ this.size = "md";
7632
+ this.value = "on";
7633
+ this.projection = new ProjectionController(this, [
7634
+ "data-sp-switch-label"
7635
+ ]);
7636
+ }
7637
+ get id() {
7638
+ return super.id;
7639
+ }
7640
+ set id(value) {
7641
+ super.id = value;
7642
+ }
7643
+ get title() {
7644
+ return super.title;
7645
+ }
7646
+ set title(value) {
7647
+ super.title = value;
7648
+ }
7649
+ willUpdate(changedProperties) {
7650
+ if (changedProperties.has("checked") && this.checked == null) {
7651
+ this.checked = false;
7652
+ }
7653
+ if (changedProperties.has("disabled") && this.disabled == null) {
7654
+ this.disabled = false;
7655
+ }
7656
+ if (changedProperties.has("required") && this.required == null) {
7657
+ this.required = false;
7658
+ }
7659
+ if (changedProperties.has("size") && (this.size == null || !isInputSize(this.size))) {
7660
+ this.size = "md";
7661
+ }
7662
+ }
7663
+ get nativeInput() {
7664
+ return this.querySelector("[data-sp-switch-native]");
7665
+ }
7666
+ focus(options) {
7667
+ this.nativeInput?.focus(options);
7668
+ }
7669
+ blur() {
7670
+ this.nativeInput?.blur();
7671
+ }
7672
+ handleChange(event) {
7673
+ this.checked = event.currentTarget.checked;
7674
+ }
7675
+ render() {
7676
+ const disabled = this.disabled ?? false;
7677
+ const labelContent = this.projection.has() ? this.projection.nodes() : this.label ? html`<span
7678
+ class="${getInputLabelClasses({ disabled })}"
7679
+ data-sp-switch-label-fallback
7680
+ >${this.label}</span
7681
+ >` : nothing;
7682
+ return html`<label data-sp-switch-label>
7683
+ <input
7684
+ aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
7685
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7686
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
7687
+ .checked="${live(this.checked ?? false)}"
7688
+ class="${getSwitchClasses({
7689
+ focused: this.focused ?? false,
7690
+ size: this.size
7691
+ })}"
7692
+ data-sp-switch-native
7693
+ ?disabled="${disabled}"
7694
+ form="${ifDefined(this.form || void 0)}"
7695
+ id="${ifDefined(this.id || void 0)}"
7696
+ name="${ifDefined(this.name || void 0)}"
7697
+ ?required="${this.required ?? false}"
7698
+ role="switch"
7699
+ title="${ifDefined(this.title || void 0)}"
7700
+ type="checkbox"
7701
+ value="${ifDefined(this.value)}"
7702
+ @change="${this.handleChange}"
7703
+ />
7704
+ ${labelContent}
7705
+ </label>`;
7706
+ }
7707
+ };
7708
+ SpectreSwitchElement.properties = {
7709
+ checked: { type: Boolean, reflect: true },
7710
+ disabled: { type: Boolean, reflect: true },
7711
+ focused: { type: Boolean, reflect: true },
7712
+ form: { type: String },
7713
+ label: { type: String },
7714
+ name: { type: String, reflect: true },
7715
+ required: { type: Boolean, reflect: true },
7716
+ size: { type: String, reflect: true },
7717
+ value: { type: String }
7718
+ };
7719
+ function defineSpectreSwitch(tagName = "sp-switch") {
7720
+ const existingElement = customElements.get(tagName);
7721
+ if (existingElement) {
7722
+ return existingElement;
7723
+ }
7724
+ customElements.define(tagName, SpectreSwitchElement);
7725
+ return SpectreSwitchElement;
7726
+ }
7727
+ var SpectreRangeElement = class extends SpectreBaseElement {
7728
+ constructor() {
7729
+ super(...arguments);
7730
+ this.disabled = false;
7731
+ this.focused = false;
7732
+ this.form = void 0;
7733
+ this.max = 100;
7734
+ this.min = 0;
7735
+ this.name = void 0;
7736
+ this.step = 1;
7737
+ this.value = 50;
7738
+ }
7739
+ get id() {
7740
+ return super.id;
7741
+ }
7742
+ set id(value) {
7743
+ super.id = value;
7744
+ }
7745
+ get title() {
7746
+ return super.title;
7747
+ }
7748
+ set title(value) {
7749
+ super.title = value;
7750
+ }
7751
+ willUpdate(changedProperties) {
7752
+ if (changedProperties.has("disabled") && this.disabled == null) {
7753
+ this.disabled = false;
7754
+ }
7755
+ if (changedProperties.has("min") && typeof this.min !== "number") {
7756
+ this.min = 0;
7757
+ }
7758
+ if (changedProperties.has("max") && (typeof this.max !== "number" || this.max <= (this.min ?? 0))) {
7759
+ this.max = (this.min ?? 0) + 100;
7760
+ }
7761
+ if (changedProperties.has("value") || changedProperties.has("min") || changedProperties.has("max")) {
7762
+ const value = typeof this.value === "number" ? this.value : 0;
7763
+ this.value = Math.min(Math.max(value, this.min ?? 0), this.max ?? 100);
7764
+ }
7765
+ }
7766
+ // WebKit/Blink paint the filled track from this recipe-defined variable;
7767
+ // Firefox fills natively.
7768
+ updated(changedProperties) {
7769
+ super.updated(changedProperties);
7770
+ const min = this.min ?? 0;
7771
+ const span = (this.max ?? 100) - min;
7772
+ const percent = span > 0 ? ((this.value ?? min) - min) / span * 100 : 0;
7773
+ this.nativeInput?.style.setProperty(
7774
+ "--sp-component-range-value",
7775
+ `${percent}%`
7776
+ );
7777
+ }
7778
+ get nativeInput() {
7779
+ return this.querySelector("[data-sp-range-native]");
7780
+ }
7781
+ focus(options) {
7782
+ this.nativeInput?.focus(options);
7783
+ }
7784
+ blur() {
7785
+ this.nativeInput?.blur();
7786
+ }
7787
+ handleInput(event) {
7788
+ this.value = event.currentTarget.valueAsNumber;
7789
+ }
7790
+ render() {
7791
+ return html`<input
7792
+ aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
7793
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7794
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
7795
+ class="${getRangeClasses({
7796
+ disabled: this.disabled ?? false,
7797
+ focused: this.focused ?? false
7798
+ })}"
7799
+ data-sp-range-native
7800
+ ?disabled="${this.disabled ?? false}"
7801
+ form="${ifDefined(this.form || void 0)}"
7802
+ id="${ifDefined(this.id || void 0)}"
7803
+ max="${this.max ?? 100}"
7804
+ min="${this.min ?? 0}"
7805
+ name="${ifDefined(this.name || void 0)}"
7806
+ step="${this.step ?? 1}"
7807
+ title="${ifDefined(this.title || void 0)}"
7808
+ type="range"
7809
+ .value="${live(String(this.value ?? 0))}"
7810
+ @change="${this.handleInput}"
7811
+ @input="${this.handleInput}"
7812
+ />`;
7813
+ }
7814
+ };
7815
+ SpectreRangeElement.properties = {
7816
+ disabled: { type: Boolean, reflect: true },
7817
+ focused: { type: Boolean, reflect: true },
7818
+ form: { type: String },
7819
+ max: { type: Number, reflect: true },
7820
+ min: { type: Number, reflect: true },
7821
+ name: { type: String, reflect: true },
7822
+ step: { type: Number, reflect: true },
7823
+ value: { type: Number, reflect: true }
7824
+ };
7825
+ function defineSpectreRange(tagName = "sp-range") {
7826
+ const existingElement = customElements.get(tagName);
7827
+ if (existingElement) {
7828
+ return existingElement;
7829
+ }
7830
+ customElements.define(tagName, SpectreRangeElement);
7831
+ return SpectreRangeElement;
7832
+ }
7833
+ var SpectreFileInputElement = class extends SpectreBaseElement {
7834
+ constructor() {
7835
+ super(...arguments);
7836
+ this.accept = void 0;
7837
+ this.disabled = false;
7838
+ this.focused = false;
7839
+ this.form = void 0;
7840
+ this.fullWidth = false;
7841
+ this.invalid = false;
7842
+ this.multiple = false;
7843
+ this.name = void 0;
7844
+ this.required = false;
7845
+ this.size = "md";
7846
+ this.success = false;
7847
+ }
7848
+ get id() {
7849
+ return super.id;
7850
+ }
7851
+ set id(value) {
7852
+ super.id = value;
7853
+ }
7854
+ get title() {
7855
+ return super.title;
7856
+ }
7857
+ set title(value) {
7858
+ super.title = value;
7859
+ }
7860
+ willUpdate(changedProperties) {
7861
+ if (changedProperties.has("size") && (this.size == null || !isInputSize(this.size))) {
7862
+ this.size = "md";
7863
+ }
7864
+ }
7865
+ get nativeInput() {
7866
+ return this.querySelector("[data-sp-file-input-native]");
7867
+ }
7868
+ get files() {
7869
+ return this.nativeInput?.files ?? null;
7870
+ }
7871
+ focus(options) {
7872
+ this.nativeInput?.focus(options);
7873
+ }
7874
+ blur() {
7875
+ this.nativeInput?.blur();
7876
+ }
7877
+ render() {
7878
+ const state = this.invalid ? "invalid" : this.success ? "success" : "default";
7879
+ return html`<input
7880
+ accept="${ifDefined(this.accept || void 0)}"
7881
+ aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
7882
+ aria-invalid="${ifDefined(this.invalid ? "true" : void 0)}"
7883
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7884
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
7885
+ class="${getFileInputClasses({
7886
+ disabled: this.disabled ?? false,
7887
+ focused: this.focused ?? false,
7888
+ fullWidth: this.fullWidth ?? false,
7889
+ size: this.size,
7890
+ state
7891
+ })}"
7892
+ data-sp-file-input-native
7893
+ ?disabled="${this.disabled ?? false}"
7894
+ form="${ifDefined(this.form || void 0)}"
7895
+ id="${ifDefined(this.id || void 0)}"
7896
+ ?multiple="${this.multiple ?? false}"
7897
+ name="${ifDefined(this.name || void 0)}"
7898
+ ?required="${this.required ?? false}"
7899
+ title="${ifDefined(this.title || void 0)}"
7900
+ type="file"
7901
+ />`;
7902
+ }
7903
+ };
7904
+ SpectreFileInputElement.properties = {
7905
+ accept: { type: String, reflect: true },
7906
+ disabled: { type: Boolean, reflect: true },
7907
+ focused: { type: Boolean, reflect: true },
7908
+ form: { type: String },
7909
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
7910
+ invalid: { type: Boolean, reflect: true },
7911
+ multiple: { type: Boolean, reflect: true },
7912
+ name: { type: String, reflect: true },
7913
+ required: { type: Boolean, reflect: true },
7914
+ size: { type: String, reflect: true },
7915
+ success: { type: Boolean, reflect: true }
7916
+ };
7917
+ function defineSpectreFileInput(tagName = "sp-file-input") {
7918
+ const existingElement = customElements.get(tagName);
7919
+ if (existingElement) {
7920
+ return existingElement;
7921
+ }
7922
+ customElements.define(tagName, SpectreFileInputElement);
7923
+ return SpectreFileInputElement;
7924
+ }
7925
+ var SpectreExternalAuthButtonElement = class extends SpectreBaseElement {
7926
+ constructor() {
7927
+ super(...arguments);
7928
+ this.active = false;
7929
+ this.focused = false;
7930
+ this.hovered = false;
7931
+ this.disabled = false;
7932
+ this.fullWidth = false;
7933
+ this.href = void 0;
7934
+ this.loading = false;
7935
+ this.type = "button";
7936
+ this.projection = new ProjectionController(this, [
7937
+ "data-sp-external-auth-button-native"
7938
+ ]);
7939
+ }
7940
+ get id() {
7941
+ return super.id;
7942
+ }
7943
+ set id(value) {
7944
+ super.id = value;
7945
+ }
7946
+ get title() {
7947
+ return super.title;
7948
+ }
7949
+ set title(value) {
7950
+ super.title = value;
7951
+ }
7952
+ willUpdate(changedProperties) {
7953
+ if (changedProperties.has("type") && this.type !== "button" && this.type !== "submit") {
7954
+ this.type = "button";
7955
+ }
7956
+ }
7957
+ get nativeElement() {
7958
+ return this.querySelector("[data-sp-external-auth-button-native]");
7959
+ }
7960
+ focus(options) {
7961
+ this.nativeElement?.focus(options);
7962
+ }
7963
+ blur() {
7964
+ this.nativeElement?.blur();
7965
+ }
7966
+ // A submit button inside a light-DOM form submits natively.
7967
+ render() {
7968
+ const classes = getExternalAuthButtonClasses({
7969
+ ...interactionStates(this),
7970
+ disabled: this.isDisabled,
7971
+ fullWidth: this.fullWidth ?? false,
7972
+ loading: this.loading ?? false
7973
+ });
7974
+ const content = html`${this.projection.has("icon") ? html`<span class="${getExternalAuthButtonIconClasses()}"
7975
+ >${this.projection.nodes("icon")}</span
7976
+ >` : nothing}${this.projection.nodes()}`;
7977
+ if (this.href) {
7978
+ return html`<a
7979
+ aria-busy="${ifDefined(this.loading ? "true" : void 0)}"
7980
+ aria-disabled="${ifDefined(this.isDisabled ? "true" : void 0)}"
7981
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7982
+ class="${classes}"
7983
+ data-sp-external-auth-button-native
7984
+ href="${ifDefined(this.isDisabled ? void 0 : this.href)}"
7985
+ id="${ifDefined(this.id || void 0)}"
7986
+ title="${ifDefined(this.title || void 0)}"
7987
+ >${content}</a
7988
+ >`;
7989
+ }
7990
+ return html`<button
7991
+ aria-busy="${ifDefined(this.loading ? "true" : void 0)}"
7992
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
7993
+ class="${classes}"
7994
+ data-sp-external-auth-button-native
7995
+ ?disabled="${this.isDisabled}"
7996
+ id="${ifDefined(this.id || void 0)}"
7997
+ title="${ifDefined(this.title || void 0)}"
7998
+ type="${this.type ?? "button"}"
7999
+ >
8000
+ ${content}
8001
+ </button>`;
8002
+ }
8003
+ };
8004
+ SpectreExternalAuthButtonElement.properties = {
8005
+ ...interactionStateProperties,
8006
+ disabled: { type: Boolean, reflect: true },
8007
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
8008
+ href: { type: String },
8009
+ loading: { type: Boolean, reflect: true },
8010
+ type: { type: String }
8011
+ };
8012
+ function defineSpectreExternalAuthButton(tagName = "sp-external-auth-button") {
8013
+ const existingElement = customElements.get(tagName);
8014
+ if (existingElement) {
8015
+ return existingElement;
8016
+ }
8017
+ customElements.define(tagName, SpectreExternalAuthButtonElement);
8018
+ return SpectreExternalAuthButtonElement;
8019
+ }
8020
+ function owningCard(input) {
8021
+ let node = input.parentElement;
8022
+ while (node && !isSpectreKind(node, "choice-card")) {
8023
+ node = node.parentElement;
8024
+ }
8025
+ return node;
8026
+ }
8027
+ var _a4, _b4;
8028
+ var SpectreChoiceCardElement = class extends (_b4 = SpectreBaseElement, _a4 = spectreKindKey, _b4) {
8029
+ constructor() {
8030
+ super(...arguments);
8031
+ this[_a4] = "choice-card";
8032
+ this.focused = false;
8033
+ this.hovered = false;
8034
+ this.checked = false;
8035
+ this.disabled = false;
8036
+ this.form = void 0;
8037
+ this.name = void 0;
8038
+ this.required = false;
8039
+ this.type = "radio";
8040
+ this.value = void 0;
8041
+ this.projection = new ProjectionController(this, [
8042
+ "data-sp-choice-card-native"
8043
+ ]);
8044
+ }
8045
+ get id() {
8046
+ return super.id;
8047
+ }
8048
+ set id(value) {
8049
+ super.id = value;
8050
+ }
8051
+ get title() {
8052
+ return super.title;
8053
+ }
8054
+ set title(value) {
8055
+ super.title = value;
8056
+ }
8057
+ connectedCallback() {
8058
+ var _a5;
8059
+ super.connectedCallback();
8060
+ (_a5 = this.style).display || (_a5.display = "block");
8061
+ }
8062
+ willUpdate(changedProperties) {
8063
+ if (changedProperties.has("checked") && this.checked == null) {
8064
+ this.checked = false;
8065
+ }
8066
+ if (changedProperties.has("disabled") && this.disabled == null) {
8067
+ this.disabled = false;
8068
+ }
8069
+ if (changedProperties.has("type") && this.type !== "radio" && this.type !== "checkbox") {
8070
+ this.type = "radio";
8071
+ }
8072
+ }
8073
+ get nativeInput() {
8074
+ return this.querySelector("[data-sp-choice-card-input]");
8075
+ }
8076
+ focus(options) {
8077
+ this.nativeInput?.focus(options);
8078
+ }
8079
+ blur() {
8080
+ this.nativeInput?.blur();
8081
+ }
8082
+ // Checking a radio unchecks its group natively; mirror that onto the other
8083
+ // cards' `checked` properties.
8084
+ handleChange(event) {
8085
+ const input = event.currentTarget;
8086
+ this.checked = input.checked;
8087
+ if (this.type !== "radio" || !this.name) {
8088
+ return;
8089
+ }
8090
+ const root = this.getRootNode();
8091
+ root.querySelectorAll("input[data-sp-choice-card-input]").forEach((other) => {
8092
+ if (other === input || other.name !== this.name) {
8093
+ return;
8094
+ }
8095
+ const card = owningCard(other);
8096
+ if (card) {
8097
+ card.checked = other.checked;
8098
+ }
8099
+ });
8100
+ }
8101
+ render() {
8102
+ return html`<label
8103
+ class="${getChoiceCardClasses({
8104
+ ...hoverFocusStates(this),
8105
+ disabled: this.disabled ?? false
8106
+ })}"
8107
+ data-sp-choice-card-native
8108
+ title="${ifDefined(this.title || void 0)}"
8109
+ >
8110
+ <input
8111
+ aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
8112
+ .checked="${live(this.checked ?? false)}"
8113
+ data-sp-choice-card-input
8114
+ ?disabled="${this.disabled ?? false}"
8115
+ form="${ifDefined(this.form || void 0)}"
8116
+ id="${ifDefined(this.id || void 0)}"
8117
+ name="${ifDefined(this.name || void 0)}"
8118
+ ?required="${this.required ?? false}"
8119
+ type="${this.type ?? "radio"}"
8120
+ value="${ifDefined(this.value)}"
8121
+ @change="${this.handleChange}"
8122
+ />
8123
+ <span data-sp-choice-card-content>${this.projection.nodes()}</span>
8124
+ </label>`;
8125
+ }
8126
+ };
8127
+ SpectreChoiceCardElement.properties = {
8128
+ ...hoverFocusStateProperties,
8129
+ checked: { type: Boolean, reflect: true },
8130
+ disabled: { type: Boolean, reflect: true },
8131
+ form: { type: String },
8132
+ name: { type: String, reflect: true },
8133
+ required: { type: Boolean, reflect: true },
8134
+ type: { type: String, reflect: true },
8135
+ value: { type: String }
8136
+ };
8137
+ function defineSpectreChoiceCard(tagName = "sp-choice-card") {
8138
+ const existingElement = customElements.get(tagName);
8139
+ if (existingElement) {
8140
+ return existingElement;
8141
+ }
8142
+ customElements.define(tagName, SpectreChoiceCardElement);
8143
+ return SpectreChoiceCardElement;
8144
+ }
8145
+ function controlClasses(element) {
8146
+ if (element instanceof HTMLInputElement) {
8147
+ return element.type === "file" ? getFileInputClasses() : getInputClasses();
8148
+ }
8149
+ if (element instanceof HTMLSelectElement) {
8150
+ return getSelectClasses();
8151
+ }
8152
+ if (element instanceof HTMLButtonElement) {
8153
+ return getButtonClasses({ variant: "secondary" });
8154
+ }
8155
+ return void 0;
8156
+ }
8157
+ var SpectreInputGroupElement = class extends SpectreBaseElement {
8158
+ constructor() {
8159
+ super(...arguments);
8160
+ this.disabled = false;
8161
+ this.projection = new ProjectionController(this, [
8162
+ "data-sp-input-group-native"
8163
+ ]);
8164
+ }
8165
+ get id() {
8166
+ return super.id;
8167
+ }
8168
+ set id(value) {
8169
+ super.id = value;
8170
+ }
8171
+ get title() {
8172
+ return super.title;
8173
+ }
8174
+ set title(value) {
8175
+ super.title = value;
8176
+ }
8177
+ connectedCallback() {
8178
+ var _a5;
8179
+ super.connectedCallback();
8180
+ (_a5 = this.style).display || (_a5.display = "block");
8181
+ }
8182
+ // Native controls without an author-chosen `sp-*` class get their recipe
8183
+ // class; `slot="addon"` children become addons.
8184
+ updated(changedProperties) {
8185
+ super.updated(changedProperties);
8186
+ this.projection.elements().forEach((element) => {
8187
+ const styled = Array.from(element.classList).some(
8188
+ (name) => name.startsWith("sp-")
8189
+ );
8190
+ const classes = styled ? void 0 : controlClasses(element);
8191
+ if (classes) {
8192
+ element.classList.add(...classes.split(/\s+/).filter(Boolean));
8193
+ }
8194
+ });
8195
+ applyPartClasses(this.projection.elements("addon"), {
8196
+ addon: getInputGroupAddonClasses()
8197
+ });
8198
+ }
8199
+ render() {
8200
+ return html`<div
8201
+ aria-disabled="${ifDefined(this.disabled ? "true" : void 0)}"
8202
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
8203
+ aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
8204
+ class="${getInputGroupClasses({ disabled: this.disabled ?? false })}"
8205
+ data-sp-input-group-native
8206
+ id="${ifDefined(this.id || void 0)}"
8207
+ role="group"
8208
+ title="${ifDefined(this.title || void 0)}"
8209
+ >
8210
+ ${this.projection.all()}
8211
+ </div>`;
8212
+ }
8213
+ };
8214
+ SpectreInputGroupElement.properties = {
8215
+ disabled: { type: Boolean, reflect: true }
8216
+ };
8217
+ function defineSpectreInputGroup(tagName = "sp-input-group") {
8218
+ const existingElement = customElements.get(tagName);
8219
+ if (existingElement) {
8220
+ return existingElement;
8221
+ }
8222
+ customElements.define(tagName, SpectreInputGroupElement);
8223
+ return SpectreInputGroupElement;
8224
+ }
8225
+ var SpectrePopoverElement = class extends SpectreBaseElement {
8226
+ constructor() {
8227
+ super(...arguments);
8228
+ this.label = void 0;
8229
+ this.open = false;
8230
+ this.placement = "bottom";
8231
+ this.triggerLabel = "Show details";
8232
+ this.baseId = createUniqueId("sp-popover");
8233
+ this.projection = new ProjectionController(this, [
8234
+ "data-sp-popover-trigger",
8235
+ "data-sp-popover-native"
8236
+ ]);
8237
+ this.handleDocumentClick = (event) => {
8238
+ if (this.open && !event.composedPath().includes(this)) {
8239
+ this.setOpen(false);
8240
+ }
8241
+ };
8242
+ this.handleDocumentKeydown = (event) => {
8243
+ if (event.key === "Escape" && this.open) {
8244
+ this.setOpen(false);
8245
+ this.triggerElement?.focus();
8246
+ }
8247
+ };
8248
+ }
8249
+ get id() {
8250
+ return super.id;
8251
+ }
8252
+ set id(value) {
8253
+ super.id = value;
8254
+ }
8255
+ get title() {
8256
+ return super.title;
8257
+ }
8258
+ set title(value) {
8259
+ super.title = value;
8260
+ }
8261
+ connectedCallback() {
8262
+ var _a5, _b5;
8263
+ super.connectedCallback();
8264
+ (_a5 = this.style).position || (_a5.position = "relative");
8265
+ (_b5 = this.style).display || (_b5.display = "inline-block");
8266
+ document.addEventListener("click", this.handleDocumentClick);
8267
+ document.addEventListener("keydown", this.handleDocumentKeydown);
8268
+ }
8269
+ disconnectedCallback() {
8270
+ document.removeEventListener("click", this.handleDocumentClick);
8271
+ document.removeEventListener("keydown", this.handleDocumentKeydown);
8272
+ super.disconnectedCallback();
8273
+ }
8274
+ willUpdate(changedProperties) {
8275
+ if (changedProperties.has("open") && this.open == null) {
8276
+ this.open = false;
8277
+ }
8278
+ if (changedProperties.has("placement") && (this.placement == null || !isPopoverPlacement(this.placement))) {
8279
+ this.placement = "bottom";
8280
+ }
8281
+ if (changedProperties.has("triggerLabel") && !this.triggerLabel) {
8282
+ this.triggerLabel = "Show details";
8283
+ }
8284
+ }
8285
+ get triggerElement() {
8286
+ return this.querySelector("[data-sp-popover-trigger]");
8287
+ }
8288
+ get panelId() {
8289
+ return this.id || `${this.baseId}-panel`;
8290
+ }
8291
+ get headerId() {
8292
+ return `${this.baseId}-header`;
8293
+ }
8294
+ get hasHeader() {
8295
+ return this.projection.has("header") || Boolean(this.label);
8296
+ }
8297
+ setOpen(open) {
8298
+ if (this.open === open) {
8299
+ return;
8300
+ }
8301
+ this.open = open;
8302
+ this.dispatchEvent(
8303
+ new CustomEvent(open ? "sp-open" : "sp-close", { bubbles: true })
8304
+ );
8305
+ }
8306
+ get dialogLabelledBy() {
8307
+ if (this.forwardedAriaLabel) {
8308
+ return void 0;
8309
+ }
8310
+ return this.hasHeader ? this.headerId : `${this.baseId}-trigger`;
8311
+ }
8312
+ render() {
8313
+ const open = this.open ?? false;
8314
+ return html`<button
8315
+ aria-controls="${this.panelId}"
8316
+ aria-expanded="${open ? "true" : "false"}"
8317
+ aria-haspopup="dialog"
8318
+ data-sp-popover-trigger
8319
+ id="${this.baseId}-trigger"
8320
+ type="button"
8321
+ @click="${() => this.setOpen(!open)}"
8322
+ >
8323
+ ${this.projection.has("trigger") ? this.projection.nodes("trigger") : this.triggerLabel}
8324
+ </button>
8325
+ <div
8326
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
8327
+ aria-labelledby="${ifDefined(this.dialogLabelledBy)}"
8328
+ class="${getPopoverClasses({
8329
+ open,
8330
+ placement: this.placement
8331
+ })}"
8332
+ data-sp-popover-native
8333
+ id="${this.panelId}"
8334
+ role="dialog"
8335
+ title="${ifDefined(this.title || void 0)}"
8336
+ >
8337
+ <span aria-hidden="true" class="${getPopoverArrowClasses()}"></span>
8338
+ ${this.hasHeader ? html`<div
8339
+ class="${getPopoverHeaderClasses()}"
8340
+ id="${this.headerId}"
8341
+ >
8342
+ ${this.projection.has("header") ? this.projection.nodes("header") : this.label}
8343
+ </div>` : nothing}
8344
+ <div class="${getPopoverBodyClasses()}">${this.projection.nodes()}</div>
8345
+ </div>`;
8346
+ }
8347
+ };
8348
+ SpectrePopoverElement.properties = {
8349
+ label: { type: String },
8350
+ open: { type: Boolean, reflect: true },
8351
+ placement: { type: String, reflect: true },
8352
+ triggerLabel: { attribute: "trigger-label", type: String }
8353
+ };
8354
+ function defineSpectrePopover(tagName = "sp-popover") {
8355
+ const existingElement = customElements.get(tagName);
8356
+ if (existingElement) {
8357
+ return existingElement;
8358
+ }
8359
+ customElements.define(tagName, SpectrePopoverElement);
8360
+ return SpectrePopoverElement;
8361
+ }
8362
+ var ISO_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
8363
+ function pad(value) {
8364
+ return String(value).padStart(2, "0");
8365
+ }
8366
+ function toIsoDate(date) {
8367
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
8368
+ }
8369
+ function parseIsoDate(value) {
8370
+ const match = value ? ISO_DATE.exec(value) : null;
8371
+ if (!match) {
8372
+ return void 0;
8373
+ }
8374
+ const [year, month, day] = [
8375
+ Number(match[1]),
8376
+ Number(match[2]),
8377
+ Number(match[3])
8378
+ ];
8379
+ const date = new Date(year, month - 1, day);
8380
+ return date.getMonth() === month - 1 && date.getDate() === day ? date : void 0;
8381
+ }
8382
+ function addDays(date, days) {
8383
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);
8384
+ }
8385
+ function addMonths(date, months) {
8386
+ const target = new Date(date.getFullYear(), date.getMonth() + months, 1);
8387
+ const lastDay = new Date(
8388
+ target.getFullYear(),
8389
+ target.getMonth() + 1,
8390
+ 0
8391
+ ).getDate();
8392
+ target.setDate(Math.min(date.getDate(), lastDay));
8393
+ return target;
8394
+ }
8395
+ function today() {
8396
+ const now = /* @__PURE__ */ new Date();
8397
+ return new Date(now.getFullYear(), now.getMonth(), now.getDate());
8398
+ }
8399
+ var SpectreDatepickerElement = class extends SpectreBaseElement {
8400
+ constructor() {
8401
+ super(...arguments);
8402
+ this.locale = void 0;
8403
+ this.max = void 0;
8404
+ this.min = void 0;
8405
+ this.name = void 0;
8406
+ this.nextLabel = "Next month";
8407
+ this.previousLabel = "Previous month";
8408
+ this.value = void 0;
8409
+ this.weekStart = 0;
8410
+ // The roving-focus day; its month is the one on display.
8411
+ this.activeDate = today();
8412
+ this.titleId = `${createUniqueId("sp-datepicker")}-title`;
8413
+ this.handleKeydown = async (event) => {
8414
+ const active = this.activeDate;
8415
+ const weekday = (active.getDay() - (this.weekStart ?? 0) + 7) % 7;
8416
+ const moves = {
8417
+ ArrowLeft: () => addDays(active, -1),
8418
+ ArrowRight: () => addDays(active, 1),
8419
+ ArrowUp: () => addDays(active, -7),
8420
+ ArrowDown: () => addDays(active, 7),
8421
+ Home: () => addDays(active, -weekday),
8422
+ End: () => addDays(active, 6 - weekday),
8423
+ PageUp: () => addMonths(active, event.shiftKey ? -12 : -1),
8424
+ PageDown: () => addMonths(active, event.shiftKey ? 12 : 1)
8425
+ };
8426
+ const move = moves[event.key];
8427
+ if (!move) {
8428
+ return;
8429
+ }
8430
+ event.preventDefault();
8431
+ this.activeDate = move();
8432
+ await this.updateComplete;
8433
+ this.querySelector(
8434
+ `[data-sp-day="${toIsoDate(this.activeDate)}"]`
8435
+ )?.focus();
8436
+ };
8437
+ }
8438
+ get id() {
8439
+ return super.id;
8440
+ }
8441
+ set id(value) {
8442
+ super.id = value;
8443
+ }
8444
+ get title() {
8445
+ return super.title;
8446
+ }
8447
+ set title(value) {
8448
+ super.title = value;
8449
+ }
8450
+ connectedCallback() {
8451
+ var _a5;
8452
+ super.connectedCallback();
8453
+ (_a5 = this.style).display || (_a5.display = "inline-block");
8454
+ }
8455
+ willUpdate(changedProperties) {
8456
+ if (changedProperties.has("value")) {
8457
+ const parsed = parseIsoDate(this.value);
8458
+ if (this.value && !parsed) {
8459
+ this.value = void 0;
8460
+ } else if (parsed) {
8461
+ this.activeDate = parsed;
8462
+ }
8463
+ }
8464
+ if (changedProperties.has("min") && !parseIsoDate(this.min)) {
8465
+ this.min = void 0;
8466
+ }
8467
+ if (changedProperties.has("max") && !parseIsoDate(this.max)) {
8468
+ this.max = void 0;
8469
+ }
8470
+ if (changedProperties.has("weekStart")) {
8471
+ const weekStart = normalizeInt(this.weekStart, 0) ?? 0;
8472
+ this.weekStart = weekStart > 6 ? 0 : weekStart;
8473
+ }
8474
+ if (changedProperties.has("nextLabel") && !this.nextLabel) {
8475
+ this.nextLabel = "Next month";
8476
+ }
8477
+ if (changedProperties.has("previousLabel") && !this.previousLabel) {
8478
+ this.previousLabel = "Previous month";
8479
+ }
8480
+ }
8481
+ isOutOfRange(date) {
8482
+ const iso = toIsoDate(date);
8483
+ return this.min !== void 0 && iso < this.min || this.max !== void 0 && iso > this.max;
8484
+ }
8485
+ get visibleDays() {
8486
+ const first = new Date(
8487
+ this.activeDate.getFullYear(),
8488
+ this.activeDate.getMonth(),
8489
+ 1
8490
+ );
8491
+ const daysInMonth = new Date(
8492
+ first.getFullYear(),
8493
+ first.getMonth() + 1,
8494
+ 0
8495
+ ).getDate();
8496
+ const leading = (first.getDay() - (this.weekStart ?? 0) + 7) % 7;
8497
+ const count = Math.ceil((leading + daysInMonth) / 7) * 7;
8498
+ const start = addDays(first, -leading);
8499
+ return Array.from({ length: count }, (_, index) => addDays(start, index));
8500
+ }
8501
+ select(date) {
8502
+ if (this.isOutOfRange(date)) {
8503
+ return;
8504
+ }
8505
+ this.activeDate = date;
8506
+ const value = toIsoDate(date);
8507
+ if (value === this.value) {
8508
+ return;
8509
+ }
8510
+ this.value = value;
8511
+ this.dispatchEvent(
8512
+ new CustomEvent("sp-change", { bubbles: true, detail: { value } })
8513
+ );
8514
+ }
8515
+ showMonth(offset) {
8516
+ this.activeDate = addMonths(this.activeDate, offset);
8517
+ }
8518
+ renderDay(date) {
8519
+ const iso = toIsoDate(date);
8520
+ const selected = iso === this.value;
8521
+ const isToday = iso === toIsoDate(today());
8522
+ const disabled = this.isOutOfRange(date);
8523
+ const label = new Intl.DateTimeFormat(this.locale, {
8524
+ dateStyle: "full"
8525
+ }).format(date);
8526
+ return html`<button
8527
+ aria-current="${ifDefined(isToday ? "date" : void 0)}"
8528
+ aria-label="${label}"
8529
+ aria-pressed="${selected ? "true" : "false"}"
8530
+ class="${getDayClasses({
8531
+ disabled,
8532
+ outsideMonth: date.getMonth() !== this.activeDate.getMonth(),
8533
+ selected,
8534
+ today: isToday
8535
+ })}"
8536
+ data-sp-day="${iso}"
8537
+ ?disabled="${disabled}"
8538
+ tabindex="${iso === toIsoDate(this.activeDate) ? "0" : "-1"}"
8539
+ type="button"
8540
+ @click="${() => this.select(date)}"
8541
+ >
8542
+ ${date.getDate()}
8543
+ </button>`;
8544
+ }
8545
+ render() {
8546
+ const days = this.visibleDays;
8547
+ const weekdayFormat = new Intl.DateTimeFormat(this.locale, {
8548
+ weekday: "short"
8549
+ });
8550
+ const navClasses = getButtonClasses({
8551
+ iconOnly: true,
8552
+ size: "sm",
8553
+ variant: "ghost"
8554
+ });
8555
+ return html`<div
8556
+ aria-label="${ifDefined(this.forwardedAriaLabel)}"
8557
+ aria-labelledby="${ifDefined(
8558
+ this.forwardedAriaLabel ? void 0 : this.titleId
8559
+ )}"
8560
+ class="${getDatepickerClasses()}"
8561
+ data-sp-datepicker-native
8562
+ id="${ifDefined(this.id || void 0)}"
8563
+ role="group"
8564
+ title="${ifDefined(this.title || void 0)}"
8565
+ >
8566
+ <div class="${getDatepickerHeaderClasses()}">
8567
+ <button
8568
+ aria-label="${this.previousLabel ?? "Previous month"}"
8569
+ class="${navClasses}"
8570
+ data-sp-datepicker-prev
8571
+ type="button"
8572
+ @click="${() => this.showMonth(-1)}"
8573
+ >
8574
+ ${renderIcon("chevronLeft")}
8575
+ </button>
8576
+ <span aria-live="polite" id="${this.titleId}"
8577
+ >${new Intl.DateTimeFormat(this.locale, {
8578
+ month: "long",
8579
+ year: "numeric"
8580
+ }).format(this.activeDate)}</span
8581
+ >
8582
+ <button
8583
+ aria-label="${this.nextLabel ?? "Next month"}"
8584
+ class="${navClasses}"
8585
+ data-sp-datepicker-next
8586
+ type="button"
8587
+ @click="${() => this.showMonth(1)}"
8588
+ >
8589
+ ${renderIcon("chevronRight")}
8590
+ </button>
8591
+ </div>
8592
+ <div
8593
+ class="${getDatepickerGridClasses()}"
8594
+ data-sp-datepicker-grid
8595
+ @keydown="${this.handleKeydown}"
8596
+ >
8597
+ ${days.slice(0, 7).map(
8598
+ (date) => html`<span
8599
+ aria-hidden="true"
8600
+ class="${getDatepickerWeekdayClasses()}"
8601
+ >${weekdayFormat.format(date)}</span
8602
+ >`
8603
+ )}
8604
+ ${days.map((date) => this.renderDay(date))}
8605
+ </div>
8606
+ ${this.name ? html`<input
8607
+ name="${this.name}"
8608
+ type="hidden"
8609
+ .value="${this.value ?? ""}"
8610
+ />` : nothing}
8611
+ </div>`;
8612
+ }
8613
+ };
8614
+ SpectreDatepickerElement.properties = {
8615
+ activeDate: { state: true },
8616
+ locale: { type: String },
8617
+ max: { type: String },
8618
+ min: { type: String },
8619
+ name: { type: String },
8620
+ nextLabel: { attribute: "next-label", type: String },
8621
+ previousLabel: { attribute: "previous-label", type: String },
8622
+ value: { type: String, reflect: true },
8623
+ weekStart: { attribute: "week-start", type: Number }
8624
+ };
8625
+ function defineSpectreDatepicker(tagName = "sp-datepicker") {
8626
+ const existingElement = customElements.get(tagName);
8627
+ if (existingElement) {
8628
+ return existingElement;
8629
+ }
8630
+ customElements.define(tagName, SpectreDatepickerElement);
8631
+ return SpectreDatepickerElement;
8632
+ }
5172
8633
 
5173
8634
  // src/index.ts
5174
8635
  function defineSpectreComponents() {
@@ -5207,8 +8668,31 @@ function defineSpectreComponents() {
5207
8668
  defineSpectreToast();
5208
8669
  defineSpectreTooltip();
5209
8670
  defineSpectreText();
8671
+ defineSpectreTabs();
8672
+ defineSpectreTabPanel();
8673
+ defineSpectreAccordion();
8674
+ defineSpectreAccordionItem();
8675
+ defineSpectreBreadcrumb();
8676
+ defineSpectreListGroup();
8677
+ defineSpectreListGroupItem();
8678
+ defineSpectreOffcanvas();
8679
+ defineSpectreCarousel();
8680
+ defineSpectreTable();
8681
+ defineSpectrePagination();
8682
+ defineSpectreStepper();
8683
+ defineSpectreCardBleed();
8684
+ defineSpectreProse();
8685
+ defineSpectreProgress();
8686
+ defineSpectreSwitch();
8687
+ defineSpectreRange();
8688
+ defineSpectreFileInput();
8689
+ defineSpectreExternalAuthButton();
8690
+ defineSpectreChoiceCard();
8691
+ defineSpectreInputGroup();
8692
+ defineSpectrePopover();
8693
+ defineSpectreDatepicker();
5210
8694
  }
5211
8695
 
5212
- export { SpectreAlertElement, SpectreAvatarElement, SpectreBadgeElement, SpectreButtonElement, SpectreCardElement, SpectreCheckboxElement, SpectreContainerElement, SpectreDropdownElement, SpectreFieldsetElement, SpectreFooterChipElement, SpectreFooterElement, SpectreFooterLinkElement, SpectreGridElement, SpectreIconBoxElement, SpectreInputElement, SpectreLabelElement, SpectreModalElement, SpectreNavElement, SpectreNavItemElement, SpectrePricingCardElement, SpectreRadioElement, SpectreRatingElement, SpectreSectionElement, SpectreSelectElement, SpectreSidebarElement, SpectreSidebarLinkElement, SpectreSidebarToggleElement, SpectreSpinnerElement, SpectreStackElement, SpectreTagElement, SpectreTestimonialElement, SpectreTextElement, SpectreTextareaElement, SpectreToastElement, SpectreTooltipElement, defineSpectreAlert, defineSpectreAvatar, defineSpectreBadge, defineSpectreButton, defineSpectreCard, defineSpectreCheckbox, defineSpectreComponents, defineSpectreContainer, defineSpectreDropdown, defineSpectreFieldset, defineSpectreFooter, defineSpectreFooterChip, defineSpectreFooterLink, defineSpectreGrid, defineSpectreIconBox, defineSpectreInput, defineSpectreLabel, defineSpectreModal, defineSpectreNav, defineSpectreNavItem, defineSpectrePricingCard, defineSpectreRadio, defineSpectreRating, defineSpectreSection, defineSpectreSelect, defineSpectreSidebar, defineSpectreSidebarLink, defineSpectreSidebarToggle, defineSpectreSpinner, defineSpectreStack, defineSpectreTag, defineSpectreTestimonial, defineSpectreText, defineSpectreTextarea, defineSpectreToast, defineSpectreTooltip, spectreInputSizes as spectreAlertSizes, spectreAlertVariants, spectreAvatarShapes, spectreAvatarSizes, spectreInputSizes as spectreBadgeSizes, spectreBadgeVariants, spectreInputSizes as spectreButtonSizes, spectreButtonTypes, spectreButtonVariants, spectreAccentColors as spectreCardAccentColors, spectreAccentEdges as spectreCardAccentEdges, spectreCardVariants, spectreContainerMaxWidths, spectreDropdownPlacements, spectreGridAligns, spectreGridColumns, spectreGridGaps, spectreInputSizes as spectreIconBoxSizes, spectreIconBoxVariants, spectreInputSizes, spectreInputTypes, spectreInputSizes as spectreRatingSizes, spectreInputSizes as spectreSpinnerSizes, spectreSpinnerVariants, spectreStackAligns, spectreStackBases, spectreStackDirections, spectreStackGaps, spectreInputSizes as spectreTagSizes, spectreTagVariants, spectreTestimonialVariants, spectreTextFamilies, spectreTextLevels, spectreTextSizes, spectreTextVariants, spectreToastVariants, spectreTooltipPlacements };
8696
+ export { SpectreAccordionElement, SpectreAccordionItemElement, SpectreAlertElement, SpectreAvatarElement, SpectreBadgeElement, SpectreBreadcrumbElement, SpectreButtonElement, SpectreCardBleedElement, SpectreCardElement, SpectreCarouselElement, SpectreCheckboxElement, SpectreChoiceCardElement, SpectreContainerElement, SpectreDatepickerElement, SpectreDropdownElement, SpectreExternalAuthButtonElement, SpectreFieldsetElement, SpectreFileInputElement, SpectreFooterChipElement, SpectreFooterElement, SpectreFooterLinkElement, SpectreGridElement, SpectreIconBoxElement, SpectreInputElement, SpectreInputGroupElement, SpectreLabelElement, SpectreListGroupElement, SpectreListGroupItemElement, SpectreModalElement, SpectreNavElement, SpectreNavItemElement, SpectreOffcanvasElement, SpectrePaginationElement, SpectrePopoverElement, SpectrePricingCardElement, SpectreProgressElement, SpectreProseElement, SpectreRadioElement, SpectreRangeElement, SpectreRatingElement, SpectreSectionElement, SpectreSelectElement, SpectreSidebarElement, SpectreSidebarLinkElement, SpectreSidebarToggleElement, SpectreSpinnerElement, SpectreStackElement, SpectreStepperElement, SpectreSwitchElement, SpectreTabPanelElement, SpectreTableElement, SpectreTabsElement, SpectreTagElement, SpectreTestimonialElement, SpectreTextElement, SpectreTextareaElement, SpectreToastElement, SpectreTooltipElement, defineSpectreAccordion, defineSpectreAccordionItem, defineSpectreAlert, defineSpectreAvatar, defineSpectreBadge, defineSpectreBreadcrumb, defineSpectreButton, defineSpectreCard, defineSpectreCardBleed, defineSpectreCarousel, defineSpectreCheckbox, defineSpectreChoiceCard, defineSpectreComponents, defineSpectreContainer, defineSpectreDatepicker, defineSpectreDropdown, defineSpectreExternalAuthButton, defineSpectreFieldset, defineSpectreFileInput, defineSpectreFooter, defineSpectreFooterChip, defineSpectreFooterLink, defineSpectreGrid, defineSpectreIconBox, defineSpectreInput, defineSpectreInputGroup, defineSpectreLabel, defineSpectreListGroup, defineSpectreListGroupItem, defineSpectreModal, defineSpectreNav, defineSpectreNavItem, defineSpectreOffcanvas, defineSpectrePagination, defineSpectrePopover, defineSpectrePricingCard, defineSpectreProgress, defineSpectreProse, defineSpectreRadio, defineSpectreRange, defineSpectreRating, defineSpectreSection, defineSpectreSelect, defineSpectreSidebar, defineSpectreSidebarLink, defineSpectreSidebarToggle, defineSpectreSpinner, defineSpectreStack, defineSpectreStepper, defineSpectreSwitch, defineSpectreTabPanel, defineSpectreTable, defineSpectreTabs, defineSpectreTag, defineSpectreTestimonial, defineSpectreText, defineSpectreTextarea, defineSpectreToast, defineSpectreTooltip, spectreInputSizes as spectreAlertSizes, spectreAlertVariants, spectreAvatarShapes, spectreAvatarSizes, spectreInputSizes as spectreBadgeSizes, spectreBadgeVariants, spectreInputSizes as spectreButtonSizes, spectreButtonTypes, spectreButtonVariants, spectreAccentColors as spectreCardAccentColors, spectreAccentEdges as spectreCardAccentEdges, spectreCardVariants, spectreContainerMaxWidths, spectreSpacingScale as spectreContainerPaddings, spectreDisplayLevels, spectreDropdownPlacements, spectreInputSizes as spectreFileInputSizes, spectreGridAligns, spectreGridColStarts, spectreGridColumns, spectreGridGaps, spectreHeadingLevels, spectreInputSizes as spectreIconBoxSizes, spectreIconBoxVariants, spectreInputSizes, spectreInputTypes, spectreOffcanvasPlacements, spectreInputSizes as spectrePaginationSizes, spectrePopoverPlacements, spectreInputSizes as spectreProgressSizes, spectreProgressVariants, spectreInputSizes as spectreRatingSizes, spectreSpacingScale as spectreSectionSpacings, spectreInputSizes as spectreSpinnerSizes, spectreSpinnerVariants, spectreStackAligns, spectreStackBases, spectreStackDirections, spectreStackGaps, spectreStepperOrientations, spectreInputSizes as spectreSwitchSizes, spectreTableRowVariants, spectreTableSizes, spectreTabsVariants, spectreInputSizes as spectreTagSizes, spectreTagVariants, spectreTestimonialVariants, spectreTextFamilies, spectreTextLevels, spectreTextPresets, spectreTextSizes, spectreTextVariants, spectreToastVariants, spectreTooltipPlacements };
5213
8697
  //# sourceMappingURL=index.js.map
5214
8698
  //# sourceMappingURL=index.js.map