@phcdevworks/spectre-components 1.19.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 (352) hide show
  1. package/README.md +770 -125
  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 +83 -3
  27. package/dist/badge.cjs.map +1 -1
  28. package/dist/badge.d.cts +51 -3
  29. package/dist/badge.d.ts +51 -3
  30. package/dist/badge.js +83 -3
  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 +61 -1
  51. package/dist/card.cjs.map +1 -1
  52. package/dist/card.d.cts +33 -4
  53. package/dist/card.d.ts +33 -4
  54. package/dist/card.js +60 -2
  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 +66 -3
  87. package/dist/dropdown.cjs.map +1 -1
  88. package/dist/dropdown.d.cts +22 -2
  89. package/dist/dropdown.d.ts +22 -2
  90. package/dist/dropdown.js +67 -4
  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 +62 -1
  121. package/dist/footer.cjs.map +1 -1
  122. package/dist/footer.d.cts +15 -0
  123. package/dist/footer.d.ts +15 -0
  124. package/dist/footer.js +63 -2
  125. package/dist/footer.js.map +1 -1
  126. package/dist/{form-TvtLcoW0.d.cts → form-CVO7mlDa.d.cts} +42 -9
  127. package/dist/{form-TvtLcoW0.d.ts → form-CVO7mlDa.d.ts} +42 -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 +3849 -109
  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 +3787 -112
  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 +70 -35
  175. package/dist/modal.cjs.map +1 -1
  176. package/dist/modal.d.cts +14 -2
  177. package/dist/modal.d.ts +14 -2
  178. package/dist/modal.js +70 -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 +57 -1
  187. package/dist/nav.cjs.map +1 -1
  188. package/dist/nav.d.cts +15 -1
  189. package/dist/nav.d.ts +15 -1
  190. package/dist/nav.js +58 -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 +153 -64
  211. package/dist/pricing-card.cjs.map +1 -1
  212. package/dist/pricing-card.d.cts +34 -6
  213. package/dist/pricing-card.d.ts +34 -6
  214. package/dist/pricing-card.js +154 -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 +162 -64
  323. package/dist/testimonial.cjs.map +1 -1
  324. package/dist/testimonial.d.cts +36 -8
  325. package/dist/testimonial.d.ts +36 -8
  326. package/dist/testimonial.js +163 -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 +34 -1
  341. package/dist/toast.cjs.map +1 -1
  342. package/dist/toast.d.cts +15 -2
  343. package/dist/toast.d.ts +15 -2
  344. package/dist/toast.js +34 -1
  345. package/dist/toast.js.map +1 -1
  346. package/dist/tooltip.cjs +32 -0
  347. package/dist/tooltip.cjs.map +1 -1
  348. package/dist/tooltip.d.cts +15 -2
  349. package/dist/tooltip.d.ts +15 -2
  350. package/dist/tooltip.js +32 -0
  351. package/dist/tooltip.js.map +1 -1
  352. package/package.json +130 -15
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);
@@ -85,6 +92,22 @@ function isCardPaddingSize(value) {
85
92
  value
86
93
  );
87
94
  }
95
+ var spectreAccentEdges = ["top", "right", "bottom", "left"];
96
+ function isAccentEdge(value) {
97
+ return spectreAccentEdges.includes(value);
98
+ }
99
+ var spectreAccentColors = [
100
+ "neutral",
101
+ "brand",
102
+ "info",
103
+ "success",
104
+ "warning",
105
+ "danger",
106
+ "cta"
107
+ ];
108
+ function isAccentColor(value) {
109
+ return spectreAccentColors.includes(value);
110
+ }
88
111
  var spectreIconBoxVariants = [
89
112
  "primary",
90
113
  "secondary",
@@ -121,7 +144,8 @@ var spectreSpinnerVariants = [
121
144
  "info",
122
145
  "neutral",
123
146
  "accent",
124
- "cta"
147
+ "cta",
148
+ "inverse"
125
149
  ];
126
150
  function isSpinnerVariant(value) {
127
151
  return spectreSpinnerVariants.includes(value);
@@ -151,7 +175,7 @@ var spectreAvatarShapes = ["circle", "square"];
151
175
  function isAvatarShape(value) {
152
176
  return spectreAvatarShapes.includes(value);
153
177
  }
154
- var spectreContainerMaxWidths = ["prose"];
178
+ var spectreContainerMaxWidths = ["none", "prose", "wide"];
155
179
  function isContainerMaxWidth(value) {
156
180
  return spectreContainerMaxWidths.includes(
157
181
  value
@@ -306,7 +330,7 @@ var spectreStackDirections = ["vertical", "horizontal"];
306
330
  function isStackDirection(value) {
307
331
  return spectreStackDirections.includes(value);
308
332
  }
309
- var spectreStackBases = ["sidebar"];
333
+ var spectreStackBases = ["none", "sidebar"];
310
334
  function isStackBasis(value) {
311
335
  return spectreStackBases.includes(value);
312
336
  }
@@ -337,7 +361,8 @@ var spectreToastVariants = [
337
361
  "info",
338
362
  "success",
339
363
  "warning",
340
- "danger"
364
+ "danger",
365
+ "neutral"
341
366
  ];
342
367
  function isToastVariant(value) {
343
368
  return spectreToastVariants.includes(value);
@@ -381,7 +406,12 @@ var spectreTextVariants = [
381
406
  "meta",
382
407
  "brand",
383
408
  "onInverse",
384
- "onInverseMuted"
409
+ "onInverseMuted",
410
+ "onSurface",
411
+ "onSurfaceMuted",
412
+ "onSurfaceSubtle",
413
+ "onSurfaceMeta",
414
+ "onSurfaceBrand"
385
415
  ];
386
416
  function isTextVariant(value) {
387
417
  return spectreTextVariants.includes(value);
@@ -412,6 +442,114 @@ var spectreTextTransforms = [
412
442
  function isTextTransform(value) {
413
443
  return spectreTextTransforms.includes(value);
414
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
+ }
415
553
  function normalizeInt(value, fallback, min = 0) {
416
554
  if (value == null || typeof value !== "number" || !Number.isInteger(value) || value < min) {
417
555
  return fallback;
@@ -700,6 +838,22 @@ function hasMeaningfulContent(nodes) {
700
838
  return false;
701
839
  });
702
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
+ }
703
857
 
704
858
  // src/utils/projectable.ts
705
859
  var SpectreProjectableElement = class extends SpectreBaseElement {
@@ -735,7 +889,9 @@ var SpectreProjectableElement = class extends SpectreBaseElement {
735
889
  nextProjectedContent.push(node);
736
890
  }
737
891
  });
738
- 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
+ );
739
895
  if (hasChanged) {
740
896
  this.projectedContent = nextProjectedContent;
741
897
  }
@@ -765,9 +921,31 @@ var SpectreProjectableElement = class extends SpectreBaseElement {
765
921
  this.contentObserver = void 0;
766
922
  }
767
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
+ }
768
943
  var SpectreButtonElement = class extends SpectreProjectableElement {
769
944
  constructor() {
770
945
  super(...arguments);
946
+ this.active = false;
947
+ this.focused = false;
948
+ this.hovered = false;
771
949
  this.compact = false;
772
950
  this.disabled = false;
773
951
  this.fullWidth = false;
@@ -851,6 +1029,7 @@ var SpectreButtonElement = class extends SpectreProjectableElement {
851
1029
  }
852
1030
  get buttonClasses() {
853
1031
  const recipeClasses = getButtonClasses({
1032
+ ...interactionStates(this),
854
1033
  compact: this.compact ?? false,
855
1034
  disabled: this.isDisabled,
856
1035
  fullWidth: this.fullWidth ?? false,
@@ -930,6 +1109,7 @@ var SpectreButtonElement = class extends SpectreProjectableElement {
930
1109
  }
931
1110
  };
932
1111
  SpectreButtonElement.properties = {
1112
+ ...interactionStateProperties,
933
1113
  compact: { type: Boolean, reflect: true },
934
1114
  disabled: { type: Boolean, reflect: true },
935
1115
  form: { type: String },
@@ -960,6 +1140,9 @@ function defineSpectreButton(tagName = "sp-button") {
960
1140
  var SpectreInputElement = class extends SpectreBaseElement {
961
1141
  constructor() {
962
1142
  super(...arguments);
1143
+ this.active = false;
1144
+ this.focused = false;
1145
+ this.hovered = false;
963
1146
  this.disabled = false;
964
1147
  this.fullWidth = false;
965
1148
  this.invalid = false;
@@ -971,6 +1154,10 @@ var SpectreInputElement = class extends SpectreBaseElement {
971
1154
  this.success = false;
972
1155
  this.type = "text";
973
1156
  this.value = "";
1157
+ this.errorMessage = void 0;
1158
+ this.helperText = void 0;
1159
+ this.label = void 0;
1160
+ this.generatedId = createUniqueId("sp-input");
974
1161
  }
975
1162
  get autocapitalize() {
976
1163
  return super.autocapitalize;
@@ -1045,12 +1232,30 @@ var SpectreInputElement = class extends SpectreBaseElement {
1045
1232
  }
1046
1233
  get inputClasses() {
1047
1234
  return getInputClasses({
1235
+ ...interactionStates(this),
1048
1236
  fullWidth: this.fullWidth ?? false,
1049
1237
  pill: this.pill ?? false,
1050
1238
  size: this.size,
1051
- 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"
1052
1240
  });
1053
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
+ }
1054
1259
  get nativeInput() {
1055
1260
  return this.querySelector("[data-sp-input-native]");
1056
1261
  }
@@ -1068,11 +1273,48 @@ var SpectreInputElement = class extends SpectreBaseElement {
1068
1273
  blur() {
1069
1274
  this.nativeInput?.blur();
1070
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.
1071
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() {
1072
1312
  return html`<input
1073
1313
  aria-busy="${this.loading ? "true" : "false"}"
1074
- aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
1075
- 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
+ )}"
1076
1318
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
1077
1319
  aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
1078
1320
  autocapitalize="${ifDefined(this.autocapitalize || void 0)}"
@@ -1085,7 +1327,7 @@ var SpectreInputElement = class extends SpectreBaseElement {
1085
1327
  form="${ifDefined(this.form || void 0)}"
1086
1328
  ?readonly="${this.readonly}"
1087
1329
  ?required="${this.required}"
1088
- id="${ifDefined(this.id || void 0)}"
1330
+ id="${ifDefined(this.hasFieldChrome ? this.inputId : this.id || void 0)}"
1089
1331
  inputmode="${ifDefined(this.inputmode || void 0)}"
1090
1332
  list="${ifDefined(this.list || void 0)}"
1091
1333
  max="${ifDefined(this.max || void 0)}"
@@ -1106,9 +1348,13 @@ var SpectreInputElement = class extends SpectreBaseElement {
1106
1348
  }
1107
1349
  };
1108
1350
  SpectreInputElement.properties = {
1351
+ ...interactionStateProperties,
1109
1352
  autocomplete: { type: String, reflect: true },
1110
1353
  disabled: { type: Boolean, reflect: true },
1111
1354
  enterkeyhint: { type: String, reflect: true },
1355
+ errorMessage: { attribute: "error-message", type: String },
1356
+ helperText: { attribute: "helper-text", type: String },
1357
+ label: { type: String },
1112
1358
  form: { type: String },
1113
1359
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
1114
1360
  inputmode: { type: String, reflect: true },
@@ -1143,6 +1389,7 @@ var DEFAULT_ROWS = 2;
1143
1389
  var SpectreTextareaElement = class extends SpectreBaseElement {
1144
1390
  constructor() {
1145
1391
  super(...arguments);
1392
+ this.focused = false;
1146
1393
  this.disabled = false;
1147
1394
  this.fullWidth = false;
1148
1395
  this.invalid = false;
@@ -1228,6 +1475,7 @@ var SpectreTextareaElement = class extends SpectreBaseElement {
1228
1475
  }
1229
1476
  get textareaClasses() {
1230
1477
  return getTextareaClasses({
1478
+ focused: this.focused ?? false,
1231
1479
  fullWidth: this.fullWidth ?? false,
1232
1480
  pill: this.pill ?? false,
1233
1481
  size: this.size,
@@ -1286,6 +1534,7 @@ var SpectreTextareaElement = class extends SpectreBaseElement {
1286
1534
  }
1287
1535
  };
1288
1536
  SpectreTextareaElement.properties = {
1537
+ focused: { type: Boolean, reflect: true },
1289
1538
  autocomplete: { type: String, reflect: true },
1290
1539
  disabled: { type: Boolean, reflect: true },
1291
1540
  enterkeyhint: { type: String, reflect: true },
@@ -1317,6 +1566,7 @@ function defineSpectreTextarea(tagName = "sp-textarea") {
1317
1566
  var SpectreSelectElement = class extends SpectreProjectableElement {
1318
1567
  constructor() {
1319
1568
  super(...arguments);
1569
+ this.focused = false;
1320
1570
  this.disabled = false;
1321
1571
  this.fullWidth = false;
1322
1572
  this.invalid = false;
@@ -1422,6 +1672,7 @@ var SpectreSelectElement = class extends SpectreProjectableElement {
1422
1672
  }
1423
1673
  get selectClasses() {
1424
1674
  return getSelectClasses({
1675
+ focused: this.focused ?? false,
1425
1676
  fullWidth: this.fullWidth ?? false,
1426
1677
  pill: this.pill ?? false,
1427
1678
  size: this.size,
@@ -1472,6 +1723,7 @@ var SpectreSelectElement = class extends SpectreProjectableElement {
1472
1723
  }
1473
1724
  };
1474
1725
  SpectreSelectElement.properties = {
1726
+ focused: { type: Boolean, reflect: true },
1475
1727
  autocomplete: { type: String, reflect: true },
1476
1728
  disabled: { type: Boolean, reflect: true },
1477
1729
  form: { type: String },
@@ -1982,8 +2234,16 @@ function defineSpectreFieldset(tagName = "sp-fieldset") {
1982
2234
  var SpectreBadgeElement = class extends SpectreProjectableElement {
1983
2235
  constructor() {
1984
2236
  super(...arguments);
2237
+ this.dot = false;
2238
+ this.interactive = false;
2239
+ this.active = false;
2240
+ this.focused = false;
2241
+ this.hovered = false;
2242
+ this.accentRail = void 0;
2243
+ this.accentRailColor = void 0;
1985
2244
  this.disabled = false;
1986
2245
  this.fullWidth = false;
2246
+ this.innerClass = void 0;
1987
2247
  this.loading = false;
1988
2248
  this.size = "md";
1989
2249
  this.variant = "primary";
@@ -2011,6 +2271,12 @@ var SpectreBadgeElement = class extends SpectreProjectableElement {
2011
2271
  return el.hasAttribute("data-sp-badge-native");
2012
2272
  }
2013
2273
  willUpdate(changedProperties) {
2274
+ if (changedProperties.has("accentRail") && this.accentRail != null && !isAccentEdge(this.accentRail)) {
2275
+ this.accentRail = void 0;
2276
+ }
2277
+ if (changedProperties.has("accentRailColor") && this.accentRailColor != null && !isAccentColor(this.accentRailColor)) {
2278
+ this.accentRailColor = void 0;
2279
+ }
2014
2280
  if (changedProperties.has("disabled") && this.disabled == null) {
2015
2281
  this.disabled = false;
2016
2282
  }
@@ -2028,13 +2294,24 @@ var SpectreBadgeElement = class extends SpectreProjectableElement {
2028
2294
  }
2029
2295
  }
2030
2296
  get badgeClasses() {
2031
- return getBadgeClasses({
2297
+ const recipeClasses = getBadgeClasses({
2298
+ dot: this.dot ?? false,
2299
+ interactive: this.interactive ?? false,
2300
+ ...interactionStates(this),
2301
+ ...this.accentRail !== void 0 && {
2302
+ accentRail: this.accentRail
2303
+ },
2304
+ ...this.accentRailColor !== void 0 && {
2305
+ accentRailColor: this.accentRailColor
2306
+ },
2032
2307
  disabled: this.isDisabled,
2033
2308
  fullWidth: this.fullWidth ?? false,
2034
2309
  loading: this.loading ?? false,
2035
2310
  size: this.size,
2036
2311
  variant: this.variant
2037
2312
  });
2313
+ const utilityClasses = sanitizeUtilityClasses(this.innerClass);
2314
+ return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
2038
2315
  }
2039
2316
  render() {
2040
2317
  return html`<span
@@ -2053,8 +2330,18 @@ var SpectreBadgeElement = class extends SpectreProjectableElement {
2053
2330
  }
2054
2331
  };
2055
2332
  SpectreBadgeElement.properties = {
2333
+ dot: { type: Boolean, reflect: true },
2334
+ interactive: { type: Boolean, reflect: true },
2335
+ ...interactionStateProperties,
2336
+ accentRail: { attribute: "accent-rail", type: String, reflect: true },
2337
+ accentRailColor: {
2338
+ attribute: "accent-rail-color",
2339
+ type: String,
2340
+ reflect: true
2341
+ },
2056
2342
  disabled: { type: Boolean, reflect: true },
2057
2343
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
2344
+ innerClass: { attribute: "inner-class", type: String },
2058
2345
  loading: { type: Boolean, reflect: true },
2059
2346
  size: { type: String, reflect: true },
2060
2347
  variant: { type: String, reflect: true }
@@ -2090,6 +2377,11 @@ var paddedConverter = {
2090
2377
  var SpectreCardElement = class extends SpectreProjectableElement {
2091
2378
  constructor() {
2092
2379
  super(...arguments);
2380
+ this.active = false;
2381
+ this.focused = false;
2382
+ this.hovered = false;
2383
+ this.accent = void 0;
2384
+ this.accentColor = void 0;
2093
2385
  this.disabled = false;
2094
2386
  this.fullHeight = false;
2095
2387
  this.innerClass = void 0;
@@ -2121,6 +2413,12 @@ var SpectreCardElement = class extends SpectreProjectableElement {
2121
2413
  return el.hasAttribute("data-sp-card-native");
2122
2414
  }
2123
2415
  willUpdate(changedProperties) {
2416
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
2417
+ this.accent = void 0;
2418
+ }
2419
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
2420
+ this.accentColor = void 0;
2421
+ }
2124
2422
  if (changedProperties.has("disabled") && this.disabled == null) {
2125
2423
  this.disabled = false;
2126
2424
  }
@@ -2142,6 +2440,13 @@ var SpectreCardElement = class extends SpectreProjectableElement {
2142
2440
  }
2143
2441
  get cardClasses() {
2144
2442
  const recipeClasses = getCardClasses({
2443
+ ...interactionStates(this),
2444
+ ...this.accent !== void 0 && {
2445
+ accent: this.accent
2446
+ },
2447
+ ...this.accentColor !== void 0 && {
2448
+ accentColor: this.accentColor
2449
+ },
2145
2450
  disabled: this.isDisabled,
2146
2451
  fullHeight: this.fullHeight ?? false,
2147
2452
  interactive: this.interactive ?? false,
@@ -2169,6 +2474,9 @@ var SpectreCardElement = class extends SpectreProjectableElement {
2169
2474
  }
2170
2475
  };
2171
2476
  SpectreCardElement.properties = {
2477
+ ...interactionStateProperties,
2478
+ accent: { type: String, reflect: true },
2479
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
2172
2480
  disabled: { type: Boolean, reflect: true },
2173
2481
  fullHeight: { attribute: "full-height", type: Boolean, reflect: true },
2174
2482
  innerClass: { attribute: "inner-class", type: String },
@@ -2188,6 +2496,9 @@ function defineSpectreCard(tagName = "sp-card") {
2188
2496
  var SpectreIconBoxElement = class extends SpectreProjectableElement {
2189
2497
  constructor() {
2190
2498
  super(...arguments);
2499
+ this.active = false;
2500
+ this.focused = false;
2501
+ this.hovered = false;
2191
2502
  this.disabled = false;
2192
2503
  this.fullWidth = false;
2193
2504
  this.interactive = false;
@@ -2243,6 +2554,7 @@ var SpectreIconBoxElement = class extends SpectreProjectableElement {
2243
2554
  }
2244
2555
  get iconBoxClasses() {
2245
2556
  return getIconBoxClasses({
2557
+ ...interactionStates(this),
2246
2558
  disabled: this.isDisabled,
2247
2559
  fullWidth: this.fullWidth ?? false,
2248
2560
  interactive: this.interactive ?? false,
@@ -2269,6 +2581,7 @@ var SpectreIconBoxElement = class extends SpectreProjectableElement {
2269
2581
  }
2270
2582
  };
2271
2583
  SpectreIconBoxElement.properties = {
2584
+ ...interactionStateProperties,
2272
2585
  disabled: { type: Boolean, reflect: true },
2273
2586
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
2274
2587
  interactive: { type: Boolean, reflect: true },
@@ -2288,6 +2601,12 @@ function defineSpectreIconBox(tagName = "sp-icon-box") {
2288
2601
  var SpectreRatingElement = class extends SpectreBaseElement {
2289
2602
  constructor() {
2290
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;
2291
2610
  this.disabled = false;
2292
2611
  this.loading = false;
2293
2612
  this.max = 5;
@@ -2327,6 +2646,10 @@ var SpectreRatingElement = class extends SpectreBaseElement {
2327
2646
  }
2328
2647
  get ratingClasses() {
2329
2648
  return getRatingClasses({
2649
+ fullWidth: this.fullWidth ?? false,
2650
+ pill: this.pill ?? false,
2651
+ interactive: this.interactive ?? false,
2652
+ ...interactionStates(this),
2330
2653
  disabled: this.isDisabled,
2331
2654
  loading: this.loading ?? false,
2332
2655
  size: this.size
@@ -2376,6 +2699,10 @@ var SpectreRatingElement = class extends SpectreBaseElement {
2376
2699
  }
2377
2700
  };
2378
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,
2379
2706
  disabled: { type: Boolean, reflect: true },
2380
2707
  label: { type: String, reflect: true },
2381
2708
  loading: { type: Boolean, reflect: true },
@@ -2391,14 +2718,115 @@ function defineSpectreRating(tagName = "sp-rating") {
2391
2718
  customElements.define(tagName, SpectreRatingElement);
2392
2719
  return SpectreRatingElement;
2393
2720
  }
2394
- 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 {
2395
2815
  constructor() {
2396
2816
  super(...arguments);
2817
+ this.active = false;
2818
+ this.focused = false;
2819
+ this.hovered = false;
2820
+ this.accent = void 0;
2821
+ this.accentColor = void 0;
2397
2822
  this.disabled = false;
2398
2823
  this.fullHeight = false;
2399
2824
  this.interactive = false;
2400
2825
  this.loading = false;
2401
2826
  this.variant = "elevated";
2827
+ this.projection = new ProjectionController(this, [
2828
+ "data-sp-testimonial-native"
2829
+ ]);
2402
2830
  }
2403
2831
  get id() {
2404
2832
  return super.id;
@@ -2412,17 +2840,13 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2412
2840
  set title(value) {
2413
2841
  super.title = value;
2414
2842
  }
2415
- getContentContainer() {
2416
- return this.querySelector("[data-sp-testimonial-native]");
2417
- }
2418
- isInternalNode(node) {
2419
- if (node.nodeType !== Node.ELEMENT_NODE) {
2420
- return false;
2421
- }
2422
- const el = node;
2423
- return el.hasAttribute("data-sp-testimonial-native");
2424
- }
2425
2843
  willUpdate(changedProperties) {
2844
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
2845
+ this.accent = void 0;
2846
+ }
2847
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
2848
+ this.accentColor = void 0;
2849
+ }
2426
2850
  if (changedProperties.has("disabled") && this.disabled == null) {
2427
2851
  this.disabled = false;
2428
2852
  }
@@ -2441,6 +2865,13 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2441
2865
  }
2442
2866
  get testimonialClasses() {
2443
2867
  return getTestimonialClasses({
2868
+ ...interactionStates(this),
2869
+ ...this.accent !== void 0 && {
2870
+ accent: this.accent
2871
+ },
2872
+ ...this.accentColor !== void 0 && {
2873
+ accentColor: this.accentColor
2874
+ },
2444
2875
  disabled: this.isDisabled,
2445
2876
  fullHeight: this.fullHeight ?? false,
2446
2877
  interactive: this.interactive ?? false,
@@ -2448,6 +2879,24 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2448
2879
  variant: this.variant
2449
2880
  });
2450
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
+ }
2451
2900
  render() {
2452
2901
  return html`<div
2453
2902
  aria-busy="${this.loading ? "true" : "false"}"
@@ -2460,11 +2909,17 @@ var SpectreTestimonialElement = class extends SpectreProjectableElement {
2460
2909
  role="${ifDefined(this.hasForwardedLabel ? "group" : void 0)}"
2461
2910
  title="${ifDefined(this.title || void 0)}"
2462
2911
  >
2463
- ${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()}
2464
2916
  </div>`;
2465
2917
  }
2466
2918
  };
2467
2919
  SpectreTestimonialElement.properties = {
2920
+ ...interactionStateProperties,
2921
+ accent: { type: String, reflect: true },
2922
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
2468
2923
  disabled: { type: Boolean, reflect: true },
2469
2924
  fullHeight: { attribute: "full-height", type: Boolean, reflect: true },
2470
2925
  interactive: { type: Boolean, reflect: true },
@@ -2479,15 +2934,46 @@ function defineSpectreTestimonial(tagName = "sp-testimonial") {
2479
2934
  customElements.define(tagName, SpectreTestimonialElement);
2480
2935
  return SpectreTestimonialElement;
2481
2936
  }
2482
- 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 {
2483
2960
  constructor() {
2484
2961
  super(...arguments);
2962
+ this.interactive = false;
2963
+ this.active = false;
2964
+ this.focused = false;
2965
+ this.hovered = false;
2966
+ this.dismissLabel = "Dismiss";
2485
2967
  this.dismissed = false;
2968
+ this.dismissible = false;
2486
2969
  this.disabled = false;
2487
2970
  this.fullWidth = false;
2488
2971
  this.loading = false;
2489
2972
  this.size = "md";
2490
2973
  this.variant = "info";
2974
+ this.projection = new ProjectionController(this, [
2975
+ "data-sp-alert-native"
2976
+ ]);
2491
2977
  }
2492
2978
  get id() {
2493
2979
  return super.id;
@@ -2501,20 +2987,16 @@ var SpectreAlertElement = class extends SpectreProjectableElement {
2501
2987
  set title(value) {
2502
2988
  super.title = value;
2503
2989
  }
2504
- getContentContainer() {
2505
- return this.querySelector("[data-sp-alert-native]");
2506
- }
2507
- isInternalNode(node) {
2508
- if (node.nodeType !== Node.ELEMENT_NODE) {
2509
- return false;
2510
- }
2511
- const el = node;
2512
- return el.hasAttribute("data-sp-alert-native");
2513
- }
2514
2990
  willUpdate(changedProperties) {
2991
+ if (changedProperties.has("dismissLabel") && !this.dismissLabel) {
2992
+ this.dismissLabel = "Dismiss";
2993
+ }
2515
2994
  if (changedProperties.has("dismissed") && this.dismissed == null) {
2516
2995
  this.dismissed = false;
2517
2996
  }
2997
+ if (changedProperties.has("dismissible") && this.dismissible == null) {
2998
+ this.dismissible = false;
2999
+ }
2518
3000
  if (changedProperties.has("disabled") && this.disabled == null) {
2519
3001
  this.disabled = false;
2520
3002
  }
@@ -2531,10 +3013,20 @@ var SpectreAlertElement = class extends SpectreProjectableElement {
2531
3013
  this.size = "md";
2532
3014
  }
2533
3015
  }
3016
+ dismiss() {
3017
+ if (this.dismissed) {
3018
+ return;
3019
+ }
3020
+ this.dismissed = true;
3021
+ this.dispatchEvent(new CustomEvent("sp-dismiss", { bubbles: true }));
3022
+ }
2534
3023
  get alertClasses() {
2535
3024
  return getAlertClasses({
3025
+ interactive: this.interactive ?? false,
3026
+ ...interactionStates(this),
2536
3027
  disabled: this.isDisabled,
2537
3028
  dismissed: this.dismissed ?? false,
3029
+ dismissible: this.dismissible ?? false,
2538
3030
  fullWidth: this.fullWidth ?? false,
2539
3031
  loading: this.loading ?? false,
2540
3032
  size: this.size,
@@ -2553,12 +3045,28 @@ var SpectreAlertElement = class extends SpectreProjectableElement {
2553
3045
  role="alert"
2554
3046
  title="${ifDefined(this.title || void 0)}"
2555
3047
  >
2556
- ${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}
2557
3061
  </div>`;
2558
3062
  }
2559
3063
  };
2560
3064
  SpectreAlertElement.properties = {
3065
+ interactive: { type: Boolean, reflect: true },
3066
+ ...interactionStateProperties,
3067
+ dismissLabel: { attribute: "dismiss-label", type: String },
2561
3068
  dismissed: { type: Boolean, reflect: true },
3069
+ dismissible: { type: Boolean, reflect: true },
2562
3070
  disabled: { type: Boolean, reflect: true },
2563
3071
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
2564
3072
  loading: { type: Boolean, reflect: true },
@@ -2576,6 +3084,9 @@ function defineSpectreAlert(tagName = "sp-alert") {
2576
3084
  var SpectreAvatarElement = class extends SpectreProjectableElement {
2577
3085
  constructor() {
2578
3086
  super(...arguments);
3087
+ this.active = false;
3088
+ this.focused = false;
3089
+ this.hovered = false;
2579
3090
  this.disabled = false;
2580
3091
  this.fullWidth = false;
2581
3092
  this.interactive = false;
@@ -2631,6 +3142,7 @@ var SpectreAvatarElement = class extends SpectreProjectableElement {
2631
3142
  }
2632
3143
  get avatarClasses() {
2633
3144
  return getAvatarClasses({
3145
+ ...interactionStates(this),
2634
3146
  disabled: this.isDisabled,
2635
3147
  fullWidth: this.fullWidth ?? false,
2636
3148
  interactive: this.interactive ?? false,
@@ -2657,6 +3169,7 @@ var SpectreAvatarElement = class extends SpectreProjectableElement {
2657
3169
  }
2658
3170
  };
2659
3171
  SpectreAvatarElement.properties = {
3172
+ ...interactionStateProperties,
2660
3173
  disabled: { type: Boolean, reflect: true },
2661
3174
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
2662
3175
  interactive: { type: Boolean, reflect: true },
@@ -2748,6 +3261,9 @@ function defineSpectreSpinner(tagName = "sp-spinner") {
2748
3261
  var SpectreTagElement = class extends SpectreProjectableElement {
2749
3262
  constructor() {
2750
3263
  super(...arguments);
3264
+ this.active = false;
3265
+ this.focused = false;
3266
+ this.hovered = false;
2751
3267
  this.dismissible = false;
2752
3268
  this.disabled = false;
2753
3269
  this.fullWidth = false;
@@ -2807,6 +3323,7 @@ var SpectreTagElement = class extends SpectreProjectableElement {
2807
3323
  }
2808
3324
  get tagClasses() {
2809
3325
  return getTagClasses({
3326
+ ...interactionStates(this),
2810
3327
  disabled: this.isDisabled,
2811
3328
  dismissible: this.dismissible ?? false,
2812
3329
  fullWidth: this.fullWidth ?? false,
@@ -2834,6 +3351,7 @@ var SpectreTagElement = class extends SpectreProjectableElement {
2834
3351
  }
2835
3352
  };
2836
3353
  SpectreTagElement.properties = {
3354
+ ...interactionStateProperties,
2837
3355
  dismissible: { type: Boolean, reflect: true },
2838
3356
  disabled: { type: Boolean, reflect: true },
2839
3357
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
@@ -2851,14 +3369,22 @@ function defineSpectreTag(tagName = "sp-tag") {
2851
3369
  customElements.define(tagName, SpectreTagElement);
2852
3370
  return SpectreTagElement;
2853
3371
  }
2854
- var SpectrePricingCardElement = class extends SpectreProjectableElement {
3372
+ var SpectrePricingCardElement = class extends SpectreBaseElement {
2855
3373
  constructor() {
2856
3374
  super(...arguments);
3375
+ this.active = false;
3376
+ this.focused = false;
3377
+ this.hovered = false;
3378
+ this.accent = void 0;
3379
+ this.accentColor = void 0;
2857
3380
  this.disabled = false;
2858
3381
  this.featured = false;
2859
3382
  this.fullHeight = false;
2860
3383
  this.interactive = false;
2861
3384
  this.loading = false;
3385
+ this.projection = new ProjectionController(this, [
3386
+ "data-sp-pricing-card-native"
3387
+ ]);
2862
3388
  }
2863
3389
  get id() {
2864
3390
  return super.id;
@@ -2872,17 +3398,13 @@ var SpectrePricingCardElement = class extends SpectreProjectableElement {
2872
3398
  set title(value) {
2873
3399
  super.title = value;
2874
3400
  }
2875
- getContentContainer() {
2876
- return this.querySelector("[data-sp-pricing-card-native]");
2877
- }
2878
- isInternalNode(node) {
2879
- if (node.nodeType !== Node.ELEMENT_NODE) {
2880
- return false;
2881
- }
2882
- const el = node;
2883
- return el.hasAttribute("data-sp-pricing-card-native");
2884
- }
2885
3401
  willUpdate(changedProperties) {
3402
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
3403
+ this.accent = void 0;
3404
+ }
3405
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
3406
+ this.accentColor = void 0;
3407
+ }
2886
3408
  if (changedProperties.has("disabled") && this.disabled == null) {
2887
3409
  this.disabled = false;
2888
3410
  }
@@ -2901,6 +3423,13 @@ var SpectrePricingCardElement = class extends SpectreProjectableElement {
2901
3423
  }
2902
3424
  get pricingCardClasses() {
2903
3425
  return getPricingCardClasses({
3426
+ ...interactionStates(this),
3427
+ ...this.accent !== void 0 && {
3428
+ accent: this.accent
3429
+ },
3430
+ ...this.accentColor !== void 0 && {
3431
+ accentColor: this.accentColor
3432
+ },
2904
3433
  disabled: this.isDisabled,
2905
3434
  featured: this.featured ?? false,
2906
3435
  fullHeight: this.fullHeight ?? false,
@@ -2920,11 +3449,26 @@ var SpectrePricingCardElement = class extends SpectreProjectableElement {
2920
3449
  role="${ifDefined(this.hasForwardedLabel ? "group" : void 0)}"
2921
3450
  title="${ifDefined(this.title || void 0)}"
2922
3451
  >
2923
- ${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")}
2924
3465
  </div>`;
2925
3466
  }
2926
3467
  };
2927
3468
  SpectrePricingCardElement.properties = {
3469
+ ...interactionStateProperties,
3470
+ accent: { type: String, reflect: true },
3471
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
2928
3472
  disabled: { type: Boolean, reflect: true },
2929
3473
  featured: { type: Boolean, reflect: true },
2930
3474
  fullHeight: { attribute: "full-height", type: Boolean, reflect: true },
@@ -2944,6 +3488,7 @@ var SpectreContainerElement = class extends SpectreProjectableElement {
2944
3488
  super(...arguments);
2945
3489
  this.innerClass = void 0;
2946
3490
  this.maxWidth = void 0;
3491
+ this.padding = void 0;
2947
3492
  }
2948
3493
  get id() {
2949
3494
  return super.id;
@@ -2958,9 +3503,9 @@ var SpectreContainerElement = class extends SpectreProjectableElement {
2958
3503
  super.title = value;
2959
3504
  }
2960
3505
  connectedCallback() {
2961
- var _a;
3506
+ var _a5;
2962
3507
  super.connectedCallback();
2963
- (_a = this.style).display || (_a.display = "block");
3508
+ (_a5 = this.style).display || (_a5.display = "block");
2964
3509
  }
2965
3510
  getContentContainer() {
2966
3511
  return this.querySelector("[data-sp-container-native]");
@@ -2976,11 +3521,19 @@ var SpectreContainerElement = class extends SpectreProjectableElement {
2976
3521
  if (changedProperties.has("maxWidth") && this.maxWidth != null && !isContainerMaxWidth(this.maxWidth)) {
2977
3522
  this.maxWidth = void 0;
2978
3523
  }
3524
+ if (changedProperties.has("padding") && this.padding != null && !isSpacingStep(this.padding)) {
3525
+ this.padding = void 0;
3526
+ }
2979
3527
  }
2980
3528
  get containerClasses() {
2981
- const recipeClasses = getContainerClasses(
2982
- this.maxWidth != null ? { maxWidth: this.maxWidth } : {}
2983
- );
3529
+ const recipeClasses = getContainerClasses({
3530
+ ...this.maxWidth != null && {
3531
+ maxWidth: this.maxWidth
3532
+ },
3533
+ ...this.padding != null && {
3534
+ padding: this.padding
3535
+ }
3536
+ });
2984
3537
  const utilityClasses = sanitizeUtilityClasses(this.innerClass);
2985
3538
  return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
2986
3539
  }
@@ -3000,7 +3553,8 @@ var SpectreContainerElement = class extends SpectreProjectableElement {
3000
3553
  };
3001
3554
  SpectreContainerElement.properties = {
3002
3555
  innerClass: { attribute: "inner-class", type: String },
3003
- maxWidth: { attribute: "max-width", type: String, reflect: true }
3556
+ maxWidth: { attribute: "max-width", type: String, reflect: true },
3557
+ padding: { type: String, reflect: true }
3004
3558
  };
3005
3559
  function defineSpectreContainer(tagName = "sp-container") {
3006
3560
  const existingElement = customElements.get(tagName);
@@ -3077,7 +3631,7 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3077
3631
  super.removeAttribute(qualifiedName);
3078
3632
  }
3079
3633
  connectedCallback() {
3080
- var _a;
3634
+ var _a5;
3081
3635
  const initialRole = HTMLElement.prototype.getAttribute.call(this, "role");
3082
3636
  if (initialRole !== null) {
3083
3637
  HTMLElement.prototype.removeAttribute.call(this, "role");
@@ -3086,7 +3640,7 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3086
3640
  if (initialRole !== null) {
3087
3641
  this.role = initialRole;
3088
3642
  }
3089
- (_a = this.style).display || (_a.display = "block");
3643
+ (_a5 = this.style).display || (_a5.display = "block");
3090
3644
  }
3091
3645
  getContentContainer() {
3092
3646
  return this.querySelector("[data-sp-grid-native]");
@@ -3121,6 +3675,9 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3121
3675
  if (changedProperties.has("offset") && this.offset !== void 0 && !isGridOffset(this.offset) && !isGridOffsetOptions(this.offset)) {
3122
3676
  this.offset = void 0;
3123
3677
  }
3678
+ if (changedProperties.has("colStart") && this.colStart !== void 0 && !isGridColStart(this.colStart) && !isGridColStartOptions(this.colStart)) {
3679
+ this.colStart = void 0;
3680
+ }
3124
3681
  if (changedProperties.has("rowSpan") && this.rowSpan !== void 0 && !isGridSpan(this.rowSpan) && !isGridSpanOptions(this.rowSpan)) {
3125
3682
  this.rowSpan = void 0;
3126
3683
  }
@@ -3155,6 +3712,9 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3155
3712
  ...this.offset !== void 0 && {
3156
3713
  offset: this.offset
3157
3714
  },
3715
+ ...this.colStart !== void 0 && {
3716
+ colStart: this.colStart
3717
+ },
3158
3718
  ...this.rowSpan !== void 0 && {
3159
3719
  rowSpan: this.rowSpan
3160
3720
  },
@@ -3194,6 +3754,7 @@ var SpectreGridElement = class extends SpectreProjectableElement {
3194
3754
  };
3195
3755
  SpectreGridElement.properties = {
3196
3756
  align: { type: String, reflect: true },
3757
+ colStart: { attribute: "col-start", type: Object },
3197
3758
  columns: { type: Number, reflect: true },
3198
3759
  columnGap: { attribute: "column-gap", type: String, reflect: true },
3199
3760
  explicitTemplate: { attribute: "explicit-template", type: Object },
@@ -3219,7 +3780,9 @@ function defineSpectreGrid(tagName = "sp-grid") {
3219
3780
  var SpectreSectionElement = class extends SpectreProjectableElement {
3220
3781
  constructor() {
3221
3782
  super(...arguments);
3783
+ this.gap = void 0;
3222
3784
  this.innerClass = void 0;
3785
+ this.spacing = void 0;
3223
3786
  }
3224
3787
  get id() {
3225
3788
  return super.id;
@@ -3234,9 +3797,9 @@ var SpectreSectionElement = class extends SpectreProjectableElement {
3234
3797
  super.title = value;
3235
3798
  }
3236
3799
  connectedCallback() {
3237
- var _a;
3800
+ var _a5;
3238
3801
  super.connectedCallback();
3239
- (_a = this.style).display || (_a.display = "block");
3802
+ (_a5 = this.style).display || (_a5.display = "block");
3240
3803
  }
3241
3804
  getContentContainer() {
3242
3805
  return this.querySelector("[data-sp-section-native]");
@@ -3248,8 +3811,21 @@ var SpectreSectionElement = class extends SpectreProjectableElement {
3248
3811
  const el = node;
3249
3812
  return el.hasAttribute("data-sp-section-native");
3250
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
+ }
3251
3822
  get sectionClasses() {
3252
- const recipeClasses = getSectionClasses({});
3823
+ const recipeClasses = getSectionClasses({
3824
+ ...this.gap != null && { gap: this.gap },
3825
+ ...this.spacing != null && {
3826
+ spacing: this.spacing
3827
+ }
3828
+ });
3253
3829
  const utilityClasses = sanitizeUtilityClasses(this.innerClass);
3254
3830
  return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
3255
3831
  }
@@ -3268,7 +3844,9 @@ var SpectreSectionElement = class extends SpectreProjectableElement {
3268
3844
  }
3269
3845
  };
3270
3846
  SpectreSectionElement.properties = {
3271
- 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 }
3272
3850
  };
3273
3851
  function defineSpectreSection(tagName = "sp-section") {
3274
3852
  const existingElement = customElements.get(tagName);
@@ -3300,9 +3878,9 @@ var SpectreStackElement = class extends SpectreProjectableElement {
3300
3878
  super.title = value;
3301
3879
  }
3302
3880
  connectedCallback() {
3303
- var _a;
3881
+ var _a5;
3304
3882
  super.connectedCallback();
3305
- (_a = this.style).display || (_a.display = "block");
3883
+ (_a5 = this.style).display || (_a5.display = "block");
3306
3884
  }
3307
3885
  getContentContainer() {
3308
3886
  return this.querySelector("[data-sp-stack-native]");
@@ -3367,14 +3945,33 @@ function defineSpectreStack(tagName = "sp-stack") {
3367
3945
  customElements.define(tagName, SpectreStackElement);
3368
3946
  return SpectreStackElement;
3369
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
+ }
3370
3964
  var SpectreDropdownElement = class extends SpectreBaseElement {
3371
3965
  constructor() {
3372
3966
  super(...arguments);
3967
+ this.accent = void 0;
3968
+ this.accentColor = void 0;
3373
3969
  this.fullWidth = false;
3374
3970
  this.mega = false;
3375
3971
  this.open = false;
3376
3972
  this.placement = "bottom-start";
3377
3973
  this.triggerLabel = "Toggle menu";
3974
+ this.viewport = false;
3378
3975
  this.triggerContent = [];
3379
3976
  this.menuContent = [];
3380
3977
  this.handleDocumentClick = (event) => {
@@ -3479,6 +4076,12 @@ var SpectreDropdownElement = class extends SpectreBaseElement {
3479
4076
  this.contentObserver = void 0;
3480
4077
  }
3481
4078
  willUpdate(changedProperties) {
4079
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
4080
+ this.accent = void 0;
4081
+ }
4082
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
4083
+ this.accentColor = void 0;
4084
+ }
3482
4085
  if (changedProperties.has("fullWidth") && this.fullWidth == null) {
3483
4086
  this.fullWidth = false;
3484
4087
  }
@@ -3494,6 +4097,17 @@ var SpectreDropdownElement = class extends SpectreBaseElement {
3494
4097
  if (changedProperties.has("triggerLabel") && !this.triggerLabel) {
3495
4098
  this.triggerLabel = "Toggle menu";
3496
4099
  }
4100
+ if (changedProperties.has("viewport") && this.viewport == null) {
4101
+ this.viewport = false;
4102
+ }
4103
+ }
4104
+ updated(changedProperties) {
4105
+ super.updated(changedProperties);
4106
+ applyPartClasses(childElements(this.menuContent), {
4107
+ divider: getDropdownDividerClasses(),
4108
+ header: getDropdownHeaderClasses(),
4109
+ item: getDropdownItemClasses()
4110
+ });
3497
4111
  }
3498
4112
  get triggerElement() {
3499
4113
  return this.querySelector("[data-sp-dropdown-trigger]");
@@ -3522,14 +4136,22 @@ var SpectreDropdownElement = class extends SpectreBaseElement {
3522
4136
  get dropdownClasses() {
3523
4137
  return getDropdownClasses({
3524
4138
  fullWidth: this.fullWidth ?? false,
3525
- mega: this.mega ?? false
4139
+ mega: this.mega ?? false,
4140
+ viewport: this.viewport ?? false
3526
4141
  });
3527
4142
  }
3528
4143
  get menuClasses() {
3529
4144
  return getDropdownMenuClasses({
4145
+ ...this.accent !== void 0 && {
4146
+ accent: this.accent
4147
+ },
4148
+ ...this.accentColor !== void 0 && {
4149
+ accentColor: this.accentColor
4150
+ },
3530
4151
  mega: this.mega ?? false,
3531
4152
  open: this.open ?? false,
3532
- placement: this.placement
4153
+ placement: this.placement,
4154
+ viewport: this.viewport ?? false
3533
4155
  });
3534
4156
  }
3535
4157
  render() {
@@ -3557,11 +4179,14 @@ var SpectreDropdownElement = class extends SpectreBaseElement {
3557
4179
  }
3558
4180
  };
3559
4181
  SpectreDropdownElement.properties = {
4182
+ accent: { type: String, reflect: true },
4183
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
3560
4184
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
3561
4185
  mega: { type: Boolean, reflect: true },
3562
4186
  open: { type: Boolean, reflect: true },
3563
4187
  placement: { type: String, reflect: true },
3564
- triggerLabel: { attribute: "trigger-label", type: String }
4188
+ triggerLabel: { attribute: "trigger-label", type: String },
4189
+ viewport: { type: Boolean, reflect: true }
3565
4190
  };
3566
4191
  function defineSpectreDropdown(tagName = "sp-dropdown") {
3567
4192
  const existingElement = customElements.get(tagName);
@@ -3574,6 +4199,8 @@ function defineSpectreDropdown(tagName = "sp-dropdown") {
3574
4199
  var SpectreFooterElement = class extends SpectreProjectableElement {
3575
4200
  constructor() {
3576
4201
  super(...arguments);
4202
+ this.accent = void 0;
4203
+ this.accentColor = void 0;
3577
4204
  this.bordered = false;
3578
4205
  this.fullWidth = false;
3579
4206
  this.innerClass = void 0;
@@ -3591,9 +4218,9 @@ var SpectreFooterElement = class extends SpectreProjectableElement {
3591
4218
  super.title = value;
3592
4219
  }
3593
4220
  connectedCallback() {
3594
- var _a;
4221
+ var _a5;
3595
4222
  super.connectedCallback();
3596
- (_a = this.style).display || (_a.display = "block");
4223
+ (_a5 = this.style).display || (_a5.display = "block");
3597
4224
  }
3598
4225
  getContentContainer() {
3599
4226
  return this.querySelector("[data-sp-footer-native]");
@@ -3606,6 +4233,12 @@ var SpectreFooterElement = class extends SpectreProjectableElement {
3606
4233
  return el.hasAttribute("data-sp-footer-native");
3607
4234
  }
3608
4235
  willUpdate(changedProperties) {
4236
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
4237
+ this.accent = void 0;
4238
+ }
4239
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
4240
+ this.accentColor = void 0;
4241
+ }
3609
4242
  if (changedProperties.has("bordered") && this.bordered == null) {
3610
4243
  this.bordered = false;
3611
4244
  }
@@ -3615,12 +4248,34 @@ var SpectreFooterElement = class extends SpectreProjectableElement {
3615
4248
  }
3616
4249
  get footerClasses() {
3617
4250
  const recipeClasses = getFooterClasses({
4251
+ ...this.accent !== void 0 && {
4252
+ accent: this.accent
4253
+ },
4254
+ ...this.accentColor !== void 0 && {
4255
+ accentColor: this.accentColor
4256
+ },
3618
4257
  bordered: this.bordered ?? false,
3619
4258
  fullWidth: this.fullWidth ?? false
3620
4259
  });
3621
4260
  const utilityClasses = sanitizeUtilityClasses(this.innerClass);
3622
4261
  return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
3623
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
+ }
3624
4279
  render() {
3625
4280
  return html`<footer
3626
4281
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
@@ -3634,6 +4289,8 @@ var SpectreFooterElement = class extends SpectreProjectableElement {
3634
4289
  }
3635
4290
  };
3636
4291
  SpectreFooterElement.properties = {
4292
+ accent: { type: String, reflect: true },
4293
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
3637
4294
  bordered: { type: Boolean, reflect: true },
3638
4295
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
3639
4296
  innerClass: { attribute: "inner-class", type: String }
@@ -3649,6 +4306,8 @@ function defineSpectreFooter(tagName = "sp-footer") {
3649
4306
  var SpectreFooterChipElement = class extends SpectreProjectableElement {
3650
4307
  constructor() {
3651
4308
  super(...arguments);
4309
+ this.focused = false;
4310
+ this.hovered = false;
3652
4311
  this.disabled = false;
3653
4312
  }
3654
4313
  get id() {
@@ -3679,7 +4338,10 @@ var SpectreFooterChipElement = class extends SpectreProjectableElement {
3679
4338
  }
3680
4339
  }
3681
4340
  get footerChipClasses() {
3682
- return getFooterChipClasses({ disabled: this.disabled ?? false });
4341
+ return getFooterChipClasses({
4342
+ ...hoverFocusStates(this),
4343
+ disabled: this.disabled ?? false
4344
+ });
3683
4345
  }
3684
4346
  render() {
3685
4347
  return html`<span
@@ -3695,6 +4357,7 @@ var SpectreFooterChipElement = class extends SpectreProjectableElement {
3695
4357
  }
3696
4358
  };
3697
4359
  SpectreFooterChipElement.properties = {
4360
+ ...hoverFocusStateProperties,
3698
4361
  disabled: { type: Boolean, reflect: true }
3699
4362
  };
3700
4363
  function defineSpectreFooterChip(tagName = "sp-footer-chip") {
@@ -3708,6 +4371,8 @@ function defineSpectreFooterChip(tagName = "sp-footer-chip") {
3708
4371
  var SpectreFooterLinkElement = class extends SpectreProjectableElement {
3709
4372
  constructor() {
3710
4373
  super(...arguments);
4374
+ this.focused = false;
4375
+ this.hovered = false;
3711
4376
  this.active = false;
3712
4377
  this.disabled = false;
3713
4378
  this.href = void 0;
@@ -3744,6 +4409,7 @@ var SpectreFooterLinkElement = class extends SpectreProjectableElement {
3744
4409
  }
3745
4410
  get footerLinkClasses() {
3746
4411
  return getFooterLinkClasses({
4412
+ ...hoverFocusStates(this),
3747
4413
  active: this.active ?? false,
3748
4414
  disabled: this.disabled ?? false
3749
4415
  });
@@ -3765,6 +4431,7 @@ var SpectreFooterLinkElement = class extends SpectreProjectableElement {
3765
4431
  }
3766
4432
  };
3767
4433
  SpectreFooterLinkElement.properties = {
4434
+ ...hoverFocusStateProperties,
3768
4435
  active: { type: Boolean, reflect: true },
3769
4436
  disabled: { type: Boolean, reflect: true },
3770
4437
  href: { type: String }
@@ -3777,6 +4444,8 @@ function defineSpectreFooterLink(tagName = "sp-footer-link") {
3777
4444
  customElements.define(tagName, SpectreFooterLinkElement);
3778
4445
  return SpectreFooterLinkElement;
3779
4446
  }
4447
+
4448
+ // src/utils/focus.ts
3780
4449
  var FOCUSABLE_SELECTOR = [
3781
4450
  "a[href]",
3782
4451
  "button:not([disabled])",
@@ -3785,9 +4454,34 @@ var FOCUSABLE_SELECTOR = [
3785
4454
  "textarea:not([disabled])",
3786
4455
  '[tabindex]:not([tabindex="-1"])'
3787
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
+ }
3788
4480
  var SpectreModalElement = class extends SpectreProjectableElement {
3789
4481
  constructor() {
3790
4482
  super(...arguments);
4483
+ this.accent = void 0;
4484
+ this.accentColor = void 0;
3791
4485
  this.fullWidth = false;
3792
4486
  this.open = false;
3793
4487
  this.previouslyFocusedElement = null;
@@ -3800,7 +4494,7 @@ var SpectreModalElement = class extends SpectreProjectableElement {
3800
4494
  return;
3801
4495
  }
3802
4496
  if (event.key === "Tab") {
3803
- this.trapFocus(event);
4497
+ trapFocus(event, this.modalElement);
3804
4498
  }
3805
4499
  };
3806
4500
  }
@@ -3827,6 +4521,12 @@ var SpectreModalElement = class extends SpectreProjectableElement {
3827
4521
  return el.hasAttribute("data-sp-modal-native") || el.hasAttribute("data-sp-modal-overlay");
3828
4522
  }
3829
4523
  willUpdate(changedProperties) {
4524
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
4525
+ this.accent = void 0;
4526
+ }
4527
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
4528
+ this.accentColor = void 0;
4529
+ }
3830
4530
  if (changedProperties.has("fullWidth") && this.fullWidth == null) {
3831
4531
  this.fullWidth = false;
3832
4532
  }
@@ -3858,34 +4558,10 @@ var SpectreModalElement = class extends SpectreProjectableElement {
3858
4558
  get modalElement() {
3859
4559
  return this.querySelector("[data-sp-modal-native]");
3860
4560
  }
3861
- get focusableElements() {
3862
- const modal = this.modalElement;
3863
- if (!modal) {
3864
- return [];
3865
- }
3866
- return Array.from(modal.querySelectorAll(FOCUSABLE_SELECTOR));
3867
- }
3868
4561
  focusFirstElement() {
3869
- const [first] = this.focusableElements;
4562
+ const [first] = getFocusableElements(this.modalElement);
3870
4563
  (first ?? this.modalElement)?.focus();
3871
4564
  }
3872
- trapFocus(event) {
3873
- const focusable = this.focusableElements;
3874
- if (focusable.length === 0) {
3875
- event.preventDefault();
3876
- return;
3877
- }
3878
- const first = focusable[0];
3879
- const last = focusable[focusable.length - 1];
3880
- const active = document.activeElement;
3881
- if (event.shiftKey && active === first) {
3882
- event.preventDefault();
3883
- last?.focus();
3884
- } else if (!event.shiftKey && active === last) {
3885
- event.preventDefault();
3886
- first?.focus();
3887
- }
3888
- }
3889
4565
  close() {
3890
4566
  if (!this.open) {
3891
4567
  return;
@@ -3898,6 +4574,12 @@ var SpectreModalElement = class extends SpectreProjectableElement {
3898
4574
  }
3899
4575
  get modalClasses() {
3900
4576
  return getModalClasses({
4577
+ ...this.accent !== void 0 && {
4578
+ accent: this.accent
4579
+ },
4580
+ ...this.accentColor !== void 0 && {
4581
+ accentColor: this.accentColor
4582
+ },
3901
4583
  open: this.open ?? false,
3902
4584
  fullWidth: this.fullWidth ?? false
3903
4585
  });
@@ -3933,6 +4615,8 @@ var SpectreModalElement = class extends SpectreProjectableElement {
3933
4615
  }
3934
4616
  };
3935
4617
  SpectreModalElement.properties = {
4618
+ accent: { type: String, reflect: true },
4619
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
3936
4620
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
3937
4621
  open: { type: Boolean, reflect: true }
3938
4622
  };
@@ -3947,6 +4631,8 @@ function defineSpectreModal(tagName = "sp-modal") {
3947
4631
  var SpectreNavElement = class extends SpectreProjectableElement {
3948
4632
  constructor() {
3949
4633
  super(...arguments);
4634
+ this.accent = void 0;
4635
+ this.accentColor = void 0;
3950
4636
  this.align = void 0;
3951
4637
  this.bordered = false;
3952
4638
  this.fullWidth = false;
@@ -3966,9 +4652,9 @@ var SpectreNavElement = class extends SpectreProjectableElement {
3966
4652
  super.title = value;
3967
4653
  }
3968
4654
  connectedCallback() {
3969
- var _a;
4655
+ var _a5;
3970
4656
  super.connectedCallback();
3971
- (_a = this.style).display || (_a.display = "block");
4657
+ (_a5 = this.style).display || (_a5.display = "block");
3972
4658
  }
3973
4659
  getContentContainer() {
3974
4660
  return this.querySelector("[data-sp-nav-native]");
@@ -3981,6 +4667,12 @@ var SpectreNavElement = class extends SpectreProjectableElement {
3981
4667
  return el.hasAttribute("data-sp-nav-native");
3982
4668
  }
3983
4669
  willUpdate(changedProperties) {
4670
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
4671
+ this.accent = void 0;
4672
+ }
4673
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
4674
+ this.accentColor = void 0;
4675
+ }
3984
4676
  if (changedProperties.has("bordered") && this.bordered == null) {
3985
4677
  this.bordered = false;
3986
4678
  }
@@ -3996,6 +4688,12 @@ var SpectreNavElement = class extends SpectreProjectableElement {
3996
4688
  }
3997
4689
  get navClasses() {
3998
4690
  const recipeClasses = getNavClasses({
4691
+ ...this.accent !== void 0 && {
4692
+ accent: this.accent
4693
+ },
4694
+ ...this.accentColor !== void 0 && {
4695
+ accentColor: this.accentColor
4696
+ },
3999
4697
  bordered: this.bordered ?? false,
4000
4698
  fullWidth: this.fullWidth ?? false,
4001
4699
  sticky: this.sticky ?? false,
@@ -4004,6 +4702,12 @@ var SpectreNavElement = class extends SpectreProjectableElement {
4004
4702
  const utilityClasses = sanitizeUtilityClasses(this.innerClass);
4005
4703
  return utilityClasses ? `${recipeClasses} ${utilityClasses}` : recipeClasses;
4006
4704
  }
4705
+ updated(changedProperties) {
4706
+ super.updated(changedProperties);
4707
+ applyPartClasses(childElements(this.projectedContent), {
4708
+ links: getNavLinksClasses()
4709
+ });
4710
+ }
4007
4711
  render() {
4008
4712
  return html`<nav
4009
4713
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
@@ -4017,6 +4721,8 @@ var SpectreNavElement = class extends SpectreProjectableElement {
4017
4721
  }
4018
4722
  };
4019
4723
  SpectreNavElement.properties = {
4724
+ accent: { type: String, reflect: true },
4725
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
4020
4726
  align: { type: String, reflect: true },
4021
4727
  bordered: { type: Boolean, reflect: true },
4022
4728
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
@@ -4034,12 +4740,20 @@ function defineSpectreNav(tagName = "sp-nav") {
4034
4740
  var SpectreNavItemElement = class extends SpectreBaseElement {
4035
4741
  constructor() {
4036
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;
4037
4749
  this.dropdown = false;
4750
+ this.fullWidth = false;
4038
4751
  this.href = void 0;
4039
4752
  this.label = void 0;
4040
4753
  this.mega = false;
4041
4754
  this.open = false;
4042
4755
  this.placement = "bottom-start";
4756
+ this.viewport = false;
4043
4757
  this.triggerContent = [];
4044
4758
  this.menuContent = [];
4045
4759
  this.handleDocumentClick = (event) => {
@@ -4137,6 +4851,24 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4137
4851
  this.contentObserver = void 0;
4138
4852
  }
4139
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
+ }
4140
4872
  if (changedProperties.has("dropdown") && this.dropdown == null) {
4141
4873
  this.dropdown = false;
4142
4874
  }
@@ -4150,6 +4882,14 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4150
4882
  this.placement = "bottom-start";
4151
4883
  }
4152
4884
  }
4885
+ updated(changedProperties) {
4886
+ super.updated(changedProperties);
4887
+ applyPartClasses(childElements(this.menuContent), {
4888
+ divider: getDropdownDividerClasses(),
4889
+ header: getDropdownHeaderClasses(),
4890
+ item: getDropdownItemClasses()
4891
+ });
4892
+ }
4153
4893
  get triggerElement() {
4154
4894
  return this.querySelector("[data-sp-nav-item-trigger]");
4155
4895
  }
@@ -4175,23 +4915,40 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4175
4915
  this.dispatchEvent(new CustomEvent("sp-close", { bubbles: true }));
4176
4916
  }
4177
4917
  get wrapperClasses() {
4178
- 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
+ });
4179
4923
  }
4180
4924
  get menuClasses() {
4181
4925
  return getDropdownMenuClasses({
4926
+ ...this.accent !== void 0 && {
4927
+ accent: this.accent
4928
+ },
4929
+ ...this.accentColor !== void 0 && {
4930
+ accentColor: this.accentColor
4931
+ },
4182
4932
  mega: this.mega ?? false,
4933
+ viewport: this.viewport ?? false,
4183
4934
  open: this.open ?? false,
4184
4935
  placement: this.placement
4185
4936
  });
4186
4937
  }
4187
4938
  get navLinkClasses() {
4188
- return getNavLinkClasses();
4939
+ return getNavLinkClasses({
4940
+ ...hoverFocusStates(this),
4941
+ active: this.active ?? false,
4942
+ disabled: this.disabled ?? false
4943
+ });
4189
4944
  }
4190
4945
  renderLink() {
4191
4946
  return html`<a
4947
+ aria-current="${ifDefined(this.active ? "page" : void 0)}"
4948
+ aria-disabled="${ifDefined(this.disabled ? "true" : void 0)}"
4192
4949
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
4193
4950
  class="${this.navLinkClasses}"
4194
- href="${ifDefined(this.href)}"
4951
+ href="${ifDefined(this.disabled ? void 0 : this.href)}"
4195
4952
  id="${ifDefined(this.id || void 0)}"
4196
4953
  title="${ifDefined(this.title || void 0)}"
4197
4954
  >${this.hasMenuContent ? this.menuContent : this.label}</a
@@ -4209,6 +4966,7 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4209
4966
  aria-label="${ifDefined(this.forwardedAriaLabel ?? this.label)}"
4210
4967
  class="${this.navLinkClasses}"
4211
4968
  data-sp-nav-item-trigger
4969
+ ?disabled="${this.disabled ?? false}"
4212
4970
  type="button"
4213
4971
  @click="${() => this.toggle()}"
4214
4972
  >
@@ -4224,12 +4982,19 @@ var SpectreNavItemElement = class extends SpectreBaseElement {
4224
4982
  }
4225
4983
  };
4226
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 },
4227
4990
  dropdown: { type: Boolean, reflect: true },
4991
+ fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
4228
4992
  href: { type: String },
4229
4993
  label: { type: String },
4230
4994
  mega: { type: Boolean, reflect: true },
4231
4995
  open: { type: Boolean, reflect: true },
4232
- placement: { type: String, reflect: true }
4996
+ placement: { type: String, reflect: true },
4997
+ viewport: { type: Boolean, reflect: true }
4233
4998
  };
4234
4999
  function defineSpectreNavItem(tagName = "sp-nav-item") {
4235
5000
  const existingElement = customElements.get(tagName);
@@ -4332,6 +5097,20 @@ var SpectreSidebarElement = class extends SpectreProjectableElement {
4332
5097
  get sidebarClasses() {
4333
5098
  return getSidebarClasses({ bordered: this.bordered ?? false });
4334
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
+ }
4335
5114
  render() {
4336
5115
  return html`${this.hideToggle ? nothing : html`<button
4337
5116
  aria-expanded="${this.open ? "true" : "false"}"
@@ -4376,6 +5155,8 @@ function defineSpectreSidebar(tagName = "sp-sidebar") {
4376
5155
  var SpectreSidebarLinkElement = class extends SpectreProjectableElement {
4377
5156
  constructor() {
4378
5157
  super(...arguments);
5158
+ this.focused = false;
5159
+ this.hovered = false;
4379
5160
  this.active = false;
4380
5161
  this.disabled = false;
4381
5162
  this.href = void 0;
@@ -4416,6 +5197,7 @@ var SpectreSidebarLinkElement = class extends SpectreProjectableElement {
4416
5197
  }
4417
5198
  get sidebarLinkClasses() {
4418
5199
  return getSidebarLinkClasses({
5200
+ ...hoverFocusStates(this),
4419
5201
  active: this.active ?? false,
4420
5202
  disabled: this.disabled ?? false,
4421
5203
  level: this.level
@@ -4438,6 +5220,7 @@ var SpectreSidebarLinkElement = class extends SpectreProjectableElement {
4438
5220
  }
4439
5221
  };
4440
5222
  SpectreSidebarLinkElement.properties = {
5223
+ ...hoverFocusStateProperties,
4441
5224
  active: { type: Boolean, reflect: true },
4442
5225
  disabled: { type: Boolean, reflect: true },
4443
5226
  href: { type: String },
@@ -4567,6 +5350,8 @@ function defineSpectreSidebarToggle(tagName = "sp-sidebar-toggle") {
4567
5350
  var SpectreToastElement = class extends SpectreBaseElement {
4568
5351
  constructor() {
4569
5352
  super(...arguments);
5353
+ this.accent = void 0;
5354
+ this.accentColor = void 0;
4570
5355
  this.dismissed = false;
4571
5356
  this.fullWidth = false;
4572
5357
  this.variant = "info";
@@ -4650,6 +5435,12 @@ var SpectreToastElement = class extends SpectreBaseElement {
4650
5435
  this.contentObserver = void 0;
4651
5436
  }
4652
5437
  willUpdate(changedProperties) {
5438
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
5439
+ this.accent = void 0;
5440
+ }
5441
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
5442
+ this.accentColor = void 0;
5443
+ }
4653
5444
  if (changedProperties.has("dismissed") && this.dismissed == null) {
4654
5445
  this.dismissed = false;
4655
5446
  }
@@ -4696,6 +5487,12 @@ var SpectreToastElement = class extends SpectreBaseElement {
4696
5487
  }
4697
5488
  get toastClasses() {
4698
5489
  return getToastClasses({
5490
+ ...this.accent !== void 0 && {
5491
+ accent: this.accent
5492
+ },
5493
+ ...this.accentColor !== void 0 && {
5494
+ accentColor: this.accentColor
5495
+ },
4699
5496
  variant: this.variant,
4700
5497
  dismissed: this.dismissed ?? false,
4701
5498
  fullWidth: this.fullWidth ?? false
@@ -4723,6 +5520,8 @@ var SpectreToastElement = class extends SpectreBaseElement {
4723
5520
  }
4724
5521
  };
4725
5522
  SpectreToastElement.properties = {
5523
+ accent: { type: String, reflect: true },
5524
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
4726
5525
  autoDismiss: { attribute: "auto-dismiss", type: Number },
4727
5526
  dismissed: { type: Boolean, reflect: true },
4728
5527
  fullWidth: { attribute: "full-width", type: Boolean, reflect: true },
@@ -4739,6 +5538,8 @@ function defineSpectreToast(tagName = "sp-toast") {
4739
5538
  var SpectreTooltipElement = class extends SpectreBaseElement {
4740
5539
  constructor() {
4741
5540
  super(...arguments);
5541
+ this.accent = void 0;
5542
+ this.accentColor = void 0;
4742
5543
  this.placement = "top";
4743
5544
  this.visible = false;
4744
5545
  this.triggerContent = [];
@@ -4795,12 +5596,12 @@ var SpectreTooltipElement = class extends SpectreBaseElement {
4795
5596
  return hasMeaningfulContent(this.tooltipContent);
4796
5597
  }
4797
5598
  connectedCallback() {
4798
- var _a, _b;
5599
+ var _a5, _b5;
4799
5600
  super.connectedCallback();
4800
5601
  this.syncProjectedContent();
4801
5602
  this.startContentObserver();
4802
- (_a = this.style).position || (_a.position = "relative");
4803
- (_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");
4804
5605
  }
4805
5606
  disconnectedCallback() {
4806
5607
  this.stopContentObserver();
@@ -4827,6 +5628,12 @@ var SpectreTooltipElement = class extends SpectreBaseElement {
4827
5628
  this.contentObserver = void 0;
4828
5629
  }
4829
5630
  willUpdate(changedProperties) {
5631
+ if (changedProperties.has("accent") && this.accent != null && !isAccentEdge(this.accent)) {
5632
+ this.accent = void 0;
5633
+ }
5634
+ if (changedProperties.has("accentColor") && this.accentColor != null && !isAccentColor(this.accentColor)) {
5635
+ this.accentColor = void 0;
5636
+ }
4830
5637
  if (changedProperties.has("placement") && (this.placement == null || !isTooltipPlacement(this.placement))) {
4831
5638
  this.placement = "top";
4832
5639
  }
@@ -4850,6 +5657,12 @@ var SpectreTooltipElement = class extends SpectreBaseElement {
4850
5657
  }
4851
5658
  get tooltipClasses() {
4852
5659
  return getTooltipClasses({
5660
+ ...this.accent !== void 0 && {
5661
+ accent: this.accent
5662
+ },
5663
+ ...this.accentColor !== void 0 && {
5664
+ accentColor: this.accentColor
5665
+ },
4853
5666
  placement: this.placement,
4854
5667
  visible: this.visible ?? false
4855
5668
  });
@@ -4877,6 +5690,8 @@ var SpectreTooltipElement = class extends SpectreBaseElement {
4877
5690
  }
4878
5691
  };
4879
5692
  SpectreTooltipElement.properties = {
5693
+ accent: { type: String, reflect: true },
5694
+ accentColor: { attribute: "accent-color", type: String, reflect: true },
4880
5695
  placement: { type: String, reflect: true },
4881
5696
  visible: { type: Boolean, reflect: true }
4882
5697
  };
@@ -4901,11 +5716,23 @@ var LEVEL_TAGS = {
4901
5716
  var SpectreTextElement = class extends SpectreProjectableElement {
4902
5717
  constructor() {
4903
5718
  super(...arguments);
5719
+ this.displayLevel = void 0;
5720
+ this.headingLevel = void 0;
4904
5721
  this.level = "p";
5722
+ this.preset = void 0;
4905
5723
  this.size = "md";
4906
5724
  this.variant = "default";
4907
5725
  }
4908
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
+ }
4909
5736
  if (changedProperties.has("family") && !isTextFamily(this.family)) {
4910
5737
  this.family = void 0;
4911
5738
  }
@@ -4944,19 +5771,34 @@ var SpectreTextElement = class extends SpectreProjectableElement {
4944
5771
  const el = node;
4945
5772
  return el.hasAttribute("data-sp-text-native");
4946
5773
  }
4947
- render() {
4948
- const tag = LEVEL_TAGS[this.level ?? "p"];
4949
- 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({
4950
5789
  ...this.family !== void 0 && { family: this.family },
4951
5790
  size: this.size ?? "md",
4952
5791
  ...this.transform !== void 0 && { transform: this.transform },
4953
5792
  variant: this.variant ?? "default"
4954
5793
  });
5794
+ }
5795
+ render() {
5796
+ const tag = LEVEL_TAGS[this.level ?? "p"];
4955
5797
  return html$1`<${tag}
4956
5798
  aria-describedby="${ifDefined(this.forwardedAriaDescribedBy)}"
4957
5799
  aria-label="${ifDefined(this.forwardedAriaLabel)}"
4958
5800
  aria-labelledby="${ifDefined(this.forwardedAriaLabelledBy)}"
4959
- class="${textClasses}"
5801
+ class="${this.textClasses}"
4960
5802
  data-sp-text-native
4961
5803
  id="${ifDefined(this.id || void 0)}"
4962
5804
  title="${ifDefined(this.title || void 0)}"
@@ -4964,8 +5806,11 @@ var SpectreTextElement = class extends SpectreProjectableElement {
4964
5806
  }
4965
5807
  };
4966
5808
  SpectreTextElement.properties = {
5809
+ displayLevel: { attribute: "display-level", type: Number, reflect: true },
4967
5810
  family: { type: String, reflect: true },
5811
+ headingLevel: { attribute: "heading-level", type: String, reflect: true },
4968
5812
  level: { type: String, reflect: true },
5813
+ preset: { type: String, reflect: true },
4969
5814
  size: { type: String, reflect: true },
4970
5815
  transform: { type: String, reflect: true },
4971
5816
  variant: { type: String, reflect: true }
@@ -4978,6 +5823,2813 @@ function defineSpectreText(tagName = "sp-text") {
4978
5823
  customElements.define(tagName, SpectreTextElement);
4979
5824
  return SpectreTextElement;
4980
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
+ }
4981
8633
 
4982
8634
  // src/index.ts
4983
8635
  function defineSpectreComponents() {
@@ -5016,8 +8668,31 @@ function defineSpectreComponents() {
5016
8668
  defineSpectreToast();
5017
8669
  defineSpectreTooltip();
5018
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();
5019
8694
  }
5020
8695
 
5021
- 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, 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 };
5022
8697
  //# sourceMappingURL=index.js.map
5023
8698
  //# sourceMappingURL=index.js.map