@uva-glass/component-library 3.55.6 → 3.55.7

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 (168) hide show
  1. package/dist/Accordion-DvblEUVu.js.map +1 -1
  2. package/dist/AccordionCard-BXy-plB7.js.map +1 -1
  3. package/dist/ActionList-O9w1hqNg.js.map +1 -1
  4. package/dist/AddCatalogueLinkForm-rph4K9P0.js.map +1 -1
  5. package/dist/CheckboxButtonBar-5UMIFMKH.js.map +1 -1
  6. package/dist/ClipboardButton-geHjMl2J.js.map +1 -1
  7. package/dist/ControlsButton-B1XRpMUM.js.map +1 -1
  8. package/dist/CopyableText-DkyhZ6wk.js.map +1 -1
  9. package/dist/Drawer-e7UFHVg9.js.map +1 -1
  10. package/dist/EmptyStateDataDisplay-D0QiI8nE.js.map +1 -1
  11. package/dist/ExpandableInfoPanel-CnBVVNlJ.js.map +1 -1
  12. package/dist/FeedbackBar-ByKp32HE.js.map +1 -1
  13. package/dist/FieldHint-fxnEOsVZ.js.map +1 -1
  14. package/dist/Input-Bn-arMaC.js.map +1 -1
  15. package/dist/InputField-BWAy19w9.js.map +1 -1
  16. package/dist/Lexical.prod-CqPLSi0R.js.map +1 -1
  17. package/dist/LexicalClipboard.prod-BVw_sFpo.js.map +1 -1
  18. package/dist/LexicalComposerContext.prod-Ca-YN_fj.js.map +1 -1
  19. package/dist/LexicalExtension.prod-CUQTgbur.js.map +1 -1
  20. package/dist/LexicalLink.prod-DMhcqD9x.js.map +1 -1
  21. package/dist/LexicalList.prod-eYlcb5Ao.js.map +1 -1
  22. package/dist/LexicalTable.prod-DlOxUQou.js.map +1 -1
  23. package/dist/LexicalUtils.prod-BqcriFWV.js.map +1 -1
  24. package/dist/LinkContextMenu-ePn1iZ_z.js.map +1 -1
  25. package/dist/MenuLink-Cm1yZO_5.js.map +1 -1
  26. package/dist/ModalDialog-N50NGnd4.js.map +1 -1
  27. package/dist/MultiSelectBox-Cuh_o-A1.js.map +1 -1
  28. package/dist/MultiSelectItem-BF5xRjz5.js.map +1 -1
  29. package/dist/Notification-CIhsHuF0.js.map +1 -1
  30. package/dist/OverlayStepBar-CjaoYdsh.js.map +1 -1
  31. package/dist/PageOverlay-S4xsqJha.js.map +1 -1
  32. package/dist/PasteHandlerPlugin-BNp8ST0q.js.map +1 -1
  33. package/dist/Periods-BYETtB6R.js.map +1 -1
  34. package/dist/ProgrammeCard-76gG7ksx.js.map +1 -1
  35. package/dist/RadioGroup-JeTjVp5B.js.map +1 -1
  36. package/dist/Slider-BlLyrET9.js.map +1 -1
  37. package/dist/SortableProvider-8HYiBXJS.js.map +1 -1
  38. package/dist/Spinner-BpElTDIu.js.map +1 -1
  39. package/dist/StatusPill-DM7n3I4W.js.map +1 -1
  40. package/dist/TableCellContextMenu-D0IMQr3E.js.map +1 -1
  41. package/dist/TableCellResizerPlugin-Bc5y-Qbx.js.map +1 -1
  42. package/dist/TextArea-CuASC9bX.js.map +1 -1
  43. package/dist/ToggleSwitch-C7z7JVtx.js.map +1 -1
  44. package/dist/Tooltip-D27p9kh4.js.map +1 -1
  45. package/dist/VarIndicator-C-GueOZD.js.map +1 -1
  46. package/dist/assets/{src/css/fonts.css → fonts.css} +4 -4
  47. package/dist/chunk-SZQXB3JV-D6GR5B4F.js.map +1 -1
  48. package/dist/{client-8jeXrH7N.js → client-b7M3CmlC.js} +9 -9
  49. package/dist/{client-8jeXrH7N.js.map → client-b7M3CmlC.js.map} +1 -1
  50. package/dist/clsx-BD2qMUU1.js.map +1 -1
  51. package/dist/components/Accordion/Accordion.test.js +2 -2
  52. package/dist/components/Accordion/Accordion.test.js.map +1 -1
  53. package/dist/components/AccordionCard/AccordionCard.test.js +2 -2
  54. package/dist/components/AccordionCard/AccordionCard.test.js.map +1 -1
  55. package/dist/components/ActionList/ActionList.test.js +2 -2
  56. package/dist/components/ActionList/ActionList.test.js.map +1 -1
  57. package/dist/components/AppStatusBar/AppStatusBar.test.js +1 -1
  58. package/dist/components/AppStatusBar/AppStatusBar.test.js.map +1 -1
  59. package/dist/components/Attention/Attention.test.js +1 -1
  60. package/dist/components/Attention/Attention.test.js.map +1 -1
  61. package/dist/components/Backdrop/Backdrop.test.js +1 -1
  62. package/dist/components/Backdrop/Backdrop.test.js.map +1 -1
  63. package/dist/components/Buttons/Button.test.js +1 -1
  64. package/dist/components/Buttons/Button.test.js.map +1 -1
  65. package/dist/components/Buttons/LinkButton.test.js +1 -1
  66. package/dist/components/Buttons/LinkButton.test.js.map +1 -1
  67. package/dist/components/Buttons/MenuButton.js.map +1 -1
  68. package/dist/components/Buttons/MenuButton.test.js +1 -1
  69. package/dist/components/Buttons/MenuButton.test.js.map +1 -1
  70. package/dist/components/Card/Card.test.js +1 -1
  71. package/dist/components/Card/Card.test.js.map +1 -1
  72. package/dist/components/Checkbox/Checkbox.test.js +2 -2
  73. package/dist/components/Checkbox/Checkbox.test.js.map +1 -1
  74. package/dist/components/CheckboxButtonBar/CheckboxButtonBar.test.js +1 -1
  75. package/dist/components/CheckboxButtonBar/CheckboxButtonBar.test.js.map +1 -1
  76. package/dist/components/CheckboxTree/CheckboxTree.stories.js.map +1 -1
  77. package/dist/components/Drawer/Drawer.stories.js.map +1 -1
  78. package/dist/components/FeedbackBar/FeedbackBar.stories.js.map +1 -1
  79. package/dist/components/FeedbackBar/FeedbackBar.test.js +1 -1
  80. package/dist/components/FeedbackBar/FeedbackBar.test.js.map +1 -1
  81. package/dist/components/Icon/Icon.js.map +1 -1
  82. package/dist/components/IconButton/IconButton.stories.js.map +1 -1
  83. package/dist/components/InputField/InputField.stories.js.map +1 -1
  84. package/dist/components/Label/Label.test.js +1 -1
  85. package/dist/components/Label/Label.test.js.map +1 -1
  86. package/dist/components/MetaDataBar/MetaDataBar.test.js +1 -1
  87. package/dist/components/MetaDataBar/MetaDataBar.test.js.map +1 -1
  88. package/dist/components/MultiSelect/MultiSelect.stories.js.map +1 -1
  89. package/dist/components/MultiSelectBox/MultiSelectBox.stories.js.map +1 -1
  90. package/dist/components/MultiSelectBox/MultiSelectBox.test.js +1 -1
  91. package/dist/components/MultiSelectBox/MultiSelectBox.test.js.map +1 -1
  92. package/dist/components/Notification/Notification.test.js +1 -1
  93. package/dist/components/Notification/Notification.test.js.map +1 -1
  94. package/dist/components/OverlayStepBar/OverlayStepBar.stories.js.map +1 -1
  95. package/dist/components/PageOverlay/PageOverlay.stories.js +2 -2
  96. package/dist/components/PageOverlay/PageOverlay.stories.js.map +1 -1
  97. package/dist/components/RadioGroup/Radiogroup.test.js +1 -1
  98. package/dist/components/RadioGroup/Radiogroup.test.js.map +1 -1
  99. package/dist/components/RteEditor/Plugins/BlockFormatPlugin/BlockFormatPlugin.js.map +1 -1
  100. package/dist/components/RteEditor/Plugins/CourseCataloguePlugin/CourseCataloguePlugin.js.map +1 -1
  101. package/dist/components/RteEditor/Plugins/ListPlugin/ListPlugin.js.map +1 -1
  102. package/dist/components/RteEditor/Plugins/TablePlugin/helpers.js.map +1 -1
  103. package/dist/components/RteEditor/Providers/LanguageProvider.js.map +1 -1
  104. package/dist/components/RteEditor/RteEditor.stories.js.map +1 -1
  105. package/dist/components/RteEditor/helpers.js.map +1 -1
  106. package/dist/components/RteEditor/hooks/useFlyout.js.map +1 -1
  107. package/dist/components/RteEditor/hooks/useTranslation.js.map +1 -1
  108. package/dist/components/RteEditor/nodes/CourseCatalogueNode/CourseCatalogueNode.js.map +1 -1
  109. package/dist/components/RteEditor/nodes/TableWrapperNode/TableWrapperNode.js.map +1 -1
  110. package/dist/components/SearchField/SearchField.js.map +1 -1
  111. package/dist/components/SearchField/SearcheField.stories.js.map +1 -1
  112. package/dist/components/SearchField/components/ResultsOption.js.map +1 -1
  113. package/dist/components/SelectListbox/SelectListBox.stories.js.map +1 -1
  114. package/dist/components/SelectListbox/SelectListbox.js.map +1 -1
  115. package/dist/components/SelectListbox/SelectProvider.js.map +1 -1
  116. package/dist/components/SelectListbox/components/SelectButton.js.map +1 -1
  117. package/dist/components/SelectListbox/components/SelectContainer.js.map +1 -1
  118. package/dist/components/SelectListbox/components/SelectOption.js.map +1 -1
  119. package/dist/components/SelectListbox/components/SelectOptionBox.js.map +1 -1
  120. package/dist/components/Slider/Slider.stories.js.map +1 -1
  121. package/dist/components/Sortable/Sortable.js.map +1 -1
  122. package/dist/components/Sortable/components/SortableHandle.js.map +1 -1
  123. package/dist/components/Sortable/components/SortableItem.js.map +1 -1
  124. package/dist/components/Sortable/sortableReducer.js.map +1 -1
  125. package/dist/components/StatusBadge/StatusBadge.test.js +1 -1
  126. package/dist/components/StatusBadge/StatusBadge.test.js.map +1 -1
  127. package/dist/components/TextArea/TextArea.test.js +2 -2
  128. package/dist/components/TextArea/TextArea.test.js.map +1 -1
  129. package/dist/components/VarIndicator/VarIndicator.test.js +2 -2
  130. package/dist/components/VarIndicator/VarIndicator.test.js.map +1 -1
  131. package/dist/components/WeekSelector/WeekSelector.js.map +1 -1
  132. package/dist/components/WeekSelector/WeekSelector.stories.js.map +1 -1
  133. package/dist/components/WeekSelector/components/WeekSelectorOption.js.map +1 -1
  134. package/dist/components/hooks/useDebounce.js.map +1 -1
  135. package/dist/components/hooks/useOnClickOutside.js.map +1 -1
  136. package/dist/components/hooks/usePositionedFloaters.js.map +1 -1
  137. package/dist/components/hooks/useResponsive.js.map +1 -1
  138. package/dist/components-BzxAULjf.js.map +1 -1
  139. package/dist/dist-V_v3kC0L.js.map +1 -1
  140. package/dist/{esm-BwHoYxVb.js → esm-BoujHjK5.js} +2 -2
  141. package/dist/{esm-BwHoYxVb.js.map → esm-BoujHjK5.js.map} +1 -1
  142. package/dist/helpers-B1VK8xTF.js.map +1 -1
  143. package/dist/lib-BvOQt8El.js.map +1 -1
  144. package/dist/{react-18-B7MZmX_Z.js → react-18-DxAWL8_m.js} +2 -2
  145. package/dist/{react-18-B7MZmX_Z.js.map → react-18-DxAWL8_m.js.map} +1 -1
  146. package/dist/{react.esm-D_F72rY1.js → react.esm-CweFe1CK.js} +2 -2
  147. package/dist/{react.esm-D_F72rY1.js.map → react.esm-CweFe1CK.js.map} +1 -1
  148. package/dist/setupTests.js +2 -2
  149. package/dist/setupTests.js.map +1 -1
  150. package/dist/storybook__react.d.js +1 -1
  151. package/dist/storybook__react.d.js.map +1 -1
  152. package/dist/test-Pa9Lwbsq.js.map +1 -1
  153. package/dist/test-utils-Cmn06m_x.js.map +1 -1
  154. package/package.json +7 -6
  155. /package/dist/assets/favicon/{src/assets/favicon/android-chrome-192x192.png → android-chrome-192x192.png} +0 -0
  156. /package/dist/assets/favicon/{src/assets/favicon/android-chrome-512x512.png → android-chrome-512x512.png} +0 -0
  157. /package/dist/assets/favicon/{src/assets/favicon/apple-touch-icon.png → apple-touch-icon.png} +0 -0
  158. /package/dist/assets/favicon/{src/assets/favicon/favicon-16x16.png → favicon-16x16.png} +0 -0
  159. /package/dist/assets/favicon/{src/assets/favicon/favicon-32x32.png → favicon-32x32.png} +0 -0
  160. /package/dist/assets/favicon/{src/assets/favicon/favicon.ico → favicon.ico} +0 -0
  161. /package/dist/assets/favicon/{src/assets/favicon/favicon.svg → favicon.svg} +0 -0
  162. /package/dist/assets/favicon/{src/assets/favicon/site.webmanifest → site.webmanifest} +0 -0
  163. /package/dist/assets/fonts/{src/assets/fonts/SourceSans3-Regular.otf.woff → SourceSans3-Regular.otf.woff} +0 -0
  164. /package/dist/assets/fonts/{src/assets/fonts/SourceSans3-Regular.otf.woff2 → SourceSans3-Regular.otf.woff2} +0 -0
  165. /package/dist/assets/fonts/{src/assets/fonts/SourceSans3-Semibold.otf.woff → SourceSans3-Semibold.otf.woff} +0 -0
  166. /package/dist/assets/fonts/{src/assets/fonts/SourceSans3-Semibold.otf.woff2 → SourceSans3-Semibold.otf.woff2} +0 -0
  167. /package/dist/assets/{src/css/globals.css → globals.css} +0 -0
  168. /package/dist/assets/{src/css/variables.css → variables.css} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion-DvblEUVu.js","names":[],"sources":["../src/components/Accordion/Accordion.module.css","../src/components/Accordion/Accordion.tsx"],"sourcesContent":[".accordion {\n overflow: hidden;\n position: relative;\n}\n\n.accordion__title {\n align-items: center;\n display: flex;\n gap: 0.5rem;\n}\n\n.accordion__title:hover {\n cursor: pointer;\n text-decoration: underline;\n}\n\n.accordion__title:focus-visible {\n text-decoration: underline;\n}\n\n.accordion__title-icon,\n.accordion__title-icon-right {\n transform: rotate(-90deg);\n transition: transform 300ms ease-in;\n margin-right: 0.25rem;\n}\n\n.accordion__title-icon--margin-0 {\n margin: 0;\n}\n\n.accordion__title-icon--margin-025 {\n margin: 0 0.25rem;\n}\n\n.accordion__title-icon--margin-050 {\n margin: 0 0.5rem;\n}\n\n.accordion__title-icon--margin-075 {\n margin: 0 0.75rem;\n}\n\n.accordion__title-icon--margin-100 {\n margin: 0 1rem;\n}\n\n.accordion__title-icon--margin-150 {\n margin: 0 1.5rem;\n}\n\n.accordion__title-icon--margin-200 {\n margin: 0 2rem;\n}\n\n.accordion__title-icon-right {\n margin-left: auto;\n}\n\n.accordion__title-icon--expanded,\n.accordion__title-icon-right--expanded {\n transform: rotate(90deg);\n transition: transform 300ms ease-out;\n}\n\n.accordion__content {\n display: none;\n}\n\n.accordion__content--expanded {\n display: block;\n}\n","import { clsx } from 'clsx';\nimport { forwardRef, useId, useImperativeHandle, useState } from 'react';\n\nimport type { KeyboardEvent, ReactNode } from 'react';\n\nimport styles from './Accordion.module.css';\n\nimport { Icon } from 'components/Icon';\n\nexport interface AccordionProps {\n /** Clickable title (always visible). */\n title: ReactNode;\n /** Main content (hidden when expanded is false). */\n content: ReactNode;\n /** Indicator if Accordion should be expanded by default.*/\n expanded?: boolean;\n /** Indicator for cheveron icon placement.*/\n cheveronPlacement?: 'left' | 'right';\n /** Indicator for cheveron icon margin. By default '050'. */\n cheveronMargin?: '0' | '025' | '050' | '075' | '100' | '150' | '200';\n}\n\nexport interface AccordionMethods {\n closeContent: () => void;\n openContent: () => void;\n}\n\n/** A controller for accordion display toggling of content with click on a title. */\nexport const Accordion = forwardRef<AccordionMethods, AccordionProps>(\n ({ title, content, expanded = false, cheveronPlacement = 'right', cheveronMargin = '050' }, ref) => {\n const [isExpanded, setIsExpanded] = useState(expanded);\n const accordionId = useId();\n\n function onKeyUp(event: KeyboardEvent<HTMLDivElement>) {\n const { code } = event;\n\n if (code === 'Enter' || code === 'Space') {\n setIsExpanded(!isExpanded);\n }\n }\n\n const closeContent = () => {\n setIsExpanded(false);\n };\n\n const openContent = () => {\n setIsExpanded(true);\n };\n\n useImperativeHandle(ref, () => ({\n closeContent,\n openContent,\n }));\n\n return (\n <div>\n <div className={styles['accordion']}>\n <div\n className={styles['accordion__title']}\n id={accordionId}\n role=\"button\"\n tabIndex={0}\n onClick={() => setIsExpanded(!isExpanded)}\n onKeyUp={onKeyUp}\n aria-expanded={isExpanded}\n >\n {cheveronPlacement === 'left' && (\n <Icon\n className={clsx(\n styles['accordion__title-icon'],\n styles[`accordion__title-icon--margin-${cheveronMargin}`],\n {\n [styles['accordion__title-icon--expanded']]: isExpanded,\n }\n )}\n name=\"CheveronLeft\"\n size={16}\n />\n )}\n\n {title}\n {cheveronPlacement === 'right' && (\n <Icon\n className={clsx(\n styles['accordion__title-icon-right'],\n styles[`accordion__title-icon--margin-${cheveronMargin}`],\n {\n [styles['accordion__title-icon-right--expanded']]: isExpanded,\n }\n )}\n name=\"CheveronLeft\"\n size={16}\n />\n )}\n </div>\n <div\n aria-labelledby={accordionId}\n className={clsx(styles.accordion__content, { [styles['accordion__content--expanded']]: isExpanded })}\n >\n {content}\n </div>\n </div>\n </div>\n );\n }\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;GC4Ba,IAAY,GACtB,EAAE,UAAO,YAAS,cAAW,IAAO,uBAAoB,SAAS,oBAAiB,SAAS,MAAQ;CAClG,IAAM,CAAC,GAAY,KAAiB,EAAS,EAAS,EAChD,IAAc,GAAO;CAE3B,SAAS,EAAQ,GAAsC;EACrD,IAAM,EAAE,YAAS;AAEjB,GAAI,MAAS,WAAW,MAAS,YAC/B,EAAc,CAAC,EAAW;;CAI9B,IAAM,UAAqB;AACzB,IAAc,GAAM;IAGhB,UAAoB;AACxB,IAAc,GAAK;;AAQrB,QALA,EAAoB,UAAY;EAC9B;EACA;EACD,EAAE,EAGD,kBAAC,OAAD,EAAA,UACE,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACE,kBAAC,OAAD;GACE,WAAW,EAAO;GAClB,IAAI;GACJ,MAAK;GACL,UAAU;GACV,eAAe,EAAc,CAAC,EAAW;GAChC;GACT,iBAAe;aAPjB;IASG,MAAsB,UACrB,kBAAC,GAAD;KACE,WAAW,EACT,EAAO,0BACP,EAAO,iCAAiC,MACxC,GACG,EAAO,qCAAqC,GAC9C,CACF;KACD,MAAK;KACL,MAAM;KACN,CAAA;IAGH;IACA,MAAsB,WACrB,kBAAC,GAAD;KACE,WAAW,EACT,EAAO,gCACP,EAAO,iCAAiC,MACxC,GACG,EAAO,2CAA2C,GACpD,CACF;KACD,MAAK;KACL,MAAM;KACN,CAAA;IAEA;MACN,kBAAC,OAAD;GACE,mBAAiB;GACjB,WAAW,EAAK,EAAO,oBAAoB,GAAG,EAAO,kCAAkC,GAAY,CAAC;aAEnG;GACG,CAAA,CACF;KACF,CAAA;EAGX"}
1
+ {"version":3,"file":"Accordion-DvblEUVu.js","names":[],"sources":["../src/components/Accordion/Accordion.module.css","../src/components/Accordion/Accordion.tsx"],"sourcesContent":[".accordion {\n overflow: hidden;\n position: relative;\n}\n\n.accordion__title {\n align-items: center;\n display: flex;\n gap: 0.5rem;\n}\n\n.accordion__title:hover {\n cursor: pointer;\n text-decoration: underline;\n}\n\n.accordion__title:focus-visible {\n text-decoration: underline;\n}\n\n.accordion__title-icon,\n.accordion__title-icon-right {\n transform: rotate(-90deg);\n transition: transform 300ms ease-in;\n margin-right: 0.25rem;\n}\n\n.accordion__title-icon--margin-0 {\n margin: 0;\n}\n\n.accordion__title-icon--margin-025 {\n margin: 0 0.25rem;\n}\n\n.accordion__title-icon--margin-050 {\n margin: 0 0.5rem;\n}\n\n.accordion__title-icon--margin-075 {\n margin: 0 0.75rem;\n}\n\n.accordion__title-icon--margin-100 {\n margin: 0 1rem;\n}\n\n.accordion__title-icon--margin-150 {\n margin: 0 1.5rem;\n}\n\n.accordion__title-icon--margin-200 {\n margin: 0 2rem;\n}\n\n.accordion__title-icon-right {\n margin-left: auto;\n}\n\n.accordion__title-icon--expanded,\n.accordion__title-icon-right--expanded {\n transform: rotate(90deg);\n transition: transform 300ms ease-out;\n}\n\n.accordion__content {\n display: none;\n}\n\n.accordion__content--expanded {\n display: block;\n}\n","import { clsx } from 'clsx';\nimport { forwardRef, useId, useImperativeHandle, useState } from 'react';\n\nimport type { KeyboardEvent, ReactNode } from 'react';\n\nimport styles from './Accordion.module.css';\n\nimport { Icon } from 'components/Icon';\n\nexport interface AccordionProps {\n /** Clickable title (always visible). */\n title: ReactNode;\n /** Main content (hidden when expanded is false). */\n content: ReactNode;\n /** Indicator if Accordion should be expanded by default.*/\n expanded?: boolean;\n /** Indicator for cheveron icon placement.*/\n cheveronPlacement?: 'left' | 'right';\n /** Indicator for cheveron icon margin. By default '050'. */\n cheveronMargin?: '0' | '025' | '050' | '075' | '100' | '150' | '200';\n}\n\nexport interface AccordionMethods {\n closeContent: () => void;\n openContent: () => void;\n}\n\n/** A controller for accordion display toggling of content with click on a title. */\nexport const Accordion = forwardRef<AccordionMethods, AccordionProps>(\n ({ title, content, expanded = false, cheveronPlacement = 'right', cheveronMargin = '050' }, ref) => {\n const [isExpanded, setIsExpanded] = useState(expanded);\n const accordionId = useId();\n\n function onKeyUp(event: KeyboardEvent<HTMLDivElement>) {\n const { code } = event;\n\n if (code === 'Enter' || code === 'Space') {\n setIsExpanded(!isExpanded);\n }\n }\n\n const closeContent = () => {\n setIsExpanded(false);\n };\n\n const openContent = () => {\n setIsExpanded(true);\n };\n\n useImperativeHandle(ref, () => ({\n closeContent,\n openContent,\n }));\n\n return (\n <div>\n <div className={styles['accordion']}>\n <div\n className={styles['accordion__title']}\n id={accordionId}\n role=\"button\"\n tabIndex={0}\n onClick={() => setIsExpanded(!isExpanded)}\n onKeyUp={onKeyUp}\n aria-expanded={isExpanded}\n >\n {cheveronPlacement === 'left' && (\n <Icon\n className={clsx(\n styles['accordion__title-icon'],\n styles[`accordion__title-icon--margin-${cheveronMargin}`],\n {\n [styles['accordion__title-icon--expanded']]: isExpanded,\n }\n )}\n name=\"CheveronLeft\"\n size={16}\n />\n )}\n\n {title}\n {cheveronPlacement === 'right' && (\n <Icon\n className={clsx(\n styles['accordion__title-icon-right'],\n styles[`accordion__title-icon--margin-${cheveronMargin}`],\n {\n [styles['accordion__title-icon-right--expanded']]: isExpanded,\n }\n )}\n name=\"CheveronLeft\"\n size={16}\n />\n )}\n </div>\n <div\n aria-labelledby={accordionId}\n className={clsx(styles.accordion__content, { [styles['accordion__content--expanded']]: isExpanded })}\n >\n {content}\n </div>\n </div>\n </div>\n );\n }\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;GC4Ba,IAAY,GACtB,EAAE,UAAO,YAAS,cAAW,IAAO,uBAAoB,SAAS,oBAAiB,SAAS,MAAQ;CAClG,IAAM,CAAC,GAAY,KAAiB,EAAS,EAAS,EAChD,IAAc,GAAO;CAE3B,SAAS,EAAQ,GAAsC;EACrD,IAAM,EAAE,YAAS;EAEjB,CAAI,MAAS,WAAW,MAAS,YAC/B,EAAc,CAAC,EAAW;;CAI9B,IAAM,UAAqB;EACzB,EAAc,GAAM;IAGhB,UAAoB;EACxB,EAAc,GAAK;;CAQrB,OALA,EAAoB,UAAY;EAC9B;EACA;EACD,EAAE,EAGD,kBAAC,OAAD,EAAA,UACE,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACE,kBAAC,OAAD;GACE,WAAW,EAAO;GAClB,IAAI;GACJ,MAAK;GACL,UAAU;GACV,eAAe,EAAc,CAAC,EAAW;GAChC;GACT,iBAAe;aAPjB;IASG,MAAsB,UACrB,kBAAC,GAAD;KACE,WAAW,EACT,EAAO,0BACP,EAAO,iCAAiC,MACxC,GACG,EAAO,qCAAqC,GAC9C,CACF;KACD,MAAK;KACL,MAAM;KACN,CAAA;IAGH;IACA,MAAsB,WACrB,kBAAC,GAAD;KACE,WAAW,EACT,EAAO,gCACP,EAAO,iCAAiC,MACxC,GACG,EAAO,2CAA2C,GACpD,CACF;KACD,MAAK;KACL,MAAM;KACN,CAAA;IAEA;MACN,kBAAC,OAAD;GACE,mBAAiB;GACjB,WAAW,EAAK,EAAO,oBAAoB,GAAG,EAAO,kCAAkC,GAAY,CAAC;aAEnG;GACG,CAAA,CACF;KACF,CAAA;EAGX"}
@@ -1 +1 @@
1
- {"version":3,"file":"AccordionCard-BXy-plB7.js","names":[],"sources":["../src/components/AccordionCard/AccordionCard.module.css","../src/components/AccordionCard/AccordionCard.tsx"],"sourcesContent":[".accordion-card {\n background-color: var(--color-grey-200);\n overflow: hidden;\n position: relative;\n}\n\n.accordion-card__title {\n align-items: center;\n cursor: pointer;\n display: flex;\n gap: 0.5rem;\n justify-content: flex-start;\n padding: 1.5rem 1rem;\n user-select: none;\n}\n\n.accordion-card__title h3 {\n margin: 0;\n}\n\n.accordion-card__title:focus-visible {\n text-decoration: underline;\n}\n\n.accordion-card__title-icon {\n transform: rotate(-90deg);\n transition: transform 300ms ease-in;\n}\n\n.accordion-card__title-icon--expanded {\n transform: rotate(90deg);\n transition: transform 300ms ease-out;\n}\n\n.accordion-card__content {\n display: none;\n margin: 0.5rem 2.5rem 2.5rem;\n}\n\n.accordion-card__content--expanded {\n display: block;\n}\n","import { clsx } from 'clsx';\nimport { useId, useState } from 'react';\n\nimport type { KeyboardEvent, ReactNode } from 'react';\n\nimport styles from './AccordionCard.module.css';\n\nimport { Icon } from 'components/Icon';\n\nexport interface AccordionCardProps {\n /** Clickable title (always visible). */\n title: ReactNode;\n /** Main content (hidden when expanded is false). */\n content: ReactNode;\n /** Indicator if Accordion should be expanded by default.*/\n expanded?: boolean;\n}\n\nexport const AccordionCard = ({ title, content, expanded = false }: AccordionCardProps) => {\n const [isExpanded, setIsExpanded] = useState(expanded);\n const accordionId = useId();\n\n const onKeyUp = (event: KeyboardEvent<HTMLDivElement>) => {\n const { code } = event;\n\n if (code === 'Enter' || code === 'Space') {\n setIsExpanded(!isExpanded);\n }\n };\n\n return (\n <div className={styles['accordion-card']}>\n <div\n className={styles['accordion-card__title']}\n id={accordionId}\n role=\"button\"\n tabIndex={0}\n onClick={() => setIsExpanded(!isExpanded)}\n onKeyUp={onKeyUp}\n aria-expanded={isExpanded}\n >\n <Icon\n className={clsx(styles['accordion-card__title-icon'], {\n [styles['accordion-card__title-icon--expanded']]: isExpanded,\n })}\n name=\"CheveronLeft\"\n size={16}\n />\n <h3>{title}</h3>\n </div>\n <div\n aria-labelledby={accordionId}\n className={clsx(styles['accordion-card__content'], {\n [styles['accordion-card__content--expanded']]: isExpanded,\n })}\n >\n {content}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;GCkBa,KAAiB,EAAE,UAAO,YAAS,cAAW,SAAgC;CACzF,IAAM,CAAC,GAAY,KAAiB,EAAS,EAAS,EAChD,IAAc,GAAO;AAU3B,QACE,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACE,kBAAC,OAAD;GACE,WAAW,EAAO;GAClB,IAAI;GACJ,MAAK;GACL,UAAU;GACV,eAAe,EAAc,CAAC,EAAW;GAChC,UAhBE,MAAyC;IACxD,IAAM,EAAE,YAAS;AAEjB,KAAI,MAAS,WAAW,MAAS,YAC/B,EAAc,CAAC,EAAW;;GAaxB,iBAAe;aAPjB,CASE,kBAAC,GAAD;IACE,WAAW,EAAK,EAAO,+BAA+B,GACnD,EAAO,0CAA0C,GACnD,CAAC;IACF,MAAK;IACL,MAAM;IACN,CAAA,EACF,kBAAC,MAAD,EAAA,UAAK,GAAW,CAAA,CACZ;MACN,kBAAC,OAAD;GACE,mBAAiB;GACjB,WAAW,EAAK,EAAO,4BAA4B,GAChD,EAAO,uCAAuC,GAChD,CAAC;aAED;GACG,CAAA,CACF"}
1
+ {"version":3,"file":"AccordionCard-BXy-plB7.js","names":[],"sources":["../src/components/AccordionCard/AccordionCard.module.css","../src/components/AccordionCard/AccordionCard.tsx"],"sourcesContent":[".accordion-card {\n background-color: var(--color-grey-200);\n overflow: hidden;\n position: relative;\n}\n\n.accordion-card__title {\n align-items: center;\n cursor: pointer;\n display: flex;\n gap: 0.5rem;\n justify-content: flex-start;\n padding: 1.5rem 1rem;\n user-select: none;\n}\n\n.accordion-card__title h3 {\n margin: 0;\n}\n\n.accordion-card__title:focus-visible {\n text-decoration: underline;\n}\n\n.accordion-card__title-icon {\n transform: rotate(-90deg);\n transition: transform 300ms ease-in;\n}\n\n.accordion-card__title-icon--expanded {\n transform: rotate(90deg);\n transition: transform 300ms ease-out;\n}\n\n.accordion-card__content {\n display: none;\n margin: 0.5rem 2.5rem 2.5rem;\n}\n\n.accordion-card__content--expanded {\n display: block;\n}\n","import { clsx } from 'clsx';\nimport { useId, useState } from 'react';\n\nimport type { KeyboardEvent, ReactNode } from 'react';\n\nimport styles from './AccordionCard.module.css';\n\nimport { Icon } from 'components/Icon';\n\nexport interface AccordionCardProps {\n /** Clickable title (always visible). */\n title: ReactNode;\n /** Main content (hidden when expanded is false). */\n content: ReactNode;\n /** Indicator if Accordion should be expanded by default.*/\n expanded?: boolean;\n}\n\nexport const AccordionCard = ({ title, content, expanded = false }: AccordionCardProps) => {\n const [isExpanded, setIsExpanded] = useState(expanded);\n const accordionId = useId();\n\n const onKeyUp = (event: KeyboardEvent<HTMLDivElement>) => {\n const { code } = event;\n\n if (code === 'Enter' || code === 'Space') {\n setIsExpanded(!isExpanded);\n }\n };\n\n return (\n <div className={styles['accordion-card']}>\n <div\n className={styles['accordion-card__title']}\n id={accordionId}\n role=\"button\"\n tabIndex={0}\n onClick={() => setIsExpanded(!isExpanded)}\n onKeyUp={onKeyUp}\n aria-expanded={isExpanded}\n >\n <Icon\n className={clsx(styles['accordion-card__title-icon'], {\n [styles['accordion-card__title-icon--expanded']]: isExpanded,\n })}\n name=\"CheveronLeft\"\n size={16}\n />\n <h3>{title}</h3>\n </div>\n <div\n aria-labelledby={accordionId}\n className={clsx(styles['accordion-card__content'], {\n [styles['accordion-card__content--expanded']]: isExpanded,\n })}\n >\n {content}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;GCkBa,KAAiB,EAAE,UAAO,YAAS,cAAW,SAAgC;CACzF,IAAM,CAAC,GAAY,KAAiB,EAAS,EAAS,EAChD,IAAc,GAAO;CAU3B,OACE,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACE,kBAAC,OAAD;GACE,WAAW,EAAO;GAClB,IAAI;GACJ,MAAK;GACL,UAAU;GACV,eAAe,EAAc,CAAC,EAAW;GAChC,UAhBE,MAAyC;IACxD,IAAM,EAAE,YAAS;IAEjB,CAAI,MAAS,WAAW,MAAS,YAC/B,EAAc,CAAC,EAAW;;GAaxB,iBAAe;aAPjB,CASE,kBAAC,GAAD;IACE,WAAW,EAAK,EAAO,+BAA+B,GACnD,EAAO,0CAA0C,GACnD,CAAC;IACF,MAAK;IACL,MAAM;IACN,CAAA,EACF,kBAAC,MAAD,EAAA,UAAK,GAAW,CAAA,CACZ;MACN,kBAAC,OAAD;GACE,mBAAiB;GACjB,WAAW,EAAK,EAAO,4BAA4B,GAChD,EAAO,uCAAuC,GAChD,CAAC;aAED;GACG,CAAA,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"ActionList-O9w1hqNg.js","names":[],"sources":["../src/components/ActionList/ActionList.module.css","../src/components/ActionList/ActionList.tsx"],"sourcesContent":[".action-list {\n background-color: var(--color-uva-white);\n border-radius: 0.5rem;\n box-shadow: 0 0 6px 2px rgb(0 0 0 / 15%);\n display: none;\n padding: 0.25rem;\n position: absolute;\n right: 0;\n top: calc(100% + 0.5rem);\n z-index: 100;\n}\n\n.action-list--open {\n display: block;\n}\n\n.action-list-container {\n position: relative;\n}\n\n.action-list [role=\"menuitem\"] > * {\n background: 0;\n border: 0;\n border-radius: 0.25rem;\n cursor: pointer;\n display: block;\n font: inherit;\n margin: 0;\n padding: 0.5rem 0.75rem;\n text-align: left;\n white-space: pre;\n width: 100%;\n}\n\n.action-list [role=\"menuitem\"] > *:not(:last-of-type) {\n border-bottom: 1px solid var(--color-grey-300);\n}\n\n.action-list [role=\"menuitem\"] > *:hover {\n background-color: var(--color-grey-200);\n}\n","import { clsx } from 'clsx';\nimport { Children, useEffect, useId, useRef, useState } from 'react';\n\nimport type { KeyboardEvent, MouseEvent as ReactMouseEvent, ReactElement, RefObject } from 'react';\nimport type { IconProps } from 'components/Icon';\nimport type { UIButtonVariant } from 'types/UserInterface';\n\nimport styles from './ActionList.module.css';\n\nimport { Icon } from 'components/Icon';\nimport { MenuButton } from 'components/Buttons';\n\nexport interface ActionListProps {\n /** The label that is displayed before the icon. */\n label: string;\n /** The icon that is shown in front of the label. */\n prefixIcon?: IconProps['name'];\n /** The icon that is shown to toggle the menu. If none is specified, CheveronUp and CheveronDown is used depending on whether the menu is opened or closed. */\n iconName?: IconProps['name'];\n /** Determines the button variant. */\n variant?: UIButtonVariant;\n /** The child component(s). */\n children: ReactElement | ReactElement[];\n}\n\nconst inactiveIndex = -1;\nconst indexIncrement = 1;\n\n/** A component to show an action list to toggle a menu. */\nexport function ActionList({ label, prefixIcon, iconName, variant = 'secondary', children }: ActionListProps) {\n const listId = useId();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const numberOfChildren = Children.count(children);\n\n const [activeIndex, setActiveIndex] = useState(inactiveIndex);\n const [isOpen, setIsOpen] = useState(false);\n\n function open() {\n setIsOpen(true);\n\n document.addEventListener('click', onClickOutside, { once: true, capture: true });\n }\n\n function close(event?: ReactMouseEvent<HTMLDivElement>) {\n // When a click occurs on an element that is not an immediate descendant of the action list container\n // (can happen when a modal window is triggered from a button in the action list), the setIsOpen state\n // handler should not be called, because this causes a re-render of the entire component and can lead\n // to undesired effects, like a select element closing immediately after it has been clicked.\n if (event && containerRef.current && !containerRef.current.contains(event.target as Node)) {\n return;\n }\n\n setActiveIndex(inactiveIndex);\n setIsOpen(false);\n\n document.removeEventListener('click', onClickOutside, { capture: true });\n }\n\n function toggle() {\n if (isOpen) close();\n else open();\n }\n\n function onKeyDown(event: KeyboardEvent) {\n if (!isOpen) return;\n\n const eventPreventCodes = ['ArrowUp', 'ArrowDown', 'Home', 'End'];\n\n if (eventPreventCodes.includes(event.code)) {\n // prevent page from scrolling when navigating through items in list\n event.preventDefault();\n }\n\n if (event.code === 'Tab') {\n close();\n }\n }\n\n function onKeyUp(event: KeyboardEvent) {\n if (event.code === 'Space' || event.key === 'Enter') {\n if (event.target === triggerRef.current) {\n toggle();\n } else if (event.key === 'Enter' && event.target !== listRef.current) {\n if ('firstChild' in event.target) {\n const firstChild = event.target.firstChild as HTMLButtonElement;\n\n firstChild.click();\n }\n }\n }\n\n if (event.code === 'Escape') close();\n\n if (event.code === 'ArrowUp') {\n setActiveIndex((prevState) => {\n if (prevState === 0) return numberOfChildren - indexIncrement;\n\n return prevState - indexIncrement;\n });\n }\n\n if (event.code === 'ArrowDown') {\n setActiveIndex((prevState) => {\n if (prevState === numberOfChildren - indexIncrement) return 0;\n\n return prevState + indexIncrement;\n });\n }\n\n if (event.code === 'Home') {\n setActiveIndex(0);\n }\n\n if (event.code === 'End') {\n setActiveIndex(numberOfChildren - indexIncrement);\n }\n }\n\n const onClickOutside = (event: MouseEvent) => {\n const { target } = event;\n\n if (!target || !containerRef.current) return;\n\n if (!containerRef.current.contains(target as Node)) {\n close();\n }\n };\n\n useEffect(() => {\n if (activeIndex < 0 || !listRef.current) return;\n\n const listItem = listRef.current.children.item(activeIndex);\n\n if (listItem) {\n (listItem as HTMLDivElement).focus();\n }\n }, [activeIndex]);\n\n useEffect(() => {\n if (!listRef.current || !listRef.current.hasChildNodes()) return;\n\n Array.from(listRef.current.children)\n .filter((overlayChild) => overlayChild.nodeType === Node.ELEMENT_NODE && overlayChild.hasChildNodes())\n .forEach((overlayChild) => {\n Array.from(overlayChild.children)\n .filter((childOfChild) => childOfChild.nodeType === Node.ELEMENT_NODE)\n .forEach((childOfChild) => {\n // internal children may be buttons and can get focus when tab is pressed; preventing those elements\n // from getting focus so that list can be tabbed over and traversed with arrow keys\n childOfChild.setAttribute('tabIndex', '-1');\n });\n });\n }, [children]);\n\n return (\n <div className={styles['action-list-container']} ref={containerRef}>\n <MenuButton\n onClick={toggle}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n buttonRef={triggerRef as RefObject<HTMLButtonElement>}\n variant={variant}\n >\n {prefixIcon && <Icon size={24} name={prefixIcon} />}\n {label}\n {iconName ? (\n <Icon size={24} name={iconName} />\n ) : (\n <Icon size={16} name={isOpen ? 'CheveronUp' : 'CheveronDown'} />\n )}\n </MenuButton>\n <div\n aria-activedescendant={`${listId}-child-${activeIndex}`}\n aria-label={label}\n className={clsx(styles['action-list'], {\n [styles['action-list--open']]: isOpen,\n })}\n onClickCapture={close}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n ref={listRef}\n role=\"menu\"\n tabIndex={-1}\n >\n {Children.map(children, (child, index) => (\n <div key={`${listId}-child-${index}`} role=\"menuitem\" tabIndex={-1}>\n {child}\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ActionList-O9w1hqNg.js","names":[],"sources":["../src/components/ActionList/ActionList.module.css","../src/components/ActionList/ActionList.tsx"],"sourcesContent":[".action-list {\n background-color: var(--color-uva-white);\n border-radius: 0.5rem;\n box-shadow: 0 0 6px 2px rgb(0 0 0 / 15%);\n display: none;\n padding: 0.25rem;\n position: absolute;\n right: 0;\n top: calc(100% + 0.5rem);\n z-index: 100;\n}\n\n.action-list--open {\n display: block;\n}\n\n.action-list-container {\n position: relative;\n}\n\n.action-list [role=\"menuitem\"] > * {\n background: 0;\n border: 0;\n border-radius: 0.25rem;\n cursor: pointer;\n display: block;\n font: inherit;\n margin: 0;\n padding: 0.5rem 0.75rem;\n text-align: left;\n white-space: pre;\n width: 100%;\n}\n\n.action-list [role=\"menuitem\"] > *:not(:last-of-type) {\n border-bottom: 1px solid var(--color-grey-300);\n}\n\n.action-list [role=\"menuitem\"] > *:hover {\n background-color: var(--color-grey-200);\n}\n","import { clsx } from 'clsx';\nimport { Children, useEffect, useId, useRef, useState } from 'react';\n\nimport type { KeyboardEvent, MouseEvent as ReactMouseEvent, ReactElement, RefObject } from 'react';\nimport type { IconProps } from 'components/Icon';\nimport type { UIButtonVariant } from 'types/UserInterface';\n\nimport styles from './ActionList.module.css';\n\nimport { Icon } from 'components/Icon';\nimport { MenuButton } from 'components/Buttons';\n\nexport interface ActionListProps {\n /** The label that is displayed before the icon. */\n label: string;\n /** The icon that is shown in front of the label. */\n prefixIcon?: IconProps['name'];\n /** The icon that is shown to toggle the menu. If none is specified, CheveronUp and CheveronDown is used depending on whether the menu is opened or closed. */\n iconName?: IconProps['name'];\n /** Determines the button variant. */\n variant?: UIButtonVariant;\n /** The child component(s). */\n children: ReactElement | ReactElement[];\n}\n\nconst inactiveIndex = -1;\nconst indexIncrement = 1;\n\n/** A component to show an action list to toggle a menu. */\nexport function ActionList({ label, prefixIcon, iconName, variant = 'secondary', children }: ActionListProps) {\n const listId = useId();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const numberOfChildren = Children.count(children);\n\n const [activeIndex, setActiveIndex] = useState(inactiveIndex);\n const [isOpen, setIsOpen] = useState(false);\n\n function open() {\n setIsOpen(true);\n\n document.addEventListener('click', onClickOutside, { once: true, capture: true });\n }\n\n function close(event?: ReactMouseEvent<HTMLDivElement>) {\n // When a click occurs on an element that is not an immediate descendant of the action list container\n // (can happen when a modal window is triggered from a button in the action list), the setIsOpen state\n // handler should not be called, because this causes a re-render of the entire component and can lead\n // to undesired effects, like a select element closing immediately after it has been clicked.\n if (event && containerRef.current && !containerRef.current.contains(event.target as Node)) {\n return;\n }\n\n setActiveIndex(inactiveIndex);\n setIsOpen(false);\n\n document.removeEventListener('click', onClickOutside, { capture: true });\n }\n\n function toggle() {\n if (isOpen) close();\n else open();\n }\n\n function onKeyDown(event: KeyboardEvent) {\n if (!isOpen) return;\n\n const eventPreventCodes = ['ArrowUp', 'ArrowDown', 'Home', 'End'];\n\n if (eventPreventCodes.includes(event.code)) {\n // prevent page from scrolling when navigating through items in list\n event.preventDefault();\n }\n\n if (event.code === 'Tab') {\n close();\n }\n }\n\n function onKeyUp(event: KeyboardEvent) {\n if (event.code === 'Space' || event.key === 'Enter') {\n if (event.target === triggerRef.current) {\n toggle();\n } else if (event.key === 'Enter' && event.target !== listRef.current) {\n if ('firstChild' in event.target) {\n const firstChild = event.target.firstChild as HTMLButtonElement;\n\n firstChild.click();\n }\n }\n }\n\n if (event.code === 'Escape') close();\n\n if (event.code === 'ArrowUp') {\n setActiveIndex((prevState) => {\n if (prevState === 0) return numberOfChildren - indexIncrement;\n\n return prevState - indexIncrement;\n });\n }\n\n if (event.code === 'ArrowDown') {\n setActiveIndex((prevState) => {\n if (prevState === numberOfChildren - indexIncrement) return 0;\n\n return prevState + indexIncrement;\n });\n }\n\n if (event.code === 'Home') {\n setActiveIndex(0);\n }\n\n if (event.code === 'End') {\n setActiveIndex(numberOfChildren - indexIncrement);\n }\n }\n\n const onClickOutside = (event: MouseEvent) => {\n const { target } = event;\n\n if (!target || !containerRef.current) return;\n\n if (!containerRef.current.contains(target as Node)) {\n close();\n }\n };\n\n useEffect(() => {\n if (activeIndex < 0 || !listRef.current) return;\n\n const listItem = listRef.current.children.item(activeIndex);\n\n if (listItem) {\n (listItem as HTMLDivElement).focus();\n }\n }, [activeIndex]);\n\n useEffect(() => {\n if (!listRef.current || !listRef.current.hasChildNodes()) return;\n\n Array.from(listRef.current.children)\n .filter((overlayChild) => overlayChild.nodeType === Node.ELEMENT_NODE && overlayChild.hasChildNodes())\n .forEach((overlayChild) => {\n Array.from(overlayChild.children)\n .filter((childOfChild) => childOfChild.nodeType === Node.ELEMENT_NODE)\n .forEach((childOfChild) => {\n // internal children may be buttons and can get focus when tab is pressed; preventing those elements\n // from getting focus so that list can be tabbed over and traversed with arrow keys\n childOfChild.setAttribute('tabIndex', '-1');\n });\n });\n }, [children]);\n\n return (\n <div className={styles['action-list-container']} ref={containerRef}>\n <MenuButton\n onClick={toggle}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n buttonRef={triggerRef as RefObject<HTMLButtonElement>}\n variant={variant}\n >\n {prefixIcon && <Icon size={24} name={prefixIcon} />}\n {label}\n {iconName ? (\n <Icon size={24} name={iconName} />\n ) : (\n <Icon size={16} name={isOpen ? 'CheveronUp' : 'CheveronDown'} />\n )}\n </MenuButton>\n <div\n aria-activedescendant={`${listId}-child-${activeIndex}`}\n aria-label={label}\n className={clsx(styles['action-list'], {\n [styles['action-list--open']]: isOpen,\n })}\n onClickCapture={close}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n ref={listRef}\n role=\"menu\"\n tabIndex={-1}\n >\n {Children.map(children, (child, index) => (\n <div key={`${listId}-child-${index}`} role=\"menuitem\" tabIndex={-1}>\n {child}\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AddCatalogueLinkForm-rph4K9P0.js","names":[],"sources":["../src/components/RteEditor/Plugins/CourseCataloguePlugin/AddCatalogueLinkForm/AddCatalogueLinkForm.module.css","../src/components/RteEditor/Plugins/CourseCataloguePlugin/AddCatalogueLinkForm/AddCatalogueLinkForm.tsx"],"sourcesContent":[".courselinkform {\n font-family: inherit;\n font-size: inherit;\n width: 30rem;\n}\n\n.courselinkform__input-field {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.courselinkform__footer {\n display: flex;\n gap: 0.5rem;\n justify-content: flex-end;\n margin-top: 1rem;\n}\n\n.courselinkform__results-wrapper {\n position: relative;\n}\n\n.courselinkform__results-header {\n align-items: center;\n display: flex;\n font-size: var(--font-size-text-base);\n gap: 0.5rem;\n padding: 0.5rem;\n text-align: left;\n width: 100%;\n}\n\n.courselinkform__results {\n border: 1px solid var(--color-grey-300);\n border-radius: 0.25rem;\n max-height: 10rem;\n overflow-y: auto;\n}\n\n.courselinkform__result-message {\n align-items: center;\n color: var(--color-grey-600);\n display: flex;\n font-size: var(--font-size-text-non-essential);\n height: 2rem;\n justify-content: flex-start;\n padding: 0 0.5rem;\n}\n\n.courselinkform__result-item {\n align-items: center;\n appearance: none;\n background-color: transparent;\n border: none;\n cursor: pointer;\n display: flex;\n font-family: inherit;\n font-size: var(--font-size-text-base);\n gap: 0.5rem;\n min-height: 2.5rem;\n padding: 0.5rem;\n text-align: left;\n width: 100%;\n}\n\n.courselinkform__results-header span,\n.courselinkform__result-item span {\n line-height: 1.4;\n width: calc(100% - 9rem);\n}\n\n.courselinkform__results-header span:first-child,\n.courselinkform__result-item span:first-child {\n width: 9rem;\n}\n\n.courselinkform__result-item:focus-visible {\n background-color: var(--color-grey-300);\n outline: none;\n}\n\n.courselinkform__result-item:hover,\n.courselinkform__result-item:focus-visible {\n background-color: var(--color-grey-300);\n}\n\n.courselinkform__result-item:not(:last-child) {\n border-bottom: 1px solid var(--color-grey-300);\n}\n","import { useEffect, useId, useRef } from 'react';\r\n\r\nimport type { KeyboardEvent } from 'react';\r\n\r\nimport styles from './AddCatalogueLinkForm.module.css';\r\n\r\nimport { Button } from 'components/Buttons';\r\nimport { FormField } from 'components/FormField';\r\nimport { Label } from 'components/Label';\r\nimport { useTranslation } from 'components/RteEditor/hooks/useTranslation';\r\nimport { InputField } from 'components/InputField';\r\nimport { useLanguage } from 'components/RteEditor/Providers/LanguageProvider';\r\nimport { Repeater } from 'components/Repeater';\r\n\r\ntype SearchResult = {\r\n code: string;\r\n id: string;\r\n name: {\r\n EN: string;\r\n NL: string;\r\n };\r\n programmeType: string;\r\n};\r\n\r\nexport type SearchResponse = {\r\n state: 'idle' | 'pending' | 'ready';\r\n results: SearchResult[];\r\n};\r\n\r\ninterface AddCatalogueLinkFormProps {\r\n linkType: 'course' | 'programme';\r\n onCloseHandler: () => void;\r\n onSearchHandler: (query: string, type: 'course' | 'programme') => void;\r\n searchResponse?: SearchResponse;\r\n onSelect?: (code: string, label: string, type: 'course' | 'programme') => void;\r\n}\r\n\r\nexport const AddCatalogueLinkForm = ({\r\n linkType,\r\n onCloseHandler,\r\n onSearchHandler,\r\n searchResponse,\r\n onSelect,\r\n}: AddCatalogueLinkFormProps) => {\r\n const t = useTranslation();\r\n const searchId = `search_${useId()}`;\r\n const searchFieldRef = useRef<HTMLInputElement>(null);\r\n const resultListRef = useRef<HTMLDivElement>(null);\r\n const { currentLanguage } = useLanguage();\r\n\r\n const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const query = event.target.value;\r\n if (onSearchHandler) {\r\n onSearchHandler(query, linkType);\r\n }\r\n };\r\n\r\n const handleClose = () => {\r\n onCloseHandler();\r\n };\r\n\r\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\r\n if (event.key === 'ArrowDown') {\r\n event.preventDefault();\r\n const container = resultListRef.current;\r\n const firstFocusable = container?.querySelector<HTMLElement>('button');\r\n firstFocusable?.focus();\r\n }\r\n };\r\n\r\n const onResultKeyDown = (\r\n event: KeyboardEvent<HTMLButtonElement>,\r\n code: string,\r\n name: string,\r\n linkType: 'course' | 'programme'\r\n ) => {\r\n switch (event.key) {\r\n case 'Escape':\r\n event.preventDefault();\r\n event.stopPropagation();\r\n handleClose();\r\n break;\r\n case 'Enter':\r\n event.preventDefault();\r\n onSelect && onSelect(code, name, linkType);\r\n break;\r\n case 'ArrowDown': {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n const nextElement = event.currentTarget.nextElementSibling;\r\n (nextElement as HTMLButtonElement)?.focus();\r\n break;\r\n }\r\n case 'ArrowUp': {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n const previousElement = event.currentTarget.previousElementSibling;\r\n (previousElement as HTMLButtonElement)?.focus();\r\n break;\r\n }\r\n case 'Tab':\r\n event.preventDefault();\r\n handleClose();\r\n break;\r\n default:\r\n event.preventDefault();\r\n break;\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n if (searchFieldRef.current) {\r\n onSearchHandler('', linkType);\r\n searchFieldRef.current.value = '';\r\n searchFieldRef.current.focus();\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n return (\r\n <div className={styles['courselinkform']}>\r\n <Repeater gap=\"050\">\r\n <FormField className={styles['courselinkform__input-field']}>\r\n <Label htmlFor={searchId}>\r\n {t.cataloguelinks[linkType === 'course' ? 'searchCourseFieldLabel' : 'searchProgrammeFieldLabel']}\r\n </Label>\r\n <div className={styles['linkform__input-url-wrapper']}>\r\n <InputField\r\n id={searchId}\r\n placeholder={t.cataloguelinks.searchFieldPlaceholder}\r\n onChange={handleSearch}\r\n onKeyDown={handleKeyDown}\r\n ref={searchFieldRef}\r\n aria-label={t.aria.labels.searchField}\r\n />\r\n </div>\r\n </FormField>\r\n {searchResponse && searchResponse.state === 'pending' && (\r\n <div className={styles['courselinkform__result-message']}>{t.cataloguelinks.loading}</div>\r\n )}\r\n {searchResponse && searchResponse.results.length === 0 && searchResponse.state === 'ready' && (\r\n <div className={styles['courselinkform__result-message']}>{t.cataloguelinks.noResults}</div>\r\n )}\r\n {searchResponse && searchResponse.results.length > 0 && (\r\n <div className={styles['courselinkform__results-wrapper']}>\r\n <div className={styles['courselinkform__results-header']}>\r\n <span>\r\n {\r\n t.cataloguelinks[\r\n linkType === 'course' ? 'resultCourseListCatalogNumber' : 'resultProgrammeListCatalogNumber'\r\n ]\r\n }\r\n </span>\r\n <span>{t.cataloguelinks.resultListName}</span>\r\n </div>\r\n <div className={styles['courselinkform__results']} ref={resultListRef}>\r\n {searchResponse.results.map(({ id, code, name }) => (\r\n <button\r\n key={id}\r\n type=\"button\"\r\n className={styles['courselinkform__result-item']}\r\n onClick={() => onSelect && onSelect(code, name[currentLanguage], linkType)}\r\n onKeyDown={(event) => onResultKeyDown(event, code, name[currentLanguage], linkType)}\r\n tabIndex={0}\r\n aria-label={`${code} ${name[currentLanguage]}`}\r\n >\r\n <span>{code}</span>\r\n <span>{name[currentLanguage]}</span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </Repeater>\r\n <div className={styles['courselinkform__footer']}>\r\n <Button variant={'secondary'} onClick={handleClose} aria-label={t.common.cancel} type=\"button\">\r\n {t.common.cancel}\r\n </Button>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"AddCatalogueLinkForm-rph4K9P0.js","names":[],"sources":["../src/components/RteEditor/Plugins/CourseCataloguePlugin/AddCatalogueLinkForm/AddCatalogueLinkForm.module.css","../src/components/RteEditor/Plugins/CourseCataloguePlugin/AddCatalogueLinkForm/AddCatalogueLinkForm.tsx"],"sourcesContent":[".courselinkform {\n font-family: inherit;\n font-size: inherit;\n width: 30rem;\n}\n\n.courselinkform__input-field {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.courselinkform__footer {\n display: flex;\n gap: 0.5rem;\n justify-content: flex-end;\n margin-top: 1rem;\n}\n\n.courselinkform__results-wrapper {\n position: relative;\n}\n\n.courselinkform__results-header {\n align-items: center;\n display: flex;\n font-size: var(--font-size-text-base);\n gap: 0.5rem;\n padding: 0.5rem;\n text-align: left;\n width: 100%;\n}\n\n.courselinkform__results {\n border: 1px solid var(--color-grey-300);\n border-radius: 0.25rem;\n max-height: 10rem;\n overflow-y: auto;\n}\n\n.courselinkform__result-message {\n align-items: center;\n color: var(--color-grey-600);\n display: flex;\n font-size: var(--font-size-text-non-essential);\n height: 2rem;\n justify-content: flex-start;\n padding: 0 0.5rem;\n}\n\n.courselinkform__result-item {\n align-items: center;\n appearance: none;\n background-color: transparent;\n border: none;\n cursor: pointer;\n display: flex;\n font-family: inherit;\n font-size: var(--font-size-text-base);\n gap: 0.5rem;\n min-height: 2.5rem;\n padding: 0.5rem;\n text-align: left;\n width: 100%;\n}\n\n.courselinkform__results-header span,\n.courselinkform__result-item span {\n line-height: 1.4;\n width: calc(100% - 9rem);\n}\n\n.courselinkform__results-header span:first-child,\n.courselinkform__result-item span:first-child {\n width: 9rem;\n}\n\n.courselinkform__result-item:focus-visible {\n background-color: var(--color-grey-300);\n outline: none;\n}\n\n.courselinkform__result-item:hover,\n.courselinkform__result-item:focus-visible {\n background-color: var(--color-grey-300);\n}\n\n.courselinkform__result-item:not(:last-child) {\n border-bottom: 1px solid var(--color-grey-300);\n}\n","import { useEffect, useId, useRef } from 'react';\r\n\r\nimport type { KeyboardEvent } from 'react';\r\n\r\nimport styles from './AddCatalogueLinkForm.module.css';\r\n\r\nimport { Button } from 'components/Buttons';\r\nimport { FormField } from 'components/FormField';\r\nimport { Label } from 'components/Label';\r\nimport { useTranslation } from 'components/RteEditor/hooks/useTranslation';\r\nimport { InputField } from 'components/InputField';\r\nimport { useLanguage } from 'components/RteEditor/Providers/LanguageProvider';\r\nimport { Repeater } from 'components/Repeater';\r\n\r\ntype SearchResult = {\r\n code: string;\r\n id: string;\r\n name: {\r\n EN: string;\r\n NL: string;\r\n };\r\n programmeType: string;\r\n};\r\n\r\nexport type SearchResponse = {\r\n state: 'idle' | 'pending' | 'ready';\r\n results: SearchResult[];\r\n};\r\n\r\ninterface AddCatalogueLinkFormProps {\r\n linkType: 'course' | 'programme';\r\n onCloseHandler: () => void;\r\n onSearchHandler: (query: string, type: 'course' | 'programme') => void;\r\n searchResponse?: SearchResponse;\r\n onSelect?: (code: string, label: string, type: 'course' | 'programme') => void;\r\n}\r\n\r\nexport const AddCatalogueLinkForm = ({\r\n linkType,\r\n onCloseHandler,\r\n onSearchHandler,\r\n searchResponse,\r\n onSelect,\r\n}: AddCatalogueLinkFormProps) => {\r\n const t = useTranslation();\r\n const searchId = `search_${useId()}`;\r\n const searchFieldRef = useRef<HTMLInputElement>(null);\r\n const resultListRef = useRef<HTMLDivElement>(null);\r\n const { currentLanguage } = useLanguage();\r\n\r\n const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const query = event.target.value;\r\n if (onSearchHandler) {\r\n onSearchHandler(query, linkType);\r\n }\r\n };\r\n\r\n const handleClose = () => {\r\n onCloseHandler();\r\n };\r\n\r\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\r\n if (event.key === 'ArrowDown') {\r\n event.preventDefault();\r\n const container = resultListRef.current;\r\n const firstFocusable = container?.querySelector<HTMLElement>('button');\r\n firstFocusable?.focus();\r\n }\r\n };\r\n\r\n const onResultKeyDown = (\r\n event: KeyboardEvent<HTMLButtonElement>,\r\n code: string,\r\n name: string,\r\n linkType: 'course' | 'programme'\r\n ) => {\r\n switch (event.key) {\r\n case 'Escape':\r\n event.preventDefault();\r\n event.stopPropagation();\r\n handleClose();\r\n break;\r\n case 'Enter':\r\n event.preventDefault();\r\n onSelect && onSelect(code, name, linkType);\r\n break;\r\n case 'ArrowDown': {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n const nextElement = event.currentTarget.nextElementSibling;\r\n (nextElement as HTMLButtonElement)?.focus();\r\n break;\r\n }\r\n case 'ArrowUp': {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n const previousElement = event.currentTarget.previousElementSibling;\r\n (previousElement as HTMLButtonElement)?.focus();\r\n break;\r\n }\r\n case 'Tab':\r\n event.preventDefault();\r\n handleClose();\r\n break;\r\n default:\r\n event.preventDefault();\r\n break;\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n if (searchFieldRef.current) {\r\n onSearchHandler('', linkType);\r\n searchFieldRef.current.value = '';\r\n searchFieldRef.current.focus();\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n return (\r\n <div className={styles['courselinkform']}>\r\n <Repeater gap=\"050\">\r\n <FormField className={styles['courselinkform__input-field']}>\r\n <Label htmlFor={searchId}>\r\n {t.cataloguelinks[linkType === 'course' ? 'searchCourseFieldLabel' : 'searchProgrammeFieldLabel']}\r\n </Label>\r\n <div className={styles['linkform__input-url-wrapper']}>\r\n <InputField\r\n id={searchId}\r\n placeholder={t.cataloguelinks.searchFieldPlaceholder}\r\n onChange={handleSearch}\r\n onKeyDown={handleKeyDown}\r\n ref={searchFieldRef}\r\n aria-label={t.aria.labels.searchField}\r\n />\r\n </div>\r\n </FormField>\r\n {searchResponse && searchResponse.state === 'pending' && (\r\n <div className={styles['courselinkform__result-message']}>{t.cataloguelinks.loading}</div>\r\n )}\r\n {searchResponse && searchResponse.results.length === 0 && searchResponse.state === 'ready' && (\r\n <div className={styles['courselinkform__result-message']}>{t.cataloguelinks.noResults}</div>\r\n )}\r\n {searchResponse && searchResponse.results.length > 0 && (\r\n <div className={styles['courselinkform__results-wrapper']}>\r\n <div className={styles['courselinkform__results-header']}>\r\n <span>\r\n {\r\n t.cataloguelinks[\r\n linkType === 'course' ? 'resultCourseListCatalogNumber' : 'resultProgrammeListCatalogNumber'\r\n ]\r\n }\r\n </span>\r\n <span>{t.cataloguelinks.resultListName}</span>\r\n </div>\r\n <div className={styles['courselinkform__results']} ref={resultListRef}>\r\n {searchResponse.results.map(({ id, code, name }) => (\r\n <button\r\n key={id}\r\n type=\"button\"\r\n className={styles['courselinkform__result-item']}\r\n onClick={() => onSelect && onSelect(code, name[currentLanguage], linkType)}\r\n onKeyDown={(event) => onResultKeyDown(event, code, name[currentLanguage], linkType)}\r\n tabIndex={0}\r\n aria-label={`${code} ${name[currentLanguage]}`}\r\n >\r\n <span>{code}</span>\r\n <span>{name[currentLanguage]}</span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </Repeater>\r\n <div className={styles['courselinkform__footer']}>\r\n <Button variant={'secondary'} onClick={handleClose} aria-label={t.common.cancel} type=\"button\">\r\n {t.common.cancel}\r\n </Button>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CheckboxButtonBar-5UMIFMKH.js","names":[],"sources":["../src/components/CheckboxButtonBar/CheckboxButtonBar.module.css","../src/components/CheckboxButtonBar/CheckboxButtonBar.tsx"],"sourcesContent":[".checkbox-button-bar__container {\n display: flex;\n flex-wrap: wrap;\n}\n\n.checkbox-button-bar__container--label-left {\n align-items: baseline;\n flex-direction: row;\n gap: 1rem;\n}\n\n.checkbox-button-bar__container--label-top {\n align-items: flex-start;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.checkbox-button-bar__row-container {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.checkbox-button-bar__row-container--segmented {\n flex-direction: row;\n}\n\n.checkbox-button-bar__row {\n align-items: center;\n background-color: var(--color-uva-white);\n border: 1px solid var(--color-grey-700);\n border-radius: 0.5rem;\n display: flex;\n flex-wrap: nowrap;\n gap: 0.25rem;\n padding: 0.25rem;\n}\n\n.checkbox-button-bar__row--not-valid {\n border-color: var(--color-red-600);\n}\n\n.checkbox-button-bar__sub-text {\n color: var(--color-grey-700);\n font-size: var(--font-size-text-non-essential);\n}\n","import { useState } from 'react';\nimport { clsx } from 'clsx';\n\nimport type { ReactNode } from 'react';\n\nimport styles from './CheckboxButtonBar.module.css';\n\nimport { Label } from 'components/Label';\nimport { FeedbackBox } from 'components/FeedbackBox';\nimport { ControlsButton } from 'components/ControlsButton';\n\ntype CheckboxProps = {\n label: string | ReactNode;\n value: string;\n prefix?: string;\n tooltip?: ReactNode;\n tooltipPosition?: 'left' | 'center' | 'right';\n disabled?: boolean;\n};\n\nexport interface CheckboxButtonBarProps {\n /** array with objects with label, value, prefix and disabled*/\n checkboxes: CheckboxProps[];\n //** array with value(s) */\n defaultValues?: string[];\n label?: string;\n /** optional sub-label text (only displayed when label is positioned 'top') */\n subLabel?: string;\n /** 'top' | 'left' */\n labelPosition?: 'top' | 'left';\n /** `true` to show an asterisk to indicate an item is required; otherwise, `false`. */\n required?: boolean;\n /** `true` to color border red to show not valid; otherwise, `false`. */\n notValid?: boolean;\n /** error text to display under the bar */\n notValidatedText?: string;\n /** returns an array with only one value */\n actAsRadioButtonBar?: boolean;\n /** optional footer text */\n footerText?: string;\n /** disables all checkboxes in the bar */\n disableGroup?: boolean;\n /** `true` to sepearte each button in their own bordered container */\n segmented?: boolean;\n /** `true` sets forceSquared on all buttons */\n forceSquared?: boolean;\n onSetValues: (value: string[]) => void;\n}\n\nexport const CheckboxButtonBar = ({\n checkboxes,\n defaultValues,\n label,\n subLabel = '',\n labelPosition = 'top',\n required = false,\n notValid = false,\n notValidatedText = '',\n actAsRadioButtonBar = false,\n footerText = '',\n disableGroup = false,\n segmented = false,\n forceSquared = false,\n onSetValues,\n}: CheckboxButtonBarProps) => {\n const [currentValues, setCurrentValues] = useState<string[]>(\n defaultValues && !actAsRadioButtonBar\n ? defaultValues.map(String)\n : defaultValues && actAsRadioButtonBar\n ? defaultValues.slice(0, 1)\n : []\n );\n\n const handleChange = (value: string) => {\n let values = currentValues;\n\n if (actAsRadioButtonBar) {\n setCurrentValues([value]);\n onSetValues([value]);\n } else {\n if (values.includes(value)) {\n values = values.filter((val) => val !== value);\n } else {\n values = [...values, value];\n }\n setCurrentValues(values);\n onSetValues(values);\n }\n };\n\n return (\n <div\n className={clsx(\n styles['checkbox-button-bar__container'],\n styles[`checkbox-button-bar__container--label-${labelPosition}`]\n )}\n >\n {(label || subLabel) && (\n <div>\n {label && (\n <Label htmlFor=\"\" required={required}>\n {label}\n </Label>\n )}\n\n {subLabel && labelPosition === 'top' && (\n <div className={styles['checkbox-button-bar__sub-text']}>{subLabel}</div>\n )}\n </div>\n )}\n\n <div\n className={clsx(styles['checkbox-button-bar__row-container'], {\n [styles['checkbox-button-bar__row-container--segmented']]: segmented,\n })}\n >\n {segmented ? (\n checkboxes.map(({ label, value, prefix, tooltip, tooltipPosition, disabled }) => (\n <div\n key={value}\n className={clsx(styles['checkbox-button-bar__row'], {\n [styles['checkbox-button-bar__row--not-valid']]: notValid || notValidatedText,\n })}\n >\n <ControlsButton\n type={actAsRadioButtonBar ? 'radio' : 'checkbox'}\n label={label}\n prefix={prefix}\n tooltip={tooltip}\n tooltipPosition={tooltipPosition}\n forceSquared={forceSquared}\n value={value}\n checked={currentValues.includes(value)}\n disabled={disabled || disableGroup}\n onSetValue={(event) => handleChange(event.target.value)}\n />\n </div>\n ))\n ) : (\n <div\n className={clsx(styles['checkbox-button-bar__row'], {\n [styles['checkbox-button-bar__row--not-valid']]: notValid || notValidatedText,\n })}\n >\n {checkboxes.map(({ label, value, prefix, tooltip, tooltipPosition, disabled }) => (\n <ControlsButton\n key={value}\n type={actAsRadioButtonBar ? 'radio' : 'checkbox'}\n label={label}\n prefix={prefix}\n tooltip={tooltip}\n tooltipPosition={tooltipPosition}\n forceSquared={forceSquared}\n value={value}\n checked={currentValues.includes(value)}\n disabled={disabled || disableGroup}\n onSetValue={(event) => handleChange(event.target.value)}\n />\n ))}\n </div>\n )}\n </div>\n\n {footerText && <div className={styles['checkbox-button-bar__sub-text']}>{footerText}</div>}\n {notValidatedText !== '' && <FeedbackBox level=\"error\" feedback={notValidatedText} />}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;GCiDa,KAAqB,EAChC,eACA,kBACA,UACA,cAAW,IACX,mBAAgB,OAChB,cAAW,IACX,cAAW,IACX,sBAAmB,IACnB,yBAAsB,IACtB,gBAAa,IACb,kBAAe,IACf,eAAY,IACZ,kBAAe,IACf,qBAC4B;CAC5B,IAAM,CAAC,GAAe,KAAoB,EACxC,KAAiB,CAAC,IACd,EAAc,IAAI,OAAO,GACzB,KAAiB,IACf,EAAc,MAAM,GAAG,EAAE,GACzB,EAAE,CACT,EAEK,KAAgB,MAAkB;EACtC,IAAI,IAAS;AAEb,EAAI,KACF,EAAiB,CAAC,EAAM,CAAC,EACzB,EAAY,CAAC,EAAM,CAAC,KAEpB,AAGE,IAHE,EAAO,SAAS,EAAM,GACf,EAAO,QAAQ,MAAQ,MAAQ,EAAM,GAErC,CAAC,GAAG,GAAQ,EAAM,EAE7B,EAAiB,EAAO,EACxB,EAAY,EAAO;;AAIvB,QACE,kBAAC,OAAD;EACE,WAAW,EACT,EAAO,mCACP,EAAO,yCAAyC,KACjD;YAJH;IAMI,KAAS,MACT,kBAAC,OAAD,EAAA,UAAA,CACG,KACC,kBAAC,GAAD;IAAO,SAAQ;IAAa;cACzB;IACK,CAAA,EAGT,KAAY,MAAkB,SAC7B,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAmC;IAAe,CAAA,CAEvE,EAAA,CAAA;GAGR,kBAAC,OAAD;IACE,WAAW,EAAK,EAAO,uCAAuC,GAC3D,EAAO,mDAAmD,GAC5D,CAAC;cAED,IACC,EAAW,KAAK,EAAE,UAAO,UAAO,WAAQ,YAAS,oBAAiB,kBAChE,kBAAC,OAAD;KAEE,WAAW,EAAK,EAAO,6BAA6B,GACjD,EAAO,yCAAyC,KAAY,GAC9D,CAAC;eAEF,kBAAC,GAAD;MACE,MAAM,IAAsB,UAAU;MAC/B;MACC;MACC;MACQ;MACH;MACP;MACP,SAAS,EAAc,SAAS,EAAM;MACtC,UAAU,KAAY;MACtB,aAAa,MAAU,EAAa,EAAM,OAAO,MAAM;MACvD,CAAA;KACE,EAjBC,EAiBD,CACN,GAEF,kBAAC,OAAD;KACE,WAAW,EAAK,EAAO,6BAA6B,GACjD,EAAO,yCAAyC,KAAY,GAC9D,CAAC;eAED,EAAW,KAAK,EAAE,UAAO,UAAO,WAAQ,YAAS,oBAAiB,kBACjE,kBAAC,GAAD;MAEE,MAAM,IAAsB,UAAU;MAC/B;MACC;MACC;MACQ;MACH;MACP;MACP,SAAS,EAAc,SAAS,EAAM;MACtC,UAAU,KAAY;MACtB,aAAa,MAAU,EAAa,EAAM,OAAO,MAAM;MACvD,EAXK,EAWL,CACF;KACE,CAAA;IAEJ,CAAA;GAEL,KAAc,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAmC;IAAiB,CAAA;GACzF,MAAqB,MAAM,kBAAC,GAAD;IAAa,OAAM;IAAQ,UAAU;IAAoB,CAAA;GACjF"}
1
+ {"version":3,"file":"CheckboxButtonBar-5UMIFMKH.js","names":[],"sources":["../src/components/CheckboxButtonBar/CheckboxButtonBar.module.css","../src/components/CheckboxButtonBar/CheckboxButtonBar.tsx"],"sourcesContent":[".checkbox-button-bar__container {\n display: flex;\n flex-wrap: wrap;\n}\n\n.checkbox-button-bar__container--label-left {\n align-items: baseline;\n flex-direction: row;\n gap: 1rem;\n}\n\n.checkbox-button-bar__container--label-top {\n align-items: flex-start;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.checkbox-button-bar__row-container {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.checkbox-button-bar__row-container--segmented {\n flex-direction: row;\n}\n\n.checkbox-button-bar__row {\n align-items: center;\n background-color: var(--color-uva-white);\n border: 1px solid var(--color-grey-700);\n border-radius: 0.5rem;\n display: flex;\n flex-wrap: nowrap;\n gap: 0.25rem;\n padding: 0.25rem;\n}\n\n.checkbox-button-bar__row--not-valid {\n border-color: var(--color-red-600);\n}\n\n.checkbox-button-bar__sub-text {\n color: var(--color-grey-700);\n font-size: var(--font-size-text-non-essential);\n}\n","import { useState } from 'react';\nimport { clsx } from 'clsx';\n\nimport type { ReactNode } from 'react';\n\nimport styles from './CheckboxButtonBar.module.css';\n\nimport { Label } from 'components/Label';\nimport { FeedbackBox } from 'components/FeedbackBox';\nimport { ControlsButton } from 'components/ControlsButton';\n\ntype CheckboxProps = {\n label: string | ReactNode;\n value: string;\n prefix?: string;\n tooltip?: ReactNode;\n tooltipPosition?: 'left' | 'center' | 'right';\n disabled?: boolean;\n};\n\nexport interface CheckboxButtonBarProps {\n /** array with objects with label, value, prefix and disabled*/\n checkboxes: CheckboxProps[];\n //** array with value(s) */\n defaultValues?: string[];\n label?: string;\n /** optional sub-label text (only displayed when label is positioned 'top') */\n subLabel?: string;\n /** 'top' | 'left' */\n labelPosition?: 'top' | 'left';\n /** `true` to show an asterisk to indicate an item is required; otherwise, `false`. */\n required?: boolean;\n /** `true` to color border red to show not valid; otherwise, `false`. */\n notValid?: boolean;\n /** error text to display under the bar */\n notValidatedText?: string;\n /** returns an array with only one value */\n actAsRadioButtonBar?: boolean;\n /** optional footer text */\n footerText?: string;\n /** disables all checkboxes in the bar */\n disableGroup?: boolean;\n /** `true` to sepearte each button in their own bordered container */\n segmented?: boolean;\n /** `true` sets forceSquared on all buttons */\n forceSquared?: boolean;\n onSetValues: (value: string[]) => void;\n}\n\nexport const CheckboxButtonBar = ({\n checkboxes,\n defaultValues,\n label,\n subLabel = '',\n labelPosition = 'top',\n required = false,\n notValid = false,\n notValidatedText = '',\n actAsRadioButtonBar = false,\n footerText = '',\n disableGroup = false,\n segmented = false,\n forceSquared = false,\n onSetValues,\n}: CheckboxButtonBarProps) => {\n const [currentValues, setCurrentValues] = useState<string[]>(\n defaultValues && !actAsRadioButtonBar\n ? defaultValues.map(String)\n : defaultValues && actAsRadioButtonBar\n ? defaultValues.slice(0, 1)\n : []\n );\n\n const handleChange = (value: string) => {\n let values = currentValues;\n\n if (actAsRadioButtonBar) {\n setCurrentValues([value]);\n onSetValues([value]);\n } else {\n if (values.includes(value)) {\n values = values.filter((val) => val !== value);\n } else {\n values = [...values, value];\n }\n setCurrentValues(values);\n onSetValues(values);\n }\n };\n\n return (\n <div\n className={clsx(\n styles['checkbox-button-bar__container'],\n styles[`checkbox-button-bar__container--label-${labelPosition}`]\n )}\n >\n {(label || subLabel) && (\n <div>\n {label && (\n <Label htmlFor=\"\" required={required}>\n {label}\n </Label>\n )}\n\n {subLabel && labelPosition === 'top' && (\n <div className={styles['checkbox-button-bar__sub-text']}>{subLabel}</div>\n )}\n </div>\n )}\n\n <div\n className={clsx(styles['checkbox-button-bar__row-container'], {\n [styles['checkbox-button-bar__row-container--segmented']]: segmented,\n })}\n >\n {segmented ? (\n checkboxes.map(({ label, value, prefix, tooltip, tooltipPosition, disabled }) => (\n <div\n key={value}\n className={clsx(styles['checkbox-button-bar__row'], {\n [styles['checkbox-button-bar__row--not-valid']]: notValid || notValidatedText,\n })}\n >\n <ControlsButton\n type={actAsRadioButtonBar ? 'radio' : 'checkbox'}\n label={label}\n prefix={prefix}\n tooltip={tooltip}\n tooltipPosition={tooltipPosition}\n forceSquared={forceSquared}\n value={value}\n checked={currentValues.includes(value)}\n disabled={disabled || disableGroup}\n onSetValue={(event) => handleChange(event.target.value)}\n />\n </div>\n ))\n ) : (\n <div\n className={clsx(styles['checkbox-button-bar__row'], {\n [styles['checkbox-button-bar__row--not-valid']]: notValid || notValidatedText,\n })}\n >\n {checkboxes.map(({ label, value, prefix, tooltip, tooltipPosition, disabled }) => (\n <ControlsButton\n key={value}\n type={actAsRadioButtonBar ? 'radio' : 'checkbox'}\n label={label}\n prefix={prefix}\n tooltip={tooltip}\n tooltipPosition={tooltipPosition}\n forceSquared={forceSquared}\n value={value}\n checked={currentValues.includes(value)}\n disabled={disabled || disableGroup}\n onSetValue={(event) => handleChange(event.target.value)}\n />\n ))}\n </div>\n )}\n </div>\n\n {footerText && <div className={styles['checkbox-button-bar__sub-text']}>{footerText}</div>}\n {notValidatedText !== '' && <FeedbackBox level=\"error\" feedback={notValidatedText} />}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;GCiDa,KAAqB,EAChC,eACA,kBACA,UACA,cAAW,IACX,mBAAgB,OAChB,cAAW,IACX,cAAW,IACX,sBAAmB,IACnB,yBAAsB,IACtB,gBAAa,IACb,kBAAe,IACf,eAAY,IACZ,kBAAe,IACf,qBAC4B;CAC5B,IAAM,CAAC,GAAe,KAAoB,EACxC,KAAiB,CAAC,IACd,EAAc,IAAI,OAAO,GACzB,KAAiB,IACf,EAAc,MAAM,GAAG,EAAE,GACzB,EAAE,CACT,EAEK,KAAgB,MAAkB;EACtC,IAAI,IAAS;EAEb,AAAI,KACF,EAAiB,CAAC,EAAM,CAAC,EACzB,EAAY,CAAC,EAAM,CAAC,KAEpB,AAGE,IAHE,EAAO,SAAS,EAAM,GACf,EAAO,QAAQ,MAAQ,MAAQ,EAAM,GAErC,CAAC,GAAG,GAAQ,EAAM,EAE7B,EAAiB,EAAO,EACxB,EAAY,EAAO;;CAIvB,OACE,kBAAC,OAAD;EACE,WAAW,EACT,EAAO,mCACP,EAAO,yCAAyC,KACjD;YAJH;IAMI,KAAS,MACT,kBAAC,OAAD,EAAA,UAAA,CACG,KACC,kBAAC,GAAD;IAAO,SAAQ;IAAa;cACzB;IACK,CAAA,EAGT,KAAY,MAAkB,SAC7B,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAmC;IAAe,CAAA,CAEvE,EAAA,CAAA;GAGR,kBAAC,OAAD;IACE,WAAW,EAAK,EAAO,uCAAuC,GAC3D,EAAO,mDAAmD,GAC5D,CAAC;cAED,IACC,EAAW,KAAK,EAAE,UAAO,UAAO,WAAQ,YAAS,oBAAiB,kBAChE,kBAAC,OAAD;KAEE,WAAW,EAAK,EAAO,6BAA6B,GACjD,EAAO,yCAAyC,KAAY,GAC9D,CAAC;eAEF,kBAAC,GAAD;MACE,MAAM,IAAsB,UAAU;MAC/B;MACC;MACC;MACQ;MACH;MACP;MACP,SAAS,EAAc,SAAS,EAAM;MACtC,UAAU,KAAY;MACtB,aAAa,MAAU,EAAa,EAAM,OAAO,MAAM;MACvD,CAAA;KACE,EAjBC,EAiBD,CACN,GAEF,kBAAC,OAAD;KACE,WAAW,EAAK,EAAO,6BAA6B,GACjD,EAAO,yCAAyC,KAAY,GAC9D,CAAC;eAED,EAAW,KAAK,EAAE,UAAO,UAAO,WAAQ,YAAS,oBAAiB,kBACjE,kBAAC,GAAD;MAEE,MAAM,IAAsB,UAAU;MAC/B;MACC;MACC;MACQ;MACH;MACP;MACP,SAAS,EAAc,SAAS,EAAM;MACtC,UAAU,KAAY;MACtB,aAAa,MAAU,EAAa,EAAM,OAAO,MAAM;MACvD,EAXK,EAWL,CACF;KACE,CAAA;IAEJ,CAAA;GAEL,KAAc,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAmC;IAAiB,CAAA;GACzF,MAAqB,MAAM,kBAAC,GAAD;IAAa,OAAM;IAAQ,UAAU;IAAoB,CAAA;GACjF"}
@@ -1 +1 @@
1
- {"version":3,"file":"ClipboardButton-geHjMl2J.js","names":[],"sources":["../src/storyComponents/ClipboardButton/ClipboardButton.module.css","../src/storyComponents/ClipboardButton/ClipboardButton.tsx"],"sourcesContent":[".clipboard-button {\n align-items: center;\n appearance: none;\n background-color: transparent;\n border: none;\n color: #000;\n cursor: pointer;\n display: inline-flex;\n font-size: 0.875rem;\n font-weight: 500;\n height: 1.5rem;\n justify-content: center;\n outline: none;\n transition: all 0.15s;\n width: 1.5rem;\n}\n\n.clipboard-button:focus-visible {\n box-shadow: 0 0 0 0.125rem #000;\n outline: 2px solid #000;\n}\n\n.clipboard-button:hover {\n color: #bd0032;\n}\n\n.clipboard-button:disabled {\n opacity: 0.5;\n pointer-events: none;\n}\n","import { useState } from 'react';\n\nimport styles from './ClipboardButton.module.css';\n\ninterface ClipboardButtonProps {\n text: string;\n}\n\nconst DELAY = 2000;\n\nexport const ClipboardButton = ({ text }: ClipboardButtonProps) => {\n const [isCopied, setIsCopied] = useState(false);\n\n const handleCopyClick = () => {\n if (!isCopied) {\n void navigator.clipboard.writeText(text).then(() => {\n setIsCopied(true);\n setTimeout(() => {\n setIsCopied(false);\n }, DELAY);\n });\n }\n };\n\n return (\n <div style={{ position: 'relative' }}>\n <button onClick={handleCopyClick} className={styles['clipboard-button']} aria-label={`Copy ${text}`}>\n <svg\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 15 15\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3 w-3\"\n >\n {isCopied ? (\n <path\n d=\"M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n ) : (\n <path\n d=\"M1 9.50006C1 10.3285 1.67157 11.0001 2.5 11.0001H4L4 10.0001H2.5C2.22386 10.0001 2 9.7762 2 9.50006L2 2.50006C2 2.22392 2.22386 2.00006 2.5 2.00006L9.5 2.00006C9.77614 2.00006 10 2.22392 10 2.50006V4.00002H5.5C4.67158 4.00002 4 4.67159 4 5.50002V12.5C4 13.3284 4.67158 14 5.5 14H12.5C13.3284 14 14 13.3284 14 12.5V5.50002C14 4.67159 13.3284 4.00002 12.5 4.00002H11V2.50006C11 1.67163 10.3284 1.00006 9.5 1.00006H2.5C1.67157 1.00006 1 1.67163 1 2.50006V9.50006ZM5 5.50002C5 5.22388 5.22386 5.00002 5.5 5.00002H12.5C12.7761 5.00002 13 5.22388 13 5.50002V12.5C13 12.7762 12.7761 13 12.5 13H5.5C5.22386 13 5 12.7762 5 12.5V5.50002Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n )}\n </svg>\n </button>\n </div>\n );\n};\n"],"mappings":";;;6DCQM,IAAQ,KAED,KAAmB,EAAE,cAAiC;CACjE,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM;AAa/C,QACE,kBAAC,OAAD;EAAK,OAAO,EAAE,UAAU,YAAY;YAClC,kBAAC,UAAD;GAAQ,eAbkB;AAC5B,IAAK,KACE,UAAU,UAAU,UAAU,EAAK,CAAC,WAAW;AAElD,KADA,EAAY,GAAK,EACjB,iBAAiB;AACf,QAAY,GAAM;QACjB,EAAM;MACT;;GAMgC,WAAW,EAAO;GAAqB,cAAY,QAAQ;aAC3F,kBAAC,OAAD;IACE,OAAM;IACN,QAAO;IACP,SAAQ;IACR,MAAK;IACL,OAAM;IACN,WAAU;cAET,IACC,kBAAC,QAAD;KACE,GAAE;KACF,MAAK;KACL,UAAS;KACT,UAAS;KACT,CAAA,GAEF,kBAAC,QAAD;KACE,GAAE;KACF,MAAK;KACL,UAAS;KACT,UAAS;KACT,CAAA;IAEA,CAAA;GACC,CAAA;EACL,CAAA"}
1
+ {"version":3,"file":"ClipboardButton-geHjMl2J.js","names":[],"sources":["../src/storyComponents/ClipboardButton/ClipboardButton.module.css","../src/storyComponents/ClipboardButton/ClipboardButton.tsx"],"sourcesContent":[".clipboard-button {\n align-items: center;\n appearance: none;\n background-color: transparent;\n border: none;\n color: #000;\n cursor: pointer;\n display: inline-flex;\n font-size: 0.875rem;\n font-weight: 500;\n height: 1.5rem;\n justify-content: center;\n outline: none;\n transition: all 0.15s;\n width: 1.5rem;\n}\n\n.clipboard-button:focus-visible {\n box-shadow: 0 0 0 0.125rem #000;\n outline: 2px solid #000;\n}\n\n.clipboard-button:hover {\n color: #bd0032;\n}\n\n.clipboard-button:disabled {\n opacity: 0.5;\n pointer-events: none;\n}\n","import { useState } from 'react';\n\nimport styles from './ClipboardButton.module.css';\n\ninterface ClipboardButtonProps {\n text: string;\n}\n\nconst DELAY = 2000;\n\nexport const ClipboardButton = ({ text }: ClipboardButtonProps) => {\n const [isCopied, setIsCopied] = useState(false);\n\n const handleCopyClick = () => {\n if (!isCopied) {\n void navigator.clipboard.writeText(text).then(() => {\n setIsCopied(true);\n setTimeout(() => {\n setIsCopied(false);\n }, DELAY);\n });\n }\n };\n\n return (\n <div style={{ position: 'relative' }}>\n <button onClick={handleCopyClick} className={styles['clipboard-button']} aria-label={`Copy ${text}`}>\n <svg\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 15 15\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-3 w-3\"\n >\n {isCopied ? (\n <path\n d=\"M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n ) : (\n <path\n d=\"M1 9.50006C1 10.3285 1.67157 11.0001 2.5 11.0001H4L4 10.0001H2.5C2.22386 10.0001 2 9.7762 2 9.50006L2 2.50006C2 2.22392 2.22386 2.00006 2.5 2.00006L9.5 2.00006C9.77614 2.00006 10 2.22392 10 2.50006V4.00002H5.5C4.67158 4.00002 4 4.67159 4 5.50002V12.5C4 13.3284 4.67158 14 5.5 14H12.5C13.3284 14 14 13.3284 14 12.5V5.50002C14 4.67159 13.3284 4.00002 12.5 4.00002H11V2.50006C11 1.67163 10.3284 1.00006 9.5 1.00006H2.5C1.67157 1.00006 1 1.67163 1 2.50006V9.50006ZM5 5.50002C5 5.22388 5.22386 5.00002 5.5 5.00002H12.5C12.7761 5.00002 13 5.22388 13 5.50002V12.5C13 12.7762 12.7761 13 12.5 13H5.5C5.22386 13 5 12.7762 5 12.5V5.50002Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n )}\n </svg>\n </button>\n </div>\n );\n};\n"],"mappings":";;;6DCQM,IAAQ,KAED,KAAmB,EAAE,cAAiC;CACjE,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM;CAa/C,OACE,kBAAC,OAAD;EAAK,OAAO,EAAE,UAAU,YAAY;YAClC,kBAAC,UAAD;GAAQ,eAbkB;IAC5B,AAAK,KACH,UAAe,UAAU,UAAU,EAAK,CAAC,WAAW;KAElD,AADA,EAAY,GAAK,EACjB,iBAAiB;MACf,EAAY,GAAM;QACjB,EAAM;MACT;;GAMgC,WAAW,EAAO;GAAqB,cAAY,QAAQ;aAC3F,kBAAC,OAAD;IACE,OAAM;IACN,QAAO;IACP,SAAQ;IACR,MAAK;IACL,OAAM;IACN,WAAU;cAET,IACC,kBAAC,QAAD;KACE,GAAE;KACF,MAAK;KACL,UAAS;KACT,UAAS;KACT,CAAA,GAEF,kBAAC,QAAD;KACE,GAAE;KACF,MAAK;KACL,UAAS;KACT,UAAS;KACT,CAAA;IAEA,CAAA;GACC,CAAA;EACL,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ControlsButton-B1XRpMUM.js","names":[],"sources":["../src/components/ControlsButton/ControlsButton.module.css","../src/components/ControlsButton/ControlsButton.tsx"],"sourcesContent":[".controls-input {\n aspect-ratio: unset;\n cursor: pointer;\n height: 0;\n opacity: 0;\n position: absolute;\n width: 0;\n}\n\n.controls-input:focus-visible + label {\n outline: 0.125rem dotted var(--color-navy-600);\n outline-offset: 0.125rem;\n}\n\n.controls-input:checked + label,\n[type=\"radio\"]:checked:hover + label {\n background-color: var(--color-navy-600);\n color: var(--color-uva-white);\n font-weight: var(--semibold);\n}\n\n.controls-input:disabled + label,\n.controls-input:disabled:hover + label {\n background-color: var(--color-grey-400);\n color: var(--color-grey-700);\n cursor: not-allowed;\n}\n\n.controls-input:disabled:checked + label {\n background-color: var(--color-grey-500);\n color: var(--color-grey-900);\n font-weight: var(--semibold);\n}\n\n.controls-input:hover + label {\n background-color: var(--color-grey-300);\n color: var(--color-uva-black);\n}\n\n.controls-button {\n align-items: center;\n background-color: var(--color-uva-white);\n border: 1px solid transparent;\n border-radius: 0.25rem;\n box-sizing: border-box;\n cursor: pointer;\n display: inline-flex;\n font-size: var(--font-size-default);\n height: 2.25rem;\n justify-content: center;\n min-width: 2.25rem;\n padding: 0.5rem;\n position: relative;\n user-select: none;\n white-space: nowrap;\n}\n\n.controls-button--squared {\n width: 2.25rem;\n}\n\n.controls-button::after {\n content: \"\";\n min-height: 2.625rem;\n min-width: 2.625rem;\n position: absolute;\n width: 100%;\n}\n\n.controls-button--with-prefix {\n height: auto;\n padding: 0.125rem 0.5rem;\n width: auto;\n}\n\n.controls-button--with-icon {\n gap: 0.5rem;\n}\n\n.controls-button__wrapper {\n align-items: center;\n display: flex;\n flex-direction: column;\n}\n\n.controls-button__prefix {\n color: var(--color-uva-700);\n font-size: var(--font-size-text-non-essential);\n}\n\n.controls-button__tooltip {\n background-color: var(--color-uva-white);\n box-shadow: 0 0 0.25rem 0 rgba(0 0 0 / 25%);\n color: var(--color-grey-700);\n display: none;\n font-size: var(--font-size-text-non-essential);\n font-style: italic;\n font-weight: normal;\n padding: 0.5rem 1rem;\n position: absolute;\n text-align: center;\n top: calc(100% + 0.5rem);\n z-index: 1;\n}\n\n.controls-button__tooltip--left {\n left: 0rem;\n}\n\n.controls-button__tooltip--center {\n left: 50%;\n transform: translateX(-50%);\n}\n\n.controls-button__tooltip--right {\n right: 0rem;\n}\n\n.controls-button__tooltip::before {\n border-color: transparent transparent var(--color-grey-400) transparent;\n border-style: solid;\n border-width: 0.5rem;\n bottom: calc(100% + 0.125rem);\n content: \"\";\n filter: blur(0.125rem);\n position: absolute;\n z-index: -1;\n}\n\n.controls-button__tooltip::after {\n border-color: transparent transparent var(--color-uva-white) transparent;\n border-style: solid;\n border-width: 0.5rem;\n bottom: 100%;\n content: \"\";\n position: absolute;\n}\n\n.controls-button:hover .controls-button__tooltip,\n.controls-input:focus-visible + label .controls-button__tooltip {\n display: block;\n}\n\n.controls-button__tooltip--left::before,\n.controls-button__tooltip--left::after {\n left: 0.5rem;\n}\n\n.controls-button__tooltip--center::before,\n.controls-button__tooltip--center::after {\n left: 50%;\n transform: translateX(-50%);\n}\n\n.controls-button__tooltip--right::before,\n.controls-button__tooltip--right::after {\n right: 0.5rem;\n}\n\n.controls-button--checked span.periods__item,\n.controls-button--checked [data-period-item] {\n border: 1px solid var(--color-uva-white) !important;\n}\n","import { useId } from 'react';\r\nimport { clsx } from 'clsx';\r\n\r\nimport type { ChangeEvent, ReactNode } from 'react';\r\nimport type { IconProps } from 'components/Icon';\r\n\r\nimport styles from './ControlsButton.module.css';\r\n\r\nimport { Icon } from 'components/Icon';\r\n\r\nexport interface ControlsButtonProps {\r\n /** to set type/behaviour of input radio or checkbox */\r\n type?: 'radio' | 'checkbox';\r\n /** button label */\r\n label: string | ReactNode;\r\n /** button value */\r\n value: string;\r\n /** set if icon is needed in font of label */\r\n iconName?: IconProps['name'];\r\n /** set if prefix is needed above of label */\r\n prefix?: string;\r\n /** set tooltip */\r\n tooltip?: ReactNode;\r\n /** set horizontal position of the tooltip */\r\n tooltipPosition?: 'left' | 'center' | 'right';\r\n /** set if used as radiogroup */\r\n name?: string;\r\n /** `true` to set squared button; otherwise, `false`. The default is `false`. Note: hides icon */\r\n forceSquared?: boolean;\r\n /** to set default status */\r\n checked?: boolean;\r\n /** `true` to disable the button; otherwise, `false`. The default is `false`. */\r\n disabled?: boolean;\r\n /** The callback function that is invoked when the radio button changes value. */\r\n onSetValue: (event: ChangeEvent<HTMLInputElement>) => void;\r\n}\r\n\r\nexport const ControlsButton = ({\r\n type = 'checkbox',\r\n label,\r\n value,\r\n iconName,\r\n prefix,\r\n tooltip,\r\n tooltipPosition = 'center',\r\n name,\r\n forceSquared = false,\r\n checked,\r\n disabled,\r\n onSetValue,\r\n}: ControlsButtonProps) => {\r\n const idPrefix = useId();\r\n const labelString = typeof label === 'string' ? label : value;\r\n const sanitizedLabel = labelString.replace(/\\s+/g, '_');\r\n const baseId = `${idPrefix}${sanitizedLabel}`;\r\n const tooltipId = `${baseId}-tooltip`;\r\n\r\n return (\r\n <>\r\n <input\r\n type={type}\r\n id={baseId}\r\n name={name ?? sanitizedLabel}\r\n disabled={disabled}\r\n value={value}\r\n checked={checked}\r\n onChange={onSetValue}\r\n className={styles['controls-input']}\r\n aria-describedby={tooltip ? tooltipId : undefined}\r\n />\r\n <label\r\n htmlFor={baseId}\r\n className={clsx(styles['controls-button'], [\r\n forceSquared && styles['controls-button--squared'],\r\n prefix && styles['controls-button--with-prefix'],\r\n iconName && styles['controls-button--with-icon'],\r\n checked && styles['controls-button--checked'],\r\n ])}\r\n >\r\n {iconName && <Icon name={iconName} size={20} />}\r\n <div className={styles['controls-button__wrapper']}>\r\n {prefix && <div className={styles['controls-button__prefix']}>{prefix}</div>}\r\n {label}\r\n </div>\r\n {tooltip && (\r\n <div\r\n id={tooltipId}\r\n role=\"tooltip\"\r\n className={clsx(styles['controls-button__tooltip'], styles[`controls-button__tooltip--${tooltipPosition}`])}\r\n >\r\n {tooltip}\r\n </div>\r\n )}\r\n </label>\r\n </>\r\n );\r\n};\r\n"],"mappings":";;;;;;;;;;;;;;;;;;GCqCa,KAAkB,EAC7B,UAAO,YACP,UACA,UACA,aACA,WACA,YACA,qBAAkB,UAClB,SACA,kBAAe,IACf,YACA,aACA,oBACyB;CACzB,IAAM,IAAW,GAAO,EAElB,KADc,OAAO,KAAU,WAAW,IAAQ,GACrB,QAAQ,QAAQ,IAAI,EACjD,IAAS,GAAG,IAAW,KACvB,IAAY,GAAG,EAAO;AAE5B,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,SAAD;EACQ;EACN,IAAI;EACJ,MAAM,KAAQ;EACJ;EACH;EACE;EACT,UAAU;EACV,WAAW,EAAO;EAClB,oBAAkB,IAAU,IAAY,KAAA;EACxC,CAAA,EACF,kBAAC,SAAD;EACE,SAAS;EACT,WAAW,EAAK,EAAO,oBAAoB;GACzC,KAAgB,EAAO;GACvB,KAAU,EAAO;GACjB,KAAY,EAAO;GACnB,KAAW,EAAO;GACnB,CAAC;YAPJ;GASG,KAAY,kBAAC,GAAD;IAAM,MAAM;IAAU,MAAM;IAAM,CAAA;GAC/C,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACG,KAAU,kBAAC,OAAD;KAAK,WAAW,EAAO;eAA6B;KAAa,CAAA,EAC3E,EACG;;GACL,KACC,kBAAC,OAAD;IACE,IAAI;IACJ,MAAK;IACL,WAAW,EAAK,EAAO,6BAA6B,EAAO,6BAA6B,KAAmB;cAE1G;IACG,CAAA;GAEF;IACP,EAAA,CAAA"}
1
+ {"version":3,"file":"ControlsButton-B1XRpMUM.js","names":[],"sources":["../src/components/ControlsButton/ControlsButton.module.css","../src/components/ControlsButton/ControlsButton.tsx"],"sourcesContent":[".controls-input {\n aspect-ratio: unset;\n cursor: pointer;\n height: 0;\n opacity: 0;\n position: absolute;\n width: 0;\n}\n\n.controls-input:focus-visible + label {\n outline: 0.125rem dotted var(--color-navy-600);\n outline-offset: 0.125rem;\n}\n\n.controls-input:checked + label,\n[type=\"radio\"]:checked:hover + label {\n background-color: var(--color-navy-600);\n color: var(--color-uva-white);\n font-weight: var(--semibold);\n}\n\n.controls-input:disabled + label,\n.controls-input:disabled:hover + label {\n background-color: var(--color-grey-400);\n color: var(--color-grey-700);\n cursor: not-allowed;\n}\n\n.controls-input:disabled:checked + label {\n background-color: var(--color-grey-500);\n color: var(--color-grey-900);\n font-weight: var(--semibold);\n}\n\n.controls-input:hover + label {\n background-color: var(--color-grey-300);\n color: var(--color-uva-black);\n}\n\n.controls-button {\n align-items: center;\n background-color: var(--color-uva-white);\n border: 1px solid transparent;\n border-radius: 0.25rem;\n box-sizing: border-box;\n cursor: pointer;\n display: inline-flex;\n font-size: var(--font-size-default);\n height: 2.25rem;\n justify-content: center;\n min-width: 2.25rem;\n padding: 0.5rem;\n position: relative;\n user-select: none;\n white-space: nowrap;\n}\n\n.controls-button--squared {\n width: 2.25rem;\n}\n\n.controls-button::after {\n content: \"\";\n min-height: 2.625rem;\n min-width: 2.625rem;\n position: absolute;\n width: 100%;\n}\n\n.controls-button--with-prefix {\n height: auto;\n padding: 0.125rem 0.5rem;\n width: auto;\n}\n\n.controls-button--with-icon {\n gap: 0.5rem;\n}\n\n.controls-button__wrapper {\n align-items: center;\n display: flex;\n flex-direction: column;\n}\n\n.controls-button__prefix {\n color: var(--color-uva-700);\n font-size: var(--font-size-text-non-essential);\n}\n\n.controls-button__tooltip {\n background-color: var(--color-uva-white);\n box-shadow: 0 0 0.25rem 0 rgba(0 0 0 / 25%);\n color: var(--color-grey-700);\n display: none;\n font-size: var(--font-size-text-non-essential);\n font-style: italic;\n font-weight: normal;\n padding: 0.5rem 1rem;\n position: absolute;\n text-align: center;\n top: calc(100% + 0.5rem);\n z-index: 1;\n}\n\n.controls-button__tooltip--left {\n left: 0rem;\n}\n\n.controls-button__tooltip--center {\n left: 50%;\n transform: translateX(-50%);\n}\n\n.controls-button__tooltip--right {\n right: 0rem;\n}\n\n.controls-button__tooltip::before {\n border-color: transparent transparent var(--color-grey-400) transparent;\n border-style: solid;\n border-width: 0.5rem;\n bottom: calc(100% + 0.125rem);\n content: \"\";\n filter: blur(0.125rem);\n position: absolute;\n z-index: -1;\n}\n\n.controls-button__tooltip::after {\n border-color: transparent transparent var(--color-uva-white) transparent;\n border-style: solid;\n border-width: 0.5rem;\n bottom: 100%;\n content: \"\";\n position: absolute;\n}\n\n.controls-button:hover .controls-button__tooltip,\n.controls-input:focus-visible + label .controls-button__tooltip {\n display: block;\n}\n\n.controls-button__tooltip--left::before,\n.controls-button__tooltip--left::after {\n left: 0.5rem;\n}\n\n.controls-button__tooltip--center::before,\n.controls-button__tooltip--center::after {\n left: 50%;\n transform: translateX(-50%);\n}\n\n.controls-button__tooltip--right::before,\n.controls-button__tooltip--right::after {\n right: 0.5rem;\n}\n\n.controls-button--checked span.periods__item,\n.controls-button--checked [data-period-item] {\n border: 1px solid var(--color-uva-white) !important;\n}\n","import { useId } from 'react';\r\nimport { clsx } from 'clsx';\r\n\r\nimport type { ChangeEvent, ReactNode } from 'react';\r\nimport type { IconProps } from 'components/Icon';\r\n\r\nimport styles from './ControlsButton.module.css';\r\n\r\nimport { Icon } from 'components/Icon';\r\n\r\nexport interface ControlsButtonProps {\r\n /** to set type/behaviour of input radio or checkbox */\r\n type?: 'radio' | 'checkbox';\r\n /** button label */\r\n label: string | ReactNode;\r\n /** button value */\r\n value: string;\r\n /** set if icon is needed in font of label */\r\n iconName?: IconProps['name'];\r\n /** set if prefix is needed above of label */\r\n prefix?: string;\r\n /** set tooltip */\r\n tooltip?: ReactNode;\r\n /** set horizontal position of the tooltip */\r\n tooltipPosition?: 'left' | 'center' | 'right';\r\n /** set if used as radiogroup */\r\n name?: string;\r\n /** `true` to set squared button; otherwise, `false`. The default is `false`. Note: hides icon */\r\n forceSquared?: boolean;\r\n /** to set default status */\r\n checked?: boolean;\r\n /** `true` to disable the button; otherwise, `false`. The default is `false`. */\r\n disabled?: boolean;\r\n /** The callback function that is invoked when the radio button changes value. */\r\n onSetValue: (event: ChangeEvent<HTMLInputElement>) => void;\r\n}\r\n\r\nexport const ControlsButton = ({\r\n type = 'checkbox',\r\n label,\r\n value,\r\n iconName,\r\n prefix,\r\n tooltip,\r\n tooltipPosition = 'center',\r\n name,\r\n forceSquared = false,\r\n checked,\r\n disabled,\r\n onSetValue,\r\n}: ControlsButtonProps) => {\r\n const idPrefix = useId();\r\n const labelString = typeof label === 'string' ? label : value;\r\n const sanitizedLabel = labelString.replace(/\\s+/g, '_');\r\n const baseId = `${idPrefix}${sanitizedLabel}`;\r\n const tooltipId = `${baseId}-tooltip`;\r\n\r\n return (\r\n <>\r\n <input\r\n type={type}\r\n id={baseId}\r\n name={name ?? sanitizedLabel}\r\n disabled={disabled}\r\n value={value}\r\n checked={checked}\r\n onChange={onSetValue}\r\n className={styles['controls-input']}\r\n aria-describedby={tooltip ? tooltipId : undefined}\r\n />\r\n <label\r\n htmlFor={baseId}\r\n className={clsx(styles['controls-button'], [\r\n forceSquared && styles['controls-button--squared'],\r\n prefix && styles['controls-button--with-prefix'],\r\n iconName && styles['controls-button--with-icon'],\r\n checked && styles['controls-button--checked'],\r\n ])}\r\n >\r\n {iconName && <Icon name={iconName} size={20} />}\r\n <div className={styles['controls-button__wrapper']}>\r\n {prefix && <div className={styles['controls-button__prefix']}>{prefix}</div>}\r\n {label}\r\n </div>\r\n {tooltip && (\r\n <div\r\n id={tooltipId}\r\n role=\"tooltip\"\r\n className={clsx(styles['controls-button__tooltip'], styles[`controls-button__tooltip--${tooltipPosition}`])}\r\n >\r\n {tooltip}\r\n </div>\r\n )}\r\n </label>\r\n </>\r\n );\r\n};\r\n"],"mappings":";;;;;;;;;;;;;;;;;;GCqCa,KAAkB,EAC7B,UAAO,YACP,UACA,UACA,aACA,WACA,YACA,qBAAkB,UAClB,SACA,kBAAe,IACf,YACA,aACA,oBACyB;CACzB,IAAM,IAAW,GAAO,EAElB,KADc,OAAO,KAAU,WAAW,IAAQ,GACrB,QAAQ,QAAQ,IAAI,EACjD,IAAS,GAAG,IAAW,KACvB,IAAY,GAAG,EAAO;CAE5B,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,SAAD;EACQ;EACN,IAAI;EACJ,MAAM,KAAQ;EACJ;EACH;EACE;EACT,UAAU;EACV,WAAW,EAAO;EAClB,oBAAkB,IAAU,IAAY,KAAA;EACxC,CAAA,EACF,kBAAC,SAAD;EACE,SAAS;EACT,WAAW,EAAK,EAAO,oBAAoB;GACzC,KAAgB,EAAO;GACvB,KAAU,EAAO;GACjB,KAAY,EAAO;GACnB,KAAW,EAAO;GACnB,CAAC;YAPJ;GASG,KAAY,kBAAC,GAAD;IAAM,MAAM;IAAU,MAAM;IAAM,CAAA;GAC/C,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACG,KAAU,kBAAC,OAAD;KAAK,WAAW,EAAO;eAA6B;KAAa,CAAA,EAC3E,EACG;;GACL,KACC,kBAAC,OAAD;IACE,IAAI;IACJ,MAAK;IACL,WAAW,EAAK,EAAO,6BAA6B,EAAO,6BAA6B,KAAmB;cAE1G;IACG,CAAA;GAEF;IACP,EAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"CopyableText-DkyhZ6wk.js","names":[],"sources":["../src/components/CopyableText/CopyableText.module.css","../src/components/CopyableText/CopyableText.tsx"],"sourcesContent":[".copyable-text-container {\n cursor: pointer;\n display: flex;\n position: relative;\n width: fit-content;\n}\n\n.copyable-text-copy-button {\n align-items: center;\n background-color: var(--color-grey-300);\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n display: flex;\n font-family: inherit;\n font-size: inherit;\n font-weight: inherit;\n gap: 0.25rem;\n inset: calc(-0.25rem + 1px) auto auto -0.5rem;\n justify-content: center;\n padding: 0.25rem 0.5rem;\n position: absolute;\n transition: opacity 150ms ease;\n white-space: nowrap;\n z-index: 10;\n}\n\n.copyable-text-container:focus-within {\n outline: none;\n}\n\n.copyable-text-copy-visually-hidden {\n border-width: 0;\n clip: rect(0, 0, 0, 0);\n height: 1px;\n margin: -1px;\n overflow: hidden;\n padding: 0;\n position: absolute;\n white-space: nowrap;\n width: 1px;\n}\n","import { clsx } from 'clsx';\r\nimport { useState, useRef, useEffect } from 'react';\r\n\r\nimport type { KeyboardEvent, MouseEvent } from 'react';\r\n\r\nimport styles from './CopyableText.module.css';\r\n\r\nimport { Icon } from 'components/Icon';\r\n\r\nexport interface CopyableTextProps {\r\n /** The text to be copied */\r\n text: string;\r\n /** Additional class name to style the text so it suits the design */\r\n additionalClassName?: string;\r\n /** ARIA label for the copy button */\r\n ariaLabelCopy?: string;\r\n /** ARIA label for the copied state */\r\n ariaLabelHasBeenCopied?: string;\r\n /** custom value to be copied in place of the display text */\r\n customCopyValue?: string;\r\n}\r\n\r\nconst COPYTIME = 2000;\r\n\r\nexport const CopyableText = ({\r\n text,\r\n additionalClassName = '',\r\n ariaLabelCopy,\r\n ariaLabelHasBeenCopied,\r\n customCopyValue,\r\n}: CopyableTextProps) => {\r\n const [isCopying, setIsCopying] = useState(false);\r\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const buttonRef = useRef<HTMLButtonElement | null>(null);\r\n const [buttonActive, setButtonActive] = useState(false);\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n };\r\n }, []);\r\n\r\n const handleCopy = (event: MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLSpanElement>) => {\r\n // prevent event bubbling if placed inside another clikable element\r\n event.stopPropagation();\r\n event.preventDefault();\r\n\r\n setIsCopying(true);\r\n timeoutRef.current = setTimeout(() => {\r\n setIsCopying(false);\r\n setButtonActive(false);\r\n }, COPYTIME);\r\n navigator.clipboard.writeText(customCopyValue ?? text).catch(() => setIsCopying(false));\r\n };\r\n\r\n return (\r\n <span\r\n className={clsx(styles['copyable-text-container'], additionalClassName)}\r\n role=\"button\"\r\n tabIndex={0}\r\n onFocus={() => setButtonActive(true)}\r\n onBlur={() => !isCopying && setButtonActive(false)}\r\n onKeyDown={(event) => {\r\n setButtonActive(true);\r\n if (event.key === 'Enter' || event.key === ' ') {\r\n event.preventDefault();\r\n handleCopy(event);\r\n }\r\n }}\r\n onMouseEnter={() => setButtonActive(true)}\r\n onMouseLeave={() => !isCopying && setButtonActive(false)}\r\n >\r\n {text}\r\n {buttonActive && (\r\n <button\r\n ref={buttonRef}\r\n className={clsx(styles['copyable-text-copy-button'], additionalClassName)}\r\n onClick={handleCopy}\r\n type=\"button\"\r\n aria-keyshortcuts=\"Enter Space\"\r\n aria-label={isCopying ? (ariaLabelHasBeenCopied ?? 'Copied') : (ariaLabelCopy ?? 'Copy to clipboard')}\r\n tabIndex={-1}\r\n >\r\n {text}\r\n <Icon name={isCopying ? 'CheckSmall' : 'Copy'} size={20} />\r\n <span className={styles['copyable-text-copy-visually-hidden']} aria-live=\"polite\">\r\n {isCopying ? (ariaLabelHasBeenCopied ?? 'Copied') : (ariaLabelCopy ?? 'Copy to clipboard')}\r\n </span>\r\n </button>\r\n )}\r\n </span>\r\n );\r\n};\r\n"],"mappings":";;;;;;;;;GCsBM,IAAW,KAEJ,KAAgB,EAC3B,SACA,yBAAsB,IACtB,kBACA,2BACA,yBACuB;CACvB,IAAM,CAAC,GAAW,KAAgB,EAAS,GAAM,EAC3C,IAAa,EAA6C,KAAK,EAC/D,IAAY,EAAiC,KAAK,EAClD,CAAC,GAAc,KAAmB,EAAS,GAAM;AAEvD,eACe;AACX,EAAI,EAAW,WAAS,aAAa,EAAW,QAAQ;IAEzD,EAAE,CAAC;CAEN,IAAM,KAAc,MAA0E;AAU5F,EARA,EAAM,iBAAiB,EACvB,EAAM,gBAAgB,EAEtB,EAAa,GAAK,EAClB,EAAW,UAAU,iBAAiB;AAEpC,GADA,EAAa,GAAM,EACnB,EAAgB,GAAM;KACrB,EAAS,EACZ,UAAU,UAAU,UAAU,KAAmB,EAAK,CAAC,YAAY,EAAa,GAAM,CAAC;;AAGzF,QACE,kBAAC,QAAD;EACE,WAAW,EAAK,EAAO,4BAA4B,EAAoB;EACvE,MAAK;EACL,UAAU;EACV,eAAe,EAAgB,GAAK;EACpC,cAAc,CAAC,KAAa,EAAgB,GAAM;EAClD,YAAY,MAAU;AAEpB,GADA,EAAgB,GAAK,GACjB,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,gBAAgB,EACtB,EAAW,EAAM;;EAGrB,oBAAoB,EAAgB,GAAK;EACzC,oBAAoB,CAAC,KAAa,EAAgB,GAAM;YAd1D,CAgBG,GACA,KACC,kBAAC,UAAD;GACE,KAAK;GACL,WAAW,EAAK,EAAO,8BAA8B,EAAoB;GACzE,SAAS;GACT,MAAK;GACL,qBAAkB;GAClB,cAAY,IAAa,KAA0B,WAAa,KAAiB;GACjF,UAAU;aAPZ;IASG;IACD,kBAAC,GAAD;KAAM,MAAM,IAAY,eAAe;KAAQ,MAAM;KAAM,CAAA;IAC3D,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAuC,aAAU;eACtE,IAAa,KAA0B,WAAa,KAAiB;KACjE,CAAA;IACA;KAEN"}
1
+ {"version":3,"file":"CopyableText-DkyhZ6wk.js","names":[],"sources":["../src/components/CopyableText/CopyableText.module.css","../src/components/CopyableText/CopyableText.tsx"],"sourcesContent":[".copyable-text-container {\n cursor: pointer;\n display: flex;\n position: relative;\n width: fit-content;\n}\n\n.copyable-text-copy-button {\n align-items: center;\n background-color: var(--color-grey-300);\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n display: flex;\n font-family: inherit;\n font-size: inherit;\n font-weight: inherit;\n gap: 0.25rem;\n inset: calc(-0.25rem + 1px) auto auto -0.5rem;\n justify-content: center;\n padding: 0.25rem 0.5rem;\n position: absolute;\n transition: opacity 150ms ease;\n white-space: nowrap;\n z-index: 10;\n}\n\n.copyable-text-container:focus-within {\n outline: none;\n}\n\n.copyable-text-copy-visually-hidden {\n border-width: 0;\n clip: rect(0, 0, 0, 0);\n height: 1px;\n margin: -1px;\n overflow: hidden;\n padding: 0;\n position: absolute;\n white-space: nowrap;\n width: 1px;\n}\n","import { clsx } from 'clsx';\r\nimport { useState, useRef, useEffect } from 'react';\r\n\r\nimport type { KeyboardEvent, MouseEvent } from 'react';\r\n\r\nimport styles from './CopyableText.module.css';\r\n\r\nimport { Icon } from 'components/Icon';\r\n\r\nexport interface CopyableTextProps {\r\n /** The text to be copied */\r\n text: string;\r\n /** Additional class name to style the text so it suits the design */\r\n additionalClassName?: string;\r\n /** ARIA label for the copy button */\r\n ariaLabelCopy?: string;\r\n /** ARIA label for the copied state */\r\n ariaLabelHasBeenCopied?: string;\r\n /** custom value to be copied in place of the display text */\r\n customCopyValue?: string;\r\n}\r\n\r\nconst COPYTIME = 2000;\r\n\r\nexport const CopyableText = ({\r\n text,\r\n additionalClassName = '',\r\n ariaLabelCopy,\r\n ariaLabelHasBeenCopied,\r\n customCopyValue,\r\n}: CopyableTextProps) => {\r\n const [isCopying, setIsCopying] = useState(false);\r\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const buttonRef = useRef<HTMLButtonElement | null>(null);\r\n const [buttonActive, setButtonActive] = useState(false);\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n };\r\n }, []);\r\n\r\n const handleCopy = (event: MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLSpanElement>) => {\r\n // prevent event bubbling if placed inside another clikable element\r\n event.stopPropagation();\r\n event.preventDefault();\r\n\r\n setIsCopying(true);\r\n timeoutRef.current = setTimeout(() => {\r\n setIsCopying(false);\r\n setButtonActive(false);\r\n }, COPYTIME);\r\n navigator.clipboard.writeText(customCopyValue ?? text).catch(() => setIsCopying(false));\r\n };\r\n\r\n return (\r\n <span\r\n className={clsx(styles['copyable-text-container'], additionalClassName)}\r\n role=\"button\"\r\n tabIndex={0}\r\n onFocus={() => setButtonActive(true)}\r\n onBlur={() => !isCopying && setButtonActive(false)}\r\n onKeyDown={(event) => {\r\n setButtonActive(true);\r\n if (event.key === 'Enter' || event.key === ' ') {\r\n event.preventDefault();\r\n handleCopy(event);\r\n }\r\n }}\r\n onMouseEnter={() => setButtonActive(true)}\r\n onMouseLeave={() => !isCopying && setButtonActive(false)}\r\n >\r\n {text}\r\n {buttonActive && (\r\n <button\r\n ref={buttonRef}\r\n className={clsx(styles['copyable-text-copy-button'], additionalClassName)}\r\n onClick={handleCopy}\r\n type=\"button\"\r\n aria-keyshortcuts=\"Enter Space\"\r\n aria-label={isCopying ? (ariaLabelHasBeenCopied ?? 'Copied') : (ariaLabelCopy ?? 'Copy to clipboard')}\r\n tabIndex={-1}\r\n >\r\n {text}\r\n <Icon name={isCopying ? 'CheckSmall' : 'Copy'} size={20} />\r\n <span className={styles['copyable-text-copy-visually-hidden']} aria-live=\"polite\">\r\n {isCopying ? (ariaLabelHasBeenCopied ?? 'Copied') : (ariaLabelCopy ?? 'Copy to clipboard')}\r\n </span>\r\n </button>\r\n )}\r\n </span>\r\n );\r\n};\r\n"],"mappings":";;;;;;;;;GCsBM,IAAW,KAEJ,KAAgB,EAC3B,SACA,yBAAsB,IACtB,kBACA,2BACA,yBACuB;CACvB,IAAM,CAAC,GAAW,KAAgB,EAAS,GAAM,EAC3C,IAAa,EAA6C,KAAK,EAC/D,IAAY,EAAiC,KAAK,EAClD,CAAC,GAAc,KAAmB,EAAS,GAAM;CAEvD,cACe;EACX,AAAI,EAAW,WAAS,aAAa,EAAW,QAAQ;IAEzD,EAAE,CAAC;CAEN,IAAM,KAAc,MAA0E;EAU5F,AARA,EAAM,iBAAiB,EACvB,EAAM,gBAAgB,EAEtB,EAAa,GAAK,EAClB,EAAW,UAAU,iBAAiB;GAEpC,AADA,EAAa,GAAM,EACnB,EAAgB,GAAM;KACrB,EAAS,EACZ,UAAU,UAAU,UAAU,KAAmB,EAAK,CAAC,YAAY,EAAa,GAAM,CAAC;;CAGzF,OACE,kBAAC,QAAD;EACE,WAAW,EAAK,EAAO,4BAA4B,EAAoB;EACvE,MAAK;EACL,UAAU;EACV,eAAe,EAAgB,GAAK;EACpC,cAAc,CAAC,KAAa,EAAgB,GAAM;EAClD,YAAY,MAAU;GAEpB,AADA,EAAgB,GAAK,GACjB,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,gBAAgB,EACtB,EAAW,EAAM;;EAGrB,oBAAoB,EAAgB,GAAK;EACzC,oBAAoB,CAAC,KAAa,EAAgB,GAAM;YAd1D,CAgBG,GACA,KACC,kBAAC,UAAD;GACE,KAAK;GACL,WAAW,EAAK,EAAO,8BAA8B,EAAoB;GACzE,SAAS;GACT,MAAK;GACL,qBAAkB;GAClB,cAAY,IAAa,KAA0B,WAAa,KAAiB;GACjF,UAAU;aAPZ;IASG;IACD,kBAAC,GAAD;KAAM,MAAM,IAAY,eAAe;KAAQ,MAAM;KAAM,CAAA;IAC3D,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAuC,aAAU;eACtE,IAAa,KAA0B,WAAa,KAAiB;KACjE,CAAA;IACA;KAEN"}
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer-e7UFHVg9.js","names":[],"sources":["../src/components/Drawer/Drawer.module.css","../src/components/Drawer/Drawer.tsx"],"sourcesContent":[".drawer {\n background-color: var(--color-uva-white);\n bottom: 0;\n box-shadow: 0 0 0.75rem 0.25rem rgb(0 0 0 / 10%);\n display: flex;\n flex-direction: column;\n left: 10vw;\n max-width: 90vw;\n min-width: 25rem;\n padding: 2.5rem 2rem;\n position: fixed;\n right: 0;\n top: 0;\n transform: translateX(100%);\n transform-origin: right;\n transition-duration: 200ms;\n transition-property: transform;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n width: 100%;\n}\n\n.drawer__content {\n /**\n * Drawer content height cannot exceed the available height, dictated by its parent.\n * Subtracting top and bottom padding from .drawer as well as the height and bottom margin of\n * .drawer__heading from the parent's height gives us the maximum height the content should be.\n */\n max-height: calc(100vh - 7rem);\n overflow-y: auto;\n}\n\n.drawer__header {\n display: flex;\n gap: 2rem;\n justify-content: space-between;\n position: relative;\n}\n\n.drawer__footer {\n gap: 2rem;\n justify-content: flex-end;\n margin-top: auto;\n}\n\n.drawer__heading {\n font-size: var(--font-size-s);\n line-height: var(--line-height-s);\n margin: 0.25rem 0 0.5rem;\n padding-right: 2rem;\n}\n\n@media only screen and (min-width: 40rem) {\n .drawer {\n left: auto;\n max-width: 37.5rem;\n }\n}\n\n.drawer--open {\n transform: translateX(0);\n transition-duration: 250ms;\n}\n\n.drawer__buttons {\n display: flex;\n flex-flow: row wrap;\n gap: 0.75rem;\n justify-content: flex-end;\n margin: 2.5rem 0 0;\n}\n","import { useDialog } from '@react-aria/dialog';\nimport { FocusScope } from '@react-aria/focus';\nimport { OverlayContainer, useModal, useOverlay, usePreventScroll } from '@react-aria/overlays';\nimport { clsx } from 'clsx';\nimport { useEffect, useRef, useState } from 'react';\n\nimport type { HTMLAttributes, PropsWithChildren, ReactNode } from 'react';\n\nimport styles from './Drawer.module.css';\n\nimport { Backdrop } from 'components/Backdrop/Backdrop';\nimport { OverlayCloseButton } from 'components/OverlayCloseButton';\n\nexport interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'className'> {\n /** The buttons to render in the drawer. */\n buttons?: ReactNode;\n /** true if the drawer should be open; otherwise, false. The default is false. */\n isOpen?: boolean;\n /** The callback method that is invoked when the drawer is closed. */\n onClose: () => void;\n /** The title of the drawer. */\n title: string;\n /** The aria-label of the close button. */\n closeButtonAriaValueText?: string;\n}\n\nconst closingDelay = 200;\n\n/** Represents a Drawer component. */\nexport function Drawer({\n buttons,\n children,\n isOpen,\n onClose,\n title,\n closeButtonAriaValueText = 'Close',\n ...restProps\n}: PropsWithChildren<DrawerProps>) {\n const [containerClassNames, setContainerClassNames] = useState(styles.drawer);\n // Hide content outside the modal from screen readers.\n const { modalProps } = useModal({ isDisabled: !isOpen });\n const contentRef = useRef<HTMLDivElement>(null);\n\n function onCloseDrawer() {\n setContainerClassNames(styles.drawer);\n\n globalThis.setTimeout(() => {\n onClose();\n }, closingDelay);\n }\n\n // Handle interacting outside the dialog and pressing\n // the Escape key to close the modal.\n const { overlayProps, underlayProps } = useOverlay(\n { isDismissable: true, isKeyboardDismissDisabled: false, isOpen, onClose: onCloseDrawer },\n contentRef\n );\n\n // Get props for the dialog and its title\n const { dialogProps, titleProps } = useDialog({}, contentRef);\n\n usePreventScroll({ isDisabled: !isOpen });\n\n useEffect(() => {\n // setting class name after render so that element can slide in after it is mounted and slide out\n // before it is unmounted\n setContainerClassNames(clsx(styles.drawer, { [styles['drawer--open']]: isOpen }));\n }, [isOpen]);\n\n return (\n <OverlayContainer>\n <Backdrop {...underlayProps}>\n <FocusScope contain restoreFocus>\n <aside\n {...modalProps}\n {...overlayProps}\n {...dialogProps}\n {...restProps}\n className={containerClassNames}\n ref={contentRef}\n >\n <header className={styles.drawer__header}>\n <h1 className={styles.drawer__heading} {...titleProps}>\n {title}\n </h1>\n\n <OverlayCloseButton aria-label={closeButtonAriaValueText} onClick={onCloseDrawer} />\n </header>\n\n <div className={styles.drawer__content}>{children}</div>\n\n {buttons && (\n <footer className={styles.drawer__footer}>\n <div className={styles.drawer__buttons}>{buttons}</div>\n </footer>\n )}\n </aside>\n </FocusScope>\n </Backdrop>\n </OverlayContainer>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;GC0BM,IAAe;AAGrB,SAAgB,EAAO,EACrB,YACA,aACA,WACA,YACA,UACA,8BAA2B,SAC3B,GAAG,KAC8B;CACjC,IAAM,CAAC,GAAqB,KAA0B,EAAS,EAAO,OAAO,EAEvE,EAAE,kBAAe,EAAS,EAAE,YAAY,CAAC,GAAQ,CAAC,EAClD,IAAa,EAAuB,KAAK;CAE/C,SAAS,IAAgB;AAGvB,EAFA,EAAuB,EAAO,OAAO,EAErC,WAAW,iBAAiB;AAC1B,MAAS;KACR,EAAa;;CAKlB,IAAM,EAAE,iBAAc,qBAAkB,EACtC;EAAE,eAAe;EAAM,2BAA2B;EAAO;EAAQ,SAAS;EAAe,EACzF,EACD,EAGK,EAAE,gBAAa,kBAAe,EAAU,EAAE,EAAE,EAAW;AAU7D,QARA,EAAiB,EAAE,YAAY,CAAC,GAAQ,CAAC,EAEzC,QAAgB;AAGd,IAAuB,EAAK,EAAO,QAAQ,GAAG,EAAO,kBAAkB,GAAQ,CAAC,CAAC;IAChF,CAAC,EAAO,CAAC,EAGV,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EAAU,GAAI;YACZ,kBAAC,GAAD;GAAY,SAAA;GAAQ,cAAA;aAClB,kBAAC,SAAD;IACE,GAAI;IACJ,GAAI;IACJ,GAAI;IACJ,GAAI;IACJ,WAAW;IACX,KAAK;cANP;KAQE,kBAAC,UAAD;MAAQ,WAAW,EAAO;gBAA1B,CACE,kBAAC,MAAD;OAAI,WAAW,EAAO;OAAiB,GAAI;iBACxC;OACE,CAAA,EAEL,kBAAC,GAAD;OAAoB,cAAY;OAA0B,SAAS;OAAiB,CAAA,CAC7E;;KAET,kBAAC,OAAD;MAAK,WAAW,EAAO;MAAkB;MAAe,CAAA;KAEvD,KACC,kBAAC,UAAD;MAAQ,WAAW,EAAO;gBACxB,kBAAC,OAAD;OAAK,WAAW,EAAO;iBAAkB;OAAc,CAAA;MAChD,CAAA;KAEL;;GACG,CAAA;EACJ,CAAA,EACM,CAAA"}
1
+ {"version":3,"file":"Drawer-e7UFHVg9.js","names":[],"sources":["../src/components/Drawer/Drawer.module.css","../src/components/Drawer/Drawer.tsx"],"sourcesContent":[".drawer {\n background-color: var(--color-uva-white);\n bottom: 0;\n box-shadow: 0 0 0.75rem 0.25rem rgb(0 0 0 / 10%);\n display: flex;\n flex-direction: column;\n left: 10vw;\n max-width: 90vw;\n min-width: 25rem;\n padding: 2.5rem 2rem;\n position: fixed;\n right: 0;\n top: 0;\n transform: translateX(100%);\n transform-origin: right;\n transition-duration: 200ms;\n transition-property: transform;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n width: 100%;\n}\n\n.drawer__content {\n /**\n * Drawer content height cannot exceed the available height, dictated by its parent.\n * Subtracting top and bottom padding from .drawer as well as the height and bottom margin of\n * .drawer__heading from the parent's height gives us the maximum height the content should be.\n */\n max-height: calc(100vh - 7rem);\n overflow-y: auto;\n}\n\n.drawer__header {\n display: flex;\n gap: 2rem;\n justify-content: space-between;\n position: relative;\n}\n\n.drawer__footer {\n gap: 2rem;\n justify-content: flex-end;\n margin-top: auto;\n}\n\n.drawer__heading {\n font-size: var(--font-size-s);\n line-height: var(--line-height-s);\n margin: 0.25rem 0 0.5rem;\n padding-right: 2rem;\n}\n\n@media only screen and (min-width: 40rem) {\n .drawer {\n left: auto;\n max-width: 37.5rem;\n }\n}\n\n.drawer--open {\n transform: translateX(0);\n transition-duration: 250ms;\n}\n\n.drawer__buttons {\n display: flex;\n flex-flow: row wrap;\n gap: 0.75rem;\n justify-content: flex-end;\n margin: 2.5rem 0 0;\n}\n","import { useDialog } from '@react-aria/dialog';\nimport { FocusScope } from '@react-aria/focus';\nimport { OverlayContainer, useModal, useOverlay, usePreventScroll } from '@react-aria/overlays';\nimport { clsx } from 'clsx';\nimport { useEffect, useRef, useState } from 'react';\n\nimport type { HTMLAttributes, PropsWithChildren, ReactNode } from 'react';\n\nimport styles from './Drawer.module.css';\n\nimport { Backdrop } from 'components/Backdrop/Backdrop';\nimport { OverlayCloseButton } from 'components/OverlayCloseButton';\n\nexport interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'className'> {\n /** The buttons to render in the drawer. */\n buttons?: ReactNode;\n /** true if the drawer should be open; otherwise, false. The default is false. */\n isOpen?: boolean;\n /** The callback method that is invoked when the drawer is closed. */\n onClose: () => void;\n /** The title of the drawer. */\n title: string;\n /** The aria-label of the close button. */\n closeButtonAriaValueText?: string;\n}\n\nconst closingDelay = 200;\n\n/** Represents a Drawer component. */\nexport function Drawer({\n buttons,\n children,\n isOpen,\n onClose,\n title,\n closeButtonAriaValueText = 'Close',\n ...restProps\n}: PropsWithChildren<DrawerProps>) {\n const [containerClassNames, setContainerClassNames] = useState(styles.drawer);\n // Hide content outside the modal from screen readers.\n const { modalProps } = useModal({ isDisabled: !isOpen });\n const contentRef = useRef<HTMLDivElement>(null);\n\n function onCloseDrawer() {\n setContainerClassNames(styles.drawer);\n\n globalThis.setTimeout(() => {\n onClose();\n }, closingDelay);\n }\n\n // Handle interacting outside the dialog and pressing\n // the Escape key to close the modal.\n const { overlayProps, underlayProps } = useOverlay(\n { isDismissable: true, isKeyboardDismissDisabled: false, isOpen, onClose: onCloseDrawer },\n contentRef\n );\n\n // Get props for the dialog and its title\n const { dialogProps, titleProps } = useDialog({}, contentRef);\n\n usePreventScroll({ isDisabled: !isOpen });\n\n useEffect(() => {\n // setting class name after render so that element can slide in after it is mounted and slide out\n // before it is unmounted\n setContainerClassNames(clsx(styles.drawer, { [styles['drawer--open']]: isOpen }));\n }, [isOpen]);\n\n return (\n <OverlayContainer>\n <Backdrop {...underlayProps}>\n <FocusScope contain restoreFocus>\n <aside\n {...modalProps}\n {...overlayProps}\n {...dialogProps}\n {...restProps}\n className={containerClassNames}\n ref={contentRef}\n >\n <header className={styles.drawer__header}>\n <h1 className={styles.drawer__heading} {...titleProps}>\n {title}\n </h1>\n\n <OverlayCloseButton aria-label={closeButtonAriaValueText} onClick={onCloseDrawer} />\n </header>\n\n <div className={styles.drawer__content}>{children}</div>\n\n {buttons && (\n <footer className={styles.drawer__footer}>\n <div className={styles.drawer__buttons}>{buttons}</div>\n </footer>\n )}\n </aside>\n </FocusScope>\n </Backdrop>\n </OverlayContainer>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;GC0BM,IAAe;AAGrB,SAAgB,EAAO,EACrB,YACA,aACA,WACA,YACA,UACA,8BAA2B,SAC3B,GAAG,KAC8B;CACjC,IAAM,CAAC,GAAqB,KAA0B,EAAS,EAAO,OAAO,EAEvE,EAAE,kBAAe,EAAS,EAAE,YAAY,CAAC,GAAQ,CAAC,EAClD,IAAa,EAAuB,KAAK;CAE/C,SAAS,IAAgB;EAGvB,AAFA,EAAuB,EAAO,OAAO,EAErC,WAAW,iBAAiB;GAC1B,GAAS;KACR,EAAa;;CAKlB,IAAM,EAAE,iBAAc,qBAAkB,EACtC;EAAE,eAAe;EAAM,2BAA2B;EAAO;EAAQ,SAAS;EAAe,EACzF,EACD,EAGK,EAAE,gBAAa,kBAAe,EAAU,EAAE,EAAE,EAAW;CAU7D,OARA,EAAiB,EAAE,YAAY,CAAC,GAAQ,CAAC,EAEzC,QAAgB;EAGd,EAAuB,EAAK,EAAO,QAAQ,GAAG,EAAO,kBAAkB,GAAQ,CAAC,CAAC;IAChF,CAAC,EAAO,CAAC,EAGV,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EAAU,GAAI;YACZ,kBAAC,GAAD;GAAY,SAAA;GAAQ,cAAA;aAClB,kBAAC,SAAD;IACE,GAAI;IACJ,GAAI;IACJ,GAAI;IACJ,GAAI;IACJ,WAAW;IACX,KAAK;cANP;KAQE,kBAAC,UAAD;MAAQ,WAAW,EAAO;gBAA1B,CACE,kBAAC,MAAD;OAAI,WAAW,EAAO;OAAiB,GAAI;iBACxC;OACE,CAAA,EAEL,kBAAC,GAAD;OAAoB,cAAY;OAA0B,SAAS;OAAiB,CAAA,CAC7E;;KAET,kBAAC,OAAD;MAAK,WAAW,EAAO;MAAkB;MAAe,CAAA;KAEvD,KACC,kBAAC,UAAD;MAAQ,WAAW,EAAO;gBACxB,kBAAC,OAAD;OAAK,WAAW,EAAO;iBAAkB;OAAc,CAAA;MAChD,CAAA;KAEL;;GACG,CAAA;EACJ,CAAA,EACM,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyStateDataDisplay-D0QiI8nE.js","names":[],"sources":["../src/components/EmptyStateDataDisplay/EmptyStateDataDisplay.module.css","../src/components/EmptyStateDataDisplay/EmptyStateDataDisplay.tsx"],"sourcesContent":[".empty-state-data-display_wrapper {\n align-items: center;\n background-color: var(--color-uva-white);\n display: flex;\n gap: 1.5rem;\n padding: 1.5rem;\n}\n\n.empty-state-data-display_icon-frame {\n align-items: center;\n background-color: var(--color-grey-200);\n border-radius: 50%;\n display: flex;\n justify-content: center;\n min-height: 4rem;\n min-width: 4rem;\n}\n\n.empty-state-data-display_wrapper--invert-colors {\n background-color: var(--color-grey-200);\n}\n\n.empty-state-data-display_wrapper--slim {\n gap: 1rem;\n padding: 1rem;\n}\n\n.empty-state-data-display_icon-frame--invert-colors {\n background-color: var(--color-uva-white);\n}\n\n.empty-state-data-display_icon-frame--slim {\n min-height: 2rem;\n min-width: 2rem;\n}\n\n.empty-state-data-display_text-content {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.empty-state-data-display_label {\n font-weight: var(--semibold);\n}\n\n.empty-state-data-display_paragraph {\n color: var(--color-grey-700);\n margin: 0;\n}\n","import { clsx } from 'clsx';\n\nimport type { UISizeVariant } from 'types/UserInterface';\n\nimport styles from './EmptyStateDataDisplay.module.css';\n\nimport { Icon } from 'components/Icon';\n\nexport interface EmptyStateDataDisplayProps {\n /** The main text to display. */\n label: string;\n /** The sub-text to display. */\n paragraph?: string;\n /** The colors of the wrapper and icon background are inverted. */\n invertColors?: boolean;\n /** The display variant. */\n variant?: UISizeVariant;\n}\n\nconst ICON_SIZE_REGULAR = 24;\nconst ICON_SIZE_SLIM = 16;\n\n/** Represents a component to indicate an empty state. */\nexport function EmptyStateDataDisplay({\n label,\n paragraph,\n invertColors,\n variant = 'regular',\n}: EmptyStateDataDisplayProps) {\n return (\n <div\n className={clsx(styles['empty-state-data-display_wrapper'], {\n [styles['empty-state-data-display_wrapper--invert-colors']]: invertColors,\n [styles['empty-state-data-display_wrapper--slim']]: variant === 'slim',\n })}\n >\n <div\n className={clsx(styles['empty-state-data-display_icon-frame'], {\n [styles['empty-state-data-display_icon-frame--invert-colors']]: invertColors,\n [styles['empty-state-data-display_icon-frame--slim']]: variant === 'slim',\n })}\n >\n <Icon name=\"CubeTransparent\" size={variant === 'regular' ? ICON_SIZE_REGULAR : ICON_SIZE_SLIM} />\n </div>\n <div className={styles['empty-state-data-display_text-content']}>\n <label className={styles['empty-state-data-display_label']}>{label}</label>\n {paragraph && <p className={styles['empty-state-data-display_paragraph']}>{paragraph}</p>}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;GCmBM,IAAoB,IACpB,IAAiB;AAGvB,SAAgB,EAAsB,EACpC,UACA,cACA,iBACA,aAAU,aACmB;AAC7B,QACE,kBAAC,OAAD;EACE,WAAW,EAAK,EAAO,qCAAqC;IACzD,EAAO,qDAAqD;IAC5D,EAAO,4CAA4C,MAAY;GACjE,CAAC;YAJJ,CAME,kBAAC,OAAD;GACE,WAAW,EAAK,EAAO,wCAAwC;KAC5D,EAAO,wDAAwD;KAC/D,EAAO,+CAA+C,MAAY;IACpE,CAAC;aAEF,kBAAC,GAAD;IAAM,MAAK;IAAkB,MAAM,MAAY,YAAY,IAAoB;IAAkB,CAAA;GAC7F,CAAA,EACN,kBAAC,OAAD;GAAK,WAAW,EAAO;aAAvB,CACE,kBAAC,SAAD;IAAO,WAAW,EAAO;cAAoC;IAAc,CAAA,EAC1E,KAAa,kBAAC,KAAD;IAAG,WAAW,EAAO;cAAwC;IAAc,CAAA,CACrF;KACF"}
1
+ {"version":3,"file":"EmptyStateDataDisplay-D0QiI8nE.js","names":[],"sources":["../src/components/EmptyStateDataDisplay/EmptyStateDataDisplay.module.css","../src/components/EmptyStateDataDisplay/EmptyStateDataDisplay.tsx"],"sourcesContent":[".empty-state-data-display_wrapper {\n align-items: center;\n background-color: var(--color-uva-white);\n display: flex;\n gap: 1.5rem;\n padding: 1.5rem;\n}\n\n.empty-state-data-display_icon-frame {\n align-items: center;\n background-color: var(--color-grey-200);\n border-radius: 50%;\n display: flex;\n justify-content: center;\n min-height: 4rem;\n min-width: 4rem;\n}\n\n.empty-state-data-display_wrapper--invert-colors {\n background-color: var(--color-grey-200);\n}\n\n.empty-state-data-display_wrapper--slim {\n gap: 1rem;\n padding: 1rem;\n}\n\n.empty-state-data-display_icon-frame--invert-colors {\n background-color: var(--color-uva-white);\n}\n\n.empty-state-data-display_icon-frame--slim {\n min-height: 2rem;\n min-width: 2rem;\n}\n\n.empty-state-data-display_text-content {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.empty-state-data-display_label {\n font-weight: var(--semibold);\n}\n\n.empty-state-data-display_paragraph {\n color: var(--color-grey-700);\n margin: 0;\n}\n","import { clsx } from 'clsx';\n\nimport type { UISizeVariant } from 'types/UserInterface';\n\nimport styles from './EmptyStateDataDisplay.module.css';\n\nimport { Icon } from 'components/Icon';\n\nexport interface EmptyStateDataDisplayProps {\n /** The main text to display. */\n label: string;\n /** The sub-text to display. */\n paragraph?: string;\n /** The colors of the wrapper and icon background are inverted. */\n invertColors?: boolean;\n /** The display variant. */\n variant?: UISizeVariant;\n}\n\nconst ICON_SIZE_REGULAR = 24;\nconst ICON_SIZE_SLIM = 16;\n\n/** Represents a component to indicate an empty state. */\nexport function EmptyStateDataDisplay({\n label,\n paragraph,\n invertColors,\n variant = 'regular',\n}: EmptyStateDataDisplayProps) {\n return (\n <div\n className={clsx(styles['empty-state-data-display_wrapper'], {\n [styles['empty-state-data-display_wrapper--invert-colors']]: invertColors,\n [styles['empty-state-data-display_wrapper--slim']]: variant === 'slim',\n })}\n >\n <div\n className={clsx(styles['empty-state-data-display_icon-frame'], {\n [styles['empty-state-data-display_icon-frame--invert-colors']]: invertColors,\n [styles['empty-state-data-display_icon-frame--slim']]: variant === 'slim',\n })}\n >\n <Icon name=\"CubeTransparent\" size={variant === 'regular' ? ICON_SIZE_REGULAR : ICON_SIZE_SLIM} />\n </div>\n <div className={styles['empty-state-data-display_text-content']}>\n <label className={styles['empty-state-data-display_label']}>{label}</label>\n {paragraph && <p className={styles['empty-state-data-display_paragraph']}>{paragraph}</p>}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;GCmBM,IAAoB,IACpB,IAAiB;AAGvB,SAAgB,EAAsB,EACpC,UACA,cACA,iBACA,aAAU,aACmB;CAC7B,OACE,kBAAC,OAAD;EACE,WAAW,EAAK,EAAO,qCAAqC;IACzD,EAAO,qDAAqD;IAC5D,EAAO,4CAA4C,MAAY;GACjE,CAAC;YAJJ,CAME,kBAAC,OAAD;GACE,WAAW,EAAK,EAAO,wCAAwC;KAC5D,EAAO,wDAAwD;KAC/D,EAAO,+CAA+C,MAAY;IACpE,CAAC;aAEF,kBAAC,GAAD;IAAM,MAAK;IAAkB,MAAM,MAAY,YAAY,IAAoB;IAAkB,CAAA;GAC7F,CAAA,EACN,kBAAC,OAAD;GAAK,WAAW,EAAO;aAAvB,CACE,kBAAC,SAAD;IAAO,WAAW,EAAO;cAAoC;IAAc,CAAA,EAC1E,KAAa,kBAAC,KAAD;IAAG,WAAW,EAAO;cAAwC;IAAc,CAAA,CACrF;KACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExpandableInfoPanel-CnBVVNlJ.js","names":[],"sources":["../src/components/ExpandableInfoPanel/ExpandableInfoPanel.module.css","../src/components/ExpandableInfoPanel/ExpandableInfoPanel.tsx"],"sourcesContent":[".expandable-info-panel_wrapper {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n\n.expandable-info-panel_header {\n align-items: center;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n padding-bottom: 0.5rem;\n width: 100%;\n}\n\n.expandable-info-panel_trigger {\n align-items: center;\n appearance: none;\n background-color: transparent;\n border: none;\n border-radius: 0.25rem;\n display: flex;\n font: inherit;\n font-size: var(--font-size-default);\n gap: 0.5rem;\n height: 2.75rem;\n margin-bottom: 0;\n outline: none;\n padding: 0.5rem;\n position: relative;\n width: fit-content;\n cursor: pointer;\n}\n\n.expandable-info-panel_trigger:focus-visible {\n outline: 0.125rem dotted var(--color-navy-600);\n outline-offset: 0.125rem;\n text-decoration: underline;\n}\n\n.expandable-info-panel_trigger:hover {\n background-color: var(--color-grey-200);\n text-decoration: underline;\n}\n\n.expandable-info-panel_trigger--active {\n background-color: var(--color-navy-200);\n border-radius: 0.25rem 0.25rem 0 0;\n}\n\n.expandable-info-panel_trigger--active:after {\n background-color: var(--color-navy-200);\n content: \"\";\n display: block;\n height: 0.5rem;\n left: 0;\n position: absolute;\n right: 0;\n top: 100%;\n z-index: -1;\n}\n\n.expandable-info-panel_trigger--active:hover,\n.expandable-info-panel_trigger--active:hover:after {\n background-color: var(--color-navy-300);\n}\n\n.expandable-info-panel_content-wrapper {\n align-items: start;\n background-color: var(--color-navy-200);\n display: grid;\n gap: 1rem;\n grid-template-columns: 1.5rem 1fr;\n padding: 1.5rem;\n}\n\n.expandable-info-panel_content-with-note-container {\n display: flex;\n gap: 0.5rem;\n justify-content: space-between;\n}\n\n.expandable-info-panel_note {\n background-color: var(--color-navy-100);\n padding: 1rem;\n /* both min and max width needed as not all react elements repect width */\n /* if react node contenct is placed next to \"note\" it may squish a pure \"width\" note */\n min-width: 15.875rem;\n max-width: 15.875rem;\n}\n","import { useState, type ReactNode } from 'react';\r\nimport { clsx } from 'clsx';\r\nimport { useId } from 'react';\r\n\r\nimport styles from './ExpandableInfoPanel.module.css';\r\n\r\nimport { Icon } from 'components/Icon';\r\n\r\nexport interface ExpandableInfoPanelProps {\r\n /** Label for the trigger button that toggles the expandable panel. */\r\n triggerLabel: string;\r\n /** Main header displayed inline left of the trigger button. */\r\n mainHeader?: ReactNode | string;\r\n /** Aria-label for the button when the panel is collapsed. */\r\n collapseLabel?: string;\r\n /** Aria-label for the button when the panel is expanded. */\r\n expandLabel?: string;\r\n /** Content to be displayed inside the expandable panel. */\r\n content: ReactNode | string;\r\n /** Optional content area on in seperate box on right side of expanded content. */\r\n note?: ReactNode | string;\r\n /** Optional state, if true; sets the expandable panel as 'open' by default. */\r\n defaultOpen?: boolean;\r\n}\r\n\r\nexport const ExpandableInfoPanel = ({\r\n triggerLabel,\r\n mainHeader,\r\n collapseLabel = '',\r\n expandLabel = '',\r\n content,\r\n note = '',\r\n defaultOpen = false,\r\n}: ExpandableInfoPanelProps) => {\r\n const [active, setActive] = useState(defaultOpen);\r\n const contentId = useId();\r\n\r\n return (\r\n <div className={styles['expandable-info-panel_wrapper']}>\r\n <div className={styles['expandable-info-panel_header']}>\r\n {mainHeader}\r\n <button\r\n className={clsx(styles['expandable-info-panel_trigger'], {\r\n [styles['expandable-info-panel_trigger--active']]: active,\r\n })}\r\n type=\"button\"\r\n aria-expanded={active}\r\n aria-controls={contentId}\r\n aria-label={`${triggerLabel} - ${active ? collapseLabel : expandLabel}`}\r\n onClick={() => setActive(!active)}\r\n >\r\n <Icon name={active ? 'SquareInfoSolid' : 'SquareInfo'} size={24} />\r\n {triggerLabel}\r\n <Icon name={active ? 'CheveronUp' : 'CheveronDown'} size={16} />\r\n </button>\r\n </div>\r\n {active && (\r\n <div id={contentId} className={styles['expandable-info-panel_content-wrapper']}>\r\n <Icon name=\"SquareInfo\" size={24} />\r\n {!note ? (\r\n <div>{content}</div>\r\n ) : (\r\n <div className={styles['expandable-info-panel_content-with-note-container']}>\r\n <div>{content}</div>\r\n <div className={styles['expandable-info-panel_note']}>{note}</div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n"],"mappings":";;;;;;;;;;;;;GCyBa,KAAuB,EAClC,iBACA,eACA,mBAAgB,IAChB,iBAAc,IACd,YACA,UAAO,IACP,iBAAc,SACgB;CAC9B,IAAM,CAAC,GAAQ,KAAa,EAAS,EAAY,EAC3C,IAAY,GAAO;AAEzB,QACE,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACE,kBAAC,OAAD;GAAK,WAAW,EAAO;aAAvB,CACG,GACD,kBAAC,UAAD;IACE,WAAW,EAAK,EAAO,kCAAkC,GACtD,EAAO,2CAA2C,GACpD,CAAC;IACF,MAAK;IACL,iBAAe;IACf,iBAAe;IACf,cAAY,GAAG,EAAa,KAAK,IAAS,IAAgB;IAC1D,eAAe,EAAU,CAAC,EAAO;cARnC;KAUE,kBAAC,GAAD;MAAM,MAAM,IAAS,oBAAoB;MAAc,MAAM;MAAM,CAAA;KAClE;KACD,kBAAC,GAAD;MAAM,MAAM,IAAS,eAAe;MAAgB,MAAM;MAAM,CAAA;KACzD;MACL;MACL,KACC,kBAAC,OAAD;GAAK,IAAI;GAAW,WAAW,EAAO;aAAtC,CACE,kBAAC,GAAD;IAAM,MAAK;IAAa,MAAM;IAAM,CAAA,EAClC,IAGA,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACE,kBAAC,OAAD,EAAA,UAAM,GAAc,CAAA,EACpB,kBAAC,OAAD;KAAK,WAAW,EAAO;eAAgC;KAAW,CAAA,CAC9D;QALN,kBAAC,OAAD,EAAA,UAAM,GAAc,CAAA,CAOlB;KAEJ"}
1
+ {"version":3,"file":"ExpandableInfoPanel-CnBVVNlJ.js","names":[],"sources":["../src/components/ExpandableInfoPanel/ExpandableInfoPanel.module.css","../src/components/ExpandableInfoPanel/ExpandableInfoPanel.tsx"],"sourcesContent":[".expandable-info-panel_wrapper {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n\n.expandable-info-panel_header {\n align-items: center;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n padding-bottom: 0.5rem;\n width: 100%;\n}\n\n.expandable-info-panel_trigger {\n align-items: center;\n appearance: none;\n background-color: transparent;\n border: none;\n border-radius: 0.25rem;\n display: flex;\n font: inherit;\n font-size: var(--font-size-default);\n gap: 0.5rem;\n height: 2.75rem;\n margin-bottom: 0;\n outline: none;\n padding: 0.5rem;\n position: relative;\n width: fit-content;\n cursor: pointer;\n}\n\n.expandable-info-panel_trigger:focus-visible {\n outline: 0.125rem dotted var(--color-navy-600);\n outline-offset: 0.125rem;\n text-decoration: underline;\n}\n\n.expandable-info-panel_trigger:hover {\n background-color: var(--color-grey-200);\n text-decoration: underline;\n}\n\n.expandable-info-panel_trigger--active {\n background-color: var(--color-navy-200);\n border-radius: 0.25rem 0.25rem 0 0;\n}\n\n.expandable-info-panel_trigger--active:after {\n background-color: var(--color-navy-200);\n content: \"\";\n display: block;\n height: 0.5rem;\n left: 0;\n position: absolute;\n right: 0;\n top: 100%;\n z-index: -1;\n}\n\n.expandable-info-panel_trigger--active:hover,\n.expandable-info-panel_trigger--active:hover:after {\n background-color: var(--color-navy-300);\n}\n\n.expandable-info-panel_content-wrapper {\n align-items: start;\n background-color: var(--color-navy-200);\n display: grid;\n gap: 1rem;\n grid-template-columns: 1.5rem 1fr;\n padding: 1.5rem;\n}\n\n.expandable-info-panel_content-with-note-container {\n display: flex;\n gap: 0.5rem;\n justify-content: space-between;\n}\n\n.expandable-info-panel_note {\n background-color: var(--color-navy-100);\n padding: 1rem;\n /* both min and max width needed as not all react elements repect width */\n /* if react node contenct is placed next to \"note\" it may squish a pure \"width\" note */\n min-width: 15.875rem;\n max-width: 15.875rem;\n}\n","import { useState, type ReactNode } from 'react';\r\nimport { clsx } from 'clsx';\r\nimport { useId } from 'react';\r\n\r\nimport styles from './ExpandableInfoPanel.module.css';\r\n\r\nimport { Icon } from 'components/Icon';\r\n\r\nexport interface ExpandableInfoPanelProps {\r\n /** Label for the trigger button that toggles the expandable panel. */\r\n triggerLabel: string;\r\n /** Main header displayed inline left of the trigger button. */\r\n mainHeader?: ReactNode | string;\r\n /** Aria-label for the button when the panel is collapsed. */\r\n collapseLabel?: string;\r\n /** Aria-label for the button when the panel is expanded. */\r\n expandLabel?: string;\r\n /** Content to be displayed inside the expandable panel. */\r\n content: ReactNode | string;\r\n /** Optional content area on in seperate box on right side of expanded content. */\r\n note?: ReactNode | string;\r\n /** Optional state, if true; sets the expandable panel as 'open' by default. */\r\n defaultOpen?: boolean;\r\n}\r\n\r\nexport const ExpandableInfoPanel = ({\r\n triggerLabel,\r\n mainHeader,\r\n collapseLabel = '',\r\n expandLabel = '',\r\n content,\r\n note = '',\r\n defaultOpen = false,\r\n}: ExpandableInfoPanelProps) => {\r\n const [active, setActive] = useState(defaultOpen);\r\n const contentId = useId();\r\n\r\n return (\r\n <div className={styles['expandable-info-panel_wrapper']}>\r\n <div className={styles['expandable-info-panel_header']}>\r\n {mainHeader}\r\n <button\r\n className={clsx(styles['expandable-info-panel_trigger'], {\r\n [styles['expandable-info-panel_trigger--active']]: active,\r\n })}\r\n type=\"button\"\r\n aria-expanded={active}\r\n aria-controls={contentId}\r\n aria-label={`${triggerLabel} - ${active ? collapseLabel : expandLabel}`}\r\n onClick={() => setActive(!active)}\r\n >\r\n <Icon name={active ? 'SquareInfoSolid' : 'SquareInfo'} size={24} />\r\n {triggerLabel}\r\n <Icon name={active ? 'CheveronUp' : 'CheveronDown'} size={16} />\r\n </button>\r\n </div>\r\n {active && (\r\n <div id={contentId} className={styles['expandable-info-panel_content-wrapper']}>\r\n <Icon name=\"SquareInfo\" size={24} />\r\n {!note ? (\r\n <div>{content}</div>\r\n ) : (\r\n <div className={styles['expandable-info-panel_content-with-note-container']}>\r\n <div>{content}</div>\r\n <div className={styles['expandable-info-panel_note']}>{note}</div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n"],"mappings":";;;;;;;;;;;;;GCyBa,KAAuB,EAClC,iBACA,eACA,mBAAgB,IAChB,iBAAc,IACd,YACA,UAAO,IACP,iBAAc,SACgB;CAC9B,IAAM,CAAC,GAAQ,KAAa,EAAS,EAAY,EAC3C,IAAY,GAAO;CAEzB,OACE,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACE,kBAAC,OAAD;GAAK,WAAW,EAAO;aAAvB,CACG,GACD,kBAAC,UAAD;IACE,WAAW,EAAK,EAAO,kCAAkC,GACtD,EAAO,2CAA2C,GACpD,CAAC;IACF,MAAK;IACL,iBAAe;IACf,iBAAe;IACf,cAAY,GAAG,EAAa,KAAK,IAAS,IAAgB;IAC1D,eAAe,EAAU,CAAC,EAAO;cARnC;KAUE,kBAAC,GAAD;MAAM,MAAM,IAAS,oBAAoB;MAAc,MAAM;MAAM,CAAA;KAClE;KACD,kBAAC,GAAD;MAAM,MAAM,IAAS,eAAe;MAAgB,MAAM;MAAM,CAAA;KACzD;MACL;MACL,KACC,kBAAC,OAAD;GAAK,IAAI;GAAW,WAAW,EAAO;aAAtC,CACE,kBAAC,GAAD;IAAM,MAAK;IAAa,MAAM;IAAM,CAAA,EAClC,IAGA,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACE,kBAAC,OAAD,EAAA,UAAM,GAAc,CAAA,EACpB,kBAAC,OAAD;KAAK,WAAW,EAAO;eAAgC;KAAW,CAAA,CAC9D;QALN,kBAAC,OAAD,EAAA,UAAM,GAAc,CAAA,CAOlB;KAEJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"FeedbackBar-ByKp32HE.js","names":[],"sources":["../src/components/FeedbackBar/FeedbackBar.module.css","../src/components/FeedbackBar/FeedbackBar.tsx"],"sourcesContent":[".feedback-bar {\n background-color: var(--color-forest-100);\n border: 1px solid var(--color-forest-800);\n border-radius: 0.5rem;\n display: flex;\n font-weight: var(--semibold);\n gap: 0.5rem;\n justify-content: space-between;\n max-height: 0;\n opacity: 0;\n padding: 0 1rem;\n transition: all 0.5s;\n}\n\n.feedback-bar--visible {\n max-height: 6.625rem;\n opacity: 1;\n padding: 1rem;\n}\n\n.feedback-bar__icon {\n color: var(--color-forest-800);\n}\n\n.feedback-bar__close-button {\n align-items: center;\n background-color: transparent;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n color: var(--color-uva-black);\n display: inline-flex;\n height: 1.5rem;\n justify-content: center;\n transition: var(--transition-colors);\n width: 1.5rem;\n}\n\n.feedback-bar__close-button:focus-visible {\n outline: 0.125rem dotted var(--color-navy-600);\n outline-offset: 0.125rem;\n}\n\n.feedback-bar__close-button:hover {\n background-color: var(--color-forest-600);\n cursor: pointer;\n outline: 0;\n}\n\n/* make the clickable area of the overlay close button 42x42px simmilar to a regular button */\n\n.feedback-bar__close-button::after {\n content: \" \";\n height: 2.625rem;\n position: absolute;\n width: 2.625rem;\n}\n","import classNames from 'clsx';\nimport { useEffect, useState, type PropsWithChildren } from 'react';\n\nimport styles from './FeedbackBar.module.css';\n\nimport { Icon } from 'components/Icon';\nimport { Repeater } from 'components/Repeater';\n\n/** Represents a component to show feedback within a Page. */\nexport const FeedbackBar = ({ children }: PropsWithChildren) => {\n const [isVisible, setIsVisible] = useState(false);\n\n useEffect(() => {\n setIsVisible(true);\n }, []);\n\n const close = () => {\n setIsVisible(false);\n };\n\n return (\n <div className={classNames(styles['feedback-bar'], { [styles['feedback-bar--visible']]: isVisible })} role=\"alert\">\n <Repeater flexDirection=\"row\">\n <Icon className={classNames(styles['feedback-bar__icon'])} name=\"CheckCircle\" />\n {children}\n </Repeater>\n <button className={classNames(styles['feedback-bar__close-button'])} type=\"button\" onClick={close}>\n <Icon name=\"Cross\" size={24} />\n </button>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;GCSa,KAAe,EAAE,kBAAkC;CAC9D,IAAM,CAAC,GAAW,KAAgB,EAAS,GAAM;AAEjD,SAAgB;AACd,IAAa,GAAK;IACjB,EAAE,CAAC;CAEN,IAAM,UAAc;AAClB,IAAa,GAAM;;AAGrB,QACE,kBAAC,OAAD;EAAK,WAAW,EAAW,EAAO,iBAAiB,GAAG,EAAO,2BAA2B,GAAW,CAAC;EAAE,MAAK;YAA3G,CACE,kBAAC,GAAD;GAAU,eAAc;aAAxB,CACE,kBAAC,GAAD;IAAM,WAAW,EAAW,EAAO,sBAAsB;IAAE,MAAK;IAAgB,CAAA,EAC/E,EACQ;MACX,kBAAC,UAAD;GAAQ,WAAW,EAAW,EAAO,8BAA8B;GAAE,MAAK;GAAS,SAAS;aAC1F,kBAAC,GAAD;IAAM,MAAK;IAAQ,MAAM;IAAM,CAAA;GACxB,CAAA,CACL"}
1
+ {"version":3,"file":"FeedbackBar-ByKp32HE.js","names":[],"sources":["../src/components/FeedbackBar/FeedbackBar.module.css","../src/components/FeedbackBar/FeedbackBar.tsx"],"sourcesContent":[".feedback-bar {\n background-color: var(--color-forest-100);\n border: 1px solid var(--color-forest-800);\n border-radius: 0.5rem;\n display: flex;\n font-weight: var(--semibold);\n gap: 0.5rem;\n justify-content: space-between;\n max-height: 0;\n opacity: 0;\n padding: 0 1rem;\n transition: all 0.5s;\n}\n\n.feedback-bar--visible {\n max-height: 6.625rem;\n opacity: 1;\n padding: 1rem;\n}\n\n.feedback-bar__icon {\n color: var(--color-forest-800);\n}\n\n.feedback-bar__close-button {\n align-items: center;\n background-color: transparent;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n color: var(--color-uva-black);\n display: inline-flex;\n height: 1.5rem;\n justify-content: center;\n transition: var(--transition-colors);\n width: 1.5rem;\n}\n\n.feedback-bar__close-button:focus-visible {\n outline: 0.125rem dotted var(--color-navy-600);\n outline-offset: 0.125rem;\n}\n\n.feedback-bar__close-button:hover {\n background-color: var(--color-forest-600);\n cursor: pointer;\n outline: 0;\n}\n\n/* make the clickable area of the overlay close button 42x42px simmilar to a regular button */\n\n.feedback-bar__close-button::after {\n content: \" \";\n height: 2.625rem;\n position: absolute;\n width: 2.625rem;\n}\n","import classNames from 'clsx';\nimport { useEffect, useState, type PropsWithChildren } from 'react';\n\nimport styles from './FeedbackBar.module.css';\n\nimport { Icon } from 'components/Icon';\nimport { Repeater } from 'components/Repeater';\n\n/** Represents a component to show feedback within a Page. */\nexport const FeedbackBar = ({ children }: PropsWithChildren) => {\n const [isVisible, setIsVisible] = useState(false);\n\n useEffect(() => {\n setIsVisible(true);\n }, []);\n\n const close = () => {\n setIsVisible(false);\n };\n\n return (\n <div className={classNames(styles['feedback-bar'], { [styles['feedback-bar--visible']]: isVisible })} role=\"alert\">\n <Repeater flexDirection=\"row\">\n <Icon className={classNames(styles['feedback-bar__icon'])} name=\"CheckCircle\" />\n {children}\n </Repeater>\n <button className={classNames(styles['feedback-bar__close-button'])} type=\"button\" onClick={close}>\n <Icon name=\"Cross\" size={24} />\n </button>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;GCSa,KAAe,EAAE,kBAAkC;CAC9D,IAAM,CAAC,GAAW,KAAgB,EAAS,GAAM;CAEjD,QAAgB;EACd,EAAa,GAAK;IACjB,EAAE,CAAC;CAEN,IAAM,UAAc;EAClB,EAAa,GAAM;;CAGrB,OACE,kBAAC,OAAD;EAAK,WAAW,EAAW,EAAO,iBAAiB,GAAG,EAAO,2BAA2B,GAAW,CAAC;EAAE,MAAK;YAA3G,CACE,kBAAC,GAAD;GAAU,eAAc;aAAxB,CACE,kBAAC,GAAD;IAAM,WAAW,EAAW,EAAO,sBAAsB;IAAE,MAAK;IAAgB,CAAA,EAC/E,EACQ;MACX,kBAAC,UAAD;GAAQ,WAAW,EAAW,EAAO,8BAA8B;GAAE,MAAK;GAAS,SAAS;aAC1F,kBAAC,GAAD;IAAM,MAAK;IAAQ,MAAM;IAAM,CAAA;GACxB,CAAA,CACL"}
@@ -1 +1 @@
1
- {"version":3,"file":"FieldHint-fxnEOsVZ.js","names":[],"sources":["../src/components/FieldHint/FieldHint.module.css","../src/components/FieldHint/FieldHint.tsx"],"sourcesContent":[".field-hint {\n font-size: 0.875rem;\n}\n","import styles from './FieldHint.module.css';\n\nimport { Spinner } from 'components/Spinner/Spinner';\n\nexport interface FieldHintProps {\n /** The value to display. */\n value?: string;\n /** The aria-valuetext value of the spinner component. */\n spinnerAriaValueText: string;\n /** true if the field hint is loading; otherwise, false. The default is false. */\n loading?: boolean;\n}\n\n/** Represents a component to show a hint for an input element. */\nexport function FieldHint({ value, spinnerAriaValueText, loading }: FieldHintProps) {\n return (\n <span className={styles['field-hint']}>\n {value && <>{value}</>}\n {!value && loading && <Spinner ariaValueText={spinnerAriaValueText} />}\n </span>\n );\n}\n"],"mappings":";;;;;;ACcA,SAAgB,EAAU,EAAE,UAAO,yBAAsB,cAA2B;AAClF,QACE,kBAAC,QAAD;EAAM,WAAW,EAAO;YAAxB,CACG,KAAS,kBAAA,GAAA,EAAA,UAAG,GAAS,CAAA,EACrB,CAAC,KAAS,KAAW,kBAAC,GAAD,EAAS,eAAe,GAAwB,CAAA,CACjE"}
1
+ {"version":3,"file":"FieldHint-fxnEOsVZ.js","names":[],"sources":["../src/components/FieldHint/FieldHint.module.css","../src/components/FieldHint/FieldHint.tsx"],"sourcesContent":[".field-hint {\n font-size: 0.875rem;\n}\n","import styles from './FieldHint.module.css';\n\nimport { Spinner } from 'components/Spinner/Spinner';\n\nexport interface FieldHintProps {\n /** The value to display. */\n value?: string;\n /** The aria-valuetext value of the spinner component. */\n spinnerAriaValueText: string;\n /** true if the field hint is loading; otherwise, false. The default is false. */\n loading?: boolean;\n}\n\n/** Represents a component to show a hint for an input element. */\nexport function FieldHint({ value, spinnerAriaValueText, loading }: FieldHintProps) {\n return (\n <span className={styles['field-hint']}>\n {value && <>{value}</>}\n {!value && loading && <Spinner ariaValueText={spinnerAriaValueText} />}\n </span>\n );\n}\n"],"mappings":";;;;;;ACcA,SAAgB,EAAU,EAAE,UAAO,yBAAsB,cAA2B;CAClF,OACE,kBAAC,QAAD;EAAM,WAAW,EAAO;YAAxB,CACG,KAAS,kBAAA,GAAA,EAAA,UAAG,GAAS,CAAA,EACrB,CAAC,KAAS,KAAW,kBAAC,GAAD,EAAS,eAAe,GAAwB,CAAA,CACjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"Input-Bn-arMaC.js","names":[],"sources":["../src/components/Input/Input.module.css","../src/components/Input/Input.tsx"],"sourcesContent":[".input {\n appearance: none;\n background-color: transparent;\n border: 1px solid var(--color-uva-black);\n color: var(--color-uva-black);\n font-family: inherit;\n font-size: inherit;\n height: 2rem;\n margin: 0;\n padding: 0 0.5rem;\n}\n\n.input--numeric {\n text-align: right;\n width: 8rem;\n}\n\n.input--error,\n.input:invalid {\n border-color: var(--color-red-600);\n}\n\n.input--full-with {\n min-width: 100%;\n width: 0; /* Reset the default width of the input */\n}\n\n.input::placeholder {\n color: var(--color-grey-700);\n font-size: inherit;\n opacity: 1;\n}\n\n.input[type=\"file\"] {\n border: none;\n}\n\n.input:disabled {\n color: var(--color-grey-700);\n}\n","import { forwardRef } from 'react';\nimport { clsx } from 'clsx';\n\nimport type { InputHTMLAttributes } from 'react';\n\nimport styles from './Input.module.css';\n\nexport interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'style'> {\n /** The appearance of the element. Possible values: `error`. */\n appearance?: 'error';\n /** The type of the input element. */\n type?: 'text' | 'search' | 'password' | 'email' | 'file';\n /** `true` if the element should render at full width of its container; otherwise, `false`. The default is `false`. */\n fullWidth?: boolean;\n /** The id of the element. */\n id: string;\n /** `true` if the element is used for numeric values; otherwise, `false`. The default is `false`. */\n isNumeric?: boolean;\n}\n\n/** Represents a component for an input element. */\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n { id, appearance, type = 'text', isNumeric, fullWidth, ...restProps }: InputProps,\n forwardedRef\n) {\n return (\n <input\n {...restProps}\n ref={forwardedRef}\n id={id}\n className={clsx(styles['input'], {\n [styles['input--error']]: appearance === 'error',\n [styles['input--full-with']]: fullWidth,\n [styles['input--numeric']]: isNumeric,\n })}\n type={type}\n />\n );\n});\n"],"mappings":";;;;;;;;GCqBa,IAAQ,EAAyC,SAC5D,EAAE,OAAI,eAAY,UAAO,QAAQ,cAAW,cAAW,GAAG,KAC1D,GACA;AACA,QACE,kBAAC,SAAD;EACE,GAAI;EACJ,KAAK;EACD;EACJ,WAAW,EAAK,EAAO,OAAU;IAC9B,EAAO,kBAAkB,MAAe;IACxC,EAAO,sBAAsB;IAC7B,EAAO,oBAAoB;GAC7B,CAAC;EACI;EACN,CAAA;EAEJ"}
1
+ {"version":3,"file":"Input-Bn-arMaC.js","names":[],"sources":["../src/components/Input/Input.module.css","../src/components/Input/Input.tsx"],"sourcesContent":[".input {\n appearance: none;\n background-color: transparent;\n border: 1px solid var(--color-uva-black);\n color: var(--color-uva-black);\n font-family: inherit;\n font-size: inherit;\n height: 2rem;\n margin: 0;\n padding: 0 0.5rem;\n}\n\n.input--numeric {\n text-align: right;\n width: 8rem;\n}\n\n.input--error,\n.input:invalid {\n border-color: var(--color-red-600);\n}\n\n.input--full-with {\n min-width: 100%;\n width: 0; /* Reset the default width of the input */\n}\n\n.input::placeholder {\n color: var(--color-grey-700);\n font-size: inherit;\n opacity: 1;\n}\n\n.input[type=\"file\"] {\n border: none;\n}\n\n.input:disabled {\n color: var(--color-grey-700);\n}\n","import { forwardRef } from 'react';\nimport { clsx } from 'clsx';\n\nimport type { InputHTMLAttributes } from 'react';\n\nimport styles from './Input.module.css';\n\nexport interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'style'> {\n /** The appearance of the element. Possible values: `error`. */\n appearance?: 'error';\n /** The type of the input element. */\n type?: 'text' | 'search' | 'password' | 'email' | 'file';\n /** `true` if the element should render at full width of its container; otherwise, `false`. The default is `false`. */\n fullWidth?: boolean;\n /** The id of the element. */\n id: string;\n /** `true` if the element is used for numeric values; otherwise, `false`. The default is `false`. */\n isNumeric?: boolean;\n}\n\n/** Represents a component for an input element. */\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n { id, appearance, type = 'text', isNumeric, fullWidth, ...restProps }: InputProps,\n forwardedRef\n) {\n return (\n <input\n {...restProps}\n ref={forwardedRef}\n id={id}\n className={clsx(styles['input'], {\n [styles['input--error']]: appearance === 'error',\n [styles['input--full-with']]: fullWidth,\n [styles['input--numeric']]: isNumeric,\n })}\n type={type}\n />\n );\n});\n"],"mappings":";;;;;;;;GCqBa,IAAQ,EAAyC,SAC5D,EAAE,OAAI,eAAY,UAAO,QAAQ,cAAW,cAAW,GAAG,KAC1D,GACA;CACA,OACE,kBAAC,SAAD;EACE,GAAI;EACJ,KAAK;EACD;EACJ,WAAW,EAAK,EAAO,OAAU;IAC9B,EAAO,kBAAkB,MAAe;IACxC,EAAO,sBAAsB;IAC7B,EAAO,oBAAoB;GAC7B,CAAC;EACI;EACN,CAAA;EAEJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"InputField-BWAy19w9.js","names":[],"sources":["../src/components/InputField/InputField.module.css","../src/components/InputField/InputField.tsx"],"sourcesContent":[".input-field-wrapper {\n align-items: center;\n display: flex;\n position: relative;\n}\n\n.input-field {\n appearance: none;\n background-color: transparent;\n border: 1px solid;\n border-radius: 0.5rem;\n color: var(--color-uva-black);\n flex: 1;\n font-family: inherit;\n font-size: inherit;\n height: 2.75rem;\n margin: 0;\n padding: 0 1rem;\n text-align: inherit;\n}\n\n.input-field--large {\n height: 3rem;\n}\n\n.input-field--small {\n max-width: 5.25rem;\n}\n\n.input-field--compact {\n max-width: 6.25rem;\n}\n\n.input-field--white {\n background-color: var(--color-uva-white);\n}\n\n.input-field--not-valid {\n border-color: var(--color-red-600);\n}\n\n.input-field:disabled {\n color: var(--color-grey-700);\n}\n\n.input-field__clear-button {\n align-items: center;\n background: none;\n border: none;\n cursor: pointer;\n display: flex;\n height: 100%;\n padding: 0 1rem 0 0.5rem;\n position: absolute;\n right: 0;\n}\n","import { forwardRef, useEffect, useRef, useState } from 'react';\nimport { clsx } from 'clsx';\n\nimport type { InputHTMLAttributes, ReactNode } from 'react';\n\nimport styles from './InputField.module.css';\n\nexport interface InputFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'style'> {\n /** The variant to render. */\n variant?: 'large';\n /** The width to render. */\n width?: 'small' | 'compact';\n /** The type of the input element. */\n type?: 'text' | 'password' | 'email';\n /** The background color of the input. InputField is by default transparent. */\n background?: 'white';\n /** The id of the input element. */\n id: string;\n /** An element that represents a clear button. */\n clearTrigger?: ReactNode;\n /** `true` to color border red to show not valid; otherwise, `false`. */\n notValid?: boolean;\n /** The callback that is invoked when the clear button is triggered. */\n onClear?: () => void;\n}\n\n/** Represents a component that renders an input field which can have a clear button. */\nexport const InputField = forwardRef<HTMLInputElement, InputFieldProps>(\n (\n {\n autoComplete = 'off',\n id,\n value,\n variant,\n width,\n type = 'text',\n background,\n clearTrigger,\n notValid = false,\n onClear,\n ...restProps\n }: InputFieldProps,\n forwardedRef\n ) => {\n const [clearButtonWidth, setClearButtonWidth] = useState<number>(0);\n const clearButtonRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n if (clearButtonRef.current) {\n setClearButtonWidth(clearButtonRef.current.offsetWidth);\n }\n }, [value]);\n\n const handleClearTriggerClick = () => {\n if (onClear && forwardedRef && 'current' in forwardedRef && forwardedRef.current) {\n onClear();\n forwardedRef.current.focus();\n }\n };\n\n return (\n <div className={styles['input-field-wrapper']}>\n <input\n {...restProps}\n autoComplete={autoComplete}\n ref={forwardedRef}\n id={id}\n className={clsx(styles['input-field'], {\n [styles['input-field--large']]: variant === 'large',\n [styles[`input-field--${width}`]]: width,\n [styles[`input-field--${background}`]]: background,\n [styles[`input-field--not-valid`]]: notValid,\n })}\n type={type}\n value={value}\n style={{ paddingRight: value && clearTrigger ? clearButtonWidth : undefined }}\n />\n {Boolean(value) && clearTrigger && (\n <button\n type=\"button\"\n className={styles['input-field__clear-button']}\n onClick={handleClearTriggerClick}\n ref={clearButtonRef}\n aria-label={`clear trigger for ${id}`}\n >\n {clearTrigger}\n </button>\n )}\n </div>\n );\n }\n);\n"],"mappings":";;;;;;;;;;;;;GC2Ba,IAAa,GAEtB,EACE,kBAAe,OACf,OACA,UACA,YACA,UACA,UAAO,QACP,eACA,iBACA,cAAW,IACX,YACA,GAAG,KAEL,MACG;CACH,IAAM,CAAC,GAAkB,KAAuB,EAAiB,EAAE,EAC7D,IAAiB,EAA0B,KAAK;AAEtD,SAAgB;AACd,EAAI,EAAe,WACjB,EAAoB,EAAe,QAAQ,YAAY;IAExD,CAAC,EAAM,CAAC;CAEX,IAAM,UAAgC;AACpC,EAAI,KAAW,KAAgB,aAAa,KAAgB,EAAa,YACvE,GAAS,EACT,EAAa,QAAQ,OAAO;;AAIhC,QACE,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACE,kBAAC,SAAD;GACE,GAAI;GACU;GACd,KAAK;GACD;GACJ,WAAW,EAAK,EAAO,gBAAgB;KACpC,EAAO,wBAAwB,MAAY;KAC3C,EAAO,gBAAgB,OAAW;KAClC,EAAO,gBAAgB,OAAgB;KACvC,EAAO,4BAA4B;IACrC,CAAC;GACI;GACC;GACP,OAAO,EAAE,cAAc,KAAS,IAAe,IAAmB,KAAA,GAAW;GAC7E,CAAA,EACD,EAAQ,KAAU,KACjB,kBAAC,UAAD;GACE,MAAK;GACL,WAAW,EAAO;GAClB,SAAS;GACT,KAAK;GACL,cAAY,qBAAqB;aAEhC;GACM,CAAA,CAEP;;EAGX"}
1
+ {"version":3,"file":"InputField-BWAy19w9.js","names":[],"sources":["../src/components/InputField/InputField.module.css","../src/components/InputField/InputField.tsx"],"sourcesContent":[".input-field-wrapper {\n align-items: center;\n display: flex;\n position: relative;\n}\n\n.input-field {\n appearance: none;\n background-color: transparent;\n border: 1px solid;\n border-radius: 0.5rem;\n color: var(--color-uva-black);\n flex: 1;\n font-family: inherit;\n font-size: inherit;\n height: 2.75rem;\n margin: 0;\n padding: 0 1rem;\n text-align: inherit;\n}\n\n.input-field--large {\n height: 3rem;\n}\n\n.input-field--small {\n max-width: 5.25rem;\n}\n\n.input-field--compact {\n max-width: 6.25rem;\n}\n\n.input-field--white {\n background-color: var(--color-uva-white);\n}\n\n.input-field--not-valid {\n border-color: var(--color-red-600);\n}\n\n.input-field:disabled {\n color: var(--color-grey-700);\n}\n\n.input-field__clear-button {\n align-items: center;\n background: none;\n border: none;\n cursor: pointer;\n display: flex;\n height: 100%;\n padding: 0 1rem 0 0.5rem;\n position: absolute;\n right: 0;\n}\n","import { forwardRef, useEffect, useRef, useState } from 'react';\nimport { clsx } from 'clsx';\n\nimport type { InputHTMLAttributes, ReactNode } from 'react';\n\nimport styles from './InputField.module.css';\n\nexport interface InputFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'style'> {\n /** The variant to render. */\n variant?: 'large';\n /** The width to render. */\n width?: 'small' | 'compact';\n /** The type of the input element. */\n type?: 'text' | 'password' | 'email';\n /** The background color of the input. InputField is by default transparent. */\n background?: 'white';\n /** The id of the input element. */\n id: string;\n /** An element that represents a clear button. */\n clearTrigger?: ReactNode;\n /** `true` to color border red to show not valid; otherwise, `false`. */\n notValid?: boolean;\n /** The callback that is invoked when the clear button is triggered. */\n onClear?: () => void;\n}\n\n/** Represents a component that renders an input field which can have a clear button. */\nexport const InputField = forwardRef<HTMLInputElement, InputFieldProps>(\n (\n {\n autoComplete = 'off',\n id,\n value,\n variant,\n width,\n type = 'text',\n background,\n clearTrigger,\n notValid = false,\n onClear,\n ...restProps\n }: InputFieldProps,\n forwardedRef\n ) => {\n const [clearButtonWidth, setClearButtonWidth] = useState<number>(0);\n const clearButtonRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n if (clearButtonRef.current) {\n setClearButtonWidth(clearButtonRef.current.offsetWidth);\n }\n }, [value]);\n\n const handleClearTriggerClick = () => {\n if (onClear && forwardedRef && 'current' in forwardedRef && forwardedRef.current) {\n onClear();\n forwardedRef.current.focus();\n }\n };\n\n return (\n <div className={styles['input-field-wrapper']}>\n <input\n {...restProps}\n autoComplete={autoComplete}\n ref={forwardedRef}\n id={id}\n className={clsx(styles['input-field'], {\n [styles['input-field--large']]: variant === 'large',\n [styles[`input-field--${width}`]]: width,\n [styles[`input-field--${background}`]]: background,\n [styles[`input-field--not-valid`]]: notValid,\n })}\n type={type}\n value={value}\n style={{ paddingRight: value && clearTrigger ? clearButtonWidth : undefined }}\n />\n {Boolean(value) && clearTrigger && (\n <button\n type=\"button\"\n className={styles['input-field__clear-button']}\n onClick={handleClearTriggerClick}\n ref={clearButtonRef}\n aria-label={`clear trigger for ${id}`}\n >\n {clearTrigger}\n </button>\n )}\n </div>\n );\n }\n);\n"],"mappings":";;;;;;;;;;;;;GC2Ba,IAAa,GAEtB,EACE,kBAAe,OACf,OACA,UACA,YACA,UACA,UAAO,QACP,eACA,iBACA,cAAW,IACX,YACA,GAAG,KAEL,MACG;CACH,IAAM,CAAC,GAAkB,KAAuB,EAAiB,EAAE,EAC7D,IAAiB,EAA0B,KAAK;CAEtD,QAAgB;EACd,AAAI,EAAe,WACjB,EAAoB,EAAe,QAAQ,YAAY;IAExD,CAAC,EAAM,CAAC;CAEX,IAAM,UAAgC;EACpC,AAAI,KAAW,KAAgB,aAAa,KAAgB,EAAa,YACvE,GAAS,EACT,EAAa,QAAQ,OAAO;;CAIhC,OACE,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACE,kBAAC,SAAD;GACE,GAAI;GACU;GACd,KAAK;GACD;GACJ,WAAW,EAAK,EAAO,gBAAgB;KACpC,EAAO,wBAAwB,MAAY;KAC3C,EAAO,gBAAgB,OAAW;KAClC,EAAO,gBAAgB,OAAgB;KACvC,EAAO,4BAA4B;IACrC,CAAC;GACI;GACC;GACP,OAAO,EAAE,cAAc,KAAS,IAAe,IAAmB,KAAA,GAAW;GAC7E,CAAA,EACD,EAAQ,KAAU,KACjB,kBAAC,UAAD;GACE,MAAK;GACL,WAAW,EAAO;GAClB,SAAS;GACT,KAAK;GACL,cAAY,qBAAqB;aAEhC;GACM,CAAA,CAEP;;EAGX"}