@pitchfork-ui/elements 0.1.0 → 0.2.1

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 (264) hide show
  1. package/dist/cjs/control-label-C0eK8bPh.js +36 -0
  2. package/dist/cjs/control-label-C0eK8bPh.js.map +1 -0
  3. package/dist/cjs/index-CIskGKk1.js +4 -4
  4. package/dist/cjs/loader.cjs.js +1 -1
  5. package/dist/cjs/pf-checkbox.cjs.entry.js +3 -1
  6. package/dist/cjs/pf-checkbox.cjs.entry.js.map +1 -1
  7. package/dist/cjs/pf-combobox.cjs.entry.js +4 -3
  8. package/dist/cjs/pf-combobox.cjs.entry.js.map +1 -1
  9. package/dist/cjs/pf-date-picker.cjs.entry.js +3 -2
  10. package/dist/cjs/pf-date-picker.cjs.entry.js.map +1 -1
  11. package/dist/cjs/pf-date-range-picker.cjs.entry.js +6 -5
  12. package/dist/cjs/pf-date-range-picker.cjs.entry.js.map +1 -1
  13. package/dist/cjs/pf-header-navigation.cjs.entry.js +15 -3
  14. package/dist/cjs/pf-header-navigation.cjs.entry.js.map +1 -1
  15. package/dist/cjs/pf-input.cjs.entry.js +3 -1
  16. package/dist/cjs/pf-input.cjs.entry.js.map +1 -1
  17. package/dist/cjs/pf-modal.cjs.entry.js +89 -1
  18. package/dist/cjs/pf-modal.cjs.entry.js.map +1 -1
  19. package/dist/cjs/pf-multi-select.cjs.entry.js +4 -3
  20. package/dist/cjs/pf-multi-select.cjs.entry.js.map +1 -1
  21. package/dist/cjs/pf-nav-item.cjs.entry.js +29 -4
  22. package/dist/cjs/pf-nav-item.cjs.entry.js.map +1 -1
  23. package/dist/cjs/pf-number-input.cjs.entry.js +2 -1
  24. package/dist/cjs/pf-number-input.cjs.entry.js.map +1 -1
  25. package/dist/cjs/pf-select.cjs.entry.js +4 -3
  26. package/dist/cjs/pf-select.cjs.entry.js.map +1 -1
  27. package/dist/cjs/pf-sidebar-navigation.cjs.entry.js +11 -8
  28. package/dist/cjs/pf-sidebar-navigation.cjs.entry.js.map +1 -1
  29. package/dist/cjs/pf-slider.cjs.entry.js +4 -2
  30. package/dist/cjs/pf-slider.cjs.entry.js.map +1 -1
  31. package/dist/cjs/pf-switch.cjs.entry.js +3 -1
  32. package/dist/cjs/pf-switch.cjs.entry.js.map +1 -1
  33. package/dist/cjs/pf-tag-input.cjs.entry.js +3 -2
  34. package/dist/cjs/pf-tag-input.cjs.entry.js.map +1 -1
  35. package/dist/cjs/pf-textarea.cjs.entry.js +2 -1
  36. package/dist/cjs/pf-textarea.cjs.entry.js.map +1 -1
  37. package/dist/cjs/pf-time-picker.cjs.entry.js +3 -2
  38. package/dist/cjs/pf-time-picker.cjs.entry.js.map +1 -1
  39. package/dist/cjs/pitchfork.cjs.js +1 -1
  40. package/dist/collection/components/pf-accordion/pf-accordion.js +2 -2
  41. package/dist/collection/components/pf-alert/pf-alert.js +1 -1
  42. package/dist/collection/components/pf-avatar/pf-avatar.js +2 -2
  43. package/dist/collection/components/pf-badge/pf-badge.js +1 -1
  44. package/dist/collection/components/pf-badge-group/pf-badge-group.js +3 -3
  45. package/dist/collection/components/pf-button/pf-button.js +3 -3
  46. package/dist/collection/components/pf-checkbox/pf-checkbox.js +4 -1
  47. package/dist/collection/components/pf-checkbox/pf-checkbox.js.map +1 -1
  48. package/dist/collection/components/pf-combobox/pf-combobox.js +4 -3
  49. package/dist/collection/components/pf-combobox/pf-combobox.js.map +1 -1
  50. package/dist/collection/components/pf-content-divider/pf-content-divider.js +1 -1
  51. package/dist/collection/components/pf-credit-card/pf-credit-card.js +1 -1
  52. package/dist/collection/components/pf-date-picker/pf-date-picker.js +3 -2
  53. package/dist/collection/components/pf-date-picker/pf-date-picker.js.map +1 -1
  54. package/dist/collection/components/pf-date-range-picker/pf-date-range-picker.js +6 -5
  55. package/dist/collection/components/pf-date-range-picker/pf-date-range-picker.js.map +1 -1
  56. package/dist/collection/components/pf-empty-state/pf-empty-state.js +1 -1
  57. package/dist/collection/components/pf-header-navigation/pf-header-navigation.js +25 -4
  58. package/dist/collection/components/pf-header-navigation/pf-header-navigation.js.map +1 -1
  59. package/dist/collection/components/pf-inline-cta/pf-inline-cta.js +1 -1
  60. package/dist/collection/components/pf-input/pf-input.js +5 -2
  61. package/dist/collection/components/pf-input/pf-input.js.map +1 -1
  62. package/dist/collection/components/pf-kbd/pf-kbd.js +1 -1
  63. package/dist/collection/components/pf-line-chart/pf-line-chart.js +1 -1
  64. package/dist/collection/components/pf-loading-dots/pf-loading-dots.js +1 -1
  65. package/dist/collection/components/pf-metric-card/pf-metric-card.js +1 -1
  66. package/dist/collection/components/pf-modal/pf-modal.js +77 -6
  67. package/dist/collection/components/pf-modal/pf-modal.js.map +1 -1
  68. package/dist/collection/components/pf-multi-select/pf-multi-select.js +4 -3
  69. package/dist/collection/components/pf-multi-select/pf-multi-select.js.map +1 -1
  70. package/dist/collection/components/pf-nav-item/pf-nav-item.js +50 -5
  71. package/dist/collection/components/pf-nav-item/pf-nav-item.js.map +1 -1
  72. package/dist/collection/components/pf-notification/pf-notification.js +1 -1
  73. package/dist/collection/components/pf-number-input/pf-number-input.js +2 -1
  74. package/dist/collection/components/pf-number-input/pf-number-input.js.map +1 -1
  75. package/dist/collection/components/pf-progress-steps/pf-progress-steps.js +1 -1
  76. package/dist/collection/components/pf-radio-group/pf-radio-group.js +1 -1
  77. package/dist/collection/components/pf-rating-badge/pf-rating-badge.js +1 -1
  78. package/dist/collection/components/pf-scroll-area/pf-scroll-area.js +1 -1
  79. package/dist/collection/components/pf-section-header/pf-section-header.js +1 -1
  80. package/dist/collection/components/pf-select/pf-select.js +4 -3
  81. package/dist/collection/components/pf-select/pf-select.js.map +1 -1
  82. package/dist/collection/components/pf-sidebar-navigation/pf-sidebar-navigation.js +12 -9
  83. package/dist/collection/components/pf-sidebar-navigation/pf-sidebar-navigation.js.map +1 -1
  84. package/dist/collection/components/pf-slideout-menu/pf-slideout-menu.js +2 -2
  85. package/dist/collection/components/pf-slider/pf-slider.js +5 -2
  86. package/dist/collection/components/pf-slider/pf-slider.js.map +1 -1
  87. package/dist/collection/components/pf-switch/pf-switch.js +4 -1
  88. package/dist/collection/components/pf-switch/pf-switch.js.map +1 -1
  89. package/dist/collection/components/pf-tab/pf-tab.js +2 -2
  90. package/dist/collection/components/pf-table-cell/pf-table-cell.js +1 -1
  91. package/dist/collection/components/pf-tabs/pf-tabs.js +2 -2
  92. package/dist/collection/components/pf-tag/pf-tag.js +1 -1
  93. package/dist/collection/components/pf-tag-input/pf-tag-input.js +3 -2
  94. package/dist/collection/components/pf-tag-input/pf-tag-input.js.map +1 -1
  95. package/dist/collection/components/pf-textarea/pf-textarea.js +2 -1
  96. package/dist/collection/components/pf-textarea/pf-textarea.js.map +1 -1
  97. package/dist/collection/components/pf-time-picker/pf-time-picker.js +3 -2
  98. package/dist/collection/components/pf-time-picker/pf-time-picker.js.map +1 -1
  99. package/dist/collection/components/pf-timeline-item/pf-timeline-item.js +1 -1
  100. package/dist/collection/components/pf-toaster/pf-toaster.js +2 -2
  101. package/dist/collection/components/pf-toolbar/pf-toolbar.js +1 -1
  102. package/dist/collection/components/pf-toolbar-separator/pf-toolbar-separator.js +1 -1
  103. package/dist/collection/components/pf-utility-button/pf-utility-button.js +2 -2
  104. package/dist/collection/components/pf-video-player/pf-video-player.js +2 -2
  105. package/dist/collection/control-label.js +30 -0
  106. package/dist/collection/control-label.js.map +1 -0
  107. package/dist/components/p-Cy_kHPeC.js +2 -0
  108. package/dist/components/p-Cy_kHPeC.js.map +1 -0
  109. package/dist/components/pf-checkbox.js +1 -1
  110. package/dist/components/pf-checkbox.js.map +1 -1
  111. package/dist/components/pf-combobox.js +1 -1
  112. package/dist/components/pf-combobox.js.map +1 -1
  113. package/dist/components/pf-date-picker.js +1 -1
  114. package/dist/components/pf-date-picker.js.map +1 -1
  115. package/dist/components/pf-date-range-picker.js +1 -1
  116. package/dist/components/pf-date-range-picker.js.map +1 -1
  117. package/dist/components/pf-header-navigation.js +1 -1
  118. package/dist/components/pf-header-navigation.js.map +1 -1
  119. package/dist/components/pf-input.js +1 -1
  120. package/dist/components/pf-input.js.map +1 -1
  121. package/dist/components/pf-modal.js +1 -1
  122. package/dist/components/pf-modal.js.map +1 -1
  123. package/dist/components/pf-multi-select.js +1 -1
  124. package/dist/components/pf-multi-select.js.map +1 -1
  125. package/dist/components/pf-nav-item.js +1 -1
  126. package/dist/components/pf-nav-item.js.map +1 -1
  127. package/dist/components/pf-number-input.js +1 -1
  128. package/dist/components/pf-number-input.js.map +1 -1
  129. package/dist/components/pf-select.js +1 -1
  130. package/dist/components/pf-select.js.map +1 -1
  131. package/dist/components/pf-sidebar-navigation.js +1 -1
  132. package/dist/components/pf-sidebar-navigation.js.map +1 -1
  133. package/dist/components/pf-slider.js +1 -1
  134. package/dist/components/pf-slider.js.map +1 -1
  135. package/dist/components/pf-switch.js +1 -1
  136. package/dist/components/pf-switch.js.map +1 -1
  137. package/dist/components/pf-tag-input.js +1 -1
  138. package/dist/components/pf-tag-input.js.map +1 -1
  139. package/dist/components/pf-textarea.js +1 -1
  140. package/dist/components/pf-textarea.js.map +1 -1
  141. package/dist/components/pf-time-picker.js +1 -1
  142. package/dist/components/pf-time-picker.js.map +1 -1
  143. package/dist/docs.json +73 -52
  144. package/dist/elements.json +100 -10
  145. package/dist/esm/control-label-Cy_kHPeC.js +34 -0
  146. package/dist/esm/control-label-Cy_kHPeC.js.map +1 -0
  147. package/dist/esm/index-Bm6UxEit.js +4 -4
  148. package/dist/esm/loader.js +1 -1
  149. package/dist/esm/pf-checkbox.entry.js +4 -2
  150. package/dist/esm/pf-checkbox.entry.js.map +1 -1
  151. package/dist/esm/pf-combobox.entry.js +4 -3
  152. package/dist/esm/pf-combobox.entry.js.map +1 -1
  153. package/dist/esm/pf-date-picker.entry.js +3 -2
  154. package/dist/esm/pf-date-picker.entry.js.map +1 -1
  155. package/dist/esm/pf-date-range-picker.entry.js +6 -5
  156. package/dist/esm/pf-date-range-picker.entry.js.map +1 -1
  157. package/dist/esm/pf-header-navigation.entry.js +15 -3
  158. package/dist/esm/pf-header-navigation.entry.js.map +1 -1
  159. package/dist/esm/pf-input.entry.js +4 -2
  160. package/dist/esm/pf-input.entry.js.map +1 -1
  161. package/dist/esm/pf-modal.entry.js +89 -1
  162. package/dist/esm/pf-modal.entry.js.map +1 -1
  163. package/dist/esm/pf-multi-select.entry.js +4 -3
  164. package/dist/esm/pf-multi-select.entry.js.map +1 -1
  165. package/dist/esm/pf-nav-item.entry.js +30 -5
  166. package/dist/esm/pf-nav-item.entry.js.map +1 -1
  167. package/dist/esm/pf-number-input.entry.js +2 -1
  168. package/dist/esm/pf-number-input.entry.js.map +1 -1
  169. package/dist/esm/pf-select.entry.js +4 -3
  170. package/dist/esm/pf-select.entry.js.map +1 -1
  171. package/dist/esm/pf-sidebar-navigation.entry.js +11 -8
  172. package/dist/esm/pf-sidebar-navigation.entry.js.map +1 -1
  173. package/dist/esm/pf-slider.entry.js +5 -3
  174. package/dist/esm/pf-slider.entry.js.map +1 -1
  175. package/dist/esm/pf-switch.entry.js +4 -2
  176. package/dist/esm/pf-switch.entry.js.map +1 -1
  177. package/dist/esm/pf-tag-input.entry.js +3 -2
  178. package/dist/esm/pf-tag-input.entry.js.map +1 -1
  179. package/dist/esm/pf-textarea.entry.js +2 -1
  180. package/dist/esm/pf-textarea.entry.js.map +1 -1
  181. package/dist/esm/pf-time-picker.entry.js +3 -2
  182. package/dist/esm/pf-time-picker.entry.js.map +1 -1
  183. package/dist/esm/pitchfork.js +1 -1
  184. package/dist/pitchfork/p-01ed0d56.entry.js +2 -0
  185. package/dist/pitchfork/p-01ed0d56.entry.js.map +1 -0
  186. package/dist/pitchfork/p-02e28338.entry.js +2 -0
  187. package/dist/pitchfork/p-02e28338.entry.js.map +1 -0
  188. package/dist/pitchfork/p-19c0145c.entry.js +2 -0
  189. package/dist/pitchfork/p-19c0145c.entry.js.map +1 -0
  190. package/dist/pitchfork/p-22d8c69d.entry.js +2 -0
  191. package/dist/pitchfork/p-22d8c69d.entry.js.map +1 -0
  192. package/dist/pitchfork/p-2add2e98.entry.js +2 -0
  193. package/dist/pitchfork/p-2add2e98.entry.js.map +1 -0
  194. package/dist/pitchfork/p-45039de3.entry.js +2 -0
  195. package/dist/pitchfork/p-45039de3.entry.js.map +1 -0
  196. package/dist/pitchfork/p-4dfe7e8a.entry.js +2 -0
  197. package/dist/pitchfork/p-4dfe7e8a.entry.js.map +1 -0
  198. package/dist/pitchfork/p-51353d53.entry.js +2 -0
  199. package/dist/pitchfork/p-51353d53.entry.js.map +1 -0
  200. package/dist/pitchfork/p-5b98848c.entry.js +2 -0
  201. package/dist/pitchfork/{p-fd5a5ea1.entry.js.map → p-5b98848c.entry.js.map} +1 -1
  202. package/dist/pitchfork/p-7197ef71.entry.js +2 -0
  203. package/dist/pitchfork/p-7197ef71.entry.js.map +1 -0
  204. package/dist/pitchfork/p-Cy_kHPeC.js +2 -0
  205. package/dist/pitchfork/p-Cy_kHPeC.js.map +1 -0
  206. package/dist/pitchfork/p-ab6c09e7.entry.js +2 -0
  207. package/dist/pitchfork/p-ab6c09e7.entry.js.map +1 -0
  208. package/dist/pitchfork/p-d7ca4026.entry.js +2 -0
  209. package/dist/pitchfork/p-d7ca4026.entry.js.map +1 -0
  210. package/dist/pitchfork/p-dd48d94d.entry.js +2 -0
  211. package/dist/pitchfork/p-dd48d94d.entry.js.map +1 -0
  212. package/dist/pitchfork/p-ec8df806.entry.js +2 -0
  213. package/dist/pitchfork/p-ec8df806.entry.js.map +1 -0
  214. package/dist/pitchfork/p-f5df568f.entry.js +2 -0
  215. package/dist/pitchfork/p-f5df568f.entry.js.map +1 -0
  216. package/dist/pitchfork/p-f713c62d.entry.js +2 -0
  217. package/dist/pitchfork/p-f713c62d.entry.js.map +1 -0
  218. package/dist/pitchfork/p-fd802631.entry.js +2 -0
  219. package/dist/pitchfork/p-fd802631.entry.js.map +1 -0
  220. package/dist/pitchfork/pitchfork.esm.js +1 -1
  221. package/dist/types/components/pf-checkbox/pf-checkbox.d.ts +1 -0
  222. package/dist/types/components/pf-header-navigation/pf-header-navigation.d.ts +11 -2
  223. package/dist/types/components/pf-input/pf-input.d.ts +1 -0
  224. package/dist/types/components/pf-modal/pf-modal.d.ts +56 -3
  225. package/dist/types/components/pf-nav-item/pf-nav-item.d.ts +21 -1
  226. package/dist/types/components/pf-sidebar-navigation/pf-sidebar-navigation.d.ts +10 -7
  227. package/dist/types/components/pf-slider/pf-slider.d.ts +1 -0
  228. package/dist/types/components/pf-switch/pf-switch.d.ts +1 -0
  229. package/dist/types/components.d.ts +57 -18
  230. package/dist/types/control-label.d.ts +24 -0
  231. package/package.json +4 -4
  232. package/dist/pitchfork/p-1dbea97f.entry.js +0 -2
  233. package/dist/pitchfork/p-1dbea97f.entry.js.map +0 -1
  234. package/dist/pitchfork/p-23b1be9b.entry.js +0 -2
  235. package/dist/pitchfork/p-23b1be9b.entry.js.map +0 -1
  236. package/dist/pitchfork/p-33857f80.entry.js +0 -2
  237. package/dist/pitchfork/p-33857f80.entry.js.map +0 -1
  238. package/dist/pitchfork/p-47cabc33.entry.js +0 -2
  239. package/dist/pitchfork/p-47cabc33.entry.js.map +0 -1
  240. package/dist/pitchfork/p-48b2d3f7.entry.js +0 -2
  241. package/dist/pitchfork/p-48b2d3f7.entry.js.map +0 -1
  242. package/dist/pitchfork/p-5064d2dd.entry.js +0 -2
  243. package/dist/pitchfork/p-5064d2dd.entry.js.map +0 -1
  244. package/dist/pitchfork/p-52eef7eb.entry.js +0 -2
  245. package/dist/pitchfork/p-52eef7eb.entry.js.map +0 -1
  246. package/dist/pitchfork/p-845c5252.entry.js +0 -2
  247. package/dist/pitchfork/p-845c5252.entry.js.map +0 -1
  248. package/dist/pitchfork/p-a24bf2bd.entry.js +0 -2
  249. package/dist/pitchfork/p-a24bf2bd.entry.js.map +0 -1
  250. package/dist/pitchfork/p-a9b77dbb.entry.js +0 -2
  251. package/dist/pitchfork/p-a9b77dbb.entry.js.map +0 -1
  252. package/dist/pitchfork/p-c6bdd9cd.entry.js +0 -2
  253. package/dist/pitchfork/p-c6bdd9cd.entry.js.map +0 -1
  254. package/dist/pitchfork/p-d0d2070b.entry.js +0 -2
  255. package/dist/pitchfork/p-d0d2070b.entry.js.map +0 -1
  256. package/dist/pitchfork/p-d248b027.entry.js +0 -2
  257. package/dist/pitchfork/p-d248b027.entry.js.map +0 -1
  258. package/dist/pitchfork/p-d6425298.entry.js +0 -2
  259. package/dist/pitchfork/p-d6425298.entry.js.map +0 -1
  260. package/dist/pitchfork/p-d7eb6335.entry.js +0 -2
  261. package/dist/pitchfork/p-d7eb6335.entry.js.map +0 -1
  262. package/dist/pitchfork/p-e944f504.entry.js +0 -2
  263. package/dist/pitchfork/p-e944f504.entry.js.map +0 -1
  264. package/dist/pitchfork/p-fd5a5ea1.entry.js +0 -2
@@ -1,10 +1,11 @@
1
- import { r as registerInstance, h, H as Host } from './index-Bm6UxEit.js';
1
+ import { r as registerInstance, c as createEvent, h, H as Host } from './index-Bm6UxEit.js';
2
2
 
3
3
  const pfNavItemCss = () => `:host{display:block}:host([hidden]){display:none}:host([orientation='horizontal']){flex:0 0 auto}.link{align-items:center;background:transparent;border:0;border-radius:var(--pf-nav-item-radius, var(--radius-sm));color:var(--pf-nav-item-text);cursor:pointer;display:flex;font:inherit;gap:var(--pf-nav-item-gap, var(--space-2));min-height:var(--pf-nav-item-min-height, 32px);padding:var(--pf-nav-item-padding, 0 var(--space-2));text-decoration:none;white-space:nowrap}:host([orientation='vertical']) .link{min-height:var(--pf-nav-item-vertical-min-height, 36px);padding:var(--pf-nav-item-vertical-padding, 0 var(--space-3));width:100%}.link:hover{background:var(--pf-nav-item-hover-bg);color:var(--pf-nav-item-hover-text)}a.link:focus-visible{box-shadow:var(--pf-nav-item-focus-ring, var(--pf-focus-ring));outline:none}:host([current-page]) .link{background:var(--pf-nav-item-current-bg);color:var(--pf-nav-item-current-text);font-weight:var(--font-weight-semibold)}:host([disabled]) .link{cursor:not-allowed;opacity:var(--pf-nav-item-disabled-opacity, 0.5)}:host([disabled]) .link:hover{background:transparent;color:var(--pf-nav-item-text)}.label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}:host([orientation='horizontal']) .label{flex:0 0 auto}::slotted([slot='icon']){color:inherit;flex:0 0 auto}::slotted([slot='badge']){flex:0 0 auto}::slotted(a),::slotted(button){align-items:center;align-self:stretch;background:none;border:0;color:inherit;cursor:inherit;display:flex;flex:1 1 auto;font:inherit;margin:0;padding:0;text-decoration:none}`;
4
4
 
5
5
  const PfNavItem = class {
6
6
  constructor(hostRef) {
7
7
  registerInstance(this, hostRef);
8
+ this.pfNavStructure = createEvent(this, "pfNavStructure");
8
9
  }
9
10
  /** Where the item goes. Reflected; a consumer's stylesheet reads it. */
10
11
  href;
@@ -21,6 +22,25 @@ const PfNavItem = class {
21
22
  * behind on an item the consumer had not marked.
22
23
  */
23
24
  current = false;
25
+ /**
26
+ * Tells the group the ask changed, so it can resolve again.
27
+ *
28
+ * The same event `pf-nav-section` emits when its items move, because the
29
+ * groups do the same thing with both: re-read every item and resolve the
30
+ * one current page. Without this a navigation resolves at load and never
31
+ * again for a consumer who marks items through the *property*, which is
32
+ * every framework consumer — the generated bindings set props as
33
+ * properties, so there is no attribute change and no `slotchange` either.
34
+ * The symptom is a navigation whose highlight never moves while the router
35
+ * works perfectly, which is what porting `apps/demo` ran into.
36
+ *
37
+ * `current` only. Watching `currentPage` would loop, since that is what the
38
+ * group writes back.
39
+ */
40
+ pfNavStructure;
41
+ handleCurrentChange() {
42
+ this.pfNavStructure.emit();
43
+ }
24
44
  /**
25
45
  * Set by the group: the resolved current page, which is the one thing that
26
46
  * renders `aria-current="page"`. At most one item in a navigation carries
@@ -41,12 +61,17 @@ const PfNavItem = class {
41
61
  orientation = 'horizontal';
42
62
  render() {
43
63
  const content = [
44
- h("slot", { key: '35769e4f7edb3524591111fd8c78eca5a6ae5e76', name: "icon" }),
45
- h("span", { key: '201e0efd80af4ec26fde67d5c90fbf47d2f8f16f', class: "label", part: "label" }, h("slot", { key: 'bf2ada457257d25f3a054beb41133e872585a26b' })),
46
- h("slot", { key: 'c807ea3208d83e9f205392aa655a35e211c75e3e', name: "badge" }),
64
+ h("slot", { key: 'b478a66b7ae6c6d00b18f762600435dbac37996d', name: "icon" }),
65
+ h("span", { key: '4b1ddbe87804c604d492b00bbc743299c54f7240', class: "label", part: "label" }, h("slot", { key: '86778db42fef8af44096211cd8a743155dca3fb0' })),
66
+ h("slot", { key: '02fef2701ef217701ce18e71e9ff873dc3bd3a44', name: "badge" }),
47
67
  ];
48
- return (h(Host, { key: 'ad28038cf786d9c8431e1da725305cceacac5a15', role: "listitem" }, this.href && !this.disabled ? (h("a", { class: "link", part: "link", href: this.href, target: this.target, rel: this.rel, "aria-current": this.currentPage ? 'page' : null }, content)) : (h("span", { class: "link", part: "link", "aria-current": this.currentPage ? 'page' : null, "aria-disabled": this.disabled ? 'true' : null }, content))));
68
+ return (h(Host, { key: 'c4ee7f6245eedd2bf0546ebcb987120212ea18e3', role: "listitem" }, this.href && !this.disabled ? (h("a", { class: "link", part: "link", href: this.href, target: this.target, rel: this.rel, "aria-current": this.currentPage ? 'page' : null }, content)) : (h("span", { class: "link", part: "link", "aria-current": this.currentPage ? 'page' : null, "aria-disabled": this.disabled ? 'true' : null }, content))));
49
69
  }
70
+ static get watchers() { return {
71
+ "current": [{
72
+ "handleCurrentChange": 0
73
+ }]
74
+ }; }
50
75
  };
51
76
  PfNavItem.style = pfNavItemCss();
52
77
 
@@ -1 +1 @@
1
- {"version":3,"file":"pf-nav-item.entry.js","sources":["src/components/pf-nav-item/pf-nav-item.css?tag=pf-nav-item&encapsulation=shadow","src/components/pf-nav-item/pf-nav-item.tsx"],"sourcesContent":["/*\n * This element is shared by pf-header-navigation and pf-sidebar-navigation,\n * whose React counterparts have separate alias families with their own\n * values. Rather than pick one and diverge from the other, the item reads a\n * generic `--pf-nav-item-*` set that each navigation defines on itself --\n * custom properties inherit through the shadow boundary, so a slotted item\n * picks up whichever navigation it is inside, which no selector can do\n * (`:host-context` is not in Firefox). Exactly the pf-option arrangement, for\n * the same reason. There is deliberately no `:root` default: without one the\n * bridge is load-bearing, and a missing one shows up as an item with no\n * colours at all rather than as one that quietly looks right.\n */\n:host {\n display: block;\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host([orientation='horizontal']) {\n flex: 0 0 auto;\n}\n\n.link {\n align-items: center;\n background: transparent;\n border: 0;\n border-radius: var(--pf-nav-item-radius, var(--radius-sm));\n color: var(--pf-nav-item-text);\n cursor: pointer;\n display: flex;\n font: inherit;\n gap: var(--pf-nav-item-gap, var(--space-2));\n min-height: var(--pf-nav-item-min-height, 32px);\n padding: var(--pf-nav-item-padding, 0 var(--space-2));\n text-decoration: none;\n white-space: nowrap;\n}\n\n:host([orientation='vertical']) .link {\n min-height: var(--pf-nav-item-vertical-min-height, 36px);\n padding: var(--pf-nav-item-vertical-padding, 0 var(--space-3));\n width: 100%;\n}\n\n.link:hover {\n background: var(--pf-nav-item-hover-bg);\n color: var(--pf-nav-item-hover-text);\n}\n\na.link:focus-visible {\n box-shadow: var(--pf-nav-item-focus-ring, var(--pf-focus-ring));\n outline: none;\n}\n\n/*\n * `current-page` is the group's answer, not the consumer's `current` ask: the\n * highlight and the announcement are the same decision, so they read the same\n * attribute.\n */\n:host([current-page]) .link {\n background: var(--pf-nav-item-current-bg);\n color: var(--pf-nav-item-current-text);\n font-weight: var(--font-weight-semibold);\n}\n\n:host([disabled]) .link {\n cursor: not-allowed;\n opacity: var(--pf-nav-item-disabled-opacity, 0.5);\n}\n\n:host([disabled]) .link:hover {\n background: transparent;\n color: var(--pf-nav-item-text);\n}\n\n/* The label takes the slack so a badge sits at the far edge of a sidebar. */\n.label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n:host([orientation='horizontal']) .label {\n flex: 0 0 auto;\n}\n\n/*\n * No wrapper around the icon and badge slots: an unassigned slot is\n * `display: contents` and generates nothing, while a wrapper around one\n * cannot be collapsed from CSS and would cost a gap in front of every label\n * with no icon.\n */\n::slotted([slot='icon']) {\n color: inherit;\n flex: 0 0 auto;\n}\n\n::slotted([slot='badge']) {\n flex: 0 0 auto;\n}\n\n/*\n * A consumer's own router link, slotted in with no `href` of ours. It fills\n * the box's content area rather than being a word inside it, and it inherits\n * every colour the box resolved, so hover and the current page look the same\n * whichever of the two is the control.\n */\n::slotted(a),\n::slotted(button) {\n align-items: center;\n align-self: stretch;\n background: none;\n border: 0;\n color: inherit;\n cursor: inherit;\n display: flex;\n flex: 1 1 auto;\n font: inherit;\n margin: 0;\n padding: 0;\n text-decoration: none;\n}\n","import { Component, h, Host, Prop } from '@stencil/core';\n\n/**\n * One item in a `pf-header-navigation` or a `pf-sidebar-navigation`.\n *\n * Shared by both, because the React library's `HeaderNavigationItem` and\n * `SidebarNavigationItem` are the same shape — one element rather than two\n * that would drift. What differs is the layout, and that is the group's to\n * say: it pushes `orientation` down, which is the only thing an item cannot\n * work out for itself.\n *\n * With an `href` it renders a link; without one it renders a plain box, which\n * is how a framework's own router is used — slot an `<a routerLink>` or a\n * `<Link>` in and leave `href` unset.\n *\n * `currentPage` and `orientation` are the group's to set. A consumer asks by\n * setting `current`; the group resolves every item with core's rule and\n * writes the answer to `currentPage`.\n *\n * @slot - the item's label.\n * @slot icon - a leading icon.\n * @slot badge - a trailing badge or count.\n * @part link - the link, or the box standing in for one.\n */\n@Component({\n tag: 'pf-nav-item',\n styleUrl: 'pf-nav-item.css',\n shadow: true,\n})\nexport class PfNavItem {\n /** Where the item goes. Reflected; a consumer's stylesheet reads it. */\n @Prop({ reflect: true }) href?: string;\n\n /** Opens elsewhere, as on a plain anchor. Ignored without an `href`. */\n @Prop() target?: string;\n\n /** Goes on the anchor as-is. Ignored without an `href`. */\n @Prop() rel?: string;\n\n /**\n * Set it to mark this item as the current page.\n *\n * The *asking* half, which the group never writes — `currentPage` below is\n * the answer. The two are kept apart for the reason `pf-breadcrumb` keeps\n * them apart: a group that wrote its answer back would leave the mark\n * behind on an item the consumer had not marked.\n */\n @Prop({ reflect: true }) current = false;\n\n /**\n * Set by the group: the resolved current page, which is the one thing that\n * renders `aria-current=\"page\"`. At most one item in a navigation carries\n * it, and the highlight follows it rather than `current` — a second\n * highlighted item with no `aria-current` would be a sighted-only lie.\n */\n @Prop({ mutable: true, reflect: true }) currentPage = false;\n\n /**\n * Takes the item out of the navigation without removing it.\n *\n * A disabled item renders **no anchor at all**, because an anchor has no\n * disabled state: `aria-disabled` alone leaves it focusable and clickable,\n * and dropping the `href` is the only thing that really takes it out of the\n * tab order.\n */\n @Prop({ reflect: true }) disabled = false;\n\n /** Set by the group, which is the only one that knows which it is. */\n @Prop({ mutable: true, reflect: true }) orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n render() {\n const content = [\n <slot name=\"icon\" />,\n <span class=\"label\" part=\"label\">\n <slot />\n </span>,\n <slot name=\"badge\" />,\n ];\n\n return (\n <Host role=\"listitem\">\n {this.href && !this.disabled ? (\n <a\n class=\"link\"\n part=\"link\"\n href={this.href}\n target={this.target}\n rel={this.rel}\n aria-current={this.currentPage ? 'page' : null}\n >\n {content}\n </a>\n ) : (\n <span\n class=\"link\"\n part=\"link\"\n aria-current={this.currentPage ? 'page' : null}\n aria-disabled={this.disabled ? 'true' : null}\n >\n {content}\n </span>\n )}\n </Host>\n );\n }\n}\n"],"names":[],"mappings":";;AAAA,MAAM,YAAY,GAAG,MAAM,CAAC,0hDAA0hD,CAAC;;MC6B1iD,SAAS,GAAA,MAAA;;;;;AAEK,IAAA,IAAI;;AAGrB,IAAA,MAAM;;AAGN,IAAA,GAAG;AAEX;;;;;;;AAOG;IACsB,OAAO,GAAG,KAAK;AAExC;;;;;AAKG;IACqC,WAAW,GAAG,KAAK;AAE3D;;;;;;;AAOG;IACsB,QAAQ,GAAG,KAAK;;IAGD,WAAW,GAA8B,YAAY;IAE7F,MAAM,GAAA;AACJ,QAAA,MAAM,OAAO,GAAG;AACd,YAAA,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,IAAI,EAAC,MAAM,EAAA,CAAG;YACpB,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAA,EAC9B,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,CAAQ,CACH;AACP,YAAA,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,IAAI,EAAC,OAAO,EAAA,CAAG;SACtB;AAED,QAAA,QACE,EAAC,IAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAC,IAAI,EAAC,UAAU,EAAA,EAClB,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,IAC1B,CAAA,CAAA,GAAA,EAAA,EACE,KAAK,EAAC,MAAM,EACZ,IAAI,EAAC,MAAM,EACX,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,GAAG,EAAE,IAAI,CAAC,GAAG,EAAA,cAAA,EACC,IAAI,CAAC,WAAW,GAAG,MAAM,GAAG,IAAI,IAE7C,OAAO,CACN,KAEJ,CAAA,CAAA,MAAA,EAAA,EACE,KAAK,EAAC,MAAM,EACZ,IAAI,EAAC,MAAM,EAAA,cAAA,EACG,IAAI,CAAC,WAAW,GAAG,MAAM,GAAG,IAAI,EAAA,eAAA,EAC/B,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,IAAI,EAAA,EAE3C,OAAO,CACH,CACR,CACI;;;;;;;"}
1
+ {"version":3,"file":"pf-nav-item.entry.js","sources":["src/components/pf-nav-item/pf-nav-item.css?tag=pf-nav-item&encapsulation=shadow","src/components/pf-nav-item/pf-nav-item.tsx"],"sourcesContent":["/*\n * This element is shared by pf-header-navigation and pf-sidebar-navigation,\n * whose React counterparts have separate alias families with their own\n * values. Rather than pick one and diverge from the other, the item reads a\n * generic `--pf-nav-item-*` set that each navigation defines on itself --\n * custom properties inherit through the shadow boundary, so a slotted item\n * picks up whichever navigation it is inside, which no selector can do\n * (`:host-context` is not in Firefox). Exactly the pf-option arrangement, for\n * the same reason. There is deliberately no `:root` default: without one the\n * bridge is load-bearing, and a missing one shows up as an item with no\n * colours at all rather than as one that quietly looks right.\n */\n:host {\n display: block;\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host([orientation='horizontal']) {\n flex: 0 0 auto;\n}\n\n.link {\n align-items: center;\n background: transparent;\n border: 0;\n border-radius: var(--pf-nav-item-radius, var(--radius-sm));\n color: var(--pf-nav-item-text);\n cursor: pointer;\n display: flex;\n font: inherit;\n gap: var(--pf-nav-item-gap, var(--space-2));\n min-height: var(--pf-nav-item-min-height, 32px);\n padding: var(--pf-nav-item-padding, 0 var(--space-2));\n text-decoration: none;\n white-space: nowrap;\n}\n\n:host([orientation='vertical']) .link {\n min-height: var(--pf-nav-item-vertical-min-height, 36px);\n padding: var(--pf-nav-item-vertical-padding, 0 var(--space-3));\n width: 100%;\n}\n\n.link:hover {\n background: var(--pf-nav-item-hover-bg);\n color: var(--pf-nav-item-hover-text);\n}\n\na.link:focus-visible {\n box-shadow: var(--pf-nav-item-focus-ring, var(--pf-focus-ring));\n outline: none;\n}\n\n/*\n * `current-page` is the group's answer, not the consumer's `current` ask: the\n * highlight and the announcement are the same decision, so they read the same\n * attribute.\n */\n:host([current-page]) .link {\n background: var(--pf-nav-item-current-bg);\n color: var(--pf-nav-item-current-text);\n font-weight: var(--font-weight-semibold);\n}\n\n:host([disabled]) .link {\n cursor: not-allowed;\n opacity: var(--pf-nav-item-disabled-opacity, 0.5);\n}\n\n:host([disabled]) .link:hover {\n background: transparent;\n color: var(--pf-nav-item-text);\n}\n\n/* The label takes the slack so a badge sits at the far edge of a sidebar. */\n.label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n:host([orientation='horizontal']) .label {\n flex: 0 0 auto;\n}\n\n/*\n * No wrapper around the icon and badge slots: an unassigned slot is\n * `display: contents` and generates nothing, while a wrapper around one\n * cannot be collapsed from CSS and would cost a gap in front of every label\n * with no icon.\n */\n::slotted([slot='icon']) {\n color: inherit;\n flex: 0 0 auto;\n}\n\n::slotted([slot='badge']) {\n flex: 0 0 auto;\n}\n\n/*\n * A consumer's own router link, slotted in with no `href` of ours. It fills\n * the box's content area rather than being a word inside it, and it inherits\n * every colour the box resolved, so hover and the current page look the same\n * whichever of the two is the control.\n */\n::slotted(a),\n::slotted(button) {\n align-items: center;\n align-self: stretch;\n background: none;\n border: 0;\n color: inherit;\n cursor: inherit;\n display: flex;\n flex: 1 1 auto;\n font: inherit;\n margin: 0;\n padding: 0;\n text-decoration: none;\n}\n","import { Component, Event, EventEmitter, h, Host, Prop, Watch } from '@stencil/core';\n\n/**\n * One item in a `pf-header-navigation` or a `pf-sidebar-navigation`.\n *\n * Shared by both, because the React library's `HeaderNavigationItem` and\n * `SidebarNavigationItem` are the same shape — one element rather than two\n * that would drift. What differs is the layout, and that is the group's to\n * say: it pushes `orientation` down, which is the only thing an item cannot\n * work out for itself.\n *\n * With an `href` it renders a link; without one it renders a plain box, which\n * is how a framework's own router is used — slot an `<a routerLink>` or a\n * `<Link>` in and leave `href` unset.\n *\n * `currentPage` and `orientation` are the group's to set. A consumer asks by\n * setting `current`; the group resolves every item with core's rule and\n * writes the answer to `currentPage`. Changing the ask tells the group, so\n * the answer follows a framework's re-render without the consumer calling\n * anything.\n *\n * @slot - the item's label.\n * @slot icon - a leading icon.\n * @slot badge - a trailing badge or count.\n * @part link - the link, or the box standing in for one.\n */\n@Component({\n tag: 'pf-nav-item',\n styleUrl: 'pf-nav-item.css',\n shadow: true,\n})\nexport class PfNavItem {\n /** Where the item goes. Reflected; a consumer's stylesheet reads it. */\n @Prop({ reflect: true }) href?: string;\n\n /** Opens elsewhere, as on a plain anchor. Ignored without an `href`. */\n @Prop() target?: string;\n\n /** Goes on the anchor as-is. Ignored without an `href`. */\n @Prop() rel?: string;\n\n /**\n * Set it to mark this item as the current page.\n *\n * The *asking* half, which the group never writes — `currentPage` below is\n * the answer. The two are kept apart for the reason `pf-breadcrumb` keeps\n * them apart: a group that wrote its answer back would leave the mark\n * behind on an item the consumer had not marked.\n */\n @Prop({ reflect: true }) current = false;\n\n /**\n * Tells the group the ask changed, so it can resolve again.\n *\n * The same event `pf-nav-section` emits when its items move, because the\n * groups do the same thing with both: re-read every item and resolve the\n * one current page. Without this a navigation resolves at load and never\n * again for a consumer who marks items through the *property*, which is\n * every framework consumer — the generated bindings set props as\n * properties, so there is no attribute change and no `slotchange` either.\n * The symptom is a navigation whose highlight never moves while the router\n * works perfectly, which is what porting `apps/demo` ran into.\n *\n * `current` only. Watching `currentPage` would loop, since that is what the\n * group writes back.\n */\n @Event() pfNavStructure!: EventEmitter<void>;\n\n @Watch('current')\n handleCurrentChange() {\n this.pfNavStructure.emit();\n }\n\n /**\n * Set by the group: the resolved current page, which is the one thing that\n * renders `aria-current=\"page\"`. At most one item in a navigation carries\n * it, and the highlight follows it rather than `current` — a second\n * highlighted item with no `aria-current` would be a sighted-only lie.\n */\n @Prop({ mutable: true, reflect: true }) currentPage = false;\n\n /**\n * Takes the item out of the navigation without removing it.\n *\n * A disabled item renders **no anchor at all**, because an anchor has no\n * disabled state: `aria-disabled` alone leaves it focusable and clickable,\n * and dropping the `href` is the only thing that really takes it out of the\n * tab order.\n */\n @Prop({ reflect: true }) disabled = false;\n\n /** Set by the group, which is the only one that knows which it is. */\n @Prop({ mutable: true, reflect: true }) orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n render() {\n const content = [\n <slot name=\"icon\" />,\n <span class=\"label\" part=\"label\">\n <slot />\n </span>,\n <slot name=\"badge\" />,\n ];\n\n return (\n <Host role=\"listitem\">\n {this.href && !this.disabled ? (\n <a\n class=\"link\"\n part=\"link\"\n href={this.href}\n target={this.target}\n rel={this.rel}\n aria-current={this.currentPage ? 'page' : null}\n >\n {content}\n </a>\n ) : (\n <span\n class=\"link\"\n part=\"link\"\n aria-current={this.currentPage ? 'page' : null}\n aria-disabled={this.disabled ? 'true' : null}\n >\n {content}\n </span>\n )}\n </Host>\n );\n }\n}\n"],"names":[],"mappings":";;AAAA,MAAM,YAAY,GAAG,MAAM,CAAC,0hDAA0hD,CAAC;;MC+B1iD,SAAS,GAAA,MAAA;;;;;;AAEK,IAAA,IAAI;;AAGrB,IAAA,MAAM;;AAGN,IAAA,GAAG;AAEX;;;;;;;AAOG;IACsB,OAAO,GAAG,KAAK;AAExC;;;;;;;;;;;;;;AAcG;AACM,IAAA,cAAc;IAGvB,mBAAmB,GAAA;AACjB,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE;;AAG5B;;;;;AAKG;IACqC,WAAW,GAAG,KAAK;AAE3D;;;;;;;AAOG;IACsB,QAAQ,GAAG,KAAK;;IAGD,WAAW,GAA8B,YAAY;IAE7F,MAAM,GAAA;AACJ,QAAA,MAAM,OAAO,GAAG;AACd,YAAA,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,IAAI,EAAC,MAAM,EAAA,CAAG;YACpB,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAA,EAC9B,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,CAAQ,CACH;AACP,YAAA,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,IAAI,EAAC,OAAO,EAAA,CAAG;SACtB;AAED,QAAA,QACE,EAAC,IAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAC,IAAI,EAAC,UAAU,EAAA,EAClB,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,IAC1B,CAAA,CAAA,GAAA,EAAA,EACE,KAAK,EAAC,MAAM,EACZ,IAAI,EAAC,MAAM,EACX,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,GAAG,EAAE,IAAI,CAAC,GAAG,EAAA,cAAA,EACC,IAAI,CAAC,WAAW,GAAG,MAAM,GAAG,IAAI,IAE7C,OAAO,CACN,KAEJ,CAAA,CAAA,MAAA,EAAA,EACE,KAAK,EAAC,MAAM,EACZ,IAAI,EAAC,MAAM,EAAA,cAAA,EACG,IAAI,CAAC,WAAW,GAAG,MAAM,GAAG,IAAI,EAAA,eAAA,EAC/B,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,IAAI,EAAA,EAE3C,OAAO,CACH,CACR,CACI;;;;;;;;;;;;"}
@@ -3,6 +3,7 @@ import { c as composeDescribedBy } from './aria-DfpCerXM.js';
3
3
  import { K as Keys } from './keys-g4FlTDZx.js';
4
4
  import { p as parseNumberValue, r as roundToStep, s as stepNumber, f as formatNumberValue, c as clampNumber } from './number-field-DSXauhXX.js';
5
5
  import { a as applyControlValidity } from './form-validity-Cr6IXrUk.js';
6
+ import { c as controlAriaLabel } from './control-label-Cy_kHPeC.js';
6
7
 
7
8
  const pfNumberInputCss = () => `:host{display:block}:host([hidden]){display:none}.field{display:grid;gap:var(--space-2)}.label{color:var(--pf-numberinput-field-label, var(--pf-field-label));font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.required{color:var(--pf-field-required);margin-inline-start:var(--space-1)}.control{align-items:stretch;background:var(--pf-numberinput-bg);border:1px solid var(--pf-numberinput-border);border-radius:var(--radius-md);display:inline-flex;min-height:40px;overflow:hidden;transition:border var(--pf-transition-fast), box-shadow var(--pf-transition-fast);width:100%}.control:focus-within{border-color:var(--pf-numberinput-focus-border);box-shadow:var(--pf-numberinput-focus-ring, var(--pf-focus-ring))}.control--invalid{border-color:var(--pf-numberinput-invalid-border)}:host([disabled]) .control{background:var(--pf-control-bg-disabled);border-color:var(--pf-control-border-disabled);color:var(--pf-control-text-disabled);opacity:0.6}.input{background:transparent;border:none;color:var(--pf-numberinput-text);flex:1;font:inherit;min-width:0;outline:none;padding:0 var(--space-3);text-align:center;width:100%}.input::placeholder{color:var(--pf-numberinput-placeholder)}.input:disabled{cursor:not-allowed}.step{align-items:center;align-self:stretch;background:var(--pf-numberinput-step-bg);border:none;color:var(--pf-numberinput-step-text);cursor:pointer;display:inline-flex;flex-shrink:0;justify-content:center;padding:0;transition:background var(--pf-transition-fast), color var(--pf-transition-fast);width:40px}.step:hover:not(:disabled){background:var(--pf-numberinput-step-hover-bg);color:var(--pf-numberinput-step-hover-text)}.step:disabled{cursor:not-allowed;opacity:0.45}[part='decrement']{border-inline-end:1px solid var(--pf-numberinput-border)}[part='increment']{border-inline-start:1px solid var(--pf-numberinput-border)}.step pf-icon{font-size:16px}.description{color:var(--pf-numberinput-field-description, var(--pf-field-description));font-size:var(--font-size-sm);margin:0}.error{color:var(--pf-field-error);font-size:var(--font-size-sm);margin:0}@media (prefers-reduced-motion: reduce){.control,.step{transition:none}}`;
8
9
 
@@ -166,7 +167,7 @@ const PfNumberInput = class {
166
167
  const describedBy = composeDescribedBy(this.description && 'description', this.error && 'error');
167
168
  const { min, max } = this.bounds;
168
169
  const shown = this.draft ?? formatNumberValue(this.current);
169
- return (h(Host, { key: 'b873ad5d26191b9589a3f67432f911f57a3db2cc' }, h("div", { key: '1fe3503ee61589e6cd9ebe683c937665b934fc8e', class: "field", part: "field" }, this.label && (h("label", { key: '7d9da068ca611a068b89e5292238852f2d40ba53', class: "label", part: "label", htmlFor: "input" }, this.label, this.required && (h("span", { key: 'bfb6e221092438b3ccef19dfe811767f4d2f3a5d', class: "required", "aria-hidden": "true" }, "*")))), h("div", { key: '7bb8c35312b4d30e1b09fefa78f752c6791a34f9', class: { control: true, 'control--invalid': Boolean(this.error) }, part: "control" }, h("button", { key: 'ff991dc6a65ca1fc5984e5b260b7b9c77def5d49', type: "button", class: "step", part: "decrement", "aria-label": this.decrementLabel, disabled: this.disabled || this.atMin, tabindex: "-1", onMouseDown: (event) => event.preventDefault(), onClick: () => this.step_(-1) }, h("pf-icon", { key: '4d65e8eda2958a1e9a7308a3b23f2f3bcf9083cf', name: "minus", "aria-hidden": "true" })), h("input", { key: '4a7db9fb97f9cdf12c4228ff47079f2cecadf7d8', id: "input", part: "input", class: "input", type: "text", inputMode: "decimal", role: "spinbutton", name: this.name, value: shown, placeholder: this.placeholder, required: this.required, disabled: this.disabled, autocomplete: "off", "aria-invalid": this.error ? 'true' : null, "aria-describedby": describedBy, "aria-valuenow": this.current ?? null, "aria-valuemin": Number.isFinite(min) ? min : null, "aria-valuemax": Number.isFinite(max) ? max : null, onInput: this.onInput, onBlur: this.onBlur, onKeyDown: this.onKeyDown }), h("button", { key: '436e0a6557aef36b2bd59b7f0cee8d0a08636c53', type: "button", class: "step", part: "increment", "aria-label": this.incrementLabel, disabled: this.disabled || this.atMax, tabindex: "-1", onMouseDown: (event) => event.preventDefault(), onClick: () => this.step_(1) }, h("pf-icon", { key: '0ae5162f3d63f69c135cc9991c9d02aaf3ac86ea', name: "plus", "aria-hidden": "true" }))), this.description && (h("p", { key: '6c958dd2bdeb22310d6c422d1757f4938687513c', class: "description", part: "description", id: "description" }, this.description)), this.error && (h("p", { key: 'f8ea4d36f4941251e63cdfdc127fd08d3bb55ae4', class: "error", part: "error", id: "error" }, this.error)))));
170
+ return (h(Host, { key: '27f7f45a2732cbca6d252f4b9128901ed7868663' }, h("div", { key: '75bfab2f72a83b830fd960e5fae19b9941eeae6c', class: "field", part: "field" }, this.label && (h("label", { key: 'f2e60206f153933cde6b36a23c510225bd5fb2ab', class: "label", part: "label", htmlFor: "input" }, this.label, this.required && (h("span", { key: '3925b4690d5b560190aaa04e7e7cf83453c7c49e', class: "required", "aria-hidden": "true" }, "*")))), h("div", { key: 'dcf1949c7fd8626c5a334fd3d72d8c4544369b41', class: { control: true, 'control--invalid': Boolean(this.error) }, part: "control" }, h("button", { key: '03e3592fa8ff57a23e3675c475e7a66908af6cc3', type: "button", class: "step", part: "decrement", "aria-label": this.decrementLabel, disabled: this.disabled || this.atMin, tabindex: "-1", onMouseDown: (event) => event.preventDefault(), onClick: () => this.step_(-1) }, h("pf-icon", { key: '157e45ebe127230052c34215c3f88d487dacd41a', name: "minus", "aria-hidden": "true" })), h("input", { key: '6fb05cb46de22b37387a16869f93b31b2ea6cc0a', id: "input", "aria-label": controlAriaLabel(this.el, this.label), part: "input", class: "input", type: "text", inputMode: "decimal", role: "spinbutton", name: this.name, value: shown, placeholder: this.placeholder, required: this.required, disabled: this.disabled, autocomplete: "off", "aria-invalid": this.error ? 'true' : null, "aria-describedby": describedBy, "aria-valuenow": this.current ?? null, "aria-valuemin": Number.isFinite(min) ? min : null, "aria-valuemax": Number.isFinite(max) ? max : null, onInput: this.onInput, onBlur: this.onBlur, onKeyDown: this.onKeyDown }), h("button", { key: '9b6eeddb4884a2961ac5a5cfe6a406111635cf79', type: "button", class: "step", part: "increment", "aria-label": this.incrementLabel, disabled: this.disabled || this.atMax, tabindex: "-1", onMouseDown: (event) => event.preventDefault(), onClick: () => this.step_(1) }, h("pf-icon", { key: '2a97e66ca7bf42c6d10a872c4b8eec52316d0784', name: "plus", "aria-hidden": "true" }))), this.description && (h("p", { key: '3943b0c1ec5ad58d749b0e6d1fb5f60a17eb917e', class: "description", part: "description", id: "description" }, this.description)), this.error && (h("p", { key: '5aafabcd042976f000f906e6c16fc3eb45d57bf6', class: "error", part: "error", id: "error" }, this.error)))));
170
171
  }
171
172
  static get delegatesFocus() { return true; }
172
173
  static get formAssociated() { return true; }
@@ -1 +1 @@
1
- {"version":3,"file":"pf-number-input.entry.js","sources":["src/components/pf-number-input/pf-number-input.css?tag=pf-number-input&encapsulation=shadow","src/components/pf-number-input/pf-number-input.tsx"],"sourcesContent":[":host {\n display: block;\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.field {\n display: grid;\n gap: var(--space-2);\n}\n\n.label {\n color: var(--pf-numberinput-field-label, var(--pf-field-label));\n font-size: var(--font-size-sm);\n font-weight: var(--font-weight-medium);\n}\n\n.required {\n color: var(--pf-field-required);\n margin-inline-start: var(--space-1);\n}\n\n.control {\n align-items: stretch;\n background: var(--pf-numberinput-bg);\n border: 1px solid var(--pf-numberinput-border);\n border-radius: var(--radius-md);\n display: inline-flex;\n min-height: 40px;\n overflow: hidden;\n transition:\n border var(--pf-transition-fast),\n box-shadow var(--pf-transition-fast);\n width: 100%;\n}\n\n.control:focus-within {\n border-color: var(--pf-numberinput-focus-border);\n box-shadow: var(--pf-numberinput-focus-ring, var(--pf-focus-ring));\n}\n\n.control--invalid {\n border-color: var(--pf-numberinput-invalid-border);\n}\n\n/*\n * `:host([disabled])` rather than the React component's\n * `:has(.input:disabled)`: the host carries the reflected attribute, which is\n * both simpler and the thing a consumer's own stylesheet can see.\n */\n:host([disabled]) .control {\n background: var(--pf-control-bg-disabled);\n border-color: var(--pf-control-border-disabled);\n color: var(--pf-control-text-disabled);\n opacity: 0.6;\n}\n\n.input {\n background: transparent;\n border: none;\n color: var(--pf-numberinput-text);\n flex: 1;\n font: inherit;\n min-width: 0;\n outline: none;\n padding: 0 var(--space-3);\n text-align: center;\n width: 100%;\n}\n\n.input::placeholder {\n color: var(--pf-numberinput-placeholder);\n}\n\n.input:disabled {\n cursor: not-allowed;\n}\n\n.step {\n align-items: center;\n align-self: stretch;\n background: var(--pf-numberinput-step-bg);\n border: none;\n color: var(--pf-numberinput-step-text);\n cursor: pointer;\n display: inline-flex;\n flex-shrink: 0;\n justify-content: center;\n padding: 0;\n transition:\n background var(--pf-transition-fast),\n color var(--pf-transition-fast);\n width: 40px;\n}\n\n.step:hover:not(:disabled) {\n background: var(--pf-numberinput-step-hover-bg);\n color: var(--pf-numberinput-step-hover-text);\n}\n\n.step:disabled {\n cursor: not-allowed;\n opacity: 0.45;\n}\n\n[part='decrement'] {\n border-inline-end: 1px solid var(--pf-numberinput-border);\n}\n\n[part='increment'] {\n border-inline-start: 1px solid var(--pf-numberinput-border);\n}\n\n.step pf-icon {\n font-size: 16px;\n}\n\n.description {\n color: var(--pf-numberinput-field-description, var(--pf-field-description));\n font-size: var(--font-size-sm);\n margin: 0;\n}\n\n.error {\n color: var(--pf-field-error);\n font-size: var(--font-size-sm);\n margin: 0;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .control,\n .step {\n transition: none;\n }\n}\n","import {\n clampNumber,\n composeDescribedBy,\n formatNumberValue,\n Keys,\n parseNumberValue,\n roundToStep,\n stepNumber,\n} from '@pitchfork-ui/core';\nimport {\n AttachInternals,\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\n\nimport { applyControlValidity } from '../../form-validity';\n\n/**\n * A form-associated stepper field.\n *\n * The value is a **string** rather than a number, because that is what an\n * attribute can carry and what a form submits; `pfChange` reports the parsed\n * number beside it, which is what a framework consumer wants. An empty string\n * is an empty field — not zero, which is a value someone chose.\n *\n * All of the arithmetic is core's, so this and the React `NumberInput` step,\n * round and clamp identically: ten steps of `0.1` reach exactly 1 in both.\n *\n * @part field - the wrapper around label, control and messages.\n * @part label - the label element.\n * @part control - the box holding the steppers and the input.\n * @part decrement - the step-down button.\n * @part input - the native input.\n * @part increment - the step-up button.\n * @part description - the hint text below the control.\n * @part error - the error message below the control.\n */\n@Component({\n tag: 'pf-number-input',\n styleUrl: 'pf-number-input.css',\n formAssociated: true,\n shadow: { delegatesFocus: true },\n})\nexport class PfNumberInput {\n @Element() el!: HTMLElement;\n\n @AttachInternals() internals!: ElementInternals;\n\n /**\n * Submitted under this name. Reflected, because a form-associated element\n * takes its submission name from the attribute, not this property.\n */\n @Prop({ reflect: true }) name?: string;\n\n /** The value, as a string. Empty means an empty field. */\n @Prop({ mutable: true }) value = '';\n\n /** The lowest value the field accepts. */\n @Prop() min?: number;\n\n /** The highest value the field accepts. */\n @Prop() max?: number;\n\n /** How far one step moves, and what the result is rounded to. */\n @Prop() step = 1;\n\n /** Visible label. Rendered in the same root as the input, so `for` works. */\n @Prop() label?: string;\n\n /** Hint text below the control. */\n @Prop() description?: string;\n\n /** Error message. Its presence is what marks the control invalid. */\n @Prop() error?: string;\n\n @Prop() placeholder?: string;\n\n @Prop({ reflect: true }) required = false;\n\n @Prop({ reflect: true }) disabled = false;\n\n /** The step-down button's accessible name. */\n @Prop() decrementLabel = 'Decrease';\n\n /** The step-up button's accessible name. */\n @Prop() incrementLabel = 'Increase';\n\n /** Fires when the value changes, with the parsed number beside the string. */\n @Event() pfChange!: EventEmitter<{ value: string; number: number | null }>;\n\n /**\n * What the input shows while it is being edited, which is not always the\n * value: a half-typed \"-\" or \"1.\" is neither a number nor a reason to throw\n * the keystroke away.\n */\n @State() draft: string | null = null;\n\n /** The value a form reset restores, which is the initial attribute. */\n private initialValue = '';\n\n componentWillLoad() {\n this.initialValue = this.value ?? '';\n this.syncFormState();\n }\n\n @Watch('value')\n @Watch('error')\n @Watch('required')\n syncFormState() {\n this.internals.setFormValue(this.value ?? '');\n applyControlValidity(this.internals, Boolean(this.value), this.required, this.error);\n }\n\n /** A form-associated custom element does not inherit this. */\n @Method()\n async checkValidity(): Promise<boolean> {\n return this.internals.checkValidity();\n }\n\n /** As `checkValidity`, but also shows the browser's validation message. */\n @Method()\n async reportValidity(): Promise<boolean> {\n return this.internals.reportValidity();\n }\n\n /** The message explaining why the control is invalid, or an empty string. */\n @Method()\n async getValidationMessage(): Promise<string> {\n return this.internals.validationMessage;\n }\n\n /** A reset restores the value the field started with. */\n formResetCallback() {\n this.value = this.initialValue;\n this.draft = null;\n }\n\n /** Steps the value up or down, as the buttons and the arrows do. */\n @Method()\n async stepBy(direction: 1 | -1): Promise<void> {\n this.step_(direction);\n }\n\n private get bounds() {\n return {\n min: this.min === undefined ? -Infinity : Number(this.min),\n max: this.max === undefined ? Infinity : Number(this.max),\n step: Number(this.step) || 1,\n };\n }\n\n private get current(): number | null {\n return parseNumberValue(this.value);\n }\n\n private get atMin(): boolean {\n const { min } = this.bounds;\n return this.current !== null && this.current <= min;\n }\n\n private get atMax(): boolean {\n const { max } = this.bounds;\n return this.current !== null && this.current >= max;\n }\n\n private commit(next: number | null) {\n const { min, max, step } = this.bounds;\n const value = next === null ? '' : String(roundToStep(clampNumber(next, min, max), step));\n if (value === this.value) return;\n\n this.value = value;\n this.pfChange.emit({ value, number: parseNumberValue(value) });\n }\n\n private step_(direction: 1 | -1) {\n if (this.disabled) return;\n this.draft = null;\n this.commit(stepNumber(this.current, direction, this.bounds));\n }\n\n private onInput = (event: Event) => {\n const raw = (event.target as HTMLInputElement).value;\n /*\n * The draft is kept as typed and the value follows it, rather than the\n * input being rewritten from the value: clamping mid-keystroke would make\n * \"5\" unreachable in a field whose minimum is 50, and rounding would eat\n * the \".\" of \"1.5\" as it was typed.\n */\n this.draft = raw;\n const parsed = parseNumberValue(raw);\n if (raw.trim() === '') {\n this.commit(null);\n return;\n }\n if (parsed !== null) this.commit(parsed);\n };\n\n /** On blur the draft is given up, so the field shows its real value. */\n private onBlur = () => {\n this.draft = null;\n };\n\n private onKeyDown = (event: KeyboardEvent) => {\n if (this.disabled) return;\n const { min, max } = this.bounds;\n\n if (event.key === Keys.ArrowUp) {\n event.preventDefault();\n this.step_(1);\n } else if (event.key === Keys.ArrowDown) {\n event.preventDefault();\n this.step_(-1);\n } else if (event.key === Keys.Home && Number.isFinite(min)) {\n event.preventDefault();\n this.draft = null;\n this.commit(min);\n } else if (event.key === Keys.End && Number.isFinite(max)) {\n event.preventDefault();\n this.draft = null;\n this.commit(max);\n }\n };\n\n render() {\n // IDs are scoped to this shadow root, so they can be literal.\n const describedBy = composeDescribedBy(\n this.description && 'description',\n this.error && 'error',\n );\n const { min, max } = this.bounds;\n const shown = this.draft ?? formatNumberValue(this.current);\n\n return (\n <Host>\n <div class=\"field\" part=\"field\">\n {this.label && (\n <label class=\"label\" part=\"label\" htmlFor=\"input\">\n {this.label}\n {this.required && (\n <span class=\"required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <div class={{ control: true, 'control--invalid': Boolean(this.error) }} part=\"control\">\n {/*\n The steppers are out of the tab order and the arrows are on the\n input, which is the spinbutton pattern: a keyboard user steps\n without leaving the field. `mousedown` is prevented so a click\n does not take focus off it either.\n */}\n <button\n type=\"button\"\n class=\"step\"\n part=\"decrement\"\n aria-label={this.decrementLabel}\n disabled={this.disabled || this.atMin}\n tabindex=\"-1\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => this.step_(-1)}\n >\n <pf-icon name=\"minus\" aria-hidden=\"true\"></pf-icon>\n </button>\n\n <input\n id=\"input\"\n part=\"input\"\n class=\"input\"\n type=\"text\"\n inputMode=\"decimal\"\n role=\"spinbutton\"\n name={this.name}\n value={shown}\n placeholder={this.placeholder}\n required={this.required}\n disabled={this.disabled}\n autocomplete=\"off\"\n aria-invalid={this.error ? 'true' : null}\n aria-describedby={describedBy}\n aria-valuenow={this.current ?? null}\n aria-valuemin={Number.isFinite(min) ? min : null}\n aria-valuemax={Number.isFinite(max) ? max : null}\n onInput={this.onInput}\n onBlur={this.onBlur}\n onKeyDown={this.onKeyDown}\n />\n\n <button\n type=\"button\"\n class=\"step\"\n part=\"increment\"\n aria-label={this.incrementLabel}\n disabled={this.disabled || this.atMax}\n tabindex=\"-1\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => this.step_(1)}\n >\n <pf-icon name=\"plus\" aria-hidden=\"true\"></pf-icon>\n </button>\n </div>\n\n {this.description && (\n <p class=\"description\" part=\"description\" id=\"description\">\n {this.description}\n </p>\n )}\n {this.error && (\n <p class=\"error\" part=\"error\" id=\"error\">\n {this.error}\n </p>\n )}\n </div>\n </Host>\n );\n }\n}\n"],"names":[],"mappings":";;;;;;AAAA,MAAM,gBAAgB,GAAG,MAAM,CAAC,qnEAAqnE,CAAC;;MCmDzoE,aAAa,GAAA,MAAA;;;;;;;;;;;;;AAGL,IAAA,SAAS;AAE5B;;;AAGG;AACsB,IAAA,IAAI;;IAGJ,KAAK,GAAG,EAAE;;AAG3B,IAAA,GAAG;;AAGH,IAAA,GAAG;;IAGH,IAAI,GAAG,CAAC;;AAGR,IAAA,KAAK;;AAGL,IAAA,WAAW;;AAGX,IAAA,KAAK;AAEL,IAAA,WAAW;IAEM,QAAQ,GAAG,KAAK;IAEhB,QAAQ,GAAG,KAAK;;IAGjC,cAAc,GAAG,UAAU;;IAG3B,cAAc,GAAG,UAAU;;AAG1B,IAAA,QAAQ;AAEjB;;;;AAIG;IACM,KAAK,GAAkB,IAAI;;IAG5B,YAAY,GAAG,EAAE;IAEzB,iBAAiB,GAAA;QACf,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE;QACpC,IAAI,CAAC,aAAa,EAAE;;IAMtB,aAAa,GAAA;QACX,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,oBAAoB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC;;;AAKtF,IAAA,MAAM,aAAa,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE;;;AAKvC,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE;;;AAKxC,IAAA,MAAM,oBAAoB,GAAA;AACxB,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,iBAAiB;;;IAIzC,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY;AAC9B,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;;;IAKnB,MAAM,MAAM,CAAC,SAAiB,EAAA;AAC5B,QAAA,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;;AAGvB,IAAA,IAAY,MAAM,GAAA;QAChB,OAAO;AACL,YAAA,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,SAAS,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;AAC1D,YAAA,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;YACzD,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7B;;AAGH,IAAA,IAAY,OAAO,GAAA;AACjB,QAAA,OAAO,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;;AAGrC,IAAA,IAAY,KAAK,GAAA;AACf,QAAA,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM;QAC3B,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,GAAG;;AAGrD,IAAA,IAAY,KAAK,GAAA;AACf,QAAA,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM;QAC3B,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,GAAG;;AAG7C,IAAA,MAAM,CAAC,IAAmB,EAAA;QAChC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM;AACtC,QAAA,MAAM,KAAK,GAAG,IAAI,KAAK,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AACzF,QAAA,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK;YAAE;AAE1B,QAAA,IAAI,CAAC,KAAK,GAAG,KAAK;AAClB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;;AAGxD,IAAA,KAAK,CAAC,SAAiB,EAAA;QAC7B,IAAI,IAAI,CAAC,QAAQ;YAAE;AACnB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,QAAA,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;;AAGvD,IAAA,OAAO,GAAG,CAAC,KAAY,KAAI;AACjC,QAAA,MAAM,GAAG,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK;AACpD;;;;;AAKG;AACH,QAAA,IAAI,CAAC,KAAK,GAAG,GAAG;AAChB,QAAA,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC;AACpC,QAAA,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;AACrB,YAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACjB;;QAEF,IAAI,MAAM,KAAK,IAAI;AAAE,YAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;AAC1C,KAAC;;IAGO,MAAM,GAAG,MAAK;AACpB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACnB,KAAC;AAEO,IAAA,SAAS,GAAG,CAAC,KAAoB,KAAI;QAC3C,IAAI,IAAI,CAAC,QAAQ;YAAE;QACnB,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM;QAEhC,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,OAAO,EAAE;YAC9B,KAAK,CAAC,cAAc,EAAE;AACtB,YAAA,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;;aACR,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,SAAS,EAAE;YACvC,KAAK,CAAC,cAAc,EAAE;AACtB,YAAA,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;;AACT,aAAA,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YAC1D,KAAK,CAAC,cAAc,EAAE;AACtB,YAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;;AACX,aAAA,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YACzD,KAAK,CAAC,cAAc,EAAE;AACtB,YAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;;AAEpB,KAAC;IAED,MAAM,GAAA;;AAEJ,QAAA,MAAM,WAAW,GAAG,kBAAkB,CACpC,IAAI,CAAC,WAAW,IAAI,aAAa,EACjC,IAAI,CAAC,KAAK,IAAI,OAAO,CACtB;QACD,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM;AAChC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC;QAE3D,QACE,EAAC,IAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,EACH,CAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAK,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAA,EAC5B,IAAI,CAAC,KAAK,KACT,8DAAO,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAC,OAAO,EAAA,EAC9C,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,QAAQ,KACZ,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,KAAK,EAAC,UAAU,EAAA,aAAA,EAAa,MAAM,EAAA,EAAA,GAAA,CAElC,CACR,CACK,CACT,EAED,CAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAK,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAC,SAAS,EAAA,EAOpF,CAAA,CAAA,QAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EACE,IAAI,EAAC,QAAQ,EACb,KAAK,EAAC,MAAM,EACZ,IAAI,EAAC,WAAW,EAAA,YAAA,EACJ,IAAI,CAAC,cAAc,EAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EACrC,QAAQ,EAAC,IAAI,EACb,WAAW,EAAE,CAAC,KAAK,KAAK,KAAK,CAAC,cAAc,EAAE,EAC9C,OAAO,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAA,EAE7B,CAAA,CAAA,SAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAS,IAAI,EAAC,OAAO,EAAA,aAAA,EAAa,MAAM,GAAW,CAC5C,EAET,CAAA,CAAA,OAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EACE,EAAE,EAAC,OAAO,EACV,IAAI,EAAC,OAAO,EACZ,KAAK,EAAC,OAAO,EACb,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,SAAS,EACnB,IAAI,EAAC,YAAY,EACjB,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,IAAI,CAAC,WAAW,EAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,YAAY,EAAC,KAAK,EAAA,cAAA,EACJ,IAAI,CAAC,KAAK,GAAG,MAAM,GAAG,IAAI,EAAA,kBAAA,EACtB,WAAW,EAAA,eAAA,EACd,IAAI,CAAC,OAAO,IAAI,IAAI,EAAA,eAAA,EACpB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,IAAI,EAAA,eAAA,EACjC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,IAAI,EAChD,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,SAAS,EAAE,IAAI,CAAC,SAAS,EAAA,CACzB,EAEF,CAAA,CAAA,QAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EACE,IAAI,EAAC,QAAQ,EACb,KAAK,EAAC,MAAM,EACZ,IAAI,EAAC,WAAW,EAAA,YAAA,EACJ,IAAI,CAAC,cAAc,EAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EACrC,QAAQ,EAAC,IAAI,EACb,WAAW,EAAE,CAAC,KAAK,KAAK,KAAK,CAAC,cAAc,EAAE,EAC9C,OAAO,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAA,EAE5B,CAAA,CAAA,SAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAS,IAAI,EAAC,MAAM,iBAAa,MAAM,EAAA,CAAW,CAC3C,CACL,EAEL,IAAI,CAAC,WAAW,KACf,0DAAG,KAAK,EAAC,aAAa,EAAC,IAAI,EAAC,aAAa,EAAC,EAAE,EAAC,aAAa,IACvD,IAAI,CAAC,WAAW,CACf,CACL,EACA,IAAI,CAAC,KAAK,KACT,CAAA,CAAA,GAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAG,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAC,EAAE,EAAC,OAAO,EAAA,EACrC,IAAI,CAAC,KAAK,CACT,CACL,CACG,CACD;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"pf-number-input.entry.js","sources":["src/components/pf-number-input/pf-number-input.css?tag=pf-number-input&encapsulation=shadow","src/components/pf-number-input/pf-number-input.tsx"],"sourcesContent":[":host {\n display: block;\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.field {\n display: grid;\n gap: var(--space-2);\n}\n\n.label {\n color: var(--pf-numberinput-field-label, var(--pf-field-label));\n font-size: var(--font-size-sm);\n font-weight: var(--font-weight-medium);\n}\n\n.required {\n color: var(--pf-field-required);\n margin-inline-start: var(--space-1);\n}\n\n.control {\n align-items: stretch;\n background: var(--pf-numberinput-bg);\n border: 1px solid var(--pf-numberinput-border);\n border-radius: var(--radius-md);\n display: inline-flex;\n min-height: 40px;\n overflow: hidden;\n transition:\n border var(--pf-transition-fast),\n box-shadow var(--pf-transition-fast);\n width: 100%;\n}\n\n.control:focus-within {\n border-color: var(--pf-numberinput-focus-border);\n box-shadow: var(--pf-numberinput-focus-ring, var(--pf-focus-ring));\n}\n\n.control--invalid {\n border-color: var(--pf-numberinput-invalid-border);\n}\n\n/*\n * `:host([disabled])` rather than the React component's\n * `:has(.input:disabled)`: the host carries the reflected attribute, which is\n * both simpler and the thing a consumer's own stylesheet can see.\n */\n:host([disabled]) .control {\n background: var(--pf-control-bg-disabled);\n border-color: var(--pf-control-border-disabled);\n color: var(--pf-control-text-disabled);\n opacity: 0.6;\n}\n\n.input {\n background: transparent;\n border: none;\n color: var(--pf-numberinput-text);\n flex: 1;\n font: inherit;\n min-width: 0;\n outline: none;\n padding: 0 var(--space-3);\n text-align: center;\n width: 100%;\n}\n\n.input::placeholder {\n color: var(--pf-numberinput-placeholder);\n}\n\n.input:disabled {\n cursor: not-allowed;\n}\n\n.step {\n align-items: center;\n align-self: stretch;\n background: var(--pf-numberinput-step-bg);\n border: none;\n color: var(--pf-numberinput-step-text);\n cursor: pointer;\n display: inline-flex;\n flex-shrink: 0;\n justify-content: center;\n padding: 0;\n transition:\n background var(--pf-transition-fast),\n color var(--pf-transition-fast);\n width: 40px;\n}\n\n.step:hover:not(:disabled) {\n background: var(--pf-numberinput-step-hover-bg);\n color: var(--pf-numberinput-step-hover-text);\n}\n\n.step:disabled {\n cursor: not-allowed;\n opacity: 0.45;\n}\n\n[part='decrement'] {\n border-inline-end: 1px solid var(--pf-numberinput-border);\n}\n\n[part='increment'] {\n border-inline-start: 1px solid var(--pf-numberinput-border);\n}\n\n.step pf-icon {\n font-size: 16px;\n}\n\n.description {\n color: var(--pf-numberinput-field-description, var(--pf-field-description));\n font-size: var(--font-size-sm);\n margin: 0;\n}\n\n.error {\n color: var(--pf-field-error);\n font-size: var(--font-size-sm);\n margin: 0;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .control,\n .step {\n transition: none;\n }\n}\n","import {\n clampNumber,\n composeDescribedBy,\n formatNumberValue,\n Keys,\n parseNumberValue,\n roundToStep,\n stepNumber,\n} from '@pitchfork-ui/core';\nimport {\n AttachInternals,\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\n\nimport { applyControlValidity } from '../../form-validity';\nimport { controlAriaLabel } from '../../control-label';\n\n/**\n * A form-associated stepper field.\n *\n * The value is a **string** rather than a number, because that is what an\n * attribute can carry and what a form submits; `pfChange` reports the parsed\n * number beside it, which is what a framework consumer wants. An empty string\n * is an empty field — not zero, which is a value someone chose.\n *\n * All of the arithmetic is core's, so this and the React `NumberInput` step,\n * round and clamp identically: ten steps of `0.1` reach exactly 1 in both.\n *\n * @part field - the wrapper around label, control and messages.\n * @part label - the label element.\n * @part control - the box holding the steppers and the input.\n * @part decrement - the step-down button.\n * @part input - the native input.\n * @part increment - the step-up button.\n * @part description - the hint text below the control.\n * @part error - the error message below the control.\n */\n@Component({\n tag: 'pf-number-input',\n styleUrl: 'pf-number-input.css',\n formAssociated: true,\n shadow: { delegatesFocus: true },\n})\nexport class PfNumberInput {\n @Element() el!: HTMLElement;\n\n @AttachInternals() internals!: ElementInternals;\n\n /**\n * Submitted under this name. Reflected, because a form-associated element\n * takes its submission name from the attribute, not this property.\n */\n @Prop({ reflect: true }) name?: string;\n\n /** The value, as a string. Empty means an empty field. */\n @Prop({ mutable: true }) value = '';\n\n /** The lowest value the field accepts. */\n @Prop() min?: number;\n\n /** The highest value the field accepts. */\n @Prop() max?: number;\n\n /** How far one step moves, and what the result is rounded to. */\n @Prop() step = 1;\n\n /** Visible label. Rendered in the same root as the input, so `for` works. */\n @Prop() label?: string;\n\n /** Hint text below the control. */\n @Prop() description?: string;\n\n /** Error message. Its presence is what marks the control invalid. */\n @Prop() error?: string;\n\n @Prop() placeholder?: string;\n\n @Prop({ reflect: true }) required = false;\n\n @Prop({ reflect: true }) disabled = false;\n\n /** The step-down button's accessible name. */\n @Prop() decrementLabel = 'Decrease';\n\n /** The step-up button's accessible name. */\n @Prop() incrementLabel = 'Increase';\n\n /** Fires when the value changes, with the parsed number beside the string. */\n @Event() pfChange!: EventEmitter<{ value: string; number: number | null }>;\n\n /**\n * What the input shows while it is being edited, which is not always the\n * value: a half-typed \"-\" or \"1.\" is neither a number nor a reason to throw\n * the keystroke away.\n */\n @State() draft: string | null = null;\n\n /** The value a form reset restores, which is the initial attribute. */\n private initialValue = '';\n\n componentWillLoad() {\n this.initialValue = this.value ?? '';\n this.syncFormState();\n }\n\n @Watch('value')\n @Watch('error')\n @Watch('required')\n syncFormState() {\n this.internals.setFormValue(this.value ?? '');\n applyControlValidity(this.internals, Boolean(this.value), this.required, this.error);\n }\n\n /** A form-associated custom element does not inherit this. */\n @Method()\n async checkValidity(): Promise<boolean> {\n return this.internals.checkValidity();\n }\n\n /** As `checkValidity`, but also shows the browser's validation message. */\n @Method()\n async reportValidity(): Promise<boolean> {\n return this.internals.reportValidity();\n }\n\n /** The message explaining why the control is invalid, or an empty string. */\n @Method()\n async getValidationMessage(): Promise<string> {\n return this.internals.validationMessage;\n }\n\n /** A reset restores the value the field started with. */\n formResetCallback() {\n this.value = this.initialValue;\n this.draft = null;\n }\n\n /** Steps the value up or down, as the buttons and the arrows do. */\n @Method()\n async stepBy(direction: 1 | -1): Promise<void> {\n this.step_(direction);\n }\n\n private get bounds() {\n return {\n min: this.min === undefined ? -Infinity : Number(this.min),\n max: this.max === undefined ? Infinity : Number(this.max),\n step: Number(this.step) || 1,\n };\n }\n\n private get current(): number | null {\n return parseNumberValue(this.value);\n }\n\n private get atMin(): boolean {\n const { min } = this.bounds;\n return this.current !== null && this.current <= min;\n }\n\n private get atMax(): boolean {\n const { max } = this.bounds;\n return this.current !== null && this.current >= max;\n }\n\n private commit(next: number | null) {\n const { min, max, step } = this.bounds;\n const value = next === null ? '' : String(roundToStep(clampNumber(next, min, max), step));\n if (value === this.value) return;\n\n this.value = value;\n this.pfChange.emit({ value, number: parseNumberValue(value) });\n }\n\n private step_(direction: 1 | -1) {\n if (this.disabled) return;\n this.draft = null;\n this.commit(stepNumber(this.current, direction, this.bounds));\n }\n\n private onInput = (event: Event) => {\n const raw = (event.target as HTMLInputElement).value;\n /*\n * The draft is kept as typed and the value follows it, rather than the\n * input being rewritten from the value: clamping mid-keystroke would make\n * \"5\" unreachable in a field whose minimum is 50, and rounding would eat\n * the \".\" of \"1.5\" as it was typed.\n */\n this.draft = raw;\n const parsed = parseNumberValue(raw);\n if (raw.trim() === '') {\n this.commit(null);\n return;\n }\n if (parsed !== null) this.commit(parsed);\n };\n\n /** On blur the draft is given up, so the field shows its real value. */\n private onBlur = () => {\n this.draft = null;\n };\n\n private onKeyDown = (event: KeyboardEvent) => {\n if (this.disabled) return;\n const { min, max } = this.bounds;\n\n if (event.key === Keys.ArrowUp) {\n event.preventDefault();\n this.step_(1);\n } else if (event.key === Keys.ArrowDown) {\n event.preventDefault();\n this.step_(-1);\n } else if (event.key === Keys.Home && Number.isFinite(min)) {\n event.preventDefault();\n this.draft = null;\n this.commit(min);\n } else if (event.key === Keys.End && Number.isFinite(max)) {\n event.preventDefault();\n this.draft = null;\n this.commit(max);\n }\n };\n\n render() {\n // IDs are scoped to this shadow root, so they can be literal.\n const describedBy = composeDescribedBy(\n this.description && 'description',\n this.error && 'error',\n );\n const { min, max } = this.bounds;\n const shown = this.draft ?? formatNumberValue(this.current);\n\n return (\n <Host>\n <div class=\"field\" part=\"field\">\n {this.label && (\n <label class=\"label\" part=\"label\" htmlFor=\"input\">\n {this.label}\n {this.required && (\n <span class=\"required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <div class={{ control: true, 'control--invalid': Boolean(this.error) }} part=\"control\">\n {/*\n The steppers are out of the tab order and the arrows are on the\n input, which is the spinbutton pattern: a keyboard user steps\n without leaving the field. `mousedown` is prevented so a click\n does not take focus off it either.\n */}\n <button\n type=\"button\"\n class=\"step\"\n part=\"decrement\"\n aria-label={this.decrementLabel}\n disabled={this.disabled || this.atMin}\n tabindex=\"-1\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => this.step_(-1)}\n >\n <pf-icon name=\"minus\" aria-hidden=\"true\"></pf-icon>\n </button>\n\n <input\n id=\"input\"\n aria-label={controlAriaLabel(this.el, this.label)}\n part=\"input\"\n class=\"input\"\n type=\"text\"\n inputMode=\"decimal\"\n role=\"spinbutton\"\n name={this.name}\n value={shown}\n placeholder={this.placeholder}\n required={this.required}\n disabled={this.disabled}\n autocomplete=\"off\"\n aria-invalid={this.error ? 'true' : null}\n aria-describedby={describedBy}\n aria-valuenow={this.current ?? null}\n aria-valuemin={Number.isFinite(min) ? min : null}\n aria-valuemax={Number.isFinite(max) ? max : null}\n onInput={this.onInput}\n onBlur={this.onBlur}\n onKeyDown={this.onKeyDown}\n />\n\n <button\n type=\"button\"\n class=\"step\"\n part=\"increment\"\n aria-label={this.incrementLabel}\n disabled={this.disabled || this.atMax}\n tabindex=\"-1\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => this.step_(1)}\n >\n <pf-icon name=\"plus\" aria-hidden=\"true\"></pf-icon>\n </button>\n </div>\n\n {this.description && (\n <p class=\"description\" part=\"description\" id=\"description\">\n {this.description}\n </p>\n )}\n {this.error && (\n <p class=\"error\" part=\"error\" id=\"error\">\n {this.error}\n </p>\n )}\n </div>\n </Host>\n );\n }\n}\n"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import { c as composeDescribedBy } from './aria-DfpCerXM.js';
4
4
  import { i as isActivationKey, K as Keys } from './keys-g4FlTDZx.js';
5
5
  import { g as getEnabledIndexes, r as resolveListMove } from './navigation-CAz7-p8y.js';
6
6
  import { a as applyControlValidity } from './form-validity-Cr6IXrUk.js';
7
+ import { c as controlAriaLabel } from './control-label-Cy_kHPeC.js';
7
8
 
8
9
  //#region src/typeahead.ts
9
10
  /**
@@ -377,12 +378,12 @@ const PfSelect = class {
377
378
  }
378
379
  render() {
379
380
  const describedBy = composeDescribedBy(this.description && 'description', this.error && 'error');
380
- return (h(Host, { key: '24c97882ec87fd8dc346ab6b10efe9d6a23359e3' }, h("div", { key: 'd96e86483cad67270c6359f1594872f7638ec218', class: "field", part: "field" }, this.label && (h("label", { key: '92736ce6664e9b107a85008cacccaf0e8b6175d4', class: "label", part: "label", htmlFor: "trigger" }, this.label, this.required && (h("span", { key: '72c82fe29714e9c3ecca4bcad72318fb0e0dc217', class: "required", "aria-hidden": "true" }, "*")))), h("button", { key: 'c07e0f5ef7f202dc1239a6868d4c5360194889a4', id: "trigger", part: "trigger", class: { trigger: true, 'trigger--invalid': Boolean(this.error) }, type: "button", role: "combobox", disabled: this.disabled, "aria-haspopup": "listbox", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": "listbox", "aria-invalid": this.error ? 'true' : null, "aria-required": this.required ? 'true' : null, "aria-describedby": describedBy, onClick: () => {
381
+ return (h(Host, { key: 'ccb96054293516751523dc6b89d3fd3bb3e08902' }, h("div", { key: '65d6ca23015f8371f02715f1b3cf862122c94932', class: "field", part: "field" }, this.label && (h("label", { key: '580a891de1e1c60481a494ab5f915e0c8528d511', class: "label", part: "label", htmlFor: "trigger" }, this.label, this.required && (h("span", { key: 'dd0e347bcfafdca6eba7dc06f596215b47331e8f', class: "required", "aria-hidden": "true" }, "*")))), h("button", { key: '7c6b543a99a06b9d18a6339e0aa3c6ad3d2eb260', id: "trigger", "aria-label": controlAriaLabel(this.el, this.label), part: "trigger", class: { trigger: true, 'trigger--invalid': Boolean(this.error) }, type: "button", role: "combobox", disabled: this.disabled, "aria-haspopup": "listbox", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": "listbox", "aria-invalid": this.error ? 'true' : null, "aria-required": this.required ? 'true' : null, "aria-describedby": describedBy, onClick: () => {
381
382
  if (!this.disabled)
382
383
  this.open = !this.open;
383
- } }, h("span", { key: 'a745f2fcce7fd7d3e2a8d0b245d4b6e38baf934d', class: { value: true, 'value--placeholder': !this.selectedLabel } }, this.selectedLabel || this.placeholder), h("span", { key: 'f4fe94fb5877aa8b7a9442112d897368d208e108', class: "chevron", "aria-hidden": "true" }, h("pf-icon", { key: '0e9c5dbedc04f727fe9be09b56a5cebbec99607f', name: "chevron-down" }))), this.description && (h("p", { key: '80e491e4ce53b694803d0f8978af584cb418ea79', class: "description", part: "description", id: "description" }, this.description)), this.error && (h("p", { key: '1e8e8c4d46f746981f831ca8e7574f94bd9673bb', class: "error", part: "error", id: "error" }, this.error))), h("div", { key: '9daf605fa081d9e2b3f4a07e9cb41e17cd142b42', id: "listbox", part: "listbox", class: "listbox", popover: "auto", role: "listbox", "aria-label": this.label ?? this.placeholder, style: this.maxVisibleOptions
384
+ } }, h("span", { key: '032fb5d8de622dde393a5100ce69d08944916bb9', class: { value: true, 'value--placeholder': !this.selectedLabel } }, this.selectedLabel || this.placeholder), h("span", { key: 'eae5f550a6b4f16a27a044220db57236aebd31b8', class: "chevron", "aria-hidden": "true" }, h("pf-icon", { key: '7983ac569e121be6a98822cdbec4c46ae43dc99e', name: "chevron-down" }))), this.description && (h("p", { key: 'c27fc89569900855af8966fcec3246f7f12c1d20', class: "description", part: "description", id: "description" }, this.description)), this.error && (h("p", { key: '6d805181ffb58622ed41e688195bdf58511e7efa', class: "error", part: "error", id: "error" }, this.error))), h("div", { key: '2dbc1adeaf68449ffaf32fc07d694d4c66860e90', id: "listbox", part: "listbox", class: "listbox", popover: "auto", role: "listbox", "aria-label": this.label ?? this.placeholder, style: this.maxVisibleOptions
384
385
  ? { maxHeight: `calc(${this.maxVisibleOptions} * 36px)`, overflowY: 'auto' }
385
- : undefined, onToggle: this.onToggle }, h("slot", { key: 'f23712d710ef4aa13b186ef5a8f075494dc7b5ca', onSlotchange: this.onSlotChange }))));
386
+ : undefined, onToggle: this.onToggle }, h("slot", { key: '02373173990a5e9ecad005b21f1a4b11d2cef032', onSlotchange: this.onSlotChange }))));
386
387
  }
387
388
  static get formAssociated() { return true; }
388
389
  static get watchers() { return {
@@ -1 +1 @@
1
- {"version":3,"file":"pf-select.entry.js","sources":["../core/dist/typeahead.js","src/components/pf-select/pf-select.css?tag=pf-select&encapsulation=shadow","src/components/pf-select/pf-select.tsx"],"sourcesContent":["//#region src/typeahead.ts\n/**\n* Printable-character typeahead for a listbox, menu or tree.\n*\n* The ARIA listbox pattern expects it: typing `b` jumps to the next option\n* beginning with `b`, and typing `br` narrows to `br`. The React `Select` has\n* none of this — `todo.md` has the fix — so the rules live here, where\n* `<pf-select>` and every later `pf-combobox` / `pf-multi-select` /\n* `pf-tree-view` read the same ones.\n*\n* Core owns the matching; the rendering layer owns the buffer and its timer,\n* because a timer is state and core is never a state container.\n*/\n/** How long a quiet gap ends one typeahead word, in milliseconds. */\nvar TYPEAHEAD_TIMEOUT_MS = 500;\n/**\n* Whether a key should go into the buffer at all.\n*\n* One character, so `Enter`, `ArrowDown` and `Escape` are excluded by length\n* rather than by a list that would need keeping up to date. A space is\n* deliberately *not* typeahead: in a listbox it selects.\n*/\nfunction isTypeaheadKey(key) {\n\treturn key.length === 1 && key !== \" \";\n}\n/**\n* The buffer after `key`: lower-cased and appended, nothing more.\n*\n* A repeat is *not* special-cased here. Pressing `b` four times means \"the\n* fourth option starting with b\" rather than \"an option starting with bbbb\",\n* but that is a matching question, so `findTypeaheadMatch` reads it off the\n* buffer's shape instead — which keeps this function a plain append and lets\n* the caller hold one string.\n*/\nfunction nextTypeaheadBuffer(buffer, key) {\n\tif (!isTypeaheadKey(key)) return buffer;\n\treturn buffer + key.toLowerCase();\n}\n/**\n* True when the buffer is one character repeated — including just once.\n*\n* The single-character case is the important one, and requiring two got it\n* wrong: pressing `b` while already on Banana has to move to Blackberry, the\n* way a native `<select>` does, not sit still because Banana also starts with\n* `b`. Found by a browser test on `pf-select`.\n*/\nfunction isCycling(buffer) {\n\treturn buffer.length > 0 && [...buffer].every((char) => char === buffer[0]);\n}\n/**\n* The index of the option the buffer points at, or -1.\n*\n* Searches from `fromIndex` and wraps, so a match behind the current option is\n* still found. Two modes:\n*\n* - **Narrowing** (`br`): the current option is included, because typing more\n* of the label you are already on should keep you there rather than skip to\n* the next `br`.\n* - **Cycling** (`b`, `bb`, `bbb`): one character repeated, searched from\n* *after* the current option — so pressing one letter walks through the\n* options beginning with it, which is what a native `<select>` does.\n*\n* A disabled option is never matched: the keyboard would land somewhere it\n* cannot act, which is worse than not moving.\n*/\nfunction findTypeaheadMatch(labels, buffer, fromIndex = -1, isDisabled = () => false) {\n\tif (!buffer || labels.length === 0) return -1;\n\tconst cycling = isCycling(buffer);\n\tconst needle = cycling ? buffer[0] : buffer;\n\tconst start = fromIndex < 0 ? 0 : cycling ? fromIndex + 1 : fromIndex;\n\tfor (let step = 0; step < labels.length; step += 1) {\n\t\tconst index = (start + step) % labels.length;\n\t\tif (isDisabled(index)) continue;\n\t\tif (labels[index]?.trim().toLowerCase().startsWith(needle)) return index;\n\t}\n\treturn -1;\n}\n//#endregion\nexport { TYPEAHEAD_TIMEOUT_MS, findTypeaheadMatch, isTypeaheadKey, nextTypeaheadBuffer };\n","/*\n * The generic set pf-option reads, mapped to this control's own family. They\n * inherit through the shadow boundary, so a slotted option is themed by the\n * listbox it sits in without knowing which that is.\n */\n:host {\n display: block;\n --pf-option-text: var(--pf-select-input-text, var(--pf-input-text));\n --pf-option-text-disabled: var(--pf-select-input-placeholder, var(--pf-input-placeholder));\n --pf-option-active-bg: var(--pf-select-option-active-bg);\n --pf-option-active-text: var(--pf-select-option-active-text);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.field {\n display: grid;\n gap: var(--space-1);\n}\n\n.label {\n color: var(--pf-input-label-text, var(--pf-input-text));\n font-size: var(--font-size-sm);\n font-weight: var(--font-weight-medium);\n}\n\n.required {\n color: var(--pf-select-invalid-border);\n margin-inline-start: var(--space-1);\n}\n\n.trigger {\n align-items: center;\n background: var(--pf-input-bg);\n border: 1px solid var(--pf-input-border);\n border-radius: var(--radius-md);\n color: var(--pf-input-text);\n cursor: pointer;\n display: flex;\n font-family: inherit;\n font-size: var(--font-size-sm);\n gap: var(--space-2);\n justify-content: space-between;\n padding: var(--space-2) var(--space-3);\n text-align: start;\n width: 100%;\n}\n\n.trigger:hover:not(:disabled) {\n border-color: var(--pf-input-border-hover);\n}\n\n.trigger:focus-visible {\n border-color: var(--pf-select-focus-border);\n box-shadow: var(--pf-focus-ring);\n outline: none;\n}\n\n.trigger:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.trigger--invalid {\n border-color: var(--pf-select-invalid-border);\n}\n\n.value {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.value--placeholder {\n color: var(--pf-input-placeholder);\n}\n\n.chevron {\n align-items: center;\n display: inline-flex;\n flex-shrink: 0;\n transition: transform var(--pf-transition-fast);\n}\n\n:host([open]) .chevron {\n transform: rotate(180deg);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .chevron {\n transition: none;\n }\n}\n\n/*\n * See src/place-popover.ts: `inset: auto; margin: 0` are what make the\n * coordinates mean what they say, since the UA stylesheet centres a popover.\n */\n.listbox {\n inset: auto;\n margin: 0;\n background: var(--pf-select-menu-bg);\n border: 1px solid var(--pf-select-menu-border);\n border-radius: var(--radius-md);\n box-shadow: var(--pf-elevation-popover-shadow);\n padding: var(--space-1);\n}\n\n.listbox:popover-open {\n animation: pf-select-in var(--pf-transition-enter);\n}\n\n/* Its own copy: @keyframes do not cross a shadow boundary. */\n@keyframes pf-select-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .listbox:popover-open {\n animation: none;\n }\n}\n","import {\n composeDescribedBy,\n findTypeaheadMatch,\n getEnabledIndexes,\n isActivationKey,\n Keys,\n nextTypeaheadBuffer,\n observeAnchoredPosition,\n resolveListMove,\n TYPEAHEAD_TIMEOUT_MS,\n isTypeaheadKey,\n type ListNavigationAction,\n} from '@pitchfork-ui/core';\n\nimport { applyControlValidity } from '../../form-validity';\nimport { placePopover } from '../../place-popover';\nimport {\n AttachInternals,\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Listen,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\n\nconst MOVES: Record<string, ListNavigationAction> = {\n [Keys.ArrowDown]: 'next',\n [Keys.ArrowUp]: 'previous',\n [Keys.Home]: 'first',\n [Keys.End]: 'last',\n};\n\n/**\n * A form-associated single-choice select over `pf-option` children.\n *\n * The first of Wave 5, and the worked example for §2.1: the options are child\n * elements, so a label is a slot and can hold anything, where the React\n * `Select`'s `options` array can only hold a string.\n *\n * **It has typeahead, which the React component does not.** Typing `b` jumps\n * to the next option beginning with `b`, `br` narrows, and `bbb` cycles — the\n * ARIA listbox pattern, and the matching is core's so a later `pf-combobox`\n * answers the same keystrokes. `todo.md` has the React fix.\n *\n * Form-associated, so the value submits by itself. The React component fakes\n * that with a hidden `<input>` beside the trigger.\n *\n * The active option is set as an *element*, not an IDREF: the trigger is in\n * this shadow root and the options are slotted light DOM, and a cross-root\n * IDREF is absent from the accessibility tree — measured. `aria-controls` does\n * work, because the listbox itself is in this same root.\n *\n * @slot - the `pf-option` children.\n * @part field - the wrapper around label, control and messages.\n * @part label - the label element.\n * @part trigger - the combobox button.\n * @part listbox - the floating listbox the options are slotted into.\n * @part description - the hint text below the control.\n * @part error - the error message below the control.\n */\n@Component({\n tag: 'pf-select',\n styleUrl: 'pf-select.css',\n formAssociated: true,\n shadow: true,\n})\nexport class PfSelect {\n @Element() el!: HTMLElement;\n @AttachInternals() internals!: ElementInternals;\n\n /** Submitted under this name. Reflected; the submission reads the attribute. */\n @Prop({ reflect: true }) name?: string;\n\n /** The chosen option's value, or empty. */\n @Prop({ mutable: true, reflect: true }) value = '';\n\n /** Whether the listbox is showing. Reflected for the stylesheet. */\n @Prop({ mutable: true, reflect: true }) open = false;\n\n @Prop() label?: string;\n\n @Prop() description?: string;\n\n @Prop() error?: string;\n\n @Prop() placeholder = 'Select an option';\n\n @Prop({ reflect: true }) required = false;\n\n @Prop({ reflect: true }) disabled = false;\n\n /** Options to show before the listbox scrolls. Unset means it fits them all. */\n @Prop() maxVisibleOptions?: number;\n\n /** Fires when the chosen value changes. */\n @Event() pfChange!: EventEmitter<{ value: string }>;\n\n /** Fires whenever the listbox opens or closes, whoever caused it. */\n @Event() pfOpenChange!: EventEmitter<{ open: boolean }>;\n\n /** The label of the chosen option, for the trigger to show. */\n @State() selectedLabel = '';\n\n private initialValue = '';\n private stopObserving?: () => void;\n private activeOption: HTMLElement | null = null;\n private typeahead = '';\n private typeaheadTimer?: ReturnType<typeof setTimeout>;\n\n componentWillLoad() {\n this.initialValue = this.value ?? '';\n this.syncFormState();\n this.syncOptions();\n }\n\n componentDidRender() {\n this.syncActiveDescendant();\n }\n\n disconnectedCallback() {\n this.stopObserving?.();\n if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);\n }\n\n @Watch('value')\n @Watch('error')\n @Watch('required')\n syncFormState() {\n this.internals.setFormValue(this.value || null);\n applyControlValidity(this.internals, Boolean(this.value), this.required, this.error);\n }\n\n /** The value changed, so the children's `selected` and the trigger follow. */\n @Watch('value')\n syncOptions() {\n const options = this.options();\n let label = '';\n\n for (const option of options) {\n const selected = this.optionValue(option) === this.value && this.value !== '';\n (option as HTMLElement & { selected: boolean }).selected = selected;\n if (selected) label = option.textContent?.trim() ?? '';\n }\n\n this.selectedLabel = label;\n }\n\n @Watch('open')\n syncOpen(next: boolean, previous: boolean) {\n if (next) this.showListbox();\n else this.hideListbox();\n if (next !== previous) this.pfOpenChange.emit({ open: next });\n }\n\n @Method()\n async show(): Promise<void> {\n if (!this.disabled) this.open = true;\n }\n\n @Method()\n async hide(): Promise<void> {\n this.open = false;\n }\n\n @Method()\n async checkValidity(): Promise<boolean> {\n return this.internals.checkValidity();\n }\n\n @Method()\n async reportValidity(): Promise<boolean> {\n return this.internals.reportValidity();\n }\n\n @Method()\n async getValidationMessage(): Promise<string> {\n return this.internals.validationMessage;\n }\n\n /** A reset restores the value the control started with, not an empty one. */\n formResetCallback() {\n this.value = this.initialValue;\n }\n\n /** An option added or removed while mounted; re-mark the children. */\n private onSlotChange = () => {\n this.syncOptions();\n };\n\n /** Re-reads the options, for a label edited in place (which fires no slotchange). */\n @Method()\n async refresh(): Promise<void> {\n this.syncOptions();\n }\n\n private options(): HTMLElement[] {\n return Array.from(this.el.querySelectorAll<HTMLElement>('pf-option'));\n }\n\n private enabled(): HTMLElement[] {\n return this.options().filter((option) => !option.hasAttribute('disabled'));\n }\n\n /** The property, never the attribute: a binding may only have set the former. */\n private optionValue(option: HTMLElement): string {\n return (option as HTMLElement & { value?: string }).value ?? option.getAttribute('value') ?? '';\n }\n\n private get listbox() {\n return this.el.shadowRoot?.querySelector<HTMLElement>('[part=\"listbox\"]') ?? null;\n }\n\n private get trigger() {\n return this.el.shadowRoot?.querySelector<HTMLButtonElement>('[part=\"trigger\"]') ?? null;\n }\n\n private showListbox() {\n const panel = this.listbox;\n if (this.disabled || !panel || panel.matches(':popover-open')) return;\n\n panel.showPopover();\n this.stopObserving?.();\n this.stopObserving = observeAnchoredPosition({\n getAnchor: () => this.trigger,\n getFloating: () => panel,\n // The listbox matches the trigger's width, as the React component does.\n matchAnchorWidth: true,\n flip: true,\n /*\n * `width` *and* `minWidth`: core reports whichever the mode calls for\n * and leaves the other undefined — `matchAnchorWidth: true` gives a\n * `width`, false gives a `minWidth`. Reading only `minWidth`, which is\n * what pf-dropdown needs, left the listbox at its intrinsic 156px beside\n * a 1216px trigger. The smoke test against a real build caught it.\n */\n onChange: ({ left, top, width, minWidth }) => {\n placePopover(panel, left, top);\n if (width !== undefined) panel.style.width = `${width}px`;\n if (minWidth !== undefined) panel.style.minWidth = `${minWidth}px`;\n },\n });\n\n /*\n * Opens on the chosen option, or the first selectable one. Landing\n * anywhere else would make the arrows start from somewhere the user has\n * no reason to expect.\n */\n const options = this.options();\n const chosen = options.find((option) => this.optionValue(option) === this.value);\n this.setActive(\n chosen && !chosen.hasAttribute('disabled') ? chosen : (this.enabled()[0] ?? null),\n );\n }\n\n private hideListbox() {\n this.stopObserving?.();\n this.stopObserving = undefined;\n this.clearTypeahead();\n const panel = this.listbox;\n if (panel?.matches(':popover-open')) panel.hidePopover();\n }\n\n private onToggle = (event: ToggleEvent) => {\n const nowOpen = event.newState === 'open';\n if (this.open !== nowOpen) this.open = nowOpen;\n if (!nowOpen) this.trigger?.focus();\n };\n\n private setActive(option: HTMLElement | null) {\n for (const other of this.options()) {\n if (other !== option) (other as HTMLElement & { active: boolean }).active = false;\n }\n if (option) (option as HTMLElement & { active: boolean }).active = true;\n\n this.activeOption = option;\n this.syncActiveDescendant();\n if (option && typeof option.scrollIntoView === 'function') {\n option.scrollIntoView({ block: 'nearest' });\n }\n }\n\n /**\n * Feature-detected. Where ARIA element reflection is missing there is no\n * cross-root equivalent, so the active option stops being *announced* while\n * the arrows and Enter still work — recorded in `todo.md`.\n */\n private syncActiveDescendant() {\n const trigger = this.trigger;\n if (!trigger || !('ariaActiveDescendantElement' in trigger)) return;\n (\n trigger as unknown as { ariaActiveDescendantElement: Element | null }\n ).ariaActiveDescendantElement = this.open ? this.activeOption : null;\n }\n\n private commit(option: HTMLElement) {\n if (option.hasAttribute('disabled')) return;\n\n const next = this.optionValue(option);\n this.open = false;\n this.trigger?.focus();\n\n if (next === this.value) return;\n this.value = next;\n this.pfChange.emit({ value: next });\n }\n\n /** An option asked to be taken. The select decides, reports and closes. */\n @Listen('pfOptionSelect')\n handleOptionSelect(event: CustomEvent<{ value: string }>) {\n event.stopPropagation();\n if (this.disabled) return;\n\n const option = this.options().find(\n (candidate) => this.optionValue(candidate) === event.detail.value,\n );\n if (option) this.commit(option);\n }\n\n private move(action: ListNavigationAction) {\n const options = this.options();\n const enabledIndexes = getEnabledIndexes(options, (option) => option.hasAttribute('disabled'));\n const current = this.activeOption ? options.indexOf(this.activeOption) : -1;\n const next = resolveListMove(action, enabledIndexes, current);\n if (next !== -1) this.setActive(options[next] ?? null);\n }\n\n private clearTypeahead() {\n if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);\n this.typeaheadTimer = undefined;\n this.typeahead = '';\n }\n\n /**\n * Typeahead. The buffer and its timer live here, because a timer is state\n * and core is never a state container; the matching is core's.\n */\n private handleTypeahead(key: string) {\n this.typeahead = nextTypeaheadBuffer(this.typeahead, key);\n\n if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);\n this.typeaheadTimer = setTimeout(() => this.clearTypeahead(), TYPEAHEAD_TIMEOUT_MS);\n\n const options = this.options();\n const labels = options.map((option) => option.textContent ?? '');\n const from = this.activeOption ? options.indexOf(this.activeOption) : -1;\n const match = findTypeaheadMatch(labels, this.typeahead, from, (index) =>\n options[index].hasAttribute('disabled'),\n );\n\n if (match === -1) return;\n\n /*\n * Closed, typeahead *chooses* rather than merely highlighting: that is\n * what a native `<select>` does, and with no listbox on screen a\n * highlight nobody can see would be no feedback at all.\n */\n if (this.open) this.setActive(options[match]);\n else this.commit(options[match]);\n }\n\n @Listen('keydown')\n handleKeyDown(event: KeyboardEvent) {\n if (this.disabled || event.defaultPrevented) return;\n\n const move = MOVES[event.key];\n if (move) {\n event.preventDefault();\n // Down or Up on a closed select opens it, as a combobox should.\n if (!this.open) this.open = true;\n else this.move(move);\n return;\n }\n\n if (isActivationKey(event.key)) {\n event.preventDefault();\n if (!this.open) {\n this.open = true;\n } else if (this.activeOption) {\n this.commit(this.activeOption);\n }\n return;\n }\n\n // Escape is the browser's while the listbox is a `popover=\"auto\"`.\n if (isTypeaheadKey(event.key)) {\n event.preventDefault();\n this.handleTypeahead(event.key);\n }\n }\n\n render() {\n const describedBy = composeDescribedBy(\n this.description && 'description',\n this.error && 'error',\n );\n\n return (\n <Host>\n <div class=\"field\" part=\"field\">\n {this.label && (\n <label class=\"label\" part=\"label\" htmlFor=\"trigger\">\n {this.label}\n {this.required && (\n <span class=\"required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <button\n id=\"trigger\"\n part=\"trigger\"\n class={{ trigger: true, 'trigger--invalid': Boolean(this.error) }}\n type=\"button\"\n role=\"combobox\"\n disabled={this.disabled}\n aria-haspopup=\"listbox\"\n aria-expanded={this.open ? 'true' : 'false'}\n /* Same shadow root as the listbox, so this IDREF resolves. */\n aria-controls=\"listbox\"\n aria-invalid={this.error ? 'true' : null}\n aria-required={this.required ? 'true' : null}\n aria-describedby={describedBy}\n onClick={() => {\n if (!this.disabled) this.open = !this.open;\n }}\n >\n <span class={{ value: true, 'value--placeholder': !this.selectedLabel }}>\n {this.selectedLabel || this.placeholder}\n </span>\n <span class=\"chevron\" aria-hidden=\"true\">\n <pf-icon name=\"chevron-down\"></pf-icon>\n </span>\n </button>\n\n {this.description && (\n <p class=\"description\" part=\"description\" id=\"description\">\n {this.description}\n </p>\n )}\n {this.error && (\n <p class=\"error\" part=\"error\" id=\"error\">\n {this.error}\n </p>\n )}\n </div>\n\n <div\n id=\"listbox\"\n part=\"listbox\"\n class=\"listbox\"\n popover=\"auto\"\n role=\"listbox\"\n aria-label={this.label ?? this.placeholder}\n style={\n this.maxVisibleOptions\n ? { maxHeight: `calc(${this.maxVisibleOptions} * 36px)`, overflowY: 'auto' }\n : undefined\n }\n onToggle={this.onToggle}\n >\n <slot onSlotchange={this.onSlotChange} />\n </div>\n </Host>\n );\n }\n}\n"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,oBAAoB,GAAG,GAAG;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,cAAc,CAAC,GAAG,EAAE;AAC7B,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,KAAK,GAAG;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,mBAAmB,CAAC,MAAM,EAAE,GAAG,EAAE;AAC1C,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,OAAO,MAAM;AACxC,CAAC,OAAO,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,SAAS,CAAC,MAAM,EAAE;AAC3B,CAAC,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,UAAU,GAAG,MAAM,KAAK,EAAE;AACtF,CAAC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE;AAC9C,CAAC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC;AAClC,CAAC,MAAM,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM;AAC5C,CAAC,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,GAAG,SAAS,GAAG,CAAC,GAAG,SAAS;AACtE,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,EAAE;AACrD,EAAE,MAAM,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,IAAI,MAAM,CAAC,MAAM;AAC9C,EAAE,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE;AACzB,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK;AAC1E;AACA,CAAC,OAAO,EAAE;AACV;;AC5EA,MAAM,WAAW,GAAG,MAAM,CAAC,o8DAAo8D,CAAC;;AC+Bh+D,MAAM,KAAK,GAAyC;AAClD,IAAA,CAAC,IAAI,CAAC,SAAS,GAAG,MAAM;AACxB,IAAA,CAAC,IAAI,CAAC,OAAO,GAAG,UAAU;AAC1B,IAAA,CAAC,IAAI,CAAC,IAAI,GAAG,OAAO;AACpB,IAAA,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM;CACnB;MAoCY,QAAQ,GAAA,MAAA;;;;;;;;;;;;;;AAEA,IAAA,SAAS;;AAGH,IAAA,IAAI;;IAGW,KAAK,GAAG,EAAE;;IAGV,IAAI,GAAG,KAAK;AAE5C,IAAA,KAAK;AAEL,IAAA,WAAW;AAEX,IAAA,KAAK;IAEL,WAAW,GAAG,kBAAkB;IAEf,QAAQ,GAAG,KAAK;IAEhB,QAAQ,GAAG,KAAK;;AAGjC,IAAA,iBAAiB;;AAGhB,IAAA,QAAQ;;AAGR,IAAA,YAAY;;IAGZ,aAAa,GAAG,EAAE;IAEnB,YAAY,GAAG,EAAE;AACjB,IAAA,aAAa;IACb,YAAY,GAAuB,IAAI;IACvC,SAAS,GAAG,EAAE;AACd,IAAA,cAAc;IAEtB,iBAAiB,GAAA;QACf,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE;QACpC,IAAI,CAAC,aAAa,EAAE;QACpB,IAAI,CAAC,WAAW,EAAE;;IAGpB,kBAAkB,GAAA;QAChB,IAAI,CAAC,oBAAoB,EAAE;;IAG7B,oBAAoB,GAAA;AAClB,QAAA,IAAI,CAAC,aAAa,IAAI;QACtB,IAAI,IAAI,CAAC,cAAc;AAAE,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;;IAM5D,aAAa,GAAA;QACX,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;QAC/C,oBAAoB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC;;;IAKtF,WAAW,GAAA;AACT,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;QAC9B,IAAI,KAAK,GAAG,EAAE;AAEd,QAAA,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;AAC5B,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE;AAC5E,YAAA,MAA8C,CAAC,QAAQ,GAAG,QAAQ;AACnE,YAAA,IAAI,QAAQ;gBAAE,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;;AAGxD,QAAA,IAAI,CAAC,aAAa,GAAG,KAAK;;IAI5B,QAAQ,CAAC,IAAa,EAAE,QAAiB,EAAA;AACvC,QAAA,IAAI,IAAI;YAAE,IAAI,CAAC,WAAW,EAAE;;YACvB,IAAI,CAAC,WAAW,EAAE;QACvB,IAAI,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;;AAI/D,IAAA,MAAM,IAAI,GAAA;QACR,IAAI,CAAC,IAAI,CAAC,QAAQ;AAAE,YAAA,IAAI,CAAC,IAAI,GAAG,IAAI;;AAItC,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,IAAI,CAAC,IAAI,GAAG,KAAK;;AAInB,IAAA,MAAM,aAAa,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE;;AAIvC,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE;;AAIxC,IAAA,MAAM,oBAAoB,GAAA;AACxB,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,iBAAiB;;;IAIzC,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY;;;IAIxB,YAAY,GAAG,MAAK;QAC1B,IAAI,CAAC,WAAW,EAAE;AACpB,KAAC;;AAID,IAAA,MAAM,OAAO,GAAA;QACX,IAAI,CAAC,WAAW,EAAE;;IAGZ,OAAO,GAAA;AACb,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAc,WAAW,CAAC,CAAC;;IAG/D,OAAO,GAAA;QACb,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;;;AAIpE,IAAA,WAAW,CAAC,MAAmB,EAAA;AACrC,QAAA,OAAQ,MAA2C,CAAC,KAAK,IAAI,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE;;AAGjG,IAAA,IAAY,OAAO,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,CAAc,kBAAkB,CAAC,IAAI,IAAI;;AAGnF,IAAA,IAAY,OAAO,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,CAAoB,kBAAkB,CAAC,IAAI,IAAI;;IAGjF,WAAW,GAAA;AACjB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO;AAC1B,QAAA,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC;YAAE;QAE/D,KAAK,CAAC,WAAW,EAAE;AACnB,QAAA,IAAI,CAAC,aAAa,IAAI;AACtB,QAAA,IAAI,CAAC,aAAa,GAAG,uBAAuB,CAAC;AAC3C,YAAA,SAAS,EAAE,MAAM,IAAI,CAAC,OAAO;AAC7B,YAAA,WAAW,EAAE,MAAM,KAAK;;AAExB,YAAA,gBAAgB,EAAE,IAAI;AACtB,YAAA,IAAI,EAAE,IAAI;AACV;;;;;;AAMG;AACH,YAAA,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAI;AAC3C,gBAAA,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC;gBAC9B,IAAI,KAAK,KAAK,SAAS;oBAAE,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAA,EAAG,KAAK,IAAI;gBACzD,IAAI,QAAQ,KAAK,SAAS;oBAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAA,EAAG,QAAQ,IAAI;aACnE;AACF,SAAA,CAAC;AAEF;;;;AAIG;AACH,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;QAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC;AAChF,QAAA,IAAI,CAAC,SAAS,CACZ,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAClF;;IAGK,WAAW,GAAA;AACjB,QAAA,IAAI,CAAC,aAAa,IAAI;AACtB,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;QAC9B,IAAI,CAAC,cAAc,EAAE;AACrB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO;AAC1B,QAAA,IAAI,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC;YAAE,KAAK,CAAC,WAAW,EAAE;;AAGlD,IAAA,QAAQ,GAAG,CAAC,KAAkB,KAAI;AACxC,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,KAAK,MAAM;AACzC,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;AAAE,YAAA,IAAI,CAAC,IAAI,GAAG,OAAO;AAC9C,QAAA,IAAI,CAAC,OAAO;AAAE,YAAA,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE;AACrC,KAAC;AAEO,IAAA,SAAS,CAAC,MAA0B,EAAA;QAC1C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;YAClC,IAAI,KAAK,KAAK,MAAM;AAAG,gBAAA,KAA2C,CAAC,MAAM,GAAG,KAAK;;AAEnF,QAAA,IAAI,MAAM;AAAG,YAAA,MAA4C,CAAC,MAAM,GAAG,IAAI;AAEvE,QAAA,IAAI,CAAC,YAAY,GAAG,MAAM;QAC1B,IAAI,CAAC,oBAAoB,EAAE;QAC3B,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,cAAc,KAAK,UAAU,EAAE;YACzD,MAAM,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;;;AAI/C;;;;AAIG;IACK,oBAAoB,GAAA;AAC1B,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO;QAC5B,IAAI,CAAC,OAAO,IAAI,EAAE,6BAA6B,IAAI,OAAO,CAAC;YAAE;AAE3D,QAAA,OACD,CAAC,2BAA2B,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,YAAY,GAAG,IAAI;;AAG9D,IAAA,MAAM,CAAC,MAAmB,EAAA;AAChC,QAAA,IAAI,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;YAAE;QAErC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;AACrC,QAAA,IAAI,CAAC,IAAI,GAAG,KAAK;AACjB,QAAA,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE;AAErB,QAAA,IAAI,IAAI,KAAK,IAAI,CAAC,KAAK;YAAE;AACzB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;QACjB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;;;AAKrC,IAAA,kBAAkB,CAAC,KAAqC,EAAA;QACtD,KAAK,CAAC,eAAe,EAAE;QACvB,IAAI,IAAI,CAAC,QAAQ;YAAE;QAEnB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAChC,CAAC,SAAS,KAAK,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,CAClE;AACD,QAAA,IAAI,MAAM;AAAE,YAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;;AAGzB,IAAA,IAAI,CAAC,MAA4B,EAAA;AACvC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;AAC9B,QAAA,MAAM,cAAc,GAAG,iBAAiB,CAAC,OAAO,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC9F,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE;QAC3E,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC;QAC7D,IAAI,IAAI,KAAK,EAAE;YAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;;IAGhD,cAAc,GAAA;QACpB,IAAI,IAAI,CAAC,cAAc;AAAE,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AAC1D,QAAA,IAAI,CAAC,cAAc,GAAG,SAAS;AAC/B,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;;AAGrB;;;AAGG;AACK,IAAA,eAAe,CAAC,GAAW,EAAA;QACjC,IAAI,CAAC,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC;QAEzD,IAAI,IAAI,CAAC,cAAc;AAAE,YAAA,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC;AAC1D,QAAA,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,EAAE,oBAAoB,CAAC;AAEnF,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;AAC9B,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE;QACxE,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,KAAK,KACnE,OAAO,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,CACxC;QAED,IAAI,KAAK,KAAK,EAAE;YAAE;AAElB;;;;AAIG;QACH,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;;YACxC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;;AAIlC,IAAA,aAAa,CAAC,KAAoB,EAAA;AAChC,QAAA,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,gBAAgB;YAAE;QAE7C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;QAC7B,IAAI,IAAI,EAAE;YACR,KAAK,CAAC,cAAc,EAAE;;YAEtB,IAAI,CAAC,IAAI,CAAC,IAAI;AAAE,gBAAA,IAAI,CAAC,IAAI,GAAG,IAAI;;AAC3B,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACpB;;AAGF,QAAA,IAAI,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YAC9B,KAAK,CAAC,cAAc,EAAE;AACtB,YAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;AACd,gBAAA,IAAI,CAAC,IAAI,GAAG,IAAI;;AACX,iBAAA,IAAI,IAAI,CAAC,YAAY,EAAE;AAC5B,gBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;;YAEhC;;;AAIF,QAAA,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YAC7B,KAAK,CAAC,cAAc,EAAE;AACtB,YAAA,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC;;;IAInC,MAAM,GAAA;AACJ,QAAA,MAAM,WAAW,GAAG,kBAAkB,CACpC,IAAI,CAAC,WAAW,IAAI,aAAa,EACjC,IAAI,CAAC,KAAK,IAAI,OAAO,CACtB;QAED,QACE,EAAC,IAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,EACH,CAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAK,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAA,EAC5B,IAAI,CAAC,KAAK,KACT,8DAAO,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAC,SAAS,EAAA,EAChD,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,QAAQ,KACZ,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,KAAK,EAAC,UAAU,EAAA,aAAA,EAAa,MAAM,EAAA,EAAA,GAAA,CAElC,CACR,CACK,CACT,EAED,CAAA,CAAA,QAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EACE,EAAE,EAAC,SAAS,EACZ,IAAI,EAAC,SAAS,EACd,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EACjE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,UAAU,EACf,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAA,eAAA,EACT,SAAS,EAAA,eAAA,EACR,IAAI,CAAC,IAAI,GAAG,MAAM,GAAG,OAAO,EAAA,eAAA,EAE7B,SAAS,EAAA,cAAA,EACT,IAAI,CAAC,KAAK,GAAG,MAAM,GAAG,IAAI,mBACzB,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,IAAI,EAAA,kBAAA,EAC1B,WAAW,EAC7B,OAAO,EAAE,MAAK;gBACZ,IAAI,CAAC,IAAI,CAAC,QAAQ;AAAE,oBAAA,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI;AAC5C,aAAC,EAAA,EAED,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,IACpE,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,WAAW,CAClC,EACP,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,KAAK,EAAC,SAAS,EAAA,aAAA,EAAa,MAAM,EAAA,EACtC,CAAA,CAAA,SAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAS,IAAI,EAAC,cAAc,EAAA,CAAW,CAClC,CACA,EAER,IAAI,CAAC,WAAW,KACf,0DAAG,KAAK,EAAC,aAAa,EAAC,IAAI,EAAC,aAAa,EAAC,EAAE,EAAC,aAAa,IACvD,IAAI,CAAC,WAAW,CACf,CACL,EACA,IAAI,CAAC,KAAK,KACT,0DAAG,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAC,EAAE,EAAC,OAAO,EAAA,EACrC,IAAI,CAAC,KAAK,CACT,CACL,CACG,EAEN,CAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EACE,EAAE,EAAC,SAAS,EACZ,IAAI,EAAC,SAAS,EACd,KAAK,EAAC,SAAS,EACf,OAAO,EAAC,MAAM,EACd,IAAI,EAAC,SAAS,EAAA,YAAA,EACF,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,EAC1C,KAAK,EACH,IAAI,CAAC;AACH,kBAAE,EAAE,SAAS,EAAE,CAAA,KAAA,EAAQ,IAAI,CAAC,iBAAiB,CAAA,QAAA,CAAU,EAAE,SAAS,EAAE,MAAM;AAC1E,kBAAE,SAAS,EAEf,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAA,EAEvB,CAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,YAAY,EAAE,IAAI,CAAC,YAAY,EAAA,CAAI,CACrC,CACD;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"pf-select.entry.js","sources":["../core/dist/typeahead.js","src/components/pf-select/pf-select.css?tag=pf-select&encapsulation=shadow","src/components/pf-select/pf-select.tsx"],"sourcesContent":["//#region src/typeahead.ts\n/**\n* Printable-character typeahead for a listbox, menu or tree.\n*\n* The ARIA listbox pattern expects it: typing `b` jumps to the next option\n* beginning with `b`, and typing `br` narrows to `br`. The React `Select` has\n* none of this — `todo.md` has the fix — so the rules live here, where\n* `<pf-select>` and every later `pf-combobox` / `pf-multi-select` /\n* `pf-tree-view` read the same ones.\n*\n* Core owns the matching; the rendering layer owns the buffer and its timer,\n* because a timer is state and core is never a state container.\n*/\n/** How long a quiet gap ends one typeahead word, in milliseconds. */\nvar TYPEAHEAD_TIMEOUT_MS = 500;\n/**\n* Whether a key should go into the buffer at all.\n*\n* One character, so `Enter`, `ArrowDown` and `Escape` are excluded by length\n* rather than by a list that would need keeping up to date. A space is\n* deliberately *not* typeahead: in a listbox it selects.\n*/\nfunction isTypeaheadKey(key) {\n\treturn key.length === 1 && key !== \" \";\n}\n/**\n* The buffer after `key`: lower-cased and appended, nothing more.\n*\n* A repeat is *not* special-cased here. Pressing `b` four times means \"the\n* fourth option starting with b\" rather than \"an option starting with bbbb\",\n* but that is a matching question, so `findTypeaheadMatch` reads it off the\n* buffer's shape instead — which keeps this function a plain append and lets\n* the caller hold one string.\n*/\nfunction nextTypeaheadBuffer(buffer, key) {\n\tif (!isTypeaheadKey(key)) return buffer;\n\treturn buffer + key.toLowerCase();\n}\n/**\n* True when the buffer is one character repeated — including just once.\n*\n* The single-character case is the important one, and requiring two got it\n* wrong: pressing `b` while already on Banana has to move to Blackberry, the\n* way a native `<select>` does, not sit still because Banana also starts with\n* `b`. Found by a browser test on `pf-select`.\n*/\nfunction isCycling(buffer) {\n\treturn buffer.length > 0 && [...buffer].every((char) => char === buffer[0]);\n}\n/**\n* The index of the option the buffer points at, or -1.\n*\n* Searches from `fromIndex` and wraps, so a match behind the current option is\n* still found. Two modes:\n*\n* - **Narrowing** (`br`): the current option is included, because typing more\n* of the label you are already on should keep you there rather than skip to\n* the next `br`.\n* - **Cycling** (`b`, `bb`, `bbb`): one character repeated, searched from\n* *after* the current option — so pressing one letter walks through the\n* options beginning with it, which is what a native `<select>` does.\n*\n* A disabled option is never matched: the keyboard would land somewhere it\n* cannot act, which is worse than not moving.\n*/\nfunction findTypeaheadMatch(labels, buffer, fromIndex = -1, isDisabled = () => false) {\n\tif (!buffer || labels.length === 0) return -1;\n\tconst cycling = isCycling(buffer);\n\tconst needle = cycling ? buffer[0] : buffer;\n\tconst start = fromIndex < 0 ? 0 : cycling ? fromIndex + 1 : fromIndex;\n\tfor (let step = 0; step < labels.length; step += 1) {\n\t\tconst index = (start + step) % labels.length;\n\t\tif (isDisabled(index)) continue;\n\t\tif (labels[index]?.trim().toLowerCase().startsWith(needle)) return index;\n\t}\n\treturn -1;\n}\n//#endregion\nexport { TYPEAHEAD_TIMEOUT_MS, findTypeaheadMatch, isTypeaheadKey, nextTypeaheadBuffer };\n","/*\n * The generic set pf-option reads, mapped to this control's own family. They\n * inherit through the shadow boundary, so a slotted option is themed by the\n * listbox it sits in without knowing which that is.\n */\n:host {\n display: block;\n --pf-option-text: var(--pf-select-input-text, var(--pf-input-text));\n --pf-option-text-disabled: var(--pf-select-input-placeholder, var(--pf-input-placeholder));\n --pf-option-active-bg: var(--pf-select-option-active-bg);\n --pf-option-active-text: var(--pf-select-option-active-text);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.field {\n display: grid;\n gap: var(--space-1);\n}\n\n.label {\n color: var(--pf-input-label-text, var(--pf-input-text));\n font-size: var(--font-size-sm);\n font-weight: var(--font-weight-medium);\n}\n\n.required {\n color: var(--pf-select-invalid-border);\n margin-inline-start: var(--space-1);\n}\n\n.trigger {\n align-items: center;\n background: var(--pf-input-bg);\n border: 1px solid var(--pf-input-border);\n border-radius: var(--radius-md);\n color: var(--pf-input-text);\n cursor: pointer;\n display: flex;\n font-family: inherit;\n font-size: var(--font-size-sm);\n gap: var(--space-2);\n justify-content: space-between;\n padding: var(--space-2) var(--space-3);\n text-align: start;\n width: 100%;\n}\n\n.trigger:hover:not(:disabled) {\n border-color: var(--pf-input-border-hover);\n}\n\n.trigger:focus-visible {\n border-color: var(--pf-select-focus-border);\n box-shadow: var(--pf-focus-ring);\n outline: none;\n}\n\n.trigger:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.trigger--invalid {\n border-color: var(--pf-select-invalid-border);\n}\n\n.value {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.value--placeholder {\n color: var(--pf-input-placeholder);\n}\n\n.chevron {\n align-items: center;\n display: inline-flex;\n flex-shrink: 0;\n transition: transform var(--pf-transition-fast);\n}\n\n:host([open]) .chevron {\n transform: rotate(180deg);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .chevron {\n transition: none;\n }\n}\n\n/*\n * See src/place-popover.ts: `inset: auto; margin: 0` are what make the\n * coordinates mean what they say, since the UA stylesheet centres a popover.\n */\n.listbox {\n inset: auto;\n margin: 0;\n background: var(--pf-select-menu-bg);\n border: 1px solid var(--pf-select-menu-border);\n border-radius: var(--radius-md);\n box-shadow: var(--pf-elevation-popover-shadow);\n padding: var(--space-1);\n}\n\n.listbox:popover-open {\n animation: pf-select-in var(--pf-transition-enter);\n}\n\n/* Its own copy: @keyframes do not cross a shadow boundary. */\n@keyframes pf-select-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .listbox:popover-open {\n animation: none;\n }\n}\n","import {\n composeDescribedBy,\n findTypeaheadMatch,\n getEnabledIndexes,\n isActivationKey,\n Keys,\n nextTypeaheadBuffer,\n observeAnchoredPosition,\n resolveListMove,\n TYPEAHEAD_TIMEOUT_MS,\n isTypeaheadKey,\n type ListNavigationAction,\n} from '@pitchfork-ui/core';\n\nimport { applyControlValidity } from '../../form-validity';\nimport { controlAriaLabel } from '../../control-label';\nimport { placePopover } from '../../place-popover';\nimport {\n AttachInternals,\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Listen,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\n\nconst MOVES: Record<string, ListNavigationAction> = {\n [Keys.ArrowDown]: 'next',\n [Keys.ArrowUp]: 'previous',\n [Keys.Home]: 'first',\n [Keys.End]: 'last',\n};\n\n/**\n * A form-associated single-choice select over `pf-option` children.\n *\n * The first of Wave 5, and the worked example for §2.1: the options are child\n * elements, so a label is a slot and can hold anything, where the React\n * `Select`'s `options` array can only hold a string.\n *\n * **It has typeahead, which the React component does not.** Typing `b` jumps\n * to the next option beginning with `b`, `br` narrows, and `bbb` cycles — the\n * ARIA listbox pattern, and the matching is core's so a later `pf-combobox`\n * answers the same keystrokes. `todo.md` has the React fix.\n *\n * Form-associated, so the value submits by itself. The React component fakes\n * that with a hidden `<input>` beside the trigger.\n *\n * The active option is set as an *element*, not an IDREF: the trigger is in\n * this shadow root and the options are slotted light DOM, and a cross-root\n * IDREF is absent from the accessibility tree — measured. `aria-controls` does\n * work, because the listbox itself is in this same root.\n *\n * @slot - the `pf-option` children.\n * @part field - the wrapper around label, control and messages.\n * @part label - the label element.\n * @part trigger - the combobox button.\n * @part listbox - the floating listbox the options are slotted into.\n * @part description - the hint text below the control.\n * @part error - the error message below the control.\n */\n@Component({\n tag: 'pf-select',\n styleUrl: 'pf-select.css',\n formAssociated: true,\n shadow: true,\n})\nexport class PfSelect {\n @Element() el!: HTMLElement;\n @AttachInternals() internals!: ElementInternals;\n\n /** Submitted under this name. Reflected; the submission reads the attribute. */\n @Prop({ reflect: true }) name?: string;\n\n /** The chosen option's value, or empty. */\n @Prop({ mutable: true, reflect: true }) value = '';\n\n /** Whether the listbox is showing. Reflected for the stylesheet. */\n @Prop({ mutable: true, reflect: true }) open = false;\n\n @Prop() label?: string;\n\n @Prop() description?: string;\n\n @Prop() error?: string;\n\n @Prop() placeholder = 'Select an option';\n\n @Prop({ reflect: true }) required = false;\n\n @Prop({ reflect: true }) disabled = false;\n\n /** Options to show before the listbox scrolls. Unset means it fits them all. */\n @Prop() maxVisibleOptions?: number;\n\n /** Fires when the chosen value changes. */\n @Event() pfChange!: EventEmitter<{ value: string }>;\n\n /** Fires whenever the listbox opens or closes, whoever caused it. */\n @Event() pfOpenChange!: EventEmitter<{ open: boolean }>;\n\n /** The label of the chosen option, for the trigger to show. */\n @State() selectedLabel = '';\n\n private initialValue = '';\n private stopObserving?: () => void;\n private activeOption: HTMLElement | null = null;\n private typeahead = '';\n private typeaheadTimer?: ReturnType<typeof setTimeout>;\n\n componentWillLoad() {\n this.initialValue = this.value ?? '';\n this.syncFormState();\n this.syncOptions();\n }\n\n componentDidRender() {\n this.syncActiveDescendant();\n }\n\n disconnectedCallback() {\n this.stopObserving?.();\n if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);\n }\n\n @Watch('value')\n @Watch('error')\n @Watch('required')\n syncFormState() {\n this.internals.setFormValue(this.value || null);\n applyControlValidity(this.internals, Boolean(this.value), this.required, this.error);\n }\n\n /** The value changed, so the children's `selected` and the trigger follow. */\n @Watch('value')\n syncOptions() {\n const options = this.options();\n let label = '';\n\n for (const option of options) {\n const selected = this.optionValue(option) === this.value && this.value !== '';\n (option as HTMLElement & { selected: boolean }).selected = selected;\n if (selected) label = option.textContent?.trim() ?? '';\n }\n\n this.selectedLabel = label;\n }\n\n @Watch('open')\n syncOpen(next: boolean, previous: boolean) {\n if (next) this.showListbox();\n else this.hideListbox();\n if (next !== previous) this.pfOpenChange.emit({ open: next });\n }\n\n @Method()\n async show(): Promise<void> {\n if (!this.disabled) this.open = true;\n }\n\n @Method()\n async hide(): Promise<void> {\n this.open = false;\n }\n\n @Method()\n async checkValidity(): Promise<boolean> {\n return this.internals.checkValidity();\n }\n\n @Method()\n async reportValidity(): Promise<boolean> {\n return this.internals.reportValidity();\n }\n\n @Method()\n async getValidationMessage(): Promise<string> {\n return this.internals.validationMessage;\n }\n\n /** A reset restores the value the control started with, not an empty one. */\n formResetCallback() {\n this.value = this.initialValue;\n }\n\n /** An option added or removed while mounted; re-mark the children. */\n private onSlotChange = () => {\n this.syncOptions();\n };\n\n /** Re-reads the options, for a label edited in place (which fires no slotchange). */\n @Method()\n async refresh(): Promise<void> {\n this.syncOptions();\n }\n\n private options(): HTMLElement[] {\n return Array.from(this.el.querySelectorAll<HTMLElement>('pf-option'));\n }\n\n private enabled(): HTMLElement[] {\n return this.options().filter((option) => !option.hasAttribute('disabled'));\n }\n\n /** The property, never the attribute: a binding may only have set the former. */\n private optionValue(option: HTMLElement): string {\n return (option as HTMLElement & { value?: string }).value ?? option.getAttribute('value') ?? '';\n }\n\n private get listbox() {\n return this.el.shadowRoot?.querySelector<HTMLElement>('[part=\"listbox\"]') ?? null;\n }\n\n private get trigger() {\n return this.el.shadowRoot?.querySelector<HTMLButtonElement>('[part=\"trigger\"]') ?? null;\n }\n\n private showListbox() {\n const panel = this.listbox;\n if (this.disabled || !panel || panel.matches(':popover-open')) return;\n\n panel.showPopover();\n this.stopObserving?.();\n this.stopObserving = observeAnchoredPosition({\n getAnchor: () => this.trigger,\n getFloating: () => panel,\n // The listbox matches the trigger's width, as the React component does.\n matchAnchorWidth: true,\n flip: true,\n /*\n * `width` *and* `minWidth`: core reports whichever the mode calls for\n * and leaves the other undefined — `matchAnchorWidth: true` gives a\n * `width`, false gives a `minWidth`. Reading only `minWidth`, which is\n * what pf-dropdown needs, left the listbox at its intrinsic 156px beside\n * a 1216px trigger. The smoke test against a real build caught it.\n */\n onChange: ({ left, top, width, minWidth }) => {\n placePopover(panel, left, top);\n if (width !== undefined) panel.style.width = `${width}px`;\n if (minWidth !== undefined) panel.style.minWidth = `${minWidth}px`;\n },\n });\n\n /*\n * Opens on the chosen option, or the first selectable one. Landing\n * anywhere else would make the arrows start from somewhere the user has\n * no reason to expect.\n */\n const options = this.options();\n const chosen = options.find((option) => this.optionValue(option) === this.value);\n this.setActive(\n chosen && !chosen.hasAttribute('disabled') ? chosen : (this.enabled()[0] ?? null),\n );\n }\n\n private hideListbox() {\n this.stopObserving?.();\n this.stopObserving = undefined;\n this.clearTypeahead();\n const panel = this.listbox;\n if (panel?.matches(':popover-open')) panel.hidePopover();\n }\n\n private onToggle = (event: ToggleEvent) => {\n const nowOpen = event.newState === 'open';\n if (this.open !== nowOpen) this.open = nowOpen;\n if (!nowOpen) this.trigger?.focus();\n };\n\n private setActive(option: HTMLElement | null) {\n for (const other of this.options()) {\n if (other !== option) (other as HTMLElement & { active: boolean }).active = false;\n }\n if (option) (option as HTMLElement & { active: boolean }).active = true;\n\n this.activeOption = option;\n this.syncActiveDescendant();\n if (option && typeof option.scrollIntoView === 'function') {\n option.scrollIntoView({ block: 'nearest' });\n }\n }\n\n /**\n * Feature-detected. Where ARIA element reflection is missing there is no\n * cross-root equivalent, so the active option stops being *announced* while\n * the arrows and Enter still work — recorded in `todo.md`.\n */\n private syncActiveDescendant() {\n const trigger = this.trigger;\n if (!trigger || !('ariaActiveDescendantElement' in trigger)) return;\n (\n trigger as unknown as { ariaActiveDescendantElement: Element | null }\n ).ariaActiveDescendantElement = this.open ? this.activeOption : null;\n }\n\n private commit(option: HTMLElement) {\n if (option.hasAttribute('disabled')) return;\n\n const next = this.optionValue(option);\n this.open = false;\n this.trigger?.focus();\n\n if (next === this.value) return;\n this.value = next;\n this.pfChange.emit({ value: next });\n }\n\n /** An option asked to be taken. The select decides, reports and closes. */\n @Listen('pfOptionSelect')\n handleOptionSelect(event: CustomEvent<{ value: string }>) {\n event.stopPropagation();\n if (this.disabled) return;\n\n const option = this.options().find(\n (candidate) => this.optionValue(candidate) === event.detail.value,\n );\n if (option) this.commit(option);\n }\n\n private move(action: ListNavigationAction) {\n const options = this.options();\n const enabledIndexes = getEnabledIndexes(options, (option) => option.hasAttribute('disabled'));\n const current = this.activeOption ? options.indexOf(this.activeOption) : -1;\n const next = resolveListMove(action, enabledIndexes, current);\n if (next !== -1) this.setActive(options[next] ?? null);\n }\n\n private clearTypeahead() {\n if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);\n this.typeaheadTimer = undefined;\n this.typeahead = '';\n }\n\n /**\n * Typeahead. The buffer and its timer live here, because a timer is state\n * and core is never a state container; the matching is core's.\n */\n private handleTypeahead(key: string) {\n this.typeahead = nextTypeaheadBuffer(this.typeahead, key);\n\n if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);\n this.typeaheadTimer = setTimeout(() => this.clearTypeahead(), TYPEAHEAD_TIMEOUT_MS);\n\n const options = this.options();\n const labels = options.map((option) => option.textContent ?? '');\n const from = this.activeOption ? options.indexOf(this.activeOption) : -1;\n const match = findTypeaheadMatch(labels, this.typeahead, from, (index) =>\n options[index].hasAttribute('disabled'),\n );\n\n if (match === -1) return;\n\n /*\n * Closed, typeahead *chooses* rather than merely highlighting: that is\n * what a native `<select>` does, and with no listbox on screen a\n * highlight nobody can see would be no feedback at all.\n */\n if (this.open) this.setActive(options[match]);\n else this.commit(options[match]);\n }\n\n @Listen('keydown')\n handleKeyDown(event: KeyboardEvent) {\n if (this.disabled || event.defaultPrevented) return;\n\n const move = MOVES[event.key];\n if (move) {\n event.preventDefault();\n // Down or Up on a closed select opens it, as a combobox should.\n if (!this.open) this.open = true;\n else this.move(move);\n return;\n }\n\n if (isActivationKey(event.key)) {\n event.preventDefault();\n if (!this.open) {\n this.open = true;\n } else if (this.activeOption) {\n this.commit(this.activeOption);\n }\n return;\n }\n\n // Escape is the browser's while the listbox is a `popover=\"auto\"`.\n if (isTypeaheadKey(event.key)) {\n event.preventDefault();\n this.handleTypeahead(event.key);\n }\n }\n\n render() {\n const describedBy = composeDescribedBy(\n this.description && 'description',\n this.error && 'error',\n );\n\n return (\n <Host>\n <div class=\"field\" part=\"field\">\n {this.label && (\n <label class=\"label\" part=\"label\" htmlFor=\"trigger\">\n {this.label}\n {this.required && (\n <span class=\"required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <button\n id=\"trigger\"\n aria-label={controlAriaLabel(this.el, this.label)}\n part=\"trigger\"\n class={{ trigger: true, 'trigger--invalid': Boolean(this.error) }}\n type=\"button\"\n role=\"combobox\"\n disabled={this.disabled}\n aria-haspopup=\"listbox\"\n aria-expanded={this.open ? 'true' : 'false'}\n /* Same shadow root as the listbox, so this IDREF resolves. */\n aria-controls=\"listbox\"\n aria-invalid={this.error ? 'true' : null}\n aria-required={this.required ? 'true' : null}\n aria-describedby={describedBy}\n onClick={() => {\n if (!this.disabled) this.open = !this.open;\n }}\n >\n <span class={{ value: true, 'value--placeholder': !this.selectedLabel }}>\n {this.selectedLabel || this.placeholder}\n </span>\n <span class=\"chevron\" aria-hidden=\"true\">\n <pf-icon name=\"chevron-down\"></pf-icon>\n </span>\n </button>\n\n {this.description && (\n <p class=\"description\" part=\"description\" id=\"description\">\n {this.description}\n </p>\n )}\n {this.error && (\n <p class=\"error\" part=\"error\" id=\"error\">\n {this.error}\n </p>\n )}\n </div>\n\n <div\n id=\"listbox\"\n part=\"listbox\"\n class=\"listbox\"\n popover=\"auto\"\n role=\"listbox\"\n aria-label={this.label ?? this.placeholder}\n style={\n this.maxVisibleOptions\n ? { maxHeight: `calc(${this.maxVisibleOptions} * 36px)`, overflowY: 'auto' }\n : undefined\n }\n onToggle={this.onToggle}\n >\n <slot onSlotchange={this.onSlotChange} />\n </div>\n </Host>\n );\n }\n}\n"],"names":[],"mappings":"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"}
@@ -28,21 +28,24 @@ const PfSidebarNavigation = class {
28
28
  this.sync();
29
29
  }
30
30
  /**
31
- * A section's own slot changed, so the items below it have moved.
31
+ * A section's items moved, or an item's `current` changed. Either way the
32
+ * resolution has to run again.
32
33
  *
33
34
  * `slotchange` is not composed, so this is the only way the navigation
34
- * hears about an item appended inside a section. The event comes from a
35
- * slotted child in the navigation's own tree, so `event.target` is the
36
- * section rather than the host — nothing is retargeted, which is what makes
37
- * a host listener safe here and not on a child in the shadow root.
35
+ * hears about an item appended inside a section — and an item's `current`
36
+ * arriving as a *property* fires no DOM event at all, which is why the item
37
+ * emits this too. The event comes from a slotted child in the navigation's
38
+ * own tree, so `event.target` is the section or the item rather than the
39
+ * host — nothing is retargeted, which is what makes a host listener safe
40
+ * here and not on a child in the shadow root.
38
41
  */
39
42
  handleStructureChange(event) {
40
43
  event.stopPropagation();
41
44
  this.sync();
42
45
  }
43
46
  /**
44
- * Re-reads the items, for a consumer who marked one current through its
45
- * *property* — which leaves no attribute and fires no `slotchange`.
47
+ * Re-reads the items, for a consumer who changed something the group reads
48
+ * and has no event for.
46
49
  */
47
50
  async refresh() {
48
51
  this.sync();
@@ -90,7 +93,7 @@ const PfSidebarNavigation = class {
90
93
  }
91
94
  }
92
95
  render() {
93
- return (h(Host, { key: 'c53d731970844c06cf2d86789dfbc9e111eeb83e' }, h("div", { key: '1ca019d8890305e0f1656243bcca112f461ea51c', class: { header: true, empty: !this.hasHeader }, part: "header" }, h("slot", { key: '750fc4f32e167e6b186824d1429ea25d09818c3d', name: "header", onSlotchange: () => this.refresh() })), h("nav", { key: '6ebe62b6bd357a9fac58220f31309c811a6af76a', class: "nav", part: "nav", "aria-label": this.label }, h("slot", { key: '636b7284ed6113e7c60da733da62c0562a8ba042', onSlotchange: () => this.refresh() })), h("div", { key: '9a5b32c84e82ced42bc6520806f9d02b5c7af65e', class: { footer: true, empty: !this.hasFooter }, part: "footer" }, h("slot", { key: 'd04ef066ba6168173d0f778e8dc163ba34deeef5', name: "footer", onSlotchange: () => this.refresh() }))));
96
+ return (h(Host, { key: '32d3374c206ae575f3b572e249203d9b5e1b5c66' }, h("div", { key: '18ddded266a900836c09b26b3716bb4e4d17a027', class: { header: true, empty: !this.hasHeader }, part: "header" }, h("slot", { key: '8a74ca32bb1574d64bf6bfca53b799580fae5980', name: "header", onSlotchange: () => this.refresh() })), h("nav", { key: 'b4168ab94367d2e7086ec82aa08d81e92540d1f3', class: "nav", part: "nav", "aria-label": this.label }, h("slot", { key: 'afa43f3d6f1b247e527a3d1e6a11ac585dd8fdd9', onSlotchange: () => this.refresh() })), h("div", { key: '00afd1800a0aff350f73422823431287457ad2a9', class: { footer: true, empty: !this.hasFooter }, part: "footer" }, h("slot", { key: 'cf899e9e6cab4199f7ed5846ea2fdb4011e71672', name: "footer", onSlotchange: () => this.refresh() }))));
94
97
  }
95
98
  };
96
99
  PfSidebarNavigation.style = pfSidebarNavigationCss();
@@ -1 +1 @@
1
- {"version":3,"file":"pf-sidebar-navigation.entry.js","sources":["src/components/pf-sidebar-navigation/pf-sidebar-navigation.css?tag=pf-sidebar-navigation&encapsulation=shadow","src/components/pf-sidebar-navigation/pf-sidebar-navigation.tsx"],"sourcesContent":[":host {\n background: var(--pf-sidebar-nav-bg);\n border: 1px solid var(--pf-sidebar-nav-border);\n border-radius: var(--pf-sidebar-nav-radius, var(--radius-md));\n display: flex;\n flex-direction: column;\n min-height: 0;\n width: 100%;\n\n /*\n * The bridge to the shared item. `pf-header-navigation` defines the same\n * five from its own aliases; custom properties inherit through the shadow\n * boundary, which is how one item element takes its colours from whichever\n * navigation it is slotted into.\n */\n --pf-nav-item-text: var(--pf-sidebar-nav-text-muted);\n --pf-nav-item-hover-text: var(--pf-sidebar-nav-text);\n --pf-nav-item-hover-bg: var(--pf-sidebar-nav-bg-subtle);\n --pf-nav-item-current-text: var(--pf-sidebar-nav-text);\n --pf-nav-item-current-bg: var(--pf-sidebar-nav-bg-subtle);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n/* Mobile first: full width, growing to a fixed column on a wider screen. */\n@media (--md) {\n :host {\n min-height: var(--pf-sidebar-nav-min-height, 360px);\n width: min(100%, var(--pf-sidebar-nav-width, 280px));\n }\n}\n\n.header,\n.footer {\n padding: var(--space-3);\n}\n\n.header {\n border-bottom: 1px solid var(--pf-sidebar-nav-border);\n}\n\n.footer {\n border-top: 1px solid var(--pf-sidebar-nav-border);\n /* Pushed to the bottom, so a short navigation still has it at the foot. */\n margin-top: auto;\n}\n\n/*\n * Both classes rather than a bare `.empty`: an empty box here would draw a\n * rule across the sidebar, which is the most visible version of the\n * can't-collapse-a-slot-wrapper problem.\n */\n.header.empty,\n.footer.empty {\n display: none;\n}\n\n.nav {\n display: grid;\n gap: var(--space-3);\n padding: var(--space-3);\n}\n\n/* The sections are grid children of the nav, not of a box inside it. */\n.nav slot {\n display: contents;\n}\n","import { resolveCurrentNavItem } from '@pitchfork-ui/core';\nimport { Component, Element, h, Host, Listen, Method, Prop, State } from '@stencil/core';\n\n/**\n * A sidebar navigation over `pf-nav-item` children, optionally grouped into\n * `pf-nav-section`s.\n *\n * The group owns the one thing an item cannot know: which item is the current\n * page. Core's rule decides, so the React `SidebarNavigation` marks the same\n * one — and the resolution runs across every section rather than within one,\n * because `aria-current=\"page\"` names the one page the reader is on and a\n * sidebar with two marked sections would claim two.\n *\n * As with `pf-header-navigation`, the host is not a landmark of its own: the\n * React component renders an `<aside>`, and an element cannot know whether it\n * is the page's complementary region. Only the `<nav>` is rendered.\n *\n * Items are grouped: the default slot takes `pf-nav-section` children, each\n * of which owns its own `<ul>`. A navigation with no section titles is one\n * untitled section, which is exactly what the React `sections` array is — and\n * it is also the only arrangement that keeps the list semantics honest, since\n * a `<ul>` here would be a list whose children were sections rather than\n * items.\n *\n * @slot - the `pf-nav-section` children.\n * @slot header - a box above the navigation, such as a product switcher.\n * @slot footer - a box below it, pushed to the bottom.\n * @part header - the header's box.\n * @part nav - the navigation landmark.\n * @part footer - the footer's box.\n */\n@Component({\n tag: 'pf-sidebar-navigation',\n styleUrl: 'pf-sidebar-navigation.css',\n shadow: true,\n})\nexport class PfSidebarNavigation {\n @Element() el!: HTMLElement;\n\n /** The navigation's accessible name. */\n @Prop() label = 'Sidebar navigation';\n\n /**\n * Whether anything was slotted into `header` and `footer`.\n *\n * Asked in JS: both boxes carry a border and padding, so an empty one draws\n * a rule across the sidebar for no reason, and a wrapper around a slot\n * cannot be collapsed from CSS. The same arrangement as\n * `pf-slideout-menu`'s footer.\n */\n @State() hasHeader = false;\n @State() hasFooter = false;\n\n /** The light DOM is readable here, so first paint is already right. */\n componentWillLoad() {\n this.sync();\n }\n\n componentDidLoad() {\n this.sync();\n }\n\n /**\n * A section's own slot changed, so the items below it have moved.\n *\n * `slotchange` is not composed, so this is the only way the navigation\n * hears about an item appended inside a section. The event comes from a\n * slotted child in the navigation's own tree, so `event.target` is the\n * section rather than the host — nothing is retargeted, which is what makes\n * a host listener safe here and not on a child in the shadow root.\n */\n @Listen('pfNavStructure')\n handleStructureChange(event: CustomEvent<void>) {\n event.stopPropagation();\n this.sync();\n }\n\n /**\n * Re-reads the items, for a consumer who marked one current through its\n * *property* — which leaves no attribute and fires no `slotchange`.\n */\n @Method()\n async refresh() {\n this.sync();\n }\n\n /**\n * Every item this navigation owns, in document order, however deeply a\n * section nests it — but not one belonging to a navigation nested inside\n * this one.\n */\n private get items(): HTMLElement[] {\n /*\n * The walk up is written out rather than done with `closest`, which would\n * need a comma selector the mock DOM may not take. The first navigation\n * above an item is the one that owns it, so a navigation nested inside\n * this one keeps its own.\n */\n const ownedByThis = (item: HTMLElement) => {\n for (let node = item.parentElement; node; node = node.parentElement) {\n const tag = node.tagName.toLowerCase();\n if (tag === 'pf-sidebar-navigation' || tag === 'pf-header-navigation') {\n return node === this.el;\n }\n }\n return false;\n };\n\n return Array.from(this.el.querySelectorAll<HTMLElement>('pf-nav-item')).filter(ownedByThis);\n }\n\n /**\n * The property if the item has upgraded, the attribute if it has not:\n * `componentWillLoad` can run before a child parsed from HTML upgrades.\n */\n private isCurrent(item: HTMLElement) {\n return (item as HTMLElement & { current?: boolean }).current ?? item.hasAttribute('current');\n }\n\n private sync() {\n const slotted = (name: string) =>\n Array.from(this.el.children).some((child) => child.getAttribute('slot') === name);\n\n this.hasHeader = slotted('header');\n this.hasFooter = slotted('footer');\n\n const items = this.items;\n const currentIndex = resolveCurrentNavItem(\n items.map((item) => ({ current: this.isCurrent(item) })),\n );\n\n for (const [index, item] of items.entries()) {\n const node = item as HTMLElement & { currentPage: boolean; orientation: string };\n node.currentPage = index === currentIndex;\n node.orientation = 'vertical';\n }\n }\n\n render() {\n return (\n <Host>\n <div class={{ header: true, empty: !this.hasHeader }} part=\"header\">\n <slot name=\"header\" onSlotchange={() => this.refresh()} />\n </div>\n\n <nav class=\"nav\" part=\"nav\" aria-label={this.label}>\n <slot onSlotchange={() => this.refresh()} />\n </nav>\n\n <div class={{ footer: true, empty: !this.hasFooter }} part=\"footer\">\n <slot name=\"footer\" onSlotchange={() => this.refresh()} />\n </div>\n </Host>\n );\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pf-sidebar-navigation.entry.js","sources":["src/components/pf-sidebar-navigation/pf-sidebar-navigation.css?tag=pf-sidebar-navigation&encapsulation=shadow","src/components/pf-sidebar-navigation/pf-sidebar-navigation.tsx"],"sourcesContent":[":host {\n background: var(--pf-sidebar-nav-bg);\n border: 1px solid var(--pf-sidebar-nav-border);\n border-radius: var(--pf-sidebar-nav-radius, var(--radius-md));\n display: flex;\n flex-direction: column;\n min-height: 0;\n width: 100%;\n\n /*\n * The bridge to the shared item. `pf-header-navigation` defines the same\n * five from its own aliases; custom properties inherit through the shadow\n * boundary, which is how one item element takes its colours from whichever\n * navigation it is slotted into.\n */\n --pf-nav-item-text: var(--pf-sidebar-nav-text-muted);\n --pf-nav-item-hover-text: var(--pf-sidebar-nav-text);\n --pf-nav-item-hover-bg: var(--pf-sidebar-nav-bg-subtle);\n --pf-nav-item-current-text: var(--pf-sidebar-nav-text);\n --pf-nav-item-current-bg: var(--pf-sidebar-nav-bg-subtle);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n/* Mobile first: full width, growing to a fixed column on a wider screen. */\n@media (--md) {\n :host {\n min-height: var(--pf-sidebar-nav-min-height, 360px);\n width: min(100%, var(--pf-sidebar-nav-width, 280px));\n }\n}\n\n.header,\n.footer {\n padding: var(--space-3);\n}\n\n.header {\n border-bottom: 1px solid var(--pf-sidebar-nav-border);\n}\n\n.footer {\n border-top: 1px solid var(--pf-sidebar-nav-border);\n /* Pushed to the bottom, so a short navigation still has it at the foot. */\n margin-top: auto;\n}\n\n/*\n * Both classes rather than a bare `.empty`: an empty box here would draw a\n * rule across the sidebar, which is the most visible version of the\n * can't-collapse-a-slot-wrapper problem.\n */\n.header.empty,\n.footer.empty {\n display: none;\n}\n\n.nav {\n display: grid;\n gap: var(--space-3);\n padding: var(--space-3);\n}\n\n/* The sections are grid children of the nav, not of a box inside it. */\n.nav slot {\n display: contents;\n}\n","import { resolveCurrentNavItem } from '@pitchfork-ui/core';\nimport { Component, Element, h, Host, Listen, Method, Prop, State } from '@stencil/core';\n\n/**\n * A sidebar navigation over `pf-nav-item` children, optionally grouped into\n * `pf-nav-section`s.\n *\n * The group owns the one thing an item cannot know: which item is the current\n * page. Core's rule decides, so the React `SidebarNavigation` marks the same\n * one — and the resolution runs across every section rather than within one,\n * because `aria-current=\"page\"` names the one page the reader is on and a\n * sidebar with two marked sections would claim two.\n *\n * As with `pf-header-navigation`, the host is not a landmark of its own: the\n * React component renders an `<aside>`, and an element cannot know whether it\n * is the page's complementary region. Only the `<nav>` is rendered.\n *\n * Items are grouped: the default slot takes `pf-nav-section` children, each\n * of which owns its own `<ul>`. A navigation with no section titles is one\n * untitled section, which is exactly what the React `sections` array is — and\n * it is also the only arrangement that keeps the list semantics honest, since\n * a `<ul>` here would be a list whose children were sections rather than\n * items.\n *\n * @slot - the `pf-nav-section` children.\n * @slot header - a box above the navigation, such as a product switcher.\n * @slot footer - a box below it, pushed to the bottom.\n * @part header - the header's box.\n * @part nav - the navigation landmark.\n * @part footer - the footer's box.\n */\n@Component({\n tag: 'pf-sidebar-navigation',\n styleUrl: 'pf-sidebar-navigation.css',\n shadow: true,\n})\nexport class PfSidebarNavigation {\n @Element() el!: HTMLElement;\n\n /** The navigation's accessible name. */\n @Prop() label = 'Sidebar navigation';\n\n /**\n * Whether anything was slotted into `header` and `footer`.\n *\n * Asked in JS: both boxes carry a border and padding, so an empty one draws\n * a rule across the sidebar for no reason, and a wrapper around a slot\n * cannot be collapsed from CSS. The same arrangement as\n * `pf-slideout-menu`'s footer.\n */\n @State() hasHeader = false;\n @State() hasFooter = false;\n\n /** The light DOM is readable here, so first paint is already right. */\n componentWillLoad() {\n this.sync();\n }\n\n componentDidLoad() {\n this.sync();\n }\n\n /**\n * A section's items moved, or an item's `current` changed. Either way the\n * resolution has to run again.\n *\n * `slotchange` is not composed, so this is the only way the navigation\n * hears about an item appended inside a section — and an item's `current`\n * arriving as a *property* fires no DOM event at all, which is why the item\n * emits this too. The event comes from a slotted child in the navigation's\n * own tree, so `event.target` is the section or the item rather than the\n * host — nothing is retargeted, which is what makes a host listener safe\n * here and not on a child in the shadow root.\n */\n @Listen('pfNavStructure')\n handleStructureChange(event: CustomEvent<void>) {\n event.stopPropagation();\n this.sync();\n }\n\n /**\n * Re-reads the items, for a consumer who changed something the group reads\n * and has no event for.\n */\n @Method()\n async refresh() {\n this.sync();\n }\n\n /**\n * Every item this navigation owns, in document order, however deeply a\n * section nests it — but not one belonging to a navigation nested inside\n * this one.\n */\n private get items(): HTMLElement[] {\n /*\n * The walk up is written out rather than done with `closest`, which would\n * need a comma selector the mock DOM may not take. The first navigation\n * above an item is the one that owns it, so a navigation nested inside\n * this one keeps its own.\n */\n const ownedByThis = (item: HTMLElement) => {\n for (let node = item.parentElement; node; node = node.parentElement) {\n const tag = node.tagName.toLowerCase();\n if (tag === 'pf-sidebar-navigation' || tag === 'pf-header-navigation') {\n return node === this.el;\n }\n }\n return false;\n };\n\n return Array.from(this.el.querySelectorAll<HTMLElement>('pf-nav-item')).filter(ownedByThis);\n }\n\n /**\n * The property if the item has upgraded, the attribute if it has not:\n * `componentWillLoad` can run before a child parsed from HTML upgrades.\n */\n private isCurrent(item: HTMLElement) {\n return (item as HTMLElement & { current?: boolean }).current ?? item.hasAttribute('current');\n }\n\n private sync() {\n const slotted = (name: string) =>\n Array.from(this.el.children).some((child) => child.getAttribute('slot') === name);\n\n this.hasHeader = slotted('header');\n this.hasFooter = slotted('footer');\n\n const items = this.items;\n const currentIndex = resolveCurrentNavItem(\n items.map((item) => ({ current: this.isCurrent(item) })),\n );\n\n for (const [index, item] of items.entries()) {\n const node = item as HTMLElement & { currentPage: boolean; orientation: string };\n node.currentPage = index === currentIndex;\n node.orientation = 'vertical';\n }\n }\n\n render() {\n return (\n <Host>\n <div class={{ header: true, empty: !this.hasHeader }} part=\"header\">\n <slot name=\"header\" onSlotchange={() => this.refresh()} />\n </div>\n\n <nav class=\"nav\" part=\"nav\" aria-label={this.label}>\n <slot onSlotchange={() => this.refresh()} />\n </nav>\n\n <div class={{ footer: true, empty: !this.hasFooter }} part=\"footer\">\n <slot name=\"footer\" onSlotchange={() => this.refresh()} />\n </div>\n </Host>\n );\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
- import { r as registerInstance, c as createEvent, h, H as Host } from './index-Bm6UxEit.js';
1
+ import { r as registerInstance, c as createEvent, a as getElement, h, H as Host } from './index-Bm6UxEit.js';
2
2
  import { c as composeDescribedBy } from './aria-DfpCerXM.js';
3
3
  import { n as normalizeRange, a as clampToRange, b as getRangePercent } from './progress-BA6CMosJ.js';
4
4
  import { a as applyControlValidity } from './form-validity-Cr6IXrUk.js';
5
+ import { c as controlAriaLabel } from './control-label-Cy_kHPeC.js';
5
6
 
6
7
  const pfSliderCss = () => `:host{display:block}:host([hidden]){display:none}.field{display:grid;gap:var(--space-2)}.label{color:var(--pf-slider-field-label, var(--pf-field-label));font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.required{color:var(--pf-field-required);margin-inline-start:var(--space-1)}.description{color:var(--pf-slider-field-description, var(--pf-field-description));font-size:var(--font-size-sm);margin:0}.error{color:var(--pf-slider-field-error, var(--pf-field-error));font-size:var(--font-size-sm);margin:0}.header{align-items:center;display:flex;justify-content:space-between}.value{color:var(--pf-slider-text-muted);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.slider{appearance:none;background:linear-gradient( to right, var(--pf-slider-action) 0, var(--pf-slider-action) var(--pf-slider-progress, 0%), var(--pf-slider-border) var(--pf-slider-progress, 0%), var(--pf-slider-border) 100% );border-radius:var(--radius-full);cursor:pointer;height:var(--pf-slider-track-height);width:100%}.slider:focus{outline:none}.slider:focus-visible{box-shadow:var(--pf-slider-focus-ring, var(--pf-focus-ring))}.slider::-webkit-slider-thumb{appearance:none;background:var(--pf-slider-bg);border:2px solid var(--pf-slider-action);border-radius:50%;box-shadow:var(--pf-slider-control-thumb-outline-shadow, var(--pf-control-thumb-outline-shadow));height:var(--pf-slider-thumb-size);margin-top:calc((var(--pf-slider-track-height) - var(--pf-slider-thumb-size)) / 2);width:var(--pf-slider-thumb-size)}.slider::-moz-range-thumb{background:var(--pf-slider-bg);border:2px solid var(--pf-slider-action);border-radius:50%;box-shadow:var(--pf-slider-control-thumb-outline-shadow, var(--pf-control-thumb-outline-shadow));height:var(--pf-slider-thumb-size);width:var(--pf-slider-thumb-size)}.slider::-moz-range-track{background:transparent;border-radius:var(--radius-full);height:var(--pf-slider-track-height)}.slider:disabled{cursor:not-allowed;opacity:0.55}.slider--invalid{background:linear-gradient( to right, var(--pf-slider-danger-fill) 0, var(--pf-slider-danger-fill) var(--pf-slider-progress, 0%), var(--pf-slider-border) var(--pf-slider-progress, 0%), var(--pf-slider-border) 100% )}.slider--invalid::-webkit-slider-thumb{border-color:var(--pf-slider-danger-fill)}.slider--invalid::-moz-range-thumb{border-color:var(--pf-slider-danger-fill)}`;
7
8
 
@@ -18,6 +19,7 @@ const PfSlider = class {
18
19
  hostRef.$hostElement$["s-ei"] = this.internals;
19
20
  }
20
21
  }
22
+ get el() { return getElement(this); }
21
23
  internals;
22
24
  /**
23
25
  * Submitted under this name. Reflected, because a form-associated element
@@ -93,10 +95,10 @@ const PfSlider = class {
93
95
  const { min, max, step } = this.range;
94
96
  const current = this.current;
95
97
  const describedBy = composeDescribedBy(this.description && 'description', this.error && 'error');
96
- return (h(Host, { key: 'aa9f73bc61fc164df6b960827337c57c89f3e041' }, h("div", { key: '6de203487f260a1025c2a49abeef29f3a9a1e250', class: "field", part: "field" }, (this.label || this.showValue) && (h("div", { key: 'c02c8be4fff2bb3eafbb45c8d19c777d79f984a4', class: "header", part: "header" }, this.label ? (h("label", { class: "label", part: "label", htmlFor: "input" }, this.label)) : (h("span", null)), this.showValue && (
98
+ return (h(Host, { key: '6d0718760dc214dbd200824c20417bfa51d49371' }, h("div", { key: 'cdfb094bb52dcc8b41fcd6fabf43a2057af644cf', class: "field", part: "field" }, (this.label || this.showValue) && (h("div", { key: '7278ee388367c3c5a33a837cd6f26e148ced2387', class: "header", part: "header" }, this.label ? (h("label", { class: "label", part: "label", htmlFor: "input" }, this.label)) : (h("span", null)), this.showValue && (
97
99
  // aria-hidden: the input already reports its value to
98
100
  // assistive technology through the range role.
99
- h("span", { key: '6638b3e9b626493e92c4dd76428a0ba2637956d6', class: "value", part: "value", "aria-hidden": "true" }, Math.round(current))))), h("input", { key: '03a97800d5dabc7d17e6f1cd91b9884485cafb42', id: "input", part: "input", class: { slider: true, 'slider--invalid': Boolean(this.error) }, type: "range", name: this.name, value: `${current}`, min: `${min}`, max: `${max}`, step: `${step}`, disabled: this.disabled, "aria-invalid": this.error ? 'true' : null, "aria-describedby": describedBy, onInput: this.onInput, onChange: this.onChange, style: { '--pf-slider-progress': `${getRangePercent(current, min, max)}%` } }), this.description && (h("p", { key: '0338224959bff19c234bfe07b8bf83027d85b17d', class: "description", part: "description", id: "description" }, this.description)), this.error && (h("p", { key: 'f469ebcbb86d81d933c0b66f578f8990d2a4b9a5', class: "error", part: "error", id: "error" }, this.error)))));
101
+ h("span", { key: 'f23e6b6e4db255a1f3e74785a07d185c64b89a62', class: "value", part: "value", "aria-hidden": "true" }, Math.round(current))))), h("input", { key: '8287d9fe81179e731ff30855f7e3d644ca7874ca', id: "input", "aria-label": controlAriaLabel(this.el, this.label), part: "input", class: { slider: true, 'slider--invalid': Boolean(this.error) }, type: "range", name: this.name, value: `${current}`, min: `${min}`, max: `${max}`, step: `${step}`, disabled: this.disabled, "aria-invalid": this.error ? 'true' : null, "aria-describedby": describedBy, onInput: this.onInput, onChange: this.onChange, style: { '--pf-slider-progress': `${getRangePercent(current, min, max)}%` } }), this.description && (h("p", { key: '810b7f5aff7336fd9042b7e70a834d6a4a69e32e', class: "description", part: "description", id: "description" }, this.description)), this.error && (h("p", { key: 'a95ec2ba460bdce626df1e66b94b9d290b8d600d', class: "error", part: "error", id: "error" }, this.error)))));
100
102
  }
101
103
  static get delegatesFocus() { return true; }
102
104
  static get formAssociated() { return true; }