ember-primitives 0.40.0 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/README.md +91 -0
  2. package/declarations/-private.d.ts +1 -0
  3. package/declarations/-private.d.ts.map +1 -0
  4. package/declarations/color-scheme.d.ts +1 -0
  5. package/declarations/color-scheme.d.ts.map +1 -0
  6. package/declarations/components/-private/typed-elements.d.ts +1 -0
  7. package/declarations/components/-private/typed-elements.d.ts.map +1 -0
  8. package/declarations/components/-private/utils.d.ts +1 -0
  9. package/declarations/components/-private/utils.d.ts.map +1 -0
  10. package/declarations/components/accordion/content.d.ts +1 -0
  11. package/declarations/components/accordion/content.d.ts.map +1 -0
  12. package/declarations/components/accordion/header.d.ts +1 -0
  13. package/declarations/components/accordion/header.d.ts.map +1 -0
  14. package/declarations/components/accordion/item.d.ts +1 -0
  15. package/declarations/components/accordion/item.d.ts.map +1 -0
  16. package/declarations/components/accordion/public.d.ts +1 -0
  17. package/declarations/components/accordion/public.d.ts.map +1 -0
  18. package/declarations/components/accordion/trigger.d.ts +1 -0
  19. package/declarations/components/accordion/trigger.d.ts.map +1 -0
  20. package/declarations/components/accordion.d.ts +1 -0
  21. package/declarations/components/accordion.d.ts.map +1 -0
  22. package/declarations/components/avatar.d.ts +1 -0
  23. package/declarations/components/avatar.d.ts.map +1 -0
  24. package/declarations/components/dialog.d.ts +1 -0
  25. package/declarations/components/dialog.d.ts.map +1 -0
  26. package/declarations/components/external-link.d.ts +1 -0
  27. package/declarations/components/external-link.d.ts.map +1 -0
  28. package/declarations/components/form.d.ts +1 -0
  29. package/declarations/components/form.d.ts.map +1 -0
  30. package/declarations/components/keys.d.ts +1 -0
  31. package/declarations/components/keys.d.ts.map +1 -0
  32. package/declarations/components/layout/hero.d.ts +1 -0
  33. package/declarations/components/layout/hero.d.ts.map +1 -0
  34. package/declarations/components/layout/sticky-footer.d.ts +1 -0
  35. package/declarations/components/layout/sticky-footer.d.ts.map +1 -0
  36. package/declarations/components/link.d.ts +1 -0
  37. package/declarations/components/link.d.ts.map +1 -0
  38. package/declarations/components/menu.d.ts +1 -0
  39. package/declarations/components/menu.d.ts.map +1 -0
  40. package/declarations/components/one-time-password/buttons.d.ts +1 -0
  41. package/declarations/components/one-time-password/buttons.d.ts.map +1 -0
  42. package/declarations/components/one-time-password/index.d.ts +1 -0
  43. package/declarations/components/one-time-password/index.d.ts.map +1 -0
  44. package/declarations/components/one-time-password/input.d.ts +1 -0
  45. package/declarations/components/one-time-password/input.d.ts.map +1 -0
  46. package/declarations/components/one-time-password/otp.d.ts +1 -0
  47. package/declarations/components/one-time-password/otp.d.ts.map +1 -0
  48. package/declarations/components/one-time-password/utils.d.ts +1 -0
  49. package/declarations/components/one-time-password/utils.d.ts.map +1 -0
  50. package/declarations/components/popover.d.ts +1 -0
  51. package/declarations/components/popover.d.ts.map +1 -0
  52. package/declarations/components/portal-targets.d.ts +1 -0
  53. package/declarations/components/portal-targets.d.ts.map +1 -0
  54. package/declarations/components/portal.d.ts +1 -0
  55. package/declarations/components/portal.d.ts.map +1 -0
  56. package/declarations/components/progress.d.ts +1 -0
  57. package/declarations/components/progress.d.ts.map +1 -0
  58. package/declarations/components/rating/index.d.ts +1 -0
  59. package/declarations/components/rating/index.d.ts.map +1 -0
  60. package/declarations/components/rating/public-types.d.ts +1 -0
  61. package/declarations/components/rating/public-types.d.ts.map +1 -0
  62. package/declarations/components/rating/range.d.ts +1 -0
  63. package/declarations/components/rating/range.d.ts.map +1 -0
  64. package/declarations/components/rating/stars.d.ts +1 -0
  65. package/declarations/components/rating/stars.d.ts.map +1 -0
  66. package/declarations/components/rating/state.d.ts +1 -0
  67. package/declarations/components/rating/state.d.ts.map +1 -0
  68. package/declarations/components/rating/utils.d.ts +1 -0
  69. package/declarations/components/rating/utils.d.ts.map +1 -0
  70. package/declarations/components/rating.d.ts +1 -0
  71. package/declarations/components/rating.d.ts.map +1 -0
  72. package/declarations/components/scroller.d.ts +1 -0
  73. package/declarations/components/scroller.d.ts.map +1 -0
  74. package/declarations/components/shadowed.d.ts +1 -0
  75. package/declarations/components/shadowed.d.ts.map +1 -0
  76. package/declarations/components/switch.d.ts +1 -0
  77. package/declarations/components/switch.d.ts.map +1 -0
  78. package/declarations/components/tabs.d.ts +233 -0
  79. package/declarations/components/tabs.d.ts.map +1 -0
  80. package/declarations/components/toggle-group.d.ts +1 -0
  81. package/declarations/components/toggle-group.d.ts.map +1 -0
  82. package/declarations/components/toggle.d.ts +1 -0
  83. package/declarations/components/toggle.d.ts.map +1 -0
  84. package/declarations/components/violations.css.d.ts +2 -0
  85. package/declarations/components/violations.css.d.ts.map +1 -0
  86. package/declarations/components/visually-hidden.d.ts +1 -0
  87. package/declarations/components/visually-hidden.d.ts.map +1 -0
  88. package/declarations/components/zoetrope/index.d.ts +1 -0
  89. package/declarations/components/zoetrope/index.d.ts.map +1 -0
  90. package/declarations/components/zoetrope/types.d.ts +1 -0
  91. package/declarations/components/zoetrope/types.d.ts.map +1 -0
  92. package/declarations/components/zoetrope.d.ts +1 -0
  93. package/declarations/components/zoetrope.d.ts.map +1 -0
  94. package/declarations/dom-context.d.ts +1 -0
  95. package/declarations/dom-context.d.ts.map +1 -0
  96. package/declarations/floating-ui/component.d.ts +1 -0
  97. package/declarations/floating-ui/component.d.ts.map +1 -0
  98. package/declarations/floating-ui/middleware.d.ts +1 -0
  99. package/declarations/floating-ui/middleware.d.ts.map +1 -0
  100. package/declarations/floating-ui/modifier.d.ts +1 -0
  101. package/declarations/floating-ui/modifier.d.ts.map +1 -0
  102. package/declarations/floating-ui.d.ts +1 -0
  103. package/declarations/floating-ui.d.ts.map +1 -0
  104. package/declarations/head.d.ts +1 -0
  105. package/declarations/head.d.ts.map +1 -0
  106. package/declarations/helpers/body-class.d.ts +1 -0
  107. package/declarations/helpers/body-class.d.ts.map +1 -0
  108. package/declarations/helpers/link.d.ts +1 -0
  109. package/declarations/helpers/link.d.ts.map +1 -0
  110. package/declarations/helpers/service.d.ts +1 -0
  111. package/declarations/helpers/service.d.ts.map +1 -0
  112. package/declarations/helpers.d.ts +1 -0
  113. package/declarations/helpers.d.ts.map +1 -0
  114. package/declarations/iframe.d.ts +1 -0
  115. package/declarations/iframe.d.ts.map +1 -0
  116. package/declarations/index.d.ts +1 -0
  117. package/declarations/index.d.ts.map +1 -0
  118. package/declarations/load.d.ts +1 -0
  119. package/declarations/load.d.ts.map +1 -0
  120. package/declarations/narrowing.d.ts +1 -0
  121. package/declarations/narrowing.d.ts.map +1 -0
  122. package/declarations/on-resize.d.ts +2 -12
  123. package/declarations/on-resize.d.ts.map +1 -0
  124. package/declarations/proper-links.d.ts +1 -0
  125. package/declarations/proper-links.d.ts.map +1 -0
  126. package/declarations/qp.d.ts +1 -0
  127. package/declarations/qp.d.ts.map +1 -0
  128. package/declarations/resize-observer.d.ts +52 -0
  129. package/declarations/resize-observer.d.ts.map +1 -0
  130. package/declarations/store.d.ts +1 -0
  131. package/declarations/store.d.ts.map +1 -0
  132. package/declarations/styles.css.d.ts +1 -0
  133. package/declarations/styles.css.d.ts.map +1 -0
  134. package/declarations/tabster.d.ts +1 -0
  135. package/declarations/tabster.d.ts.map +1 -0
  136. package/declarations/template-registry.d.ts +1 -0
  137. package/declarations/template-registry.d.ts.map +1 -0
  138. package/declarations/test-support/a11y.d.ts +1 -0
  139. package/declarations/test-support/a11y.d.ts.map +1 -0
  140. package/declarations/test-support/index.d.ts +1 -0
  141. package/declarations/test-support/index.d.ts.map +1 -0
  142. package/declarations/test-support/otp.d.ts +1 -0
  143. package/declarations/test-support/otp.d.ts.map +1 -0
  144. package/declarations/test-support/rating.d.ts +1 -0
  145. package/declarations/test-support/rating.d.ts.map +1 -0
  146. package/declarations/test-support/routing.d.ts +1 -0
  147. package/declarations/test-support/routing.d.ts.map +1 -0
  148. package/declarations/test-support/zoetrope.d.ts +1 -0
  149. package/declarations/test-support/zoetrope.d.ts.map +1 -0
  150. package/declarations/type-utils.d.ts +1 -0
  151. package/declarations/type-utils.d.ts.map +1 -0
  152. package/declarations/utils.d.ts +25 -0
  153. package/declarations/utils.d.ts.map +1 -0
  154. package/dist/-private.js +1 -0
  155. package/dist/-private.js.map +1 -1
  156. package/dist/color-scheme.js +1 -0
  157. package/dist/color-scheme.js.map +1 -1
  158. package/dist/components/-private/typed-elements.js +1 -0
  159. package/dist/components/-private/typed-elements.js.map +1 -1
  160. package/dist/components/-private/utils.js +1 -0
  161. package/dist/components/-private/utils.js.map +1 -1
  162. package/dist/components/accordion/content.js +2 -1
  163. package/dist/components/accordion/content.js.map +1 -1
  164. package/dist/components/accordion/header.js +2 -1
  165. package/dist/components/accordion/header.js.map +1 -1
  166. package/dist/components/accordion/item.js +2 -1
  167. package/dist/components/accordion/item.js.map +1 -1
  168. package/dist/components/accordion/trigger.js +2 -1
  169. package/dist/components/accordion/trigger.js.map +1 -1
  170. package/dist/components/accordion.js +2 -1
  171. package/dist/components/accordion.js.map +1 -1
  172. package/dist/components/avatar.js +1 -0
  173. package/dist/components/avatar.js.map +1 -1
  174. package/dist/components/dialog.js +1 -0
  175. package/dist/components/dialog.js.map +1 -1
  176. package/dist/components/external-link.js +1 -0
  177. package/dist/components/external-link.js.map +1 -1
  178. package/dist/components/form.js +1 -0
  179. package/dist/components/form.js.map +1 -1
  180. package/dist/components/keys.js +1 -0
  181. package/dist/components/keys.js.map +1 -1
  182. package/dist/components/layout/hero.js +3 -1
  183. package/dist/components/layout/hero.js.map +1 -1
  184. package/dist/components/layout/sticky-footer.js +3 -1
  185. package/dist/components/layout/sticky-footer.js.map +1 -1
  186. package/dist/components/link.js +1 -0
  187. package/dist/components/link.js.map +1 -1
  188. package/dist/components/menu.js +1 -0
  189. package/dist/components/menu.js.map +1 -1
  190. package/dist/components/one-time-password/buttons.js +1 -0
  191. package/dist/components/one-time-password/buttons.js.map +1 -1
  192. package/dist/components/one-time-password/index.js +1 -0
  193. package/dist/components/one-time-password/index.js.map +1 -1
  194. package/dist/components/one-time-password/input.js +1 -0
  195. package/dist/components/one-time-password/input.js.map +1 -1
  196. package/dist/components/one-time-password/otp.js +1 -0
  197. package/dist/components/one-time-password/otp.js.map +1 -1
  198. package/dist/components/one-time-password/utils.js +1 -0
  199. package/dist/components/one-time-password/utils.js.map +1 -1
  200. package/dist/components/popover.js +1 -0
  201. package/dist/components/popover.js.map +1 -1
  202. package/dist/components/portal-targets.js +1 -0
  203. package/dist/components/portal-targets.js.map +1 -1
  204. package/dist/components/portal.js +1 -0
  205. package/dist/components/portal.js.map +1 -1
  206. package/dist/components/progress.js +1 -0
  207. package/dist/components/progress.js.map +1 -1
  208. package/dist/components/rating/index.js +1 -0
  209. package/dist/components/rating/index.js.map +1 -1
  210. package/dist/components/rating/range.js +1 -0
  211. package/dist/components/rating/range.js.map +1 -1
  212. package/dist/components/rating/stars.js +1 -0
  213. package/dist/components/rating/stars.js.map +1 -1
  214. package/dist/components/rating/state.js +1 -0
  215. package/dist/components/rating/state.js.map +1 -1
  216. package/dist/components/rating/utils.js +1 -0
  217. package/dist/components/rating/utils.js.map +1 -1
  218. package/dist/components/rating.js +1 -0
  219. package/dist/components/scroller.js +1 -0
  220. package/dist/components/scroller.js.map +1 -1
  221. package/dist/components/shadowed.js +1 -0
  222. package/dist/components/shadowed.js.map +1 -1
  223. package/dist/components/switch.js +1 -0
  224. package/dist/components/switch.js.map +1 -1
  225. package/dist/components/tabs.js +218 -0
  226. package/dist/components/tabs.js.map +1 -0
  227. package/dist/components/toggle-group.js +1 -0
  228. package/dist/components/toggle-group.js.map +1 -1
  229. package/dist/components/toggle.js +1 -0
  230. package/dist/components/toggle.js.map +1 -1
  231. package/dist/components/violations.css.js +3 -0
  232. package/dist/components/violations.css.js.map +1 -0
  233. package/dist/components/visually-hidden.js +2 -1
  234. package/dist/components/visually-hidden.js.map +1 -1
  235. package/dist/components/zoetrope/index.js +3 -1
  236. package/dist/components/zoetrope/index.js.map +1 -1
  237. package/dist/components/zoetrope.js +1 -0
  238. package/dist/dom-context.js +2 -1
  239. package/dist/dom-context.js.map +1 -1
  240. package/dist/floating-ui/component.js +1 -0
  241. package/dist/floating-ui/component.js.map +1 -1
  242. package/dist/floating-ui/middleware.js +1 -0
  243. package/dist/floating-ui/middleware.js.map +1 -1
  244. package/dist/floating-ui/modifier.js +1 -0
  245. package/dist/floating-ui/modifier.js.map +1 -1
  246. package/dist/floating-ui.js +1 -0
  247. package/dist/floating-ui.js.map +1 -1
  248. package/dist/head.js +1 -0
  249. package/dist/head.js.map +1 -1
  250. package/dist/helpers/body-class.js +1 -0
  251. package/dist/helpers/body-class.js.map +1 -1
  252. package/dist/helpers/link.js +1 -0
  253. package/dist/helpers/link.js.map +1 -1
  254. package/dist/helpers/service.js +1 -0
  255. package/dist/helpers/service.js.map +1 -1
  256. package/dist/helpers.js +1 -0
  257. package/dist/helpers.js.map +1 -1
  258. package/dist/iframe.js +1 -0
  259. package/dist/iframe.js.map +1 -1
  260. package/dist/index.js +1 -0
  261. package/dist/index.js.map +1 -1
  262. package/dist/{item-D6pwWzMs.js → item-CwIzoqlC.js} +2 -1
  263. package/dist/item-CwIzoqlC.js.map +1 -0
  264. package/dist/load.js +1 -0
  265. package/dist/load.js.map +1 -1
  266. package/dist/narrowing.js +1 -0
  267. package/dist/narrowing.js.map +1 -1
  268. package/dist/on-resize.js +5 -88
  269. package/dist/on-resize.js.map +1 -1
  270. package/dist/proper-links.js +1 -0
  271. package/dist/proper-links.js.map +1 -1
  272. package/dist/qp.js +1 -0
  273. package/dist/qp.js.map +1 -1
  274. package/dist/resize-observer.js +113 -0
  275. package/dist/resize-observer.js.map +1 -0
  276. package/dist/store.js +1 -0
  277. package/dist/store.js.map +1 -1
  278. package/dist/styles.css.js +2 -1
  279. package/dist/tabster.js +1 -0
  280. package/dist/tabster.js.map +1 -1
  281. package/dist/test-support/a11y.js +1 -0
  282. package/dist/test-support/a11y.js.map +1 -1
  283. package/dist/test-support/index.js +1 -0
  284. package/dist/test-support/index.js.map +1 -1
  285. package/dist/test-support/otp.js +1 -0
  286. package/dist/test-support/otp.js.map +1 -1
  287. package/dist/test-support/rating.js +1 -0
  288. package/dist/test-support/rating.js.map +1 -1
  289. package/dist/test-support/routing.js +1 -0
  290. package/dist/test-support/routing.js.map +1 -1
  291. package/dist/test-support/zoetrope.js +1 -0
  292. package/dist/test-support/zoetrope.js.map +1 -1
  293. package/dist/utils.js +47 -1
  294. package/dist/utils.js.map +1 -1
  295. package/dist/visually-hidden-CGP1FSjt.js +3 -0
  296. package/dist/visually-hidden-CGP1FSjt.js.map +1 -0
  297. package/package.json +23 -25
  298. package/dist/item-D6pwWzMs.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/components/one-time-password/utils.ts"],"sourcesContent":["import { assert } from '@ember/debug';\n\nfunction getInputs(current: HTMLInputElement) {\n const fieldset = current.closest('fieldset');\n\n assert('[BUG]: fieldset went missing', fieldset);\n\n return [...fieldset.querySelectorAll('input')];\n}\n\nfunction nextInput(current: HTMLInputElement) {\n const inputs = getInputs(current);\n const currentIndex = inputs.indexOf(current);\n\n return inputs[currentIndex + 1];\n}\n\nexport function selectAll(event: Event) {\n const target = event.target;\n\n assert(`selectAll is only meant for use with input elements`, target instanceof HTMLInputElement);\n\n target.select();\n}\n\nexport function handlePaste(event: Event) {\n const target = event.target;\n\n assert(\n `handlePaste is only meant for use with input elements`,\n target instanceof HTMLInputElement\n );\n\n const clipboardData = (event as ClipboardEvent).clipboardData;\n\n assert(\n `Could not get clipboardData while handling the paste event on OTP. Please report this issue on the ember-primitives repo with a reproduction. Thanks!`,\n clipboardData\n );\n\n // This is typically not good to prevent paste.\n // But because of the UX we're implementing,\n // we want to split the pasted value across\n // multiple text fields\n event.preventDefault();\n\n const value = clipboardData.getData('Text');\n const digits = value;\n let i = 0;\n let currElement: HTMLInputElement | null = target;\n\n while (currElement) {\n currElement.value = digits[i++] || '';\n\n const next = nextInput(currElement);\n\n if (next instanceof HTMLInputElement) {\n currElement = next;\n } else {\n break;\n }\n }\n\n // We want to select the first field again\n // so that if someone holds paste, or\n // pastes again, they get the same result.\n target.select();\n}\n\nexport function handleNavigation(event: KeyboardEvent) {\n switch (event.key) {\n case 'Backspace':\n return handleBackspace(event);\n case 'ArrowLeft':\n return focusLeft(event);\n case 'ArrowRight':\n return focusRight(event);\n }\n}\n\nfunction focusLeft(event: Pick<Event, 'target'>) {\n const target = event.target;\n\n assert(`only allowed on input elements`, target instanceof HTMLInputElement);\n\n const input = previousInput(target);\n\n input?.focus();\n requestAnimationFrame(() => {\n input?.select();\n });\n}\n\nfunction focusRight(event: Pick<Event, 'target'>) {\n const target = event.target;\n\n assert(`only allowed on input elements`, target instanceof HTMLInputElement);\n\n const input = nextInput(target);\n\n input?.focus();\n requestAnimationFrame(() => {\n input?.select();\n });\n}\n\nconst syntheticEvent = new InputEvent('input');\n\nfunction handleBackspace(event: KeyboardEvent) {\n if (event.key !== 'Backspace') return;\n\n /**\n * We have to prevent default because we\n * - want to clear the whole field\n * - have the focus behavior keep up with the key-repeat\n * speed of the user's computer\n */\n event.preventDefault();\n\n const target = event.target;\n\n if (target && 'value' in target) {\n if (target.value === '') {\n focusLeft({ target });\n } else {\n target.value = '';\n }\n }\n\n target?.dispatchEvent(syntheticEvent);\n}\n\nfunction previousInput(current: HTMLInputElement) {\n const inputs = getInputs(current);\n const currentIndex = inputs.indexOf(current);\n\n return inputs[currentIndex - 1];\n}\n\nexport const autoAdvance = (event: Event) => {\n assert(\n '[BUG]: autoAdvance called on non-input element',\n event.target instanceof HTMLInputElement\n );\n\n const value = event.target.value;\n\n if (value.length === 0) return;\n\n if (value.length > 0) {\n if ('data' in event && event.data && typeof event.data === 'string') {\n event.target.value = event.data;\n }\n\n return focusRight(event);\n }\n};\n\nexport function getCollectiveValue(elementTarget: EventTarget | null, length: number) {\n if (!elementTarget) return;\n\n assert(\n `[BUG]: somehow the element target is not HTMLElement`,\n elementTarget instanceof HTMLElement\n );\n\n let parent: null | HTMLElement | ShadowRoot;\n\n // TODO: should this logic be extracted?\n // why is getting the target element within a shadow root hard?\n if (!(elementTarget instanceof HTMLInputElement)) {\n if (elementTarget.shadowRoot) {\n parent = elementTarget.shadowRoot;\n } else {\n parent = elementTarget.closest('fieldset');\n }\n } else {\n parent = elementTarget.closest('fieldset');\n }\n\n assert(`[BUG]: somehow the input fields were rendered without a parent element`, parent);\n\n const elements = parent.querySelectorAll('input');\n\n let value = '';\n\n assert(\n `found elements (${elements.length}) do not match length (${length}). Was the same OTP input rendered more than once?`,\n elements.length === length\n );\n\n for (const element of elements) {\n assert(\n '[BUG]: how did the queried elements become a non-input element?',\n element instanceof HTMLInputElement\n );\n value += element.value;\n }\n\n return value;\n}\n"],"names":["getInputs","current","fieldset","closest","assert","querySelectorAll","nextInput","inputs","currentIndex","indexOf","selectAll","event","target","HTMLInputElement","select","handlePaste","clipboardData","preventDefault","value","getData","digits","i","currElement","next","handleNavigation","key","handleBackspace","focusLeft","focusRight","input","previousInput","focus","requestAnimationFrame","syntheticEvent","InputEvent","dispatchEvent","autoAdvance","length","data","getCollectiveValue","elementTarget","HTMLElement","parent","shadowRoot","elements","element"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import { hash } from '@ember/helper';
2
3
  import { arrow } from '@floating-ui/dom';
3
4
  import { element } from 'ember-element-helper';
@@ -1 +1 @@
1
- {"version":3,"file":"popover.js","sources":["../../src/components/popover.gts"],"sourcesContent":["import { hash } from \"@ember/helper\";\n\nimport { arrow } from \"@floating-ui/dom\";\nimport { element } from \"ember-element-helper\";\nimport { modifier as eModifier } from \"ember-modifier\";\nimport { cell } from \"ember-resources\";\n\nimport { FloatingUI } from \"../floating-ui.ts\";\nimport { Portal } from \"./portal.gts\";\nimport { TARGETS } from \"./portal-targets.gts\";\n\nimport type { Signature as FloatingUiComponentSignature } from \"../floating-ui/component.ts\";\nimport type { Signature as HookSignature } from \"../floating-ui/modifier.ts\";\nimport type { TOC } from \"@ember/component/template-only\";\nimport type { ElementContext, Middleware } from \"@floating-ui/dom\";\nimport type { ModifierLike, WithBoundArgs } from \"@glint/template\";\n\nexport interface Signature {\n Args: {\n /**\n * See the Floating UI's [flip docs](https://floating-ui.com/docs/flip) for possible values.\n *\n * This argument is forwarded to the `<FloatingUI>` component.\n */\n flipOptions?: HookSignature[\"Args\"][\"Named\"][\"flipOptions\"];\n /**\n * Array of one or more objects to add to Floating UI's list of [middleware](https://floating-ui.com/docs/middleware)\n *\n * This argument is forwarded to the `<FloatingUI>` component.\n */\n middleware?: HookSignature[\"Args\"][\"Named\"][\"middleware\"];\n /**\n * See the Floating UI's [offset docs](https://floating-ui.com/docs/offset) for possible values.\n *\n * This argument is forwarded to the `<FloatingUI>` component.\n */\n offsetOptions?: HookSignature[\"Args\"][\"Named\"][\"offsetOptions\"];\n /**\n * One of the possible [`placements`](https://floating-ui.com/docs/computeposition#placement). The default is 'bottom'.\n *\n * Possible values are\n * - top\n * - bottom\n * - right\n * - left\n *\n * And may optionally have `-start` or `-end` added to adjust position along the side.\n *\n * This argument is forwarded to the `<FloatingUI>` component.\n */\n placement?: `${\"top\" | \"bottom\" | \"left\" | \"right\"}${\"\" | \"-start\" | \"-end\"}`;\n /**\n * See the Floating UI's [shift docs](https://floating-ui.com/docs/shift) for possible values.\n *\n * This argument is forwarded to the `<FloatingUI>` component.\n */\n shiftOptions?: HookSignature[\"Args\"][\"Named\"][\"shiftOptions\"];\n /**\n * CSS position property, either `fixed` or `absolute`.\n *\n * Pros and cons of each strategy are explained on [Floating UI's Docs](https://floating-ui.com/docs/computePosition#strategy)\n *\n * This argument is forwarded to the `<FloatingUI>` component.\n */\n strategy?: HookSignature[\"Args\"][\"Named\"][\"strategy\"];\n\n /**\n * By default, the popover is portaled.\n * If you don't control your CSS, and the positioning of the popover content\n * is misbehaving, you may pass \"@inline={{true}}\" to opt out of portalling.\n *\n * Inline may also be useful in nested menus, where you know exactly how the nesting occurs\n */\n inline?: boolean;\n };\n Blocks: {\n default: [\n {\n reference: FloatingUiComponentSignature[\"Blocks\"][\"default\"][0];\n setReference: FloatingUiComponentSignature[\"Blocks\"][\"default\"][2][\"setReference\"];\n Content: WithBoundArgs<typeof Content, \"floating\">;\n data: FloatingUiComponentSignature[\"Blocks\"][\"default\"][2][\"data\"];\n arrow: ModifierLike<{ Element: HTMLElement }>;\n },\n ];\n };\n}\n\nfunction getElementTag(tagName: undefined | string) {\n return tagName || \"div\";\n}\n\n/**\n * Allows lazy evaluation of the portal target (do nothing until rendered)\n * This is useful because the algorithm for finding the portal target isn't cheap.\n */\nconst Content: TOC<{\n Element: HTMLDivElement;\n Args: {\n floating: ModifierLike<{ Element: HTMLElement }>;\n inline?: boolean;\n /**\n * By default the popover content is wrapped in a div.\n * You may change this by supplying the name of an element here.\n *\n * For example:\n * ```gjs\n * <Popover as |p|>\n * <p.Content @as=\"dialog\">\n * this is now focus trapped\n * </p.Content>\n * </Popover>\n * ```\n */\n as?: string;\n };\n Blocks: { default: [] };\n}> = <template>\n {{#let (element (getElementTag @as)) as |El|}}\n {{#if @inline}}\n {{! @glint-ignore\n https://github.com/tildeio/ember-element-helper/issues/91\n https://github.com/typed-ember/glint/issues/610\n }}\n <El {{@floating}} ...attributes>\n {{yield}}\n </El>\n {{else}}\n <Portal @to={{TARGETS.popover}}>\n {{! @glint-ignore\n https://github.com/tildeio/ember-element-helper/issues/91\n https://github.com/typed-ember/glint/issues/610\n }}\n <El {{@floating}} ...attributes>\n {{yield}}\n </El>\n </Portal>\n {{/if}}\n {{/let}}\n</template>;\n\ninterface AttachArrowSignature {\n Element: HTMLElement;\n Args: {\n Named: {\n arrowElement: ReturnType<typeof ArrowElement>;\n data:\n | undefined\n | {\n placement: string;\n middlewareData?: {\n arrow?: { x?: number; y?: number };\n };\n };\n };\n };\n}\n\nconst arrowSides = {\n top: \"bottom\",\n right: \"left\",\n bottom: \"top\",\n left: \"right\",\n};\n\ntype Direction = \"top\" | \"bottom\" | \"left\" | \"right\";\ntype Placement = `${Direction}${\"\" | \"-start\" | \"-end\"}`;\n\nconst attachArrow: ModifierLike<AttachArrowSignature> = eModifier<AttachArrowSignature>(\n (element, _: [], named) => {\n if (element === named.arrowElement.current) {\n if (!named.data) return;\n if (!named.data.middlewareData) return;\n\n const { arrow } = named.data.middlewareData;\n const { placement } = named.data;\n\n if (!arrow) return;\n if (!placement) return;\n\n const { x: arrowX, y: arrowY } = arrow;\n const otherSide = (placement as Placement).split(\"-\")[0] as Direction;\n const staticSide = arrowSides[otherSide];\n\n Object.assign(named.arrowElement.current.style, {\n left: arrowX != null ? `${arrowX}px` : \"\",\n top: arrowY != null ? `${arrowY}px` : \"\",\n right: \"\",\n bottom: \"\",\n [staticSide]: \"-4px\",\n });\n\n return;\n }\n\n void (async () => {\n await Promise.resolve();\n named.arrowElement.set(element);\n })();\n },\n);\n\nconst ArrowElement: () => ReturnType<typeof cell<HTMLElement>> = () => cell<HTMLElement>();\n\nfunction maybeAddArrow(middleware: Middleware[] | undefined, element: Element | undefined) {\n const result = [...(middleware || [])];\n\n if (element) {\n result.push(arrow({ element }));\n }\n\n return result;\n}\n\nfunction flipOptions(options: HookSignature[\"Args\"][\"Named\"][\"flipOptions\"]) {\n return {\n elementContext: \"reference\" as ElementContext,\n ...options,\n };\n}\n\nexport const Popover: TOC<Signature> = <template>\n {{#let (ArrowElement) as |arrowElement|}}\n <FloatingUI\n @placement={{@placement}}\n @strategy={{@strategy}}\n @middleware={{maybeAddArrow @middleware arrowElement.current}}\n @flipOptions={{flipOptions @flipOptions}}\n @shiftOptions={{@shiftOptions}}\n @offsetOptions={{@offsetOptions}}\n as |reference floating extra|\n >\n {{#let (modifier attachArrow arrowElement=arrowElement data=extra.data) as |arrow|}}\n {{yield\n (hash\n reference=reference\n setReference=extra.setReference\n Content=(component Content floating=floating inline=@inline)\n data=extra.data\n arrow=arrow\n )\n }}\n {{/let}}\n </FloatingUI>\n {{/let}}\n</template>;\n\nexport default Popover;\n"],"names":["getElementTag","tagName","Content","setComponentTemplate","precompileTemplate","strictMode","scope","element","Portal","TARGETS","templateOnly","arrowSides","top","right","bottom","left","attachArrow","eModifier","_","named","arrowElement","current","data","middlewareData","arrow","placement","x","arrowX","y","arrowY","otherSide","split","staticSide","Object","assign","style","Promise","resolve","set","ArrowElement","cell","maybeAddArrow","middleware","result","push","flipOptions","options","elementContext","Popover","FloatingUI","hash"],"mappings":"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"}
1
+ {"version":3,"file":"popover.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import { assert } from '@ember/debug';
2
3
  import { macroCondition, isDevelopingApp } from '@embroider/macros';
3
4
  import { modifier } from 'ember-modifier';
@@ -1 +1 @@
1
- {"version":3,"file":"portal-targets.js","sources":["../../src/components/portal-targets.gts"],"sourcesContent":["import { assert } from \"@ember/debug\";\nimport { isDevelopingApp, macroCondition } from \"@embroider/macros\";\n\nimport { modifier } from \"ember-modifier\";\nimport { TrackedMap, TrackedSet } from \"tracked-built-ins\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\nconst cache = new TrackedMap<string, Set<Element>>();\n\nexport const TARGETS = Object.freeze({\n popover: \"ember-primitives__portal-targets__popover\",\n tooltip: \"ember-primitives__portal-targets__tooltip\",\n modal: \"ember-primitives__portal-targets__modal\",\n});\n\nexport function findNearestTarget(origin: Element, name: string): Element | undefined {\n assert(`first argument to \\`findNearestTarget\\` must be an element`, origin instanceof Element);\n assert(`second argument to \\`findNearestTarget\\` must be a string`, typeof name === `string`);\n\n let element: Element | undefined | null = null;\n\n let parent = origin.parentNode;\n\n const manuallyRegisteredSet = cache.get(name);\n const manuallyRegistered: Element[] | null = manuallyRegisteredSet?.size\n ? [...manuallyRegisteredSet]\n : null;\n\n /**\n * For use with <PortalTarget @name=\"hi\" />\n */\n function findRegistered(host: ParentNode): Element | undefined {\n return manuallyRegistered?.find((element) => {\n if (host.contains(element)) {\n return element;\n }\n });\n }\n\n const selector = Object.values(TARGETS as Record<string, string>).includes(name)\n ? `[data-portal-name=${name}]`\n : name;\n\n /**\n * Default portals / non-registered -- here we match a query selector instead of an element\n */\n function findDefault(host: ParentNode): Element | undefined {\n return host.querySelector(selector) as Element;\n }\n\n const finder = manuallyRegistered ? findRegistered : findDefault;\n\n /**\n * Crawl up the ancestry looking for our portal target\n */\n while (!element && parent) {\n element = finder(parent);\n if (element) break;\n parent = parent.parentNode;\n }\n\n if (macroCondition(isDevelopingApp())) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (window as any).prime0 = origin;\n }\n\n if (name.startsWith(\"ember-primitives\")) {\n assert(\n `Could not find element by the given name: \\`${name}\\`.` +\n ` The known names are ` +\n `${Object.values(TARGETS).join(\", \")} ` +\n `-- but any name will work as long as it is set to the \\`data-portal-name\\` attribute ` +\n `(or if the name has been specifically registered via the <PortalTarget /> component). ` +\n `Double check that the element you're wanting to portal to is rendered. ` +\n `The element passed to \\`findNearestTarget\\` is stored on \\`window.prime0\\` ` +\n `You can debug in your browser's console via ` +\n `\\`document.querySelector('[data-portal-name=\"${name}\"]')\\``,\n element,\n );\n }\n\n return element ?? undefined;\n}\n\nconst register = modifier((element: Element, [name]: [name: string]) => {\n assert(`@name is required when using <PortalTarget>`, name);\n\n void (async () => {\n // Bad TypeScript lint.\n // eslint-disable-next-line @typescript-eslint/await-thenable\n await 0;\n\n let existing = cache.get(name);\n\n if (!existing) {\n existing = new TrackedSet<Element>();\n cache.set(name, existing);\n }\n\n existing.add(element);\n })();\n\n return () => {\n cache.delete(name);\n };\n});\n\nexport interface Signature {\n Element: null;\n}\n\nexport const PortalTargets: TOC<Signature> = <template>\n <div data-portal-name={{TARGETS.popover}}></div>\n <div data-portal-name={{TARGETS.tooltip}}></div>\n <div data-portal-name={{TARGETS.modal}}></div>\n</template>;\n\n/**\n * For manually registering a PortalTarget for use with Portal\n */\nexport const PortalTarget: TOC<{\n Element: HTMLDivElement;\n Args: {\n /**\n * The name of the PortalTarget\n *\n * This exact string may be passed to `Portal`'s `@to` argument.\n */\n name: string;\n };\n}> = <template>\n <div {{register @name}} ...attributes></div>\n</template>;\n\nexport default PortalTargets;\n"],"names":["cache","TrackedMap","TARGETS","Object","freeze","popover","tooltip","modal","findNearestTarget","origin","name","assert","Element","element","parent","parentNode","manuallyRegisteredSet","get","manuallyRegistered","size","findRegistered","host","find","contains","selector","values","includes","findDefault","querySelector","finder","macroCondition","isDevelopingApp","window","prime0","startsWith","join","undefined","register","modifier","existing","TrackedSet","set","add","delete","PortalTargets","setComponentTemplate","precompileTemplate","strictMode","scope","templateOnly","PortalTarget"],"mappings":"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"}
1
+ {"version":3,"file":"portal-targets.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import { assert } from '@ember/debug';
2
3
  import { schedule } from '@ember/runloop';
3
4
  import { buildWaiter } from '@ember/test-waiters';
@@ -1 +1 @@
1
- {"version":3,"file":"portal.js","sources":["../../src/components/portal.gts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-redundant-type-constituents */\nimport { assert } from \"@ember/debug\";\nimport { schedule } from \"@ember/runloop\";\nimport { buildWaiter } from \"@ember/test-waiters\";\n\nimport { modifier } from \"ember-modifier\";\nimport { cell, resource, resourceFactory } from \"ember-resources\";\n\nimport { isElement } from \"../narrowing.ts\";\nimport { findNearestTarget, type TARGETS } from \"./portal-targets.gts\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\ntype Targets = (typeof TARGETS)[keyof typeof TARGETS];\n\ninterface ToSignature {\n Args: {\n to: string;\n append?: boolean;\n };\n Blocks: {\n default: [];\n };\n}\ninterface ElementSignature {\n Args: {\n to: Element;\n append?: boolean;\n };\n Blocks: {\n default: [];\n };\n}\n\nexport interface Signature {\n Args: {\n /**\n * The name of the PortalTarget to render in to.\n * This is the value of the `data-portal-name` attribute\n * of the element you wish to render in to.\n *\n * This can also be an Element which pairs nicely with query-utilities such as the platform-native `querySelector`\n */\n to?: (Targets | (string & {})) | Element;\n\n /**\n * Set to true to append to the portal instead of replace\n *\n * Default: false\n */\n append?: boolean;\n /**\n * For ember-wormhole style behavior, this argument may be an id,\n * or a selector.\n * This can also be an element, in which case the behavior is identical to `@to`\n */\n wormhole?: string | Element;\n };\n Blocks: {\n /**\n * The portaled content\n */\n default: [];\n };\n}\n\n/**\n * Polyfill for ember-wormhole behavior\n *\n * Example usage:\n * ```gjs\n * import { wormhole, Portal } from 'ember-primitives/components/portal';\n *\n * <template>\n * <div id=\"the-portal\"></div>\n *\n * <Portal @to={{wormhole \"the-portal\"}}>\n * content renders in the above div\n * </Portal>\n * </template>\n *\n * ```\n */\nexport function wormhole(query: string | null | undefined | Element) {\n assert(`Expected query/element to be truthy.`, query);\n\n if (isElement(query)) {\n return query;\n }\n\n let found = document.getElementById(query);\n\n found ??= document.querySelector(query);\n\n return found;\n}\n\nconst anchor = modifier(\n (element: Element, [to, update]: [string, ReturnType<typeof ElementValue>[\"set\"]]) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n const found = findNearestTarget(element, to);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n update(found);\n },\n);\n\nconst ElementValue = () => cell<Element | ShadowRoot | null | undefined>();\n\nconst waiter = buildWaiter(\"ember-primitives:portal\");\n\nfunction wormholeCompat(selector: string | Element) {\n const target = wormhole(selector);\n\n if (target) return target;\n\n return resource(() => {\n const target = cell<Element | undefined | null>();\n\n const token = waiter.beginAsync();\n\n // eslint-disable-next-line ember/no-runloop\n schedule(\"afterRender\", () => {\n const result = wormhole(selector);\n\n waiter.endAsync(token);\n target.current = result;\n assert(\n `Could not find element with id/selector \\`${typeof selector === \"string\" ? selector : \"<Element>\"}\\``,\n result,\n );\n });\n\n return () => target.current;\n });\n}\n\nresourceFactory(wormholeCompat);\n\nexport const Portal: TOC<Signature> = <template>\n {{#if (isElement @to)}}\n <ToElement @to={{@to}} @append={{@append}}>\n {{yield}}\n </ToElement>\n {{else if @wormhole}}\n {{#let (wormholeCompat @wormhole) as |target|}}\n {{#if target}}\n {{#in-element target insertBefore=null}}\n {{yield}}\n {{/in-element}}\n {{/if}}\n {{/let}}\n {{else if @to}}\n <Nestable @to={{@to}} @append={{@append}}>\n {{yield}}\n </Nestable>\n {{else}}\n {{assert \"either @to or @wormhole is required. Received neither\"}}\n {{/if}}\n</template>;\n\nconst ToElement: TOC<ElementSignature> = <template>\n {{#if @append}}\n {{#in-element @to insertBefore=null}}\n {{yield}}\n {{/in-element}}\n {{else}}\n {{#in-element @to}}\n {{yield}}\n {{/in-element}}\n {{/if}}\n</template>;\n\nconst Nestable: TOC<ToSignature> = <template>\n {{#let (ElementValue) as |target|}}\n {{! This div is always going to be empty,\n because it'll either find the portal and render content elsewhere,\n it it won't find the portal and won't render anything.\n }}\n {{! template-lint-disable no-inline-styles }}\n <div style=\"display:contents;\" {{anchor @to target.set}}>\n {{#if target.current}}\n {{#if @append}}\n {{#in-element target.current insertBefore=null}}\n {{yield}}\n {{/in-element}}\n {{else}}\n {{#in-element target.current}}\n {{yield}}\n {{/in-element}}\n {{/if}}\n {{/if}}\n </div>\n {{/let}}\n</template>;\n\nexport default Portal;\n"],"names":["wormhole","query","assert","isElement","found","document","getElementById","querySelector","anchor","modifier","element","to","update","findNearestTarget","ElementValue","cell","waiter","buildWaiter","wormholeCompat","selector","target","resource","token","beginAsync","schedule","result","endAsync","current","resourceFactory","Portal","setComponentTemplate","precompileTemplate","strictMode","scope","ToElement","Nestable","templateOnly"],"mappings":";;;;;;;;;;;AAAA;AAkEA;;;;;;;;;;;;;;;;;AAiBO,SAASA,QAAAA,CAASC,KAA0C,EAAA;AACjEC,EAAAA,MAAA,CAAO,CAAA,oCAAA,CAAsC,EAAED,KAAA,CAAA;AAE/C,EAAA,IAAIE,UAAUF,KAAA,CAAA,EAAQ;AACpB,IAAA,OAAOA,KAAA;AACT,EAAA;AAEA,EAAA,IAAIG,KAAA,GAAQC,QAAA,CAASC,cAAc,CAACL,KAAA,CAAA;AAEpCG,EAAAA,KAAA,KAAUC,QAAA,CAASE,aAAa,CAACN,KAAA,CAAA;AAEjC,EAAA,OAAOG,KAAA;AACT;AAEA,MAAMI,MAAA,GAASC,QAAA,CACb,CAACC,OAAS,EAAS,CAACC,EAAA,EAAIC,MAAA,CAAyD,KAAA;AAC/E;AACA,EAAA,MAAMR,KAAA,GAAQS,kBAAkBH,OAAA,EAASC,EAAA,CAAA;AAEzC;EACAC,MAAA,CAAOR,KAAA,CAAA;AACT,CAAA,CAAA;AAGF,MAAMU,eAAeA,MAAMC,IAAA,EAA4C;AAEvE,MAAMC,SAASC,WAAA,CAAY,yBAAA,CAAA;AAE3B,SAASC,cAAAA,CAAeC,QAA0B,EAAA;AAChD,EAAA,MAAMC,SAASpB,QAAA,CAASmB,QAAA,CAAA;EAExB,IAAIC,QAAQ,OAAOA,MAAA;EAEnB,OAAOC,QAAA,CAAS,MAAA;AACd,IAAA,MAAMD,MAAA,GAASL,IAAA,EAA+B;AAE9C,IAAA,MAAMO,KAAA,GAAQN,OAAOO,UAAU,EAAA;AAE/B;IACAC,QAAA,CAAS,aAAA,EAAe,MAAA;AACtB,MAAA,MAAMC,SAASzB,QAAA,CAASmB,QAAA,CAAA;AAExBH,MAAAA,MAAA,CAAOU,QAAQ,CAACJ,KAAA,CAAA;MAChBF,MAAA,CAAOO,OAAO,GAAGF,MAAA;AACjBvB,MAAAA,MAAA,CACE,CAAA,0CAAA,EAA6C,OAAOiB,QAAA,KAAa,WAAWA,QAAA,GAAW,WAAA,CAAA,EAAA,CAAe,EACtGM,MAAA,CAAA;AAEJ,IAAA,CAAA,CAAA;IAEA,OAAO,MAAML,OAAOO,OAAO;AAC7B,EAAA,CAAA,CAAA;AACF;AAEAC,eAAA,CAAgBV,cAAA,CAAA;MAEHW,MAAY,GAAAC,oBAAA,CAAaC,kBAAA,CAAA,0hBAAA,EAoBtC;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAA9B,SAAA;IAAA+B,SAAA;IAAAhB,cAAA;IAAAiB,QAAA;AAAAjC,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAkC,YAAA,EAAA;AAEV,MAAMF,SAAe,GAAAJ,oBAAA,CAAoBC,kBAAA,CAAA,8LAAA,EAUzC;EAAAC,UAAA,EAAA;AAAU,CAAA,CAAA,EAAAI,YAAA,EAAA,CAAA;AAEV,MAAMD,QAAc,GAAAL,oBAAA,CAAeC,kBAAA,CAAA,2rBAAA,EAqBnC;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAnB,YAAA;AAAAN,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAA4B,YAAA,EAAA,CAAA;;;;"}
1
+ {"version":3,"file":"portal.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import Component from '@glimmer/component';
2
3
  import { hash } from '@ember/helper';
3
4
  import { precompileTemplate } from '@ember/template-compilation';
@@ -1 +1 @@
1
- {"version":3,"file":"progress.js","sources":["../../src/components/progress.gts"],"sourcesContent":["import Component from \"@glimmer/component\";\nimport { hash } from \"@ember/helper\";\n\nimport type { TOC } from \"@ember/component/template-only\";\nimport type { WithBoundArgs } from \"@glint/template\";\n\nexport interface Signature {\n Element: HTMLDivElement;\n Args: {\n /**\n * The current progress\n * This may be less than 0 or more than `max`,\n * but the resolved value (managed internally, and yielded out)\n * does not exceed the range [0, max]\n */\n value: number;\n /**\n * The max value, defaults to 100\n */\n max?: number;\n };\n Blocks: {\n default: [\n {\n /**\n * The indicator element with some state applied.\n * This can be used to style the progress of bar.\n */\n Indicator: WithBoundArgs<typeof Indicator, \"value\" | \"max\" | \"percent\">;\n /**\n * The value as a percent of how far along the indicator should be\n * positioned, between 0 and 100.\n * Will be rounded to two decimal places.\n */\n percent: number;\n /**\n * The value as a percent of how far along the indicator should be positioned,\n * between 0 and 1\n */\n decimal: number;\n /**\n * The resolved value within the limits of the progress bar.\n */\n value: number;\n },\n ];\n };\n}\n\ntype ProgressState = \"indeterminate\" | \"complete\" | \"loading\";\n\nconst DEFAULT_MAX = 100;\n\n/**\n * Non-negative, non-NaN, non-Infinite, positive, rational\n */\nfunction isValidProgressNumber(value: number | undefined | null): value is number {\n if (typeof value !== \"number\") return false;\n if (!Number.isFinite(value)) return false;\n\n return value >= 0;\n}\n\nfunction progressState(value: number | undefined | null, maxValue: number): ProgressState {\n return value == null ? \"indeterminate\" : value === maxValue ? \"complete\" : \"loading\";\n}\n\nfunction getMax(userMax: number | undefined | null): number {\n return isValidProgressNumber(userMax) ? userMax : DEFAULT_MAX;\n}\n\nfunction getValue(userValue: number | undefined | null, maxValue: number): number {\n const max = getMax(maxValue);\n\n if (!isValidProgressNumber(userValue)) {\n return 0;\n }\n\n if (userValue > max) {\n return max;\n }\n\n return userValue;\n}\n\nfunction getValueLabel(value: number, max: number) {\n return `${Math.round((value / max) * 100)}%`;\n}\n\nconst Indicator: TOC<{\n Element: HTMLDivElement;\n Args: { max: number; value: number; percent: number };\n Blocks: { default: [] };\n}> = <template>\n <div\n ...attributes\n data-max={{@max}}\n data-value={{@value}}\n data-state={{progressState @value @max}}\n data-percent={{@percent}}\n >\n {{yield}}\n </div>\n</template>;\n\nexport class Progress extends Component<Signature> {\n get max() {\n return getMax(this.args.max);\n }\n\n get value() {\n return getValue(this.args.value, this.max);\n }\n\n get valueLabel() {\n return getValueLabel(this.value, this.max);\n }\n\n get decimal() {\n return this.value / this.max;\n }\n\n get percent() {\n return Math.round(this.decimal * 100 * 100) / 100;\n }\n\n <template>\n <div\n ...attributes\n aria-valuemax={{this.max}}\n aria-valuemin=\"0\"\n aria-valuenow={{this.value}}\n aria-valuetext={{this.valueLabel}}\n role=\"progressbar\"\n data-value={{this.value}}\n data-state={{progressState this.value this.max}}\n data-max={{this.max}}\n data-min=\"0\"\n data-percent={{this.percent}}\n >\n\n {{yield\n (hash\n Indicator=(component Indicator value=this.value max=this.max percent=this.percent)\n value=this.value\n percent=this.percent\n decimal=this.decimal\n )\n }}\n </div>\n </template>\n}\n\nexport default Progress;\n"],"names":["DEFAULT_MAX","isValidProgressNumber","value","Number","isFinite","progressState","maxValue","getMax","userMax","getValue","userValue","max","getValueLabel","Math","round","Indicator","setComponentTemplate","precompileTemplate","strictMode","scope","templateOnly","Progress","Component","args","valueLabel","decimal","percent","hash"],"mappings":";;;;;;AAmDA,MAAMA,WAAA,GAAc,GAAA;AAEpB;;;AAGA,SAASC,qBAAAA,CAAsBC,KAAgC,EAAkB;AAC/E,EAAA,IAAI,OAAOA,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;EACtC,IAAI,CAACC,MAAA,CAAOC,QAAQ,CAACF,QAAQ,OAAO,KAAA;EAEpC,OAAOA,KAAA,IAAS,CAAA;AAClB;AAEA,SAASG,aAAAA,CAAcH,KAAgC,EAAEI,QAAgB,EAAG;AAC1E,EAAA,OAAOJ,KAAA,IAAS,IAAA,GAAO,eAAA,GAAkBA,KAAA,KAAUI,WAAW,UAAA,GAAa,SAAA;AAC7E;AAEA,SAASC,MAAAA,CAAOC,OAAkC,EAAS;AACzD,EAAA,OAAOP,qBAAA,CAAsBO,WAAWA,OAAA,GAAUR,WAAA;AACpD;AAEA,SAASS,QAAAA,CAASC,SAAoC,EAAEJ,QAAgB,EAAS;AAC/E,EAAA,MAAMK,MAAMJ,MAAA,CAAOD,QAAA,CAAA;AAEnB,EAAA,IAAI,CAACL,sBAAsBS,SAAA,CAAA,EAAY;AACrC,IAAA,OAAO,CAAA;AACT,EAAA;EAEA,IAAIA,YAAYC,GAAA,EAAK;AACnB,IAAA,OAAOA,GAAA;AACT,EAAA;AAEA,EAAA,OAAOD,SAAA;AACT;AAEA,SAASE,aAAAA,CAAcV,KAAa,EAAES,GAAW,EAAA;EAC/C,OAAO,CAAA,EAAGE,IAAA,CAAKC,KAAK,CAAEZ,KAAA,GAAQS,GAAG,GAAI,GAAA,CAAA,CAAA,CAAA,CAAO;AAC9C;AAEA,MAAMI,SAID,GAAAC,oBAAA,CAAAC,kBAAA,CAAA,+JAAA,EAUL;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;AAAAd,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAe,YAAA,EAAA,CAAA;AAEH,MAAMC,iBAAiBC,SAAA,CAAU;EACtC,IAAIX,GAAAA,GAAM;AACR,IAAA,OAAOJ,MAAA,CAAO,IAAI,CAACgB,IAAI,CAACZ,GAAG,CAAA;AAC7B,EAAA;EAEA,IAAIT,KAAAA,GAAQ;IACV,OAAOO,QAAA,CAAS,IAAI,CAACc,IAAI,CAACrB,KAAK,EAAE,IAAI,CAACS,GAAG,CAAA;AAC3C,EAAA;EAEA,IAAIa,UAAAA,GAAa;IACf,OAAOZ,cAAc,IAAI,CAACV,KAAK,EAAE,IAAI,CAACS,GAAG,CAAA;AAC3C,EAAA;EAEA,IAAIc,OAAAA,GAAU;AACZ,IAAA,OAAO,IAAI,CAACvB,KAAK,GAAG,IAAI,CAACS,GAAG;AAC9B,EAAA;EAEA,IAAIe,OAAAA,GAAU;AACZ,IAAA,OAAOb,IAAA,CAAKC,KAAK,CAAC,IAAI,CAACW,OAAO,GAAG,MAAM,GAAA,CAAA,GAAO,GAAA;AAChD,EAAA;AAEA,EAAA;IAAAT,oBAAA,CAAAC,kBAAA,CAAA,qeAAA,EAwBA;MAAAC,UAAA,EAAA,IAAA;AAAAC,MAAAA,KAAA,EAAAA,OAAA;QAAAd,aAAA;QAAAsB,IAAA;AAAAZ,QAAAA;AAAA,OAAA;KAAU,CAAA,EAAV,IAAW,CAAA;AAAD;AACZ;;;;"}
1
+ {"version":3,"file":"progress.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import Component from '@glimmer/component';
2
3
  import { hash } from '@ember/helper';
3
4
  import { on } from '@ember/modifier';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/components/rating/index.gts"],"sourcesContent":["import Component from \"@glimmer/component\";\nimport { hash } from \"@ember/helper\";\nimport { on } from \"@ember/modifier\";\n\nimport { uniqueId } from \"../../utils.ts\";\nimport { RatingRange } from \"./range.gts\";\nimport { Stars } from \"./stars.gts\";\nimport { RatingState } from \"./state.gts\";\n\nimport type { ComponentIcons, StringIcons } from \"./public-types.ts\";\nimport type { WithBoundArgs } from \"@glint/template\";\n\nexport interface Signature {\n /*\n * The element all passed attributes / modifiers are applied to.\n *\n * This is a `<fieldset>`, becaues the rating elements are\n * powered by a group of radio buttons.\n */\n Element: HTMLFieldSetElement;\n Args: (ComponentIcons | StringIcons) & {\n /**\n * The number of stars/whichever-icon to show\n *\n * Defaults to 5\n */\n max?: number;\n\n /**\n * The current number of stars/whichever-icon to show as selected\n *\n * Defaults to 0\n */\n value?: number;\n\n /**\n * Prevents click events on the icons and sets aria-readonly.\n *\n * Also sets data-readonly=true on the wrapping element\n */\n readonly?: boolean;\n\n /**\n * Toggles the ability to interact with the rating component.\n * When `true` (the default), the Rating component can be as a form input\n * to gather user feedback.\n *\n * When false, only the `@value` will be shown, and it cannot be changed.\n */\n interactive?: boolean;\n\n /**\n * Callback when the selected rating changes.\n * Can include half-ratings if the iconHalf argument is passed.\n */\n onChange?: (value: number) => void;\n };\n\n Blocks: {\n default: [\n rating: {\n /**\n * The maximum rating\n */\n max: number;\n /**\n * The maxium rating\n */\n total: number;\n /**\n * The current rating\n */\n value: number;\n /**\n * The name shared by the field group\n */\n name: string;\n /**\n * If the rating can be changed\n */\n isReadonly: boolean;\n /**\n * If the rating can be changed\n */\n isChangeable: boolean;\n /**\n * The stars / items radio group\n */\n Stars: WithBoundArgs<\n typeof Stars,\n \"stars\" | \"icon\" | \"isReadonly\" | \"name\" | \"total\" | \"currentValue\"\n >;\n /**\n * Input range for adjusting the rating via fractional means\n */\n Range: WithBoundArgs<typeof RatingRange, \"max\" | \"value\" | \"name\" | \"handleChange\">;\n },\n ];\n label: [\n state: {\n /**\n * The current rating\n */\n value: number;\n\n /**\n * The maximum rating\n */\n total: number;\n },\n ];\n };\n}\n\nexport class Rating extends Component<Signature> {\n name = `rating-${uniqueId()}`;\n\n get icon() {\n return this.args.icon ?? \"★\";\n }\n\n get isInteractive() {\n return this.args.interactive ?? true;\n }\n\n get isChangeable() {\n const readonly = this.args.readonly ?? false;\n\n return !readonly && this.isInteractive;\n }\n\n get isReadonly() {\n return !this.isChangeable;\n }\n\n get needsDescription() {\n return !this.isInteractive;\n }\n\n <template>\n <RatingState\n @max={{@max}}\n @value={{@value}}\n @name={{this.name}}\n @readonly={{this.isReadonly}}\n @onChange={{@onChange}}\n as |r publicState|\n >\n <fieldset\n class=\"ember-primitives__rating\"\n data-total={{r.total}}\n data-value={{r.value}}\n data-readonly={{this.isReadonly}}\n {{! We use event delegation, this isn't a primary interactive -- we're capturing events from inputs }}\n {{! template-lint-disable no-invalid-interactive }}\n {{on \"click\" r.handleClick}}\n ...attributes\n >\n {{#let\n (component\n Stars\n stars=r.stars\n icon=this.icon\n isReadonly=this.isReadonly\n name=this.name\n total=r.total\n currentValue=r.value\n )\n as |RatingStars|\n }}\n\n {{#if (has-block)}}\n {{yield\n (hash\n max=r.total\n total=r.total\n value=r.value\n name=this.name\n isReadonly=this.isReadonly\n isChangeable=this.isChangeable\n Stars=RatingStars\n Range=(component\n RatingRange max=r.total value=r.value name=this.name handleChange=r.handleChange\n )\n )\n }}\n {{else}}\n {{#if this.needsDescription}}\n {{#if (has-block \"label\")}}\n {{yield publicState to=\"label\"}}\n {{else}}\n <span visually-hidden class=\"ember-primitives__rating__label\">Rated\n {{r.value}}\n out of\n {{r.total}}</span>\n {{/if}}\n {{else}}\n {{#if (has-block \"label\")}}\n <legend>\n {{yield publicState to=\"label\"}}\n </legend>\n {{/if}}\n {{/if}}\n\n <RatingStars />\n {{/if}}\n {{/let}}\n\n </fieldset>\n </RatingState>\n </template>\n}\n"],"names":["Rating","Component","name","uniqueId","icon","args","isInteractive","interactive","isChangeable","readonly","isReadonly","needsDescription","setComponentTemplate","precompileTemplate","strictMode","scope","RatingState","on","Stars","hash","RatingRange"],"mappings":";;;;;;;;;;AAkHO,MAAMA,eAAeC,SAAA,CAAU;AACpCC,EAAAA,IAAA,GAAO,CAAA,OAAA,EAAUC,QAAA,EAAA,CAAA,CAAY;EAE7B,IAAIC,IAAAA,GAAO;AACT,IAAA,OAAO,IAAI,CAACC,IAAI,CAACD,IAAI,IAAI,GAAA;AAC3B,EAAA;EAEA,IAAIE,aAAAA,GAAgB;AAClB,IAAA,OAAO,IAAI,CAACD,IAAI,CAACE,WAAW,IAAI,IAAA;AAClC,EAAA;EAEA,IAAIC,YAAAA,GAAe;IACjB,MAAMC,WAAW,IAAI,CAACJ,IAAI,CAACI,QAAQ,IAAI,KAAA;AAEvC,IAAA,OAAO,CAACA,QAAA,IAAY,IAAI,CAACH,aAAa;AACxC,EAAA;EAEA,IAAII,UAAAA,GAAa;IACf,OAAO,CAAC,IAAI,CAACF,YAAY;AAC3B,EAAA;EAEA,IAAIG,gBAAAA,GAAmB;IACrB,OAAO,CAAC,IAAI,CAACL,aAAa;AAC5B,EAAA;AAEA,EAAA;IAAAM,oBAAA,CAAAC,kBAAA,CAAA,2nDAAA,EAuEA;MAAAC,UAAA,EAAA,IAAA;AAAAC,MAAAA,KAAA,EAAAA,OAAA;QAAAC,WAAA;QAAAC,EAAA;QAAAC,KAAA;QAAAC,IAAA;AAAAC,QAAAA;AAAA,OAAA;KAAU,CAAA,EAAV,IAAW,CAAA;AAAD;AACZ;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import { on } from '@ember/modifier';
2
3
  import { precompileTemplate } from '@ember/template-compilation';
3
4
  import { setComponentTemplate } from '@ember/component';
@@ -1 +1 @@
1
- {"version":3,"file":"range.js","sources":["../../../src/components/rating/range.gts"],"sourcesContent":["import { on } from \"@ember/modifier\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\nexport const RatingRange: TOC<{\n Element: HTMLInputElement;\n Args: {\n name: string;\n max: number;\n value: number;\n handleChange: (event: Event) => void;\n };\n}> = <template>\n <input\n ...attributes\n name={{@name}}\n type=\"range\"\n max={{@max}}\n value={{@value}}\n {{on \"change\" @handleChange}}\n />\n</template>;\n"],"names":["RatingRange","setComponentTemplate","precompileTemplate","strictMode","scope","on","templateOnly"],"mappings":";;;;;MAIaA,WAQR,GAAAC,oBAAA,CAAAC,kBAAA,CAAA,2HAAA,EASL;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;AAAAC,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAC,YAAA,EAAA;;;;"}
1
+ {"version":3,"file":"range.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import { uniqueId } from '../../utils.js';
2
3
  import { isString, lte, percentSelected } from './utils.js';
3
4
  import { precompileTemplate } from '@ember/template-compilation';
@@ -1 +1 @@
1
- {"version":3,"file":"stars.js","sources":["../../../src/components/rating/stars.gts"],"sourcesContent":["import { uniqueId } from \"../../utils.ts\";\nimport { isString, lte, percentSelected } from \"./utils.ts\";\n\nimport type { ComponentIcons, StringIcons } from \"./public-types.ts\";\nimport type { TOC } from \"@ember/component/template-only\";\n\nexport const Stars: TOC<{\n Args: {\n // Configuration\n stars: number[];\n icon: StringIcons[\"icon\"] | ComponentIcons[\"icon\"];\n isReadonly: boolean;\n\n // HTML Boilerplate\n name: string;\n\n // State\n currentValue: number;\n total: number;\n };\n}> = <template>\n <div class=\"ember-primitives__rating__items\">\n {{#each @stars as |star|}}\n {{#let (uniqueId) as |id|}}\n <span\n class=\"ember-primitives__rating__item\"\n data-number={{star}}\n data-percent-selected={{percentSelected star @currentValue}}\n data-selected={{lte star @currentValue}}\n data-readonly={{@isReadonly}}\n >\n <label for=\"input-{{id}}\">\n <span visually-hidden>{{star}} star</span>\n <span aria-hidden=\"true\">\n {{#if (isString @icon)}}\n {{@icon}}\n {{else}}\n <@icon\n @value={{star}}\n @isSelected={{lte star @currentValue}}\n @percentSelected={{percentSelected star @currentValue}}\n @readonly={{@isReadonly}}\n />\n {{/if}}\n </span>\n </label>\n\n <input\n id=\"input-{{id}}\"\n type=\"radio\"\n name={{@name}}\n value={{star}}\n readonly={{@isReadonly}}\n checked={{lte star @currentValue}}\n />\n </span>\n {{/let}}\n {{/each}}\n </div>\n</template>;\n"],"names":["Stars","setComponentTemplate","precompileTemplate","strictMode","scope","uniqueId","percentSelected","lte","isString","templateOnly"],"mappings":";;;;;;MAMaA,KAcR,GAAAC,oBAAA,CAAAC,kBAAA,CAAA,k+BAAA,EAuCL;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAC,QAAA;IAAAC,eAAA;IAAAC,GAAA;AAAAC,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAC,YAAA,EAAA;;;;"}
1
+ {"version":3,"file":"stars.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import Component from '@glimmer/component';
2
3
  import { cached } from '@glimmer/tracking';
3
4
  import { assert } from '@ember/debug';
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sources":["../../../src/components/rating/state.gts"],"sourcesContent":["import Component from \"@glimmer/component\";\nimport { cached } from \"@glimmer/tracking\";\nimport { assert } from \"@ember/debug\";\nimport { hash } from \"@ember/helper\";\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-expect-error\nimport { localCopy } from \"tracked-toolbox\";\n\nexport class RatingState extends Component<{\n Args: {\n max: number | undefined;\n value: number | undefined;\n readonly: boolean | undefined;\n name: string;\n onChange?: (value: number) => void;\n };\n Blocks: {\n default: [\n internalApi: {\n stars: number[];\n value: number;\n total: number;\n handleClick: (event: Event) => void;\n handleChange: (event: Event) => void;\n setRating: (num: number) => void;\n },\n publicApi: {\n value: number;\n total: number;\n },\n ];\n };\n}> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n @localCopy(\"args.value\") declare _value: number;\n\n get value() {\n return this._value ?? 0;\n }\n\n @cached\n get stars() {\n return Array.from({ length: this.args.max ?? 5 }, (_, index) => index + 1);\n }\n\n setRating = (value: number) => {\n if (this.args.readonly) {\n return;\n }\n\n if (value === this._value) {\n this._value = 0;\n } else {\n this._value = value;\n }\n\n this.args.onChange?.(value);\n };\n\n setFromString = (value: unknown) => {\n assert(\"[BUG]: value from input must be a string.\", typeof value === \"string\");\n\n const num = parseFloat(value);\n\n if (isNaN(num)) {\n // something went wrong.\n // Since we're using event delegation,\n // this could be from an unrelated input\n return;\n }\n\n this.setRating(num);\n };\n\n /**\n * Click events are captured by\n * - radio changes (mouse and keyboard)\n * - but only range clicks\n */\n handleClick = (event: Event) => {\n // Since we're doing event delegation on a click, we want to make sure\n // we don't do anything on other elements\n const isValid =\n event.target instanceof HTMLInputElement &&\n event.target.name === this.args.name &&\n event.target.type === \"radio\";\n\n if (!isValid) return;\n\n const selected = event.target?.value;\n\n this.setFromString(selected);\n };\n\n /**\n * Only attached to a range element, if present.\n * Range elements don't fire click events on keyboard usage, like radios do\n */\n handleChange = (event: Event) => {\n const isValid = event.target !== null && \"value\" in event.target;\n\n if (!isValid) return;\n\n this.setFromString(event.target.value);\n };\n\n <template>\n {{yield\n (hash\n stars=this.stars\n total=this.stars.length\n handleClick=this.handleClick\n handleChange=this.handleChange\n setRating=this.setRating\n value=this.value\n )\n (hash total=this.stars.length value=this.value)\n }}\n </template>\n}\n"],"names":["RatingState","Component","localCopy","i","void 0","value","_value","stars","Array","from","length","args","max","_","index","n","prototype","cached","setRating","readonly","onChange","setFromString","assert","num","parseFloat","isNaN","handleClick","event","isValid","target","HTMLInputElement","name","type","selected","handleChange","setComponentTemplate","precompileTemplate","strictMode","scope","hash"],"mappings":";;;;;;;;;AASO,MAAMA,WAAA,SAAoBC,SAAA;;iCA0B9BC,SAAA,CAAU,YAAA,CAAA,CAAA,CAAA;AAAA;AAAA,EAAA,OAAA,IAAAC,CAAA,CAAA,IAAA,EAAA,QAAA,CAAA,EAAAC,MAAA,EAAA;EAEX,IAAIC,KAAAA,GAAQ;AACV,IAAA,OAAO,IAAI,CAACC,MAAM,IAAI,CAAA;AACxB,EAAA;EAEA,IACIC,KAAAA,GAAQ;IACV,OAAOC,KAAA,CAAMC,IAAI,CAAC;AAAEC,MAAAA,MAAA,EAAQ,IAAI,CAACC,IAAI,CAACC,GAAG,IAAI;KAAE,EAAG,CAACC,CAAA,EAAGC,KAAA,KAAUA,KAAA,GAAQ,CAAA,CAAA;AAC1E,EAAA;AAAA,EAAA;IAAAC,CAAA,CAAA,IAAA,CAAAC,SAAA,EAAA,OAAA,EAAA,CAHCC,MAAA,CAAA,CAAA;AAAA;EAKDC,SAAA,GAAab,KAAa,IAAA;AACxB,IAAA,IAAI,IAAI,CAACM,IAAI,CAACQ,QAAQ,EAAE;AACtB,MAAA;AACF,IAAA;AAEA,IAAA,IAAId,KAAA,KAAU,IAAI,CAACC,MAAM,EAAE;MACzB,IAAI,CAACA,MAAM,GAAG,CAAA;AAChB,IAAA,CAAA,MAAO;MACL,IAAI,CAACA,MAAM,GAAGD,KAAA;AAChB,IAAA;AAEA,IAAA,IAAI,CAACM,IAAI,CAACS,QAAQ,GAAGf,KAAA,CAAA;EACvB,CAAA;EAEAgB,aAAA,GAAiBhB,KAAc,IAAA;AAC7BiB,IAAAA,MAAA,CAAO,2CAAA,EAA6C,OAAOjB,KAAA,KAAU,QAAA,CAAA;AAErE,IAAA,MAAMkB,MAAMC,UAAA,CAAWnB,KAAA,CAAA;AAEvB,IAAA,IAAIoB,MAAMF,GAAA,CAAA,EAAM;AACd;AACA;AACA;AACA,MAAA;AACF,IAAA;AAEA,IAAA,IAAI,CAACL,SAAS,CAACK,GAAA,CAAA;EACjB,CAAA;AAEA;;;;;EAKAG,WAAA,GAAeC,KAAO,IAAA;AACpB;AACA;IACA,MAAMC,OAAA,GACJD,MAAME,MAAM,YAAYC,oBACxBH,KAAA,CAAME,MAAM,CAACE,IAAI,KAAK,IAAI,CAACpB,IAAI,CAACoB,IAAI,IACpCJ,MAAME,MAAM,CAACG,IAAI,KAAK,OAAA;IAExB,IAAI,CAACJ,OAAA,EAAS;AAEd,IAAA,MAAMK,QAAA,GAAWN,KAAA,CAAME,MAAM,EAAExB,KAAA;AAE/B,IAAA,IAAI,CAACgB,aAAa,CAACY,QAAA,CAAA;EACrB,CAAA;AAEA;;;;EAIAC,YAAA,GAAgBP,KAAO,IAAA;AACrB,IAAA,MAAMC,UAAUD,KAAA,CAAME,MAAM,KAAK,IAAA,IAAQ,OAAA,IAAWF,MAAME,MAAM;IAEhE,IAAI,CAACD,OAAA,EAAS;IAEd,IAAI,CAACP,aAAa,CAACM,KAAA,CAAME,MAAM,CAACxB,KAAK,CAAA;EACvC,CAAA;AAEA,EAAA;IAAA8B,oBAAA,CAAAC,kBAAA,CAAA,2NAAA,EAYA;MAAAC,UAAA,EAAA,IAAA;AAAAC,MAAAA,KAAA,EAAAA,OAAA;AAAAC,QAAAA;AAAA,OAAA;KAAU,CAAA,EAAV,IAAW,CAAA;AAAD;AACZ;;;;"}
1
+ {"version":3,"file":"state.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  function isString(x) {
2
3
  return typeof x === 'string';
3
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/components/rating/utils.ts"],"sourcesContent":["export function isString(x: unknown) {\n return typeof x === 'string';\n}\n\nexport function lte(a: number, b: number) {\n return a <= b;\n}\n\nexport function percentSelected(a: number, b: number) {\n const diff = b + 1 - a;\n\n if (diff < 0) return 0;\n if (diff > 1) return 100;\n if (a === b) return 100;\n\n const percent = diff * 100;\n\n return percent;\n}\n"],"names":["isString","x","lte","a","b","percentSelected","diff","percent"],"mappings":"AAAO,SAASA,QAAQA,CAACC,CAAU,EAAE;EACnC,OAAO,OAAOA,CAAC,KAAK,QAAQ;AAC9B;AAEO,SAASC,GAAGA,CAACC,CAAS,EAAEC,CAAS,EAAE;EACxC,OAAOD,CAAC,IAAIC,CAAC;AACf;AAEO,SAASC,eAAeA,CAACF,CAAS,EAAEC,CAAS,EAAE;AACpD,EAAA,MAAME,IAAI,GAAGF,CAAC,GAAG,CAAC,GAAGD,CAAC;AAEtB,EAAA,IAAIG,IAAI,GAAG,CAAC,EAAE,OAAO,CAAC;AACtB,EAAA,IAAIA,IAAI,GAAG,CAAC,EAAE,OAAO,GAAG;AACxB,EAAA,IAAIH,CAAC,KAAKC,CAAC,EAAE,OAAO,GAAG;AAEvB,EAAA,MAAMG,OAAO,GAAGD,IAAI,GAAG,GAAG;AAE1B,EAAA,OAAOC,OAAO;AAChB;;;;"}
1
+ {"version":3,"file":"utils.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,2 +1,3 @@
1
+
1
2
  export { Rating } from './rating/index.js';
2
3
  //# sourceMappingURL=rating.js.map
@@ -1,3 +1,4 @@
1
+
1
2
  import Component from '@glimmer/component';
2
3
  import { isDestroyed, isDestroying } from '@ember/destroyable';
3
4
  import { hash } from '@ember/helper';
@@ -1 +1 @@
1
- {"version":3,"file":"scroller.js","sources":["../../src/components/scroller.gts"],"sourcesContent":["import Component from \"@glimmer/component\";\nimport { isDestroyed, isDestroying } from \"@ember/destroyable\";\nimport { hash } from \"@ember/helper\";\n\nimport { modifier } from \"ember-modifier\";\n\n/**\n * Utility component for helping with scrolling in any direction within\n * any of the 4 directions: up, down, left, right.\n *\n * This can be used to auto-scroll content as new content is inserted into the scrollable area, or possibly to bring focus to something on the page.\n */\nexport class Scroller extends Component<{\n /**\n * A containing element is required - in this case, a div.\n * It must be scrollable for this component to work, but can be customized.\n *\n * By default, this element will have some styling applied:\n * overflow: auto;\n *\n * By default, this element will have tabindex=\"0\" to support keyboard usage.\n *\n * The scroll-behavior is \"auto\", which can be controlled via CSS\n * https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior\n *\n */\n Element: HTMLDivElement;\n Blocks: {\n default: [\n {\n /**\n * Scroll the content to the bottom\n *\n * ```gjs\n * import { Scroller } from 'ember-primitives';\n *\n * <template>\n * <Scroller as |s|>\n * ...\n *\n * {{ (s.scrollToBottom) }}\n * </Scroller>\n * </template>\n * ```\n */\n scrollToBottom: () => void;\n /**\n * Scroll the content to the top\n *\n * ```gjs\n * import { Scroller } from 'ember-primitives';\n *\n * <template>\n * <Scroller as |s|>\n * ...\n *\n * {{ (s.scrollToTop) }}\n * </Scroller>\n * </template>\n * ```\n */\n scrollToTop: () => void;\n /**\n * Scroll the content to the left\n *\n * ```gjs\n * import { Scroller } from 'ember-primitives';\n *\n * <template>\n * <Scroller as |s|>\n * ...\n *\n * {{ (s.scrollToLeft) }}\n * </Scroller>\n * </template>\n * ```\n */\n scrollToLeft: () => void;\n /**\n * Scroll the content to the right\n *\n * ```gjs\n * import { Scroller } from 'ember-primitives';\n *\n * <template>\n * <Scroller as |s|>\n * ...\n *\n * {{ (s.scrollToRight) }}\n * </Scroller>\n * </template>\n * ```\n */\n scrollToRight: () => void;\n },\n ];\n };\n}> {\n declare withinElement: HTMLDivElement;\n\n ref = modifier((el: HTMLDivElement) => {\n this.withinElement = el;\n });\n\n #frame?: number;\n\n scrollToBottom = () => {\n if (this.#frame) {\n cancelAnimationFrame(this.#frame);\n }\n\n this.#frame = requestAnimationFrame(() => {\n if (isDestroyed(this) || isDestroying(this)) return;\n\n this.withinElement.scrollTo({\n top: this.withinElement.scrollHeight,\n behavior: \"auto\",\n });\n });\n };\n\n scrollToTop = () => {\n if (this.#frame) {\n cancelAnimationFrame(this.#frame);\n }\n\n this.#frame = requestAnimationFrame(() => {\n if (isDestroyed(this) || isDestroying(this)) return;\n\n this.withinElement.scrollTo({\n top: 0,\n behavior: \"auto\",\n });\n });\n };\n\n scrollToLeft = () => {\n if (this.#frame) {\n cancelAnimationFrame(this.#frame);\n }\n\n this.#frame = requestAnimationFrame(() => {\n if (isDestroyed(this) || isDestroying(this)) return;\n\n this.withinElement.scrollTo({\n left: 0,\n behavior: \"auto\",\n });\n });\n };\n\n scrollToRight = () => {\n if (this.#frame) {\n cancelAnimationFrame(this.#frame);\n }\n\n this.#frame = requestAnimationFrame(() => {\n if (isDestroyed(this) || isDestroying(this)) return;\n\n this.withinElement.scrollTo({\n left: this.withinElement.scrollWidth,\n behavior: \"auto\",\n });\n });\n };\n\n <template>\n <div tabindex=\"0\" ...attributes {{this.ref}}>\n {{yield\n (hash\n scrollToBottom=this.scrollToBottom\n scrollToTop=this.scrollToTop\n scrollToLeft=this.scrollToLeft\n scrollToRight=this.scrollToRight\n )\n }}\n </div>\n </template>\n}\n"],"names":["Scroller","Component","ref","modifier","el","withinElement","scrollToBottom","cancelAnimationFrame","requestAnimationFrame","isDestroyed","isDestroying","scrollTo","top","scrollHeight","behavior","scrollToTop","scrollToLeft","left","scrollToRight","scrollWidth","setComponentTemplate","precompileTemplate","strictMode","scope","hash"],"mappings":";;;;;;;AAYO,MAAMA,QAAA,SAAiBC,SAAA;AAwF5BC,EAAAA,GAAA,GAAMC,QAAA,CAAUC,EAAI,IAAA;IAClB,IAAI,CAACC,aAAa,GAAGD,EAAA;AACvB,EAAA,CAAA,CAAA;AAEA,EAAA,MAAM;EAENE,cAAA,GAAiBA,MAAA;AACf,IAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACfC,MAAAA,oBAAA,CAAqB,IAAI,CAAC,MAAM,CAAA;AAClC,IAAA;AAEA,IAAA,IAAI,CAAC,MAAM,GAAGC,qBAAA,CAAsB,MAAA;MAClC,IAAIC,WAAA,CAAY,IAAI,CAAA,IAAKC,YAAA,CAAa,IAAI,CAAA,EAAG;AAE7C,MAAA,IAAI,CAACL,aAAa,CAACM,QAAQ,CAAC;AAC1BC,QAAAA,GAAA,EAAK,IAAI,CAACP,aAAa,CAACQ,YAAY;AACpCC,QAAAA,QAAA,EAAU;AACZ,OAAA,CAAA;AACF,IAAA,CAAA,CAAA;EACF,CAAA;EAEAC,WAAA,GAAcA,MAAA;AACZ,IAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACfR,MAAAA,oBAAA,CAAqB,IAAI,CAAC,MAAM,CAAA;AAClC,IAAA;AAEA,IAAA,IAAI,CAAC,MAAM,GAAGC,qBAAA,CAAsB,MAAA;MAClC,IAAIC,WAAA,CAAY,IAAI,CAAA,IAAKC,YAAA,CAAa,IAAI,CAAA,EAAG;AAE7C,MAAA,IAAI,CAACL,aAAa,CAACM,QAAQ,CAAC;AAC1BC,QAAAA,GAAA,EAAK,CAAA;AACLE,QAAAA,QAAA,EAAU;AACZ,OAAA,CAAA;AACF,IAAA,CAAA,CAAA;EACF,CAAA;EAEAE,YAAA,GAAeA,MAAA;AACb,IAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACfT,MAAAA,oBAAA,CAAqB,IAAI,CAAC,MAAM,CAAA;AAClC,IAAA;AAEA,IAAA,IAAI,CAAC,MAAM,GAAGC,qBAAA,CAAsB,MAAA;MAClC,IAAIC,WAAA,CAAY,IAAI,CAAA,IAAKC,YAAA,CAAa,IAAI,CAAA,EAAG;AAE7C,MAAA,IAAI,CAACL,aAAa,CAACM,QAAQ,CAAC;AAC1BM,QAAAA,IAAA,EAAM,CAAA;AACNH,QAAAA,QAAA,EAAU;AACZ,OAAA,CAAA;AACF,IAAA,CAAA,CAAA;EACF,CAAA;EAEAI,aAAA,GAAgBA,MAAA;AACd,IAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACfX,MAAAA,oBAAA,CAAqB,IAAI,CAAC,MAAM,CAAA;AAClC,IAAA;AAEA,IAAA,IAAI,CAAC,MAAM,GAAGC,qBAAA,CAAsB,MAAA;MAClC,IAAIC,WAAA,CAAY,IAAI,CAAA,IAAKC,YAAA,CAAa,IAAI,CAAA,EAAG;AAE7C,MAAA,IAAI,CAACL,aAAa,CAACM,QAAQ,CAAC;AAC1BM,QAAAA,IAAA,EAAM,IAAI,CAACZ,aAAa,CAACc,WAAW;AACpCL,QAAAA,QAAA,EAAU;AACZ,OAAA,CAAA;AACF,IAAA,CAAA,CAAA;EACF,CAAA;AAEA,EAAA;IAAAM,oBAAA,CAAAC,kBAAA,CAAA,+NAAA,EAWA;MAAAC,UAAA,EAAA,IAAA;AAAAC,MAAAA,KAAA,EAAAA,OAAA;AAAAC,QAAAA;AAAA,OAAA;KAAU,CAAA,EAAV,IAAW,CAAA;AAAD;AACZ;;;;"}
1
+ {"version":3,"file":"scroller.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import { modifier } from 'ember-modifier';
2
3
  import { cell } from 'ember-resources';
3
4
  import { precompileTemplate } from '@ember/template-compilation';
@@ -1 +1 @@
1
- {"version":3,"file":"shadowed.js","sources":["../../src/components/shadowed.gts"],"sourcesContent":["import { modifier } from \"ember-modifier\";\nimport { cell } from \"ember-resources\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\nconst Shadow = () => {\n const shadow = cell<Element>();\n\n return {\n get root() {\n return shadow.current;\n },\n attach: modifier((element: Element) => {\n const shadowRoot = element.attachShadow({ mode: \"open\" });\n const div = document.createElement(\"div\");\n\n // ember-source 5.6 broke the ability to in-element\n // natively into a shadowroot.\n //\n // See these ember-source bugs:\n // - https://github.com/emberjs/ember.js/issues/20643\n // - https://github.com/emberjs/ember.js/issues/20642\n // - https://github.com/emberjs/ember.js/issues/20641\n shadowRoot.appendChild(div);\n\n shadow.set(div);\n }),\n };\n};\n\n// index.html has the production-fingerprinted references to these links\n// Ideally, we'd have some pre-processor scan everything for references to\n// assets in public, but idk how to set that up\nconst getStyles = () => [...document.querySelectorAll(\"link\")].map((link) => link.href);\n\n/**\n * style + native @import\n * is the only robust way to load styles in a shadowroot.\n *\n * link is only valid in the head element.\n */\nconst Styles = <template>\n <style>\n {{#each (getStyles) as |styleHref|}}\n\n @import \"{{styleHref}}\";\n\n {{/each}}\n </style>\n</template>;\n\n/**\n * Render content in a shadow dom, attached to a div.\n *\n * Uses the [shadow DOM][mdn-shadow-dom] API.\n *\n * [mdn-shadow-dom]: https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM\n *\n * This is useful when you want to render content that escapes your app's styles.\n */\nexport const Shadowed: TOC<{\n /**\n * The shadow dom attaches to a div element.\n * You may specify any attribute, and it'll be applied to this host element.\n */\n Element: HTMLDivElement;\n Args: {\n /**\n * @public\n *\n * By default, shadow-dom does not include any styles.\n * Setting this to true will include all the `<style>` tags\n * that are present in the `<head>` element.\n */\n includeStyles?: boolean;\n };\n Blocks: {\n /**\n * Content to be placed within the ShadowDOM\n */\n default: [];\n };\n}> = <template>\n {{#let (Shadow) as |shadow|}}\n {{! TODO: We need a way in ember to render in to a shadow dom without an effect }}\n <div {{shadow.attach}} ...attributes></div>\n\n {{#if shadow.root}}\n {{#in-element shadow.root}}\n\n {{#if @includeStyles}}\n <Styles />\n {{/if}}\n\n {{yield}}\n\n {{/in-element}}\n {{/if}}\n {{/let}}\n</template>;\n\nexport default Shadowed;\n"],"names":["Shadow","shadow","cell","root","current","attach","modifier","element","shadowRoot","attachShadow","mode","div","document","createElement","appendChild","set","getStyles","querySelectorAll","map","link","href","Styles","setComponentTemplate","precompileTemplate","strictMode","scope","templateOnly","Shadowed"],"mappings":";;;;;;AAKA,MAAMA,MAAA,GAASA,MAAA;AACb,EAAA,MAAMC,SAASC,IAAA,EAAK;EAEpB,OAAO;IACL,IAAIC,IAAAA,GAAO;MACT,OAAOF,OAAOG,OAAO;IACvB,CAAA;AACAC,IAAAA,MAAA,EAAQC,QAAA,CAAUC,OAAS,IAAA;AACzB,MAAA,MAAMC,UAAA,GAAaD,OAAA,CAAQE,YAAY,CAAC;AAAEC,QAAAA,IAAA,EAAM;AAAO,OAAA,CAAA;AACvD,MAAA,MAAMC,GAAA,GAAMC,QAAA,CAASC,aAAa,CAAC,KAAA,CAAA;AAEnC;AACA;AACA;AACA;AACA;AACA;AACA;AACAL,MAAAA,UAAA,CAAWM,WAAW,CAACH,GAAA,CAAA;AAEvBV,MAAAA,MAAA,CAAOc,GAAG,CAACJ,GAAA,CAAA;IACb,CAAA;GACF;AACF,CAAA;AAEA;AACA;AACA;AACA,MAAMK,YAAYA,MAAM,CAAI,GAAAJ,QAAA,CAASK,gBAAgB,CAAC,MAAA,CAAA,CAAQ,CAACC,GAAG,CAAEC,IAAA,IAASA,KAAKC,IAAI,CAAA;AAEtF;;;;;;AAMA,MAAMC,MAAA,GAAAC,oBAAA,CAASC,kBAAA,CAAA,0HAAA,EAQf;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;AAAAT,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAU,YAAA,EAAA,CAAA;AAEV;;;;;;;;;MASaC,QAsBR,GAAAL,oBAAA,CAAAC,kBAAA,CAAA,gYAAA,EAiBL;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAzB,MAAA;AAAAqB,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAK,YAAA,EAAA;;;;"}
1
+ {"version":3,"file":"shadowed.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import { fn, hash } from '@ember/helper';
2
3
  import { on } from '@ember/modifier';
3
4
  import { cell } from 'ember-resources';
@@ -1 +1 @@
1
- {"version":3,"file":"switch.js","sources":["../../src/components/switch.gts"],"sourcesContent":["import { fn, hash } from \"@ember/helper\";\nimport { on } from \"@ember/modifier\";\n\nimport { cell } from \"ember-resources\";\n\nimport { uniqueId } from \"../utils.ts\";\nimport { Label } from \"./-private/typed-elements.gts\";\nimport { toggleWithFallback } from \"./-private/utils.ts\";\n\nimport type { TOC } from \"@ember/component/template-only\";\nimport type { WithBoundArgs } from \"@glint/template\";\n\nexport interface Signature {\n Element: HTMLInputElement;\n Args: {\n /**\n * The initial checked value of the Switch.\n * This value is reactive, so if the value that\n * `@checked` is set to updates, the state of the Switch will also update.\n */\n checked?: boolean;\n /**\n * Callback when the Switch state is toggled\n */\n onChange?: (checked: boolean, event: Event) => void;\n };\n Blocks: {\n default?: [\n {\n /**\n * The Switch Element.\n * It has a pre-wired `id` so that the relevant Label is\n * appropriately associated via the `for` property of the Label.\n *\n * ```gjs\n * import { Switch } from 'ember-primitives';\n *\n * <template>\n * <Switch as |s|>\n * <s.Control />\n * </Switch>\n * </template>\n * ```\n */\n Control: WithBoundArgs<typeof Checkbox, \"checked\" | \"id\" | \"onChange\">;\n /**\n * The Switch element requires a label, and this label already has\n * the association to the Control by setting the `for` attribute to the `id` of the Control\n *\n * ```gjs\n * import { Switch } from 'ember-primitives';\n *\n * <template>\n * <Switch as |s|>\n * <s.Label />\n * </Switch>\n * </template>\n * ```\n */\n Label: WithBoundArgs<typeof Label, \"for\">;\n },\n ];\n };\n}\n\ninterface ControlSignature {\n Element: HTMLInputElement;\n Args: { id: string; checked?: boolean; onChange: () => void };\n}\n\nconst Checkbox: TOC<ControlSignature> = <template>\n {{#let (cell @checked) as |checked|}}\n <input\n id={{@id}}\n type=\"checkbox\"\n role=\"switch\"\n checked={{checked.current}}\n aria-checked={{checked.current}}\n data-state={{if checked.current \"on\" \"off\"}}\n {{on \"click\" (fn toggleWithFallback checked.toggle @onChange)}}\n ...attributes\n />\n {{/let}}\n</template>;\n\n/**\n * @public\n */\nexport const Switch: TOC<Signature> = <template>\n <div ...attributes data-prim-switch>\n {{! @glint-nocheck }}\n {{#let (uniqueId) as |id|}}\n {{yield\n (hash\n Control=(component Checkbox checked=@checked id=id onChange=@onChange)\n Label=(component Label for=id)\n )\n }}\n {{/let}}\n </div>\n</template>;\n\nexport default Switch;\n"],"names":["Checkbox","setComponentTemplate","precompileTemplate","strictMode","scope","cell","on","fn","toggleWithFallback","templateOnly","Switch","uniqueId","hash","Label"],"mappings":";;;;;;;;;;AAsEA,MAAMA,QAAc,GAAAC,oBAAA,CAAoBC,kBAAA,CAAA,mTAAA,EAaxC;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAC,IAAA;IAAAC,EAAA;IAAAC,EAAA;AAAAC,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAC,YAAA,EAAA,CAAA;AAEV;;AAEC;MACYC,MAAY,GAAAT,oBAAA,CAAaC,kBAAA,CAAA,kQAAA,EAYtC;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAO,QAAA;IAAAC,IAAA;IAAAZ,QAAA;AAAAa,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAJ,YAAA,EAAA;;;;"}
1
+ {"version":3,"file":"switch.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,218 @@
1
+
2
+ import Component from '@glimmer/component';
3
+ import { tracked } from '@glimmer/tracking';
4
+ import { isDestroyed, isDestroying } from '@ember/destroyable';
5
+ import { fn } from '@ember/helper';
6
+ import { on } from '@ember/modifier';
7
+ import { next } from '@ember/runloop';
8
+ import { getTabsterAttribute, MoverDirections } from 'tabster';
9
+ import { uniqueId } from '../utils.js';
10
+ import { Portal } from './portal.js';
11
+ import { buildWaiter } from '@ember/test-waiters';
12
+ import { precompileTemplate } from '@ember/template-compilation';
13
+ import { setComponentTemplate } from '@ember/component';
14
+ import templateOnly from '@ember/component/template-only';
15
+ import { g, i } from 'decorator-transforms/runtime';
16
+
17
+ /**
18
+ * References:
19
+ * - https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/tablist_role
20
+ * - https://www.w3.org/WAI/ARIA/apg/patterns/tabs/
21
+ *
22
+ *
23
+ * Keyboard behaviors (optionally) provided by tabster
24
+ */
25
+ const UNSET = Symbol.for("ember-primitives:tabs:unset");
26
+ const TABSTER_CONFIG = getTabsterAttribute({
27
+ mover: {
28
+ direction: MoverDirections.Both,
29
+ cyclic: true,
30
+ memorizeCurrent: true
31
+ },
32
+ deloser: {}
33
+ }, true);
34
+ const TabLink = setComponentTemplate(precompileTemplate("\n <a href=\"##missing##\" ...attributes role=\"tab\" aria-controls={{@panelId}} id={{@id}}>\n {{yield}}\n </a>\n", {
35
+ strictMode: true
36
+ }), templateOnly());
37
+ const TabButton = setComponentTemplate(precompileTemplate("\n <button ...attributes role=\"tab\" type=\"button\" aria-controls={{@panelId}} aria-selected={{String (@state.isActive @id @value)}} id={{@id}} {{on \"click\" @handleClick}} {{!-- The Types for modifier are wrong --}} {{!-- @glint-expect-error--}} {{(if @state.isAutomatic (modifier on \"focus\" @handleClick))}}>\n {{yield}}\n </button>\n", {
38
+ strictMode: true,
39
+ scope: () => ({
40
+ String,
41
+ on
42
+ })
43
+ }), templateOnly());
44
+ const TabContent = setComponentTemplate(precompileTemplate("\n <Portal @to=\"#{{@state.tabpanelId}}\" @append={{true}}>\n {{#if (@state.isActive @tabId)}}\n <div ...attributes role=\"tabpanel\" aria-labelledby={{@tabId}} id={{@id}}>\n {{yield}}\n </div>\n {{/if}}\n </Portal>\n", {
45
+ strictMode: true,
46
+ scope: () => ({
47
+ Portal
48
+ })
49
+ }), templateOnly());
50
+ function isString(x) {
51
+ return typeof x === "string";
52
+ }
53
+ function makeTab(tabButton, tabLink) {
54
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
55
+ tabButton.Link = tabLink;
56
+ return tabButton;
57
+ }
58
+ class TabContainer extends Component {
59
+ id = `ember-primitives__tab-${uniqueId()}`;
60
+ get tabId() {
61
+ return `${this.id}__tab`;
62
+ }
63
+ get panelId() {
64
+ return `${this.id}__panel`;
65
+ }
66
+ get label() {
67
+ return this.args.label ?? this.tabId;
68
+ }
69
+ static {
70
+ setComponentTemplate(precompileTemplate("\n {{#if @label}}\n <TabButton @state={{@state}} @id={{this.tabId}} @value={{@value}} @panelId={{this.panelId}} @handleClick={{fn @state.handleChange this.tabId @value}}>\n {{#if (isString @label)}}\n {{@label}}\n {{else}}\n <@label />\n {{/if}}\n </TabButton>\n\n <TabContent @state={{@state}} @id={{this.panelId}} @tabId={{this.tabId}}>\n {{#if @content}}\n {{#if (isString @content)}}\n {{@content}}\n {{else}}\n <@content />\n {{/if}}\n {{else}}\n {{yield}}\n {{/if}}\n </TabContent>\n {{else}}\n {{yield (makeTab (component TabButton state=@state value=@value id=this.tabId panelId=this.panelId handleClick=(fn @state.handleChange this.tabId @value)) (component TabLink state=@state id=this.tabId panelId=this.panelId)) (component TabContent state=@state id=this.panelId tabId=this.tabId)}}\n {{/if}}\n ", {
71
+ strictMode: true,
72
+ scope: () => ({
73
+ TabButton,
74
+ fn,
75
+ isString,
76
+ TabContent,
77
+ makeTab,
78
+ TabLink
79
+ })
80
+ }), this);
81
+ }
82
+ }
83
+ const Label = setComponentTemplate(precompileTemplate("\n <Portal @to=\"#{{@state.labelId}}\">\n {{yield}}\n </Portal>\n", {
84
+ strictMode: true,
85
+ scope: () => ({
86
+ Portal
87
+ })
88
+ }), templateOnly());
89
+ /**
90
+ * We're doing old skool hax with this, so we don't need to care about what the types think, really
91
+ */
92
+ function makeAPI(tabContainer, labelComponent) {
93
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
94
+ tabContainer.Label = labelComponent;
95
+ return tabContainer;
96
+ }
97
+ const stateWaiter = buildWaiter("ember-primitives:tabs");
98
+ /**
99
+ * State bucket passed around to all the sub-components.
100
+ *
101
+ * Sort of a "Context", but with a bit of prop-drilling (which is more efficient than dom-context)
102
+ */
103
+ class TabState {
104
+ static {
105
+ g(this.prototype, "_active", [tracked], function () {
106
+ return null;
107
+ });
108
+ }
109
+ #_active = (i(this, "_active"), void 0);
110
+ static {
111
+ g(this.prototype, "_label", [tracked]);
112
+ }
113
+ #_label = (i(this, "_label"), void 0);
114
+ #first = null;
115
+ id;
116
+ labelId;
117
+ tabpanelId;
118
+ #token;
119
+ constructor(args) {
120
+ this.args = args;
121
+ this.id = `ember-primitives-${uniqueId()}`;
122
+ this.labelId = `${this.id}__label`;
123
+ this.tabpanelId = `${this.id}__tabpanel`;
124
+ }
125
+ get activationMode() {
126
+ return this.args.activationMode ?? "automatic";
127
+ }
128
+ get isAutomatic() {
129
+ return this.activationMode === "automatic";
130
+ }
131
+ /**
132
+ * This function relies on the fact that during rendering,
133
+ * the first component to be rendered will be first,
134
+ * and it will be the one to set the secret first value,
135
+ * which means all other tabs will not be first.
136
+ *
137
+ */
138
+ isActive = (tabId, tabValue) => {
139
+ /**
140
+ * When users pass the @value to a tab, we use that for managing
141
+ * the "active state" instead of the DOM ID.
142
+ *
143
+ * NOTE: DOM IDs must be unique across the whole document, but @value
144
+ * does not need to be unqiue.
145
+ * `@value` *should* be unique for the Tabs component though
146
+ */
147
+ const isSelected = x => {
148
+ if (tabValue) return x === tabValue;
149
+ return x === tabId;
150
+ };
151
+ if (this.active === UNSET) {
152
+ if (this.#first) return isSelected(this.#first);
153
+ this.#first = tabValue ?? tabId;
154
+ this.#token = stateWaiter.beginAsync();
155
+ // eslint-disable-next-line ember/no-runloop
156
+ next(() => {
157
+ if (!this.#token) return;
158
+ stateWaiter.endAsync(this.#token);
159
+ if (this._active) return;
160
+ if (isDestroyed(this) || isDestroying(this)) return;
161
+ this._label = tabValue ?? tabId;
162
+ });
163
+ return true;
164
+ }
165
+ return isSelected(this.active);
166
+ };
167
+ get active() {
168
+ return this._active ?? this.args.activeTab ?? UNSET;
169
+ }
170
+ get activeLabel() {
171
+ /**
172
+ * This is only needed during the first set
173
+ * because we prioritize rendering first, and then updating metadata later
174
+ * (next render)
175
+ *
176
+ * NOTE: this does not mean that the a11y tree is updated later.
177
+ * it is correct on initial render
178
+ */
179
+ if (this._label) {
180
+ return this._label;
181
+ }
182
+ if (this.active === UNSET) {
183
+ return "Pending";
184
+ }
185
+ return this.active;
186
+ }
187
+ handleChange = (tabId, tabValue) => {
188
+ const previous = this.active;
189
+ const next = tabValue ?? tabId;
190
+ // No change, no need to be noisy
191
+ if (next === previous) return;
192
+ this._active = this._label = next;
193
+ this.args.onChange?.(next, previous === UNSET ? null : previous);
194
+ };
195
+ }
196
+ class Tabs extends Component {
197
+ state;
198
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
199
+ constructor(owner, args) {
200
+ super(owner, args);
201
+ this.state = new TabState(args);
202
+ }
203
+ static {
204
+ setComponentTemplate(precompileTemplate("\n <div class=\"ember-primitives__tabs\" ...attributes data-active={{this.state.activeLabel}}>\n {{!-- This element will be portaled in to and replaced if tabs.Label is invoked --}}\n <div class=\"ember-primitives__tabs__label\" id={{this.state.labelId}}>\n {{#if (isString @label)}}\n {{@label}}\n {{else}}\n <@label />\n {{/if}}\n </div>\n <div class=\"ember-primitives__tabs__tablist\" role=\"tablist\" aria-labelledby={{this.state.labelId}} data-tabster={{TABSTER_CONFIG}}>\n {{yield (makeAPI (component TabContainer state=this.state) (component Label state=this.state))}}\n </div>\n {{!--\n Tab's contents are portaled in to this element\n --}}\n <div class=\"ember-primitives__tabs__tabpanel\" id={{this.state.tabpanelId}}></div>\n </div>\n ", {
205
+ strictMode: true,
206
+ scope: () => ({
207
+ isString,
208
+ TABSTER_CONFIG,
209
+ makeAPI,
210
+ TabContainer,
211
+ Label
212
+ })
213
+ }), this);
214
+ }
215
+ }
216
+
217
+ export { Tabs };
218
+ //# sourceMappingURL=tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import Component from '@glimmer/component';
2
3
  import { cached } from '@glimmer/tracking';
3
4
  import { hash } from '@ember/helper';
@@ -1 +1 @@
1
- {"version":3,"file":"toggle-group.js","sources":["../../src/components/toggle-group.gts"],"sourcesContent":["import Component from \"@glimmer/component\";\nimport { cached } from \"@glimmer/tracking\";\nimport { hash } from \"@ember/helper\";\n\nimport { getTabsterAttribute, MoverDirections } from \"tabster\";\nimport { TrackedSet } from \"tracked-built-ins\";\n// The consumer will need to provide types for tracked-toolbox.\n// Or.. better yet, we PR to trakcked-toolbox to provide them\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport { localCopy } from \"tracked-toolbox\";\n\nimport { Toggle } from \"./toggle.gts\";\n\nimport type { ComponentLike } from \"@glint/template\";\n\nconst TABSTER_CONFIG = getTabsterAttribute(\n {\n mover: {\n direction: MoverDirections.Both,\n cyclic: true,\n },\n },\n true,\n);\n\nexport interface ItemSignature<Value = any> {\n /**\n * The button element will have aria-pressed=\"true\" on it when the button is in the pressed state.\n */\n Element: HTMLButtonElement;\n Args: {\n /**\n * When used in a group of Toggles, this option will be helpful to\n * know which toggle was pressed if you're using the same @onChange\n * handler for multiple toggles.\n */\n value?: Value;\n };\n Blocks: {\n default: [\n /**\n * the current pressed state of the toggle button\n *\n * Useful when using the toggle button as an uncontrolled component\n */\n pressed: boolean,\n ];\n };\n}\n\nexport type Item<Value = any> = ComponentLike<ItemSignature<Value>>;\n\nexport interface SingleSignature<Value> {\n Element: HTMLDivElement;\n Args: {\n /**\n * Optionally set the initial toggle state\n */\n value?: Value;\n /**\n * Callback for when the toggle-group's state is changed.\n *\n * Can be used to control the state of the component.\n *\n *\n * When none of the toggles are selected, undefined will be passed.\n */\n onChange?: (value: Value | undefined) => void;\n };\n Blocks: {\n default: [\n {\n /**\n * The Toggle Switch\n */\n Item: Item;\n },\n ];\n };\n}\n\nexport interface MultiSignature<Value = any> {\n Element: HTMLDivElement;\n Args: {\n /**\n * Optionally set the initial toggle state\n */\n value?: Value[] | Set<Value> | Value;\n /**\n * Callback for when the toggle-group's state is changed.\n *\n * Can be used to control the state of the component.\n *\n *\n * When none of the toggles are selected, undefined will be passed.\n */\n onChange?: (value: Set<Value>) => void;\n };\n Blocks: {\n default: [\n {\n /**\n * The Toggle Switch\n */\n Item: Item;\n },\n ];\n };\n}\n\ninterface PrivateSingleSignature<Value = any> {\n Element: HTMLDivElement;\n Args: {\n type?: \"single\";\n\n /**\n * Optionally set the initial toggle state\n */\n value?: Value;\n /**\n * Callback for when the toggle-group's state is changed.\n *\n * Can be used to control the state of the component.\n *\n *\n * When none of the toggles are selected, undefined will be passed.\n */\n onChange?: (value: Value | undefined) => void;\n };\n Blocks: {\n default: [\n {\n Item: Item;\n },\n ];\n };\n}\n\ninterface PrivateMultiSignature<Value = any> {\n Element: HTMLDivElement;\n Args: {\n type: \"multi\";\n /**\n * Optionally set the initial toggle state\n */\n value?: Value[] | Set<Value> | Value;\n /**\n * Callback for when the toggle-group's state is changed.\n *\n * Can be used to control the state of the component.\n *\n *\n * When none of the toggles are selected, undefined will be passed.\n */\n onChange?: (value: Set<Value>) => void;\n };\n Blocks: {\n default: [\n {\n Item: Item;\n },\n ];\n };\n}\n\nfunction isMulti(x: \"single\" | \"multi\" | undefined): x is \"multi\" {\n return x === \"multi\";\n}\n\nexport class ToggleGroup<Value = any> extends Component<\n PrivateSingleSignature<Value> | PrivateMultiSignature<Value>\n> {\n // See: https://github.com/typed-ember/glint/issues/715\n <template>\n {{#if (isMulti this.args.type)}}\n <MultiToggleGroup\n @value={{this.args.value}}\n @onChange={{this.args.onChange}}\n ...attributes\n as |x|\n >\n {{yield x}}\n </MultiToggleGroup>\n {{else}}\n <SingleToggleGroup\n @value={{this.args.value}}\n @onChange={{this.args.onChange}}\n ...attributes\n as |x|\n >\n {{yield x}}\n </SingleToggleGroup>\n {{/if}}\n </template>\n}\n\nclass SingleToggleGroup<Value = any> extends Component<SingleSignature<Value>> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n @localCopy(\"args.value\") activePressed?: Value;\n\n handleToggle = (value: Value) => {\n if (this.activePressed === value) {\n this.activePressed = undefined;\n\n return;\n }\n\n this.activePressed = value;\n\n this.args.onChange?.(this.activePressed);\n };\n\n isPressed = (value: Value | undefined) => value === this.activePressed;\n\n <template>\n <div data-tabster={{TABSTER_CONFIG}} ...attributes>\n {{yield (hash Item=(component Toggle onChange=this.handleToggle isPressed=this.isPressed))}}\n </div>\n </template>\n}\n\nclass MultiToggleGroup<Value = any> extends Component<MultiSignature<Value>> {\n /**\n * Normalizes @value to a Set\n * and makes sure that even if the input Set is reactive,\n * we don't mistakenly dirty it.\n */\n @cached\n get activePressed(): TrackedSet<Value> {\n const value = this.args.value;\n\n if (!value) {\n return new TrackedSet();\n }\n\n if (Array.isArray(value)) {\n return new TrackedSet(value);\n }\n\n if (value instanceof Set) {\n return new TrackedSet(value);\n }\n\n return new TrackedSet([value]);\n }\n\n handleToggle = (value: Value) => {\n if (this.activePressed.has(value)) {\n this.activePressed.delete(value);\n } else {\n this.activePressed.add(value);\n }\n\n this.args.onChange?.(new Set<Value>(this.activePressed.values()));\n };\n\n isPressed = (value: Value) => this.activePressed.has(value);\n\n <template>\n <div data-tabster={{TABSTER_CONFIG}} ...attributes>\n {{yield (hash Item=(component Toggle onChange=this.handleToggle isPressed=this.isPressed))}}\n </div>\n </template>\n}\n"],"names":["TABSTER_CONFIG","getTabsterAttribute","mover","direction","MoverDirections","Both","cyclic","isMulti","x","ToggleGroup","Component","setComponentTemplate","precompileTemplate","strictMode","scope","MultiToggleGroup","SingleToggleGroup","g","prototype","localCopy","i","void 0","handleToggle","value","activePressed","undefined","args","onChange","isPressed","hash","Toggle","TrackedSet","Array","isArray","Set","n","cached","has","delete","add","values"],"mappings":"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"}
1
+ {"version":3,"file":"toggle-group.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+
1
2
  import { fn } from '@ember/helper';
2
3
  import { on } from '@ember/modifier';
3
4
  import { cell } from 'ember-resources';
@@ -1 +1 @@
1
- {"version":3,"file":"toggle.js","sources":["../../src/components/toggle.gts"],"sourcesContent":["// import Component from '@glimmer/component';\nimport { fn } from \"@ember/helper\";\nimport { on } from \"@ember/modifier\";\n\nimport { cell } from \"ember-resources\";\n\nimport { toggleWithFallback } from \"./-private/utils.ts\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\nexport interface Signature<Value = any> {\n Element: HTMLButtonElement;\n Args: {\n /**\n * The pressed-state of the toggle.\n *\n * Can be used to control the state of the component.\n */\n pressed?: boolean;\n /**\n * Callback for when the toggle's state is changed.\n *\n * Can be used to control the state of the component.\n *\n * if a `@value` is passed to this `<Toggle>`, that @value will\n * be passed to the `@onChange` handler.\n *\n * This can be useful when using the same function for the `@onChange`\n * handler with multiple `<Toggle>` components.\n */\n onChange?: (value: Value | undefined, pressed: boolean) => void;\n\n /**\n * When used in a group of Toggles, this option will be helpful to\n * know which toggle was pressed if you're using the same @onChange\n * handler for multiple toggles.\n */\n value?: Value;\n\n /**\n * When controlling state in a wrapping component, this function can be used in conjunction with `@value` to determine if this `<Toggle>` should appear pressed.\n */\n isPressed?: (value?: Value) => boolean;\n };\n Blocks: {\n default: [\n /**\n * the current pressed state of the toggle button\n *\n * Useful when using the toggle button as an uncontrolled component\n */\n pressed: boolean,\n ];\n };\n}\n\nfunction isPressed(\n pressed?: boolean,\n value?: unknown,\n isPressed?: (value?: unknown) => boolean,\n): boolean {\n if (!value) return Boolean(pressed);\n if (!isPressed) return Boolean(pressed);\n\n return isPressed(value);\n}\n\nexport const Toggle: TOC<Signature> = <template>\n {{#let (cell (isPressed @pressed @value @isPressed)) as |pressed|}}\n <button\n type=\"button\"\n aria-pressed=\"{{pressed.current}}\"\n {{on \"click\" (fn toggleWithFallback pressed.toggle @onChange @value)}}\n ...attributes\n >\n {{yield pressed.current}}\n </button>\n {{/let}}\n</template>;\n\nexport default Toggle;\n"],"names":["isPressed","pressed","value","Boolean","Toggle","setComponentTemplate","precompileTemplate","strictMode","scope","cell","on","fn","toggleWithFallback","templateOnly"],"mappings":";;;;;;;;AAAA;;AAwDA,SAASA,SAAAA,CACPC,OAAiB,EACjBC,KAAe,EACfF,SAAwC,EAChC;AACR,EAAA,IAAI,CAACE,KAAA,EAAO,OAAOC,OAAA,CAAQF,OAAA,CAAA;AAC3B,EAAA,IAAI,CAACD,SAAA,EAAW,OAAOG,OAAA,CAAQF,OAAA,CAAA;EAE/B,OAAOD,SAAA,CAAUE,KAAA,CAAA;AACnB;MAEaE,MAAY,GAAAC,oBAAA,CAAaC,kBAAA,CAAA,iSAAA,EAWtC;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;IAAAC,IAAA;IAAAT,SAAA;IAAAU,EAAA;IAAAC,EAAA;AAAAC,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAC,YAAA,EAAA;;;;"}
1
+ {"version":3,"file":"toggle.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import "./violations.css"
2
+ ;
3
+ //# sourceMappingURL=violations.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"violations.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,4 +1,5 @@
1
- import './visually-hidden.css';
1
+
2
+ import '../visually-hidden-CGP1FSjt.js';
2
3
  import { precompileTemplate } from '@ember/template-compilation';
3
4
  import { setComponentTemplate } from '@ember/component';
4
5
  import templateOnly from '@ember/component/template-only';