@ahrowe/ui 0.13.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/common/animatedIcon/animatedIcon.mjs +2 -0
- package/dist/esm/common/animatedIcon/animatedIcon.mjs.map +1 -0
- package/dist/esm/common/animatedIcon/animatedIcon.module.mjs +2 -0
- package/dist/esm/common/animatedIcon/animatedIcon.module.mjs.map +1 -0
- package/dist/esm/common/breadcrumb/breadcrumb.mjs +1 -1
- package/dist/esm/common/breadcrumb/breadcrumb.mjs.map +1 -1
- package/dist/esm/common/buttonGroup/buttonGroup.mjs +2 -0
- package/dist/esm/common/buttonGroup/buttonGroup.mjs.map +1 -0
- package/dist/esm/common/buttonGroup/buttonGroup.module.mjs +2 -0
- package/dist/esm/common/buttonGroup/buttonGroup.module.mjs.map +1 -0
- package/dist/esm/common/buttonGroup/buttonGroup.types.mjs +2 -0
- package/dist/esm/common/buttonGroup/buttonGroup.types.mjs.map +1 -0
- package/dist/esm/common/divider/divider.mjs +1 -1
- package/dist/esm/common/divider/divider.mjs.map +1 -1
- package/dist/esm/common/divider/divider.module.mjs +1 -1
- package/dist/esm/common/divider/divider.module.mjs.map +1 -1
- package/dist/esm/common/divider/divider.types.mjs +1 -1
- package/dist/esm/common/divider/divider.types.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.module.mjs +1 -1
- package/dist/esm/common/dropdown/dropdown.module.mjs.map +1 -1
- package/dist/esm/common/fab/fab.mjs +1 -1
- package/dist/esm/common/fab/fab.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.mjs +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.module.mjs.map +1 -1
- package/dist/esm/common/hooks/useFocusBoundary.mjs +2 -0
- package/dist/esm/common/hooks/useFocusBoundary.mjs.map +1 -0
- package/dist/esm/common/input/input.mjs +1 -1
- package/dist/esm/common/input/input.mjs.map +1 -1
- package/dist/esm/common/input/input.module.mjs +1 -1
- package/dist/esm/common/input/input.module.mjs.map +1 -1
- package/dist/esm/common/input/input.types.mjs +1 -1
- package/dist/esm/common/input/input.types.mjs.map +1 -1
- package/dist/esm/common/interactableDiv/interactableDiv.mjs +1 -1
- package/dist/esm/common/interactableDiv/interactableDiv.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/KanbanBoard.mjs +6 -1
- package/dist/esm/common/kanbanBoard/KanbanBoard.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/KanbanColumn.mjs +1 -1
- package/dist/esm/common/kanbanBoard/KanbanColumn.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/KanbanItem.mjs +1 -1
- package/dist/esm/common/kanbanBoard/KanbanItem.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/kanbanBoard.module.mjs +1 -1
- package/dist/esm/common/kanbanBoard/kanbanBoard.module.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/kanbanBoard.utils.mjs +2 -0
- package/dist/esm/common/kanbanBoard/kanbanBoard.utils.mjs.map +1 -0
- package/dist/esm/common/klipyPicker/klipyPicker.mjs +1 -1
- package/dist/esm/common/klipyPicker/klipyPicker.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs.map +1 -1
- package/dist/esm/common/popover/popover.mjs +1 -1
- package/dist/esm/common/popover/popover.mjs.map +1 -1
- package/dist/esm/common/splitButton/splitButton.mjs +2 -0
- package/dist/esm/common/splitButton/splitButton.mjs.map +1 -0
- package/dist/esm/common/splitButton/splitButton.module.mjs +2 -0
- package/dist/esm/common/splitButton/splitButton.module.mjs.map +1 -0
- package/dist/esm/common/virtualList/useRowDrag.mjs +1 -1
- package/dist/esm/common/virtualList/useRowDrag.mjs.map +1 -1
- package/dist/esm/common/virtualList/useVirtualWindow.mjs +1 -1
- package/dist/esm/common/virtualList/useVirtualWindow.mjs.map +1 -1
- package/dist/esm/common/virtualList/virtualList.mjs +1 -1
- package/dist/esm/common/virtualList/virtualList.mjs.map +1 -1
- package/dist/esm/common/virtualList/virtualRow.mjs +1 -1
- package/dist/esm/common/virtualList/virtualRow.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/index.cjs +9 -4
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/package/common/animatedIcon/animatedIcon.d.ts +3 -0
- package/dist/types/package/common/animatedIcon/animatedIcon.types.d.ts +25 -0
- package/dist/types/package/common/animatedIcon/index.d.ts +2 -0
- package/dist/types/package/common/buttonGroup/buttonGroup.d.ts +4 -0
- package/dist/types/package/common/buttonGroup/buttonGroup.types.d.ts +12 -0
- package/dist/types/package/common/buttonGroup/index.d.ts +2 -0
- package/dist/types/package/common/configProvider/configProvider.types.d.ts +2 -0
- package/dist/types/package/common/divider/divider.types.d.ts +5 -0
- package/dist/types/package/common/hooks/useFocusBoundary.d.ts +20 -0
- package/dist/types/package/common/input/input.types.d.ts +5 -0
- package/dist/types/package/common/kanbanBoard/KanbanBoard.d.ts +1 -1
- package/dist/types/package/common/kanbanBoard/KanbanColumn.d.ts +29 -1
- package/dist/types/package/common/kanbanBoard/KanbanItem.d.ts +2 -6
- package/dist/types/package/common/kanbanBoard/kanbanBoard.types.d.ts +71 -5
- package/dist/types/package/common/kanbanBoard/kanbanBoard.utils.d.ts +60 -0
- package/dist/types/package/common/splitButton/index.d.ts +2 -0
- package/dist/types/package/common/splitButton/splitButton.d.ts +3 -0
- package/dist/types/package/common/splitButton/splitButton.types.d.ts +28 -0
- package/dist/types/package/common/themeProvider/theme.types.d.ts +3 -0
- package/dist/types/package/common/virtualList/useRowDrag.d.ts +4 -0
- package/dist/types/package/common/virtualList/useVirtualWindow.d.ts +3 -1
- package/dist/types/package/common/virtualList/virtualList.types.d.ts +5 -1
- package/dist/types/package/common/virtualList/virtualRow.d.ts +8 -1
- package/dist/types/package/index.d.ts +4 -0
- package/docs/ButtonGroup.md +90 -0
- package/docs/CLAUDE.md +2 -0
- package/docs/Divider.md +15 -3
- package/docs/FloatingMenu.md +7 -3
- package/docs/Input.md +30 -6
- package/docs/KanbanBoard.md +129 -4
- package/docs/NumberInput.md +2 -0
- package/docs/SearchInput.md +6 -0
- package/docs/SplitButton.md +79 -0
- package/docs/VirtualList.md +86 -3
- package/package.json +2 -4
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../package/common/accordion/accordion.types.ts","../package/common/accordion/accordion.module.pcss","../package/common/accordion/accordion.primary.module.pcss","../package/common/accordion/accordion.plain.module.pcss","../package/common/configProvider/configProvider.tsx","../package/common/configProvider/useComponentDefaults.ts","../package/common/accordion/accordion.tsx","../package/common/actionButtons/actionButtons.module.pcss","../package/common/button/button.module.pcss","../package/common/loading/spinnerLoading/spinnerLoading.module.pcss","../package/common/loading/spinnerLoading/spinnerLoading.tsx","../package/common/loading/spinnerLoading/index.ts","../package/common/button/button.types.ts","../package/common/ripple/ripple.module.pcss","../package/common/ripple/ripple.tsx","../package/common/button/button.tsx","../package/common/actionButtons/actionButtons.tsx","../package/common/interactableDiv/interactableDiv.module.pcss","../package/common/interactableDiv/interactableDiv.tsx","../package/common/interactableDiv/index.ts","../package/common/actionIcon/actionIcon.module.pcss","../package/common/actionIcon/actionIcon.tsx","../package/common/alert/alert.types.ts","../package/common/alert/alert.module.pcss","../package/common/alert/alert.tsx","../package/common/animatedLogo/animatedLogo.module.pcss","../package/common/animatedLogo/animatedLogo.tsx","../package/common/animatedText/animatedText.types.ts","../package/common/animatedText/animatedText.module.pcss","../package/common/animatedText/animatedText.tsx","../package/common/badge/badge.types.ts","../package/common/badge/badge.module.pcss","../package/common/badge/badge.tsx","../package/common/avatar/avatar.module.pcss","../package/common/avatar/avatar.tsx","../package/common/avatar/avatarGroup.tsx","../package/common/bodyEnd/bodyEnd.tsx","../package/common/floatingMenu/floatingMenu.module.pcss","../package/common/utils/scrollAncestors.ts","../package/common/floatingMenu/useFloatingPosition.ts","../package/common/floatingMenu/floatingMenu.types.ts","../package/common/floatingMenu/floatingMenu.tsx","../package/common/breadcrumb/breadcrumb.module.pcss","../package/common/breadcrumb/breadcrumb.tsx","../package/common/card/card.types.ts","../package/common/card/card.module.pcss","../package/common/card/Card.tsx","../package/common/card/CardHeader.tsx","../package/common/card/CardMedia.tsx","../package/common/card/CardContent.tsx","../package/common/card/CardActions.tsx","../package/common/carousel/carousel.module.pcss","../package/common/carousel/carousel.tsx","../package/common/checkbox/checkbox.module.pcss","../package/common/checkbox/checkbox.tsx","../package/common/chip/chip.types.ts","../package/common/chip/chip.module.pcss","../package/common/chip/chip.tsx","../package/common/chip/chipContainer.tsx","../package/common/tooltip/tooltip.module.pcss","../package/common/tooltip/tooltip.tsx","../package/common/input/input.module.pcss","../package/common/input/input.types.ts","../package/common/input/input.tsx","../package/common/colorPicker/colorPicker.module.pcss","../package/common/colorPicker/colorPicker.tsx","../package/common/modal/modal.module.pcss","../package/common/modal/modal.tsx","../package/common/confirmModal/confirmModal.tsx","../package/common/datePicker/components/datePickerMonth/datePickerMonth.module.pcss","../package/services/localization.ts","../package/common/datePicker/dateFunctions.ts","../package/common/datePicker/components/datePickerMonth/datePickerMonth.tsx","../package/common/infiniteBlock/infiniteBlock.module.pcss","../package/common/infiniteBlock/infiniteBlock.tsx","../package/common/dropdown/dropdown.module.pcss","../package/common/dropdown/dropdown.tsx","../package/common/datePicker/datePicker.module.pcss","../package/common/datePicker/datePicker.tsx","../package/common/divider/divider.types.ts","../package/common/divider/divider.module.pcss","../package/common/divider/divider.tsx","../package/common/drawer/drawer.module.pcss","../package/common/drawer/drawer.tsx","../package/common/dropZone/dropZone.types.ts","../package/common/dropZone/dropZone.module.pcss","../package/common/dropZone/dropZone.tsx","../package/common/emptyState/emptyState.module.pcss","../package/common/emptyState/emptyState.tsx","../package/common/fab/components/fabBase/fabBase.module.pcss","../package/common/fab/components/fabBase/fabBase.tsx","../package/common/fab/fab.module.pcss","../package/common/fab/fab.tsx","../package/common/iconPicker/iconPicker.module.pcss","../package/common/iconPicker/iconPicker.tsx","../package/common/idleManager/idleManager.tsx","../package/common/inputDropdown/inputDropdown.module.pcss","../package/common/inputDropdown/inputDropdown.tsx","../package/common/kanbanBoard/kanbanBoard.module.pcss","../package/common/kanbanBoard/KanbanItem.tsx","../package/common/kanbanBoard/KanbanColumn.tsx","../package/common/kanbanBoard/KanbanBoard.tsx","../package/services/klipy.ts","../package/common/searchInput/searchInput.module.pcss","../package/common/searchInput/searchInput.tsx","../package/common/klipyPicker/components/gifPreview/gifPreview.module.pcss","../package/common/klipyPicker/components/gifPreview/gifPreview.tsx","../package/common/klipyPicker/components/gifView/gifView.module.pcss","../package/common/klipyPicker/components/gifView/gifView.tsx","../package/common/klipyPicker/klipyPicker.module.pcss","../package/common/klipyPicker/klipyPicker.tsx","../package/common/loading/iconLoading/iconLoading.module.pcss","../package/common/loading/iconLoading/iconLoading.tsx","../package/common/loading/iconLoading/index.ts","../package/common/numberInput/numberInput.module.pcss","../package/common/numberInput/numberInput.tsx","../package/common/numberInput/index.ts","../package/common/optionPicker/optionPicker.module.pcss","../package/common/optionPicker/optionPicker.tsx","../package/hooks/useWindowSize.ts","../package/common/overscroll/overscroll.module.pcss","../package/common/overscroll/overscroll.tsx","../package/common/popover/popover.module.pcss","../package/common/popover/popover.types.ts","../package/common/popover/usePopoverPosition.ts","../package/common/popover/popover.tsx","../package/common/progressBar/progressBar.module.pcss","../package/common/progressBar/progressBar.tsx","../package/common/radioGroup/radioGroup.types.ts","../package/common/radioGroup/radioGroup.module.pcss","../package/common/radioGroup/radioGroup.tsx","../package/common/rating/rating.module.pcss","../package/common/rating/rating.tsx","../package/common/roomDrawer/roomDrawer.utils.ts","../package/common/roomDrawer/roomDrawer.module.pcss","../package/common/roomDrawer/roomDrawer.tsx","../package/common/roomViewer/roomViewer.module.pcss","../package/common/roomViewer/roomViewer.tsx","../package/common/scrollbarProvider/scrollbarProvider.module.pcss","../package/common/scrollbarProvider/scrollbarProvider.tsx","../package/common/scrollbarProvider/index.ts","../package/common/sectionHeader/sectionHeader.types.ts","../package/common/sectionHeader/sectionHeader.module.pcss","../package/common/sectionHeader/sectionHeader.tsx","../package/common/skeleton/skeleton.types.ts","../package/common/skeleton/skeleton.module.pcss","../package/common/skeleton/skeleton.tsx","../package/common/slider/slider.module.pcss","../package/common/slider/slider.tsx","../package/common/stepper/stepper.module.pcss","../package/common/stepper/stepper.types.ts","../package/common/stepper/stepper.tsx","../package/common/sticky/stickyStack.ts","../package/common/sticky/sticky.module.pcss","../package/common/sticky/sticky.tsx","../package/common/switch/switch.module.pcss","../package/common/switch/switch.tsx","../package/common/tabHeader/tabHeader.module.pcss","../package/common/tabHeader/tabHeader.tsx","../package/common/textarea/textarea.tsx","../package/common/themeProvider/defaultTheme.ts","../package/common/themeProvider/theme.module.pcss","../package/common/themeProvider/themeProvider.tsx","../package/common/themeProvider/useTheme.ts","../package/common/timeInput/timeFunctions.ts","../package/common/timeInput/components/clockDial/clockDial.module.pcss","../package/common/timeInput/components/clockDial/clockDial.tsx","../package/common/timeInput/timeInput.module.pcss","../package/common/timeInput/timeInput.tsx","../package/common/toast/toast.module.pcss","../package/common/hooks/useSwipeDismiss.ts","../package/common/toast/toast.tsx","../package/common/toast/toastService.ts","../package/common/toast/toastProvider.tsx","../package/common/virtualList/virtualList.module.pcss","../package/common/virtualList/virtualRow.tsx","../package/common/virtualList/virtualList.utils.ts","../package/common/virtualList/useVirtualWindow.ts","../package/common/virtualList/useSelection.ts","../package/common/virtualList/useColumns.ts","../package/common/virtualList/useRowDrag.ts","../package/common/virtualList/virtualList.tsx","../package/common/wizard/wizard.module.pcss","../package/common/wizard/wizard.tsx","../package/services/formValidation/FormValidatorGroupWithForm.tsx","../package/services/formValidation/validatableComponent.tsx","../package/services/formValidation/useFormValidatorGroup.ts"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum AccordionStyleType {\n Default = 'default',\n Primary = 'primary',\n Plain = 'plain',\n}\n\nexport type AccordionSlots = 'root' | 'header' | 'title' | 'icon' | 'body' | 'bodyInner';\n\nexport interface AccordionProps extends HtmlProps {\n title?: string;\n children?: ReactNode;\n expanded?: boolean | null;\n onHeaderClicked?: (id: string, isExpanded: boolean) => void;\n styleType?: AccordionStyleType;\n startOpen?: boolean;\n hideHeader?: boolean;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<AccordionSlots>;\n styles?: SlotStyles<AccordionSlots>;\n}\n","\n.accordion {\n transition: margin 0.2s;\n margin: -1px;\n color: var(--text-color);\n\n &-title {\n width: 100%;\n }\n\n &-active {\n margin: 10px 0;\n }\n\n &-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background: var(--background);\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n font-size: 16px;\n font-weight: 400;\n transition: all 0.2s;\n\n &-active {\n border: 1px solid var(--primary-color);\n background: var(--background-accent);\n border-radius: var(--default-border-radius) var(--default-border-radius) 0px 0px;\n }\n }\n\n &-body {\n overflow: hidden;\n transition: all 0.2s ease;\n position: relative;\n border-radius: 0px 0px var(--default-border-radius) var(--default-border-radius);\n border: 1px solid var(--border-color);\n border-top: none;\n border-bottom: none;\n\n &-inner {\n padding: 16px;\n }\n\n &-active {\n border: 1px solid var(--primary-color);\n border-top: none;\n }\n }\n\n &-icon {\n transition: transform 0.2s;\n transform: rotate(0deg);\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n color: var(--border-color);\n &-active {\n transform: rotate(180deg);\n }\n }\n}\n","\n.accordion {\n transition: margin 0.2s;\n margin: -1px;\n\n &-title {\n width: 100%;\n }\n\n &-active {\n margin: 10px 0;\n border: 2px solid var(--primary-color);\n border-radius: var(--default-border-radius);\n }\n\n &-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background: var(--background);\n border-radius: var(--default-border-radius);\n font-size: 16px;\n font-weight: 400;\n transition: all 0.2s;\n\n &-active {\n background: var(--background-accent);\n border-radius: var(--default-border-radius) var(--default-border-radius) 0px 0px;\n }\n }\n\n &-body {\n overflow: hidden;\n transition: all 0.2s ease;\n position: relative;\n border-radius: 0px 0px var(--default-border-radius) var(--default-border-radius);\n border-top: none;\n border-bottom: none;\n\n &-inner {\n padding: 16px;\n }\n\n &-active {\n border-top: none;\n }\n }\n\n &-icon {\n transition: transform 0.2s;\n transform: rotate(0deg);\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n color: var(--primary-color);\n &-active {\n transform: rotate(180deg);\n }\n }\n}\n","\n.accordion {\n transition: margin 0.2s;\n margin: -1px;\n\n &-title {\n width: 100%;\n }\n\n &-active {\n margin: 10px 0;\n }\n\n &-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n border-radius: var(--default-border-radius);\n font-size: 16px;\n font-weight: 400;\n transition: all 0.2s;\n\n &-active {\n border-radius: var(--default-border-radius) var(--default-border-radius) 0px 0px;\n }\n }\n\n &-body {\n overflow: hidden;\n transition: all 0.2s ease;\n position: relative;\n border-radius: 0px 0px var(--default-border-radius) var(--default-border-radius);\n\n &-inner {\n padding: 0px;\n }\n }\n\n &-icon {\n transition: transform 0.2s;\n transform: rotate(0deg);\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n color: var(--primary-color);\n &-active {\n transform: rotate(180deg);\n }\n }\n}\n","import React, { createContext, useContext, useMemo } from 'react';\nimport type { ComponentDefaults, ConfigProviderProps } from './configProvider.types';\n\nexport const ConfigContext = createContext<ComponentDefaults | null>(null);\n\n/**\n * Shallow-merge two default maps per component key, so nested ConfigProviders\n * compose: an inner provider's `Input` defaults extend (and override on\n * conflict) the outer provider's `Input` defaults rather than replacing them.\n */\nfunction mergeDefaults(\n parent: ComponentDefaults | null,\n own: ComponentDefaults | undefined,\n): ComponentDefaults {\n if (!parent) return own ?? {};\n if (!own) return parent;\n\n const merged: Record<string, object> = { ...parent };\n for (const key in own) {\n merged[key] = {\n ...(parent as Record<string, object>)[key],\n ...(own as Record<string, object>)[key],\n };\n }\n return merged as ComponentDefaults;\n}\n\nfunction ConfigProvider({ children, defaultProps }: ConfigProviderProps) {\n const parent = useContext(ConfigContext);\n const value = useMemo(() => mergeDefaults(parent, defaultProps), [parent, defaultProps]);\n\n return <ConfigContext.Provider value={value}>{children}</ConfigContext.Provider>;\n}\n\nexport default ConfigProvider;\n","import { useContext } from 'react';\nimport { ConfigContext } from './configProvider';\nimport type { ComponentDefaults } from './configProvider.types';\n\n/**\n * Merge global defaults from the nearest `ConfigProvider` **under** the props\n * the caller actually passed: an explicit prop always wins, a global default\n * fills in only props the caller left `undefined`, and the component's own\n * built-in default (its destructuring default) applies when neither is set.\n *\n * Call it at the very top of a component and destructure from the result\n * instead of from the raw props:\n *\n * ```tsx\n * function Input(props: InputProps) {\n * const { alwaysFloatLabel = false, ... } = useComponentDefaults('Input', props);\n * }\n * ```\n */\nexport function useComponentDefaults<P extends object>(\n component: keyof ComponentDefaults,\n props: P,\n): P {\n const ctx = useContext(ConfigContext);\n const defaults = ctx?.[component];\n if (!defaults) return props;\n\n const merged: Record<string, unknown> = { ...defaults };\n for (const key in props) {\n const value = (props as Record<string, unknown>)[key];\n if (value !== undefined) merged[key] = value;\n }\n return merged as P;\n}\n","import React, { useState, useEffect, useRef, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronDown as arrowIcon } from '@fortawesome/free-solid-svg-icons';\n\nimport { AccordionStyleType, type AccordionProps } from './accordion.types';\n\nimport defaultStyles from './accordion.module.pcss';\nimport primaryStyles from './accordion.primary.module.pcss';\nimport plainStyles from './accordion.plain.module.pcss';\nimport { useComponentDefaults } from '../configProvider';\n\nconst STYLES_BY_TYPE: Record<AccordionStyleType, typeof defaultStyles> = {\n [AccordionStyleType.Default]: defaultStyles,\n [AccordionStyleType.Primary]: primaryStyles,\n [AccordionStyleType.Plain]: plainStyles,\n};\n\nfunction Accordion(props: AccordionProps): ReactElement {\n const {\n id = '',\n title = '',\n children = null,\n expanded = null,\n onHeaderClicked = () => {},\n styleType = AccordionStyleType.Default,\n startOpen = false,\n hideHeader = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Accordion', props);\n const s = STYLES_BY_TYPE[styleType];\n const bodyRef = useRef<HTMLDivElement>(null);\n\n const [isExpanded, setIsExpanded] = useState(expanded ?? startOpen);\n const [bodyHeight, setBodyHeight] = useState<number | null>(null);\n\n // Sync controlled expanded prop\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n if (expanded !== null) setIsExpanded(expanded);\n }, [expanded]);\n\n // Measure body height via ResizeObserver\n useEffect(() => {\n const el = bodyRef.current;\n if (!el) return;\n const observer = new ResizeObserver(() => setBodyHeight(el.offsetHeight));\n observer.observe(el);\n return () => observer.unobserve(el);\n }, []);\n\n function toggleExpanded() {\n const next = !isExpanded;\n onHeaderClicked(id, next);\n if (expanded === null) setIsExpanded(next);\n }\n\n const headerHeight = 24;\n const headerStyle = { height: `${isExpanded ? headerHeight + headerHeight / 3 : headerHeight}px` };\n const bodyStyle = { height: isExpanded ? (bodyHeight ?? 'auto') : '0px' };\n\n return (\n <div {...rest} id={id || undefined} className={cx(s.accordion, isExpanded && s.accordionActive, className, classNames?.root)} style={{ ...style, ...slotStyles?.root }}>\n {!hideHeader && (\n <div\n className={cx(s.accordionHeader, isExpanded && s.accordionHeaderActive, classNames?.header)}\n style={{ ...headerStyle, ...slotStyles?.header }}\n onClick={toggleExpanded}\n role=\"button\"\n tabIndex={0}\n onKeyDown={({ key }) => { if (key === 'Enter') toggleExpanded(); }}\n >\n <div className={cx(s.accordionTitle, classNames?.title)} style={slotStyles?.title}>{title}</div>\n <FontAwesomeIcon\n icon={arrowIcon}\n className={cx(s.accordionIcon, isExpanded && s.accordionIconActive, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </div>\n )}\n <div\n className={cx(s.accordionBody, isExpanded && s.accordionBodyActive, classNames?.body)}\n style={{ ...bodyStyle, ...slotStyles?.body }}\n >\n <div className={cx(s.accordionBodyInner, classNames?.bodyInner)} style={slotStyles?.bodyInner} ref={bodyRef}>\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nexport default Accordion;\n","\n.actionButtons {\n display: flex;\n gap: var(--spacing-m);\n\n @media (--mq-mobile) {\n flex-direction: column;\n }\n\n &-margin {\n margin-top: var(--spacing-l);\n }\n}\n",".button {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n font-size: 16px;\n background: transparent;\n color: var(--text-color);\n border: 1px solid transparent;\n padding: 0;\n font-family: var(--default-font);\n border-radius: var(--default-border-radius);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n position: relative;\n overflow: hidden;\n\n &-notAllowed {\n cursor: not-allowed;\n filter: opacity(0.8);\n }\n\n &-loading-icon {\n width: 100% !important;\n height: 100% !important;\n }\n\n &-content {\n position: relative;\n white-space: break-spaces;\n\n div {\n text-overflow: ellipsis;\n overflow: hidden;\n }\n }\n\n &-loading {\n visibility: hidden;\n\n &-container {\n position: absolute;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n }\n\n &-withIcon {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-s);\n }\n\n &-style {\n &-default {\n background: var(--button-default-background, transparent);\n color: var(--button-default-color, var(--text-color));\n border: var(--button-default-border, 1px solid transparent);\n }\n\n &-primary {\n background: var(--primary-color);\n color: var(--text-color);\n color: var(--text-on-primary);\n\n .button-loading-icon {\n stroke: var(--text-on-primary);\n }\n }\n\n &-delete {\n background: var(--error-color);\n color: var(--text-on-delete);\n\n .button-loading-icon {\n stroke: var(--text-on-delete);\n }\n }\n }\n\n &-background {\n display: block;\n padding: 8px 12px;\n }\n\n &-size {\n &-default {\n font-size: 16px;\n }\n\n &-small {\n /* Small button is same as default for now */\n font-size: 12px;\n\n &-background {\n display: block;\n padding: 0px;\n }\n }\n\n &-medium {\n /* Medium button is same as default for now */\n font-size: 16px;\n }\n\n &-large {\n /* Large button is same as default for now */\n font-size: 20px;\n }\n }\n}\n",".spinner-loading {\n width: 70px;\n height: 70px;\n\n circle {\n stroke-dasharray: 283;\n stroke-dashoffset: 281;\n stroke-linecap: round;\n animation:\n animate-spinner 2s cubic-bezier(0.89, 0.01, 0.12, 1) infinite,\n spin 3s linear infinite;\n transform-origin: center;\n }\n\n @keyframes animate-spinner {\n 0% {\n stroke-dashoffset: 281;\n }\n\n 50% {\n stroke-dashoffset: 0;\n }\n\n 100% {\n stroke-dashoffset: -281;\n }\n }\n\n @keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(360deg);\n }\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport styles from './spinnerLoading.module.pcss';\n\ninterface Properties {\n className?: string | undefined;\n}\n\nfunction SpinnerLoading({ className }: Properties): ReactElement {\n return (\n <svg\n data-testid=\"spinner\"\n className={cx(styles.spinnerLoading, className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 100 100\"\n fill=\"none\"\n stroke=\"var(--primary-color)\"\n >\n <circle cx=\"50\" cy=\"50\" r=\"45\" strokeWidth=\"10\" />\n </svg>\n );\n}\n\nSpinnerLoading.defaultProps = {\n className: undefined,\n};\n\nexport default SpinnerLoading;\n","import SpinnerLoading from './spinnerLoading';\n\nexport default SpinnerLoading;\n","import type { CSSProperties } from 'react';\nimport type { IconDefinition } from '@fortawesome/free-solid-svg-icons';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum ButtonStyleType {\n Primary = 'primary',\n Default = 'default',\n Delete = 'delete',\n}\n\nexport enum ButtonSize {\n Default = 'default',\n Small = 'small',\n Medium = 'medium',\n Large = 'large',\n}\n\nexport enum ButtonType {\n Button = 'button',\n Reset = 'reset',\n Submit = 'submit',\n}\n\nexport type ButtonSlots = 'background' | 'content' | 'loadingContainer' | 'label';\n\nexport interface ButtonProps extends HtmlProps {\n className?: string;\n style?: CSSProperties;\n type?: ButtonType;\n styleType?: ButtonStyleType;\n size?: ButtonSize;\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => Promise<void> | void;\n children?: React.ReactNode;\n icon?: IconDefinition;\n isLoading?: boolean;\n disabled?: boolean;\n title?: string;\n ref?: React.Ref<HTMLButtonElement>;\n classNames?: SlotClassNames<ButtonSlots>;\n styles?: SlotStyles<ButtonSlots>;\n}\n",".ripple {\n background: rgba(255, 255, 255, 0.2);\n border-radius: 1000px;\n width: 100%;\n aspect-ratio: 1;\n position: absolute;\n left: 0;\n top: 0;\n transform: translate(-50%, -50%) scale(0);\n animation: ripple var(--ripple-animation-length) linear forwards;\n\n &-container {\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n border-radius: inherit;\n user-select: none;\n pointer-events: none;\n }\n\n @keyframes ripple {\n to {\n transform: translate(-50%, -50%) scale(4);\n opacity: 0;\n }\n }\n}\n","import React, { useRef, useEffect, useImperativeHandle, forwardRef } from 'react';\n\nimport styles from './ripple.module.pcss';\nimport type { RippleProps, RippleHandle } from './ripple.types';\n\nexport type { RippleProps, RippleHandle };\n\nconst Ripple = forwardRef<RippleHandle, RippleProps>(function Ripple({\n disabled = false,\n children,\n className,\n style,\n overflowHidden = true,\n rippleAnimationLength = 0.6,\n rippleBackground = 'rgba(255, 255, 255, 0.2)',\n manualOnly = false,\n ...rest\n}, ref) {\n const containerRef = useRef<HTMLDivElement>(null);\n const addRippleRef = useRef<((event: MouseEvent) => void) | null>(null);\n\n function spawnRipple(x: number, y: number) {\n if (disabled) return;\n const ripple = document.createElement('div');\n ripple.style.left = `${x}px`;\n ripple.style.top = `${y}px`;\n ripple.style.background = rippleBackground;\n ripple.classList.add(styles.ripple);\n containerRef.current?.appendChild(ripple);\n setTimeout(() => {\n containerRef.current?.removeChild(ripple);\n }, rippleAnimationLength * 1000 + 50);\n }\n\n function addRipple(event: MouseEvent | React.MouseEvent) {\n if (!containerRef.current) return;\n const pos = containerRef.current.getBoundingClientRect();\n spawnRipple(event.clientX - pos.x, event.clientY - pos.y);\n }\n\n useImperativeHandle(ref, () => ({\n addRipple() {\n const el = containerRef.current;\n if (!el) return;\n spawnRipple(el.offsetWidth / 2, el.offsetHeight / 2);\n },\n }));\n\n useEffect(() => {\n addRippleRef.current = addRipple;\n });\n\n useEffect(() => {\n if (children !== undefined || manualOnly) return;\n const parent = containerRef.current?.parentElement;\n if (!parent) return;\n const handler = (e: MouseEvent) => addRippleRef.current?.(e);\n parent.addEventListener('click', handler);\n return () => parent.removeEventListener('click', handler);\n }, [children, manualOnly]);\n\n const containerStyle: React.CSSProperties & { '--ripple-animation-length'?: string } = {\n '--ripple-animation-length': `${rippleAnimationLength}s`,\n };\n\n if (children !== undefined) {\n return (\n <div\n {...rest}\n className={className}\n onClick={manualOnly ? undefined : (e) => addRipple(e)}\n style={{\n position: 'relative',\n ...style,\n }}\n >\n {children}\n <div\n className={styles.rippleContainer}\n ref={containerRef}\n style={{\n overflow: overflowHidden ? 'hidden' : 'visible',\n ...containerStyle,\n }}\n />\n </div>\n );\n }\n\n return (\n <div\n className={styles.rippleContainer}\n ref={containerRef}\n style={{\n overflow: overflowHidden ? 'hidden' : 'visible',\n ...containerStyle,\n }}\n />\n );\n});\n\nexport default Ripple;\n","import cx from 'classnames';\nimport type { ReactElement } from 'react';\n\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport styles from './button.module.pcss';\nimport SpinnerLoading from 'components/common/loading/spinnerLoading';\nimport { ButtonStyleType, ButtonSize, ButtonType } from './button.types';\nimport type { ButtonProps } from './button.types';\nimport Ripple from '../ripple';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_STYLE: Record<ButtonStyleType, string> = {\n default: styles.buttonStyleDefault,\n primary: styles.buttonStylePrimary,\n delete: styles.buttonStyleDelete,\n};\n\nconst CLASS_BY_SIZE: Record<ButtonSize, string> = {\n default: styles.buttonSizeDefault,\n small: styles.buttonSizeSmall,\n medium: styles.buttonSizeMedium,\n large: styles.buttonSizeLarge,\n};\n\nfunction Button(props: ButtonProps): ReactElement {\n const {\n className,\n style,\n type = ButtonType.Button,\n styleType = ButtonStyleType.Default,\n size = ButtonSize.Default,\n onClick = (): void => {},\n children,\n icon,\n isLoading = false,\n disabled = false,\n title = undefined,\n ref,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Button', props);\n return (\n <button\n {...rest}\n className={cx(\n styles.button,\n CLASS_BY_STYLE[styleType],\n CLASS_BY_SIZE[size],\n {\n [styles.buttonNotAllowed]: isLoading || disabled,\n },\n className\n )}\n style={style}\n type={type}\n onClick={onClick}\n disabled={disabled || isLoading}\n title={title}\n ref={ref}\n >\n <Ripple disabled={isLoading || disabled}>\n <div className={cx(styles.buttonBackground, classNames?.background)} style={slotStyles?.background}>\n <div className={cx(styles.buttonContent, classNames?.content)} style={slotStyles?.content}>\n {isLoading ? (\n <div className={cx(styles.buttonLoadingContainer, classNames?.loadingContainer)} style={slotStyles?.loadingContainer}>\n <SpinnerLoading className={styles.buttonLoadingIcon} />\n </div>\n ) : null}\n <div\n className={cx(classNames?.label, {\n [styles.buttonLoading]: isLoading,\n [styles.buttonWithIcon]: !!icon,\n })}\n style={slotStyles?.label}\n >\n {icon ? <FontAwesomeIcon icon={icon} /> : null}\n {children}\n </div>\n </div>\n </div>\n </Ripple>\n </button>\n );\n}\n\nButton.StyleType = ButtonStyleType;\nButton.Size = ButtonSize;\nButton.Type = ButtonType;\n\nexport default Button;\n","import cx from 'classnames';\n\nimport styles from './actionButtons.module.pcss';\nimport Button, { ButtonStyleType, ButtonType } from '../button';\nimport { useComponentDefaults } from '../configProvider';\nimport { ActionButtonsProps } from './actionButtons.types';\n\nexport default function ActionButtons(props: ActionButtonsProps) {\n const {\n onSubmit = () => null,\n onClose = () => null,\n submitLabel = 'Save',\n cancelLabel = 'Cancel',\n submitButtonStyle = ButtonStyleType.Primary,\n isSubmitButtonLoading = false,\n isSubmitButtonDisabled = false,\n submitButtonIcon = undefined,\n cancelButtonStyle = ButtonStyleType.Default,\n isCancelButtonLoading = false,\n isCancelButtonDisabled = false,\n cancelButtonIcon = undefined,\n hidePrimaryButton = false,\n hideSecondaryButton = false,\n noMargin = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('ActionButtons', props);\n return (\n <div\n {...rest}\n className={cx(styles.actionButtons, !noMargin && styles.actionButtonsMargin, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {!hidePrimaryButton && (\n <Button\n isLoading={isSubmitButtonLoading}\n disabled={isSubmitButtonDisabled}\n styleType={submitButtonStyle}\n type={ButtonType.Submit}\n onClick={onSubmit}\n className={classNames?.submitButton}\n style={slotStyles?.submitButton}\n icon={submitButtonIcon}\n >\n {submitLabel}\n </Button>\n )}\n {!hideSecondaryButton && (\n <Button\n isLoading={isCancelButtonLoading}\n disabled={isCancelButtonDisabled}\n onClick={onClose}\n styleType={cancelButtonStyle}\n className={classNames?.cancelButton}\n style={slotStyles?.cancelButton}\n icon={cancelButtonIcon}\n >\n {cancelLabel}\n </Button>\n )}\n </div>\n );\n}",".interactableDiv {\n}\n","import cx from 'classnames';\nimport React, {\n ReactNode,\n useCallback,\n type KeyboardEvent,\n type KeyboardEventHandler,\n type MouseEvent,\n type MouseEventHandler,\n type ReactElement,\n} from 'react';\n\nimport styles from './interactableDiv.module.pcss';\nimport type { HtmlProps } from '../types/baseProps.types';\n\ninterface Properties extends HtmlProps {\n className?: string | undefined;\n children?: ReactNode | undefined;\n onClick?: MouseEventHandler<HTMLDivElement> | undefined;\n onMouseDown?: MouseEventHandler<HTMLDivElement> | undefined;\n onKeyDown?: KeyboardEventHandler<HTMLDivElement> | undefined;\n style?: React.CSSProperties | undefined;\n tabIndex?: number | null;\n title?: string | undefined;\n}\n\nconst InteractableDiv = React.forwardRef<HTMLDivElement, Properties>(\n ({ className, children, onClick, onMouseDown, onKeyDown, tabIndex = 0, title, ...props }, ref): ReactElement => {\n const onKeyDownHandler = useCallback(\n (e: KeyboardEvent<HTMLDivElement> | MouseEvent<HTMLDivElement>) => {\n if ((e as React.KeyboardEvent).key === 'Enter') {\n onClick?.(e as MouseEvent<HTMLDivElement>);\n }\n onKeyDown?.(e as KeyboardEvent<HTMLDivElement>);\n },\n [onClick, onKeyDown]\n );\n\n return (\n <div\n className={cx(styles.interactableDiv, className)}\n onClick={onClick}\n onMouseDown={onMouseDown}\n tabIndex={tabIndex == undefined ? 0 : tabIndex}\n role=\"button\"\n onKeyDown={onKeyDownHandler}\n ref={ref}\n title={title}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nInteractableDiv.displayName = 'InteractableDiv';\n\nexport default InteractableDiv;\n","import InteractableDiv from './interactableDiv';\n\nexport default InteractableDiv;\n",".actionIcon {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 4px;\n &:hover {\n filter: brightness(0.8);\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport type { ReactElement } from 'react';\n\nimport InteractableDiv from '../interactableDiv';\nimport type { ActionIconProps } from './actionIcon.types';\nimport styles from './actionIcon.module.pcss';\n\nfunction ActionIcon({\n icon,\n className = '',\n style,\n title = '',\n onClick = () => {},\n classNames,\n styles: slotStyles,\n ...rest\n}: ActionIconProps): ReactElement {\n return (\n <InteractableDiv\n {...rest}\n className={cx(styles.actionIcon, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n title={title}\n onClick={onClick}\n >\n <FontAwesomeIcon\n icon={icon}\n className={classNames?.icon}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </InteractableDiv>\n );\n}\n\nexport default ActionIcon;\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { IconDefinition } from '@fortawesome/fontawesome-svg-core';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum AlertStyleType {\n Default = 'default',\n Info = 'info',\n Success = 'success',\n Warn = 'warn',\n Error = 'error',\n}\n\nexport type AlertSlots = 'root' | 'icon' | 'content' | 'title' | 'description' | 'closeButton';\n\nexport interface AlertProps extends HtmlProps {\n title?: ReactNode;\n children?: ReactNode;\n styleType?: AlertStyleType;\n icon?: IconDefinition;\n hideIcon?: boolean;\n onClose?: () => void;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<AlertSlots>;\n styles?: SlotStyles<AlertSlots>;\n}\n",".alert {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 14px;\n border-radius: var(--default-border-radius);\n background: var(--background-accent);\n color: var(--text-color);\n font-family: var(--default-font);\n box-sizing: border-box;\n\n &-icon {\n flex-shrink: 0;\n margin-top: 2px;\n font-size: 15px;\n }\n\n &-content {\n flex: 1;\n font-size: 14px;\n line-height: 1.4;\n }\n\n &-title {\n font-weight: var(--header-font-weight, 600);\n\n &:not(:only-child) {\n margin-bottom: 2px;\n }\n }\n\n &-description {\n color: var(--text-dark);\n }\n\n &-closeButton {\n flex-shrink: 0;\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 0;\n color: var(--text-dark);\n font-size: 13px;\n opacity: 0.6;\n transition: opacity 0.15s;\n margin-top: 2px;\n\n &:hover {\n opacity: 1;\n }\n }\n\n &-style {\n &-default {\n border-left: 3px solid var(--primary-color);\n\n .alert-icon {\n color: var(--primary-color);\n }\n }\n\n &-info {\n border-left: 3px solid var(--info-color, #3b82f6);\n\n .alert-icon {\n color: var(--info-color, #3b82f6);\n }\n }\n\n &-success {\n border-left: 3px solid var(--success-color);\n\n .alert-icon {\n color: var(--success-color);\n }\n }\n\n &-warn {\n border-left: 3px solid var(--warn-color);\n\n .alert-icon {\n color: var(--warn-color);\n }\n }\n\n &-error {\n border-left: 3px solid var(--error-color, #ef4444);\n\n .alert-icon {\n color: var(--error-color, #ef4444);\n }\n }\n }\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faCircleInfo,\n faCircleCheck,\n faCircleXmark,\n faTriangleExclamation,\n faBell,\n faXmark,\n} from '@fortawesome/free-solid-svg-icons';\n\nimport { AlertStyleType } from './alert.types';\nimport type { AlertProps } from './alert.types';\nimport styles from './alert.module.pcss';\nimport ActionIcon from '../actionIcon';\nimport { useComponentDefaults } from '../configProvider';\n\nconst ICON_BY_STYLE: Record<AlertStyleType, typeof faBell> = {\n [AlertStyleType.Default]: faBell,\n [AlertStyleType.Info]: faCircleInfo,\n [AlertStyleType.Success]: faCircleCheck,\n [AlertStyleType.Warn]: faTriangleExclamation,\n [AlertStyleType.Error]: faCircleXmark,\n};\n\nconst CLASS_BY_STYLE: Record<AlertStyleType, string> = {\n [AlertStyleType.Default]: styles.alertStyleDefault,\n [AlertStyleType.Info]: styles.alertStyleInfo,\n [AlertStyleType.Success]: styles.alertStyleSuccess,\n [AlertStyleType.Warn]: styles.alertStyleWarn,\n [AlertStyleType.Error]: styles.alertStyleError,\n};\n\nfunction Alert(props: AlertProps): ReactElement {\n const {\n title,\n children = null,\n styleType = AlertStyleType.Default,\n icon,\n hideIcon = false,\n onClose,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Alert', props);\n\n return (\n <div\n {...rest}\n role=\"alert\"\n className={cx(styles.alert, CLASS_BY_STYLE[styleType], classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {!hideIcon && (\n <FontAwesomeIcon\n icon={icon ?? ICON_BY_STYLE[styleType]}\n className={cx(styles.alertIcon, classNames?.icon)}\n style={slotStyles?.icon as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n )}\n\n <div className={cx(styles.alertContent, classNames?.content)} style={slotStyles?.content}>\n {title && (\n <div className={cx(styles.alertTitle, classNames?.title)} style={slotStyles?.title}>\n {title}\n </div>\n )}\n {children && (\n <div className={cx(styles.alertDescription, classNames?.description)} style={slotStyles?.description}>\n {children}\n </div>\n )}\n </div>\n\n {onClose && (\n <ActionIcon\n icon={faXmark}\n onClick={onClose}\n className={cx(styles.alertCloseButton, classNames?.closeButton)}\n style={slotStyles?.closeButton}\n aria-label=\"Dismiss\"\n />\n )}\n </div>\n );\n}\n\nexport default Alert;\n",".animatedLogo {\n display: inline-block;\n overflow: visible;\n\n &-path {\n stroke: var(--primary-color);\n fill: var(--primary-color);\n fill-opacity: 0;\n }\n\n &-pathLoop {\n animation-name: animatedLogoRevealLoop;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n animation-iteration-count: infinite;\n }\n\n &-pathOnce {\n animation-name: animatedLogoRevealOnce;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n\n &-pathLoopNoFill {\n animation-name: animatedLogoRevealLoopNoFill;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n animation-iteration-count: infinite;\n }\n\n &-pathOnceNoFill {\n animation-name: animatedLogoRevealOnceNoFill;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n\n &-spinLoop,\n &-spinOnce,\n &-scaleLoop,\n &-scaleOnce {\n display: inline-block;\n transform-box: fill-box;\n transform-origin: center;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n }\n\n &-spinLoop {\n animation-name: animatedLogoRotateLoop;\n animation-iteration-count: infinite;\n }\n\n &-spinOnce {\n animation-name: animatedLogoRotateOnce;\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n\n &-scaleLoop {\n animation-name: animatedLogoGrowLoop;\n animation-iteration-count: infinite;\n }\n\n &-scaleOnce {\n animation-name: animatedLogoGrowOnce;\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n\n @media (prefers-reduced-motion: reduce) {\n &-pathLoop,\n &-pathOnce {\n animation: none;\n fill-opacity: 1;\n stroke-dashoffset: 0;\n }\n\n &-pathLoopNoFill,\n &-pathOnceNoFill {\n animation: none;\n stroke-dashoffset: 0;\n }\n\n &-spinLoop,\n &-spinOnce,\n &-scaleLoop,\n &-scaleOnce {\n animation: none;\n }\n }\n}\n\n@keyframes animatedLogoRevealLoop {\n 0% {\n stroke-dashoffset: var(--animated-logo-length);\n fill-opacity: 0;\n }\n\n 38% {\n stroke-dashoffset: 0;\n fill-opacity: 0;\n }\n\n 62% {\n fill-opacity: 1;\n }\n\n 86% {\n fill-opacity: 1;\n }\n\n 96% {\n stroke-dashoffset: 0;\n fill-opacity: 0;\n }\n\n 100% {\n stroke-dashoffset: var(--animated-logo-length);\n fill-opacity: 0;\n }\n}\n\n@keyframes animatedLogoRevealOnce {\n 0% {\n stroke-dashoffset: var(--animated-logo-length);\n fill-opacity: 0;\n }\n\n 45% {\n stroke-dashoffset: 0;\n fill-opacity: 0;\n }\n\n 100% {\n stroke-dashoffset: 0;\n fill-opacity: 1;\n }\n}\n\n@keyframes animatedLogoRevealLoopNoFill {\n 0% {\n stroke-dashoffset: var(--animated-logo-length);\n }\n\n 38% {\n stroke-dashoffset: 0;\n }\n\n 86% {\n stroke-dashoffset: 0;\n }\n\n 100% {\n stroke-dashoffset: var(--animated-logo-length);\n }\n}\n\n@keyframes animatedLogoRevealOnceNoFill {\n 0% {\n stroke-dashoffset: var(--animated-logo-length);\n }\n\n 45% {\n stroke-dashoffset: 0;\n }\n\n 100% {\n stroke-dashoffset: 0;\n }\n}\n\n@keyframes animatedLogoRotateLoop {\n 0% {\n transform: rotate(180deg);\n }\n\n 38% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(0deg);\n }\n}\n\n@keyframes animatedLogoRotateOnce {\n 0% {\n transform: rotate(180deg);\n }\n\n 45% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(0deg);\n }\n}\n\n@keyframes animatedLogoGrowLoop {\n 0% {\n transform: scale(0);\n }\n\n 38% {\n transform: scale(1);\n }\n\n 96% {\n transform: scale(1);\n }\n\n 100% {\n transform: scale(0);\n }\n}\n\n@keyframes animatedLogoGrowOnce {\n 0% {\n transform: scale(0);\n }\n\n 45% {\n transform: scale(1);\n }\n\n 100% {\n transform: scale(1);\n }\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { CSSProperties, ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport type { AnimatedLogoProps } from './animatedLogo.types';\nimport styles from './animatedLogo.module.pcss';\n\nconst DEFAULT_PATH =\n 'M 1.292 0.278 C -0.41 4.855 3.185 6.433 0.344 8.916 Q 3.923 10.712 5.361 14.001 Q 6.128 14.398 6.876 14.003 Q 8.439 10.632 11.86 8.912 C 8.893 6.387 12.578 5.159 10.86 0.255 Q 8.655 1.166 7.391 3.377 Q 6.092 2.93 4.843 3.38 Q 3.246 0.883 1.292 0.278 Z M 1.663 1.28 Q 2.413 1.635 3.195 2.718 Q 2.083 2.778 1.595 3.884 Q 1.309 2.7 1.663 1.28 M 3.802 7.908 Q 4.426 8.069 3.284 9.003 Q 3.824 9.32 4.557 10.141 Q 4.812 10.869 4.849 11.671 Q 4.371 10.09 2.642 9.144 Q 2.438 9.033 2.609 8.922 Q 3.229 8.537 3.802 7.908 M 8.469 7.927 Q 8.955 8.469 9.646 8.926 Q 9.791 9.032 9.647 9.136 Q 7.821 10.157 7.389 11.702 Q 7.464 10.869 7.709 10.119 Q 8.219 9.53 8.956 9.025 Q 7.81 7.927 8.469 7.927';\n\nconst DEFAULT_VIEW_BOX = '0.244 0.155 11.72 14.25';\n\nfunction AnimatedLogo(props: AnimatedLogoProps): ReactElement {\n const {\n path = DEFAULT_PATH,\n viewBox = DEFAULT_VIEW_BOX,\n size = 96,\n color,\n duration = 4.2,\n loop = true,\n fill = true,\n spin = false,\n scale = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = props;\n\n const pathRef = useRef<SVGPathElement>(null);\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n const pathEl = pathRef.current;\n if (!pathEl) return;\n\n setReady(false);\n const length = pathEl.getTotalLength();\n pathEl.style.setProperty('--animated-logo-length', String(length));\n pathEl.style.strokeDasharray = String(length);\n pathEl.style.strokeDashoffset = String(length);\n\n const frame = requestAnimationFrame(() => setReady(true));\n return () => cancelAnimationFrame(frame);\n }, [path]);\n\n const pathStyle: CSSProperties = {\n animationDuration: `${duration}s`,\n ...(color ? { stroke: color, fill: color } : undefined),\n ...slotStyles?.path,\n };\n\n return (\n <svg\n {...rest}\n className={cx(styles.animatedLogo, className)}\n style={{ width: size, height: size, ...style }}\n viewBox={viewBox}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <g\n className={cx(ready && scale && (loop ? styles.animatedLogoScaleLoop : styles.animatedLogoScaleOnce))}\n style={{ animationDuration: `${duration}s` }}\n >\n <g\n className={cx(ready && spin && (loop ? styles.animatedLogoSpinLoop : styles.animatedLogoSpinOnce))}\n style={{ animationDuration: `${duration}s` }}\n >\n <path\n ref={pathRef}\n className={cx(\n styles.animatedLogoPath,\n ready &&\n (loop\n ? fill\n ? styles.animatedLogoPathLoop\n : styles.animatedLogoPathLoopNoFill\n : fill\n ? styles.animatedLogoPathOnce\n : styles.animatedLogoPathOnceNoFill),\n classNames?.path\n )}\n style={pathStyle}\n strokeWidth={0.1}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n d={path}\n />\n </g>\n </g>\n </svg>\n );\n}\n\nexport default AnimatedLogo;\n","import type { CSSProperties } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Which animation plays across the text. */\nexport enum AnimatedTextVariant {\n /** Each unit rises up from below its baseline, staggered left to right. */\n RiseUp = 'rise-up',\n /** Each unit fades in from a blur, staggered left to right. */\n BlurIn = 'blur-in',\n /** Each unit drops in from above with a spring overshoot, staggered left to right. */\n Bounce = 'bounce',\n /** Each unit pops in in order, like it's being typed, with a blinking cursor at the end. */\n Typewriter = 'typewriter',\n /** Each unit resolves from random characters to its real value, staggered left to right. */\n Scramble = 'scramble',\n /** Each unit briefly RGB-splits and jitters before settling, staggered left to right. */\n Glitch = 'glitch',\n /** Every unit continuously bobs up and down in a travelling wave, on a loop. */\n Wave = 'wave',\n /** A highlight sweeps across the text, left to right, on a loop. */\n Shine = 'shine',\n /** A marker-style highlight block wipes in behind the whole string, once, left to right. */\n Highlight = 'highlight',\n}\n\n/**\n * What gets staggered and animated as one entrance unit. Applies to every variant except\n * `Shine` and `Highlight`, which always animate the whole string as a single run.\n */\nexport enum AnimatedTextUnit {\n /** Every letter animates on its own. */\n Letter = 'letter',\n /** Every word animates as a whole block. */\n Word = 'word',\n}\n\nexport type AnimatedTextSlots = 'letter' | 'cursor';\n\nexport interface AnimatedTextProps extends HtmlProps {\n /** The text to animate. Split and animated one unit at a time for every variant but `Shine`/`Highlight`. */\n text: string;\n /** Which animation plays (default `RiseUp`). */\n variant?: AnimatedTextVariant;\n /** Whether entrance/loop variants stagger by letter or by word (default `Letter`). Ignored by `Shine`/`Highlight`. */\n unit?: AnimatedTextUnit;\n /**\n * Delay in ms between each unit's animation start. Applies to every variant except `Shine`\n * and `Highlight`, which animate as a single run (default `40`).\n */\n staggerDelay?: number;\n /**\n * Duration in ms of one animation cycle: a single unit's entrance for `RiseUp`/`BlurIn`/\n * `Bounce`/`Glitch` (default `500`), one bob cycle for `Wave` (default `1200`), one sweep of\n * the highlight for `Shine` (default `2000`), or the one-shot wipe-in for `Highlight` (default\n * `600`). Ignored by `Typewriter` and `Scramble`, since each unit resolves instantly; use\n * `staggerDelay` to control their pacing.\n */\n duration?: number;\n /**\n * When `true` (default), the animation doesn't start until the component first scrolls into\n * the viewport. Set to `false` to play immediately on mount, e.g. for text already in view\n * above the fold.\n */\n triggerOnView?: boolean;\n\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<AnimatedTextSlots>;\n styles?: SlotStyles<AnimatedTextSlots>;\n}\n",".animatedText {\n display: inline-block;\n position: relative;\n\n &-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n &-letter {\n display: inline-block;\n white-space: pre;\n opacity: 0;\n animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);\n animation-fill-mode: forwards;\n }\n\n &-variant {\n &-rise-up {\n animation-name: animatedTextRiseUp;\n }\n\n &-blur-in {\n animation-name: animatedTextBlurIn;\n }\n\n &-bounce {\n animation-name: animatedTextBounceIn;\n animation-timing-function: ease-out;\n }\n\n &-glitch {\n animation-name: animatedTextGlitch;\n animation-timing-function: steps(5, jump-none);\n }\n\n &-wave {\n /* Ambient/looping, not an entrance, so the letter stays visible throughout, overriding\n `.animatedText-letter`'s opacity:0 base (meant for one-shot entrance variants). */\n opacity: 1;\n animation-name: animatedTextWave;\n animation-iteration-count: infinite;\n animation-timing-function: ease-in-out;\n }\n }\n\n &-typewriter-letter {\n display: inline-block;\n white-space: pre;\n }\n\n &-scramble-letter {\n display: inline-block;\n white-space: pre;\n }\n\n &-cursor {\n display: inline-block;\n width: 0.08em;\n min-width: 1px;\n height: 0.85em;\n margin-left: 0.05em;\n background: var(--text-color);\n vertical-align: baseline;\n\n &-blinking {\n animation: animatedTextCursorBlink 1s step-end infinite;\n }\n }\n\n &-shine {\n display: inline-block;\n white-space: pre;\n /* currentColor can't be used here: it would resolve against this same rule's\n `color: transparent` below, making the whole gradient transparent. */\n background-image: linear-gradient(90deg, var(--text-color) 25%, var(--primary-lighter) 50%, var(--text-color) 75%);\n background-size: 200% 100%;\n background-clip: text;\n -webkit-background-clip: text;\n color: transparent;\n -webkit-text-fill-color: transparent;\n animation-name: animatedTextShineSweep;\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n }\n\n &-highlight {\n display: inline-block;\n white-space: pre;\n background-image: linear-gradient(var(--primary-lighter), var(--primary-lighter));\n background-repeat: no-repeat;\n background-position: left center;\n background-size: 0% 100%;\n animation-name: animatedTextHighlightSweep;\n animation-timing-function: ease-out;\n animation-fill-mode: forwards;\n }\n\n @media (prefers-reduced-motion: reduce) {\n &-letter {\n animation: none;\n opacity: 1;\n }\n\n &-shine {\n animation: none;\n background-image: none;\n color: currentColor;\n -webkit-text-fill-color: currentColor;\n }\n\n &-highlight {\n animation: none;\n background-size: 100% 100%;\n }\n\n &-cursor-blinking {\n animation: none;\n opacity: 1;\n }\n }\n}\n\n@keyframes animatedTextRiseUp {\n from {\n opacity: 0;\n transform: translateY(0.6em);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes animatedTextBlurIn {\n from {\n opacity: 0;\n filter: blur(8px);\n }\n\n to {\n opacity: 1;\n filter: blur(0);\n }\n}\n\n@keyframes animatedTextBounceIn {\n 0% {\n opacity: 0;\n transform: translateY(-0.8em);\n }\n\n 60% {\n opacity: 1;\n transform: translateY(0.15em);\n }\n\n 80% {\n transform: translateY(-0.05em);\n }\n\n 100% {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes animatedTextGlitch {\n 0% {\n opacity: 0;\n transform: translate(0, 0);\n text-shadow: none;\n }\n\n 15% {\n opacity: 1;\n transform: translate(-0.05em, 0.03em);\n text-shadow: 0.06em 0 var(--error-color), -0.06em 0 var(--info-color);\n }\n\n 30% {\n transform: translate(0.05em, -0.03em);\n text-shadow: -0.06em 0 var(--error-color), 0.06em 0 var(--info-color);\n }\n\n 45% {\n transform: translate(-0.03em, 0);\n text-shadow: 0.03em 0 var(--error-color), -0.03em 0 var(--info-color);\n }\n\n 60%,\n 100% {\n opacity: 1;\n transform: translate(0, 0);\n text-shadow: none;\n }\n}\n\n@keyframes animatedTextWave {\n 0%,\n 100% {\n transform: translateY(0);\n }\n\n 50% {\n transform: translateY(-0.25em);\n }\n}\n\n@keyframes animatedTextShineSweep {\n 0% {\n background-position: 200% 0;\n }\n\n 100% {\n background-position: -200% 0;\n }\n}\n\n@keyframes animatedTextHighlightSweep {\n from {\n background-size: 0% 100%;\n }\n\n to {\n background-size: 100% 100%;\n }\n}\n\n@keyframes animatedTextCursorBlink {\n 0%,\n 50% {\n opacity: 1;\n }\n\n 50.01%,\n 100% {\n opacity: 0;\n }\n}\n","import { Fragment, useEffect, useMemo, useRef, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { AnimatedTextVariant, AnimatedTextUnit } from './animatedText.types';\nimport type { AnimatedTextProps } from './animatedText.types';\nimport styles from './animatedText.module.pcss';\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n ? window.matchMedia('(prefers-reduced-motion: reduce)').matches\n : false;\n}\n\n// CSS-driven one-shot entrance variants: identical rendering, only the keyframe (via this class)\n// differs. RiseUp/BlurIn/Bounce/Glitch all animate opacity 0 -> 1 with `animation-fill-mode:\n// forwards`, staggered per unit via `animation-delay`.\nconst ENTRANCE_VARIANT_CLASS: Partial<Record<AnimatedTextVariant, string>> = {\n [AnimatedTextVariant.RiseUp]: styles.animatedTextVariantRiseUp,\n [AnimatedTextVariant.BlurIn]: styles.animatedTextVariantBlurIn,\n [AnimatedTextVariant.Bounce]: styles.animatedTextVariantBounce,\n [AnimatedTextVariant.Glitch]: styles.animatedTextVariantGlitch,\n};\n\nfunction splitUnits(text: string, unit: AnimatedTextUnit): string[] {\n return unit === AnimatedTextUnit.Word ? text.split(' ').filter(Boolean) : Array.from(text);\n}\n\ninterface TypewriterProps {\n units: string[];\n unit: AnimatedTextUnit;\n staggerDelay: number;\n classNames: AnimatedTextProps['classNames'];\n slotStyles: AnimatedTextProps['styles'];\n}\n\n// Split out so its wrapper (keyed by `replayKey`, see below) can be remounted on prop change to\n// reset this component's reveal state, the idiomatic React way to reset state on prop change.\n// It also keeps the reveal-count updates that happen over time (inside the interval callback) as\n// the only setState calls, none of them synchronous-in-effect.\nfunction Typewriter({ units, unit, staggerDelay, classNames, slotStyles }: TypewriterProps) {\n const [revealCount, setRevealCount] = useState(() => {\n if (units.length === 0) return 0;\n return prefersReducedMotion() ? units.length : 1;\n });\n\n useEffect(() => {\n if (units.length <= 1 || prefersReducedMotion()) return;\n let revealed = 1;\n const id = setInterval(() => {\n revealed += 1;\n setRevealCount(revealed);\n if (revealed >= units.length) clearInterval(id);\n }, staggerDelay);\n return () => clearInterval(id);\n }, [units, staggerDelay]);\n\n const isDone = revealCount >= units.length;\n\n return (\n <>\n {units.slice(0, revealCount).map((unitText, index) => (\n <Fragment key={index}>\n <span className={cx(styles.animatedTextTypewriterLetter, classNames?.letter)} style={slotStyles?.letter}>\n {unitText}\n </span>\n {unit === AnimatedTextUnit.Word && index < revealCount - 1 ? ' ' : null}\n </Fragment>\n ))}\n <span\n className={cx(styles.animatedTextCursor, isDone && styles.animatedTextCursorBlinking, classNames?.cursor)}\n style={slotStyles?.cursor}\n />\n </>\n );\n}\n\nconst SCRAMBLE_CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%&*';\nconst SCRAMBLE_TICK_MS = 35;\n\nfunction randomScrambleText(length: number): string {\n return Array.from({ length }, () => SCRAMBLE_CHARSET[Math.floor(Math.random() * SCRAMBLE_CHARSET.length)]).join('');\n}\n\ninterface ScrambleProps {\n units: string[];\n unit: AnimatedTextUnit;\n staggerDelay: number;\n classNames: AnimatedTextProps['classNames'];\n slotStyles: AnimatedTextProps['styles'];\n}\n\n// Same keyed-remount-on-prop-change approach as Typewriter. Every unit starts scrambled and\n// \"locks in\" left to right; the scramble refresh (SCRAMBLE_TICK_MS) is a separate, faster cadence\n// than the per-unit settle pacing (staggerDelay) so still-scrambling units keep visibly flickering.\nfunction Scramble({ units, unit, staggerDelay, classNames, slotStyles }: ScrambleProps) {\n const [reduceMotion] = useState(prefersReducedMotion);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (units.length === 0 || reduceMotion) return;\n let t = 0;\n const totalTicks = Math.ceil((units.length * staggerDelay) / SCRAMBLE_TICK_MS) + 1;\n const id = setInterval(() => {\n t += 1;\n setTick(t);\n if (t >= totalTicks) clearInterval(id);\n }, SCRAMBLE_TICK_MS);\n return () => clearInterval(id);\n }, [units, staggerDelay, reduceMotion]);\n\n const settledCount = Math.min(units.length, Math.floor((tick * SCRAMBLE_TICK_MS) / staggerDelay));\n\n return (\n <>\n {units.map((unitText, index) => {\n const isSettled = reduceMotion || index < settledCount;\n return (\n <Fragment key={index}>\n <span className={cx(styles.animatedTextScrambleLetter, classNames?.letter)} style={slotStyles?.letter}>\n {unitText === ' ' ? ' ' : isSettled ? unitText : randomScrambleText(unitText.length)}\n </span>\n {unit === AnimatedTextUnit.Word && index < units.length - 1 ? ' ' : null}\n </Fragment>\n );\n })}\n </>\n );\n}\n\nfunction AnimatedText({\n text,\n variant = AnimatedTextVariant.RiseUp,\n unit = AnimatedTextUnit.Letter,\n staggerDelay = 40,\n duration,\n triggerOnView = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: AnimatedTextProps): ReactElement {\n const units = useMemo(() => splitUnits(text, unit), [text, unit]);\n const rootRef = useRef<HTMLSpanElement>(null);\n\n // When `triggerOnView` is on, the animated subtree stays unmounted (see `isVisible` below)\n // until the root first scrolls into the viewport, so the entrance/loop only plays once someone\n // can actually see it instead of burning its one-shot animation off-screen on mount. Falls back\n // to immediately visible when IntersectionObserver isn't available (SSR, old browsers, jsdom).\n const [isVisible, setIsVisible] = useState(() => !triggerOnView || typeof IntersectionObserver === 'undefined');\n\n useEffect(() => {\n if (isVisible) return;\n const node = rootRef.current;\n if (!node) return;\n const observer = new IntersectionObserver(([entry]) => {\n if (entry?.isIntersecting) {\n setIsVisible(true);\n observer.disconnect();\n }\n });\n observer.observe(node);\n return () => observer.disconnect();\n }, [isVisible]);\n\n // Forces the animated subtree (not the whole component) to remount whenever anything that\n // affects the animation changes, most commonly `text`. Without this, CSS entrance variants\n // rely on `animation-fill-mode: forwards`, which just holds the prior end state instead of\n // replaying when the letters underneath it change; keying on these values makes every variant\n // (CSS-driven and JS-driven alike) replay consistently, matching what a component named\n // AnimatedText should do when the text it's animating actually changes.\n const replayKey = `${variant} ${text} ${unit} ${staggerDelay} ${duration ?? ''}`;\n\n let content: ReactElement;\n\n if (!isVisible) {\n // Reserves the same layout space as the real content without playing anything yet.\n content = (\n <span aria-hidden=\"true\" style={{ opacity: 0 }}>\n {text}\n </span>\n );\n } else if (variant === AnimatedTextVariant.Shine) {\n content = (\n <span\n key={replayKey}\n aria-hidden=\"true\"\n className={cx(styles.animatedTextShine, classNames?.letter)}\n style={{ animationDuration: `${duration ?? 2000}ms`, ...slotStyles?.letter }}\n >\n {text}\n </span>\n );\n } else if (variant === AnimatedTextVariant.Highlight) {\n content = (\n <span\n key={replayKey}\n aria-hidden=\"true\"\n className={cx(styles.animatedTextHighlight, classNames?.letter)}\n style={{ animationDuration: `${duration ?? 600}ms`, ...slotStyles?.letter }}\n >\n {text}\n </span>\n );\n } else if (variant === AnimatedTextVariant.Typewriter) {\n content = (\n <span key={replayKey} aria-hidden=\"true\">\n <Typewriter units={units} unit={unit} staggerDelay={staggerDelay} classNames={classNames} slotStyles={slotStyles} />\n </span>\n );\n } else if (variant === AnimatedTextVariant.Scramble) {\n content = (\n <span key={replayKey} aria-hidden=\"true\">\n <Scramble units={units} unit={unit} staggerDelay={staggerDelay} classNames={classNames} slotStyles={slotStyles} />\n </span>\n );\n } else if (variant === AnimatedTextVariant.Wave) {\n content = (\n <span key={replayKey} aria-hidden=\"true\">\n {units.map((unitText, index) => (\n <Fragment key={index}>\n <span\n className={cx(styles.animatedTextLetter, styles.animatedTextVariantWave, classNames?.letter)}\n style={{\n // Negative delay starts the loop already mid-cycle, phase-shifted per unit.\n // That's what makes it read as a travelling wave from the very first frame,\n // instead of every unit bobbing in lockstep or staggering in once and then syncing.\n animationDelay: `-${index * staggerDelay}ms`,\n animationDuration: `${duration ?? 1200}ms`,\n ...slotStyles?.letter,\n }}\n >\n {unitText === ' ' ? ' ' : unitText}\n </span>\n {unit === AnimatedTextUnit.Word && index < units.length - 1 ? ' ' : null}\n </Fragment>\n ))}\n </span>\n );\n } else {\n const entranceClass = ENTRANCE_VARIANT_CLASS[variant] ?? styles.animatedTextVariantRiseUp;\n content = (\n <span key={replayKey} aria-hidden=\"true\">\n {units.map((unitText, index) => (\n <Fragment key={index}>\n <span\n className={cx(styles.animatedTextLetter, entranceClass, classNames?.letter)}\n style={{\n animationDelay: `${index * staggerDelay}ms`,\n animationDuration: `${duration ?? 500}ms`,\n ...slotStyles?.letter,\n }}\n >\n {unitText === ' ' ? ' ' : unitText}\n </span>\n {unit === AnimatedTextUnit.Word && index < units.length - 1 ? ' ' : null}\n </Fragment>\n ))}\n </span>\n );\n }\n\n return (\n <span {...rest} ref={rootRef} className={cx(styles.animatedText, className)} style={style}>\n <span className={styles.animatedTextVisuallyHidden}>{text}</span>\n {content}\n </span>\n );\n}\n\nexport default AnimatedText;\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum BadgeStyleType {\n Default = 'default',\n Primary = 'primary',\n Success = 'success',\n Info = 'info',\n Warn = 'warn',\n Error = 'error',\n}\n\nexport enum BadgePosition {\n TopRight = 'top-right',\n TopLeft = 'top-left',\n BottomRight = 'bottom-right',\n BottomLeft = 'bottom-left',\n}\n\nexport type BadgeSlots = 'badge';\n\nexport interface BadgeProps extends HtmlProps {\n count?: number;\n max?: number;\n content?: ReactNode;\n dot?: boolean;\n showZero?: boolean;\n styleType?: BadgeStyleType;\n position?: BadgePosition;\n children?: ReactNode;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<BadgeSlots>;\n styles?: SlotStyles<BadgeSlots>;\n}\n",".wrapper {\n position: relative;\n display: inline-flex;\n align-items: center;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n min-width: 1.5em;\n height: 1.5em;\n padding: 0 0.375em;\n border-radius: var(--default-border-radius);\n font-size: 0.75em;\n font-weight: 600;\n line-height: 1;\n white-space: nowrap;\n background: var(--badge-bg);\n color: var(--badge-fg);\n\n &-dot {\n min-width: 0.8em;\n width: 0.8em;\n height: 0.8em;\n padding: 0;\n border-radius: 100%;\n background: var(--badge-solid);\n\n &.badge-position-top-right {\n transform: translate(20%, -20%);\n }\n\n &.badge-position-top-left {\n transform: translate(-20%, -20%);\n }\n\n &.badge-position-bottom-right {\n transform: translate(20%, 20%);\n }\n\n &.badge-position-bottom-left {\n transform: translate(-20%, 20%);\n }\n }\n\n &-overlay {\n position: absolute;\n z-index: 1;\n }\n\n &-position {\n &-top-right {\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n }\n\n &-top-left {\n top: 0;\n left: 0;\n transform: translate(-50%, -50%);\n }\n\n &-bottom-right {\n bottom: 0;\n right: 0;\n transform: translate(50%, 50%);\n }\n\n &-bottom-left {\n bottom: 0;\n left: 0;\n transform: translate(-50%, 50%);\n }\n }\n\n &-style {\n &-default {\n --badge-bg: rgba(0, 0, 0, 0.08);\n --badge-fg: var(--text-color);\n --badge-solid: var(--text-dark);\n }\n\n &-primary {\n --badge-bg: var(--primary-color);\n --badge-fg: var(--text-on-primary);\n --badge-solid: var(--primary-color);\n }\n\n &-success {\n --badge-bg: var(--success-lighter);\n --badge-fg: var(--success-color);\n --badge-solid: var(--success-color);\n }\n\n &-info {\n --badge-bg: var(--info-lighter);\n --badge-fg: var(--info-color);\n --badge-solid: var(--info-color);\n }\n\n &-warn {\n --badge-bg: var(--warn-lighter);\n --badge-fg: var(--warn-color);\n --badge-solid: var(--warn-color);\n }\n\n &-error {\n --badge-bg: var(--error-lighter);\n --badge-fg: var(--error-color);\n --badge-solid: var(--error-color);\n }\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { BadgeStyleType, BadgePosition } from './badge.types';\nimport type { BadgeProps } from './badge.types';\nimport styles from './badge.module.pcss';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_STYLE: Record<BadgeStyleType, string> = {\n [BadgeStyleType.Default]: styles.badgeStyleDefault,\n [BadgeStyleType.Primary]: styles.badgeStylePrimary,\n [BadgeStyleType.Success]: styles.badgeStyleSuccess,\n [BadgeStyleType.Info]: styles.badgeStyleInfo,\n [BadgeStyleType.Warn]: styles.badgeStyleWarn,\n [BadgeStyleType.Error]: styles.badgeStyleError,\n};\n\nconst CLASS_BY_POSITION: Record<BadgePosition, string> = {\n [BadgePosition.TopRight]: styles.badgePositionTopRight,\n [BadgePosition.TopLeft]: styles.badgePositionTopLeft,\n [BadgePosition.BottomRight]: styles.badgePositionBottomRight,\n [BadgePosition.BottomLeft]: styles.badgePositionBottomLeft,\n};\n\nfunction Badge(props: BadgeProps): ReactElement {\n const {\n count,\n max = 99,\n content,\n dot = false,\n showZero = false,\n styleType = BadgeStyleType.Primary,\n position = BadgePosition.TopRight,\n children = null,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Badge', props);\n const hasCount = typeof count === 'number';\n const hasContent = content != null;\n const isHiddenByZero = !dot && !hasContent && hasCount && count === 0 && !showZero;\n const showBadge = (dot || hasContent || hasCount) && !isHiddenByZero;\n\n const displayValue = hasContent ? content : hasCount ? (count > max ? `${max}+` : count) : null;\n const isOverlay = children != null;\n\n return (\n <span\n {...rest}\n className={cx(styles.wrapper, className)}\n style={style}\n >\n {children}\n {showBadge && (\n <span\n className={cx(\n styles.badge,\n CLASS_BY_STYLE[styleType],\n dot && styles.badgeDot,\n isOverlay && styles.badgeOverlay,\n isOverlay && CLASS_BY_POSITION[position],\n classNames?.badge\n )}\n style={slotStyles?.badge}\n >\n {!dot && displayValue}\n </span>\n )}\n </span>\n );\n}\n\nexport default Badge;\n",".avatar {\n --avatar-size: 2.5em;\n --custom-avatar-radius: var(--avatar-radius, var(--default-border-radius));\n display: inline-flex;\n width: var(--avatar-size);\n height: var(--avatar-size);\n flex-shrink: 0;\n box-sizing: border-box;\n vertical-align: middle;\n\n &-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n border-radius: var(--custom-avatar-radius);\n }\n\n &-fallback {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n border-radius: var(--custom-avatar-radius);\n background: var(--background-accent);\n color: var(--text-dark);\n font-size: calc(var(--avatar-size) * 0.4);\n font-weight: 600;\n user-select: none;\n text-transform: uppercase;\n }\n\n &-status-badge {\n border: 2px solid var(--background);\n box-sizing: border-box;\n }\n}\n\n.avatarGroup {\n display: inline-flex;\n align-items: center;\n\n &-item {\n display: inline-flex;\n border-radius: calc(var(--avatar-radius, var(--default-border-radius)) + 3px);\n border: 2px solid var(--background);\n box-sizing: content-box;\n margin-left: -0.5em;\n\n &:first-child {\n margin-left: 0;\n }\n }\n}\n","import { useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faUser } from '@fortawesome/free-solid-svg-icons';\nimport Badge, { BadgeStyleType, BadgePosition } from '../badge';\n\nimport type { AvatarProps, AvatarStatus } from './avatar.types';\nimport styles from './avatar.module.pcss';\n\nconst STATUS_STYLE: Record<AvatarStatus, BadgeStyleType> = {\n online: BadgeStyleType.Success,\n away: BadgeStyleType.Warn,\n busy: BadgeStyleType.Error,\n offline: BadgeStyleType.Default,\n};\n\nfunction getInitials(name?: string): string {\n if (!name) return '';\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '';\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n}\n\nfunction Avatar({\n src,\n alt,\n name,\n icon = faUser,\n content,\n status,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: AvatarProps): ReactElement {\n const [hasError, setHasError] = useState(false);\n const [prevSrc, setPrevSrc] = useState(src);\n\n if (src !== prevSrc) {\n setPrevSrc(src);\n setHasError(false);\n }\n\n const initials = getInitials(name);\n const showImage = !!src && !hasError;\n\n const rendered = showImage ? (\n <img\n className={cx(styles.avatarImage, classNames?.image)}\n style={slotStyles?.image}\n src={src}\n alt={alt ?? name ?? ''}\n onError={() => setHasError(true)}\n />\n ) : (\n <span className={cx(styles.avatarFallback, classNames?.fallback)} style={slotStyles?.fallback}>\n {content ?? (initials || <FontAwesomeIcon icon={icon} />)}\n </span>\n );\n\n if (!status) {\n return (\n <span {...rest} className={cx(styles.avatar, className)} style={style}>\n {rendered}\n </span>\n );\n }\n\n return (\n <Badge\n {...rest}\n dot\n position={BadgePosition.BottomRight}\n styleType={STATUS_STYLE[status]}\n className={className}\n style={style}\n classNames={{ badge: cx(styles.avatarStatusBadge, classNames?.status) }}\n styles={{ badge: slotStyles?.status }}\n >\n <span className={styles.avatar}>{rendered}</span>\n </Badge>\n );\n}\n\nexport default Avatar;\n","import { Children, type ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport Avatar from './avatar';\nimport type { AvatarGroupProps } from './avatar.types';\nimport styles from './avatar.module.pcss';\n\nfunction AvatarGroup({\n children,\n max,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: AvatarGroupProps): ReactElement {\n const items = Children.toArray(children);\n const visible = max != null ? items.slice(0, max) : items;\n const overflow = max != null ? items.length - max : 0;\n\n return (\n <span {...rest} className={cx(styles.avatarGroup, className)} style={style}>\n {visible.map((child, index) => (\n <span\n key={index}\n className={cx(styles.avatarGroupItem, classNames?.item)}\n style={slotStyles?.item}\n >\n {child}\n </span>\n ))}\n {overflow > 0 && (\n <span\n className={cx(styles.avatarGroupItem, classNames?.overflow)}\n style={slotStyles?.overflow}\n >\n <Avatar content={`+${overflow}`} />\n </span>\n )}\n </span>\n );\n}\n\nexport default AvatarGroup;\n","import { createPortal } from 'react-dom';\nimport type { ReactElement } from 'react';\n\nimport type { BodyEndProps } from './bodyEnd.types';\n\n// Module-scoped ambient typing for the bundler-replaced NODE_ENV guard below.\n// Browsers don't define `process`, so the value is read defensively at runtime;\n// bundlers (Vite/webpack) still statically replace the `process.env.NODE_ENV`\n// token. Declared at module scope (not globally), it isn't emitted into the\n// .d.ts and can't clash with a consumer's @types/node.\ndeclare const process: { env: { NODE_ENV?: string } };\n\nfunction BodyEnd({ children = null }: BodyEndProps): ReactElement | null {\n const target = document.getElementById('bodyEnd');\n if (!target) {\n if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {\n console.error('[BodyEnd] No element with id=\"bodyEnd\" found. Add <div id=\"bodyEnd\"></div> to your app root.');\n }\n return null;\n }\n return createPortal(children, target);\n}\n\nexport default BodyEnd;\n",".floatingMenu {\n position: relative;\n\n &-content {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-container {\n color: var(--text-color);\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n box-shadow: var(--card-shadow);\n position: absolute;\n margin-top: 10px;\n background: var(--background-modal);\n padding: 8px;\n border-radius: calc(var(--default-border-radius) + 4px);\n\n .floatingMenu-anim-flip & {\n top: auto;\n bottom: 0;\n margin-top: 0;\n margin-bottom: 10px;\n }\n\n &-align {\n &-left {\n left: 0px;\n }\n\n &-right {\n right: 0px;\n }\n\n &-center {\n left: 50%;\n transform: translateX(-50%);\n }\n }\n\n &-flag {\n box-shadow: var(--card-shadow);\n background: var(--background-modal);\n height: 10px;\n width: 10px;\n position: absolute;\n margin-top: 5px;\n transform: rotate(45deg);\n\n .floatingMenu-anim-flip & {\n top: auto;\n bottom: 0;\n margin-top: 0;\n margin-bottom: 5px;\n }\n\n &-align-right {\n right: 8px;\n }\n\n &-align-left {\n left: 8px;\n }\n\n &-align-center {\n left: 50%;\n transform: translateX(-50%) rotate(45deg);\n }\n }\n }\n\n &-anim {\n transform: scale(0.7);\n opacity: 0.7;\n animation: showMenu 0.1s forwards;\n position: fixed;\n z-index: 1;\n }\n\n @keyframes showMenu {\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n}\n","// Scrollable ancestors up to (not including) <body>. This is computed once per open rather\n// than on every scroll tick, since walking the tree and reading computed style forces layout,\n// which is too expensive to repeat at scroll frequency (Floating UI's autoUpdate does the same\n// thing, resolving the ancestor list once via getOverflowAncestors). Plain page/viewport scroll\n// is deliberately left out: a trigger that scrolls off the top of the page already renders its\n// fixed-position anchor off-screen for free.\nexport function getScrollableAncestors(el: HTMLElement): HTMLElement[] {\n const ancestors: HTMLElement[] = [];\n let node = el.parentElement;\n while (node && node !== document.body && node !== document.documentElement) {\n const style = getComputedStyle(node);\n if (style.overflowX !== 'visible' || style.overflowY !== 'visible') ancestors.push(node);\n node = node.parentElement;\n }\n return ancestors;\n}\n\nexport function isHiddenByAnyAncestor(rect: DOMRect, ancestors: HTMLElement[]): boolean {\n return ancestors.some((ancestor) => {\n const a = ancestor.getBoundingClientRect();\n return rect.bottom <= a.top || rect.top >= a.bottom || rect.right <= a.left || rect.left >= a.right;\n });\n}\n","import { useLayoutEffect, type RefObject } from 'react';\nimport { getScrollableAncestors, isHiddenByAnyAncestor } from 'components/common/utils/scrollAncestors';\n\nexport interface UseFloatingPositionArgs {\n isOpen: boolean;\n /** The element the popup is anchored to. */\n triggerRef: RefObject<HTMLElement | null>;\n /** The `position: fixed` element that gets `top`/`left`/`visibility` written to it directly. */\n anchorRef: RefObject<HTMLElement | null>;\n /** The visible panel whose height decides whether there's room to render on the preferred side. */\n panelRef: RefObject<HTMLElement | null>;\n /** Class toggled on `anchorRef` when flipped to the non-preferred side. */\n flipClassName: string;\n /** Preferred side relative to the trigger (default `'bottom'`) — flips to the other side when there's no room. */\n placement?: 'top' | 'bottom';\n}\n\n/**\n * Keeps a portaled, `position: fixed` popup anchored to a trigger element: tracks the\n * trigger across scroll/resize on every real scrolling ancestor, flips above the trigger\n * when there's no room below, and hides (not closes) the popup when the trigger itself\n * scrolls behind a clipping ancestor — matching Floating UI's autoUpdate + hide middleware.\n *\n * Position/visibility are written straight to the DOM via refs, not through React state:\n * going through setState -> re-render -> commit adds a round-trip that lags behind the\n * browser's own scroll painting by at least a frame.\n */\nexport function useFloatingPosition({ isOpen, triggerRef, anchorRef, panelRef, flipClassName, placement = 'bottom' }: UseFloatingPositionArgs) {\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let rafId: number | undefined;\n let teardown: (() => void) | undefined;\n\n // The anchor/trigger may not be mounted yet on the very first invocation of this\n // effect: a portal target (e.g. BodyEnd's `#bodyEnd` div) can still be missing on\n // the initial render, in which case the portaled content — and this ref — commits\n // one render later. Since refs never change identity, that later commit doesn't\n // re-trigger this effect on its own, so retry on the next frame until it's there.\n function trySetup() {\n const trigger = triggerRef.current;\n const anchor = anchorRef.current;\n if (!trigger || !anchor) {\n rafId = requestAnimationFrame(trySetup);\n return;\n }\n const ancestors = getScrollableAncestors(trigger);\n\n function updatePos() {\n const rect = trigger!.getBoundingClientRect();\n const panelHeight = panelRef.current?.offsetHeight ?? 0;\n const spaceBelow = window.innerHeight - rect.bottom;\n const spaceAbove = rect.top;\n const preferredSpace = placement === 'top' ? spaceAbove : spaceBelow;\n const alternateSpace = placement === 'top' ? spaceBelow : spaceAbove;\n const flip = preferredSpace < panelHeight && alternateSpace > preferredSpace;\n const renderAbove = placement === 'top' ? !flip : flip;\n anchor!.classList.toggle(flipClassName, flip);\n // Shift up by the anchor's own height when rendering above, so this works whether\n // the anchor is a zero-height decorative wrapper (FloatingMenu, whose real panel\n // hangs off it via absolute-positioned CSS) or the visible panel itself\n // (Dropdown) — for the former the shift is a no-op (height 0).\n anchor!.style.top = `${renderAbove ? rect.top - anchor!.offsetHeight : rect.bottom}px`;\n anchor!.style.left = `${rect.left}px`;\n anchor!.style.visibility = isHiddenByAnyAncestor(rect, ancestors) ? 'hidden' : '';\n }\n\n updatePos();\n\n const scrollTargets: (Window | HTMLElement)[] = [window, ...ancestors];\n scrollTargets.forEach((t) => t.addEventListener('scroll', updatePos, { passive: true }));\n window.addEventListener('resize', updatePos);\n teardown = () => {\n scrollTargets.forEach((t) => t.removeEventListener('scroll', updatePos));\n window.removeEventListener('resize', updatePos);\n };\n }\n\n trySetup();\n\n return () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n teardown?.();\n };\n }, [isOpen, triggerRef, anchorRef, panelRef, flipClassName, placement]);\n}","import type { CSSProperties, ReactNode } from \"react\";\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum Align {\n Left = 'left',\n Right = 'right',\n Center = 'center',\n}\n\nexport type FloatingMenuSlots = 'root' | 'trigger' | 'menu' | 'menuContainer';\n\nexport interface FloatingMenuProps extends HtmlProps {\n align?: Align;\n children?: ReactNode;\n content?: ReactNode;\n isOpen?: boolean;\n onOpenChange?: (isOpen: boolean) => void;\n dontCloseOnChildClick?: boolean;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<FloatingMenuSlots>;\n styles?: SlotStyles<FloatingMenuSlots>;\n}","import { useRef, useEffect, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './floatingMenu.module.pcss';\nimport { useFloatingPosition } from './useFloatingPosition';\nimport { Align, FloatingMenuProps } from './floatingMenu.types';\n\nfunction capitalize(s: string) {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction FloatingMenu({\n align = Align.Left,\n children = null,\n content = null,\n isOpen = false,\n onOpenChange = () => {},\n dontCloseOnChildClick = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: FloatingMenuProps) {\n const menuContainerRef = useRef<HTMLDivElement>(null);\n const menuAnimRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const onOpenChangeRef = useRef(onOpenChange);\n const [triggerWidth, setTriggerWidth] = useState(10);\n\n const contentInteractedRef = useRef(false);\n function handleContentMouseUp() {\n contentInteractedRef.current = true;\n }\n\n useEffect(() => { onOpenChangeRef.current = onOpenChange; });\n\n function handleTriggerClick() {\n if (!isOpen) {\n const rect = triggerRef.current?.getBoundingClientRect();\n setTriggerWidth(rect?.width ?? 10);\n onOpenChange(true);\n }\n }\n\n useFloatingPosition({\n isOpen,\n triggerRef,\n anchorRef: menuAnimRef,\n panelRef: menuContainerRef,\n flipClassName: styles.floatingMenuAnimFlip,\n });\n\n useEffect(() => {\n if (!isOpen) return;\n\n function onMouseUp(event: MouseEvent) {\n const menuElem = menuContainerRef.current;\n const triggerElem = triggerRef.current;\n if (!menuElem || !triggerElem) return;\n\n const contentInteracted = contentInteractedRef.current;\n contentInteractedRef.current = false;\n\n const menuClicked =\n contentInteracted || menuElem === event.target || menuElem.contains(event.target as Node);\n const triggerClicked = dontCloseOnChildClick &&\n (triggerElem === event.target || triggerElem.contains(event.target as Node));\n\n if (!menuClicked && !triggerClicked) {\n onOpenChangeRef.current(false);\n }\n }\n\n window.addEventListener('mouseup', onMouseUp);\n return () => window.removeEventListener('mouseup', onMouseUp);\n }, [isOpen, dontCloseOnChildClick]);\n\n return (\n <div {...rest} className={cx(styles.floatingMenu, className, classNames?.root)} style={{ ...style, ...slotStyles?.root }}>\n <div\n className={cx(styles.floatingMenuContent, classNames?.trigger)}\n style={slotStyles?.trigger}\n ref={triggerRef}\n onClick={handleTriggerClick}\n >\n {children}\n </div>\n {isOpen && (\n <BodyEnd>\n <div\n ref={menuAnimRef}\n className={cx(styles.floatingMenuAnim, classNames?.menu)}\n style={{\n width: `${triggerWidth}px`,\n ...slotStyles?.menu,\n }}\n >\n <div className={cx(\n styles.floatingMenuContainerFlag,\n styles[`floatingMenuContainerFlagAlign${capitalize(align)}`],\n )} />\n <div\n ref={menuContainerRef}\n className={cx(\n styles.floatingMenuContainer,\n styles[`floatingMenuContainerAlign${capitalize(align)}`],\n classNames?.menuContainer,\n )}\n style={slotStyles?.menuContainer}\n onMouseUpCapture={handleContentMouseUp}\n >\n {content}\n </div>\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n\nexport default FloatingMenu;\n",".breadcrumb {\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n\n &-list {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n &-item {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n &-icon {\n margin-right: 6px;\n font-size: 0.9em;\n }\n\n &-link {\n display: flex;\n align-items: center;\n text-decoration: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: color 0.15s;\n\n /* Explicit :link/:visited beats the browser default a:visited { color: purple } on\n specificity, otherwise every crumb using the same href (e.g. \"#\") turns purple as\n soon as any one of them is clicked. */\n &:link,\n &:visited {\n color: var(--text-dark);\n }\n\n &:hover {\n color: var(--primary-color);\n }\n\n &-disabled {\n color: var(--text-dark);\n opacity: 0.5;\n cursor: default;\n pointer-events: none;\n }\n }\n\n &-current {\n display: flex;\n align-items: center;\n color: var(--text-color);\n font-weight: var(--header-font-weight, 600);\n }\n\n &-separator {\n display: flex;\n align-items: center;\n color: var(--text-dark);\n font-size: 0.75em;\n opacity: 0.7;\n }\n\n &-ellipsis {\n width: 1.8em;\n height: 1.8em;\n font-size: 1em;\n color: var(--text-dark);\n\n &:hover {\n color: var(--primary-color);\n }\n }\n\n &-hiddenList {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin: 0;\n padding: 6px;\n list-style: none;\n min-width: 160px;\n }\n\n &-hiddenItem {\n display: flex;\n\n .breadcrumb-link {\n width: 100%;\n padding: 6px 8px;\n border-radius: var(--default-border-radius);\n\n &:hover {\n background: var(--background-accent-light);\n }\n }\n }\n}\n","import { useState } from 'react';\nimport type { CSSProperties, ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronRight, faEllipsis } from '@fortawesome/free-solid-svg-icons';\n\nimport InteractableDiv from '../interactableDiv';\nimport ActionIcon from '../actionIcon';\nimport FloatingMenu from '../floatingMenu';\nimport { useComponentDefaults } from '../configProvider';\nimport type { BreadcrumbItem, BreadcrumbProps } from './breadcrumb.types';\n\nimport styles from './breadcrumb.module.pcss';\n\ninterface IndexedItem {\n item: BreadcrumbItem;\n index: number;\n}\n\nfunction getGroups(items: BreadcrumbItem[], maxItems?: number) {\n const indexed = items.map((item, index) => ({ item, index }));\n if (!maxItems || items.length <= maxItems) {\n return { leading: indexed, hidden: [] as IndexedItem[], trailing: [] as IndexedItem[] };\n }\n\n const trailingCount = Math.max(1, maxItems - 2);\n const hiddenCount = items.length - 1 - trailingCount;\n if (hiddenCount <= 0) {\n return { leading: indexed, hidden: [] as IndexedItem[], trailing: [] as IndexedItem[] };\n }\n\n return {\n leading: indexed.slice(0, 1),\n hidden: indexed.slice(1, 1 + hiddenCount),\n trailing: indexed.slice(1 + hiddenCount),\n };\n}\n\nfunction Breadcrumb(props: BreadcrumbProps): ReactElement {\n const {\n items = [],\n separator,\n maxItems,\n 'aria-label': ariaLabel = 'Breadcrumb',\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Breadcrumb', props);\n\n const [isHiddenMenuOpen, setIsHiddenMenuOpen] = useState(false);\n const { leading, hidden, trailing } = getGroups(items, maxItems);\n const lastIndex = items.length - 1;\n\n function renderSeparatorAfter(index: number) {\n if (index === lastIndex) return null;\n return (\n <span className={cx(styles.breadcrumbSeparator, classNames?.separator)} style={slotStyles?.separator}>\n {separator ?? <FontAwesomeIcon icon={faChevronRight} />}\n </span>\n );\n }\n\n function renderItem({ item, index }: IndexedItem) {\n return (\n <li key={item.id ?? index} className={cx(styles.breadcrumbItem, classNames?.item)} style={slotStyles?.item}>\n {renderCrumb(item, index === lastIndex, styles, classNames, slotStyles)}\n {renderSeparatorAfter(index)}\n </li>\n );\n }\n\n return (\n <nav\n {...rest}\n aria-label={ariaLabel}\n className={cx(styles.breadcrumb, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <ol className={cx(styles.breadcrumbList, classNames?.list)} style={slotStyles?.list}>\n {leading.map(renderItem)}\n\n {hidden.length > 0 && (\n <li className={cx(styles.breadcrumbItem, classNames?.item)} style={slotStyles?.item}>\n <FloatingMenu\n isOpen={isHiddenMenuOpen}\n onOpenChange={setIsHiddenMenuOpen}\n content={\n <ul className={cx(styles.breadcrumbHiddenList, classNames?.hiddenList)} style={slotStyles?.hiddenList}>\n {hidden.map(({ item, index }) => (\n <li\n key={item.id ?? index}\n className={cx(styles.breadcrumbHiddenItem, classNames?.hiddenItem)}\n style={slotStyles?.hiddenItem}\n >\n {renderCrumb(\n {\n ...item,\n onClick: (event) => {\n item.onClick?.(event);\n setIsHiddenMenuOpen(false);\n },\n },\n false,\n styles,\n classNames,\n slotStyles\n )}\n </li>\n ))}\n </ul>\n }\n >\n <ActionIcon\n icon={faEllipsis}\n title=\"Show hidden breadcrumbs\"\n aria-label=\"Show hidden breadcrumbs\"\n className={cx(styles.breadcrumbEllipsis, classNames?.ellipsis)}\n style={slotStyles?.ellipsis}\n />\n </FloatingMenu>\n {renderSeparatorAfter(hidden[hidden.length - 1].index)}\n </li>\n )}\n\n {trailing.map(renderItem)}\n </ol>\n </nav>\n );\n}\n\nfunction renderCrumb(\n item: BreadcrumbItem,\n isCurrent: boolean,\n styles: Record<string, string>,\n classNames: BreadcrumbProps['classNames'],\n slotStyles: BreadcrumbProps['styles']\n) {\n const content = (\n <>\n {item.icon && (\n <FontAwesomeIcon\n icon={item.icon}\n className={cx(styles.breadcrumbIcon, classNames?.icon)}\n style={slotStyles?.icon as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n )}\n {item.label}\n </>\n );\n\n if (isCurrent) {\n return (\n <span\n aria-current=\"page\"\n className={cx(styles.breadcrumbCurrent, classNames?.current)}\n style={slotStyles?.current}\n >\n {content}\n </span>\n );\n }\n\n if (item.disabled) {\n return (\n <span className={cx(styles.breadcrumbLink, styles.breadcrumbLinkDisabled, classNames?.link)} style={slotStyles?.link}>\n {content}\n </span>\n );\n }\n\n if (item.href) {\n return (\n <a\n href={item.href}\n onClick={item.onClick}\n className={cx(styles.breadcrumbLink, classNames?.link)}\n style={slotStyles?.link}\n >\n {content}\n </a>\n );\n }\n\n if (item.onClick) {\n return (\n <InteractableDiv\n onClick={item.onClick}\n className={cx(styles.breadcrumbLink, classNames?.link)}\n style={slotStyles?.link}\n >\n {content}\n </InteractableDiv>\n );\n }\n\n return (\n <span className={cx(styles.breadcrumbLink, styles.breadcrumbLinkDisabled, classNames?.link)} style={slotStyles?.link}>\n {content}\n </span>\n );\n}\n\nexport default Breadcrumb;\n","import type { ReactNode } from 'react';\nimport type { ButtonStyleType } from '../button/button.types';\nimport type { HtmlProps } from '../types/slots.types';\nimport type { IconAction } from '../types/actions.types';\n\nexport enum CardStyleType {\n Elevated = 'elevated',\n Outlined = 'outlined',\n Filled = 'filled',\n}\n\nexport interface CardProps extends HtmlProps {\n className?: string | undefined;\n children?: ReactNode;\n styleType?: CardStyleType;\n onClick?: () => void;\n tabIndex?: number | null;\n hoverEffect?: boolean;\n style?: React.CSSProperties;\n autoGap?: boolean;\n clip?: boolean;\n}\n\nexport type CardHeaderAction = IconAction;\n\nexport interface CardHeaderProps {\n className?: string;\n title?: ReactNode;\n subTitle?: ReactNode;\n /** URL string → rendered as background-image. Any other ReactNode → rendered inside the thumbnail div. */\n thumbnail?: string | ReactNode;\n actions?: CardHeaderAction[] | ReactNode;\n}\n\nexport interface CardMediaProps {\n src?: string;\n alt?: string;\n}\n\nexport interface CardContentProps {\n children?: ReactNode;\n}\n\nexport interface CardAction {\n id?: string;\n label?: string;\n styleType?: ButtonStyleType;\n onClick?: () => void;\n}\n\nexport interface CardActionsProps {\n className?: string;\n /** Renders a Button for each action object. Pass `children` for custom content instead. */\n actions?: CardAction[];\n children?: ReactNode;\n}\n",".card {\n border-radius: var(--default-border-radius);\n color: var(--text-color);\n border: 1px solid transparent;\n box-sizing: border-box;\n\n &-clip {\n overflow: hidden;\n }\n\n &-padding {\n padding: 16px;\n }\n\n &-gaps {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-s);\n }\n\n &-style {\n &-elevated {\n background: var(--background-card-elevated, var(--background-accent-light));\n box-shadow: var(--card-shadow);\n }\n\n &-outlined {\n background: var(--background-card-outlined, transparent);\n border-color: var(--border-color);\n }\n\n &-filled {\n background: var(--background-card-filled, var(--background-accent));\n }\n }\n\n &-interactable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-hover {\n transition:\n transform 0.15s ease,\n box-shadow 0.15s ease,\n filter 0.3s ease;\n\n &:hover {\n transform: translateY(-2px);\n background: var(--background-accent);\n }\n }\n}\n\n.cardHeader {\n display: flex;\n gap: 16px;\n align-items: center;\n\n &-thumbnail {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 40px;\n height: 40px;\n background: rgba(0, 0, 0, 0.08);\n border-radius: 40px;\n overflow: hidden;\n background-size: cover;\n background-position: center;\n flex-shrink: 0;\n }\n\n &-actions {\n display: flex;\n gap: var(--spacing-s);\n flex-wrap: wrap;\n flex-shrink: 1;\n align-items: center;\n justify-content: flex-end;\n }\n\n &-titles {\n display: flex;\n flex-flow: column;\n flex: 1;\n gap: 4px;\n overflow: hidden;\n\n &-main {\n font-size: 18px;\n font-weight: 600;\n min-width: 3ch;\n flex-shrink: 100000;\n overflow: hidden;\n text-overflow: ellipsis;\n\n &-container {\n display: flex;\n align-items: center;\n gap: var(--spacing-m);\n justify-content: space-between;\n }\n }\n\n &-sub {\n font-weight: 300;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n }\n}\n\n.cardMedia {\n width: calc(100% + 32px);\n margin: 0 -16px 0 -16px;\n}\n\n.cardActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n","import cx from 'classnames';\n\nimport { CardStyleType, type CardProps } from './card.types';\nimport styles from './card.module.pcss';\nimport InteractableDiv from '../interactableDiv';\nimport Ripple from '../ripple';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_STYLE: Record<CardStyleType, string> = {\n elevated: styles.cardStyleElevated,\n outlined: styles.cardStyleOutlined,\n filled: styles.cardStyleFilled,\n};\n\nfunction Card(props: CardProps) {\n const {\n className = undefined,\n children = null,\n styleType = CardStyleType.Elevated,\n onClick = undefined,\n tabIndex = null,\n hoverEffect = undefined,\n style = undefined,\n autoGap = true,\n clip = false,\n ...rest\n } = useComponentDefaults('Card', props);\n const isInteractable = !!onClick;\n\n return (\n <InteractableDiv\n {...rest}\n className={cx(\n styles.card,\n CLASS_BY_STYLE[styleType],\n clip && styles.cardClip,\n isInteractable && styles.cardInteractable,\n ((isInteractable && hoverEffect !== false) || hoverEffect) && styles.cardHover,\n className\n )}\n onClick={onClick}\n tabIndex={tabIndex ?? (isInteractable ? 0 : null)}\n style={style}\n >\n <Ripple\n disabled={!isInteractable}\n className={cx(styles.cardPadding, autoGap && styles.cardGaps)}\n style={{ borderRadius: 'inherit' }}\n >\n {children}\n </Ripple>\n </InteractableDiv>\n );\n}\n\nexport default Card;\n","import React from 'react';\nimport cx from 'classnames';\n\nimport type { CardHeaderProps } from './card.types';\nimport styles from './card.module.pcss';\nimport ActionIcon from '../actionIcon';\n\nfunction CardHeader({\n className = '',\n title = '',\n subTitle = '',\n thumbnail = '',\n actions = undefined,\n}: CardHeaderProps) {\n const thumbnailUrl =\n typeof thumbnail === 'string' && thumbnail.startsWith('http') ? thumbnail : undefined;\n\n return (\n <div className={cx(styles.cardHeader, className)}>\n {thumbnail && (\n <div\n className={styles.cardHeaderThumbnail}\n style={thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}}\n >\n {!thumbnailUrl && thumbnail}\n </div>\n )}\n <div className={styles.cardHeaderTitles}>\n <div className={styles.cardHeaderTitlesMainContainer}>\n <div className={styles.cardHeaderTitlesMain}>{title}</div>\n <div className={styles.cardHeaderActions}>\n {Array.isArray(actions)\n ? actions.map((action, index) => (\n <ActionIcon\n key={index}\n title={action.title}\n onClick={action.onClick ? (e: React.MouseEvent<HTMLDivElement>) => { e.stopPropagation(); action.onClick?.(e); } : undefined}\n icon={action.icon}\n />\n ))\n : actions}\n </div>\n </div>\n <div className={styles.cardHeaderTitlesSub}>{subTitle}</div>\n </div>\n </div>\n );\n}\n\nexport default CardHeader;\n","import React from 'react';\n\nimport type { CardMediaProps } from './card.types';\nimport styles from './card.module.pcss';\n\nfunction CardMedia({ src = '', alt = '' }: CardMediaProps) {\n return <img className={styles.cardMedia} src={src} alt={alt} />;\n}\n\nexport default CardMedia;\n","import React from 'react';\n\nimport type { CardContentProps } from './card.types';\n\nfunction CardContent({ children = null }: CardContentProps) {\n return <>{children}</>;\n}\n\nexport default CardContent;\n","import React from 'react';\nimport cx from 'classnames';\nimport Button from '../button';\nimport { ButtonStyleType } from '../button/button.types';\n\nimport type { CardActionsProps } from './card.types';\nimport styles from './card.module.pcss';\n\nfunction CardActions({ className = '', actions = [], children = null }: CardActionsProps) {\n return (\n <div className={cx(styles.cardActions, className)}>\n {actions.map(({ id, onClick, label, styleType = ButtonStyleType.Default }) => (\n <div key={id ?? label}>\n <Button onClick={onClick} styleType={styleType}>\n {label}\n </Button>\n </div>\n ))}\n {children}\n </div>\n );\n}\n\nexport default CardActions;\n",".carousel {\n position: relative;\n overflow: hidden;\n border-radius: var(--default-border-radius);\n\n &-track {\n display: flex;\n align-items: stretch;\n transition: transform 0.4s ease;\n touch-action: pan-y;\n user-select: none;\n }\n\n &-slide {\n flex-shrink: 0;\n box-sizing: border-box;\n }\n\n &-prevButton,\n &-nextButton {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n z-index: 1;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n background: var(--background-accent);\n color: var(--text-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: opacity 0.15s, background 0.15s;\n\n &:hover {\n background: var(--background-accent-light);\n }\n }\n\n &-buttonDisabled {\n opacity: 0.35;\n pointer-events: none;\n }\n\n &-prevButton {\n left: 12px;\n }\n\n &-nextButton {\n right: 12px;\n }\n\n &-dots {\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 1;\n display: flex;\n gap: 8px;\n }\n\n &-dot {\n width: 8px;\n height: 8px;\n border-radius: 2000px;\n background: var(--background-accent);\n opacity: 0.6;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: opacity 0.15s, background 0.15s, width 0.15s;\n\n &:hover {\n opacity: 0.85;\n }\n\n &-active {\n background: var(--primary-color);\n opacity: 1;\n width: 20px;\n }\n }\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults } from '../configProvider';\nimport type { CarouselProps } from './carousel.types';\n\nimport styles from './carousel.module.pcss';\n\nconst AXIS_LOCK_THRESHOLD = 10;\nconst DRAG_COMMIT_RATIO = 0.2;\n\nfunction Carousel(props: CarouselProps) {\n const {\n children,\n currentIndex,\n defaultIndex = 0,\n onChange = () => {},\n loop = true,\n autoPlay = false,\n autoPlayInterval = 4000,\n pauseOnHover = true,\n showArrows = true,\n showDots = true,\n swipeable = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Carousel', props);\n\n const slides = React.Children.toArray(children);\n const count = slides.length;\n const canLoop = loop && count > 1;\n const offset = canLoop ? 1 : 0;\n const extendedSlides = canLoop ? [slides[count - 1], ...slides, slides[0]] : slides;\n\n const isControlled = currentIndex !== undefined;\n const [internalIndex, setInternalIndex] = useState(() => clampIndex(defaultIndex, count, canLoop));\n const realIndex = clampIndex(isControlled ? currentIndex! : internalIndex, count, canLoop);\n\n const [displayIndex, setDisplayIndex] = useState(realIndex + offset);\n const [transitionEnabled, setTransitionEnabled] = useState(true);\n const prevRealIndexRef = useRef(realIndex);\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n const [dragging, setDragging] = useState(false);\n const [dragOffsetPercent, setDragOffsetPercent] = useState(0);\n\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const prevReal = prevRealIndexRef.current;\n prevRealIndexRef.current = realIndex;\n if (prevReal === realIndex) return;\n\n const forwardWrap = canLoop && prevReal === count - 1 && realIndex === 0;\n const backwardWrap = canLoop && prevReal === 0 && realIndex === count - 1;\n\n setTransitionEnabled(true);\n if (forwardWrap) {\n setDisplayIndex((d) => d + 1);\n } else if (backwardWrap) {\n setDisplayIndex((d) => d - 1);\n } else {\n setDisplayIndex(realIndex + offset);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [realIndex]);\n\n function goToIndex(nextIndex: number) {\n const clamped = clampIndex(nextIndex, count, canLoop);\n if (!isControlled) setInternalIndex(clamped);\n onChange(clamped);\n }\n\n function goNext() {\n if (!canLoop && realIndex >= count - 1) return;\n goToIndex(realIndex + 1);\n }\n\n function goPrev() {\n if (!canLoop && realIndex <= 0) return;\n goToIndex(realIndex - 1);\n }\n\n function handleTrackTransitionEnd(event: React.TransitionEvent<HTMLDivElement>) {\n if (event.target !== event.currentTarget || !canLoop) return;\n if (displayIndex === 0) {\n setTransitionEnabled(false);\n setDisplayIndex(count);\n } else if (displayIndex === extendedSlides.length - 1) {\n setTransitionEnabled(false);\n setDisplayIndex(1);\n }\n }\n\n const isPaused = (pauseOnHover && (hovered || focused)) || dragging;\n useEffect(() => {\n if (!autoPlay || count <= 1 || isPaused) return;\n const timer = setInterval(goNext, autoPlayInterval);\n return () => clearInterval(timer);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [autoPlay, autoPlayInterval, isPaused, realIndex, count]);\n\n const dragRef = useRef<{\n startX: number;\n startY: number;\n axisLocked: boolean;\n active: boolean;\n } | null>(null);\n\n function handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n if (!swipeable || count <= 1) return;\n dragRef.current = { startX: event.clientX, startY: event.clientY, axisLocked: false, active: true };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (!drag || !drag.active) return;\n\n const deltaX = event.clientX - drag.startX;\n const deltaY = event.clientY - drag.startY;\n\n if (!drag.axisLocked) {\n if (Math.abs(deltaX) < AXIS_LOCK_THRESHOLD && Math.abs(deltaY) < AXIS_LOCK_THRESHOLD) return;\n if (Math.abs(deltaY) > Math.abs(deltaX)) {\n drag.active = false;\n return;\n }\n drag.axisLocked = true;\n setDragging(true);\n setTransitionEnabled(false);\n }\n\n const width = containerRef.current?.getBoundingClientRect().width || 1;\n setDragOffsetPercent((deltaX / width) * 100);\n }\n\n function handlePointerUp() {\n const drag = dragRef.current;\n dragRef.current = null;\n if (!drag || !drag.axisLocked) {\n setDragging(false);\n return;\n }\n\n const committed = Math.abs(dragOffsetPercent) >= DRAG_COMMIT_RATIO * 100;\n setDragOffsetPercent(0);\n setTransitionEnabled(true);\n setDragging(false);\n if (committed) {\n if (dragOffsetPercent < 0) goNext();\n else goPrev();\n }\n }\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n goPrev();\n } else if (event.key === 'ArrowRight') {\n event.preventDefault();\n goNext();\n }\n }\n\n const isPrevDisabled = !canLoop && realIndex <= 0;\n const isNextDisabled = !canLoop && realIndex >= count - 1;\n\n const slideWidthPercent = extendedSlides.length > 0 ? 100 / extendedSlides.length : 100;\n const trackTransform = `translateX(calc(${-displayIndex * slideWidthPercent}% + ${dragOffsetPercent * (slideWidthPercent / 100)}%))`;\n\n return (\n <div\n {...rest}\n ref={containerRef}\n role=\"region\"\n aria-roledescription=\"carousel\"\n className={cx(styles.carousel, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n onMouseEnter={pauseOnHover ? () => setHovered(true) : undefined}\n onMouseLeave={pauseOnHover ? () => setHovered(false) : undefined}\n onFocus={pauseOnHover ? () => setFocused(true) : undefined}\n onBlur={pauseOnHover ? () => setFocused(false) : undefined}\n onKeyDown={handleKeyDown}\n >\n <div\n className={cx(styles.carouselTrack, classNames?.track)}\n style={{\n width: `${extendedSlides.length * 100}%`,\n transform: trackTransform,\n transition: transitionEnabled ? undefined : 'none',\n ...slotStyles?.track,\n }}\n onTransitionEnd={handleTrackTransitionEnd}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n {extendedSlides.map((slide, idx) => {\n const isClonePosition = canLoop && (idx === 0 || idx === extendedSlides.length - 1);\n const logicalIndex = idx - offset;\n const isActive = !isClonePosition && logicalIndex === realIndex;\n\n return (\n <div\n key={`carousel-slide-${idx}`}\n className={cx(styles.carouselSlide, classNames?.slide)}\n style={{ width: `${100 / extendedSlides.length}%`, ...slotStyles?.slide }}\n inert={isActive ? undefined : true}\n >\n {slide}\n </div>\n );\n })}\n </div>\n\n {showArrows && count > 1 && (\n <>\n <ActionIcon\n icon={faChevronLeft}\n title=\"Previous slide\"\n aria-label=\"Previous slide\"\n aria-disabled={isPrevDisabled || undefined}\n onClick={() => !isPrevDisabled && goPrev()}\n className={cx(styles.carouselPrevButton, isPrevDisabled && styles.carouselButtonDisabled, classNames?.prevButton)}\n style={slotStyles?.prevButton}\n />\n <ActionIcon\n icon={faChevronRight}\n title=\"Next slide\"\n aria-label=\"Next slide\"\n aria-disabled={isNextDisabled || undefined}\n onClick={() => !isNextDisabled && goNext()}\n className={cx(styles.carouselNextButton, isNextDisabled && styles.carouselButtonDisabled, classNames?.nextButton)}\n style={slotStyles?.nextButton}\n />\n </>\n )}\n\n {showDots && count > 1 && (\n <div className={cx(styles.carouselDots, classNames?.dots)} style={slotStyles?.dots}>\n {slides.map((_, index) => (\n <InteractableDiv\n key={`carousel-dot-${index}`}\n aria-label={`Go to slide ${index + 1}`}\n aria-current={index === realIndex}\n onClick={() => goToIndex(index)}\n className={cx(styles.carouselDot, index === realIndex && styles.carouselDotActive, classNames?.dot)}\n style={slotStyles?.dot}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction clampIndex(index: number, count: number, canLoop: boolean): number {\n if (count === 0) return 0;\n if (canLoop) return ((index % count) + count) % count;\n return Math.max(0, Math.min(count - 1, index));\n}\n\nexport default Carousel;\n","\n.checkbox {\n user-select: none;\n display: flex;\n align-items: center;\n column-gap: 10px;\n margin: -1px;\n border: 1px solid transparent;\n width: fit-content;\n\n &-icon {\n color: #a3a9b9;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n background-color: var(--light-background-color);\n width: fit-content;\n height: fit-content;\n /* width: 16px;\n height: 16px; */\n }\n\n &-loading {\n background: transparent;\n\n &-spinner {\n width: 100%;\n height: 100%;\n }\n }\n\n &-pointer {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &:focus-visible {\n outline: none;\n border: 1px solid var(--primary-color);\n border-radius: 6px;\n }\n\n &-disabled {\n filter: brightness(0.8);\n cursor: not-allowed;\n }\n\n &-checkmark {\n border: 1.8px solid var(--text-color);\n border-radius: var(--default-border-radius);\n position: relative;\n\n svg {\n stroke: var(--text-on-primary);\n stroke-dasharray: 5;\n stroke-dashoffset: 5;\n transition:\n transform 0.1s,\n stroke-dashoffset 0.4s;\n transition-delay: 0s, 0.2s;\n background: var(--primary-color);\n transform: scale(0);\n box-sizing: content-box;\n padding: 2px;\n border-radius: var(--default-border-radius);\n }\n\n &-checked {\n svg {\n stroke-dashoffset: 0;\n transform: scale(1) translate(-3px, -3px);\n }\n }\n }\n}\n","import { useRef, useEffect, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport Ripple from 'components/common/ripple';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport { useComponentDefaults } from '../configProvider';\n\nimport type { CheckboxProps } from './checkbox.types';\nimport styles from './checkbox.module.pcss';\n\nfunction Checkbox(props: CheckboxProps): ReactElement {\n const {\n label = '',\n selected = false,\n onToggle = () => {},\n className = '',\n style,\n disabled = false,\n lineHeight = '',\n title = '',\n tabIndex = 0,\n cursorDefault = false,\n width = '17px',\n height = '17px',\n formValidator = null,\n children = null,\n background = null,\n isLoading = false,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Checkbox', props);\n const rippleRef = useRef<{ addRipple: () => void }>(null);\n const [, forceUpdate] = useState(0);\n\n useEffect(() => {\n if (!formValidator) return;\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n function handleToggle(event?: React.MouseEvent | React.KeyboardEvent) {\n if (disabled || isLoading) return;\n rippleRef.current?.addRipple();\n if (formValidator) {\n formValidator.set(!formValidator.value);\n }\n onToggle(!selected, event);\n }\n\n const currSelected = (formValidator ? formValidator.value : selected) as boolean;\n\n return (\n <div\n {...rest}\n className={cx(\n styles.checkbox,\n {\n [styles.checkboxDisabled]: disabled,\n [styles.checkboxPointer]: !cursorDefault,\n },\n className\n )}\n style={style}\n onClick={handleToggle}\n onKeyPress={(e) => { if (e.key === 'Enter') handleToggle(e); }}\n role=\"checkbox\"\n aria-checked={currSelected}\n aria-disabled={disabled || undefined}\n tabIndex={tabIndex}\n >\n <div\n title={title}\n className={cx(styles.checkboxIcon, isLoading ? styles.checkboxLoading : null, classNames?.icon)}\n style={slotStyles?.icon}\n >\n {isLoading ? (\n <div style={{ width, height }}>\n <SpinnerLoading className={styles.checkboxLoadingSpinner} />\n </div>\n ) : (\n <div\n style={{ width, height, ...slotStyles?.checkmark }}\n className={cx(\n styles.checkboxCheckmark,\n currSelected && styles.checkboxCheckmarkChecked,\n classNames?.checkmark\n )}\n >\n <Ripple\n ref={rippleRef}\n manualOnly\n overflowHidden={false}\n rippleAnimationLength={0.3}\n rippleBackground=\"radial-gradient(transparent, var(--primary-color))\"\n />\n <svg\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"-0.5 -1.5 4 2.6\"\n width={`calc(${width} + 1px)`}\n height={`calc(${height} + 1px)`}\n {...(background ? { style: { background } } : {})}\n >\n <path d=\"M 0 0 l 1 1 l 2 -2\" strokeWidth=\"0.4\" fill=\"none\" />\n </svg>\n </div>\n )}\n </div>\n <div className={classNames?.label} style={{ lineHeight: lineHeight || '100%', ...slotStyles?.label }}>{children || label}</div>\n </div>\n );\n}\n\nexport default Checkbox;\n","import type { HtmlProps } from '../types/slots.types';\n\nexport enum ChipStyleType {\n Default = 'default',\n Primary = 'primary',\n Info = 'info',\n Warn = 'warn',\n Error = 'error',\n}\n\nexport interface ChipProps extends HtmlProps {\n className?: string;\n text?: string;\n thumbnail?: React.ReactNode;\n styleType?: ChipStyleType;\n showRemoveIcon?: boolean;\n onClick?: () => void;\n onRemove?: () => void;\n}\n\nexport interface ChipContainerProps extends HtmlProps {\n className?: string;\n children?: React.ReactNode;\n inline?: boolean;\n}\n",".chip {\n background: rgba(0, 0, 0, 0.08);\n border-radius: 99999px;\n width: fit-content;\n position: relative;\n box-sizing: border-box;\n max-width: 100%;\n\n &-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-style {\n &-default {\n background: rgba(0, 0, 0, 0.08);\n color: var(--text-color);\n }\n\n &-primary {\n background: var(--primary-color);\n color: var(--text-on-primary);\n }\n\n &-info {\n background: var(--info-lighter);\n color: var(--info-color);\n }\n\n &-warn {\n background: var(--warn-lighter);\n color: var(--warn-color);\n }\n\n &-error {\n background: var(--error-lighter);\n color: var(--error-color);\n }\n }\n\n &-inner {\n display: flex;\n gap: 8px;\n align-items: center;\n padding: 4px 8px;\n\n & > * {\n white-space: nowrap;\n }\n }\n\n &-text {\n text-overflow: ellipsis;\n overflow: hidden;\n }\n\n &-thumbnail {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 18px;\n height: 18px;\n background: rgba(0, 0, 0, 0.08);\n border-radius: 18px;\n overflow: hidden;\n background-size: cover;\n }\n\n &-container {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n\n &-inline {\n flex-wrap: nowrap;\n overflow: auto;\n }\n }\n}\n","import React, { useMemo } from 'react';\nimport { faXmarkCircle } from '@fortawesome/free-solid-svg-icons';\nimport cx from 'classnames';\n\nimport Ripple from '../ripple';\nimport ActionIcon from '../actionIcon';\nimport { ChipStyleType, ChipProps } from './chip.types';\nimport { useComponentDefaults } from '../configProvider';\n\nimport styles from './chip.module.pcss';\n\nconst CLASS_BY_STYLE: Record<ChipStyleType, string> = {\n default: styles.chipStyleDefault,\n primary: styles.chipStylePrimary,\n info: styles.chipStyleInfo,\n warn: styles.chipStyleWarn,\n error: styles.chipStyleError,\n};\n\nfunction Chip(props: ChipProps) {\n const {\n className = '',\n thumbnail = '',\n text = '',\n styleType = ChipStyleType.Default,\n showRemoveIcon = false,\n onClick,\n onRemove,\n ...rest\n } = useComponentDefaults('Chip', props);\n const thumbnailUrl = useMemo(() => {\n if (typeof thumbnail === 'string' && thumbnail.startsWith('http')) return thumbnail;\n return undefined;\n }, [thumbnail]);\n\n return (\n <div\n {...rest}\n className={cx(styles.chip, CLASS_BY_STYLE[styleType], onClick && styles.chipClickable, className)}\n onClick={onClick}\n >\n <Ripple disabled={!onClick} style={{ borderRadius: 'inherit' }}>\n <div className={styles.chipInner}>\n {thumbnail && (\n <div\n className={styles.chipThumbnail}\n style={thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}}\n >\n {!thumbnailUrl && thumbnail}\n </div>\n )}\n <div className={styles.chipText}>{text}</div>\n {showRemoveIcon && <ActionIcon icon={faXmarkCircle} onClick={(e) => { e.stopPropagation(); onRemove?.(); }} />}\n </div>\n </Ripple>\n </div>\n );\n}\n\nexport default Chip;\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { ChipContainerProps } from './chip.types';\nimport styles from './chip.module.pcss';\n\nfunction ChipContainer({\n className = undefined,\n children = null,\n inline = false,\n ...rest\n}: ChipContainerProps): ReactElement {\n return (\n <div {...rest} className={cx(styles.chipContainer, inline && styles.chipContainerInline, className)}>\n {children}\n </div>\n );\n}\n\nexport default ChipContainer;\n","\n.tooltipAnchor {\n position: fixed;\n z-index: 10;\n}\n\n.tooltipBubble {\n position: absolute;\n bottom: 0;\n margin-bottom: 6px;\n left: 0;\n border-radius: 3px;\n width: max-content;\n max-width: 200px;\n font-size: 12px;\n background-color: #454953;\n padding: 6px 9px;\n color: white;\n pointer-events: none;\n\n .tooltip-anchor-flip & {\n bottom: auto;\n top: 0;\n margin-bottom: 0;\n margin-top: 6px;\n }\n\n &:after {\n content: '';\n position: absolute;\n top: 100%;\n left: calc(var(--tooltip-trigger-width, 10px) / 2 - 5px);\n border-width: 5px;\n border-style: solid;\n border-color: #454953 transparent transparent transparent;\n }\n\n .tooltip-anchor-flip &:after {\n top: auto;\n bottom: 100%;\n border-color: transparent transparent #454953 transparent;\n }\n}\n\n.tooltipDetails {\n position: relative;\n display: inline-flex;\n align-items: center;\n\n &-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n font-size: 11px;\n font-weight: 700;\n background-color: #454953;\n color: white;\n cursor: default;\n user-select: none;\n }\n}\n\n.tooltipError {\n position: absolute;\n bottom: 0;\n margin-bottom: 6px;\n right: 0;\n width: max-content;\n border-radius: 3px;\n background-color: var(--error-lighter);\n color: var(--red);\n font-size: 10px;\n padding: 6px 9px;\n\n .tooltip-anchor-flip & {\n bottom: auto;\n top: 0;\n margin-bottom: 0;\n margin-top: 6px;\n }\n\n &:after {\n content: '';\n position: absolute;\n top: 100%;\n right: 12px;\n border-width: 5px;\n border-style: solid;\n border-color: var(--error-border-color) transparent transparent transparent;\n }\n\n .tooltip-anchor-flip &:after {\n top: auto;\n bottom: 100%;\n border-color: transparent transparent var(--error-border-color) transparent;\n }\n}\n","import React, { useLayoutEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\nimport { useFloatingPosition } from '../floatingMenu/useFloatingPosition';\nimport styles from './tooltip.module.pcss';\nimport type { TooltipProps } from './tooltip.types';\n\nexport default function Tooltip({\n variant,\n message = '',\n isVisible = true,\n tooltipPosition,\n onClick,\n}: TooltipProps) {\n const [detailsHovered, setDetailsHovered] = useState(false);\n\n const sentinelRef = useRef<HTMLSpanElement>(null);\n const detailsRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const [triggerWidth, setTriggerWidth] = useState(10);\n\n const shown = variant === 'details' ? detailsHovered : isVisible;\n\n useLayoutEffect(() => {\n triggerRef.current = variant === 'details' ? detailsRef.current : (sentinelRef.current?.parentElement ?? null);\n });\n\n useLayoutEffect(() => {\n if (shown) {\n const rect = triggerRef.current?.getBoundingClientRect();\n setTriggerWidth(rect?.width ?? 10);\n }\n }, [shown]);\n\n useFloatingPosition({\n isOpen: shown,\n triggerRef,\n anchorRef,\n panelRef,\n flipClassName: styles.tooltipAnchorFlip,\n placement: 'top',\n });\n\n const bubble = shown && (\n <BodyEnd>\n <div\n ref={anchorRef}\n className={styles.tooltipAnchor}\n style={{ width: `${triggerWidth}px`, '--tooltip-trigger-width': `${triggerWidth}px` } as React.CSSProperties}\n >\n <div\n ref={panelRef}\n className={cx(variant === 'error' ? styles.tooltipError : styles.tooltipBubble, tooltipPosition)}\n onClick={onClick}\n >\n {message}\n </div>\n </div>\n </BodyEnd>\n );\n\n if (variant === 'details') {\n return (\n <div ref={detailsRef} className={styles.tooltipDetails}>\n <span\n className={styles.tooltipDetailsIcon}\n onMouseEnter={() => setDetailsHovered(true)}\n onMouseLeave={() => setDetailsHovered(false)}\n >\n ?\n </span>\n {bubble}\n </div>\n );\n }\n\n if (variant === 'info' || variant === 'error') {\n return (\n <>\n <span ref={sentinelRef} style={{ display: 'none' }} />\n {bubble}\n </>\n );\n }\n\n return null;\n}\n","\n.required-mark {\n padding: 0px 0px 0px 4px;\n color: var(--required-mark-color, var(--error-color));\n}\n\n.input {\n position: relative;\n width: 100%;\n --input-notch-height: 1.75em;\n\n &-placeholder {\n position: absolute;\n top: 50%;\n left: 7px;\n transform: translateY(-50%);\n transition: all 0.2s;\n opacity: 0;\n user-select: none;\n pointer-events: none;\n\n &-shown {\n animation: 0.2s fadeIn 0.3s forwards;\n }\n\n &-multiline {\n top: 14px;\n transform: translateY(0);\n }\n }\n\n &-matLabel {\n position: absolute;\n transition: all 0.3s;\n left: 7px;\n right: 0;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1em;\n color: var(--input-label-resting-color, var(--text-light));\n pointer-events: none;\n user-select: none;\n\n &-floating {\n top: 0;\n bottom: auto;\n left: 14px;\n right: 0;\n font-size: 0.8em;\n color: var(--input-label-floating-color, var(--text-color));\n transform: translateY(-50%);\n }\n\n &-multiline {\n top: 14px;\n transform: translateY(0);\n }\n }\n\n &-fieldset {\n position: absolute;\n width: 100%;\n margin: 0;\n padding: 0;\n min-width: 0;\n box-sizing: border-box;\n border-radius: var(--default-border-radius);\n font-size: 0.8em;\n inset: calc(var(--input-notch-height) / -2) 0 0 0;\n padding-left: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: var(--border-color);\n pointer-events: none;\n user-select: none;\n\n &-legend {\n display: block;\n max-width: 0;\n transition: max-width 0.2s;\n white-space: nowrap;\n padding: 0;\n\n &-active {\n max-width: 300px;\n }\n\n span {\n line-height: var(--input-notch-height);\n padding: 0 5px;\n opacity: 0;\n }\n\n span:empty {\n padding: 0.000001px;\n }\n }\n }\n\n &-container {\n display: flex;\n align-items: center;\n border-radius: var(--default-border-radius);\n background-color: var(--input-background);\n transition: border-color;\n cursor: text;\n height: 100%;\n\n &-multiline {\n overflow: hidden;\n padding-top: 10px;\n align-items: flex-start;\n }\n\n &-border {\n outline: 1px solid var(--border-color);\n transition: border-color;\n background-color: var(--input-background);\n outline: none;\n\n &-focused {\n outline-color: var(--primary-color);\n border-color: var(--primary-color);\n }\n\n &-searchFocused {\n outline-color: var(--search-input-color);\n outline-width: 2px;\n border-color: var(--search-input-color);\n }\n\n &-invalid {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-invalid:hover {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-error {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n }\n }\n\n &-label {\n display: flex;\n color: var(--text-color);\n height: 100%;\n\n &-column {\n flex-direction: column;\n }\n\n &-text {\n white-space: nowrap;\n margin-right: 5px;\n margin-bottom: 6px;\n display: flex;\n align-items: center;\n color: color(var(--border-color) lightness(40%));\n background-color: transparent;\n font-size: 12px;\n position: absolute;\n top: -15px;\n white-space: nowrap;\n }\n }\n\n &-upper-right-label {\n position: absolute;\n transform: translateY(calc(-100% - 1.5px));\n right: 8px;\n min-height: 12px;\n font-size: 12px;\n color: color(var(--border-color) lightness(40%));\n }\n\n &-field {\n appearance: none;\n -webkit-appearance: none;\n font-family: inherit;\n font-size: inherit;\n box-sizing: border-box;\n resize: none;\n width: 100%;\n border: none;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n line-height: 1.25;\n color: var(--text-color);\n background: transparent;\n\n &:focus {\n outline: none;\n }\n\n &::placeholder {\n color: var(--text-light);\n }\n\n &-withIcon {\n padding-right: 37px !important;\n\n &-left {\n padding-right: 9px !important;\n padding-left: 37px !important;\n }\n }\n\n &-suffix {\n padding-right: 9px;\n }\n\n &-date {\n padding: 6px 9px;\n color-scheme: dark;\n\n svg {\n color: white;\n }\n }\n\n &-default {\n padding: 8px 7.5px 6px;\n }\n\n &[disabled] {\n background-color: var(--disabled-input-color);\n color: var(--disabled-font-color);\n -webkit-text-fill-color: var(--disabled-font-color);\n opacity: 1;\n\n &::placeholder {\n color: var(--disabled-font-color);\n -webkit-text-fill-color: var(--disabled-font-color);\n }\n }\n\n &-readOnly {\n cursor: default;\n color: var(--text-dark);\n -webkit-text-fill-color: var(--text-dark);\n }\n\n &-uppercase {\n text-transform: uppercase;\n }\n\n &-multiline {\n overflow-y: auto;\n resize: vertical;\n padding-top: 4px;\n min-height: 30px;\n\n &-autoResize {\n resize: none;\n overflow: hidden;\n }\n }\n\n &-icon {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: transparent;\n border: none;\n position: absolute;\n outline: none;\n right: 10px;\n top: 8px;\n color: var(--input-icon-color);\n width: 19px !important;\n height: 19px !important;\n user-select: none;\n top: 50%;\n transform: translateY(-50%);\n\n &-left {\n left: 10px;\n }\n\n &-notClickable {\n pointer-events: none;\n }\n }\n }\n\n &-error {\n height: 1em;\n padding-top: 3px;\n color: var(--error-font-color);\n font-size: 11px;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 0.5;\n }\n }\n}\n","import React from 'react';\nimport type { FormValidator } from 'services/formValidation';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum InputType {\n Edit = 'edit',\n Phone = 'phone',\n Email = 'email',\n Iban = 'iban',\n Date = 'date',\n HasNoIcon = 'hasNoIcon',\n Search = 'searchInput',\n Password = 'password',\n}\n\nexport type InputSlots = 'label' | 'container' | 'input' | 'suffix' | 'upperRightLabel' | 'fieldset';\n\ntype OverriddenInputAttributes =\n | 'onChange'\n | 'onFocus'\n | 'onBlur'\n | 'onMouseEnter'\n | 'onMouseLeave'\n | 'onClick'\n | 'type'\n | 'value'\n | 'min'\n | 'max'\n | 'autoComplete';\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, OverriddenInputAttributes>,\n HtmlProps {\n onMouseEnter?: ((event: React.MouseEvent) => void) | null;\n onMouseLeave?: ((event: React.MouseEvent) => void) | null;\n onFocus?: ((event: React.FocusEvent) => void) | null;\n onBlur?: ((event: React.FocusEvent) => void) | null;\n onChange?: ((value: string, event?: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement, Element>) => void) | null;\n errorMessage?: string;\n isValid?: boolean;\n isRequired?: boolean;\n label?: string;\n name?: string;\n className?: string;\n style?: React.CSSProperties;\n value?: string | number;\n icon?: React.ReactElement | null;\n isUppercase?: boolean;\n isRow?: boolean;\n tabIndex?: number;\n type?: InputType;\n onIconClick?: (() => void) | null;\n parse?: ((value: string) => string) | null;\n suffix?: string | React.ReactNode;\n disabled?: boolean;\n upperRightLabel?: string | React.ReactNode;\n labelInBorder?: boolean;\n showCancel?: boolean;\n onClearClicked?: (() => void) | null;\n min?: string | number | null;\n max?: string | number | null;\n placeholder?: string;\n useMatLabelStyle?: boolean;\n alwaysFloatLabel?: boolean;\n autoComplete?: string | null;\n onClick?: (() => void) | null;\n readOnly?: boolean;\n customInput?: React.ReactElement | null;\n autoFocus?: boolean;\n alwaysShowCancel?: boolean;\n formValidator?: FormValidator | null;\n multiline?: boolean;\n rows?: number;\n autoResize?: boolean;\n classNames?: SlotClassNames<InputSlots>;\n styles?: SlotStyles<InputSlots>;\n}\n","import React, { useState, useEffect, useRef, useCallback, useId } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faPhone,\n faPen,\n faEnvelope,\n faSearch,\n faXmark,\n faEye as passwordHiddenIcon,\n faEyeSlash as passwordShownIcon,\n} from '@fortawesome/free-solid-svg-icons';\nimport Tooltip from 'components/common/tooltip';\nimport { useComponentDefaults } from 'components/common/configProvider';\nimport styles from './input.module.pcss';\nimport type { InputProps } from './input.types';\nimport { InputType } from './input.types';\n\nfunction Input(props: InputProps) {\n const {\n name = '',\n id,\n label = '',\n errorMessage = '',\n isValid = true,\n className = '',\n style,\n value = '',\n icon = null,\n onChange = () => {},\n onFocus: onFocusProp = null,\n onBlur: onBlurProp = null,\n onMouseEnter: onMouseEnterProp = null,\n onMouseLeave: onMouseLeaveProp = null,\n isUppercase = false,\n isRequired = false,\n tabIndex = 0,\n type = undefined,\n isRow = false,\n onIconClick = null,\n parse = null,\n formValidator = null,\n autoFocus = false,\n suffix = null,\n upperRightLabel = null,\n labelInBorder = false,\n showCancel = false,\n onClearClicked,\n min = null,\n max = null,\n placeholder = '',\n useMatLabelStyle = true,\n alwaysFloatLabel = false,\n autoComplete = null,\n onClick = () => null,\n readOnly = false,\n customInput,\n alwaysShowCancel = false,\n multiline = false,\n rows,\n autoResize = false,\n classNames,\n styles: slotStyles,\n disabled = false,\n ...rest\n } = useComponentDefaults('Input', props);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [isPasswordShown, setIsPasswordShown] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n const fvRef = useRef(formValidator);\n\n const generatedId = useId();\n const inputId = id || name || generatedId;\n\n const resizeTextarea = useCallback(() => {\n const el = inputRef.current;\n if (!el || !autoResize) return;\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n }, [autoResize]);\n\n useEffect(() => {\n resizeTextarea();\n }, []);\n\n useEffect(() => {\n if (autoFocus && inputRef.current) {\n setTimeout(() => { inputRef.current?.focus(); }, 1);\n }\n }, [autoFocus]);\n\n useEffect(() => {\n fvRef.current = formValidator;\n const fv = fvRef.current;\n if (!fv) return;\n fv.label = label ?? '';\n fv.validate();\n const listener = () => forceUpdate(n => n + 1);\n fv.registerOnUpdateListener(listener);\n return () => { fv.removeOnUpdateListener(listener); };\n }, [formValidator, label]);\n\n const hasError = (): boolean => {\n return formValidator\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n };\n\n const computedIsRequired = (): boolean => {\n return !!(isRequired || (formValidator && formValidator.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n )));\n };\n\n const onMouseEnterHandler = (event: React.MouseEvent) => {\n setIsHovered(true);\n if (onMouseEnterProp) onMouseEnterProp(event);\n };\n\n const onMouseLeaveHandler = (event: React.MouseEvent) => {\n setIsHovered(false);\n if (onMouseLeaveProp) onMouseLeaveProp(event);\n };\n\n const onFocusHandler = (event: React.FocusEvent) => {\n setIsFocused(true);\n if (onFocusProp) onFocusProp(event);\n };\n\n const onBlurHandler = (event: React.FocusEvent) => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n if (onBlurProp) onBlurProp(event);\n };\n\n const onChangeHandler = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | string): void => {\n let parsedEvent: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | undefined;\n let val: string;\n\n if (typeof event !== 'string') {\n parsedEvent = event;\n val = event.target.value;\n } else {\n val = event;\n }\n\n if (parse) val = parse(val);\n if (formValidator) formValidator.set(val);\n if (onChange) onChange(val, parsedEvent);\n resizeTextarea();\n };\n\n const getInputType = (): string | undefined => {\n if (type === 'email') return undefined;\n if (type === 'password' && isPasswordShown) return 'text';\n return type;\n };\n\n const hasIcon =\n type &&\n type !== InputType.Date &&\n type !== InputType.Iban &&\n type !== InputType.HasNoIcon;\n\n const hasIconLeft =\n hasIcon && !useMatLabelStyle &&\n (type === InputType.Email || type === InputType.Phone || type === InputType.Search);\n\n const iconProps = {\n className: cx(styles.inputFieldIcon, {\n [styles.inputFieldIconNotClickable]: !onIconClick,\n [styles.inputFieldIconLeft]: hasIconLeft,\n }),\n onClick: onIconClick ?? undefined,\n };\n\n const customIcon = icon as React.ReactElement<{ className?: string; onClick?: React.MouseEventHandler }> | null;\n const renderedIcon = customIcon\n ? React.cloneElement(customIcon, {\n className: cx(\n styles.inputFieldIcon,\n { [styles.inputFieldIconNotClickable]: !onIconClick && !customIcon.props.onClick },\n customIcon.props.className,\n ),\n onClick: onIconClick ?? customIcon.props.onClick,\n })\n : null;\n const hasCustomIcon = !!icon;\n\n const passwordIconProps = {\n className: cx(styles.inputFieldIcon, styles.inputFieldIconPassword),\n onClick: () => setIsPasswordShown(!isPasswordShown),\n };\n\n const hasErr = hasError();\n\n let editedLabel = label;\n if (editedLabel && computedIsRequired()) editedLabel = `${editedLabel} *`;\n const requiredMark = computedIsRequired() ? <span className={styles.requiredMark}>*</span> : null;\n\n const currVal = formValidator ? formValidator.value : value;\n // A readOnly field is focusable but not editable — don't let focus drive the\n // \"editing\" affordances (primary-color border, label floating up on focus).\n // The label still floats when there's a value, since that's value-driven.\n const showFocus = isFocused && !readOnly;\n const shouldFloatLabel = useMatLabelStyle && (alwaysFloatLabel || showFocus || currVal || type === InputType.Date);\n\n return (\n <div className={cx(styles.input, className)} style={style}>\n <label\n htmlFor={inputId}\n className={cx(styles.inputLabel, classNames?.label, {\n [styles.inputLabelColumn]: !isRow,\n [styles.inputLabelInBorder]: labelInBorder,\n })}\n style={slotStyles?.label}\n >\n {label && !useMatLabelStyle ? (\n <span className={styles.inputLabelText}>\n {label}\n {requiredMark}\n </span>\n ) : null}\n {upperRightLabel && (\n <div className={cx(styles.inputUpperRightLabel, classNames?.upperRightLabel)} style={slotStyles?.upperRightLabel}>\n {upperRightLabel}\n </div>\n )}\n <div\n className={cx(styles.inputContainer, { [styles.inputContainerMultiline]: multiline }, classNames?.container)}\n style={slotStyles?.container}\n onMouseEnter={onMouseEnterHandler}\n onMouseLeave={onMouseLeaveHandler}\n >\n {renderedIcon}\n {React.cloneElement(customInput || (multiline ? <textarea /> : <input />), {\n ...rest,\n className: cx(\n styles.inputField,\n {\n [styles.inputFieldUppercase]: isUppercase,\n [styles.inputFieldDate]: type === InputType.Date,\n [styles.inputFieldDefault]: type !== InputType.Date,\n [styles.inputFieldWithIcon]: hasIcon || hasCustomIcon,\n [styles.inputFieldWithIconLeft]: hasIconLeft,\n [styles.inputFieldMultiline]: multiline,\n [styles.inputFieldMultilineAutoResize]: multiline && autoResize,\n [styles.inputFieldReadOnly]: readOnly && !disabled,\n },\n classNames?.input\n ),\n name,\n id: inputId,\n value: formValidator ? formValidator.value : value,\n tabIndex,\n ref: customInput ? undefined : inputRef,\n onChange: onChangeHandler,\n onFocus: onFocusHandler,\n onBlur: onBlurHandler,\n placeholder: !useMatLabelStyle ? placeholder : '',\n autoComplete,\n onClick,\n readOnly,\n disabled,\n ...(!multiline && { type: getInputType(), min, max }),\n ...(multiline && rows !== undefined && { rows }),\n })}\n {suffix && <div className={cx(styles.inputFieldSuffix, classNames?.suffix)} style={slotStyles?.suffix}>{suffix}</div>}\n </div>\n <fieldset\n className={cx(styles.inputFieldset, classNames?.fieldset, {\n [styles.inputContainerBorderFocused]: showFocus,\n [styles.inputContainerBorderSearchFocused]:\n type === InputType.Search && (showFocus || value),\n [styles.inputContainerBorderInvalid]: hasErr,\n [styles.inputContainerBorderError]: hasErr,\n })}\n style={slotStyles?.fieldset}\n >\n <legend\n className={cx(styles.inputFieldsetLegend, {\n [styles.inputFieldsetLegendActive]: shouldFloatLabel,\n })}\n >\n <span>{editedLabel}</span>\n </legend>\n </fieldset>\n {useMatLabelStyle && label && (\n <div\n className={cx(styles.inputMatLabel, {\n [styles.inputMatLabelFloating]: shouldFloatLabel,\n [styles.inputMatLabelMultiline]: multiline && !shouldFloatLabel,\n })}\n >\n {label}\n {requiredMark}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.inputPlaceholder,\n showFocus && !currVal && styles.inputPlaceholderShown,\n multiline && styles.inputPlaceholderMultiline,\n )}\n >\n {placeholder}\n </div>\n )}\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() : (errorMessage || '')}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </label>\n\n {type === InputType.Phone && <FontAwesomeIcon icon={faPhone} {...iconProps} />}\n {type === InputType.Email && <FontAwesomeIcon icon={faEnvelope} {...iconProps} />}\n {type === InputType.Edit && <FontAwesomeIcon icon={faPen} {...iconProps} />}\n {type === InputType.Search && <FontAwesomeIcon icon={faSearch} {...iconProps} />}\n {type === InputType.Password && (\n <FontAwesomeIcon\n icon={isPasswordShown ? passwordShownIcon : passwordHiddenIcon}\n {...passwordIconProps}\n />\n )}\n\n {((showCancel && value && (isFocused || isHovered)) || alwaysShowCancel) && (\n <FontAwesomeIcon\n icon={faXmark}\n className={styles.inputFieldIcon}\n onClick={onClearClicked ?? undefined}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n )}\n </div>\n );\n}\n\nexport default Input;\n",".colorPicker {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.swatch {\n width: 32px;\n height: 32px;\n border-radius: var(--default-border-radius);\n position: relative;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n flex-shrink: 0;\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);\n /* checkerboard so transparency is visible */\n background-image:\n linear-gradient(45deg, #bbb 25%, transparent 25%),\n linear-gradient(-45deg, #bbb 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, #bbb 75%),\n linear-gradient(-45deg, transparent 75%, #bbb 75%);\n background-size: 8px 8px;\n background-position: 0 0, 0 4px, 4px -4px, -4px 0;\n background-color: white;\n\n &:hover {\n & .swatchHex {\n opacity: 1;\n }\n }\n}\n\n.swatchFill {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n}\n\n.swatchHex {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-family: monospace;\n background: rgba(0, 0, 0, 0.55);\n color: white;\n border-radius: inherit;\n opacity: 0;\n transition: opacity 0.15s;\n user-select: none;\n pointer-events: none;\n z-index: 1;\n}\n\n.panel {\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 224px;\n}\n\n.gradientArea {\n width: 200px;\n height: 160px;\n position: relative;\n cursor: crosshair;\n border-radius: 4px;\n overflow: hidden;\n touch-action: none;\n background: linear-gradient(to right, white, hsl(calc(var(--hue) * 1deg), 100%, 50%));\n}\n\n.gradientOverlay {\n position: absolute;\n inset: 0;\n background: linear-gradient(to bottom, transparent, black);\n}\n\n.cursor {\n position: absolute;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n border: 2px solid white;\n box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: 1;\n}\n\n.hueSlider {\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n height: 10px;\n border-radius: var(--default-border-radius);\n outline: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background: linear-gradient(\n to right,\n hsl(0, 100%, 50%),\n hsl(60, 100%, 50%),\n hsl(120, 100%, 50%),\n hsl(180, 100%, 50%),\n hsl(240, 100%, 50%),\n hsl(300, 100%, 50%),\n hsl(360, 100%, 50%)\n );\n\n &::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 6px;\n height: 20px;\n border-radius: var(--default-border-radius);\n background: var(--primary-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &::-moz-range-thumb {\n width: 6px;\n height: 20px;\n border-radius: var(--default-border-radius);\n background: var(--primary-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n}\n\n.alphaSlider {\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n height: 10px;\n border-radius: var(--default-border-radius);\n outline: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n /* checkerboard base so transparency is visible under the gradient */\n background-image:\n linear-gradient(to right, transparent, var(--alpha-color)),\n linear-gradient(45deg, #bbb 25%, transparent 25%),\n linear-gradient(-45deg, #bbb 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, #bbb 75%),\n linear-gradient(-45deg, transparent 75%, #bbb 75%);\n background-size: 100% 100%, 8px 8px, 8px 8px, 8px 8px, 8px 8px;\n background-position: 0 0, 0 0, 0 4px, 4px -4px, -4px 0;\n background-color: white;\n\n &::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 6px;\n height: 20px;\n border-radius: var(--default-border-radius);\n background: var(--primary-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &::-moz-range-thumb {\n width: 6px;\n height: 20px;\n border-radius: var(--default-border-radius);\n background: var(--primary-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n}\n\n.hexRow {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.hexInput {\n width: 100%;\n padding: 5px 8px;\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n background: var(--input-background);\n color: var(--text-color);\n font-size: 13px;\n font-family: monospace;\n box-sizing: border-box;\n outline: none;\n\n &:focus {\n border-color: var(--primary-color);\n }\n}\n\n.eyeDropperButton {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 28px;\n height: 28px;\n padding: 0;\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n background: var(--input-background);\n color: var(--text-color);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover {\n border-color: var(--primary-color);\n color: var(--primary-color);\n }\n}\n","import { useState, useRef, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faEyeDropper } from '@fortawesome/free-solid-svg-icons';\n\nimport InteractableDiv from 'components/common/interactableDiv';\nimport FloatingMenu from 'components/common/floatingMenu';\nimport Input from 'components/common/input';\nimport { Align } from 'components/common/floatingMenu/floatingMenu.types';\nimport type { ColorPickerProps } from './colorPicker.types';\n\nimport styles from './colorPicker.module.pcss';\n\ninterface EyeDropperConstructor {\n new (): { open: (options?: { signal?: AbortSignal }) => Promise<{ sRGBHex: string }> };\n}\n\nconst eyeDropperSupported = typeof window !== 'undefined' && 'EyeDropper' in window;\n\nasync function pickColorFromScreen(): Promise<string | null> {\n const EyeDropperCtor = (window as unknown as { EyeDropper?: EyeDropperConstructor }).EyeDropper;\n if (!EyeDropperCtor) return null;\n try {\n const result = await new EyeDropperCtor().open();\n return result.sRGBHex;\n } catch {\n return null; // user cancelled or picker failed\n }\n}\n\n// ── Color utilities ──────────────────────────────────────────────────────────\n\nfunction isValidHex(s: string): boolean {\n return /^#[0-9a-fA-F]{6}$/.test(s) || /^#[0-9a-fA-F]{8}$/.test(s);\n}\n\n/** Split any valid hex into its 6-digit base and 0-100 alpha. */\nfunction parseHex(hex: string): { hex6: string; alpha: number } {\n if (/^#[0-9a-fA-F]{8}$/.test(hex)) {\n return {\n hex6: hex.slice(0, 7),\n alpha: Math.round((parseInt(hex.slice(7, 9), 16) / 255) * 100),\n };\n }\n return { hex6: hex.slice(0, 7), alpha: 100 };\n}\n\n/** Combine a 6-digit hex + 0-100 alpha into the right output format.\n * Full opacity (alpha === 100) is omitted — 6-digit hex implies opaque. */\nfunction buildValue(hex6: string, alpha: number, showAlpha: boolean): string {\n if (!showAlpha || alpha >= 100) return hex6;\n const a = Math.round((alpha / 100) * 255).toString(16).padStart(2, '0');\n return `${hex6}${a}`;\n}\n\nfunction hexToRgba(hex6: string, alpha: number): string {\n const r = parseInt(hex6.slice(1, 3), 16);\n const g = parseInt(hex6.slice(3, 5), 16);\n const b = parseInt(hex6.slice(5, 7), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha / 100})`;\n}\n\nfunction hexToHsv(hex6: string): { h: number; s: number; v: number } {\n const r = parseInt(hex6.slice(1, 3), 16) / 255;\n const g = parseInt(hex6.slice(3, 5), 16) / 255;\n const b = parseInt(hex6.slice(5, 7), 16) / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const delta = max - min;\n\n let h = 0;\n if (delta !== 0) {\n if (max === r) h = ((g - b) / delta) % 6;\n else if (max === g) h = (b - r) / delta + 2;\n else h = (r - g) / delta + 4;\n h = Math.round(h * 60);\n if (h < 0) h += 360;\n }\n\n const s = max === 0 ? 0 : Math.round((delta / max) * 100);\n const v = Math.round(max * 100);\n\n return { h, s, v };\n}\n\nfunction hsvToHex(h: number, s: number, v: number): string {\n const sv = s / 100;\n const vv = v / 100;\n const c = vv * sv;\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n const m = vv - c;\n\n let r = 0, g = 0, b = 0;\n if (h < 60) { r = c; g = x; b = 0; }\n else if (h < 120) { r = x; g = c; b = 0; }\n else if (h < 180) { r = 0; g = c; b = x; }\n else if (h < 240) { r = 0; g = x; b = c; }\n else if (h < 300) { r = x; g = 0; b = c; }\n else { r = c; g = 0; b = x; }\n\n const toHex = (n: number) => Math.round((n + m) * 255).toString(16).padStart(2, '0');\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n}\n\n// ── HexInput ─────────────────────────────────────────────────────────────────\n\ninterface HexInputProps {\n hex: string;\n onChange: (hex: string) => void;\n useInputComponent?: boolean;\n}\n\nfunction HexInput({ hex, onChange, useInputComponent = false }: HexInputProps): ReactElement {\n const [draft, setDraft] = useState(hex);\n\n const [prevHex, setPrevHex] = useState(hex);\n if (hex !== prevHex) {\n setPrevHex(hex);\n setDraft(hex);\n }\n\n function handleChange(raw: string) {\n setDraft(raw);\n const normalized = raw.startsWith('#') ? raw : `#${raw}`;\n if (isValidHex(normalized)) onChange(normalized);\n }\n\n function handleBlur() {\n const normalized = draft.startsWith('#') ? draft : `#${draft}`;\n if (!isValidHex(normalized)) setDraft(hex);\n }\n\n if (useInputComponent) {\n return (\n <Input\n value={draft}\n onChange={(value: string) => handleChange(value)}\n onBlur={handleBlur}\n />\n );\n }\n\n return (\n <input\n type=\"text\"\n value={draft}\n onChange={(e) => handleChange(e.target.value)}\n onBlur={handleBlur}\n className={styles.hexInput}\n spellCheck={false}\n />\n );\n}\n\n// ── Picker panel ─────────────────────────────────────────────────────────────\n\ninterface PickerPanelProps {\n hue: number;\n sat: number;\n val: number;\n alpha: number;\n onHueChange: (h: number) => void;\n onSVChange: (s: number, v: number) => void;\n onAlphaChange: (a: number) => void;\n showInput?: boolean;\n showAlpha?: boolean;\n}\n\nfunction PickerPanel({\n hue, sat, val, alpha,\n onHueChange, onSVChange, onAlphaChange,\n showInput = true, showAlpha = false,\n}: PickerPanelProps): ReactElement {\n const gradientRef = useRef<HTMLDivElement>(null);\n\n function getSVFromEvent(e: { clientX: number; clientY: number }): { s: number; v: number } {\n const rect = gradientRef.current!.getBoundingClientRect();\n const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));\n const y = Math.max(0, Math.min(1, (e.clientY - rect.top) / rect.height));\n return { s: x * 100, v: (1 - y) * 100 };\n }\n\n // Pointer Events (not mouse events) so dragging works for touch/pen too.\n function onGradientPointerDown(e: React.PointerEvent) {\n e.currentTarget.setPointerCapture(e.pointerId);\n const { s, v } = getSVFromEvent(e);\n onSVChange(s, v);\n\n const onMove = (ev: PointerEvent) => {\n const { s, v } = getSVFromEvent(ev);\n onSVChange(s, v);\n };\n const onUp = () => {\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', onUp);\n };\n window.addEventListener('pointermove', onMove);\n window.addEventListener('pointerup', onUp);\n }\n\n function onHexChange(normalized: string) {\n const { hex6, alpha: parsedAlpha } = parseHex(normalized);\n const { h, s, v } = hexToHsv(hex6);\n onHueChange(h);\n onSVChange(s, v);\n if (showAlpha) onAlphaChange(parsedAlpha);\n }\n\n const hex6 = hsvToHex(hue, sat, val);\n const hexInputValue = showAlpha ? buildValue(hex6, alpha, true) : hex6;\n\n return (\n <div className={styles.panel}>\n <div\n ref={gradientRef}\n className={styles.gradientArea}\n style={{ '--hue': hue } as React.CSSProperties}\n onPointerDown={onGradientPointerDown}\n >\n <div className={styles.gradientOverlay} />\n <div\n className={styles.cursor}\n style={{ left: `${sat}%`, top: `${100 - val}%` }}\n />\n </div>\n\n <input\n type=\"range\"\n min={0}\n max={359}\n value={hue}\n onChange={(e) => onHueChange(Number(e.target.value))}\n className={styles.hueSlider}\n />\n\n {showAlpha && (\n <input\n type=\"range\"\n min={0}\n max={100}\n value={alpha}\n onChange={(e) => onAlphaChange(Number(e.target.value))}\n className={styles.alphaSlider}\n style={{ '--alpha-color': hex6 } as React.CSSProperties}\n />\n )}\n\n {(showInput || eyeDropperSupported) && (\n <div className={styles.hexRow}>\n {showInput && <HexInput hex={hexInputValue} onChange={onHexChange} />}\n {eyeDropperSupported && (\n <button\n type=\"button\"\n className={styles.eyeDropperButton}\n onClick={async () => {\n const hex = await pickColorFromScreen();\n if (hex) onHexChange(hex);\n }}\n aria-label=\"Pick color from screen\"\n >\n <FontAwesomeIcon icon={faEyeDropper} />\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n\n// ── ColorPicker ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_COLOR = '#3b82f6';\n\nfunction ColorPicker({\n className,\n value = DEFAULT_COLOR,\n onChange,\n showInput = false,\n showAlpha = false,\n inline = false,\n ...rest\n}: ColorPickerProps): ReactElement {\n const [isOpen, setIsOpen] = useState(false);\n\n const initSafe = isValidHex(value) ? value : DEFAULT_COLOR;\n const { hex6: initHex6, alpha: initAlpha } = parseHex(initSafe);\n const initHsv = hexToHsv(initHex6);\n\n // Single state object so hue survives when saturation/value hit 0\n // (hexToHsv of any grey returns h=0, which would corrupt hue if derived from props).\n const [hsva, setHsva] = useState({ h: initHsv.h, s: initHsv.s, v: initHsv.v, a: initAlpha });\n\n // Ref mirrors state so drag callbacks never read stale closure values.\n const cur = useRef(hsva);\n\n // Sync from external prop changes: \"derive state during render\" pattern\n // avoids setState-in-effect. We compare the incoming hex against what our\n // current state produces — if they match, the change came from us and we skip.\n const [prevValue, setPrevValue] = useState(value);\n if (value !== prevValue) {\n setPrevValue(value);\n const safe = isValidHex(value) ? value : DEFAULT_COLOR;\n const { hex6: incomingHex6, alpha: incomingA } = parseHex(safe);\n const currentHex6 = hsvToHex(hsva.h, hsva.s, hsva.v);\n if (incomingHex6 !== currentHex6 || incomingA !== hsva.a) {\n const hsv = hexToHsv(incomingHex6);\n const next = { h: hsv.h, s: hsv.s, v: hsv.v, a: incomingA };\n setHsva(next);\n }\n }\n\n const { h: hue, s: sat, v: val, a: alpha } = hsva;\n\n function emit(h: number, s: number, v: number, a: number) {\n onChange?.(buildValue(hsvToHex(h, s, v), a, showAlpha));\n }\n\n function handleHueChange(h: number) {\n cur.current.h = h;\n setHsva(prev => ({ ...prev, h }));\n emit(h, cur.current.s, cur.current.v, cur.current.a);\n }\n\n function handleSVChange(s: number, v: number) {\n cur.current.s = s;\n cur.current.v = v;\n setHsva(prev => ({ ...prev, s, v }));\n emit(cur.current.h, s, v, cur.current.a);\n }\n\n function handleAlphaChange(a: number) {\n cur.current.a = a;\n setHsva(prev => ({ ...prev, a }));\n emit(cur.current.h, cur.current.s, cur.current.v, a);\n }\n\n const hex6 = hsvToHex(hue, sat, val);\n const swatchBackground = showAlpha ? hexToRgba(hex6, alpha) : hex6;\n const displayValue = buildValue(hex6, alpha, showAlpha);\n\n const pickerPanelProps: PickerPanelProps = {\n hue, sat, val, alpha,\n onHueChange: handleHueChange,\n onSVChange: handleSVChange,\n onAlphaChange: handleAlphaChange,\n showAlpha,\n };\n\n if (inline) {\n return (\n <div {...rest} className={cx(styles.colorPicker, className)}>\n <PickerPanel {...pickerPanelProps} showInput={showInput} />\n </div>\n );\n }\n\n return (\n <div {...rest} className={cx(styles.colorPicker, className)}>\n <FloatingMenu\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n dontCloseOnChildClick\n align={Align.Left}\n content={<PickerPanel {...pickerPanelProps} />}\n >\n <InteractableDiv className={styles.swatch}>\n <div className={styles.swatchFill} style={{ background: swatchBackground }} />\n <span className={styles.swatchHex}>{displayValue}</span>\n </InteractableDiv>\n </FloatingMenu>\n\n {showInput && (\n <HexInput\n hex={displayValue}\n onChange={(v) => onChange?.(v)}\n useInputComponent\n />\n )}\n </div>\n );\n}\n\nexport default ColorPicker;\n","\n.modal {\n padding: 16px;\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n color: var(--text-color);\n font-family: var(--default-font);\n box-sizing: border-box;\n position: relative;\n transform-origin: bottom center;\n animation:\n slideIn 0.2s,\n fadeIn 0.3s forwards;\n max-width: 95%;\n max-height: 95%;\n overflow: auto;\n\n @media not (--breakpoint-desktop) {\n max-width: 100%;\n max-height: 100%;\n }\n\n &-container {\n position: absolute;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n top: 0;\n left: 0;\n\n @media (--breakpoint-tablet) {\n z-index: 1;\n }\n }\n\n &-header {\n display: flex;\n gap: 8px;\n justify-content: space-between;\n margin-bottom: 16px;\n\n div {\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n svg {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n &-wrapper {\n position: fixed;\n width: 100%;\n height: 100%;\n background: #00000052;\n top: 0;\n left: 0;\n transition: all 0.3s ease-in-out;\n opacity: 0;\n\n &-shown {\n opacity: 1;\n }\n }\n}\n\n@keyframes slideIn {\n from {\n transform: scale(0);\n }\n to {\n transform: scale(0.99);\n }\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './modal.module.pcss';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faXmark as closeIcon } from '@fortawesome/free-solid-svg-icons';\nimport { ModalProps } from './modal.types';\nimport { useEffect, useState } from 'react';\n\nfunction Modal({\n children = null,\n title = '',\n isOpen = false,\n onClose = () => null,\n className = '',\n style,\n hideHeader = false,\n classNames,\n styles: slotStyles,\n}: ModalProps) {\n const [isRendered, setIsRendered] = useState(isOpen);\n const [animateIn, setAnimateIn] = useState(isOpen);\n\n useEffect(() => {\n if (isOpen) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setIsRendered(isOpen);\n setTimeout(() => setAnimateIn(true), 1);\n } else {\n setAnimateIn(false);\n setTimeout(() => setIsRendered(isOpen), 300);\n }\n }, [isOpen]);\n\n if (!isRendered) return null;\n\n return (\n <BodyEnd>\n <div className={cx(styles.modalContainer, classNames?.container)} style={slotStyles?.container}>\n <div\n className={cx(styles.modalWrapper, animateIn && styles.modalWrapperShown, classNames?.backdrop)}\n style={slotStyles?.backdrop}\n onClick={onClose}\n />\n {animateIn && (\n <div\n className={cx(styles.modal, animateIn && styles.modalShown, className, classNames?.modal)}\n style={{ ...style, ...slotStyles?.modal }}\n onClick={(e) => e.stopPropagation()}\n >\n {!hideHeader && (\n <div className={cx(styles.modalHeader, classNames?.header)} style={slotStyles?.header}>\n <div className={classNames?.title} style={slotStyles?.title}>{title}</div>\n <FontAwesomeIcon onClick={onClose} icon={closeIcon} className={classNames?.closeButton} style={slotStyles?.closeButton as React.CSSProperties & Record<`--fa-font-${string}`, string>} />\n </div>\n )}\n {children}\n </div>\n )}\n </div>\n </BodyEnd>\n );\n}\n\nexport default Modal;\n","import { useState, type ReactElement } from 'react';\n\nimport Modal from '../modal';\nimport { ActionButtons } from '../actionButtons';\nimport { ButtonStyleType } from '../button';\nimport { useComponentDefaults } from '../configProvider';\nimport type { ConfirmModalProps } from './confirmModal.types';\n\nfunction ConfirmModal(props: ConfirmModalProps): ReactElement {\n const {\n children = null,\n className = '',\n onClose = () => {},\n onConfirm = () => {},\n title = '',\n content = null,\n isOpen: propIsOpen = undefined,\n submitLabel = 'Confirm',\n cancelLabel = 'Cancel',\n isDelete = false,\n actionButtonsProps = {},\n } = useComponentDefaults('ConfirmModal', props);\n const [internalOpen, setInternalOpen] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n function handleClose(didSubmit = false) {\n setInternalOpen(false);\n onClose(didSubmit);\n }\n\n async function handleConfirm() {\n setIsSubmitting(true);\n try {\n await onConfirm();\n handleClose(true);\n } finally {\n setIsSubmitting(false);\n }\n }\n\n const isOpen = propIsOpen === undefined ? internalOpen : propIsOpen;\n\n const modal = (\n <Modal title={title} isOpen={isOpen} onClose={() => handleClose()} className={children ? undefined : className}>\n {content}\n <ActionButtons\n onClose={() => handleClose()}\n onSubmit={handleConfirm}\n submitLabel={submitLabel}\n cancelLabel={cancelLabel}\n submitButtonStyle={isDelete ? ButtonStyleType.Delete : undefined}\n isSubmitButtonLoading={isSubmitting}\n {...actionButtonsProps}\n />\n </Modal>\n );\n\n if (!children) return modal;\n\n return (\n <div className={className}>\n <span onClick={() => setInternalOpen(true)}>{children}</span>\n {modal}\n </div>\n );\n}\n\nexport default ConfirmModal;\n","\n.datePickerMonth {\n &-item {\n aspect-ratio: 1;\n display: flex;\n justify-content: center;\n align-items: center;\n margin: 1px 0;\n }\n\n &-content {\n display: grid;\n text-align: center;\n grid-template-columns: repeat(7, minmax(0, 1fr));\n gap: 0px;\n }\n\n &-day {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover {\n /* background-color: var(--primary-color);\n border-radius: 800px; */\n }\n\n &-today {\n background-color: var(--background-accent-light);\n border-radius: var(--default-border-radius);\n }\n\n &-selected {\n background-color: var(--primary-color);\n color: var(--text-on-primary);\n border-radius: 0;\n\n &-start {\n border-top-left-radius: var(--default-border-radius);\n border-bottom-left-radius: var(--default-border-radius);\n }\n\n &-end {\n border-top-right-radius: var(--default-border-radius);\n border-bottom-right-radius: var(--default-border-radius);\n }\n }\n\n &-disabled {\n filter: brightness(0.5);\n cursor: not-allowed;\n }\n }\n\n &-placeholder {\n user-select: none;\n pointer-events: none;\n }\n}\n","// import { Settings } from 'luxon';\n// import Polyglot from 'node-polyglot';\n\nconst supportedLocales: string[] = ['de_AT', 'de_CH', 'de_DE', 'en_US', 'en_GB', 'de', 'en'];\n\nconst defaultLocale = 'en_US';\n\nconst getCurrentLocale = (): string => {\n const locale = navigator.languages[0]?.replace('-', '_') || defaultLocale;\n\n if (!supportedLocales.includes(locale)) return defaultLocale;\n\n if (locale === 'en_GB' || locale === 'en') return 'en_US'; // Change GB to US. Alternatively, add GB File\n if (locale === 'de') return 'de_DE';\n\n return locale;\n};\n\nexport const mapLocale = (locale: string): string => {\n switch (locale) {\n case 'en_US':\n case 'en_GB':\n return 'en';\n case 'de_DE':\n case 'de_CH':\n case 'de_AT':\n return 'de';\n default:\n return 'de';\n }\n};\n\n// const getPolyglot = async (locale: string): Promise<Polyglot> => {\n// let phrases: object = {};\n// let extendPhrases: object = {};\n// const { default: impPhrasesLocale } = await import(`../locales/${locale || defaultLocale}.json`);\n// if ((locale || '').startsWith('de')) {\n// const { default: impPhrases } = await import('locales/de_DE.json');\n// phrases = impPhrases;\n// extendPhrases = impPhrasesLocale;\n// } else {\n// phrases = impPhrasesLocale;\n// }\n// const shortLocale: string = mapLocale(locale);\n// Settings.defaultLocale = shortLocale;\n\n// const polyglot: Polyglot = new Polyglot({\n// phrases: JSON.parse(JSON.stringify(phrases)),\n// locale: shortLocale,\n// });\n\n// polyglot.extend(JSON.parse(JSON.stringify(extendPhrases)));\n// return polyglot;\n// };\n\nlet currentLocale: string = getCurrentLocale();\n// let polyglot: Polyglot = await getPolyglot(currentLocale);\n\n// export default polyglot;\n\nexport async function setLocale(locale: string): Promise<void> {\n currentLocale = locale;\n // polyglot = await getPolyglot(locale);\n}\n\nexport function getLocale(delimiter = '_'): string {\n return currentLocale.replace('_', delimiter);\n}\n","import { getLocale } from 'services/localization';\n\nexport function getDaysInMonth(month: number, year: number): number {\n return new Date(year, month, 0).getDate();\n}\n\nexport function getDateFromDayMonthAndYear(day: number, month: number, year: number): Date {\n return new Date(Date.UTC(year, month - 1, day));\n}\n\nexport function getMonthName(locale: string, year: number, month: number, day: number, short = false): string {\n const currDate = new Date(Date.UTC(year, month - 1, day));\n return currDate.toLocaleDateString(locale, { month: short ? 'short' : 'long' });\n}\n\nexport function getMonthNames(locale = getLocale('-')): string[] {\n return Array.from(Array(12).keys()).map((index) => getMonthName(locale, 2023, index + 1, 1));\n}\n\nexport function getWeekDays(locale: string, short = true): string[] {\n const currDate = new Date(Date.UTC(2023, 3, 10)); // Random Monday - 10.4.2023\n const weekDays: string[] = [];\n for (let i = 0; i < 7; i++) {\n weekDays.push(currDate.toLocaleDateString(locale, { weekday: short ? 'short' : 'long' }));\n currDate.setDate(currDate.getDate() + 1);\n }\n return weekDays;\n}\n\nexport function getStartWeekDayOfMonth(month: number, year: number): number {\n const start = new Date(Date.UTC(year, month - 1, 1)).getDay();\n return start || 7;\n}\n\nexport function getDayMonthAndYearOfDate(date: Date): { day: number; month: number; year: number } {\n return {\n day: date.getDate(),\n month: date.getMonth() + 1,\n year: date.getFullYear(),\n };\n}\n\nexport function getDateString(date: Date): string {\n const day = date.getDate();\n const month = date.getMonth() + 1;\n const year = date.getFullYear();\n\n return `${day < 10 ? `0${day}` : day}.${month < 10 ? `0${month}` : month}.${year}`;\n}\n\nexport interface DateMaskSelection {\n start: number;\n end: number;\n}\n\nexport interface DateMaskState {\n value: string;\n selection: DateMaskSelection | null;\n}\n\n/**\n * Auto-corrects a partially typed `dd.mm.yyyy` mask value so a single out-of-range\n * digit doesn't force the user to backtrack:\n * - a day \"tens\" digit > 3 (e.g. typing `4`) becomes `04` and the caret jumps to the month\n * - a day of `3x` where x > 1 (e.g. `35`) becomes `0x`\n * - a month \"tens\" digit > 1 (e.g. `2`) becomes `02` and the caret jumps to the year\n * - a month `1x` where x > 2 (e.g. `13`) is clamped to `12`\n *\n * `previousValue` supplies the digits to retain for the part of the field that isn't\n * being rewritten. The returned `selection` is the adjusted caret position, or the\n * passed-in `selection` when no correction applies.\n */\nexport function correctDateMaskValue(\n nextValue: string,\n previousValue: string,\n selection: DateMaskSelection | null,\n): DateMaskState {\n let value = nextValue;\n let nextSelection = selection;\n\n if (value[0] !== '_') {\n if (value[0] > '3') {\n value = `0${value[0]}${previousValue.substring(2)}`;\n nextSelection = { start: 3, end: 3 };\n } else if (value[0] === '3') {\n if (value[1] !== '_' && value[1] > '1') {\n value = `0${value[1]}${previousValue.substring(2)}`;\n nextSelection = { start: 3, end: 3 };\n }\n }\n }\n if (value[3] !== '_' && value[3] > '1') {\n value = `${value.substring(0, 3)}0${value[3]}${previousValue.substring(5)}`;\n nextSelection = { start: 6, end: 6 };\n }\n if (value[3] === '1' && value[4] !== '_' && value[4] > '2') {\n value = `${value.substring(0, 3)}${value[3]}2${previousValue.substring(5)}`;\n }\n\n return { value, selection: nextSelection };\n}\n","import cx from 'classnames';\n\nimport styles from './datePickerMonth.module.pcss';\nimport { getLocale } from 'services/localization';\nimport InteractableDiv from 'components/common/interactableDiv';\nimport {\n getDateFromDayMonthAndYear,\n getDayMonthAndYearOfDate,\n getDaysInMonth,\n getStartWeekDayOfMonth,\n getWeekDays,\n} from '../../dateFunctions';\n\ninterface DatePickerMonthProps {\n className?: string;\n month?: number;\n year?: number;\n onSelect?: (date: Date) => void;\n selectionStart?: Date;\n selectionEnd?: Date;\n minDate?: Date | null;\n maxDate?: Date | null;\n}\n\nfunction checkSelected(\n day: number,\n month: number,\n year: number,\n selectionStart: Date | undefined,\n selectionEnd: Date | undefined,\n) {\n const { day: startDay, month: startMonth, year: startYear } = selectionStart\n ? getDayMonthAndYearOfDate(selectionStart)\n : { day: undefined, month: undefined, year: undefined };\n const { day: endDay, month: endMonth, year: endYear } = selectionEnd\n ? getDayMonthAndYearOfDate(selectionEnd)\n : { day: undefined, month: undefined, year: undefined };\n\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n const isStartDate = day === startDay && month === startMonth && year === startYear;\n const isEndDate = day === endDay && month === endMonth && year === endYear;\n\n let isInRange = false;\n if (startDay !== undefined && startMonth !== undefined && startYear !== undefined &&\n endDay !== undefined && endMonth !== undefined && endYear !== undefined) {\n const selectionStartNoTime = getDateFromDayMonthAndYear(startDay, startMonth, startYear);\n const selectionEndNoTime = getDateFromDayMonthAndYear(endDay, endMonth, endYear);\n isInRange =\n toCheckNoTime.getTime() >= selectionStartNoTime.getTime() &&\n toCheckNoTime.getTime() <= selectionEndNoTime.getTime();\n }\n\n return { isStartDate, isInRange, isEndDate };\n}\n\nfunction checkDisabled(\n day: number,\n month: number,\n year: number,\n minDate: Date | null | undefined,\n maxDate: Date | null | undefined,\n): boolean {\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n if (minDate) {\n const { day: minDay, month: minMonth, year: minYear } = getDayMonthAndYearOfDate(minDate);\n if (toCheckNoTime < getDateFromDayMonthAndYear(minDay, minMonth, minYear)) return true;\n }\n\n if (maxDate) {\n const { day: maxDay, month: maxMonth, year: maxYear } = getDayMonthAndYearOfDate(maxDate);\n if (toCheckNoTime > getDateFromDayMonthAndYear(maxDay, maxMonth, maxYear)) return true;\n }\n\n return false;\n}\n\nfunction checkIsToday(day: number, month: number, year: number): boolean {\n const { day: currDay, month: currMonth, year: currYear } = getDayMonthAndYearOfDate(new Date());\n return day === currDay && month === currMonth && year === currYear;\n}\n\nexport default function DatePickerMonth({\n className = '',\n month = new Date().getMonth() + 1,\n year = new Date().getFullYear(),\n onSelect = () => null,\n selectionStart,\n selectionEnd,\n minDate = null,\n maxDate = null,\n}: DatePickerMonthProps) {\n const locale = getLocale('-');\n const daysInMonth = getDaysInMonth(month, year);\n const startWeekDayOfMonth = getStartWeekDayOfMonth(month, year);\n\n return (\n <div className={cx(styles.datePickerMonth, className)}>\n <div className={cx(styles.datePickerMonthContent)}>\n {getWeekDays(locale).map((weekDay, index) => <div key={index}>{weekDay}</div>)}\n {Array.from(Array(startWeekDayOfMonth - 1).keys()).map((index) => (\n <div\n key={index}\n className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)}\n />\n ))}\n {Array.from(Array(daysInMonth).keys()).map((index) => {\n const day = index + 1;\n const selectedRes = checkSelected(day, month, year, selectionStart, selectionEnd);\n const isDisabled = checkDisabled(day, month, year, minDate, maxDate);\n const isToday = checkIsToday(day, month, year);\n\n return (\n <InteractableDiv\n key={day}\n onClick={() => isDisabled ? null : onSelect(getDateFromDayMonthAndYear(day, month, year))}\n className={cx(styles.datePickerMonthDay, styles.datePickerMonthItem, {\n [styles.datePickerMonthDaySelected]: selectedRes.isInRange,\n [styles.datePickerMonthDaySelectedStart]: selectedRes.isStartDate,\n [styles.datePickerMonthDaySelectedEnd]: selectedRes.isEndDate,\n [styles.datePickerMonthDayDisabled]: isDisabled,\n [styles.datePickerMonthDayToday]: isToday,\n })}\n >\n {day}\n </InteractableDiv>\n );\n })}\n {Array.from(Array(42 - (startWeekDayOfMonth + daysInMonth - 1)).keys()).map((index) => (\n <div\n key={index}\n className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)}\n >\n \n </div>\n ))}\n </div>\n </div>\n );\n}\n",".infiniteBlock {\n max-height: none;\n}\n\n.spinner-wrapper {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 4px 0;\n}\n\n.spinner {\n width: 32px;\n height: 32px;\n}\n","import React, { useState, useRef, useCallback } from 'react';\nimport cx from 'classnames';\n\nimport styles from './infiniteBlock.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport type { InfiniteBlockProps } from './infiniteBlock.types';\n\n// Walk down a React element tree until we reach a string leaf or an array of children.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction childStartsWithKey(child: React.ReactElement<any>, key: string): boolean {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let node: React.ReactElement<any> = child;\n\n while (\n node.props.children !== null &&\n typeof node.props.children === 'object' &&\n !Array.isArray(node.props.children)\n ) {\n node = node.props.children as typeof node;\n }\n\n const content: unknown = node.props.children;\n\n if (Array.isArray(content)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = content as any[];\n // If the first element has no children of its own, scan for a raw string\n if (!arr[0]?.props?.children) {\n for (const item of arr) {\n if (typeof item === 'string' && item.trim().length > 0) {\n return item.toLowerCase().startsWith(key);\n }\n }\n }\n return String(arr[0].props.children).toLowerCase().startsWith(key);\n }\n\n return String(content).toLowerCase().startsWith(key);\n}\n\nfunction clampIndex(index: number, change: number, length: number): number {\n const next = index + change;\n if (next === length) return 0;\n if (next < -1) return length - 1;\n return next;\n}\n\nfunction InfiniteBlock({\n children,\n onScroll,\n className = '',\n isDataLoading = false,\n setHighlightedIndex = () => null,\n}: InfiniteBlockProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Use a ref (not state) for the scroll-guard so reads are always synchronous,\n // avoiding the React-batching race where two scroll events fire before the\n // first setState call has been committed.\n const isScrollLoadingRef = useRef(false);\n const [showScrollSpinner, setShowScrollSpinner] = useState(false);\n\n // Keyboard nav state lives in refs — it doesn't affect rendering.\n const indexRef = useRef(-1);\n const lastKeyRef = useRef<string | null>(null);\n\n const handleScroll = useCallback(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const { scrollTop, offsetHeight, scrollHeight } = el;\n\n // Browsers calculate scrollTop with a small floating-point error under zoom,\n // so we allow up to 5px of slack before deciding we are at the bottom.\n if (Math.abs(scrollTop + offsetHeight - scrollHeight) > 5) return;\n if (isScrollLoadingRef.current) return;\n\n isScrollLoadingRef.current = true;\n setShowScrollSpinner(true);\n onScroll().then(() => {\n isScrollLoadingRef.current = false;\n setShowScrollSpinner(false);\n });\n }, [onScroll]);\n\n const respondToUserInput = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n const el = containerRef.current;\n if (!el) return;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const childArray = React.Children.toArray(children) as React.ReactElement<any>[];\n let index = indexRef.current;\n\n switch (event.key) {\n case 'ArrowDown':\n index = clampIndex(index, 1, childArray.length);\n break;\n case 'ArrowUp':\n index = clampIndex(index, -1, childArray.length);\n break;\n default:\n for (let i = 0; i < childArray.length; i++) {\n if (childStartsWithKey(childArray[i], event.key)) {\n if (index >= i && lastKeyRef.current === event.key) {\n continue;\n }\n index = i;\n break;\n }\n }\n }\n\n indexRef.current = index;\n lastKeyRef.current = event.key;\n\n if (index >= 0) {\n const child = el.children[index] as HTMLElement | undefined;\n if (child) {\n const childTop = child.offsetTop;\n const childBottom = childTop + child.offsetHeight;\n if (childTop < el.scrollTop) {\n el.scrollTop = childTop;\n } else if (childBottom > el.scrollTop + el.clientHeight) {\n el.scrollTop = childBottom - el.clientHeight;\n }\n }\n setHighlightedIndex(index);\n }\n },\n [children, setHighlightedIndex]\n );\n\n return (\n <div\n className={cx(styles.infiniteBlock, className)}\n onScroll={handleScroll}\n onKeyDown={respondToUserInput}\n tabIndex={0}\n ref={containerRef}\n >\n {isDataLoading ? (\n <div className={styles.spinnerWrapper}>\n <SpinnerLoading className={styles.spinner} />\n </div>\n ) : children}\n {showScrollSpinner && (\n <div className={styles.spinnerWrapper}>\n <SpinnerLoading className={styles.spinner} />\n </div>\n )}\n </div>\n );\n}\n\nexport default InfiniteBlock;\n","\n.required-mark {\n padding: 0px 0px 0px 4px;\n color: var(--required-mark-color, var(--error-color));\n}\n\n.dropdown {\n position: relative;\n\n &-label {\n display: flex;\n\n &-column {\n flex-direction: column;\n }\n\n &-text {\n white-space: nowrap;\n margin-right: 5px;\n margin-bottom: 5px;\n display: flex;\n align-items: center;\n color: var(--text-color);\n font-size: 12px;\n position: absolute;\n top: -15px;\n }\n }\n\n &-input {\n position: relative;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: var(--input-background);\n border-radius: var(--default-border-radius);\n\n &-plain {\n background: transparent;\n }\n\n &-readOnly {\n cursor: default;\n }\n\n &:focus-within {\n outline: none;\n }\n\n &-button {\n padding: 7px 20% 7px 7.5px !important;\n background-color: transparent;\n border: none;\n font-family: inherit;\n font-size: inherit;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n text-align: left;\n width: 100%;\n line-height: 1.25;\n color: var(--text-color);\n\n &-disabled {\n background-color: var(--disabled-input-color);\n color: var(--disabled-font-color);\n border-radius: var(--default-border-radius);\n }\n\n &-readOnly {\n cursor: default;\n }\n\n &:focus {\n outline: none;\n }\n\n &-icon {\n float: right;\n background-color: transparent;\n border: none;\n position: absolute;\n outline: none;\n right: var(--spacing-s);\n top: 50%;\n transform: translateY(-50%);\n color: var(--text-color);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &-arrow {\n transition: transform 0.25s;\n pointer-events: none;\n\n &-open {\n transform: rotate(180deg);\n }\n }\n }\n }\n\n &-list-anim {\n position: fixed;\n z-index: 1;\n color: var(--text-color);\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n border-radius: var(--default-border-radius);\n overflow: hidden;\n transform: scaleY(1);\n transition: transform 0.25s;\n transform-origin: right top;\n\n &-flip {\n transform-origin: right bottom;\n }\n\n &-wider {\n width: max-content !important;\n }\n }\n\n &-list {\n width: 100%;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n max-height: 160px;\n list-style-type: none;\n\n &-item {\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: var(--background-modal);\n padding: 8px;\n text-align: left;\n border-radius: 0;\n transition: all 0.3s;\n\n &-active {\n background-color: var(--background-accent);\n }\n\n &-selected {\n font-weight: 500;\n }\n\n &:focus {\n outline: none;\n }\n\n &:hover {\n background-color: var(--background-accent);\n }\n\n &-disabled {\n background-color: var(--disabled-input-color);\n color: var(--disabled-font-color);\n cursor: not-allowed;\n\n &:hover {\n background-color: var(--disabled-input-color);\n }\n }\n }\n\n &-hidden {\n transform: scaleY(0);\n }\n }\n }\n\n &-fieldset {\n position: absolute;\n width: 100%;\n margin: 0;\n box-sizing: border-box;\n border-radius: var(--default-border-radius);\n inset: -10px 0 0 0;\n padding-left: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: var(--border-color);\n pointer-events: none;\n user-select: none;\n\n &-legend {\n display: block;\n max-width: 0;\n transition: max-width 0.2s;\n white-space: nowrap;\n padding: 0;\n\n &-active {\n max-width: 300px;\n }\n\n span {\n font-size: 13px;\n padding: 5px;\n opacity: 0;\n }\n\n /* With an empty label the span would still reserve its padding, leaving a gap in\n the fieldset's top border. Collapse it so the notch closes when there's no label. */\n span:empty {\n padding: 0.000001px;\n }\n }\n }\n\n &-placeholder {\n position: absolute;\n top: 8px;\n left: 7px;\n transition: all 0.2s;\n opacity: 0;\n\n &-shown {\n animation: 0.2s fadeIn 0.3s forwards;\n }\n }\n\n &-matLabel {\n position: absolute;\n transition: all 0.3s;\n inset: 9px 0 0 7px;\n font-size: 16px;\n color: var(--input-label-resting-color, var(--text-light));\n pointer-events: none;\n user-select: none;\n\n &-floating {\n inset: -9px 0 0 14px;\n font-size: 13px;\n color: var(--input-label-floating-color, var(--text-color));\n }\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 0.5;\n }\n }\n\n &-border {\n outline: 1px solid var(--border-color);\n transition: border-color;\n background-color: var(--input-background);\n outline: none;\n\n &-focused {\n outline-color: var(--primary-color);\n border-color: var(--primary-color);\n }\n\n &-searchFocused {\n outline-color: var(--search-input-color);\n outline-width: 2px;\n border-color: var(--search-input-color);\n }\n\n &-plain {\n border-color: transparent;\n outline-color: transparent;\n }\n\n &-invalid {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-invalid:hover {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-error {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n }\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport InfiniteBlock from 'components/common/infiniteBlock';\nimport BodyEnd from 'components/common/bodyEnd';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronDown as dropdownIcon } from '@fortawesome/free-solid-svg-icons';\nimport Downshift, { StateChangeOptions, DownshiftState } from 'downshift';\nimport Tooltip from 'components/common/tooltip';\n\nimport { useFloatingPosition } from '../floatingMenu/useFloatingPosition';\nimport { useComponentDefaults } from '../configProvider';\nimport styles from './dropdown.module.pcss';\nimport type { DropdownProps, DropdownItem } from './dropdown.types';\n\nfunction Dropdown(props: DropdownProps) {\n const {\n errorMessage = '',\n className = '',\n label = '',\n value = '',\n isValid = true,\n tabIndex = 0,\n isRequired = false,\n customProps = {},\n isRow = false,\n disabled = false,\n readOnly = false,\n onScroll = () => Promise.resolve(),\n onClick,\n onChange,\n onFocus: onFocusProp = null,\n onBlur: onBlurProp = null,\n onMouseEnter: onMouseEnterProp = null,\n onMouseLeave: onMouseLeaveProp = null,\n dropdownLabel: dropdownLabelProp,\n isDropdownListWider = false,\n inputClassName = '',\n dropDownIconClassName = '',\n dropDownClassName = '',\n formValidator = null,\n labelClassName = '',\n dropDownInputClassName = '',\n items = [],\n useMatLabelStyle = true,\n alwaysFloatLabel = false,\n placeholder = '',\n plainStyle = false,\n scrollToSelected = false,\n reactRef,\n ...rest\n } = useComponentDefaults('Dropdown', props);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const fvRef = useRef(formValidator);\n const triggerRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const [menuIsOpen, setMenuIsOpen] = useState(false);\n const [triggerWidth, setTriggerWidth] = useState(10);\n\n useEffect(() => {\n if (menuIsOpen) {\n const rect = triggerRef.current?.getBoundingClientRect();\n setTriggerWidth(rect?.width ?? 10);\n }\n }, [menuIsOpen]);\n\n useFloatingPosition({\n isOpen: menuIsOpen,\n triggerRef,\n anchorRef,\n panelRef: anchorRef,\n flipClassName: styles.dropdownInputListAnimFlip,\n });\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!fvRef.current) return;\n fvRef.current.label = label ?? '';\n fvRef.current.validate();\n const listener = () => forceUpdate(n => n + 1);\n fvRef.current.registerOnUpdateListener(listener);\n return () => fvRef.current?.removeOnUpdateListener(listener);\n }, [formValidator, label]);\n\n const onMouseEnterHandler = (event: React.MouseEvent) => {\n setIsHovered(true);\n onMouseEnterProp?.(event);\n };\n\n const onMouseLeaveHandler = (event: React.MouseEvent) => {\n setIsHovered(false);\n onMouseLeaveProp?.(event);\n };\n\n const onFocusHandler = (event: React.FocusEvent) => {\n setIsFocused(true);\n onFocusProp?.(event);\n };\n\n const onBlurHandler = (event: React.FocusEvent) => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n onBlurProp?.(event);\n };\n\n const hasError = (): boolean => {\n return formValidator\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n };\n\n const computedIsRequired = (): boolean => {\n return !!(isRequired || formValidator?.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n ));\n };\n\n const onChangeHandler = (val: string | number): void => {\n if (formValidator) {\n formValidator.set(val);\n onChange?.(formValidator.value, customProps);\n } else {\n onChange?.(val, customProps);\n }\n };\n\n let dropdownLabel = dropdownLabelProp;\n const currentValue = formValidator ? formValidator.value as string | number : value;\n const hasErr = hasError();\n\n items.forEach((item: DropdownItem) => {\n if (item.key === currentValue) {\n dropdownLabel = item.label as string;\n }\n });\n\n const displayValue = dropdownLabel || currentValue;\n const isDisplayBlank =\n displayValue == null ||\n (typeof displayValue === 'string' && displayValue.trim() === '');\n\n const requiredMark = computedIsRequired() ? <span className={styles.requiredMark}>*</span> : null;\n const editedLabel = label && computedIsRequired() ? `${label} *` : label;\n\n const showFocus = isFocused && !readOnly;\n\n return (\n <div\n {...rest}\n className={cx(className, styles.dropdownLabel, styles.dropdown, {\n [styles.dropdownLabelColumn]: !isRow,\n })}\n onMouseEnter={onMouseEnterHandler}\n onMouseLeave={onMouseLeaveHandler}\n >\n <Downshift\n {...(readOnly ? { isOpen: false } : {})}\n onChange={(selection: DropdownItem | null) => onChangeHandler((selection || { key: '' }).key)}\n itemToString={(item: DropdownItem | null) => (item ? String(item.key) : '')}\n selectedItem={items.find((el) => el.key === currentValue) ?? null}\n onStateChange={(changes: StateChangeOptions<DropdownItem>) => {\n if (typeof changes.isOpen === 'boolean') setMenuIsOpen(changes.isOpen);\n }}\n stateReducer={(state: DownshiftState<DropdownItem>, changes: StateChangeOptions<DropdownItem>) => {\n if (scrollToSelected && Object.prototype.hasOwnProperty.call(changes, 'isOpen')) {\n return {\n ...changes,\n highlightedIndex: changes.isOpen ? items.indexOf(state.selectedItem as DropdownItem) : null,\n };\n }\n return changes;\n }}\n >\n {({\n getItemProps,\n getMenuProps,\n getToggleButtonProps,\n isOpen,\n selectedItem,\n highlightedIndex,\n setHighlightedIndex,\n }) => (\n <div>\n <div\n ref={triggerRef}\n onFocus={onFocusHandler}\n onBlur={onBlurHandler}\n className={cx(\n styles.dropdownInput,\n {\n [styles.dropdownInputPlain]: plainStyle,\n [styles.dropdownInputReadOnly]: readOnly && !disabled,\n },\n dropDownInputClassName\n )}\n >\n <button\n tabIndex={tabIndex}\n type=\"button\"\n disabled={disabled}\n aria-readonly={readOnly || undefined}\n style={isDropdownListWider ? { padding: '6px', border: 'none' } : {}}\n className={cx(\n styles.dropdownInputButton,\n {\n [styles.dropdownInputButtonDisabled]: disabled,\n [styles.dropdownInputButtonReadOnly]: readOnly && !disabled,\n },\n inputClassName\n )}\n {...getToggleButtonProps()}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n getToggleButtonProps().onClick?.(e);\n onClick?.(e);\n }}\n ref={reactRef}\n >\n {/* Non-breaking space when blank (same text-node layout as a\n real value) so the button keeps a full line of height. */}\n {isDisplayBlank ? '\\u00A0' : displayValue}\n </button>\n <button\n type=\"button\"\n tabIndex={-1}\n disabled={disabled}\n className={cx(styles.dropdownInputButtonIcon, dropDownIconClassName)}\n {...getToggleButtonProps()}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n getToggleButtonProps().onClick?.(e);\n onClick?.(e);\n }}\n >\n {!disabled && !readOnly && (\n <FontAwesomeIcon\n icon={dropdownIcon}\n className={cx(styles.dropdownInputButtonIconArrow, {\n [styles.dropdownInputButtonIconArrowOpen]: isOpen,\n })}\n />\n )}\n </button>\n {!disabled && !readOnly && isOpen ? (\n <BodyEnd>\n <div\n {...getMenuProps(\n {\n ref: (node: HTMLDivElement | null) => {\n anchorRef.current = node;\n },\n 'aria-label': label || placeholder || undefined,\n },\n { suppressRefError: true }\n )}\n className={cx(styles.dropdownInputListAnim, {\n [styles.dropdownInputListAnimWider]: isDropdownListWider,\n })}\n style={{ width: `${triggerWidth}px` }}\n >\n <InfiniteBlock\n onScroll={onScroll}\n className={styles.dropdownInputList}\n setHighlightedIndex={setHighlightedIndex}\n >\n {items.map((item: DropdownItem, index: number) => (\n <div\n key={item.key}\n {...getItemProps({ index, item, disabled: !!item.disabled })}\n className={cx(styles.dropdownInputListItem, dropDownClassName, {\n [styles.dropdownInputListItemActive]: highlightedIndex === index,\n [styles.dropdownInputListItemSelected]: selectedItem === item,\n [styles.dropdownInputListItemDisabled]: !!item.disabled,\n })}\n >\n {item.label}\n </div>\n ))}\n </InfiniteBlock>\n </div>\n </BodyEnd>\n ) : null}\n <fieldset\n className={cx(styles.dropdownFieldset, {\n [styles.dropdownBorderPlain]: plainStyle,\n [styles.dropdownBorderFocused]: showFocus,\n [styles.dropdownBorderInvalid]: hasErr,\n [styles.dropdownBorderError]: hasErr,\n })}\n >\n <legend\n className={cx(styles.dropdownFieldsetLegend, {\n [styles.dropdownFieldsetLegendActive]:\n useMatLabelStyle && (alwaysFloatLabel || showFocus || !isDisplayBlank),\n })}\n >\n <span>{editedLabel}</span>\n </legend>\n </fieldset>\n {useMatLabelStyle && label && (\n <div\n className={cx(styles.dropdownMatLabel, {\n [styles.dropdownMatLabelFloating]: alwaysFloatLabel || showFocus || !isDisplayBlank,\n })}\n >\n {label}\n {requiredMark}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.dropdownPlaceholder,\n showFocus && !dropdownLabel && styles.dropdownPlaceholderShown\n )}\n >\n {placeholder}\n </div>\n )}\n </div>\n </div>\n )}\n </Downshift>\n {label && !useMatLabelStyle && (\n <div className={cx(styles.dropdownLabelText, labelClassName)}>\n {label}\n {requiredMark}\n </div>\n )}\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() : (errorMessage || '')}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n\nexport default Dropdown;\n",".datePicker {\n position: relative;\n width: 100%;\n flex: 1;\n min-width: 105px;\n\n &-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin: 8px 0;\n\n &-monthAndYear {\n display: flex;\n\n &-container {\n display: flex;\n gap: 16px;\n position: relative;\n }\n }\n\n &-month {\n width: 120px;\n }\n\n &-year {\n width: 75px;\n }\n }\n\n &-month {\n min-width: 185px;\n }\n\n &-modalInput {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n color: var(--text-color);\n -webkit-text-fill-color: var(--text-color);\n }\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport Input from '../input';\nimport { useComponentDefaults } from '../configProvider';\nimport DatePickerMonth from './components/datePickerMonth';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\nimport { getLocale } from 'services/localization';\nimport ActionIcon from '../actionIcon';\nimport Modal from '../modal';\nimport FloatingMenu from '../floatingMenu';\nimport Dropdown from '../dropdown';\nimport { Align } from '../floatingMenu/floatingMenu.types';\nimport InputMask, { InputState, BeforeMaskedStateChangeStates } from '@mona-health/react-input-mask';\nimport { getDateFromDayMonthAndYear, getMonthName, getMonthNames, getDateString, correctDateMaskValue } from './dateFunctions';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport type { FormValidator } from 'services/formValidation';\n\nimport styles from './datePicker.module.pcss';\n\nexport interface DatePickerProps {\n className?: string;\n selected?: Date;\n onSelect?: (date: Date | null) => void;\n formValidator?: FormValidator | null;\n noInput?: boolean;\n noHeader?: boolean;\n isModal?: boolean;\n isInline?: boolean;\n onChange?: (date: Date | null) => void;\n minDate?: Date | null;\n maxDate?: Date | null;\n children?: React.ReactNode;\n showClearButton?: boolean;\n label?: string;\n isValid?: boolean;\n errorMessage?: string;\n isRequired?: boolean;\n startDate?: Date;\n endDate?: Date;\n}\n\nexport default function DatePicker(props: DatePickerProps) {\n const {\n className = '',\n selected,\n onSelect = () => null,\n formValidator = null,\n noInput = false,\n noHeader = false,\n isModal = false,\n isInline = false,\n onChange = () => null,\n minDate = null,\n maxDate = null,\n children = null,\n showClearButton = false,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n startDate,\n endDate,\n } = useComponentDefaults('DatePicker', props);\n const getCurrValue = (): Date | undefined =>\n formValidator ? (formValidator.value as Date) : selected;\n\n const initialDate = getCurrValue() ?? new Date();\n\n const [currentMonth, setCurrentMonth] = useState(initialDate.getMonth() + 1);\n const [currentYear, setCurrentYear] = useState(initialDate.getFullYear());\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [currentDateString, setCurrentDateString] = useState(() =>\n getCurrValue() ? getDateString(initialDate) : ''\n );\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const [prevSelected, setPrevSelected] = useState(selected);\n\n const fvRef = useRef(formValidator);\n\n // Sync navigation view when `selected` prop changes externally\n if (prevSelected !== selected) {\n setPrevSelected(selected);\n const d = selected ?? new Date();\n setCurrentMonth(d.getMonth() + 1);\n setCurrentYear(d.getFullYear());\n setCurrentDateString(selected ? getDateString(selected) : '');\n }\n\n // Subscribe to formValidator updates (external system → setState in callback)\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n const val = formValidator.value as Date | undefined;\n if (val) {\n setCurrentMonth(val.getMonth() + 1);\n setCurrentYear(val.getFullYear());\n setCurrentDateString(getDateString(val));\n } else {\n setCurrentDateString('');\n }\n forceUpdate((n: number) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean => {\n return formValidator\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n };\n\n const computedIsRequired = (): boolean => {\n return !!(isRequired || formValidator?.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n ));\n };\n\n const handleChange = (date: Date | null) => {\n setCurrentDateString(date ? getDateString(date) : '');\n if (formValidator) formValidator.set(date);\n onChange(date);\n };\n\n const handleSelect = (date: Date | null) => {\n handleChange(date);\n onSelect(date);\n setIsPickerOpen(false);\n };\n\n const changeMonth = (delta: number) => {\n setCurrentMonth((prev) => {\n let next = prev + delta;\n if (next < 1) { next = 12; setCurrentYear((y) => y - 1); }\n else if (next > 12) { next = 1; setCurrentYear((y) => y + 1); }\n return next;\n });\n };\n\n const tryParseDateString = (dateString: string): Date | null => {\n if (dateString.match(/\\d{2}\\.\\d{2}\\.\\d{4}/gi)) {\n const [day, month, year] = dateString.split('.');\n const parsedDate = getDateFromDayMonthAndYear(Number(day), Number(month), Number(year));\n if (parsedDate && parsedDate.toString() !== 'Invalid Date') {\n const isSmallerThanMaxDate = !maxDate || parsedDate <= maxDate;\n const isBiggerThanMinDate = !minDate || parsedDate >= minDate;\n if (isSmallerThanMaxDate && isBiggerThanMinDate) return parsedDate;\n }\n }\n return null;\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): InputState => {\n // previousState is only supplied on user-driven change events; on mount/focus/blur\n // there is nothing to auto-correct, so the next state passes through unchanged.\n if (!previousState || nextState.value === previousState.value) return nextState;\n\n const corrected = correctDateMaskValue(nextState.value, previousState.value, nextState.selection ?? null);\n\n const parsedDate = tryParseDateString(corrected.value);\n if (parsedDate) handleChange(parsedDate);\n\n return corrected;\n };\n\n const getYearDropdownOptions = () => {\n let length = 400;\n let zeroOffset = new Date().getFullYear() - 200;\n if (minDate) zeroOffset = minDate.getFullYear();\n if (maxDate) length = maxDate.getFullYear() - zeroOffset + 1;\n return Array.from(Array(length).keys()).map((i) => ({ key: i + zeroOffset, label: i + zeroOffset }));\n };\n\n const currValue = getCurrValue();\n const hasErr = hasError();\n\n const header = noHeader ? null : (\n <div className={styles.datePickerHeader}>\n <ActionIcon icon={faChevronLeft} onClick={() => changeMonth(-1)} />\n <div className={styles.datePickerHeaderMonthAndYearContainer}>\n <div className={styles.datePickerHeaderMonthAndYear}>\n <Dropdown\n plainStyle\n scrollToSelected\n onChange={(v) => setCurrentMonth(v as number)}\n className={styles.datePickerHeaderMonth}\n value={getMonthName(getLocale('-'), currentYear, currentMonth, 1)}\n items={getMonthNames().map((month, index) => ({ key: index + 1, label: month }))}\n />\n <Dropdown\n plainStyle\n scrollToSelected\n useMatLabelStyle={false}\n className={styles.datePickerHeaderYear}\n onChange={(v) => setCurrentYear(v as number)}\n value={currentYear}\n items={getYearDropdownOptions()}\n />\n </div>\n </div>\n <ActionIcon icon={faChevronRight} onClick={() => changeMonth(1)} />\n </div>\n );\n\n const pickerContent = (\n <>\n {header}\n <DatePickerMonth\n className={styles.datePickerMonth}\n month={currentMonth}\n year={currentYear}\n onSelect={handleSelect}\n selectionStart={startDate ?? currValue}\n selectionEnd={endDate ?? currValue}\n minDate={minDate}\n maxDate={maxDate}\n />\n {showClearButton && <Button onClick={() => handleSelect(null)}>Clear</Button>}\n {children}\n </>\n );\n\n const input = noInput ? null : (\n <Input\n readOnly={isModal}\n classNames={isModal ? { input: styles.datePickerModalInput } : undefined}\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentDateString}\n onChange={(v) => setCurrentDateString(v as string)}\n onClick={() => setIsPickerOpen(true)}\n customInput={\n <InputMask mask=\"99.99.9999\" maskPlaceholder=\"_\" beforeMaskedStateChange={beforeMaskedStateChange} />\n }\n onBlur={() => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n handleChange(tryParseDateString(currentDateString));\n }}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n isValid={!hasErr}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <FloatingMenu\n isOpen={isPickerOpen}\n onOpenChange={(open: boolean) => setIsPickerOpen(open)}\n content={pickerContent}\n align={Align.Left}\n dontCloseOnChildClick\n >\n {input}\n </FloatingMenu>\n );\n })();\n\n return (\n <div className={cx(styles.datePicker, className)}>\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() : (errorMessage || '')}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum DividerTextPosition {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\nexport type DividerSlots = 'root' | 'line' | 'content';\n\nexport interface DividerProps extends HtmlProps {\n text?: ReactNode;\n textPosition?: DividerTextPosition;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<DividerSlots>;\n styles?: SlotStyles<DividerSlots>;\n}\n",".divider {\n display: flex;\n align-items: center;\n width: 100%;\n\n &-line {\n flex: 1 1 auto;\n height: 1px;\n background-color: var(--border-color);\n }\n\n &-content {\n flex: 0 0 auto;\n padding: 0 0.75em;\n color: var(--text-dark);\n font-size: 0.875em;\n white-space: nowrap;\n }\n\n &-text-left &-line:first-child {\n flex-grow: 0;\n flex-basis: 1.5em;\n }\n\n &-text-right &-line:last-child {\n flex-grow: 0;\n flex-basis: 1.5em;\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { DividerTextPosition } from './divider.types';\nimport type { DividerProps } from './divider.types';\nimport styles from './divider.module.pcss';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_TEXT_POSITION: Record<DividerTextPosition, string> = {\n [DividerTextPosition.Left]: styles.dividerTextLeft,\n [DividerTextPosition.Center]: styles.dividerTextCenter,\n [DividerTextPosition.Right]: styles.dividerTextRight,\n};\n\nfunction Divider(props: DividerProps): ReactElement {\n const {\n text,\n textPosition = DividerTextPosition.Center,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Divider', props);\n\n const hasText = text != null && text !== '';\n\n return (\n <div\n {...rest}\n role=\"separator\"\n className={cx(\n styles.divider,\n hasText && CLASS_BY_TEXT_POSITION[textPosition],\n className,\n classNames?.root,\n )}\n style={{ ...style, ...slotStyles?.root }}\n >\n <span className={cx(styles.dividerLine, classNames?.line)} style={slotStyles?.line} />\n {hasText && (\n <span className={cx(styles.dividerContent, classNames?.content)} style={slotStyles?.content}>\n {text}\n </span>\n )}\n {hasText && (\n <span className={cx(styles.dividerLine, classNames?.line)} style={slotStyles?.line} />\n )}\n </div>\n );\n}\n\nexport default Divider;\n",".drawer {\n height: 100%;\n overflow-x: hidden;\n width: var(--drawer-closed-width, 0px);\n transition: width 0.3s ease;\n background: var(--background-accent);\n\n &-open {\n width: var(--drawer-opened-width, var(--drawer-content-width, max-content));\n }\n\n &-content {\n width: max-content;\n height: 100%;\n pointer-events: all;\n\n &-inner {\n height: 100%;\n }\n }\n}\n","import type { ReactElement, CSSProperties } from 'react';\nimport { useRef, useEffect } from 'react';\nimport { DrawerProps } from './drawer.types';\nimport cx from 'classnames';\n\nimport styles from './drawer.module.pcss';\n\n\nfunction Drawer({\n className,\n isOpen = false,\n closedWidth,\n openedWidth,\n children,\n}: DrawerProps): ReactElement {\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const observer = new ResizeObserver(() => {\n if (containerRef.current && contentRef.current) {\n containerRef.current.style.setProperty(\n '--drawer-content-width',\n `${contentRef.current.scrollWidth}px`\n );\n }\n });\n if (contentRef.current) observer.observe(contentRef.current);\n return () => observer.disconnect();\n }, []);\n\n return (\n <div\n ref={containerRef}\n className={cx(styles.drawer, isOpen && styles.drawerOpen, className)}\n style={{\n ...(closedWidth !== undefined && { '--drawer-closed-width': closedWidth }),\n ...(openedWidth !== undefined && { '--drawer-opened-width': openedWidth }),\n } as CSSProperties}\n >\n <div ref={contentRef} className={styles.drawerContent}>\n <div className={styles.drawerContentInner}>\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nexport default Drawer;\n","import type React from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum DropZoneStatus {\n /** Nothing is happening. */\n Idle = 'idle',\n /** A file drag is somewhere in the window — the zone is \"armed\". */\n Dragging = 'dragging',\n /** A file drag is hovering directly over this zone. */\n Active = 'active',\n /** The last drop / selection was rejected. */\n Error = 'error',\n}\n\nexport enum DropZoneReturnType {\n /** Emit the raw `File` objects (default). */\n File = 'file',\n /** Read each file as a base64 data URL and emit `LoadedFile`. */\n Base64 = 'base64',\n /** Read each file as UTF-8 text and emit `LoadedFile`. */\n Text = 'text',\n}\n\nexport interface LoadedFile {\n name: string;\n size: number;\n type: string;\n lastModified: number;\n /** The FileReader result — a base64 data URL or text, depending on `returnType`. */\n data: string;\n}\n\nexport type DropZoneRejectionReason =\n /** File extension / mime type not in `acceptedTypes`. */\n | 'unacceptedType'\n /** File exceeds `maxSize`. */\n | 'tooLarge'\n /** More files than `maxFiles` were provided. */\n | 'tooMany'\n /** Reading the file (base64 / text) failed. */\n | 'readError';\n\nexport interface DropZoneRejection {\n file: File;\n reason: DropZoneRejectionReason;\n}\n\nexport interface DropZoneRenderState {\n status: DropZoneStatus;\n /** A drag is anywhere in the window (zone armed) or directly over it. */\n isDragging: boolean;\n /** A drag is directly over this zone. */\n isActive: boolean;\n disabled: boolean;\n}\n\nexport type DropZoneSlots = 'root' | 'content' | 'fileList' | 'fileItem' | 'input';\n\nexport interface DropZoneProps extends HtmlProps {\n /** Static content, or a render function that receives the live drop state. */\n children?: React.ReactNode | ((state: DropZoneRenderState) => React.ReactNode);\n\n /**\n * Accepted file types: extensions (`'.png'`), mime types (`'image/png'`),\n * or wildcards (`'image/*'`). Empty / omitted means accept everything.\n * Also drives the native picker's `accept` attribute.\n */\n acceptedTypes?: string[];\n /** Output shape for each accepted file. Default: `File`. */\n returnType?: DropZoneReturnType;\n\n /** Open the native file picker when the zone is clicked. */\n openPickerOnClick?: boolean;\n /** Allow more than one file. Default: `true`. */\n multiple?: boolean;\n /** Reject files beyond this count (extras reported via `onReject`). */\n maxFiles?: number;\n /** Reject files larger than this many bytes. */\n maxSize?: number;\n /** Accept files pasted from the clipboard while the zone is focused. */\n enablePaste?: boolean;\n /** Recurse into dropped directories. Default: `true`. */\n allowDirectories?: boolean;\n\n /** Native `capture` attribute (mobile camera / mic). */\n capture?: boolean | 'user' | 'environment';\n disabled?: boolean;\n\n /** Drop the built-in border / background styling; keep only base layout. */\n unstyled?: boolean;\n /** Render the names of `files` beneath the content. */\n showFileNames?: boolean;\n /** Files whose names are listed when `showFileNames` is set. */\n files?: (File | LoadedFile)[];\n\n onFilesChanged?: (files: (File | LoadedFile)[]) => void;\n onReject?: (rejections: DropZoneRejection[]) => void;\n onStatusChanged?: (status: DropZoneStatus) => void;\n\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<DropZoneSlots>;\n styles?: SlotStyles<DropZoneSlots>;\n}\n",".dropZone {\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n outline: none;\n\n &-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n &-default {\n padding: var(--spacing-l, 24px);\n border: 1px dashed var(--border-color);\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n transition: border-color 0.2s, background 0.2s, color 0.2s;\n }\n\n &-default&-clickable:hover {\n border-color: var(--primary-color);\n background: var(--background-accent-light);\n }\n\n /* A drag is somewhere in the window — the zone is armed. */\n &-dragging {\n border-color: var(--primary-color);\n }\n\n /* A drag is hovering directly over this zone. */\n &-active {\n border-width: 2px;\n border-color: var(--primary-color);\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n\n &-error {\n border-color: var(--error-color);\n color: var(--error-color);\n }\n\n &-error&-clickable:hover {\n border-color: var(--error-color);\n background: var(--error-lighter);\n }\n\n &-content {\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n\n /* While dragging, let drop events fall through to the root instead of child elements. */\n &-dragging {\n pointer-events: none;\n }\n }\n\n &-fileList {\n width: 100%;\n margin-top: var(--spacing-s, 8px);\n pointer-events: none;\n }\n\n &-fileItem {\n font-size: var(--text-small-font-size);\n color: var(--text-dark);\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n }\n\n &-input {\n display: none;\n }\n}\n","import React, { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport cx from 'classnames';\n\nimport {\n DropZoneProps,\n DropZoneReturnType,\n DropZoneStatus,\n DropZoneRejection,\n DropZoneRenderState,\n LoadedFile,\n} from './dropZone.types';\n\nimport styles from './dropZone.module.pcss';\n\n// ── Pure helpers ──────────────────────────────────────────────────────────────\n\n/** True when a file matches one of the accepted tokens (extension, mime, or wildcard). */\nfunction matchesAccepted(file: File, acceptedTypes: string[]): boolean {\n if (!acceptedTypes.length) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return acceptedTypes.some((raw) => {\n const accept = raw.trim().toLowerCase();\n if (!accept) return false;\n if (accept.startsWith('.')) return name.endsWith(accept); // extension\n if (accept.endsWith('/*')) return type.startsWith(accept.slice(0, -1)); // wildcard e.g. image/\n return type === accept; // exact mime type\n });\n}\n\ntype ReadResult = { ok: true; value: File | LoadedFile } | { ok: false };\n\n/** Read a single file into the requested return shape. Never rejects — failures resolve to `{ ok: false }`. */\nfunction readFile(file: File, returnType: DropZoneReturnType): Promise<ReadResult> {\n if (returnType === DropZoneReturnType.File) {\n return Promise.resolve({ ok: true, value: file });\n }\n return new Promise<ReadResult>((resolve) => {\n const reader = new FileReader();\n reader.onload = (event) => {\n const data = event.target?.result;\n if (typeof data !== 'string') {\n resolve({ ok: false });\n return;\n }\n resolve({\n ok: true,\n value: { name: file.name, size: file.size, type: file.type, lastModified: file.lastModified, data },\n });\n };\n reader.onerror = () => resolve({ ok: false });\n if (returnType === DropZoneReturnType.Base64) reader.readAsDataURL(file);\n else reader.readAsText(file);\n });\n}\n\n/** Recursively flatten a dropped file-system entry into a list of Files. */\nfunction readEntry(entry: FileSystemEntry): Promise<File[]> {\n return new Promise((resolve) => {\n if (entry.isFile) {\n (entry as FileSystemFileEntry).file(\n (file) => resolve([file]),\n () => resolve([])\n );\n } else if (entry.isDirectory) {\n const reader = (entry as FileSystemDirectoryEntry).createReader();\n const collected: FileSystemEntry[] = [];\n const readBatch = () => {\n // readEntries yields entries in chunks — keep calling until it returns empty.\n reader.readEntries((batch) => {\n if (!batch.length) {\n Promise.all(collected.map(readEntry)).then((nested) => resolve(nested.flat()));\n } else {\n collected.push(...batch);\n readBatch();\n }\n }, () => resolve([]));\n };\n readBatch();\n } else {\n resolve([]);\n }\n });\n}\n\n/**\n * Extract Files from a drop's DataTransfer. `webkitGetAsEntry()` must be called\n * synchronously within the drop handler, so all entries are captured before any await.\n */\nfunction gatherFiles(dataTransfer: DataTransfer, allowDirectories: boolean): Promise<File[]> {\n const items = dataTransfer.items;\n if (items && items.length) {\n if (allowDirectories && typeof items[0].webkitGetAsEntry === 'function') {\n const entries: FileSystemEntry[] = [];\n for (let i = 0; i < items.length; i += 1) {\n if (items[i].kind === 'file') {\n const entry = items[i].webkitGetAsEntry();\n if (entry) entries.push(entry);\n }\n }\n if (entries.length) {\n return Promise.all(entries.map(readEntry)).then((nested) => nested.flat());\n }\n }\n const files: File[] = [];\n for (let i = 0; i < items.length; i += 1) {\n if (items[i].kind === 'file') {\n const file = items[i].getAsFile();\n if (file) files.push(file);\n }\n }\n return Promise.resolve(files);\n }\n return Promise.resolve(Array.from(dataTransfer.files || []));\n}\n\n// ── Component ───────────────────────────────────────────────────────────────\n\nfunction DropZone({\n children,\n acceptedTypes = [],\n returnType = DropZoneReturnType.File,\n openPickerOnClick = false,\n multiple = true,\n maxFiles,\n maxSize,\n enablePaste = false,\n allowDirectories = true,\n capture,\n disabled = false,\n unstyled = false,\n showFileNames = false,\n files,\n onFilesChanged,\n onReject,\n onStatusChanged,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: DropZoneProps) {\n const [status, setStatus] = useState<DropZoneStatus>(DropZoneStatus.Idle);\n\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = useId();\n const statusRef = useRef(status);\n const windowDragDepth = useRef(0);\n const zoneDragDepth = useRef(0);\n\n // Latest props/callbacks, so the once-mounted window listeners never read stale values.\n const cfg = useRef({\n acceptedTypes, returnType, multiple, maxFiles, maxSize, allowDirectories,\n disabled, onFilesChanged, onReject, onStatusChanged,\n });\n cfg.current = {\n acceptedTypes, returnType, multiple, maxFiles, maxSize, allowDirectories,\n disabled, onFilesChanged, onReject, onStatusChanged,\n };\n\n const changeStatus = useCallback((next: DropZoneStatus) => {\n if (statusRef.current === next) return;\n statusRef.current = next;\n setStatus(next);\n cfg.current.onStatusChanged?.(next);\n }, []);\n\n const processFiles = useCallback(async (incoming: File[]) => {\n const c = cfg.current;\n const rejections: DropZoneRejection[] = [];\n let accepted: File[] = [];\n\n for (const file of incoming) {\n if (!matchesAccepted(file, c.acceptedTypes)) {\n rejections.push({ file, reason: 'unacceptedType' });\n } else if (c.maxSize != null && file.size > c.maxSize) {\n rejections.push({ file, reason: 'tooLarge' });\n } else {\n accepted.push(file);\n }\n }\n\n if (!c.multiple) accepted = accepted.slice(0, 1);\n if (c.maxFiles != null && accepted.length > c.maxFiles) {\n accepted.slice(c.maxFiles).forEach((file) => rejections.push({ file, reason: 'tooMany' }));\n accepted = accepted.slice(0, c.maxFiles);\n }\n\n // Read in input order — Promise.all preserves index regardless of completion order.\n const results = await Promise.all(accepted.map((file) => readFile(file, c.returnType)));\n const loaded: (File | LoadedFile)[] = [];\n results.forEach((result, index) => {\n if (result.ok) loaded.push(result.value);\n else rejections.push({ file: accepted[index], reason: 'readError' });\n });\n\n if (rejections.length) c.onReject?.(rejections);\n changeStatus(rejections.length && !loaded.length ? DropZoneStatus.Error : DropZoneStatus.Idle);\n if (loaded.length) c.onFilesChanged?.(loaded);\n }, [changeStatus]);\n\n // Window-level drag tracking via an enter/leave depth counter (robust against bubbling).\n useEffect(() => {\n const hasFiles = (dt: DataTransfer | null) =>\n !dt || Array.from(dt.types || []).includes('Files');\n\n const onWindowDragEnter = (e: DragEvent) => {\n if (cfg.current.disabled || !hasFiles(e.dataTransfer)) return;\n windowDragDepth.current += 1;\n if (statusRef.current === DropZoneStatus.Idle || statusRef.current === DropZoneStatus.Error) {\n changeStatus(DropZoneStatus.Dragging);\n }\n };\n const onWindowDragLeave = () => {\n windowDragDepth.current = Math.max(0, windowDragDepth.current - 1);\n if (windowDragDepth.current === 0 && statusRef.current === DropZoneStatus.Dragging) {\n changeStatus(DropZoneStatus.Idle);\n }\n };\n const onWindowDrop = () => {\n windowDragDepth.current = 0;\n zoneDragDepth.current = 0;\n if (statusRef.current === DropZoneStatus.Dragging) changeStatus(DropZoneStatus.Idle);\n };\n\n window.addEventListener('dragenter', onWindowDragEnter);\n window.addEventListener('dragleave', onWindowDragLeave);\n window.addEventListener('drop', onWindowDrop);\n return () => {\n window.removeEventListener('dragenter', onWindowDragEnter);\n window.removeEventListener('dragleave', onWindowDragLeave);\n window.removeEventListener('drop', onWindowDrop);\n };\n }, [changeStatus]);\n\n const onDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer) e.dataTransfer.dropEffect = disabled ? 'none' : 'copy';\n }, [disabled]);\n\n const onDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n if (disabled) return;\n zoneDragDepth.current += 1;\n changeStatus(DropZoneStatus.Active);\n }, [disabled, changeStatus]);\n\n const onDragLeave = useCallback((e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n zoneDragDepth.current = Math.max(0, zoneDragDepth.current - 1);\n if (zoneDragDepth.current === 0) {\n // Left the zone, but a drag may still be active elsewhere in the window.\n changeStatus(windowDragDepth.current > 0 ? DropZoneStatus.Dragging : DropZoneStatus.Idle);\n }\n }, [changeStatus]);\n\n const onDrop = useCallback((e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n zoneDragDepth.current = 0;\n windowDragDepth.current = 0;\n if (disabled || !e.dataTransfer) {\n changeStatus(DropZoneStatus.Idle);\n return;\n }\n changeStatus(DropZoneStatus.Idle);\n // gatherFiles captures any directory entries synchronously before awaiting.\n gatherFiles(e.dataTransfer, cfg.current.allowDirectories).then((collected) => {\n if (collected.length) processFiles(collected);\n });\n }, [disabled, changeStatus, processFiles]);\n\n const openPicker = useCallback(() => {\n if (disabled || !openPickerOnClick) return;\n inputRef.current?.click();\n }, [disabled, openPickerOnClick]);\n\n const onInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const selected = Array.from(e.target.files || []);\n // Reset so picking the same file again still fires onChange.\n e.target.value = '';\n if (selected.length) processFiles(selected);\n }, [processFiles]);\n\n const onPaste = useCallback((e: React.ClipboardEvent<HTMLDivElement>) => {\n if (!enablePaste || disabled) return;\n const pasted = Array.from(e.clipboardData?.files || []);\n if (pasted.length) {\n e.preventDefault();\n processFiles(pasted);\n }\n }, [enablePaste, disabled, processFiles]);\n\n const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (!openPickerOnClick || disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n openPicker();\n }\n }, [openPickerOnClick, disabled, openPicker]);\n\n const isDragging = status === DropZoneStatus.Dragging || status === DropZoneStatus.Active;\n const renderState: DropZoneRenderState = {\n status,\n isDragging,\n isActive: status === DropZoneStatus.Active,\n disabled,\n };\n\n const acceptAttr = acceptedTypes.length ? acceptedTypes.join(',') : undefined;\n\n return (\n <div\n {...rest}\n className={cx(\n styles.dropZone,\n openPickerOnClick && styles.dropZoneClickable,\n disabled && styles.dropZoneDisabled,\n !unstyled && styles.dropZoneDefault,\n !unstyled && status === DropZoneStatus.Dragging && styles.dropZoneDragging,\n !unstyled && status === DropZoneStatus.Active && styles.dropZoneActive,\n !unstyled && status === DropZoneStatus.Error && styles.dropZoneError,\n classNames?.root,\n className\n )}\n style={{ ...slotStyles?.root, ...style }}\n onDragEnter={onDragEnter}\n onDragLeave={onDragLeave}\n onDragOver={onDragOver}\n onDrop={onDrop}\n onClick={openPicker}\n onKeyDown={onKeyDown}\n onPaste={enablePaste ? onPaste : undefined}\n role={openPickerOnClick ? 'button' : undefined}\n tabIndex={openPickerOnClick && !disabled ? 0 : undefined}\n aria-disabled={disabled || undefined}\n >\n <div\n className={cx(styles.dropZoneContent, isDragging && styles.dropZoneContentDragging, classNames?.content)}\n style={slotStyles?.content}\n >\n {typeof children === 'function' ? children(renderState) : children}\n </div>\n\n {showFileNames && files && files.length > 0 && (\n <div className={cx(styles.dropZoneFileList, classNames?.fileList)} style={slotStyles?.fileList}>\n {files.map((file, index) => (\n <div\n key={`${file.name}-${index}`}\n className={cx(styles.dropZoneFileItem, classNames?.fileItem)}\n style={slotStyles?.fileItem}\n >\n {file.name}\n </div>\n ))}\n </div>\n )}\n\n <input\n ref={inputRef}\n id={inputId}\n type=\"file\"\n className={cx(styles.dropZoneInput, classNames?.input)}\n style={slotStyles?.input}\n accept={acceptAttr}\n multiple={multiple}\n capture={capture}\n disabled={disabled}\n onChange={onInputChange}\n tabIndex={-1}\n aria-hidden=\"true\"\n />\n </div>\n );\n}\n\nexport default DropZone;\n",".emptyState {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-flow: column;\n gap: var(--spacing-m);\n}\n","import cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport type { ReactElement } from 'react';\nimport type { EmptyStateProps } from './emptyState.types';\nimport styles from './emptyState.module.pcss';\n\nexport default function EmptyState({ className, icon, children, ...rest }: EmptyStateProps): ReactElement {\n return (\n <div {...rest} className={cx(styles.emptyState, className)}>\n {icon && <FontAwesomeIcon icon={icon} />}\n <div>{children ?? 'No entries available'}</div>\n </div>\n );\n}\n",".fab {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n display: flex;\n align-items: stretch;\n padding: 0;\n\n --icon-size: 18px;\n\n /* Make the Ripple wrapper fill the full circular button */\n & > div {\n width: 100%;\n border-radius: 50%;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n &-content {\n font-size: var(--icon-size);\n width: var(--icon-size);\n height: var(--icon-size);\n\n svg {\n width: var(--icon-size);\n height: var(--icon-size);\n }\n\n &-container {\n display: flex;\n justify-content: center;\n align-items: center;\n }\n }\n\n &-size {\n &-mini {\n width: 40px;\n height: 40px;\n background: var(--background-accent-light);\n }\n }\n}\n","import cx from 'classnames';\n\nimport Button from 'components/common/button';\nimport { ButtonStyleType } from 'components/common/button/button.types';\nimport type { FabBaseProps, FabBaseSize } from './fabBase.types';\n\nimport styles from './fabBase.module.pcss';\n\nconst sizeClass: Record<FabBaseSize, string | null> = {\n default: null,\n mini: styles.fabSizeMini,\n};\n\nfunction FabBase({\n children = null,\n size = 'default',\n className = '',\n styleType = ButtonStyleType.Primary,\n onClick = () => {},\n}: FabBaseProps) {\n return (\n <Button\n styleType={styleType}\n className={cx(styles.fab, sizeClass[size], className)}\n onClick={onClick}\n >\n <div className={styles.fabContentContainer}>\n <div className={styles.fabContent}>{children}</div>\n </div>\n </Button>\n );\n}\n\nexport default FabBase;\n","\n.fab {\n animation: appear 0.3s forwards;\n opacity: 0;\n transform: scale(0);\n box-shadow:\n 0px 3px 5px -1px rgb(0 0 0 / 20%),\n 0px 6px 10px 0px rgb(0 0 0 / 14%),\n 0px 1px 18px 0px rgb(0 0 0 / 12%);\n border-radius: 50%;\n\n &-container {\n position: fixed;\n bottom: 16px;\n right: 16px;\n\n @media (--breakpoint-tablet) {\n z-index: 2;\n }\n }\n\n &-menu {\n position: absolute;\n top: 0;\n transform: translateY(calc(-100% - 16px));\n width: 100%;\n display: flex;\n flex-flow: column-reverse;\n gap: 16px;\n align-items: center;\n pointer-events: none;\n user-select: none;\n\n &-backdrop {\n width: 0%;\n height: 0%;\n position: fixed;\n top: 0;\n left: 0;\n background: black;\n opacity: 0;\n transition: opacity 0.4s;\n\n &-open {\n width: 100%;\n height: 100%;\n opacity: 0.5;\n }\n }\n\n &-entry {\n position: relative;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n opacity: 0;\n transform: scale(0);\n transition: all 0.2s;\n pointer-events: all;\n\n &:nth-child(2) {\n transition-delay: 0.05s;\n }\n\n &:nth-child(3) {\n transition-delay: 0.1s;\n }\n\n &:nth-child(4) {\n transition-delay: 0.15s;\n }\n\n &:nth-child(5) {\n transition-delay: 0.2s;\n }\n\n &:nth-child(6) {\n transition-delay: 0.25s;\n }\n\n &:nth-child(7) {\n transition-delay: 0.3s;\n }\n\n &-shown {\n opacity: 1;\n transform: scale(1);\n }\n\n &-label {\n background: var(--background-accent-light);\n border-radius: var(--default-border-radius);\n padding: 4px 8px;\n\n &-container {\n position: absolute;\n width: max-content;\n transform: translateX(-100%);\n height: 100%;\n margin-left: -8px;\n align-items: center;\n display: flex;\n }\n }\n }\n }\n\n &-icon {\n transition: all 0.4s;\n display: flex;\n justify-content: center;\n align-items: center;\n position: relative;\n width: 100%;\n height: 100%;\n\n &-menuOpen {\n transform: rotate(225deg);\n }\n\n &-content {\n position: absolute;\n width: 18px;\n height: 18px;\n opacity: 0;\n transition: opacity 0.3s;\n\n &-shown {\n opacity: 1;\n }\n }\n }\n\n @keyframes appear {\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n}\n","import { useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faPlus as addIcon } from '@fortawesome/free-solid-svg-icons';\n\nimport FabBase from './components/fabBase';\nimport type { FabProps } from './fab.types';\n\nimport styles from './fab.module.pcss';\n\nfunction Fab({\n children = null,\n size = 'default',\n menuEntries = [],\n onMenuEntryClicked = () => {},\n onClick = () => {},\n closeMenuOnEntryClicked = true,\n ...rest\n}: FabProps) {\n const [menuOpen, setMenuOpen] = useState(false);\n\n function handleFabClick() {\n if (menuEntries.length > 0) setMenuOpen((prev) => !prev);\n onClick();\n }\n\n function handleEntryClick(e: React.MouseEvent, id: string) {\n e.stopPropagation();\n if (closeMenuOnEntryClicked) setMenuOpen(false);\n onMenuEntryClicked(id);\n }\n\n return (\n <div {...rest} className={styles.fabContainer}>\n <div\n className={cx(styles.fabMenuBackdrop, menuOpen && styles.fabMenuBackdropOpen)}\n onClick={(e) => { e.stopPropagation(); setMenuOpen(false); }}\n />\n <div onClick={(e) => e.stopPropagation()}>\n <FabBase className={styles.fab} size={size} onClick={handleFabClick}>\n <div className={cx(styles.fabIcon, menuOpen && styles.fabIconMenuOpen)}>\n <div className={cx(styles.fabIconContent, !menuOpen && styles.fabIconContentShown)}>\n {children}\n </div>\n <div className={cx(styles.fabIconContent, menuOpen && styles.fabIconContentShown)}>\n <FontAwesomeIcon icon={addIcon} />\n </div>\n </div>\n </FabBase>\n </div>\n <div className={styles.fabMenu}>\n {menuEntries.map(({ id, label, icon }) => (\n <div\n key={id}\n className={cx(styles.fabMenuEntry, menuOpen && styles.fabMenuEntryShown)}\n onClick={(e) => handleEntryClick(e, id)}\n >\n {label && (\n <div className={styles.fabMenuEntryLabelContainer}>\n <div className={styles.fabMenuEntryLabel}>{label}</div>\n </div>\n )}\n <FabBase size=\"mini\">\n <FontAwesomeIcon icon={icon} />\n </FabBase>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport default Fab;\n",".iconPicker {\n border-width: 1px;\n border-radius: var(--default-border-radius);\n border-color: transparent;\n border-style: solid;\n\n &-label {\n font-size: var(--text-small-font-size);\n margin-bottom: 8px;\n }\n\n &-item {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 8px;\n width: 24px;\n height: 24px;\n background: var(--background-accent);\n border-radius: 200px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n stroke: var(--text-color);\n position: relative;\n\n &:focus-visible {\n outline: 1px solid var(--primary-color);\n }\n\n &-container {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-around;\n gap: 8px 14px;\n }\n\n &-selected {\n background: var(--primary-color);\n }\n }\n\n &-error {\n border-color: red;\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport styles from './iconPicker.module.pcss';\nimport Ripple from '../ripple';\nimport type { IconPickerItem, IconPickerProps } from './iconPicker.types';\n\nfunction hasError(props: IconPickerProps): boolean {\n const { formValidator } = props;\n return formValidator ? (formValidator.touched && formValidator.hasError()) : false;\n}\n\nfunction isRequired(props: IconPickerProps): boolean {\n const { isRequired: reqProp, formValidator } = props;\n return !!(reqProp || formValidator?.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n ));\n}\n\nexport default function IconPicker({\n data = [],\n selectedId = null,\n label = '',\n onChange,\n formValidator = null,\n isRequired: _isRequired,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: IconPickerProps) {\n const currentValue = formValidator ? (formValidator.value as string) ?? null : selectedId;\n const showError = hasError({ formValidator, isRequired: _isRequired });\n const required = isRequired({ formValidator, isRequired: _isRequired });\n\n function handleSelect(id: string) {\n if (formValidator) formValidator.set(id);\n onChange?.(id);\n }\n\n return (\n <div\n {...rest}\n className={cx(styles.iconPicker, { [styles.iconPickerError]: showError }, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n >\n {label && (\n <div className={cx(styles.iconPickerLabel, classNames?.label)} style={slotStyles?.label}>\n {label}\n {required && ' *'}\n </div>\n )}\n <div\n className={cx(styles.iconPickerItemContainer, classNames?.itemContainer)}\n style={slotStyles?.itemContainer}\n >\n {data.map(({ id, label: itemLabel, icon, customIcon }: IconPickerItem) => (\n <div\n key={id}\n className={cx(\n styles.iconPickerItem,\n { [styles.iconPickerItemSelected]: currentValue === id },\n classNames?.item\n )}\n style={slotStyles?.item}\n title={itemLabel}\n tabIndex={0}\n role=\"button\"\n onClick={() => handleSelect(id)}\n onKeyDown={({ key }) => { if (key === 'Enter') handleSelect(id); }}\n >\n {icon && <FontAwesomeIcon icon={icon} />}\n {customIcon ?? null}\n <Ripple />\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport type { IdleManagerProps } from './idleManager.types';\n\nconst ACTIVITY_EVENTS = ['click', 'mousemove', 'keydown', 'scroll', 'touchstart'] as const;\n\nfunction IdleManager({\n children = null,\n idleAfterSeconds = 600,\n renderCondition = true,\n}: IdleManagerProps) {\n const [isIdleContentShown, setIsIdleContentShown] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const resetIdleTimeout = useCallback(() => {\n if (timeoutRef.current !== null) clearTimeout(timeoutRef.current);\n setIsIdleContentShown(false);\n timeoutRef.current = setTimeout(() => {\n setIsIdleContentShown(true);\n }, idleAfterSeconds * 1000);\n }, [idleAfterSeconds]);\n\n // Re-run whenever idleAfterSeconds changes (or on first mount)\n useEffect(() => {\n resetIdleTimeout();\n }, [resetIdleTimeout]);\n\n // Register / unregister activity listeners\n useEffect(() => {\n for (const event of ACTIVITY_EVENTS) {\n document.addEventListener(event, resetIdleTimeout);\n }\n return () => {\n for (const event of ACTIVITY_EVENTS) {\n document.removeEventListener(event, resetIdleTimeout);\n }\n // Clear any pending timeout on unmount so it never fires after we're gone\n if (timeoutRef.current !== null) clearTimeout(timeoutRef.current);\n };\n }, [resetIdleTimeout]);\n\n return <>{renderCondition && isIdleContentShown && children}</>;\n}\n\nexport default IdleManager;\n",".inputDropdown {\n position: relative;\n}\n\n.dropdown {\n position: fixed;\n width: fit-content;\n max-width: 240px;\n color: var(--text-color);\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n box-sizing: border-box;\n overflow: hidden;\n transition: all 0.1s;\n transform-origin: top left;\n opacity: 0;\n transform: scale(0.95);\n z-index: 1;\n\n &-scroll {\n overflow: auto;\n max-height: 200px;\n }\n\n &-shown {\n transform: scale(1);\n opacity: 1;\n }\n\n &-flip {\n transform-origin: bottom left;\n }\n\n &-item {\n padding: 8px;\n z-index: 0;\n outline: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover,\n &:focus {\n background: var(--background-accent);\n }\n\n &-highlighted {\n background: var(--background-accent);\n }\n }\n\n &-category {\n padding: 16px 8px 4px 8px;\n }\n}\n","import React, { useCallback, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\nimport styles from './inputDropdown.module.pcss';\nimport Input from '../input';\nimport { useFloatingPosition } from '../floatingMenu/useFloatingPosition';\nimport { useComponentDefaults } from '../configProvider';\nimport type { InputDropdownItem, InputDropdownProps } from './inputDropdown.types';\n\nfunction getKeyFromProps(value: string | undefined, formValidator: InputDropdownProps['formValidator']): string {\n return formValidator ? (formValidator.value as string) ?? '' : (value ?? '');\n}\n\nfunction labelForKey(key: string, items: InputDropdownItem[]): string {\n const match = items.find((item) => item.value === key);\n return match ? (match.label ?? match.value) : key;\n}\n\nexport default function InputDropdown(props: InputDropdownProps) {\n const {\n label = '',\n value = '',\n formValidator = null,\n items = [],\n allowCustomValue = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n onSelect = () => null,\n onChange,\n placeholder = '',\n readOnly = false,\n ...rest\n } = useComponentDefaults('InputDropdown', props);\n const currentKey = getKeyFromProps(value, formValidator);\n\n const [inputText, setInputText] = useState(() => labelForKey(currentKey, items));\n const [prevKey, setPrevKey] = useState(currentKey);\n const [isMenuShown, setIsMenuShown] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState<number | null>(null);\n const hideTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n\n useFloatingPosition({\n isOpen: isMenuShown,\n triggerRef,\n anchorRef,\n panelRef: anchorRef,\n flipClassName: styles.dropdownFlip,\n });\n\n // Sync display text when the controlled key changes externally (e.g. parent reset).\n if (currentKey !== prevKey) {\n setPrevKey(currentKey);\n const match = items.find((item) => item.value === currentKey);\n if (match) setInputText(match.label ?? match.value);\n else if (allowCustomValue) setInputText(currentKey);\n }\n\n const currItems = items.filter((item) =>\n (item.label ?? item.value).toLowerCase().includes(inputText.toLowerCase())\n );\n\n const handleFocus = () => {\n if (readOnly) return;\n if (hideTimeoutRef.current) {\n clearTimeout(hideTimeoutRef.current);\n hideTimeoutRef.current = null;\n }\n setIsMenuShown(true);\n };\n\n const handleBlur = () => {\n hideTimeoutRef.current = setTimeout(() => {\n setIsMenuShown(false);\n hideTimeoutRef.current = null;\n // Without custom values, uncommitted typed text is invalid — snap the\n // display back to the currently selected item's label.\n if (!allowCustomValue) setInputText(labelForKey(currentKey, items));\n }, 100);\n };\n\n const handleSelect = useCallback((item: InputDropdownItem) => {\n setInputText(item.label ?? item.value);\n setIsMenuShown(false);\n setHighlightedIndex(null);\n if (formValidator) formValidator.set(item.value);\n if (onChange) onChange(item.value);\n onSelect(item.value);\n }, [formValidator, onChange, onSelect]);\n\n const onKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (readOnly) return;\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n setHighlightedIndex((idx) => (!idx ? null : idx - 1));\n } else if (event.key === 'ArrowDown') {\n event.preventDefault();\n setHighlightedIndex((idx) =>\n idx === null ? 0 : Math.min(idx + 1, currItems.length - 1)\n );\n } else if (event.key === 'Enter') {\n if (highlightedIndex !== null && currItems[highlightedIndex]) {\n handleSelect(currItems[highlightedIndex]);\n } else if (allowCustomValue) {\n setIsMenuShown(false);\n setHighlightedIndex(null);\n }\n }\n }, [currItems, highlightedIndex, handleSelect, allowCustomValue, readOnly]);\n\n return (\n <div\n {...rest}\n ref={triggerRef}\n className={cx(styles.inputDropdown, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={onKeyDown}\n >\n <Input\n label={label}\n value={inputText}\n readOnly={readOnly}\n onChange={(text) => {\n setInputText(text);\n setHighlightedIndex(null);\n setIsMenuShown(true);\n if (allowCustomValue) {\n if (formValidator) formValidator.set(text);\n if (onChange) onChange(text);\n } else if (text === '') {\n if (formValidator) formValidator.set('');\n if (onChange) onChange('');\n onSelect('');\n } else {\n // Emit when the typed text exactly matches an item's label/value.\n const match = items.find(\n (item) => (item.label ?? item.value).toLowerCase() === text.toLowerCase()\n );\n if (match) {\n if (formValidator) formValidator.set(match.value);\n if (onChange) onChange(match.value);\n onSelect(match.value);\n }\n }\n }}\n placeholder={placeholder}\n />\n {isMenuShown && !readOnly && (\n <BodyEnd>\n <div\n ref={anchorRef}\n className={cx(styles.dropdown, styles.dropdownShown, classNames?.dropdown)}\n style={slotStyles?.dropdown}\n >\n <div className={styles.dropdownScroll}>\n {currItems.map((item, key) => (\n <div\n key={`${key}_${item.label}_${item.value}`}\n className={cx(\n styles.dropdownItem,\n highlightedIndex === key && styles.dropdownItemHighlighted,\n classNames?.item\n )}\n style={slotStyles?.item}\n // Prevent the input from blurring before the click resolves.\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleSelect(item)}\n >\n {item.label ?? item.value}\n </div>\n ))}\n </div>\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n",".board {\n display: flex;\n gap: var(--spacing-s);\n overflow-x: auto;\n align-items: flex-start;\n width: 100%;\n}\n\n.column {\n background: var(--background-accent-light);\n border-radius: var(--default-border-radius);\n box-shadow: var(--card-shadow);\n flex: 1 1 0;\n display: flex;\n flex-direction: column;\n border: 2px solid transparent;\n transition: border-color 0.15s ease, background 0.15s ease;\n\n &-empty {\n flex: 0 1 0;\n min-width: 140px;\n }\n\n &-over {\n border-color: var(--primary-lighter);\n background: var(--background-accent);\n }\n\n &-header {\n padding: var(--spacing-m) var(--spacing-l);\n background: var(--background-accent);\n border-radius: var(--default-border-radius) var(--default-border-radius) 0 0;\n font-size: var(--header-small-font-size);\n font-weight: var(--header-font-weight);\n color: var(--text-color);\n border-bottom: 1px solid var(--border-color);\n }\n\n &-items {\n padding: var(--spacing-m);\n display: flex;\n flex-direction: column;\n gap: var(--spacing-m);\n min-height: 80px;\n flex: 1;\n }\n}\n\n.item {\n cursor: grab;\n touch-action: none;\n\n &:active {\n cursor: grabbing;\n }\n\n &-dragging {\n opacity: 0.4;\n }\n}\n\n.dragOverlay {\n border-radius: var(--default-border-radius);\n cursor: grabbing;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25), var(--card-shadow);\n}\n","import type { ReactNode } from 'react';\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport cx from 'classnames';\n\nimport styles from './kanbanBoard.module.pcss';\n\ninterface KanbanItemProps {\n id: string;\n children: ReactNode;\n}\n\nfunction KanbanItem({ id, children }: KanbanItemProps) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id,\n });\n\n return (\n <div\n ref={setNodeRef}\n style={{ transform: CSS.Transform.toString(transform), transition }}\n className={cx(styles.item, isDragging && styles.itemDragging)}\n {...attributes}\n {...listeners}\n >\n {children}\n </div>\n );\n}\n\nexport default KanbanItem;\n","import type { ReactNode } from 'react';\nimport { useDroppable } from '@dnd-kit/core';\nimport { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';\nimport cx from 'classnames';\n\nimport type { KanbanColumnProps } from './kanbanBoard.types';\nimport styles from './kanbanBoard.module.pcss';\nimport KanbanItem from './KanbanItem';\n\ninterface KanbanColumnInternalProps<T> extends KanbanColumnProps {\n itemIds: string[];\n items: Record<string, T>;\n renderItem: (item: T, id: string) => ReactNode;\n}\n\nfunction KanbanColumn<T>({\n id,\n title,\n itemIds,\n items,\n renderItem,\n className,\n classNames,\n styles: slotStyles,\n}: KanbanColumnInternalProps<T>) {\n const droppableId = `column-${id}`;\n const { setNodeRef, isOver } = useDroppable({ id: droppableId });\n\n return (\n <div className={cx(styles.column, isOver && styles.columnOver, itemIds.length === 0 && styles.columnEmpty, className)}>\n <div className={cx(styles.columnHeader, classNames?.header)} style={slotStyles?.header}>{title}</div>\n <SortableContext items={itemIds} strategy={verticalListSortingStrategy}>\n <div ref={setNodeRef} className={cx(styles.columnItems, classNames?.items)} style={slotStyles?.items}>\n {itemIds.map((itemId) => (\n <KanbanItem key={itemId} id={itemId}>\n {items[itemId] !== undefined ? renderItem(items[itemId], itemId) : null}\n </KanbanItem>\n ))}\n </div>\n </SortableContext>\n </div>\n );\n}\n\nexport default KanbanColumn;\n","import { useState } from 'react';\nimport {\n DndContext,\n DragOverlay,\n PointerSensor,\n useSensor,\n useSensors,\n closestCorners,\n type DragStartEvent,\n type DragOverEvent,\n type DragEndEvent,\n} from '@dnd-kit/core';\nimport { arrayMove } from '@dnd-kit/sortable';\nimport cx from 'classnames';\n\nimport type { KanbanBoardProps, KanbanColumnDef } from './kanbanBoard.types';\nimport styles from './kanbanBoard.module.pcss';\nimport KanbanColumn from './KanbanColumn';\n\nfunction KanbanBoard<T = unknown>({\n columns,\n items,\n renderItem,\n onChange,\n className,\n style,\n classNames,\n styles: slotStyles,\n}: KanbanBoardProps<T>) {\n const [activeId, setActiveId] = useState<string | null>(null);\n const [shadowColumns, setShadowColumns] = useState<KanbanColumnDef[] | null>(null);\n\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: { distance: 8 },\n })\n );\n\n const displayColumns = shadowColumns ?? columns;\n\n function findColumnForItem(cols: KanbanColumnDef[], itemId: string): number {\n return cols.findIndex((col) => col.itemIds.includes(itemId));\n }\n\n function handleDragStart({ active }: DragStartEvent) {\n setActiveId(String(active.id));\n setShadowColumns(columns.map((col) => ({ ...col, itemIds: [...col.itemIds] })));\n }\n\n function handleDragOver({ active, over }: DragOverEvent) {\n if (!over) return;\n\n const activeItemId = String(active.id);\n const overId = String(over.id);\n\n setShadowColumns((prev) => {\n const base = prev ?? columns.map((col) => ({ ...col, itemIds: [...col.itemIds] }));\n const next = base.map((col) => ({ ...col, itemIds: [...col.itemIds] }));\n\n const sourceColIndex = findColumnForItem(next, activeItemId);\n if (sourceColIndex === -1) return prev;\n\n // Determine destination column\n let destColIndex: number;\n if (overId.startsWith('column-')) {\n const colId = overId.slice('column-'.length);\n destColIndex = next.findIndex((col) => col.id === colId);\n } else {\n destColIndex = findColumnForItem(next, overId);\n }\n\n if (destColIndex === -1) return prev;\n\n if (sourceColIndex === destColIndex) {\n // Reorder within the same column\n const col = next[sourceColIndex];\n const oldIndex = col.itemIds.indexOf(activeItemId);\n const newIndex = col.itemIds.indexOf(overId);\n if (oldIndex !== -1 && newIndex !== -1 && oldIndex !== newIndex) {\n next[sourceColIndex] = {\n ...col,\n itemIds: arrayMove(col.itemIds, oldIndex, newIndex),\n };\n }\n } else {\n // Move across columns\n next[sourceColIndex].itemIds = next[sourceColIndex].itemIds.filter(\n (id) => id !== activeItemId\n );\n const overIndex = next[destColIndex].itemIds.indexOf(overId);\n const insertAt = overIndex === -1 ? next[destColIndex].itemIds.length : overIndex;\n next[destColIndex].itemIds.splice(insertAt, 0, activeItemId);\n }\n\n return next;\n });\n }\n\n function handleDragEnd({ active, over }: DragEndEvent) {\n setActiveId(null);\n\n if (!over || !shadowColumns) {\n setShadowColumns(null);\n return;\n }\n\n // Commit shadow columns to parent\n onChange(shadowColumns);\n setShadowColumns(null);\n }\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCorners}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDragEnd={handleDragEnd}\n >\n <div className={cx(styles.board, className)} style={style}>\n {displayColumns.map((col) => (\n <KanbanColumn\n key={col.id}\n id={col.id}\n title={col.title}\n itemIds={col.itemIds}\n items={items}\n renderItem={renderItem}\n />\n ))}\n </div>\n <DragOverlay>\n {activeId && items[activeId] !== undefined ? (\n <div className={cx(styles.dragOverlay, classNames?.dragOverlay)} style={slotStyles?.dragOverlay}>{renderItem(items[activeId], activeId)}</div>\n ) : null}\n </DragOverlay>\n </DndContext>\n );\n}\n\nexport default KanbanBoard;\n","const BASE_URL = 'https://api.klipy.com/v2';\n\nexport interface KlipyMediaFormat {\n url: string;\n dims: [number, number];\n size: number;\n}\n\nexport interface KlipyResult {\n id: string;\n title: string;\n media_formats: {\n gif: KlipyMediaFormat;\n tinygif: KlipyMediaFormat;\n mediumgif: KlipyMediaFormat;\n mp4: KlipyMediaFormat;\n tinymp4: KlipyMediaFormat;\n };\n tags: string[];\n url: string;\n}\n\ninterface SearchOptions {\n limit?: number;\n contentfilter?: 'off' | 'low' | 'medium' | 'high';\n pos?: string;\n}\n\nexport default class KlipyService {\n private key: string;\n\n constructor(key: string) {\n this.key = key;\n }\n\n async search(\n query: string,\n options: SearchOptions = {},\n ): Promise<{ results: KlipyResult[]; next: string }> {\n const params = new URLSearchParams({ q: query, key: this.key });\n if (options.limit != null) params.set('limit', String(options.limit));\n if (options.contentfilter != null) params.set('contentfilter', options.contentfilter);\n if (options.pos != null) params.set('pos', options.pos);\n\n const res = await fetch(`${BASE_URL}/search?${params}`);\n return res.json();\n }\n\n async searchSuggestions(query: string): Promise<{ results: string[] }> {\n const params = new URLSearchParams({ q: query, key: this.key });\n const res = await fetch(`${BASE_URL}/search_suggestions?${params}`);\n return res.json();\n }\n\n registerShare(query: string, id: string): void {\n const params = new URLSearchParams({ id, q: query, key: this.key });\n fetch(`${BASE_URL}/registershare?${params}`).catch(() => null);\n }\n}\n",".resultCount {\n margin: 6px 0 0;\n font-size: 12px;\n color: var(--text-dark);\n}\n","import { useEffect, useRef, type ReactElement } from 'react';\nimport Input from 'components/common/input';\nimport { InputType } from 'components/common/input/input.types';\nimport styles from './searchInput.module.pcss';\nimport type { SearchInputProps } from './searchInput.types';\n\n\nexport default function SearchInput({\n value,\n onChange,\n onDebounce,\n placeholder,\n label,\n debounceMs = 500,\n totalAmount,\n showAmount = true,\n className,\n width,\n ...rest\n}: SearchInputProps): ReactElement {\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => () => {\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n }, []);\n\n function handleChange(val: unknown) {\n const str = val != null ? String(val) : '';\n const trimmed = str.trim() === '' ? '' : str;\n onChange(trimmed);\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => { onDebounce?.(trimmed); }, debounceMs);\n }\n\n const showCount = showAmount && typeof totalAmount === 'number' && !Number.isNaN(totalAmount);\n\n return (\n <div {...rest} className={className} style={width != null ? { width } : undefined}>\n <Input\n type={InputType.Search}\n label={label}\n placeholder={placeholder}\n value={value}\n onChange={handleChange}\n />\n {showCount && (\n <p className={styles.resultCount}>\n {totalAmount} {totalAmount === 1 ? 'result' : 'results'}\n </p>\n )}\n </div>\n );\n}\n","\n.gifPreview {\n width: min(420px, 90vw);\n aspect-ratio: 1;\n display: flex;\n flex-wrap: wrap;\n overflow: hidden;\n --gif-preview-gap-size: 5px;\n gap: var(--gif-preview-gap-size);\n position: relative;\n justify-content: center;\n overflow: auto;\n\n &-image {\n background-position: center;\n background-size: cover;\n width: 100%;\n height: 100%;\n\n &-container {\n width: min(140px, 33.3%);\n aspect-ratio: 1;\n background: linear-gradient(\n 45deg,\n var(--primary-color) 10%,\n var(--primary-lighter),\n var(--primary-accent),\n var(--primary-color) 85%\n );\n background-size: 500% 500%;\n animation: gradientBottomLeftToTopRight 1s infinite linear;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n width: min(\n calc(140px - var(--gif-preview-gap-size)),\n calc(33.3% - var(--gif-preview-gap-size))\n );\n }\n }\n}\n","import cx from 'classnames';\nimport type { ReactElement, UIEvent } from 'react';\nimport InteractableDiv from 'components/common/interactableDiv';\nimport type { GifPreviewProps } from './gifPreview.types';\nimport styles from './gifPreview.module.pcss';\n\nexport default function GifPreview({\n className,\n previewItems = [],\n onSelect,\n onLoadAdditional,\n}: GifPreviewProps): ReactElement {\n function handleScroll(event: UIEvent<HTMLDivElement>) {\n const el = event.currentTarget;\n const loadAdditionalHeight = el.scrollHeight - el.clientHeight * 1.5;\n if (el.scrollTop >= loadAdditionalHeight) {\n onLoadAdditional?.();\n }\n }\n\n return (\n <>\n {previewItems.length > 0 && (\n <div className={cx(styles.gifPreview, className)} onScroll={handleScroll}>\n {previewItems.map((preview, index) => (\n <InteractableDiv\n key={`${preview.id}_${index}`}\n className={styles.gifPreviewImageContainer}\n onClick={() => onSelect?.(preview)}\n >\n <div\n className={styles.gifPreviewImage}\n style={{ backgroundImage: `url(${preview.media_formats.tinygif.url})` }}\n />\n </InteractableDiv>\n ))}\n </div>\n )}\n </>\n );\n}\n","\n.gifView {\n display: flex;\n justify-content: center;\n align-items: center;\n position: relative;\n\n img {\n max-width: 100%;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n }\n\n &-loading {\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n background: linear-gradient(\n 45deg,\n var(--primary-color) 10%,\n var(--primary-lighter),\n var(--primary-accent),\n var(--primary-color) 85%\n );\n background-size: 500% 500%;\n animation: gradientBottomLeftToTopRight 1s infinite linear;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n }\n}\n","import { useEffect, useState } from 'react';\nimport cx from 'classnames';\nimport type { ReactElement } from 'react';\nimport type { GifViewProps } from './gifView.types';\nimport styles from './gifView.module.pcss';\n\nexport default function GifView({ className, src = '' }: GifViewProps): ReactElement {\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n setIsLoading(true);\n }, [src]);\n\n return (\n <div className={cx(styles.gifView, className)}>\n <img className={styles.klipyPickerSelected} src={src} onLoad={() => setIsLoading(false)} />\n {isLoading && <div className={styles.gifViewLoading} />}\n </div>\n );\n}\n",".klipyPicker {\n &-selected {\n margin-top: 8px;\n }\n\n &-modal {\n &-content {\n display: flex;\n flex-flow: column;\n gap: var(--spacing-m);\n }\n }\n\n &-suggestions {\n &-container {\n max-width: 420px;\n }\n\n &-item {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n }\n}\n","import { useMemo, useState } from 'react';\nimport cx from 'classnames';\nimport type { ReactElement, ReactNode } from 'react';\nimport KlipyService from 'services/klipy';\nimport type { KlipyResult } from 'services/klipy';\nimport SearchInput from '../searchInput';\nimport GifPreview from './components/gifPreview';\nimport FloatingMenu from '../floatingMenu';\nimport Button, { ButtonStyleType } from '../button';\nimport Modal from '../modal';\nimport Chip, { ChipContainer } from '../chip';\nimport GifView from './components/gifView';\nimport type { KlipyPickerProps } from './klipyPicker.types';\nimport styles from './klipyPicker.module.pcss';\nimport actionButtonStyles from 'components/common/actionButtons/actionButtons.module.pcss';\nimport { Align } from '../floatingMenu/floatingMenu.types';\n\nexport default function KlipyPicker({\n className,\n token = '',\n isModal = false,\n onSelect = () => undefined,\n selected = null,\n}: KlipyPickerProps): ReactElement {\n const klipyService = useMemo(() => new KlipyService(token), [token]);\n\n const [searchText, setSearchText] = useState('');\n const [currentPreviews, setCurrentPreviews] = useState<KlipyResult[]>([]);\n const [currentSuggestions, setCurrentSuggestions] = useState<string[]>([]);\n const [lastNext, setLastNext] = useState<string | null>(null);\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n async function searchFor(query: string) {\n setSearchText(query);\n if (!query.trim()) {\n setCurrentPreviews([]);\n setCurrentSuggestions([]);\n setLastNext(null);\n return;\n }\n const [{ results: searchResults = [], next = null }, { results: suggestionResults = [] }] =\n await Promise.all([\n klipyService.search(query, { limit: 18, contentfilter: 'medium' }),\n klipyService.searchSuggestions(query),\n ]);\n setCurrentPreviews(searchResults);\n setLastNext(next);\n setCurrentSuggestions(suggestionResults);\n }\n\n async function handleLoadAdditional() {\n const { results: searchResults = [], next = null } = await klipyService.search(searchText, {\n limit: 36,\n pos: lastNext ?? undefined,\n contentfilter: 'medium',\n });\n setLastNext(next);\n setCurrentPreviews((prev) => [...prev, ...searchResults]);\n }\n\n async function handlePreviewSelect(preview: KlipyResult | null) {\n await onSelect(preview);\n setIsMenuOpen(false);\n if (preview) klipyService.registerShare(searchText, preview.id);\n }\n\n function renderSuggestions(): ReactNode {\n return (\n <ChipContainer inline className={styles.klipyPickerSuggestionsContainer}>\n {currentSuggestions.map((suggestion) => (\n <Chip\n className={styles.klipyPickerSuggestionsItem}\n key={suggestion}\n text={suggestion}\n onClick={() => searchFor(suggestion)}\n />\n ))}\n </ChipContainer>\n );\n }\n\n function renderPreviewPicker(): ReactNode {\n return (\n <GifPreview\n previewItems={currentPreviews}\n onSelect={handlePreviewSelect}\n onLoadAdditional={handleLoadAdditional}\n />\n );\n }\n\n function renderSearchInput(): ReactNode {\n return (\n <SearchInput\n label=\"Pick gif\"\n value={searchText}\n onDebounce={searchFor}\n onChange={setSearchText}\n />\n );\n }\n\n if (isModal) {\n return (\n <div className={cx(styles.klipyPicker, className)}>\n <div className={actionButtonStyles.actionButtons}>\n <Button onClick={() => setIsMenuOpen(true)}>Pick gif</Button>\n {selected && (\n <Button styleType={ButtonStyleType.Delete} onClick={() => handlePreviewSelect(null)}>\n Remove gif\n </Button>\n )}\n </div>\n {selected && <GifView className={styles.klipyPickerSelected} src={selected} />}\n <Modal isOpen={isMenuOpen} onClose={() => setIsMenuOpen(false)}>\n <div className={styles.klipyPickerModalContent}>\n {renderSearchInput()}\n {renderSuggestions()}\n {renderPreviewPicker()}\n </div>\n </Modal>\n </div>\n );\n }\n\n return (\n <div className={cx(styles.klipyPicker, className)}>\n <FloatingMenu\n align={Align.Left}\n isOpen={currentPreviews.length > 0 && isMenuOpen}\n onOpenChange={setIsMenuOpen}\n content={\n <>\n {renderSuggestions()}\n {renderPreviewPicker()}\n </>\n }\n >\n {renderSearchInput()}\n </FloatingMenu>\n {selected && (\n <Button styleType={ButtonStyleType.Delete} onClick={() => handlePreviewSelect(null)}>\n Remove gif\n </Button>\n )}\n {selected && <GifView className={styles.klipyPickerSelected} src={selected} />}\n </div>\n );\n}\n",".iconLoading {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n position: absolute;\n left: 0;\n top: 0;\n user-select: none;\n pointer-events: none;\n\n --draw-duration: 0.8s;\n --delay: 0.4s;\n\n svg {\n stroke-dasharray: 14;\n stroke-dashoffset: 14;\n width: 200px;\n aspect-ratio: 1;\n animation: calc(var(--draw-duration) * 3) spin-to-oblivion var(--delay) infinite;\n transform: rotate(0deg);\n stroke: var(--primary-color);\n stroke-linecap: round;\n }\n\n &-first {\n animation: calc(var(--draw-duration) * 3) draw-line var(--delay) infinite;\n }\n\n &-second {\n animation: calc(var(--draw-duration) * 3) draw-line-two var(--delay) infinite;\n }\n\n @keyframes draw-line {\n 33% {\n stroke-dashoffset: 0;\n }\n 95% {\n stroke-dashoffset: 0;\n }\n 96% {\n stroke-dashoffset: 14;\n }\n }\n\n @keyframes draw-line-two {\n 33% {\n stroke-dashoffset: 14;\n }\n 66% {\n stroke-dashoffset: 0;\n }\n 95% {\n stroke-dashoffset: 0;\n }\n 96% {\n stroke-dashoffset: 14;\n }\n }\n\n @keyframes spin-to-oblivion {\n 50% {\n transform: rotate(180deg);\n }\n 75% {\n transform: rotate(180deg) scale(0);\n }\n 100% {\n transform: rotate(180deg) scale(0);\n }\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\n\nimport styles from './iconLoading.module.pcss';\n\nfunction IconLoading({ className = '' }) {\n return (\n <div className={cx(styles.iconLoading, className)}>\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-8 -1 16 14\">\n <path\n className={styles.iconLoadingFirst}\n d=\"M 0 0 C 3 5 6 5 6 12\"\n strokeWidth=\"1.7\"\n fill=\"none\"\n />\n <path\n className={styles.iconLoadingFirst}\n d=\"M 0 0 C -3 5 -6 5 -6 12\"\n strokeWidth=\"1.7\"\n fill=\"none\"\n />\n <path className={styles.iconLoadingFirst} d=\"M 0 0 L 0 10\" strokeWidth=\"1.7\" fill=\"none\" />\n <path\n className={styles.iconLoadingSecond}\n d=\"M 0.1 10 C -3 10 -4 10 -6 12\"\n strokeWidth=\"1.7\"\n fill=\"none\"\n />\n <path\n className={styles.iconLoadingSecond}\n d=\"M -0.1 10 C 3 10 4 10 6 12\"\n strokeWidth=\"1.7\"\n fill=\"none\"\n />\n </svg>\n </div>\n );\n}\n\nexport default IconLoading;\n","import IconLoading from './iconLoading.js';\n\nexport default IconLoading;\n",".numberInput {}\n\n.arrows {\n display: flex;\n flex-direction: column;\n align-self: stretch;\n border-left: 1px solid var(--border-color);\n margin: 4px 0;\n}\n\n.arrowBtn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n color: var(--text-dark);\n padding: 0 6px;\n font-size: 0.55rem;\n line-height: 1;\n transition: color 0.15s, background 0.15s;\n\n &:hover {\n color: var(--primary-color);\n background: var(--background-accent-light);\n }\n\n &:active {\n color: var(--primary-lighter);\n }\n}\n","import type { ReactElement } from 'react';\nimport React from 'react';\nimport cx from 'classnames';\nimport { NumericFormat, NumericFormatProps } from 'react-number-format';\nimport type { FormValidator } from 'services/formValidation';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './numberInput.module.pcss';\nimport Input from '../input';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults } from '../configProvider';\n\nexport interface NumberInputProps\n extends Omit<NumericFormatProps, 'onValueChange' | 'value' | 'customInput' | 'onChange' | 'step' | 'onKeyDown'> {\n value?: number | string;\n onChange?: (value: number | undefined) => void;\n formValidator?: FormValidator | null;\n label?: string;\n error?: string;\n className?: string;\n allowNegative?: boolean;\n decimalSeparator?: string;\n thousandSeparator?: string | boolean;\n prefix?: string;\n suffix?: string;\n decimalScale?: number;\n /**\n * Whether to pad the value to exactly `decimalScale` decimals. Default `true`\n * (e.g. with `decimalScale={2}`, `12` displays as `12.00`). Set `false` to make\n * `decimalScale` an upper limit only — the user may type fewer decimals and they\n * are kept as-is (`12` stays `12`, `12.1` stays `12.1`), while anything beyond\n * `decimalScale` is still truncated.\n */\n fixedDecimalScale?: boolean;\n placeholder?: string;\n sign?: '+' | '-';\n showArrows?: boolean;\n step?: number;\n readOnly?: boolean;\n onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n}\n\nfunction NumberInput(props: NumberInputProps): ReactElement {\n const {\n value,\n onChange,\n formValidator,\n label,\n error,\n className,\n allowNegative = false,\n decimalSeparator,\n thousandSeparator,\n prefix,\n suffix,\n decimalScale,\n fixedDecimalScale = true,\n placeholder,\n sign,\n showArrows = false,\n step = 1,\n readOnly = false,\n onKeyDown: onKeyDownProp,\n ...rest\n } = useComponentDefaults('NumberInput', props);\n const rawValue = formValidator != null ? formValidator.value as number | string : value;\n // When a sign is forced, display the absolute value — the prefix character carries the sign visually.\n const displayValue = sign != null && rawValue != null ? Math.abs(Number(rawValue)) : rawValue;\n const controlledValue = displayValue != null ? String(displayValue) : '';\n\n function handleValueChange(floatValue: number | undefined) {\n let out = floatValue;\n if (out !== undefined) {\n if (sign === '-') out = -Math.abs(out);\n if (sign === '+') out = Math.abs(out);\n }\n if (formValidator != null) formValidator.set(out ?? null);\n onChange?.(out);\n }\n\n function handleStep(delta: number) {\n if (readOnly) return;\n const current = rawValue != null && rawValue !== '' ? Number(rawValue) : 0;\n let next = current + delta;\n if (!allowNegative && sign !== '-') next = Math.max(0, next);\n if (sign === '-') next = Math.min(0, next);\n handleValueChange(next);\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if (readOnly) { onKeyDownProp?.(e); return; }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n handleStep(e.shiftKey ? step * 10 : step);\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n handleStep(e.shiftKey ? -step * 10 : -step);\n return;\n }\n onKeyDownProp?.(e);\n }\n\n const resolvedPrefix = sign === '-' ? '-' : sign === '+' ? '+' : prefix;\n\n const arrowSuffix = showArrows && !readOnly ? (\n <div className={styles.arrows}>\n <InteractableDiv\n className={styles.arrowBtn}\n tabIndex={-1}\n onMouseDown={(e) => { e.preventDefault(); handleStep(e.shiftKey ? step * 10 : step); }}\n >\n <FontAwesomeIcon icon={faChevronUp} />\n </InteractableDiv>\n <InteractableDiv\n className={styles.arrowBtn}\n tabIndex={-1}\n onMouseDown={(e) => { e.preventDefault(); handleStep(e.shiftKey ? -step * 10 : -step); }}\n >\n <FontAwesomeIcon icon={faChevronDown} />\n </InteractableDiv>\n </div>\n ) : null;\n\n return (\n <Input\n label={label}\n className={cx(styles.numberInput, className)}\n value={controlledValue}\n onChange={() => {}}\n formValidator={null}\n isValid={formValidator ? (formValidator.touched ? !formValidator.hasError() : true) : !error}\n errorMessage={formValidator ? (formValidator.getCurrentErrorMessage() ?? '') : (error ?? '')}\n placeholder={placeholder}\n readOnly={readOnly}\n suffix={arrowSuffix}\n customInput={\n <NumericFormat\n onValueChange={(vals) => handleValueChange(vals.floatValue)}\n allowNegative={sign != null ? false : allowNegative}\n decimalSeparator={decimalSeparator}\n thousandSeparator={thousandSeparator}\n decimalScale={decimalScale}\n fixedDecimalScale={fixedDecimalScale}\n prefix={resolvedPrefix}\n suffix={suffix}\n onKeyDown={showArrows ? handleKeyDown : onKeyDownProp}\n {...rest}\n />\n }\n />\n );\n}\n\nexport default NumberInput;\n","import NumberInput from './numberInput';\n\nexport default NumberInput;\n",".optionPicker{\n display: flex;\n width: 100%;\n gap: var(--spacing-m);\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n justify-content: space-around;\n position: relative;\n overflow: hidden;\n\n &-chip {\n position: absolute;\n height: 100%;\n top: 0;\n left: 0;\n background: var(--primary-color);\n border-radius: var(--default-border-radius);\n transition: left 0.25s ease-in-out, width 0.25s ease-in-out;\n }\n\n &-option {\n position: relative;\n width: 100%;\n height: 100%;\n display: block;\n text-align: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: var(--spacing-m);\n overflow: hidden;\n text-overflow: ellipsis;\n border-radius: var(--default-border-radius);\n transition: color 0.25s;\n\n &:focus {\n outline: var(--primary-color) solid 2px;\n outline-offset: -2px;\n }\n\n &-active {\n color: var(--text-on-primary);\n }\n }\n}\n","import type { ReactElement } from 'react';\nimport { OptionPickerProps } from './optionPicker.types';\nimport cx from 'classnames';\n\nimport styles from './optionPicker.module.pcss';\nimport InteractableDiv from '../interactableDiv';\n\n\nfunction OptionPicker({\n className = undefined,\n options,\n onChange,\n value,\n ...rest\n}: OptionPickerProps): ReactElement {\n const optionPickerLeft = options.findIndex((option) => option.key === value) * 100 / options.length;\n\n return (\n <div {...rest} className={cx(styles.optionPicker, className)}>\n <div className={styles.optionPickerChip} style={{ left: `${optionPickerLeft}%`, width: `${100 / options.length}%` }} />\n {options.map((option) => (\n <InteractableDiv\n onClick={(e) => onChange(option.key, e)}\n key={option.key}\n className={cx(\n styles.optionPickerOption,\n option.key === value && styles.optionPickerOptionActive\n )}\n tabIndex={option.key === value ? -1 : 0}\n >\n {option.label}\n </InteractableDiv>\n ))}\n </div>\n );\n}\n\nexport default OptionPicker;\n","import { useState, useEffect } from 'react';\n\nconst MOBILE_BREAKPOINT = 768;\n\nexport interface WindowSize {\n width: number;\n height: number;\n isMobileSize: boolean;\n}\n\nexport default function useWindowSize(): WindowSize {\n const [size, setSize] = useState<WindowSize>(() => ({\n width: window.innerWidth,\n height: window.innerHeight,\n isMobileSize: window.innerWidth < MOBILE_BREAKPOINT,\n }));\n\n useEffect(() => {\n function onResize() {\n setSize({\n width: window.innerWidth,\n height: window.innerHeight,\n isMobileSize: window.innerWidth < MOBILE_BREAKPOINT,\n });\n }\n window.addEventListener('resize', onResize);\n return () => window.removeEventListener('resize', onResize);\n }, []);\n\n return size;\n}\n",".overscroll {\n height: 100vh;\n overflow: auto;\n -ms-overflow-style: none; /* IE and Edge */\n scrollbar-width: none; /* Firefox */\n\n &::-webkit-scrollbar {\n display: none;\n }\n\n &-header {\n position: absolute;\n bottom: 0;\n width: 100%;\n\n &-centered {\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n &-container {\n position: relative;\n }\n }\n}\n","import { useRef, useEffect, useCallback } from 'react';\nimport cx from 'classnames';\nimport type { UIEvent } from 'react';\nimport useWindowSize from '../../hooks/useWindowSize';\nimport styles from './overscroll.module.pcss';\nimport type { OverscrollProps } from './overscroll.types';\n\nexport default function Overscroll({\n children = null,\n overscrollContent = null,\n overscrollContentDesktop = null,\n centerHeader = true,\n min = 10,\n max = 80,\n start = 30,\n unit = '%',\n mobileOnly = true,\n onScrollChange = () => {},\n scrollDisabled = false,\n}: OverscrollProps) {\n const { isMobileSize, height } = useWindowSize();\n\n const overscrollRef = useRef<HTMLDivElement>(null);\n const overscrollHeaderRef = useRef<HTMLDivElement>(null);\n const overscrollHeaderContainerRef = useRef<HTMLDivElement>(null);\n const isScrollingRef = useRef(false);\n const scrollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const onScrollChangeRef = useRef(onScrollChange);\n onScrollChangeRef.current = onScrollChange;\n\n const updateHeaderHeight = useCallback(\n (scrollTop: number) => {\n let h: number;\n if (unit === '%') {\n if (!overscrollHeaderContainerRef.current) return;\n const containerH = overscrollHeaderContainerRef.current.clientHeight;\n h = Math.max((containerH * min) / 100, containerH - scrollTop);\n } else {\n h = Math.max(min, max - scrollTop);\n }\n if (overscrollHeaderRef.current) {\n overscrollHeaderRef.current.style.height = `${h}px`;\n }\n },\n [min, max, unit],\n );\n\n const scrollToInitialPosition = useCallback(() => {\n let toScroll: number;\n if (unit === '%') {\n if (!overscrollHeaderContainerRef.current) return;\n const hundredPerc = (overscrollHeaderContainerRef.current.clientHeight / max) * 100;\n toScroll =\n overscrollHeaderContainerRef.current.clientHeight - hundredPerc * (start / 100);\n } else {\n toScroll = max - start;\n }\n if (overscrollRef.current) {\n overscrollRef.current.scrollTop = toScroll;\n updateHeaderHeight(toScroll);\n }\n }, [max, start, unit, updateHeaderHeight]);\n\n // Initial scroll position on mount (and if scroll-related props change)\n useEffect(() => {\n const id = setTimeout(scrollToInitialPosition, 100);\n return () => clearTimeout(id);\n }, [scrollToInitialPosition]);\n\n // Toggle overflow when scrollDisabled changes\n useEffect(() => {\n if (overscrollRef.current) {\n overscrollRef.current.style.overflow = scrollDisabled ? 'hidden' : 'auto';\n }\n }, [scrollDisabled]);\n\n // Scroll to initial position when entering mobile view\n const prevIsMobileRef = useRef(isMobileSize);\n useEffect(() => {\n if (isMobileSize && !prevIsMobileRef.current) scrollToInitialPosition();\n prevIsMobileRef.current = isMobileSize;\n }, [isMobileSize, scrollToInitialPosition]);\n\n // Scroll to initial position when mobileOnly is turned off (full overscroll DOM just mounted)\n const prevMobileOnlyRef = useRef(mobileOnly);\n useEffect(() => {\n if (!mobileOnly && prevMobileOnlyRef.current) scrollToInitialPosition();\n prevMobileOnlyRef.current = mobileOnly;\n }, [mobileOnly, scrollToInitialPosition]);\n\n // Update header height on window resize while in mobile view\n const prevHeightRef = useRef(height);\n useEffect(() => {\n if (isMobileSize && height !== prevHeightRef.current && overscrollRef.current) {\n updateHeaderHeight(overscrollRef.current.scrollTop);\n }\n prevHeightRef.current = height;\n }, [height, isMobileSize, updateHeaderHeight]);\n\n function handleScroll(e: UIEvent<HTMLDivElement>) {\n updateHeaderHeight(e.currentTarget.scrollTop);\n if (!isScrollingRef.current) {\n isScrollingRef.current = true;\n onScrollChangeRef.current(true);\n }\n if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);\n scrollTimeoutRef.current = setTimeout(() => {\n scrollTimeoutRef.current = null;\n isScrollingRef.current = false;\n onScrollChangeRef.current(false);\n }, 500);\n }\n\n if (mobileOnly && !isMobileSize) {\n if (overscrollContentDesktop) return <div>{overscrollContentDesktop}{children}</div>;\n return <>{children}</>;\n }\n\n const contentMinHeight = unit === '%' ? `${100 - min}%` : `calc(100% - ${min}px)`;\n\n return (\n <div className={styles.overscroll} ref={overscrollRef} onScroll={handleScroll}>\n <div\n className={styles.overscrollHeaderContainer}\n style={{ height: `${max}${unit}` }}\n ref={overscrollHeaderContainerRef}\n >\n <div\n className={cx(styles.overscrollHeader, centerHeader && styles.overscrollHeaderCentered)}\n ref={overscrollHeaderRef}\n >\n {overscrollContent}\n </div>\n </div>\n <div style={{ minHeight: contentMinHeight }}>{children}</div>\n </div>\n );\n}\n",".popover {\n position: relative;\n display: inline-flex;\n\n &-trigger {\n display: inline-flex;\n }\n\n &-floating {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 1000;\n /* Hidden until usePopoverPosition writes the first coordinates, to avoid a top-left flash. */\n visibility: hidden;\n }\n\n &-panel {\n position: relative;\n /* Above the arrow so the panel background hides the arrow's inner half — only the\n tip pokes out past the panel edge. */\n z-index: 1;\n color: var(--text-color);\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n border-radius: calc(var(--default-border-radius) + 4px);\n padding: 12px 14px;\n max-width: min(320px, calc(100vw - 24px));\n animation: popoverIn 0.12s ease forwards;\n }\n\n &-arrow {\n position: absolute;\n width: 10px;\n height: 10px;\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n transform: rotate(45deg);\n }\n\n /* Arrow sits on the panel edge facing the trigger; --arrow-x / --arrow-y centre it on the trigger. */\n &-floating[data-placement='bottom'] &-arrow {\n top: -5px;\n left: var(--arrow-x, 50%);\n margin-left: -5px;\n }\n &-floating[data-placement='top'] &-arrow {\n bottom: -5px;\n left: var(--arrow-x, 50%);\n margin-left: -5px;\n }\n &-floating[data-placement='right'] &-arrow {\n left: -5px;\n top: var(--arrow-y, 50%);\n margin-top: -5px;\n }\n &-floating[data-placement='left'] &-arrow {\n right: -5px;\n top: var(--arrow-y, 50%);\n margin-top: -5px;\n }\n\n /* Grow from the edge nearest the trigger. */\n &-floating[data-placement='bottom'] &-panel { transform-origin: top center; }\n &-floating[data-placement='top'] &-panel { transform-origin: bottom center; }\n &-floating[data-placement='right'] &-panel { transform-origin: center left; }\n &-floating[data-placement='left'] &-panel { transform-origin: center right; }\n\n @keyframes popoverIn {\n from {\n opacity: 0;\n transform: scale(0.94);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n}\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Preferred side of the trigger the panel opens on. Flips to the opposite side when there's no room. */\nexport enum PopoverPlacement {\n Top = 'top',\n Bottom = 'bottom',\n Left = 'left',\n Right = 'right',\n}\n\n/** Alignment along the trigger's cross axis (horizontal for top/bottom, vertical for left/right). */\nexport enum PopoverAlign {\n Start = 'start',\n Center = 'center',\n End = 'end',\n}\n\n/** What opens the popover. */\nexport enum PopoverTrigger {\n Click = 'click',\n Hover = 'hover',\n Focus = 'focus',\n}\n\nexport type PopoverSlots = 'root' | 'trigger' | 'floating' | 'panel' | 'arrow';\n\nexport interface PopoverProps extends HtmlProps {\n /** The trigger element. */\n children?: ReactNode;\n /** The popover body. */\n content?: ReactNode;\n /** Preferred side (default `Bottom`). */\n placement?: PopoverPlacement;\n /** Cross-axis alignment (default `Center`). */\n align?: PopoverAlign;\n /** What opens the popover (default `Click`). */\n trigger?: PopoverTrigger;\n /** Controlled open state. Omit for uncontrolled. */\n isOpen?: boolean;\n /** Initial open state when uncontrolled (default `false`). */\n defaultOpen?: boolean;\n /** Fires whenever the popover wants to open or close. */\n onOpenChange?: (isOpen: boolean) => void;\n /** Gap in px between trigger and panel (default `10`). */\n offset?: number;\n /** Render the arrow pointing at the trigger (default `true`). */\n withArrow?: boolean;\n /** Close when clicking outside the panel (default `true`). */\n closeOnOutsideClick?: boolean;\n /** Close when pressing Escape (default `true`). */\n closeOnEscape?: boolean;\n /** Delay in ms before a hover-triggered popover opens (default `100`). */\n openDelay?: number;\n /** Delay in ms before a hover-triggered popover closes (default `120`). */\n closeDelay?: number;\n /** Prevent the popover from opening. */\n disabled?: boolean;\n\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<PopoverSlots>;\n styles?: SlotStyles<PopoverSlots>;\n}\n","import { useLayoutEffect, type RefObject } from 'react';\nimport { getScrollableAncestors, isHiddenByAnyAncestor } from 'components/common/utils/scrollAncestors';\nimport { PopoverPlacement, PopoverAlign } from './popover.types';\n\ntype Axis = 'top' | 'bottom' | 'left' | 'right';\nconst OPPOSITE: Record<PopoverPlacement, Axis> = {\n [PopoverPlacement.Top]: 'bottom',\n [PopoverPlacement.Bottom]: 'top',\n [PopoverPlacement.Left]: 'right',\n [PopoverPlacement.Right]: 'left',\n};\n\nconst MARGIN = 8; // viewport gutter kept clear when shifting a panel back on-screen\n\nexport interface UsePopoverPositionArgs {\n isOpen: boolean;\n placement: PopoverPlacement;\n align: PopoverAlign;\n offset: number;\n triggerRef: RefObject<HTMLElement | null>;\n /** `position: fixed` wrapper that receives top/left/visibility and the resolved-placement data attribute. */\n floatingRef: RefObject<HTMLElement | null>;\n /** Visible panel, measured to decide flip and shift. */\n panelRef: RefObject<HTMLElement | null>;\n /** Arrow element; gets `--arrow-x` / `--arrow-y` written to it. Pass a null ref when `withArrow` is false. */\n arrowRef: RefObject<HTMLElement | null>;\n}\n\n/**\n * Positions a portaled, `position: fixed` popover on any of the four sides of its trigger with\n * start/center/end cross-axis alignment. Flips to the opposite side when the preferred one has no\n * room, shifts back on-screen along the cross axis, points the arrow at the trigger centre, and\n * hides (not closes) the panel once the trigger scrolls behind a clipping ancestor. Position is\n * written straight to the DOM via refs — going through setState lags the browser's scroll paint.\n */\nexport function usePopoverPosition({\n isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef,\n}: UsePopoverPositionArgs) {\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let rafId: number | undefined;\n let teardown: (() => void) | undefined;\n\n // The portal target (BodyEnd's #bodyEnd) can still be missing on the first commit, so the\n // floating ref lands one render later. Refs don't re-fire the effect, so retry each frame.\n function trySetup() {\n const trigger = triggerRef.current;\n const floating = floatingRef.current;\n const panel = panelRef.current;\n if (!trigger || !floating || !panel) {\n rafId = requestAnimationFrame(trySetup);\n return;\n }\n const ancestors = getScrollableAncestors(trigger);\n\n function updatePos() {\n const t = trigger!.getBoundingClientRect();\n const pw = panel!.offsetWidth;\n const ph = panel!.offsetHeight;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n // Resolve the main-axis side, flipping when the preferred side lacks room and the\n // opposite side has more.\n const room: Record<Axis, number> = {\n top: t.top,\n bottom: vh - t.bottom,\n left: t.left,\n right: vw - t.right,\n };\n const need = (placement === PopoverPlacement.Top || placement === PopoverPlacement.Bottom) ? ph : pw;\n let side: Axis = placement as unknown as Axis;\n const opp = OPPOSITE[placement];\n if (room[side] < need + offset && room[opp] > room[side]) side = opp;\n\n const vertical = side === 'top' || side === 'bottom';\n\n // Main axis: place the panel just outside the trigger on the resolved side.\n let top: number;\n let left: number;\n if (side === 'bottom') { top = t.bottom + offset; }\n else if (side === 'top') { top = t.top - offset - ph; }\n else if (side === 'right') { left = t.right + offset; }\n else { left = t.left - offset - pw; }\n\n // Cross axis: align start/center/end against the trigger, then shift on-screen.\n if (vertical) {\n if (align === PopoverAlign.Start) left = t.left;\n else if (align === PopoverAlign.End) left = t.right - pw;\n else left = t.left + t.width / 2 - pw / 2;\n left = Math.max(MARGIN, Math.min(left!, vw - pw - MARGIN));\n } else {\n if (align === PopoverAlign.Start) top = t.top;\n else if (align === PopoverAlign.End) top = t.bottom - ph;\n else top = t.top + t.height / 2 - ph / 2;\n top = Math.max(MARGIN, Math.min(top!, vh - ph - MARGIN));\n }\n\n floating!.style.top = `${top!}px`;\n floating!.style.left = `${left!}px`;\n floating!.style.visibility = isHiddenByAnyAncestor(t, ancestors) ? 'hidden' : 'visible';\n floating!.dataset.placement = side;\n\n // Arrow: centre it on the trigger along the cross axis, clamped inside the panel edges.\n const arrow = arrowRef.current;\n if (arrow) {\n const half = arrow.offsetWidth / 2 || 5;\n if (vertical) {\n const x = t.left + t.width / 2 - left!;\n arrow.style.setProperty('--arrow-x', `${Math.max(half + 2, Math.min(x, pw - half - 2))}px`);\n arrow.style.removeProperty('--arrow-y');\n } else {\n const y = t.top + t.height / 2 - top!;\n arrow.style.setProperty('--arrow-y', `${Math.max(half + 2, Math.min(y, ph - half - 2))}px`);\n arrow.style.removeProperty('--arrow-x');\n }\n }\n }\n\n updatePos();\n\n const scrollTargets: (Window | HTMLElement)[] = [window, ...ancestors];\n scrollTargets.forEach((tt) => tt.addEventListener('scroll', updatePos, { passive: true }));\n window.addEventListener('resize', updatePos);\n teardown = () => {\n scrollTargets.forEach((tt) => tt.removeEventListener('scroll', updatePos));\n window.removeEventListener('resize', updatePos);\n };\n }\n\n trySetup();\n\n return () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n teardown?.();\n };\n }, [isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef]);\n}\n","import { useRef, useEffect, useState, useCallback } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './popover.module.pcss';\nimport { usePopoverPosition } from './usePopoverPosition';\nimport { PopoverPlacement, PopoverAlign, PopoverTrigger, type PopoverProps } from './popover.types';\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n].join(',');\n\n/** Tabbable descendants of `root`, in DOM order. */\nfunction tabbablesIn(root: ParentNode | null): HTMLElement[] {\n if (!root) return [];\n return Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));\n}\n\nfunction Popover({\n children = null,\n content = null,\n placement = PopoverPlacement.Bottom,\n align = PopoverAlign.Center,\n trigger = PopoverTrigger.Click,\n isOpen,\n defaultOpen = false,\n onOpenChange = () => {},\n offset = 10,\n withArrow = true,\n closeOnOutsideClick = true,\n closeOnEscape = true,\n openDelay = 100,\n closeDelay = 120,\n disabled = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: PopoverProps) {\n const triggerRef = useRef<HTMLDivElement>(null);\n const floatingRef = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const arrowRef = useRef<HTMLDivElement>(null);\n const hoverTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const isControlled = isOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = isControlled ? isOpen : internalOpen;\n\n // Keep the outside-click/Escape listeners pointed at the latest setter without re-subscribing.\n const onOpenChangeRef = useRef(onOpenChange);\n useEffect(() => { onOpenChangeRef.current = onOpenChange; });\n\n const setOpen = useCallback((next: boolean) => {\n if (disabled && next) return;\n if (!isControlled) setInternalOpen(next);\n onOpenChangeRef.current(next);\n }, [disabled, isControlled]);\n\n usePopoverPosition({\n isOpen: !!open,\n placement,\n align,\n offset,\n triggerRef,\n floatingRef,\n panelRef,\n arrowRef: withArrow ? arrowRef : { current: null },\n });\n\n function firstTriggerFocusable(): HTMLElement | null {\n return tabbablesIn(triggerRef.current)[0] ?? triggerRef.current;\n }\n\n // Hand focus back to the trigger — used on Escape and on Shift+Tab out of the panel top.\n function restoreFocusToTrigger() {\n firstTriggerFocusable()?.focus();\n }\n\n // Move focus to the tabbable element that follows the trigger in the document, skipping the\n // portaled panel — the \"natural next\" stop when Tab exits the bottom of the panel.\n function focusAfterTrigger() {\n const all = tabbablesIn(document.body).filter((el) => !floatingRef.current?.contains(el));\n const trig = firstTriggerFocusable();\n const idx = trig ? all.indexOf(trig) : -1;\n if (idx >= 0) all[idx + 1]?.focus();\n }\n\n // The panel is portaled to the end of the DOM, so Tab never flows into it naturally. When we\n // manage focus (click trigger + focusable content), move focus in on open and, on Tab out of\n // either end, close and continue focus as if the panel sat right after the trigger.\n useEffect(() => {\n if (!open || trigger !== PopoverTrigger.Click) return;\n const focusables = tabbablesIn(panelRef.current);\n if (focusables.length === 0) return;\n // Only claim the dialog role when we're actually managing focus for real content.\n floatingRef.current?.setAttribute('role', 'dialog');\n focusables[0].focus();\n }, [open, trigger]);\n\n function handleFloatingKeyDown(event: React.KeyboardEvent) {\n if (event.key !== 'Tab' || trigger !== PopoverTrigger.Click) return;\n const focusables = tabbablesIn(panelRef.current);\n if (focusables.length === 0) return;\n const active = document.activeElement;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusAfterTrigger();\n setOpen(false);\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n restoreFocusToTrigger();\n setOpen(false);\n }\n }\n\n // Outside click + Escape. Registered only while open and only for the relevant trigger mode.\n useEffect(() => {\n if (!open) return;\n\n function onMouseUp(event: MouseEvent) {\n const target = event.target as Node;\n const inPanel = floatingRef.current?.contains(target);\n const inTrigger = triggerRef.current?.contains(target);\n if (!inPanel && !inTrigger) setOpen(false);\n }\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== 'Escape') return;\n // Hand focus back to the trigger when it currently sits inside the panel.\n if (floatingRef.current?.contains(document.activeElement)) {\n (tabbablesIn(triggerRef.current)[0] ?? triggerRef.current)?.focus();\n }\n setOpen(false);\n }\n // Keyboard counterpart to the outside click: once focus leaves both the trigger\n // and the (portaled) panel — e.g. tabbing on to the next element — close.\n function onFocusIn(event: FocusEvent) {\n const target = event.target as Node;\n const inPanel = floatingRef.current?.contains(target);\n const inTrigger = triggerRef.current?.contains(target);\n if (!inPanel && !inTrigger) setOpen(false);\n }\n\n if (closeOnOutsideClick && trigger !== PopoverTrigger.Hover) {\n window.addEventListener('mouseup', onMouseUp);\n document.addEventListener('focusin', onFocusIn);\n }\n if (closeOnEscape) window.addEventListener('keydown', onKeyDown);\n return () => {\n window.removeEventListener('mouseup', onMouseUp);\n document.removeEventListener('focusin', onFocusIn);\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [open, closeOnOutsideClick, closeOnEscape, trigger, setOpen]);\n\n useEffect(() => () => clearTimeout(hoverTimer.current), []);\n\n function scheduleHover(next: boolean) {\n clearTimeout(hoverTimer.current);\n hoverTimer.current = setTimeout(() => setOpen(next), next ? openDelay : closeDelay);\n }\n\n const triggerHandlers =\n trigger === PopoverTrigger.Click\n ? { onClick: () => setOpen(!open) }\n : trigger === PopoverTrigger.Hover\n ? { onMouseEnter: () => scheduleHover(true), onMouseLeave: () => scheduleHover(false) }\n : { onFocus: () => setOpen(true), onBlur: () => setOpen(false) };\n\n const floatingHoverHandlers =\n trigger === PopoverTrigger.Hover\n ? { onMouseEnter: () => scheduleHover(true), onMouseLeave: () => scheduleHover(false) }\n : {};\n\n return (\n <div\n {...rest}\n className={cx(styles.popover, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div\n ref={triggerRef}\n className={cx(styles.popoverTrigger, classNames?.trigger)}\n style={slotStyles?.trigger}\n {...triggerHandlers}\n >\n {children}\n </div>\n {open && (\n <BodyEnd>\n <div\n ref={floatingRef}\n className={cx(styles.popoverFloating, classNames?.floating)}\n style={slotStyles?.floating}\n data-placement={placement}\n onKeyDown={handleFloatingKeyDown}\n {...floatingHoverHandlers}\n >\n <div\n ref={panelRef}\n className={cx(styles.popoverPanel, classNames?.panel)}\n style={slotStyles?.panel}\n >\n {content}\n </div>\n {withArrow && (\n <div\n ref={arrowRef}\n className={cx(styles.popoverArrow, classNames?.arrow)}\n style={slotStyles?.arrow}\n />\n )}\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n\nexport default Popover;\n",".progressBar{\n min-width: 100px;\n min-height: 10px;\n background-color: #e0e0e0;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n display: flex;\n align-items: center;\n\n &-fill {\n height: stretch;\n background-color: var(--primary-color);\n width: 0;\n display: flex;\n align-items: center;\n overflow: hidden;\n transition: width .3s ease;\n\n &-end {\n border-radius: 0 var(--default-border-radius) var(--default-border-radius) 0;\n }\n }\n\n &-label {\n color: white;\n font-size: 12px;\n padding: 0 5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n &-custom {\n mix-blend-mode: difference;\n }\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { Progress, ProgressBarProps } from './progressBar.types';\n\nimport styles from './progressBar.module.pcss';\n\nexport function getContrastColor(hexColor: string): string {\n const hex = hexColor.replace('#', '');\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n \n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n return luminance > 0.5 ? '#000000' : '#ffffff';\n}\n\nfunction ProgressBar({\n className = undefined,\n total = 100,\n progress = 0,\n style = undefined,\n ...rest\n}: ProgressBarProps): ReactElement {\n\n function renderProgressBars() {\n const progressArray: Progress[] = [];\n\n if (Array.isArray(progress)) progressArray.push(...progress);\n else if (typeof progress === 'object') progressArray.push(progress);\n else progressArray.push({ amount: progress });\n\n return progressArray.map((prog, index) => {\n const widthPercentage = !total ? 0 : (prog.amount / total) * 100;\n\n return (\n <div\n key={index}\n className={cx(\n styles.progressBarFill,\n index === progressArray.length - 1 && styles.progressBarFillEnd,\n prog.class,\n )}\n style={{\n width: `${widthPercentage}%`,\n background: prog.color || undefined,\n ...(style || {}),\n }}\n title={prog.label ? `${prog.label}: ${prog.amount}` : undefined}\n >\n {prog.label && <div className={styles.progressBarLabel} style={prog.color ? { color: getContrastColor(prog.color) } : {}}>{prog.label}</div>}\n </div>\n );\n });\n }\n\n return (\n <div {...rest} className={cx(styles.progressBar, className)} style={style}>\n {renderProgressBars()}\n </div>\n );\n}\n\nexport default ProgressBar;\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { FormValidator } from 'services/formValidation';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport type RadioValue = string | number;\n\nexport enum RadioGroupOrientation {\n Vertical = 'vertical',\n Horizontal = 'horizontal',\n}\n\nexport interface RadioOption {\n value: RadioValue;\n /** Visible label; falls back to `value` when omitted. */\n label?: ReactNode;\n /** Secondary description shown under the label. */\n description?: ReactNode;\n /** Disable just this option. */\n disabled?: boolean;\n}\n\nexport type RadioGroupSlots = 'root' | 'option' | 'radio' | 'dot' | 'label' | 'description';\n\nexport interface RadioGroupProps extends HtmlProps {\n /** The selectable options. */\n options: RadioOption[];\n /** Controlled selected value. Omit for uncontrolled. */\n value?: RadioValue;\n /** Initial value when uncontrolled. */\n defaultValue?: RadioValue;\n /** Fires with the newly selected value. */\n onChange?: (value: RadioValue, event?: React.MouseEvent | React.KeyboardEvent) => void;\n /** Layout direction (default `Vertical`). */\n orientation?: RadioGroupOrientation;\n /** Disable the whole group. */\n disabled?: boolean;\n /** Diameter of the radio circle (default `'18px'`). */\n size?: string;\n /** Tab index of the active (roving) option. */\n tabIndex?: number;\n formValidator?: FormValidator | null;\n /** Manual error message shown in a tooltip (used when there's no `formValidator`, or to force one). */\n errorMessage?: string;\n /** Manual valid state when not using a `formValidator` (default `true`). */\n isValid?: boolean;\n\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<RadioGroupSlots>;\n styles?: SlotStyles<RadioGroupSlots>;\n}\n",".radioGroup {\n --radio-size: 18px;\n user-select: none;\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: fit-content;\n\n &-horizontal {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 20px;\n }\n\n &-disabled {\n filter: brightness(0.85);\n cursor: not-allowed;\n }\n\n &-error &-radio:not(.radioGroup-radio-checked) {\n border-color: var(--error-color);\n }\n\n &-option {\n display: flex;\n align-items: flex-start;\n column-gap: 10px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n margin: -1px;\n color: var(--text-color);\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n\n &:focus-visible {\n outline: none;\n border-color: var(--primary-color);\n }\n\n &-disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n }\n\n &-radio {\n flex-shrink: 0;\n width: var(--radio-size);\n height: var(--radio-size);\n border-radius: 50%;\n border: 1.8px solid var(--border-color);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-top: 1px;\n transition: border-color 0.15s;\n\n &-checked {\n border-color: var(--primary-color);\n }\n }\n\n &-dot {\n width: calc(var(--radio-size) * 0.5);\n height: calc(var(--radio-size) * 0.5);\n border-radius: 50%;\n background-color: var(--primary-color);\n transform: scale(0);\n transition: transform 0.15s ease;\n\n &-checked {\n transform: scale(1);\n }\n }\n\n &-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n &-label {\n line-height: 1.2;\n color: var(--text-color);\n }\n\n &-description {\n font-size: 0.85em;\n line-height: 1.3;\n color: var(--text-dark);\n }\n}\n","import { useEffect, useRef, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport Tooltip from 'components/common/tooltip';\n\nimport { useComponentDefaults } from '../configProvider';\nimport { RadioGroupOrientation, type RadioGroupProps, type RadioValue } from './radioGroup.types';\nimport styles from './radioGroup.module.pcss';\n\nfunction RadioGroup(props: RadioGroupProps): ReactElement {\n const {\n options = [],\n value,\n defaultValue,\n onChange = () => {},\n orientation = RadioGroupOrientation.Vertical,\n disabled = false,\n size = '18px',\n tabIndex = 0,\n formValidator = null,\n errorMessage = '',\n isValid = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('RadioGroup', props);\n\n const optionRefs = useRef<(HTMLDivElement | null)[]>([]);\n const fvRef = useRef(formValidator);\n useEffect(() => { fvRef.current = formValidator; });\n const [, forceUpdate] = useState(0);\n const [internalValue, setInternalValue] = useState<RadioValue | undefined>(defaultValue);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n\n useEffect(() => {\n if (!formValidator) return;\n formValidator.validate();\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = formValidator\n ? formValidator.touched && formValidator.hasError()\n : !isValid || !!errorMessage;\n const errorText = formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || '';\n\n const isControlled = value !== undefined && !formValidator;\n const currentValue = (formValidator ? formValidator.value : isControlled ? value : internalValue) as\n | RadioValue\n | undefined;\n\n function select(next: RadioValue, event?: React.MouseEvent | React.KeyboardEvent) {\n if (formValidator) formValidator.set(next);\n else if (!isControlled) setInternalValue(next);\n onChange(next, event);\n }\n\n function handleBlur(event: React.FocusEvent<HTMLDivElement>) {\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) return;\n setIsFocused(false);\n if (fvRef.current) fvRef.current.touched = true;\n }\n\n const selectedIndex = options.findIndex((o) => o.value === currentValue);\n const firstEnabledIndex = options.findIndex((o) => !o.disabled);\n const rovingIndex = selectedIndex >= 0 ? selectedIndex : firstEnabledIndex;\n\n function focusOption(index: number) {\n optionRefs.current[index]?.focus();\n }\n\n function moveTo(step: 1 | -1, fromIndex: number, event: React.KeyboardEvent) {\n if (disabled || options.length === 0) return;\n let i = fromIndex;\n for (let count = 0; count < options.length; count++) {\n i = (i + step + options.length) % options.length;\n if (!options[i].disabled) {\n focusOption(i);\n select(options[i].value, event);\n return;\n }\n }\n }\n\n function handleKeyDown(event: React.KeyboardEvent, index: number) {\n const option = options[index];\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowRight':\n event.preventDefault();\n moveTo(1, index, event);\n break;\n case 'ArrowUp':\n case 'ArrowLeft':\n event.preventDefault();\n moveTo(-1, index, event);\n break;\n case ' ':\n case 'Enter':\n event.preventDefault();\n if (!disabled && !option.disabled) select(option.value, event);\n break;\n default:\n break;\n }\n }\n\n return (\n <div\n {...rest}\n role=\"radiogroup\"\n aria-orientation={orientation}\n aria-disabled={disabled || undefined}\n aria-invalid={hasError || undefined}\n className={cx(\n styles.radioGroup,\n orientation === RadioGroupOrientation.Horizontal && styles.radioGroupHorizontal,\n disabled && styles.radioGroupDisabled,\n hasError && styles.radioGroupError,\n className,\n classNames?.root,\n )}\n style={{ '--radio-size': size, ...style, ...slotStyles?.root } as React.CSSProperties}\n onFocus={() => setIsFocused(true)}\n onBlur={handleBlur}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {options.map((option, index) => {\n const checked = option.value === currentValue;\n const optionDisabled = disabled || !!option.disabled;\n return (\n <div\n key={String(option.value)}\n ref={(el) => { optionRefs.current[index] = el; }}\n role=\"radio\"\n aria-checked={checked}\n aria-disabled={optionDisabled || undefined}\n tabIndex={optionDisabled ? -1 : index === rovingIndex ? tabIndex : -1}\n className={cx(\n styles.radioGroupOption,\n checked && styles.radioGroupOptionChecked,\n optionDisabled && styles.radioGroupOptionDisabled,\n classNames?.option,\n )}\n style={slotStyles?.option}\n onClick={() => { if (!optionDisabled) select(option.value); }}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n <div\n className={cx(styles.radioGroupRadio, checked && styles.radioGroupRadioChecked, classNames?.radio)}\n style={slotStyles?.radio}\n >\n <div\n className={cx(styles.radioGroupDot, checked && styles.radioGroupDotChecked, classNames?.dot)}\n style={slotStyles?.dot}\n />\n </div>\n {(option.label ?? option.value) !== '' && (\n <div className={styles.radioGroupText}>\n <div className={cx(styles.radioGroupLabel, classNames?.label)} style={slotStyles?.label}>\n {option.label ?? option.value}\n </div>\n {option.description != null && (\n <div\n className={cx(styles.radioGroupDescription, classNames?.description)}\n style={slotStyles?.description}\n >\n {option.description}\n </div>\n )}\n </div>\n )}\n </div>\n );\n })}\n <Tooltip\n variant=\"error\"\n message={errorText}\n isVisible={hasError && (isFocused || isHovered)}\n />\n </div>\n );\n}\n\nexport default RadioGroup;\n",".rating {\n display: inline-flex;\n align-items: center;\n align-self: flex-start;\n width: fit-content;\n gap: 0.15em;\n font-size: 20px;\n outline: none;\n touch-action: pan-y;\n user-select: none;\n\n &:focus-visible {\n box-shadow: 0 0 0 2px var(--primary-lighter);\n border-radius: var(--default-border-radius);\n }\n\n &-disabled {\n opacity: 0.5;\n }\n\n &-disabled,\n &-readOnly {\n pointer-events: none;\n }\n\n &-item {\n position: relative;\n display: inline-flex;\n width: 1em;\n height: 1em;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-iconEmpty {\n width: 1em;\n height: 1em;\n color: var(--rating-empty-color, var(--background-accent-light));\n }\n\n &-iconFilledClip {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n overflow: hidden;\n pointer-events: none;\n }\n\n &-iconFilled {\n width: 1em;\n height: 1em;\n color: var(--rating-filled-color, var(--primary-color));\n }\n}\n","import { useRef, useState } from 'react';\nimport type { CSSProperties, ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faStar } from '@fortawesome/free-solid-svg-icons';\n\nimport { useComponentDefaults } from '../configProvider';\nimport type { RatingProps } from './rating.types';\n\nimport styles from './rating.module.pcss';\n\nconst DRAG_THRESHOLD = 4;\n\nfunction clampValue(value: number, max: number): number {\n return Math.max(0, Math.min(max, value));\n}\n\nfunction Rating(props: RatingProps): ReactElement {\n const {\n value: controlledValue,\n defaultValue = 0,\n onChange = () => {},\n max = 5,\n allowHalf = false,\n allowClear = true,\n readOnly = false,\n disabled = false,\n icon = faStar,\n 'aria-label': ariaLabel = 'Rating',\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Rating', props);\n\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState(defaultValue);\n const value = clampValue(isControlled ? controlledValue! : internalValue, max);\n\n const [hoverValue, setHoverValue] = useState<number | null>(null);\n const isInteractive = !readOnly && !disabled;\n const displayValue = hoverValue ?? value;\n\n const rootRef = useRef<HTMLDivElement>(null);\n const valueBeforeGestureRef = useRef(value);\n const draggingRef = useRef(false);\n const gestureStartXRef = useRef(0);\n const hasDraggedRef = useRef(false);\n\n function commit(nextValue: number) {\n const clamped = clampValue(nextValue, max);\n if (!isControlled) setInternalValue(clamped);\n onChange(clamped);\n }\n\n function getValueFromClientX(clientX: number): number | null {\n const rect = rootRef.current?.getBoundingClientRect();\n if (!rect || rect.width === 0) return null;\n const fraction = clampValue((clientX - rect.left) / rect.width, 1);\n const raw = fraction * max;\n return allowHalf ? Math.round(raw * 2) / 2 : Math.ceil(raw);\n }\n\n function handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n if (!isInteractive) return;\n event.currentTarget.setPointerCapture?.(event.pointerId);\n draggingRef.current = true;\n hasDraggedRef.current = false;\n gestureStartXRef.current = event.clientX;\n valueBeforeGestureRef.current = value;\n const next = getValueFromClientX(event.clientX);\n if (next !== null) setHoverValue(next);\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n if (!isInteractive) return;\n const next = getValueFromClientX(event.clientX);\n if (next === null) return;\n if (draggingRef.current) {\n event.preventDefault();\n if (Math.abs(event.clientX - gestureStartXRef.current) > DRAG_THRESHOLD) {\n hasDraggedRef.current = true;\n }\n }\n setHoverValue(next);\n }\n\n function handlePointerUp(event: React.PointerEvent<HTMLDivElement>) {\n if (!isInteractive || !draggingRef.current) return;\n event.currentTarget.releasePointerCapture?.(event.pointerId);\n draggingRef.current = false;\n const next = getValueFromClientX(event.clientX) ?? hoverValue;\n if (next !== null) {\n const isClick = !hasDraggedRef.current;\n commit(isClick && allowClear && next === valueBeforeGestureRef.current ? 0 : next);\n }\n setHoverValue(null);\n }\n\n function handlePointerLeave() {\n if (!isInteractive || draggingRef.current) return;\n setHoverValue(null);\n }\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const step = allowHalf ? 0.5 : 1;\n if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {\n event.preventDefault();\n commit(value + step);\n } else if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {\n event.preventDefault();\n commit(value - step);\n } else if (event.key === 'Home') {\n event.preventDefault();\n commit(0);\n } else if (event.key === 'End') {\n event.preventDefault();\n commit(max);\n }\n }\n\n return (\n <div\n {...rest}\n ref={rootRef}\n role=\"slider\"\n aria-label={ariaLabel}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-valuetext={`${value} out of ${max}`}\n aria-readonly={readOnly || undefined}\n aria-disabled={disabled || undefined}\n tabIndex={isInteractive ? 0 : -1}\n className={cx(\n styles.rating,\n disabled && styles.ratingDisabled,\n readOnly && styles.ratingReadOnly,\n classNames?.root,\n className\n )}\n style={{ ...style, ...slotStyles?.root }}\n onKeyDown={isInteractive ? handleKeyDown : undefined}\n onPointerDown={isInteractive ? handlePointerDown : undefined}\n onPointerMove={isInteractive ? handlePointerMove : undefined}\n onPointerUp={isInteractive ? handlePointerUp : undefined}\n onPointerCancel={isInteractive ? handlePointerUp : undefined}\n onPointerLeave={isInteractive ? handlePointerLeave : undefined}\n >\n {Array.from({ length: max }, (_, index) => {\n const fillPercent = Math.round(Math.max(0, Math.min(1, displayValue - index)) * 100);\n\n return (\n <div key={index} className={cx(styles.ratingItem, classNames?.item)} style={slotStyles?.item}>\n <FontAwesomeIcon\n icon={icon}\n className={cx(styles.ratingIconEmpty, classNames?.iconEmpty)}\n style={slotStyles?.iconEmpty as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n <div className={styles.ratingIconFilledClip} style={{ width: `${fillPercent}%` }}>\n <FontAwesomeIcon\n icon={icon}\n className={cx(styles.ratingIconFilled, classNames?.iconFilled)}\n style={slotStyles?.iconFilled as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport default Rating;\n","import type { Point, RoomData, DoorData } from './roomDrawer.types';\n\nexport const CANVAS_W = 400;\nexport const CANVAS_H = 300;\nexport const GRID = 5;\nexport const DOOR_WIDTH = 12;\nexport const CLOSE_THRESHOLD = 8; // px in SVG units to close a polygon\nexport const WALL_TOLERANCE = 8; // max distance to snap to a wall for door placement\n\n// ─── Coordinate helpers ────────────────────────────────────────────────────\n\nexport function snap(v: number): number {\n return Math.round(v / GRID) * GRID;\n}\n\nexport function snapPt(p: Point): Point {\n return { x: snap(p.x), y: snap(p.y) };\n}\n\nexport function clientToSVG(clientX: number, clientY: number, svg: SVGSVGElement): Point {\n const pt = svg.createSVGPoint();\n pt.x = clientX;\n pt.y = clientY;\n const m = svg.getScreenCTM();\n if (!m) return { x: 0, y: 0 };\n const raw = pt.matrixTransform(m.inverse());\n return snapPt({ x: raw.x, y: raw.y });\n}\n\n// ─── Geometry ──────────────────────────────────────────────────────────────\n\nexport function dist(a: Point, b: Point): number {\n return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);\n}\n\nexport function pointToSegment(p: Point, a: Point, b: Point): { dist: number; t: number } {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) return { dist: dist(p, a), t: 0 };\n const t = Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2));\n const px = a.x + t * dx;\n const py = a.y + t * dy;\n return { dist: Math.sqrt((p.x - px) ** 2 + (p.y - py) ** 2), t };\n}\n\nexport function nearestWall(pt: Point, rooms: RoomData[]): { roomId: string; wallIndex: number; t: number } | null {\n let best: { roomId: string; wallIndex: number; t: number; dist: number } | null = null;\n for (const room of rooms) {\n const pts = room.points;\n for (let i = 0; i < pts.length; i++) {\n const a = pts[i];\n const b = pts[(i + 1) % pts.length];\n const { dist: d, t } = pointToSegment(pt, a, b);\n if (d <= WALL_TOLERANCE && (!best || d < best.dist)) {\n best = { roomId: room.id, wallIndex: i, t, dist: d };\n }\n }\n }\n return best;\n}\n\nexport function pointInPolygon(pt: Point, poly: Point[]): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i].x, yi = poly[i].y;\n const xj = poly[j].x, yj = poly[j].y;\n if ((yi > pt.y) !== (yj > pt.y) && pt.x < ((xj - xi) * (pt.y - yi)) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}\n\nexport function centroid(pts: Point[]): Point {\n return {\n x: pts.reduce((s, p) => s + p.x, 0) / pts.length,\n y: pts.reduce((s, p) => s + p.y, 0) / pts.length,\n };\n}\n\nexport function rectToPoints(x: number, y: number, w: number, h: number): Point[] {\n return [\n { x, y },\n { x: x + w, y },\n { x: x + w, y: y + h },\n { x, y: y + h },\n ];\n}\n\n// Returns the two endpoints of the door opening and a perpendicular unit vector (for the swing arc).\nexport function doorEndpoints(\n a: Point,\n b: Point,\n t: number,\n width: number,\n): { p1: Point; p2: Point; perp: Point } | null {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n if (len < 0.001) return null;\n const nx = dx / len;\n const ny = dy / len;\n const cx = a.x + dx * t;\n const cy = a.y + dy * t;\n const hw = Math.min(width / 2, len / 2 - 0.001);\n return {\n p1: { x: cx - nx * hw, y: cy - ny * hw },\n p2: { x: cx + nx * hw, y: cy + ny * hw },\n perp: { x: -ny, y: nx },\n };\n}\n\n// ─── SVG export ────────────────────────────────────────────────────────────\n\nfunction escapeSVG(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\nfunction ptsToClosedPath(pts: Point[]): string {\n return pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(' ') + ' Z';\n}\n\n// Returns one path string per wall segment between door gaps.\n// 0 doors → [closed path] | N doors → N open paths\nexport function buildWallSegments(pts: Point[], wallDoors: DoorData[]): string[] {\n if (pts.length < 2) return [];\n\n if (wallDoors.length === 0) {\n return [pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(' ') + ' Z'];\n }\n\n const n = pts.length;\n const segments: string[][] = [];\n let current: string[] = [`M ${pts[0].x.toFixed(2)},${pts[0].y.toFixed(2)}`];\n\n for (let i = 0; i < n; i++) {\n const a = pts[i];\n const b = pts[(i + 1) % n];\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n const segs = wallDoors.filter((d) => d.wallIndex === i).sort((x, y) => x.t - y.t);\n\n if (segs.length === 0) {\n current.push(`L ${b.x.toFixed(2)},${b.y.toFixed(2)}`);\n } else {\n for (const door of segs) {\n const hw = door.width / 2;\n const t1 = Math.max(0, door.t - hw / len);\n const t2 = Math.min(1, door.t + hw / len);\n const gs = { x: a.x + dx * t1, y: a.y + dy * t1 };\n const ge = { x: a.x + dx * t2, y: a.y + dy * t2 };\n current.push(`L ${gs.x.toFixed(2)},${gs.y.toFixed(2)}`);\n segments.push(current);\n current = [`M ${ge.x.toFixed(2)},${ge.y.toFixed(2)}`];\n }\n current.push(`L ${b.x.toFixed(2)},${b.y.toFixed(2)}`);\n }\n }\n\n // Wrap-around: the last segment ends at pts[0] where segments[0] started —\n // merge them so each segment is one continuous open path.\n segments[0] = [...current, ...segments[0].slice(1)];\n\n return segments.map((s) => s.join(' '));\n}\n\nfunction buildDoorArcPath(a: Point, b: Point, door: DoorData): string {\n const ep = doorEndpoints(a, b, door.t, door.width);\n if (!ep) return '';\n const { p1, p2, perp } = ep;\n const swingEnd = { x: p1.x + perp.x * door.width, y: p1.y + perp.y * door.width };\n return [\n `M ${p1.x.toFixed(2)},${p1.y.toFixed(2)} L ${p2.x.toFixed(2)},${p2.y.toFixed(2)}`,\n `M ${p1.x.toFixed(2)},${p1.y.toFixed(2)} A ${door.width},${door.width} 0 0,1 ${swingEnd.x.toFixed(2)},${swingEnd.y.toFixed(2)}`,\n ].join(' ');\n}\n\nexport function generateSVG(rooms: RoomData[], doors: DoorData[]): string {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const r of rooms) {\n for (const p of r.points) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n }\n if (!isFinite(minX)) { minX = 0; minY = 0; maxX = CANVAS_W; maxY = CANVAS_H; }\n\n const pad = 5;\n const vb = [\n (minX - pad).toFixed(2),\n (minY - pad).toFixed(2),\n (maxX - minX + pad * 2).toFixed(2),\n (maxY - minY + pad * 2).toFixed(2),\n ].join(' ');\n\n const roomEls = rooms.map((room) => {\n const roomDoors = doors.filter((d) => d.roomId === room.id);\n const wallSegs = buildWallSegments(room.points, roomDoors);\n const bgPath = ptsToClosedPath(room.points);\n const c = centroid(room.points);\n\n const wallPaths = wallSegs.map((d) => ` <path d=\"${d}\" />`).join('\\n');\n\n const doorPaths = roomDoors\n .map((door) => {\n const a = room.points[door.wallIndex];\n const b = room.points[(door.wallIndex + 1) % room.points.length];\n const d = buildDoorArcPath(a, b, door);\n return d ? ` <path d=\"${d}\" fill=\"none\" />` : '';\n })\n .filter(Boolean)\n .join('\\n');\n\n const labelEl = room.name\n ? ` <text fontSize=\"5\" x=\"${c.x.toFixed(1)}\" y=\"${c.y.toFixed(1)}\">${escapeSVG(room.name)}</text>`\n : '';\n\n return [` <g id=\"${room.id}\">`, wallPaths, ` <path id=\"background\" d=\"${bgPath}\" />`, doorPaths, labelEl, ` </g>`]\n .filter(Boolean)\n .join('\\n');\n });\n\n return [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"${vb}\">`,\n ` <g id=\"layer1\">`,\n ...roomEls,\n ` </g>`,\n ` <use id=\"use\" href=\"\" />`,\n `</svg>`,\n ].join('\\n');\n}\n\n// ─── SVG import ────────────────────────────────────────────────────────────\n\nfunction parseClosedPath(d: string): Point[] {\n const points: Point[] = [];\n for (const m of d.matchAll(/[ML]\\s*([-\\d.]+)[,\\s]+([-\\d.]+)/gi)) {\n points.push({ x: parseFloat(m[1]), y: parseFloat(m[2]) });\n }\n return points;\n}\n\nexport function parseSVGRooms(svgString: string): RoomData[] {\n const doc = new DOMParser().parseFromString(svgString, 'image/svg+xml');\n const rooms: RoomData[] = [];\n doc.querySelectorAll('[id^=\"room\"]').forEach((group) => {\n const bg = group.querySelector('[id=\"background\"]');\n if (!bg) return;\n const d = bg.getAttribute('d');\n if (!d) return;\n const points = parseClosedPath(d);\n if (points.length < 3) return;\n const name = group.querySelector('text')?.textContent?.trim() ?? '';\n rooms.push({ id: group.id, name, points });\n });\n return rooms;\n}\n\nexport function downloadSVG(rooms: RoomData[], doors: DoorData[]): void {\n const svg = generateSVG(rooms, doors);\n const blob = new Blob([svg], { type: 'image/svg+xml' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'room-plan.svg';\n a.click();\n URL.revokeObjectURL(url);\n}\n",".roomDrawer {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n overflow: hidden;\n background: var(--background);\n user-select: none;\n\n &-toolbar {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 8px;\n background: var(--background-accent);\n border-bottom: 1px solid var(--border-color);\n\n &-sep {\n flex: 1;\n }\n\n &-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 13px;\n transition: background 0.12s, color 0.12s;\n\n &:hover:not(:disabled) {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n\n &-active {\n background: var(--primary-accent);\n color: var(--primary-color);\n border-color: var(--primary-lighter);\n }\n }\n\n &-zoomLabel {\n padding: 0 4px;\n min-width: 40px;\n height: 32px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 11px;\n text-align: center;\n\n &:hover {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n }\n }\n\n &-canvas {\n display: block;\n width: 100%;\n cursor: crosshair;\n user-select: none;\n\n &-select {\n cursor: default;\n }\n }\n\n &-info {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n background: var(--background-accent);\n border-top: 1px solid var(--border-color);\n\n &-label {\n font-size: 12px;\n color: var(--text-dark);\n white-space: nowrap;\n }\n\n &-input {\n flex: 1;\n max-width: 220px;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: var(--background);\n color: var(--text-color);\n font-size: 13px;\n\n &:focus {\n outline: none;\n border-color: var(--primary-color);\n }\n }\n\n &-spacer {\n flex: 1;\n }\n\n &-delete {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 12px;\n transition: background 0.12s, color 0.12s, border-color 0.12s;\n\n &:hover {\n background: #e53935;\n color: #fff;\n border-color: #e53935;\n }\n }\n }\n\n &-hint {\n padding: 4px 8px;\n font-size: 11px;\n color: var(--text-dark);\n background: var(--background-accent);\n border-top: 1px solid var(--border-color);\n }\n\n &-info {\n &-doorsBtn {\n display: flex;\n align-items: center;\n gap: 5px;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 12px;\n white-space: nowrap;\n transition: background 0.12s, color 0.12s;\n\n &:hover {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n }\n }\n\n &-doorPanel {\n display: flex;\n flex-direction: column;\n background: var(--background-accent);\n border-top: 1px solid var(--border-color);\n\n &-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-bottom: 1px solid var(--border-color);\n }\n\n &-icon {\n color: var(--text-dark);\n font-size: 12px;\n }\n\n &-title {\n flex: 1;\n font-size: 12px;\n color: var(--text-dark);\n }\n\n &-done {\n display: flex;\n align-items: center;\n gap: 5px;\n height: 26px;\n padding: 0 10px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 12px;\n transition: background 0.12s, color 0.12s;\n\n &:hover {\n background: var(--primary-accent);\n color: var(--primary-color);\n border-color: var(--primary-lighter);\n }\n }\n\n &-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 6px 8px;\n max-height: 130px;\n overflow-y: auto;\n }\n\n &-item {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n &-label {\n font-size: 12px;\n color: var(--text-color);\n min-width: 48px;\n }\n\n &-widthLabel {\n font-size: 11px;\n color: var(--text-dark);\n }\n\n &-empty {\n font-size: 11px;\n color: var(--text-dark);\n font-style: italic;\n padding: 2px 0;\n }\n }\n\n &-canvas {\n &-door {\n cursor: crosshair;\n }\n }\n}\n\n/* ── SVG element classes ── */\n\n.doorGap {\n stroke: var(--background);\n stroke-width: 4;\n stroke-linecap: butt;\n pointer-events: none;\n}\n\n.doorMarker {\n fill: var(--primary-color);\n stroke: var(--background);\n stroke-width: 0.8;\n pointer-events: all;\n cursor: grab;\n\n &:active {\n cursor: grabbing;\n }\n}\n\n.gridLine {\n stroke: var(--text-color);\n stroke-width: 0.3;\n opacity: 0.12;\n}\n\n.roomFill {\n fill: var(--primary-accent);\n fill-opacity: 0.08;\n stroke: none;\n\n &-selected {\n fill-opacity: 0.22;\n }\n}\n\n.roomStroke {\n fill: none;\n stroke: var(--primary-color);\n stroke-width: 1.5;\n stroke-linejoin: round;\n\n &-selected {\n stroke: var(--primary-lighter);\n stroke-width: 2;\n }\n}\n\n.roomText {\n fill: var(--text-color);\n stroke: none;\n font-size: 7px;\n pointer-events: none;\n user-select: none;\n}\n\n.doorPanel {\n stroke: var(--primary-color);\n stroke-width: 1.5;\n stroke-linecap: round;\n\n &-selected {\n stroke: var(--primary-lighter);\n stroke-width: 2;\n }\n}\n\n.doorSwing {\n fill: none;\n stroke: var(--primary-color);\n stroke-width: 0.8;\n stroke-dasharray: 3 2;\n pointer-events: none;\n\n &-selected {\n stroke: var(--primary-lighter);\n }\n}\n\n.preview {\n fill: var(--primary-accent);\n stroke: var(--primary-color);\n stroke-width: 1;\n stroke-dasharray: 4 2;\n pointer-events: none;\n}\n\n.polyCloseTarget {\n fill: var(--primary-color);\n opacity: 0.5;\n pointer-events: none;\n}\n\n.polyVertex {\n fill: var(--primary-color);\n stroke: none;\n pointer-events: none;\n}\n\n.vertexHandle {\n fill: var(--background);\n stroke: var(--primary-color);\n stroke-width: 1.5;\n cursor: grab;\n pointer-events: all;\n\n &:hover {\n fill: var(--primary-accent);\n stroke: var(--primary-lighter);\n }\n}\n","import { useState, useRef, useEffect, useLayoutEffect } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faHandPointer,\n faSquare,\n faDrawPolygon,\n faTrash,\n faDownload,\n faUpload,\n faMagnifyingGlassPlus,\n faMagnifyingGlassMinus,\n faDoorOpen,\n faCheck,\n} from '@fortawesome/free-solid-svg-icons';\nimport type { MouseEvent, ReactElement } from 'react';\nimport type { Tool, Point, RoomData, DoorData, RoomDrawerProps } from './roomDrawer.types';\nimport {\n CANVAS_W,\n CANVAS_H,\n GRID,\n DOOR_WIDTH,\n CLOSE_THRESHOLD,\n clientToSVG,\n dist,\n pointToSegment,\n nearestWall,\n pointInPolygon,\n centroid,\n rectToPoints,\n doorEndpoints,\n buildWallSegments,\n downloadSVG,\n parseSVGRooms,\n snapPt,\n} from './roomDrawer.utils';\nimport styles from './roomDrawer.module.pcss';\n\nconst VERTEX_HIT = 6;\nconst WALL_HIT = 5;\nconst ZOOM_STEP = 1.25;\nconst ZOOM_MIN = 0.25;\nconst ZOOM_MAX = 12;\n\ntype DragState =\n | { type: 'room'; roomId: string; start: Point; origPoints: Point[] }\n | { type: 'vertex'; roomId: string; index: number; start: Point; origPt: Point };\n\nlet _seq = 0;\nfunction nextId(prefix: string): string {\n _seq += 1;\n return `${prefix}${_seq}`;\n}\n\nconst TOOL_HINTS: Record<Tool, string> = {\n select:\n 'Drag inside to move · Drag corner to reshape · Click wall to add corner · Dbl-click corner to remove · Delete to erase',\n rect: 'Drag to draw a rectangular room',\n polygon:\n 'Click to place corners · Click first point or Enter to close · Esc to cancel',\n};\n\nexport default function RoomDrawer({ className }: RoomDrawerProps): ReactElement {\n const [rooms, setRooms] = useState<RoomData[]>([]);\n const [doors, setDoors] = useState<DoorData[]>([]);\n const [tool, setTool] = useState<Tool>('rect');\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [editingDoorsForRoomId, setEditingDoorsForRoomId] = useState<string | null>(null);\n\n const [rectStart, setRectStart] = useState<Point | null>(null);\n const [rectCursor, setRectCursor] = useState<Point | null>(null);\n\n const [polyPoints, setPolyPoints] = useState<Point[]>([]);\n const [polyCursor, setPolyCursor] = useState<Point | null>(null);\n\n const [zoom, setZoom] = useState(1);\n const [pan, setPan] = useState<Point>({ x: 0, y: 0 });\n\n const dragRef = useRef<DragState | null>(null);\n const doorDragRef = useRef<string | null>(null); // door id being dragged\n const panDragRef = useRef<{ startClient: Point; origPan: Point; scaleX: number; scaleY: number } | null>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n const uploadRef = useRef<HTMLInputElement>(null);\n\n const stateRef = useRef({ rooms, doors, tool, selectedId, editingDoorsForRoomId, polyPoints, zoom, pan });\n useLayoutEffect(() => {\n stateRef.current = { rooms, doors, tool, selectedId, editingDoorsForRoomId, polyPoints, zoom, pan };\n });\n\n function commitPolygon(pts: Point[]) {\n if (pts.length < 3) return;\n setRooms((prev) => [\n ...prev,\n { id: nextId('room'), name: `Room ${prev.length + 1}`, points: pts },\n ]);\n setPolyPoints([]);\n setPolyCursor(null);\n }\n\n // Wheel zoom (passive: false so we can preventDefault)\n useEffect(() => {\n const svg = svgRef.current;\n if (!svg) return;\n function onWheel(e: WheelEvent) {\n e.preventDefault();\n const { zoom: z, pan: p } = stateRef.current;\n const pt = clientToSVG(e.clientX, e.clientY, svgRef.current!);\n if (!pt) return;\n const factor = e.deltaY < 0 ? ZOOM_STEP : 1 / ZOOM_STEP;\n const newZoom = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, z * factor));\n setPan({\n x: pt.x - (pt.x - p.x) * (z / newZoom),\n y: pt.y - (pt.y - p.y) * (z / newZoom),\n });\n setZoom(newZoom);\n }\n svg.addEventListener('wheel', onWheel, { passive: false });\n return () => svg.removeEventListener('wheel', onWheel);\n }, []);\n\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n const { tool: t, selectedId: sel, editingDoorsForRoomId: editDoors, polyPoints: pp, zoom: z, pan: p } = stateRef.current;\n\n if (e.key === 'Escape') {\n if (editDoors) { setEditingDoorsForRoomId(null); return; }\n if (t === 'polygon') { setPolyPoints([]); setPolyCursor(null); }\n setSelectedId(null);\n return;\n }\n if (e.key === 'Enter' && t === 'polygon' && pp.length >= 3) {\n commitPolygon(pp);\n return;\n }\n if ((e.key === '+' || e.key === '=') && !(e.target instanceof HTMLInputElement)) {\n const nz = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, z * ZOOM_STEP));\n const cx = p.x + CANVAS_W / z / 2; const cy = p.y + CANVAS_H / z / 2;\n setZoom(nz); setPan({ x: cx - CANVAS_W / nz / 2, y: cy - CANVAS_H / nz / 2 });\n return;\n }\n if (e.key === '-' && !(e.target instanceof HTMLInputElement)) {\n const nz = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, z / ZOOM_STEP));\n const cx = p.x + CANVAS_W / z / 2; const cy = p.y + CANVAS_H / z / 2;\n setZoom(nz); setPan({ x: cx - CANVAS_W / nz / 2, y: cy - CANVAS_H / nz / 2 });\n return;\n }\n if (e.key === '0' && !(e.target instanceof HTMLInputElement)) {\n setZoom(1); setPan({ x: 0, y: 0 });\n return;\n }\n if ((e.key === 'Delete' || e.key === 'Backspace') && sel && !editDoors && !(e.target instanceof HTMLInputElement)) {\n setRooms((prev) => prev.filter((r) => r.id !== sel));\n setDoors((prev) => prev.filter((d) => d.roomId !== sel));\n setSelectedId(null);\n }\n }\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, []);\n\n // ─── Zoom helpers ─────────────────────────────────────────────────────────\n\n function zoomBy(factor: number, currentZoom = zoom, currentPan = pan) {\n const newZoom = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, currentZoom * factor));\n const cx = currentPan.x + CANVAS_W / currentZoom / 2;\n const cy = currentPan.y + CANVAS_H / currentZoom / 2;\n setPan({\n x: cx - CANVAS_W / newZoom / 2,\n y: cy - CANVAS_H / newZoom / 2,\n });\n setZoom(newZoom);\n }\n\n // ─── Drawing helpers ──────────────────────────────────────────────────────\n\n function svgPt(e: MouseEvent): Point | null {\n if (!svgRef.current) return null;\n return clientToSVG(e.clientX, e.clientY, svgRef.current);\n }\n\n // ─── Vertex / wall editing helpers ───────────────────────────────────────\n\n function nearestVertex(pt: Point, room: RoomData): { index: number; d: number } | null {\n let best: { index: number; d: number } | null = null;\n for (let i = 0; i < room.points.length; i++) {\n const d = dist(pt, room.points[i]);\n if (d <= VERTEX_HIT && (!best || d < best.d)) best = { index: i, d };\n }\n return best;\n }\n\n function nearestWallSegment(\n pt: Point,\n room: RoomData,\n ): { index: number; t: number; d: number } | null {\n let best: { index: number; t: number; d: number } | null = null;\n for (let i = 0; i < room.points.length; i++) {\n const a = room.points[i];\n const b = room.points[(i + 1) % room.points.length];\n const { dist: d, t } = pointToSegment(pt, a, b);\n if (d <= WALL_HIT && (!best || d < best.d)) best = { index: i, t, d };\n }\n return best;\n }\n\n function insertVertex(roomId: string, wallIndex: number, t: number, newPt: Point): number {\n setRooms((prev) =>\n prev.map((r) => {\n if (r.id !== roomId) return r;\n const pts = [...r.points];\n pts.splice(wallIndex + 1, 0, newPt);\n return { ...r, points: pts };\n }),\n );\n setDoors((prev) =>\n prev.map((d) => {\n if (d.roomId !== roomId) return d;\n if (d.wallIndex === wallIndex) {\n if (d.t <= t) return { ...d, t: t > 0 ? d.t / t : 0 };\n return { ...d, wallIndex: wallIndex + 1, t: (d.t - t) / (1 - t) };\n }\n if (d.wallIndex > wallIndex) return { ...d, wallIndex: d.wallIndex + 1 };\n return d;\n }),\n );\n return wallIndex + 1;\n }\n\n function removeVertex(roomId: string, index: number) {\n const room = rooms.find((r) => r.id === roomId);\n if (!room || room.points.length <= 3) return;\n const n = room.points.length;\n setRooms((prev) =>\n prev.map((r) => {\n if (r.id !== roomId) return r;\n return { ...r, points: r.points.filter((_, i) => i !== index) };\n }),\n );\n setDoors((prev) =>\n prev.map((d) => {\n if (d.roomId !== roomId) return d;\n const prevWall = (index - 1 + n) % n;\n if (d.wallIndex === prevWall || d.wallIndex === index) return { ...d, wallIndex: -1 };\n if (d.wallIndex > index) return { ...d, wallIndex: d.wallIndex - 1 };\n return d;\n }).filter((d) => d.wallIndex !== -1),\n );\n }\n\n // ─── Mouse events ─────────────────────────────────────────────────────────\n\n function handleMouseDown(e: MouseEvent<SVGSVGElement>) {\n // Middle mouse → pan\n if (e.button === 1) {\n e.preventDefault();\n const svg = svgRef.current;\n if (svg) {\n const rect = svg.getBoundingClientRect();\n panDragRef.current = {\n startClient: { x: e.clientX, y: e.clientY },\n origPan: { ...pan },\n scaleX: (CANVAS_W / zoom) / rect.width,\n scaleY: (CANVAS_H / zoom) / rect.height,\n };\n }\n return;\n }\n\n if (e.button !== 0) return;\n e.preventDefault();\n const pt = svgPt(e);\n if (!pt) return;\n\n // Door editing mode: click a wall to add a door\n if (editingDoorsForRoomId) {\n const editingRoom = rooms.find((r) => r.id === editingDoorsForRoomId);\n if (editingRoom) {\n const wall = nearestWall(pt, [editingRoom]);\n if (wall) {\n setDoors((prev) => [\n ...prev,\n { id: nextId('door'), roomId: wall.roomId, wallIndex: wall.wallIndex, t: wall.t, width: DOOR_WIDTH },\n ]);\n }\n }\n return;\n }\n\n if (tool === 'rect') {\n setRectStart(pt); setRectCursor(pt); return;\n }\n\n if (tool === 'polygon') {\n if (polyPoints.length >= 3 && dist(pt, polyPoints[0]) <= CLOSE_THRESHOLD) {\n commitPolygon(polyPoints);\n } else {\n setPolyPoints((prev) => [...prev, pt]);\n }\n return;\n }\n\n if (tool === 'select') {\n const selRoom = rooms.find((r) => r.id === selectedId) ?? null;\n\n if (selRoom) {\n const vh = nearestVertex(pt, selRoom);\n if (vh) {\n dragRef.current = { type: 'vertex', roomId: selRoom.id, index: vh.index, start: pt, origPt: selRoom.points[vh.index] };\n return;\n }\n }\n\n if (selRoom) {\n const wh = nearestWallSegment(pt, selRoom);\n if (wh) {\n const a = selRoom.points[wh.index];\n const b = selRoom.points[(wh.index + 1) % selRoom.points.length];\n const newPt = snapPt({ x: a.x + (b.x - a.x) * wh.t, y: a.y + (b.y - a.y) * wh.t });\n const insertedIndex = insertVertex(selRoom.id, wh.index, wh.t, newPt);\n dragRef.current = { type: 'vertex', roomId: selRoom.id, index: insertedIndex, start: pt, origPt: newPt };\n return;\n }\n }\n\n const clickedRoom = rooms.find((r) => pointInPolygon(pt, r.points));\n if (clickedRoom) {\n setSelectedId(clickedRoom.id);\n dragRef.current = { type: 'room', roomId: clickedRoom.id, start: pt, origPoints: [...clickedRoom.points] };\n return;\n }\n\n setSelectedId(null);\n }\n }\n\n function handleDoubleClick(e: MouseEvent<SVGSVGElement>) {\n if (tool !== 'select' || editingDoorsForRoomId) return;\n const pt = svgPt(e);\n if (!pt) return;\n const selRoom = rooms.find((r) => r.id === selectedId);\n if (!selRoom) return;\n const vh = nearestVertex(pt, selRoom);\n if (vh) { e.preventDefault(); removeVertex(selRoom.id, vh.index); }\n }\n\n function handleMouseMove(e: MouseEvent<SVGSVGElement>) {\n if (panDragRef.current) {\n const { startClient, origPan, scaleX, scaleY } = panDragRef.current;\n setPan({\n x: origPan.x - (e.clientX - startClient.x) * scaleX,\n y: origPan.y - (e.clientY - startClient.y) * scaleY,\n });\n return;\n }\n\n const pt = svgPt(e);\n if (!pt) return;\n\n if (doorDragRef.current && editingDoorsForRoomId) {\n const editRoom = rooms.find((r) => r.id === editingDoorsForRoomId);\n if (editRoom) {\n const wall = nearestWall(pt, [editRoom]);\n if (wall) {\n setDoors((prev) => prev.map((d) =>\n d.id === doorDragRef.current ? { ...d, wallIndex: wall.wallIndex, t: wall.t } : d\n ));\n }\n }\n return;\n }\n\n if (tool === 'rect' && rectStart) { setRectCursor(pt); return; }\n if (tool === 'polygon') { setPolyCursor(pt); return; }\n\n if (tool === 'select' && !editingDoorsForRoomId && dragRef.current) {\n const drag = dragRef.current;\n if (drag.type === 'vertex') {\n const dx = pt.x - drag.start.x;\n const dy = pt.y - drag.start.y;\n const moved = snapPt({ x: drag.origPt.x + dx, y: drag.origPt.y + dy });\n setRooms((prev) =>\n prev.map((r) => {\n if (r.id !== drag.roomId) return r;\n const pts = [...r.points];\n pts[drag.index] = moved;\n return { ...r, points: pts };\n }),\n );\n } else {\n const dx = pt.x - drag.start.x;\n const dy = pt.y - drag.start.y;\n setRooms((prev) =>\n prev.map((r) =>\n r.id === drag.roomId\n ? { ...r, points: drag.origPoints.map((p) => ({ x: p.x + dx, y: p.y + dy })) }\n : r,\n ),\n );\n }\n }\n }\n\n function handleMouseUp(e: MouseEvent<SVGSVGElement>) {\n if (panDragRef.current) { panDragRef.current = null; return; }\n\n const pt = svgPt(e);\n if (!pt) return;\n\n if (tool === 'rect' && rectStart) {\n const x = Math.min(rectStart.x, pt.x);\n const y = Math.min(rectStart.y, pt.y);\n const w = Math.abs(pt.x - rectStart.x);\n const h = Math.abs(pt.y - rectStart.y);\n if (w >= GRID * 2 && h >= GRID * 2) {\n setRooms((prev) => [\n ...prev,\n { id: nextId('room'), name: `Room ${prev.length + 1}`, points: rectToPoints(x, y, w, h) },\n ]);\n }\n setRectStart(null); setRectCursor(null);\n }\n\n doorDragRef.current = null;\n dragRef.current = null;\n }\n\n // ─── Info bar handlers ────────────────────────────────────────────────────\n\n function handleRenameChange(value: string) {\n if (selectedId) setRooms((prev) => prev.map((r) => (r.id === selectedId ? { ...r, name: value } : r)));\n }\n\n function handleDoorWidthChange(doorId: string, value: string) {\n const w = parseFloat(value);\n if (isNaN(w) || w <= 0) return;\n setDoors((prev) => prev.map((d) => (d.id === doorId ? { ...d, width: w } : d)));\n }\n\n function handleDeleteRoom() {\n if (!selectedId) return;\n setRooms((prev) => prev.filter((r) => r.id !== selectedId));\n setDoors((prev) => prev.filter((d) => d.roomId !== selectedId));\n setEditingDoorsForRoomId(null);\n setSelectedId(null);\n }\n\n function handleDeleteDoor(doorId: string) {\n setDoors((prev) => prev.filter((d) => d.id !== doorId));\n }\n\n function switchTool(t: Tool) {\n setTool(t);\n setEditingDoorsForRoomId(null);\n setPolyPoints([]); setPolyCursor(null);\n setRectStart(null); setRectCursor(null);\n }\n\n function handleUploadChange(e: React.ChangeEvent<HTMLInputElement>) {\n const file = e.target.files?.[0];\n if (!file) return;\n e.target.value = '';\n const reader = new FileReader();\n reader.onload = (ev) => {\n const text = ev.target?.result;\n if (typeof text !== 'string') return;\n const loaded = parseSVGRooms(text);\n if (loaded.length === 0) return;\n const remapped = loaded.map((r) => ({ ...r, id: nextId('room') }));\n setRooms(remapped);\n setDoors([]);\n setSelectedId(null);\n setEditingDoorsForRoomId(null);\n setZoom(1);\n setPan({ x: 0, y: 0 });\n };\n reader.readAsText(file);\n }\n\n // ─── Derived values ───────────────────────────────────────────────────────\n\n const previewRect =\n tool === 'rect' && rectStart && rectCursor\n ? {\n x: Math.min(rectStart.x, rectCursor.x),\n y: Math.min(rectStart.y, rectCursor.y),\n w: Math.abs(rectCursor.x - rectStart.x),\n h: Math.abs(rectCursor.y - rectStart.y),\n }\n : null;\n\n const selectedRoom = selectedId ? (rooms.find((r) => r.id === selectedId) ?? null) : null;\n const editingRoom = editingDoorsForRoomId ? (rooms.find((r) => r.id === editingDoorsForRoomId) ?? null) : null;\n const editingRoomDoors = editingDoorsForRoomId ? doors.filter((d) => d.roomId === editingDoorsForRoomId) : [];\n\n const TOOLS = [\n { t: 'select' as Tool, icon: faHandPointer, label: 'Select & edit' },\n { t: 'rect' as Tool, icon: faSquare, label: 'Rectangle room' },\n { t: 'polygon' as Tool, icon: faDrawPolygon, label: 'Polygon room' },\n ] as const;\n\n const vw = CANVAS_W / zoom;\n const vh = CANVAS_H / zoom;\n\n const canvasCursor = editingDoorsForRoomId ? styles.roomDrawerCanvasDoor : tool === 'select' ? styles.roomDrawerCanvasSelect : undefined;\n\n // ─── Render ───────────────────────────────────────────────────────────────\n\n return (\n <div className={cx(styles.roomDrawer, className)}>\n {/* ── Toolbar ── */}\n <div className={styles.roomDrawerToolbar}>\n {TOOLS.map(({ t, icon, label }) => (\n <button\n key={t}\n title={label}\n className={cx(styles.roomDrawerToolbarBtn, t === tool && !editingDoorsForRoomId && styles.roomDrawerToolbarBtnActive)}\n onClick={() => switchTool(t)}\n >\n <FontAwesomeIcon icon={icon} />\n </button>\n ))}\n <div className={styles.roomDrawerToolbarSep} />\n <button title=\"Zoom in (+)\" className={styles.roomDrawerToolbarBtn} onClick={() => zoomBy(ZOOM_STEP)} disabled={zoom >= ZOOM_MAX}>\n <FontAwesomeIcon icon={faMagnifyingGlassPlus} />\n </button>\n <button\n title={`Reset zoom (0) — ${Math.round(zoom * 100)}%`}\n className={styles.roomDrawerToolbarZoomLabel}\n onClick={() => { setZoom(1); setPan({ x: 0, y: 0 }); }}\n >\n {Math.round(zoom * 100)}%\n </button>\n <button title=\"Zoom out (−)\" className={styles.roomDrawerToolbarBtn} onClick={() => zoomBy(1 / ZOOM_STEP)} disabled={zoom <= ZOOM_MIN}>\n <FontAwesomeIcon icon={faMagnifyingGlassMinus} />\n </button>\n <div className={styles.roomDrawerToolbarSep} />\n <button\n title=\"Upload SVG\"\n className={styles.roomDrawerToolbarBtn}\n onClick={() => uploadRef.current?.click()}\n >\n <FontAwesomeIcon icon={faUpload} />\n </button>\n <button\n title=\"Download SVG\"\n className={styles.roomDrawerToolbarBtn}\n onClick={() => downloadSVG(rooms, doors)}\n disabled={rooms.length === 0}\n >\n <FontAwesomeIcon icon={faDownload} />\n </button>\n <input ref={uploadRef} type=\"file\" accept=\".svg,image/svg+xml\" style={{ display: 'none' }} onChange={handleUploadChange} />\n </div>\n\n {/* ── SVG Canvas ── */}\n <svg\n ref={svgRef}\n className={cx(styles.roomDrawerCanvas, canvasCursor)}\n viewBox={`${pan.x} ${pan.y} ${vw} ${vh}`}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onDoubleClick={handleDoubleClick}\n >\n <defs>\n <pattern id=\"rd-grid\" width={GRID} height={GRID} patternUnits=\"userSpaceOnUse\">\n <path d={`M ${GRID} 0 L 0 0 0 ${GRID}`} fill=\"none\" className={styles.gridLine} />\n </pattern>\n </defs>\n <rect x={pan.x} y={pan.y} width={vw} height={vh} fill=\"url(#rd-grid)\" />\n\n {/* ── Rooms ── */}\n {rooms.map((room) => {\n const pts = room.points;\n const fillD = pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x},${p.y}`).join(' ') + ' Z';\n const wallSegs = buildWallSegments(pts, doors.filter((d) => d.roomId === room.id));\n const c = centroid(pts);\n const isSelected = selectedId === room.id;\n const isEditing = editingDoorsForRoomId === room.id;\n return (\n <g key={room.id}>\n <path d={fillD} className={cx(styles.roomFill, (isSelected || isEditing) && styles.roomFillSelected)} />\n {wallSegs.map((seg, si) => (\n <path key={si} d={seg} className={cx(styles.roomStroke, (isSelected || isEditing) && styles.roomStrokeSelected)} />\n ))}\n {room.name && (\n <text x={c.x} y={c.y} className={styles.roomText} textAnchor=\"middle\" dominantBaseline=\"middle\">\n {room.name}\n </text>\n )}\n </g>\n );\n })}\n\n {/* ── Door gap overlays — rendered after all rooms so they cut through adjacent walls ── */}\n {doors.map((door) => {\n const room = rooms.find((r) => r.id === door.roomId);\n if (!room) return null;\n const a = room.points[door.wallIndex];\n const b = room.points[(door.wallIndex + 1) % room.points.length];\n const ep = doorEndpoints(a, b, door.t, door.width);\n if (!ep) return null;\n return (\n <line\n key={door.id}\n x1={ep.p1.x} y1={ep.p1.y}\n x2={ep.p2.x} y2={ep.p2.y}\n className={styles.doorGap}\n />\n );\n })}\n\n {/* ── Door markers (visible in door editing mode) ── */}\n {editingDoorsForRoomId && editingRoomDoors.map((door) => {\n const room = rooms.find((r) => r.id === door.roomId);\n if (!room) return null;\n const a = room.points[door.wallIndex];\n const b = room.points[(door.wallIndex + 1) % room.points.length];\n const ep = doorEndpoints(a, b, door.t, door.width);\n if (!ep) return null;\n const mid = { x: (ep.p1.x + ep.p2.x) / 2, y: (ep.p1.y + ep.p2.y) / 2 };\n return (\n <circle\n key={door.id}\n cx={mid.x} cy={mid.y} r={2.5}\n className={styles.doorMarker}\n onMouseDown={(e) => {\n if (e.button !== 0) return;\n e.preventDefault();\n e.stopPropagation();\n doorDragRef.current = door.id;\n }}\n />\n );\n })}\n\n {/* ── Vertex handles ── */}\n {tool === 'select' && !editingDoorsForRoomId && selectedRoom &&\n selectedRoom.points.map((p, i) => (\n <circle key={i} cx={p.x} cy={p.y} r={3.5} className={styles.vertexHandle} />\n ))}\n\n {/* ── Rect preview ── */}\n {previewRect && (\n <rect x={previewRect.x} y={previewRect.y} width={previewRect.w} height={previewRect.h} className={styles.preview} />\n )}\n\n {/* ── Polygon preview ── */}\n {tool === 'polygon' && polyPoints.length > 0 && (\n <>\n <polyline\n points={[...polyPoints, polyCursor ?? polyPoints[polyPoints.length - 1]].map((p) => `${p.x},${p.y}`).join(' ')}\n className={styles.preview}\n />\n {polyPoints.length >= 3 && (\n <circle cx={polyPoints[0].x} cy={polyPoints[0].y} r={CLOSE_THRESHOLD / 2} className={styles.polyCloseTarget} />\n )}\n {polyPoints.map((p, i) => (\n <circle key={i} cx={p.x} cy={p.y} r={2} className={styles.polyVertex} />\n ))}\n </>\n )}\n </svg>\n\n {/* ── Room info bar ── */}\n {selectedRoom && !editingDoorsForRoomId && (\n <div className={styles.roomDrawerInfo}>\n <span className={styles.roomDrawerInfoLabel}>Name</span>\n <input\n className={styles.roomDrawerInfoInput}\n value={selectedRoom.name}\n onChange={(e) => handleRenameChange(e.target.value)}\n placeholder=\"Room name\"\n />\n <button\n className={styles.roomDrawerInfoDoorsBtn}\n onClick={() => setEditingDoorsForRoomId(selectedRoom.id)}\n title=\"Edit doors\"\n >\n <FontAwesomeIcon icon={faDoorOpen} />\n <span>{doors.filter((d) => d.roomId === selectedRoom.id).length}</span>\n </button>\n <button className={styles.roomDrawerInfoDelete} onClick={handleDeleteRoom} title=\"Delete room\">\n <FontAwesomeIcon icon={faTrash} />\n </button>\n </div>\n )}\n\n {/* ── Door editing panel ── */}\n {editingDoorsForRoomId && editingRoom && (\n <div className={styles.roomDrawerDoorPanel}>\n <div className={styles.roomDrawerDoorPanelHeader}>\n <FontAwesomeIcon icon={faDoorOpen} className={styles.roomDrawerDoorPanelIcon} />\n <span className={styles.roomDrawerDoorPanelTitle}>\n {editingRoom.name ? `Doors · ${editingRoom.name}` : 'Doors'}\n </span>\n <button\n className={styles.roomDrawerDoorPanelDone}\n onClick={() => setEditingDoorsForRoomId(null)}\n title=\"Done (Esc)\"\n >\n <FontAwesomeIcon icon={faCheck} />\n Done\n </button>\n </div>\n <div className={styles.roomDrawerDoorPanelList}>\n {editingRoomDoors.length === 0 && (\n <span className={styles.roomDrawerDoorPanelEmpty}>Click on a wall to add a door</span>\n )}\n {editingRoomDoors.map((door, i) => (\n <div key={door.id} className={styles.roomDrawerDoorPanelItem}>\n <span className={styles.roomDrawerDoorPanelLabel}>Door {i + 1}</span>\n <span className={styles.roomDrawerDoorPanelWidthLabel}>Width</span>\n <input\n className={styles.roomDrawerInfoInput}\n type=\"number\"\n min={1}\n value={door.width}\n onChange={(e) => handleDoorWidthChange(door.id, e.target.value)}\n />\n <button\n className={styles.roomDrawerInfoDelete}\n onClick={() => handleDeleteDoor(door.id)}\n title=\"Delete door\"\n >\n <FontAwesomeIcon icon={faTrash} />\n </button>\n </div>\n ))}\n </div>\n </div>\n )}\n\n <div className={styles.roomDrawerHint}>\n {editingDoorsForRoomId\n ? 'Click a wall to add a door · Adjust width or delete from the list · Done or Esc to finish'\n : `${TOOL_HINTS[tool]} · Scroll to zoom · Middle-drag to pan · 0 to reset`}\n </div>\n </div>\n );\n}\n",".roomViewer{\n &-container{\n &Loading {\n opacity: 0.4;\n pointer-events: none;\n }\n\n svg{\n stroke-width: 1px;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-opacity: 1;\n path {\n stroke: var(--primary-color);\n fill: transparent;\n }\n path[id=\"background\"] {\n stroke: none;\n fill: transparent;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n *[id^=\"room\"] {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n text{\n fill: var(--text-color);\n stroke: none;\n font-size: 5px;\n }\n }\n }\n\n &-active{\n stroke: #18f810 !important;\n fill: #20f81013 !important;\n path {\n stroke: #18f810 !important;\n fill: none !important;\n }\n path[id=\"background\"] {\n stroke: none !important;\n fill: #20f81013 !important;\n }\n }\n\n &-selected {\n stroke: #18f810 !important;\n path {\n stroke: #18f810 !important;\n fill: none !important;\n }\n path[id=\"background\"] {\n stroke: none !important;\n fill: #20f81013 !important;\n }\n\n text{\n stroke: none;\n fill: var(--text-color);\n }\n }\n\n &-tint {\n fill: #20f81013 !important;\n\n path{\n fill: #20f81013 !important;\n }\n\n text{\n stroke: none;\n fill: none;\n }\n }\n\n &-actions{\n display: flex;\n width: 100%;\n justify-content: center;\n gap: 8px;\n font-size: 16px;\n\n svg{\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n &-header{\n margin-bottom: 4px;\n }\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faChevronLeft as leftIcon,\n faChevronRight as rightIcon,\n faLayerGroup as layerIcon,\n} from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './roomViewer.module.pcss';\nimport type { RoomViewerProps } from './roomViewer.types';\n\nfunction RoomViewer({ data = [] }: RoomViewerProps) {\n const roomViewerRef = useRef<HTMLDivElement>(null);\n\n const [, setSelectedRoomId] = useState<string | null>(null);\n const [selectedDataId, setSelectedDataId] = useState(0);\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n const abortController = new AbortController();\n\n setSelectedRoomId(null);\n\n const container = roomViewerRef.current;\n\n if (selectedDataId > data.length - 1 || !container) {\n setIsLoading(false);\n return () => abortController.abort();\n }\n\n // useEffect fires after the DOM has been committed, so the SVG rendered\n // from data[selectedDataId].data is already in the container here.\n const rooms = container.querySelectorAll<Element>('[id^=\"room\"]');\n rooms.forEach((element) => {\n element.addEventListener(\n 'click',\n () => onRoomClicked(element.id, container),\n { signal: abortController.signal }\n );\n });\n setIsLoading(false);\n\n return () => abortController.abort();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [data, selectedDataId]);\n\n function onRoomClicked(roomId: string, container: Element) {\n const pureRoomId = roomId.substring(4);\n\n setSelectedRoomId((prevSelectedRoomId) => {\n if (pureRoomId === prevSelectedRoomId) return prevSelectedRoomId;\n\n const [use] = container.querySelectorAll<Element>('[id=\"use\"]');\n use?.setAttribute('href', `#${roomId}`);\n\n const [room] = container.querySelectorAll<Element>(`[id=\"${roomId}\"]`);\n\n if (prevSelectedRoomId) {\n const [prevRoom] = container.querySelectorAll<Element>(`[id=\"room${prevSelectedRoomId}\"]`);\n if (prevRoom) {\n prevRoom.classList.remove(styles.roomViewerSelected, styles.roomViewerTint);\n const [prevBackground] = prevRoom.querySelectorAll<Element>('[id=\"background\"]');\n if (prevBackground) prevBackground.classList.remove(styles.roomViewerTint);\n }\n }\n\n if (room) {\n room.classList.add(styles.roomViewerSelected);\n const [background] = room.querySelectorAll<Element>('[id=\"background\"]');\n (background ?? room).classList.add(styles.roomViewerTint);\n }\n\n return pureRoomId;\n });\n }\n\n function addToCurrentFloor(change: number) {\n setSelectedDataId((prev) => {\n const next = prev + change;\n if (next < 0 || next > data.length - 1) return prev;\n return next;\n });\n }\n\n const svgData = data[selectedDataId]?.data ?? null;\n\n return (\n <div className={styles.roomViewer} ref={roomViewerRef}>\n <h3 className={styles.roomViewerHeader}>{data[selectedDataId]?.label ?? ''}</h3>\n <div\n key={selectedDataId}\n className={cx(styles.roomViewerContainer, isLoading && styles.roomViewerContainerLoading)}\n >\n {svgData}\n </div>\n {data.length > 1 && (\n <div className={styles.roomViewerActions}>\n <FontAwesomeIcon icon={leftIcon} onClick={() => addToCurrentFloor(-1)} />\n <FontAwesomeIcon icon={layerIcon} />\n <FontAwesomeIcon icon={rightIcon} onClick={() => addToCurrentFloor(1)} />\n </div>\n )}\n </div>\n );\n}\n\nexport default RoomViewer;\n",".scrollbarProvider{\n display: contents;\n /* Firefox */\n * {\n scrollbar-width: thin;\n scrollbar-color: var(--background-accent-light) transparent;\n }\n\n /* Chrome, Edge, and Safari */\n *::-webkit-scrollbar {\n width: 12px;\n }\n\n *::-webkit-scrollbar-track {\n background: transparent;\n }\n\n *::-webkit-scrollbar-thumb {\n background-color: var(--background-accent-light);\n border-radius: 10px;\n border: 3px solid transparent;\n background-clip: padding-box;\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport styles from './scrollbarProvider.module.pcss';\n\ninterface Properties {\n className?: string | undefined;\n children?: React.ReactNode | undefined;\n};\n\nfunction ScrollbarProvider({\n className = undefined,\n children = undefined,\n}: Properties): ReactElement {\n return (\n <div className={cx(styles.scrollbarProvider, className)}>\n {children}\n </div>\n );\n}\n\nexport default ScrollbarProvider;\n","import ScrollbarProvider from './scrollbarProvider';\n\nexport default ScrollbarProvider;\n","import type { CSSProperties, ReactNode } from 'react';\nimport { IconDefinition } from '@fortawesome/free-solid-svg-icons';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\nimport type { IconAction } from '../types/actions.types';\n\nexport enum SectionHeaderSize {\n Small = 'small',\n Medium = 'medium',\n Large = 'large',\n}\n\nexport type SectionHeaderAction = IconAction;\n\nexport type SectionHeaderSlots =\n | 'root'\n | 'leading'\n | 'titles'\n | 'title'\n | 'subtitle'\n | 'trailing'\n | 'left'\n | 'center'\n | 'actions';\n\nexport interface SectionHeaderProps extends HtmlProps {\n title?: ReactNode;\n subtitle?: ReactNode;\n icon?: IconDefinition;\n thumbnail?: string | ReactNode;\n left?: ReactNode;\n center?: ReactNode;\n actions?: SectionHeaderAction[] | ReactNode;\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n size?: SectionHeaderSize;\n divider?: boolean;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<SectionHeaderSlots>;\n styles?: SlotStyles<SectionHeaderSlots>;\n}\n",".sectionHeader {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-m, 16px);\n align-items: center;\n color: var(--text-color);\n\n &-leading {\n display: flex;\n justify-content: center;\n align-items: center;\n width: var(--section-header-leading-size);\n height: var(--section-header-leading-size);\n color: var(--primary-color);\n background: var(--background-accent);\n border-radius: var(--default-border-radius);\n overflow: hidden;\n background-size: cover;\n background-position: center;\n flex-shrink: 0;\n font-size: calc(var(--section-header-leading-size) * 0.5);\n }\n\n &-titles {\n display: flex;\n flex-flow: column;\n flex: 0 1 auto;\n gap: 2px;\n min-width: 0;\n }\n\n &-title {\n margin: 0;\n font-size: var(--section-header-title-size);\n font-weight: var(--header-font-weight, 600);\n line-height: 1.2;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n &-subtitle {\n color: var(--text-dark);\n font-weight: 300;\n font-size: var(--section-header-subtitle-size);\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n &-trailing {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-m, 16px);\n flex: 1 1 auto;\n }\n\n &-left {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n &-center {\n display: flex;\n align-items: center;\n min-width: 0;\n }\n\n &-actions {\n display: flex;\n gap: var(--spacing-s, 8px);\n flex-wrap: wrap;\n flex-shrink: 0;\n align-items: center;\n justify-content: flex-end;\n }\n\n &-divider {\n margin-top: var(--spacing-s, 8px);\n }\n\n &-size {\n &-small {\n --section-header-title-size: var(--header-small-font-size, 16px);\n --section-header-subtitle-size: 12px;\n --section-header-leading-size: calc(var(--section-header-title-size) * 2.2);\n }\n\n &-medium {\n --section-header-title-size: var(--header-medium-font-size, 18px);\n --section-header-subtitle-size: 14px;\n --section-header-leading-size: calc(var(--section-header-title-size) * 2.2);\n }\n\n &-large {\n --section-header-title-size: var(--header-font-size, 24px);\n --section-header-subtitle-size: 15px;\n --section-header-leading-size: calc(var(--section-header-title-size) * 2.2);\n }\n }\n}\n\n@media (max-width: 640px) {\n .sectionHeader-center {\n flex: 1 1 100%;\n }\n}\n","import React from 'react';\nimport type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\n\nimport { SectionHeaderSize } from './sectionHeader.types';\nimport type { SectionHeaderProps, SectionHeaderAction } from './sectionHeader.types';\nimport styles from './sectionHeader.module.pcss';\nimport ActionIcon from '../actionIcon';\nimport Divider from '../divider';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_SIZE: Record<SectionHeaderSize, string> = {\n [SectionHeaderSize.Small]: styles.sectionHeaderSizeSmall,\n [SectionHeaderSize.Medium]: styles.sectionHeaderSizeMedium,\n [SectionHeaderSize.Large]: styles.sectionHeaderSizeLarge,\n};\n\nfunction SectionHeader(props: SectionHeaderProps): ReactElement {\n const {\n title,\n subtitle,\n icon,\n thumbnail,\n left,\n center,\n actions,\n level = 2,\n size = SectionHeaderSize.Medium,\n divider = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('SectionHeader', props);\n\n const thumbnailUrl =\n typeof thumbnail === 'string' && thumbnail.startsWith('http') ? thumbnail : undefined;\n const hasThumbnail = thumbnail != null && thumbnail !== '';\n const hasLeading = hasThumbnail || icon != null;\n\n const Heading = `h${level}` as keyof React.JSX.IntrinsicElements;\n\n return (\n <>\n <div\n {...rest}\n className={cx(\n styles.sectionHeader,\n CLASS_BY_SIZE[size],\n className,\n classNames?.root,\n )}\n style={{ ...style, ...slotStyles?.root }}\n >\n {hasLeading && (\n <div\n className={cx(styles.sectionHeaderLeading, classNames?.leading)}\n style={{\n ...(thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}),\n ...slotStyles?.leading,\n }}\n >\n {hasThumbnail\n ? !thumbnailUrl && thumbnail\n : icon && <FontAwesomeIcon icon={icon} />}\n </div>\n )}\n\n <div\n className={cx(styles.sectionHeaderTitles, classNames?.titles)}\n style={slotStyles?.titles}\n >\n <Heading\n className={cx(styles.sectionHeaderTitle, classNames?.title)}\n style={slotStyles?.title}\n >\n {title}\n </Heading>\n {subtitle != null && subtitle !== '' && (\n <div\n className={cx(styles.sectionHeaderSubtitle, classNames?.subtitle)}\n style={slotStyles?.subtitle}\n >\n {subtitle}\n </div>\n )}\n </div>\n\n <div\n className={cx(styles.sectionHeaderTrailing, classNames?.trailing)}\n style={slotStyles?.trailing}\n >\n <div className={cx(styles.sectionHeaderLeft, classNames?.left)} style={slotStyles?.left}>\n {left}\n </div>\n\n <div\n className={cx(styles.sectionHeaderCenter, classNames?.center)}\n style={slotStyles?.center}\n >\n {center}\n </div>\n\n <div\n className={cx(styles.sectionHeaderActions, classNames?.actions)}\n style={slotStyles?.actions}\n >\n {Array.isArray(actions)\n ? (actions as SectionHeaderAction[]).map((action, index) => (\n <ActionIcon\n key={index}\n title={action.title}\n onClick={\n action.onClick\n ? (e: React.MouseEvent<HTMLDivElement>) => {\n e.stopPropagation();\n action.onClick?.(e);\n }\n : undefined\n }\n icon={action.icon}\n />\n ))\n : (actions as React.ReactNode)}\n </div>\n </div>\n </div>\n {divider && <Divider className={styles.sectionHeaderDivider} />}\n </>\n );\n}\n\nexport default SectionHeader;\n","import type { CSSProperties } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum SkeletonVariant {\n Text = 'text',\n Circle = 'circle',\n Rectangular = 'rectangular',\n}\n\nexport enum SkeletonAnimation {\n Shimmer = 'shimmer',\n Pulse = 'pulse',\n None = 'none',\n}\n\nexport type SkeletonSlots = 'line';\n\nexport interface SkeletonProps extends HtmlProps {\n variant?: SkeletonVariant;\n animation?: SkeletonAnimation;\n lines?: number;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<SkeletonSlots>;\n styles?: SlotStyles<SkeletonSlots>;\n}\n",".skeleton {\n display: block;\n background-color: var(--background-accent);\n border-radius: var(--default-border-radius);\n\n &-lines {\n display: flex;\n flex-direction: column;\n gap: 0.5em;\n }\n\n &-line-last {\n width: 60%;\n }\n\n &-text {\n width: 100%;\n height: 1em;\n }\n\n &-circle {\n border-radius: 50%;\n }\n\n &-rectangular {\n border-radius: var(--default-border-radius);\n }\n\n &-animation {\n &-pulse {\n animation: skeletonPulse 1.5s ease-in-out infinite;\n }\n\n &-shimmer {\n background-image: linear-gradient(\n 90deg,\n var(--background-accent) 25%,\n var(--background-accent-light) 50%,\n var(--background-accent) 75%\n );\n background-size: 200% 100%;\n animation: skeletonShimmer 1.5s ease-in-out infinite;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n &-animation-pulse,\n &-animation-shimmer {\n animation: none;\n }\n }\n}\n\n@keyframes skeletonPulse {\n 0%,\n 100% {\n opacity: 1;\n }\n\n 50% {\n opacity: 0.4;\n }\n}\n\n@keyframes skeletonShimmer {\n 0% {\n background-position: 200% 0;\n }\n\n 100% {\n background-position: -200% 0;\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { SkeletonVariant, SkeletonAnimation } from './skeleton.types';\nimport type { SkeletonProps } from './skeleton.types';\nimport styles from './skeleton.module.pcss';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_VARIANT: Record<SkeletonVariant, string> = {\n [SkeletonVariant.Text]: styles.skeletonText,\n [SkeletonVariant.Circle]: styles.skeletonCircle,\n [SkeletonVariant.Rectangular]: styles.skeletonRectangular,\n};\n\nconst CLASS_BY_ANIMATION: Record<SkeletonAnimation, string | undefined> = {\n [SkeletonAnimation.Shimmer]: styles.skeletonAnimationShimmer,\n [SkeletonAnimation.Pulse]: styles.skeletonAnimationPulse,\n [SkeletonAnimation.None]: undefined,\n};\n\nfunction Skeleton(props: SkeletonProps): ReactElement {\n const {\n variant = SkeletonVariant.Text,\n animation = SkeletonAnimation.Shimmer,\n lines = 1,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Skeleton', props);\n const variantClass = CLASS_BY_VARIANT[variant];\n const animationClass = CLASS_BY_ANIMATION[animation];\n\n if (variant !== SkeletonVariant.Text || lines <= 1) {\n return (\n <span\n {...rest}\n className={cx(styles.skeleton, variantClass, animationClass, className)}\n style={style}\n />\n );\n }\n\n return (\n <span {...rest} className={cx(styles.skeletonLines, className)} style={style}>\n {Array.from({ length: lines }, (_, index) => (\n <span\n key={index}\n className={cx(\n styles.skeleton,\n variantClass,\n animationClass,\n index === lines - 1 && styles.skeletonLineLast,\n classNames?.line\n )}\n style={slotStyles?.line}\n />\n ))}\n </span>\n );\n}\n\nexport default Skeleton;\n",".slider {\n /* Theme tokens resolved once, each with a built-in fallback. Set any of the\n public `--slider-*` variables via ThemeProvider or `style` to override. */\n --custom-slider-track-color: var(--slider-track-color, var(--background-accent-light));\n --custom-slider-range-color: var(--slider-range-color, var(--primary-color));\n --custom-slider-thumb-color: var(--slider-thumb-color, var(--primary-color));\n --custom-slider-thumb-size: var(--slider-thumb-size, 18px);\n --custom-slider-track-height: var(--slider-track-height, 6px);\n\n position: relative;\n display: flex;\n align-items: center;\n box-sizing: border-box;\n /* Fill the container, and allow shrinking when used inside a flex row so the\n track never collapses to nothing next to a sibling (e.g. a value readout). */\n width: 100%;\n min-width: 0;\n height: var(--custom-slider-thumb-size);\n padding: 0 calc(var(--custom-slider-thumb-size) / 2);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n touch-action: none;\n user-select: none;\n\n &:focus-visible {\n outline: none;\n }\n &:focus-visible .slider-thumb {\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--custom-slider-range-color) 30%, transparent);\n }\n\n &-disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n /* Reserve room under the track for mark labels. */\n &-has-mark-labels {\n margin-bottom: 22px;\n }\n\n &-track {\n position: relative;\n flex: 1;\n height: var(--custom-slider-track-height);\n background-color: var(--custom-slider-track-color);\n border-radius: 999px;\n }\n\n &-range {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n background-color: var(--custom-slider-range-color);\n border-radius: 999px;\n transition: width 0.12s ease;\n }\n\n &-thumb {\n position: absolute;\n top: 50%;\n width: var(--custom-slider-thumb-size);\n height: var(--custom-slider-thumb-size);\n transform: translate(-50%, -50%);\n background-color: var(--custom-slider-thumb-color);\n border-radius: 50%;\n box-shadow: var(--card-shadow);\n transition: left 0.12s ease, box-shadow 0.15s ease;\n }\n\n /* No lag between pointer and thumb/fill while dragging. */\n &-dragging &-range,\n &-dragging &-thumb {\n transition: box-shadow 0.15s ease;\n }\n\n &-mark {\n position: absolute;\n top: 50%;\n width: 3px;\n height: 3px;\n transform: translate(-50%, -50%);\n border-radius: 50%;\n background-color: var(--background);\n pointer-events: none;\n }\n\n &-mark-label {\n position: absolute;\n top: calc(50% + var(--custom-slider-thumb-size));\n transform: translateX(-50%);\n font-size: var(--text-small-font-size, 12px);\n color: var(--text-dark);\n white-space: nowrap;\n pointer-events: none;\n }\n\n &-value {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n padding: 2px 8px;\n border-radius: var(--default-border-radius);\n background-color: var(--background-accent-light);\n color: var(--text-color);\n font-size: var(--text-small-font-size, 12px);\n white-space: nowrap;\n pointer-events: none;\n font-variant-numeric: tabular-nums;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .slider-range,\n .slider-thumb {\n transition: none;\n }\n}\n","import React, { useEffect, useRef, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport styles from './slider.module.pcss';\nimport type { SliderProps } from './slider.types';\n\n/** Count decimal places in a step so snapped values don't accumulate float error. */\nfunction decimalsOf(step: number): number {\n const s = String(step);\n const dot = s.indexOf('.');\n return dot === -1 ? 0 : s.length - dot - 1;\n}\n\nexport default function Slider({\n value,\n defaultValue,\n onChange,\n onChangeEnd,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n marks,\n showValue = false,\n formatValue,\n size = '18px',\n tabIndex = 0,\n className,\n style,\n classNames,\n styles: slotStyles,\n 'aria-label': ariaLabel,\n ...rest\n}: SliderProps): ReactElement {\n const trackRef = useRef<HTMLDivElement>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const draggingRef = useRef(false);\n const [dragging, setDragging] = useState(false);\n\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<number>(defaultValue ?? min);\n\n const decimals = decimalsOf(step);\n\n function clamp(v: number): number {\n return Math.min(max, Math.max(min, v));\n }\n\n function snap(v: number): number {\n const snapped = Math.round((v - min) / step) * step + min;\n return Number(clamp(snapped).toFixed(decimals));\n }\n\n const current = clamp(isControlled ? (value as number) : internal);\n // Latest committed value, for reading inside pointer handlers without stale\n // closures. Synced after render (never written during render) and optimistically\n // in commit() so a drag burst dedupes before the next render lands.\n const currentRef = useRef(current);\n useEffect(() => {\n currentRef.current = current;\n }, [current]);\n\n const fraction = max > min ? (current - min) / (max - min) : 0;\n const percent = `${fraction * 100}%`;\n\n function commit(next: number, ended: boolean) {\n const snapped = snap(next);\n if (snapped !== currentRef.current) {\n currentRef.current = snapped;\n if (!isControlled) setInternal(snapped);\n onChange?.(snapped);\n }\n if (ended) onChangeEnd?.(snapped);\n }\n\n function valueFromClientX(clientX: number): number {\n const track = trackRef.current;\n if (!track) return currentRef.current;\n const rect = track.getBoundingClientRect();\n const ratio = rect.width ? (clientX - rect.left) / rect.width : 0;\n return min + Math.min(1, Math.max(0, ratio)) * (max - min);\n }\n\n function handlePointerDown(e: React.PointerEvent<HTMLDivElement>) {\n if (disabled) return;\n e.preventDefault();\n rootRef.current?.focus();\n rootRef.current?.setPointerCapture?.(e.pointerId);\n draggingRef.current = true;\n setDragging(true);\n commit(valueFromClientX(e.clientX), false);\n }\n\n function handlePointerMove(e: React.PointerEvent<HTMLDivElement>) {\n if (!draggingRef.current) return;\n commit(valueFromClientX(e.clientX), false);\n }\n\n function handlePointerUp(e: React.PointerEvent<HTMLDivElement>) {\n if (!draggingRef.current) return;\n draggingRef.current = false;\n setDragging(false);\n rootRef.current?.releasePointerCapture?.(e.pointerId);\n onChangeEnd?.(currentRef.current);\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>) {\n if (disabled) return;\n const page = step * 10;\n let next: number | null = null;\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + step;\n break;\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - step;\n break;\n case 'PageUp':\n next = current + page;\n break;\n case 'PageDown':\n next = current - page;\n break;\n case 'Home':\n next = min;\n break;\n case 'End':\n next = max;\n break;\n default:\n return;\n }\n e.preventDefault();\n commit(next, true);\n }\n\n const valueText = formatValue ? formatValue(current) : current;\n const hasMarkLabels = !!marks?.some((m) => m.label != null);\n\n return (\n <div\n {...rest}\n ref={rootRef}\n role=\"slider\"\n aria-label={ariaLabel}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={current}\n aria-valuetext={typeof valueText === 'string' || typeof valueText === 'number' ? String(valueText) : undefined}\n aria-orientation=\"horizontal\"\n aria-disabled={disabled || undefined}\n tabIndex={disabled ? -1 : tabIndex}\n className={cx(\n styles.slider,\n disabled && styles.sliderDisabled,\n dragging && styles.sliderDragging,\n hasMarkLabels && styles.sliderHasMarkLabels,\n className,\n classNames?.root,\n )}\n style={{ '--slider-thumb-size': size, ...style, ...slotStyles?.root } as React.CSSProperties}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onKeyDown={handleKeyDown}\n >\n <div ref={trackRef} className={cx(styles.sliderTrack, classNames?.track)} style={slotStyles?.track}>\n <div\n className={cx(styles.sliderRange, classNames?.range)}\n style={{ width: percent, ...slotStyles?.range }}\n />\n {marks?.map((mark) => {\n const markFraction = max > min ? (clamp(mark.value) - min) / (max - min) : 0;\n const left = `${markFraction * 100}%`;\n return (\n <React.Fragment key={mark.value}>\n <span\n className={cx(styles.sliderMark, classNames?.mark)}\n style={{ left, ...slotStyles?.mark }}\n />\n {mark.label != null && (\n <span\n className={cx(styles.sliderMarkLabel, classNames?.markLabel)}\n style={{ left, ...slotStyles?.markLabel }}\n >\n {mark.label}\n </span>\n )}\n </React.Fragment>\n );\n })}\n <div\n className={cx(styles.sliderThumb, classNames?.thumb)}\n style={{ left: percent, ...slotStyles?.thumb }}\n >\n {showValue && (\n <span className={cx(styles.sliderValue, classNames?.value)} style={slotStyles?.value}>\n {valueText}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n}\n",".stepper {\n /* Theme tokens resolved once, each with a built-in fallback. Set any of the\n public `--stepper-*` variables via ThemeProvider (theme-wide) or `style`\n (per instance) to override; unset ones fall back to the values below. */\n --custom-stepper-marker-size: var(--stepper-marker-size, 40px);\n --custom-stepper-marker-radius: var(--stepper-marker-radius, var(--default-border-radius));\n --custom-stepper-idle-color: var(--stepper-idle-color, var(--primary-lighter));\n --custom-stepper-active-color: var(--stepper-active-color, var(--primary-color));\n --custom-stepper-done-color: var(--stepper-done-color, var(--primary-color));\n --custom-stepper-error-color: var(--stepper-error-color, var(--error-color));\n --custom-stepper-connector-color: var(--stepper-connector-color, var(--primary-color));\n --custom-stepper-connector-thickness: var(--stepper-connector-thickness, 3px);\n --custom-stepper-connector-idle-thickness: var(--stepper-connector-idle-thickness, 1px);\n --custom-stepper-gap: var(--stepper-gap, 12px);\n --custom-stepper-text-on-marker: var(--stepper-text-on-marker, var(--text-on-primary));\n\n user-select: none;\n color: var(--text-color);\n\n &-vertical {\n display: flex;\n flex-flow: column;\n }\n\n &:not(.stepper-vertical) {\n display: flex;\n align-items: center;\n }\n &-label-bottom:not(.stepper-vertical) {\n padding-bottom: 46px;\n }\n &-label-top:not(.stepper-vertical) {\n padding-top: 46px;\n }\n\n /* Entry --------------------------------------------------------------- */\n &-entry {\n display: flex;\n align-items: flex-start;\n gap: var(--custom-stepper-gap);\n box-sizing: border-box;\n }\n &:not(.stepper-vertical) &-entry {\n position: relative;\n flex: 0 0 auto;\n align-items: center;\n gap: 0;\n }\n &-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n &-entry-disabled {\n opacity: 0.5;\n }\n\n &-entry-number {\n width: var(--custom-stepper-marker-size);\n height: var(--custom-stepper-marker-size);\n box-sizing: border-box;\n flex-shrink: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n border: 1px solid var(--custom-stepper-idle-color);\n color: var(--custom-stepper-idle-color);\n border-radius: var(--custom-stepper-marker-radius);\n font-weight: 600;\n font-size: calc(var(--custom-stepper-marker-size) * 0.4);\n box-shadow: inset 0px 0px 0px var(--custom-stepper-done-color);\n transition: all 0.4s;\n }\n &-entry-active &-entry-number {\n border: 2px solid var(--custom-stepper-active-color);\n color: var(--custom-stepper-active-color);\n transform: scale3d(1.1, 1.1, 1);\n }\n &-entry-done &-entry-number {\n border-color: var(--custom-stepper-done-color);\n color: var(--custom-stepper-text-on-marker);\n background-color: var(--custom-stepper-done-color);\n box-shadow: inset 0px 0px 0px 30px var(--custom-stepper-done-color);\n transform: none;\n }\n &-entry-error &-entry-number {\n border: 2px solid var(--custom-stepper-error-color);\n color: var(--custom-stepper-error-color);\n box-shadow: inset 0px 0px 0px var(--custom-stepper-error-color);\n transform: none;\n }\n\n &-checkmark path {\n stroke: var(--custom-stepper-text-on-marker);\n stroke-dasharray: 5;\n stroke-dashoffset: 5;\n animation: showCheckmark 0.4s 0.2s forwards;\n }\n\n &-marker-cell {\n display: flex;\n flex-direction: column;\n align-items: center;\n flex-shrink: 0;\n width: var(--custom-stepper-marker-size);\n }\n &-rail-segment {\n flex: 1 1 0;\n min-height: 0;\n width: var(--custom-stepper-connector-idle-thickness);\n background-size: 100% 200%;\n background-image: linear-gradient(\n 180deg,\n var(--custom-stepper-connector-color) 0 50%,\n var(--custom-stepper-idle-color) 50% 100%\n );\n background-position: 0 100%;\n transition: background-position 0.4s, width 0.4s;\n }\n &-rail-filled {\n width: var(--custom-stepper-connector-thickness);\n background-position: 0 0;\n }\n &-rail-hidden {\n background-image: none;\n background-color: transparent;\n }\n\n &-entry-labels {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n align-self: center;\n }\n &-entry-label {\n color: var(--text-color);\n }\n &-description {\n color: var(--text-dark);\n font-size: var(--text-small-font-size, 0.85em);\n }\n &-optional {\n color: var(--text-light);\n font-size: var(--text-small-font-size, 0.85em);\n font-style: italic;\n }\n\n &:not(.stepper-vertical) &-entry-labels {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n width: max-content;\n max-width: 160px;\n text-align: center;\n align-items: center;\n }\n &-label-bottom:not(.stepper-vertical) &-entry-labels {\n top: calc(var(--custom-stepper-marker-size) + 6px);\n }\n &-label-top:not(.stepper-vertical) &-entry-labels {\n bottom: calc(var(--custom-stepper-marker-size) + 6px);\n }\n\n &-connector {\n flex: 1 1 auto;\n min-width: 24px;\n height: var(--custom-stepper-connector-idle-thickness);\n background-size: 200% 100%;\n background-image: linear-gradient(\n 90deg,\n var(--custom-stepper-connector-color) 0 50%,\n var(--custom-stepper-idle-color) 50% 100%\n );\n background-position: 100% 0;\n transition: background-position 0.6s, height 0.4s, width 0.4s;\n\n &-filled {\n height: var(--custom-stepper-connector-thickness);\n background-position: 0 0;\n }\n }\n\n &-step {\n display: grid;\n grid-template-columns: var(--custom-stepper-marker-size) 1fr;\n column-gap: var(--custom-stepper-gap);\n }\n &-vertical &-entry {\n grid-column: 1 / -1;\n align-items: stretch;\n }\n &-vertical &-connector {\n grid-column: 1;\n justify-self: center;\n flex: none;\n width: var(--custom-stepper-connector-idle-thickness);\n min-width: 0;\n height: 100%;\n min-height: 24px;\n background-size: 100% 200%;\n background-image: linear-gradient(\n 180deg,\n var(--custom-stepper-connector-color) 0 50%,\n var(--custom-stepper-idle-color) 50% 100%\n );\n background-position: 0 100%;\n transition: background-position 0.4s, width 0.4s;\n\n &-filled {\n width: var(--custom-stepper-connector-thickness);\n background-position: 0 0;\n }\n }\n &-vertical &-content {\n grid-column: 2;\n }\n\n &-vertical.stepper-label-left &-step {\n grid-template-columns: 1fr var(--custom-stepper-marker-size);\n }\n &-vertical.stepper-label-left &-entry {\n flex-direction: row-reverse;\n }\n &-vertical.stepper-label-left &-connector {\n grid-column: 2;\n }\n &-vertical.stepper-label-left &-content {\n grid-column: 1;\n text-align: right;\n }\n\n &-content {\n overflow: hidden;\n transition: height 0.25s ease;\n }\n &-content-inner {\n padding: 4px 0 12px;\n }\n\n /* Outlined: completed markers stay ringed (a coloured check, no solid fill) */\n &-outlined {\n --stepper-text-on-marker: var(--custom-stepper-done-color);\n\n & .stepper-entry-done .stepper-entry-number {\n box-shadow: none;\n background-color: transparent;\n color: var(--custom-stepper-done-color);\n }\n }\n &-dots {\n --stepper-marker-size: 16px;\n --stepper-marker-radius: 50%;\n --stepper-gap: 10px;\n\n & .stepper-entry-number {\n font-size: 0;\n border-width: 2px;\n }\n & .stepper-entry-number svg {\n display: none;\n }\n }\n}\n\n@keyframes showCheckmark {\n to {\n stroke-dashoffset: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .stepper-content {\n transition: none;\n }\n .stepper-entry-number,\n .stepper-connector,\n .stepper-rail-segment {\n transition: none;\n }\n .stepper-checkmark path {\n animation: none;\n stroke-dashoffset: 0;\n }\n}\n","import type React from 'react';\nimport type { IconDefinition } from '@fortawesome/fontawesome-svg-core';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Layout direction of the stepper. */\nexport enum StepperAlignment {\n Horizontal = 'horizontal',\n Vertical = 'vertical',\n}\n\n/** Visual preset for the step markers and connectors. */\nexport enum StepperStyleType {\n /** Numbered markers, filled solid on completion (the default look). */\n Default = 'default',\n /** Numbered markers that stay ringed when completed (a coloured check, no solid fill). */\n Outlined = 'outlined',\n /** Minimal dots without numbers, for a compact onboarding or carousel style. */\n Dots = 'dots',\n}\n\n/**\n * Which step bodies (`step.content`) are expanded. Only affects vertical\n * steppers with per-step `content`; ignored otherwise.\n */\nexport enum StepperCollapse {\n /** Every step body stays expanded. */\n None = 'none',\n /** Only the current step's body is expanded (classic vertical wizard). */\n ActiveOnly = 'activeOnly',\n /** Completed (past) step bodies collapse; current and upcoming stay expanded. */\n Completed = 'completed',\n}\n\n/**\n * Where the label block sits relative to the marker. Horizontal steppers use\n * `Top`/`Bottom`; vertical steppers use `Left`/`Right`. An out-of-orientation\n * value falls back to that orientation's default.\n */\nexport enum StepperLabelPlacement {\n Top = 'top',\n Bottom = 'bottom',\n Left = 'left',\n Right = 'right',\n}\n\nexport type StepperSlots =\n | 'root'\n | 'entry'\n | 'entryNumber'\n | 'entryLabel'\n | 'connector'\n | 'description'\n | 'content'\n | 'optional'\n | 'icon';\n\nexport interface StepperStep {\n /** Primary label for the step. */\n label: React.ReactNode;\n /** Secondary line shown under the label. */\n description?: React.ReactNode;\n /** Collapsible body content, rendered under the label (vertical only). */\n content?: React.ReactNode;\n /** FontAwesome icon shown in the marker instead of the step number. */\n icon?: IconDefinition;\n /** Marks the step as errored, recolouring the marker with `--stepper-error-color`. */\n error?: boolean;\n /** `true` renders an \"Optional\" hint; a node renders custom hint text. */\n optional?: boolean | React.ReactNode;\n /** Disables this step: never clickable, dimmed. */\n disabled?: boolean;\n}\n\nexport interface StepperProps extends HtmlProps {\n steps?: StepperStep[];\n currentStep?: number;\n alignment?: StepperAlignment | 'horizontal' | 'vertical';\n onStepClicked?: ((index: number) => void) | null;\n /** Allow clicking any step, not just completed ones. */\n nonLinear?: boolean;\n /** Hide the label text (and description) beneath each step entry. */\n hideLabels?: boolean;\n /** Visual preset for markers and connectors (default `Default`). */\n styleType?: StepperStyleType;\n /** Which step bodies are expanded. Vertical `content` only (default `None`). */\n collapse?: StepperCollapse;\n /** Label position relative to the marker (default: horizontal `Bottom`, vertical `Right`). */\n labelPlacement?: StepperLabelPlacement;\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<StepperSlots>;\n styles?: SlotStyles<StepperSlots>;\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport styles from './stepper.module.pcss';\nimport {\n StepperAlignment,\n StepperCollapse,\n StepperLabelPlacement,\n StepperStyleType,\n type StepperProps,\n type StepperStep,\n} from './stepper.types';\n\nconst STYLE_CLASS: Record<StepperStyleType, string> = {\n [StepperStyleType.Default]: styles.stepperDefault,\n [StepperStyleType.Outlined]: styles.stepperOutlined,\n [StepperStyleType.Dots]: styles.stepperDots,\n};\n\nconst PLACEMENT_CLASS: Record<StepperLabelPlacement, string> = {\n [StepperLabelPlacement.Top]: styles.stepperLabelTop,\n [StepperLabelPlacement.Bottom]: styles.stepperLabelBottom,\n [StepperLabelPlacement.Left]: styles.stepperLabelLeft,\n [StepperLabelPlacement.Right]: styles.stepperLabelRight,\n};\n\nfunction Checkmark() {\n return (\n <svg\n className={styles.stepperCheckmark}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"-0.2 -1.2 3.4 2\"\n height=\"20px\"\n width=\"20px\"\n >\n <path d=\"M 0 0 l 1 1 l 2 -2\" strokeWidth=\"0.4\" fill=\"none\" />\n </svg>\n );\n}\n\nfunction StepBody({\n open,\n className,\n style,\n children,\n}: {\n open: boolean;\n className?: string;\n style?: React.CSSProperties;\n children: React.ReactNode;\n}) {\n const innerRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<number | null>(null);\n\n useEffect(() => {\n const el = innerRef.current;\n if (!el) return;\n const observer = new ResizeObserver(() => setHeight(el.offsetHeight));\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n return (\n <div\n className={cx(styles.stepperContent, className)}\n style={{ ...style, height: open ? (height ?? 'auto') : 0 }}\n aria-hidden={!open}\n >\n <div ref={innerRef} className={styles.stepperContentInner}>\n {children}\n </div>\n </div>\n );\n}\n\nfunction resolvePlacement(\n placement: StepperLabelPlacement | undefined,\n isVertical: boolean,\n): StepperLabelPlacement {\n const verticalValues = [StepperLabelPlacement.Left, StepperLabelPlacement.Right];\n if (isVertical) {\n return placement && verticalValues.includes(placement) ? placement : StepperLabelPlacement.Right;\n }\n return placement && !verticalValues.includes(placement) ? placement : StepperLabelPlacement.Bottom;\n}\n\nexport default function Stepper({\n steps = [],\n currentStep = 0,\n alignment = StepperAlignment.Horizontal,\n onStepClicked = null,\n nonLinear = false,\n hideLabels = false,\n styleType = StepperStyleType.Default,\n collapse = StepperCollapse.None,\n labelPlacement,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: StepperProps) {\n const isVertical = alignment === StepperAlignment.Vertical;\n const placement = resolvePlacement(labelPlacement, isVertical);\n\n return (\n <div\n {...rest}\n className={cx(\n styles.stepper,\n STYLE_CLASS[styleType],\n PLACEMENT_CLASS[placement],\n { [styles.stepperVertical]: isVertical },\n classNames?.root,\n className,\n )}\n style={{ ...slotStyles?.root, ...style }}\n >\n {steps.map((step: StepperStep, index: number) => {\n const isDone = index < currentStep;\n const isActive = index <= currentStep;\n const hasError = !!step.error;\n // nonLinear: every enabled step except the current one is clickable.\n // linear: only completed steps are clickable.\n const isClickable =\n !!onStepClicked && !step.disabled && (nonLinear ? index !== currentStep : isDone);\n\n const entryClassName = cx(\n styles.stepperEntry,\n { [styles.stepperEntryActive]: isActive },\n { [styles.stepperEntryDone]: isDone && !hasError },\n { [styles.stepperEntryError]: hasError },\n { [styles.stepperEntryDisabled]: step.disabled },\n { [styles.stepperClickable]: isClickable },\n classNames?.entry,\n );\n\n const markerContent = step.icon ? (\n <FontAwesomeIcon\n icon={step.icon}\n className={classNames?.icon}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n ) : isDone && !hasError ? (\n <Checkmark />\n ) : (\n index + 1\n );\n\n const marker = (\n <div\n className={cx(\n styles.stepperEntryNumber,\n { [styles.stepperEntryNumberDone]: isDone && !hasError },\n classNames?.entryNumber,\n )}\n style={slotStyles?.entryNumber}\n >\n {markerContent}\n </div>\n );\n\n const optionalNode =\n step.optional === true ? 'Optional' : step.optional !== false ? step.optional : null;\n\n const labels = !hideLabels && (\n <div className={styles.stepperEntryLabels}>\n <div\n className={cx(styles.stepperEntryLabel, classNames?.entryLabel)}\n style={slotStyles?.entryLabel}\n >\n {step.label}\n </div>\n {step.description != null && (\n <div\n className={cx(styles.stepperDescription, classNames?.description)}\n style={slotStyles?.description}\n >\n {step.description}\n </div>\n )}\n {optionalNode != null && (\n <div\n className={cx(styles.stepperOptional, classNames?.optional)}\n style={slotStyles?.optional}\n >\n {optionalNode}\n </div>\n )}\n </div>\n );\n\n const interactiveProps: React.HTMLAttributes<HTMLDivElement> = isClickable\n ? {\n role: 'button',\n tabIndex: 0,\n onClick: () => onStepClicked?.(index),\n onKeyDown: (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onStepClicked?.(index);\n }\n },\n }\n : {};\n\n const wrapHeader = (inner: React.ReactNode) => (\n <div\n className={entryClassName}\n style={slotStyles?.entry}\n aria-current={index === currentStep ? 'step' : undefined}\n aria-invalid={hasError || undefined}\n {...interactiveProps}\n >\n {inner}\n </div>\n );\n\n const connector = index < steps.length - 1 && (\n <div\n className={cx(\n styles.stepperConnector,\n { [styles.stepperConnectorFilled]: isDone },\n classNames?.connector,\n )}\n style={slotStyles?.connector}\n />\n );\n\n if (isVertical) {\n const isFirst = index === 0;\n const isLast = index === steps.length - 1;\n const bodyOpen =\n collapse === StepperCollapse.None\n ? true\n : collapse === StepperCollapse.ActiveOnly\n ? index === currentStep\n : !isDone;\n\n const railSegment = (variant: 'lead' | 'trail') => {\n const hidden = variant === 'lead' ? isFirst : isLast;\n const filled = variant === 'lead' ? isActive : isDone;\n return (\n <div\n className={cx(styles.stepperRailSegment, {\n [styles.stepperRailFilled]: !hidden && filled,\n [styles.stepperRailHidden]: hidden,\n })}\n />\n );\n };\n\n const markerCell = (\n <div className={styles.stepperMarkerCell}>\n {railSegment('lead')}\n {marker}\n {railSegment('trail')}\n </div>\n );\n\n return (\n <div key={index} className={styles.stepperStep}>\n {wrapHeader(\n <>\n {markerCell}\n {labels}\n </>,\n )}\n {connector}\n {step.content != null && !hideLabels && (\n <StepBody open={bodyOpen} className={classNames?.content} style={slotStyles?.content}>\n {step.content}\n </StepBody>\n )}\n </div>\n );\n }\n\n return (\n <React.Fragment key={index}>\n {wrapHeader(\n <>\n {marker}\n {labels}\n </>,\n )}\n {connector}\n </React.Fragment>\n );\n })}\n </div>\n );\n}\n","/**\n * Coordinates every mounted `Sticky` so ones that overlap horizontally stack\n * underneath each other (in DOM order) instead of pinning to the same spot.\n * Non-overlapping ones (e.g. side-by-side halves under a full-width one) land\n * at the same top instead of being pushed down by each other.\n */\n\nexport interface StickyStackMetrics {\n /** Current (unstuck-flow) top of the root element, from getBoundingClientRect. */\n top: number;\n left: number;\n width: number;\n contentHeight: number;\n}\n\nexport interface StickyStackEntry {\n node: HTMLElement;\n offsetTop: number;\n disabled: boolean;\n getMetrics: () => StickyStackMetrics | null;\n}\n\nexport interface StickyStackResult {\n isStuck: boolean;\n /** Effective `top` to pin at while stuck — offsetTop plus the height of any stuck, overlapping entries above it. */\n top: number;\n}\n\ntype ResultListener = (result: StickyStackResult) => void;\n\nfunction rangesOverlap(aLeft: number, aRight: number, bLeft: number, bRight: number): boolean {\n return aLeft < bRight && bLeft < aRight;\n}\n\nfunction compareDomOrder(a: HTMLElement, b: HTMLElement): number {\n if (a === b) return 0;\n const position = a.compareDocumentPosition(b);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;\n if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;\n return 0;\n}\n\nclass StickyStack {\n private entries = new Map<symbol, StickyStackEntry>();\n private listeners = new Map<symbol, ResultListener>();\n private results = new Map<symbol, StickyStackResult>();\n private rafId = 0;\n private listenerCount = 0;\n\n schedule = (): void => {\n cancelAnimationFrame(this.rafId);\n this.rafId = requestAnimationFrame(this.recompute);\n };\n\n register(entry: StickyStackEntry, onChange: ResultListener): symbol {\n const id = Symbol('sticky');\n this.entries.set(id, entry);\n this.listeners.set(id, onChange);\n this.startListening();\n return id;\n }\n\n updateEntry(id: symbol, patch: Partial<Pick<StickyStackEntry, 'offsetTop' | 'disabled'>>): void {\n const entry = this.entries.get(id);\n if (entry) Object.assign(entry, patch);\n }\n\n unregister(id: symbol): void {\n if (!this.entries.has(id)) return;\n this.entries.delete(id);\n this.listeners.delete(id);\n this.results.delete(id);\n this.stopListening();\n }\n\n recompute = (): void => {\n const ordered = [...this.entries.entries()].sort(([, a], [, b]) => compareDomOrder(a.node, b.node));\n const placed: { left: number; right: number; bottom: number }[] = [];\n\n for (const [id, entry] of ordered) {\n const metrics = entry.getMetrics();\n if (!metrics) continue;\n\n const overlapping = placed.filter((p) => rangesOverlap(p.left, p.right, metrics.left, metrics.left + metrics.width));\n const baseTop = overlapping.reduce((max, p) => Math.max(max, p.bottom), entry.offsetTop);\n const isStuck = !entry.disabled && metrics.top <= baseTop;\n const result: StickyStackResult = { isStuck, top: isStuck ? baseTop : entry.offsetTop };\n\n if (isStuck) {\n placed.push({ left: metrics.left, right: metrics.left + metrics.width, bottom: baseTop + metrics.contentHeight });\n }\n\n const prev = this.results.get(id);\n if (!prev || prev.isStuck !== result.isStuck || prev.top !== result.top) {\n this.results.set(id, result);\n this.listeners.get(id)?.(result);\n }\n }\n };\n\n private startListening(): void {\n if (this.listenerCount === 0) {\n window.addEventListener('scroll', this.schedule, { passive: true, capture: true });\n window.addEventListener('resize', this.schedule);\n }\n this.listenerCount++;\n }\n\n private stopListening(): void {\n this.listenerCount--;\n if (this.listenerCount === 0) {\n window.removeEventListener('scroll', this.schedule, { capture: true } as EventListenerOptions);\n window.removeEventListener('resize', this.schedule);\n }\n }\n}\n\nexport const stickyStack = new StickyStack();\n",".sticky {\n display: block;\n\n &-content {\n /* No positioning by default — the content lives in normal flow until it sticks. */\n }\n\n &-content-stuck {\n /* Positioning (position/top/left/width/z-index) is applied inline so it can be measured;\n this class is a styling hook for consumers (e.g. a shadow once stuck). */\n }\n\n &-placeholder {\n /* Reserves the exact space the content left behind, so nothing below jumps up. */\n pointer-events: none;\n }\n}\n","import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport type { StickyProps } from './sticky.types';\nimport { stickyStack } from './stickyStack';\nimport type { StickyStackResult } from './stickyStack';\n\nimport styles from './sticky.module.pcss';\n\ninterface Metrics {\n width: number;\n left: number;\n height: number;\n}\n\nexport default function Sticky({\n children,\n offsetTop = 0,\n zIndex = 20,\n disabled = false,\n onStuckChange,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: StickyProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const stackIdRef = useRef<symbol | null>(null);\n const [metrics, setMetrics] = useState<Metrics>({ width: 0, left: 0, height: 0 });\n const [stackResult, setStackResult] = useState<StickyStackResult>({ isStuck: false, top: offsetTop });\n\n const onStuckChangeRef = useRef(onStuckChange);\n useEffect(() => {\n onStuckChangeRef.current = onStuckChange;\n }, [onStuckChange]);\n\n // Local geometry (width/left/height) doesn't depend on other Stickies — only the\n // effective `top` and `isStuck` (from the stack coordinator) do.\n const measure = useCallback(() => {\n const root = rootRef.current;\n const content = contentRef.current;\n if (!root || !content) return;\n const rootRect = root.getBoundingClientRect();\n setMetrics({ width: root.clientWidth, left: rootRect.left, height: content.offsetHeight });\n stickyStack.schedule();\n }, []);\n\n useLayoutEffect(() => {\n const id = stickyStack.register(\n {\n node: rootRef.current as HTMLElement,\n offsetTop,\n disabled,\n getMetrics: () => {\n const root = rootRef.current;\n const content = contentRef.current;\n if (!root || !content) return null;\n const rect = root.getBoundingClientRect();\n return { top: rect.top, left: rect.left, width: root.clientWidth, contentHeight: content.offsetHeight };\n },\n },\n setStackResult,\n );\n stackIdRef.current = id;\n return () => {\n stickyStack.unregister(id);\n stackIdRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (stackIdRef.current) {\n stickyStack.updateEntry(stackIdRef.current, { offsetTop, disabled });\n }\n stickyStack.schedule();\n }, [offsetTop, disabled]);\n\n useLayoutEffect(() => {\n measure();\n }, [measure, children]);\n\n useEffect(() => {\n const ro = new ResizeObserver(measure);\n if (rootRef.current) ro.observe(rootRef.current);\n if (contentRef.current) ro.observe(contentRef.current);\n return () => ro.disconnect();\n }, [measure]);\n\n const firstRun = useRef(true);\n useEffect(() => {\n if (firstRun.current) {\n firstRun.current = false;\n return;\n }\n onStuckChangeRef.current?.(stackResult.isStuck);\n }, [stackResult.isStuck]);\n\n const contentStyle: React.CSSProperties | undefined = stackResult.isStuck\n ? {\n position: 'fixed',\n top: stackResult.top,\n left: metrics.left,\n width: metrics.width,\n zIndex,\n ...slotStyles?.content,\n }\n : slotStyles?.content;\n\n return (\n <div ref={rootRef} className={cx(styles.sticky, className, classNames?.root)} style={{ ...slotStyles?.root, ...style }} {...rest}>\n {stackResult.isStuck && (\n <div\n aria-hidden\n className={cx(styles.stickyPlaceholder, classNames?.placeholder)}\n style={{ height: metrics.height, ...slotStyles?.placeholder }}\n />\n )}\n <div\n ref={contentRef}\n className={cx(styles.stickyContent, stackResult.isStuck && styles.stickyContentStuck, classNames?.content)}\n style={contentStyle}\n >\n {children}\n </div>\n </div>\n );\n}\n",".switch {\n user-select: none;\n display: flex;\n align-items: center;\n column-gap: 0.625em;\n width: fit-content;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n border: 1px solid transparent;\n margin: -1px;\n\n &:focus-visible {\n outline: none;\n border: 1px solid var(--primary-color);\n border-radius: var(--default-border-radius);\n }\n\n &-disabled {\n filter: brightness(0.8);\n cursor: not-allowed;\n }\n\n &-track {\n width: 2.25em;\n height: 1.25em;\n flex-shrink: 0;\n border-radius: var(--default-border-radius);\n background-color: var(--border-color);\n position: relative;\n transition: background-color 0.2s;\n box-sizing: border-box;\n padding: 0.125em;\n\n &-checked {\n background-color: var(--primary-color);\n }\n }\n\n &-thumb {\n width: 1em;\n height: 1em;\n border-radius: var(--default-border-radius);\n background-color: var(--background);\n box-shadow: var(--card-shadow);\n transform: translateX(0);\n transition: transform 0.2s;\n\n &-checked {\n transform: translateX(1em);\n }\n }\n\n &-label {\n line-height: 100%;\n color: var(--text-color);\n }\n}\n","import { useEffect, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { useComponentDefaults } from '../configProvider';\nimport type { SwitchProps } from './switch.types';\nimport styles from './switch.module.pcss';\n\nfunction Switch(props: SwitchProps): ReactElement {\n const {\n label = '',\n selected = false,\n onToggle = () => {},\n className = '',\n style,\n disabled = false,\n title = '',\n tabIndex = 0,\n formValidator = null,\n children = null,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Switch', props);\n const [, forceUpdate] = useState(0);\n\n useEffect(() => {\n if (!formValidator) return;\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n function handleToggle(event?: React.MouseEvent | React.KeyboardEvent) {\n if (disabled) return;\n if (formValidator) {\n formValidator.set(!formValidator.value);\n }\n onToggle(!currSelected, event);\n }\n\n const currSelected = (formValidator ? formValidator.value : selected) as boolean;\n\n return (\n <div\n {...rest}\n title={title}\n className={cx(\n styles.switch,\n {\n [styles.switchDisabled]: disabled,\n },\n className\n )}\n style={style}\n onClick={handleToggle}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleToggle(e);\n }\n }}\n role=\"switch\"\n aria-checked={currSelected}\n tabIndex={disabled ? -1 : tabIndex}\n >\n <div\n className={cx(styles.switchTrack, currSelected && styles.switchTrackChecked, classNames?.track)}\n style={slotStyles?.track}\n >\n <div\n className={cx(styles.switchThumb, currSelected && styles.switchThumbChecked, classNames?.thumb)}\n style={slotStyles?.thumb}\n />\n </div>\n {(children || label) && (\n <div className={cx(styles.switchLabel, classNames?.label)} style={slotStyles?.label}>\n {children || label}\n </div>\n )}\n </div>\n );\n}\n\nexport default Switch;\n",".tabHeader {\n display: flex;\n align-items: stretch;\n gap: 4px;\n border-bottom: 1px solid var(--border-color);\n user-select: none;\n overflow-x: auto;\n\n &-tab {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n color: var(--text-dark);\n border-bottom: 2px solid transparent;\n border-radius: var(--default-border-radius) var(--default-border-radius) 0 0;\n transition: color 0.2s, background 0.2s, border-color 0.2s;\n white-space: nowrap;\n\n &:hover {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n\n &-active {\n color: var(--primary-color);\n border-bottom-color: var(--primary-color);\n\n &:hover {\n color: var(--primary-color);\n }\n }\n\n &-disabled {\n opacity: 0.5;\n pointer-events: none;\n cursor: default;\n }\n }\n\n &-icon {\n font-size: 18px;\n flex-shrink: 0;\n }\n\n &-labels {\n display: flex;\n flex-direction: column;\n text-align: left;\n line-height: 1.25;\n }\n\n &-title {\n font-weight: var(--header-font-weight, 600);\n font-size: var(--default-font-size);\n }\n\n &-subtitle {\n font-size: var(--text-small-font-size);\n color: var(--text-dark);\n }\n}\n\n@media (max-width: 640px) {\n .tabHeader-tab:not(.tabHeader-tab-active) .tabHeader-labels {\n display: none;\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\n\nimport InteractableDiv from '../interactableDiv';\nimport type { TabHeaderProps, TabHeaderTab } from './tabHeader.types';\n\nimport styles from './tabHeader.module.pcss';\n\nfunction TabHeader({\n tabs = [],\n currentTab,\n onChange,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TabHeaderProps) {\n return (\n <div\n {...rest}\n role=\"tablist\"\n className={cx(styles.tabHeader, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n >\n {tabs.map((tab: TabHeaderTab) => {\n const isActive = tab.id === currentTab;\n const hasLabels = !!tab.title || !!tab.subtitle;\n\n return (\n <InteractableDiv\n key={tab.id}\n role=\"tab\"\n aria-selected={isActive}\n aria-disabled={tab.disabled || undefined}\n tabIndex={tab.disabled ? -1 : 0}\n className={cx(\n styles.tabHeaderTab,\n { [styles.tabHeaderTabActive]: isActive },\n { [styles.tabHeaderTabDisabled]: tab.disabled },\n classNames?.tab\n )}\n style={slotStyles?.tab}\n onClick={() => {\n if (tab.disabled || isActive) return;\n onChange(tab.id);\n }}\n >\n <FontAwesomeIcon\n icon={tab.icon}\n className={cx(styles.tabHeaderIcon, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n {hasLabels && (\n <div className={cx(styles.tabHeaderLabels, classNames?.labels)} style={slotStyles?.labels}>\n {tab.title && (\n <span className={cx(styles.tabHeaderTitle, classNames?.title)} style={slotStyles?.title}>\n {tab.title}\n </span>\n )}\n {tab.subtitle && (\n <span className={cx(styles.tabHeaderSubtitle, classNames?.subtitle)} style={slotStyles?.subtitle}>\n {tab.subtitle}\n </span>\n )}\n </div>\n )}\n </InteractableDiv>\n );\n })}\n </div>\n );\n}\n\nexport default TabHeader;\n","import React from 'react';\nimport Input from 'components/common/input';\nimport { useComponentDefaults } from 'components/common/configProvider';\nimport type { TextareaProps } from './textarea.types';\n\nexport default function Textarea(props: TextareaProps) {\n return <Input {...useComponentDefaults('Textarea', props)} multiline />;\n}\n","import type { Theme } from './theme.types';\n\n/**\n * Built-in default theme used by ThemeProvider when no `themes` prop is\n * supplied. Provides a complete set of CSS variables so the component\n * library renders correctly out of the box.\n */\nexport const defaultTheme: Theme = {\n id: 'default',\n variables: {\n '--grey': '#8A8A8A',\n '--lightgrey': '#e0e0e0',\n '--lightergrey': '#B1B1B1',\n '--white': '#FFFFFF',\n '--red': '#D6002A',\n '--lighter-red': '#ffeae9',\n '--green': '#287626',\n '--lighter-green': '#C4FFC9',\n '--blue': '#5873d5',\n '--lighter-blue': '#C6DBFF',\n '--black': 'black',\n '--orange': '#ff7f50',\n '--lighter-orange': '#ffe5d9',\n\n '--primary-color': '#8184d6',\n '--primary-accent': '#90CAF9',\n '--primary-lighter': '#9a9ce4',\n '--accent-color': 'var(--grey)',\n '--accent-color-light': 'var(--lightgrey)',\n\n '--text-color': 'var(--white)',\n '--text-dark': 'var(--lightergrey)',\n '--text-light': 'var(--lightergrey)',\n '--text-on-primary': 'var(--white)',\n '--text-on-delete': 'var(--white)',\n '--border-color': '#656574',\n\n '--background': '#393945',\n '--background-accent': '#33333c',\n '--background-accent-dark': 'var(--grey)',\n '--background-accent-light': '#484856',\n '--background-modal': '#484856',\n\n '--success-color': 'var(--green)',\n '--success-lighter': 'var(--lighter-green)',\n '--error-color': 'var(--red)',\n '--error-lighter': 'var(--lighter-red)',\n '--required-mark-color': 'var(--error-color)',\n '--info-color': 'var(--blue)',\n '--info-lighter': 'var(--lighter-blue)',\n '--warn-color': 'var(--orange)',\n '--warn-lighter': 'var(--lighter-orange)',\n\n '--default-font-size': '14px',\n '--text-small-font-size': '12px',\n '--header-font-size': '24px',\n '--header-medium-font-size': '18px',\n '--header-small-font-size': '16px',\n\n '--default-font-weight': '400',\n '--header-font-weight': '600',\n\n '--input-background': 'transparent',\n '--input-icon-color': 'var(--text-color)',\n '--error-border-color': 'var(--red)',\n\n '--button-default-color': 'var(--primary-color)',\n '--button-default-border': '1px solid var(--primary-color)',\n\n '--default-border-radius': '8px',\n '--padding-sides': '15px',\n '--margin-top': '10px',\n\n '--default-font': \"'Inter', sans-serif\",\n '--themed-font': \"'Inter', sans-serif\",\n\n '--card-shadow':\n '0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%)',\n\n '--background-card-elevated': 'var(--background-accent-light)',\n '--background-card-outlined': 'transparent',\n '--background-card-filled': 'var(--background-accent)',\n\n '--spacing-s': '4px',\n '--spacing-m': '8px',\n '--spacing-l': '16px',\n },\n};\n",".themeRoot {\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n font-weight: var(--default-font-weight);\n color: var(--text-color);\n}\n\n.colorFade * {\n transition: background 0.3s ease-in-out;\n}\n","import React, { Component } from 'react';\nimport cx from 'classnames';\n\nimport type { Theme } from './theme.types';\nimport { defaultTheme } from './defaultTheme';\nimport styles from './theme.module.pcss';\n\ninterface Props {\n children: React.ReactNode;\n themes?: Theme[];\n currentThemeId?: string;\n}\n\ninterface State {\n resolvedVariables: Record<string, string>;\n colorFadeActive: boolean;\n currentThemeColor: string | null;\n}\n\nclass ThemeProvider extends Component<Props, State> {\n state: State = {\n resolvedVariables: {},\n colorFadeActive: false,\n currentThemeColor: null,\n };\n\n private colorFadeTimeout: ReturnType<typeof setTimeout> | null = null;\n private wrapperRef = React.createRef<HTMLDivElement>();\n private themeColorMeta: HTMLMetaElement | null = null;\n private createdThemeColorMeta = false;\n\n componentDidMount() {\n this.applyTheme(this.props.currentThemeId);\n this.syncThemeColorMeta(this.state.currentThemeColor ?? '');\n }\n\n componentDidUpdate(prevProps: Props, prevState: State) {\n if (prevState.currentThemeColor !== this.state.currentThemeColor) {\n this.syncThemeColorMeta(this.state.currentThemeColor ?? '');\n }\n if (\n prevProps.currentThemeId !== this.props.currentThemeId ||\n prevProps.themes !== this.props.themes\n ) {\n this.applyTheme(this.props.currentThemeId);\n }\n }\n\n componentWillUnmount() {\n if (this.colorFadeTimeout) clearTimeout(this.colorFadeTimeout);\n // Only remove the meta tag if we created it; leave a host-app tag intact.\n // Also clear the cached refs — StrictMode's dev-only mount/unmount/remount\n // cycle reuses this instance, and a stale ref would otherwise point at a\n // detached element on remount instead of re-inserting into <head>.\n if (this.createdThemeColorMeta) {\n this.themeColorMeta?.remove();\n this.themeColorMeta = null;\n this.createdThemeColorMeta = false;\n }\n }\n\n /**\n * Replaces the former react-helmet usage: keep a single\n * <meta name=\"theme-color\"> in sync with the active theme's primary colour.\n * Reuses a tag the host app already declares; otherwise creates its own\n * (and removes it again on unmount).\n */\n private syncThemeColorMeta(color: string) {\n if (typeof document === 'undefined') return;\n\n if (!this.themeColorMeta) {\n const existing = document.head.querySelector<HTMLMetaElement>(\n 'meta[name=\"theme-color\"]',\n );\n if (existing) {\n this.themeColorMeta = existing;\n } else {\n const meta = document.createElement('meta');\n meta.setAttribute('name', 'theme-color');\n document.head.appendChild(meta);\n this.themeColorMeta = meta;\n this.createdThemeColorMeta = true;\n }\n }\n\n this.themeColorMeta.setAttribute('content', color);\n }\n\n /**\n * Resolves the full variable set for a given theme ID by walking up the\n * baseThemeId chain. Returns variables ordered from deepest ancestor to\n * the requested theme so callers can merge in order (later entries win).\n */\n private resolveChain(id: string): Record<string, string>[] {\n const themes = this.props.themes ?? [defaultTheme];\n const theme = themes.find((t) => t.id === id);\n if (!theme) return [];\n\n const parentVars = theme.baseThemeId ? this.resolveChain(theme.baseThemeId) : [];\n\n return [...parentVars, theme.variables as Record<string, string>];\n }\n\n private applyTheme = (currentThemeId: string | undefined) => {\n const themes = this.props.themes ?? [defaultTheme];\n\n // The root theme is the first theme without a baseThemeId.\n // It is always applied as the variable foundation.\n const rootTheme = themes.find((t) => !t.baseThemeId) ?? themes[0];\n const rootVars: Record<string, string> = rootTheme\n ? (rootTheme.variables as Record<string, string>)\n : {};\n\n // Resolve the selected theme's full inheritance chain.\n const selectedTheme = themes.find((t) => t.id === currentThemeId);\n const chainVars = selectedTheme ? this.resolveChain(selectedTheme.id) : [];\n\n // Merge: root foundation → ancestor chain → selected theme (each step overrides)\n const resolvedVariables = Object.assign({}, rootVars, ...chainVars);\n\n this.setState({ resolvedVariables, colorFadeActive: true });\n\n if (this.colorFadeTimeout) clearTimeout(this.colorFadeTimeout);\n this.colorFadeTimeout = setTimeout(() => {\n this.setState({ colorFadeActive: false });\n this.colorFadeTimeout = null;\n }, 500);\n\n // Read --primary-color after the new style is painted for the theme-color meta tag.\n setTimeout(() => {\n if (this.wrapperRef.current) {\n this.setState({\n currentThemeColor: getComputedStyle(this.wrapperRef.current)\n .getPropertyValue('--primary-color')\n .trim(),\n });\n }\n }, 1);\n };\n\n render() {\n const { children } = this.props;\n const { resolvedVariables, colorFadeActive } = this.state;\n\n return (\n <div\n ref={this.wrapperRef}\n id=\"themeProvider\"\n className={cx(styles.themeRoot, colorFadeActive && styles.colorFade)}\n style={resolvedVariables as React.CSSProperties}\n >\n {children}\n </div>\n );\n }\n}\n\nexport default ThemeProvider;\n","import { useState } from \"react\";\n\nexport function useTheme(defaultThemeId: string = 'default') {\n const [currentThemeId, setThemeId] = useState<string>(localStorage.getItem('theme') || defaultThemeId);\n\n const setCurrentThemeId = (themeId: string) => {\n setThemeId(themeId);\n localStorage.setItem('theme', themeId);\n };\n\n return { currentThemeId, setCurrentThemeId };\n}","export interface TimeValue {\n hours: number; // 0–23\n minutes: number; // 0–59\n}\n\nexport const clampHour = (h: number): number => ((Math.trunc(h) % 24) + 24) % 24;\nexport const clampMinute = (m: number): number => ((Math.trunc(m) % 60) + 60) % 60;\n\n/** Parse a \"HH:MM\" (24-hour) string. Returns null for anything that isn't a valid time. */\nexport function parseTimeString(value: string | null | undefined): TimeValue | null {\n if (!value) return null;\n const match = value.match(/^(\\d{1,2}):(\\d{1,2})$/);\n if (!match) return null;\n const hours = Number(match[1]);\n const minutes = Number(match[2]);\n if (hours > 23 || minutes > 59) return null;\n return { hours, minutes };\n}\n\n/** Format a TimeValue as a zero-padded \"HH:MM\" string. */\nexport function formatTime(time: TimeValue | null | undefined): string {\n if (!time) return '';\n const hh = String(clampHour(time.hours)).padStart(2, '0');\n const mm = String(clampMinute(time.minutes)).padStart(2, '0');\n return `${hh}:${mm}`;\n}\n\n/** Snap a minute value to the nearest multiple of `step` (step <= 1 is a no-op). */\nexport function snapMinute(minute: number, step: number): number {\n if (!step || step <= 1) return clampMinute(minute);\n return clampMinute(Math.round(clampMinute(minute) / step) * step);\n}\n\nexport const timeToMinutes = (time: TimeValue): number => time.hours * 60 + time.minutes;\n\n/** Clamp a time into [min, max] (both \"HH:MM\" strings, either optional). */\nexport function clampToRange(time: TimeValue, min?: string | null, max?: string | null): TimeValue {\n let total = timeToMinutes(time);\n const minVal = parseTimeString(min);\n const maxVal = parseTimeString(max);\n if (minVal) total = Math.max(total, timeToMinutes(minVal));\n if (maxVal) total = Math.min(total, timeToMinutes(maxVal));\n return { hours: Math.floor(total / 60), minutes: total % 60 };\n}\n\nexport function isWithinRange(time: TimeValue, min?: string | null, max?: string | null): boolean {\n const total = timeToMinutes(time);\n const minVal = parseTimeString(min);\n const maxVal = parseTimeString(max);\n if (minVal && total < timeToMinutes(minVal)) return false;\n if (maxVal && total > timeToMinutes(maxVal)) return false;\n return true;\n}\n\n/**\n * Auto-correct a masked \"HH:MM\" value as the user types: clamp the hour segment to 23\n * and the minute segment to 59 so the field can never hold an impossible time.\n */\nexport function correctTimeMaskValue(value: string): string {\n const digits = value.replace(/[^\\d]/g, '');\n if (!digits) return value;\n\n let hourDigits = digits.slice(0, 2);\n const minuteDigits = digits.slice(2, 4);\n\n // First hour digit > 2 → it can only be a single-digit hour (e.g. \"9\" → \"09\").\n if (hourDigits.length === 1 && Number(hourDigits) > 2) {\n hourDigits = `0${hourDigits}`;\n }\n if (hourDigits.length === 2 && Number(hourDigits) > 23) hourDigits = '23';\n\n let result = hourDigits;\n if (minuteDigits.length > 0 || /:/.test(value)) result += ':';\n if (minuteDigits.length > 0) {\n const clamped = minuteDigits.length === 2 && Number(minuteDigits) > 59 ? '59' : minuteDigits;\n result += clamped;\n }\n return result;\n}\n\n// ── Clock-dial geometry ─────────────────────────────────────────────────────\n\nexport interface DialPoint {\n x: number;\n y: number;\n}\n\n/**\n * Cartesian coordinates for a point on the dial. `slot` is the step index from the\n * top of the clock, going clockwise; `stepDegrees` is the angle between steps\n * (30° for hours, 6° for minutes). Returns coordinates relative to (cx, cy).\n */\nexport function polarPoint(cx: number, cy: number, radius: number, slot: number, stepDegrees: number): DialPoint {\n const theta = (slot * stepDegrees * Math.PI) / 180;\n return {\n x: cx + radius * Math.sin(theta),\n y: cy - radius * Math.cos(theta),\n };\n}\n\n/** Rotation (deg) of a hand pointing at `slot`. A 3-o'clock-default hand points up at slot 0. */\nexport const handAngle = (slot: number, stepDegrees: number): number => slot * stepDegrees - 90;\n\n/** Angle (0–360, clockwise from top) of a pointer at (dx, dy) relative to the dial centre. */\nexport function pointerAngle(dx: number, dy: number): number {\n const deg = (Math.atan2(dx, -dy) * 180) / Math.PI;\n return (deg + 360) % 360;\n}\n\nexport const pointerRadius = (dx: number, dy: number): number => Math.sqrt(dx * dx + dy * dy);\n",".clockFace {\n position: relative;\n width: var(--clock-size, 256px);\n height: var(--clock-size, 256px);\n margin: 4px auto;\n border-radius: 50%;\n background: var(--background-accent-light, var(--background-accent));\n touch-action: none;\n user-select: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n}\n\n.clockHand {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n overflow: visible;\n\n &-line {\n stroke: var(--primary-color);\n stroke-width: 0.7;\n }\n\n &-center {\n fill: var(--primary-color);\n }\n\n &-knob {\n fill: var(--primary-color);\n }\n}\n\n.clockNumber {\n position: absolute;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n color: var(--text-color);\n font-size: 15px;\n font-weight: 500;\n line-height: 1;\n /* Visual only — the face handles all pointer interaction. */\n pointer-events: none;\n z-index: 1;\n\n &-inner {\n font-size: 12px;\n color: var(--text-dark);\n }\n\n &-selected {\n color: var(--text-on-primary);\n font-weight: 600;\n }\n}\n","import React, { useRef } from 'react';\nimport cx from 'classnames';\nimport {\n type TimeValue,\n clampHour,\n snapMinute,\n polarPoint,\n pointerAngle,\n pointerRadius,\n} from '../../timeFunctions';\nimport type { ClockDialProps, DialNumber } from './clockDial.types';\n\nimport styles from './clockDial.module.pcss';\n\n// viewBox units (0–100). The face scales with its CSS box; geometry stays in this space.\nconst CENTER = 50;\nconst OUTER_RADIUS = 40;\nconst INNER_RADIUS = 25.5;\nconst RING_THRESHOLD = (OUTER_RADIUS + INNER_RADIUS) / 2;\n\nconst HOUR_STEP_DEG = 30;\nconst MINUTE_STEP_DEG = 6;\n\nconst to12 = (hour: number): number => ((hour + 11) % 12) + 1;\n\n/** Build the labelled numbers for the current mode/format. */\nfunction buildNumbers(mode: 'hours' | 'minutes', use24Hour: boolean): DialNumber[] {\n if (mode === 'minutes') {\n return Array.from({ length: 12 }, (_, slot) => {\n const value = slot * 5;\n return { label: String(value).padStart(2, '0'), slot, value, ring: 'outer' as const };\n });\n }\n\n if (!use24Hour) {\n return Array.from({ length: 12 }, (_, slot) => {\n const value = slot === 0 ? 12 : slot; // displayed hour (1–12)\n return { label: String(value), slot, value, ring: 'outer' as const };\n });\n }\n\n // 24-hour double ring: outer 1–12, inner 00/13–23.\n const outer = Array.from({ length: 12 }, (_, slot) => {\n const value = slot === 0 ? 12 : slot;\n return { label: String(value), slot, value, ring: 'outer' as const };\n });\n const inner = Array.from({ length: 12 }, (_, slot) => {\n const value = slot === 0 ? 0 : slot + 12;\n return { label: String(value).padStart(2, '0'), slot, value, ring: 'inner' as const };\n });\n return [...outer, ...inner];\n}\n\nexport default function ClockDial({\n time,\n mode,\n use24Hour,\n minuteStep,\n onChange,\n onCommit,\n classNames,\n styles: slotStyles,\n}: ClockDialProps) {\n const faceRef = useRef<HTMLDivElement>(null);\n const draggingRef = useRef(false);\n\n const numbers = buildNumbers(mode, use24Hour);\n\n // Resolve the active value and the hand geometry for the current time.\n const isPm = time.hours >= 12;\n const selectedHour12 = to12(time.hours);\n\n const hand = (() => {\n if (mode === 'minutes') {\n // 6° per minute → angle = minutes * MINUTE_STEP_DEG.\n return { slot: time.minutes, radius: OUTER_RADIUS };\n }\n if (!use24Hour) {\n return { slot: selectedHour12 % 12, radius: OUTER_RADIUS };\n }\n if (time.hours === 0) return { slot: 0, radius: INNER_RADIUS };\n if (time.hours <= 12) return { slot: time.hours % 12, radius: OUTER_RADIUS };\n return { slot: (time.hours - 12) % 12, radius: INNER_RADIUS };\n })();\n\n const knob = polarPoint(CENTER, CENTER, hand.radius, hand.slot, mode === 'minutes' ? MINUTE_STEP_DEG : HOUR_STEP_DEG);\n\n const isSelected = (n: DialNumber): boolean =>\n mode === 'minutes'\n ? snapMinute(time.minutes, minuteStep) === n.value || time.minutes === n.value\n : use24Hour\n ? time.hours === n.value\n : selectedHour12 === n.value;\n\n const valueFromPointer = (clientX: number, clientY: number): TimeValue => {\n const rect = faceRef.current?.getBoundingClientRect();\n if (!rect) return time;\n const dx = clientX - (rect.left + rect.width / 2);\n const dy = clientY - (rect.top + rect.height / 2);\n const angle = pointerAngle(dx, dy);\n\n if (mode === 'minutes') {\n const minutes = snapMinute(Math.round(angle / MINUTE_STEP_DEG), minuteStep);\n return { hours: time.hours, minutes };\n }\n\n const slot = Math.round(angle / HOUR_STEP_DEG) % 12;\n if (!use24Hour) {\n const display = slot === 0 ? 12 : slot;\n const hours = isPm ? (display % 12) + 12 : display % 12;\n return { hours: clampHour(hours), minutes: time.minutes };\n }\n\n // 24h: inner vs outer ring decided by pointer distance from centre.\n const radiusFrac = (pointerRadius(dx, dy) / (rect.width / 2)) * CENTER;\n const inner = radiusFrac < RING_THRESHOLD;\n const hours = inner ? (slot === 0 ? 0 : slot + 12) : slot === 0 ? 12 : slot;\n return { hours: clampHour(hours), minutes: time.minutes };\n };\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n draggingRef.current = true;\n // setPointerCapture keeps move/up events flowing to the face even when the\n // pointer started on (or drags over) a number. Guarded for jsdom.\n (e.currentTarget as HTMLElement).setPointerCapture?.(e.pointerId);\n onChange(valueFromPointer(e.clientX, e.clientY));\n };\n\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggingRef.current) return;\n onChange(valueFromPointer(e.clientX, e.clientY));\n };\n\n const handlePointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggingRef.current) return;\n draggingRef.current = false;\n onCommit(valueFromPointer(e.clientX, e.clientY));\n };\n\n return (\n <div\n ref={faceRef}\n className={cx(styles.clockFace, classNames?.clockFace)}\n style={slotStyles?.clockFace}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n role=\"slider\"\n aria-label={mode === 'minutes' ? 'Minutes' : 'Hours'}\n aria-valuetext={mode === 'minutes' ? `${time.minutes} minutes` : `${time.hours} hours`}\n >\n <svg className={styles.clockHand} viewBox=\"0 0 100 100\" aria-hidden>\n <circle cx={CENTER} cy={CENTER} r={1.8} className={styles.clockHandCenter} />\n <line x1={CENTER} y1={CENTER} x2={knob.x} y2={knob.y} className={styles.clockHandLine} />\n <circle\n cx={knob.x}\n cy={knob.y}\n r={7}\n className={cx(styles.clockHandKnob, classNames?.clockHand)}\n style={slotStyles?.clockHand as React.CSSProperties}\n />\n </svg>\n\n {numbers.map((n) => {\n const p = polarPoint(CENTER, CENTER, n.ring === 'inner' ? INNER_RADIUS : OUTER_RADIUS, n.slot, HOUR_STEP_DEG);\n const selected = isSelected(n);\n // Purely visual — the face owns all pointer handling so click and drag\n // behave identically whether the pointer lands on a number or between two.\n return (\n <div\n key={`${n.ring}-${n.value}`}\n className={cx(\n styles.clockNumber,\n n.ring === 'inner' && styles.clockNumberInner,\n selected && styles.clockNumberSelected,\n classNames?.clockNumber,\n )}\n style={{ left: `${p.x}%`, top: `${p.y}%`, ...slotStyles?.clockNumber }}\n >\n {n.label}\n </div>\n );\n })}\n </div>\n );\n}\n",".timeInput {\n position: relative;\n width: 100%;\n flex: 1;\n min-width: 105px;\n\n &-clock {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px;\n min-width: 280px;\n }\n\n &-clockHeader {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n margin-bottom: 4px;\n }\n\n &-headerSegment {\n border: none;\n background: var(--background-accent);\n color: var(--text-dark);\n font-size: 32px;\n font-weight: 600;\n line-height: 1;\n padding: 6px 10px;\n border-radius: var(--default-border-radius);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &-active {\n background: var(--primary-color);\n color: var(--text-on-primary);\n }\n }\n\n &-headerColon {\n font-size: 32px;\n font-weight: 600;\n color: var(--text-dark);\n }\n\n &-meridiem {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-left: 8px;\n\n & button {\n border: 1px solid var(--border-color);\n background: var(--background-accent);\n color: var(--text-dark);\n font-size: 12px;\n font-weight: 600;\n padding: 3px 8px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:first-child { border-radius: var(--default-border-radius) var(--default-border-radius) 0 0; }\n &:last-child { border-radius: 0 0 var(--default-border-radius) var(--default-border-radius); }\n }\n\n &-active {\n background: var(--primary-color) !important;\n color: var(--text-on-primary) !important;\n }\n }\n\n &-footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 4px;\n }\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport InputMask, { type BeforeMaskedStateChangeStates, type InputState } from '@mona-health/react-input-mask';\nimport { faClock } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport Input from '../input';\nimport Modal from '../modal';\nimport FloatingMenu from '../floatingMenu';\nimport Button from '../button';\nimport { ButtonStyleType } from '../button/button.types';\nimport Tooltip from '../tooltip';\nimport ClockDial from './components/clockDial';\nimport { Align } from '../floatingMenu/floatingMenu.types';\nimport {\n type TimeValue,\n parseTimeString,\n formatTime,\n snapMinute,\n clampToRange,\n clampHour,\n} from './timeFunctions';\nimport type { TimeInputProps } from './timeInput.types';\n\nimport styles from './timeInput.module.pcss';\n\ntype ClockMode = 'hours' | 'minutes';\n\nexport default function TimeInput({\n value,\n selected,\n onChange = () => null,\n onSelect = () => null,\n formValidator = null,\n isInline = false,\n isModal = false,\n noInput = false,\n noHeader = false,\n showClearButton = false,\n showNowButton = false,\n minuteStep = 1,\n use24Hour = true,\n minTime = null,\n maxTime = null,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n disabled = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimeInputProps) {\n const getExternalString = (): string => {\n if (formValidator) return (formValidator.value as string) || '';\n return value ?? selected ?? '';\n };\n\n const [currentTimeString, setCurrentTimeString] = useState(getExternalString);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [mode, setMode] = useState<ClockMode>('hours');\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const externalString = getExternalString();\n const [prevExternal, setPrevExternal] = useState(externalString);\n const fvRef = useRef(formValidator);\n\n // Sync when the controlled value changes externally.\n if (!formValidator && prevExternal !== externalString) {\n setPrevExternal(externalString);\n setCurrentTimeString(externalString);\n }\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n setCurrentTimeString((formValidator.value as string) || '');\n forceUpdate((n) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean =>\n formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n\n const computedIsRequired = (): boolean =>\n !!(isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'));\n\n /** Push a value out to formValidator/onChange without touching the input string. */\n const emit = (time: TimeValue | null) => {\n const str = time ? formatTime(time) : null;\n if (formValidator) formValidator.set(str);\n onChange?.(str);\n };\n\n const applyTime = (time: TimeValue | null) => {\n setCurrentTimeString(time ? formatTime(time) : '');\n emit(time);\n };\n\n const parsed = parseTimeString(currentTimeString);\n const dialTime: TimeValue = parsed ?? { hours: 12, minutes: 0 };\n\n const handleDialChange = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n applyTime(clampToRange(snapped, minTime, maxTime));\n };\n\n const handleDialCommit = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n const next = clampToRange(snapped, minTime, maxTime);\n applyTime(next);\n if (mode === 'hours') {\n setMode('minutes');\n return;\n }\n onSelect?.(formatTime(next));\n if (!isInline) setIsPickerOpen(false);\n };\n\n const openPicker = () => {\n if (disabled) return;\n setMode('hours');\n setIsPickerOpen(true);\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): InputState => {\n if (!previousState || nextState.value === previousState.value) return nextState;\n let v = nextState.value;\n const hourStr = v.slice(0, 2);\n if (/^\\d\\d$/.test(hourStr) && Number(hourStr) > 23) v = `23${v.slice(2)}`;\n const minStr = v.slice(3, 5);\n if (/^\\d\\d$/.test(minStr) && Number(minStr) > 59) v = `${v.slice(0, 3)}59`;\n return v === nextState.value ? nextState : { ...nextState, value: v };\n };\n\n const handleInputChange = (v: string) => {\n setCurrentTimeString(v);\n const t = parseTimeString(v);\n if (t) emit(t);\n };\n\n const handleBlur = () => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n emit(parseTimeString(currentTimeString));\n };\n\n const setMeridiem = (pm: boolean) => {\n const isPm = dialTime.hours >= 12;\n if (pm === isPm) return;\n applyTime({ hours: clampHour(dialTime.hours + (pm ? 12 : -12)), minutes: dialTime.minutes });\n };\n\n const hasErr = hasError();\n const displayHours = parsed ? String(use24Hour ? parsed.hours : ((parsed.hours + 11) % 12) + 1).padStart(2, '0') : '--';\n const displayMinutes = parsed ? String(parsed.minutes).padStart(2, '0') : '--';\n\n const header = noHeader ? null : (\n <div className={cx(styles.timeInputClockHeader, classNames?.clockHeader)} style={slotStyles?.clockHeader}>\n <button\n type=\"button\"\n className={cx(styles.timeInputHeaderSegment, mode === 'hours' && styles.timeInputHeaderSegmentActive, classNames?.headerSegment)}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('hours')}\n >\n {displayHours}\n </button>\n <span className={styles.timeInputHeaderColon}>:</span>\n <button\n type=\"button\"\n className={cx(styles.timeInputHeaderSegment, mode === 'minutes' && styles.timeInputHeaderSegmentActive, classNames?.headerSegment)}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('minutes')}\n >\n {displayMinutes}\n </button>\n {!use24Hour && (\n <div className={cx(styles.timeInputMeridiem, classNames?.meridiem)} style={slotStyles?.meridiem}>\n <button type=\"button\" className={cx(dialTime.hours < 12 && styles.timeInputMeridiemActive)} onClick={() => setMeridiem(false)}>AM</button>\n <button type=\"button\" className={cx(dialTime.hours >= 12 && styles.timeInputMeridiemActive)} onClick={() => setMeridiem(true)}>PM</button>\n </div>\n )}\n </div>\n );\n\n const footer =\n showClearButton || showNowButton ? (\n <div className={cx(styles.timeInputFooter, classNames?.footer)} style={slotStyles?.footer}>\n {showNowButton && (\n <Button\n styleType={ButtonStyleType.Default}\n onClick={() => {\n const now = new Date();\n handleDialChange({ hours: now.getHours(), minutes: now.getMinutes() });\n }}\n >\n Now\n </Button>\n )}\n {showClearButton && (\n <Button styleType={ButtonStyleType.Default} onClick={() => { applyTime(null); onSelect?.(null); }}>\n Clear\n </Button>\n )}\n </div>\n ) : null;\n\n const pickerContent = (\n <div className={cx(styles.timeInputClock, classNames?.clock)} style={slotStyles?.clock}>\n {header}\n <ClockDial\n time={dialTime}\n mode={mode}\n use24Hour={use24Hour}\n minuteStep={minuteStep}\n onChange={handleDialChange}\n onCommit={handleDialCommit}\n classNames={classNames}\n styles={slotStyles}\n />\n {footer}\n </div>\n );\n\n const input = noInput ? null : (\n <Input\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentTimeString}\n icon={<FontAwesomeIcon icon={faClock} />}\n onIconClick={openPicker}\n onClick={openPicker}\n readOnly={isModal}\n disabled={disabled}\n isValid={!hasErr}\n customInput={<InputMask mask=\"99:99\" maskPlaceholder=\"_\" beforeMaskedStateChange={beforeMaskedStateChange} />}\n onChange={(v) => handleInputChange(v as string)}\n onBlur={handleBlur}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <FloatingMenu\n isOpen={isPickerOpen}\n onOpenChange={setIsPickerOpen}\n content={pickerContent}\n align={Align.Left}\n dontCloseOnChildClick\n >\n {input}\n </FloatingMenu>\n );\n })();\n\n return (\n <div className={cx(styles.timeInput, classNames?.root, className)} style={{ ...slotStyles?.root, ...style }} {...rest}>\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() ?? '' : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n",".container {\n position: fixed;\n z-index: 9999;\n display: flex;\n flex-direction: column;\n gap: 8px;\n pointer-events: none;\n padding: 16px;\n box-sizing: border-box;\n\n &-top-left {\n top: 0;\n left: 0;\n align-items: flex-start;\n }\n\n &-top-center {\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n }\n\n &-top-right {\n top: 0;\n right: 0;\n align-items: flex-end;\n }\n\n &-bottom-left {\n bottom: 0;\n left: 0;\n align-items: flex-start;\n flex-direction: column-reverse;\n }\n\n &-bottom-center {\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n flex-direction: column-reverse;\n }\n\n &-bottom-right {\n bottom: 0;\n right: 0;\n align-items: flex-end;\n flex-direction: column-reverse;\n }\n}\n\n.toast {\n pointer-events: all;\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 14px;\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n color: var(--text-color);\n font-family: var(--default-font);\n box-shadow: var(--card-shadow);\n min-width: 240px;\n max-width: 380px;\n box-sizing: border-box;\n position: relative;\n /* Tells the browser vertical panning is native (so the page can still scroll behind the toast)\n while horizontal movement is left for useSwipeDismiss's own pointer handling to decide. */\n touch-action: pan-y;\n overflow: hidden;\n animation: toastSlideDown 0.25s ease forwards;\n\n &-bottom {\n animation: toastSlideUp 0.25s ease forwards;\n }\n\n &-dismissing {\n animation: toastFadeOut 0.2s ease forwards;\n }\n\n &-paused .toastProgressBar {\n animation-play-state: paused;\n }\n\n &-info {\n border-left: 3px solid var(--info-color, #3b82f6);\n\n .toastIcon {\n color: var(--info-color, #3b82f6);\n }\n }\n\n &-success {\n border-left: 3px solid var(--success-color);\n\n .toastIcon {\n color: var(--success-color);\n }\n }\n\n &-error {\n border-left: 3px solid var(--error-color, #ef4444);\n\n .toastIcon {\n color: var(--error-color, #ef4444);\n }\n }\n\n &-warn {\n border-left: 3px solid var(--warn-color);\n\n .toastIcon {\n color: var(--warn-color);\n }\n }\n\n &-default {\n border-left: 3px solid var(--primary-color);\n\n .toastIcon {\n color: var(--primary-color);\n }\n }\n}\n\n.toastIcon {\n flex-shrink: 0;\n margin-top: 1px;\n font-size: 15px;\n}\n\n.toastContent {\n flex: 1;\n font-size: 14px;\n line-height: 1.4;\n}\n\n.toastCloseButton {\n flex-shrink: 0;\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 0;\n color: var(--text-dark);\n font-size: 13px;\n opacity: 0.6;\n transition: opacity 0.15s;\n margin-top: 1px;\n\n &:hover {\n opacity: 1;\n }\n}\n\n.toastProgressBar {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 3px;\n width: 100%;\n background: currentColor;\n opacity: 0.35;\n transform-origin: left;\n animation: toastShrink var(--toast-duration) linear forwards;\n}\n\n@keyframes toastSlideDown {\n from {\n opacity: 0;\n transform: translateY(-12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastSlideUp {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastFadeOut {\n from {\n opacity: 1;\n transform: scale(1);\n }\n to {\n opacity: 0;\n transform: scale(0.92);\n }\n}\n\n@keyframes toastShrink {\n from {\n transform: scaleX(1);\n }\n to {\n transform: scaleX(0);\n }\n}\n","import { useEffect, useRef, useState } from 'react';\n\nexport interface UseSwipeDismissOptions {\n /** Called once the swipe commits (past the threshold) — after the exit transition finishes,\n * not the instant the pointer is released. */\n onDismiss: () => void;\n /** Which axis the drag tracks (default `'x'`, the natural direction for a toast/notification). */\n axis?: 'x' | 'y';\n /** Distance in px past which releasing counts as a commit, regardless of speed (default `80`). */\n distanceThreshold?: number;\n /** Speed in px/ms past which releasing counts as a commit, regardless of distance (default `0.5`) —\n * lets a fast flick dismiss even if the pointer didn't travel very far. */\n velocityThreshold?: number;\n /** Disables the gesture entirely — no listeners are attached. */\n disabled?: boolean;\n /** Restricts the gesture to coarse (touch) pointers, auto-detected via `matchMedia`. On a\n * mouse/trackpad device a drag is more likely to be a text selection than an intentional\n * dismiss, and other affordances (a close button, auto-dismiss) typically already cover that\n * case. Default `true`; set `false` to allow the gesture on any pointer type. */\n mobileOnly?: boolean;\n}\n\nexport interface UseSwipeDismissResult<T extends HTMLElement> {\n /** Attach to the element that should become draggable. The hook wires up its own pointer\n * listeners on this node directly (no handlers to spread), so this is the only thing to attach. */\n ref: React.RefObject<T | null>;\n /** True for the duration of an active drag — e.g. use it to pause an auto-dismiss timer. */\n isDragging: boolean;\n}\n\nconst EXIT_TRANSITION_MS = 180;\n// Below this many px of movement, direction intent isn't decided yet — lets a vertical scroll\n// gesture that merely starts on the element pass through instead of being hijacked as a swipe.\nconst AXIS_LOCK_THRESHOLD = 10;\n\n/**\n * Drag-to-dismiss on any pointer type (touch, mouse, pen) via the Pointer Events API. Applies the\n * drag offset and a fading opacity directly to the DOM node (bypassing React state) so the visual\n * tracks the pointer at native speed, then either springs back or animates fully off-screen and\n * calls `onDismiss` once that exit transition completes.\n */\nexport function useSwipeDismiss<T extends HTMLElement>({\n onDismiss,\n axis = 'x',\n distanceThreshold = 80,\n velocityThreshold = 0.5,\n disabled = false,\n mobileOnly = true,\n}: UseSwipeDismissOptions): UseSwipeDismissResult<T> {\n const ref = useRef<T>(null);\n const [isDragging, setIsDragging] = useState(false);\n\n const [isCoarsePointer, setIsCoarsePointer] = useState(\n () => typeof window !== 'undefined' && typeof window.matchMedia === 'function' && window.matchMedia('(pointer: coarse)').matches\n );\n useEffect(() => {\n if (typeof window.matchMedia !== 'function') return;\n const mql = window.matchMedia('(pointer: coarse)');\n const onChange = (event: MediaQueryListEvent) => setIsCoarsePointer(event.matches);\n mql.addEventListener('change', onChange);\n return () => mql.removeEventListener('change', onChange);\n }, []);\n\n const effectiveDisabled = disabled || (mobileOnly && !isCoarsePointer);\n\n // Mutable across the life of one drag; doesn't need to trigger re-renders.\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n startTime: number;\n offset: number;\n axisLocked: boolean;\n active: boolean;\n } | null>(null);\n\n const onDismissRef = useRef(onDismiss);\n useEffect(() => {\n onDismissRef.current = onDismiss;\n });\n\n useEffect(() => {\n const el = ref.current;\n if (!el || effectiveDisabled) return;\n\n function applyTransform(offset: number, transition: string) {\n if (!el) return;\n if (transition !== 'none') {\n // Switching straight from the live drag's `transition: none` to an animated one, in the\n // same tick as the transform change, can get coalesced into a single frame with no\n // animation in between — the element just jumps to its end state instead of sliding\n // there. Forcing a layout read first commits the current (pre-transition) position as\n // its own frame, so the transition below actually has something to animate from.\n void el.offsetHeight;\n }\n const translate = axis === 'x' ? `translateX(${offset}px)` : `translateY(${offset}px)`;\n el.style.transition = transition;\n el.style.transform = translate;\n const fade = Math.max(0, 1 - Math.abs(offset) / (distanceThreshold * 2.5));\n el.style.opacity = String(fade);\n }\n\n function onPointerMove(event: PointerEvent) {\n const drag = dragRef.current;\n if (!drag || event.pointerId !== drag.pointerId) return;\n\n const deltaX = event.clientX - drag.startX;\n const deltaY = event.clientY - drag.startY;\n\n if (!drag.axisLocked) {\n const primary = axis === 'x' ? deltaX : deltaY;\n const cross = axis === 'x' ? deltaY : deltaX;\n if (Math.abs(primary) < AXIS_LOCK_THRESHOLD && Math.abs(cross) < AXIS_LOCK_THRESHOLD) return;\n if (Math.abs(cross) > Math.abs(primary)) {\n // The gesture is mostly along the other axis (e.g. a page scroll) — hand it back.\n drag.active = false;\n return;\n }\n drag.axisLocked = true;\n setIsDragging(true);\n }\n\n if (!drag.active) return;\n event.preventDefault();\n drag.offset = axis === 'x' ? deltaX : deltaY;\n applyTransform(drag.offset, 'none');\n }\n\n function finishDrag() {\n const drag = dragRef.current;\n dragRef.current = null;\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', finishDrag);\n window.removeEventListener('pointercancel', finishDrag);\n if (!drag || !drag.active || !drag.axisLocked) {\n setIsDragging(false);\n return;\n }\n\n const elapsed = Math.max(1, Date.now() - drag.startTime);\n const velocity = drag.offset / elapsed;\n const committed =\n Math.abs(drag.offset) >= distanceThreshold || Math.abs(velocity) >= velocityThreshold;\n\n if (committed) {\n const width = el?.getBoundingClientRect().width ?? 0;\n const exitOffset = Math.sign(drag.offset || 1) * (width + 40);\n applyTransform(exitOffset, `transform ${EXIT_TRANSITION_MS}ms ease-out, opacity ${EXIT_TRANSITION_MS}ms ease-out`);\n setTimeout(() => onDismissRef.current(), EXIT_TRANSITION_MS);\n } else {\n applyTransform(0, `transform ${EXIT_TRANSITION_MS}ms ease-out, opacity ${EXIT_TRANSITION_MS}ms ease-out`);\n }\n setIsDragging(false);\n }\n\n function onPointerDown(event: PointerEvent) {\n if (dragRef.current || !el) return;\n // A still-\"forwards\"-filling CSS animation (e.g. the toast's entrance slide) wins the\n // cascade over an inline style.transform, so the drag offset below would silently never\n // show up on screen unless the animation is cleared first.\n el.style.animation = 'none';\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n startTime: Date.now(),\n offset: 0,\n axisLocked: false,\n active: true,\n };\n window.addEventListener('pointermove', onPointerMove, { passive: false });\n window.addEventListener('pointerup', finishDrag);\n window.addEventListener('pointercancel', finishDrag);\n }\n\n el.addEventListener('pointerdown', onPointerDown);\n return () => {\n el.removeEventListener('pointerdown', onPointerDown);\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', finishDrag);\n window.removeEventListener('pointercancel', finishDrag);\n };\n }, [axis, distanceThreshold, velocityThreshold, effectiveDisabled]);\n\n return { ref, isDragging };\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faCircleInfo,\n faCircleCheck,\n faCircleXmark,\n faTriangleExclamation,\n faBell,\n faXmark,\n} from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './toast.module.pcss';\nimport type { ToastItem } from './toast.types';\nimport ActionIcon from '../actionIcon';\nimport { useSwipeDismiss } from '../hooks/useSwipeDismiss';\n\ninterface ToastProps {\n item: ToastItem;\n isBottom: boolean;\n onDismiss: (id: string) => void;\n}\n\nconst typeIcons = {\n info: faCircleInfo,\n success: faCircleCheck,\n error: faCircleXmark,\n warn: faTriangleExclamation,\n default: faBell,\n};\n\nfunction Toast({ item, isBottom, onDismiss }: ToastProps) {\n const { id, content, options, dismissing } = item;\n const { duration, showRemainingTime, showCloseButton, pauseOnHover, type, classNames, styles: slotStyles } = options;\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n\n const [swiped, setSwiped] = useState(false);\n const { ref: swipeRef, isDragging } = useSwipeDismiss<HTMLDivElement>({\n onDismiss: () => {\n setSwiped(true);\n onDismiss(id);\n },\n });\n\n const paused = (pauseOnHover && (hovered || focused)) || isDragging;\n\n // Remaining time is carried across pause/resume cycles so the timer continues\n // where it left off instead of restarting on every hover.\n const remainingRef = useRef(duration);\n\n useEffect(() => {\n if (duration === 0 || paused) return;\n const start = Date.now();\n const timer = setTimeout(() => onDismiss(id), remainingRef.current);\n return () => {\n clearTimeout(timer);\n remainingRef.current -= Date.now() - start;\n };\n }, [id, duration, onDismiss, paused]);\n\n return (\n <div\n ref={swipeRef}\n className={cx(\n styles.toast,\n isBottom ? styles.toastBottom : null,\n styles[`toast-${type}`],\n dismissing && !swiped && styles.toastDismissing,\n paused && styles.toastPaused,\n classNames?.root,\n )}\n style={slotStyles?.root}\n onMouseEnter={pauseOnHover ? () => setHovered(true) : undefined}\n onMouseLeave={pauseOnHover ? () => setHovered(false) : undefined}\n onFocus={pauseOnHover ? () => setFocused(true) : undefined}\n onBlur={pauseOnHover ? () => setFocused(false) : undefined}\n >\n <FontAwesomeIcon\n icon={typeIcons[type]}\n className={cx(styles.toastIcon, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n\n <div className={cx(styles.toastContent, classNames?.content)} style={slotStyles?.content}>\n {content}\n </div>\n\n {showCloseButton && (\n <ActionIcon\n icon={faXmark}\n onClick={() => onDismiss(id)}\n className={cx(styles.toastCloseButton, classNames?.closeButton)}\n style={slotStyles?.closeButton}\n aria-label=\"Close\"\n />\n )}\n\n {showRemainingTime && duration > 0 && (\n <div\n className={cx(styles.toastProgressBar, classNames?.progressBar)}\n style={{ '--toast-duration': `${duration}ms`, ...slotStyles?.progressBar } as React.CSSProperties}\n />\n )}\n </div>\n );\n}\n\nexport default Toast;\n","import type { ReactNode } from 'react';\nimport type { ToastOptions } from './toast.types';\n\ntype ShowToastFn = (content: ReactNode, options?: ToastOptions) => void;\n\nlet _handler: ShowToastFn | null = null;\n\nexport function _registerToastHandler(fn: ShowToastFn): void {\n _handler = fn;\n}\n\nexport function _unregisterToastHandler(): void {\n _handler = null;\n}\n\nexport function showToast(content: ReactNode, options?: ToastOptions): void {\n if (!_handler) {\n console.error('[Toast] No ToastProvider found. Wrap your app with <ToastProvider>.');\n return;\n }\n _handler(content, options);\n}\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './toast.module.pcss';\nimport Toast from './toast';\nimport { _registerToastHandler, _unregisterToastHandler } from './toastService';\nimport type { ToastContextConfig, ToastItem, ToastOptions, ResolvedToastOptions, ToastPosition } from './toast.types';\nimport type { ReactNode } from 'react';\n\nconst DEFAULTS: Required<ToastContextConfig> = {\n position: 'top-right',\n duration: 4000,\n showRemainingTime: true,\n showCloseButton: true,\n allowStacking: true,\n pauseOnHover: true,\n};\n\nconst DISMISS_ANIMATION_MS = 220;\n\nfunction positionToClass(position: ToastPosition): string {\n return styles[`container-${position}`];\n}\n\ninterface ToastProviderProps extends ToastContextConfig {\n children: ReactNode;\n}\n\nfunction ToastProvider({\n children,\n position = DEFAULTS.position,\n duration = DEFAULTS.duration,\n showRemainingTime = DEFAULTS.showRemainingTime,\n showCloseButton = DEFAULTS.showCloseButton,\n allowStacking = DEFAULTS.allowStacking,\n pauseOnHover = DEFAULTS.pauseOnHover,\n}: ToastProviderProps) {\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n const counterRef = useRef(0);\n\n const dismiss = useCallback((id: string) => {\n setToasts((prev) =>\n prev.map((t) => (t.id === id ? { ...t, dismissing: true } : t)),\n );\n setTimeout(() => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, DISMISS_ANIMATION_MS);\n }, []);\n\n const addToast = useCallback(\n (content: ReactNode, options?: ToastOptions) => {\n const resolved: ResolvedToastOptions = {\n position: options?.position ?? position,\n duration: options?.duration ?? duration,\n showRemainingTime: options?.showRemainingTime ?? showRemainingTime,\n showCloseButton: options?.showCloseButton ?? showCloseButton,\n pauseOnHover: options?.pauseOnHover ?? pauseOnHover,\n type: options?.type ?? 'default',\n classNames: options?.classNames,\n styles: options?.styles,\n };\n\n counterRef.current += 1;\n const id = `toast-${counterRef.current}`;\n const newToast: ToastItem = { id, content, options: resolved, dismissing: false };\n\n setToasts((prev) => {\n if (!allowStacking && prev.length > 0) {\n // Mark all existing as dismissing, then replace\n setTimeout(() => {\n setToasts([newToast]);\n }, DISMISS_ANIMATION_MS);\n return prev.map((t) => ({ ...t, dismissing: true }));\n }\n return [...prev, newToast];\n });\n },\n [position, duration, showRemainingTime, showCloseButton, allowStacking, pauseOnHover],\n );\n\n useEffect(() => {\n _registerToastHandler(addToast);\n return () => _unregisterToastHandler();\n }, [addToast]);\n\n // Group toasts by position so per-toast position overrides work correctly\n const byPosition = toasts.reduce<Record<string, ToastItem[]>>((acc, t) => {\n const pos = t.options.position;\n if (!acc[pos]) acc[pos] = [];\n acc[pos].push(t);\n return acc;\n }, {});\n\n return (\n <>\n {children}\n <BodyEnd>\n {Object.entries(byPosition).map(([pos, items]) => (\n <div\n key={pos}\n className={cx(styles.container, positionToClass(pos as typeof position))}\n >\n {items.map((item) => (\n <Toast\n key={item.id}\n item={item}\n isBottom={pos.startsWith('bottom')}\n onDismiss={dismiss}\n />\n ))}\n </div>\n ))}\n </BodyEnd>\n </>\n );\n}\n\nexport default ToastProvider;\nexport type { ToastProviderProps };\n",".virtualList {\n overflow-y: auto;\n box-sizing: border-box;\n color: var(--text-color);\n font-family: var(--default-font);\n /* Disable the browser's own scroll anchoring — the component does its own\n scroll-position correction when row heights change, and the two fighting\n each other causes the thumb to desync while dragging. */\n overflow-anchor: none;\n /* Reserve the scrollbar gutter so rows don't re-wrap (and re-measure) when the\n vertical scrollbar appears/disappears as content grows. */\n scrollbar-gutter: stable;\n /* Establish a stacking context so every z-index inside the list (sticky\n header, toggle popover, drag clone) stays scoped to this component and\n can't paint over outside content like a modal. */\n isolation: isolate;\n\n &-drag-clone {\n box-sizing: border-box;\n contain: layout paint style;\n cursor: grabbing;\n /* It tracks the finger via transform — never animate that. */\n transition: none;\n }\n\n &-header {\n display: grid;\n position: sticky;\n top: 0;\n /* Above focused rows (z-index 1) so a focused row scrolled under the header\n never paints over it; the drag clone (z-index 3) still floats above both. */\n z-index: 2;\n background: var(--background-accent);\n border-bottom: 1px solid var(--border-color);\n box-sizing: border-box;\n\n &-cell {\n padding: 8px 12px;\n font-weight: 600;\n font-size: 13px;\n color: var(--text-dark);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n box-sizing: border-box;\n }\n\n &-toggle {\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 4px 8px;\n color: var(--text-dark);\n display: flex;\n align-items: center;\n border-radius: var(--default-border-radius);\n transition: background 0.15s;\n\n &:hover {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n }\n }\n\n &-toggle {\n &-wrapper {\n position: absolute;\n right: 0;\n top: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n padding: 0 4px;\n }\n\n /* Chrome (background, shadow, radius, positioning) is provided by the\n FloatingMenu container this renders inside — keep only sizing here. */\n &-popover {\n display: flex;\n flex-direction: column;\n min-width: 160px;\n }\n\n &-item {\n padding: 4px 12px;\n white-space: nowrap;\n transition: background 0.1s;\n font-size: 14px;\n\n &:hover {\n background: var(--background-accent-light);\n }\n }\n }\n\n /* Count badge on the column-toggle cog: how many columns the user has hidden.\n Positioned at the cog's upper-right corner; non-interactive. */\n &-column-chip {\n position: absolute;\n top: 0;\n right: 0;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--primary-color);\n color: var(--text-on-primary);\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n border-radius: 8px;\n pointer-events: none;\n }\n\n &-select-cell {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n box-sizing: border-box;\n }\n\n &-body {\n position: relative;\n box-sizing: border-box;\n }\n\n &-row {\n border-bottom: 1px solid var(--border-color);\n box-sizing: border-box;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: background 0.1s;\n /* Isolate each row's layout/style so measuring or restyling one row can't force\n the whole list to re-layout — keeps fast scrolling smooth. */\n contain: layout style;\n\n &-no-divider {\n border-bottom: none;\n }\n\n &:hover {\n background: var(--background-accent-light);\n }\n\n /* Opt out of the hover highlight (e.g. when each row is a Card that handles\n its own hover). Declared before the `-selected` rule below, so a selected\n row's highlight still wins on hover. */\n &-no-hover:hover {\n background: transparent;\n }\n\n &-selected {\n background: var(--primary-lighter);\n\n &:hover {\n background: var(--primary-lighter);\n }\n }\n\n &-draggable {\n cursor: grab;\n /* Stop the mobile long-press from selecting text or showing the callout. */\n user-select: none;\n -webkit-touch-callout: none;\n\n &:active {\n cursor: grabbing;\n }\n }\n\n &-dragging {\n opacity: 0.4;\n }\n\n /* Tree-reorder `inside` drop: the dragged node becomes a child of this row,\n so highlight the whole row instead of drawing a between-rows line. */\n &-drop-inside {\n background: var(--primary-lighter);\n box-shadow: inset 0 0 0 2px var(--primary-color);\n }\n }\n\n /* Tree-reorder `before`/`after` drop line. Positioned inside the (relatively\n positioned absolute) row; `left` is set inline to the target's indent so it\n starts where the dropped content will. */\n &-drop-line {\n position: absolute;\n right: 0;\n height: 2px;\n background: var(--primary-color);\n pointer-events: none;\n z-index: 1;\n\n /* A small knob at the line's start, the usual tree drop-indicator look. */\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 50%;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--primary-color);\n transform: translate(-50%, -50%);\n }\n\n &-before { top: -1px; }\n &-after { bottom: -1px; }\n }\n\n /* While a row is being dragged, suppress hover backgrounds so the pointer\n moving across rows doesn't light up the wrong one, and stop text selection.\n `touch-action: none` stops the touch drag from also scrolling the list\n (only active once the long-press has armed the drag). */\n &-reordering {\n touch-action: none;\n\n .virtualList-row {\n user-select: none;\n\n &:hover {\n background: transparent;\n }\n\n &.virtualList-row-selected:hover {\n background: var(--primary-lighter);\n }\n\n &.virtualList-row-dragging {\n background: transparent;\n }\n }\n }\n\n &-cell {\n padding: 8px 12px;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 14px;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n min-width: 0;\n\n /* `fit` columns are content-sized — keep their cells on a single line so the\n content can't wrap, and so the width measurement reads the true intrinsic\n width. (Other cells are free to wrap for variable-height rows.) */\n &[data-fit-key] {\n white-space: nowrap;\n }\n }\n\n &-loading {\n &-full {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n }\n\n &-indicator {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 8px 0;\n }\n }\n\n &-spinner {\n width: 32px;\n height: 32px;\n }\n}\n","import React, { useRef, useLayoutEffect } from 'react';\nimport cx from 'classnames';\n\nimport styles from './virtualList.module.pcss';\nimport type { TreeDropPosition } from './virtualList.types';\n\nexport interface VirtualRowProps {\n index: number;\n top: number;\n /** Padding applied to the row (already normalised to a CSS string). */\n padding?: string;\n columnTemplate: string | undefined;\n isSelected: boolean;\n showDivider: boolean;\n hover: boolean;\n onClick: () => void;\n observer: ResizeObserver | null;\n ariaRowIndex?: number;\n ariaPosInSet?: number;\n ariaSetSize?: number;\n rowRole: 'row' | 'listitem';\n reorderable?: boolean;\n draggable?: boolean;\n isDragging?: boolean;\n reserveToggleGutter?: boolean;\n onMouseDown?: (e: React.MouseEvent<HTMLDivElement>) => void;\n onDragStart?: (e: React.DragEvent<HTMLDivElement>) => void;\n onDragOver?: (e: React.DragEvent<HTMLDivElement>) => void;\n onDragEnd?: () => void;\n onDrop?: (e: React.DragEvent<HTMLDivElement>) => void;\n onTouchStart?: (e: React.TouchEvent<HTMLDivElement>) => void;\n dropPosition?: TreeDropPosition;\n dropIndentPx?: number;\n dropIndicatorClassName?: string;\n dropIndicatorStyle?: React.CSSProperties;\n rowClassName?: string;\n rowStyle?: React.CSSProperties;\n children: React.ReactNode;\n}\n\n/**\n * A single virtualized row: absolutely positioned at its `top`, optionally a\n * grid (table mode), registering itself with the shared ResizeObserver and\n * carrying all the drag / drop-indicator wiring the parent assigns it.\n */\nfunction VirtualRow({\n index,\n top,\n padding,\n columnTemplate,\n isSelected,\n showDivider,\n hover,\n onClick,\n observer,\n ariaRowIndex,\n ariaPosInSet,\n ariaSetSize,\n rowRole,\n reorderable,\n draggable,\n isDragging,\n reserveToggleGutter,\n onMouseDown,\n onDragStart,\n onDragOver,\n onDragEnd,\n onDrop,\n onTouchStart,\n dropPosition,\n dropIndentPx,\n dropIndicatorClassName,\n dropIndicatorStyle,\n rowClassName,\n rowStyle,\n children,\n}: VirtualRowProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n // A single observer is shared across all rows (created by the parent); each\n // row just registers/unregisters its element. The parent reads the row index\n // back from the `data-index` attribute when the observer fires.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || !observer) return;\n observer.observe(el);\n return () => observer.unobserve(el);\n }, [observer]);\n\n return (\n <div\n ref={ref}\n data-index={index}\n className={cx(\n styles.virtualListRow,\n isSelected && styles.virtualListRowSelected,\n !showDivider && styles.virtualListRowNoDivider,\n !hover && styles.virtualListRowNoHover,\n reorderable && styles.virtualListRowDraggable,\n isDragging && styles.virtualListRowDragging,\n dropPosition === 'inside' && styles.virtualListRowDropInside,\n rowClassName,\n )}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n transform: `translateY(${top}px)`,\n ...(padding != null ? { padding } : {}),\n ...(columnTemplate ? { display: 'grid', gridTemplateColumns: columnTemplate } : {}),\n // Match the header's reserved gutter for the column-toggle cog so row\n // cells line up with their header cells instead of drifting under it.\n // Applied after `padding` so the alignment gutter always wins on the right.\n ...(reserveToggleGutter ? { paddingRight: 32 } : {}),\n ...rowStyle,\n }}\n onClick={onClick}\n draggable={draggable}\n onMouseDown={onMouseDown}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDrop={onDrop ?? (draggable ? (e) => e.preventDefault() : undefined)}\n onTouchStart={onTouchStart}\n onContextMenu={draggable ? (e) => e.preventDefault() : undefined}\n aria-selected={isSelected}\n aria-rowindex={ariaRowIndex}\n aria-posinset={ariaPosInSet}\n aria-setsize={ariaSetSize}\n role={rowRole}\n >\n {(dropPosition === 'before' || dropPosition === 'after') && (\n <div\n data-drop-line={dropPosition}\n aria-hidden\n className={cx(\n styles.virtualListDropLine,\n dropPosition === 'before' ? styles.virtualListDropLineBefore : styles.virtualListDropLineAfter,\n dropIndicatorClassName,\n )}\n style={{ left: dropIndentPx ?? 0, ...dropIndicatorStyle }}\n />\n )}\n {children}\n </div>\n );\n}\n\nexport default VirtualRow;\n","import type { ColumnWidthSpec, VirtualListColumn } from './virtualList.types';\n\n// ─── Layout / windowing math ──────────────────────────────────────────────────\n\nexport function buildOffsets(\n keys: (string | number)[],\n heightsMap: Map<string | number, number>,\n estimatedRowHeight: number,\n rowGap = 0,\n): { offsets: number[]; totalHeight: number } {\n const itemCount = keys.length;\n const offsets = new Array<number>(itemCount + 1);\n offsets[0] = 0;\n for (let i = 0; i < itemCount; i++) {\n const gap = i < itemCount - 1 ? rowGap : 0;\n // Heights are cached by item key, not index, so a measured row keeps its\n // height across reorders/filters instead of inheriting its neighbour's.\n offsets[i + 1] = offsets[i] + (heightsMap.get(keys[i]) ?? estimatedRowHeight) + gap;\n }\n return { offsets, totalHeight: offsets[itemCount] };\n}\n\n/** Index of the row that sits at `scrollTop` — i.e. the first row whose bottom edge is below it. */\nexport function findStartIndex(offsets: number[], scrollTop: number, itemCount: number): number {\n if (itemCount <= 0) return 0;\n let lo = 0;\n let hi = itemCount - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (offsets[mid + 1] <= scrollTop) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\nexport function getVisibleRange(\n offsets: number[],\n scrollTop: number,\n containerHeight: number,\n overscan: number,\n itemCount: number,\n): { startIndex: number; endIndex: number } {\n if (itemCount === 0) return { startIndex: 0, endIndex: -1 };\n\n const lo = findStartIndex(offsets, scrollTop, itemCount);\n\n let end = lo;\n while (end < itemCount && offsets[end] < scrollTop + containerHeight) end++;\n\n return {\n startIndex: Math.max(0, lo - overscan),\n endIndex: Math.min(itemCount - 1, end + overscan - 1),\n };\n}\n\n// ─── Reorder / tree-drop math ─────────────────────────────────────────────────\n\n/**\n * Decides where a dragged row should move to, applying midpoint hysteresis: a\n * move only happens once the pointer has crossed the centre of the row it is\n * over (downwards when moving down, upwards when moving up). Returns the target\n * index, or null if no move should occur. Pure for easy unit testing.\n */\nexport function resolveReorderTarget(\n fromIndex: number,\n overIndex: number,\n pointerY: number,\n rowTop: number,\n rowHeight: number,\n): number | null {\n if (fromIndex === -1 || fromIndex === overIndex) return null;\n const midpoint = rowTop + rowHeight / 2;\n const movingDown = overIndex > fromIndex;\n if (movingDown ? pointerY >= midpoint : pointerY <= midpoint) return overIndex;\n return null;\n}\n\n/**\n * Decides where a tree-reorder drop should land relative to the row under the\n * pointer. Group rows expose three zones (top third → `before`, middle →\n * `inside`, bottom third → `after`); leaf rows split in half (`before`/`after`)\n * since they can't receive children. Pure for easy unit testing.\n */\nexport function resolveTreeDropTarget(\n pointerY: number,\n rowTop: number,\n rowHeight: number,\n isGroup: boolean,\n): 'before' | 'inside' | 'after' {\n if (rowHeight <= 0) return 'before';\n const rel = (pointerY - rowTop) / rowHeight;\n if (isGroup) {\n if (rel < 1 / 3) return 'before';\n if (rel > 2 / 3) return 'after';\n return 'inside';\n }\n return rel < 0.5 ? 'before' : 'after';\n}\n\n/**\n * Index of the last descendant of the node at `index` in a depth-tagged flat\n * list (a contiguous run of following rows with a greater depth). Returns\n * `index` itself when the node has no children. A drop is forbidden anywhere in\n * `[index, lastDescendantIndex]` — that's the node and its own subtree.\n */\nexport function lastDescendantIndex(index: number, depths: number[]): number {\n const d = depths[index];\n let i = index + 1;\n while (i < depths.length && depths[i] > d) i++;\n return i - 1;\n}\n\n// ─── Column template ──────────────────────────────────────────────────────────\n\nexport function buildColumnTemplate(\n columns: { key: string; width: ColumnWidthSpec }[],\n fitWidths?: Record<string, number>,\n): string {\n if (columns.length === 0) return '1fr';\n return columns\n .map((col) => {\n switch (col.width.type) {\n case 'fixed': return `${col.width.px}px`;\n case 'flex': return `${col.width.weight ?? 1}fr`;\n // A `fit` track is content-sized, so it resolves independently in each\n // grid (the header and every row are separate grids) and would drift\n // out of alignment. Once we've measured the column's natural width\n // across all those grids, pin it to that exact px so every grid uses an\n // identical track. Until then, fall back to content-sizing.\n case 'fit': {\n const w = fitWidths?.[col.key];\n return w != null ? `${w}px` : 'fit-content(100%)';\n }\n }\n })\n .join(' ');\n}\n\n// ─── Column-visibility persistence ────────────────────────────────────────────\n\nexport const COLUMN_STORAGE_PREFIX = 'ahroweui:virtuallist:columns:';\n\n// We persist both the visible keys and the full set of columns that existed at\n// save time. That lets us tell \"the user hid this column\" from \"this column\n// didn't exist yet\" when columns are added later — the former stays hidden, the\n// latter falls back to its defaultHidden value.\nexport interface PersistedColumns {\n visible: string[];\n known: string[];\n}\n\nexport function loadPersistedColumns(persistKey: string | undefined): PersistedColumns | null {\n if (!persistKey || typeof window === 'undefined') return null;\n try {\n const raw = window.localStorage.getItem(COLUMN_STORAGE_PREFIX + persistKey);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (parsed && Array.isArray(parsed.visible) && Array.isArray(parsed.known)) {\n return {\n visible: parsed.visible.filter((k: unknown): k is string => typeof k === 'string'),\n known: parsed.known.filter((k: unknown): k is string => typeof k === 'string'),\n };\n }\n } catch {\n // Corrupt/unavailable storage — fall back to defaults.\n }\n return null;\n}\n\n/** Whether a column should start visible, honouring saved settings then `defaultHidden`. */\nexport function isColumnInitiallyVisible<T>(col: VirtualListColumn<T>, persisted: PersistedColumns | null): boolean {\n // A locked column is always visible and can't be hidden — ignore saved state.\n if (col.lockVisible) return true;\n if (persisted && persisted.known.includes(col.key)) return persisted.visible.includes(col.key);\n return !col.defaultHidden;\n}\n","import React, { useState, useRef, useEffect, useLayoutEffect, useMemo, useCallback } from 'react';\n\nimport { buildOffsets, findStartIndex, getVisibleRange } from './virtualList.utils';\nimport type { VirtualListHandle, VirtualListScrollOptions } from './virtualList.types';\n\n/**\n * Resolve a `rowGap` value to pixels for the offset math. Numbers and plain\n * `px`/numeric strings parse directly (no DOM, SSR/test-safe); any other CSS\n * length (`em`, `rem`, `%`, `var(...)`) is resolved via a hidden probe appended\n * to `contextEl` so it inherits the list's font-size and custom properties.\n */\nfunction resolveCssLength(value: number | string, contextEl: HTMLElement | null): number {\n if (typeof value === 'number') return value;\n const trimmed = value.trim();\n if (trimmed === '') return 0;\n const asNumber = Number(trimmed);\n if (!Number.isNaN(asNumber)) return asNumber; // \"8\" → 8\n const pxMatch = /^(-?\\d*\\.?\\d+)px$/.exec(trimmed);\n if (pxMatch) return parseFloat(pxMatch[1]); // \"8px\" → 8\n if (typeof document === 'undefined' || !contextEl) return 0;\n const probe = document.createElement('div');\n probe.style.cssText = `position:absolute;visibility:hidden;height:${trimmed};`;\n contextEl.appendChild(probe);\n const px = probe.getBoundingClientRect().height;\n contextEl.removeChild(probe);\n return Number.isFinite(px) ? px : 0;\n}\n\ninterface UseVirtualWindowArgs<T> {\n items: T[];\n /** Stable key per row (already derived by the caller). */\n keys: (string | number)[];\n getItemKey?: (item: T, index: number) => string | number;\n estimatedRowHeight: number;\n rowGap: number | string;\n overscan: number;\n onLoadMore?: () => Promise<void>;\n loadMoreThreshold: number;\n}\n\ninterface UseVirtualWindowResult {\n rootRef: React.RefObject<HTMLDivElement | null>;\n headerRef: React.RefObject<HTMLDivElement | null>;\n /** Shared by every row to measure its height (read back via `data-index`). */\n rowObserver: ResizeObserver | null;\n /** Latest index → key mapping, for async consumers (e.g. the drag hook). */\n keysRef: React.RefObject<(string | number)[]>;\n offsets: number[];\n totalHeight: number;\n containerHeight: number;\n containerWidth: number;\n startIndex: number;\n endIndex: number;\n handleScroll: (e: React.UIEvent<HTMLDivElement>) => void;\n showLoadMoreSpinner: boolean;\n /** The scroll-related imperative methods, for the component to compose into\n * the forwarded handle alongside column controls. */\n scrollApi: Omit<VirtualListHandle, 'recalculateColumns'>;\n}\n\n/**\n * The generic virtualization engine: viewport measurement, per-row height\n * caching, offset/visible-range computation, scroll coalescing, scroll\n * anchoring on height changes, infinite-load triggering, and the imperative\n * scroll handle. Mode-agnostic — knows nothing about columns, selection or\n * dragging.\n */\nexport function useVirtualWindow<T>({\n items,\n keys,\n getItemKey,\n estimatedRowHeight,\n rowGap,\n overscan,\n onLoadMore,\n loadMoreThreshold,\n}: UseVirtualWindowArgs<T>): UseVirtualWindowResult {\n const [scrollTop, setScrollTop] = useState(0);\n const [containerHeight, setContainerHeight] = useState(0);\n const [containerWidth, setContainerWidth] = useState(0);\n // rowGap may be any CSS length; resolve it to px for the offset math. Seed with\n // the synchronous fast path (number / px), then refine before paint for units\n // that need the DOM (em/rem/%/var).\n const [resolvedRowGap, setResolvedRowGap] = useState<number>(() => resolveCssLength(rowGap, null));\n const [heightsMap, setHeightsMap] = useState<Map<string | number, number>>(new Map());\n const [showLoadMoreSpinner, setShowLoadMoreSpinner] = useState(false);\n const isLoadingMoreRef = useRef(false);\n\n const rootRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n const prevOffsetsRef = useRef<number[]>([]);\n const scrollRafRef = useRef<number | null>(null);\n const pendingScrollTopRef = useRef(0);\n const keysRef = useRef<(string | number)[]>([]);\n\n // One ResizeObserver shared by every row, created once via a lazy state\n // initializer so rows mounting in the same commit can register in their\n // layout effect. Batching all entries into a single setState avoids a\n // re-render per row when many rows enter the viewport at once (the main\n // source of scroll jank). The row index is read back from `data-index`.\n const [rowObserver] = useState<ResizeObserver | null>(() => {\n if (typeof ResizeObserver === 'undefined') return null;\n return new ResizeObserver((entries) => {\n setHeightsMap((prev) => {\n let next: Map<string | number, number> | null = null;\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const idx = Number(el.dataset.index);\n if (Number.isNaN(idx)) continue;\n // Resolve the row's stable key so the cache survives reorders/filters.\n const key = keysRef.current[idx];\n if (key === undefined) continue;\n // Prefer the size the observer already computed — reading offsetHeight\n // here would force a synchronous reflow on every measurement batch.\n const box = entry.borderBoxSize?.[0];\n const h = box ? Math.round(box.blockSize) : el.offsetHeight;\n if (prev.get(key) === h) continue;\n if (!next) next = new Map(prev);\n next.set(key, h);\n }\n return next ?? prev;\n });\n });\n });\n useEffect(() => () => rowObserver?.disconnect(), [rowObserver]);\n\n useLayoutEffect(() => {\n const el = rootRef.current;\n if (!el) return;\n // Measure synchronously before the first paint so the initial render fills\n // the viewport, instead of painting a few overscan rows and re-rendering.\n setContainerHeight(el.clientHeight);\n setContainerWidth(el.clientWidth);\n // Track width too: `fit` columns are measured against this box and capped at\n // its width, so when the container settles to its real width after a route\n // transition / async layout, that change has to re-trigger the measure —\n // otherwise an early measure against a 0/tiny width gets pinned and sticks.\n const observer = new ResizeObserver(() => {\n setContainerHeight(el.clientHeight);\n setContainerWidth(el.clientWidth);\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {\n const el = e.currentTarget;\n // Coalesce scroll-driven re-renders to at most one per animation frame.\n // Scroll events can fire several times per frame (especially while dragging\n // the scrollbar thumb); rendering the visible window once per frame keeps\n // the content in step with the cursor instead of lagging behind.\n pendingScrollTopRef.current = el.scrollTop;\n if (scrollRafRef.current == null) {\n scrollRafRef.current = requestAnimationFrame(() => {\n scrollRafRef.current = null;\n setScrollTop(pendingScrollTopRef.current);\n });\n }\n\n if (onLoadMore && !isLoadingMoreRef.current) {\n if (el.scrollTop + el.clientHeight >= el.scrollHeight - loadMoreThreshold) {\n isLoadingMoreRef.current = true;\n setShowLoadMoreSpinner(true);\n onLoadMore().finally(() => {\n isLoadingMoreRef.current = false;\n setShowLoadMoreSpinner(false);\n });\n }\n }\n }, [onLoadMore, loadMoreThreshold]);\n\n useEffect(() => () => {\n if (scrollRafRef.current != null) cancelAnimationFrame(scrollRafRef.current);\n }, []);\n\n useLayoutEffect(() => {\n keysRef.current = keys;\n });\n\n // Resolve the gap to px before paint, re-running when the value or the\n // container's layout changes (a theme/font change that alters em/var is caught\n // by the container ResizeObserver feeding containerWidth/Height).\n useLayoutEffect(() => {\n const px = resolveCssLength(rowGap, rootRef.current);\n setResolvedRowGap((prev) => (prev === px ? prev : px));\n }, [rowGap, containerWidth, containerHeight]);\n\n const { offsets, totalHeight } = useMemo(\n () => buildOffsets(keys, heightsMap, estimatedRowHeight, resolvedRowGap),\n [keys, heightsMap, estimatedRowHeight, resolvedRowGap],\n );\n\n useLayoutEffect(() => {\n const el = rootRef.current;\n const prevOffsets = prevOffsetsRef.current;\n prevOffsetsRef.current = offsets;\n\n // Nothing to anchor against on the first pass or when pinned at the top.\n if (!el || prevOffsets.length === 0) return;\n const curScrollTop = el.scrollTop;\n if (curScrollTop <= 0) return;\n\n // Scroll anchoring: pin the row at the top of the viewport. Find it under\n // the *previous* offsets, then re-derive scrollTop from its *new* offset so\n // it stays visually fixed when rows above it are measured or resized. This\n // is more robust than summing per-row height deltas — it can't drift, and\n // one correction covers any number of simultaneous changes above the fold.\n const prevCount = prevOffsets.length - 1;\n const anchor = findStartIndex(prevOffsets, curScrollTop, prevCount);\n if (anchor >= items.length) return;\n const within = curScrollTop - prevOffsets[anchor];\n const target = offsets[anchor] + within;\n if (Math.abs(target - curScrollTop) > 0.5) {\n el.scrollTop = target;\n pendingScrollTopRef.current = target;\n setScrollTop(target);\n }\n }, [offsets, items.length]);\n\n const scrollApi = useMemo<Omit<VirtualListHandle, 'recalculateColumns'>>(() => {\n function scrollToOffset(top: number, behavior?: ScrollBehavior) {\n const el = rootRef.current;\n if (!el) return;\n const clamped = Math.max(0, top);\n if (typeof el.scrollTo === 'function') el.scrollTo({ top: clamped, behavior: behavior ?? 'auto' });\n else el.scrollTop = clamped;\n }\n function scrollToIndex(index: number, options?: VirtualListScrollOptions) {\n const el = rootRef.current;\n if (!el || items.length === 0) return;\n const i = Math.max(0, Math.min(index, items.length - 1));\n const rowTop = offsets[i] ?? 0;\n const rowHeight = (offsets[i + 1] ?? rowTop) - rowTop;\n // The sticky header overlaps the top of the scroll area, so the usable\n // viewport starts below it — account for that when aligning.\n const headerH = headerRef.current?.offsetHeight ?? 0;\n const usable = Math.max(0, el.clientHeight - headerH);\n const align = options?.align ?? 'start';\n let top = rowTop - headerH;\n if (align === 'center') top -= (usable - rowHeight) / 2;\n else if (align === 'end') top -= usable - rowHeight;\n scrollToOffset(top, options?.behavior);\n }\n return {\n scrollToIndex,\n scrollToKey(key, options) {\n const i = items.findIndex((item, idx) => (getItemKey ? getItemKey(item, idx) : idx) === key);\n if (i >= 0) scrollToIndex(i, options);\n },\n scrollToTop(options) {\n scrollToOffset(0, options?.behavior);\n },\n getScrollElement: () => rootRef.current,\n };\n }, [items, offsets, getItemKey]);\n\n const { startIndex, endIndex } = useMemo(\n () => getVisibleRange(offsets, scrollTop, containerHeight, overscan, items.length),\n [offsets, scrollTop, containerHeight, overscan, items.length],\n );\n\n return {\n rootRef,\n headerRef,\n rowObserver,\n keysRef,\n offsets,\n totalHeight,\n containerHeight,\n containerWidth,\n startIndex,\n endIndex,\n handleScroll,\n showLoadMoreSpinner,\n scrollApi,\n };\n}\n","import { useState, useMemo } from 'react';\n\ninterface UseSelectionArgs<T> {\n items: T[];\n getKey: (item: T, index: number) => string | number;\n multiSelect: boolean;\n /** Controlled selected keys. When provided, internal state is ignored. */\n selectedKeys?: Set<string | number>;\n onSelectionChange?: (keys: Set<string | number>) => void;\n}\n\ninterface UseSelectionResult {\n effectiveSelectedKeys: Set<string | number>;\n /** Toggle one row's membership in the selection. */\n handleRowSelect: (key: string | number) => void;\n /** Select all rows, or clear if all are already selected. */\n handleSelectAll: () => void;\n allSelected: boolean;\n someSelected: boolean;\n}\n\n/**\n * Multi-row selection, controlled or uncontrolled. `allSelected`/`someSelected`\n * (for the header checkbox) are O(n) scans, so they're only computed when\n * `multiSelect` is on.\n */\nexport function useSelection<T>({\n items,\n getKey,\n multiSelect,\n selectedKeys,\n onSelectionChange,\n}: UseSelectionArgs<T>): UseSelectionResult {\n const isControlled = selectedKeys !== undefined;\n const [internalSelectedKeys, setInternalSelectedKeys] = useState<Set<string | number>>(new Set());\n const effectiveSelectedKeys = isControlled ? selectedKeys! : internalSelectedKeys;\n\n function applySelection(next: Set<string | number>) {\n if (!isControlled) setInternalSelectedKeys(next);\n onSelectionChange?.(next);\n }\n\n function handleRowSelect(key: string | number) {\n const next = new Set(effectiveSelectedKeys);\n if (next.has(key)) next.delete(key); else next.add(key);\n applySelection(next);\n }\n\n function handleSelectAll() {\n const allKeys = items.map((item, i) => getKey(item, i));\n const allChosen = allKeys.every((k) => effectiveSelectedKeys.has(k));\n applySelection(allChosen ? new Set() : new Set(allKeys));\n }\n\n // O(n) header-checkbox state. The component re-renders every scroll frame\n // (scrollTop is state), but these depend only on the items and the selection —\n // so memoise to keep two full-list scans off the scroll path.\n const { allSelected, someSelected } = useMemo(() => {\n if (!multiSelect || items.length === 0) return { allSelected: false, someSelected: false };\n const all = items.every((item, i) => effectiveSelectedKeys.has(getKey(item, i)));\n const some = !all && items.some((item, i) => effectiveSelectedKeys.has(getKey(item, i)));\n return { allSelected: all, someSelected: some };\n }, [multiSelect, items, effectiveSelectedKeys, getKey]);\n\n return { effectiveSelectedKeys, handleRowSelect, handleSelectAll, allSelected, someSelected };\n}\n","import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\n\nimport {\n buildColumnTemplate,\n loadPersistedColumns,\n isColumnInitiallyVisible,\n COLUMN_STORAGE_PREFIX,\n type PersistedColumns,\n} from './virtualList.utils';\nimport type { VirtualListColumn } from './virtualList.types';\n\ninterface UseColumnsArgs<T> {\n columns?: VirtualListColumn<T>[];\n items: T[];\n multiSelect: boolean;\n visibleColumnKeys?: string[];\n onVisibleColumnsChange?: (keys: string[]) => void;\n persistColumnsKey?: string;\n showColumnToggle?: boolean;\n rootRef: React.RefObject<HTMLDivElement | null>;\n /** Visible-window bounds — re-measure `fit` columns as new cells scroll in. */\n startIndex: number;\n endIndex: number;\n containerHeight: number;\n /** Re-measure `fit` columns when the container width settles (e.g. after a route transition). */\n containerWidth: number;\n}\n\ninterface UseColumnsResult<T> {\n hasColumns: boolean;\n visibleColumns: VirtualListColumn<T>[];\n columnTemplate: string | undefined;\n shouldShowToggle: boolean;\n effectiveVisible: Set<string>;\n /** How many default-visible columns the user has hidden (excludes defaultHidden). */\n manuallyHiddenCount: number;\n toggleOpen: boolean;\n setToggleOpen: React.Dispatch<React.SetStateAction<boolean>>;\n handleToggleColumn: (key: string) => void;\n /** Imperative escape hatch: drop fit-column pins so they re-measure on the\n * next layout. For out-of-band content changes that don't flow through a new\n * `items` array or `columns` set (which reset automatically). */\n recalculateColumns: () => void;\n}\n\n/**\n * Table-mode column logic: visibility (controlled or uncontrolled, with\n * localStorage persistence and runtime reconciliation), the toggle popover, and\n * `fit`-column width measurement that pins one shared px track across the header\n * and every row grid so they stay aligned.\n */\nexport function useColumns<T>({\n columns,\n items,\n multiSelect,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n rootRef,\n startIndex,\n endIndex,\n containerHeight,\n containerWidth,\n}: UseColumnsArgs<T>): UseColumnsResult<T> {\n const isControlled = visibleColumnKeys !== undefined;\n const [toggleOpen, setToggleOpen] = useState(false);\n // Measured px widths for `fit` columns, keyed by column key. Pinning these\n // into the shared column template keeps the header and rows aligned (a raw\n // `fit-content` track resolves per-grid and drifts). See the effects below.\n const [fitWidths, setFitWidths] = useState<Record<string, number>>({});\n\n const [internalVisibleKeys, setInternalVisibleKeys] = useState<Set<string>>(() => {\n const persisted = loadPersistedColumns(persistColumnsKey);\n return new Set((columns ?? []).filter((c) => isColumnInitiallyVisible(c, persisted)).map((c) => c.key));\n });\n // The set of column keys the internal visibility state was last reconciled\n // against. The lazy initializer above only runs at mount, so without this a\n // list that mounts in list mode (no columns) and later switches to table mode\n // would keep an empty visible set and render no columns.\n const knownColumnKeysRef = useRef<Set<string>>(new Set((columns ?? []).map((c) => c.key)));\n\n // Re-derive internal visibility when the column set changes at runtime: new\n // columns get their saved/default visibility, removed columns drop out, and\n // existing columns keep whatever the user toggled them to. This is also what\n // applies persisted settings when a list switches from list mode to table\n // mode (columns absent at mount, supplied later).\n useEffect(() => {\n if (isControlled) return;\n const cols = columns ?? [];\n const currentKeys = new Set(cols.map((c) => c.key));\n const known = knownColumnKeysRef.current;\n let identical = currentKeys.size === known.size;\n if (identical) for (const k of currentKeys) if (!known.has(k)) { identical = false; break; }\n if (identical) return;\n knownColumnKeysRef.current = currentKeys;\n const persisted = loadPersistedColumns(persistColumnsKey);\n setInternalVisibleKeys((prev) => {\n const next = new Set<string>();\n for (const c of cols) {\n if (known.has(c.key)) {\n if (prev.has(c.key)) next.add(c.key); // preserve the current-session choice\n } else if (isColumnInitiallyVisible(c, persisted)) {\n next.add(c.key); // newly-added column: saved setting, else defaultHidden\n }\n }\n return next;\n });\n }, [columns, isControlled, persistColumnsKey]);\n\n // Persist visibility whenever it changes (uncontrolled mode only). Skip while\n // there are no columns, or the transient empty state during a list→table\n // switch before the reconcile effect above has filled in the visible set —\n // writing then would clobber the saved config with an empty set.\n useEffect(() => {\n if (isControlled || !persistColumnsKey || typeof window === 'undefined') return;\n const cols = columns ?? [];\n if (cols.length === 0 || internalVisibleKeys.size === 0) return;\n try {\n window.localStorage.setItem(\n COLUMN_STORAGE_PREFIX + persistColumnsKey,\n JSON.stringify({ visible: [...internalVisibleKeys], known: cols.map((c) => c.key) } satisfies PersistedColumns),\n );\n } catch {\n // Storage full or unavailable — non-fatal, just don't persist.\n }\n }, [internalVisibleKeys, columns, isControlled, persistColumnsKey]);\n\n // Locked columns can never be hidden — force them into the visible set even if\n // a controlled `visibleColumnKeys` or persisted state omits them. Only clone\n // (rather than mutate the state Set) when a locked key is actually missing;\n // in uncontrolled mode they're already present via isColumnInitiallyVisible.\n const baseVisible: Set<string> = isControlled ? new Set(visibleColumnKeys) : internalVisibleKeys;\n const lockedKeys = (columns ?? []).filter((c) => c.lockVisible).map((c) => c.key);\n const effectiveVisible: Set<string> = lockedKeys.some((k) => !baseVisible.has(k))\n ? new Set([...baseVisible, ...lockedKeys])\n : baseVisible;\n\n const hasColumns = !!columns?.length;\n const visibleColumns = hasColumns ? columns!.filter((c) => effectiveVisible.has(c.key)) : [];\n // A column counts as \"manually hidden\" only if it's default-visible yet\n // currently hidden — a defaultHidden column being hidden is its default\n // state, not a user choice, so it never contributes to the chip.\n const manuallyHiddenCount = hasColumns\n ? columns!.filter((c) => !c.defaultHidden && !effectiveVisible.has(c.key)).length\n : 0;\n const selectPrefix = multiSelect && hasColumns ? '40px ' : '';\n const columnTemplate = hasColumns ? `${selectPrefix}${buildColumnTemplate(visibleColumns, fitWidths)}` : undefined;\n // Hide the gear entirely when nothing is left to toggle (every column opts out).\n const shouldShowToggle = showColumnToggle !== false && hasColumns && columns!.some((c) => !c.hideFromToggle);\n\n // ── `fit` column width measurement ──────────────────────────────────────────\n const fitColumns = visibleColumns.filter((c) => c.width.type === 'fit');\n const hasFit = fitColumns.length > 0;\n const fitColKey = fitColumns.map((c) => c.key).join('|');\n\n // Drop the measured pins when the data or the fit-column set changes, so the\n // measure effect below re-reads the true intrinsic width on the next pass —\n // this is what lets a column shrink (during scroll the effect only grows it,\n // to avoid jitter). Resetting state during render is React's recommended\n // pattern for \"reset on prop change\" and avoids a cascading effect render.\n const [fitReset, setFitReset] = useState<{ key: string; items: T[] }>({ key: fitColKey, items });\n if (fitReset.key !== fitColKey || fitReset.items !== items) {\n setFitReset({ key: fitColKey, items });\n if (Object.keys(fitWidths).length > 0) setFitWidths({});\n }\n\n // Measure every fit cell currently in the DOM (header + visible rows), keyed\n // by its `data-fit-key`, and grow each column's pin to the widest. Reading the\n // key off the DOM (rather than closing over `fitColumns`) keeps this a stable\n // callback the ResizeObserver below can reuse. `scrollWidth` reports the true\n // content width even when the cell is pinned narrower than its content, so a\n // later pass always recovers a column first measured while it was still empty\n // (e.g. an actions cell whose buttons mount a tick after the row commits — its\n // empty width is just the padding, ~24px, which \"only grow\" can't undo).\n const measureFitWidths = useCallback(() => {\n const root = rootRef.current;\n if (!root) return;\n const maxByKey = new Map<string, number>();\n root.querySelectorAll('[data-fit-key]').forEach((node) => {\n const el = node as HTMLElement;\n const key = el.getAttribute('data-fit-key');\n if (!key) return;\n const overflowing = el.scrollWidth > el.clientWidth;\n let w = el.scrollWidth;\n // Only resolve computed padding when we actually need it — the overflow\n // fix-up, or the collapse check below — so the hot scroll path stays cheap\n // for plain in-flow cells.\n if (overflowing || el.firstElementChild) {\n const cs = getComputedStyle(el);\n const padLeft = parseFloat(cs.paddingLeft) || 0;\n const padRight = parseFloat(cs.paddingRight) || 0;\n // scrollWidth includes the left padding but drops the right padding when\n // the content overflows — add it back.\n if (overflowing) w += padRight;\n // Collapsed-content case (FontAwesome icons etc.): element children are\n // present, yet scrollWidth is only the cell's padding because their boxes\n // overflow via `overflow: visible` and carry no intrinsic width, so they\n // don't count toward scrollWidth (and, when right-aligned, overflow to the\n // *left* into negative offsets). ONLY then walk the descendants for their\n // true span — once a real width pins, the cell is no longer collapsed, so\n // this stops running on every scroll frame.\n if (el.firstElementChild && !overflowing && el.scrollWidth <= padLeft + padRight + 1) {\n let minLeft = Infinity;\n let maxRight = -Infinity;\n el.querySelectorAll('*').forEach((d) => {\n const r = d.getBoundingClientRect();\n if (r.left < minLeft) minLeft = r.left;\n if (r.right > maxRight) maxRight = r.right;\n });\n if (maxRight > minLeft) {\n const span = Math.ceil(maxRight - minLeft) + padLeft + padRight;\n if (span > w) w = span;\n }\n }\n }\n if (w > (maxByKey.get(key) ?? 0)) maxByKey.set(key, w);\n });\n if (maxByKey.size === 0) return;\n setFitWidths((prev) => {\n let changed = false;\n const next = { ...prev };\n for (const [key, max] of maxByKey) {\n if (max <= 0) continue;\n // Cap at the viewport width so one oversized cell can't blow out layout.\n const pinned = Math.min(Math.ceil(max), root.clientWidth);\n if (pinned > (prev[key] ?? 0)) { next[key] = pinned; changed = true; }\n }\n return changed ? next : prev;\n });\n }, [rootRef]);\n\n // One ResizeObserver shared across all fit cells. It re-measures whenever a\n // cell's box changes — crucially when content first appears after mount (which\n // changes the cell's height even while its width is pinned), so a too-early or\n // empty-cell measure self-corrects instead of sticking. Its initial callback\n // also fires once after layout settles, covering route transitions and other\n // post-mount layout shifts without depending on font/rAF timing.\n const [fitObserver] = useState<ResizeObserver | null>(() =>\n typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => measureFitWidths()),\n );\n const observedRef = useRef<Set<Element>>(new Set());\n useEffect(() => () => { fitObserver?.disconnect(); observedRef.current.clear(); }, [fitObserver]);\n\n // Measure synchronously (before paint, so a wider row scrolling in never shows\n // a clipped frame), then *diff* the observed set rather than re-observing every\n // cell. Re-observing fires a redundant ResizeObserver callback per node, and\n // `startIndex`/`endIndex` change every scroll frame — so observing only the\n // cells that entered (and dropping the ones that left) keeps stable, already\n // pinned cells from generating any observer traffic while scrolling. A newly\n // entered cell still fires exactly once, which is when we want to measure it.\n useLayoutEffect(() => {\n if (!hasFit) return;\n const root = rootRef.current;\n if (!root) return;\n measureFitWidths();\n if (!fitObserver) return;\n const current = new Set<Element>(root.querySelectorAll('[data-fit-key]'));\n const observed = observedRef.current;\n for (const el of observed) if (!current.has(el)) { fitObserver.unobserve(el); observed.delete(el); }\n for (const el of current) if (!observed.has(el)) { fitObserver.observe(el); observed.add(el); }\n }, [hasFit, fitColKey, fitWidths, startIndex, endIndex, containerHeight, containerWidth, items, measureFitWidths, fitObserver]);\n\n // Cheap insurance: re-measure on the next two frames after mount / data /\n // fit-column changes, in case the icons (or the injected FontAwesome sizing\n // CSS) resolve a frame after the first synchronous pass. Safe and scoped —\n // measureFitWidths only ever grows a pin, and this runs on mount / data change\n // (not every scroll frame), so it keeps the diff-observe perf win.\n useEffect(() => {\n if (!hasFit) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n measureFitWidths();\n raf2 = requestAnimationFrame(() => measureFitWidths());\n });\n return () => { cancelAnimationFrame(raf1); cancelAnimationFrame(raf2); };\n }, [hasFit, fitColKey, items, measureFitWidths]);\n\n // Force a fresh fit-column measure regardless of current pins. Always installs\n // a new empty object so the measure layout effect re-runs even when nothing\n // was pinned (e.g. content changed while the column was still fit-content).\n const recalculateColumns = useCallback(() => setFitWidths({}), []);\n\n function handleToggleColumn(key: string) {\n // Locked columns can't be toggled off.\n if (columns?.find((c) => c.key === key)?.lockVisible) return;\n const next = new Set(effectiveVisible);\n if (next.has(key)) {\n if (next.size <= 1) return;\n next.delete(key);\n } else {\n next.add(key);\n }\n const nextArray = [...next];\n if (!isControlled) setInternalVisibleKeys(next);\n onVisibleColumnsChange?.(nextArray);\n }\n\n return {\n hasColumns,\n visibleColumns,\n columnTemplate,\n shouldShowToggle,\n effectiveVisible,\n manuallyHiddenCount,\n toggleOpen,\n setToggleOpen,\n handleToggleColumn,\n recalculateColumns,\n };\n}\n","import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\n\nimport styles from './virtualList.module.pcss';\nimport { resolveReorderTarget, resolveTreeDropTarget, lastDescendantIndex } from './virtualList.utils';\nimport type { TreeDropPosition, TreeDropTarget } from './virtualList.types';\n\ninterface UseRowDragArgs {\n reorderable: boolean;\n treeReorder: boolean;\n onReorder?: (fromIndex: number, toIndex: number) => void;\n onTreeDrop?: (dragKey: string | number, target: TreeDropTarget) => void;\n longPressDelay: number;\n dragHandle: boolean;\n treeIndentPx: number;\n /** Current flat ordering and depth tags (mouse handlers read these directly). */\n keys: (string | number)[];\n depths: number[];\n isGroupAt: (index: number) => boolean;\n rootRef: React.RefObject<HTMLDivElement | null>;\n /** Latest keys for async (touch / rAF) consumers — owned by useVirtualWindow. */\n keysRef: React.RefObject<(string | number)[]>;\n}\n\n/** The drag-related props the parent spreads onto a given row. */\nexport interface RowDragProps {\n reorderable: boolean;\n draggable: boolean | undefined;\n isDragging: boolean;\n onMouseDown: ((e: React.MouseEvent<HTMLDivElement>) => void) | undefined;\n onDragStart: ((e: React.DragEvent<HTMLDivElement>) => void) | undefined;\n onDragOver: ((e: React.DragEvent<HTMLDivElement>) => void) | undefined;\n onDragEnd: (() => void) | undefined;\n onDrop: ((e: React.DragEvent<HTMLDivElement>) => void) | undefined;\n onTouchStart: ((e: React.TouchEvent<HTMLDivElement>) => void) | undefined;\n dropPosition: TreeDropPosition | undefined;\n dropIndentPx: number | undefined;\n}\n\ninterface UseRowDragResult {\n /** True while a row is being dragged (for the root reordering style). */\n draggingKey: string | number | null;\n /** Whether either drag mode is active. */\n dragEnabled: boolean;\n /** Drag props for the row at `index` / `key`. */\n getRowDragProps: (index: number, key: string | number) => RowDragProps;\n /** Returns true (and resets) if the next click should be swallowed (post-drag). */\n consumeSuppressedClick: () => boolean;\n}\n\n/**\n * Row drag-and-drop for both modes:\n * - `reorderable` (flat): native HTML5 drag on desktop; rows move live via\n * `onReorder` with midpoint hysteresis.\n * - `treeReorder`: a drop indicator (before/after/inside) is shown during the\n * drag and `onTreeDrop` fires once on release; dropping onto the dragged\n * node's own subtree is forbidden.\n * Touch uses a long-press → lifted-clone → pointer-move path with edge\n * auto-scroll. `dragHandle` restricts initiation to `[data-drag-handle]`.\n */\nexport function useRowDrag({\n reorderable,\n treeReorder,\n onReorder,\n onTreeDrop,\n longPressDelay,\n dragHandle,\n treeIndentPx,\n keys,\n depths,\n isGroupAt,\n rootRef,\n keysRef,\n}: UseRowDragArgs): UseRowDragResult {\n // The dragged item is tracked by its stable key (indices shift after each\n // live reorder); the ref drives the logic, the state drives the row's style.\n const dragKeyRef = useRef<string | number | null>(null);\n const [draggingKey, setDraggingKey] = useState<string | number | null>(null);\n // Tree-reorder drop indicator. Unlike flat reorder (which moves rows live),\n // tree mode shows where the drop will land and commits once on release.\n const [dropTarget, setDropTarget] = useState<TreeDropTarget | null>(null);\n const dropTargetRef = useRef<TreeDropTarget | null>(null);\n const onReorderRef = useRef(onReorder);\n const onTreeDropRef = useRef(onTreeDrop);\n const treeModeRef = useRef(treeReorder);\n const depthsRef = useRef<number[]>(depths);\n const isGroupAtRef = useRef<(i: number) => boolean>(isGroupAt);\n // When `dragHandle` is on, a mousedown sets this to whether it landed on a\n // `[data-drag-handle]` element, gating whether the ensuing dragstart is honoured.\n const dragFromHandleRef = useRef(true);\n const longPressRef = useRef<number | null>(null);\n const touchActiveRef = useRef(false);\n const touchStartYRef = useRef<number | null>(null);\n const pointerXRef = useRef(0);\n const pointerYRef = useRef(0);\n const autoScrollRef = useRef<number | null>(null);\n const suppressNextClickRef = useRef(false);\n // Floating clone that follows the finger during a touch drag.\n const dragCloneRef = useRef<HTMLElement | null>(null);\n const grabOffsetYRef = useRef(0);\n const cloneLeftRef = useRef(0);\n const dragHeightRef = useRef(0);\n // The native `draggable` attribute (mouse DnD) makes a long-press start the\n // browser's own drag on touch devices, which hijacks our touch handlers. So\n // expose it only where the primary pointer is fine (mouse/trackpad); touch\n // devices use the touch handlers below instead.\n const [isCoarsePointer] = useState(() =>\n typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n ? window.matchMedia('(pointer: coarse)').matches\n : false,\n );\n\n useLayoutEffect(() => {\n onReorderRef.current = onReorder;\n onTreeDropRef.current = onTreeDrop;\n treeModeRef.current = treeReorder;\n depthsRef.current = depths;\n dropTargetRef.current = dropTarget;\n isGroupAtRef.current = isGroupAt;\n });\n\n // ── Mouse / shared start ──────────────────────────────────────────────────\n\n // With `dragHandle`, remember on mousedown whether the press landed on a\n // handle, so the dragstart that follows can be ignored if it didn't.\n function handleRowMouseDown(e: React.MouseEvent<HTMLDivElement>) {\n dragFromHandleRef.current = !!(e.target as HTMLElement).closest('[data-drag-handle]');\n }\n\n function handleReorderStart(key: string | number, e: React.DragEvent<HTMLDivElement>) {\n if (dragHandle && !dragFromHandleRef.current) {\n e.preventDefault(); // not started from a handle — let the row stay put\n return;\n }\n dragKeyRef.current = key;\n setDraggingKey(key);\n if (treeReorder) setDropTarget(null);\n }\n\n // ── Tree mode ─────────────────────────────────────────────────────────────\n\n /** Resolve the tree drop target for the row at `overIndex` under pointer `y`. */\n function computeTreeDrop(overIndex: number, y: number, rect: DOMRect): TreeDropTarget | null {\n const dragKey = dragKeyRef.current;\n if (dragKey == null) return null;\n const fromIndex = keys.indexOf(dragKey);\n // Forbid dropping onto the dragged node or anything in its own subtree.\n if (fromIndex !== -1 && overIndex >= fromIndex && overIndex <= lastDescendantIndex(fromIndex, depths)) {\n return null;\n }\n const position = resolveTreeDropTarget(y, rect.top, rect.height, isGroupAt(overIndex));\n return { key: keys[overIndex], position };\n }\n\n function handleTreeDragOver(overIndex: number, e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault(); // allow the drop\n const rect = e.currentTarget.getBoundingClientRect();\n const next = computeTreeDrop(overIndex, e.clientY, rect);\n setDropTarget((prev) =>\n prev?.key === next?.key && prev?.position === next?.position ? prev : next,\n );\n }\n\n function commitTreeDrop() {\n const dragKey = dragKeyRef.current;\n const target = dropTargetRef.current;\n if (dragKey != null && target && target.key !== dragKey) onTreeDrop?.(dragKey, target);\n }\n\n function handleTreeDrop(e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault();\n commitTreeDrop();\n setDropTarget(null);\n dragKeyRef.current = null;\n setDraggingKey(null);\n }\n\n function handleTreeDragEnd() {\n // Fires after `drop` (or on its own when released off a valid target).\n setDropTarget(null);\n dragKeyRef.current = null;\n setDraggingKey(null);\n }\n\n // ── Flat mode ─────────────────────────────────────────────────────────────\n\n function handleReorderOver(overIndex: number, e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault(); // allow the drop\n const dragKey = dragKeyRef.current;\n if (dragKey == null) return;\n const fromIndex = keys.indexOf(dragKey);\n // Midpoint hysteresis (see resolveReorderTarget): a move only happens once\n // the pointer crosses the centre of the row it's over. After a swap the\n // dragged row sits under the cursor, so moving again needs real pointer\n // travel — this stops the oscillation that made dragging feel jumpy.\n const rect = e.currentTarget.getBoundingClientRect();\n const target = resolveReorderTarget(fromIndex, overIndex, e.clientY, rect.top, rect.height);\n if (target != null) onReorder?.(fromIndex, target);\n }\n\n function handleReorderEnd() {\n dragKeyRef.current = null;\n setDraggingKey(null);\n }\n\n // ── Touch reordering (long-press to arm, then drag) ──────────────────────────\n // These handlers run from window listeners during a touch drag, so they read\n // mutable state from refs and are stable across renders.\n\n const reorderAtPoint = useCallback((x: number) => {\n const dragKey = dragKeyRef.current;\n const root = rootRef.current;\n if (dragKey == null || !root) return;\n // Reorder against the centre of the lifted clone, not the raw finger — the\n // finger sits below the clone's top by the grab offset, so using it would\n // make the top (and bottom) rows unreachable. The clone is what the user\n // aims with, so match it.\n const y = dragCloneRef.current\n ? pointerYRef.current - grabOffsetYRef.current + dragHeightRef.current / 2\n : pointerYRef.current;\n const el = document.elementFromPoint(x, y) as HTMLElement | null;\n const rowEl = el && root.contains(el) ? el.closest<HTMLElement>('[data-index]') : null;\n if (!rowEl) return;\n const overIndex = Number(rowEl.dataset.index);\n if (Number.isNaN(overIndex)) return;\n const fromIndex = keysRef.current.indexOf(dragKey);\n const rect = rowEl.getBoundingClientRect();\n if (treeModeRef.current) {\n // Tree mode: don't move live — just track where the drop will land.\n const ks = keysRef.current;\n const ds = depthsRef.current;\n if (fromIndex !== -1 && overIndex >= fromIndex && overIndex <= lastDescendantIndex(fromIndex, ds)) {\n setDropTarget(null);\n return;\n }\n const position = resolveTreeDropTarget(y, rect.top, rect.height, isGroupAtRef.current(overIndex));\n const next: TreeDropTarget = { key: ks[overIndex], position };\n setDropTarget((prev) => (prev?.key === next.key && prev?.position === next.position ? prev : next));\n return;\n }\n const target = resolveReorderTarget(fromIndex, overIndex, y, rect.top, rect.height);\n if (target != null) onReorderRef.current?.(fromIndex, target);\n }, [rootRef, keysRef]);\n\n // Keep the floating clone glued under the finger (same grab point).\n const positionDragClone = useCallback(() => {\n const clone = dragCloneRef.current;\n if (!clone) return;\n clone.style.transform = `translate(${cloneLeftRef.current}px, ${pointerYRef.current - grabOffsetYRef.current}px)`;\n }, []);\n\n // While the finger sits near a top/bottom edge (and within the list's width),\n // scroll the list and keep reordering against the rows now passing under it.\n const autoScrollTick = useCallback(() => {\n const root = rootRef.current;\n if (!root || !touchActiveRef.current) { autoScrollRef.current = null; return; }\n const rect = root.getBoundingClientRect();\n const x = pointerXRef.current;\n const y = pointerYRef.current;\n const EDGE = 48;\n let dy = 0;\n // Only auto-scroll while the finger is actually over the list — moving it\n // outside (any direction) stops the scroll instead of running away; pinning\n // the dragged row keeps touch events alive so it resumes when you come back.\n const inside = x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;\n if (inside) {\n if (y < rect.top + EDGE) dy = -Math.min(18, Math.ceil((rect.top + EDGE - y) / 3));\n else if (y > rect.bottom - EDGE) dy = Math.min(18, Math.ceil((y - (rect.bottom - EDGE)) / 3));\n }\n if (dy !== 0) {\n root.scrollTop += dy;\n reorderAtPoint(x);\n }\n autoScrollRef.current = requestAnimationFrame(autoScrollTick);\n }, [reorderAtPoint, rootRef]);\n\n const endTouchDrag = useCallback(() => {\n if (longPressRef.current != null) { clearTimeout(longPressRef.current); longPressRef.current = null; }\n window.removeEventListener('touchmove', handleTouchMove);\n window.removeEventListener('touchend', endTouchDrag);\n window.removeEventListener('touchcancel', endTouchDrag);\n if (autoScrollRef.current != null) { cancelAnimationFrame(autoScrollRef.current); autoScrollRef.current = null; }\n if (dragCloneRef.current) { dragCloneRef.current.remove(); dragCloneRef.current = null; }\n // Restore native scrolling that was locked for the duration of the drag.\n document.body.style.touchAction = '';\n document.body.style.overscrollBehavior = '';\n if (touchActiveRef.current) {\n // A real drag happened — swallow the click the browser fires afterwards\n // so it doesn't, e.g., toggle row selection.\n suppressNextClickRef.current = true;\n setTimeout(() => { suppressNextClickRef.current = false; }, 350);\n // Tree mode commits the pending drop on release (flat mode already moved\n // rows live during the drag, so there's nothing to commit here).\n if (treeModeRef.current) {\n const dk = dragKeyRef.current;\n const target = dropTargetRef.current;\n if (dk != null && target && target.key !== dk) onTreeDropRef.current?.(dk, target);\n }\n }\n setDropTarget(null);\n touchActiveRef.current = false;\n touchStartYRef.current = null;\n dragKeyRef.current = null;\n setDraggingKey(null);\n }, []);\n\n const handleTouchMove = useCallback((e: TouchEvent) => {\n const t = e.touches[0];\n if (!t) return;\n pointerXRef.current = t.clientX;\n pointerYRef.current = t.clientY;\n if (!touchActiveRef.current) {\n // Before the long-press fires: if the finger travels, the user means to\n // scroll, so disarm and let the browser handle it (we don't preventDefault).\n const sy = touchStartYRef.current;\n if (sy != null && Math.abs(t.clientY - sy) > 10 && longPressRef.current != null) {\n clearTimeout(longPressRef.current);\n longPressRef.current = null;\n }\n return;\n }\n // Non-passive listener: preventDefault cancels the native scroll for this\n // gesture — the only reliable way once touch-action has been latched at\n // touchstart. This is what makes the drag actually move on touch devices.\n if (e.cancelable) e.preventDefault();\n positionDragClone();\n reorderAtPoint(t.clientX);\n }, [reorderAtPoint, positionDragClone]);\n\n function handleRowTouchStart(key: string | number, e: React.TouchEvent<HTMLDivElement>) {\n if (!reorderable && !treeReorder) return;\n // With a drag handle, only a press that starts on it arms the drag, so the\n // rest of the row stays free for tapping/typing into inputs.\n if (dragHandle && !(e.target as HTMLElement).closest('[data-drag-handle]')) return;\n if (longPressRef.current != null || touchActiveRef.current) return; // ignore extra fingers\n const t = e.touches[0];\n if (!t) return;\n touchStartYRef.current = t.clientY;\n pointerXRef.current = t.clientX;\n pointerYRef.current = t.clientY;\n window.addEventListener('touchmove', handleTouchMove, { passive: false });\n window.addEventListener('touchend', endTouchDrag);\n window.addEventListener('touchcancel', endTouchDrag);\n longPressRef.current = window.setTimeout(() => {\n longPressRef.current = null;\n touchActiveRef.current = true;\n dragKeyRef.current = key;\n setDraggingKey(key);\n navigator.vibrate?.(10);\n // Lock native scrolling for the whole gesture — relying on per-move\n // preventDefault isn't enough once the finger leaves and re-enters the\n // list (the browser commits to a scroll and ignores it). We do all the\n // scrolling ourselves via autoScrollTick.\n document.body.style.touchAction = 'none';\n document.body.style.overscrollBehavior = 'none';\n createDragClone(key);\n if (autoScrollRef.current == null) autoScrollRef.current = requestAnimationFrame(autoScrollTick);\n }, longPressDelay);\n }\n\n // Build a floating copy of the picked-up row that tracks the finger, so the\n // drag has a visible \"lifted\" element (the original row stays dimmed in place\n // as a drop placeholder).\n function createDragClone(key: string | number) {\n const root = rootRef.current;\n if (!root) return;\n const idx = keysRef.current.indexOf(key);\n const src = root.querySelector<HTMLElement>(`[data-index=\"${idx}\"]`);\n if (!src) return;\n const r = src.getBoundingClientRect();\n grabOffsetYRef.current = pointerYRef.current - r.top;\n cloneLeftRef.current = r.left;\n dragHeightRef.current = r.height;\n const clone = src.cloneNode(true) as HTMLElement;\n clone.removeAttribute('data-index');\n clone.setAttribute('data-drag-clone', 'true');\n clone.setAttribute('aria-hidden', 'true');\n clone.classList.add(styles.virtualListDragClone);\n Object.assign(clone.style, {\n position: 'fixed',\n left: '0',\n top: '0',\n width: `${r.width}px`,\n height: `${r.height}px`,\n margin: '0',\n opacity: '1',\n pointerEvents: 'none',\n // Above the sticky header (z-index 2) and any focused row (z-index 1).\n zIndex: '3',\n background: 'var(--background)',\n boxShadow: 'var(--card-shadow)',\n borderRadius: 'var(--default-border-radius)',\n } as Partial<CSSStyleDeclaration>);\n // Appended inside the list so it inherits the active theme's CSS variables;\n // position:fixed keeps it in viewport coordinates regardless.\n root.appendChild(clone);\n dragCloneRef.current = clone;\n positionDragClone();\n }\n\n // Tear down any in-flight touch drag if the component unmounts mid-gesture.\n useEffect(() => endTouchDrag, [endTouchDrag]);\n\n // Either drag mode arms the same row gestures; the handlers above branch on\n // `treeReorder` for the differing target resolution / commit behaviour.\n const dragEnabled = reorderable || treeReorder;\n\n function getRowDragProps(index: number, key: string | number): RowDragProps {\n // The drop indicator only renders on the row currently targeted. `before`/\n // `after` lines indent to the target's depth so they sit under where the\n // dropped content will start; `inside` highlights the whole row instead.\n const rowDrop = treeReorder && dropTarget?.key === key ? dropTarget.position : undefined;\n return {\n // Drives the row-wide grab cursor. With `dragHandle`, only the handle\n // initiates a drag, so the cursor belongs on the handle (styled by the\n // consumer), not across the whole row.\n reorderable: dragEnabled && !dragHandle,\n draggable: (dragEnabled && !isCoarsePointer) || undefined,\n isDragging: dragEnabled && key === draggingKey,\n onMouseDown: dragEnabled && dragHandle ? handleRowMouseDown : undefined,\n onDragStart: dragEnabled ? (e) => handleReorderStart(key, e) : undefined,\n onDragOver:\n treeReorder ? (e) => handleTreeDragOver(index, e)\n : reorderable ? (e) => handleReorderOver(index, e)\n : undefined,\n onDragEnd: treeReorder ? handleTreeDragEnd : reorderable ? handleReorderEnd : undefined,\n onDrop: treeReorder ? handleTreeDrop : undefined,\n onTouchStart: dragEnabled ? (e) => handleRowTouchStart(key, e) : undefined,\n dropPosition: rowDrop,\n dropIndentPx: rowDrop ? (depths[index] ?? 0) * treeIndentPx : undefined,\n };\n }\n\n function consumeSuppressedClick(): boolean {\n if (suppressNextClickRef.current) { suppressNextClickRef.current = false; return true; }\n return false;\n }\n\n return { draggingKey, dragEnabled, getRowDragProps, consumeSuppressedClick };\n}\n","import React, { useMemo, useCallback, useImperativeHandle } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faGear } from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './virtualList.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport Checkbox from '../checkbox';\nimport FloatingMenu, { Align } from '../floatingMenu';\nimport VirtualRow from './virtualRow';\nimport { useVirtualWindow } from './useVirtualWindow';\nimport { useSelection } from './useSelection';\nimport { useColumns } from './useColumns';\nimport { useRowDrag } from './useRowDrag';\nimport type { VirtualListProps, VirtualListHandle } from './virtualList.types';\n\n// Pure helpers live in ./virtualList.utils; re-exported here so existing\n// imports (and unit tests) keep working against the component entry point.\nexport {\n buildOffsets,\n findStartIndex,\n getVisibleRange,\n resolveReorderTarget,\n resolveTreeDropTarget,\n lastDescendantIndex,\n buildColumnTemplate,\n} from './virtualList.utils';\n\n// ─── Orchestrator ─────────────────────────────────────────────────────────────\n// VirtualListInner wires four focused hooks together and renders. Each concern\n// lives in its own module:\n// useVirtualWindow — generic scroll / measurement / windowing (all modes)\n// useSelection — multi-row selection\n// useColumns — table mode: columns, visibility, persistence, fit widths\n// useRowDrag — reorder + tree drag-and-drop (mouse + touch)\n\nfunction VirtualListInner<T>({\n items,\n renderRow,\n columns,\n height = '100%',\n estimatedRowHeight = 40,\n overscan = 3,\n rowGap = 0,\n rowPadding,\n selectedKey,\n getItemKey,\n onRowClick,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n onLoadMore,\n loadMoreThreshold = 100,\n isLoading = false,\n multiSelect = false,\n selectedKeys,\n onSelectionChange,\n reorderable = false,\n onReorder,\n longPressDelay = 400,\n treeReorder = false,\n getItemDepth,\n isGroup,\n onTreeDrop,\n treeIndentPx = 24,\n dragHandle = false,\n showDivider = true,\n rowHover = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: VirtualListProps<T>, ref: React.ForwardedRef<VirtualListHandle>) {\n const getKey = useCallback(\n (item: T, index: number): string | number => (getItemKey ? getItemKey(item, index) : index),\n [getItemKey],\n );\n const keys = useMemo(() => items.map((item, i) => getKey(item, i)), [items, getKey]);\n const depths = useMemo(\n () => (getItemDepth ? items.map((item, i) => getItemDepth(item, i)) : []),\n [items, getItemDepth],\n );\n const isGroupAt = useCallback(\n (i: number) => (isGroup ? isGroup(items[i], i) : false),\n [isGroup, items],\n );\n\n const win = useVirtualWindow<T>({\n items, keys, getItemKey, estimatedRowHeight, rowGap, overscan,\n onLoadMore, loadMoreThreshold,\n });\n const { rootRef, headerRef, rowObserver, keysRef, offsets, totalHeight, startIndex, endIndex } = win;\n\n const selection = useSelection<T>({ items, getKey, multiSelect, selectedKeys, onSelectionChange });\n const { effectiveSelectedKeys } = selection;\n\n const cols = useColumns<T>({\n columns, items, multiSelect, visibleColumnKeys, onVisibleColumnsChange, persistColumnsKey,\n showColumnToggle, rootRef, startIndex, endIndex,\n containerHeight: win.containerHeight, containerWidth: win.containerWidth,\n });\n const {\n hasColumns, visibleColumns, columnTemplate, shouldShowToggle, effectiveVisible, manuallyHiddenCount,\n toggleOpen, setToggleOpen, handleToggleColumn, recalculateColumns,\n } = cols;\n\n // Compose the forwarded handle from both hooks: scroll methods come from the\n // windowing engine, column controls from the column hook.\n useImperativeHandle(\n ref,\n () => ({ ...win.scrollApi, recalculateColumns }),\n [win.scrollApi, recalculateColumns],\n );\n\n const drag = useRowDrag({\n reorderable, treeReorder, onReorder, onTreeDrop, longPressDelay, dragHandle, treeIndentPx,\n keys, depths, isGroupAt, rootRef, keysRef,\n });\n\n const rowPaddingValue = typeof rowPadding === 'number' ? `${rowPadding}px` : rowPadding;\n\n const renderRowAt = (i: number) => {\n const item = items[i];\n const key = getKey(item, i);\n const isSelected = (selectedKey != null && key === selectedKey) || effectiveSelectedKeys.has(key);\n const dragProps = drag.getRowDragProps(i, key);\n\n return (\n <VirtualRow\n key={key}\n index={i}\n top={offsets[i]}\n padding={rowPaddingValue}\n columnTemplate={columnTemplate}\n isSelected={isSelected}\n showDivider={showDivider}\n hover={rowHover}\n onClick={() => {\n if (drag.consumeSuppressedClick()) return;\n onRowClick?.(item, i);\n }}\n observer={rowObserver}\n ariaRowIndex={hasColumns ? i + 2 : undefined}\n ariaPosInSet={hasColumns ? undefined : i + 1}\n ariaSetSize={hasColumns ? undefined : items.length}\n rowRole={hasColumns ? 'row' : 'listitem'}\n reserveToggleGutter={shouldShowToggle}\n {...dragProps}\n dropIndicatorClassName={classNames?.dropIndicator}\n dropIndicatorStyle={slotStyles?.dropIndicator}\n rowClassName={classNames?.row}\n rowStyle={slotStyles?.row}\n >\n {hasColumns\n ? <>\n {multiSelect && (\n <div\n className={cx(styles.virtualListSelectCell, classNames?.selectCell)}\n style={slotStyles?.selectCell}\n role=\"gridcell\"\n onClick={(e) => e.stopPropagation()}\n >\n <Checkbox\n selected={effectiveSelectedKeys.has(key)}\n onToggle={() => selection.handleRowSelect(key)}\n aria-label=\"Select row\"\n />\n </div>\n )}\n {visibleColumns.map((col) => (\n <div\n key={col.key}\n className={cx(styles.virtualListCell, classNames?.cell)}\n style={slotStyles?.cell}\n role=\"gridcell\"\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.renderCell(item, i)}\n </div>\n ))}\n </>\n : renderRow?.(item, i)}\n </VirtualRow>\n );\n };\n\n const visibleRows: React.ReactNode[] = [];\n for (let i = startIndex; i <= endIndex; i++) visibleRows.push(renderRowAt(i));\n\n // Keep the row being touch-dragged mounted even if it scrolls out of the\n // window. Touch events are dispatched to the element under the finger at\n // touchstart; if that row unmounts, the browser stops delivering touchmove\n // and the drag freezes. Pinning its DOM node keeps the gesture alive.\n const draggedIndex = drag.draggingKey != null ? keys.indexOf(drag.draggingKey) : -1;\n if (draggedIndex >= 0 && (draggedIndex < startIndex || draggedIndex > endIndex)) {\n visibleRows.push(renderRowAt(draggedIndex));\n }\n\n return (\n <div\n {...rest}\n ref={rootRef}\n className={cx(styles.virtualList, drag.draggingKey != null && styles.virtualListReordering, className, classNames?.root)}\n style={{ height, ...style, ...slotStyles?.root }}\n onScroll={win.handleScroll}\n role={hasColumns ? 'grid' : 'list'}\n aria-rowcount={hasColumns ? items.length + 1 : undefined}\n >\n {hasColumns && (\n <div\n ref={headerRef}\n className={cx(styles.virtualListHeader, classNames?.header)}\n style={{ gridTemplateColumns: columnTemplate, ...(shouldShowToggle ? { paddingRight: 32 } : {}), ...slotStyles?.header }}\n role=\"row\"\n aria-rowindex={1}\n >\n {multiSelect && (\n <div\n className={cx(styles.virtualListSelectCell, classNames?.selectCell)}\n style={slotStyles?.selectCell}\n role=\"columnheader\"\n >\n <Checkbox\n selected={selection.allSelected || selection.someSelected}\n onToggle={selection.handleSelectAll}\n aria-label=\"Select all rows\"\n />\n </div>\n )}\n {visibleColumns.map((col) => (\n <div\n key={col.key}\n className={cx(styles.virtualListHeaderCell, classNames?.headerCell)}\n style={slotStyles?.headerCell}\n role=\"columnheader\"\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.label}\n </div>\n ))}\n {shouldShowToggle && (\n <div className={styles.virtualListToggleWrapper}>\n <FloatingMenu\n isOpen={toggleOpen}\n onOpenChange={setToggleOpen}\n align={Align.Right}\n content={\n <div\n className={cx(styles.virtualListTogglePopover, classNames?.togglePopover)}\n style={slotStyles?.togglePopover}\n >\n {columns!.filter((col) => !col.hideFromToggle).map((col) => (\n <Checkbox\n key={col.key}\n className={cx(styles.virtualListToggleItem, classNames?.toggleItem)}\n style={slotStyles?.toggleItem}\n selected={effectiveVisible.has(col.key)}\n onToggle={() => handleToggleColumn(col.key)}\n disabled={col.lockVisible}\n cursorDefault={false}\n >\n {col.toggleLabel ?? col.label}\n </Checkbox>\n ))}\n </div>\n }\n >\n <button\n type=\"button\"\n className={cx(styles.virtualListHeaderToggle, classNames?.headerToggle)}\n style={slotStyles?.headerToggle}\n aria-label=\"Toggle column visibility\"\n >\n <FontAwesomeIcon\n icon={faGear}\n style={slotStyles?.headerToggle as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </button>\n </FloatingMenu>\n {manuallyHiddenCount > 0 && (\n <span\n className={cx(styles.virtualListColumnChip, classNames?.columnChip)}\n style={slotStyles?.columnChip}\n data-column-hidden-count={manuallyHiddenCount}\n aria-label={`${manuallyHiddenCount} columns hidden`}\n >\n {manuallyHiddenCount}\n </span>\n )}\n </div>\n )}\n </div>\n )}\n {isLoading ? (\n <div className={styles.virtualListLoadingFull}>\n <SpinnerLoading className={styles.virtualListSpinner} />\n </div>\n ) : (\n <div\n className={cx(styles.virtualListBody, classNames?.body)}\n style={{ height: totalHeight, ...slotStyles?.body }}\n >\n {visibleRows}\n </div>\n )}\n {win.showLoadMoreSpinner && (\n <div\n className={cx(styles.virtualListLoadingIndicator, classNames?.loadingIndicator)}\n style={slotStyles?.loadingIndicator}\n >\n <SpinnerLoading className={styles.virtualListSpinner} />\n </div>\n )}\n </div>\n );\n}\n\n// forwardRef erases the generic, so cast back to a generic-preserving signature.\nconst VirtualList = React.forwardRef(VirtualListInner) as <T>(\n props: VirtualListProps<T> & { ref?: React.Ref<VirtualListHandle> },\n) => React.ReactElement | null;\n\nexport default VirtualList;\n",".wizard {\n height: 100%;\n width: 100%;\n position: relative;\n overflow: hidden;\n transition: all 0.2s;\n padding: 1px;\n\n &-content {\n position: absolute;\n height: fit-content;\n\n &-outOfFrame {\n * {\n user-select: none;\n pointer-events: none;\n visibility: hidden;\n display: none;\n }\n }\n\n &-container {\n display: flex;\n transition: all 0.6s;\n position: relative;\n }\n }\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport styles from './wizard.module.pcss';\nimport type { WizardProps } from './wizard.types';\n\nexport default function Wizard({\n currentStep = 0,\n stepCount = 0,\n renderStep = () => null,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: WizardProps) {\n const [height, setHeight] = useState<number | undefined>(undefined);\n const [showOtherContent, setShowOtherContent] = useState(false);\n const [prevStep, setPrevStep] = useState(currentStep);\n const stepRefs = useRef<(HTMLDivElement | null)[]>([]);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n // When currentStep changes, briefly show off-screen steps so they animate out.\n if (currentStep !== prevStep) {\n setPrevStep(currentStep);\n setShowOtherContent(true);\n }\n\n useEffect(() => {\n if (!showOtherContent) return;\n const id = setTimeout(() => setShowOtherContent(false), 400);\n return () => clearTimeout(id);\n }, [showOtherContent]);\n\n // Track the height of the active step via ResizeObserver.\n useEffect(() => {\n resizeObserverRef.current?.disconnect();\n const el = stepRefs.current[currentStep];\n if (!el) return;\n setHeight(el.clientHeight);\n resizeObserverRef.current = new ResizeObserver(() => {\n setHeight(el.clientHeight);\n });\n resizeObserverRef.current.observe(el);\n return () => resizeObserverRef.current?.disconnect();\n }, [currentStep, stepCount]);\n\n const rootStyle: React.CSSProperties = {\n ...(height !== undefined ? { height: `${height}px` } : {}),\n ...slotStyles?.root,\n ...style,\n };\n\n return (\n <div\n {...rest}\n className={cx(styles.wizard, classNames?.root, className)}\n style={rootStyle}\n >\n <div\n className={cx(styles.wizardContentContainer, classNames?.container)}\n style={{\n width: `${stepCount * 100}%`,\n marginLeft: `-${currentStep * 100}%`,\n ...slotStyles?.container,\n }}\n >\n {Array.from({ length: stepCount }, (_, index) => (\n <div\n key={`wizardStep${index}`}\n ref={(ref) => { stepRefs.current[index] = ref; }}\n className={cx(styles.wizardContent, classNames?.step)}\n style={{\n width: `${100 / stepCount}%`,\n marginLeft: `${(100 / stepCount) * index}%`,\n ...slotStyles?.step,\n }}\n >\n <div\n className={cx(\n { [styles.wizardContentOutOfFrame]: currentStep !== index && !showOtherContent },\n classNames?.stepContent\n )}\n style={slotStyles?.stepContent}\n inert={currentStep !== index ? true : undefined}\n >\n {renderStep(index)}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { showToast } from 'components/common/toast';\nimport { FormValidatorGroup, createFormComponent } from '@ahrowe/form-validation';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues, ValidationError } from '@ahrowe/form-validation';\nimport type React from 'react';\n\n/** Default onSubmitError: surface the first error as an error toast. Callers can override via options.onSubmitError. */\nconst defaultOnSubmitError = (errors: ValidationError[]): void => {\n showToast(errors[0].message, { type: 'error' });\n};\n\n/**\n * FormValidatorGroup with `this.Form` automatically attached.\n * Kept in a .tsx file so formValidatorGroup.ts stays framework-agnostic.\n *\n * This is the class you should use everywhere — it is a drop-in replacement\n * for FormValidatorGroup with one extra property: `this.Form`.\n *\n * Also injects the default toast-based onSubmitError so both hook and class-component\n * consumers surface errors out of the box; pass options.onSubmitError to override.\n */\nexport default class FormValidatorGroupWithForm<\n TGroup extends FormGroup = FormGroup,\n TInitial = InferGroupValues<TGroup>\n> extends FormValidatorGroup<TGroup, TInitial> {\n Form: React.FC<React.FormHTMLAttributes<HTMLFormElement>>;\n\n constructor(\n groupDef: TGroup,\n component: { forceUpdate: () => void } | null = null,\n options?: FormValidatorGroupOptions<TGroup, TInitial>\n ) {\n super(groupDef, component, { ...options, onSubmitError: options?.onSubmitError ?? defaultOnSubmitError });\n this.Form = createFormComponent(this);\n }\n}\n","/* eslint-disable react/no-unused-state */\nimport React, { PureComponent } from 'react';\nimport { FormValidator } from '@ahrowe/form-validation';\nimport Tooltip from 'components/common/tooltip';\n\nexport interface ValidatableComponentProps {\n formValidator?: FormValidator | null;\n onMouseEnter?: ((event: React.MouseEvent) => void) | null;\n onMouseLeave?: ((event: React.MouseEvent) => void) | null;\n onFocus?: ((event: React.FocusEvent) => void) | null;\n onBlur?: ((event: React.FocusEvent) => void) | null;\n onChange?: ((value: unknown) => void) | null;\n errorMessage?: string;\n isValid?: boolean;\n isRequired?: boolean;\n label?: string;\n}\n\nexport interface ValidatableComponentState {\n isFocused: boolean;\n isHovered: boolean;\n}\n\n/**\n * Base class that extends PureComponent with FormValidator integration.\n * Manages hover/focus state and renders error tooltips.\n */\nexport default class ValidatableComponent<\n P extends ValidatableComponentProps = ValidatableComponentProps,\n S extends ValidatableComponentState = ValidatableComponentState,\n> extends PureComponent<P, S> {\n static defaultProps: Partial<ValidatableComponentProps> = {\n formValidator: null,\n onMouseEnter: null,\n onMouseLeave: null,\n onFocus: null,\n onBlur: null,\n onChange: null,\n errorMessage: '',\n isValid: false,\n isRequired: false,\n label: '',\n };\n\n constructor(props: P) {\n super(props);\n const { formValidator } = props;\n\n if (formValidator) {\n formValidator.label = props.label ?? '';\n formValidator.validate();\n formValidator.registerOnUpdateListener(() => { this.forceUpdate(); });\n }\n\n this.state = { isFocused: false, isHovered: false } as S;\n\n this.onMouseEnter = this.onMouseEnter.bind(this);\n this.onMouseLeave = this.onMouseLeave.bind(this);\n this.onFocus = this.onFocus.bind(this);\n this.onBlur = this.onBlur.bind(this);\n this.hasError = this.hasError.bind(this);\n this.renderTooltip = this.renderTooltip.bind(this);\n this.onChange = this.onChange.bind(this);\n }\n\n componentDidMount(): void {\n setTimeout(() => this.setState({ isFocused: false, isHovered: false } as S), 1);\n }\n\n componentDidUpdate(prevProps: P): void {\n const { formValidator } = this.props;\n if (prevProps.formValidator && formValidator && prevProps.formValidator !== formValidator) {\n formValidator.registerOnUpdateListener(() => { this.forceUpdate(); });\n }\n }\n\n onMouseEnter(event: React.MouseEvent): void {\n const { onMouseEnter } = this.props;\n this.setState({ isHovered: true } as unknown as S);\n if (onMouseEnter) onMouseEnter(event);\n }\n\n onMouseLeave(event: React.MouseEvent): void {\n const { onMouseLeave } = this.props;\n this.setState({ isHovered: false } as unknown as S);\n if (onMouseLeave) onMouseLeave(event);\n }\n\n onFocus(event: React.FocusEvent): void {\n const { onFocus } = this.props;\n this.setState({ isFocused: true } as unknown as S);\n if (onFocus) onFocus(event);\n }\n\n onBlur(event: React.FocusEvent): void {\n const { formValidator, onBlur } = this.props;\n if (formValidator) formValidator.touched = true;\n this.setState({ isFocused: false } as unknown as S);\n if (onBlur) onBlur(event);\n }\n\n hasError(): boolean {\n const { errorMessage, isValid, formValidator } = this.props;\n return formValidator\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n }\n\n isRequired(): boolean {\n const { isRequired, formValidator } = this.props;\n return !!(isRequired\n || (formValidator && formValidator.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')));\n }\n\n renderTooltip(): React.ReactNode {\n const { errorMessage, formValidator } = this.props;\n const { isHovered, isFocused } = this.state;\n return (\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() : (errorMessage || '')}\n isVisible={this.hasError() && (isFocused || isHovered)}\n />\n );\n }\n\n onChange(newVal: unknown): void {\n const { onChange, formValidator } = this.props;\n if (formValidator) {\n let extractedVal = newVal;\n if (newVal && (newVal as React.ChangeEvent<HTMLInputElement>).target) {\n extractedVal = (newVal as React.ChangeEvent<HTMLInputElement>).target.value;\n }\n formValidator.set(extractedVal);\n }\n if (onChange) onChange(newVal);\n }\n}\n","import { useFormValidatorGroupInstance } from '@ahrowe/form-validation';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues } from '@ahrowe/form-validation';\nimport FormValidatorGroupWithForm from './FormValidatorGroupWithForm';\n\n/**\n * @ahrowe/ui's flavour of useFormValidatorGroup: the group it creates has\n * `.Form` attached and defaults `onSubmitError` to an error toast (see\n * FormValidatorGroupWithForm). Reuses the core package's reactive wiring\n * (useFormValidatorGroupInstance) so this and the pure hook share one\n * implementation of \"subscribe a function component to a group\".\n */\nexport function useFormValidatorGroup<\nTGroup extends FormGroup = FormGroup,\nTInitial = InferGroupValues<TGroup>\n>(\n groupDef: TGroup,\n { initialValues, onSubmit, onValidate, errorParser, onSubmitError }: FormValidatorGroupOptions<TGroup, TInitial> = {}\n): FormValidatorGroupWithForm<TGroup, TInitial> {\n return useFormValidatorGroupInstance(\n () => new FormValidatorGroupWithForm(groupDef, null, { initialValues, errorParser, onSubmitError }),\n onSubmit,\n onValidate,\n );\n}\n"],"mappings":"u/BAGA,IAAY,EAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,q6EIJa,GAAA,EAAA,EAAA,eAAwD,IAAI,EAOzE,SAAS,EACP,EACA,EACmB,CACnB,GAAI,CAAC,EAAQ,OAAO,GAAO,CAAC,EAC5B,GAAI,CAAC,EAAK,OAAO,EAEjB,IAAM,EAAiC,CAAE,GAAG,CAAO,EACnD,IAAK,IAAM,KAAO,EAChB,EAAO,GAAO,CACZ,GAAI,EAAkC,GACtC,GAAI,EAA+B,EACrC,EAEF,OAAO,CACT,CAEA,SAAS,EAAe,CAAE,WAAU,gBAAqC,CACvE,IAAM,GAAA,EAAA,EAAA,YAAoB,CAAa,EACjC,GAAA,EAAA,EAAA,aAAsB,EAAc,EAAQ,CAAY,EAAG,CAAC,EAAQ,CAAY,CAAC,EAEvF,OAAO,EAAA,EAAA,KAAC,EAAc,SAAf,CAA+B,QAAQ,UAAiC,CAAA,CACjF,CCbA,SAAgB,EACd,EACA,EACG,CAEH,IAAM,GAAA,EAAA,EAAA,YADiB,CACN,IAAM,GACvB,GAAI,CAAC,EAAU,OAAO,EAEtB,IAAM,EAAkC,CAAE,GAAG,CAAS,EACtD,IAAK,IAAM,KAAO,EAAO,CACvB,IAAM,EAAS,EAAkC,GAC7C,IAAU,IAAA,KAAW,EAAO,GAAO,EACzC,CACA,OAAO,CACT,CCrBA,IAAM,EAAmE,EACtE,EAAmB,SAAU,GAC7B,EAAmB,SAAU,GAC7B,EAAmB,OAAQ,CAC9B,EAEA,SAAS,EAAU,EAAqC,CACtD,GAAM,CACN,KAAK,GACL,QAAQ,GACR,WAAW,KACX,WAAW,KACX,sBAAwB,CAAC,EACzB,YAAY,EAAmB,QAC/B,YAAY,GACZ,aAAa,GACb,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,YAAa,CAAK,EACrC,EAAI,EAAe,GACnB,GAAA,EAAA,EAAA,QAAiC,IAAI,EAErC,CAAC,EAAY,IAAA,EAAA,EAAA,UAA0B,GAAY,CAAS,EAC5D,CAAC,EAAY,IAAA,EAAA,EAAA,UAAyC,IAAI,GAGhE,EAAA,EAAA,eAAgB,CAEV,IAAa,MAAM,EAAc,CAAQ,CAC/C,EAAG,CAAC,CAAQ,CAAC,GAGb,EAAA,EAAA,eAAgB,CACd,IAAM,EAAK,EAAQ,QACnB,GAAI,CAAC,EAAI,OACT,IAAM,EAAW,IAAI,mBAAqB,EAAc,EAAG,YAAY,CAAC,EAExE,OADA,EAAS,QAAQ,CAAE,MACN,EAAS,UAAU,CAAE,CACpC,EAAG,CAAC,CAAC,EAEL,SAAS,GAAiB,CACxB,IAAM,EAAO,CAAC,EACd,EAAgB,EAAI,CAAI,EACpB,IAAa,MAAM,EAAc,CAAI,CAC3C,CAGA,IAAM,EAAc,CAAE,OAAQ,GAAG,EAAa,GAAkC,GAAa,GAAI,EAC3F,EAAY,CAAE,OAAQ,EAAc,GAAc,OAAU,KAAM,EAExE,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,GAAI,EAAM,GAAI,GAAM,IAAA,GAAW,WAAA,EAAA,EAAA,SAAc,EAAE,UAAW,GAAc,EAAE,gBAAiB,EAAW,GAAY,IAAI,EAAG,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,WAArK,CACG,CAAC,IACA,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAE,gBAAiB,GAAc,EAAE,sBAAuB,GAAY,MAAM,EAC1F,MAAO,CAAE,GAAG,EAAa,GAAG,GAAY,MAAO,EAC/C,QAAS,EACT,KAAK,SACL,SAAU,EACV,WAAY,CAAE,SAAU,CAAM,IAAQ,SAAS,EAAe,CAAG,WANnE,EAQE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAE,eAAgB,GAAY,KAAK,EAAG,MAAO,GAAY,eAAQ,CAAW,CAAA,GAC/F,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,EAAA,cACN,WAAA,EAAA,EAAA,SAAc,EAAE,cAAe,GAAc,EAAE,oBAAqB,GAAY,IAAI,EACpF,MAAO,GAAY,IACpB,CAAA,CACE,KAEP,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAE,cAAe,GAAc,EAAE,oBAAqB,GAAY,IAAI,EACpF,MAAO,CAAE,GAAG,EAAW,GAAG,GAAY,IAAK,YAE3C,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAE,mBAAoB,GAAY,SAAS,EAAG,MAAO,GAAY,UAAW,IAAK,EACjG,UACE,CAAA,CACF,CAAA,CACF,GAET,4uDIrFA,SAAS,EAAe,CAAE,aAAuC,CAC/D,OACE,EAAA,EAAA,KAAC,MAAD,CACE,cAAY,UACZ,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,CAAS,EAC9C,MAAM,6BACN,QAAQ,cACR,KAAK,OACL,OAAO,iCAEP,EAAA,EAAA,KAAC,SAAD,CAAQ,GAAG,KAAK,GAAG,KAAK,EAAE,KAAK,YAAY,IAAM,CAAA,CAC9C,CAAA,CAET,CAEA,EAAe,aAAe,CAC5B,UAAW,IAAA,EACb,ECxBA,IAAA,EAAe,ECEH,EAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,OAAA,UACF,EAAA,CAAA,CAAA,EAEY,EAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,MAAA,QACA,EAAA,OAAA,SACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,EAEY,EAAL,SAAA,EAAA,OACL,GAAA,OAAA,SACA,EAAA,MAAA,QACA,EAAA,OAAA,UACF,EAAA,CAAA,CAAA,kHEdM,GAAA,EAAA,EAAA,YAA+C,SAAgB,CACnE,WAAW,GACX,WACA,YACA,QACA,iBAAiB,GACjB,wBAAwB,GACxB,mBAAmB,2BACnB,aAAa,GACb,GAAG,GACF,EAAK,CACN,IAAM,GAAA,EAAA,EAAA,QAAsC,IAAI,EAC1C,GAAA,EAAA,EAAA,QAA4D,IAAI,EAEtE,SAAS,EAAY,EAAW,EAAW,CACzC,GAAI,EAAU,OACd,IAAM,EAAS,SAAS,cAAc,KAAK,EAC3C,EAAO,MAAM,KAAO,GAAG,EAAE,IACzB,EAAO,MAAM,IAAM,GAAG,EAAE,IACxB,EAAO,MAAM,WAAa,EAC1B,EAAO,UAAU,IAAI,GAAO,MAAM,EAClC,EAAa,SAAS,YAAY,CAAM,EACxC,eAAiB,CACf,EAAa,SAAS,YAAY,CAAM,CAC1C,EAAG,EAAwB,IAAO,EAAE,CACtC,CAEA,SAAS,EAAU,EAAsC,CACvD,GAAI,CAAC,EAAa,QAAS,OAC3B,IAAM,EAAM,EAAa,QAAQ,sBAAsB,EACvD,EAAY,EAAM,QAAU,EAAI,EAAG,EAAM,QAAU,EAAI,CAAC,CAC1D,EAEA,EAAA,EAAA,qBAAoB,OAAY,CAC9B,WAAY,CACV,IAAM,EAAK,EAAa,QACnB,GACL,EAAY,EAAG,YAAc,EAAG,EAAG,aAAe,CAAC,CACrD,CACF,EAAE,GAEF,EAAA,EAAA,eAAgB,CACd,EAAa,QAAU,CACzB,CAAC,GAED,EAAA,EAAA,eAAgB,CACd,GAAI,IAAa,IAAA,IAAa,EAAY,OAC1C,IAAM,EAAS,EAAa,SAAS,cACrC,GAAI,CAAC,EAAQ,OACb,IAAM,EAAW,GAAkB,EAAa,UAAU,CAAC,EAE3D,OADA,EAAO,iBAAiB,QAAS,CAAO,MAC3B,EAAO,oBAAoB,QAAS,CAAO,CAC1D,EAAG,CAAC,EAAU,CAAU,CAAC,EAEzB,IAAM,EAAiF,CACrF,4BAA6B,GAAG,EAAsB,EACxD,EA0BA,OAxBI,IAAa,IAAA,IAyBf,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,GAAO,gBAClB,IAAK,EACL,MAAO,CACL,SAAU,EAAiB,SAAW,UACtC,GAAG,CACL,CACD,CAAA,GA9BC,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACO,YACX,QAAS,EAAa,IAAA,GAAa,GAAM,EAAU,CAAC,EACpD,MAAO,CACL,SAAU,WACV,GAAG,CACL,WAPF,CASG,GACD,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,GAAO,gBAClB,IAAK,EACL,MAAO,CACL,SAAU,EAAiB,SAAW,UACtC,GAAG,CACL,CACD,CAAA,CACE,GAcX,CAAC,ECxFK,EAAkD,CACtD,QAAS,EAAO,mBAChB,QAAS,EAAO,mBAChB,OAAQ,EAAO,iBACjB,EAEM,GAA4C,CAChD,QAAS,EAAO,kBAChB,MAAO,EAAO,gBACd,OAAQ,EAAO,iBACf,MAAO,EAAO,eAChB,EAEA,SAAS,EAAO,EAAkC,CAChD,GAAM,CACN,YACA,QACA,OAAO,EAAW,OAClB,YAAY,EAAgB,QAC5B,OAAO,EAAW,QAClB,cAAsB,CAAC,EACvB,WACA,OACA,YAAY,GACZ,WAAW,GACX,QAAQ,IAAA,GACR,MACA,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,SAAU,CAAK,EACxC,OACE,EAAA,EAAA,KAAC,SAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SACE,EAAO,OACP,EAAe,GACf,GAAc,GACd,EACG,EAAO,kBAAmB,GAAa,CAC1C,EACA,CACF,EACO,QACD,OACG,UACT,SAAU,GAAY,EACf,QACF,gBAEL,EAAA,EAAA,KAAC,EAAD,CAAQ,SAAU,GAAa,YAC7B,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,iBAAkB,GAAY,UAAU,EAAG,MAAO,GAAY,qBACtF,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,cAAe,GAAY,OAAO,EAAG,MAAO,GAAY,iBAAlF,CACG,GACC,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,uBAAwB,GAAY,gBAAgB,EAAG,MAAO,GAAY,2BAClG,EAAA,EAAA,KAAC,EAAD,CAAgB,UAAW,EAAO,iBAAoB,CAAA,CACnD,CAAA,EACH,MACJ,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAY,MAAO,EAC9B,EAAO,eAAgB,GACvB,EAAO,gBAAiB,CAAC,CAAC,CAC7B,CAAC,EACD,MAAO,GAAY,eALrB,CAOG,GAAO,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAuB,MAAO,CAAA,EAAI,KACzC,CACE,GACF,GACF,CAAA,CACC,CAAA,CACF,CAAA,CAEZ,CAEA,EAAO,UAAY,EACnB,EAAO,KAAO,EACd,EAAO,KAAO,ECjFd,SAAwB,GAAc,EAA2B,CAC/D,GAAM,CACN,eAAiB,KACjB,cAAgB,KAChB,cAAc,OACd,cAAc,SACd,oBAAoB,EAAgB,QACpC,wBAAwB,GACxB,yBAAyB,GACzB,mBAAmB,IAAA,GACnB,oBAAoB,EAAgB,QACpC,wBAAwB,GACxB,yBAAyB,GACzB,mBAAmB,IAAA,GACnB,oBAAoB,GACpB,sBAAsB,GACtB,WAAW,GACX,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,gBAAiB,CAAK,EAC/C,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,EAAO,cAAe,CAAC,GAAY,EAAO,oBAAqB,EAAW,GAAY,IAAI,EACxG,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,WAHzC,CAKG,CAAC,IACF,EAAA,EAAA,KAAC,EAAD,CACE,UAAW,EACX,SAAU,EACV,UAAW,EACX,KAAM,EAAW,OACjB,QAAS,EACT,UAAW,GAAY,aACvB,MAAO,GAAY,aACnB,KAAM,WAEL,CACK,CAAA,EAEP,CAAC,IACA,EAAA,EAAA,KAAC,EAAD,CACE,UAAW,EACX,SAAU,EACV,QAAS,EACT,UAAW,EACX,UAAW,GAAY,aACvB,MAAO,GAAY,aACnB,KAAM,WAEL,CACK,CAAA,CAEP,GAET,kDExCM,GAAkB,EAAA,QAAM,YAC3B,CAAE,YAAW,WAAU,UAAS,cAAa,YAAW,WAAW,EAAG,QAAO,GAAG,GAAS,IAAsB,CAC9G,IAAM,GAAA,EAAA,EAAA,aACH,GAAkE,CAC5D,EAA0B,MAAQ,SACrC,IAAU,CAA+B,EAE3C,IAAY,CAAkC,CAChD,EACA,CAAC,EAAS,CAAS,CACrB,EAEA,OACE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,CAAS,EACtC,UACI,cACb,SAAU,GAAwB,EAClC,KAAK,SACL,UAAW,EACN,MACE,QACP,GAAI,EAEH,UACE,CAAA,CAET,CACF,EAEA,GAAgB,YAAc,kBCrD9B,IAAA,EAAe,qCEOf,SAAS,EAAW,CAClB,OACA,YAAY,GACZ,QACA,QAAQ,GACR,cAAgB,CAAC,EACjB,aACA,OAAQ,EACR,GAAG,GAC6B,CAChC,OACE,EAAA,EAAA,KAAC,EAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,EAAO,WAAY,EAAW,GAAY,IAAI,EAC5D,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EAChC,QACE,oBAET,EAAA,EAAA,KAAC,EAAA,gBAAD,CACQ,OACN,UAAW,GAAY,KACvB,MAAO,GAAY,IACpB,CAAA,CACc,CAAA,CAErB,CC9BA,IAAY,EAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,KAAA,OACA,EAAA,QAAA,UACA,EAAA,KAAA,OACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,m1BEQM,GAAuD,EAC1D,EAAe,SAAU,EAAA,QACzB,EAAe,MAAO,EAAA,cACtB,EAAe,SAAU,EAAA,eACzB,EAAe,MAAO,EAAA,uBACtB,EAAe,OAAQ,EAAA,aAC1B,EAEM,GAAiD,EACpD,EAAe,SAAU,EAAO,mBAChC,EAAe,MAAO,EAAO,gBAC7B,EAAe,SAAU,EAAO,mBAChC,EAAe,MAAO,EAAO,gBAC7B,EAAe,OAAQ,EAAO,eACjC,EAEA,SAAS,GAAM,EAAiC,CAC9C,GAAM,CACN,QACA,WAAW,KACX,YAAY,EAAe,QAC3B,OACA,WAAW,GACX,UACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,QAAS,CAAK,EAEvC,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,KAAK,QACL,WAAA,EAAA,EAAA,SAAc,EAAO,MAAO,GAAe,GAAY,GAAY,KAAM,CAAS,EAClF,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,WAJzC,CAMG,CAAC,IACA,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,GAAQ,GAAc,GAC5B,WAAA,EAAA,EAAA,SAAc,EAAO,UAAW,GAAY,IAAI,EAChD,MAAO,GAAY,IACpB,CAAA,GAGH,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,aAAc,GAAY,OAAO,EAAG,MAAO,GAAY,iBAAjF,CACG,IACC,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,WAAY,GAAY,KAAK,EAAG,MAAO,GAAY,eAC1E,CACE,CAAA,EAEN,IACC,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,iBAAkB,GAAY,WAAW,EAAG,MAAO,GAAY,YACtF,UACE,CAAA,CAEJ,IAEJ,IACC,EAAA,EAAA,KAAC,EAAD,CACE,KAAM,EAAA,QACN,QAAS,EACT,WAAA,EAAA,EAAA,SAAc,EAAO,iBAAkB,GAAY,WAAW,EAC9D,MAAO,GAAY,YACnB,aAAW,SACZ,CAAA,CAEA,GAET,o8CEjFM,GACJ,8qBAEI,GAAmB,0BAEzB,SAAS,GAAa,EAAwC,CAC5D,GAAM,CACJ,OAAO,GACP,UAAU,GACV,OAAO,GACP,QACA,WAAW,IACX,OAAO,GACP,OAAO,GACP,OAAO,GACP,QAAQ,GACR,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAEE,GAAA,EAAA,EAAA,QAAiC,IAAI,EACrC,CAAC,EAAO,IAAA,EAAA,EAAA,UAAqB,EAAK,GAExC,EAAA,EAAA,eAAgB,CACd,IAAM,EAAS,EAAQ,QACvB,GAAI,CAAC,EAAQ,OAEb,EAAS,EAAK,EACd,IAAM,EAAS,EAAO,eAAe,EACrC,EAAO,MAAM,YAAY,yBAA0B,OAAO,CAAM,CAAC,EACjE,EAAO,MAAM,gBAAkB,OAAO,CAAM,EAC5C,EAAO,MAAM,iBAAmB,OAAO,CAAM,EAE7C,IAAM,EAAQ,0BAA4B,EAAS,EAAI,CAAC,EACxD,UAAa,qBAAqB,CAAK,CACzC,EAAG,CAAC,CAAI,CAAC,EAET,IAAM,EAA2B,CAC/B,kBAAmB,GAAG,EAAS,GAC/B,GAAI,EAAQ,CAAE,OAAQ,EAAO,KAAM,CAAM,EAAI,IAAA,GAC7C,GAAG,GAAY,IACjB,EAEA,OACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,EAAO,aAAc,CAAS,EAC5C,MAAO,CAAE,MAAO,EAAM,OAAQ,EAAM,GAAG,CAAM,EACpC,UACT,MAAM,uCAEN,EAAA,EAAA,KAAC,IAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAS,IAAU,EAAO,EAAO,sBAAwB,EAAO,sBAAsB,EACpG,MAAO,CAAE,kBAAmB,GAAG,EAAS,EAAG,YAE3C,EAAA,EAAA,KAAC,IAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAS,IAAS,EAAO,EAAO,qBAAuB,EAAO,qBAAqB,EACjG,MAAO,CAAE,kBAAmB,GAAG,EAAS,EAAG,YAE3C,EAAA,EAAA,KAAC,OAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SACE,EAAO,iBACP,IACG,EACG,EACE,EAAO,qBACP,EAAO,2BACT,EACE,EAAO,qBACP,EAAO,4BACf,GAAY,IACd,EACA,MAAO,EACP,YAAa,GACb,eAAe,QACf,cAAc,QACd,EAAG,CACJ,CAAA,CACA,CAAA,CACF,CAAA,CACA,CAAA,CAET,CCzFA,IAAY,EAAL,SAAA,EAAA,OAEL,GAAA,OAAA,UAEA,EAAA,OAAA,UAEA,EAAA,OAAA,SAEA,EAAA,WAAA,aAEA,EAAA,SAAA,WAEA,EAAA,OAAA,SAEA,EAAA,KAAA,OAEA,EAAA,MAAA,QAEA,EAAA,UAAA,aACF,EAAA,CAAA,CAAA,EAMY,GAAL,SAAA,EAAA,OAEL,GAAA,OAAA,SAEA,EAAA,KAAA,QACF,EAAA,CAAA,CAAA,69DE3BA,SAAS,IAAgC,CACvC,OAAO,OAAO,OAAW,KAAe,OAAO,OAAO,YAAe,WACjE,OAAO,WAAW,kCAAkC,EAAE,QACtD,EACN,CAKA,IAAM,GAAuE,EAC1E,EAAoB,QAAS,GAAO,2BACpC,EAAoB,QAAS,GAAO,2BACpC,EAAoB,QAAS,GAAO,2BACpC,EAAoB,QAAS,GAAO,yBACvC,EAEA,SAAS,GAAW,EAAc,EAAkC,CAClE,OAAO,IAAS,GAAiB,KAAO,EAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EAAI,MAAM,KAAK,CAAI,CAC3F,CAcA,SAAS,GAAW,CAAE,QAAO,OAAM,eAAc,aAAY,cAA+B,CAC1F,GAAM,CAAC,EAAa,IAAA,EAAA,EAAA,cACd,EAAM,SAAW,EAAU,EACxB,GAAqB,EAAI,EAAM,OAAS,CAChD,GAED,EAAA,EAAA,eAAgB,CACd,GAAI,EAAM,QAAU,GAAK,GAAqB,EAAG,OACjD,IAAI,EAAW,EACT,EAAK,gBAAkB,CAC3B,GAAY,EACZ,EAAe,CAAQ,EACnB,GAAY,EAAM,QAAQ,cAAc,CAAE,CAChD,EAAG,CAAY,EACf,UAAa,cAAc,CAAE,CAC/B,EAAG,CAAC,EAAO,CAAY,CAAC,EAExB,IAAM,EAAS,GAAe,EAAM,OAEpC,OACE,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CACG,EAAM,MAAM,EAAG,CAAW,EAAE,KAAK,EAAU,KAC1C,EAAA,EAAA,MAAC,EAAA,SAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,6BAA8B,GAAY,MAAM,EAAG,MAAO,GAAY,gBAC9F,CACG,CAAA,EACL,IAAS,GAAiB,MAAQ,EAAQ,EAAc,EAAI,IAAM,IAC3D,CAAA,EALK,CAKL,CACX,GACD,EAAA,EAAA,KAAC,OAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,mBAAoB,GAAU,GAAO,2BAA4B,GAAY,MAAM,EACxG,MAAO,GAAY,MACpB,CAAA,CACD,CAAA,CAAA,CAEN,CAEA,IAAM,GAAmB,wEACnB,GAAmB,GAEzB,SAAS,GAAmB,EAAwB,CAClD,OAAO,MAAM,KAAK,CAAE,QAAO,MAAS,GAAiB,KAAK,MAAM,KAAK,OAAO,EAAI,EAAuB,EAAE,EAAE,KAAK,EAAE,CACpH,CAaA,SAAS,GAAS,CAAE,QAAO,OAAM,eAAc,aAAY,cAA6B,CACtF,GAAM,CAAC,IAAA,EAAA,EAAA,UAAyB,EAAoB,EAC9C,CAAC,EAAM,IAAA,EAAA,EAAA,UAAoB,CAAC,GAElC,EAAA,EAAA,eAAgB,CACd,GAAI,EAAM,SAAW,GAAK,EAAc,OACxC,IAAI,EAAI,EACF,EAAa,KAAK,KAAM,EAAM,OAAS,EAAgB,EAAgB,EAAI,EAC3E,EAAK,gBAAkB,CAC3B,GAAK,EACL,EAAQ,CAAC,EACL,GAAK,GAAY,cAAc,CAAE,CACvC,EAAG,EAAgB,EACnB,UAAa,cAAc,CAAE,CAC/B,EAAG,CAAC,EAAO,EAAc,CAAY,CAAC,EAEtC,IAAM,EAAe,KAAK,IAAI,EAAM,OAAQ,KAAK,MAAO,EAAO,GAAoB,CAAY,CAAC,EAEhG,OACE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAA,SACG,EAAM,KAAK,EAAU,IAAU,CAC9B,IAAM,EAAY,GAAgB,EAAQ,EAC1C,OACE,EAAA,EAAA,MAAC,EAAA,SAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,2BAA4B,GAAY,MAAM,EAAG,MAAO,GAAY,gBAC5F,IAAa,IAAM,IAAM,EAAY,EAAW,GAAmB,EAAS,MAAM,CAC/E,CAAA,EACL,IAAS,GAAiB,MAAQ,EAAQ,EAAM,OAAS,EAAI,IAAM,IAC5D,CAAA,EALK,CAKL,CAEd,CAAC,CACD,CAAA,CAEN,CAEA,SAAS,GAAa,CACpB,OACA,UAAU,EAAoB,OAC9B,OAAO,GAAiB,OACxB,eAAe,GACf,WACA,gBAAgB,GAChB,YACA,QACA,aACA,OAAQ,EACR,GAAG,GAC+B,CAClC,IAAM,GAAA,EAAA,EAAA,aAAsB,GAAW,EAAM,CAAI,EAAG,CAAC,EAAM,CAAI,CAAC,EAC1D,GAAA,EAAA,EAAA,QAAkC,IAAI,EAMtC,CAAC,EAAW,IAAA,EAAA,EAAA,cAA+B,CAAC,GAAiB,OAAO,qBAAyB,GAAW,GAE9G,EAAA,EAAA,eAAgB,CACd,GAAI,EAAW,OACf,IAAM,EAAO,EAAQ,QACrB,GAAI,CAAC,EAAM,OACX,IAAM,EAAW,IAAI,sBAAsB,CAAC,KAAW,CACjD,GAAO,iBACT,EAAa,EAAI,EACjB,EAAS,WAAW,EAExB,CAAC,EAED,OADA,EAAS,QAAQ,CAAI,MACR,EAAS,WAAW,CACnC,EAAG,CAAC,CAAS,CAAC,EAQd,IAAM,EAAY,GAAG,EAAQ,GAAG,EAAK,GAAG,EAAK,GAAG,EAAa,GAAG,GAAY,KAExE,EAEJ,GAAI,CAAC,EAEH,GACE,EAAA,EAAA,KAAC,OAAD,CAAM,cAAY,OAAO,MAAO,CAAE,QAAS,CAAE,WAC1C,CACG,CAAA,OAEH,GAAI,IAAY,EAAoB,MACzC,GACE,EAAA,EAAA,KAAC,OAAD,CAEE,cAAY,OACZ,WAAA,EAAA,EAAA,SAAc,GAAO,kBAAmB,GAAY,MAAM,EAC1D,MAAO,CAAE,kBAAmB,GAAG,GAAY,IAAK,IAAK,GAAG,GAAY,MAAO,WAE1E,CACG,EANC,CAMD,OAEH,GAAI,IAAY,EAAoB,UACzC,GACE,EAAA,EAAA,KAAC,OAAD,CAEE,cAAY,OACZ,WAAA,EAAA,EAAA,SAAc,GAAO,sBAAuB,GAAY,MAAM,EAC9D,MAAO,CAAE,kBAAmB,GAAG,GAAY,IAAI,IAAK,GAAG,GAAY,MAAO,WAEzE,CACG,EANC,CAMD,OAEH,GAAI,IAAY,EAAoB,WACzC,GACE,EAAA,EAAA,KAAC,OAAD,CAAsB,cAAY,iBAChC,EAAA,EAAA,KAAC,GAAD,CAAmB,QAAa,OAAoB,eAA0B,aAAwB,YAAa,CAAA,CAC/G,EAFK,CAEL,OAEH,GAAI,IAAY,EAAoB,SACzC,GACE,EAAA,EAAA,KAAC,OAAD,CAAsB,cAAY,iBAChC,EAAA,EAAA,KAAC,GAAD,CAAiB,QAAa,OAAoB,eAA0B,aAAwB,YAAa,CAAA,CAC7G,EAFK,CAEL,OAEH,GAAI,IAAY,EAAoB,KACzC,GACE,EAAA,EAAA,KAAC,OAAD,CAAsB,cAAY,gBAC/B,EAAM,KAAK,EAAU,KACpB,EAAA,EAAA,MAAC,EAAA,SAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,OAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,mBAAoB,GAAO,wBAAyB,GAAY,MAAM,EAC3F,MAAO,CAIL,eAAgB,IAAI,EAAQ,EAAa,IACzC,kBAAmB,GAAG,GAAY,KAAK,IACvC,GAAG,GAAY,MACjB,WAEC,IAAa,IAAM,IAAM,CACtB,CAAA,EACL,IAAS,GAAiB,MAAQ,EAAQ,EAAM,OAAS,EAAI,IAAM,IAC5D,CAAA,EAfK,CAeL,CACX,CACG,EAnBK,CAmBL,MAEH,CACL,IAAM,EAAgB,GAAuB,IAAY,GAAO,0BAChE,GACE,EAAA,EAAA,KAAC,OAAD,CAAsB,cAAY,gBAC/B,EAAM,KAAK,EAAU,KACpB,EAAA,EAAA,MAAC,EAAA,SAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,OAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,mBAAoB,EAAe,GAAY,MAAM,EAC1E,MAAO,CACL,eAAgB,GAAG,EAAQ,EAAa,IACxC,kBAAmB,GAAG,GAAY,IAAI,IACtC,GAAG,GAAY,MACjB,WAEC,IAAa,IAAM,IAAM,CACtB,CAAA,EACL,IAAS,GAAiB,MAAQ,EAAQ,EAAM,OAAS,EAAI,IAAM,IAC5D,CAAA,EAZK,CAYL,CACX,CACG,EAhBK,CAgBL,CAEV,CAEA,OACE,EAAA,EAAA,MAAC,OAAD,CAAM,GAAI,EAAM,IAAK,EAAS,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,CAAS,EAAU,iBAApF,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,GAAO,oCAA6B,CAAW,CAAA,EAC/D,CACG,GAEV,CCzQA,IAAY,GAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,KAAA,OACA,EAAA,KAAA,OACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,EAEY,GAAL,SAAA,EAAA,OACL,GAAA,SAAA,YACA,EAAA,QAAA,WACA,EAAA,YAAA,eACA,EAAA,WAAA,eACF,EAAA,CAAA,CAAA,irCETM,GAAiD,EACpD,GAAe,SAAU,GAAO,mBAChC,GAAe,SAAU,GAAO,mBAChC,GAAe,SAAU,GAAO,mBAChC,GAAe,MAAO,GAAO,gBAC7B,GAAe,MAAO,GAAO,gBAC7B,GAAe,OAAQ,GAAO,eACjC,EAEM,GAAmD,EACtD,GAAc,UAAW,GAAO,uBAChC,GAAc,SAAU,GAAO,sBAC/B,GAAc,aAAc,GAAO,0BACnC,GAAc,YAAa,GAAO,uBACrC,EAEA,SAAS,GAAM,EAAiC,CAC9C,GAAM,CACN,QACA,MAAM,GACN,UACA,MAAM,GACN,WAAW,GACX,YAAY,GAAe,QAC3B,WAAW,GAAc,SACzB,WAAW,KACX,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,QAAS,CAAK,EACjC,EAAW,OAAO,GAAU,SAC5B,EAAa,GAAW,KAExB,GAAa,GAAO,GAAc,IAAa,EAD9B,CAAC,GAAO,CAAC,GAAc,GAAY,IAAU,GAAK,CAAC,GAGpE,EAAe,EAAa,EAAU,EAAY,EAAQ,EAAM,GAAG,EAAI,GAAK,EAAS,KACrF,EAAY,GAAY,KAE9B,OACE,EAAA,EAAA,MAAC,OAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,GAAO,QAAS,CAAS,EAChC,iBAHT,CAKG,EACA,IACC,EAAA,EAAA,KAAC,OAAD,CACE,WAAA,EAAA,EAAA,SACE,GAAO,MACP,GAAe,GACf,GAAO,GAAO,SACd,GAAa,GAAO,aACpB,GAAa,GAAkB,GAC/B,GAAY,KACd,EACA,MAAO,GAAY,eAElB,CAAC,GAAO,CACL,CAAA,CAEJ,GAEV,2YE/DM,GAAqD,CACzD,OAAQ,GAAe,QACvB,KAAM,GAAe,KACrB,KAAM,GAAe,MACrB,QAAS,GAAe,OAC1B,EAEA,SAAS,GAAY,EAAuB,CAC1C,GAAI,CAAC,EAAM,MAAO,GAClB,IAAM,EAAQ,EAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO,EAGrD,OAFI,EAAM,SAAW,EAAU,GAC3B,EAAM,SAAW,EAAU,EAAM,GAAG,MAAM,EAAG,CAAC,EAAE,YAAY,GACxD,EAAM,GAAG,GAAK,EAAM,EAAM,OAAS,GAAG,IAAI,YAAY,CAChE,CAEA,SAAS,GAAO,CACd,MACA,MACA,OACA,OAAO,EAAA,OACP,UACA,SACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACyB,CAC5B,GAAM,CAAC,EAAU,IAAA,EAAA,EAAA,UAAwB,EAAK,EACxC,CAAC,EAAS,IAAA,EAAA,EAAA,UAAuB,CAAG,EAEtC,IAAQ,IACV,EAAW,CAAG,EACd,EAAY,EAAK,GAGnB,IAAM,EAAW,GAAY,CAAI,EAG3B,EAFc,GAAO,CAAC,GAG1B,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,KAAK,EACnD,MAAO,GAAY,MACd,MACL,IAAK,GAAO,GAAQ,GACpB,YAAe,EAAY,EAAI,CAChC,CAAA,GAED,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,QAAQ,EAAG,MAAO,GAAY,kBAClF,IAAY,IAAY,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAuB,MAAO,CAAA,EACnD,CAAA,EAWR,OARK,GASH,EAAA,EAAA,KAAC,GAAD,CACE,GAAI,EACJ,IAAA,GACA,SAAU,GAAc,YACxB,UAAW,GAAa,GACb,YACJ,QACP,WAAY,CAAE,OAAA,EAAA,EAAA,SAAU,GAAO,kBAAmB,GAAY,MAAM,CAAE,EACtE,OAAQ,CAAE,MAAO,GAAY,MAAO,YAEpC,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,GAAO,gBAAS,CAAe,CAAA,CAC3C,CAAA,GAlBL,EAAA,EAAA,KAAC,OAAD,CAAM,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,OAAQ,CAAS,EAAU,iBAC7D,CACG,CAAA,CAkBZ,CC7EA,SAAS,GAAY,CACnB,WACA,MACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,GAC8B,CACjC,IAAM,EAAQ,EAAA,SAAS,QAAQ,CAAQ,EACjC,EAAU,GAAO,KAA6B,EAAtB,EAAM,MAAM,EAAG,CAAG,EAC1C,EAAW,GAAO,KAA4B,EAArB,EAAM,OAAS,EAE9C,OACE,EAAA,EAAA,MAAC,OAAD,CAAM,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,EAAU,iBAArE,CACG,EAAQ,KAAK,EAAO,KACnB,EAAA,EAAA,KAAC,OAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,IAAI,EACtD,MAAO,GAAY,cAElB,CACG,EALC,CAKD,CACP,EACA,EAAW,IACV,EAAA,EAAA,KAAC,OAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,QAAQ,EAC1D,MAAO,GAAY,mBAEnB,EAAA,EAAA,KAAC,GAAD,CAAQ,QAAS,IAAI,GAAa,CAAA,CAC9B,CAAA,CAEJ,GAEV,CC7BA,SAAS,GAAQ,CAAE,WAAW,MAA2C,CACvE,IAAM,EAAS,SAAS,eAAe,SAAS,EAOhD,OANK,GAML,EAAA,EAAA,cAAoB,EAAU,CAAM,EAF3B,IAGX,wjDEfA,SAAgB,GAAuB,EAAgC,CACrE,IAAM,EAA2B,CAAC,EAC9B,EAAO,EAAG,cACd,KAAO,GAAQ,IAAS,SAAS,MAAQ,IAAS,SAAS,iBAAiB,CAC1E,IAAM,EAAQ,iBAAiB,CAAI,GAC/B,EAAM,YAAc,WAAa,EAAM,YAAc,YAAW,EAAU,KAAK,CAAI,EACvF,EAAO,EAAK,aACd,CACA,OAAO,CACT,CAEA,SAAgB,GAAsB,EAAe,EAAmC,CACtF,OAAO,EAAU,KAAM,GAAa,CAClC,IAAM,EAAI,EAAS,sBAAsB,EACzC,OAAO,EAAK,QAAU,EAAE,KAAO,EAAK,KAAO,EAAE,QAAU,EAAK,OAAS,EAAE,MAAQ,EAAK,MAAQ,EAAE,KAChG,CAAC,CACH,CCKA,SAAgB,GAAoB,CAAE,SAAQ,aAAY,YAAW,WAAU,gBAAe,YAAY,UAAqC,EAC7I,EAAA,EAAA,qBAAsB,CACpB,GAAI,CAAC,EAAQ,OAEb,IAAI,EACA,EAOJ,SAAS,GAAW,CAClB,IAAM,EAAU,EAAW,QACrB,EAAS,EAAU,QACzB,GAAI,CAAC,GAAW,CAAC,EAAQ,CACvB,EAAQ,sBAAsB,CAAQ,EACtC,MACF,CACA,IAAM,EAAY,GAAuB,CAAO,EAEhD,SAAS,GAAY,CACnB,IAAM,EAAO,EAAS,sBAAsB,EACtC,EAAc,EAAS,SAAS,cAAgB,EAChD,EAAa,OAAO,YAAc,EAAK,OACvC,EAAa,EAAK,IAClB,EAAiB,IAAc,MAAQ,EAAa,EAEpD,EAAO,EAAiB,IADP,IAAc,MAAQ,EAAa,GACI,EACxD,EAAc,IAAc,MAAQ,CAAC,EAAO,EAClD,EAAQ,UAAU,OAAO,EAAe,CAAI,EAK5C,EAAQ,MAAM,IAAM,GAAG,EAAc,EAAK,IAAM,EAAQ,aAAe,EAAK,OAAO,IACnF,EAAQ,MAAM,KAAO,GAAG,EAAK,KAAK,IAClC,EAAQ,MAAM,WAAa,GAAsB,EAAM,CAAS,EAAI,SAAW,EACjF,CAEA,EAAU,EAEV,IAAM,EAA0C,CAAC,OAAQ,GAAG,CAAS,EACrE,EAAc,QAAS,GAAM,EAAE,iBAAiB,SAAU,EAAW,CAAE,QAAS,EAAK,CAAC,CAAC,EACvF,OAAO,iBAAiB,SAAU,CAAS,EAC3C,MAAiB,CACf,EAAc,QAAS,GAAM,EAAE,oBAAoB,SAAU,CAAS,CAAC,EACvE,OAAO,oBAAoB,SAAU,CAAS,CAChD,CACF,CAIA,OAFA,EAAS,MAEI,CACP,IAAU,IAAA,IAAW,qBAAqB,CAAK,EACnD,IAAW,CACb,CACF,EAAG,CAAC,EAAQ,EAAY,EAAW,EAAU,EAAe,CAAS,CAAC,CACxE,CClFA,IAAY,GAAL,SAAA,EAAA,OACL,GAAA,KAAA,OACA,EAAA,MAAA,QACA,EAAA,OAAA,UACF,EAAA,CAAA,CAAA,ECCA,SAAS,GAAW,EAAW,CAC7B,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,EAAI,EAAE,MAAM,CAAC,CAC9C,CAEA,SAAS,GAAa,CACpB,QAAQ,GAAM,KACd,WAAW,KACX,UAAU,KACV,SAAS,GACT,mBAAqB,CAAC,EACtB,wBAAwB,GACxB,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACiB,CACpB,IAAM,GAAA,EAAA,EAAA,QAA0C,IAAI,EAC9C,GAAA,EAAA,EAAA,QAAqC,IAAI,EACzC,GAAA,EAAA,EAAA,QAAoC,IAAI,EACxC,GAAA,EAAA,EAAA,QAAyB,CAAY,EACrC,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,EAAE,EAE7C,GAAA,EAAA,EAAA,QAA8B,EAAK,EACzC,SAAS,GAAuB,CAC9B,EAAqB,QAAU,EACjC,EAEA,EAAA,EAAA,eAAgB,CAAE,EAAgB,QAAU,CAAc,CAAC,EAE3D,SAAS,GAAqB,CAC5B,GAAI,CAAC,EAAQ,CACX,IAAM,EAAO,EAAW,SAAS,sBAAsB,EACvD,EAAgB,GAAM,OAAS,EAAE,EACjC,EAAa,EAAI,CACnB,CACF,CAmCA,OAjCA,GAAoB,CAClB,SACA,aACA,UAAW,EACX,SAAU,EACV,cAAe,GAAO,oBACxB,CAAC,GAED,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,EAAQ,OAEb,SAAS,EAAU,EAAmB,CACpC,IAAM,EAAW,EAAiB,QAC5B,EAAc,EAAW,QAC/B,GAAI,CAAC,GAAY,CAAC,EAAa,OAE/B,IAAM,EAAoB,EAAqB,QAC/C,EAAqB,QAAU,GAE/B,IAAM,EACJ,GAAqB,IAAa,EAAM,QAAU,EAAS,SAAS,EAAM,MAAc,EACpF,EAAiB,IACpB,IAAgB,EAAM,QAAU,EAAY,SAAS,EAAM,MAAc,GAExE,CAAC,GAAe,CAAC,GACnB,EAAgB,QAAQ,EAAK,CAEjC,CAGA,OADA,OAAO,iBAAiB,UAAW,CAAS,MAC/B,OAAO,oBAAoB,UAAW,CAAS,CAC9D,EAAG,CAAC,EAAQ,CAAqB,CAAC,GAGhC,EAAA,EAAA,MAAC,MAAD,CAAK,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,EAAW,GAAY,IAAI,EAAG,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,WAAvH,EACE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,oBAAqB,GAAY,OAAO,EAC7D,MAAO,GAAY,QACnB,IAAK,EACL,QAAS,EAER,UACE,CAAA,EACJ,IACC,EAAA,EAAA,KAAC,GAAD,CAAA,UACE,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,iBAAkB,GAAY,IAAI,EACvD,MAAO,CACL,MAAO,GAAG,EAAa,IACvB,GAAG,GAAY,IACjB,WANF,EAQE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SACH,GAAO,0BACP,GAAO,iCAAiC,GAAW,CAAK,IAC1D,CAAI,CAAA,GACJ,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SACE,GAAO,sBACP,GAAO,6BAA6B,GAAW,CAAK,KACpD,GAAY,aACd,EACA,MAAO,GAAY,cACnB,iBAAkB,WAEjB,CACE,CAAA,CACF,GACE,CAAA,CAER,GAET,q9BErGA,SAAS,GAAU,EAAyB,EAAmB,CAC7D,IAAM,EAAU,EAAM,KAAK,EAAM,KAAW,CAAE,OAAM,OAAM,EAAE,EAC5D,GAAI,CAAC,GAAY,EAAM,QAAU,EAC/B,MAAO,CAAE,QAAS,EAAS,OAAQ,CAAC,EAAoB,SAAU,CAAC,CAAmB,EAGxF,IAAM,EAAgB,KAAK,IAAI,EAAG,EAAW,CAAC,EACxC,EAAc,EAAM,OAAS,EAAI,EAKvC,OAJI,GAAe,EACV,CAAE,QAAS,EAAS,OAAQ,CAAC,EAAoB,SAAU,CAAC,CAAmB,EAGjF,CACL,QAAS,EAAQ,MAAM,EAAG,CAAC,EAC3B,OAAQ,EAAQ,MAAM,EAAG,EAAI,CAAW,EACxC,SAAU,EAAQ,MAAM,EAAI,CAAW,CACzC,CACF,CAEA,SAAS,GAAW,EAAsC,CACxD,GAAM,CACJ,QAAQ,CAAC,EACT,YACA,WACA,aAAc,EAAY,aAC1B,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,aAAc,CAAK,EAEtC,CAAC,EAAkB,IAAA,EAAA,EAAA,UAAgC,EAAK,EACxD,CAAE,UAAS,SAAQ,YAAa,GAAU,EAAO,CAAQ,EACzD,EAAY,EAAM,OAAS,EAEjC,SAAS,EAAqB,EAAe,CAE3C,OADI,IAAU,EAAkB,MAE9B,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,oBAAqB,GAAY,SAAS,EAAG,MAAO,GAAY,mBACxF,IAAa,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,cAAiB,CAAA,CAClD,CAAA,CAEV,CAEA,SAAS,EAAW,CAAE,OAAM,SAAsB,CAChD,OACE,EAAA,EAAA,MAAC,KAAD,CAA2B,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,IAAI,EAAG,MAAO,GAAY,cAAtG,CACG,GAAY,EAAM,IAAU,EAAW,GAAQ,EAAY,CAAU,EACrE,EAAqB,CAAK,CACzB,GAHK,EAAK,IAAM,CAGhB,CAER,CAEA,OACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACJ,aAAY,EACZ,WAAA,EAAA,EAAA,SAAc,GAAO,WAAY,GAAY,KAAM,CAAS,EAC5D,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,YAEvC,EAAA,EAAA,MAAC,KAAD,CAAI,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,IAAI,EAAG,MAAO,GAAY,cAA/E,CACG,EAAQ,IAAI,CAAU,EAEtB,EAAO,OAAS,IACf,EAAA,EAAA,MAAC,KAAD,CAAI,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,IAAI,EAAG,MAAO,GAAY,cAA/E,EACE,EAAA,EAAA,KAAC,GAAD,CACE,OAAQ,EACR,aAAc,EACd,SACE,EAAA,EAAA,KAAC,KAAD,CAAI,WAAA,EAAA,EAAA,SAAc,GAAO,qBAAsB,GAAY,UAAU,EAAG,MAAO,GAAY,oBACxF,EAAO,KAAK,CAAE,OAAM,YACnB,EAAA,EAAA,KAAC,KAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,qBAAsB,GAAY,UAAU,EACjE,MAAO,GAAY,oBAElB,GACC,CACE,GAAG,EACH,QAAU,GAAU,CAClB,EAAK,UAAU,CAAK,EACpB,EAAoB,EAAK,CAC3B,CACF,EACA,GACA,GACA,EACA,CACF,CACE,EAjBG,EAAK,IAAM,CAiBd,CACL,CACC,CAAA,YAGN,EAAA,EAAA,KAAC,EAAD,CACE,KAAM,EAAA,WACN,MAAM,0BACN,aAAW,0BACX,WAAA,EAAA,EAAA,SAAc,GAAO,mBAAoB,GAAY,QAAQ,EAC7D,MAAO,GAAY,QACpB,CAAA,CACW,CAAA,EACb,EAAqB,EAAO,EAAO,OAAS,GAAG,KAAK,CACnD,IAGL,EAAS,IAAI,CAAU,CACtB,GACD,CAAA,CAET,CAEA,SAAS,GACP,EACA,EACA,EACA,EACA,EACA,CACA,IAAM,GACJ,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CACG,EAAK,OACJ,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,EAAK,KACX,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,GAAY,IAAI,EACrD,MAAO,GAAY,IACpB,CAAA,EAEF,EAAK,KACN,CAAA,CAAA,EAgDJ,OA7CI,GAEA,EAAA,EAAA,KAAC,OAAD,CACE,eAAa,OACb,WAAA,EAAA,EAAA,SAAc,EAAO,kBAAmB,GAAY,OAAO,EAC3D,MAAO,GAAY,iBAElB,CACG,CAAA,EAIN,EAAK,UAEL,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,EAAO,uBAAwB,GAAY,IAAI,EAAG,MAAO,GAAY,cAC7G,CACG,CAAA,EAIN,EAAK,MAEL,EAAA,EAAA,KAAC,IAAD,CACE,KAAM,EAAK,KACX,QAAS,EAAK,QACd,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,GAAY,IAAI,EACrD,MAAO,GAAY,cAElB,CACA,CAAA,EAIH,EAAK,SAEL,EAAA,EAAA,KAAC,EAAD,CACE,QAAS,EAAK,QACd,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,GAAY,IAAI,EACrD,MAAO,GAAY,cAElB,CACc,CAAA,GAKnB,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,EAAO,uBAAwB,GAAY,IAAI,EAAG,MAAO,GAAY,cAC7G,CACG,CAAA,CAEV,CCrMA,IAAY,GAAL,SAAA,EAAA,OACL,GAAA,SAAA,WACA,EAAA,SAAA,WACA,EAAA,OAAA,UACF,EAAA,CAAA,CAAA,01CEDM,GAAgD,CACpD,SAAU,GAAO,kBACjB,SAAU,GAAO,kBACjB,OAAQ,GAAO,eACjB,EAEA,SAAS,GAAK,EAAkB,CAC9B,GAAM,CACN,YAAY,IAAA,GACZ,WAAW,KACX,YAAY,GAAc,SAC1B,UAAU,IAAA,GACV,WAAW,KACX,cAAc,IAAA,GACd,QAAQ,IAAA,GACR,UAAU,GACV,OAAO,GACP,GAAG,GACC,EAAqB,OAAQ,CAAK,EAChC,EAAiB,CAAC,CAAC,EAEzB,OACE,EAAA,EAAA,KAAC,EAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SACE,GAAO,KACP,GAAe,GACf,GAAQ,GAAO,SACf,GAAkB,GAAO,kBACvB,GAAkB,IAAgB,IAAU,IAAgB,GAAO,UACrE,CACF,EACS,UACT,SAAU,IAAa,EAAiB,EAAI,MACrC,kBAEP,EAAA,EAAA,KAAC,EAAD,CACE,SAAU,CAAC,EACX,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAW,GAAO,QAAQ,EAC5D,MAAO,CAAE,aAAc,SAAU,EAEhC,UACK,CAAA,CACO,CAAA,CAErB,CC9CA,SAAS,GAAW,CAClB,YAAY,GACZ,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,UAAU,IAAA,IACQ,CAClB,IAAM,EACJ,OAAO,GAAc,UAAY,EAAU,WAAW,MAAM,EAAI,EAAY,IAAA,GAE9E,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,WAAY,CAAS,WAA/C,CACG,IACC,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,GAAO,oBAClB,MAAO,EAAe,CAAE,gBAAiB,OAAO,EAAa,EAAG,EAAI,CAAC,WAEpE,CAAC,GAAgB,CACf,CAAA,GAEP,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,0BAAvB,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,uCAAvB,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,8BAAuB,CAAW,CAAA,GACzD,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,2BACpB,MAAM,QAAQ,CAAO,EAClB,EAAQ,KAAK,EAAQ,KACnB,EAAA,EAAA,KAAC,EAAD,CAEE,MAAO,EAAO,MACd,QAAS,EAAO,QAAW,GAAwC,CAAE,EAAE,gBAAgB,EAAG,EAAO,UAAU,CAAC,CAAG,EAAI,IAAA,GACnH,KAAM,EAAO,IACd,EAJM,CAIN,CACF,EACD,CACD,CAAA,CACF,KACL,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,6BAAsB,CAAc,CAAA,CACxD,GACF,GAET,CC1CA,SAAS,GAAU,CAAE,MAAM,GAAI,MAAM,IAAsB,CACzD,OAAO,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,UAAgB,MAAU,KAAM,CAAA,CAChE,CCHA,SAAS,GAAY,CAAE,WAAW,MAA0B,CAC1D,OAAO,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,UAAW,CAAA,CACvB,CCEA,SAAS,GAAY,CAAE,YAAY,GAAI,UAAU,CAAC,EAAG,WAAW,MAA0B,CACxF,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,WAAhD,CACG,EAAQ,KAAK,CAAE,KAAI,UAAS,QAAO,YAAY,EAAgB,YAC9D,EAAA,EAAA,KAAC,MAAD,CAAA,UACE,EAAA,EAAA,KAAC,EAAD,CAAiB,UAAoB,qBAClC,CACK,CAAA,CACL,EAJK,GAAM,CAIX,CACN,EACA,CACE,GAET,+tBEVM,GAAsB,GACtB,GAAoB,GAE1B,SAAS,GAAS,EAAsB,CACtC,GAAM,CACJ,WACA,eACA,eAAe,EACf,eAAiB,CAAC,EAClB,OAAO,GACP,WAAW,GACX,mBAAmB,IACnB,eAAe,GACf,aAAa,GACb,WAAW,GACX,YAAY,GACZ,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,WAAY,CAAK,EAEpC,EAAS,EAAA,QAAM,SAAS,QAAQ,CAAQ,EACxC,EAAQ,EAAO,OACf,EAAU,GAAQ,EAAQ,EAC1B,EAAS,KACT,EAAiB,EAAU,CAAC,EAAO,EAAQ,GAAI,GAAG,EAAQ,EAAO,EAAE,EAAI,EAEvE,EAAe,IAAiB,IAAA,GAChC,CAAC,EAAe,IAAA,EAAA,EAAA,cAAmC,GAAW,EAAc,EAAO,CAAO,CAAC,EAC3F,EAAY,GAAW,EAAe,EAAgB,EAAe,EAAO,CAAO,EAEnF,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,EAAY,CAAM,EAC7D,CAAC,EAAmB,IAAA,EAAA,EAAA,UAAiC,EAAI,EACzD,GAAA,EAAA,EAAA,QAA0B,CAAS,EAEnC,CAAC,EAAS,IAAA,EAAA,EAAA,UAAuB,EAAK,EACtC,CAAC,EAAS,KAAA,EAAA,EAAA,UAAuB,EAAK,EACtC,CAAC,EAAU,IAAA,EAAA,EAAA,UAAwB,EAAK,EACxC,CAAC,GAAmB,IAAA,EAAA,EAAA,UAAiC,CAAC,EAEtD,IAAA,EAAA,EAAA,QAAsC,IAAI,GAEhD,EAAA,EAAA,eAAgB,CACd,IAAM,EAAW,EAAiB,QAElC,GADA,EAAiB,QAAU,EACvB,IAAa,EAAW,OAE5B,IAAM,EAAc,GAAW,IAAa,EAAQ,GAAK,IAAc,EACjE,EAAe,GAAW,IAAa,GAAK,IAAc,EAAQ,EAExE,EAAqB,EAAI,EAEvB,EADE,EACe,GAAM,EAAI,EAClB,EACQ,GAAM,EAAI,EAEX,EAAY,CAAM,CAGtC,EAAG,CAAC,CAAS,CAAC,EAEd,SAAS,GAAU,EAAmB,CACpC,IAAM,EAAU,GAAW,EAAW,EAAO,CAAO,EAC/C,GAAc,EAAiB,CAAO,EAC3C,EAAS,CAAO,CAClB,CAEA,SAAS,IAAS,CACZ,CAAC,GAAW,GAAa,EAAQ,GACrC,GAAU,EAAY,CAAC,CACzB,CAEA,SAAS,GAAS,CACZ,CAAC,GAAW,GAAa,GAC7B,GAAU,EAAY,CAAC,CACzB,CAEA,SAAS,EAAyB,EAA8C,CAC1E,EAAM,SAAW,EAAM,eAAiB,CAAC,IACzC,IAAiB,GACnB,EAAqB,EAAK,EAC1B,EAAgB,CAAK,GACZ,IAAiB,EAAe,OAAS,IAClD,EAAqB,EAAK,EAC1B,EAAgB,CAAC,GAErB,CAEA,IAAM,EAAY,IAAiB,GAAW,IAAa,GAC3D,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,GAAY,GAAS,GAAK,EAAU,OACzC,IAAM,EAAQ,YAAY,GAAQ,CAAgB,EAClD,UAAa,cAAc,CAAK,CAElC,EAAG,CAAC,EAAU,EAAkB,EAAU,EAAW,CAAK,CAAC,EAE3D,IAAM,IAAA,EAAA,EAAA,QAKI,IAAI,EAEd,SAAS,GAAkB,EAA2C,CAChE,CAAC,GAAa,GAAS,IAC3B,GAAQ,QAAU,CAAE,OAAQ,EAAM,QAAS,OAAQ,EAAM,QAAS,WAAY,GAAO,OAAQ,EAAK,EAClG,EAAM,cAAc,oBAAoB,EAAM,SAAS,EACzD,CAEA,SAAS,GAAkB,EAA2C,CACpE,IAAM,EAAO,GAAQ,QACrB,GAAI,CAAC,GAAQ,CAAC,EAAK,OAAQ,OAE3B,IAAM,EAAS,EAAM,QAAU,EAAK,OAC9B,EAAS,EAAM,QAAU,EAAK,OAEpC,GAAI,CAAC,EAAK,WAAY,CACpB,GAAI,KAAK,IAAI,CAAM,EAAI,IAAuB,KAAK,IAAI,CAAM,EAAI,GAAqB,OACtF,GAAI,KAAK,IAAI,CAAM,EAAI,KAAK,IAAI,CAAM,EAAG,CACvC,EAAK,OAAS,GACd,MACF,CACA,EAAK,WAAa,GAClB,EAAY,EAAI,EAChB,EAAqB,EAAK,CAC5B,CAGA,EAAsB,GADR,GAAa,SAAS,sBAAsB,EAAE,OAAS,GAC7B,GAAG,CAC7C,CAEA,SAAS,GAAkB,CACzB,IAAM,EAAO,GAAQ,QAErB,GADA,GAAQ,QAAU,KACd,CAAC,GAAQ,CAAC,EAAK,WAAY,CAC7B,EAAY,EAAK,EACjB,MACF,CAEA,IAAM,EAAY,KAAK,IAAI,EAAiB,GAAK,GAAoB,IACrE,EAAqB,CAAC,EACtB,EAAqB,EAAI,EACzB,EAAY,EAAK,EACb,IACE,GAAoB,EAAG,GAAO,EAC7B,EAAO,EAEhB,CAEA,SAAS,GAAc,EAA4C,CAC7D,EAAM,MAAQ,aAChB,EAAM,eAAe,EACrB,EAAO,GACE,EAAM,MAAQ,eACvB,EAAM,eAAe,EACrB,GAAO,EAEX,CAEA,IAAM,GAAiB,CAAC,GAAW,GAAa,EAC1C,GAAiB,CAAC,GAAW,GAAa,EAAQ,EAElD,EAAoB,EAAe,OAAS,EAAI,IAAM,EAAe,OAAS,IAC9E,GAAiB,mBAAmB,CAAC,EAAe,EAAkB,MAA2B,EAAoB,IAAzC,GAA8C,KAEhI,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,IAAK,GACL,KAAK,SACL,uBAAqB,WACrB,WAAA,EAAA,EAAA,SAAc,GAAO,SAAU,GAAY,KAAM,CAAS,EAC1D,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EACvC,aAAc,MAAqB,EAAW,EAAI,EAAI,IAAA,GACtD,aAAc,MAAqB,EAAW,EAAK,EAAI,IAAA,GACvD,QAAS,MAAqB,GAAW,EAAI,EAAI,IAAA,GACjD,OAAQ,MAAqB,GAAW,EAAK,EAAI,IAAA,GACjD,UAAW,YAXb,EAaE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAY,KAAK,EACrD,MAAO,CACL,MAAO,GAAG,EAAe,OAAS,IAAI,GACtC,UAAW,GACX,WAAY,EAAoB,IAAA,GAAY,OAC5C,GAAG,GAAY,KACjB,EACA,gBAAiB,EACjB,cAAe,GACf,cAAe,GACf,YAAa,EACb,gBAAiB,WAEhB,EAAe,KAAK,EAAO,IAAQ,CAClC,IAAM,EAAkB,IAAY,IAAQ,GAAK,IAAQ,EAAe,OAAS,GAC3E,EAAe,EAAM,EACrB,EAAW,CAAC,GAAmB,IAAiB,EAEtD,OACE,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAY,KAAK,EACrD,MAAO,CAAE,MAAO,GAAG,IAAM,EAAe,OAAO,GAAI,GAAG,GAAY,KAAM,EACxE,MAAO,EAAW,IAAA,GAAY,YAE7B,CACE,EANE,kBAAkB,GAMpB,CAET,CAAC,CACE,CAAA,EAEJ,GAAc,EAAQ,IACrB,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CACE,KAAM,EAAA,cACN,MAAM,iBACN,aAAW,iBACX,gBAAe,IAAkB,IAAA,GACjC,YAAe,CAAC,IAAkB,EAAO,EACzC,WAAA,EAAA,EAAA,SAAc,GAAO,mBAAoB,IAAkB,GAAO,uBAAwB,GAAY,UAAU,EAChH,MAAO,GAAY,UACpB,CAAA,GACD,EAAA,EAAA,KAAC,EAAD,CACE,KAAM,EAAA,eACN,MAAM,aACN,aAAW,aACX,gBAAe,IAAkB,IAAA,GACjC,YAAe,CAAC,IAAkB,GAAO,EACzC,WAAA,EAAA,EAAA,SAAc,GAAO,mBAAoB,IAAkB,GAAO,uBAAwB,GAAY,UAAU,EAChH,MAAO,GAAY,UACpB,CAAA,CACD,CAAA,CAAA,EAGH,GAAY,EAAQ,IACnB,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,GAAY,IAAI,EAAG,MAAO,GAAY,cAC3E,EAAO,KAAK,EAAG,KACd,EAAA,EAAA,KAAC,EAAD,CAEE,aAAY,eAAe,EAAQ,IACnC,eAAc,IAAU,EACxB,YAAe,GAAU,CAAK,EAC9B,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,IAAU,GAAa,GAAO,kBAAmB,GAAY,GAAG,EAClG,MAAO,GAAY,GACpB,EANM,gBAAgB,GAMtB,CACF,CACE,CAAA,CAEJ,GAET,CAEA,SAAS,GAAW,EAAe,EAAe,EAA0B,CAG1E,OAFI,IAAU,EAAU,EACpB,GAAkB,EAAQ,EAAS,GAAS,EACzC,KAAK,IAAI,EAAG,KAAK,IAAI,EAAQ,EAAG,CAAK,CAAC,CAC/C,6rBEpQA,SAAS,GAAS,EAAoC,CACpD,GAAM,CACN,QAAQ,GACR,WAAW,GACX,eAAiB,CAAC,EAClB,YAAY,GACZ,QACA,WAAW,GACX,aAAa,GACb,QAAQ,GACR,WAAW,EACX,gBAAgB,GAChB,QAAQ,OACR,SAAS,OACT,gBAAgB,KAChB,WAAW,KACX,aAAa,KACb,YAAY,GACZ,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,WAAY,CAAK,EACpC,GAAA,EAAA,EAAA,QAA8C,IAAI,EAClD,EAAG,IAAA,EAAA,EAAA,UAAwB,CAAC,GAElC,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,EAAe,OACpB,IAAM,MAAiB,EAAa,GAAM,EAAI,CAAC,EAE/C,OADA,EAAc,yBAAyB,CAAQ,MAClC,EAAc,uBAAuB,CAAQ,CAC5D,EAAG,CAAC,CAAa,CAAC,EAElB,SAAS,EAAa,EAAgD,CAChE,GAAY,IAChB,EAAU,SAAS,UAAU,EACzB,GACF,EAAc,IAAI,CAAC,EAAc,KAAK,EAExC,EAAS,CAAC,EAAU,CAAK,EAC3B,CAEA,IAAM,EAAgB,EAAgB,EAAc,MAAQ,EAE5D,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SACE,GAAO,SACP,EACG,GAAO,kBAAmB,GAC1B,GAAO,iBAAkB,CAAC,CAC7B,EACA,CACF,EACO,QACP,QAAS,EACT,WAAa,GAAM,CAAM,EAAE,MAAQ,SAAS,EAAa,CAAC,CAAG,EAC7D,KAAK,WACL,eAAc,EACd,gBAAe,GAAY,IAAA,GACjB,oBAhBZ,EAkBE,EAAA,EAAA,KAAC,MAAD,CACS,QACP,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,EAAY,GAAO,gBAAkB,KAAM,GAAY,IAAI,EAC9F,MAAO,GAAY,cAElB,GACC,EAAA,EAAA,KAAC,MAAD,CAAK,MAAO,CAAE,QAAO,QAAO,YAC1B,EAAA,EAAA,KAAC,EAAD,CAAgB,UAAW,GAAO,sBAAyB,CAAA,CACxD,CAAA,GAEL,EAAA,EAAA,MAAC,MAAD,CACE,MAAO,CAAE,QAAO,SAAQ,GAAG,GAAY,SAAU,EACjD,WAAA,EAAA,EAAA,SACE,GAAO,kBACP,GAAgB,GAAO,yBACvB,GAAY,SACd,WANF,EAQE,EAAA,EAAA,KAAC,EAAD,CACE,IAAK,EACL,WAAA,GACA,eAAgB,GAChB,sBAAuB,GACvB,iBAAiB,oDAClB,CAAA,GACD,EAAA,EAAA,KAAC,MAAD,CACE,eAAe,QACf,cAAc,QACd,MAAM,6BACN,QAAQ,kBACR,MAAO,QAAQ,EAAM,SACrB,OAAQ,QAAQ,EAAO,SACvB,GAAK,EAAa,CAAE,MAAO,CAAE,YAAW,CAAE,EAAI,CAAC,YAE/C,EAAA,EAAA,KAAC,OAAD,CAAM,EAAE,qBAAqB,YAAY,MAAM,KAAK,MAAQ,CAAA,CACzD,CAAA,CACF,GAEJ,CAAA,GACL,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAY,MAAO,MAAO,CAAE,WAAY,GAAc,OAAQ,GAAG,GAAY,KAAM,WAAI,GAAY,CAAW,CAAA,CAC3H,GAET,CC/GA,IAAY,GAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,KAAA,OACA,EAAA,KAAA,OACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,04BEGM,GAAgD,CACpD,QAAS,GAAO,iBAChB,QAAS,GAAO,iBAChB,KAAM,GAAO,cACb,KAAM,GAAO,cACb,MAAO,GAAO,cAChB,EAEA,SAAS,GAAK,EAAkB,CAC9B,GAAM,CACN,YAAY,GACZ,YAAY,GACZ,OAAO,GACP,YAAY,GAAc,QAC1B,iBAAiB,GACjB,UACA,WACA,GAAG,GACC,EAAqB,OAAQ,CAAK,EAChC,GAAA,EAAA,EAAA,aAA6B,CACjC,GAAI,OAAO,GAAc,UAAY,EAAU,WAAW,MAAM,EAAG,OAAO,CAE5E,EAAG,CAAC,CAAS,CAAC,EAEd,OACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,GAAO,KAAM,GAAe,GAAY,GAAW,GAAO,cAAe,CAAS,EACvF,oBAET,EAAA,EAAA,KAAC,EAAD,CAAQ,SAAU,CAAC,EAAS,MAAO,CAAE,aAAc,SAAU,YAC3D,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,mBAAvB,CACG,IACC,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,GAAO,cAClB,MAAO,EAAe,CAAE,gBAAiB,OAAO,EAAa,EAAG,EAAI,CAAC,WAEpE,CAAC,GAAgB,CACf,CAAA,GAEP,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,kBAAW,CAAU,CAAA,EAC3C,IAAkB,EAAA,EAAA,KAAC,EAAD,CAAY,KAAM,EAAA,cAAe,QAAU,GAAM,CAAE,EAAE,gBAAgB,EAAG,IAAW,CAAG,CAAI,CAAA,CAC1G,GACC,CAAA,CACL,CAAA,CAET,CCnDA,SAAS,GAAc,CACrB,YAAY,IAAA,GACZ,WAAW,KACX,SAAS,GACT,GAAG,GACgC,CACnC,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAU,GAAO,oBAAqB,CAAS,EAC/F,UACE,CAAA,CAET,2VEVA,SAAwB,GAAQ,CAC9B,UACA,UAAU,GACV,YAAY,GACZ,kBACA,WACe,CACf,GAAM,CAAC,EAAgB,IAAA,EAAA,EAAA,UAA8B,EAAK,EAEpD,GAAA,EAAA,EAAA,QAAsC,IAAI,EAC1C,GAAA,EAAA,EAAA,QAAoC,IAAI,EACxC,GAAA,EAAA,EAAA,QAAwC,IAAI,EAC5C,GAAA,EAAA,EAAA,QAAmC,IAAI,EACvC,GAAA,EAAA,EAAA,QAAkC,IAAI,EACtC,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,EAAE,EAE7C,EAAQ,IAAY,UAAY,EAAiB,GAEvD,EAAA,EAAA,qBAAsB,CACpB,EAAW,QAAU,IAAY,UAAY,EAAW,QAAW,EAAY,SAAS,eAAiB,IAC3G,CAAC,GAED,EAAA,EAAA,qBAAsB,CACpB,GAAI,EAAO,CACT,IAAM,EAAO,EAAW,SAAS,sBAAsB,EACvD,EAAgB,GAAM,OAAS,EAAE,CACnC,CACF,EAAG,CAAC,CAAK,CAAC,EAEV,GAAoB,CAClB,OAAQ,EACR,aACA,YACA,WACA,cAAe,GAAO,kBACtB,UAAW,KACb,CAAC,EAED,IAAM,EAAS,IACb,EAAA,EAAA,KAAC,GAAD,CAAA,UACE,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,UAAW,GAAO,cAClB,MAAO,CAAE,MAAO,GAAG,EAAa,IAAK,0BAA2B,GAAG,EAAa,GAAI,YAEpF,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,IAAY,QAAU,GAAO,aAAe,GAAO,cAAe,CAAe,EACtF,mBAER,CACE,CAAA,CACF,CAAA,CACE,CAAA,EA2BX,OAxBI,IAAY,WAEZ,EAAA,EAAA,MAAC,MAAD,CAAK,IAAK,EAAY,UAAW,GAAO,wBAAxC,EACE,EAAA,EAAA,KAAC,OAAD,CACE,UAAW,GAAO,mBAClB,iBAAoB,EAAkB,EAAI,EAC1C,iBAAoB,EAAkB,EAAK,WAC5C,GAEK,CAAA,EACL,CACE,IAIL,IAAY,QAAU,IAAY,SAElC,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,IAAK,EAAa,MAAO,CAAE,QAAS,MAAO,CAAI,CAAA,EACpD,CACD,CAAA,CAAA,EAIC,IACT,qnHEpFY,GAAL,SAAA,EAAA,OACL,GAAA,KAAA,OACA,EAAA,MAAA,QACA,EAAA,MAAA,QACA,EAAA,KAAA,OACA,EAAA,KAAA,OACA,EAAA,UAAA,YACA,EAAA,OAAA,cACA,EAAA,SAAA,YACF,EAAA,CAAA,CAAA,ECKA,SAAS,GAAM,EAAmB,CAChC,GAAM,CACN,OAAO,GACP,KACA,QAAQ,GACR,eAAe,GACf,UAAU,GACV,YAAY,GACZ,QACA,QAAQ,GACR,OAAO,KACP,eAAiB,CAAC,EAClB,QAAS,EAAc,KACvB,OAAQ,EAAa,KACrB,aAAc,EAAmB,KACjC,aAAc,EAAmB,KACjC,cAAc,GACd,aAAa,GACb,WAAW,EACX,OAAO,IAAA,GACP,QAAQ,GACR,cAAc,KACd,QAAQ,KACR,gBAAgB,KAChB,YAAY,GACZ,SAAS,KACT,kBAAkB,KAClB,gBAAgB,GAChB,aAAa,GACb,iBACA,MAAM,KACN,MAAM,KACN,cAAc,GACd,mBAAmB,GACnB,oBAAmB,GACnB,eAAe,KACf,cAAgB,KAChB,YAAW,GACX,cACA,oBAAmB,GACnB,aAAY,GACZ,QACA,aAAa,GACb,aACA,OAAQ,EACR,WAAW,GACX,GAAG,GACC,EAAqB,QAAS,CAAK,EACjC,CAAC,GAAW,KAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,CAAC,GAAW,IAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,CAAC,GAAiB,KAAA,EAAA,EAAA,UAA+B,EAAK,EACtD,EAAG,KAAA,EAAA,EAAA,UAAwB,CAAC,EAE5B,GAAA,EAAA,EAAA,QAA0D,IAAI,EAC9D,IAAA,EAAA,EAAA,QAAe,CAAa,EAE5B,IAAA,EAAA,EAAA,OAAoB,EACpB,GAAU,GAAM,GAAQ,GAExB,IAAA,EAAA,EAAA,iBAAmC,CACvC,IAAM,EAAK,EAAS,QAChB,CAAC,GAAM,CAAC,IACZ,EAAG,MAAM,OAAS,OAClB,EAAG,MAAM,OAAS,GAAG,EAAG,aAAa,IACvC,EAAG,CAAC,CAAU,CAAC,GAEf,EAAA,EAAA,eAAgB,CACd,GAAe,CACjB,EAAG,CAAC,CAAC,GAEL,EAAA,EAAA,eAAgB,CACV,GAAa,EAAS,SACxB,eAAiB,CAAE,EAAS,SAAS,MAAM,CAAG,EAAG,CAAC,CAEtD,EAAG,CAAC,CAAS,CAAC,GAEd,EAAA,EAAA,eAAgB,CACd,GAAM,QAAU,EAChB,IAAM,EAAK,GAAM,QACjB,GAAI,CAAC,EAAI,OACT,EAAG,MAAQ,GAAS,GACpB,EAAG,SAAS,EACZ,IAAM,MAAiB,GAAY,GAAK,EAAI,CAAC,EAE7C,OADA,EAAG,yBAAyB,CAAQ,MACvB,CAAE,EAAG,uBAAuB,CAAQ,CAAG,CACtD,EAAG,CAAC,EAAe,CAAK,CAAC,EAEzB,IAAM,OACG,EACF,EAAc,SAAW,EAAc,SAAS,EAChD,CAAC,GAAW,CAAC,CAAC,EAGf,OACG,CAAC,EAAE,GAAe,GAAiB,EAAc,WAAW,KAChE,GAAO,EAA+B,cAAgB,UACzD,GAGI,GAAuB,GAA4B,CACvD,EAAa,EAAI,EACb,GAAkB,EAAiB,CAAK,CAC9C,EAEM,GAAuB,GAA4B,CACvD,EAAa,EAAK,EACd,GAAkB,EAAiB,CAAK,CAC9C,EAEM,GAAkB,GAA4B,CAClD,GAAa,EAAI,EACb,GAAa,EAAY,CAAK,CACpC,EAEM,GAAiB,GAA4B,CAC7C,GAAM,UAAS,GAAM,QAAQ,QAAU,IAC3C,GAAa,EAAK,EACd,GAAY,EAAW,CAAK,CAClC,EAEM,GAAmB,GAAoF,CAC3G,IAAI,EACA,EAEA,OAAO,GAAU,SAInB,EAAM,GAHN,EAAc,EACd,EAAM,EAAM,OAAO,OAKjB,IAAO,EAAM,EAAM,CAAG,GACtB,GAAe,EAAc,IAAI,CAAG,EACpC,GAAU,EAAS,EAAK,CAAW,EACvC,GAAe,CACjB,EAEM,OAAyC,CACzC,OAAS,QAEb,OADI,IAAS,YAAc,GAAwB,OAC5C,CACT,EAEM,GACJ,GACA,IAAS,GAAU,MACnB,IAAS,GAAU,MACnB,IAAS,GAAU,UAEf,GACJ,IAAW,CAAC,IACX,IAAS,GAAU,OAAS,IAAS,GAAU,OAAS,IAAS,GAAU,QAExE,GAAY,CAChB,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,EAClC,EAAO,4BAA6B,CAAC,GACrC,EAAO,oBAAqB,EAC/B,CAAC,EACD,QAAS,GAAe,IAAA,EAC1B,EAEM,GAAa,EACb,GAAe,GACjB,EAAA,QAAM,aAAa,GAAY,CAC7B,WAAA,EAAA,EAAA,SACE,EAAO,eACP,EAAG,EAAO,4BAA6B,CAAC,GAAe,CAAC,GAAW,MAAM,OAAQ,EACjF,GAAW,MAAM,SACnB,EACA,QAAS,GAAe,GAAW,MAAM,OAC3C,CAAC,EACD,KACE,GAAgB,CAAC,CAAC,EAElB,GAAoB,CACxB,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,EAAO,sBAAsB,EAClE,YAAe,GAAmB,CAAC,EAAe,CACpD,EAEM,GAAS,GAAS,EAEpB,GAAc,EACd,IAAe,GAAmB,IAAG,GAAc,GAAG,GAAY,KACtE,IAAM,GAAe,GAAmB,GAAI,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAO,sBAAc,GAAO,CAAA,EAAI,KAEvF,GAAU,EAAgB,EAAc,MAAQ,EAIhD,GAAY,IAAa,CAAC,GAC1B,GAAmB,IAAqB,IAAoB,IAAa,IAAW,IAAS,GAAU,MAE7G,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,MAAO,CAAS,EAAU,iBAApD,EACE,EAAA,EAAA,MAAC,QAAD,CACE,QAAS,GACT,WAAA,EAAA,EAAA,SAAc,EAAO,WAAY,GAAY,MAAO,EACjD,EAAO,kBAAmB,CAAC,GAC3B,EAAO,oBAAqB,CAC/B,CAAC,EACD,MAAO,GAAY,eANrB,CAQG,GAAS,CAAC,GACT,EAAA,EAAA,MAAC,OAAD,CAAM,UAAW,EAAO,wBAAxB,CACG,EACA,EACG,IACJ,KACH,IACC,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,qBAAsB,GAAY,eAAe,EAAG,MAAO,GAAY,yBAC9F,CACE,CAAA,GAEP,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,EAAG,EAAO,yBAA0B,EAAU,EAAG,GAAY,SAAS,EAC3G,MAAO,GAAY,UACnB,aAAc,GACd,aAAc,YAJhB,CAMG,GACA,EAAA,QAAM,aAAa,IAAgB,IAAY,EAAA,EAAA,KAAC,WAAD,CAAW,CAAA,GAAI,EAAA,EAAA,KAAC,QAAD,CAAQ,CAAA,GAAI,CACzE,GAAG,EACH,WAAA,EAAA,EAAA,SACE,EAAO,WACP,EACG,EAAO,qBAAsB,GAC7B,EAAO,gBAAiB,IAAS,GAAU,MAC3C,EAAO,mBAAoB,IAAS,GAAU,MAC9C,EAAO,oBAAqB,IAAW,IACvC,EAAO,wBAAyB,IAChC,EAAO,qBAAsB,IAC7B,EAAO,+BAAgC,IAAa,GACpD,EAAO,oBAAqB,IAAY,CAAC,CAC5C,EACA,GAAY,KACd,EACA,OACA,GAAI,GACJ,MAAO,EAAgB,EAAc,MAAQ,EAC7C,WACA,IAAK,EAAc,IAAA,GAAY,EAC/B,SAAU,GACV,QAAS,GACT,OAAQ,GACR,YAAc,EAAiC,GAAd,EACjC,eACA,UACA,YACA,WACA,GAAI,CAAC,IAAa,CAAE,KAAM,GAAa,EAAG,MAAK,KAAI,EACnD,GAAI,IAAa,KAAS,IAAA,IAAa,CAAE,OAAK,CAChD,CAAC,EACA,IAAU,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,iBAAkB,GAAY,MAAM,EAAG,MAAO,GAAY,gBAAS,CAAY,CAAA,CACjH,KACL,EAAA,EAAA,KAAC,WAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,cAAe,GAAY,SAAU,EACvD,EAAO,6BAA8B,IACrC,EAAO,mCACN,IAAS,GAAU,SAAW,IAAa,IAC5C,EAAO,6BAA8B,IACrC,EAAO,2BAA4B,EACtC,CAAC,EACD,MAAO,GAAY,mBAEnB,EAAA,EAAA,KAAC,SAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,oBAAqB,EACvC,EAAO,2BAA4B,EACtC,CAAC,YAED,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAkB,CAAA,CACnB,CAAA,CACA,CAAA,EACT,GAAoB,IACnB,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,cAAe,EACjC,EAAO,uBAAwB,IAC/B,EAAO,wBAAyB,IAAa,CAAC,EACjD,CAAC,WAJH,CAMG,EACA,EACE,IAEN,GAAoB,IACnB,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SACE,EAAO,iBACP,IAAa,CAAC,IAAW,EAAO,sBAChC,IAAa,EAAO,yBACtB,WAEC,CACE,CAAA,GAEP,EAAA,EAAA,KAAC,GAAD,CACE,QAAQ,QACR,QAAS,EAAgB,EAAc,uBAAuB,EAAK,GAAgB,GACnF,UAAW,KAAW,IAAa,GACpC,CAAA,CACI,IAEN,IAAS,GAAU,QAAS,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,QAAS,GAAI,EAAY,CAAA,EAC5E,IAAS,GAAU,QAAS,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,WAAY,GAAI,EAAY,CAAA,EAC/E,IAAS,GAAU,OAAQ,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,MAAO,GAAI,EAAY,CAAA,EACzE,IAAS,GAAU,SAAU,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,SAAU,GAAI,EAAY,CAAA,EAC9E,IAAS,GAAU,WAClB,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,GAAkB,EAAA,WAAoB,EAAA,MAC5C,GAAI,EACL,CAAA,GAGA,GAAc,IAAU,IAAa,KAAe,MACrD,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,EAAA,QACN,UAAW,EAAO,eAClB,QAAS,GAAkB,IAAA,GAC3B,iBAAoB,EAAa,EAAI,EACrC,iBAAoB,EAAa,EAAK,CACvC,CAAA,CAEA,GAET,oYEpUM,GAAsB,OAAO,OAAW,KAAe,eAAgB,OAE7E,eAAe,IAA8C,CAC3D,IAAM,EAAkB,OAA6D,WACrF,GAAI,CAAC,EAAgB,OAAO,KAC5B,GAAI,CAEF,OAAO,MADc,IAAI,EAAe,EAAE,KAAK,GACjC,OAChB,MAAQ,CACN,OAAO,IACT,CACF,CAIA,SAAS,GAAW,EAAoB,CACtC,MAAO,oBAAoB,KAAK,CAAC,GAAK,oBAAoB,KAAK,CAAC,CAClE,CAGA,SAAS,GAAS,EAA8C,CAO9D,MANI,oBAAoB,KAAK,CAAG,EACvB,CACL,KAAM,EAAI,MAAM,EAAG,CAAC,EACpB,MAAO,KAAK,MAAO,SAAS,EAAI,MAAM,EAAG,CAAC,EAAG,EAAE,EAAI,IAAO,GAAG,CAC/D,EAEK,CAAE,KAAM,EAAI,MAAM,EAAG,CAAC,EAAG,MAAO,GAAI,CAC7C,CAIA,SAAS,GAAW,EAAc,EAAe,EAA4B,CAG3E,MAFI,CAAC,GAAa,GAAS,IAAY,EAEhC,GAAG,IADA,KAAK,MAAO,EAAQ,IAAO,GAAG,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAClD,GACnB,CAEA,SAAS,GAAU,EAAc,EAAuB,CAItD,MAAO,QAHG,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EAGtB,EAAE,IAFP,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EAEhB,EAAE,IADb,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EACV,EAAE,IAAI,EAAQ,IAAI,EAC/C,CAEA,SAAS,GAAS,EAAmD,CACnE,IAAM,EAAI,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EAAE,EAAI,IACrC,EAAI,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EAAE,EAAI,IACrC,EAAI,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EAAE,EAAI,IAErC,EAAM,KAAK,IAAI,EAAG,EAAG,CAAC,EAEtB,EAAQ,EADF,KAAK,IAAI,EAAG,EAAG,CACP,EAEhB,EAAI,EACJ,IAAU,IACZ,AAEK,EAFD,IAAQ,GAAS,EAAI,GAAK,EAAS,EAC9B,IAAQ,GAAQ,EAAI,GAAK,EAAQ,GAChC,EAAI,GAAK,EAAQ,EAC3B,EAAI,KAAK,MAAM,EAAI,EAAE,EACjB,EAAI,IAAG,GAAK,MAGlB,IAAM,EAAI,IAAQ,EAAI,EAAI,KAAK,MAAO,EAAQ,EAAO,GAAG,EAClD,EAAI,KAAK,MAAM,EAAM,GAAG,EAE9B,MAAO,CAAE,IAAG,EAAG,GAAE,CACnB,CAEA,SAAS,GAAS,EAAW,EAAW,EAAmB,CACzD,IAAM,EAAK,EAAI,IACT,EAAK,EAAI,IACT,EAAI,EAAK,EACT,EAAI,GAAK,EAAI,KAAK,IAAM,EAAI,GAAM,EAAK,CAAC,GACxC,EAAI,EAAK,EAEX,EAAI,EAAG,EAAI,EAAG,EAAI,EAClB,EAAI,IAAY,EAAI,EAAG,EAAI,EAAG,EAAI,GAC7B,EAAI,KAAO,EAAI,EAAG,EAAI,EAAG,EAAI,GAC7B,EAAI,KAAO,EAAI,EAAG,EAAI,EAAG,EAAI,GAC7B,EAAI,KAAO,EAAI,EAAG,EAAI,EAAG,EAAI,GAC7B,EAAI,KAAO,EAAI,EAAG,EAAI,EAAG,EAAI,IAClB,EAAI,EAAG,EAAI,EAAG,EAAI,GAEtC,IAAM,EAAS,GAAc,KAAK,OAAO,EAAI,GAAK,GAAG,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,EACnF,MAAO,IAAI,EAAM,CAAC,IAAI,EAAM,CAAC,IAAI,EAAM,CAAC,GAC1C,CAUA,SAAS,GAAS,CAAE,MAAK,WAAU,oBAAoB,IAAsC,CAC3F,GAAM,CAAC,EAAO,IAAA,EAAA,EAAA,UAAqB,CAAG,EAEhC,CAAC,EAAS,IAAA,EAAA,EAAA,UAAuB,CAAG,EACtC,IAAQ,IACV,EAAW,CAAG,EACd,EAAS,CAAG,GAGd,SAAS,EAAa,EAAa,CACjC,EAAS,CAAG,EACZ,IAAM,EAAa,EAAI,WAAW,GAAG,EAAI,EAAM,IAAI,IAC/C,GAAW,CAAU,GAAG,EAAS,CAAU,CACjD,CAEA,SAAS,GAAa,CAEf,GADc,EAAM,WAAW,GAAG,EAAI,EAAQ,IAAI,GAC7B,GAAG,EAAS,CAAG,CAC3C,CAYA,OAVI,GAEA,EAAA,EAAA,KAAC,GAAD,CACE,MAAO,EACP,SAAW,GAAkB,EAAa,CAAK,EAC/C,OAAQ,CACT,CAAA,GAKH,EAAA,EAAA,KAAC,QAAD,CACE,KAAK,OACL,MAAO,EACP,SAAW,GAAM,EAAa,EAAE,OAAO,KAAK,EAC5C,OAAQ,EACR,UAAW,GAAO,SAClB,WAAY,EACb,CAAA,CAEL,CAgBA,SAAS,GAAY,CACnB,MAAK,MAAK,MAAK,QACf,cAAa,aAAY,gBACzB,YAAY,GAAM,YAAY,IACG,CACjC,IAAM,GAAA,EAAA,EAAA,QAAqC,IAAI,EAE/C,SAAS,EAAe,EAAmE,CACzF,IAAM,EAAO,EAAY,QAAS,sBAAsB,EAClD,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,EAAE,QAAU,EAAK,MAAQ,EAAK,KAAK,CAAC,EACjE,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,EAAE,QAAU,EAAK,KAAO,EAAK,MAAM,CAAC,EACvE,MAAO,CAAE,EAAG,EAAI,IAAK,GAAI,EAAI,GAAK,GAAI,CACxC,CAGA,SAAS,EAAsB,EAAuB,CACpD,EAAE,cAAc,kBAAkB,EAAE,SAAS,EAC7C,GAAM,CAAE,IAAG,KAAM,EAAe,CAAC,EACjC,EAAW,EAAG,CAAC,EAEf,IAAM,EAAU,GAAqB,CACnC,GAAM,CAAE,IAAG,KAAM,EAAe,CAAE,EAClC,EAAW,EAAG,CAAC,CACjB,EACM,MAAa,CACjB,OAAO,oBAAoB,cAAe,CAAM,EAChD,OAAO,oBAAoB,YAAa,CAAI,CAC9C,EACA,OAAO,iBAAiB,cAAe,CAAM,EAC7C,OAAO,iBAAiB,YAAa,CAAI,CAC3C,CAEA,SAAS,EAAY,EAAoB,CACvC,GAAM,CAAE,OAAM,MAAO,GAAgB,GAAS,CAAU,EAClD,CAAE,IAAG,EAAG,KAAM,GAAS,CAAI,EACjC,EAAY,CAAC,EACb,EAAW,EAAG,CAAC,EACX,GAAW,EAAc,CAAW,CAC1C,CAEA,IAAM,EAAO,GAAS,EAAK,EAAK,CAAG,EAC7B,EAAgB,EAAY,GAAW,EAAM,EAAO,EAAI,EAAI,EAElE,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,eAAvB,EACE,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,UAAW,GAAO,aAClB,MAAO,CAAE,QAAS,CAAI,EACtB,cAAe,WAJjB,EAME,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,eAAkB,CAAA,GACzC,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,GAAO,OAClB,MAAO,CAAE,KAAM,GAAG,EAAI,GAAI,IAAK,GAAG,IAAM,EAAI,EAAG,CAChD,CAAA,CACE,KAEL,EAAA,EAAA,KAAC,QAAD,CACE,KAAK,QACL,IAAK,EACL,IAAK,IACL,MAAO,EACP,SAAW,GAAM,EAAY,OAAO,EAAE,OAAO,KAAK,CAAC,EACnD,UAAW,GAAO,SACnB,CAAA,EAEA,IACC,EAAA,EAAA,KAAC,QAAD,CACE,KAAK,QACL,IAAK,EACL,IAAK,IACL,MAAO,EACP,SAAW,GAAM,EAAc,OAAO,EAAE,OAAO,KAAK,CAAC,EACrD,UAAW,GAAO,YAClB,MAAO,CAAE,gBAAiB,CAAK,CAChC,CAAA,GAGD,GAAa,MACb,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,gBAAvB,CACG,IAAa,EAAA,EAAA,KAAC,GAAD,CAAU,IAAK,EAAe,SAAU,CAAc,CAAA,EACnE,KACC,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,UAAW,GAAO,iBAClB,QAAS,SAAY,CACnB,IAAM,EAAM,MAAM,GAAoB,EAClC,GAAK,EAAY,CAAG,CAC1B,EACA,aAAW,mCAEX,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,YAAe,CAAA,CAChC,CAAA,CAEP,GAEJ,GAET,CAIA,IAAM,GAAgB,UAEtB,SAAS,GAAY,CACnB,YACA,QAAQ,GACR,WACA,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,GAAG,GAC8B,CACjC,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAsB,EAAK,EAGpC,CAAE,KAAM,EAAU,MAAO,GAAc,GAD5B,GAAW,CAAK,EAAI,EAAQ,EACiB,EACxD,EAAU,GAAS,CAAQ,EAI3B,CAAC,EAAM,IAAA,EAAA,EAAA,UAAoB,CAAE,EAAG,EAAQ,EAAG,EAAG,EAAQ,EAAG,EAAG,EAAQ,EAAG,EAAG,CAAU,CAAC,EAGrF,GAAA,EAAA,EAAA,QAAa,CAAI,EAKjB,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,CAAK,EAChD,GAAI,IAAU,EAAW,CACvB,EAAa,CAAK,EAElB,GAAM,CAAE,KAAM,EAAc,MAAO,GAAc,GADpC,GAAW,CAAK,EAAI,EAAQ,EACqB,EAE9D,GAAI,IADgB,GAAS,EAAK,EAAG,EAAK,EAAG,EAAK,CAC7B,GAAe,IAAc,EAAK,EAAG,CACxD,IAAM,EAAM,GAAS,CAAY,EAEjC,EAAQ,CADO,EAAG,EAAI,EAAG,EAAG,EAAI,EAAG,EAAG,EAAI,EAAG,EAAG,CACxC,CAAI,CACd,CACF,CAEA,GAAM,CAAE,EAAG,EAAK,EAAG,EAAK,EAAG,EAAK,EAAG,GAAU,EAE7C,SAAS,EAAK,EAAW,EAAW,EAAW,EAAW,CACxD,IAAW,GAAW,GAAS,EAAG,EAAG,CAAC,EAAG,EAAG,CAAS,CAAC,CACxD,CAEA,SAAS,EAAgB,EAAW,CAClC,EAAI,QAAQ,EAAI,EAChB,EAAQ,IAAS,CAAE,GAAG,EAAM,GAAE,EAAE,EAChC,EAAK,EAAG,EAAI,QAAQ,EAAG,EAAI,QAAQ,EAAG,EAAI,QAAQ,CAAC,CACrD,CAEA,SAAS,EAAe,EAAW,EAAW,CAC5C,EAAI,QAAQ,EAAI,EAChB,EAAI,QAAQ,EAAI,EAChB,EAAQ,IAAS,CAAE,GAAG,EAAM,IAAG,GAAE,EAAE,EACnC,EAAK,EAAI,QAAQ,EAAG,EAAG,EAAG,EAAI,QAAQ,CAAC,CACzC,CAEA,SAAS,EAAkB,EAAW,CACpC,EAAI,QAAQ,EAAI,EAChB,EAAQ,IAAS,CAAE,GAAG,EAAM,GAAE,EAAE,EAChC,EAAK,EAAI,QAAQ,EAAG,EAAI,QAAQ,EAAG,EAAI,QAAQ,EAAG,CAAC,CACrD,CAEA,IAAM,EAAO,GAAS,EAAK,EAAK,CAAG,EAC7B,EAAmB,EAAY,GAAU,EAAM,CAAK,EAAI,EACxD,EAAe,GAAW,EAAM,EAAO,CAAS,EAEhD,EAAqC,CACzC,MAAK,MAAK,MAAK,QACf,YAAa,EACb,WAAY,EACZ,cAAe,EACf,WACF,EAUA,OARI,GAEA,EAAA,EAAA,KAAC,MAAD,CAAK,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,YACxD,EAAA,EAAA,KAAC,GAAD,CAAa,GAAI,EAA6B,WAAY,CAAA,CACvD,CAAA,GAKP,EAAA,EAAA,MAAC,MAAD,CAAK,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,WAA1D,EACE,EAAA,EAAA,KAAC,GAAD,CACU,SACR,aAAc,EACd,sBAAA,GACA,MAAO,GAAM,KACb,SAAS,EAAA,EAAA,KAAC,GAAD,CAAa,GAAI,CAAmB,CAAA,YAE7C,EAAA,EAAA,MAAC,EAAD,CAAiB,UAAW,GAAO,gBAAnC,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,WAAY,MAAO,CAAE,WAAY,CAAiB,CAAI,CAAA,GAC7E,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,GAAO,mBAAY,CAAmB,CAAA,CACxC,GACL,CAAA,EAEb,IACC,EAAA,EAAA,KAAC,GAAD,CACE,IAAK,EACL,SAAW,GAAM,IAAW,CAAC,EAC7B,kBAAA,EACD,CAAA,CAEA,GAET,2YEnXA,SAAS,GAAM,CACb,WAAW,KACX,QAAQ,GACR,SAAS,GACT,cAAgB,KAChB,YAAY,GACZ,QACA,aAAa,GACb,aACA,OAAQ,GACK,CACb,GAAM,CAAC,EAAY,IAAA,EAAA,EAAA,UAA0B,CAAM,EAC7C,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,CAAM,EAejD,OAbA,EAAA,EAAA,eAAgB,CACV,GAEF,EAAc,CAAM,EACpB,eAAiB,EAAa,EAAI,EAAG,CAAC,IAEtC,EAAa,EAAK,EAClB,eAAiB,EAAc,CAAM,EAAG,GAAG,EAE/C,EAAG,CAAC,CAAM,CAAC,EAEN,GAGH,EAAA,EAAA,KAAC,GAAD,CAAA,UACE,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,SAAS,EAAG,MAAO,GAAY,mBAArF,EACE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,GAAa,GAAO,kBAAmB,GAAY,QAAQ,EAC9F,MAAO,GAAY,SACnB,QAAS,CACV,CAAA,EACA,IACC,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,MAAO,GAAa,GAAO,WAAY,EAAW,GAAY,KAAK,EACxF,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,KAAM,EACxC,QAAU,GAAM,EAAE,gBAAgB,WAHpC,CAKG,CAAC,IACA,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,MAAM,EAAG,MAAO,GAAY,gBAA/E,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAY,MAAO,MAAO,GAAY,eAAQ,CAAW,CAAA,GACzE,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,QAAS,EAAS,KAAM,EAAA,QAAW,UAAW,GAAY,YAAa,MAAO,GAAY,WAA6E,CAAA,CACrL,IAEN,CACE,GAEJ,GACE,CAAA,EA1Ba,IA4B1B,CCvDA,SAAS,GAAa,EAAwC,CAC5D,GAAM,CACN,WAAW,KACX,YAAY,GACZ,cAAgB,CAAC,EACjB,gBAAkB,CAAC,EACnB,QAAQ,GACR,UAAU,KACV,OAAQ,EAAa,IAAA,GACrB,cAAc,UACd,cAAc,SACd,WAAW,GACX,qBAAqB,CAAC,GAClB,EAAqB,eAAgB,CAAK,EACxC,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,EAAK,EAChD,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,EAAK,EAEtD,SAAS,EAAY,EAAY,GAAO,CACtC,EAAgB,EAAK,EACrB,EAAQ,CAAS,CACnB,CAEA,eAAe,GAAgB,CAC7B,EAAgB,EAAI,EACpB,GAAI,CACF,MAAM,EAAU,EAChB,EAAY,EAAI,CAClB,QAAU,CACR,EAAgB,EAAK,CACvB,CACF,CAIA,IAAM,GACJ,EAAA,EAAA,MAAC,GAAD,CAAc,QAAe,OAHhB,IAAe,IAAA,GAAY,EAAe,EAGlB,YAAe,EAAY,EAAG,UAAW,EAAW,IAAA,GAAY,WAArG,CACG,GACD,EAAA,EAAA,KAAC,GAAD,CACE,YAAe,EAAY,EAC3B,SAAU,EACG,cACA,cACb,kBAAmB,EAAW,EAAgB,OAAS,IAAA,GACvD,sBAAuB,EACvB,GAAI,CACL,CAAA,CACI,IAKT,OAFK,GAGH,EAAA,EAAA,MAAC,MAAD,CAAgB,qBAAhB,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,YAAe,EAAgB,EAAI,EAAI,UAAe,CAAA,EAC3D,CACE,IANe,CAQxB,gnCE9DM,GAA6B,CAAC,QAAS,QAAS,QAAS,QAAS,QAAS,KAAM,IAAI,EAErF,GAAgB,QAEhB,OAAiC,CACrC,IAAM,EAAS,UAAU,UAAU,IAAI,QAAQ,IAAK,GAAG,GAAK,GAO5D,OALK,GAAiB,SAAS,CAAM,EAEjC,IAAW,SAAW,IAAW,KAAa,QAC9C,IAAW,KAAa,QAErB,EALwC,EAMjD,EAEa,GAAa,GAA2B,CACnD,OAAQ,EAAR,CACE,IAAK,QACL,IAAK,QACH,MAAO,KACT,IAAK,QACL,IAAK,QACL,IAAK,QACH,MAAO,KACT,QACE,MAAO,IACX,CACF,EAyBI,GAAwB,GAAiB,EAK7C,eAAsB,GAAU,EAA+B,CAC7D,GAAgB,CAElB,CAEA,SAAgB,GAAU,EAAY,IAAa,CACjD,OAAO,GAAc,QAAQ,IAAK,CAAS,CAC7C,CCjEA,SAAgB,GAAe,EAAe,EAAsB,CAClE,OAAO,IAAI,KAAK,EAAM,EAAO,CAAC,EAAE,QAAQ,CAC1C,CAEA,SAAgB,GAA2B,EAAa,EAAe,EAAoB,CACzF,OAAO,IAAI,KAAK,KAAK,IAAI,EAAM,EAAQ,EAAG,CAAG,CAAC,CAChD,CAEA,SAAgB,GAAa,EAAgB,EAAc,EAAe,EAAa,EAAQ,GAAe,CAE5G,OAAO,IADc,KAAK,KAAK,IAAI,EAAM,EAAQ,EAAG,CAAG,CAChD,EAAS,mBAAmB,EAAQ,CAAE,MAAO,EAAQ,QAAU,MAAO,CAAC,CAChF,CAEA,SAAgB,GAAc,EAAS,GAAU,GAAG,EAAa,CAC/D,OAAO,MAAM,KAAK,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,IAAK,GAAU,GAAa,EAAQ,KAAM,EAAQ,EAAG,CAAC,CAAC,CAC7F,CAEA,SAAgB,GAAY,EAAgB,EAAQ,GAAgB,CAClE,IAAM,EAAW,IAAI,KAAK,KAAK,IAAI,KAAM,EAAG,EAAE,CAAC,EACzC,EAAqB,CAAC,EAC5B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,IACrB,EAAS,KAAK,EAAS,mBAAmB,EAAQ,CAAE,QAAS,EAAQ,QAAU,MAAO,CAAC,CAAC,EACxF,EAAS,QAAQ,EAAS,QAAQ,EAAI,CAAC,EAEzC,OAAO,CACT,CAEA,SAAgB,GAAuB,EAAe,EAAsB,CAE1E,OADc,IAAI,KAAK,KAAK,IAAI,EAAM,EAAQ,EAAG,CAAC,CAAC,EAAE,OAC9C,GAAS,CAClB,CAEA,SAAgB,GAAyB,EAA0D,CACjG,MAAO,CACL,IAAK,EAAK,QAAQ,EAClB,MAAO,EAAK,SAAS,EAAI,EACzB,KAAM,EAAK,YAAY,CACzB,CACF,CAEA,SAAgB,GAAc,EAAoB,CAChD,IAAM,EAAM,EAAK,QAAQ,EACnB,EAAQ,EAAK,SAAS,EAAI,EAC1B,EAAO,EAAK,YAAY,EAE9B,MAAO,GAAG,EAAM,GAAK,IAAI,IAAQ,EAAI,GAAG,EAAQ,GAAK,IAAI,IAAU,EAAM,GAAG,GAC9E,CAwBA,SAAgB,GACd,EACA,EACA,EACe,CACf,IAAI,EAAQ,EACR,EAAgB,EAqBpB,OAnBI,EAAM,KAAO,MACX,EAAM,GAAK,KACb,EAAQ,IAAI,EAAM,KAAK,EAAc,UAAU,CAAC,IAChD,EAAgB,CAAE,MAAO,EAAG,IAAK,CAAE,GAC1B,EAAM,KAAO,KAClB,EAAM,KAAO,KAAO,EAAM,GAAK,MACjC,EAAQ,IAAI,EAAM,KAAK,EAAc,UAAU,CAAC,IAChD,EAAgB,CAAE,MAAO,EAAG,IAAK,CAAE,IAIrC,EAAM,KAAO,KAAO,EAAM,GAAK,MACjC,EAAQ,GAAG,EAAM,UAAU,EAAG,CAAC,EAAE,GAAG,EAAM,KAAK,EAAc,UAAU,CAAC,IACxE,EAAgB,CAAE,MAAO,EAAG,IAAK,CAAE,GAEjC,EAAM,KAAO,KAAO,EAAM,KAAO,KAAO,EAAM,GAAK,MACrD,EAAQ,GAAG,EAAM,UAAU,EAAG,CAAC,IAAI,EAAM,GAAG,GAAG,EAAc,UAAU,CAAC,KAGnE,CAAE,QAAO,UAAW,CAAc,CAC3C,CC5EA,SAAS,GACP,EACA,EACA,EACA,EACA,EACA,CACA,GAAM,CAAE,IAAK,EAAU,MAAO,EAAY,KAAM,GAAc,EAC1D,GAAyB,CAAc,EACvC,CAAE,IAAK,IAAA,GAAW,MAAO,IAAA,GAAW,KAAM,IAAA,EAAU,EAClD,CAAE,IAAK,EAAQ,MAAO,EAAU,KAAM,GAAY,EACpD,GAAyB,CAAY,EACrC,CAAE,IAAK,IAAA,GAAW,MAAO,IAAA,GAAW,KAAM,IAAA,EAAU,EAElD,EAAgB,GAA2B,EAAK,EAAO,CAAI,EAE3D,EAAc,IAAQ,GAAY,IAAU,GAAc,IAAS,EACnE,EAAY,IAAQ,GAAU,IAAU,GAAY,IAAS,EAE/D,EAAY,GAChB,GAAI,IAAa,IAAA,IAAa,IAAe,IAAA,IAAa,IAAc,IAAA,IACpE,IAAW,IAAA,IAAa,IAAa,IAAA,IAAa,IAAY,IAAA,GAAW,CAC3E,IAAM,EAAuB,GAA2B,EAAU,EAAY,CAAS,EACjF,EAAqB,GAA2B,EAAQ,EAAU,CAAO,EAC/E,EACE,EAAc,QAAQ,GAAK,EAAqB,QAAQ,GACxD,EAAc,QAAQ,GAAK,EAAmB,QAAQ,CAC1D,CAEA,MAAO,CAAE,cAAa,YAAW,WAAU,CAC7C,CAEA,SAAS,GACP,EACA,EACA,EACA,EACA,EACS,CACT,IAAM,EAAgB,GAA2B,EAAK,EAAO,CAAI,EAEjE,GAAI,EAAS,CACX,GAAM,CAAE,IAAK,EAAQ,MAAO,EAAU,KAAM,GAAY,GAAyB,CAAO,EACxF,GAAI,EAAgB,GAA2B,EAAQ,EAAU,CAAO,EAAG,MAAO,EACpF,CAEA,GAAI,EAAS,CACX,GAAM,CAAE,IAAK,EAAQ,MAAO,EAAU,KAAM,GAAY,GAAyB,CAAO,EACxF,GAAI,EAAgB,GAA2B,EAAQ,EAAU,CAAO,EAAG,MAAO,EACpF,CAEA,MAAO,EACT,CAEA,SAAS,GAAa,EAAa,EAAe,EAAuB,CACvE,GAAM,CAAE,IAAK,EAAS,MAAO,EAAW,KAAM,GAAa,GAAyB,IAAI,IAAM,EAC9F,OAAO,IAAQ,GAAW,IAAU,GAAa,IAAS,CAC5D,CAEA,SAAwB,GAAgB,CACtC,YAAY,GACZ,QAAQ,IAAI,KAAK,EAAE,SAAS,EAAI,EAChC,OAAO,IAAI,KAAK,EAAE,YAAY,EAC9B,eAAiB,KACjB,iBACA,eACA,UAAU,KACV,UAAU,MACa,CACvB,IAAM,EAAS,GAAU,GAAG,EACtB,EAAc,GAAe,EAAO,CAAI,EACxC,EAAsB,GAAuB,EAAO,CAAI,EAE9D,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,CAAS,YAClD,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,sBAAsB,WAAhD,CACG,GAAY,CAAM,EAAE,KAAK,EAAS,KAAU,EAAA,EAAA,KAAC,MAAD,CAAA,SAAkB,CAAa,EAArB,CAAqB,CAAC,EAC5E,MAAM,KAAK,MAAM,EAAsB,CAAC,EAAE,KAAK,CAAC,EAAE,IAAK,IACtD,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,oBAAqB,GAAO,0BAA0B,CAC5E,EAFM,CAEN,CACF,EACA,MAAM,KAAK,MAAM,CAAW,EAAE,KAAK,CAAC,EAAE,IAAK,GAAU,CACpD,IAAM,EAAM,EAAQ,EACd,EAAc,GAAc,EAAK,EAAO,EAAM,EAAgB,CAAY,EAC1E,EAAa,GAAc,EAAK,EAAO,EAAM,EAAS,CAAO,EAC7D,EAAU,GAAa,EAAK,EAAO,CAAI,EAE7C,OACE,EAAA,EAAA,KAAC,EAAD,CAEE,YAAe,EAAa,KAAO,EAAS,GAA2B,EAAK,EAAO,CAAI,CAAC,EACxF,WAAA,EAAA,EAAA,SAAc,GAAO,mBAAoB,GAAO,oBAAqB,EAClE,GAAO,4BAA6B,EAAY,WAChD,GAAO,iCAAkC,EAAY,aACrD,GAAO,+BAAgC,EAAY,WACnD,GAAO,4BAA6B,GACpC,GAAO,yBAA0B,CACpC,CAAC,WAEA,CACc,EAXV,CAWU,CAErB,CAAC,EACA,MAAM,KAAK,MAAM,IAAM,EAAsB,EAAc,EAAE,EAAE,KAAK,CAAC,EAAE,IAAK,IAC3E,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,oBAAqB,GAAO,0BAA0B,WAC5E,MAEI,EAJE,CAIF,CACN,CACE,GACF,CAAA,CAET,uJEnIA,SAAS,GAAmB,EAAgC,EAAsB,CAEhF,IAAI,EAAgC,EAEpC,KACE,EAAK,MAAM,WAAa,MACxB,OAAO,EAAK,MAAM,UAAa,UAC/B,CAAC,MAAM,QAAQ,EAAK,MAAM,QAAQ,GAElC,EAAO,EAAK,MAAM,SAGpB,IAAM,EAAmB,EAAK,MAAM,SAEpC,GAAI,MAAM,QAAQ,CAAO,EAAG,CAE1B,IAAM,EAAM,EAEZ,GAAI,CAAC,EAAI,IAAI,OAAO,cACb,IAAM,KAAQ,EACjB,GAAI,OAAO,GAAS,UAAY,EAAK,KAAK,EAAE,OAAS,EACnD,OAAO,EAAK,YAAY,EAAE,WAAW,CAAG,CAAA,CAI9C,OAAO,OAAO,EAAI,GAAG,MAAM,QAAQ,EAAE,YAAY,EAAE,WAAW,CAAG,CACnE,CAEA,OAAO,OAAO,CAAO,EAAE,YAAY,EAAE,WAAW,CAAG,CACrD,CAEA,SAAS,GAAW,EAAe,EAAgB,EAAwB,CACzE,IAAM,EAAO,EAAQ,EAGrB,OAFI,IAAS,EAAe,EACxB,EAAO,GAAW,EAAS,EACxB,CACT,CAEA,SAAS,GAAc,CACrB,WACA,WACA,YAAY,GACZ,gBAAgB,GAChB,0BAA4B,MACP,CACrB,IAAM,GAAA,EAAA,EAAA,QAAsC,IAAI,EAK1C,GAAA,EAAA,EAAA,QAA4B,EAAK,EACjC,CAAC,EAAmB,IAAA,EAAA,EAAA,UAAiC,EAAK,EAG1D,GAAA,EAAA,EAAA,QAAkB,EAAE,EACpB,GAAA,EAAA,EAAA,QAAmC,IAAI,EAEvC,GAAA,EAAA,EAAA,iBAAiC,CACrC,IAAM,EAAK,EAAa,QACxB,GAAI,CAAC,EAAI,OAET,GAAM,CAAE,YAAW,eAAc,gBAAiB,EAI9C,KAAK,IAAI,EAAY,EAAe,CAAY,EAAI,GACpD,EAAmB,UAEvB,EAAmB,QAAU,GAC7B,EAAqB,EAAI,EACzB,EAAS,EAAE,SAAW,CACpB,EAAmB,QAAU,GAC7B,EAAqB,EAAK,CAC5B,CAAC,EACH,EAAG,CAAC,CAAQ,CAAC,EAEP,GAAA,EAAA,EAAA,aACH,GAA+C,CAC9C,IAAM,EAAK,EAAa,QACxB,GAAI,CAAC,EAAI,OAGT,IAAM,EAAa,EAAA,QAAM,SAAS,QAAQ,CAAQ,EAC9C,EAAQ,EAAS,QAErB,OAAQ,EAAM,IAAd,CACE,IAAK,YACH,EAAQ,GAAW,EAAO,EAAG,EAAW,MAAM,EAC9C,MACF,IAAK,UACH,EAAQ,GAAW,EAAO,GAAI,EAAW,MAAM,EAC/C,MACF,QACE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IACrC,GAAI,GAAmB,EAAW,GAAI,EAAM,GAAG,EAAG,CAChD,GAAI,GAAS,GAAK,EAAW,UAAY,EAAM,IAC7C,SAEF,EAAQ,EACR,KACF,CAEN,CAKA,GAHA,EAAS,QAAU,EACnB,EAAW,QAAU,EAAM,IAEvB,GAAS,EAAG,CACd,IAAM,EAAQ,EAAG,SAAS,GAC1B,GAAI,EAAO,CACT,IAAM,EAAW,EAAM,UACjB,EAAc,EAAW,EAAM,aACjC,EAAW,EAAG,UAChB,EAAG,UAAY,EACN,EAAc,EAAG,UAAY,EAAG,eACzC,EAAG,UAAY,EAAc,EAAG,aAEpC,CACA,EAAoB,CAAK,CAC3B,CACF,EACA,CAAC,EAAU,CAAmB,CAChC,EAEA,OACE,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,CAAS,EAC7C,SAAU,EACV,UAAW,EACX,SAAU,EACV,IAAK,WALP,CAOG,GACC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,yBACrB,EAAA,EAAA,KAAC,EAAD,CAAgB,UAAW,GAAO,OAAU,CAAA,CACzC,CAAA,EACH,EACH,IACC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,yBACrB,EAAA,EAAA,KAAC,EAAD,CAAgB,UAAW,GAAO,OAAU,CAAA,CACzC,CAAA,CAEJ,GAET,8gIE3IA,SAAS,GAAS,EAAsB,CACtC,GAAM,CACN,eAAe,GACf,YAAY,GACZ,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,WAAW,EACX,aAAa,GACb,cAAc,CAAC,EACf,QAAQ,GACR,WAAW,GACX,WAAW,GACX,eAAiB,QAAQ,QAAQ,EACjC,UACA,WACA,QAAS,EAAc,KACvB,OAAQ,EAAa,KACrB,aAAc,EAAmB,KACjC,aAAc,EAAmB,KACjC,cAAe,EACf,sBAAsB,GACtB,iBAAiB,GACjB,wBAAwB,GACxB,oBAAoB,GACpB,gBAAgB,KAChB,iBAAiB,GACjB,yBAAyB,GACzB,QAAQ,CAAC,EACT,mBAAmB,GACnB,mBAAmB,GACnB,cAAc,GACd,aAAa,GACb,oBAAmB,GACnB,WACA,GAAG,GACC,EAAqB,WAAY,CAAK,EACpC,CAAC,GAAW,IAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,CAAC,GAAW,KAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,EAAG,KAAA,EAAA,EAAA,UAAwB,CAAC,EAC5B,GAAA,EAAA,EAAA,QAAe,CAAa,EAC5B,GAAA,EAAA,EAAA,QAAoC,IAAI,EACxC,GAAA,EAAA,EAAA,QAAmC,IAAI,EACvC,CAAC,EAAY,IAAA,EAAA,EAAA,UAA0B,EAAK,EAC5C,CAAC,GAAc,KAAA,EAAA,EAAA,UAA4B,EAAE,GAEnD,EAAA,EAAA,eAAgB,CACd,GAAI,EAAY,CACd,IAAM,EAAO,EAAW,SAAS,sBAAsB,EACvD,GAAgB,GAAM,OAAS,EAAE,CACnC,CACF,EAAG,CAAC,CAAU,CAAC,EAEf,GAAoB,CAClB,OAAQ,EACR,aACA,YACA,SAAU,EACV,cAAe,EAAO,yBACxB,CAAC,GAED,EAAA,EAAA,eAAgB,CAEd,GADA,EAAM,QAAU,EACZ,CAAC,EAAM,QAAS,OACpB,EAAM,QAAQ,MAAQ,GAAS,GAC/B,EAAM,QAAQ,SAAS,EACvB,IAAM,MAAiB,GAAY,GAAK,EAAI,CAAC,EAE7C,OADA,EAAM,QAAQ,yBAAyB,CAAQ,MAClC,EAAM,SAAS,uBAAuB,CAAQ,CAC7D,EAAG,CAAC,EAAe,CAAK,CAAC,EAEzB,IAAM,GAAuB,GAA4B,CACvD,GAAa,EAAI,EACjB,IAAmB,CAAK,CAC1B,EAEM,EAAuB,GAA4B,CACvD,GAAa,EAAK,EAClB,IAAmB,CAAK,CAC1B,EAEM,GAAkB,GAA4B,CAClD,EAAa,EAAI,EACjB,IAAc,CAAK,CACrB,EAEM,GAAiB,GAA4B,CAC7C,EAAM,UAAS,EAAM,QAAQ,QAAU,IAC3C,EAAa,EAAK,EAClB,IAAa,CAAK,CACpB,EAEM,OACG,EACF,EAAc,SAAW,EAAc,SAAS,EAChD,CAAC,GAAW,CAAC,CAAC,EAGf,MACG,CAAC,EAAE,GAAc,GAAe,WAAW,KAC/C,GAAO,EAA+B,cAAgB,UACzD,GAGI,GAAmB,GAA+B,CAClD,GACF,EAAc,IAAI,CAAG,EACrB,IAAW,EAAc,MAAO,CAAW,GAE3C,IAAW,EAAK,CAAW,CAE/B,EAEI,GAAgB,EACd,GAAe,EAAgB,EAAc,MAA2B,EACxE,GAAS,GAAS,EAExB,EAAM,QAAS,GAAuB,CAChC,EAAK,MAAQ,KACf,GAAgB,EAAK,MAEzB,CAAC,EAED,IAAM,GAAe,IAAiB,GAChC,GACJ,IAAgB,MACf,OAAO,IAAiB,UAAY,GAAa,KAAK,IAAM,GAEzD,GAAe,EAAmB,GAAI,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAO,sBAAc,GAAO,CAAA,EAAI,KACvF,GAAc,GAAS,EAAmB,EAAI,GAAG,EAAM,IAAM,EAE7D,GAAY,IAAa,CAAC,EAEhC,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,EAAW,EAAO,cAAe,EAAO,SAAU,EAC7D,EAAO,qBAAsB,CAAC,CACjC,CAAC,EACD,aAAc,GACd,aAAc,WANhB,EAQE,EAAA,EAAA,KAAC,EAAA,QAAD,CACE,GAAK,EAAW,CAAE,OAAQ,EAAM,EAAI,CAAC,EACrC,SAAW,GAAmC,IAAiB,GAAa,CAAE,IAAK,EAAG,GAAG,GAAG,EAC5F,aAAe,GAA+B,EAAO,OAAO,EAAK,GAAG,EAAI,GACxE,aAAc,EAAM,KAAM,GAAO,EAAG,MAAQ,EAAY,GAAK,KAC7D,cAAgB,GAA8C,CACxD,OAAO,EAAQ,QAAW,WAAW,EAAc,EAAQ,MAAM,CACvE,EACA,cAAe,EAAqC,IAC9C,IAAoB,OAAO,UAAU,eAAe,KAAK,EAAS,QAAQ,EACrE,CACL,GAAG,EACH,iBAAkB,EAAQ,OAAS,EAAM,QAAQ,EAAM,YAA4B,EAAI,IACzF,EAEK,YAGP,CACA,eACA,eACA,uBACA,SACA,eACA,mBACA,0BAEA,EAAA,EAAA,KAAC,MAAD,CAAA,UACE,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,QAAS,GACT,OAAQ,GACR,WAAA,EAAA,EAAA,SACE,EAAO,cACP,EACG,EAAO,oBAAqB,GAC5B,EAAO,uBAAwB,GAAY,CAAC,CAC/C,EACA,CACF,WAXF,EAaE,EAAA,EAAA,KAAC,SAAD,CACY,WACV,KAAK,SACK,WACV,gBAAe,GAAY,IAAA,GAC3B,MAAO,EAAsB,CAAE,QAAS,MAAO,OAAQ,MAAO,EAAI,CAAC,EACnE,WAAA,EAAA,EAAA,SACE,EAAO,oBACP,EACG,EAAO,6BAA8B,GACrC,EAAO,6BAA8B,GAAY,CAAC,CACrD,EACA,CACF,EACA,GAAI,EAAqB,EACzB,QAAU,GAA2C,CACnD,EAAqB,EAAE,UAAU,CAAC,EAClC,IAAU,CAAC,CACb,EACA,IAAK,WAIJ,GAAiB,OAAW,EACvB,CAAA,GACR,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,SAAU,GACA,WACV,WAAA,EAAA,EAAA,SAAc,EAAO,wBAAyB,CAAqB,EACnE,GAAI,EAAqB,EACzB,QAAU,GAA2C,CACnD,EAAqB,EAAE,UAAU,CAAC,EAClC,IAAU,CAAC,CACb,WAEC,CAAC,GAAY,CAAC,IACb,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,EAAA,cACN,WAAA,EAAA,EAAA,SAAc,EAAO,6BAA8B,EAChD,EAAO,kCAAmC,CAC7C,CAAC,CACF,CAAA,CAEG,CAAA,EACP,CAAC,GAAY,CAAC,GAAY,GACzB,EAAA,EAAA,KAAC,GAAD,CAAA,UACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACF,CACE,IAAM,GAAgC,CACpC,EAAU,QAAU,CACtB,EACA,aAAc,GAAS,GAAe,IAAA,EACxC,EACA,CAAE,iBAAkB,EAAK,CAC3B,EACA,WAAA,EAAA,EAAA,SAAc,EAAO,sBAAuB,EACzC,EAAO,4BAA6B,CACvC,CAAC,EACD,MAAO,CAAE,MAAO,GAAG,GAAa,GAAI,YAEpC,EAAA,EAAA,KAAC,GAAD,CACY,WACV,UAAW,EAAO,kBACG,+BAEpB,EAAM,KAAK,EAAoB,KAC9B,EAAA,EAAA,KAAC,MAAD,CAEE,GAAI,EAAa,CAAE,QAAO,OAAM,SAAU,CAAC,CAAC,EAAK,QAAS,CAAC,EAC3D,WAAA,EAAA,EAAA,SAAc,EAAO,sBAAuB,EAAmB,EAC5D,EAAO,6BAA8B,IAAqB,GAC1D,EAAO,+BAAgC,IAAiB,GACxD,EAAO,+BAAgC,CAAC,CAAC,EAAK,QACjD,CAAC,WAEA,EAAK,KACH,EATE,EAAK,GASP,CACN,CACY,CAAA,CACZ,CAAA,CACE,CAAA,EACP,MACJ,EAAA,EAAA,KAAC,WAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,iBAAkB,EACpC,EAAO,qBAAsB,GAC7B,EAAO,uBAAwB,IAC/B,EAAO,uBAAwB,IAC/B,EAAO,qBAAsB,EAChC,CAAC,YAED,EAAA,EAAA,KAAC,SAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,uBAAwB,EAC1C,EAAO,8BACN,IAAqB,GAAoB,IAAa,CAAC,GAC3D,CAAC,YAED,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAkB,CAAA,CACnB,CAAA,CACA,CAAA,EACT,GAAoB,IACnB,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,iBAAkB,EACpC,EAAO,0BAA2B,GAAoB,IAAa,CAAC,EACvE,CAAC,WAHH,CAKG,EACA,EACE,IAEN,GAAoB,IACnB,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SACE,EAAO,oBACP,IAAa,CAAC,IAAiB,EAAO,wBACxC,WAEC,CACE,CAAA,CAEJ,GACF,CAAA,CAEE,CAAA,EACV,GAAS,CAAC,IACT,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,kBAAmB,CAAc,WAA3D,CACG,EACA,EACE,KAEP,EAAA,EAAA,KAAC,GAAD,CACE,QAAQ,QACR,QAAS,EAAgB,EAAc,uBAAuB,EAAK,GAAgB,GACnF,UAAW,KAAW,IAAa,GACpC,CAAA,CACE,GAET,01BErSA,SAAwB,GAAW,EAAwB,CACzD,GAAM,CACN,YAAY,GACZ,WACA,eAAiB,KACjB,gBAAgB,KAChB,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,eAAiB,KACjB,UAAU,KACV,UAAU,KACV,WAAW,KACX,kBAAkB,GAClB,QAAQ,GACR,UAAU,GACV,eAAe,GACf,aAAa,GACb,YACA,WACI,EAAqB,aAAc,CAAK,EACtC,MACJ,EAAiB,EAAc,MAAiB,EAE5C,EAAc,EAAa,GAAK,IAAI,KAEpC,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,EAAY,SAAS,EAAI,CAAC,EACrE,CAAC,EAAa,IAAA,EAAA,EAAA,UAA2B,EAAY,YAAY,CAAC,EAClE,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,EAAK,EAChD,CAAC,EAAmB,IAAA,EAAA,EAAA,cACxB,EAAa,EAAI,GAAc,CAAW,EAAI,EAChD,EACM,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,CAAC,EAAW,KAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,EAAG,IAAA,EAAA,EAAA,UAAwB,CAAC,EAC5B,CAAC,EAAc,KAAA,EAAA,EAAA,UAA4B,CAAQ,EAEnD,IAAA,EAAA,EAAA,QAAe,CAAa,EAGlC,GAAI,IAAiB,EAAU,CAC7B,GAAgB,CAAQ,EACxB,IAAM,EAAI,GAAY,IAAI,KAC1B,EAAgB,EAAE,SAAS,EAAI,CAAC,EAChC,EAAe,EAAE,YAAY,CAAC,EAC9B,EAAqB,EAAW,GAAc,CAAQ,EAAI,EAAE,CAC9D,EAGA,EAAA,EAAA,eAAgB,CAEd,GADA,GAAM,QAAU,EACZ,CAAC,EAAe,OACpB,IAAM,MAAiB,CACrB,IAAM,EAAM,EAAc,MACtB,GACF,EAAgB,EAAI,SAAS,EAAI,CAAC,EAClC,EAAe,EAAI,YAAY,CAAC,EAChC,EAAqB,GAAc,CAAG,CAAC,GAEvC,EAAqB,EAAE,EAEzB,EAAa,GAAc,EAAI,CAAC,CAClC,EAEA,OADA,EAAc,yBAAyB,CAAQ,MAClC,EAAc,uBAAuB,CAAQ,CAC5D,EAAG,CAAC,CAAa,CAAC,EAElB,IAAM,OACG,EACF,EAAc,SAAW,EAAc,SAAS,EAChD,CAAC,GAAW,CAAC,CAAC,EAGf,OACG,CAAC,EAAE,GAAc,GAAe,WAAW,KAC/C,GAAO,EAA+B,cAAgB,UACzD,GAGI,EAAgB,GAAsB,CAC1C,EAAqB,EAAO,GAAc,CAAI,EAAI,EAAE,EAChD,GAAe,EAAc,IAAI,CAAI,EACzC,EAAS,CAAI,CACf,EAEM,EAAgB,GAAsB,CAC1C,EAAa,CAAI,EACjB,EAAS,CAAI,EACb,EAAgB,EAAK,CACvB,EAEM,EAAe,GAAkB,CACrC,EAAiB,GAAS,CACxB,IAAI,EAAO,EAAO,EAGlB,OAFI,EAAO,GAAK,EAAO,GAAI,EAAgB,GAAM,EAAI,CAAC,GAC7C,EAAO,KAAM,EAAO,EAAG,EAAgB,GAAM,EAAI,CAAC,GACpD,CACT,CAAC,CACH,EAEM,EAAsB,GAAoC,CAC9D,GAAI,EAAW,MAAM,uBAAuB,EAAG,CAC7C,GAAM,CAAC,EAAK,EAAO,GAAQ,EAAW,MAAM,GAAG,EACzC,EAAa,GAA2B,OAAO,CAAG,EAAG,OAAO,CAAK,EAAG,OAAO,CAAI,CAAC,EACtF,GAAI,GAAc,EAAW,SAAS,IAAM,iBACb,CAAC,GAAW,GAAc,KAC3B,CAAC,GAAW,GAAc,GACL,OAAO,CAE5D,CACA,OAAO,IACT,EAEM,IAA2B,CAAE,gBAAe,eAA2D,CAG3G,GAAI,CAAC,GAAiB,EAAU,QAAU,EAAc,MAAO,OAAO,EAEtE,IAAM,EAAY,GAAqB,EAAU,MAAO,EAAc,MAAO,EAAU,WAAa,IAAI,EAElG,EAAa,EAAmB,EAAU,KAAK,EAGrD,OAFI,GAAY,EAAa,CAAU,EAEhC,CACT,EAEM,OAA+B,CACnC,IAAI,EAAS,IACT,EAAa,IAAI,KAAK,EAAE,YAAY,EAAI,IAG5C,OAFI,IAAS,EAAa,EAAQ,YAAY,GAC1C,IAAS,EAAS,EAAQ,YAAY,EAAI,EAAa,GACpD,MAAM,KAAK,MAAM,CAAM,EAAE,KAAK,CAAC,EAAE,IAAK,IAAO,CAAE,IAAK,EAAI,EAAY,MAAO,EAAI,CAAW,EAAE,CACrG,EAEM,GAAY,EAAa,EACzB,EAAS,GAAS,EA8BlB,IACJ,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CA7Ba,EAAW,MACxB,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,0BAAvB,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,KAAM,EAAA,cAAe,YAAe,EAAY,EAAE,CAAI,CAAA,GAClE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,gDACrB,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,sCAAvB,EACE,EAAA,EAAA,KAAC,GAAD,CACE,WAAA,GACA,iBAAA,GACA,SAAW,GAAM,EAAgB,CAAW,EAC5C,UAAW,GAAO,sBAClB,MAAO,GAAa,GAAU,GAAG,EAAG,EAAa,EAAc,CAAC,EAChE,MAAO,GAAc,EAAE,KAAK,EAAO,KAAW,CAAE,IAAK,EAAQ,EAAG,MAAO,CAAM,EAAE,CAChF,CAAA,GACD,EAAA,EAAA,KAAC,GAAD,CACE,WAAA,GACA,iBAAA,GACA,iBAAkB,GAClB,UAAW,GAAO,qBAClB,SAAW,GAAM,EAAe,CAAW,EAC3C,MAAO,EACP,MAAO,GAAuB,CAC/B,CAAA,CACE,GACF,CAAA,GACL,EAAA,EAAA,KAAC,EAAD,CAAY,KAAM,EAAA,eAAgB,YAAe,EAAY,CAAC,CAAI,CAAA,CAC/D,KAMH,EAAA,EAAA,KAAC,GAAD,CACE,UAAW,GAAO,gBAClB,MAAO,EACP,KAAM,EACN,SAAU,EACV,eAAgB,GAAa,GAC7B,aAAc,GAAW,GAChB,UACA,SACV,CAAA,EACA,IAAmB,EAAA,EAAA,KAAC,EAAD,CAAQ,YAAe,EAAa,IAAI,WAAG,OAAa,CAAA,EAC3E,CACD,CAAA,CAAA,EAGE,GAAQ,EAAU,MACtB,EAAA,EAAA,KAAC,GAAD,CACE,SAAU,EACV,WAAY,EAAU,CAAE,MAAO,GAAO,oBAAqB,EAAI,IAAA,GAC/D,MAAO,GAAG,IAAQ,GAAmB,EAAI,KAAO,KAChD,MAAO,EACP,SAAW,GAAM,EAAqB,CAAW,EACjD,YAAe,EAAgB,EAAI,EACnC,aACE,EAAA,EAAA,KAAC,EAAA,QAAD,CAAW,KAAK,aAAa,gBAAgB,IAA6B,0BAA0B,CAAA,EAEtG,WAAc,CACR,GAAM,UAAS,GAAM,QAAQ,QAAU,IAC3C,EAAa,EAAK,EAClB,EAAa,EAAmB,CAAiB,CAAC,CACpD,EACA,YAAe,EAAa,EAAI,EAChC,iBAAoB,GAAa,EAAI,EACrC,iBAAoB,GAAa,EAAK,EACtC,QAAS,CAAC,CACX,CAAA,EAGG,GACA,EAAiB,GACjB,GAEA,EAAA,EAAA,KAAC,GAAD,CAAO,WAAA,GAAW,OAAQ,EAAc,YAAe,EAAgB,EAAK,WACzE,EACI,CAAA,GAIT,EAAA,EAAA,KAAC,GAAD,CACE,OAAQ,EACR,aAAe,GAAkB,EAAgB,CAAI,EACrD,QAAS,GACT,MAAO,GAAM,KACb,sBAAA,YAEC,EACW,CAAA,EAIlB,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,WAAY,CAAS,WAA/C,EACI,GAAW,IAAa,GACzB,IACD,EAAA,EAAA,KAAC,GAAD,CACE,QAAQ,QACR,QAAS,EAAgB,EAAc,uBAAuB,EAAK,GAAgB,GACnF,UAAW,IAAW,GAAa,EACpC,CAAA,CACE,GAET,CCvRA,IAAY,GAAL,SAAA,EAAA,OACL,GAAA,KAAA,OACA,EAAA,OAAA,SACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,yWECM,GAA8D,EACjE,GAAoB,MAAO,GAAO,iBAClC,GAAoB,QAAS,GAAO,mBACpC,GAAoB,OAAQ,GAAO,gBACtC,EAEA,SAAS,GAAQ,EAAmC,CAClD,GAAM,CACJ,OACA,eAAe,GAAoB,OACnC,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,UAAW,CAAK,EAEnC,EAAU,GAAQ,MAAQ,IAAS,GAEzC,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,KAAK,YACL,WAAA,EAAA,EAAA,SACE,GAAO,QACP,GAAW,GAAuB,GAClC,EACA,GAAY,IACd,EACA,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,WATzC,EAWE,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,IAAI,EAAG,MAAO,GAAY,IAAO,CAAA,EACpF,IACC,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,OAAO,EAAG,MAAO,GAAY,iBACjF,CACG,CAAA,EAEP,IACC,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,IAAI,EAAG,MAAO,GAAY,IAAO,CAAA,CAEpF,GAET,kRE1CA,SAAS,GAAO,CACd,YACA,SAAS,GACT,cACA,cACA,YAC4B,CAC5B,IAAM,GAAA,EAAA,EAAA,QAAsC,IAAI,EAC1C,GAAA,EAAA,EAAA,QAAoC,IAAI,EAe9C,OAbA,EAAA,EAAA,eAAgB,CACd,IAAM,EAAW,IAAI,mBAAqB,CACpC,EAAa,SAAW,EAAW,SACrC,EAAa,QAAQ,MAAM,YACzB,yBACA,GAAG,EAAW,QAAQ,YAAY,GACpC,CAEJ,CAAC,EAED,OADI,EAAW,SAAS,EAAS,QAAQ,EAAW,OAAO,MAC9C,EAAS,WAAW,CACnC,EAAG,CAAC,CAAC,GAGH,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,OAAQ,GAAU,GAAO,WAAY,CAAS,EACnE,MAAO,CACL,GAAI,IAAgB,IAAA,IAAa,CAAE,wBAAyB,CAAY,EACxE,GAAI,IAAgB,IAAA,IAAa,CAAE,wBAAyB,CAAY,CAC1E,YAEA,EAAA,EAAA,KAAC,MAAD,CAAK,IAAK,EAAY,UAAW,GAAO,wBACtC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,mBACpB,UACE,CAAA,CACF,CAAA,CACF,CAAA,CAET,CC5CA,IAAY,GAAL,SAAA,EAAA,OAEL,GAAA,KAAA,OAEA,EAAA,SAAA,WAEA,EAAA,OAAA,SAEA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,EAEY,GAAL,SAAA,EAAA,OAEL,GAAA,KAAA,OAEA,EAAA,OAAA,SAEA,EAAA,KAAA,QACF,EAAA,CAAA,CAAA,++BEJA,SAAS,GAAgB,EAAY,EAAkC,CACrE,GAAI,CAAC,EAAc,OAAQ,MAAO,GAClC,IAAM,EAAO,EAAK,KAAK,YAAY,EAC7B,EAAO,EAAK,KAAK,YAAY,EACnC,OAAO,EAAc,KAAM,GAAQ,CACjC,IAAM,EAAS,EAAI,KAAK,EAAE,YAAY,EAItC,OAHK,EACD,EAAO,WAAW,GAAG,EAAU,EAAK,SAAS,CAAM,EACnD,EAAO,SAAS,IAAI,EAAU,EAAK,WAAW,EAAO,MAAM,EAAG,EAAE,CAAC,EAC9D,IAAS,EAHI,EAItB,CAAC,CACH,CAKA,SAAS,GAAS,EAAY,EAAqD,CAIjF,OAHI,IAAe,GAAmB,KAC7B,QAAQ,QAAQ,CAAE,GAAI,GAAM,MAAO,CAAK,CAAC,EAE3C,IAAI,QAAqB,GAAY,CAC1C,IAAM,EAAS,IAAI,WACnB,EAAO,OAAU,GAAU,CACzB,IAAM,EAAO,EAAM,QAAQ,OAC3B,GAAI,OAAO,GAAS,SAAU,CAC5B,EAAQ,CAAE,GAAI,EAAM,CAAC,EACrB,MACF,CACA,EAAQ,CACN,GAAI,GACJ,MAAO,CAAE,KAAM,EAAK,KAAM,KAAM,EAAK,KAAM,KAAM,EAAK,KAAM,aAAc,EAAK,aAAc,MAAK,CACpG,CAAC,CACH,EACA,EAAO,YAAgB,EAAQ,CAAE,GAAI,EAAM,CAAC,EACxC,IAAe,GAAmB,OAAQ,EAAO,cAAc,CAAI,EAClE,EAAO,WAAW,CAAI,CAC7B,CAAC,CACH,CAGA,SAAS,GAAU,EAAyC,CAC1D,OAAO,IAAI,QAAS,GAAY,CAC9B,GAAI,EAAM,OACR,EAA+B,KAC5B,GAAS,EAAQ,CAAC,CAAI,CAAC,MAClB,EAAQ,CAAC,CAAC,CAClB,OACK,GAAI,EAAM,YAAa,CAC5B,IAAM,EAAU,EAAmC,aAAa,EAC1D,EAA+B,CAAC,EAChC,MAAkB,CAEtB,EAAO,YAAa,GAAU,CACvB,EAAM,QAGT,EAAU,KAAK,GAAG,CAAK,EACvB,EAAU,GAHV,QAAQ,IAAI,EAAU,IAAI,EAAS,CAAC,EAAE,KAAM,GAAW,EAAQ,EAAO,KAAK,CAAC,CAAC,CAKjF,MAAS,EAAQ,CAAC,CAAC,CAAC,CACtB,EACA,EAAU,CACZ,MACE,EAAQ,CAAC,CAAC,CAEd,CAAC,CACH,CAMA,SAAS,GAAY,EAA4B,EAA4C,CAC3F,IAAM,EAAQ,EAAa,MAC3B,GAAI,GAAS,EAAM,OAAQ,CACzB,GAAI,GAAoB,OAAO,EAAM,GAAG,kBAAqB,WAAY,CACvE,IAAM,EAA6B,CAAC,EACpC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,GAAK,EACrC,GAAI,EAAM,GAAG,OAAS,OAAQ,CAC5B,IAAM,EAAQ,EAAM,GAAG,iBAAiB,EACpC,GAAO,EAAQ,KAAK,CAAK,CAC/B,CAEF,GAAI,EAAQ,OACV,OAAO,QAAQ,IAAI,EAAQ,IAAI,EAAS,CAAC,EAAE,KAAM,GAAW,EAAO,KAAK,CAAC,CAE7E,CACA,IAAM,EAAgB,CAAC,EACvB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,GAAK,EACrC,GAAI,EAAM,GAAG,OAAS,OAAQ,CAC5B,IAAM,EAAO,EAAM,GAAG,UAAU,EAC5B,GAAM,EAAM,KAAK,CAAI,CAC3B,CAEF,OAAO,QAAQ,QAAQ,CAAK,CAC9B,CACA,OAAO,QAAQ,QAAQ,MAAM,KAAK,EAAa,OAAS,CAAC,CAAC,CAAC,CAC7D,CAIA,SAAS,GAAS,CAChB,WACA,gBAAgB,CAAC,EACjB,aAAa,GAAmB,KAChC,oBAAoB,GACpB,WAAW,GACX,WACA,UACA,cAAc,GACd,mBAAmB,GACnB,UACA,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,QACA,iBACA,WACA,kBACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACa,CAChB,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAsC,GAAe,IAAI,EAElE,GAAA,EAAA,EAAA,QAAoC,IAAI,EACxC,GAAA,EAAA,EAAA,OAAgB,EAChB,GAAA,EAAA,EAAA,QAAmB,CAAM,EACzB,GAAA,EAAA,EAAA,QAAyB,CAAC,EAC1B,GAAA,EAAA,EAAA,QAAuB,CAAC,EAGxB,GAAA,EAAA,EAAA,QAAa,CACjB,gBAAe,aAAY,WAAU,WAAU,UAAS,mBACxD,WAAU,iBAAgB,WAAU,iBACtC,CAAC,EACD,EAAI,QAAU,CACZ,gBAAe,aAAY,WAAU,WAAU,UAAS,mBACxD,WAAU,iBAAgB,WAAU,iBACtC,EAEA,IAAM,GAAA,EAAA,EAAA,aAA4B,GAAyB,CACrD,EAAU,UAAY,IAC1B,EAAU,QAAU,EACpB,EAAU,CAAI,EACd,EAAI,QAAQ,kBAAkB,CAAI,EACpC,EAAG,CAAC,CAAC,EAEC,GAAA,EAAA,EAAA,aAA2B,KAAO,IAAqB,CAC3D,IAAM,EAAI,EAAI,QACR,EAAkC,CAAC,EACrC,EAAmB,CAAC,EAExB,IAAK,IAAM,KAAQ,EACZ,GAAgB,EAAM,EAAE,aAAa,EAE/B,EAAE,SAAW,MAAQ,EAAK,KAAO,EAAE,QAC5C,EAAW,KAAK,CAAE,OAAM,OAAQ,UAAW,CAAC,EAE5C,EAAS,KAAK,CAAI,EAJlB,EAAW,KAAK,CAAE,OAAM,OAAQ,gBAAiB,CAAC,EAQjD,EAAE,WAAU,EAAW,EAAS,MAAM,EAAG,CAAC,GAC3C,EAAE,UAAY,MAAQ,EAAS,OAAS,EAAE,WAC5C,EAAS,MAAM,EAAE,QAAQ,EAAE,QAAS,GAAS,EAAW,KAAK,CAAE,OAAM,OAAQ,SAAU,CAAC,CAAC,EACzF,EAAW,EAAS,MAAM,EAAG,EAAE,QAAQ,GAIzC,IAAM,EAAU,MAAM,QAAQ,IAAI,EAAS,IAAK,GAAS,GAAS,EAAM,EAAE,UAAU,CAAC,CAAC,EAChF,EAAgC,CAAC,EACvC,EAAQ,SAAS,EAAQ,IAAU,CAC7B,EAAO,GAAI,EAAO,KAAK,EAAO,KAAK,EAClC,EAAW,KAAK,CAAE,KAAM,EAAS,GAAQ,OAAQ,WAAY,CAAC,CACrE,CAAC,EAEG,EAAW,QAAQ,EAAE,WAAW,CAAU,EAC9C,EAAa,EAAW,QAAU,CAAC,EAAO,OAAS,GAAe,MAAQ,GAAe,IAAI,EACzF,EAAO,QAAQ,EAAE,iBAAiB,CAAM,CAC9C,EAAG,CAAC,CAAY,CAAC,GAGjB,EAAA,EAAA,eAAgB,CACd,IAAM,EAAY,GAChB,CAAC,GAAM,MAAM,KAAK,EAAG,OAAS,CAAC,CAAC,EAAE,SAAS,OAAO,EAE9C,EAAqB,GAAiB,CACtC,EAAI,QAAQ,UAAY,CAAC,EAAS,EAAE,YAAY,IACpD,EAAgB,SAAW,GACvB,EAAU,UAAY,GAAe,MAAQ,EAAU,UAAY,GAAe,QACpF,EAAa,GAAe,QAAQ,EAExC,EACM,MAA0B,CAC9B,EAAgB,QAAU,KAAK,IAAI,EAAG,EAAgB,QAAU,CAAC,EAC7D,EAAgB,UAAY,GAAK,EAAU,UAAY,GAAe,UACxE,EAAa,GAAe,IAAI,CAEpC,EACM,MAAqB,CACzB,EAAgB,QAAU,EAC1B,EAAc,QAAU,EACpB,EAAU,UAAY,GAAe,UAAU,EAAa,GAAe,IAAI,CACrF,EAKA,OAHA,OAAO,iBAAiB,YAAa,CAAiB,EACtD,OAAO,iBAAiB,YAAa,CAAiB,EACtD,OAAO,iBAAiB,OAAQ,CAAY,MAC/B,CACX,OAAO,oBAAoB,YAAa,CAAiB,EACzD,OAAO,oBAAoB,YAAa,CAAiB,EACzD,OAAO,oBAAoB,OAAQ,CAAY,CACjD,CACF,EAAG,CAAC,CAAY,CAAC,EAEjB,IAAM,GAAA,EAAA,EAAA,aAA0B,GAAuC,CACrE,EAAE,eAAe,EACjB,EAAE,gBAAgB,EACd,EAAE,eAAc,EAAE,aAAa,WAAa,EAAW,OAAS,OACtE,EAAG,CAAC,CAAQ,CAAC,EAEP,GAAA,EAAA,EAAA,aAA2B,GAAuC,CACtE,EAAE,eAAe,EACjB,EAAE,gBAAgB,EACd,KACJ,EAAc,SAAW,EACzB,EAAa,GAAe,MAAM,EACpC,EAAG,CAAC,EAAU,CAAY,CAAC,EAErB,GAAA,EAAA,EAAA,aAA2B,GAAuC,CACtE,EAAE,eAAe,EACjB,EAAE,gBAAgB,EAClB,EAAc,QAAU,KAAK,IAAI,EAAG,EAAc,QAAU,CAAC,EACzD,EAAc,UAAY,GAE5B,EAAa,EAAgB,QAAU,EAAI,GAAe,SAAW,GAAe,IAAI,CAE5F,EAAG,CAAC,CAAY,CAAC,EAEX,GAAA,EAAA,EAAA,aAAsB,GAAuC,CAKjE,GAJA,EAAE,eAAe,EACjB,EAAE,gBAAgB,EAClB,EAAc,QAAU,EACxB,EAAgB,QAAU,EACtB,GAAY,CAAC,EAAE,aAAc,CAC/B,EAAa,GAAe,IAAI,EAChC,MACF,CACA,EAAa,GAAe,IAAI,EAEhC,GAAY,EAAE,aAAc,EAAI,QAAQ,gBAAgB,EAAE,KAAM,GAAc,CACxE,EAAU,QAAQ,EAAa,CAAS,CAC9C,CAAC,CACH,EAAG,CAAC,EAAU,EAAc,CAAY,CAAC,EAEnC,IAAA,EAAA,EAAA,iBAA+B,CAC/B,GAAY,CAAC,GACjB,EAAS,SAAS,MAAM,CAC1B,EAAG,CAAC,EAAU,CAAiB,CAAC,EAE1B,GAAA,EAAA,EAAA,aAA6B,GAA2C,CAC5E,IAAM,EAAW,MAAM,KAAK,EAAE,OAAO,OAAS,CAAC,CAAC,EAEhD,EAAE,OAAO,MAAQ,GACb,EAAS,QAAQ,EAAa,CAAQ,CAC5C,EAAG,CAAC,CAAY,CAAC,EAEX,GAAA,EAAA,EAAA,aAAuB,GAA4C,CACvE,GAAI,CAAC,GAAe,EAAU,OAC9B,IAAM,EAAS,MAAM,KAAK,EAAE,eAAe,OAAS,CAAC,CAAC,EAClD,EAAO,SACT,EAAE,eAAe,EACjB,EAAa,CAAM,EAEvB,EAAG,CAAC,EAAa,EAAU,CAAY,CAAC,EAElC,IAAA,EAAA,EAAA,aAAyB,GAA2C,CACpE,CAAC,GAAqB,IACtB,EAAE,MAAQ,SAAW,EAAE,MAAQ,OACjC,EAAE,eAAe,EACjB,GAAW,EAEf,EAAG,CAAC,EAAmB,EAAU,EAAU,CAAC,EAEtC,EAAa,IAAW,GAAe,UAAY,IAAW,GAAe,OAC7E,GAAmC,CACvC,SACA,aACA,SAAU,IAAW,GAAe,OACpC,UACF,EAEM,GAAa,EAAc,OAAS,EAAc,KAAK,GAAG,EAAI,IAAA,GAEpE,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SACE,GAAO,SACP,GAAqB,GAAO,kBAC5B,GAAY,GAAO,iBACnB,CAAC,GAAY,GAAO,gBACpB,CAAC,GAAY,IAAW,GAAe,UAAY,GAAO,iBAC1D,CAAC,GAAY,IAAW,GAAe,QAAU,GAAO,eACxD,CAAC,GAAY,IAAW,GAAe,OAAS,GAAO,cACvD,GAAY,KACZ,CACF,EACA,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EAC1B,cACA,cACD,aACJ,SACR,QAAS,GACE,aACX,QAAS,EAAc,EAAU,IAAA,GACjC,KAAM,EAAoB,SAAW,IAAA,GACrC,SAAU,GAAqB,CAAC,EAAW,EAAI,IAAA,GAC/C,gBAAe,GAAY,IAAA,YAvB7B,EAyBE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAc,GAAO,wBAAyB,GAAY,OAAO,EACvG,MAAO,GAAY,iBAElB,OAAO,GAAa,WAAa,EAAS,EAAW,EAAI,CACvD,CAAA,EAEJ,GAAiB,GAAS,EAAM,OAAS,IACxC,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,iBAAkB,GAAY,QAAQ,EAAG,MAAO,GAAY,kBACnF,EAAM,KAAK,EAAM,KAChB,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,iBAAkB,GAAY,QAAQ,EAC3D,MAAO,GAAY,kBAElB,EAAK,IACH,EALE,GAAG,EAAK,KAAK,GAAG,GAKlB,CACN,CACE,CAAA,GAGP,EAAA,EAAA,KAAC,QAAD,CACE,IAAK,EACL,GAAI,EACJ,KAAK,OACL,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAY,KAAK,EACrD,MAAO,GAAY,MACnB,OAAQ,GACE,WACD,UACC,WACV,SAAU,EACV,SAAU,GACV,cAAY,MACb,CAAA,CACE,GAET,wCEnXA,SAAwB,GAAW,CAAE,YAAW,OAAM,WAAU,GAAG,GAAuC,CACxG,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,WAAY,CAAS,WAAzD,CACG,IAAQ,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAuB,MAAO,CAAA,GACvC,EAAA,EAAA,KAAC,MAAD,CAAA,SAAM,GAAY,sBAA4B,CAAA,CAC3C,GAET,2QELM,GAAgD,CACpD,QAAS,KACT,KAAM,GAAO,WACf,EAEA,SAAS,GAAQ,CACf,WAAW,KACX,OAAO,UACP,YAAY,GACZ,YAAY,EAAgB,QAC5B,cAAgB,CAAC,GACF,CACf,OACE,EAAA,EAAA,KAAC,EAAD,CACa,YACX,WAAA,EAAA,EAAA,SAAc,GAAO,IAAK,GAAU,GAAO,CAAS,EAC3C,oBAET,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,8BACrB,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,WAAa,UAAc,CAAA,CAC/C,CAAA,CACC,CAAA,CAEZ,ylCErBA,SAAS,GAAI,CACX,WAAW,KACX,OAAO,UACP,cAAc,CAAC,EACf,yBAA2B,CAAC,EAC5B,cAAgB,CAAC,EACjB,0BAA0B,GAC1B,GAAG,GACQ,CACX,GAAM,CAAC,EAAU,IAAA,EAAA,EAAA,UAAwB,EAAK,EAE9C,SAAS,GAAiB,CACpB,EAAY,OAAS,GAAG,EAAa,GAAS,CAAC,CAAI,EACvD,EAAQ,CACV,CAEA,SAAS,EAAiB,EAAqB,EAAY,CACzD,EAAE,gBAAgB,EACd,GAAyB,EAAY,EAAK,EAC9C,EAAmB,CAAE,CACvB,CAEA,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,GAAI,EAAM,UAAW,GAAO,sBAAjC,EACE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,GAAO,mBAAmB,EAC5E,QAAU,GAAM,CAAE,EAAE,gBAAgB,EAAG,EAAY,EAAK,CAAG,CAC5D,CAAA,GACD,EAAA,EAAA,KAAC,MAAD,CAAK,QAAU,GAAM,EAAE,gBAAgB,YACrC,EAAA,EAAA,KAAC,GAAD,CAAS,UAAW,GAAO,IAAW,OAAM,QAAS,YACnD,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,QAAS,GAAY,GAAO,eAAe,WAArE,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,CAAC,GAAY,GAAO,mBAAmB,EAC9E,UACE,CAAA,GACL,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,GAAO,mBAAmB,YAC9E,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,MAAU,CAAA,CAC9B,CAAA,CACF,GACE,CAAA,CACN,CAAA,GACL,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,iBACpB,EAAY,KAAK,CAAE,KAAI,QAAO,WAC7B,EAAA,EAAA,MAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,GAAY,GAAO,iBAAiB,EACvE,QAAU,GAAM,EAAiB,EAAG,CAAE,WAHxC,CAKG,IACC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,qCACrB,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,2BAAoB,CAAW,CAAA,CACnD,CAAA,GAEP,EAAA,EAAA,KAAC,GAAD,CAAS,KAAK,iBACZ,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAuB,MAAO,CAAA,CACvB,CAAA,CACN,GAZE,CAYF,CACN,CACE,CAAA,CACF,GAET,+gBE/DA,SAAS,GAAS,EAAiC,CACjD,GAAM,CAAE,iBAAkB,EAC1B,OAAO,EAAiB,EAAc,SAAW,EAAc,SAAS,EAAK,EAC/E,CAEA,SAAS,GAAW,EAAiC,CACnD,GAAM,CAAE,WAAY,EAAS,iBAAkB,EAC/C,MAAO,CAAC,EAAE,GAAW,GAAe,WAAW,KAC5C,GAAO,EAA+B,cAAgB,UACzD,EACF,CAEA,SAAwB,GAAW,CACjC,OAAO,CAAC,EACR,aAAa,KACb,QAAQ,GACR,WACA,gBAAgB,KAChB,WAAY,EACZ,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACe,CAClB,IAAM,EAAe,EAAiB,EAAc,OAAoB,KAAO,EACzE,EAAY,GAAS,CAAE,gBAAe,WAAY,CAAY,CAAC,EAC/D,EAAW,GAAW,CAAE,gBAAe,WAAY,CAAY,CAAC,EAEtE,SAAS,EAAa,EAAY,CAC5B,GAAe,EAAc,IAAI,CAAE,EACvC,IAAW,CAAE,CACf,CAEA,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,GAAO,WAAY,EAAG,GAAO,iBAAkB,CAAU,EAAG,GAAY,KAAM,CAAS,EACrG,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,WAHzC,CAKG,IACC,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,KAAK,EAAG,MAAO,GAAY,eAAlF,CACG,EACA,GAAY,IACV,KAEP,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,wBAAyB,GAAY,aAAa,EACvE,MAAO,GAAY,uBAElB,EAAK,KAAK,CAAE,KAAI,MAAO,EAAW,OAAM,iBACvC,EAAA,EAAA,MAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SACE,GAAO,eACP,EAAG,GAAO,wBAAyB,IAAiB,CAAG,EACvD,GAAY,IACd,EACA,MAAO,GAAY,KACnB,MAAO,EACP,SAAU,EACV,KAAK,SACL,YAAe,EAAa,CAAE,EAC9B,WAAY,CAAE,SAAU,CAAM,IAAQ,SAAS,EAAa,CAAE,CAAG,WAZnE,CAcG,IAAQ,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAuB,MAAO,CAAA,EACtC,GAAc,MACf,EAAA,EAAA,KAAC,EAAD,CAAS,CAAA,CACN,GAhBE,CAgBF,CACN,CACE,CAAA,CACF,GAET,CC7EA,IAAM,GAAkB,CAAC,QAAS,YAAa,UAAW,SAAU,YAAY,EAEhF,SAAS,GAAY,CACnB,WAAW,KACX,mBAAmB,IACnB,kBAAkB,IACC,CACnB,GAAM,CAAC,EAAoB,IAAA,EAAA,EAAA,UAAkC,EAAK,EAC5D,GAAA,EAAA,EAAA,QAA0D,IAAI,EAE9D,GAAA,EAAA,EAAA,iBAAqC,CACrC,EAAW,UAAY,MAAM,aAAa,EAAW,OAAO,EAChE,EAAsB,EAAK,EAC3B,EAAW,QAAU,eAAiB,CACpC,EAAsB,EAAI,CAC5B,EAAG,EAAmB,GAAI,CAC5B,EAAG,CAAC,CAAgB,CAAC,EAqBrB,OAlBA,EAAA,EAAA,eAAgB,CACd,EAAiB,CACnB,EAAG,CAAC,CAAgB,CAAC,GAGrB,EAAA,EAAA,eAAgB,CACd,IAAK,IAAM,KAAS,GAClB,SAAS,iBAAiB,EAAO,CAAgB,EAEnD,UAAa,CACX,IAAK,IAAM,KAAS,GAClB,SAAS,oBAAoB,EAAO,CAAgB,EAGlD,EAAW,UAAY,MAAM,aAAa,EAAW,OAAO,CAClE,CACF,EAAG,CAAC,CAAgB,CAAC,GAEd,EAAA,EAAA,KAAA,EAAA,SAAA,CAAA,SAAG,GAAmB,GAAsB,CAAW,CAAA,CAChE,ykBEhCA,SAAS,GAAgB,EAA2B,EAA4D,CAC9G,OAAO,EAAiB,EAAc,OAAoB,GAAM,GAAS,EAC3E,CAEA,SAAS,GAAY,EAAa,EAAoC,CACpE,IAAM,EAAQ,EAAM,KAAM,GAAS,EAAK,QAAU,CAAG,EACrD,OAAO,EAAS,EAAM,OAAS,EAAM,MAAS,CAChD,CAEA,SAAwB,GAAc,EAA2B,CAC/D,GAAM,CACN,QAAQ,GACR,QAAQ,GACR,gBAAgB,KAChB,QAAQ,CAAC,EACT,mBAAmB,GACnB,YACA,QACA,aACA,OAAQ,EACR,eAAiB,KACjB,WACA,cAAc,GACd,WAAW,GACX,GAAG,GACC,EAAqB,gBAAiB,CAAK,EACzC,EAAa,GAAgB,EAAO,CAAa,EAEjD,CAAC,EAAW,IAAA,EAAA,EAAA,cAA+B,GAAY,EAAY,CAAK,CAAC,EACzE,CAAC,EAAS,IAAA,EAAA,EAAA,UAAuB,CAAU,EAC3C,CAAC,EAAa,IAAA,EAAA,EAAA,UAA2B,EAAK,EAC9C,CAAC,EAAkB,IAAA,EAAA,EAAA,UAA+C,IAAI,EACtE,GAAA,EAAA,EAAA,QAA8D,IAAI,EAClE,GAAA,EAAA,EAAA,QAAoC,IAAI,EACxC,GAAA,EAAA,EAAA,QAAmC,IAAI,EAW7C,GATA,GAAoB,CAClB,OAAQ,EACR,aACA,YACA,SAAU,EACV,cAAe,GAAO,YACxB,CAAC,EAGG,IAAe,EAAS,CAC1B,EAAW,CAAU,EACrB,IAAM,EAAQ,EAAM,KAAM,GAAS,EAAK,QAAU,CAAU,EACxD,EAAO,EAAa,EAAM,OAAS,EAAM,KAAK,EACzC,GAAkB,EAAa,CAAU,CACpD,CAEA,IAAM,EAAY,EAAM,OAAQ,IAC7B,EAAK,OAAS,EAAK,OAAO,YAAY,EAAE,SAAS,EAAU,YAAY,CAAC,CAC3E,EAEM,MAAoB,CACpB,IACJ,AAEE,EAAe,WADf,aAAa,EAAe,OAAO,EACV,MAE3B,EAAe,EAAI,EACrB,EAEM,MAAmB,CACvB,EAAe,QAAU,eAAiB,CACxC,EAAe,EAAK,EACpB,EAAe,QAAU,KAGpB,GAAkB,EAAa,GAAY,EAAY,CAAK,CAAC,CACpE,EAAG,GAAG,CACR,EAEM,GAAA,EAAA,EAAA,aAA4B,GAA4B,CAC5D,EAAa,EAAK,OAAS,EAAK,KAAK,EACrC,EAAe,EAAK,EACpB,EAAoB,IAAI,EACpB,GAAe,EAAc,IAAI,EAAK,KAAK,EAC3C,GAAU,EAAS,EAAK,KAAK,EACjC,EAAS,EAAK,KAAK,CACrB,EAAG,CAAC,EAAe,EAAU,CAAQ,CAAC,EAEhC,GAAA,EAAA,EAAA,aAAyB,GAA+B,CACxD,IACA,EAAM,MAAQ,WAChB,EAAM,eAAe,EACrB,EAAqB,GAAU,EAAa,EAAM,EAAb,IAAe,GAC3C,EAAM,MAAQ,aACvB,EAAM,eAAe,EACrB,EAAqB,GACnB,IAAQ,KAAO,EAAI,KAAK,IAAI,EAAM,EAAG,EAAU,OAAS,CAAC,CAC3D,GACS,EAAM,MAAQ,UACnB,IAAqB,MAAQ,EAAU,GACzC,EAAa,EAAU,EAAiB,EAC/B,IACT,EAAe,EAAK,EACpB,EAAoB,IAAI,IAG9B,EAAG,CAAC,EAAW,EAAkB,EAAc,EAAkB,CAAQ,CAAC,EAE1E,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAY,KAAM,CAAS,EAC/D,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EACvC,QAAS,EACT,OAAQ,EACG,qBAPb,EASE,EAAA,EAAA,KAAC,GAAD,CACS,QACP,MAAO,EACG,WACV,SAAW,GAAS,CAIlB,GAHA,EAAa,CAAI,EACjB,EAAoB,IAAI,EACxB,EAAe,EAAI,EACf,EACE,GAAe,EAAc,IAAI,CAAI,EACrC,GAAU,EAAS,CAAI,OACtB,GAAI,IAAS,GACd,GAAe,EAAc,IAAI,EAAE,EACnC,GAAU,EAAS,EAAE,EACzB,EAAS,EAAE,MACN,CAEL,IAAM,EAAQ,EAAM,KACjB,IAAU,EAAK,OAAS,EAAK,OAAO,YAAY,IAAM,EAAK,YAAY,CAC1E,EACI,IACE,GAAe,EAAc,IAAI,EAAM,KAAK,EAC5C,GAAU,EAAS,EAAM,KAAK,EAClC,EAAS,EAAM,KAAK,EAExB,CACF,EACa,aACd,CAAA,EACA,GAAe,CAAC,IACf,EAAA,EAAA,KAAC,GAAD,CAAA,UACE,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,SAAU,GAAO,cAAe,GAAY,QAAQ,EACzE,MAAO,GAAY,mBAEnB,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,wBACpB,EAAU,KAAK,EAAM,KACpB,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SACE,GAAO,aACP,IAAqB,GAAO,GAAO,wBACnC,GAAY,IACd,EACA,MAAO,GAAY,KAEnB,YAAc,GAAM,EAAE,eAAe,EACrC,YAAe,EAAa,CAAI,WAE/B,EAAK,OAAS,EAAK,KACjB,EAZE,GAAG,EAAI,GAAG,EAAK,MAAM,GAAG,EAAK,OAY/B,CACN,CACE,CAAA,CACF,CAAA,CACE,CAAA,CAER,GAET,mcE1KA,SAAS,GAAW,CAAE,KAAI,YAA6B,CACrD,GAAM,CAAE,aAAY,YAAW,aAAY,YAAW,aAAY,eAAA,EAAA,EAAA,aAA2B,CAC3F,IACF,CAAC,EAED,OACE,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,MAAO,CAAE,UAAW,EAAA,IAAI,UAAU,SAAS,CAAS,EAAG,YAAW,EAClE,WAAA,EAAA,EAAA,SAAc,GAAO,KAAM,GAAc,GAAO,YAAY,EAC5D,GAAI,EACJ,GAAI,EAEH,UACE,CAAA,CAET,CCbA,SAAS,GAAgB,CACvB,KACA,QACA,UACA,QACA,aACA,YACA,aACA,OAAQ,GACuB,CAE/B,GAAM,CAAE,aAAY,WAAA,EAAA,EAAA,cAAwB,CAAE,GAAI,UADpB,GACgC,CAAC,EAE/D,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,OAAQ,GAAU,GAAO,WAAY,EAAQ,SAAW,GAAK,GAAO,YAAa,CAAS,WAApH,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,GAAY,MAAM,EAAG,MAAO,GAAY,gBAAS,CAAW,CAAA,GACpG,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,MAAO,EAAS,SAAU,EAAA,sCACzC,EAAA,EAAA,KAAC,MAAD,CAAK,IAAK,EAAY,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,KAAK,EAAG,MAAO,GAAY,eAC5F,EAAQ,IAAK,IACZ,EAAA,EAAA,KAAC,GAAD,CAAyB,GAAI,WAC1B,EAAM,KAAY,IAAA,GAAgD,KAApC,EAAW,EAAM,GAAS,CAAM,CACrD,EAFK,CAEL,CACb,CACE,CAAA,CACU,CAAA,CACd,GAET,CCvBA,SAAS,GAAyB,CAChC,UACA,QACA,aACA,WACA,YACA,QACA,aACA,OAAQ,GACc,CACtB,GAAM,CAAC,EAAU,IAAA,EAAA,EAAA,UAAuC,IAAI,EACtD,CAAC,EAAe,IAAA,EAAA,EAAA,UAAuD,IAAI,EAE3E,GAAA,EAAA,EAAA,aAAA,EAAA,EAAA,WACM,EAAA,cAAe,CACvB,qBAAsB,CAAE,SAAU,CAAE,CACtC,CAAC,CACH,EAEM,EAAiB,GAAiB,EAExC,SAAS,EAAkB,EAAyB,EAAwB,CAC1E,OAAO,EAAK,UAAW,GAAQ,EAAI,QAAQ,SAAS,CAAM,CAAC,CAC7D,CAEA,SAAS,EAAgB,CAAE,UAA0B,CACnD,EAAY,OAAO,EAAO,EAAE,CAAC,EAC7B,EAAiB,EAAQ,IAAK,IAAS,CAAE,GAAG,EAAK,QAAS,CAAC,GAAG,EAAI,OAAO,CAAE,EAAE,CAAC,CAChF,CAEA,SAAS,EAAe,CAAE,SAAQ,QAAuB,CACvD,GAAI,CAAC,EAAM,OAEX,IAAM,EAAe,OAAO,EAAO,EAAE,EAC/B,EAAS,OAAO,EAAK,EAAE,EAE7B,EAAkB,GAAS,CAEzB,IAAM,GADO,GAAQ,EAAQ,IAAK,IAAS,CAAE,GAAG,EAAK,QAAS,CAAC,GAAG,EAAI,OAAO,CAAE,EAAE,GAC/D,IAAK,IAAS,CAAE,GAAG,EAAK,QAAS,CAAC,GAAG,EAAI,OAAO,CAAE,EAAE,EAEhE,EAAiB,EAAkB,EAAM,CAAY,EAC3D,GAAI,IAAmB,GAAI,OAAO,EAGlC,IAAI,EACJ,GAAI,EAAO,WAAW,SAAS,EAAG,CAChC,IAAM,EAAQ,EAAO,MAAM,CAAgB,EAC3C,EAAe,EAAK,UAAW,GAAQ,EAAI,KAAO,CAAK,CACzD,MACE,EAAe,EAAkB,EAAM,CAAM,EAG/C,GAAI,IAAiB,GAAI,OAAO,EAEhC,GAAI,IAAmB,EAAc,CAEnC,IAAM,EAAM,EAAK,GACX,EAAW,EAAI,QAAQ,QAAQ,CAAY,EAC3C,EAAW,EAAI,QAAQ,QAAQ,CAAM,EACvC,IAAa,IAAM,IAAa,IAAM,IAAa,IACrD,EAAK,GAAkB,CACrB,GAAG,EACH,SAAA,EAAA,EAAA,WAAmB,EAAI,QAAS,EAAU,CAAQ,CACpD,EAEJ,KAAO,CAEL,EAAK,GAAgB,QAAU,EAAK,GAAgB,QAAQ,OACzD,GAAO,IAAO,CACjB,EACA,IAAM,EAAY,EAAK,GAAc,QAAQ,QAAQ,CAAM,EACrD,EAAW,IAAc,GAAK,EAAK,GAAc,QAAQ,OAAS,EACxE,EAAK,GAAc,QAAQ,OAAO,EAAU,EAAG,CAAY,CAC7D,CAEA,OAAO,CACT,CAAC,CACH,CAEA,SAAS,EAAc,CAAE,SAAQ,QAAsB,CAGrD,GAFA,EAAY,IAAI,EAEZ,CAAC,GAAQ,CAAC,EAAe,CAC3B,EAAiB,IAAI,EACrB,MACF,CAGA,EAAS,CAAa,EACtB,EAAiB,IAAI,CACvB,CAEA,OACE,EAAA,EAAA,MAAC,EAAA,WAAD,CACW,UACT,mBAAoB,EAAA,eACpB,YAAa,EACb,WAAY,EACZ,UAAW,WALb,EAOE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,MAAO,CAAS,EAAU,iBACjD,EAAe,IAAK,IACnB,EAAA,EAAA,KAAC,GAAD,CAEE,GAAI,EAAI,GACR,MAAO,EAAI,MACX,QAAS,EAAI,QACN,QACK,YACb,EANM,EAAI,EAMV,CACF,CACE,CAAA,GACL,EAAA,EAAA,KAAC,EAAA,YAAD,CAAA,SACG,GAAY,EAAM,KAAc,IAAA,IAC/B,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,WAAW,EAAG,MAAO,GAAY,qBAAc,EAAW,EAAM,GAAW,CAAQ,CAAO,CAAA,EAC3I,IACO,CAAA,CACH,GAEhB,CC1IA,IAAM,GAAW,2BA4BI,GAArB,KAAkC,CAGhC,YAAY,EAAa,CACvB,KAAK,IAAM,CACb,CAEA,MAAM,OACJ,EACA,EAAyB,CAAC,EACyB,CACnD,IAAM,EAAS,IAAI,gBAAgB,CAAE,EAAG,EAAO,IAAK,KAAK,GAAI,CAAC,EAM9D,OALI,EAAQ,OAAS,MAAM,EAAO,IAAI,QAAS,OAAO,EAAQ,KAAK,CAAC,EAChE,EAAQ,eAAiB,MAAM,EAAO,IAAI,gBAAiB,EAAQ,aAAa,EAChF,EAAQ,KAAO,MAAM,EAAO,IAAI,MAAO,EAAQ,GAAG,GAG/C,MADW,MAAM,GAAG,GAAS,UAAU,GAAQ,GAC3C,KAAK,CAClB,CAEA,MAAM,kBAAkB,EAA+C,CACrE,IAAM,EAAS,IAAI,gBAAgB,CAAE,EAAG,EAAO,IAAK,KAAK,GAAI,CAAC,EAE9D,OAAO,MADW,MAAM,GAAG,GAAS,sBAAsB,GAAQ,GACvD,KAAK,CAClB,CAEA,cAAc,EAAe,EAAkB,CAC7C,IAAM,EAAS,IAAI,gBAAgB,CAAE,KAAI,EAAG,EAAO,IAAK,KAAK,GAAI,CAAC,EAClE,MAAM,GAAG,GAAS,iBAAiB,GAAQ,EAAE,UAAY,IAAI,CAC/D,CACF,uCEnDA,SAAwB,GAAY,CAClC,QACA,WACA,aACA,cACA,QACA,aAAa,IACb,cACA,aAAa,GACb,YACA,QACA,GAAG,GAC8B,CACjC,IAAM,GAAA,EAAA,EAAA,QAAwD,IAAI,GAElE,EAAA,EAAA,mBAAsB,CAChB,EAAS,UAAY,MAAM,aAAa,EAAS,OAAO,CAC9D,EAAG,CAAC,CAAC,EAEL,SAAS,EAAa,EAAc,CAClC,IAAM,EAAM,GAAO,KAAqB,GAAd,OAAO,CAAG,EAC9B,EAAU,EAAI,KAAK,IAAM,GAAK,GAAK,EACzC,EAAS,CAAO,EACZ,EAAS,UAAY,MAAM,aAAa,EAAS,OAAO,EAC5D,EAAS,QAAU,eAAiB,CAAE,IAAa,CAAO,CAAG,EAAG,CAAU,CAC5E,CAEA,IAAM,EAAY,GAAc,OAAO,GAAgB,UAAY,CAAC,OAAO,MAAM,CAAW,EAE5F,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,GAAI,EAAiB,YAAW,MAAO,GAAS,KAAmB,IAAA,GAAZ,CAAE,OAAM,WAApE,EACE,EAAA,EAAA,KAAC,GAAD,CACE,KAAM,GAAU,OACT,QACM,cACN,QACP,SAAU,CACX,CAAA,EACA,IACC,EAAA,EAAA,MAAC,IAAD,CAAG,UAAW,GAAO,qBAArB,CACG,EAAY,IAAE,IAAgB,EAAI,SAAW,SAC7C,GAEF,GAET,2TE9CA,SAAwB,GAAW,CACjC,YACA,eAAe,CAAC,EAChB,WACA,oBACgC,CAChC,SAAS,EAAa,EAAgC,CACpD,IAAM,EAAK,EAAM,cACX,EAAuB,EAAG,aAAe,EAAG,aAAe,IAC7D,EAAG,WAAa,GAClB,IAAmB,CAEvB,CAEA,OACE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAA,SACG,EAAa,OAAS,IACrB,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,WAAY,CAAS,EAAG,SAAU,WACzD,EAAa,KAAK,EAAS,KAC1B,EAAA,EAAA,KAAC,EAAD,CAEE,UAAW,GAAO,yBAClB,YAAe,IAAW,CAAO,YAEjC,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,GAAO,gBAClB,MAAO,CAAE,gBAAiB,OAAO,EAAQ,cAAc,QAAQ,IAAI,EAAG,CACvE,CAAA,CACc,EARV,GAAG,EAAQ,GAAG,GAAG,GAQP,CAClB,CACE,CAAA,CAEP,CAAA,CAEN,qLElCA,SAAwB,GAAQ,CAAE,YAAW,MAAM,IAAkC,CACnF,GAAM,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,EAAI,EAM/C,OAJA,EAAA,EAAA,eAAgB,CACd,EAAa,EAAI,CACnB,EAAG,CAAC,CAAG,CAAC,GAGN,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,QAAS,CAAS,WAA5C,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,oBAA0B,MAAK,WAAc,EAAa,EAAK,CAAI,CAAA,EACzF,IAAa,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,cAAiB,CAAA,CACnD,GAET,mgBEFA,SAAwB,GAAY,CAClC,YACA,QAAQ,GACR,UAAU,GACV,eAAiB,IAAA,GACjB,WAAW,MACsB,CACjC,IAAM,GAAA,EAAA,EAAA,aAA6B,IAAI,GAAa,CAAK,EAAG,CAAC,CAAK,CAAC,EAE7D,CAAC,EAAY,IAAA,EAAA,EAAA,UAA0B,EAAE,EACzC,CAAC,EAAiB,IAAA,EAAA,EAAA,UAA8C,CAAC,CAAC,EAClE,CAAC,EAAoB,IAAA,EAAA,EAAA,UAA4C,CAAC,CAAC,EACnE,CAAC,EAAU,IAAA,EAAA,EAAA,UAAuC,IAAI,EACtD,CAAC,EAAY,IAAA,EAAA,EAAA,UAA0B,EAAK,EAElD,eAAe,EAAU,EAAe,CAEtC,GADA,EAAc,CAAK,EACf,CAAC,EAAM,KAAK,EAAG,CACjB,EAAmB,CAAC,CAAC,EACrB,EAAsB,CAAC,CAAC,EACxB,EAAY,IAAI,EAChB,MACF,CACA,GAAM,CAAC,CAAE,QAAS,EAAgB,CAAC,EAAG,OAAO,MAAQ,CAAE,QAAS,EAAoB,CAAC,IACnF,MAAM,QAAQ,IAAI,CAChB,EAAa,OAAO,EAAO,CAAE,MAAO,GAAI,cAAe,QAAS,CAAC,EACjE,EAAa,kBAAkB,CAAK,CACtC,CAAC,EACH,EAAmB,CAAa,EAChC,EAAY,CAAI,EAChB,EAAsB,CAAiB,CACzC,CAEA,eAAe,GAAuB,CACpC,GAAM,CAAE,QAAS,EAAgB,CAAC,EAAG,OAAO,MAAS,MAAM,EAAa,OAAO,EAAY,CACzF,MAAO,GACP,IAAK,GAAY,IAAA,GACjB,cAAe,QACjB,CAAC,EACD,EAAY,CAAI,EAChB,EAAoB,GAAS,CAAC,GAAG,EAAM,GAAG,CAAa,CAAC,CAC1D,CAEA,eAAe,EAAoB,EAA6B,CAC9D,MAAM,EAAS,CAAO,EACtB,EAAc,EAAK,EACf,GAAS,EAAa,cAAc,EAAY,EAAQ,EAAE,CAChE,CAEA,SAAS,GAA+B,CACtC,OACE,EAAA,EAAA,KAAC,GAAD,CAAe,OAAA,GAAO,UAAW,GAAO,yCACrC,EAAmB,IAAK,IACvB,EAAA,EAAA,KAAC,GAAD,CACE,UAAW,GAAO,2BAElB,KAAM,EACN,YAAe,EAAU,CAAU,CACpC,EAHM,CAGN,CACF,CACY,CAAA,CAEnB,CAEA,SAAS,GAAiC,CACxC,OACE,EAAA,EAAA,KAAC,GAAD,CACE,aAAc,EACd,SAAU,EACV,iBAAkB,CACnB,CAAA,CAEL,CAEA,SAAS,GAA+B,CACtC,OACE,EAAA,EAAA,KAAC,GAAD,CACE,MAAM,WACN,MAAO,EACP,WAAY,EACZ,SAAU,CACX,CAAA,CAEL,CAyBA,OAvBI,GAEA,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,WAAhD,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAmB,uBAAnC,EACE,EAAA,EAAA,KAAC,EAAD,CAAQ,YAAe,EAAc,EAAI,WAAG,UAAgB,CAAA,EAC3D,IACC,EAAA,EAAA,KAAC,EAAD,CAAQ,UAAW,EAAgB,OAAQ,YAAe,EAAoB,IAAI,WAAG,YAE7E,CAAA,CAEP,IACJ,IAAY,EAAA,EAAA,KAAC,GAAD,CAAS,UAAW,GAAO,oBAAqB,IAAK,CAAW,CAAA,GAC7E,EAAA,EAAA,KAAC,GAAD,CAAO,OAAQ,EAAY,YAAe,EAAc,EAAK,YAC3D,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,iCAAvB,CACG,EAAkB,EAClB,EAAkB,EAClB,EAAoB,CAClB,GACA,CAAA,CACJ,KAKP,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,WAAhD,EACE,EAAA,EAAA,KAAC,GAAD,CACE,MAAO,GAAM,KACb,OAAQ,EAAgB,OAAS,GAAK,EACtC,aAAc,EACd,SACE,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CACG,EAAkB,EAClB,EAAoB,CACrB,CAAA,CAAA,WAGH,EAAkB,CACP,CAAA,EACb,IACC,EAAA,EAAA,KAAC,EAAD,CAAQ,UAAW,EAAgB,OAAQ,YAAe,EAAoB,IAAI,WAAG,YAE7E,CAAA,EAET,IAAY,EAAA,EAAA,KAAC,GAAD,CAAS,UAAW,GAAO,oBAAqB,IAAK,CAAW,CAAA,CAC1E,GAET,qbE/IA,SAAS,GAAY,CAAE,YAAY,IAAM,CACvC,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,YAC9C,EAAA,EAAA,MAAC,MAAD,CAAK,MAAM,6BAA6B,QAAQ,uBAAhD,EACE,EAAA,EAAA,KAAC,OAAD,CACE,UAAW,GAAO,iBAClB,EAAE,uBACF,YAAY,MACZ,KAAK,MACN,CAAA,GACD,EAAA,EAAA,KAAC,OAAD,CACE,UAAW,GAAO,iBAClB,EAAE,0BACF,YAAY,MACZ,KAAK,MACN,CAAA,GACD,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,GAAO,iBAAkB,EAAE,eAAe,YAAY,MAAM,KAAK,MAAQ,CAAA,GAC1F,EAAA,EAAA,KAAC,OAAD,CACE,UAAW,GAAO,kBAClB,EAAE,+BACF,YAAY,MACZ,KAAK,MACN,CAAA,GACD,EAAA,EAAA,KAAC,OAAD,CACE,UAAW,GAAO,kBAClB,EAAE,6BACF,YAAY,MACZ,KAAK,MACN,CAAA,CACE,GACF,CAAA,CAET,CCnCA,IAAA,GAAe,wFEyCf,SAAS,GAAY,EAAuC,CAC1D,GAAM,CACN,QACA,WACA,gBACA,QACA,QACA,YACA,gBAAgB,GAChB,mBACA,oBACA,SACA,SACA,eACA,oBAAoB,GACpB,cACA,OACA,aAAa,GACb,OAAO,EACP,WAAW,GACX,UAAW,EACX,GAAG,GACC,EAAqB,cAAe,CAAK,EACvC,EAAW,GAAiB,KAAgD,EAAzC,EAAc,MAEjD,EAAe,GAAQ,MAAQ,GAAY,KAAO,KAAK,IAAI,OAAO,CAAQ,CAAC,EAAI,EAC/E,EAAkB,GAAgB,KAA8B,GAAvB,OAAO,CAAY,EAElE,SAAS,EAAkB,EAAgC,CACzD,IAAI,EAAM,EACN,IAAQ,IAAA,KACN,IAAS,MAAK,EAAM,CAAC,KAAK,IAAI,CAAG,GACjC,IAAS,MAAK,EAAO,KAAK,IAAI,CAAG,IAEnC,GAAqC,IAAI,GAAO,IAAI,EACxD,IAAW,CAAG,CAChB,CAEA,SAAS,EAAW,EAAe,CACjC,GAAI,EAAU,OAEd,IAAI,GADY,GAAY,MAAQ,IAAa,GAAK,OAAO,CAAQ,EAAI,GACpD,EACjB,CAAC,GAAiB,IAAS,MAAK,EAAO,KAAK,IAAI,EAAG,CAAI,GACvD,IAAS,MAAK,EAAO,KAAK,IAAI,EAAG,CAAI,GACzC,EAAkB,CAAI,CACxB,CAEA,SAAS,EAAc,EAA0C,CAC/D,GAAI,EAAU,CAAE,IAAgB,CAAC,EAAG,MAAQ,CAC5C,GAAI,EAAE,MAAQ,UAAW,CACvB,EAAE,eAAe,EACjB,EAAW,EAAE,SAAW,EAAO,GAAK,CAAI,EACxC,MACF,CACA,GAAI,EAAE,MAAQ,YAAa,CACzB,EAAE,eAAe,EACjB,EAAW,EAAE,SAAW,CAAC,EAAO,GAAK,CAAC,CAAI,EAC1C,MACF,CACA,IAAgB,CAAC,CACnB,CAEA,IAAM,EAAiB,IAAS,IAAM,IAAM,IAAS,IAAM,IAAM,EAE3D,EAAc,GAAc,CAAC,GACjC,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,gBAAvB,EACE,EAAA,EAAA,KAAC,EAAD,CACE,UAAW,GAAO,SAClB,SAAU,GACV,YAAc,GAAM,CAAE,EAAE,eAAe,EAAG,EAAW,EAAE,SAAW,EAAO,GAAK,CAAI,CAAG,YAErF,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,WAAc,CAAA,CACtB,CAAA,GACjB,EAAA,EAAA,KAAC,EAAD,CACE,UAAW,GAAO,SAClB,SAAU,GACV,YAAc,GAAM,CAAE,EAAE,eAAe,EAAG,EAAW,EAAE,SAAW,CAAC,EAAO,GAAK,CAAC,CAAI,CAAG,YAEvF,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,aAAgB,CAAA,CACxB,CAAA,CACd,IACH,KAEJ,OACE,EAAA,EAAA,KAAC,GAAD,CACS,QACP,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,EAC3C,MAAO,EACP,aAAgB,CAAC,EACjB,cAAe,KACf,QAAS,EAAiB,EAAc,QAAU,CAAC,EAAc,SAAS,EAAI,GAAQ,CAAC,EACvF,aAAc,EAAiB,EAAc,uBAAuB,GAAK,GAAO,GAAS,GAC5E,cACH,WACV,OAAQ,EACR,aACE,EAAA,EAAA,KAAC,EAAA,cAAD,CACE,cAAgB,GAAS,EAAkB,EAAK,UAAU,EAC1D,cAAe,GAAQ,KAAe,EAAR,GACZ,mBACC,oBACL,eACK,oBACnB,OAAQ,EACA,SACR,UAAW,EAAa,EAAgB,EACxC,GAAI,CACL,CAAA,CAEJ,CAAA,CAEL,CCxJA,IAAA,GAAe,gWEMf,SAAS,GAAa,CACpB,YAAY,IAAA,GACZ,UACA,WACA,QACA,GAAG,GAC+B,CAClC,IAAM,EAAmB,EAAQ,UAAW,GAAW,EAAO,MAAQ,CAAK,EAAI,IAAM,EAAQ,OAE7F,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,CAAS,WAA3D,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,iBAAkB,MAAO,CAAE,KAAM,GAAG,EAAiB,GAAI,MAAO,GAAG,IAAM,EAAQ,OAAO,EAAG,CAAI,CAAA,EACrH,EAAQ,IAAK,IACZ,EAAA,EAAA,KAAC,EAAD,CACE,QAAU,GAAM,EAAS,EAAO,IAAK,CAAC,EAEtC,WAAA,EAAA,EAAA,SACE,GAAO,mBACP,EAAO,MAAQ,GAAS,GAAO,wBACjC,EACA,SAAU,EAAO,MAAQ,EAAQ,GAAK,WAErC,EAAO,KACO,EARV,EAAO,GAQG,CAClB,CACE,GAET,CCjCA,IAAM,GAAoB,IAQ1B,SAAwB,IAA4B,CAClD,GAAM,CAAC,EAAM,IAAA,EAAA,EAAA,eAAuC,CAClD,MAAO,OAAO,WACd,OAAQ,OAAO,YACf,aAAc,OAAO,WAAa,EACpC,EAAE,EAcF,OAZA,EAAA,EAAA,eAAgB,CACd,SAAS,GAAW,CAClB,EAAQ,CACN,MAAO,OAAO,WACd,OAAQ,OAAO,YACf,aAAc,OAAO,WAAa,EACpC,CAAC,CACH,CAEA,OADA,OAAO,iBAAiB,SAAU,CAAQ,MAC7B,OAAO,oBAAoB,SAAU,CAAQ,CAC5D,EAAG,CAAC,CAAC,EAEE,CACT,6XEvBA,SAAwB,GAAW,CACjC,WAAW,KACX,oBAAoB,KACpB,2BAA2B,KAC3B,eAAe,GACf,MAAM,GACN,MAAM,GACN,QAAQ,GACR,OAAO,IACP,aAAa,GACb,qBAAuB,CAAC,EACxB,iBAAiB,IACC,CAClB,GAAM,CAAE,eAAc,UAAW,GAAc,EAEzC,GAAA,EAAA,EAAA,QAAuC,IAAI,EAC3C,GAAA,EAAA,EAAA,QAA6C,IAAI,EACjD,GAAA,EAAA,EAAA,QAAsD,IAAI,EAC1D,GAAA,EAAA,EAAA,QAAwB,EAAK,EAC7B,GAAA,EAAA,EAAA,QAAgE,IAAI,EACpE,GAAA,EAAA,EAAA,QAA2B,CAAc,EAC/C,EAAkB,QAAU,EAE5B,IAAM,GAAA,EAAA,EAAA,aACH,GAAsB,CACrB,IAAI,EACJ,GAAI,IAAS,IAAK,CAChB,GAAI,CAAC,EAA6B,QAAS,OAC3C,IAAM,EAAa,EAA6B,QAAQ,aACxD,EAAI,KAAK,IAAK,EAAa,EAAO,IAAK,EAAa,CAAS,CAC/D,MACE,EAAI,KAAK,IAAI,EAAK,EAAM,CAAS,EAE/B,EAAoB,UACtB,EAAoB,QAAQ,MAAM,OAAS,GAAG,EAAE,IAEpD,EACA,CAAC,EAAK,EAAK,CAAI,CACjB,EAEM,GAAA,EAAA,EAAA,iBAA4C,CAChD,IAAI,EACJ,GAAI,IAAS,IAAK,CAChB,GAAI,CAAC,EAA6B,QAAS,OAC3C,IAAM,EAAe,EAA6B,QAAQ,aAAe,EAAO,IAChF,EACE,EAA6B,QAAQ,aAA8B,EAAQ,IAAvB,CACxD,MACE,EAAW,EAAM,EAEf,EAAc,UAChB,EAAc,QAAQ,UAAY,EAClC,EAAmB,CAAQ,EAE/B,EAAG,CAAC,EAAK,EAAO,EAAM,CAAkB,CAAC,GAGzC,EAAA,EAAA,eAAgB,CACd,IAAM,EAAK,WAAW,EAAyB,GAAG,EAClD,UAAa,aAAa,CAAE,CAC9B,EAAG,CAAC,CAAuB,CAAC,GAG5B,EAAA,EAAA,eAAgB,CACV,EAAc,UAChB,EAAc,QAAQ,MAAM,SAAW,EAAiB,SAAW,OAEvE,EAAG,CAAC,CAAc,CAAC,EAGnB,IAAM,GAAA,EAAA,EAAA,QAAyB,CAAY,GAC3C,EAAA,EAAA,eAAgB,CACV,GAAgB,CAAC,EAAgB,SAAS,EAAwB,EACtE,EAAgB,QAAU,CAC5B,EAAG,CAAC,EAAc,CAAuB,CAAC,EAG1C,IAAM,GAAA,EAAA,EAAA,QAA2B,CAAU,GAC3C,EAAA,EAAA,eAAgB,CACV,CAAC,GAAc,EAAkB,SAAS,EAAwB,EACtE,EAAkB,QAAU,CAC9B,EAAG,CAAC,EAAY,CAAuB,CAAC,EAGxC,IAAM,GAAA,EAAA,EAAA,QAAuB,CAAM,GACnC,EAAA,EAAA,eAAgB,CACV,GAAgB,IAAW,EAAc,SAAW,EAAc,SACpE,EAAmB,EAAc,QAAQ,SAAS,EAEpD,EAAc,QAAU,CAC1B,EAAG,CAAC,EAAQ,EAAc,CAAkB,CAAC,EAE7C,SAAS,EAAa,EAA4B,CAChD,EAAmB,EAAE,cAAc,SAAS,EACvC,EAAe,UAClB,EAAe,QAAU,GACzB,EAAkB,QAAQ,EAAI,GAE5B,EAAiB,SAAS,aAAa,EAAiB,OAAO,EACnE,EAAiB,QAAU,eAAiB,CAC1C,EAAiB,QAAU,KAC3B,EAAe,QAAU,GACzB,EAAkB,QAAQ,EAAK,CACjC,EAAG,GAAG,CACR,CAEA,GAAI,GAAc,CAAC,EAEjB,OADI,GAAiC,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,CAAM,EAA0B,CAAc,CAAA,CAAA,GAC5E,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,UAAW,CAAA,EAGvB,IAAM,EAAmB,IAAS,IAAM,GAAG,IAAM,EAAI,GAAK,eAAe,EAAI,KAE7E,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,WAAY,IAAK,EAAe,SAAU,WAAjE,EACE,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,GAAO,0BAClB,MAAO,CAAE,OAAQ,GAAG,IAAM,GAAO,EACjC,IAAK,YAEL,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,iBAAkB,GAAgB,GAAO,wBAAwB,EACtF,IAAK,WAEJ,CACE,CAAA,CACF,CAAA,GACL,EAAA,EAAA,KAAC,MAAD,CAAK,MAAO,CAAE,UAAW,CAAiB,EAAI,UAAc,CAAA,CACzD,GAET,sXErIY,GAAL,SAAA,EAAA,OACL,GAAA,IAAA,MACA,EAAA,OAAA,SACA,EAAA,KAAA,OACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,EAGY,GAAL,SAAA,EAAA,OACL,GAAA,MAAA,QACA,EAAA,OAAA,SACA,EAAA,IAAA,OACF,EAAA,CAAA,CAAA,EAGY,GAAL,SAAA,EAAA,OACL,GAAA,MAAA,QACA,EAAA,MAAA,QACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,EClBM,GAA2C,EAC9C,GAAiB,KAAM,UACvB,GAAiB,QAAS,OAC1B,GAAiB,MAAO,SACxB,GAAiB,OAAQ,MAC5B,EAEM,GAAS,EAuBf,SAAgB,GAAmB,CACjC,SAAQ,YAAW,QAAO,SAAQ,aAAY,cAAa,WAAU,YAC5C,EACzB,EAAA,EAAA,qBAAsB,CACpB,GAAI,CAAC,EAAQ,OAEb,IAAI,EACA,EAIJ,SAAS,GAAW,CAClB,IAAM,EAAU,EAAW,QACrB,EAAW,EAAY,QACvB,EAAQ,EAAS,QACvB,GAAI,CAAC,GAAW,CAAC,GAAY,CAAC,EAAO,CACnC,EAAQ,sBAAsB,CAAQ,EACtC,MACF,CACA,IAAM,EAAY,GAAuB,CAAO,EAEhD,SAAS,GAAY,CACnB,IAAM,EAAI,EAAS,sBAAsB,EACnC,EAAK,EAAO,YACZ,EAAK,EAAO,aACZ,EAAK,OAAO,WACZ,EAAK,OAAO,YAIZ,EAA6B,CACjC,IAAK,EAAE,IACP,OAAQ,EAAK,EAAE,OACf,KAAM,EAAE,KACR,MAAO,EAAK,EAAE,KAChB,EACM,EAAQ,IAAc,GAAiB,KAAO,IAAc,GAAiB,OAAU,EAAK,EAC9F,EAAa,EACX,EAAM,GAAS,GACjB,EAAK,GAAQ,EAAO,GAAU,EAAK,GAAO,EAAK,KAAO,EAAO,GAEjE,IAAM,EAAW,IAAS,OAAS,IAAS,SAGxC,EACA,EACA,IAAS,SAAY,EAAM,EAAE,OAAS,EACjC,IAAS,MAAS,EAAM,EAAE,IAAM,EAAS,EAC7C,AACE,EADE,IAAS,QAAkB,EAAE,MAAQ,EAChC,EAAE,KAAO,EAAS,EAG5B,GACF,AAEK,EAFD,IAAU,GAAa,MAAc,EAAE,KAClC,IAAU,GAAa,IAAY,EAAE,MAAQ,EAC1C,EAAE,KAAO,EAAE,MAAQ,EAAI,EAAK,EACxC,EAAO,KAAK,IAAI,GAAQ,KAAK,IAAI,EAAO,EAAK,EAAK,EAAM,CAAC,IAEzD,AAEK,EAFD,IAAU,GAAa,MAAa,EAAE,IACjC,IAAU,GAAa,IAAW,EAAE,OAAS,EAC3C,EAAE,IAAM,EAAE,OAAS,EAAI,EAAK,EACvC,EAAM,KAAK,IAAI,GAAQ,KAAK,IAAI,EAAM,EAAK,EAAK,EAAM,CAAC,GAGzD,EAAU,MAAM,IAAM,GAAG,EAAK,IAC9B,EAAU,MAAM,KAAO,GAAG,EAAM,IAChC,EAAU,MAAM,WAAa,GAAsB,EAAG,CAAS,EAAI,SAAW,UAC9E,EAAU,QAAQ,UAAY,EAG9B,IAAM,EAAQ,EAAS,QACvB,GAAI,EAAO,CACT,IAAM,EAAO,EAAM,YAAc,GAAK,EACtC,GAAI,EAAU,CACZ,IAAM,EAAI,EAAE,KAAO,EAAE,MAAQ,EAAI,EACjC,EAAM,MAAM,YAAY,YAAa,GAAG,KAAK,IAAI,EAAO,EAAG,KAAK,IAAI,EAAG,EAAK,EAAO,CAAC,CAAC,EAAE,GAAG,EAC1F,EAAM,MAAM,eAAe,WAAW,CACxC,KAAO,CACL,IAAM,EAAI,EAAE,IAAM,EAAE,OAAS,EAAI,EACjC,EAAM,MAAM,YAAY,YAAa,GAAG,KAAK,IAAI,EAAO,EAAG,KAAK,IAAI,EAAG,EAAK,EAAO,CAAC,CAAC,EAAE,GAAG,EAC1F,EAAM,MAAM,eAAe,WAAW,CACxC,CACF,CACF,CAEA,EAAU,EAEV,IAAM,EAA0C,CAAC,OAAQ,GAAG,CAAS,EACrE,EAAc,QAAS,GAAO,EAAG,iBAAiB,SAAU,EAAW,CAAE,QAAS,EAAK,CAAC,CAAC,EACzF,OAAO,iBAAiB,SAAU,CAAS,EAC3C,MAAiB,CACf,EAAc,QAAS,GAAO,EAAG,oBAAoB,SAAU,CAAS,CAAC,EACzE,OAAO,oBAAoB,SAAU,CAAS,CAChD,CACF,CAIA,OAFA,EAAS,MAEI,CACP,IAAU,IAAA,IAAW,qBAAqB,CAAK,EACnD,IAAW,CACb,CACF,EAAG,CAAC,EAAQ,EAAW,EAAO,EAAQ,EAAY,EAAa,EAAU,CAAQ,CAAC,CACpF,CClIA,IAAM,GAAqB,CACzB,UACA,aACA,yBACA,wBACA,yBACA,2BACA,kCACA,0BACF,EAAE,KAAK,GAAG,EAGV,SAAS,GAAY,EAAwC,CAE3D,OADK,EACE,MAAM,KAAK,EAAK,iBAA8B,EAAkB,CAAC,EADtD,CAAC,CAErB,CAEA,SAAS,GAAQ,CACf,WAAW,KACX,UAAU,KACV,YAAY,GAAiB,OAC7B,QAAQ,GAAa,OACrB,UAAU,GAAe,MACzB,SACA,cAAc,GACd,mBAAqB,CAAC,EACtB,SAAS,GACT,YAAY,GACZ,sBAAsB,GACtB,gBAAgB,GAChB,YAAY,IACZ,aAAa,IACb,WAAW,GACX,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACY,CACf,IAAM,GAAA,EAAA,EAAA,QAAoC,IAAI,EACxC,GAAA,EAAA,EAAA,QAAqC,IAAI,EACzC,GAAA,EAAA,EAAA,QAAkC,IAAI,EACtC,GAAA,EAAA,EAAA,QAAkC,IAAI,EACtC,GAAA,EAAA,EAAA,QAA+D,IAAA,EAAS,EAExE,EAAe,IAAW,IAAA,GAC1B,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,CAAW,EACtD,EAAO,EAAe,EAAS,EAG/B,GAAA,EAAA,EAAA,QAAyB,CAAY,GAC3C,EAAA,EAAA,eAAgB,CAAE,EAAgB,QAAU,CAAc,CAAC,EAE3D,IAAM,GAAA,EAAA,EAAA,aAAuB,GAAkB,CACzC,GAAY,IACX,GAAc,EAAgB,CAAI,EACvC,EAAgB,QAAQ,CAAI,EAC9B,EAAG,CAAC,EAAU,CAAY,CAAC,EAE3B,GAAmB,CACjB,OAAQ,CAAC,CAAC,EACV,YACA,QACA,SACA,aACA,cACA,WACA,SAAU,EAAY,EAAW,CAAE,QAAS,IAAK,CACnD,CAAC,EAED,SAAS,GAA4C,CACnD,OAAO,GAAY,EAAW,OAAO,EAAE,IAAM,EAAW,OAC1D,CAGA,SAAS,GAAwB,CAC/B,EAAsB,GAAG,MAAM,CACjC,CAIA,SAAS,GAAoB,CAC3B,IAAM,EAAM,GAAY,SAAS,IAAI,EAAE,OAAQ,GAAO,CAAC,EAAY,SAAS,SAAS,CAAE,CAAC,EAClF,EAAO,EAAsB,EAC7B,EAAM,EAAO,EAAI,QAAQ,CAAI,EAAI,GACnC,GAAO,GAAG,EAAI,EAAM,IAAI,MAAM,CACpC,EAKA,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,GAAQ,IAAY,GAAe,MAAO,OAC/C,IAAM,EAAa,GAAY,EAAS,OAAO,EAC3C,EAAW,SAAW,IAE1B,EAAY,SAAS,aAAa,OAAQ,QAAQ,EAClD,EAAW,GAAG,MAAM,EACtB,EAAG,CAAC,EAAM,CAAO,CAAC,EAElB,SAAS,EAAsB,EAA4B,CACzD,GAAI,EAAM,MAAQ,OAAS,IAAY,GAAe,MAAO,OAC7D,IAAM,EAAa,GAAY,EAAS,OAAO,EAC/C,GAAI,EAAW,SAAW,EAAG,OAC7B,IAAM,EAAS,SAAS,cACpB,CAAC,EAAM,UAAY,IAAW,EAAW,EAAW,OAAS,IAC/D,EAAM,eAAe,EACrB,EAAkB,EAClB,EAAQ,EAAK,GACJ,EAAM,UAAY,IAAW,EAAW,KACjD,EAAM,eAAe,EACrB,EAAsB,EACtB,EAAQ,EAAK,EAEjB,EAGA,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,EAAM,OAEX,SAAS,EAAU,EAAmB,CACpC,IAAM,EAAS,EAAM,OACf,EAAU,EAAY,SAAS,SAAS,CAAM,EAC9C,EAAY,EAAW,SAAS,SAAS,CAAM,EACjD,CAAC,GAAW,CAAC,GAAW,EAAQ,EAAK,CAC3C,CACA,SAAS,EAAU,EAAsB,CACnC,EAAM,MAAQ,WAEd,EAAY,SAAS,SAAS,SAAS,aAAa,IACrD,GAAY,EAAW,OAAO,EAAE,IAAM,EAAW,UAAU,MAAM,EAEpE,EAAQ,EAAK,EACf,CAGA,SAAS,EAAU,EAAmB,CACpC,IAAM,EAAS,EAAM,OACf,EAAU,EAAY,SAAS,SAAS,CAAM,EAC9C,EAAY,EAAW,SAAS,SAAS,CAAM,EACjD,CAAC,GAAW,CAAC,GAAW,EAAQ,EAAK,CAC3C,CAOA,OALI,GAAuB,IAAY,GAAe,QACpD,OAAO,iBAAiB,UAAW,CAAS,EAC5C,SAAS,iBAAiB,UAAW,CAAS,GAE5C,GAAe,OAAO,iBAAiB,UAAW,CAAS,MAClD,CACX,OAAO,oBAAoB,UAAW,CAAS,EAC/C,SAAS,oBAAoB,UAAW,CAAS,EACjD,OAAO,oBAAoB,UAAW,CAAS,CACjD,CACF,EAAG,CAAC,EAAM,EAAqB,EAAe,EAAS,CAAO,CAAC,GAE/D,EAAA,EAAA,mBAAsB,aAAa,EAAW,OAAO,EAAG,CAAC,CAAC,EAE1D,SAAS,EAAc,EAAe,CACpC,aAAa,EAAW,OAAO,EAC/B,EAAW,QAAU,eAAiB,EAAQ,CAAI,EAAG,EAAO,EAAY,CAAU,CACpF,CAEA,IAAM,GACJ,IAAY,GAAe,MACvB,CAAE,YAAe,EAAQ,CAAC,CAAI,CAAE,EAChC,IAAY,GAAe,MACzB,CAAE,iBAAoB,EAAc,EAAI,EAAG,iBAAoB,EAAc,EAAK,CAAE,EACpF,CAAE,YAAe,EAAQ,EAAI,EAAG,WAAc,EAAQ,EAAK,CAAE,EAE/D,EACJ,IAAY,GAAe,MACvB,CAAE,iBAAoB,EAAc,EAAI,EAAG,iBAAoB,EAAc,EAAK,CAAE,EACpF,CAAC,EAEP,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,GAAO,QAAS,EAAW,GAAY,IAAI,EACzD,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,WAHzC,EAKE,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,OAAO,EACxD,MAAO,GAAY,QACnB,GAAI,GAEH,UACE,CAAA,EACJ,IACC,EAAA,EAAA,KAAC,GAAD,CAAA,UACE,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,QAAQ,EAC1D,MAAO,GAAY,SACnB,iBAAgB,EAChB,UAAW,EACX,GAAI,WANN,EAQE,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,GAAY,KAAK,EACpD,MAAO,GAAY,eAElB,CACE,CAAA,EACJ,IACC,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,GAAY,KAAK,EACpD,MAAO,GAAY,KACpB,CAAA,CAEA,GACE,CAAA,CAER,GAET,gbE3NA,SAAgB,GAAiB,EAA0B,CACzD,IAAM,EAAM,EAAS,QAAQ,IAAK,EAAE,EAC9B,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EACpC,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EACpC,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EAG1C,OADmB,KAAQ,EAAI,KAAQ,EAAI,KAAQ,GAAK,IACrC,GAAM,UAAY,SACvC,CAEA,SAAS,GAAY,CACnB,YAAY,IAAA,GACZ,QAAQ,IACR,WAAW,EACX,QAAQ,IAAA,GACR,GAAG,GAC8B,CAEjC,SAAS,GAAqB,CAC5B,IAAM,EAA4B,CAAC,EAMnC,OAJI,MAAM,QAAQ,CAAQ,EAAG,EAAc,KAAK,GAAG,CAAQ,EAClD,OAAO,GAAa,SAAU,EAAc,KAAK,CAAQ,EAC7D,EAAc,KAAK,CAAE,OAAQ,CAAS,CAAC,EAErC,EAAc,KAAK,EAAM,IAAU,CACxC,IAAM,EAAmB,EAAa,EAAK,OAAS,EAAS,IAA5B,EAEjC,OACE,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SACE,GAAO,gBACP,IAAU,EAAc,OAAS,GAAK,GAAO,mBAC7C,EAAK,KACP,EACA,MAAO,CACL,MAAO,GAAG,EAAgB,GAC1B,WAAY,EAAK,OAAS,IAAA,GAC1B,GAAI,GAAS,CAAC,CAChB,EACA,MAAO,EAAK,MAAQ,GAAG,EAAK,MAAM,IAAI,EAAK,SAAW,IAAA,YAErD,EAAK,QAAS,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,iBAAkB,MAAO,EAAK,MAAQ,CAAE,MAAO,GAAiB,EAAK,KAAK,CAAE,EAAI,CAAC,WAAI,EAAK,KAAW,CAAA,CACxI,EAdE,CAcF,CAET,CAAC,CACH,CAEA,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,CAAS,EAAU,iBACjE,EAAmB,CACjB,CAAA,CAET,CCtDA,IAAY,GAAL,SAAA,EAAA,OACL,GAAA,SAAA,WACA,EAAA,WAAA,cACF,EAAA,CAAA,CAAA,8qCEDA,SAAS,GAAW,EAAsC,CACxD,GAAM,CACJ,UAAU,CAAC,EACX,QACA,eACA,eAAiB,CAAC,EAClB,cAAc,GAAsB,SACpC,WAAW,GACX,OAAO,OACP,WAAW,EACX,gBAAgB,KAChB,eAAe,GACf,UAAU,GACV,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,aAAc,CAAK,EAEtC,GAAA,EAAA,EAAA,QAA+C,CAAC,CAAC,EACjD,GAAA,EAAA,EAAA,QAAe,CAAa,GAClC,EAAA,EAAA,eAAgB,CAAE,EAAM,QAAU,CAAe,CAAC,EAClD,GAAM,EAAG,IAAA,EAAA,EAAA,UAAwB,CAAC,EAC5B,CAAC,EAAe,IAAA,EAAA,EAAA,UAAqD,CAAY,EACjF,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,EAAK,GAEhD,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,EAAe,OACpB,EAAc,SAAS,EACvB,IAAM,MAAiB,EAAa,GAAM,EAAI,CAAC,EAE/C,OADA,EAAc,yBAAyB,CAAQ,MAClC,EAAc,uBAAuB,CAAQ,CAC5D,EAAG,CAAC,CAAa,CAAC,EAElB,IAAM,EAAW,EACb,EAAc,SAAW,EAAc,SAAS,EAChD,CAAC,GAAW,CAAC,CAAC,EACZ,EAAY,EAAgB,EAAc,uBAAuB,EAAI,GAAgB,GAErF,EAAe,IAAU,IAAA,IAAa,CAAC,EACvC,EAAgB,EAAgB,EAAc,MAAQ,EAAe,EAAQ,EAInF,SAAS,EAAO,EAAkB,EAAgD,CAC5E,EAAe,EAAc,IAAI,CAAI,EAC/B,GAAc,EAAiB,CAAI,EAC7C,EAAS,EAAM,CAAK,CACtB,CAEA,SAAS,EAAW,EAAyC,CACvD,EAAM,cAAc,SAAS,EAAM,aAA4B,IACnE,EAAa,EAAK,EACd,EAAM,UAAS,EAAM,QAAQ,QAAU,IAC7C,CAEA,IAAM,EAAgB,EAAQ,UAAW,GAAM,EAAE,QAAU,CAAY,EACjE,EAAoB,EAAQ,UAAW,GAAM,CAAC,EAAE,QAAQ,EACxD,EAAc,GAAiB,EAAI,EAAgB,EAEzD,SAAS,GAAY,EAAe,CAClC,EAAW,QAAQ,IAAQ,MAAM,CACnC,CAEA,SAAS,EAAO,EAAc,EAAmB,EAA4B,CAC3E,GAAI,GAAY,EAAQ,SAAW,EAAG,OACtC,IAAI,EAAI,EACR,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAQ,OAAQ,IAE1C,GADA,GAAK,EAAI,EAAO,EAAQ,QAAU,EAAQ,OACtC,CAAC,EAAQ,GAAG,SAAU,CACxB,GAAY,CAAC,EACb,EAAO,EAAQ,GAAG,MAAO,CAAK,EAC9B,MACF,CAEJ,CAEA,SAAS,EAAc,EAA4B,EAAe,CAChE,IAAM,EAAS,EAAQ,GACvB,OAAQ,EAAM,IAAd,CACE,IAAK,YACL,IAAK,aACH,EAAM,eAAe,EACrB,EAAO,EAAG,EAAO,CAAK,EACtB,MACF,IAAK,UACL,IAAK,YACH,EAAM,eAAe,EACrB,EAAO,GAAI,EAAO,CAAK,EACvB,MACF,IAAK,IACL,IAAK,QACH,EAAM,eAAe,EACjB,CAAC,GAAY,CAAC,EAAO,UAAU,EAAO,EAAO,MAAO,CAAK,EAC7D,MACF,QACE,KACJ,CACF,CAEA,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,KAAK,aACL,mBAAkB,EAClB,gBAAe,GAAY,IAAA,GAC3B,eAAc,GAAY,IAAA,GAC1B,WAAA,EAAA,EAAA,SACE,GAAO,WACP,IAAgB,GAAsB,YAAc,GAAO,qBAC3D,GAAY,GAAO,mBACnB,GAAY,GAAO,gBACnB,EACA,GAAY,IACd,EACA,MAAO,CAAE,eAAgB,EAAM,GAAG,EAAO,GAAG,GAAY,IAAK,EAC7D,YAAe,EAAa,EAAI,EAChC,OAAQ,EACR,iBAAoB,EAAa,EAAI,EACrC,iBAAoB,EAAa,EAAK,WAlBxC,CAoBG,EAAQ,KAAK,EAAQ,IAAU,CAC9B,IAAM,EAAU,EAAO,QAAU,EAC3B,EAAiB,GAAY,CAAC,CAAC,EAAO,SAC5C,OACE,EAAA,EAAA,MAAC,MAAD,CAEE,IAAM,GAAO,CAAE,EAAW,QAAQ,GAAS,CAAI,EAC/C,KAAK,QACL,eAAc,EACd,gBAAe,GAAkB,IAAA,GACjC,SAAU,EAAiB,GAAK,IAAU,EAAc,EAAW,GACnE,WAAA,EAAA,EAAA,SACE,GAAO,iBACP,GAAW,GAAO,wBAClB,GAAkB,GAAO,yBACzB,GAAY,MACd,EACA,MAAO,GAAY,OACnB,YAAe,CAAO,GAAgB,EAAO,EAAO,KAAK,CAAG,EAC5D,UAAY,GAAM,EAAc,EAAG,CAAK,WAf1C,EAiBE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAW,GAAO,uBAAwB,GAAY,KAAK,EACjG,MAAO,GAAY,gBAEnB,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAW,GAAO,qBAAsB,GAAY,GAAG,EAC3F,MAAO,GAAY,GACpB,CAAA,CACE,CAAA,GACH,EAAO,OAAS,EAAO,SAAW,KAClC,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,wBAAvB,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,KAAK,EAAG,MAAO,GAAY,eAC/E,EAAO,OAAS,EAAO,KACrB,CAAA,EACJ,EAAO,aAAe,OACrB,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,sBAAuB,GAAY,WAAW,EACnE,MAAO,GAAY,qBAElB,EAAO,WACL,CAAA,CAEJ,GAEJ,GAxCE,OAAO,EAAO,KAAK,CAwCrB,CAET,CAAC,GACD,EAAA,EAAA,KAAC,GAAD,CACE,QAAQ,QACR,QAAS,EACT,UAAW,IAAa,GAAa,EACtC,CAAA,CACE,GAET,0hBE/KM,GAAiB,EAEvB,SAAS,GAAW,EAAe,EAAqB,CACtD,OAAO,KAAK,IAAI,EAAG,KAAK,IAAI,EAAK,CAAK,CAAC,CACzC,CAEA,SAAS,GAAO,EAAkC,CAChD,GAAM,CACJ,MAAO,EACP,eAAe,EACf,eAAiB,CAAC,EAClB,MAAM,EACN,YAAY,GACZ,aAAa,GACb,WAAW,GACX,WAAW,GACX,OAAO,EAAA,OACP,aAAc,EAAY,SAC1B,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,SAAU,CAAK,EAElC,EAAe,IAAoB,IAAA,GACnC,CAAC,EAAe,IAAA,EAAA,EAAA,UAA6B,CAAY,EACzD,EAAQ,GAAW,EAAe,EAAmB,EAAe,CAAG,EAEvE,CAAC,EAAY,IAAA,EAAA,EAAA,UAAyC,IAAI,EAC1D,EAAgB,CAAC,GAAY,CAAC,EAC9B,EAAe,GAAc,EAE7B,GAAA,EAAA,EAAA,QAAiC,IAAI,EACrC,GAAA,EAAA,EAAA,QAA+B,CAAK,EACpC,GAAA,EAAA,EAAA,QAAqB,EAAK,EAC1B,GAAA,EAAA,EAAA,QAA0B,CAAC,EAC3B,GAAA,EAAA,EAAA,QAAuB,EAAK,EAElC,SAAS,EAAO,EAAmB,CACjC,IAAM,EAAU,GAAW,EAAW,CAAG,EACpC,GAAc,EAAiB,CAAO,EAC3C,EAAS,CAAO,CAClB,CAEA,SAAS,EAAoB,EAAgC,CAC3D,IAAM,EAAO,EAAQ,SAAS,sBAAsB,EACpD,GAAI,CAAC,GAAQ,EAAK,QAAU,EAAG,OAAO,KAEtC,IAAM,EADW,IAAY,EAAU,EAAK,MAAQ,EAAK,MAAO,CACpD,EAAW,EACvB,OAAO,EAAY,KAAK,MAAM,EAAM,CAAC,EAAI,EAAI,KAAK,KAAK,CAAG,CAC5D,CAEA,SAAS,EAAkB,EAA2C,CACpE,GAAI,CAAC,EAAe,OACpB,EAAM,cAAc,oBAAoB,EAAM,SAAS,EACvD,EAAY,QAAU,GACtB,EAAc,QAAU,GACxB,EAAiB,QAAU,EAAM,QACjC,EAAsB,QAAU,EAChC,IAAM,EAAO,EAAoB,EAAM,OAAO,EAC1C,IAAS,MAAM,EAAc,CAAI,CACvC,CAEA,SAAS,EAAkB,EAA2C,CACpE,GAAI,CAAC,EAAe,OACpB,IAAM,EAAO,EAAoB,EAAM,OAAO,EAC1C,IAAS,OACT,EAAY,UACd,EAAM,eAAe,EACjB,KAAK,IAAI,EAAM,QAAU,EAAiB,OAAO,EAAI,KACvD,EAAc,QAAU,KAG5B,EAAc,CAAI,EACpB,CAEA,SAAS,GAAgB,EAA2C,CAClE,GAAI,CAAC,GAAiB,CAAC,EAAY,QAAS,OAC5C,EAAM,cAAc,wBAAwB,EAAM,SAAS,EAC3D,EAAY,QAAU,GACtB,IAAM,EAAO,EAAoB,EAAM,OAAO,GAAK,EAC/C,IAAS,MAEX,EAAO,CADU,EAAc,SACb,GAAc,IAAS,EAAsB,QAAU,EAAI,CAAI,EAEnF,EAAc,IAAI,CACpB,CAEA,SAAS,GAAqB,CACxB,CAAC,GAAiB,EAAY,SAClC,EAAc,IAAI,CACpB,CAEA,SAAS,EAAc,EAA4C,CACjE,IAAM,EAAO,EAAY,GAAM,EAC3B,EAAM,MAAQ,cAAgB,EAAM,MAAQ,WAC9C,EAAM,eAAe,EACrB,EAAO,EAAQ,CAAI,GACV,EAAM,MAAQ,aAAe,EAAM,MAAQ,aACpD,EAAM,eAAe,EACrB,EAAO,EAAQ,CAAI,GACV,EAAM,MAAQ,QACvB,EAAM,eAAe,EACrB,EAAO,CAAC,GACC,EAAM,MAAQ,QACvB,EAAM,eAAe,EACrB,EAAO,CAAG,EAEd,CAEA,OACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACJ,IAAK,EACL,KAAK,SACL,aAAY,EACZ,gBAAe,EACf,gBAAe,EACf,gBAAe,EACf,iBAAgB,GAAG,EAAM,UAAU,IACnC,gBAAe,GAAY,IAAA,GAC3B,gBAAe,GAAY,IAAA,GAC3B,SAAU,EAAgB,EAAI,GAC9B,WAAA,EAAA,EAAA,SACE,GAAO,OACP,GAAY,GAAO,eACnB,GAAY,GAAO,eACnB,GAAY,KACZ,CACF,EACA,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EACvC,UAAW,EAAgB,EAAgB,IAAA,GAC3C,cAAe,EAAgB,EAAoB,IAAA,GACnD,cAAe,EAAgB,EAAoB,IAAA,GACnD,YAAa,EAAgB,GAAkB,IAAA,GAC/C,gBAAiB,EAAgB,GAAkB,IAAA,GACnD,eAAgB,EAAgB,EAAqB,IAAA,YAEpD,MAAM,KAAK,CAAE,OAAQ,CAAI,GAAI,EAAG,IAAU,CACzC,IAAM,EAAc,KAAK,MAAM,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,EAAe,CAAK,CAAC,EAAI,GAAG,EAEnF,OACE,EAAA,EAAA,MAAC,MAAD,CAAiB,WAAA,EAAA,EAAA,SAAc,GAAO,WAAY,GAAY,IAAI,EAAG,MAAO,GAAY,cAAxF,EACE,EAAA,EAAA,KAAC,EAAA,gBAAD,CACQ,OACN,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,SAAS,EAC3D,MAAO,GAAY,SACpB,CAAA,GACD,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,GAAO,qBAAsB,MAAO,CAAE,MAAO,GAAG,EAAY,EAAG,YAC7E,EAAA,EAAA,KAAC,EAAA,gBAAD,CACQ,OACN,WAAA,EAAA,EAAA,SAAc,GAAO,iBAAkB,GAAY,UAAU,EAC7D,MAAO,GAAY,UACpB,CAAA,CACE,CAAA,CACF,GAbK,CAaL,CAET,CAAC,CACE,CAAA,CAET,CCjKA,SAAgB,GAAK,EAAmB,CACtC,OAAO,KAAK,MAAM,EAAA,CAAQ,EAAA,CAC5B,CAEA,SAAgB,GAAO,EAAiB,CACtC,MAAO,CAAE,EAAG,GAAK,EAAE,CAAC,EAAG,EAAG,GAAK,EAAE,CAAC,CAAE,CACtC,CAEA,SAAgB,GAAY,EAAiB,EAAiB,EAA2B,CACvF,IAAM,EAAK,EAAI,eAAe,EAC9B,EAAG,EAAI,EACP,EAAG,EAAI,EACP,IAAM,EAAI,EAAI,aAAa,EAC3B,GAAI,CAAC,EAAG,MAAO,CAAE,EAAG,EAAG,EAAG,CAAE,EAC5B,IAAM,EAAM,EAAG,gBAAgB,EAAE,QAAQ,CAAC,EAC1C,OAAO,GAAO,CAAE,EAAG,EAAI,EAAG,EAAG,EAAI,CAAE,CAAC,CACtC,CAIA,SAAgB,GAAK,EAAU,EAAkB,CAC/C,OAAO,KAAK,MAAM,EAAE,EAAI,EAAE,IAAM,GAAK,EAAE,EAAI,EAAE,IAAM,CAAC,CACtD,CAEA,SAAgB,GAAe,EAAU,EAAU,EAAuC,CACxF,IAAM,EAAK,EAAE,EAAI,EAAE,EACb,EAAK,EAAE,EAAI,EAAE,EACb,EAAO,EAAK,EAAK,EAAK,EAC5B,GAAI,IAAS,EAAG,MAAO,CAAE,KAAM,GAAK,EAAG,CAAC,EAAG,EAAG,CAAE,EAChD,IAAM,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,IAAK,EAAE,EAAI,EAAE,GAAK,GAAM,EAAE,EAAI,EAAE,GAAK,GAAM,CAAI,CAAC,EACzE,EAAK,EAAE,EAAI,EAAI,EACf,EAAK,EAAE,EAAI,EAAI,EACrB,MAAO,CAAE,KAAM,KAAK,MAAM,EAAE,EAAI,IAAO,GAAK,EAAE,EAAI,IAAO,CAAC,EAAG,GAAE,CACjE,CAEA,SAAgB,GAAY,EAAW,EAA4E,CACjH,IAAI,EAA8E,KAClF,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAM,EAAK,OACjB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAI,OAAQ,IAAK,CACnC,IAAM,EAAI,EAAI,GACR,EAAI,GAAK,EAAI,GAAK,EAAI,QACtB,CAAE,KAAM,EAAG,KAAM,GAAe,EAAI,EAAG,CAAC,EAC1C,GAAA,IAAwB,CAAC,GAAQ,EAAI,EAAK,QAC5C,EAAO,CAAE,OAAQ,EAAK,GAAI,UAAW,EAAG,IAAG,KAAM,CAAE,EAEvD,CACF,CACA,OAAO,CACT,CAEA,SAAgB,GAAe,EAAW,EAAwB,CAChE,IAAI,EAAS,GACb,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAS,EAAG,EAAI,EAAK,OAAQ,EAAI,IAAK,CAC7D,IAAM,EAAK,EAAK,GAAG,EAAG,EAAK,EAAK,GAAG,EAC7B,EAAK,EAAK,GAAG,EAAG,EAAK,EAAK,GAAG,EAC9B,EAAK,EAAG,GAAQ,EAAK,EAAG,GAAM,EAAG,GAAM,EAAK,IAAO,EAAG,EAAI,IAAQ,EAAK,GAAM,IAChF,EAAS,CAAC,EAEd,CACA,OAAO,CACT,CAEA,SAAgB,GAAS,EAAqB,CAC5C,MAAO,CACL,EAAG,EAAI,QAAQ,EAAG,IAAM,EAAI,EAAE,EAAG,CAAC,EAAI,EAAI,OAC1C,EAAG,EAAI,QAAQ,EAAG,IAAM,EAAI,EAAE,EAAG,CAAC,EAAI,EAAI,MAC5C,CACF,CAEA,SAAgB,GAAa,EAAW,EAAW,EAAW,EAAoB,CAChF,MAAO,CACL,CAAE,IAAG,GAAE,EACP,CAAE,EAAG,EAAI,EAAG,GAAE,EACd,CAAE,EAAG,EAAI,EAAG,EAAG,EAAI,CAAE,EACrB,CAAE,IAAG,EAAG,EAAI,CAAE,CAChB,CACF,CAGA,SAAgB,GACd,EACA,EACA,EACA,EAC8C,CAC9C,IAAM,EAAK,EAAE,EAAI,EAAE,EACb,EAAK,EAAE,EAAI,EAAE,EACb,EAAM,KAAK,KAAK,EAAK,EAAK,EAAK,CAAE,EACvC,GAAI,EAAM,KAAO,OAAO,KACxB,IAAM,EAAK,EAAK,EACV,EAAK,EAAK,EACV,EAAK,EAAE,EAAI,EAAK,EAChB,EAAK,EAAE,EAAI,EAAK,EAChB,EAAK,KAAK,IAAI,EAAQ,EAAG,EAAM,EAAI,IAAK,EAC9C,MAAO,CACL,GAAI,CAAE,EAAG,EAAK,EAAK,EAAI,EAAG,EAAK,EAAK,CAAG,EACvC,GAAI,CAAE,EAAG,EAAK,EAAK,EAAI,EAAG,EAAK,EAAK,CAAG,EACvC,KAAM,CAAE,EAAG,CAAC,EAAI,EAAG,CAAG,CACxB,CACF,CAIA,SAAS,GAAU,EAAmB,CACpC,OAAO,EAAE,QAAQ,KAAM,OAAO,EAAE,QAAQ,KAAM,MAAM,EAAE,QAAQ,KAAM,MAAM,CAC5E,CAEA,SAAS,GAAgB,EAAsB,CAC7C,OAAO,EAAI,KAAK,EAAG,IAAM,GAAG,IAAM,EAAI,IAAM,IAAI,GAAG,EAAE,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,GAAG,EAAI,IACrG,CAIA,SAAgB,GAAkB,EAAc,EAAiC,CAC/E,GAAI,EAAI,OAAS,EAAG,MAAO,CAAC,EAE5B,GAAI,EAAU,SAAW,EACvB,MAAO,CAAC,EAAI,KAAK,EAAG,IAAM,GAAG,IAAM,EAAI,IAAM,IAAI,GAAG,EAAE,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,GAAG,EAAI,IAAI,EAG1G,IAAM,EAAI,EAAI,OACR,EAAuB,CAAC,EAC1B,EAAoB,CAAC,KAAK,EAAI,GAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAI,GAAG,EAAE,QAAQ,CAAC,GAAG,EAE1E,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,IAAK,CAC1B,IAAM,EAAI,EAAI,GACR,EAAI,GAAK,EAAI,GAAK,GAClB,EAAK,EAAE,EAAI,EAAE,EACb,EAAK,EAAE,EAAI,EAAE,EACb,EAAM,KAAK,KAAK,EAAK,EAAK,EAAK,CAAE,EACjC,EAAO,EAAU,OAAQ,GAAM,EAAE,YAAc,CAAC,EAAE,MAAM,EAAG,IAAM,EAAE,EAAI,EAAE,CAAC,EAEhF,GAAI,EAAK,SAAW,EAClB,EAAQ,KAAK,KAAK,EAAE,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ,CAAC,GAAG,MAC/C,CACL,IAAK,IAAM,KAAQ,EAAM,CACvB,IAAM,EAAK,EAAK,MAAQ,EAClB,EAAK,KAAK,IAAI,EAAG,EAAK,EAAI,EAAK,CAAG,EAClC,EAAK,KAAK,IAAI,EAAG,EAAK,EAAI,EAAK,CAAG,EAClC,EAAK,CAAE,EAAG,EAAE,EAAI,EAAK,EAAI,EAAG,EAAE,EAAI,EAAK,CAAG,EAC1C,EAAK,CAAE,EAAG,EAAE,EAAI,EAAK,EAAI,EAAG,EAAE,EAAI,EAAK,CAAG,EAChD,EAAQ,KAAK,KAAK,EAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAG,EAAE,QAAQ,CAAC,GAAG,EACtD,EAAS,KAAK,CAAO,EACrB,EAAU,CAAC,KAAK,EAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAG,EAAE,QAAQ,CAAC,GAAG,CACtD,CACA,EAAQ,KAAK,KAAK,EAAE,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ,CAAC,GAAG,CACtD,CACF,CAMA,MAFA,GAAS,GAAK,CAAC,GAAG,EAAS,GAAG,EAAS,GAAG,MAAM,CAAC,CAAC,EAE3C,EAAS,IAAK,GAAM,EAAE,KAAK,GAAG,CAAC,CACxC,CAEA,SAAS,GAAiB,EAAU,EAAU,EAAwB,CACpE,IAAM,EAAK,GAAc,EAAG,EAAG,EAAK,EAAG,EAAK,KAAK,EACjD,GAAI,CAAC,EAAI,MAAO,GAChB,GAAM,CAAE,KAAI,KAAI,QAAS,EACnB,EAAW,CAAE,EAAG,EAAG,EAAI,EAAK,EAAI,EAAK,MAAO,EAAG,EAAG,EAAI,EAAK,EAAI,EAAK,KAAM,EAChF,MAAO,CACL,KAAK,EAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAG,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAG,EAAE,QAAQ,CAAC,IAC9E,KAAK,EAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAG,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAK,MAAM,GAAG,EAAK,MAAM,SAAS,EAAS,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAS,EAAE,QAAQ,CAAC,GAC9H,EAAE,KAAK,GAAG,CACZ,CAEA,SAAgB,GAAY,EAAmB,EAA2B,CACxE,IAAI,EAAO,IAAU,EAAO,IAAU,EAAO,KAAW,EAAO,KAC/D,IAAK,IAAM,KAAK,EACd,IAAK,IAAM,KAAK,EAAE,OACZ,EAAE,EAAI,IAAM,EAAO,EAAE,GACrB,EAAE,EAAI,IAAM,EAAO,EAAE,GACrB,EAAE,EAAI,IAAM,EAAO,EAAE,GACrB,EAAE,EAAI,IAAM,EAAO,EAAE,GAGxB,SAAS,CAAI,IAAK,EAAO,EAAG,EAAO,EAAG,EAAA,IAAiB,EAAA,KAE5D,IACM,EAAK,EACR,EAAO,GAAK,QAAQ,CAAC,GACrB,EAAO,GAAK,QAAQ,CAAC,GACrB,EAAO,EAAO,IAAS,QAAQ,CAAC,GAChC,EAAO,EAAO,IAAS,QAAQ,CAAC,CACnC,EAAE,KAAK,GAAG,EAEJ,EAAU,EAAM,IAAK,GAAS,CAClC,IAAM,EAAY,EAAM,OAAQ,GAAM,EAAE,SAAW,EAAK,EAAE,EACpD,EAAW,GAAkB,EAAK,OAAQ,CAAS,EACnD,EAAS,GAAgB,EAAK,MAAM,EACpC,EAAI,GAAS,EAAK,MAAM,EAExB,EAAY,EAAS,IAAK,GAAM,gBAAgB,EAAE,KAAK,EAAE,KAAK;CAAI,EAElE,EAAY,EACf,IAAK,GAAS,CACb,IAAM,EAAI,EAAK,OAAO,EAAK,WACrB,EAAI,EAAK,QAAQ,EAAK,UAAY,GAAK,EAAK,OAAO,QACnD,EAAI,GAAiB,EAAG,EAAG,CAAI,EACrC,OAAO,EAAI,gBAAgB,EAAE,kBAAoB,EACnD,CAAC,EACA,OAAO,OAAO,EACd,KAAK;CAAI,EAEN,EAAU,EAAK,KACjB,6BAA6B,EAAE,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,QAAQ,CAAC,EAAE,IAAI,GAAU,EAAK,IAAI,EAAE,SAC3F,GAEJ,MAAO,CAAC,YAAY,EAAK,GAAG,IAAK,EAAW,gCAAgC,EAAO,MAAO,EAAW,EAAS,QAAQ,EACnH,OAAO,OAAO,EACd,KAAK;CAAI,CACd,CAAC,EAED,MAAO,CACL,kEAAkE,EAAG,IACrE,oBACA,GAAG,EACH,SACA,6BACA,QACF,EAAE,KAAK;CAAI,CACb,CAIA,SAAS,GAAgB,EAAoB,CAC3C,IAAM,EAAkB,CAAC,EACzB,IAAK,IAAM,KAAK,EAAE,SAAS,mCAAmC,EAC5D,EAAO,KAAK,CAAE,EAAG,WAAW,EAAE,EAAE,EAAG,EAAG,WAAW,EAAE,EAAE,CAAE,CAAC,EAE1D,OAAO,CACT,CAEA,SAAgB,GAAc,EAA+B,CAC3D,IAAM,EAAM,IAAI,UAAU,EAAE,gBAAgB,EAAW,eAAe,EAChE,EAAoB,CAAC,EAW3B,OAVA,EAAI,iBAAiB,cAAc,EAAE,QAAS,GAAU,CACtD,IAAM,EAAK,EAAM,cAAc,mBAAmB,EAClD,GAAI,CAAC,EAAI,OACT,IAAM,EAAI,EAAG,aAAa,GAAG,EAC7B,GAAI,CAAC,EAAG,OACR,IAAM,EAAS,GAAgB,CAAC,EAChC,GAAI,EAAO,OAAS,EAAG,OACvB,IAAM,EAAO,EAAM,cAAc,MAAM,GAAG,aAAa,KAAK,GAAK,GACjE,EAAM,KAAK,CAAE,GAAI,EAAM,GAAI,OAAM,QAAO,CAAC,CAC3C,CAAC,EACM,CACT,CAEA,SAAgB,GAAY,EAAmB,EAAyB,CACtE,IAAM,EAAM,GAAY,EAAO,CAAK,EAC9B,EAAO,IAAI,KAAK,CAAC,CAAG,EAAG,CAAE,KAAM,eAAgB,CAAC,EAChD,EAAM,IAAI,gBAAgB,CAAI,EAC9B,EAAI,SAAS,cAAc,GAAG,EACpC,EAAE,KAAO,EACT,EAAE,SAAW,gBACb,EAAE,MAAM,EACR,IAAI,gBAAgB,CAAG,CACzB,q/GEzOM,GAAa,EACb,GAAW,EACX,GAAY,KACZ,GAAW,IACX,GAAW,GAMb,GAAO,EACX,SAAS,GAAO,EAAwB,CAEtC,MADA,KAAQ,EACD,GAAG,IAAS,IACrB,CAEA,IAAM,GAAmC,CACvC,OACE,yHACF,KAAM,kCACN,QACE,8EACJ,EAEA,SAAwB,GAAW,CAAE,aAA4C,CAC/E,GAAM,CAAC,EAAO,IAAA,EAAA,EAAA,UAAiC,CAAC,CAAC,EAC3C,CAAC,EAAO,IAAA,EAAA,EAAA,UAAiC,CAAC,CAAC,EAC3C,CAAC,EAAM,IAAA,EAAA,EAAA,UAA0B,MAAM,EACvC,CAAC,EAAY,IAAA,EAAA,EAAA,UAAyC,IAAI,EAC1D,CAAC,EAAuB,IAAA,EAAA,EAAA,UAAoD,IAAI,EAEhF,CAAC,EAAW,IAAA,EAAA,EAAA,UAAuC,IAAI,EACvD,CAAC,EAAY,IAAA,EAAA,EAAA,UAAwC,IAAI,EAEzD,CAAC,EAAY,IAAA,EAAA,EAAA,UAAmC,CAAC,CAAC,EAClD,CAAC,EAAY,IAAA,EAAA,EAAA,UAAwC,IAAI,EAEzD,CAAC,EAAM,IAAA,EAAA,EAAA,UAAoB,CAAC,EAC5B,CAAC,EAAK,IAAA,EAAA,EAAA,UAA0B,CAAE,EAAG,EAAG,EAAG,CAAE,CAAC,EAE9C,GAAA,EAAA,EAAA,QAAmC,IAAI,EACvC,GAAA,EAAA,EAAA,QAAoC,IAAI,EACxC,GAAA,EAAA,EAAA,QAAmG,IAAI,EACvG,GAAA,EAAA,EAAA,QAA+B,IAAI,EACnC,GAAA,EAAA,EAAA,QAAqC,IAAI,EAEzC,GAAA,EAAA,EAAA,QAAkB,CAAE,QAAO,QAAO,OAAM,aAAY,wBAAuB,aAAY,OAAM,KAAI,CAAC,GACxG,EAAA,EAAA,qBAAsB,CACpB,EAAS,QAAU,CAAE,QAAO,QAAO,OAAM,aAAY,wBAAuB,aAAY,OAAM,KAAI,CACpG,CAAC,EAED,SAAS,EAAc,EAAc,CAC/B,EAAI,OAAS,IACjB,EAAU,GAAS,CACjB,GAAG,EACH,CAAE,GAAI,GAAO,MAAM,EAAG,KAAM,QAAQ,EAAK,OAAS,IAAK,OAAQ,CAAI,CACrE,CAAC,EACD,EAAc,CAAC,CAAC,EAChB,EAAc,IAAI,EACpB,EAGA,EAAA,EAAA,eAAgB,CACd,IAAM,EAAM,EAAO,QACnB,GAAI,CAAC,EAAK,OACV,SAAS,EAAQ,EAAe,CAC9B,EAAE,eAAe,EACjB,GAAM,CAAE,KAAM,EAAG,IAAK,GAAM,EAAS,QAC/B,EAAK,GAAY,EAAE,QAAS,EAAE,QAAS,EAAO,OAAQ,EAC5D,GAAI,CAAC,EAAI,OACT,IAAM,EAAS,EAAE,OAAS,EAAI,GAAY,EAAI,GACxC,EAAU,KAAK,IAAI,GAAU,KAAK,IAAI,GAAU,EAAI,CAAM,CAAC,EACjE,EAAO,CACL,EAAG,EAAG,GAAK,EAAG,EAAI,EAAE,IAAM,EAAI,GAC9B,EAAG,EAAG,GAAK,EAAG,EAAI,EAAE,IAAM,EAAI,EAChC,CAAC,EACD,EAAQ,CAAO,CACjB,CAEA,OADA,EAAI,iBAAiB,QAAS,EAAS,CAAE,QAAS,EAAM,CAAC,MAC5C,EAAI,oBAAoB,QAAS,CAAO,CACvD,EAAG,CAAC,CAAC,GAEL,EAAA,EAAA,eAAgB,CACd,SAAS,EAAM,EAAkB,CAC/B,GAAM,CAAE,KAAM,EAAG,WAAY,EAAK,sBAAuB,EAAW,WAAY,EAAI,KAAM,EAAG,IAAK,GAAM,EAAS,QAEjH,GAAI,EAAE,MAAQ,SAAU,CACtB,GAAI,EAAW,CAAE,EAAyB,IAAI,EAAG,MAAQ,CACrD,IAAM,YAAa,EAAc,CAAC,CAAC,EAAG,EAAc,IAAI,GAC5D,EAAc,IAAI,EAClB,MACF,CACA,GAAI,EAAE,MAAQ,SAAW,IAAM,WAAa,EAAG,QAAU,EAAG,CAC1D,EAAc,CAAE,EAChB,MACF,CACA,IAAK,EAAE,MAAQ,KAAO,EAAE,MAAQ,MAAQ,EAAE,EAAE,kBAAkB,kBAAmB,CAC/E,IAAM,EAAK,KAAK,IAAI,GAAU,KAAK,IAAI,GAAU,EAAI,EAAS,CAAC,EACzD,EAAK,EAAE,EAAA,IAAe,EAAI,EAAS,EAAK,EAAE,EAAA,IAAe,EAAI,EACnE,EAAQ,CAAE,EAAG,EAAO,CAAE,EAAG,EAAA,IAAgB,EAAK,EAAG,EAAG,EAAA,IAAgB,EAAK,CAAE,CAAC,EAC5E,MACF,CACA,GAAI,EAAE,MAAQ,KAAO,EAAE,EAAE,kBAAkB,kBAAmB,CAC5D,IAAM,EAAK,KAAK,IAAI,GAAU,KAAK,IAAI,GAAU,EAAI,EAAS,CAAC,EACzD,EAAK,EAAE,EAAA,IAAe,EAAI,EAAS,EAAK,EAAE,EAAA,IAAe,EAAI,EACnE,EAAQ,CAAE,EAAG,EAAO,CAAE,EAAG,EAAA,IAAgB,EAAK,EAAG,EAAG,EAAA,IAAgB,EAAK,CAAE,CAAC,EAC5E,MACF,CACA,GAAI,EAAE,MAAQ,KAAO,EAAE,EAAE,kBAAkB,kBAAmB,CAC5D,EAAQ,CAAC,EAAG,EAAO,CAAE,EAAG,EAAG,EAAG,CAAE,CAAC,EACjC,MACF,EACK,EAAE,MAAQ,UAAY,EAAE,MAAQ,cAAgB,GAAO,CAAC,GAAa,EAAE,EAAE,kBAAkB,oBAC9F,EAAU,GAAS,EAAK,OAAQ,GAAM,EAAE,KAAO,CAAG,CAAC,EACnD,EAAU,GAAS,EAAK,OAAQ,GAAM,EAAE,SAAW,CAAG,CAAC,EACvD,EAAc,IAAI,EAEtB,CAEA,OADA,OAAO,iBAAiB,UAAW,CAAK,MAC3B,OAAO,oBAAoB,UAAW,CAAK,CAC1D,EAAG,CAAC,CAAC,EAIL,SAAS,EAAO,EAAgB,EAAc,EAAM,EAAa,EAAK,CACpE,IAAM,EAAU,KAAK,IAAI,GAAU,KAAK,IAAI,GAAU,EAAc,CAAM,CAAC,EACrE,EAAK,EAAW,EAAA,IAAe,EAAc,EAC7C,EAAK,EAAW,EAAA,IAAe,EAAc,EACnD,EAAO,CACL,EAAG,EAAA,IAAgB,EAAU,EAC7B,EAAG,EAAA,IAAgB,EAAU,CAC/B,CAAC,EACD,EAAQ,CAAO,CACjB,CAIA,SAAS,EAAM,EAA6B,CAE1C,OADK,EAAO,QACL,GAAY,EAAE,QAAS,EAAE,QAAS,EAAO,OAAO,EAD3B,IAE9B,CAIA,SAAS,EAAc,EAAW,EAAqD,CACrF,IAAI,EAA4C,KAChD,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAO,OAAQ,IAAK,CAC3C,IAAM,EAAI,GAAK,EAAI,EAAK,OAAO,EAAE,EAC7B,GAAK,KAAe,CAAC,GAAQ,EAAI,EAAK,KAAI,EAAO,CAAE,MAAO,EAAG,GAAE,EACrE,CACA,OAAO,CACT,CAEA,SAAS,EACP,EACA,EACgD,CAChD,IAAI,EAAuD,KAC3D,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAO,OAAQ,IAAK,CAC3C,IAAM,EAAI,EAAK,OAAO,GAChB,EAAI,EAAK,QAAQ,EAAI,GAAK,EAAK,OAAO,QACtC,CAAE,KAAM,EAAG,KAAM,GAAe,EAAI,EAAG,CAAC,EAC1C,GAAK,KAAa,CAAC,GAAQ,EAAI,EAAK,KAAI,EAAO,CAAE,MAAO,EAAG,IAAG,GAAE,EACtE,CACA,OAAO,CACT,CAEA,SAAS,GAAa,EAAgB,EAAmB,EAAW,EAAsB,CAoBxF,OAnBA,EAAU,GACR,EAAK,IAAK,GAAM,CACd,GAAI,EAAE,KAAO,EAAQ,OAAO,EAC5B,IAAM,EAAM,CAAC,GAAG,EAAE,MAAM,EAExB,OADA,EAAI,OAAO,EAAY,EAAG,EAAG,CAAK,EAC3B,CAAE,GAAG,EAAG,OAAQ,CAAI,CAC7B,CAAC,CACH,EACA,EAAU,GACR,EAAK,IAAK,GACJ,EAAE,SAAW,EACb,EAAE,YAAc,EACd,EAAE,GAAK,EAAU,CAAE,GAAG,EAAG,EAAG,EAAI,EAAI,EAAE,EAAI,EAAI,CAAE,EAC7C,CAAE,GAAG,EAAG,UAAW,EAAY,EAAG,GAAI,EAAE,EAAI,IAAM,EAAI,EAAG,EAE9D,EAAE,UAAY,EAAkB,CAAE,GAAG,EAAG,UAAW,EAAE,UAAY,CAAE,EAChE,EANyB,CAOjC,CACH,EACO,EAAY,CACrB,CAEA,SAAS,EAAa,EAAgB,EAAe,CACnD,IAAM,EAAO,EAAM,KAAM,GAAM,EAAE,KAAO,CAAM,EAC9C,GAAI,CAAC,GAAQ,EAAK,OAAO,QAAU,EAAG,OACtC,IAAM,EAAI,EAAK,OAAO,OACtB,EAAU,GACR,EAAK,IAAK,GACJ,EAAE,KAAO,EACN,CAAE,GAAG,EAAG,OAAQ,EAAE,OAAO,QAAQ,EAAG,IAAM,IAAM,CAAK,CAAE,EADlC,CAE7B,CACH,EACA,EAAU,GACR,EAAK,IAAK,GAAM,CACd,GAAI,EAAE,SAAW,EAAQ,OAAO,EAChC,IAAM,GAAY,EAAQ,EAAI,GAAK,EAGnC,OAFI,EAAE,YAAc,GAAY,EAAE,YAAc,EAAc,CAAE,GAAG,EAAG,UAAW,EAAG,EAChF,EAAE,UAAY,EAAc,CAAE,GAAG,EAAG,UAAW,EAAE,UAAY,CAAE,EAC5D,CACT,CAAC,EAAE,OAAQ,GAAM,EAAE,YAAc,EAAE,CACrC,CACF,CAIA,SAAS,EAAgB,EAA8B,CAErD,GAAI,EAAE,SAAW,EAAG,CAClB,EAAE,eAAe,EACjB,IAAM,EAAM,EAAO,QACnB,GAAI,EAAK,CACP,IAAM,EAAO,EAAI,sBAAsB,EACvC,EAAW,QAAU,CACnB,YAAa,CAAE,EAAG,EAAE,QAAS,EAAG,EAAE,OAAQ,EAC1C,QAAS,CAAE,GAAG,CAAI,EAClB,OAAA,IAAoB,EAAQ,EAAK,MACjC,OAAA,IAAoB,EAAQ,EAAK,MACnC,CACF,CACA,MACF,CAEA,GAAI,EAAE,SAAW,EAAG,OACpB,EAAE,eAAe,EACjB,IAAM,EAAK,EAAM,CAAC,EACb,KAGL,IAAI,EAAuB,CACzB,IAAM,EAAc,EAAM,KAAM,GAAM,EAAE,KAAO,CAAqB,EACpE,GAAI,EAAa,CACf,IAAM,EAAO,GAAY,EAAI,CAAC,CAAW,CAAC,EACtC,GACF,EAAU,GAAS,CACjB,GAAG,EACH,CAAE,GAAI,GAAO,MAAM,EAAG,OAAQ,EAAK,OAAQ,UAAW,EAAK,UAAW,EAAG,EAAK,EAAG,MAAA,EAAkB,CACrG,CAAC,CAEL,CACA,MACF,CAEA,GAAI,IAAS,OAAQ,CACnB,EAAa,CAAE,EAAG,EAAc,CAAE,EAAG,MACvC,CAEA,GAAI,IAAS,UAAW,CAClB,EAAW,QAAU,GAAK,GAAK,EAAI,EAAW,EAAE,GAAA,EAClD,EAAc,CAAU,EAExB,EAAe,GAAS,CAAC,GAAG,EAAM,CAAE,CAAC,EAEvC,MACF,CAEA,GAAI,IAAS,SAAU,CACrB,IAAM,EAAU,EAAM,KAAM,GAAM,EAAE,KAAO,CAAU,GAAK,KAE1D,GAAI,EAAS,CACX,IAAM,EAAK,EAAc,EAAI,CAAO,EACpC,GAAI,EAAI,CACN,EAAQ,QAAU,CAAE,KAAM,SAAU,OAAQ,EAAQ,GAAI,MAAO,EAAG,MAAO,MAAO,EAAI,OAAQ,EAAQ,OAAO,EAAG,MAAO,EACrH,MACF,CACF,CAEA,GAAI,EAAS,CACX,IAAM,EAAK,EAAmB,EAAI,CAAO,EACzC,GAAI,EAAI,CACN,IAAM,EAAI,EAAQ,OAAO,EAAG,OACtB,EAAI,EAAQ,QAAQ,EAAG,MAAQ,GAAK,EAAQ,OAAO,QACnD,EAAQ,GAAO,CAAE,EAAG,EAAE,GAAK,EAAE,EAAI,EAAE,GAAK,EAAG,EAAG,EAAG,EAAE,GAAK,EAAE,EAAI,EAAE,GAAK,EAAG,CAAE,CAAC,EAC3E,EAAgB,GAAa,EAAQ,GAAI,EAAG,MAAO,EAAG,EAAG,CAAK,EACpE,EAAQ,QAAU,CAAE,KAAM,SAAU,OAAQ,EAAQ,GAAI,MAAO,EAAe,MAAO,EAAI,OAAQ,CAAM,EACvG,MACF,CACF,CAEA,IAAM,EAAc,EAAM,KAAM,GAAM,GAAe,EAAI,EAAE,MAAM,CAAC,EAClE,GAAI,EAAa,CACf,EAAc,EAAY,EAAE,EAC5B,EAAQ,QAAU,CAAE,KAAM,OAAQ,OAAQ,EAAY,GAAI,MAAO,EAAI,WAAY,CAAC,GAAG,EAAY,MAAM,CAAE,EACzG,MACF,CAEA,EAAc,IAAI,CACpB,CA9CA,CA+CF,CAEA,SAAS,GAAkB,EAA8B,CACvD,GAAI,IAAS,UAAY,EAAuB,OAChD,IAAM,EAAK,EAAM,CAAC,EAClB,GAAI,CAAC,EAAI,OACT,IAAM,EAAU,EAAM,KAAM,GAAM,EAAE,KAAO,CAAU,EACrD,GAAI,CAAC,EAAS,OACd,IAAM,EAAK,EAAc,EAAI,CAAO,EAChC,IAAM,EAAE,eAAe,EAAG,EAAa,EAAQ,GAAI,EAAG,KAAK,EACjE,CAEA,SAAS,EAAgB,EAA8B,CACrD,GAAI,EAAW,QAAS,CACtB,GAAM,CAAE,cAAa,UAAS,SAAQ,UAAW,EAAW,QAC5D,EAAO,CACL,EAAG,EAAQ,GAAK,EAAE,QAAU,EAAY,GAAK,EAC7C,EAAG,EAAQ,GAAK,EAAE,QAAU,EAAY,GAAK,CAC/C,CAAC,EACD,MACF,CAEA,IAAM,EAAK,EAAM,CAAC,EACb,KAEL,IAAI,EAAY,SAAW,EAAuB,CAChD,IAAM,EAAW,EAAM,KAAM,GAAM,EAAE,KAAO,CAAqB,EACjE,GAAI,EAAU,CACZ,IAAM,EAAO,GAAY,EAAI,CAAC,CAAQ,CAAC,EACnC,GACF,EAAU,GAAS,EAAK,IAAK,GAC3B,EAAE,KAAO,EAAY,QAAU,CAAE,GAAG,EAAG,UAAW,EAAK,UAAW,EAAG,EAAK,CAAE,EAAI,CAClF,CAAC,CAEL,CACA,MACF,CAEA,GAAI,IAAS,QAAU,EAAW,CAAE,EAAc,CAAE,EAAG,MAAQ,CAC/D,GAAI,IAAS,UAAW,CAAE,EAAc,CAAE,EAAG,MAAQ,CAErD,GAAI,IAAS,UAAY,CAAC,GAAyB,EAAQ,QAAS,CAClE,IAAM,EAAO,EAAQ,QACrB,GAAI,EAAK,OAAS,SAAU,CAC1B,IAAM,EAAK,EAAG,EAAI,EAAK,MAAM,EACvB,EAAK,EAAG,EAAI,EAAK,MAAM,EACvB,EAAQ,GAAO,CAAE,EAAG,EAAK,OAAO,EAAI,EAAI,EAAG,EAAK,OAAO,EAAI,CAAG,CAAC,EACrE,EAAU,GACR,EAAK,IAAK,GAAM,CACd,GAAI,EAAE,KAAO,EAAK,OAAQ,OAAO,EACjC,IAAM,EAAM,CAAC,GAAG,EAAE,MAAM,EAExB,MADA,GAAI,EAAK,OAAS,EACX,CAAE,GAAG,EAAG,OAAQ,CAAI,CAC7B,CAAC,CACH,CACF,KAAO,CACL,IAAM,EAAK,EAAG,EAAI,EAAK,MAAM,EACvB,EAAK,EAAG,EAAI,EAAK,MAAM,EAC7B,EAAU,GACR,EAAK,IAAK,GACR,EAAE,KAAO,EAAK,OACV,CAAE,GAAG,EAAG,OAAQ,EAAK,WAAW,IAAK,IAAO,CAAE,EAAG,EAAE,EAAI,EAAI,EAAG,EAAE,EAAI,CAAG,EAAE,CAAE,EAC3E,CACN,CACF,CACF,CACF,CA9BA,CA+BF,CAEA,SAAS,GAAc,EAA8B,CACnD,GAAI,EAAW,QAAS,CAAE,EAAW,QAAU,KAAM,MAAQ,CAE7D,IAAM,EAAK,EAAM,CAAC,EACb,KAEL,IAAI,IAAS,QAAU,EAAW,CAChC,IAAM,EAAI,KAAK,IAAI,EAAU,EAAG,EAAG,CAAC,EAC9B,EAAI,KAAK,IAAI,EAAU,EAAG,EAAG,CAAC,EAC9B,EAAI,KAAK,IAAI,EAAG,EAAI,EAAU,CAAC,EAC/B,EAAI,KAAK,IAAI,EAAG,EAAI,EAAU,CAAC,EACjC,GAAA,IAAiB,GAAA,IACnB,EAAU,GAAS,CACjB,GAAG,EACH,CAAE,GAAI,GAAO,MAAM,EAAG,KAAM,QAAQ,EAAK,OAAS,IAAK,OAAQ,GAAa,EAAG,EAAG,EAAG,CAAC,CAAE,CAC1F,CAAC,EAEH,EAAa,IAAI,EAAG,EAAc,IAAI,CACxC,CAEA,EAAY,QAAU,KACtB,EAAQ,QAAU,IAHlB,CAIF,CAIA,SAAS,GAAmB,EAAe,CACrC,GAAY,EAAU,GAAS,EAAK,IAAK,GAAO,EAAE,KAAO,EAAa,CAAE,GAAG,EAAG,KAAM,CAAM,EAAI,CAAE,CAAC,CACvG,CAEA,SAAS,GAAsB,EAAgB,EAAe,CAC5D,IAAM,EAAI,WAAW,CAAK,EACtB,MAAM,CAAC,GAAK,GAAK,GACrB,EAAU,GAAS,EAAK,IAAK,GAAO,EAAE,KAAO,EAAS,CAAE,GAAG,EAAG,MAAO,CAAE,EAAI,CAAE,CAAC,CAChF,CAEA,SAAS,GAAmB,CACrB,IACL,EAAU,GAAS,EAAK,OAAQ,GAAM,EAAE,KAAO,CAAU,CAAC,EAC1D,EAAU,GAAS,EAAK,OAAQ,GAAM,EAAE,SAAW,CAAU,CAAC,EAC9D,EAAyB,IAAI,EAC7B,EAAc,IAAI,EACpB,CAEA,SAAS,EAAiB,EAAgB,CACxC,EAAU,GAAS,EAAK,OAAQ,GAAM,EAAE,KAAO,CAAM,CAAC,CACxD,CAEA,SAAS,EAAW,EAAS,CAC3B,EAAQ,CAAC,EACT,EAAyB,IAAI,EAC7B,EAAc,CAAC,CAAC,EAAG,EAAc,IAAI,EACrC,EAAa,IAAI,EAAG,EAAc,IAAI,CACxC,CAEA,SAAS,EAAmB,EAAwC,CAClE,IAAM,EAAO,EAAE,OAAO,QAAQ,GAC9B,GAAI,CAAC,EAAM,OACX,EAAE,OAAO,MAAQ,GACjB,IAAM,EAAS,IAAI,WACnB,EAAO,OAAU,GAAO,CACtB,IAAM,EAAO,EAAG,QAAQ,OACxB,GAAI,OAAO,GAAS,SAAU,OAC9B,IAAM,EAAS,GAAc,CAAI,EAC7B,EAAO,SAAW,IAEtB,EADiB,EAAO,IAAK,IAAO,CAAE,GAAG,EAAG,GAAI,GAAO,MAAM,CAAE,EACtD,CAAQ,EACjB,EAAS,CAAC,CAAC,EACX,EAAc,IAAI,EAClB,EAAyB,IAAI,EAC7B,EAAQ,CAAC,EACT,EAAO,CAAE,EAAG,EAAG,EAAG,CAAE,CAAC,EACvB,EACA,EAAO,WAAW,CAAI,CACxB,CAIA,IAAM,EACJ,IAAS,QAAU,GAAa,EAC5B,CACE,EAAG,KAAK,IAAI,EAAU,EAAG,EAAW,CAAC,EACrC,EAAG,KAAK,IAAI,EAAU,EAAG,EAAW,CAAC,EACrC,EAAG,KAAK,IAAI,EAAW,EAAI,EAAU,CAAC,EACtC,EAAG,KAAK,IAAI,EAAW,EAAI,EAAU,CAAC,CACxC,EACA,KAEA,GAAe,EAAc,EAAM,KAAM,GAAM,EAAE,KAAO,CAAU,GAAK,KAAQ,KAC/E,GAAc,EAAyB,EAAM,KAAM,GAAM,EAAE,KAAO,CAAqB,GAAK,KAAQ,KACpG,GAAmB,EAAwB,EAAM,OAAQ,GAAM,EAAE,SAAW,CAAqB,EAAI,CAAC,EAEtG,EAAQ,CACZ,CAAE,EAAG,SAAkB,KAAM,EAAA,cAAe,MAAO,eAAgB,EACnE,CAAE,EAAG,OAAgB,KAAM,EAAA,SAAU,MAAO,gBAAiB,EAC7D,CAAE,EAAG,UAAmB,KAAM,EAAA,cAAe,MAAO,cAAe,CACrE,EAEM,GAAA,IAAgB,EAChB,GAAA,IAAgB,EAEhB,GAAe,EAAwB,EAAO,qBAAuB,IAAS,SAAW,EAAO,uBAAyB,IAAA,GAI/H,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,EAAO,WAAY,CAAS,WAA/C,EAEE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAO,2BAAvB,CACG,EAAM,KAAK,CAAE,IAAG,OAAM,YACrB,EAAA,EAAA,KAAC,SAAD,CAEE,MAAO,EACP,WAAA,EAAA,EAAA,SAAc,EAAO,qBAAsB,IAAM,GAAQ,CAAC,GAAyB,EAAO,0BAA0B,EACpH,YAAe,EAAW,CAAC,YAE3B,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAuB,MAAO,CAAA,CACxB,EAND,CAMC,CACT,GACD,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAO,oBAAuB,CAAA,GAC9C,EAAA,EAAA,KAAC,SAAD,CAAQ,MAAM,cAAc,UAAW,EAAO,qBAAsB,YAAe,EAAO,EAAS,EAAG,SAAU,GAAQ,aACtH,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,qBAAwB,CAAA,CACzC,CAAA,GACR,EAAA,EAAA,MAAC,SAAD,CACE,MAAO,oBAAoB,KAAK,MAAM,EAAO,GAAG,EAAE,GAClD,UAAW,EAAO,2BAClB,YAAe,CAAE,EAAQ,CAAC,EAAG,EAAO,CAAE,EAAG,EAAG,EAAG,CAAE,CAAC,CAAG,WAHvD,CAKG,KAAK,MAAM,EAAO,GAAG,EAAE,GAClB,KACR,EAAA,EAAA,KAAC,SAAD,CAAQ,MAAM,eAAe,UAAW,EAAO,qBAAsB,YAAe,EAAO,EAAI,EAAS,EAAG,SAAU,GAAQ,aAC3H,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,sBAAyB,CAAA,CAC1C,CAAA,GACR,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAO,oBAAuB,CAAA,GAC9C,EAAA,EAAA,KAAC,SAAD,CACE,MAAM,aACN,UAAW,EAAO,qBAClB,YAAe,EAAU,SAAS,MAAM,YAExC,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,QAAW,CAAA,CAC5B,CAAA,GACR,EAAA,EAAA,KAAC,SAAD,CACE,MAAM,eACN,UAAW,EAAO,qBAClB,YAAe,GAAY,EAAO,CAAK,EACvC,SAAU,EAAM,SAAW,YAE3B,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,UAAa,CAAA,CAC9B,CAAA,GACR,EAAA,EAAA,KAAC,QAAD,CAAO,IAAK,EAAW,KAAK,OAAO,OAAO,qBAAqB,MAAO,CAAE,QAAS,MAAO,EAAG,SAAU,CAAqB,CAAA,CACvH,KAGL,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,EAAO,iBAAkB,EAAY,EACnD,QAAS,GAAG,EAAI,EAAE,GAAG,EAAI,EAAE,GAAG,GAAG,GAAG,KACpC,YAAa,EACb,YAAa,EACb,UAAW,GACX,cAAe,YAPjB,EASE,EAAA,EAAA,KAAC,OAAD,CAAA,UACE,EAAA,EAAA,KAAC,UAAD,CAAS,GAAG,UAAU,MAAA,EAAa,OAAA,EAAc,aAAa,2BAC5D,EAAA,EAAA,KAAC,OAAD,CAAM,EAAG,kBAA+B,KAAK,OAAO,UAAW,EAAO,QAAW,CAAA,CAC1E,CAAA,CACL,CAAA,GACN,EAAA,EAAA,KAAC,OAAD,CAAM,EAAG,EAAI,EAAG,EAAG,EAAI,EAAG,MAAO,GAAI,OAAQ,GAAI,KAAK,eAAiB,CAAA,EAGtE,EAAM,IAAK,GAAS,CACnB,IAAM,EAAM,EAAK,OACX,EAAQ,EAAI,KAAK,EAAG,IAAM,GAAG,IAAM,EAAI,IAAM,IAAI,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,GAAG,EAAI,KAC9E,EAAW,GAAkB,EAAK,EAAM,OAAQ,GAAM,EAAE,SAAW,EAAK,EAAE,CAAC,EAC3E,EAAI,GAAS,CAAG,EAChB,EAAa,IAAe,EAAK,GACjC,EAAY,IAA0B,EAAK,GACjD,OACE,EAAA,EAAA,MAAC,IAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,EAAG,EAAO,WAAA,EAAA,EAAA,SAAc,EAAO,UAAW,GAAc,IAAc,EAAO,gBAAgB,CAAI,CAAA,EACtG,EAAS,KAAK,EAAK,KAClB,EAAA,EAAA,KAAC,OAAD,CAAe,EAAG,EAAK,WAAA,EAAA,EAAA,SAAc,EAAO,YAAa,GAAc,IAAc,EAAO,kBAAkB,CAAI,EAAvG,CAAuG,CACnH,EACA,EAAK,OACJ,EAAA,EAAA,KAAC,OAAD,CAAM,EAAG,EAAE,EAAG,EAAG,EAAE,EAAG,UAAW,EAAO,SAAU,WAAW,SAAS,iBAAiB,kBACpF,EAAK,IACF,CAAA,CAEP,CAAA,EAVK,EAAK,EAUV,CAEP,CAAC,EAGA,EAAM,IAAK,GAAS,CACnB,IAAM,EAAO,EAAM,KAAM,GAAM,EAAE,KAAO,EAAK,MAAM,EACnD,GAAI,CAAC,EAAM,OAAO,KAClB,IAAM,EAAI,EAAK,OAAO,EAAK,WACrB,EAAI,EAAK,QAAQ,EAAK,UAAY,GAAK,EAAK,OAAO,QACnD,EAAK,GAAc,EAAG,EAAG,EAAK,EAAG,EAAK,KAAK,EAEjD,OADK,GAEH,EAAA,EAAA,KAAC,OAAD,CAEE,GAAI,EAAG,GAAG,EAAG,GAAI,EAAG,GAAG,EACvB,GAAI,EAAG,GAAG,EAAG,GAAI,EAAG,GAAG,EACvB,UAAW,EAAO,OACnB,EAJM,EAAK,EAIX,EAPa,IASlB,CAAC,EAGA,GAAyB,GAAiB,IAAK,GAAS,CACvD,IAAM,EAAO,EAAM,KAAM,GAAM,EAAE,KAAO,EAAK,MAAM,EACnD,GAAI,CAAC,EAAM,OAAO,KAClB,IAAM,EAAI,EAAK,OAAO,EAAK,WACrB,EAAI,EAAK,QAAQ,EAAK,UAAY,GAAK,EAAK,OAAO,QACnD,EAAK,GAAc,EAAG,EAAG,EAAK,EAAG,EAAK,KAAK,EACjD,GAAI,CAAC,EAAI,OAAO,KAChB,IAAM,EAAM,CAAE,GAAI,EAAG,GAAG,EAAI,EAAG,GAAG,GAAK,EAAG,GAAI,EAAG,GAAG,EAAI,EAAG,GAAG,GAAK,CAAE,EACrE,OACE,EAAA,EAAA,KAAC,SAAD,CAEE,GAAI,EAAI,EAAG,GAAI,EAAI,EAAG,EAAG,IACzB,UAAW,EAAO,WAClB,YAAc,GAAM,CACd,EAAE,SAAW,IACjB,EAAE,eAAe,EACjB,EAAE,gBAAgB,EAClB,EAAY,QAAU,EAAK,GAC7B,CACD,EATM,EAAK,EASX,CAEL,CAAC,EAGA,IAAS,UAAY,CAAC,GAAyB,IAC9C,GAAa,OAAO,KAAK,EAAG,KAC1B,EAAA,EAAA,KAAC,SAAD,CAAgB,GAAI,EAAE,EAAG,GAAI,EAAE,EAAG,EAAG,IAAK,UAAW,EAAO,YAAe,EAA9D,CAA8D,CAC5E,EAGF,IACC,EAAA,EAAA,KAAC,OAAD,CAAM,EAAG,EAAY,EAAG,EAAG,EAAY,EAAG,MAAO,EAAY,EAAG,OAAQ,EAAY,EAAG,UAAW,EAAO,OAAU,CAAA,EAIpH,IAAS,WAAa,EAAW,OAAS,IACzC,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,WAAD,CACE,OAAQ,CAAC,GAAG,EAAY,GAAc,EAAW,EAAW,OAAS,EAAE,EAAE,IAAK,GAAM,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,GAAG,EAC7G,UAAW,EAAO,OACnB,CAAA,EACA,EAAW,QAAU,IACpB,EAAA,EAAA,KAAC,SAAD,CAAQ,GAAI,EAAW,GAAG,EAAG,GAAI,EAAW,GAAG,EAAG,EAAA,EAAqB,EAAG,UAAW,EAAO,eAAkB,CAAA,EAE/G,EAAW,KAAK,EAAG,KAClB,EAAA,EAAA,KAAC,SAAD,CAAgB,GAAI,EAAE,EAAG,GAAI,EAAE,EAAG,EAAG,EAAG,UAAW,EAAO,UAAa,EAA1D,CAA0D,CACxE,CACD,CAAA,CAAA,CAED,IAGJ,IAAgB,CAAC,IAChB,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAO,wBAAvB,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAO,6BAAqB,MAAU,CAAA,GACvD,EAAA,EAAA,KAAC,QAAD,CACE,UAAW,EAAO,oBAClB,MAAO,GAAa,KACpB,SAAW,GAAM,GAAmB,EAAE,OAAO,KAAK,EAClD,YAAY,WACb,CAAA,GACD,EAAA,EAAA,MAAC,SAAD,CACE,UAAW,EAAO,uBAClB,YAAe,EAAyB,GAAa,EAAE,EACvD,MAAM,sBAHR,EAKE,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,UAAa,CAAA,GACpC,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAM,OAAQ,GAAM,EAAE,SAAW,GAAa,EAAE,EAAE,MAAa,CAAA,CAChE,KACR,EAAA,EAAA,KAAC,SAAD,CAAQ,UAAW,EAAO,qBAAsB,QAAS,EAAkB,MAAM,wBAC/E,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,OAAU,CAAA,CAC3B,CAAA,CACL,IAIN,GAAyB,KACxB,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAO,6BAAvB,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAO,mCAAvB,EACE,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,WAAY,UAAW,EAAO,uBAA0B,CAAA,GAC/E,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAO,kCACrB,GAAY,KAAO,WAAW,GAAY,OAAS,OAChD,CAAA,GACN,EAAA,EAAA,MAAC,SAAD,CACE,UAAW,EAAO,wBAClB,YAAe,EAAyB,IAAI,EAC5C,MAAM,sBAHR,EAKE,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,OAAU,CAAA,EAAC,MAE5B,GACL,KACL,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAO,iCAAvB,CACG,GAAiB,SAAW,IAC3B,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAO,kCAA0B,+BAAmC,CAAA,EAEtF,GAAiB,KAAK,EAAM,KAC3B,EAAA,EAAA,MAAC,MAAD,CAAmB,UAAW,EAAO,iCAArC,EACE,EAAA,EAAA,MAAC,OAAD,CAAM,UAAW,EAAO,kCAAxB,CAAkD,QAAM,EAAI,CAAQ,KACpE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAO,uCAA+B,OAAW,CAAA,GAClE,EAAA,EAAA,KAAC,QAAD,CACE,UAAW,EAAO,oBAClB,KAAK,SACL,IAAK,EACL,MAAO,EAAK,MACZ,SAAW,GAAM,GAAsB,EAAK,GAAI,EAAE,OAAO,KAAK,CAC/D,CAAA,GACD,EAAA,EAAA,KAAC,SAAD,CACE,UAAW,EAAO,qBAClB,YAAe,EAAiB,EAAK,EAAE,EACvC,MAAM,wBAEN,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,OAAU,CAAA,CAC3B,CAAA,CACL,GAjBK,EAAK,EAiBV,CACN,CACE,GACF,KAGP,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAO,wBACpB,EACG,4FACA,GAAG,GAAW,GAAM,oDACrB,CAAA,CACF,GAET,irBExtBA,SAAS,GAAW,CAAE,OAAO,CAAC,GAAsB,CAClD,IAAM,GAAA,EAAA,EAAA,QAAuC,IAAI,EAE3C,EAAG,IAAA,EAAA,EAAA,UAA6C,IAAI,EACpD,CAAC,EAAgB,IAAA,EAAA,EAAA,UAA8B,CAAC,EAChD,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,EAAI,GAE/C,EAAA,EAAA,eAAgB,CACd,IAAM,EAAkB,IAAI,gBAE5B,EAAkB,IAAI,EAEtB,IAAM,EAAY,EAAc,QAmBhC,OAjBI,EAAiB,EAAK,OAAS,GAAK,CAAC,GACvC,EAAa,EAAK,MACL,EAAgB,MAAM,IAMrC,EADwB,iBAA0B,cAClD,EAAM,QAAS,GAAY,CACzB,EAAQ,iBACN,YACM,EAAc,EAAQ,GAAI,CAAS,EACzC,CAAE,OAAQ,EAAgB,MAAO,CACnC,CACF,CAAC,EACD,EAAa,EAAK,MAEL,EAAgB,MAAM,EAErC,EAAG,CAAC,EAAM,CAAc,CAAC,EAEzB,SAAS,EAAc,EAAgB,EAAoB,CACzD,IAAM,EAAa,EAAO,UAAU,CAAC,EAErC,EAAmB,GAAuB,CACxC,GAAI,IAAe,EAAoB,OAAO,EAE9C,GAAM,CAAC,GAAO,EAAU,iBAA0B,YAAY,EAC9D,GAAK,aAAa,OAAQ,IAAI,GAAQ,EAEtC,GAAM,CAAC,GAAQ,EAAU,iBAA0B,QAAQ,EAAO,GAAG,EAErE,GAAI,EAAoB,CACtB,GAAM,CAAC,GAAY,EAAU,iBAA0B,YAAY,EAAmB,GAAG,EACzF,GAAI,EAAU,CACZ,EAAS,UAAU,OAAO,GAAO,mBAAoB,GAAO,cAAc,EAC1E,GAAM,CAAC,GAAkB,EAAS,iBAA0B,mBAAmB,EAC3E,GAAgB,EAAe,UAAU,OAAO,GAAO,cAAc,CAC3E,CACF,CAEA,GAAI,EAAM,CACR,EAAK,UAAU,IAAI,GAAO,kBAAkB,EAC5C,GAAM,CAAC,GAAc,EAAK,iBAA0B,mBAAmB,GACtE,GAAc,GAAM,UAAU,IAAI,GAAO,cAAc,CAC1D,CAEA,OAAO,CACT,CAAC,CACH,CAEA,SAAS,EAAkB,EAAgB,CACzC,EAAmB,GAAS,CAC1B,IAAM,EAAO,EAAO,EAEpB,OADI,EAAO,GAAK,EAAO,EAAK,OAAS,EAAU,EACxC,CACT,CAAC,CACH,CAEA,IAAM,EAAU,EAAK,IAAiB,MAAQ,KAE9C,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,WAAY,IAAK,WAAxC,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAW,GAAO,0BAAmB,EAAK,IAAiB,OAAS,EAAO,CAAA,GAC/E,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,oBAAqB,GAAa,GAAO,0BAA0B,WAEvF,CACE,EAJE,CAIF,EACJ,EAAK,OAAS,IACb,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,2BAAvB,EACE,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,cAAU,YAAe,EAAkB,EAAE,CAAI,CAAA,GACxE,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,YAAY,CAAA,GACnC,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,eAAW,YAAe,EAAkB,CAAC,CAAI,CAAA,CACrE,GAEJ,GAET,sDE/FA,SAAS,GAAkB,CACzB,YAAY,IAAA,GACZ,WAAW,IAAA,IACgB,CAC3B,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,kBAAmB,CAAS,EACnD,UACE,CAAA,CAET,CCjBA,IAAA,GAAe,GCGH,GAAL,SAAA,EAAA,OACL,GAAA,MAAA,QACA,EAAA,OAAA,SACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,wyCEGM,GAAmD,EACtD,GAAkB,OAAQ,GAAO,wBACjC,GAAkB,QAAS,GAAO,yBAClC,GAAkB,OAAQ,GAAO,sBACpC,EAEA,SAAS,GAAc,EAAyC,CAC9D,GAAM,CACJ,QACA,WACA,OACA,YACA,OACA,SACA,UACA,QAAQ,EACR,OAAO,GAAkB,OACzB,UAAU,GACV,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,gBAAiB,CAAK,EAEzC,EACJ,OAAO,GAAc,UAAY,EAAU,WAAW,MAAM,EAAI,EAAY,IAAA,GACxE,EAAe,GAAa,MAAQ,IAAc,GAClD,EAAa,GAAgB,GAAQ,KAErC,EAAU,IAAI,IAEpB,OACE,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SACE,GAAO,cACP,GAAc,GACd,EACA,GAAY,IACd,EACA,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,WARzC,CAUG,IACC,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,qBAAsB,GAAY,OAAO,EAC9D,MAAO,CACL,GAAI,EAAe,CAAE,gBAAiB,OAAO,EAAa,EAAG,EAAI,CAAC,EAClE,GAAG,GAAY,OACjB,WAEC,EACG,CAAC,GAAgB,EACjB,IAAQ,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAuB,MAAO,CAAA,CACvC,CAAA,GAGP,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,oBAAqB,GAAY,MAAM,EAC5D,MAAO,GAAY,gBAFrB,EAIE,EAAA,EAAA,KAAC,EAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,mBAAoB,GAAY,KAAK,EAC1D,MAAO,GAAY,eAElB,CACM,CAAA,EACR,GAAY,MAAQ,IAAa,KAChC,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,sBAAuB,GAAY,QAAQ,EAChE,MAAO,GAAY,kBAElB,CACE,CAAA,CAEJ,KAEL,EAAA,EAAA,MAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,sBAAuB,GAAY,QAAQ,EAChE,MAAO,GAAY,kBAFrB,EAIE,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,kBAAmB,GAAY,IAAI,EAAG,MAAO,GAAY,cAChF,CACE,CAAA,GAEL,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,oBAAqB,GAAY,MAAM,EAC5D,MAAO,GAAY,gBAElB,CACE,CAAA,GAEL,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,qBAAsB,GAAY,OAAO,EAC9D,MAAO,GAAY,iBAElB,MAAM,QAAQ,CAAO,EACjB,EAAkC,KAAK,EAAQ,KAC9C,EAAA,EAAA,KAAC,EAAD,CAEE,MAAO,EAAO,MACd,QACE,EAAO,QACF,GAAwC,CACvC,EAAE,gBAAgB,EAClB,EAAO,UAAU,CAAC,CACpB,EACA,IAAA,GAEN,KAAM,EAAO,IACd,EAXM,CAWN,CACF,EACA,CACF,CAAA,CACF,GACF,IACJ,IAAW,EAAA,EAAA,KAAC,GAAD,CAAS,UAAW,GAAO,oBAAuB,CAAA,CAC9D,CAAA,CAAA,CAEN,CCjIA,IAAY,GAAL,SAAA,EAAA,OACL,GAAA,KAAA,OACA,EAAA,OAAA,SACA,EAAA,YAAA,eACF,EAAA,CAAA,CAAA,EAEY,GAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,MAAA,QACA,EAAA,KAAA,QACF,EAAA,CAAA,CAAA,qwBELM,GAAoD,EACvD,GAAgB,MAAO,GAAO,cAC9B,GAAgB,QAAS,GAAO,gBAChC,GAAgB,aAAc,GAAO,mBACxC,EAEM,GAAoE,EACvE,GAAkB,SAAU,GAAO,0BACnC,GAAkB,OAAQ,GAAO,wBACjC,GAAkB,MAAO,IAAA,EAC5B,EAEA,SAAS,GAAS,EAAoC,CACpD,GAAM,CACN,UAAU,GAAgB,KAC1B,YAAY,GAAkB,QAC9B,QAAQ,EACR,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,WAAY,CAAK,EACpC,EAAe,GAAiB,GAChC,EAAiB,GAAmB,GAY1C,OAVI,IAAY,GAAgB,MAAQ,GAAS,GAE7C,EAAA,EAAA,KAAC,OAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,GAAO,SAAU,EAAc,EAAgB,CAAS,EAC/D,OACR,CAAA,GAKH,EAAA,EAAA,KAAC,OAAD,CAAM,GAAI,EAAM,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,CAAS,EAAU,iBACpE,MAAM,KAAK,CAAE,OAAQ,CAAM,GAAI,EAAG,KACjC,EAAA,EAAA,KAAC,OAAD,CAEE,WAAA,EAAA,EAAA,SACE,GAAO,SACP,EACA,EACA,IAAU,EAAQ,GAAK,GAAO,iBAC9B,GAAY,IACd,EACA,MAAO,GAAY,IACpB,EATM,CASN,CACF,CACG,CAAA,CAEV,0tBEvDA,SAAS,GAAW,EAAsB,CACxC,IAAM,EAAI,OAAO,CAAI,EACf,EAAM,EAAE,QAAQ,GAAG,EACzB,OAAO,IAAQ,GAAK,EAAI,EAAE,OAAS,EAAM,CAC3C,CAEA,SAAwB,GAAO,CAC7B,QACA,eACA,WACA,cACA,MAAM,EACN,MAAM,IACN,OAAO,EACP,WAAW,GACX,QACA,YAAY,GACZ,cACA,OAAO,OACP,WAAW,EACX,YACA,QACA,aACA,OAAQ,EACR,aAAc,EACd,GAAG,GACyB,CAC5B,IAAM,GAAA,EAAA,EAAA,QAAkC,IAAI,EACtC,GAAA,EAAA,EAAA,QAAiC,IAAI,EACrC,GAAA,EAAA,EAAA,QAAqB,EAAK,EAC1B,CAAC,EAAU,IAAA,EAAA,EAAA,UAAwB,EAAK,EAExC,EAAe,IAAU,IAAA,GACzB,CAAC,EAAU,IAAA,EAAA,EAAA,UAAgC,GAAgB,CAAG,EAE9D,EAAW,GAAW,CAAI,EAEhC,SAAS,EAAM,EAAmB,CAChC,OAAO,KAAK,IAAI,EAAK,KAAK,IAAI,EAAK,CAAC,CAAC,CACvC,CAEA,SAAS,EAAK,EAAmB,CAC/B,IAAM,EAAU,KAAK,OAAO,EAAI,GAAO,CAAI,EAAI,EAAO,EACtD,OAAO,OAAO,EAAM,CAAO,EAAE,QAAQ,CAAQ,CAAC,CAChD,CAEA,IAAM,EAAU,EAAM,EAAgB,EAAmB,CAAQ,EAI3D,GAAA,EAAA,EAAA,QAAoB,CAAO,GACjC,EAAA,EAAA,eAAgB,CACd,EAAW,QAAU,CACvB,EAAG,CAAC,CAAO,CAAC,EAGZ,IAAM,EAAU,IADC,EAAM,GAAO,EAAU,IAAQ,EAAM,GAAO,GAC/B,IAAI,GAElC,SAAS,EAAO,EAAc,EAAgB,CAC5C,IAAM,EAAU,EAAK,CAAI,EACrB,IAAY,EAAW,UACzB,EAAW,QAAU,EAChB,GAAc,EAAY,CAAO,EACtC,IAAW,CAAO,GAEhB,GAAO,IAAc,CAAO,CAClC,CAEA,SAAS,EAAiB,EAAyB,CACjD,IAAM,EAAQ,EAAS,QACvB,GAAI,CAAC,EAAO,OAAO,EAAW,QAC9B,IAAM,EAAO,EAAM,sBAAsB,EACnC,EAAQ,EAAK,OAAS,EAAU,EAAK,MAAQ,EAAK,MAAQ,EAChE,OAAO,EAAM,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,CAAK,CAAC,GAAK,EAAM,EACxD,CAEA,SAAS,EAAkB,EAAuC,CAC5D,IACJ,EAAE,eAAe,EACjB,EAAQ,SAAS,MAAM,EACvB,EAAQ,SAAS,oBAAoB,EAAE,SAAS,EAChD,EAAY,QAAU,GACtB,EAAY,EAAI,EAChB,EAAO,EAAiB,EAAE,OAAO,EAAG,EAAK,EAC3C,CAEA,SAAS,GAAkB,EAAuC,CAC3D,EAAY,SACjB,EAAO,EAAiB,EAAE,OAAO,EAAG,EAAK,CAC3C,CAEA,SAAS,EAAgB,EAAuC,CACzD,EAAY,UACjB,EAAY,QAAU,GACtB,EAAY,EAAK,EACjB,EAAQ,SAAS,wBAAwB,EAAE,SAAS,EACpD,IAAc,EAAW,OAAO,EAClC,CAEA,SAAS,EAAc,EAAwC,CAC7D,GAAI,EAAU,OACd,IAAM,EAAO,EAAO,GAChB,EAAsB,KAC1B,OAAQ,EAAE,IAAV,CACE,IAAK,aACL,IAAK,UACH,EAAO,EAAU,EACjB,MACF,IAAK,YACL,IAAK,YACH,EAAO,EAAU,EACjB,MACF,IAAK,SACH,EAAO,EAAU,EACjB,MACF,IAAK,WACH,EAAO,EAAU,EACjB,MACF,IAAK,OACH,EAAO,EACP,MACF,IAAK,MACH,EAAO,EACP,MACF,QACE,MACJ,CACA,EAAE,eAAe,EACjB,EAAO,EAAM,EAAI,CACnB,CAEA,IAAM,GAAY,EAAc,EAAY,CAAO,EAAI,EACjD,EAAgB,CAAC,CAAC,GAAO,KAAM,GAAM,EAAE,OAAS,IAAI,EAE1D,OACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACJ,IAAK,EACL,KAAK,SACL,aAAY,EACZ,gBAAe,EACf,gBAAe,EACf,gBAAe,EACf,iBAAgB,OAAO,IAAc,UAAY,OAAO,IAAc,SAAW,OAAO,EAAS,EAAI,IAAA,GACrG,mBAAiB,aACjB,gBAAe,GAAY,IAAA,GAC3B,SAAU,EAAW,GAAK,EAC1B,WAAA,EAAA,EAAA,SACE,GAAO,OACP,GAAY,GAAO,eACnB,GAAY,GAAO,eACnB,GAAiB,GAAO,oBACxB,EACA,GAAY,IACd,EACA,MAAO,CAAE,sBAAuB,EAAM,GAAG,EAAO,GAAG,GAAY,IAAK,EACpE,cAAe,EACf,cAAe,GACf,YAAa,EACb,UAAW,YAEX,EAAA,EAAA,MAAC,MAAD,CAAK,IAAK,EAAU,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,KAAK,EAAG,MAAO,GAAY,eAA7F,EACE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,KAAK,EACnD,MAAO,CAAE,MAAO,EAAS,GAAG,GAAY,KAAM,CAC/C,CAAA,EACA,GAAO,IAAK,GAAS,CAEpB,IAAM,EAAO,IADQ,EAAM,GAAO,EAAM,EAAK,KAAK,EAAI,IAAQ,EAAM,GAAO,GAC5C,IAAI,GACnC,OACE,EAAA,EAAA,MAAC,EAAA,QAAM,SAAP,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,OAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,WAAY,GAAY,IAAI,EACjD,MAAO,CAAE,OAAM,GAAG,GAAY,IAAK,CACpC,CAAA,EACA,EAAK,OAAS,OACb,EAAA,EAAA,KAAC,OAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,SAAS,EAC3D,MAAO,CAAE,OAAM,GAAG,GAAY,SAAU,WAEvC,EAAK,KACF,CAAA,CAEM,CAAA,EAbK,EAAK,KAaV,CAEpB,CAAC,GACD,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,KAAK,EACnD,MAAO,CAAE,KAAM,EAAS,GAAG,GAAY,KAAM,WAE5C,IACC,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,KAAK,EAAG,MAAO,GAAY,eAC5E,EACG,CAAA,CAEL,CAAA,CACF,GACF,CAAA,CAET,ggFExMY,GAAL,SAAA,EAAA,OACL,GAAA,WAAA,aACA,EAAA,SAAA,YACF,EAAA,CAAA,CAAA,EAGY,GAAL,SAAA,EAAA,OAEL,GAAA,QAAA,UAEA,EAAA,SAAA,WAEA,EAAA,KAAA,QACF,EAAA,CAAA,CAAA,EAMY,GAAL,SAAA,EAAA,OAEL,GAAA,KAAA,OAEA,EAAA,WAAA,aAEA,EAAA,UAAA,aACF,EAAA,CAAA,CAAA,EAOY,GAAL,SAAA,EAAA,OACL,GAAA,IAAA,MACA,EAAA,OAAA,SACA,EAAA,KAAA,OACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,EC9BM,GAAgD,EACnD,GAAiB,SAAU,EAAO,gBAClC,GAAiB,UAAW,EAAO,iBACnC,GAAiB,MAAO,EAAO,WAClC,EAEM,GAAyD,EAC5D,GAAsB,KAAM,EAAO,iBACnC,GAAsB,QAAS,EAAO,oBACtC,GAAsB,MAAO,EAAO,kBACpC,GAAsB,OAAQ,EAAO,iBACxC,EAEA,SAAS,IAAY,CACnB,OACE,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,EAAO,iBAClB,eAAe,QACf,cAAc,QACd,MAAM,6BACN,QAAQ,kBACR,OAAO,OACP,MAAM,iBAEN,EAAA,EAAA,KAAC,OAAD,CAAM,EAAE,qBAAqB,YAAY,MAAM,KAAK,MAAQ,CAAA,CACzD,CAAA,CAET,CAEA,SAAS,GAAS,CAChB,OACA,YACA,QACA,YAMC,CACD,IAAM,GAAA,EAAA,EAAA,QAAkC,IAAI,EACtC,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAqC,IAAI,EAUxD,OARA,EAAA,EAAA,eAAgB,CACd,IAAM,EAAK,EAAS,QACpB,GAAI,CAAC,EAAI,OACT,IAAM,EAAW,IAAI,mBAAqB,EAAU,EAAG,YAAY,CAAC,EAEpE,OADA,EAAS,QAAQ,CAAE,MACN,EAAS,WAAW,CACnC,EAAG,CAAC,CAAC,GAGH,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,eAAgB,CAAS,EAC9C,MAAO,CAAE,GAAG,EAAO,OAAQ,EAAQ,GAAU,OAAU,CAAE,EACzD,cAAa,CAAC,YAEd,EAAA,EAAA,KAAC,MAAD,CAAK,IAAK,EAAU,UAAW,EAAO,oBACnC,UACE,CAAA,CACF,CAAA,CAET,CAEA,SAAS,GACP,EACA,EACuB,CACvB,IAAM,EAAiB,CAAC,GAAsB,KAAM,GAAsB,KAAK,EAI/E,OAHI,EACK,GAAa,EAAe,SAAS,CAAS,EAAI,EAAY,GAAsB,MAEtF,GAAa,CAAC,EAAe,SAAS,CAAS,EAAI,EAAY,GAAsB,MAC9F,CAEA,SAAwB,GAAQ,CAC9B,QAAQ,CAAC,EACT,cAAc,EACd,YAAY,GAAiB,WAC7B,gBAAgB,KAChB,YAAY,GACZ,aAAa,GACb,YAAY,GAAiB,QAC7B,WAAW,GAAgB,KAC3B,iBACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACY,CACf,IAAM,EAAa,IAAc,GAAiB,SAC5C,EAAY,GAAiB,EAAgB,CAAU,EAE7D,OACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SACE,EAAO,QACP,GAAY,GACZ,GAAgB,GAChB,EAAG,EAAO,iBAAkB,CAAW,EACvC,GAAY,KACZ,CACF,EACA,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,WAEtC,EAAM,KAAK,EAAmB,IAAkB,CAC/C,IAAM,EAAS,EAAQ,EACjB,EAAW,GAAS,EACpB,EAAW,CAAC,CAAC,EAAK,MAGlB,EACJ,CAAC,CAAC,GAAiB,CAAC,EAAK,WAAa,EAAY,IAAU,EAAc,GAEtE,GAAA,EAAA,EAAA,SACJ,EAAO,aACP,EAAG,EAAO,oBAAqB,CAAS,EACxC,EAAG,EAAO,kBAAmB,GAAU,CAAC,CAAS,EACjD,EAAG,EAAO,mBAAoB,CAAS,EACvC,EAAG,EAAO,sBAAuB,EAAK,QAAS,EAC/C,EAAG,EAAO,kBAAmB,CAAY,EACzC,GAAY,KACd,EAEM,EAAgB,EAAK,MACzB,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,EAAK,KACX,UAAW,GAAY,KACvB,MAAO,GAAY,IACpB,CAAA,EACC,GAAU,CAAC,GACb,EAAA,EAAA,KAAC,GAAD,CAAY,CAAA,EAEZ,EAAQ,EAGJ,GACJ,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SACE,EAAO,mBACP,EAAG,EAAO,wBAAyB,GAAU,CAAC,CAAS,EACvD,GAAY,WACd,EACA,MAAO,GAAY,qBAElB,CACE,CAAA,EAGD,EACJ,EAAK,WAAa,GAAO,WAAa,EAAK,WAAa,GAAwB,KAAhB,EAAK,SAEjE,EAAS,CAAC,IACd,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAO,4BAAvB,EACE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,kBAAmB,GAAY,UAAU,EAC9D,MAAO,GAAY,oBAElB,EAAK,KACH,CAAA,EACJ,EAAK,aAAe,OACnB,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,mBAAoB,GAAY,WAAW,EAChE,MAAO,GAAY,qBAElB,EAAK,WACH,CAAA,EAEN,GAAgB,OACf,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,gBAAiB,GAAY,QAAQ,EAC1D,MAAO,GAAY,kBAElB,CACE,CAAA,CAEJ,IAGD,EAAyD,EAC3D,CACE,KAAM,SACN,SAAU,EACV,YAAe,IAAgB,CAAK,EACpC,UAAY,GAAM,EACZ,EAAE,MAAQ,SAAW,EAAE,MAAQ,OACjC,EAAE,eAAe,EACjB,IAAgB,CAAK,EAEzB,CACF,EACA,CAAC,EAEC,EAAc,IAClB,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,EACX,MAAO,GAAY,MACnB,eAAc,IAAU,EAAc,OAAS,IAAA,GAC/C,eAAc,GAAY,IAAA,GAC1B,GAAI,WAEH,CACE,CAAA,EAGD,EAAY,EAAQ,EAAM,OAAS,IACvC,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SACE,EAAO,iBACP,EAAG,EAAO,wBAAyB,CAAO,EAC1C,GAAY,SACd,EACA,MAAO,GAAY,SACpB,CAAA,EAGH,GAAI,EAAY,CACd,IAAM,EAAU,IAAU,EACpB,EAAS,IAAU,EAAM,OAAS,EAClC,EACJ,IAAa,GAAgB,KACzB,GACA,IAAa,GAAgB,WAC3B,IAAU,EACV,CAAC,EAEH,EAAe,GAA8B,CACjD,IAAM,EAAS,IAAY,OAAS,EAAU,EACxC,EAAS,IAAY,OAAS,EAAW,EAC/C,OACE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,mBAAoB,EACtC,EAAO,mBAAoB,CAAC,GAAU,GACtC,EAAO,mBAAoB,CAC9B,CAAC,CACF,CAAA,CAEL,EAEM,GACJ,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAO,2BAAvB,CACG,EAAY,MAAM,EAClB,EACA,EAAY,OAAO,CACjB,IAGP,OACE,EAAA,EAAA,MAAC,MAAD,CAAiB,UAAW,EAAO,qBAAnC,CACG,GACC,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CACG,EACA,CACD,CAAA,CAAA,CACJ,EACC,EACA,EAAK,SAAW,MAAQ,CAAC,IACxB,EAAA,EAAA,KAAC,GAAD,CAAU,KAAM,EAAU,UAAW,GAAY,QAAS,MAAO,GAAY,iBAC1E,EAAK,OACE,CAAA,CAET,GAbK,CAaL,CAET,CAEA,OACE,EAAA,EAAA,MAAC,EAAA,QAAM,SAAP,CAAA,SAAA,CACG,GACC,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CACG,EACA,CACD,CAAA,CAAA,CACJ,EACC,CACa,CAAA,EARK,CAQL,CAEpB,CAAC,CACE,CAAA,CAET,CCxQA,SAAS,GAAc,EAAe,EAAgB,EAAe,EAAyB,CAC5F,OAAO,EAAQ,GAAU,EAAQ,CACnC,CAEA,SAAS,GAAgB,EAAgB,EAAwB,CAC/D,GAAI,IAAM,EAAG,MAAO,GACpB,IAAM,EAAW,EAAE,wBAAwB,CAAC,EAG5C,OAFI,EAAW,KAAK,4BAAoC,GACpD,EAAW,KAAK,4BAAoC,EACjD,CACT,CA6EA,IAAa,GAAc,IAAI,KA3Eb,4BACE,IAAI,mBACF,IAAI,iBACN,IAAI,eACN,qBACQ,oBAED,CACrB,qBAAqB,KAAK,KAAK,EAC/B,KAAK,MAAQ,sBAAsB,KAAK,SAAS,CACnD,qBAuBwB,CACtB,IAAM,EAAU,CAAC,GAAG,KAAK,QAAQ,QAAQ,CAAC,EAAE,MAAM,EAAG,GAAI,EAAG,KAAO,GAAgB,EAAE,KAAM,EAAE,IAAI,CAAC,EAC5F,EAA4D,CAAC,EAEnE,IAAK,GAAM,CAAC,EAAI,KAAU,EAAS,CACjC,IAAM,EAAU,EAAM,WAAW,EACjC,GAAI,CAAC,EAAS,SAGd,IAAM,EADc,EAAO,OAAQ,GAAM,GAAc,EAAE,KAAM,EAAE,MAAO,EAAQ,KAAM,EAAQ,KAAO,EAAQ,KAAK,CAClG,EAAY,QAAQ,EAAK,IAAM,KAAK,IAAI,EAAK,EAAE,MAAM,EAAG,EAAM,SAAS,EACjF,EAAU,CAAC,EAAM,UAAY,EAAQ,KAAO,EAC5C,EAA4B,CAAE,UAAS,IAAK,EAAU,EAAU,EAAM,SAAU,EAElF,GACF,EAAO,KAAK,CAAE,KAAM,EAAQ,KAAM,MAAO,EAAQ,KAAO,EAAQ,MAAO,OAAQ,EAAU,EAAQ,aAAc,CAAC,EAGlH,IAAM,EAAO,KAAK,QAAQ,IAAI,CAAE,GAC5B,CAAC,GAAQ,EAAK,UAAY,EAAO,SAAW,EAAK,MAAQ,EAAO,OAClE,KAAK,QAAQ,IAAI,EAAI,CAAM,EAC3B,KAAK,UAAU,IAAI,CAAE,IAAI,CAAM,EAEnC,CACF,EA5CA,SAAS,EAAyB,EAAkC,CAClE,IAAM,EAAK,OAAO,QAAQ,EAI1B,OAHA,KAAK,QAAQ,IAAI,EAAI,CAAK,EAC1B,KAAK,UAAU,IAAI,EAAI,CAAQ,EAC/B,KAAK,eAAe,EACb,CACT,CAEA,YAAY,EAAY,EAAwE,CAC9F,IAAM,EAAQ,KAAK,QAAQ,IAAI,CAAE,EAC7B,GAAO,OAAO,OAAO,EAAO,CAAK,CACvC,CAEA,WAAW,EAAkB,CACtB,KAAK,QAAQ,IAAI,CAAE,IACxB,KAAK,QAAQ,OAAO,CAAE,EACtB,KAAK,UAAU,OAAO,CAAE,EACxB,KAAK,QAAQ,OAAO,CAAE,EACtB,KAAK,cAAc,EACrB,CA2BA,gBAA+B,CACzB,KAAK,gBAAkB,IACzB,OAAO,iBAAiB,SAAU,KAAK,SAAU,CAAE,QAAS,GAAM,QAAS,EAAK,CAAC,EACjF,OAAO,iBAAiB,SAAU,KAAK,QAAQ,GAEjD,KAAK,eACP,CAEA,eAA8B,CAC5B,KAAK,gBACD,KAAK,gBAAkB,IACzB,OAAO,oBAAoB,SAAU,KAAK,SAAU,CAAE,QAAS,EAAK,CAAyB,EAC7F,OAAO,oBAAoB,SAAU,KAAK,QAAQ,EAEtD,CACF,2SErGA,SAAwB,GAAO,CAC7B,WACA,YAAY,EACZ,SAAS,GACT,WAAW,GACX,gBACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACW,CACd,IAAM,GAAA,EAAA,EAAA,QAAiC,IAAI,EACrC,GAAA,EAAA,EAAA,QAAoC,IAAI,EACxC,GAAA,EAAA,EAAA,QAAmC,IAAI,EACvC,CAAC,EAAS,IAAA,EAAA,EAAA,UAAgC,CAAE,MAAO,EAAG,KAAM,EAAG,OAAQ,CAAE,CAAC,EAC1E,CAAC,EAAa,IAAA,EAAA,EAAA,UAA8C,CAAE,QAAS,GAAO,IAAK,CAAU,CAAC,EAE9F,GAAA,EAAA,EAAA,QAA0B,CAAa,GAC7C,EAAA,EAAA,eAAgB,CACd,EAAiB,QAAU,CAC7B,EAAG,CAAC,CAAa,CAAC,EAIlB,IAAM,GAAA,EAAA,EAAA,iBAA4B,CAChC,IAAM,EAAO,EAAQ,QACf,EAAU,EAAW,QAC3B,GAAI,CAAC,GAAQ,CAAC,EAAS,OACvB,IAAM,EAAW,EAAK,sBAAsB,EAC5C,EAAW,CAAE,MAAO,EAAK,YAAa,KAAM,EAAS,KAAM,OAAQ,EAAQ,YAAa,CAAC,EACzF,GAAY,SAAS,CACvB,EAAG,CAAC,CAAC,GAEL,EAAA,EAAA,qBAAsB,CACpB,IAAM,EAAK,GAAY,SACrB,CACE,KAAM,EAAQ,QACd,YACA,WACA,eAAkB,CAChB,IAAM,EAAO,EAAQ,QACf,EAAU,EAAW,QAC3B,GAAI,CAAC,GAAQ,CAAC,EAAS,OAAO,KAC9B,IAAM,EAAO,EAAK,sBAAsB,EACxC,MAAO,CAAE,IAAK,EAAK,IAAK,KAAM,EAAK,KAAM,MAAO,EAAK,YAAa,cAAe,EAAQ,YAAa,CACxG,CACF,EACA,CACF,EAEA,MADA,GAAW,QAAU,MACR,CACX,GAAY,WAAW,CAAE,EACzB,EAAW,QAAU,IACvB,CAEF,EAAG,CAAC,CAAC,GAEL,EAAA,EAAA,eAAgB,CACV,EAAW,SACb,GAAY,YAAY,EAAW,QAAS,CAAE,YAAW,UAAS,CAAC,EAErE,GAAY,SAAS,CACvB,EAAG,CAAC,EAAW,CAAQ,CAAC,GAExB,EAAA,EAAA,qBAAsB,CACpB,EAAQ,CACV,EAAG,CAAC,EAAS,CAAQ,CAAC,GAEtB,EAAA,EAAA,eAAgB,CACd,IAAM,EAAK,IAAI,eAAe,CAAO,EAGrC,OAFI,EAAQ,SAAS,EAAG,QAAQ,EAAQ,OAAO,EAC3C,EAAW,SAAS,EAAG,QAAQ,EAAW,OAAO,MACxC,EAAG,WAAW,CAC7B,EAAG,CAAC,CAAO,CAAC,EAEZ,IAAM,GAAA,EAAA,EAAA,QAAkB,EAAI,GAC5B,EAAA,EAAA,eAAgB,CACd,GAAI,EAAS,QAAS,CACpB,EAAS,QAAU,GACnB,MACF,CACA,EAAiB,UAAU,EAAY,OAAO,CAChD,EAAG,CAAC,EAAY,OAAO,CAAC,EAExB,IAAM,EAAgD,EAAY,QAC9D,CACE,SAAU,QACV,IAAK,EAAY,IACjB,KAAM,EAAQ,KACd,MAAO,EAAQ,MACf,SACA,GAAG,GAAY,OACjB,EACA,GAAY,QAEhB,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,IAAK,EAAS,WAAA,EAAA,EAAA,SAAc,GAAO,OAAQ,EAAW,GAAY,IAAI,EAAG,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EAAG,GAAI,WAA5H,CACG,EAAY,UACX,EAAA,EAAA,KAAC,MAAD,CACE,cAAA,GACA,WAAA,EAAA,EAAA,SAAc,GAAO,kBAAmB,GAAY,WAAW,EAC/D,MAAO,CAAE,OAAQ,EAAQ,OAAQ,GAAG,GAAY,WAAY,CAC7D,CAAA,GAEH,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,EAAY,SAAW,GAAO,mBAAoB,GAAY,OAAO,EACzG,MAAO,EAEN,UACE,CAAA,CACF,GAET,wgBEzHA,SAAS,GAAO,EAAkC,CAChD,GAAM,CACN,QAAQ,GACR,WAAW,GACX,eAAiB,CAAC,EAClB,YAAY,GACZ,QACA,WAAW,GACX,QAAQ,GACR,WAAW,EACX,gBAAgB,KAChB,WAAW,KACX,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,SAAU,CAAK,EAClC,EAAG,IAAA,EAAA,EAAA,UAAwB,CAAC,GAElC,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,EAAe,OACpB,IAAM,MAAiB,EAAa,GAAM,EAAI,CAAC,EAE/C,OADA,EAAc,yBAAyB,CAAQ,MAClC,EAAc,uBAAuB,CAAQ,CAC5D,EAAG,CAAC,CAAa,CAAC,EAElB,SAAS,EAAa,EAAgD,CAChE,IACA,GACF,EAAc,IAAI,CAAC,EAAc,KAAK,EAExC,EAAS,CAAC,EAAc,CAAK,EAC/B,CAEA,IAAM,EAAgB,EAAgB,EAAc,MAAQ,EAE5D,OACE,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,EACG,QACP,WAAA,EAAA,EAAA,SACE,GAAO,OACP,EACG,GAAO,gBAAiB,CAC3B,EACA,CACF,EACO,QACP,QAAS,EACT,UAAY,GAAM,EACZ,EAAE,MAAQ,SAAW,EAAE,MAAQ,OACjC,EAAE,eAAe,EACjB,EAAa,CAAC,EAElB,EACA,KAAK,SACL,eAAc,EACd,SAAU,EAAW,GAAK,WApB5B,EAsBE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAgB,GAAO,mBAAoB,GAAY,KAAK,EAC9F,MAAO,GAAY,gBAEnB,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAgB,GAAO,mBAAoB,GAAY,KAAK,EAC9F,MAAO,GAAY,KACpB,CAAA,CACE,CAAA,GACH,GAAY,KACZ,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,YAAa,GAAY,KAAK,EAAG,MAAO,GAAY,eAC3E,GAAY,CACV,CAAA,CAEJ,GAET,+oBExEA,SAAS,GAAU,CACjB,OAAO,CAAC,EACR,aACA,WACA,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACc,CACjB,OACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACJ,KAAK,UACL,WAAA,EAAA,EAAA,SAAc,GAAO,UAAW,GAAY,KAAM,CAAS,EAC3D,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,WAEtC,EAAK,IAAK,GAAsB,CAC/B,IAAM,EAAW,EAAI,KAAO,EACtB,EAAY,CAAC,CAAC,EAAI,OAAS,CAAC,CAAC,EAAI,SAEvC,OACE,EAAA,EAAA,MAAC,EAAD,CAEE,KAAK,MACL,gBAAe,EACf,gBAAe,EAAI,UAAY,IAAA,GAC/B,SAAU,EAAI,SAAW,GAAK,EAC9B,WAAA,EAAA,EAAA,SACE,GAAO,aACP,EAAG,GAAO,oBAAqB,CAAS,EACxC,EAAG,GAAO,sBAAuB,EAAI,QAAS,EAC9C,GAAY,GACd,EACA,MAAO,GAAY,IACnB,YAAe,CACT,EAAI,UAAY,GACpB,EAAS,EAAI,EAAE,CACjB,WAhBF,EAkBE,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,EAAI,KACV,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAY,IAAI,EACpD,MAAO,GAAY,IACpB,CAAA,EACA,IACC,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,MAAM,EAAG,MAAO,GAAY,gBAAnF,CACG,EAAI,QACH,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,KAAK,EAAG,MAAO,GAAY,eAC/E,EAAI,KACD,CAAA,EAEP,EAAI,WACH,EAAA,EAAA,KAAC,OAAD,CAAM,WAAA,EAAA,EAAA,SAAc,GAAO,kBAAmB,GAAY,QAAQ,EAAG,MAAO,GAAY,kBACrF,EAAI,QACD,CAAA,CAEL,GAEQ,GApCV,EAAI,EAoCM,CAErB,CAAC,CACE,CAAA,CAET,CCpEA,SAAwB,GAAS,EAAsB,CACrD,OAAO,EAAA,EAAA,KAAC,GAAD,CAAO,GAAI,EAAqB,WAAY,CAAK,EAAG,UAAA,EAAW,CAAA,CACxE,CCAA,IAAa,GAAsB,CACjC,GAAI,UACJ,UAAW,CACT,SAAU,UACV,cAAe,UACf,gBAAiB,UACjB,UAAW,UACX,QAAS,UACT,gBAAiB,UACjB,UAAW,UACX,kBAAmB,UACnB,SAAU,UACV,iBAAkB,UAClB,UAAW,QACX,WAAY,UACZ,mBAAoB,UAEpB,kBAAmB,UACnB,mBAAoB,UACpB,oBAAqB,UACrB,iBAAkB,cAClB,uBAAwB,mBAExB,eAAgB,eAChB,cAAe,qBACf,eAAgB,qBAChB,oBAAqB,eACrB,mBAAoB,eACpB,iBAAkB,UAElB,eAAgB,UAChB,sBAAuB,UACvB,2BAA4B,cAC5B,4BAA6B,UAC7B,qBAAsB,UAEtB,kBAAmB,eACnB,oBAAqB,uBACrB,gBAAiB,aACjB,kBAAmB,qBACnB,wBAAyB,qBACzB,eAAgB,cAChB,iBAAkB,sBAClB,eAAgB,gBAChB,iBAAkB,wBAElB,sBAAuB,OACvB,yBAA0B,OAC1B,qBAAsB,OACtB,4BAA6B,OAC7B,2BAA4B,OAE5B,wBAAyB,MACzB,uBAAwB,MAExB,qBAAsB,cACtB,qBAAsB,oBACtB,uBAAwB,aAExB,yBAA0B,uBAC1B,0BAA2B,iCAE3B,0BAA2B,MAC3B,kBAAmB,OACnB,eAAgB,OAEhB,iBAAkB,sBAClB,gBAAiB,sBAEjB,gBACE,8FAEF,6BAA8B,iCAC9B,6BAA8B,cAC9B,2BAA4B,2BAE5B,cAAe,MACf,cAAe,MACf,cAAe,MACjB,CACF,+DEpEM,GAAN,cAA4B,EAAA,SAAwB,0CACnC,CACb,kBAAmB,CAAC,EACpB,gBAAiB,GACjB,kBAAmB,IACrB,wBAEiE,qBAC5C,EAAA,QAAM,UAA0B,sBACJ,gCACjB,mBA0EV,GAAuC,CAC3D,IAAM,EAAS,KAAK,MAAM,QAAU,CAAC,EAAY,EAI3C,EAAY,EAAO,KAAM,GAAM,CAAC,EAAE,WAAW,GAAK,EAAO,GACzD,EAAmC,EACpC,EAAU,UACX,CAAC,EAGC,EAAgB,EAAO,KAAM,GAAM,EAAE,KAAO,CAAc,EAC1D,EAAY,EAAgB,KAAK,aAAa,EAAc,EAAE,EAAI,CAAC,EAGnE,EAAoB,OAAO,OAAO,CAAC,EAAG,EAAU,GAAG,CAAS,EAElE,KAAK,SAAS,CAAE,oBAAmB,gBAAiB,EAAK,CAAC,EAEtD,KAAK,kBAAkB,aAAa,KAAK,gBAAgB,EAC7D,KAAK,iBAAmB,eAAiB,CACvC,KAAK,SAAS,CAAE,gBAAiB,EAAM,CAAC,EACxC,KAAK,iBAAmB,IAC1B,EAAG,GAAG,EAGN,eAAiB,CACX,KAAK,WAAW,SAClB,KAAK,SAAS,CACZ,kBAAmB,iBAAiB,KAAK,WAAW,OAAO,EACxD,iBAAiB,iBAAiB,EAClC,KAAK,CACV,CAAC,CAEL,EAAG,CAAC,CACN,EA3GA,mBAAoB,CAClB,KAAK,WAAW,KAAK,MAAM,cAAc,EACzC,KAAK,mBAAmB,KAAK,MAAM,mBAAqB,EAAE,CAC5D,CAEA,mBAAmB,EAAkB,EAAkB,CACjD,EAAU,oBAAsB,KAAK,MAAM,mBAC7C,KAAK,mBAAmB,KAAK,MAAM,mBAAqB,EAAE,GAG1D,EAAU,iBAAmB,KAAK,MAAM,gBACxC,EAAU,SAAW,KAAK,MAAM,SAEhC,KAAK,WAAW,KAAK,MAAM,cAAc,CAE7C,CAEA,sBAAuB,CACjB,KAAK,kBAAkB,aAAa,KAAK,gBAAgB,EAK7D,AAGE,KAAK,yBAFL,KAAK,gBAAgB,OAAO,EAC5B,KAAK,eAAiB,KACO,GAEjC,CAQA,mBAA2B,EAAe,CACpC,YAAO,SAAa,KAExB,IAAI,CAAC,KAAK,eAAgB,CACxB,IAAM,EAAW,SAAS,KAAK,cAC7B,0BACF,EACA,GAAI,EACF,KAAK,eAAiB,MACjB,CACL,IAAM,EAAO,SAAS,cAAc,MAAM,EAC1C,EAAK,aAAa,OAAQ,aAAa,EACvC,SAAS,KAAK,YAAY,CAAI,EAC9B,KAAK,eAAiB,EACtB,KAAK,sBAAwB,EAC/B,CACF,CAEA,KAAK,eAAe,aAAa,UAAW,CAAK,CAFjD,CAGF,CAOA,aAAqB,EAAsC,CAEzD,IAAM,GADS,KAAK,MAAM,QAAU,CAAC,EAAY,GAC5B,KAAM,GAAM,EAAE,KAAO,CAAE,EAK5C,OAJK,EAIE,CAAC,GAFW,EAAM,YAAc,KAAK,aAAa,EAAM,WAAW,EAAI,CAAC,EAExD,EAAM,SAAmC,EAJ7C,CAAC,CAKtB,CAuCA,QAAS,CACP,GAAM,CAAE,YAAa,KAAK,MACpB,CAAE,oBAAmB,mBAAoB,KAAK,MAEpD,OACE,EAAA,EAAA,KAAC,MAAD,CACE,IAAK,KAAK,WACV,GAAG,gBACH,WAAA,EAAA,EAAA,SAAc,GAAO,UAAW,GAAmB,GAAO,SAAS,EACnE,MAAO,EAEN,UACE,CAAA,CAET,CACF,ECzJA,SAAgB,GAAS,EAAyB,UAAW,CAC3D,GAAM,CAAC,EAAgB,IAAA,EAAA,EAAA,UAA+B,aAAa,QAAQ,OAAO,GAAK,CAAc,EAOrG,MAAO,CAAE,iBAAgB,kBALE,GAAoB,CAC7C,EAAW,CAAO,EAClB,aAAa,QAAQ,QAAS,CAAO,CACvC,CAE2C,CAC7C,CCNA,IAAa,GAAa,IAAwB,KAAK,MAAM,CAAC,EAAI,GAAM,IAAM,GACjE,GAAe,IAAwB,KAAK,MAAM,CAAC,EAAI,GAAM,IAAM,GAGhF,SAAgB,GAAgB,EAAoD,CAClF,GAAI,CAAC,EAAO,OAAO,KACnB,IAAM,EAAQ,EAAM,MAAM,uBAAuB,EACjD,GAAI,CAAC,EAAO,OAAO,KACnB,IAAM,EAAQ,OAAO,EAAM,EAAE,EACvB,EAAU,OAAO,EAAM,EAAE,EAE/B,OADI,EAAQ,IAAM,EAAU,GAAW,KAChC,CAAE,QAAO,SAAQ,CAC1B,CAGA,SAAgB,GAAW,EAA4C,CAIrE,OAHK,EAGE,GAFI,OAAO,GAAU,EAAK,KAAK,CAAC,EAAE,SAAS,EAAG,GAE3C,EAAG,GADF,OAAO,GAAY,EAAK,OAAO,CAAC,EAAE,SAAS,EAAG,GACzC,IAHE,EAIpB,CAGA,SAAgB,GAAW,EAAgB,EAAsB,CAE/D,OAD+B,GAA3B,CAAC,GAAQ,GAAQ,EAAsB,EACxB,KAAK,MAAM,GAAY,CAAM,EAAI,CAAI,EAAI,CADX,CAEnD,CAEA,IAAa,GAAiB,GAA4B,EAAK,MAAQ,GAAK,EAAK,QAGjF,SAAgB,GAAa,EAAiB,EAAqB,EAAgC,CACjG,IAAI,EAAQ,GAAc,CAAI,EACxB,EAAS,GAAgB,CAAG,EAC5B,EAAS,GAAgB,CAAG,EAGlC,OAFI,IAAQ,EAAQ,KAAK,IAAI,EAAO,GAAc,CAAM,CAAC,GACrD,IAAQ,EAAQ,KAAK,IAAI,EAAO,GAAc,CAAM,CAAC,GAClD,CAAE,MAAO,KAAK,MAAM,EAAQ,EAAE,EAAG,QAAS,EAAQ,EAAG,CAC9D,CAiDA,SAAgB,GAAW,EAAY,EAAY,EAAgB,EAAc,EAAgC,CAC/G,IAAM,EAAS,EAAO,EAAc,KAAK,GAAM,IAC/C,MAAO,CACL,EAAG,EAAK,EAAS,KAAK,IAAI,CAAK,EAC/B,EAAG,EAAK,EAAS,KAAK,IAAI,CAAK,CACjC,CACF,CAMA,SAAgB,GAAa,EAAY,EAAoB,CAE3D,OADa,KAAK,MAAM,EAAI,CAAC,CAAE,EAAI,IAAO,KAAK,GACjC,KAAO,GACvB,CAEA,IAAa,IAAiB,EAAY,IAAuB,KAAK,KAAK,EAAK,EAAK,EAAK,CAAE,4gBE9FtF,GAAS,GACT,GAAe,GACf,GAAe,KACf,GAAkB,KAA+B,EAEjD,GAAgB,GAChB,GAAkB,EAElB,GAAQ,IAA2B,EAAO,IAAM,GAAM,EAG5D,SAAS,GAAa,EAA2B,EAAkC,CACjF,GAAI,IAAS,UACX,OAAO,MAAM,KAAK,CAAE,OAAQ,EAAG,GAAI,EAAG,IAAS,CAC7C,IAAM,EAAQ,EAAO,EACrB,MAAO,CAAE,MAAO,OAAO,CAAK,EAAE,SAAS,EAAG,GAAG,EAAG,OAAM,QAAO,KAAM,OAAiB,CACtF,CAAC,EAGH,GAAI,CAAC,EACH,OAAO,MAAM,KAAK,CAAE,OAAQ,EAAG,GAAI,EAAG,IAAS,CAC7C,IAAM,EAAQ,IAAS,EAAI,GAAK,EAChC,MAAO,CAAE,MAAO,OAAO,CAAK,EAAG,OAAM,QAAO,KAAM,OAAiB,CACrE,CAAC,EAIH,IAAM,EAAQ,MAAM,KAAK,CAAE,OAAQ,EAAG,GAAI,EAAG,IAAS,CACpD,IAAM,EAAQ,IAAS,EAAI,GAAK,EAChC,MAAO,CAAE,MAAO,OAAO,CAAK,EAAG,OAAM,QAAO,KAAM,OAAiB,CACrE,CAAC,EACK,EAAQ,MAAM,KAAK,CAAE,OAAQ,EAAG,GAAI,EAAG,IAAS,CACpD,IAAM,EAAQ,IAAS,EAAI,EAAI,EAAO,GACtC,MAAO,CAAE,MAAO,OAAO,CAAK,EAAE,SAAS,EAAG,GAAG,EAAG,OAAM,QAAO,KAAM,OAAiB,CACtF,CAAC,EACD,MAAO,CAAC,GAAG,EAAO,GAAG,CAAK,CAC5B,CAEA,SAAwB,GAAU,CAChC,OACA,OACA,YACA,aACA,WACA,WACA,aACA,OAAQ,GACS,CACjB,IAAM,GAAA,EAAA,EAAA,QAAiC,IAAI,EACrC,GAAA,EAAA,EAAA,QAAqB,EAAK,EAE1B,EAAU,GAAa,EAAM,CAAS,EAGtC,EAAO,EAAK,OAAS,GACrB,EAAiB,GAAK,EAAK,KAAK,EAEhC,EACA,IAAS,UAEJ,CAAE,KAAM,EAAK,QAAS,OAAQ,EAAa,EAE/C,EAGD,EAAK,QAAU,EAAU,CAAE,KAAM,EAAG,OAAQ,EAAa,EACzD,EAAK,OAAS,GAAW,CAAE,KAAM,EAAK,MAAQ,GAAI,OAAQ,EAAa,EACpE,CAAE,MAAO,EAAK,MAAQ,IAAM,GAAI,OAAQ,EAAa,EAJnD,CAAE,KAAM,EAAiB,GAAI,OAAQ,EAAa,EAOvD,EAAO,GAAW,GAAQ,GAAQ,EAAK,OAAQ,EAAK,KAAM,IAAS,UAAY,GAAkB,EAAa,EAE9G,EAAc,GAClB,IAAS,UACL,GAAW,EAAK,QAAS,CAAU,IAAM,EAAE,OAAS,EAAK,UAAY,EAAE,MACvE,EACE,EAAK,QAAU,EAAE,MACjB,IAAmB,EAAE,MAEvB,GAAoB,EAAiB,IAA+B,CACxE,IAAM,EAAO,EAAQ,SAAS,sBAAsB,EACpD,GAAI,CAAC,EAAM,OAAO,EAClB,IAAM,EAAK,GAAW,EAAK,KAAO,EAAK,MAAQ,GACzC,EAAK,GAAW,EAAK,IAAM,EAAK,OAAS,GACzC,EAAQ,GAAa,EAAI,CAAE,EAEjC,GAAI,IAAS,UAAW,CACtB,IAAM,EAAU,GAAW,KAAK,MAAM,EAAQ,EAAe,EAAG,CAAU,EAC1E,MAAO,CAAE,MAAO,EAAK,MAAO,SAAQ,CACtC,CAEA,IAAM,EAAO,KAAK,MAAM,EAAQ,EAAa,EAAI,GACjD,GAAI,CAAC,EAAW,CACd,IAAM,EAAU,IAAS,EAAI,GAAK,EAElC,MAAO,CAAE,MAAO,GADF,EAAQ,EAAU,GAAM,GAAK,EAAU,EACtB,EAAG,QAAS,EAAK,OAAQ,CAC1D,CAMA,MAAO,CAAE,MAAO,GAHI,GAAc,EAAI,CAAE,GAAK,EAAK,MAAQ,GAAM,GACrC,GACJ,IAAS,EAAI,EAAI,EAAO,GAAM,IAAS,EAAI,GAAK,CACxC,EAAG,QAAS,EAAK,OAAQ,CAC1D,EAqBA,OACE,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,GAAO,UAAW,GAAY,SAAS,EACrD,MAAO,GAAY,UACnB,cAxBuB,GAA0C,CACnE,EAAY,QAAU,GAGtB,EAAG,cAA8B,oBAAoB,EAAE,SAAS,EAChE,EAAS,EAAiB,EAAE,QAAS,EAAE,OAAO,CAAC,CACjD,EAmBI,cAjBuB,GAA0C,CAC9D,EAAY,SACjB,EAAS,EAAiB,EAAE,QAAS,EAAE,OAAO,CAAC,CACjD,EAeI,YAbqB,GAA0C,CAC5D,EAAY,UACjB,EAAY,QAAU,GACtB,EAAS,EAAiB,EAAE,QAAS,EAAE,OAAO,CAAC,EACjD,EAUI,KAAK,SACL,aAAY,IAAS,UAAY,UAAY,QAC7C,iBAAgB,IAAS,UAAY,GAAG,EAAK,QAAQ,UAAY,GAAG,EAAK,MAAM,iBATjF,EAWE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,GAAO,UAAW,QAAQ,cAAc,cAAA,YAAxD,EACE,EAAA,EAAA,KAAC,SAAD,CAAQ,GAAI,GAAQ,GAAI,GAAQ,EAAG,IAAK,UAAW,GAAO,eAAkB,CAAA,GAC5E,EAAA,EAAA,KAAC,OAAD,CAAM,GAAI,GAAQ,GAAI,GAAQ,GAAI,EAAK,EAAG,GAAI,EAAK,EAAG,UAAW,GAAO,aAAgB,CAAA,GACxF,EAAA,EAAA,KAAC,SAAD,CACE,GAAI,EAAK,EACT,GAAI,EAAK,EACT,EAAG,EACH,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAY,SAAS,EACzD,MAAO,GAAY,SACpB,CAAA,CACE,IAEJ,EAAQ,IAAK,GAAM,CAClB,IAAM,EAAI,GAAW,GAAQ,GAAQ,EAAE,OAAS,QAAU,GAAe,GAAc,EAAE,KAAM,EAAa,EACtG,EAAW,EAAW,CAAC,EAG7B,OACE,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SACE,GAAO,YACP,EAAE,OAAS,SAAW,GAAO,iBAC7B,GAAY,GAAO,oBACnB,GAAY,WACd,EACA,MAAO,CAAE,KAAM,GAAG,EAAE,EAAE,GAAI,IAAK,GAAG,EAAE,EAAE,GAAI,GAAG,GAAY,WAAY,WAEpE,EAAE,KACA,EAVE,GAAG,EAAE,KAAK,GAAG,EAAE,OAUjB,CAET,CAAC,CACE,GAET,g3BE9JA,SAAwB,GAAU,CAChC,QACA,WACA,eAAiB,KACjB,eAAiB,KACjB,gBAAgB,KAChB,WAAW,GACX,UAAU,GACV,UAAU,GACV,WAAW,GACX,kBAAkB,GAClB,gBAAgB,GAChB,aAAa,EACb,YAAY,GACZ,UAAU,KACV,UAAU,KACV,QAAQ,GACR,UAAU,GACV,eAAe,GACf,aAAa,GACb,WAAW,GACX,YAAY,GACZ,QACA,aACA,OAAQ,EACR,GAAG,GACc,CACjB,IAAM,MACA,EAAuB,EAAc,OAAoB,GACtD,GAAS,GAAY,GAGxB,CAAC,EAAmB,IAAA,EAAA,EAAA,UAAiC,CAAiB,EACtE,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,EAAK,EAChD,CAAC,EAAM,IAAA,EAAA,EAAA,UAA+B,OAAO,EAC7C,CAAC,GAAW,IAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,CAAC,EAAW,KAAA,EAAA,EAAA,UAAyB,EAAK,EAC1C,EAAG,KAAA,EAAA,EAAA,UAAwB,CAAC,EAE5B,GAAiB,EAAkB,EACnC,CAAC,GAAc,IAAA,EAAA,EAAA,UAA4B,EAAc,EACzD,GAAA,EAAA,EAAA,QAAe,CAAa,EAG9B,CAAC,GAAiB,KAAiB,KACrC,EAAgB,EAAc,EAC9B,EAAqB,EAAc,IAGrC,EAAA,EAAA,eAAgB,CAEd,GADA,EAAM,QAAU,EACZ,CAAC,EAAe,OACpB,IAAM,MAAiB,CACrB,EAAsB,EAAc,OAAoB,EAAE,EAC1D,GAAa,GAAM,EAAI,CAAC,CAC1B,EAEA,OADA,EAAc,yBAAyB,CAAQ,MAClC,EAAc,uBAAuB,CAAQ,CAC5D,EAAG,CAAC,CAAa,CAAC,EAElB,IAAM,MACJ,EAAgB,EAAc,SAAW,EAAc,SAAS,EAAI,CAAC,GAAW,CAAC,CAAC,EAE9E,MACJ,CAAC,EAAE,GAAc,GAAe,WAAW,KAAM,GAAO,EAA+B,cAAgB,UAAU,GAG7G,EAAQ,GAA2B,CACvC,IAAM,EAAM,EAAO,GAAW,CAAI,EAAI,KAClC,GAAe,EAAc,IAAI,CAAG,EACxC,IAAW,CAAG,CAChB,EAEM,GAAa,GAA2B,CAC5C,EAAqB,EAAO,GAAW,CAAI,EAAI,EAAE,EACjD,EAAK,CAAI,CACX,EAEM,GAAS,GAAgB,CAAiB,EAC1C,GAAsB,IAAU,CAAE,MAAO,GAAI,QAAS,CAAE,EAExD,EAAoB,GAAoB,CAE5C,GAAU,GAAa,CADL,MAAO,EAAK,MAAO,QAAS,GAAW,EAAK,QAAS,CAAU,CAC1D,EAAS,EAAS,CAAO,CAAC,CACnD,EAEM,GAAoB,GAAoB,CAE5C,IAAM,EAAO,GAAa,CADR,MAAO,EAAK,MAAO,QAAS,GAAW,EAAK,QAAS,CAAU,CACvD,EAAS,EAAS,CAAO,EAEnD,GADA,GAAU,CAAI,EACV,IAAS,QAAS,CACpB,EAAQ,SAAS,EACjB,MACF,CACA,IAAW,GAAW,CAAI,CAAC,EACtB,GAAU,EAAgB,EAAK,CACtC,EAEM,OAAmB,CACnB,IACJ,EAAQ,OAAO,EACf,EAAgB,EAAI,EACtB,EAEM,IAA2B,CAAE,gBAAe,eAA2D,CAC3G,GAAI,CAAC,GAAiB,EAAU,QAAU,EAAc,MAAO,OAAO,EACtE,IAAI,EAAI,EAAU,MACZ,EAAU,EAAE,MAAM,EAAG,CAAC,EACxB,SAAS,KAAK,CAAO,GAAK,OAAO,CAAO,EAAI,KAAI,EAAI,KAAK,EAAE,MAAM,CAAC,KACtE,IAAM,EAAS,EAAE,MAAM,EAAG,CAAC,EAE3B,MADI,SAAS,KAAK,CAAM,GAAK,OAAO,CAAM,EAAI,KAAI,EAAI,GAAG,EAAE,MAAM,EAAG,CAAC,EAAE,KAChE,IAAM,EAAU,MAAQ,EAAY,CAAE,GAAG,EAAW,MAAO,CAAE,CACtE,EAEM,EAAqB,GAAc,CACvC,EAAqB,CAAC,EACtB,IAAM,EAAI,GAAgB,CAAC,EACvB,GAAG,EAAK,CAAC,CACf,EAEM,OAAmB,CACnB,EAAM,UAAS,EAAM,QAAQ,QAAU,IAC3C,EAAa,EAAK,EAClB,EAAK,GAAgB,CAAiB,CAAC,CACzC,EAEM,GAAe,GAAgB,CAE/B,IADS,GAAS,OAAS,IAE/B,GAAU,CAAE,MAAO,GAAU,GAAS,OAAS,EAAK,GAAK,IAAI,EAAG,QAAS,GAAS,OAAQ,CAAC,CAC7F,EAEM,GAAS,EAAS,EAClB,GAAe,GAAS,OAAO,EAAY,GAAO,OAAU,GAAO,MAAQ,IAAM,GAAM,CAAC,EAAE,SAAS,EAAG,GAAG,EAAI,KAC7G,GAAiB,GAAS,OAAO,GAAO,OAAO,EAAE,SAAS,EAAG,GAAG,EAAI,KAEpE,GAAS,EAAW,MACxB,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,qBAAsB,GAAY,WAAW,EAAG,MAAO,GAAY,qBAA7F,EACE,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,WAAA,EAAA,EAAA,SAAc,GAAO,uBAAwB,IAAS,SAAW,GAAO,6BAA8B,GAAY,aAAa,EAC/H,MAAO,GAAY,cACnB,YAAe,EAAQ,OAAO,WAE7B,EACK,CAAA,GACR,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,GAAO,8BAAsB,GAAO,CAAA,GACrD,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,WAAA,EAAA,EAAA,SAAc,GAAO,uBAAwB,IAAS,WAAa,GAAO,6BAA8B,GAAY,aAAa,EACjI,MAAO,GAAY,cACnB,YAAe,EAAQ,SAAS,WAE/B,EACK,CAAA,EACP,CAAC,IACA,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,kBAAmB,GAAY,QAAQ,EAAG,MAAO,GAAY,kBAAvF,EACE,EAAA,EAAA,KAAC,SAAD,CAAQ,KAAK,SAAS,WAAA,EAAA,EAAA,SAAc,GAAS,MAAQ,IAAM,GAAO,uBAAuB,EAAG,YAAe,GAAY,EAAK,WAAG,IAAU,CAAA,GACzI,EAAA,EAAA,KAAC,SAAD,CAAQ,KAAK,SAAS,WAAA,EAAA,EAAA,SAAc,GAAS,OAAS,IAAM,GAAO,uBAAuB,EAAG,YAAe,GAAY,EAAI,WAAG,IAAU,CAAA,CACtI,GAEJ,IAGD,GACJ,GAAmB,GACjB,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,gBAAiB,GAAY,MAAM,EAAG,MAAO,GAAY,gBAAnF,CACG,IACC,EAAA,EAAA,KAAC,EAAD,CACE,UAAW,EAAgB,QAC3B,YAAe,CACb,IAAM,EAAM,IAAI,KAChB,EAAiB,CAAE,MAAO,EAAI,SAAS,EAAG,QAAS,EAAI,WAAW,CAAE,CAAC,CACvE,WACD,KAEO,CAAA,EAET,IACC,EAAA,EAAA,KAAC,EAAD,CAAQ,UAAW,EAAgB,QAAS,YAAe,CAAE,GAAU,IAAI,EAAG,IAAW,IAAI,CAAG,WAAG,OAE3F,CAAA,CAEP,IACH,KAEA,IACJ,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,eAAgB,GAAY,KAAK,EAAG,MAAO,GAAY,eAAjF,CACG,IACD,EAAA,EAAA,KAAC,GAAD,CACE,KAAM,GACA,OACK,YACC,aACZ,SAAU,EACV,SAAU,GACE,aACZ,OAAQ,CACT,CAAA,EACA,EACE,IAGD,GAAQ,EAAU,MACtB,EAAA,EAAA,KAAC,GAAD,CACE,MAAO,GAAG,IAAQ,EAAmB,EAAI,KAAO,KAChD,MAAO,EACP,MAAM,EAAA,EAAA,KAAC,EAAA,gBAAD,CAAiB,KAAM,EAAA,OAAU,CAAA,EACvC,YAAa,GACb,QAAS,GACT,SAAU,EACA,WACV,QAAS,CAAC,GACV,aAAa,EAAA,EAAA,KAAC,EAAA,QAAD,CAAW,KAAK,QAAQ,gBAAgB,IAA6B,0BAA0B,CAAA,EAC5G,SAAW,GAAM,EAAkB,CAAW,EAC9C,OAAQ,GACR,YAAe,EAAa,EAAI,EAChC,iBAAoB,GAAa,EAAI,EACrC,iBAAoB,GAAa,EAAK,CACvC,CAAA,EAGG,GACA,EAAiB,GACjB,GAEA,EAAA,EAAA,KAAC,GAAD,CAAO,WAAA,GAAW,OAAQ,EAAc,YAAe,EAAgB,EAAK,WACzE,EACI,CAAA,GAIT,EAAA,EAAA,KAAC,GAAD,CACE,OAAQ,EACR,aAAc,EACd,QAAS,GACT,MAAO,GAAM,KACb,sBAAA,YAEC,EACW,CAAA,EAIlB,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,UAAW,GAAY,KAAM,CAAS,EAAG,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EAAG,GAAI,WAAjH,EACI,GAAW,IAAa,GACzB,IACD,EAAA,EAAA,KAAC,GAAD,CACE,QAAQ,QACR,QAAS,EAAgB,EAAc,uBAAuB,GAAK,GAAK,GAAgB,GACxF,UAAW,KAAW,IAAa,EACpC,CAAA,CACE,GAET,s+CE5PM,GAAqB,IAGrB,GAAsB,GAQ5B,SAAgB,GAAuC,CACrD,YACA,OAAO,IACP,oBAAoB,GACpB,oBAAoB,GACpB,WAAW,GACX,aAAa,IACsC,CACnD,IAAM,GAAA,EAAA,EAAA,QAAgB,IAAI,EACpB,CAAC,EAAY,IAAA,EAAA,EAAA,UAA0B,EAAK,EAE5C,CAAC,EAAiB,IAAA,EAAA,EAAA,cAChB,OAAO,OAAW,KAAe,OAAO,OAAO,YAAe,YAAc,OAAO,WAAW,mBAAmB,EAAE,OAC3H,GACA,EAAA,EAAA,eAAgB,CACd,GAAI,OAAO,OAAO,YAAe,WAAY,OAC7C,IAAM,EAAM,OAAO,WAAW,mBAAmB,EAC3C,EAAY,GAA+B,EAAmB,EAAM,OAAO,EAEjF,OADA,EAAI,iBAAiB,SAAU,CAAQ,MAC1B,EAAI,oBAAoB,SAAU,CAAQ,CACzD,EAAG,CAAC,CAAC,EAEL,IAAM,EAAoB,GAAa,GAAc,CAAC,EAGhD,GAAA,EAAA,EAAA,QAQI,IAAI,EAER,GAAA,EAAA,EAAA,QAAsB,CAAS,EA4GrC,OA3GA,EAAA,EAAA,eAAgB,CACd,EAAa,QAAU,CACzB,CAAC,GAED,EAAA,EAAA,eAAgB,CACd,IAAM,EAAK,EAAI,QACf,GAAI,CAAC,GAAM,EAAmB,OAE9B,SAAS,EAAe,EAAgB,EAAoB,CAC1D,GAAI,CAAC,EAAI,OACL,IAAe,QAMjB,EAAQ,aAEV,IAAM,EAAY,IAAS,IAAM,cAAc,EAAO,KAAO,cAAc,EAAO,KAClF,EAAG,MAAM,WAAa,EACtB,EAAG,MAAM,UAAY,EACrB,IAAM,EAAO,KAAK,IAAI,EAAG,EAAI,KAAK,IAAI,CAAM,GAAK,EAAoB,IAAI,EACzE,EAAG,MAAM,QAAU,OAAO,CAAI,CAChC,CAEA,SAAS,EAAc,EAAqB,CAC1C,IAAM,EAAO,EAAQ,QACrB,GAAI,CAAC,GAAQ,EAAM,YAAc,EAAK,UAAW,OAEjD,IAAM,EAAS,EAAM,QAAU,EAAK,OAC9B,EAAS,EAAM,QAAU,EAAK,OAEpC,GAAI,CAAC,EAAK,WAAY,CACpB,IAAM,EAAU,IAAS,IAAM,EAAS,EAClC,EAAQ,IAAS,IAAM,EAAS,EACtC,GAAI,KAAK,IAAI,CAAO,EAAI,IAAuB,KAAK,IAAI,CAAK,EAAI,GAAqB,OACtF,GAAI,KAAK,IAAI,CAAK,EAAI,KAAK,IAAI,CAAO,EAAG,CAEvC,EAAK,OAAS,GACd,MACF,CACA,EAAK,WAAa,GAClB,EAAc,EAAI,CACpB,CAEK,EAAK,SACV,EAAM,eAAe,EACrB,EAAK,OAAS,IAAS,IAAM,EAAS,EACtC,EAAe,EAAK,OAAQ,MAAM,EACpC,CAEA,SAAS,GAAa,CACpB,IAAM,EAAO,EAAQ,QAKrB,GAJA,EAAQ,QAAU,KAClB,OAAO,oBAAoB,cAAe,CAAa,EACvD,OAAO,oBAAoB,YAAa,CAAU,EAClD,OAAO,oBAAoB,gBAAiB,CAAU,EAClD,CAAC,GAAQ,CAAC,EAAK,QAAU,CAAC,EAAK,WAAY,CAC7C,EAAc,EAAK,EACnB,MACF,CAEA,IAAM,EAAU,KAAK,IAAI,EAAG,KAAK,IAAI,EAAI,EAAK,SAAS,EACjD,EAAW,EAAK,OAAS,EAI/B,GAFE,KAAK,IAAI,EAAK,MAAM,GAAK,GAAqB,KAAK,IAAI,CAAQ,GAAK,EAEvD,CACb,IAAM,EAAQ,GAAI,sBAAsB,EAAE,OAAS,EAEnD,EADmB,KAAK,KAAK,EAAK,QAAU,CAAC,GAAK,EAAQ,IAC/B,aAAa,GAAmB,uBAAuB,GAAmB,YAAY,EACjH,eAAiB,EAAa,QAAQ,EAAG,EAAkB,CAC7D,MACE,EAAe,EAAG,aAAa,GAAmB,uBAAuB,GAAmB,YAAY,EAE1G,EAAc,EAAK,CACrB,CAEA,SAAS,EAAc,EAAqB,CACtC,EAAQ,SAAW,CAAC,IAIxB,EAAG,MAAM,UAAY,OACrB,EAAQ,QAAU,CAChB,UAAW,EAAM,UACjB,OAAQ,EAAM,QACd,OAAQ,EAAM,QACd,UAAW,KAAK,IAAI,EACpB,OAAQ,EACR,WAAY,GACZ,OAAQ,EACV,EACA,OAAO,iBAAiB,cAAe,EAAe,CAAE,QAAS,EAAM,CAAC,EACxE,OAAO,iBAAiB,YAAa,CAAU,EAC/C,OAAO,iBAAiB,gBAAiB,CAAU,EACrD,CAGA,OADA,EAAG,iBAAiB,cAAe,CAAa,MACnC,CACX,EAAG,oBAAoB,cAAe,CAAa,EACnD,OAAO,oBAAoB,cAAe,CAAa,EACvD,OAAO,oBAAoB,YAAa,CAAU,EAClD,OAAO,oBAAoB,gBAAiB,CAAU,CACxD,CACF,EAAG,CAAC,EAAM,EAAmB,EAAmB,CAAiB,CAAC,EAE3D,CAAE,MAAK,YAAW,CAC3B,CClKA,IAAM,GAAY,CAChB,KAAM,EAAA,aACN,QAAS,EAAA,cACT,MAAO,EAAA,cACP,KAAM,EAAA,sBACN,QAAS,EAAA,MACX,EAEA,SAAS,GAAM,CAAE,OAAM,WAAU,aAAyB,CACxD,GAAM,CAAE,KAAI,UAAS,UAAS,cAAe,EACvC,CAAE,WAAU,oBAAmB,kBAAiB,eAAc,OAAM,aAAY,OAAQ,GAAe,EAEvG,CAAC,EAAS,IAAA,EAAA,EAAA,UAAuB,EAAK,EACtC,CAAC,EAAS,IAAA,EAAA,EAAA,UAAuB,EAAK,EAEtC,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAsB,EAAK,EACpC,CAAE,IAAK,EAAU,cAAe,GAAgC,CACpE,cAAiB,CACf,EAAU,EAAI,EACd,EAAU,CAAE,CACd,CACF,CAAC,EAEK,EAAU,IAAiB,GAAW,IAAa,EAInD,GAAA,EAAA,EAAA,QAAsB,CAAQ,EAYpC,OAVA,EAAA,EAAA,eAAgB,CACd,GAAI,IAAa,GAAK,EAAQ,OAC9B,IAAM,EAAQ,KAAK,IAAI,EACjB,EAAQ,eAAiB,EAAU,CAAE,EAAG,EAAa,OAAO,EAClE,UAAa,CACX,aAAa,CAAK,EAClB,EAAa,SAAW,KAAK,IAAI,EAAI,CACvC,CACF,EAAG,CAAC,EAAI,EAAU,EAAW,CAAM,CAAC,GAGlC,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SACE,GAAO,MACP,EAAW,GAAO,YAAc,KAChC,GAAO,SAAS,KAChB,GAAc,CAAC,GAAU,GAAO,gBAChC,GAAU,GAAO,YACjB,GAAY,IACd,EACA,MAAO,GAAY,KACnB,aAAc,MAAqB,EAAW,EAAI,EAAI,IAAA,GACtD,aAAc,MAAqB,EAAW,EAAK,EAAI,IAAA,GACvD,QAAS,MAAqB,EAAW,EAAI,EAAI,IAAA,GACjD,OAAQ,MAAqB,EAAW,EAAK,EAAI,IAAA,YAdnD,EAgBE,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,GAAU,GAChB,WAAA,EAAA,EAAA,SAAc,GAAO,UAAW,GAAY,IAAI,EAChD,MAAO,GAAY,IACpB,CAAA,GAED,EAAA,EAAA,KAAC,MAAD,CAAK,WAAA,EAAA,EAAA,SAAc,GAAO,aAAc,GAAY,OAAO,EAAG,MAAO,GAAY,iBAC9E,CACE,CAAA,EAEJ,IACC,EAAA,EAAA,KAAC,EAAD,CACE,KAAM,EAAA,QACN,YAAe,EAAU,CAAE,EAC3B,WAAA,EAAA,EAAA,SAAc,GAAO,iBAAkB,GAAY,WAAW,EAC9D,MAAO,GAAY,YACnB,aAAW,OACZ,CAAA,EAGF,GAAqB,EAAW,IAC/B,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,iBAAkB,GAAY,WAAW,EAC9D,MAAO,CAAE,mBAAoB,GAAG,EAAS,IAAK,GAAG,GAAY,WAAY,CAC1E,CAAA,CAEA,GAET,CCtGA,IAAI,GAA+B,KAEnC,SAAgB,GAAsB,EAAuB,CAC3D,GAAW,CACb,CAEA,SAAgB,IAAgC,CAC9C,GAAW,IACb,CAEA,SAAgB,GAAU,EAAoB,EAA8B,CAC1E,GAAI,CAAC,GAAU,CACb,QAAQ,MAAM,qEAAqE,EACnF,MACF,CACA,GAAS,EAAS,CAAO,CAC3B,CCXA,IAAM,GAAyC,CAC7C,SAAU,YACV,SAAU,IACV,kBAAmB,GACnB,gBAAiB,GACjB,cAAe,GACf,aAAc,EAChB,EAEM,GAAuB,IAE7B,SAAS,GAAgB,EAAiC,CACxD,OAAO,GAAO,aAAa,IAC7B,CAMA,SAAS,GAAc,CACrB,WACA,WAAW,GAAS,SACpB,WAAW,GAAS,SACpB,oBAAoB,GAAS,kBAC7B,kBAAkB,GAAS,gBAC3B,gBAAgB,GAAS,cACzB,eAAe,GAAS,cACH,CACrB,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAmC,CAAC,CAAC,EAC9C,GAAA,EAAA,EAAA,QAAoB,CAAC,EAErB,GAAA,EAAA,EAAA,aAAuB,GAAe,CAC1C,EAAW,GACT,EAAK,IAAK,GAAO,EAAE,KAAO,EAAK,CAAE,GAAG,EAAG,WAAY,EAAK,EAAI,CAAE,CAChE,EACA,eAAiB,CACf,EAAW,GAAS,EAAK,OAAQ,GAAM,EAAE,KAAO,CAAE,CAAC,CACrD,EAAG,EAAoB,CACzB,EAAG,CAAC,CAAC,EAEC,GAAA,EAAA,EAAA,cACH,EAAoB,IAA2B,CAC9C,IAAM,EAAiC,CACrC,SAAU,GAAS,UAAY,EAC/B,SAAU,GAAS,UAAY,EAC/B,kBAAmB,GAAS,mBAAqB,EACjD,gBAAiB,GAAS,iBAAmB,EAC7C,aAAc,GAAS,cAAgB,EACvC,KAAM,GAAS,MAAQ,UACvB,WAAY,GAAS,WACrB,OAAQ,GAAS,MACnB,EAEA,EAAW,SAAW,EAEtB,IAAM,EAAsB,CAAE,GAAA,SADV,EAAW,UACG,UAAS,QAAS,EAAU,WAAY,EAAM,EAEhF,EAAW,GACL,CAAC,GAAiB,EAAK,OAAS,GAElC,eAAiB,CACf,EAAU,CAAC,CAAQ,CAAC,CACtB,EAAG,EAAoB,EAChB,EAAK,IAAK,IAAO,CAAE,GAAG,EAAG,WAAY,EAAK,EAAE,GAE9C,CAAC,GAAG,EAAM,CAAQ,CAC1B,CACH,EACA,CAAC,EAAU,EAAU,EAAmB,EAAiB,EAAe,CAAY,CACtF,GAEA,EAAA,EAAA,gBACE,GAAsB,CAAQ,MACjB,GAAwB,GACpC,CAAC,CAAQ,CAAC,EAGb,IAAM,EAAa,EAAO,QAAqC,EAAK,IAAM,CACxE,IAAM,EAAM,EAAE,QAAQ,SAGtB,OAFK,EAAI,KAAM,EAAI,GAAO,CAAC,GAC3B,EAAI,GAAK,KAAK,CAAC,EACR,CACT,EAAG,CAAC,CAAC,EAEL,OACE,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CACG,GACD,EAAA,EAAA,KAAC,GAAD,CAAA,SACG,OAAO,QAAQ,CAAU,EAAE,KAAK,CAAC,EAAK,MACrC,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,GAAO,UAAW,GAAgB,CAAsB,CAAC,WAEtE,EAAM,IAAK,IACV,EAAA,EAAA,KAAC,GAAD,CAEQ,OACN,SAAU,EAAI,WAAW,QAAQ,EACjC,UAAW,CACZ,EAJM,EAAK,EAIX,CACF,CACE,EAXE,CAWF,CACN,CACM,CAAA,CACT,CAAA,CAAA,CAEN,8xFEvEA,SAAS,GAAW,CAClB,QACA,MACA,UACA,iBACA,aACA,cACA,QACA,UACA,WACA,eACA,eACA,cACA,UACA,cACA,YACA,aACA,sBACA,cACA,cACA,aACA,YACA,SACA,eACA,eACA,eACA,yBACA,qBACA,eACA,WACA,YACkB,CAClB,IAAM,GAAA,EAAA,EAAA,QAA6B,IAAI,EAYvC,OAPA,EAAA,EAAA,qBAAsB,CACpB,IAAM,EAAK,EAAI,QACX,MAAC,GAAM,CAAC,GAEZ,OADA,EAAS,QAAQ,CAAE,MACN,EAAS,UAAU,CAAE,CACpC,EAAG,CAAC,CAAQ,CAAC,GAGX,EAAA,EAAA,MAAC,MAAD,CACO,MACL,aAAY,EACZ,WAAA,EAAA,EAAA,SACE,EAAO,eACP,GAAc,EAAO,uBACrB,CAAC,GAAe,EAAO,wBACvB,CAAC,GAAS,EAAO,sBACjB,GAAe,EAAO,wBACtB,GAAc,EAAO,uBACrB,IAAiB,UAAY,EAAO,yBACpC,CACF,EACA,MAAO,CACL,SAAU,WACV,IAAK,EACL,KAAM,EACN,MAAO,EACP,UAAW,cAAc,EAAI,KAC7B,GAAI,GAAW,KAAqB,CAAC,EAAf,CAAE,SAAQ,EAChC,GAAI,EAAiB,CAAE,QAAS,OAAQ,oBAAqB,CAAe,EAAI,CAAC,EAIjF,GAAI,EAAsB,CAAE,aAAc,EAAG,EAAI,CAAC,EAClD,GAAG,CACL,EACS,UACE,YACE,cACA,cACD,aACD,YACX,OAAQ,IAAW,EAAa,GAAM,EAAE,eAAe,EAAI,IAAA,IAC7C,eACd,cAAe,EAAa,GAAM,EAAE,eAAe,EAAI,IAAA,GACvD,gBAAe,EACf,gBAAe,EACf,gBAAe,EACf,eAAc,EACd,KAAM,WAxCR,EA0CI,IAAiB,UAAY,IAAiB,WAC9C,EAAA,EAAA,KAAC,MAAD,CACE,iBAAgB,EAChB,cAAA,GACA,WAAA,EAAA,EAAA,SACE,EAAO,oBACP,IAAiB,SAAW,EAAO,0BAA4B,EAAO,yBACtE,CACF,EACA,MAAO,CAAE,KAAM,GAAgB,EAAG,GAAG,CAAmB,CACzD,CAAA,EAEF,CACE,GAET,CC/IA,SAAgB,GACd,EACA,EACA,EACA,EAAS,EACmC,CAC5C,IAAM,EAAY,EAAK,OACjB,EAAc,MAAc,EAAY,CAAC,EAC/C,EAAQ,GAAK,EACb,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,IAAK,CAClC,IAAM,EAAM,EAAI,EAAY,EAAI,EAAS,EAGzC,EAAQ,EAAI,GAAK,EAAQ,IAAM,EAAW,IAAI,EAAK,EAAE,GAAK,GAAsB,CAClF,CACA,MAAO,CAAE,UAAS,YAAa,EAAQ,EAAW,CACpD,CAGA,SAAgB,GAAe,EAAmB,EAAmB,EAA2B,CAC9F,GAAI,GAAa,EAAG,MAAO,GAC3B,IAAI,EAAK,EACL,EAAK,EAAY,EACrB,KAAO,EAAK,GAAI,CACd,IAAM,EAAO,EAAK,GAAO,EACrB,EAAQ,EAAM,IAAM,EAAW,EAAK,EAAM,EACzC,EAAK,CACZ,CACA,OAAO,CACT,CAEA,SAAgB,GACd,EACA,EACA,EACA,EACA,EAC0C,CAC1C,GAAI,IAAc,EAAG,MAAO,CAAE,WAAY,EAAG,SAAU,EAAG,EAE1D,IAAM,EAAK,GAAe,EAAS,EAAW,CAAS,EAEnD,EAAM,EACV,KAAO,EAAM,GAAa,EAAQ,GAAO,EAAY,GAAiB,IAEtE,MAAO,CACL,WAAY,KAAK,IAAI,EAAG,EAAK,CAAQ,EACrC,SAAU,KAAK,IAAI,EAAY,EAAG,EAAM,EAAW,CAAC,CACtD,CACF,CAUA,SAAgB,GACd,EACA,EACA,EACA,EACA,EACe,CACf,GAAI,IAAc,IAAM,IAAc,EAAW,OAAO,KACxD,IAAM,EAAW,EAAS,EAAY,EAGtC,OAFmB,EAAY,EACd,GAAY,EAAW,GAAY,GAAiB,EAC9D,IACT,CAQA,SAAgB,GACd,EACA,EACA,EACA,EAC+B,CAC/B,GAAI,GAAa,EAAG,MAAO,SAC3B,IAAM,GAAO,EAAW,GAAU,EAMlC,OALI,EACE,EAAM,EAAI,EAAU,SACpB,EAAM,EAAI,EAAU,QACjB,SAEF,EAAM,GAAM,SAAW,OAChC,CAQA,SAAgB,GAAoB,EAAe,EAA0B,CAC3E,IAAM,EAAI,EAAO,GACb,EAAI,EAAQ,EAChB,KAAO,EAAI,EAAO,QAAU,EAAO,GAAK,GAAG,IAC3C,OAAO,EAAI,CACb,CAIA,SAAgB,GACd,EACA,EACQ,CAER,OADI,EAAQ,SAAW,EAAU,MAC1B,EACJ,IAAK,GAAQ,CACZ,OAAQ,EAAI,MAAM,KAAlB,CACE,IAAK,QAAS,MAAO,GAAG,EAAI,MAAM,GAAG,IACrC,IAAK,OAAS,MAAO,GAAG,EAAI,MAAM,QAAU,EAAE,IAM9C,IAAK,MAAS,CACZ,IAAM,EAAI,IAAY,EAAI,KAC1B,OAAO,GAAK,KAAkB,oBAAX,GAAG,EAAE,GAC1B,CACF,CACF,CAAC,EACA,KAAK,GAAG,CACb,CAIA,IAAa,GAAwB,gCAWrC,SAAgB,GAAqB,EAAyD,CAC5F,GAAI,CAAC,GAAc,OAAO,OAAW,IAAa,OAAO,KACzD,GAAI,CACF,IAAM,EAAM,OAAO,aAAa,QAAQ,GAAwB,CAAU,EAC1E,GAAI,CAAC,EAAK,OAAO,KACjB,IAAM,EAAS,KAAK,MAAM,CAAG,EAC7B,GAAI,GAAU,MAAM,QAAQ,EAAO,OAAO,GAAK,MAAM,QAAQ,EAAO,KAAK,EACvE,MAAO,CACL,QAAS,EAAO,QAAQ,OAAQ,GAA4B,OAAO,GAAM,QAAQ,EACjF,MAAO,EAAO,MAAM,OAAQ,GAA4B,OAAO,GAAM,QAAQ,CAC/E,CAEJ,MAAQ,CAER,CACA,OAAO,IACT,CAGA,SAAgB,GAA4B,EAA2B,EAA6C,CAIlH,OAFI,EAAI,YAAoB,GACxB,GAAa,EAAU,MAAM,SAAS,EAAI,GAAG,EAAU,EAAU,QAAQ,SAAS,EAAI,GAAG,EACtF,CAAC,EAAI,aACd,CCpKA,SAAS,GAAiB,EAAwB,EAAuC,CACvF,GAAI,OAAO,GAAU,SAAU,OAAO,EACtC,IAAM,EAAU,EAAM,KAAK,EAC3B,GAAI,IAAY,GAAI,MAAO,GAC3B,IAAM,EAAW,OAAO,CAAO,EAC/B,GAAI,CAAC,OAAO,MAAM,CAAQ,EAAG,OAAO,EACpC,IAAM,EAAU,oBAAoB,KAAK,CAAO,EAChD,GAAI,EAAS,OAAO,WAAW,EAAQ,EAAE,EACzC,GAAI,OAAO,SAAa,KAAe,CAAC,EAAW,MAAO,GAC1D,IAAM,EAAQ,SAAS,cAAc,KAAK,EAC1C,EAAM,MAAM,QAAU,8CAA8C,EAAQ,GAC5E,EAAU,YAAY,CAAK,EAC3B,IAAM,EAAK,EAAM,sBAAsB,EAAE,OAEzC,OADA,EAAU,YAAY,CAAK,EACpB,OAAO,SAAS,CAAE,EAAI,EAAK,CACpC,CAyCA,SAAgB,GAAoB,CAClC,QACA,OACA,aACA,qBACA,SACA,WACA,aACA,qBACkD,CAClD,GAAM,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,CAAC,EACtC,CAAC,EAAiB,IAAA,EAAA,EAAA,UAA+B,CAAC,EAClD,CAAC,EAAgB,IAAA,EAAA,EAAA,UAA8B,CAAC,EAIhD,CAAC,EAAgB,IAAA,EAAA,EAAA,cAA4C,GAAiB,EAAQ,IAAI,CAAC,EAC3F,CAAC,EAAY,IAAA,EAAA,EAAA,UAAwD,IAAI,GAAK,EAC9E,CAAC,EAAqB,IAAA,EAAA,EAAA,UAAmC,EAAK,EAC9D,GAAA,EAAA,EAAA,QAA0B,EAAK,EAE/B,GAAA,EAAA,EAAA,QAAiC,IAAI,EACrC,GAAA,EAAA,EAAA,QAAmC,IAAI,EACvC,GAAA,EAAA,EAAA,QAAkC,CAAC,CAAC,EACpC,GAAA,EAAA,EAAA,QAAqC,IAAI,EACzC,GAAA,EAAA,EAAA,QAA6B,CAAC,EAC9B,GAAA,EAAA,EAAA,QAAsC,CAAC,CAAC,EAOxC,CAAC,IAAA,EAAA,EAAA,cACD,OAAO,eAAmB,IAAoB,KAC3C,IAAI,eAAgB,GAAY,CACrC,EAAe,GAAS,CACtB,IAAI,EAA4C,KAChD,IAAK,IAAM,KAAS,EAAS,CAC3B,IAAM,EAAK,EAAM,OACX,EAAM,OAAO,EAAG,QAAQ,KAAK,EACnC,GAAI,OAAO,MAAM,CAAG,EAAG,SAEvB,IAAM,EAAM,EAAQ,QAAQ,GAC5B,GAAI,IAAQ,IAAA,GAAW,SAGvB,IAAM,EAAM,EAAM,gBAAgB,GAC5B,EAAI,EAAM,KAAK,MAAM,EAAI,SAAS,EAAI,EAAG,aAC3C,EAAK,IAAI,CAAG,IAAM,IACtB,AAAW,IAAO,IAAI,IAAI,CAAI,EAC9B,EAAK,IAAI,EAAK,CAAC,EACjB,CACA,OAAO,GAAQ,CACjB,CAAC,CACH,CAAC,CACF,GACD,EAAA,EAAA,mBAAsB,GAAa,WAAW,EAAG,CAAC,CAAW,CAAC,GAE9D,EAAA,EAAA,qBAAsB,CACpB,IAAM,EAAK,EAAQ,QACnB,GAAI,CAAC,EAAI,OAGT,EAAmB,EAAG,YAAY,EAClC,EAAkB,EAAG,WAAW,EAKhC,IAAM,EAAW,IAAI,mBAAqB,CACxC,EAAmB,EAAG,YAAY,EAClC,EAAkB,EAAG,WAAW,CAClC,CAAC,EAED,OADA,EAAS,QAAQ,CAAE,MACN,EAAS,WAAW,CACnC,EAAG,CAAC,CAAC,EAEL,IAAM,GAAA,EAAA,EAAA,aAA4B,GAAqC,CACrE,IAAM,EAAK,EAAE,cAKb,EAAoB,QAAU,EAAG,UACjC,AACE,EAAa,UAAU,0BAA4B,CACjD,EAAa,QAAU,KACvB,EAAa,EAAoB,OAAO,CAC1C,CAAC,EAGC,GAAc,CAAC,EAAiB,SAC9B,EAAG,UAAY,EAAG,cAAgB,EAAG,aAAe,IACtD,EAAiB,QAAU,GAC3B,EAAuB,EAAI,EAC3B,EAAW,EAAE,YAAc,CACzB,EAAiB,QAAU,GAC3B,EAAuB,EAAK,CAC9B,CAAC,EAGP,EAAG,CAAC,EAAY,CAAiB,CAAC,GAElC,EAAA,EAAA,mBAAsB,CAChB,EAAa,SAAW,MAAM,qBAAqB,EAAa,OAAO,CAC7E,EAAG,CAAC,CAAC,GAEL,EAAA,EAAA,qBAAsB,CACpB,EAAQ,QAAU,CACpB,CAAC,GAKD,EAAA,EAAA,qBAAsB,CACpB,IAAM,EAAK,GAAiB,EAAQ,EAAQ,OAAO,EACnD,EAAmB,GAAU,IAAS,EAAK,EAAO,CAAG,CACvD,EAAG,CAAC,EAAQ,EAAgB,CAAe,CAAC,EAE5C,GAAM,CAAE,UAAS,gBAAA,EAAA,EAAA,aACT,GAAa,EAAM,EAAY,EAAoB,CAAc,EACvE,CAAC,EAAM,EAAY,EAAoB,CAAc,CACvD,GAEA,EAAA,EAAA,qBAAsB,CACpB,IAAM,EAAK,EAAQ,QACb,EAAc,EAAe,QAInC,GAHA,EAAe,QAAU,EAGrB,CAAC,GAAM,EAAY,SAAW,EAAG,OACrC,IAAM,EAAe,EAAG,UACxB,GAAI,GAAgB,EAAG,OAQvB,IAAM,EAAS,GAAe,EAAa,EADzB,EAAY,OAAS,CAC2B,EAClE,GAAI,GAAU,EAAM,OAAQ,OAC5B,IAAM,EAAS,EAAe,EAAY,GACpC,EAAS,EAAQ,GAAU,EAC7B,KAAK,IAAI,EAAS,CAAY,EAAI,KACpC,EAAG,UAAY,EACf,EAAoB,QAAU,EAC9B,EAAa,CAAM,EAEvB,EAAG,CAAC,EAAS,EAAM,MAAM,CAAC,EAE1B,IAAM,GAAA,EAAA,EAAA,aAAyE,CAC7E,SAAS,EAAe,EAAa,EAA2B,CAC9D,IAAM,EAAK,EAAQ,QACnB,GAAI,CAAC,EAAI,OACT,IAAM,EAAU,KAAK,IAAI,EAAG,CAAG,EAC3B,OAAO,EAAG,UAAa,WAAY,EAAG,SAAS,CAAE,IAAK,EAAS,SAAU,GAAY,MAAO,CAAC,EAC5F,EAAG,UAAY,CACtB,CACA,SAAS,EAAc,EAAe,EAAoC,CACxE,IAAM,EAAK,EAAQ,QACnB,GAAI,CAAC,GAAM,EAAM,SAAW,EAAG,OAC/B,IAAM,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,EAAO,EAAM,OAAS,CAAC,CAAC,EACjD,EAAS,EAAQ,IAAM,EACvB,GAAa,EAAQ,EAAI,IAAM,GAAU,EAGzC,EAAU,EAAU,SAAS,cAAgB,EAC7C,EAAS,KAAK,IAAI,EAAG,EAAG,aAAe,CAAO,EAC9C,EAAQ,GAAS,OAAS,QAC5B,EAAM,EAAS,EACf,IAAU,SAAU,IAAQ,EAAS,GAAa,EAC7C,IAAU,QAAO,GAAO,EAAS,GAC1C,EAAe,EAAK,GAAS,QAAQ,CACvC,CACA,MAAO,CACL,gBACA,YAAY,EAAK,EAAS,CACxB,IAAM,EAAI,EAAM,WAAW,EAAM,KAAS,EAAa,EAAW,EAAM,CAAG,EAAI,KAAS,CAAG,EACvF,GAAK,GAAG,EAAc,EAAG,CAAO,CACtC,EACA,YAAY,EAAS,CACnB,EAAe,EAAG,GAAS,QAAQ,CACrC,EACA,qBAAwB,EAAQ,OAClC,CACF,EAAG,CAAC,EAAO,EAAS,CAAU,CAAC,EAEzB,CAAE,aAAY,aAAA,EAAA,EAAA,aACZ,GAAgB,EAAS,EAAW,EAAiB,EAAU,EAAM,MAAM,EACjF,CAAC,EAAS,EAAW,EAAiB,EAAU,EAAM,MAAM,CAC9D,EAEA,MAAO,CACL,UACA,YACA,cACA,UACA,UACA,cACA,kBACA,iBACA,aACA,WACA,eACA,sBACA,WACF,CACF,CC1PA,SAAgB,GAAgB,CAC9B,QACA,SACA,cACA,eACA,qBAC0C,CAC1C,IAAM,EAAe,IAAiB,IAAA,GAChC,CAAC,EAAsB,IAAA,EAAA,EAAA,UAA0D,IAAI,GAAK,EAC1F,EAAwB,EAAe,EAAgB,EAE7D,SAAS,EAAe,EAA4B,CAC7C,GAAc,EAAwB,CAAI,EAC/C,IAAoB,CAAI,CAC1B,CAEA,SAAS,EAAgB,EAAsB,CAC7C,IAAM,EAAO,IAAI,IAAI,CAAqB,EACtC,EAAK,IAAI,CAAG,EAAG,EAAK,OAAO,CAAG,EAAQ,EAAK,IAAI,CAAG,EACtD,EAAe,CAAI,CACrB,CAEA,SAAS,GAAkB,CACzB,IAAM,EAAU,EAAM,KAAK,EAAM,IAAM,EAAO,EAAM,CAAC,CAAC,EAEtD,EADkB,EAAQ,MAAO,GAAM,EAAsB,IAAI,CAAC,CACnD,EAAY,IAAI,IAAQ,IAAI,IAAI,CAAO,CAAC,CACzD,CAKA,GAAM,CAAE,cAAa,iBAAA,EAAA,EAAA,aAA+B,CAClD,GAAI,CAAC,GAAe,EAAM,SAAW,EAAG,MAAO,CAAE,YAAa,GAAO,aAAc,EAAM,EACzF,IAAM,EAAM,EAAM,OAAO,EAAM,IAAM,EAAsB,IAAI,EAAO,EAAM,CAAC,CAAC,CAAC,EAE/E,MAAO,CAAE,YAAa,EAAK,aADd,CAAC,GAAO,EAAM,MAAM,EAAM,IAAM,EAAsB,IAAI,EAAO,EAAM,CAAC,CAAC,CAAC,CACzC,CAChD,EAAG,CAAC,EAAa,EAAO,EAAuB,CAAM,CAAC,EAEtD,MAAO,CAAE,wBAAuB,kBAAiB,kBAAiB,cAAa,cAAa,CAC9F,CCdA,SAAgB,GAAc,CAC5B,UACA,QACA,cACA,oBACA,yBACA,oBACA,mBACA,UACA,aACA,WACA,kBACA,kBACyC,CACzC,IAAM,EAAe,IAAsB,IAAA,GACrC,CAAC,EAAY,IAAA,EAAA,EAAA,UAA0B,EAAK,EAI5C,CAAC,EAAW,IAAA,EAAA,EAAA,UAAiD,CAAC,CAAC,EAE/D,CAAC,EAAqB,IAAA,EAAA,EAAA,cAAsD,CAChF,IAAM,EAAY,GAAqB,CAAiB,EACxD,OAAO,IAAI,KAAK,GAAW,CAAC,GAAG,OAAQ,GAAM,GAAyB,EAAG,CAAS,CAAC,EAAE,IAAK,GAAM,EAAE,GAAG,CAAC,CACxG,CAAC,EAKK,GAAA,EAAA,EAAA,QAAyC,IAAI,KAAK,GAAW,CAAC,GAAG,IAAK,GAAM,EAAE,GAAG,CAAC,CAAC,GAOzF,EAAA,EAAA,eAAgB,CACd,GAAI,EAAc,OAClB,IAAM,EAAO,GAAW,CAAC,EACnB,EAAc,IAAI,IAAI,EAAK,IAAK,GAAM,EAAE,GAAG,CAAC,EAC5C,EAAQ,EAAmB,QAC7B,EAAY,EAAY,OAAS,EAAM,KAC3C,GAAI,OAAgB,IAAM,KAAK,EAAa,GAAI,CAAC,EAAM,IAAI,CAAC,EAAG,CAAE,EAAY,GAAO,KAAO,EAC3F,GAAI,EAAW,OACf,EAAmB,QAAU,EAC7B,IAAM,EAAY,GAAqB,CAAiB,EACxD,EAAwB,GAAS,CAC/B,IAAM,EAAO,IAAI,IACjB,IAAK,IAAM,KAAK,EACV,EAAM,IAAI,EAAE,GAAG,EACb,EAAK,IAAI,EAAE,GAAG,GAAG,EAAK,IAAI,EAAE,GAAG,EAC1B,GAAyB,EAAG,CAAS,GAC9C,EAAK,IAAI,EAAE,GAAG,EAGlB,OAAO,CACT,CAAC,CACH,EAAG,CAAC,EAAS,EAAc,CAAiB,CAAC,GAM7C,EAAA,EAAA,eAAgB,CACd,GAAI,GAAgB,CAAC,GAAqB,OAAO,OAAW,IAAa,OACzE,IAAM,EAAO,GAAW,CAAC,EACrB,OAAK,SAAW,GAAK,EAAoB,OAAS,GACtD,GAAI,CACF,OAAO,aAAa,QAClB,GAAwB,EACxB,KAAK,UAAU,CAAE,QAAS,CAAC,GAAG,CAAmB,EAAG,MAAO,EAAK,IAAK,GAAM,EAAE,GAAG,CAAE,CAA4B,CAChH,CACF,MAAQ,CAER,CACF,EAAG,CAAC,EAAqB,EAAS,EAAc,CAAiB,CAAC,EAMlE,IAAM,EAA2B,EAAe,IAAI,IAAI,CAAiB,EAAI,EACvE,GAAc,GAAW,CAAC,GAAG,OAAQ,GAAM,EAAE,WAAW,EAAE,IAAK,GAAM,EAAE,GAAG,EAC1E,EAAgC,EAAW,KAAM,GAAM,CAAC,EAAY,IAAI,CAAC,CAAC,EAC5E,IAAI,IAAI,CAAC,GAAG,EAAa,GAAG,CAAU,CAAC,EACvC,EAEE,EAAa,CAAC,CAAC,GAAS,OACxB,EAAiB,EAAa,EAAS,OAAQ,GAAM,EAAiB,IAAI,EAAE,GAAG,CAAC,EAAI,CAAC,EAIrF,EAAsB,EACxB,EAAS,OAAQ,GAAM,CAAC,EAAE,eAAiB,CAAC,EAAiB,IAAI,EAAE,GAAG,CAAC,EAAE,OACzE,EAEE,EAAiB,EAAa,GADf,GAAe,EAAa,QAAU,KACL,GAAoB,EAAgB,CAAS,IAAM,IAAA,GAEnG,EAAmB,IAAqB,IAAS,GAAc,EAAS,KAAM,GAAM,CAAC,EAAE,cAAc,EAGrG,EAAa,EAAe,OAAQ,GAAM,EAAE,MAAM,OAAS,KAAK,EAChE,EAAS,EAAW,OAAS,EAC7B,EAAY,EAAW,IAAK,GAAM,EAAE,GAAG,EAAE,KAAK,GAAG,EAOjD,CAAC,EAAU,IAAA,EAAA,EAAA,UAAqD,CAAE,IAAK,EAAW,OAAM,CAAC,GAC3F,EAAS,MAAQ,GAAa,EAAS,QAAU,KACnD,EAAY,CAAE,IAAK,EAAW,OAAM,CAAC,EACjC,OAAO,KAAK,CAAS,EAAE,OAAS,GAAG,EAAa,CAAC,CAAC,GAWxD,IAAM,GAAA,EAAA,EAAA,iBAAqC,CACzC,IAAM,EAAO,EAAQ,QACrB,GAAI,CAAC,EAAM,OACX,IAAM,EAAW,IAAI,IACrB,EAAK,iBAAiB,gBAAgB,EAAE,QAAS,GAAS,CACxD,IAAM,EAAK,EACL,EAAM,EAAG,aAAa,cAAc,EAC1C,GAAI,CAAC,EAAK,OACV,IAAM,EAAc,EAAG,YAAc,EAAG,YACpC,EAAI,EAAG,YAIX,GAAI,GAAe,EAAG,kBAAmB,CACvC,IAAM,EAAK,iBAAiB,CAAE,EACxB,EAAU,WAAW,EAAG,WAAW,GAAK,EACxC,EAAW,WAAW,EAAG,YAAY,GAAK,EAWhD,GARI,IAAa,GAAK,GAQlB,EAAG,mBAAqB,CAAC,GAAe,EAAG,aAAe,EAAU,EAAW,EAAG,CACpF,IAAI,EAAU,IACV,EAAW,KAMf,GALA,EAAG,iBAAiB,GAAG,EAAE,QAAS,GAAM,CACtC,IAAM,EAAI,EAAE,sBAAsB,EAC9B,EAAE,KAAO,IAAS,EAAU,EAAE,MAC9B,EAAE,MAAQ,IAAU,EAAW,EAAE,MACvC,CAAC,EACG,EAAW,EAAS,CACtB,IAAM,EAAO,KAAK,KAAK,EAAW,CAAO,EAAI,EAAU,EACnD,EAAO,IAAG,EAAI,EACpB,CACF,CACF,CACI,GAAK,EAAS,IAAI,CAAG,GAAK,IAAI,EAAS,IAAI,EAAK,CAAC,CACvD,CAAC,EACG,EAAS,OAAS,GACtB,EAAc,GAAS,CACrB,IAAI,EAAU,GACR,EAAO,CAAE,GAAG,CAAK,EACvB,IAAK,GAAM,CAAC,EAAK,KAAQ,EAAU,CACjC,GAAI,GAAO,EAAG,SAEd,IAAM,EAAS,KAAK,IAAI,KAAK,KAAK,CAAG,EAAG,EAAK,WAAW,EACpD,GAAU,EAAK,IAAQ,KAAM,EAAK,GAAO,EAAQ,EAAU,GACjE,CACA,OAAO,EAAU,EAAO,CAC1B,CAAC,CACH,EAAG,CAAC,CAAO,CAAC,EAQN,CAAC,IAAA,EAAA,EAAA,cACL,OAAO,eAAmB,IAAc,KAAO,IAAI,mBAAqB,EAAiB,CAAC,CAC5F,EACM,GAAA,EAAA,EAAA,QAAmC,IAAI,GAAK,GAClD,EAAA,EAAA,mBAAsB,CAAE,GAAa,WAAW,EAAG,EAAY,QAAQ,MAAM,CAAG,EAAG,CAAC,CAAW,CAAC,GAShG,EAAA,EAAA,qBAAsB,CACpB,GAAI,CAAC,EAAQ,OACb,IAAM,EAAO,EAAQ,QAGrB,GAFI,CAAC,IACL,EAAiB,EACb,CAAC,GAAa,OAClB,IAAM,EAAU,IAAI,IAAa,EAAK,iBAAiB,gBAAgB,CAAC,EAClE,EAAW,EAAY,QAC7B,IAAK,IAAM,KAAM,EAAe,EAAQ,IAAI,CAAE,IAAK,EAAY,UAAU,CAAE,EAAG,EAAS,OAAO,CAAE,GAChG,IAAK,IAAM,KAAM,EAAc,EAAS,IAAI,CAAE,IAAK,EAAY,QAAQ,CAAE,EAAG,EAAS,IAAI,CAAE,EAC7F,EAAG,CAAC,EAAQ,EAAW,EAAW,EAAY,EAAU,EAAiB,EAAgB,EAAO,EAAkB,CAAW,CAAC,GAO9H,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,EAAQ,OACb,IAAI,EAAO,EACL,EAAO,0BAA4B,CACvC,EAAiB,EACjB,EAAO,0BAA4B,EAAiB,CAAC,CACvD,CAAC,EACD,UAAa,CAAE,qBAAqB,CAAI,EAAG,qBAAqB,CAAI,CAAG,CACzE,EAAG,CAAC,EAAQ,EAAW,EAAO,CAAgB,CAAC,EAK/C,IAAM,GAAA,EAAA,EAAA,iBAAuC,EAAa,CAAC,CAAC,EAAG,CAAC,CAAC,EAEjE,SAAS,EAAmB,EAAa,CAEvC,GAAI,GAAS,KAAM,GAAM,EAAE,MAAQ,CAAG,GAAG,YAAa,OACtD,IAAM,EAAO,IAAI,IAAI,CAAgB,EACrC,GAAI,EAAK,IAAI,CAAG,EAAG,CACjB,GAAI,EAAK,MAAQ,EAAG,OACpB,EAAK,OAAO,CAAG,CACjB,MACE,EAAK,IAAI,CAAG,EAEd,IAAM,EAAY,CAAC,GAAG,CAAI,EACrB,GAAc,EAAuB,CAAI,EAC9C,IAAyB,CAAS,CACpC,CAEA,MAAO,CACL,aACA,iBACA,iBACA,mBACA,mBACA,sBACA,aACA,gBACA,qBACA,oBACF,CACF,CC3PA,SAAgB,GAAW,CACzB,cACA,cACA,YACA,aACA,iBACA,aACA,eACA,OACA,SACA,YACA,UACA,WACmC,CAGnC,IAAM,GAAA,EAAA,EAAA,QAA4C,IAAI,EAChD,CAAC,EAAa,IAAA,EAAA,EAAA,UAAmD,IAAI,EAGrE,CAAC,EAAY,IAAA,EAAA,EAAA,UAAiD,IAAI,EAClE,GAAA,EAAA,EAAA,QAA8C,IAAI,EAClD,GAAA,EAAA,EAAA,QAAsB,CAAS,EAC/B,GAAA,EAAA,EAAA,QAAuB,CAAU,EACjC,GAAA,EAAA,EAAA,QAAqB,CAAW,EAChC,GAAA,EAAA,EAAA,QAA6B,CAAM,EACnC,GAAA,EAAA,EAAA,QAA8C,CAAS,EAGvD,GAAA,EAAA,EAAA,QAA2B,EAAI,EAC/B,GAAA,EAAA,EAAA,QAAqC,IAAI,EACzC,GAAA,EAAA,EAAA,QAAwB,EAAK,EAC7B,GAAA,EAAA,EAAA,QAAuC,IAAI,EAC3C,GAAA,EAAA,EAAA,QAAqB,CAAC,EACtB,GAAA,EAAA,EAAA,QAAqB,CAAC,EACtB,GAAA,EAAA,EAAA,QAAsC,IAAI,EAC1C,GAAA,EAAA,EAAA,QAA8B,EAAK,EAEnC,GAAA,EAAA,EAAA,QAA0C,IAAI,EAC9C,GAAA,EAAA,EAAA,QAAwB,CAAC,EACzB,GAAA,EAAA,EAAA,QAAsB,CAAC,EACvB,GAAA,EAAA,EAAA,QAAuB,CAAC,EAKxB,CAAC,IAAA,EAAA,EAAA,cACL,OAAO,OAAW,KAAe,OAAO,OAAO,YAAe,WAC1D,OAAO,WAAW,mBAAmB,EAAE,QACvC,EACN,GAEA,EAAA,EAAA,qBAAsB,CACpB,EAAa,QAAU,EACvB,EAAc,QAAU,EACxB,EAAY,QAAU,EACtB,EAAU,QAAU,EACpB,EAAc,QAAU,EACxB,EAAa,QAAU,CACzB,CAAC,EAMD,SAAS,EAAmB,EAAqC,CAC/D,EAAkB,QAAU,CAAC,CAAE,EAAE,OAAuB,QAAQ,oBAAoB,CACtF,CAEA,SAAS,EAAmB,EAAsB,EAAoC,CACpF,GAAI,GAAc,CAAC,EAAkB,QAAS,CAC5C,EAAE,eAAe,EACjB,MACF,CACA,EAAW,QAAU,EACrB,EAAe,CAAG,EACd,GAAa,EAAc,IAAI,CACrC,CAKA,SAAS,GAAgB,EAAmB,EAAW,EAAsC,CAC3F,IAAM,EAAU,EAAW,QAC3B,GAAI,GAAW,KAAM,OAAO,KAC5B,IAAM,EAAY,EAAK,QAAQ,CAAO,EAEtC,GAAI,IAAc,IAAM,GAAa,GAAa,GAAa,GAAoB,EAAW,CAAM,EAClG,OAAO,KAET,IAAM,EAAW,GAAsB,EAAG,EAAK,IAAK,EAAK,OAAQ,EAAU,CAAS,CAAC,EACrF,MAAO,CAAE,IAAK,EAAK,GAAY,UAAS,CAC1C,CAEA,SAAS,EAAmB,EAAmB,EAAoC,CACjF,EAAE,eAAe,EACjB,IAAM,EAAO,EAAE,cAAc,sBAAsB,EAC7C,EAAO,GAAgB,EAAW,EAAE,QAAS,CAAI,EACvD,EAAe,GACb,GAAM,MAAQ,GAAM,KAAO,GAAM,WAAa,GAAM,SAAW,EAAO,CACxE,CACF,CAEA,SAAS,GAAiB,CACxB,IAAM,EAAU,EAAW,QACrB,EAAS,EAAc,QACzB,GAAW,MAAQ,GAAU,EAAO,MAAQ,GAAS,IAAa,EAAS,CAAM,CACvF,CAEA,SAAS,GAAe,EAAoC,CAC1D,EAAE,eAAe,EACjB,EAAe,EACf,EAAc,IAAI,EAClB,EAAW,QAAU,KACrB,EAAe,IAAI,CACrB,CAEA,SAAS,GAAoB,CAE3B,EAAc,IAAI,EAClB,EAAW,QAAU,KACrB,EAAe,IAAI,CACrB,CAIA,SAAS,GAAkB,EAAmB,EAAoC,CAChF,EAAE,eAAe,EACjB,IAAM,EAAU,EAAW,QAC3B,GAAI,GAAW,KAAM,OACrB,IAAM,EAAY,EAAK,QAAQ,CAAO,EAKhC,EAAO,EAAE,cAAc,sBAAsB,EAC7C,EAAS,GAAqB,EAAW,EAAW,EAAE,QAAS,EAAK,IAAK,EAAK,MAAM,EACtF,GAAU,MAAM,IAAY,EAAW,CAAM,CACnD,CAEA,SAAS,IAAmB,CAC1B,EAAW,QAAU,KACrB,EAAe,IAAI,CACrB,CAMA,IAAM,IAAA,EAAA,EAAA,aAA8B,GAAc,CAChD,IAAM,EAAU,EAAW,QACrB,EAAO,EAAQ,QACrB,GAAI,GAAW,MAAQ,CAAC,EAAM,OAK9B,IAAM,EAAI,EAAa,QACnB,EAAY,QAAU,EAAe,QAAU,EAAc,QAAU,EACvE,EAAY,QACV,EAAK,SAAS,iBAAiB,EAAG,CAAC,EACnC,EAAQ,GAAM,EAAK,SAAS,CAAE,EAAI,EAAG,QAAqB,cAAc,EAAI,KAClF,GAAI,CAAC,EAAO,OACZ,IAAM,EAAY,OAAO,EAAM,QAAQ,KAAK,EAC5C,GAAI,OAAO,MAAM,CAAS,EAAG,OAC7B,IAAM,EAAY,EAAQ,QAAQ,QAAQ,CAAO,EAC3C,EAAO,EAAM,sBAAsB,EACzC,GAAI,EAAY,QAAS,CAEvB,IAAM,EAAK,EAAQ,QACb,EAAK,EAAU,QACrB,GAAI,IAAc,IAAM,GAAa,GAAa,GAAa,GAAoB,EAAW,CAAE,EAAG,CACjG,EAAc,IAAI,EAClB,MACF,CACA,IAAM,EAAW,GAAsB,EAAG,EAAK,IAAK,EAAK,OAAQ,EAAa,QAAQ,CAAS,CAAC,EAC1F,EAAuB,CAAE,IAAK,EAAG,GAAY,UAAS,EAC5D,EAAe,GAAU,GAAM,MAAQ,EAAK,KAAO,GAAM,WAAa,EAAK,SAAW,EAAO,CAAK,EAClG,MACF,CACA,IAAM,EAAS,GAAqB,EAAW,EAAW,EAAG,EAAK,IAAK,EAAK,MAAM,EAC9E,GAAU,MAAM,EAAa,UAAU,EAAW,CAAM,CAC9D,EAAG,CAAC,EAAS,CAAO,CAAC,EAGf,GAAA,EAAA,EAAA,iBAAsC,CAC1C,IAAM,EAAQ,EAAa,QACtB,IACL,EAAM,MAAM,UAAY,aAAa,EAAa,QAAQ,MAAM,EAAY,QAAU,EAAe,QAAQ,KAC/G,EAAG,CAAC,CAAC,EAIC,GAAA,EAAA,EAAA,iBAAmC,CACvC,IAAM,EAAO,EAAQ,QACrB,GAAI,CAAC,GAAQ,CAAC,EAAe,QAAS,CAAE,EAAc,QAAU,KAAM,MAAQ,CAC9E,IAAM,EAAO,EAAK,sBAAsB,EAClC,EAAI,EAAY,QAChB,EAAI,EAAY,QAElB,EAAK,EAIM,GAAK,EAAK,MAAQ,GAAK,EAAK,OAAS,GAAK,EAAK,KAAO,GAAK,EAAK,SAEzE,EAAI,EAAK,IAAM,GAAM,EAAK,CAAC,KAAK,IAAI,GAAI,KAAK,MAAM,EAAK,IAAM,GAAO,GAAK,CAAC,CAAC,EACvE,EAAI,EAAK,OAAS,KAAM,EAAK,KAAK,IAAI,GAAI,KAAK,MAAM,GAAK,EAAK,OAAS,KAAS,CAAC,CAAC,IAE1F,IAAO,IACT,EAAK,WAAa,EAClB,GAAe,CAAC,GAElB,EAAc,QAAU,sBAAsB,CAAc,CAC9D,EAAG,CAAC,GAAgB,CAAO,CAAC,EAEtB,GAAA,EAAA,EAAA,iBAAiC,CAUrC,GATI,EAAa,SAAW,OAAQ,aAAa,EAAa,OAAO,EAAG,EAAa,QAAU,MAC/F,OAAO,oBAAoB,YAAa,CAAe,EACvD,OAAO,oBAAoB,WAAY,CAAY,EACnD,OAAO,oBAAoB,cAAe,CAAY,EAClD,EAAc,SAAW,OAAQ,qBAAqB,EAAc,OAAO,EAAG,EAAc,QAAU,MAC1G,AAA2D,EAAa,WAA5C,EAAa,QAAQ,OAAO,EAA0B,MAElF,SAAS,KAAK,MAAM,YAAc,GAClC,SAAS,KAAK,MAAM,mBAAqB,GACrC,EAAe,UAGjB,EAAqB,QAAU,GAC/B,eAAiB,CAAE,EAAqB,QAAU,EAAO,EAAG,GAAG,EAG3D,EAAY,SAAS,CACvB,IAAM,EAAK,EAAW,QAChB,EAAS,EAAc,QACzB,GAAM,MAAQ,GAAU,EAAO,MAAQ,GAAI,EAAc,UAAU,EAAI,CAAM,CACnF,CAEF,EAAc,IAAI,EAClB,EAAe,QAAU,GACzB,EAAe,QAAU,KACzB,EAAW,QAAU,KACrB,EAAe,IAAI,CACrB,EAAG,CAAC,CAAC,EAEC,GAAA,EAAA,EAAA,aAA+B,GAAkB,CACrD,IAAM,EAAI,EAAE,QAAQ,GACf,KAGL,IAFA,EAAY,QAAU,EAAE,QACxB,EAAY,QAAU,EAAE,QACpB,CAAC,EAAe,QAAS,CAG3B,IAAM,EAAK,EAAe,QACtB,GAAM,MAAQ,KAAK,IAAI,EAAE,QAAU,CAAE,EAAI,IAAM,EAAa,SAAW,OACzE,aAAa,EAAa,OAAO,EACjC,EAAa,QAAU,MAEzB,MACF,CAII,EAAE,YAAY,EAAE,eAAe,EACnC,EAAkB,EAClB,GAAe,EAAE,OAAO,CANxB,CAOF,EAAG,CAAC,GAAgB,CAAiB,CAAC,EAEtC,SAAS,EAAoB,EAAsB,EAAqC,CAKtF,GAJI,CAAC,GAAe,CAAC,GAGjB,GAAc,CAAE,EAAE,OAAuB,QAAQ,oBAAoB,GACrE,EAAa,SAAW,MAAQ,EAAe,QAAS,OAC5D,IAAM,EAAI,EAAE,QAAQ,GACf,IACL,EAAe,QAAU,EAAE,QAC3B,EAAY,QAAU,EAAE,QACxB,EAAY,QAAU,EAAE,QACxB,OAAO,iBAAiB,YAAa,EAAiB,CAAE,QAAS,EAAM,CAAC,EACxE,OAAO,iBAAiB,WAAY,CAAY,EAChD,OAAO,iBAAiB,cAAe,CAAY,EACnD,EAAa,QAAU,OAAO,eAAiB,CAC7C,EAAa,QAAU,KACvB,EAAe,QAAU,GACzB,EAAW,QAAU,EACrB,EAAe,CAAG,EAClB,UAAU,UAAU,EAAE,EAKtB,SAAS,KAAK,MAAM,YAAc,OAClC,SAAS,KAAK,MAAM,mBAAqB,OACzC,GAAgB,CAAG,EACnB,AAAmC,EAAc,UAAU,sBAAsB,CAAc,CACjG,EAAG,CAAc,EACnB,CAKA,SAAS,GAAgB,EAAsB,CAC7C,IAAM,EAAO,EAAQ,QACrB,GAAI,CAAC,EAAM,OACX,IAAM,EAAM,EAAQ,QAAQ,QAAQ,CAAG,EACjC,EAAM,EAAK,cAA2B,gBAAgB,EAAI,GAAG,EACnE,GAAI,CAAC,EAAK,OACV,IAAM,EAAI,EAAI,sBAAsB,EACpC,EAAe,QAAU,EAAY,QAAU,EAAE,IACjD,EAAa,QAAU,EAAE,KACzB,EAAc,QAAU,EAAE,OAC1B,IAAM,EAAQ,EAAI,UAAU,EAAI,EAChC,EAAM,gBAAgB,YAAY,EAClC,EAAM,aAAa,kBAAmB,MAAM,EAC5C,EAAM,aAAa,cAAe,MAAM,EACxC,EAAM,UAAU,IAAI,EAAO,oBAAoB,EAC/C,OAAO,OAAO,EAAM,MAAO,CACzB,SAAU,QACV,KAAM,IACN,IAAK,IACL,MAAO,GAAG,EAAE,MAAM,IAClB,OAAQ,GAAG,EAAE,OAAO,IACpB,OAAQ,IACR,QAAS,IACT,cAAe,OAEf,OAAQ,IACR,WAAY,oBACZ,UAAW,qBACX,aAAc,8BAChB,CAAiC,EAGjC,EAAK,YAAY,CAAK,EACtB,EAAa,QAAU,EACvB,EAAkB,CACpB,EAGA,EAAA,EAAA,eAAgB,EAAc,CAAC,CAAY,CAAC,EAI5C,IAAM,GAAc,GAAe,EAEnC,SAAS,GAAgB,EAAe,EAAoC,CAI1E,IAAM,EAAU,GAAe,GAAY,MAAQ,EAAM,EAAW,SAAW,IAAA,GAC/E,MAAO,CAIL,YAAa,IAAe,CAAC,EAC7B,UAAY,IAAe,CAAC,GAAoB,IAAA,GAChD,WAAY,IAAe,IAAQ,EACnC,YAAa,IAAe,EAAa,EAAqB,IAAA,GAC9D,YAAa,GAAe,GAAM,EAAmB,EAAK,CAAC,EAAI,IAAA,GAC/D,WACE,EAAe,GAAM,EAAmB,EAAO,CAAC,EAC5C,EAAe,GAAM,GAAkB,EAAO,CAAC,EAC/C,IAAA,GACN,UAAW,EAAc,EAAoB,EAAc,GAAmB,IAAA,GAC9E,OAAQ,EAAc,GAAiB,IAAA,GACvC,aAAc,GAAe,GAAM,EAAoB,EAAK,CAAC,EAAI,IAAA,GACjE,aAAc,EACd,aAAc,GAAW,EAAO,IAAU,GAAK,EAAe,IAAA,EAChE,CACF,CAEA,SAAS,GAAkC,CAEzC,OADI,EAAqB,SAAW,EAAqB,QAAU,GAAc,IAC1E,EACT,CAEA,MAAO,CAAE,cAAa,eAAa,mBAAiB,wBAAuB,CAC7E,CClZA,SAAS,GAAoB,CAC3B,QACA,YACA,UACA,SAAS,OACT,qBAAqB,GACrB,WAAW,EACX,SAAS,EACT,aACA,cACA,aACA,aACA,oBACA,yBACA,oBACA,mBACA,aACA,oBAAoB,IACpB,YAAY,GACZ,cAAc,GACd,eACA,oBACA,cAAc,GACd,YACA,iBAAiB,IACjB,cAAc,GACd,eACA,UACA,aACA,eAAe,GACf,aAAa,GACb,cAAc,GACd,WAAW,GACX,YACA,SACA,aACA,OAAQ,EACR,GAAG,IACmB,EAA4C,CAClE,IAAM,IAAA,EAAA,EAAA,cACH,EAAS,IAAoC,EAAa,EAAW,EAAM,CAAK,EAAI,EACrF,CAAC,CAAU,CACb,EACM,IAAA,EAAA,EAAA,aAAqB,EAAM,KAAK,EAAM,IAAM,GAAO,EAAM,CAAC,CAAC,EAAG,CAAC,EAAO,EAAM,CAAC,EAC7E,IAAA,EAAA,EAAA,aACG,EAAe,EAAM,KAAK,EAAM,IAAM,EAAa,EAAM,CAAC,CAAC,EAAI,CAAC,EACvE,CAAC,EAAO,CAAY,CACtB,EACM,GAAA,EAAA,EAAA,aACH,GAAe,EAAU,EAAQ,EAAM,GAAI,CAAC,EAAI,GACjD,CAAC,EAAS,CAAK,CACjB,EAEM,EAAM,GAAoB,CAC9B,QAAO,QAAM,aAAY,qBAAoB,SAAQ,WACrD,aAAY,mBACd,CAAC,EACK,CAAE,UAAS,YAAW,cAAa,WAAS,WAAS,eAAa,aAAY,aAAa,EAE3F,GAAY,GAAgB,CAAE,QAAO,UAAQ,cAAa,eAAc,mBAAkB,CAAC,EAC3F,CAAE,0BAA0B,GAO5B,CACJ,aAAY,kBAAgB,kBAAgB,oBAAkB,oBAAkB,uBAChF,cAAY,iBAAe,sBAAoB,uBAPpC,GAAc,CACzB,UAAS,QAAO,cAAa,oBAAmB,yBAAwB,oBACxE,mBAAkB,UAAS,aAAY,YACvC,gBAAiB,EAAI,gBAAiB,eAAgB,EAAI,cAC5D,CAII,GAIJ,EAAA,EAAA,qBACE,OACO,CAAE,GAAG,EAAI,UAAW,qBAAmB,GAC9C,CAAC,EAAI,UAAW,EAAkB,CACpC,EAEA,IAAM,GAAO,GAAW,CACtB,cAAa,cAAa,YAAW,aAAY,iBAAgB,aAAY,eAC7E,QAAM,UAAQ,YAAW,UAAS,UACpC,CAAC,EAEK,GAAkB,OAAO,GAAe,SAAW,GAAG,EAAW,IAAM,EAEvE,GAAe,GAAc,CACjC,IAAM,EAAO,EAAM,GACb,EAAM,GAAO,EAAM,CAAC,EACpB,EAAc,GAAe,MAAQ,IAAQ,GAAgB,GAAsB,IAAI,CAAG,EAC1F,EAAY,GAAK,gBAAgB,EAAG,CAAG,EAE7C,OACE,EAAA,EAAA,KAAC,GAAD,CAEE,MAAO,EACP,IAAK,GAAQ,GACb,QAAS,GACO,kBACJ,aACC,cACb,MAAO,EACP,YAAe,CACT,GAAK,uBAAuB,GAChC,IAAa,EAAM,CAAC,CACtB,EACA,SAAU,EACV,aAAc,EAAa,EAAI,EAAI,IAAA,GACnC,aAAc,EAAa,IAAA,GAAY,EAAI,EAC3C,YAAa,EAAa,IAAA,GAAY,EAAM,OAC5C,QAAS,EAAa,MAAQ,WAC9B,oBAAqB,GACrB,GAAI,EACJ,uBAAwB,GAAY,cACpC,mBAAoB,GAAY,cAChC,aAAc,GAAY,IAC1B,SAAU,GAAY,aAErB,GACG,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,CACG,IACC,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,sBAAuB,GAAY,UAAU,EAClE,MAAO,GAAY,WACnB,KAAK,WACL,QAAU,GAAM,EAAE,gBAAgB,YAElC,EAAA,EAAA,KAAC,GAAD,CACE,SAAU,GAAsB,IAAI,CAAG,EACvC,aAAgB,GAAU,gBAAgB,CAAG,EAC7C,aAAW,YACZ,CAAA,CACE,CAAA,EAEN,GAAe,IAAK,IACnB,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,EAAO,gBAAiB,GAAY,IAAI,EACtD,MAAO,GAAY,KACnB,KAAK,WACL,eAAc,EAAI,MAAM,OAAS,MAAQ,EAAI,IAAM,IAAA,YAElD,EAAI,WAAW,EAAM,CAAC,CACpB,EAPE,EAAI,GAON,CACN,CACD,CAAA,CAAA,EACF,IAAY,EAAM,CAAC,CACb,EArDL,CAqDK,CAEhB,EAEM,GAAiC,CAAC,EACxC,IAAK,IAAI,EAAI,EAAY,GAAK,GAAU,IAAK,GAAY,KAAK,GAAY,CAAC,CAAC,EAM5E,IAAM,GAAe,GAAK,aAAe,KAAwC,GAAjC,GAAK,QAAQ,GAAK,WAAW,EAK7E,OAJI,IAAgB,IAAM,GAAe,GAAc,GAAe,KACpE,GAAY,KAAK,GAAY,EAAY,CAAC,GAI1C,EAAA,EAAA,MAAC,MAAD,CACE,GAAI,GACJ,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,EAAO,YAAa,GAAK,aAAe,MAAQ,EAAO,sBAAuB,EAAW,GAAY,IAAI,EACvH,MAAO,CAAE,SAAQ,GAAG,GAAO,GAAG,GAAY,IAAK,EAC/C,SAAU,EAAI,aACd,KAAM,EAAa,OAAS,OAC5B,gBAAe,EAAa,EAAM,OAAS,EAAI,IAAA,YAPjD,CASG,IACC,EAAA,EAAA,MAAC,MAAD,CACE,IAAK,EACL,WAAA,EAAA,EAAA,SAAc,EAAO,kBAAmB,GAAY,MAAM,EAC1D,MAAO,CAAE,oBAAqB,GAAgB,GAAI,GAAmB,CAAE,aAAc,EAAG,EAAI,CAAC,EAAI,GAAG,GAAY,MAAO,EACvH,KAAK,MACL,gBAAe,WALjB,CAOG,IACC,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,sBAAuB,GAAY,UAAU,EAClE,MAAO,GAAY,WACnB,KAAK,yBAEL,EAAA,EAAA,KAAC,GAAD,CACE,SAAU,GAAU,aAAe,GAAU,aAC7C,SAAU,GAAU,gBACpB,aAAW,iBACZ,CAAA,CACE,CAAA,EAEN,GAAe,IAAK,IACnB,EAAA,EAAA,KAAC,MAAD,CAEE,WAAA,EAAA,EAAA,SAAc,EAAO,sBAAuB,GAAY,UAAU,EAClE,MAAO,GAAY,WACnB,KAAK,eACL,eAAc,EAAI,MAAM,OAAS,MAAQ,EAAI,IAAM,IAAA,YAElD,EAAI,KACF,EAPE,EAAI,GAON,CACN,EACA,KACC,EAAA,EAAA,MAAC,MAAD,CAAK,UAAW,EAAO,kCAAvB,EACE,EAAA,EAAA,KAAC,GAAD,CACE,OAAQ,GACR,aAAc,GACd,MAAO,GAAM,MACb,SACE,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,yBAA0B,GAAY,aAAa,EACxE,MAAO,GAAY,uBAElB,EAAS,OAAQ,GAAQ,CAAC,EAAI,cAAc,EAAE,IAAK,IAClD,EAAA,EAAA,KAAC,GAAD,CAEE,WAAA,EAAA,EAAA,SAAc,EAAO,sBAAuB,GAAY,UAAU,EAClE,MAAO,GAAY,WACnB,SAAU,GAAiB,IAAI,EAAI,GAAG,EACtC,aAAgB,GAAmB,EAAI,GAAG,EAC1C,SAAU,EAAI,YACd,cAAe,YAEd,EAAI,aAAe,EAAI,KAChB,EATH,EAAI,GASD,CACX,CACE,CAAA,YAGP,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,WAAA,EAAA,EAAA,SAAc,EAAO,wBAAyB,GAAY,YAAY,EACtE,MAAO,GAAY,aACnB,aAAW,qCAEX,EAAA,EAAA,KAAC,EAAA,gBAAD,CACE,KAAM,EAAA,OACN,MAAO,GAAY,YACpB,CAAA,CACK,CAAA,CACI,CAAA,EACb,GAAsB,IACrB,EAAA,EAAA,KAAC,OAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,sBAAuB,GAAY,UAAU,EAClE,MAAO,GAAY,WACnB,2BAA0B,GAC1B,aAAY,GAAG,GAAoB,0BAElC,EACG,CAAA,CAEL,GAEJ,IAEN,GACC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAW,EAAO,iCACrB,EAAA,EAAA,KAAC,EAAD,CAAgB,UAAW,EAAO,kBAAqB,CAAA,CACpD,CAAA,GAEL,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,gBAAiB,GAAY,IAAI,EACtD,MAAO,CAAE,OAAQ,GAAa,GAAG,GAAY,IAAK,WAEjD,EACE,CAAA,EAEN,EAAI,sBACH,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,EAAO,4BAA6B,GAAY,gBAAgB,EAC9E,MAAO,GAAY,2BAEnB,EAAA,EAAA,KAAC,EAAD,CAAgB,UAAW,EAAO,kBAAqB,CAAA,CACpD,CAAA,CAEJ,GAET,CAGA,IAAM,GAAc,EAAA,QAAM,WAAW,EAAgB,sVE3TrD,SAAwB,GAAO,CAC7B,cAAc,EACd,YAAY,EACZ,iBAAmB,KACnB,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACW,CACd,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,UAA0C,IAAA,EAAS,EAC5D,CAAC,EAAkB,IAAA,EAAA,EAAA,UAAgC,EAAK,EACxD,CAAC,EAAU,IAAA,EAAA,EAAA,UAAwB,CAAW,EAC9C,GAAA,EAAA,EAAA,QAA6C,CAAC,CAAC,EAC/C,GAAA,EAAA,EAAA,QAAkD,IAAI,EAGxD,IAAgB,IAClB,EAAY,CAAW,EACvB,EAAoB,EAAI,IAG1B,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,EAAkB,OACvB,IAAM,EAAK,eAAiB,EAAoB,EAAK,EAAG,GAAG,EAC3D,UAAa,aAAa,CAAE,CAC9B,EAAG,CAAC,CAAgB,CAAC,GAGrB,EAAA,EAAA,eAAgB,CACd,EAAkB,SAAS,WAAW,EACtC,IAAM,EAAK,EAAS,QAAQ,GACvB,KAML,OALA,EAAU,EAAG,YAAY,EACzB,EAAkB,QAAU,IAAI,mBAAqB,CACnD,EAAU,EAAG,YAAY,CAC3B,CAAC,EACD,EAAkB,QAAQ,QAAQ,CAAE,MACvB,EAAkB,SAAS,WAAW,CACrD,EAAG,CAAC,EAAa,CAAS,CAAC,EAE3B,IAAM,EAAiC,CACrC,GAAI,IAAW,IAAA,GAAwC,CAAC,EAA7B,CAAE,OAAQ,GAAG,EAAO,GAAI,EACnD,GAAG,GAAY,KACf,GAAG,CACL,EAEA,OACE,EAAA,EAAA,KAAC,MAAD,CACE,GAAI,EACJ,WAAA,EAAA,EAAA,SAAc,GAAO,OAAQ,GAAY,KAAM,CAAS,EACxD,MAAO,YAEP,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SAAc,GAAO,uBAAwB,GAAY,SAAS,EAClE,MAAO,CACL,MAAO,GAAG,EAAY,IAAI,GAC1B,WAAY,IAAI,EAAc,IAAI,GAClC,GAAG,GAAY,SACjB,WAEC,MAAM,KAAK,CAAE,OAAQ,CAAU,GAAI,EAAG,KACrC,EAAA,EAAA,KAAC,MAAD,CAEE,IAAM,GAAQ,CAAE,EAAS,QAAQ,GAAS,CAAK,EAC/C,WAAA,EAAA,EAAA,SAAc,GAAO,cAAe,GAAY,IAAI,EACpD,MAAO,CACL,MAAO,GAAG,IAAM,EAAU,GAC1B,WAAY,GAAI,IAAM,EAAa,EAAM,GACzC,GAAG,GAAY,IACjB,YAEA,EAAA,EAAA,KAAC,MAAD,CACE,WAAA,EAAA,EAAA,SACE,EAAG,GAAO,yBAA0B,IAAgB,GAAS,CAAC,CAAiB,EAC/E,GAAY,WACd,EACA,MAAO,GAAY,YACnB,MAAO,IAAgB,EAAe,IAAA,GAAP,YAE9B,EAAW,CAAK,CACd,CAAA,CACF,EAnBE,aAAa,GAmBf,CACN,CACE,CAAA,CACF,CAAA,CAET,CCtFA,IAAM,GAAwB,GAAoC,CAChE,GAAU,EAAO,GAAG,QAAS,CAAE,KAAM,OAAQ,CAAC,CAChD,EAYqB,GAArB,cAGU,EAAA,kBAAqC,CAG7C,YACE,EACA,EAAgD,KAChD,EACA,CACA,MAAM,EAAU,EAAW,CAAE,GAAG,EAAS,cAAe,GAAS,eAAiB,EAAqB,CAAC,EACxG,KAAK,MAAA,EAAA,EAAA,qBAA2B,IAAI,CACtC,CACF,ECPqB,GAArB,cAGU,EAAA,aAAoB,0BAC8B,CACxD,cAAe,KACf,aAAc,KACd,aAAc,KACd,QAAS,KACT,OAAQ,KACR,SAAU,KACV,aAAc,GACd,QAAS,GACT,WAAY,GACZ,MAAO,EACT,EAEA,YAAY,EAAU,CACpB,MAAM,CAAK,EACX,GAAM,CAAE,iBAAkB,EAEtB,IACF,EAAc,MAAQ,EAAM,OAAS,GACrC,EAAc,SAAS,EACvB,EAAc,6BAA+B,CAAE,KAAK,YAAY,CAAG,CAAC,GAGtE,KAAK,MAAQ,CAAE,UAAW,GAAO,UAAW,EAAM,EAElD,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC/C,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC/C,KAAK,QAAU,KAAK,QAAQ,KAAK,IAAI,EACrC,KAAK,OAAS,KAAK,OAAO,KAAK,IAAI,EACnC,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,EACvC,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAI,EACjD,KAAK,SAAW,KAAK,SAAS,KAAK,IAAI,CACzC,CAEA,mBAA0B,CACxB,eAAiB,KAAK,SAAS,CAAE,UAAW,GAAO,UAAW,EAAM,CAAM,EAAG,CAAC,CAChF,CAEA,mBAAmB,EAAoB,CACrC,GAAM,CAAE,iBAAkB,KAAK,MAC3B,EAAU,eAAiB,GAAiB,EAAU,gBAAkB,GAC1E,EAAc,6BAA+B,CAAE,KAAK,YAAY,CAAG,CAAC,CAExE,CAEA,aAAa,EAA+B,CAC1C,GAAM,CAAE,gBAAiB,KAAK,MAC9B,KAAK,SAAS,CAAE,UAAW,EAAK,CAAiB,EAC7C,GAAc,EAAa,CAAK,CACtC,CAEA,aAAa,EAA+B,CAC1C,GAAM,CAAE,gBAAiB,KAAK,MAC9B,KAAK,SAAS,CAAE,UAAW,EAAM,CAAiB,EAC9C,GAAc,EAAa,CAAK,CACtC,CAEA,QAAQ,EAA+B,CACrC,GAAM,CAAE,WAAY,KAAK,MACzB,KAAK,SAAS,CAAE,UAAW,EAAK,CAAiB,EAC7C,GAAS,EAAQ,CAAK,CAC5B,CAEA,OAAO,EAA+B,CACpC,GAAM,CAAE,gBAAe,UAAW,KAAK,MACnC,IAAe,EAAc,QAAU,IAC3C,KAAK,SAAS,CAAE,UAAW,EAAM,CAAiB,EAC9C,GAAQ,EAAO,CAAK,CAC1B,CAEA,UAAoB,CAClB,GAAM,CAAE,eAAc,UAAS,iBAAkB,KAAK,MACtD,OAAO,EACF,EAAc,SAAW,EAAc,SAAS,EAChD,CAAC,GAAW,CAAC,CAAC,CACrB,CAEA,YAAsB,CACpB,GAAM,CAAE,aAAY,iBAAkB,KAAK,MAC3C,MAAO,CAAC,EAAE,GACJ,GAAiB,EAAc,WAAW,KAAM,GAAO,EAA+B,cAAgB,UAAU,EACxH,CAEA,eAAiC,CAC/B,GAAM,CAAE,eAAc,iBAAkB,KAAK,MACvC,CAAE,YAAW,aAAc,KAAK,MACtC,OACE,EAAA,EAAA,KAAC,GAAD,CACE,QAAQ,QACR,QAAS,EAAgB,EAAc,uBAAuB,EAAK,GAAgB,GACnF,UAAW,KAAK,SAAS,IAAM,GAAa,EAC7C,CAAA,CAEL,CAEA,SAAS,EAAuB,CAC9B,GAAM,CAAE,WAAU,iBAAkB,KAAK,MACzC,GAAI,EAAe,CACjB,IAAI,EAAe,EACf,GAAW,EAA+C,SAC5D,EAAgB,EAA+C,OAAO,OAExE,EAAc,IAAI,CAAY,CAChC,CACI,GAAU,EAAS,CAAM,CAC/B,CACF,EC9HA,SAAgB,GAId,EACA,CAAE,gBAAe,WAAU,aAAY,cAAa,iBAA+D,CAAC,EACtE,CAC9C,OAAA,EAAA,EAAA,mCACQ,IAAI,GAA2B,EAAU,KAAM,CAAE,gBAAe,cAAa,eAAc,CAAC,EAClG,EACA,CACF,CACF"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../package/common/accordion/accordion.types.ts","../package/common/accordion/accordion.module.pcss","../package/common/accordion/accordion.primary.module.pcss","../package/common/accordion/accordion.plain.module.pcss","../package/common/configProvider/configProvider.tsx","../package/common/configProvider/useComponentDefaults.ts","../package/common/accordion/accordion.tsx","../package/common/actionButtons/actionButtons.module.pcss","../package/common/button/button.module.pcss","../package/common/loading/spinnerLoading/spinnerLoading.module.pcss","../package/common/loading/spinnerLoading/spinnerLoading.tsx","../package/common/loading/spinnerLoading/index.ts","../package/common/button/button.types.ts","../package/common/ripple/ripple.module.pcss","../package/common/ripple/ripple.tsx","../package/common/button/button.tsx","../package/common/actionButtons/actionButtons.tsx","../package/common/interactableDiv/interactableDiv.module.pcss","../package/common/interactableDiv/interactableDiv.tsx","../package/common/interactableDiv/index.ts","../package/common/actionIcon/actionIcon.module.pcss","../package/common/actionIcon/actionIcon.tsx","../package/common/alert/alert.types.ts","../package/common/alert/alert.module.pcss","../package/common/alert/alert.tsx","../package/common/animatedLogo/animatedLogo.module.pcss","../package/common/animatedLogo/animatedLogo.tsx","../package/common/animatedText/animatedText.types.ts","../package/common/animatedText/animatedText.module.pcss","../package/common/animatedText/animatedText.tsx","../package/common/badge/badge.types.ts","../package/common/badge/badge.module.pcss","../package/common/badge/badge.tsx","../package/common/avatar/avatar.module.pcss","../package/common/avatar/avatar.tsx","../package/common/avatar/avatarGroup.tsx","../package/common/bodyEnd/bodyEnd.tsx","../package/common/floatingMenu/floatingMenu.module.pcss","../package/common/utils/scrollAncestors.ts","../package/common/floatingMenu/useFloatingPosition.ts","../package/common/hooks/useFocusBoundary.ts","../package/common/floatingMenu/floatingMenu.types.ts","../package/common/floatingMenu/floatingMenu.tsx","../package/common/breadcrumb/breadcrumb.module.pcss","../package/common/breadcrumb/breadcrumb.tsx","../package/common/buttonGroup/buttonGroup.types.ts","../package/common/buttonGroup/buttonGroup.module.pcss","../package/common/buttonGroup/buttonGroup.tsx","../package/common/card/card.types.ts","../package/common/card/card.module.pcss","../package/common/card/Card.tsx","../package/common/card/CardHeader.tsx","../package/common/card/CardMedia.tsx","../package/common/card/CardContent.tsx","../package/common/card/CardActions.tsx","../package/common/carousel/carousel.module.pcss","../package/common/carousel/carousel.tsx","../package/common/checkbox/checkbox.module.pcss","../package/common/checkbox/checkbox.tsx","../package/common/chip/chip.types.ts","../package/common/chip/chip.module.pcss","../package/common/chip/chip.tsx","../package/common/chip/chipContainer.tsx","../package/common/tooltip/tooltip.module.pcss","../package/common/tooltip/tooltip.tsx","../package/common/animatedIcon/animatedIcon.module.pcss","../package/common/animatedIcon/animatedIcon.tsx","../package/common/input/input.module.pcss","../package/common/input/input.types.ts","../package/common/input/input.tsx","../package/common/colorPicker/colorPicker.module.pcss","../package/common/colorPicker/colorPicker.tsx","../package/common/modal/modal.module.pcss","../package/common/modal/modal.tsx","../package/common/confirmModal/confirmModal.tsx","../package/common/datePicker/components/datePickerMonth/datePickerMonth.module.pcss","../package/services/localization.ts","../package/common/datePicker/dateFunctions.ts","../package/common/datePicker/components/datePickerMonth/datePickerMonth.tsx","../package/common/infiniteBlock/infiniteBlock.module.pcss","../package/common/infiniteBlock/infiniteBlock.tsx","../package/common/dropdown/dropdown.module.pcss","../package/common/dropdown/dropdown.tsx","../package/common/datePicker/datePicker.module.pcss","../package/common/datePicker/datePicker.tsx","../package/common/divider/divider.types.ts","../package/common/divider/divider.module.pcss","../package/common/divider/divider.tsx","../package/common/drawer/drawer.module.pcss","../package/common/drawer/drawer.tsx","../package/common/dropZone/dropZone.types.ts","../package/common/dropZone/dropZone.module.pcss","../package/common/dropZone/dropZone.tsx","../package/common/emptyState/emptyState.module.pcss","../package/common/emptyState/emptyState.tsx","../package/common/fab/components/fabBase/fabBase.module.pcss","../package/common/fab/components/fabBase/fabBase.tsx","../package/common/fab/fab.module.pcss","../package/common/fab/fab.tsx","../package/common/iconPicker/iconPicker.module.pcss","../package/common/iconPicker/iconPicker.tsx","../package/common/idleManager/idleManager.tsx","../package/common/inputDropdown/inputDropdown.module.pcss","../package/common/inputDropdown/inputDropdown.tsx","../package/common/kanbanBoard/kanbanBoard.module.pcss","../package/common/kanbanBoard/KanbanItem.tsx","../package/common/kanbanBoard/KanbanColumn.tsx","../package/common/kanbanBoard/kanbanBoard.utils.ts","../package/common/kanbanBoard/KanbanBoard.tsx","../package/services/klipy.ts","../package/common/searchInput/searchInput.module.pcss","../package/common/searchInput/searchInput.tsx","../package/common/klipyPicker/components/gifPreview/gifPreview.module.pcss","../package/common/klipyPicker/components/gifPreview/gifPreview.tsx","../package/common/klipyPicker/components/gifView/gifView.module.pcss","../package/common/klipyPicker/components/gifView/gifView.tsx","../package/common/klipyPicker/klipyPicker.module.pcss","../package/common/klipyPicker/klipyPicker.tsx","../package/common/loading/iconLoading/iconLoading.module.pcss","../package/common/loading/iconLoading/iconLoading.tsx","../package/common/loading/iconLoading/index.ts","../package/common/numberInput/numberInput.module.pcss","../package/common/numberInput/numberInput.tsx","../package/common/numberInput/index.ts","../package/common/optionPicker/optionPicker.module.pcss","../package/common/optionPicker/optionPicker.tsx","../package/hooks/useWindowSize.ts","../package/common/overscroll/overscroll.module.pcss","../package/common/overscroll/overscroll.tsx","../package/common/popover/popover.module.pcss","../package/common/popover/popover.types.ts","../package/common/popover/usePopoverPosition.ts","../package/common/popover/popover.tsx","../package/common/progressBar/progressBar.module.pcss","../package/common/progressBar/progressBar.tsx","../package/common/radioGroup/radioGroup.types.ts","../package/common/radioGroup/radioGroup.module.pcss","../package/common/radioGroup/radioGroup.tsx","../package/common/rating/rating.module.pcss","../package/common/rating/rating.tsx","../package/common/roomDrawer/roomDrawer.utils.ts","../package/common/roomDrawer/roomDrawer.module.pcss","../package/common/roomDrawer/roomDrawer.tsx","../package/common/roomViewer/roomViewer.module.pcss","../package/common/roomViewer/roomViewer.tsx","../package/common/scrollbarProvider/scrollbarProvider.module.pcss","../package/common/scrollbarProvider/scrollbarProvider.tsx","../package/common/scrollbarProvider/index.ts","../package/common/sectionHeader/sectionHeader.types.ts","../package/common/sectionHeader/sectionHeader.module.pcss","../package/common/sectionHeader/sectionHeader.tsx","../package/common/skeleton/skeleton.types.ts","../package/common/skeleton/skeleton.module.pcss","../package/common/skeleton/skeleton.tsx","../package/common/slider/slider.module.pcss","../package/common/slider/slider.tsx","../package/common/splitButton/splitButton.module.pcss","../package/common/splitButton/splitButton.tsx","../package/common/stepper/stepper.module.pcss","../package/common/stepper/stepper.types.ts","../package/common/stepper/stepper.tsx","../package/common/sticky/stickyStack.ts","../package/common/sticky/sticky.module.pcss","../package/common/sticky/sticky.tsx","../package/common/switch/switch.module.pcss","../package/common/switch/switch.tsx","../package/common/tabHeader/tabHeader.module.pcss","../package/common/tabHeader/tabHeader.tsx","../package/common/textarea/textarea.tsx","../package/common/themeProvider/defaultTheme.ts","../package/common/themeProvider/theme.module.pcss","../package/common/themeProvider/themeProvider.tsx","../package/common/themeProvider/useTheme.ts","../package/common/timeInput/timeFunctions.ts","../package/common/timeInput/components/clockDial/clockDial.module.pcss","../package/common/timeInput/components/clockDial/clockDial.tsx","../package/common/timeInput/timeInput.module.pcss","../package/common/timeInput/timeInput.tsx","../package/common/toast/toast.module.pcss","../package/common/hooks/useSwipeDismiss.ts","../package/common/toast/toast.tsx","../package/common/toast/toastService.ts","../package/common/toast/toastProvider.tsx","../package/common/virtualList/virtualList.module.pcss","../package/common/virtualList/virtualRow.tsx","../package/common/virtualList/virtualList.utils.ts","../package/common/virtualList/useVirtualWindow.ts","../package/common/virtualList/useSelection.ts","../package/common/virtualList/useColumns.ts","../package/common/virtualList/useRowDrag.ts","../package/common/virtualList/virtualList.tsx","../package/common/wizard/wizard.module.pcss","../package/common/wizard/wizard.tsx","../package/services/formValidation/FormValidatorGroupWithForm.tsx","../package/services/formValidation/validatableComponent.tsx","../package/services/formValidation/useFormValidatorGroup.ts"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum AccordionStyleType {\n Default = 'default',\n Primary = 'primary',\n Plain = 'plain',\n}\n\nexport type AccordionSlots = 'root' | 'header' | 'title' | 'icon' | 'body' | 'bodyInner';\n\nexport interface AccordionProps extends HtmlProps {\n title?: string;\n children?: ReactNode;\n expanded?: boolean | null;\n onHeaderClicked?: (id: string, isExpanded: boolean) => void;\n styleType?: AccordionStyleType;\n startOpen?: boolean;\n hideHeader?: boolean;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<AccordionSlots>;\n styles?: SlotStyles<AccordionSlots>;\n}\n","\n.accordion {\n transition: margin 0.2s;\n margin: -1px;\n color: var(--text-color);\n\n &-title {\n width: 100%;\n }\n\n &-active {\n margin: 10px 0;\n }\n\n &-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background: var(--background);\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n font-size: 16px;\n font-weight: 400;\n transition: all 0.2s;\n\n &-active {\n border: 1px solid var(--primary-color);\n background: var(--background-accent);\n border-radius: var(--default-border-radius) var(--default-border-radius) 0px 0px;\n }\n }\n\n &-body {\n overflow: hidden;\n transition: all 0.2s ease;\n position: relative;\n border-radius: 0px 0px var(--default-border-radius) var(--default-border-radius);\n border: 1px solid var(--border-color);\n border-top: none;\n border-bottom: none;\n\n &-inner {\n padding: 16px;\n }\n\n &-active {\n border: 1px solid var(--primary-color);\n border-top: none;\n }\n }\n\n &-icon {\n transition: transform 0.2s;\n transform: rotate(0deg);\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n color: var(--border-color);\n &-active {\n transform: rotate(180deg);\n }\n }\n}\n","\n.accordion {\n transition: margin 0.2s;\n margin: -1px;\n\n &-title {\n width: 100%;\n }\n\n &-active {\n margin: 10px 0;\n border: 2px solid var(--primary-color);\n border-radius: var(--default-border-radius);\n }\n\n &-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background: var(--background);\n border-radius: var(--default-border-radius);\n font-size: 16px;\n font-weight: 400;\n transition: all 0.2s;\n\n &-active {\n background: var(--background-accent);\n border-radius: var(--default-border-radius) var(--default-border-radius) 0px 0px;\n }\n }\n\n &-body {\n overflow: hidden;\n transition: all 0.2s ease;\n position: relative;\n border-radius: 0px 0px var(--default-border-radius) var(--default-border-radius);\n border-top: none;\n border-bottom: none;\n\n &-inner {\n padding: 16px;\n }\n\n &-active {\n border-top: none;\n }\n }\n\n &-icon {\n transition: transform 0.2s;\n transform: rotate(0deg);\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n color: var(--primary-color);\n &-active {\n transform: rotate(180deg);\n }\n }\n}\n","\n.accordion {\n transition: margin 0.2s;\n margin: -1px;\n\n &-title {\n width: 100%;\n }\n\n &-active {\n margin: 10px 0;\n }\n\n &-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n border-radius: var(--default-border-radius);\n font-size: 16px;\n font-weight: 400;\n transition: all 0.2s;\n\n &-active {\n border-radius: var(--default-border-radius) var(--default-border-radius) 0px 0px;\n }\n }\n\n &-body {\n overflow: hidden;\n transition: all 0.2s ease;\n position: relative;\n border-radius: 0px 0px var(--default-border-radius) var(--default-border-radius);\n\n &-inner {\n padding: 0px;\n }\n }\n\n &-icon {\n transition: transform 0.2s;\n transform: rotate(0deg);\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n color: var(--primary-color);\n &-active {\n transform: rotate(180deg);\n }\n }\n}\n","import React, { createContext, useContext, useMemo } from 'react';\nimport type { ComponentDefaults, ConfigProviderProps } from './configProvider.types';\n\nexport const ConfigContext = createContext<ComponentDefaults | null>(null);\n\n/**\n * Shallow-merge two default maps per component key, so nested ConfigProviders\n * compose: an inner provider's `Input` defaults extend (and override on\n * conflict) the outer provider's `Input` defaults rather than replacing them.\n */\nfunction mergeDefaults(\n parent: ComponentDefaults | null,\n own: ComponentDefaults | undefined,\n): ComponentDefaults {\n if (!parent) return own ?? {};\n if (!own) return parent;\n\n const merged: Record<string, object> = { ...parent };\n for (const key in own) {\n merged[key] = {\n ...(parent as Record<string, object>)[key],\n ...(own as Record<string, object>)[key],\n };\n }\n return merged as ComponentDefaults;\n}\n\nfunction ConfigProvider({ children, defaultProps }: ConfigProviderProps) {\n const parent = useContext(ConfigContext);\n const value = useMemo(() => mergeDefaults(parent, defaultProps), [parent, defaultProps]);\n\n return <ConfigContext.Provider value={value}>{children}</ConfigContext.Provider>;\n}\n\nexport default ConfigProvider;\n","import { useContext } from 'react';\nimport { ConfigContext } from './configProvider';\nimport type { ComponentDefaults } from './configProvider.types';\n\n/**\n * Merge global defaults from the nearest `ConfigProvider` **under** the props\n * the caller actually passed: an explicit prop always wins, a global default\n * fills in only props the caller left `undefined`, and the component's own\n * built-in default (its destructuring default) applies when neither is set.\n *\n * Call it at the very top of a component and destructure from the result\n * instead of from the raw props:\n *\n * ```tsx\n * function Input(props: InputProps) {\n * const { alwaysFloatLabel = false, ... } = useComponentDefaults('Input', props);\n * }\n * ```\n */\nexport function useComponentDefaults<P extends object>(\n component: keyof ComponentDefaults,\n props: P,\n): P {\n const ctx = useContext(ConfigContext);\n const defaults = ctx?.[component];\n if (!defaults) return props;\n\n const merged: Record<string, unknown> = { ...defaults };\n for (const key in props) {\n const value = (props as Record<string, unknown>)[key];\n if (value !== undefined) merged[key] = value;\n }\n return merged as P;\n}\n","import React, { useState, useEffect, useRef, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronDown as arrowIcon } from '@fortawesome/free-solid-svg-icons';\n\nimport { AccordionStyleType, type AccordionProps } from './accordion.types';\n\nimport defaultStyles from './accordion.module.pcss';\nimport primaryStyles from './accordion.primary.module.pcss';\nimport plainStyles from './accordion.plain.module.pcss';\nimport { useComponentDefaults } from '../configProvider';\n\nconst STYLES_BY_TYPE: Record<AccordionStyleType, typeof defaultStyles> = {\n [AccordionStyleType.Default]: defaultStyles,\n [AccordionStyleType.Primary]: primaryStyles,\n [AccordionStyleType.Plain]: plainStyles,\n};\n\nfunction Accordion(props: AccordionProps): ReactElement {\n const {\n id = '',\n title = '',\n children = null,\n expanded = null,\n onHeaderClicked = () => {},\n styleType = AccordionStyleType.Default,\n startOpen = false,\n hideHeader = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Accordion', props);\n const s = STYLES_BY_TYPE[styleType];\n const bodyRef = useRef<HTMLDivElement>(null);\n\n const [isExpanded, setIsExpanded] = useState(expanded ?? startOpen);\n const [bodyHeight, setBodyHeight] = useState<number | null>(null);\n\n // Sync controlled expanded prop\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n if (expanded !== null) setIsExpanded(expanded);\n }, [expanded]);\n\n // Measure body height via ResizeObserver\n useEffect(() => {\n const el = bodyRef.current;\n if (!el) return;\n const observer = new ResizeObserver(() => setBodyHeight(el.offsetHeight));\n observer.observe(el);\n return () => observer.unobserve(el);\n }, []);\n\n function toggleExpanded() {\n const next = !isExpanded;\n onHeaderClicked(id, next);\n if (expanded === null) setIsExpanded(next);\n }\n\n const headerHeight = 24;\n const headerStyle = { height: `${isExpanded ? headerHeight + headerHeight / 3 : headerHeight}px` };\n const bodyStyle = { height: isExpanded ? (bodyHeight ?? 'auto') : '0px' };\n\n return (\n <div {...rest} id={id || undefined} className={cx(s.accordion, isExpanded && s.accordionActive, className, classNames?.root)} style={{ ...style, ...slotStyles?.root }}>\n {!hideHeader && (\n <div\n className={cx(s.accordionHeader, isExpanded && s.accordionHeaderActive, classNames?.header)}\n style={{ ...headerStyle, ...slotStyles?.header }}\n onClick={toggleExpanded}\n role=\"button\"\n tabIndex={0}\n onKeyDown={({ key }) => { if (key === 'Enter') toggleExpanded(); }}\n >\n <div className={cx(s.accordionTitle, classNames?.title)} style={slotStyles?.title}>{title}</div>\n <FontAwesomeIcon\n icon={arrowIcon}\n className={cx(s.accordionIcon, isExpanded && s.accordionIconActive, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </div>\n )}\n <div\n className={cx(s.accordionBody, isExpanded && s.accordionBodyActive, classNames?.body)}\n style={{ ...bodyStyle, ...slotStyles?.body }}\n >\n <div className={cx(s.accordionBodyInner, classNames?.bodyInner)} style={slotStyles?.bodyInner} ref={bodyRef}>\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nexport default Accordion;\n","\n.actionButtons {\n display: flex;\n gap: var(--spacing-m);\n\n @media (--mq-mobile) {\n flex-direction: column;\n }\n\n &-margin {\n margin-top: var(--spacing-l);\n }\n}\n",".button {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n font-size: 16px;\n background: transparent;\n color: var(--text-color);\n border: 1px solid transparent;\n padding: 0;\n font-family: var(--default-font);\n border-radius: var(--default-border-radius);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n position: relative;\n overflow: hidden;\n\n &-notAllowed {\n cursor: not-allowed;\n filter: opacity(0.8);\n }\n\n &-loading-icon {\n width: 100% !important;\n height: 100% !important;\n }\n\n &-content {\n position: relative;\n white-space: break-spaces;\n\n div {\n text-overflow: ellipsis;\n overflow: hidden;\n }\n }\n\n &-loading {\n visibility: hidden;\n\n &-container {\n position: absolute;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n }\n\n &-withIcon {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-s);\n }\n\n &-style {\n &-default {\n background: var(--button-default-background, transparent);\n color: var(--button-default-color, var(--text-color));\n border: var(--button-default-border, 1px solid transparent);\n }\n\n &-primary {\n background: var(--primary-color);\n color: var(--text-color);\n color: var(--text-on-primary);\n\n .button-loading-icon {\n stroke: var(--text-on-primary);\n }\n }\n\n &-delete {\n background: var(--error-color);\n color: var(--text-on-delete);\n\n .button-loading-icon {\n stroke: var(--text-on-delete);\n }\n }\n }\n\n &-background {\n display: block;\n padding: 8px 12px;\n }\n\n &-size {\n &-default {\n font-size: 16px;\n }\n\n &-small {\n /* Small button is same as default for now */\n font-size: 12px;\n\n &-background {\n display: block;\n padding: 0px;\n }\n }\n\n &-medium {\n /* Medium button is same as default for now */\n font-size: 16px;\n }\n\n &-large {\n /* Large button is same as default for now */\n font-size: 20px;\n }\n }\n}\n",".spinner-loading {\n width: 70px;\n height: 70px;\n\n circle {\n stroke-dasharray: 283;\n stroke-dashoffset: 281;\n stroke-linecap: round;\n animation:\n animate-spinner 2s cubic-bezier(0.89, 0.01, 0.12, 1) infinite,\n spin 3s linear infinite;\n transform-origin: center;\n }\n\n @keyframes animate-spinner {\n 0% {\n stroke-dashoffset: 281;\n }\n\n 50% {\n stroke-dashoffset: 0;\n }\n\n 100% {\n stroke-dashoffset: -281;\n }\n }\n\n @keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(360deg);\n }\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport styles from './spinnerLoading.module.pcss';\n\ninterface Properties {\n className?: string | undefined;\n}\n\nfunction SpinnerLoading({ className }: Properties): ReactElement {\n return (\n <svg\n data-testid=\"spinner\"\n className={cx(styles.spinnerLoading, className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 100 100\"\n fill=\"none\"\n stroke=\"var(--primary-color)\"\n >\n <circle cx=\"50\" cy=\"50\" r=\"45\" strokeWidth=\"10\" />\n </svg>\n );\n}\n\nSpinnerLoading.defaultProps = {\n className: undefined,\n};\n\nexport default SpinnerLoading;\n","import SpinnerLoading from './spinnerLoading';\n\nexport default SpinnerLoading;\n","import type { CSSProperties } from 'react';\nimport type { IconDefinition } from '@fortawesome/free-solid-svg-icons';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum ButtonStyleType {\n Primary = 'primary',\n Default = 'default',\n Delete = 'delete',\n}\n\nexport enum ButtonSize {\n Default = 'default',\n Small = 'small',\n Medium = 'medium',\n Large = 'large',\n}\n\nexport enum ButtonType {\n Button = 'button',\n Reset = 'reset',\n Submit = 'submit',\n}\n\nexport type ButtonSlots = 'background' | 'content' | 'loadingContainer' | 'label';\n\nexport interface ButtonProps extends HtmlProps {\n className?: string;\n style?: CSSProperties;\n type?: ButtonType;\n styleType?: ButtonStyleType;\n size?: ButtonSize;\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => Promise<void> | void;\n children?: React.ReactNode;\n icon?: IconDefinition;\n isLoading?: boolean;\n disabled?: boolean;\n title?: string;\n ref?: React.Ref<HTMLButtonElement>;\n classNames?: SlotClassNames<ButtonSlots>;\n styles?: SlotStyles<ButtonSlots>;\n}\n",".ripple {\n background: rgba(255, 255, 255, 0.2);\n border-radius: 1000px;\n width: 100%;\n aspect-ratio: 1;\n position: absolute;\n left: 0;\n top: 0;\n transform: translate(-50%, -50%) scale(0);\n animation: ripple var(--ripple-animation-length) linear forwards;\n\n &-container {\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n border-radius: inherit;\n user-select: none;\n pointer-events: none;\n }\n\n @keyframes ripple {\n to {\n transform: translate(-50%, -50%) scale(4);\n opacity: 0;\n }\n }\n}\n","import React, { useRef, useEffect, useImperativeHandle, forwardRef } from 'react';\n\nimport styles from './ripple.module.pcss';\nimport type { RippleProps, RippleHandle } from './ripple.types';\n\nexport type { RippleProps, RippleHandle };\n\nconst Ripple = forwardRef<RippleHandle, RippleProps>(function Ripple({\n disabled = false,\n children,\n className,\n style,\n overflowHidden = true,\n rippleAnimationLength = 0.6,\n rippleBackground = 'rgba(255, 255, 255, 0.2)',\n manualOnly = false,\n ...rest\n}, ref) {\n const containerRef = useRef<HTMLDivElement>(null);\n const addRippleRef = useRef<((event: MouseEvent) => void) | null>(null);\n\n function spawnRipple(x: number, y: number) {\n if (disabled) return;\n const ripple = document.createElement('div');\n ripple.style.left = `${x}px`;\n ripple.style.top = `${y}px`;\n ripple.style.background = rippleBackground;\n ripple.classList.add(styles.ripple);\n containerRef.current?.appendChild(ripple);\n setTimeout(() => {\n containerRef.current?.removeChild(ripple);\n }, rippleAnimationLength * 1000 + 50);\n }\n\n function addRipple(event: MouseEvent | React.MouseEvent) {\n if (!containerRef.current) return;\n const pos = containerRef.current.getBoundingClientRect();\n spawnRipple(event.clientX - pos.x, event.clientY - pos.y);\n }\n\n useImperativeHandle(ref, () => ({\n addRipple() {\n const el = containerRef.current;\n if (!el) return;\n spawnRipple(el.offsetWidth / 2, el.offsetHeight / 2);\n },\n }));\n\n useEffect(() => {\n addRippleRef.current = addRipple;\n });\n\n useEffect(() => {\n if (children !== undefined || manualOnly) return;\n const parent = containerRef.current?.parentElement;\n if (!parent) return;\n const handler = (e: MouseEvent) => addRippleRef.current?.(e);\n parent.addEventListener('click', handler);\n return () => parent.removeEventListener('click', handler);\n }, [children, manualOnly]);\n\n const containerStyle: React.CSSProperties & { '--ripple-animation-length'?: string } = {\n '--ripple-animation-length': `${rippleAnimationLength}s`,\n };\n\n if (children !== undefined) {\n return (\n <div\n {...rest}\n className={className}\n onClick={manualOnly ? undefined : (e) => addRipple(e)}\n style={{\n position: 'relative',\n ...style,\n }}\n >\n {children}\n <div\n className={styles.rippleContainer}\n ref={containerRef}\n style={{\n overflow: overflowHidden ? 'hidden' : 'visible',\n ...containerStyle,\n }}\n />\n </div>\n );\n }\n\n return (\n <div\n className={styles.rippleContainer}\n ref={containerRef}\n style={{\n overflow: overflowHidden ? 'hidden' : 'visible',\n ...containerStyle,\n }}\n />\n );\n});\n\nexport default Ripple;\n","import cx from 'classnames';\nimport type { ReactElement } from 'react';\n\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport styles from './button.module.pcss';\nimport SpinnerLoading from 'components/common/loading/spinnerLoading';\nimport { ButtonStyleType, ButtonSize, ButtonType } from './button.types';\nimport type { ButtonProps } from './button.types';\nimport Ripple from '../ripple';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_STYLE: Record<ButtonStyleType, string> = {\n default: styles.buttonStyleDefault,\n primary: styles.buttonStylePrimary,\n delete: styles.buttonStyleDelete,\n};\n\nconst CLASS_BY_SIZE: Record<ButtonSize, string> = {\n default: styles.buttonSizeDefault,\n small: styles.buttonSizeSmall,\n medium: styles.buttonSizeMedium,\n large: styles.buttonSizeLarge,\n};\n\nfunction Button(props: ButtonProps): ReactElement {\n const {\n className,\n style,\n type = ButtonType.Button,\n styleType = ButtonStyleType.Default,\n size = ButtonSize.Default,\n onClick = (): void => {},\n children,\n icon,\n isLoading = false,\n disabled = false,\n title = undefined,\n ref,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Button', props);\n return (\n <button\n {...rest}\n className={cx(\n styles.button,\n CLASS_BY_STYLE[styleType],\n CLASS_BY_SIZE[size],\n {\n [styles.buttonNotAllowed]: isLoading || disabled,\n },\n className\n )}\n style={style}\n type={type}\n onClick={onClick}\n disabled={disabled || isLoading}\n title={title}\n ref={ref}\n >\n <Ripple disabled={isLoading || disabled}>\n <div className={cx(styles.buttonBackground, classNames?.background)} style={slotStyles?.background}>\n <div className={cx(styles.buttonContent, classNames?.content)} style={slotStyles?.content}>\n {isLoading ? (\n <div className={cx(styles.buttonLoadingContainer, classNames?.loadingContainer)} style={slotStyles?.loadingContainer}>\n <SpinnerLoading className={styles.buttonLoadingIcon} />\n </div>\n ) : null}\n <div\n className={cx(classNames?.label, {\n [styles.buttonLoading]: isLoading,\n [styles.buttonWithIcon]: !!icon,\n })}\n style={slotStyles?.label}\n >\n {icon ? <FontAwesomeIcon icon={icon} /> : null}\n {children}\n </div>\n </div>\n </div>\n </Ripple>\n </button>\n );\n}\n\nButton.StyleType = ButtonStyleType;\nButton.Size = ButtonSize;\nButton.Type = ButtonType;\n\nexport default Button;\n","import cx from 'classnames';\n\nimport styles from './actionButtons.module.pcss';\nimport Button, { ButtonStyleType, ButtonType } from '../button';\nimport { useComponentDefaults } from '../configProvider';\nimport { ActionButtonsProps } from './actionButtons.types';\n\nexport default function ActionButtons(props: ActionButtonsProps) {\n const {\n onSubmit = () => null,\n onClose = () => null,\n submitLabel = 'Save',\n cancelLabel = 'Cancel',\n submitButtonStyle = ButtonStyleType.Primary,\n isSubmitButtonLoading = false,\n isSubmitButtonDisabled = false,\n submitButtonIcon = undefined,\n cancelButtonStyle = ButtonStyleType.Default,\n isCancelButtonLoading = false,\n isCancelButtonDisabled = false,\n cancelButtonIcon = undefined,\n hidePrimaryButton = false,\n hideSecondaryButton = false,\n noMargin = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('ActionButtons', props);\n return (\n <div\n {...rest}\n className={cx(styles.actionButtons, !noMargin && styles.actionButtonsMargin, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {!hidePrimaryButton && (\n <Button\n isLoading={isSubmitButtonLoading}\n disabled={isSubmitButtonDisabled}\n styleType={submitButtonStyle}\n type={ButtonType.Submit}\n onClick={onSubmit}\n className={classNames?.submitButton}\n style={slotStyles?.submitButton}\n icon={submitButtonIcon}\n >\n {submitLabel}\n </Button>\n )}\n {!hideSecondaryButton && (\n <Button\n isLoading={isCancelButtonLoading}\n disabled={isCancelButtonDisabled}\n onClick={onClose}\n styleType={cancelButtonStyle}\n className={classNames?.cancelButton}\n style={slotStyles?.cancelButton}\n icon={cancelButtonIcon}\n >\n {cancelLabel}\n </Button>\n )}\n </div>\n );\n}",".interactableDiv {\n}\n","import cx from 'classnames';\nimport React, {\n ReactNode,\n useCallback,\n type KeyboardEvent,\n type KeyboardEventHandler,\n type MouseEvent,\n type MouseEventHandler,\n type ReactElement,\n} from 'react';\n\nimport styles from './interactableDiv.module.pcss';\nimport type { HtmlProps } from '../types/baseProps.types';\n\ninterface Properties extends HtmlProps {\n className?: string | undefined;\n children?: ReactNode | undefined;\n onClick?: MouseEventHandler<HTMLDivElement> | undefined;\n onMouseDown?: MouseEventHandler<HTMLDivElement> | undefined;\n onKeyDown?: KeyboardEventHandler<HTMLDivElement> | undefined;\n style?: React.CSSProperties | undefined;\n tabIndex?: number | null;\n title?: string | undefined;\n}\n\nconst InteractableDiv = React.forwardRef<HTMLDivElement, Properties>(\n ({ className, children, onClick, onMouseDown, onKeyDown, tabIndex = 0, title, ...props }, ref): ReactElement => {\n const onKeyDownHandler = useCallback(\n (e: KeyboardEvent<HTMLDivElement> | MouseEvent<HTMLDivElement>) => {\n if ((e as React.KeyboardEvent).key === 'Enter') {\n onClick?.(e as MouseEvent<HTMLDivElement>);\n }\n onKeyDown?.(e as KeyboardEvent<HTMLDivElement>);\n },\n [onClick, onKeyDown]\n );\n\n return (\n <div\n className={cx(styles.interactableDiv, className)}\n onClick={onClick}\n onMouseDown={onMouseDown}\n tabIndex={tabIndex ?? undefined}\n role=\"button\"\n onKeyDown={onKeyDownHandler}\n ref={ref}\n title={title}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nInteractableDiv.displayName = 'InteractableDiv';\n\nexport default InteractableDiv;\n","import InteractableDiv from './interactableDiv';\n\nexport default InteractableDiv;\n",".actionIcon {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 4px;\n &:hover {\n filter: brightness(0.8);\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport type { ReactElement } from 'react';\n\nimport InteractableDiv from '../interactableDiv';\nimport type { ActionIconProps } from './actionIcon.types';\nimport styles from './actionIcon.module.pcss';\n\nfunction ActionIcon({\n icon,\n className = '',\n style,\n title = '',\n onClick = () => {},\n classNames,\n styles: slotStyles,\n ...rest\n}: ActionIconProps): ReactElement {\n return (\n <InteractableDiv\n {...rest}\n className={cx(styles.actionIcon, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n title={title}\n onClick={onClick}\n >\n <FontAwesomeIcon\n icon={icon}\n className={classNames?.icon}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </InteractableDiv>\n );\n}\n\nexport default ActionIcon;\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { IconDefinition } from '@fortawesome/fontawesome-svg-core';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum AlertStyleType {\n Default = 'default',\n Info = 'info',\n Success = 'success',\n Warn = 'warn',\n Error = 'error',\n}\n\nexport type AlertSlots = 'root' | 'icon' | 'content' | 'title' | 'description' | 'closeButton';\n\nexport interface AlertProps extends HtmlProps {\n title?: ReactNode;\n children?: ReactNode;\n styleType?: AlertStyleType;\n icon?: IconDefinition;\n hideIcon?: boolean;\n onClose?: () => void;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<AlertSlots>;\n styles?: SlotStyles<AlertSlots>;\n}\n",".alert {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 14px;\n border-radius: var(--default-border-radius);\n background: var(--background-accent);\n color: var(--text-color);\n font-family: var(--default-font);\n box-sizing: border-box;\n\n &-icon {\n flex-shrink: 0;\n margin-top: 2px;\n font-size: 15px;\n }\n\n &-content {\n flex: 1;\n font-size: 14px;\n line-height: 1.4;\n }\n\n &-title {\n font-weight: var(--header-font-weight, 600);\n\n &:not(:only-child) {\n margin-bottom: 2px;\n }\n }\n\n &-description {\n color: var(--text-dark);\n }\n\n &-closeButton {\n flex-shrink: 0;\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 0;\n color: var(--text-dark);\n font-size: 13px;\n opacity: 0.6;\n transition: opacity 0.15s;\n margin-top: 2px;\n\n &:hover {\n opacity: 1;\n }\n }\n\n &-style {\n &-default {\n border-left: 3px solid var(--primary-color);\n\n .alert-icon {\n color: var(--primary-color);\n }\n }\n\n &-info {\n border-left: 3px solid var(--info-color, #3b82f6);\n\n .alert-icon {\n color: var(--info-color, #3b82f6);\n }\n }\n\n &-success {\n border-left: 3px solid var(--success-color);\n\n .alert-icon {\n color: var(--success-color);\n }\n }\n\n &-warn {\n border-left: 3px solid var(--warn-color);\n\n .alert-icon {\n color: var(--warn-color);\n }\n }\n\n &-error {\n border-left: 3px solid var(--error-color, #ef4444);\n\n .alert-icon {\n color: var(--error-color, #ef4444);\n }\n }\n }\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faCircleInfo,\n faCircleCheck,\n faCircleXmark,\n faTriangleExclamation,\n faBell,\n faXmark,\n} from '@fortawesome/free-solid-svg-icons';\n\nimport { AlertStyleType } from './alert.types';\nimport type { AlertProps } from './alert.types';\nimport styles from './alert.module.pcss';\nimport ActionIcon from '../actionIcon';\nimport { useComponentDefaults } from '../configProvider';\n\nconst ICON_BY_STYLE: Record<AlertStyleType, typeof faBell> = {\n [AlertStyleType.Default]: faBell,\n [AlertStyleType.Info]: faCircleInfo,\n [AlertStyleType.Success]: faCircleCheck,\n [AlertStyleType.Warn]: faTriangleExclamation,\n [AlertStyleType.Error]: faCircleXmark,\n};\n\nconst CLASS_BY_STYLE: Record<AlertStyleType, string> = {\n [AlertStyleType.Default]: styles.alertStyleDefault,\n [AlertStyleType.Info]: styles.alertStyleInfo,\n [AlertStyleType.Success]: styles.alertStyleSuccess,\n [AlertStyleType.Warn]: styles.alertStyleWarn,\n [AlertStyleType.Error]: styles.alertStyleError,\n};\n\nfunction Alert(props: AlertProps): ReactElement {\n const {\n title,\n children = null,\n styleType = AlertStyleType.Default,\n icon,\n hideIcon = false,\n onClose,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Alert', props);\n\n return (\n <div\n {...rest}\n role=\"alert\"\n className={cx(styles.alert, CLASS_BY_STYLE[styleType], classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {!hideIcon && (\n <FontAwesomeIcon\n icon={icon ?? ICON_BY_STYLE[styleType]}\n className={cx(styles.alertIcon, classNames?.icon)}\n style={slotStyles?.icon as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n )}\n\n <div className={cx(styles.alertContent, classNames?.content)} style={slotStyles?.content}>\n {title && (\n <div className={cx(styles.alertTitle, classNames?.title)} style={slotStyles?.title}>\n {title}\n </div>\n )}\n {children && (\n <div className={cx(styles.alertDescription, classNames?.description)} style={slotStyles?.description}>\n {children}\n </div>\n )}\n </div>\n\n {onClose && (\n <ActionIcon\n icon={faXmark}\n onClick={onClose}\n className={cx(styles.alertCloseButton, classNames?.closeButton)}\n style={slotStyles?.closeButton}\n aria-label=\"Dismiss\"\n />\n )}\n </div>\n );\n}\n\nexport default Alert;\n",".animatedLogo {\n display: inline-block;\n overflow: visible;\n\n &-path {\n stroke: var(--primary-color);\n fill: var(--primary-color);\n fill-opacity: 0;\n }\n\n &-pathLoop {\n animation-name: animatedLogoRevealLoop;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n animation-iteration-count: infinite;\n }\n\n &-pathOnce {\n animation-name: animatedLogoRevealOnce;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n\n &-pathLoopNoFill {\n animation-name: animatedLogoRevealLoopNoFill;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n animation-iteration-count: infinite;\n }\n\n &-pathOnceNoFill {\n animation-name: animatedLogoRevealOnceNoFill;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n\n &-spinLoop,\n &-spinOnce,\n &-scaleLoop,\n &-scaleOnce {\n display: inline-block;\n transform-box: fill-box;\n transform-origin: center;\n animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);\n }\n\n &-spinLoop {\n animation-name: animatedLogoRotateLoop;\n animation-iteration-count: infinite;\n }\n\n &-spinOnce {\n animation-name: animatedLogoRotateOnce;\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n\n &-scaleLoop {\n animation-name: animatedLogoGrowLoop;\n animation-iteration-count: infinite;\n }\n\n &-scaleOnce {\n animation-name: animatedLogoGrowOnce;\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n\n @media (prefers-reduced-motion: reduce) {\n &-pathLoop,\n &-pathOnce {\n animation: none;\n fill-opacity: 1;\n stroke-dashoffset: 0;\n }\n\n &-pathLoopNoFill,\n &-pathOnceNoFill {\n animation: none;\n stroke-dashoffset: 0;\n }\n\n &-spinLoop,\n &-spinOnce,\n &-scaleLoop,\n &-scaleOnce {\n animation: none;\n }\n }\n}\n\n@keyframes animatedLogoRevealLoop {\n 0% {\n stroke-dashoffset: var(--animated-logo-length);\n fill-opacity: 0;\n }\n\n 38% {\n stroke-dashoffset: 0;\n fill-opacity: 0;\n }\n\n 62% {\n fill-opacity: 1;\n }\n\n 86% {\n fill-opacity: 1;\n }\n\n 96% {\n stroke-dashoffset: 0;\n fill-opacity: 0;\n }\n\n 100% {\n stroke-dashoffset: var(--animated-logo-length);\n fill-opacity: 0;\n }\n}\n\n@keyframes animatedLogoRevealOnce {\n 0% {\n stroke-dashoffset: var(--animated-logo-length);\n fill-opacity: 0;\n }\n\n 45% {\n stroke-dashoffset: 0;\n fill-opacity: 0;\n }\n\n 100% {\n stroke-dashoffset: 0;\n fill-opacity: 1;\n }\n}\n\n@keyframes animatedLogoRevealLoopNoFill {\n 0% {\n stroke-dashoffset: var(--animated-logo-length);\n }\n\n 38% {\n stroke-dashoffset: 0;\n }\n\n 86% {\n stroke-dashoffset: 0;\n }\n\n 100% {\n stroke-dashoffset: var(--animated-logo-length);\n }\n}\n\n@keyframes animatedLogoRevealOnceNoFill {\n 0% {\n stroke-dashoffset: var(--animated-logo-length);\n }\n\n 45% {\n stroke-dashoffset: 0;\n }\n\n 100% {\n stroke-dashoffset: 0;\n }\n}\n\n@keyframes animatedLogoRotateLoop {\n 0% {\n transform: rotate(180deg);\n }\n\n 38% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(0deg);\n }\n}\n\n@keyframes animatedLogoRotateOnce {\n 0% {\n transform: rotate(180deg);\n }\n\n 45% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(0deg);\n }\n}\n\n@keyframes animatedLogoGrowLoop {\n 0% {\n transform: scale(0);\n }\n\n 38% {\n transform: scale(1);\n }\n\n 96% {\n transform: scale(1);\n }\n\n 100% {\n transform: scale(0);\n }\n}\n\n@keyframes animatedLogoGrowOnce {\n 0% {\n transform: scale(0);\n }\n\n 45% {\n transform: scale(1);\n }\n\n 100% {\n transform: scale(1);\n }\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { CSSProperties, ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport type { AnimatedLogoProps } from './animatedLogo.types';\nimport styles from './animatedLogo.module.pcss';\n\nconst DEFAULT_PATH =\n 'M 1.292 0.278 C -0.41 4.855 3.185 6.433 0.344 8.916 Q 3.923 10.712 5.361 14.001 Q 6.128 14.398 6.876 14.003 Q 8.439 10.632 11.86 8.912 C 8.893 6.387 12.578 5.159 10.86 0.255 Q 8.655 1.166 7.391 3.377 Q 6.092 2.93 4.843 3.38 Q 3.246 0.883 1.292 0.278 Z M 1.663 1.28 Q 2.413 1.635 3.195 2.718 Q 2.083 2.778 1.595 3.884 Q 1.309 2.7 1.663 1.28 M 3.802 7.908 Q 4.426 8.069 3.284 9.003 Q 3.824 9.32 4.557 10.141 Q 4.812 10.869 4.849 11.671 Q 4.371 10.09 2.642 9.144 Q 2.438 9.033 2.609 8.922 Q 3.229 8.537 3.802 7.908 M 8.469 7.927 Q 8.955 8.469 9.646 8.926 Q 9.791 9.032 9.647 9.136 Q 7.821 10.157 7.389 11.702 Q 7.464 10.869 7.709 10.119 Q 8.219 9.53 8.956 9.025 Q 7.81 7.927 8.469 7.927';\n\nconst DEFAULT_VIEW_BOX = '0.244 0.155 11.72 14.25';\n\nfunction AnimatedLogo(props: AnimatedLogoProps): ReactElement {\n const {\n path = DEFAULT_PATH,\n viewBox = DEFAULT_VIEW_BOX,\n size = 96,\n color,\n duration = 4.2,\n loop = true,\n fill = true,\n spin = false,\n scale = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = props;\n\n const pathRef = useRef<SVGPathElement>(null);\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n const pathEl = pathRef.current;\n if (!pathEl) return;\n\n setReady(false);\n const length = pathEl.getTotalLength();\n pathEl.style.setProperty('--animated-logo-length', String(length));\n pathEl.style.strokeDasharray = String(length);\n pathEl.style.strokeDashoffset = String(length);\n\n const frame = requestAnimationFrame(() => setReady(true));\n return () => cancelAnimationFrame(frame);\n }, [path]);\n\n const pathStyle: CSSProperties = {\n animationDuration: `${duration}s`,\n ...(color ? { stroke: color, fill: color } : undefined),\n ...slotStyles?.path,\n };\n\n return (\n <svg\n {...rest}\n className={cx(styles.animatedLogo, className)}\n style={{ width: size, height: size, ...style }}\n viewBox={viewBox}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <g\n className={cx(ready && scale && (loop ? styles.animatedLogoScaleLoop : styles.animatedLogoScaleOnce))}\n style={{ animationDuration: `${duration}s` }}\n >\n <g\n className={cx(ready && spin && (loop ? styles.animatedLogoSpinLoop : styles.animatedLogoSpinOnce))}\n style={{ animationDuration: `${duration}s` }}\n >\n <path\n ref={pathRef}\n className={cx(\n styles.animatedLogoPath,\n ready &&\n (loop\n ? fill\n ? styles.animatedLogoPathLoop\n : styles.animatedLogoPathLoopNoFill\n : fill\n ? styles.animatedLogoPathOnce\n : styles.animatedLogoPathOnceNoFill),\n classNames?.path\n )}\n style={pathStyle}\n strokeWidth={0.1}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n d={path}\n />\n </g>\n </g>\n </svg>\n );\n}\n\nexport default AnimatedLogo;\n","import type { CSSProperties } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Which animation plays across the text. */\nexport enum AnimatedTextVariant {\n /** Each unit rises up from below its baseline, staggered left to right. */\n RiseUp = 'rise-up',\n /** Each unit fades in from a blur, staggered left to right. */\n BlurIn = 'blur-in',\n /** Each unit drops in from above with a spring overshoot, staggered left to right. */\n Bounce = 'bounce',\n /** Each unit pops in in order, like it's being typed, with a blinking cursor at the end. */\n Typewriter = 'typewriter',\n /** Each unit resolves from random characters to its real value, staggered left to right. */\n Scramble = 'scramble',\n /** Each unit briefly RGB-splits and jitters before settling, staggered left to right. */\n Glitch = 'glitch',\n /** Every unit continuously bobs up and down in a travelling wave, on a loop. */\n Wave = 'wave',\n /** A highlight sweeps across the text, left to right, on a loop. */\n Shine = 'shine',\n /** A marker-style highlight block wipes in behind the whole string, once, left to right. */\n Highlight = 'highlight',\n}\n\n/**\n * What gets staggered and animated as one entrance unit. Applies to every variant except\n * `Shine` and `Highlight`, which always animate the whole string as a single run.\n */\nexport enum AnimatedTextUnit {\n /** Every letter animates on its own. */\n Letter = 'letter',\n /** Every word animates as a whole block. */\n Word = 'word',\n}\n\nexport type AnimatedTextSlots = 'letter' | 'cursor';\n\nexport interface AnimatedTextProps extends HtmlProps {\n /** The text to animate. Split and animated one unit at a time for every variant but `Shine`/`Highlight`. */\n text: string;\n /** Which animation plays (default `RiseUp`). */\n variant?: AnimatedTextVariant;\n /** Whether entrance/loop variants stagger by letter or by word (default `Letter`). Ignored by `Shine`/`Highlight`. */\n unit?: AnimatedTextUnit;\n /**\n * Delay in ms between each unit's animation start. Applies to every variant except `Shine`\n * and `Highlight`, which animate as a single run (default `40`).\n */\n staggerDelay?: number;\n /**\n * Duration in ms of one animation cycle: a single unit's entrance for `RiseUp`/`BlurIn`/\n * `Bounce`/`Glitch` (default `500`), one bob cycle for `Wave` (default `1200`), one sweep of\n * the highlight for `Shine` (default `2000`), or the one-shot wipe-in for `Highlight` (default\n * `600`). Ignored by `Typewriter` and `Scramble`, since each unit resolves instantly; use\n * `staggerDelay` to control their pacing.\n */\n duration?: number;\n /**\n * When `true` (default), the animation doesn't start until the component first scrolls into\n * the viewport. Set to `false` to play immediately on mount, e.g. for text already in view\n * above the fold.\n */\n triggerOnView?: boolean;\n\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<AnimatedTextSlots>;\n styles?: SlotStyles<AnimatedTextSlots>;\n}\n",".animatedText {\n display: inline-block;\n position: relative;\n\n &-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n &-letter {\n display: inline-block;\n white-space: pre;\n opacity: 0;\n animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);\n animation-fill-mode: forwards;\n }\n\n &-variant {\n &-rise-up {\n animation-name: animatedTextRiseUp;\n }\n\n &-blur-in {\n animation-name: animatedTextBlurIn;\n }\n\n &-bounce {\n animation-name: animatedTextBounceIn;\n animation-timing-function: ease-out;\n }\n\n &-glitch {\n animation-name: animatedTextGlitch;\n animation-timing-function: steps(5, jump-none);\n }\n\n &-wave {\n /* Ambient/looping, not an entrance, so the letter stays visible throughout, overriding\n `.animatedText-letter`'s opacity:0 base (meant for one-shot entrance variants). */\n opacity: 1;\n animation-name: animatedTextWave;\n animation-iteration-count: infinite;\n animation-timing-function: ease-in-out;\n }\n }\n\n &-typewriter-letter {\n display: inline-block;\n white-space: pre;\n }\n\n &-scramble-letter {\n display: inline-block;\n white-space: pre;\n }\n\n &-cursor {\n display: inline-block;\n width: 0.08em;\n min-width: 1px;\n height: 0.85em;\n margin-left: 0.05em;\n background: var(--text-color);\n vertical-align: baseline;\n\n &-blinking {\n animation: animatedTextCursorBlink 1s step-end infinite;\n }\n }\n\n &-shine {\n display: inline-block;\n white-space: pre;\n /* currentColor can't be used here: it would resolve against this same rule's\n `color: transparent` below, making the whole gradient transparent. */\n background-image: linear-gradient(90deg, var(--text-color) 25%, var(--primary-lighter) 50%, var(--text-color) 75%);\n background-size: 200% 100%;\n background-clip: text;\n -webkit-background-clip: text;\n color: transparent;\n -webkit-text-fill-color: transparent;\n animation-name: animatedTextShineSweep;\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n }\n\n &-highlight {\n display: inline-block;\n white-space: pre;\n background-image: linear-gradient(var(--primary-lighter), var(--primary-lighter));\n background-repeat: no-repeat;\n background-position: left center;\n background-size: 0% 100%;\n animation-name: animatedTextHighlightSweep;\n animation-timing-function: ease-out;\n animation-fill-mode: forwards;\n }\n\n @media (prefers-reduced-motion: reduce) {\n &-letter {\n animation: none;\n opacity: 1;\n }\n\n &-shine {\n animation: none;\n background-image: none;\n color: currentColor;\n -webkit-text-fill-color: currentColor;\n }\n\n &-highlight {\n animation: none;\n background-size: 100% 100%;\n }\n\n &-cursor-blinking {\n animation: none;\n opacity: 1;\n }\n }\n}\n\n@keyframes animatedTextRiseUp {\n from {\n opacity: 0;\n transform: translateY(0.6em);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes animatedTextBlurIn {\n from {\n opacity: 0;\n filter: blur(8px);\n }\n\n to {\n opacity: 1;\n filter: blur(0);\n }\n}\n\n@keyframes animatedTextBounceIn {\n 0% {\n opacity: 0;\n transform: translateY(-0.8em);\n }\n\n 60% {\n opacity: 1;\n transform: translateY(0.15em);\n }\n\n 80% {\n transform: translateY(-0.05em);\n }\n\n 100% {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes animatedTextGlitch {\n 0% {\n opacity: 0;\n transform: translate(0, 0);\n text-shadow: none;\n }\n\n 15% {\n opacity: 1;\n transform: translate(-0.05em, 0.03em);\n text-shadow: 0.06em 0 var(--error-color), -0.06em 0 var(--info-color);\n }\n\n 30% {\n transform: translate(0.05em, -0.03em);\n text-shadow: -0.06em 0 var(--error-color), 0.06em 0 var(--info-color);\n }\n\n 45% {\n transform: translate(-0.03em, 0);\n text-shadow: 0.03em 0 var(--error-color), -0.03em 0 var(--info-color);\n }\n\n 60%,\n 100% {\n opacity: 1;\n transform: translate(0, 0);\n text-shadow: none;\n }\n}\n\n@keyframes animatedTextWave {\n 0%,\n 100% {\n transform: translateY(0);\n }\n\n 50% {\n transform: translateY(-0.25em);\n }\n}\n\n@keyframes animatedTextShineSweep {\n 0% {\n background-position: 200% 0;\n }\n\n 100% {\n background-position: -200% 0;\n }\n}\n\n@keyframes animatedTextHighlightSweep {\n from {\n background-size: 0% 100%;\n }\n\n to {\n background-size: 100% 100%;\n }\n}\n\n@keyframes animatedTextCursorBlink {\n 0%,\n 50% {\n opacity: 1;\n }\n\n 50.01%,\n 100% {\n opacity: 0;\n }\n}\n","import { Fragment, useEffect, useMemo, useRef, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { AnimatedTextVariant, AnimatedTextUnit } from './animatedText.types';\nimport type { AnimatedTextProps } from './animatedText.types';\nimport styles from './animatedText.module.pcss';\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n ? window.matchMedia('(prefers-reduced-motion: reduce)').matches\n : false;\n}\n\n// CSS-driven one-shot entrance variants: identical rendering, only the keyframe (via this class)\n// differs. RiseUp/BlurIn/Bounce/Glitch all animate opacity 0 -> 1 with `animation-fill-mode:\n// forwards`, staggered per unit via `animation-delay`.\nconst ENTRANCE_VARIANT_CLASS: Partial<Record<AnimatedTextVariant, string>> = {\n [AnimatedTextVariant.RiseUp]: styles.animatedTextVariantRiseUp,\n [AnimatedTextVariant.BlurIn]: styles.animatedTextVariantBlurIn,\n [AnimatedTextVariant.Bounce]: styles.animatedTextVariantBounce,\n [AnimatedTextVariant.Glitch]: styles.animatedTextVariantGlitch,\n};\n\nfunction splitUnits(text: string, unit: AnimatedTextUnit): string[] {\n return unit === AnimatedTextUnit.Word ? text.split(' ').filter(Boolean) : Array.from(text);\n}\n\ninterface TypewriterProps {\n units: string[];\n unit: AnimatedTextUnit;\n staggerDelay: number;\n classNames: AnimatedTextProps['classNames'];\n slotStyles: AnimatedTextProps['styles'];\n}\n\n// Split out so its wrapper (keyed by `replayKey`, see below) can be remounted on prop change to\n// reset this component's reveal state, the idiomatic React way to reset state on prop change.\n// It also keeps the reveal-count updates that happen over time (inside the interval callback) as\n// the only setState calls, none of them synchronous-in-effect.\nfunction Typewriter({ units, unit, staggerDelay, classNames, slotStyles }: TypewriterProps) {\n const [revealCount, setRevealCount] = useState(() => {\n if (units.length === 0) return 0;\n return prefersReducedMotion() ? units.length : 1;\n });\n\n useEffect(() => {\n if (units.length <= 1 || prefersReducedMotion()) return;\n let revealed = 1;\n const id = setInterval(() => {\n revealed += 1;\n setRevealCount(revealed);\n if (revealed >= units.length) clearInterval(id);\n }, staggerDelay);\n return () => clearInterval(id);\n }, [units, staggerDelay]);\n\n const isDone = revealCount >= units.length;\n\n return (\n <>\n {units.slice(0, revealCount).map((unitText, index) => (\n <Fragment key={index}>\n <span className={cx(styles.animatedTextTypewriterLetter, classNames?.letter)} style={slotStyles?.letter}>\n {unitText}\n </span>\n {unit === AnimatedTextUnit.Word && index < revealCount - 1 ? ' ' : null}\n </Fragment>\n ))}\n <span\n className={cx(styles.animatedTextCursor, isDone && styles.animatedTextCursorBlinking, classNames?.cursor)}\n style={slotStyles?.cursor}\n />\n </>\n );\n}\n\nconst SCRAMBLE_CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%&*';\nconst SCRAMBLE_TICK_MS = 35;\n\nfunction randomScrambleText(length: number): string {\n return Array.from({ length }, () => SCRAMBLE_CHARSET[Math.floor(Math.random() * SCRAMBLE_CHARSET.length)]).join('');\n}\n\ninterface ScrambleProps {\n units: string[];\n unit: AnimatedTextUnit;\n staggerDelay: number;\n classNames: AnimatedTextProps['classNames'];\n slotStyles: AnimatedTextProps['styles'];\n}\n\n// Same keyed-remount-on-prop-change approach as Typewriter. Every unit starts scrambled and\n// \"locks in\" left to right; the scramble refresh (SCRAMBLE_TICK_MS) is a separate, faster cadence\n// than the per-unit settle pacing (staggerDelay) so still-scrambling units keep visibly flickering.\nfunction Scramble({ units, unit, staggerDelay, classNames, slotStyles }: ScrambleProps) {\n const [reduceMotion] = useState(prefersReducedMotion);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (units.length === 0 || reduceMotion) return;\n let t = 0;\n const totalTicks = Math.ceil((units.length * staggerDelay) / SCRAMBLE_TICK_MS) + 1;\n const id = setInterval(() => {\n t += 1;\n setTick(t);\n if (t >= totalTicks) clearInterval(id);\n }, SCRAMBLE_TICK_MS);\n return () => clearInterval(id);\n }, [units, staggerDelay, reduceMotion]);\n\n const settledCount = Math.min(units.length, Math.floor((tick * SCRAMBLE_TICK_MS) / staggerDelay));\n\n return (\n <>\n {units.map((unitText, index) => {\n const isSettled = reduceMotion || index < settledCount;\n return (\n <Fragment key={index}>\n <span className={cx(styles.animatedTextScrambleLetter, classNames?.letter)} style={slotStyles?.letter}>\n {unitText === ' ' ? ' ' : isSettled ? unitText : randomScrambleText(unitText.length)}\n </span>\n {unit === AnimatedTextUnit.Word && index < units.length - 1 ? ' ' : null}\n </Fragment>\n );\n })}\n </>\n );\n}\n\nfunction AnimatedText({\n text,\n variant = AnimatedTextVariant.RiseUp,\n unit = AnimatedTextUnit.Letter,\n staggerDelay = 40,\n duration,\n triggerOnView = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: AnimatedTextProps): ReactElement {\n const units = useMemo(() => splitUnits(text, unit), [text, unit]);\n const rootRef = useRef<HTMLSpanElement>(null);\n\n // When `triggerOnView` is on, the animated subtree stays unmounted (see `isVisible` below)\n // until the root first scrolls into the viewport, so the entrance/loop only plays once someone\n // can actually see it instead of burning its one-shot animation off-screen on mount. Falls back\n // to immediately visible when IntersectionObserver isn't available (SSR, old browsers, jsdom).\n const [isVisible, setIsVisible] = useState(() => !triggerOnView || typeof IntersectionObserver === 'undefined');\n\n useEffect(() => {\n if (isVisible) return;\n const node = rootRef.current;\n if (!node) return;\n const observer = new IntersectionObserver(([entry]) => {\n if (entry?.isIntersecting) {\n setIsVisible(true);\n observer.disconnect();\n }\n });\n observer.observe(node);\n return () => observer.disconnect();\n }, [isVisible]);\n\n // Forces the animated subtree (not the whole component) to remount whenever anything that\n // affects the animation changes, most commonly `text`. Without this, CSS entrance variants\n // rely on `animation-fill-mode: forwards`, which just holds the prior end state instead of\n // replaying when the letters underneath it change; keying on these values makes every variant\n // (CSS-driven and JS-driven alike) replay consistently, matching what a component named\n // AnimatedText should do when the text it's animating actually changes.\n const replayKey = `${variant} ${text} ${unit} ${staggerDelay} ${duration ?? ''}`;\n\n let content: ReactElement;\n\n if (!isVisible) {\n // Reserves the same layout space as the real content without playing anything yet.\n content = (\n <span aria-hidden=\"true\" style={{ opacity: 0 }}>\n {text}\n </span>\n );\n } else if (variant === AnimatedTextVariant.Shine) {\n content = (\n <span\n key={replayKey}\n aria-hidden=\"true\"\n className={cx(styles.animatedTextShine, classNames?.letter)}\n style={{ animationDuration: `${duration ?? 2000}ms`, ...slotStyles?.letter }}\n >\n {text}\n </span>\n );\n } else if (variant === AnimatedTextVariant.Highlight) {\n content = (\n <span\n key={replayKey}\n aria-hidden=\"true\"\n className={cx(styles.animatedTextHighlight, classNames?.letter)}\n style={{ animationDuration: `${duration ?? 600}ms`, ...slotStyles?.letter }}\n >\n {text}\n </span>\n );\n } else if (variant === AnimatedTextVariant.Typewriter) {\n content = (\n <span key={replayKey} aria-hidden=\"true\">\n <Typewriter units={units} unit={unit} staggerDelay={staggerDelay} classNames={classNames} slotStyles={slotStyles} />\n </span>\n );\n } else if (variant === AnimatedTextVariant.Scramble) {\n content = (\n <span key={replayKey} aria-hidden=\"true\">\n <Scramble units={units} unit={unit} staggerDelay={staggerDelay} classNames={classNames} slotStyles={slotStyles} />\n </span>\n );\n } else if (variant === AnimatedTextVariant.Wave) {\n content = (\n <span key={replayKey} aria-hidden=\"true\">\n {units.map((unitText, index) => (\n <Fragment key={index}>\n <span\n className={cx(styles.animatedTextLetter, styles.animatedTextVariantWave, classNames?.letter)}\n style={{\n // Negative delay starts the loop already mid-cycle, phase-shifted per unit.\n // That's what makes it read as a travelling wave from the very first frame,\n // instead of every unit bobbing in lockstep or staggering in once and then syncing.\n animationDelay: `-${index * staggerDelay}ms`,\n animationDuration: `${duration ?? 1200}ms`,\n ...slotStyles?.letter,\n }}\n >\n {unitText === ' ' ? ' ' : unitText}\n </span>\n {unit === AnimatedTextUnit.Word && index < units.length - 1 ? ' ' : null}\n </Fragment>\n ))}\n </span>\n );\n } else {\n const entranceClass = ENTRANCE_VARIANT_CLASS[variant] ?? styles.animatedTextVariantRiseUp;\n content = (\n <span key={replayKey} aria-hidden=\"true\">\n {units.map((unitText, index) => (\n <Fragment key={index}>\n <span\n className={cx(styles.animatedTextLetter, entranceClass, classNames?.letter)}\n style={{\n animationDelay: `${index * staggerDelay}ms`,\n animationDuration: `${duration ?? 500}ms`,\n ...slotStyles?.letter,\n }}\n >\n {unitText === ' ' ? ' ' : unitText}\n </span>\n {unit === AnimatedTextUnit.Word && index < units.length - 1 ? ' ' : null}\n </Fragment>\n ))}\n </span>\n );\n }\n\n return (\n <span {...rest} ref={rootRef} className={cx(styles.animatedText, className)} style={style}>\n <span className={styles.animatedTextVisuallyHidden}>{text}</span>\n {content}\n </span>\n );\n}\n\nexport default AnimatedText;\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum BadgeStyleType {\n Default = 'default',\n Primary = 'primary',\n Success = 'success',\n Info = 'info',\n Warn = 'warn',\n Error = 'error',\n}\n\nexport enum BadgePosition {\n TopRight = 'top-right',\n TopLeft = 'top-left',\n BottomRight = 'bottom-right',\n BottomLeft = 'bottom-left',\n}\n\nexport type BadgeSlots = 'badge';\n\nexport interface BadgeProps extends HtmlProps {\n count?: number;\n max?: number;\n content?: ReactNode;\n dot?: boolean;\n showZero?: boolean;\n styleType?: BadgeStyleType;\n position?: BadgePosition;\n children?: ReactNode;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<BadgeSlots>;\n styles?: SlotStyles<BadgeSlots>;\n}\n",".wrapper {\n position: relative;\n display: inline-flex;\n align-items: center;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n min-width: 1.5em;\n height: 1.5em;\n padding: 0 0.375em;\n border-radius: var(--default-border-radius);\n font-size: 0.75em;\n font-weight: 600;\n line-height: 1;\n white-space: nowrap;\n background: var(--badge-bg);\n color: var(--badge-fg);\n\n &-dot {\n min-width: 0.8em;\n width: 0.8em;\n height: 0.8em;\n padding: 0;\n border-radius: 100%;\n background: var(--badge-solid);\n\n &.badge-position-top-right {\n transform: translate(20%, -20%);\n }\n\n &.badge-position-top-left {\n transform: translate(-20%, -20%);\n }\n\n &.badge-position-bottom-right {\n transform: translate(20%, 20%);\n }\n\n &.badge-position-bottom-left {\n transform: translate(-20%, 20%);\n }\n }\n\n &-overlay {\n position: absolute;\n z-index: 1;\n }\n\n &-position {\n &-top-right {\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n }\n\n &-top-left {\n top: 0;\n left: 0;\n transform: translate(-50%, -50%);\n }\n\n &-bottom-right {\n bottom: 0;\n right: 0;\n transform: translate(50%, 50%);\n }\n\n &-bottom-left {\n bottom: 0;\n left: 0;\n transform: translate(-50%, 50%);\n }\n }\n\n &-style {\n &-default {\n --badge-bg: rgba(0, 0, 0, 0.08);\n --badge-fg: var(--text-color);\n --badge-solid: var(--text-dark);\n }\n\n &-primary {\n --badge-bg: var(--primary-color);\n --badge-fg: var(--text-on-primary);\n --badge-solid: var(--primary-color);\n }\n\n &-success {\n --badge-bg: var(--success-lighter);\n --badge-fg: var(--success-color);\n --badge-solid: var(--success-color);\n }\n\n &-info {\n --badge-bg: var(--info-lighter);\n --badge-fg: var(--info-color);\n --badge-solid: var(--info-color);\n }\n\n &-warn {\n --badge-bg: var(--warn-lighter);\n --badge-fg: var(--warn-color);\n --badge-solid: var(--warn-color);\n }\n\n &-error {\n --badge-bg: var(--error-lighter);\n --badge-fg: var(--error-color);\n --badge-solid: var(--error-color);\n }\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { BadgeStyleType, BadgePosition } from './badge.types';\nimport type { BadgeProps } from './badge.types';\nimport styles from './badge.module.pcss';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_STYLE: Record<BadgeStyleType, string> = {\n [BadgeStyleType.Default]: styles.badgeStyleDefault,\n [BadgeStyleType.Primary]: styles.badgeStylePrimary,\n [BadgeStyleType.Success]: styles.badgeStyleSuccess,\n [BadgeStyleType.Info]: styles.badgeStyleInfo,\n [BadgeStyleType.Warn]: styles.badgeStyleWarn,\n [BadgeStyleType.Error]: styles.badgeStyleError,\n};\n\nconst CLASS_BY_POSITION: Record<BadgePosition, string> = {\n [BadgePosition.TopRight]: styles.badgePositionTopRight,\n [BadgePosition.TopLeft]: styles.badgePositionTopLeft,\n [BadgePosition.BottomRight]: styles.badgePositionBottomRight,\n [BadgePosition.BottomLeft]: styles.badgePositionBottomLeft,\n};\n\nfunction Badge(props: BadgeProps): ReactElement {\n const {\n count,\n max = 99,\n content,\n dot = false,\n showZero = false,\n styleType = BadgeStyleType.Primary,\n position = BadgePosition.TopRight,\n children = null,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Badge', props);\n const hasCount = typeof count === 'number';\n const hasContent = content != null;\n const isHiddenByZero = !dot && !hasContent && hasCount && count === 0 && !showZero;\n const showBadge = (dot || hasContent || hasCount) && !isHiddenByZero;\n\n const displayValue = hasContent ? content : hasCount ? (count > max ? `${max}+` : count) : null;\n const isOverlay = children != null;\n\n return (\n <span\n {...rest}\n className={cx(styles.wrapper, className)}\n style={style}\n >\n {children}\n {showBadge && (\n <span\n className={cx(\n styles.badge,\n CLASS_BY_STYLE[styleType],\n dot && styles.badgeDot,\n isOverlay && styles.badgeOverlay,\n isOverlay && CLASS_BY_POSITION[position],\n classNames?.badge\n )}\n style={slotStyles?.badge}\n >\n {!dot && displayValue}\n </span>\n )}\n </span>\n );\n}\n\nexport default Badge;\n",".avatar {\n --avatar-size: 2.5em;\n --custom-avatar-radius: var(--avatar-radius, var(--default-border-radius));\n display: inline-flex;\n width: var(--avatar-size);\n height: var(--avatar-size);\n flex-shrink: 0;\n box-sizing: border-box;\n vertical-align: middle;\n\n &-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n border-radius: var(--custom-avatar-radius);\n }\n\n &-fallback {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n border-radius: var(--custom-avatar-radius);\n background: var(--background-accent);\n color: var(--text-dark);\n font-size: calc(var(--avatar-size) * 0.4);\n font-weight: 600;\n user-select: none;\n text-transform: uppercase;\n }\n\n &-status-badge {\n border: 2px solid var(--background);\n box-sizing: border-box;\n }\n}\n\n.avatarGroup {\n display: inline-flex;\n align-items: center;\n\n &-item {\n display: inline-flex;\n border-radius: calc(var(--avatar-radius, var(--default-border-radius)) + 3px);\n border: 2px solid var(--background);\n box-sizing: content-box;\n margin-left: -0.5em;\n\n &:first-child {\n margin-left: 0;\n }\n }\n}\n","import { useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faUser } from '@fortawesome/free-solid-svg-icons';\nimport Badge, { BadgeStyleType, BadgePosition } from '../badge';\n\nimport type { AvatarProps, AvatarStatus } from './avatar.types';\nimport styles from './avatar.module.pcss';\n\nconst STATUS_STYLE: Record<AvatarStatus, BadgeStyleType> = {\n online: BadgeStyleType.Success,\n away: BadgeStyleType.Warn,\n busy: BadgeStyleType.Error,\n offline: BadgeStyleType.Default,\n};\n\nfunction getInitials(name?: string): string {\n if (!name) return '';\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '';\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n}\n\nfunction Avatar({\n src,\n alt,\n name,\n icon = faUser,\n content,\n status,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: AvatarProps): ReactElement {\n const [hasError, setHasError] = useState(false);\n const [prevSrc, setPrevSrc] = useState(src);\n\n if (src !== prevSrc) {\n setPrevSrc(src);\n setHasError(false);\n }\n\n const initials = getInitials(name);\n const showImage = !!src && !hasError;\n\n const rendered = showImage ? (\n <img\n className={cx(styles.avatarImage, classNames?.image)}\n style={slotStyles?.image}\n src={src}\n alt={alt ?? name ?? ''}\n onError={() => setHasError(true)}\n />\n ) : (\n <span className={cx(styles.avatarFallback, classNames?.fallback)} style={slotStyles?.fallback}>\n {content ?? (initials || <FontAwesomeIcon icon={icon} />)}\n </span>\n );\n\n if (!status) {\n return (\n <span {...rest} className={cx(styles.avatar, className)} style={style}>\n {rendered}\n </span>\n );\n }\n\n return (\n <Badge\n {...rest}\n dot\n position={BadgePosition.BottomRight}\n styleType={STATUS_STYLE[status]}\n className={className}\n style={style}\n classNames={{ badge: cx(styles.avatarStatusBadge, classNames?.status) }}\n styles={{ badge: slotStyles?.status }}\n >\n <span className={styles.avatar}>{rendered}</span>\n </Badge>\n );\n}\n\nexport default Avatar;\n","import { Children, type ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport Avatar from './avatar';\nimport type { AvatarGroupProps } from './avatar.types';\nimport styles from './avatar.module.pcss';\n\nfunction AvatarGroup({\n children,\n max,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: AvatarGroupProps): ReactElement {\n const items = Children.toArray(children);\n const visible = max != null ? items.slice(0, max) : items;\n const overflow = max != null ? items.length - max : 0;\n\n return (\n <span {...rest} className={cx(styles.avatarGroup, className)} style={style}>\n {visible.map((child, index) => (\n <span\n key={index}\n className={cx(styles.avatarGroupItem, classNames?.item)}\n style={slotStyles?.item}\n >\n {child}\n </span>\n ))}\n {overflow > 0 && (\n <span\n className={cx(styles.avatarGroupItem, classNames?.overflow)}\n style={slotStyles?.overflow}\n >\n <Avatar content={`+${overflow}`} />\n </span>\n )}\n </span>\n );\n}\n\nexport default AvatarGroup;\n","import { createPortal } from 'react-dom';\nimport type { ReactElement } from 'react';\n\nimport type { BodyEndProps } from './bodyEnd.types';\n\n// Module-scoped ambient typing for the bundler-replaced NODE_ENV guard below.\n// Browsers don't define `process`, so the value is read defensively at runtime;\n// bundlers (Vite/webpack) still statically replace the `process.env.NODE_ENV`\n// token. Declared at module scope (not globally), it isn't emitted into the\n// .d.ts and can't clash with a consumer's @types/node.\ndeclare const process: { env: { NODE_ENV?: string } };\n\nfunction BodyEnd({ children = null }: BodyEndProps): ReactElement | null {\n const target = document.getElementById('bodyEnd');\n if (!target) {\n if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {\n console.error('[BodyEnd] No element with id=\"bodyEnd\" found. Add <div id=\"bodyEnd\"></div> to your app root.');\n }\n return null;\n }\n return createPortal(children, target);\n}\n\nexport default BodyEnd;\n",".floatingMenu {\n position: relative;\n\n &-content {\n display: flex;\n align-items: stretch;\n height: 100%;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-container {\n color: var(--text-color);\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n box-shadow: var(--card-shadow);\n position: absolute;\n margin-top: 10px;\n background: var(--background-modal);\n padding: 8px;\n border-radius: calc(var(--default-border-radius) + 4px);\n\n .floatingMenu-anim-flip & {\n top: auto;\n bottom: 0;\n margin-top: 0;\n margin-bottom: 10px;\n }\n\n &-align {\n &-left {\n left: 0px;\n }\n\n &-right {\n right: 0px;\n }\n\n &-center {\n left: 50%;\n transform: translateX(-50%);\n }\n }\n\n &-flag {\n box-shadow: var(--card-shadow);\n background: var(--background-modal);\n height: 10px;\n width: 10px;\n position: absolute;\n margin-top: 5px;\n transform: rotate(45deg);\n\n .floatingMenu-anim-flip & {\n top: auto;\n bottom: 0;\n margin-top: 0;\n margin-bottom: 5px;\n }\n\n &-align-right {\n right: 8px;\n }\n\n &-align-left {\n left: 8px;\n }\n\n &-align-center {\n left: 50%;\n transform: translateX(-50%) rotate(45deg);\n }\n }\n }\n\n &-anim {\n transform: scale(0.7);\n opacity: 0.7;\n animation: showMenu 0.1s forwards;\n position: fixed;\n z-index: 1;\n }\n\n @keyframes showMenu {\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n}\n","// Scrollable ancestors up to (not including) <body>. This is computed once per open rather\n// than on every scroll tick, since walking the tree and reading computed style forces layout,\n// which is too expensive to repeat at scroll frequency (Floating UI's autoUpdate does the same\n// thing, resolving the ancestor list once via getOverflowAncestors). Plain page/viewport scroll\n// is deliberately left out: a trigger that scrolls off the top of the page already renders its\n// fixed-position anchor off-screen for free.\nexport function getScrollableAncestors(el: HTMLElement): HTMLElement[] {\n const ancestors: HTMLElement[] = [];\n let node = el.parentElement;\n while (node && node !== document.body && node !== document.documentElement) {\n const style = getComputedStyle(node);\n if (style.overflowX !== 'visible' || style.overflowY !== 'visible') ancestors.push(node);\n node = node.parentElement;\n }\n return ancestors;\n}\n\nexport function isHiddenByAnyAncestor(rect: DOMRect, ancestors: HTMLElement[]): boolean {\n return ancestors.some((ancestor) => {\n const a = ancestor.getBoundingClientRect();\n return rect.bottom <= a.top || rect.top >= a.bottom || rect.right <= a.left || rect.left >= a.right;\n });\n}\n","import { useLayoutEffect, type RefObject } from 'react';\nimport { getScrollableAncestors, isHiddenByAnyAncestor } from 'components/common/utils/scrollAncestors';\n\nexport interface UseFloatingPositionArgs {\n isOpen: boolean;\n /** The element the popup is anchored to. */\n triggerRef: RefObject<HTMLElement | null>;\n /** The `position: fixed` element that gets `top`/`left`/`visibility` written to it directly. */\n anchorRef: RefObject<HTMLElement | null>;\n /** The visible panel whose height decides whether there's room to render on the preferred side. */\n panelRef: RefObject<HTMLElement | null>;\n /** Class toggled on `anchorRef` when flipped to the non-preferred side. */\n flipClassName: string;\n /** Preferred side relative to the trigger (default `'bottom'`) — flips to the other side when there's no room. */\n placement?: 'top' | 'bottom';\n}\n\n/**\n * Keeps a portaled, `position: fixed` popup anchored to a trigger element: tracks the\n * trigger across scroll/resize on every real scrolling ancestor, flips above the trigger\n * when there's no room below, and hides (not closes) the popup when the trigger itself\n * scrolls behind a clipping ancestor — matching Floating UI's autoUpdate + hide middleware.\n *\n * Position/visibility are written straight to the DOM via refs, not through React state:\n * going through setState -> re-render -> commit adds a round-trip that lags behind the\n * browser's own scroll painting by at least a frame.\n */\nexport function useFloatingPosition({ isOpen, triggerRef, anchorRef, panelRef, flipClassName, placement = 'bottom' }: UseFloatingPositionArgs) {\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let rafId: number | undefined;\n let teardown: (() => void) | undefined;\n\n // The anchor/trigger may not be mounted yet on the very first invocation of this\n // effect: a portal target (e.g. BodyEnd's `#bodyEnd` div) can still be missing on\n // the initial render, in which case the portaled content — and this ref — commits\n // one render later. Since refs never change identity, that later commit doesn't\n // re-trigger this effect on its own, so retry on the next frame until it's there.\n function trySetup() {\n const trigger = triggerRef.current;\n const anchor = anchorRef.current;\n if (!trigger || !anchor) {\n rafId = requestAnimationFrame(trySetup);\n return;\n }\n const ancestors = getScrollableAncestors(trigger);\n\n function updatePos() {\n const rect = trigger!.getBoundingClientRect();\n const panelHeight = panelRef.current?.offsetHeight ?? 0;\n const spaceBelow = window.innerHeight - rect.bottom;\n const spaceAbove = rect.top;\n const preferredSpace = placement === 'top' ? spaceAbove : spaceBelow;\n const alternateSpace = placement === 'top' ? spaceBelow : spaceAbove;\n const flip = preferredSpace < panelHeight && alternateSpace > preferredSpace;\n const renderAbove = placement === 'top' ? !flip : flip;\n anchor!.classList.toggle(flipClassName, flip);\n // Shift up by the anchor's own height when rendering above, so this works whether\n // the anchor is a zero-height decorative wrapper (FloatingMenu, whose real panel\n // hangs off it via absolute-positioned CSS) or the visible panel itself\n // (Dropdown) — for the former the shift is a no-op (height 0).\n anchor!.style.top = `${renderAbove ? rect.top - anchor!.offsetHeight : rect.bottom}px`;\n anchor!.style.left = `${rect.left}px`;\n anchor!.style.visibility = isHiddenByAnyAncestor(rect, ancestors) ? 'hidden' : '';\n }\n\n updatePos();\n\n const scrollTargets: (Window | HTMLElement)[] = [window, ...ancestors];\n scrollTargets.forEach((t) => t.addEventListener('scroll', updatePos, { passive: true }));\n window.addEventListener('resize', updatePos);\n teardown = () => {\n scrollTargets.forEach((t) => t.removeEventListener('scroll', updatePos));\n window.removeEventListener('resize', updatePos);\n };\n }\n\n trySetup();\n\n return () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n teardown?.();\n };\n }, [isOpen, triggerRef, anchorRef, panelRef, flipClassName, placement]);\n}","import type { RefObject } from 'react';\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n].join(',');\n\n/** Tabbable descendants of `root`, in DOM order. */\nexport function tabbablesIn(root: ParentNode | null): HTMLElement[] {\n if (!root) return [];\n return Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));\n}\n\nexport interface UseFocusBoundaryArgs {\n /** The trigger element focus returns to on Escape / Shift+Tab out of the content's top. */\n triggerRef: RefObject<HTMLElement | null>;\n /** The portaled content root — tabbables inside it define the Tab boundary. */\n contentRef: RefObject<HTMLElement | null>;\n}\n\n/**\n * Focus helpers for content portaled to the end of the DOM (e.g. via BodyEnd), where Tab can't\n * reach it in visual document order on its own. Shared by FloatingMenu and Popover, which both\n * need to hand focus back to the trigger on Escape / Shift+Tab out of the top, and continue\n * focus naturally past the trigger when Tab exits the bottom.\n */\nexport function useFocusBoundary({ triggerRef, contentRef }: UseFocusBoundaryArgs) {\n function firstTriggerFocusable(): HTMLElement | null {\n return tabbablesIn(triggerRef.current)[0] ?? triggerRef.current;\n }\n\n function restoreFocusToTrigger() {\n firstTriggerFocusable()?.focus();\n }\n\n // Move focus to the tabbable element that follows the trigger in the document, skipping the\n // portaled content — the \"natural next\" stop when Tab exits the bottom of the content.\n function focusAfterTrigger() {\n const all = tabbablesIn(document.body).filter((el) => !contentRef.current?.contains(el));\n const trig = firstTriggerFocusable();\n const idx = trig ? all.indexOf(trig) : -1;\n if (idx >= 0) all[idx + 1]?.focus();\n }\n\n return { firstTriggerFocusable, restoreFocusToTrigger, focusAfterTrigger };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum Align {\n Left = 'left',\n Right = 'right',\n Center = 'center',\n}\n\nexport type FloatingMenuSlots = 'root' | 'trigger' | 'menu' | 'menuContainer';\n\nexport interface FloatingMenuProps extends HtmlProps {\n align?: Align;\n children?: ReactNode;\n content?: ReactNode;\n isOpen?: boolean;\n onOpenChange?: (isOpen: boolean) => void;\n dontCloseOnChildClick?: boolean;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<FloatingMenuSlots>;\n styles?: SlotStyles<FloatingMenuSlots>;\n}","import { useRef, useEffect, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './floatingMenu.module.pcss';\nimport { useFloatingPosition } from './useFloatingPosition';\nimport { useFocusBoundary, tabbablesIn } from '../hooks/useFocusBoundary';\nimport { Align, FloatingMenuProps } from './floatingMenu.types';\n\nfunction capitalize(s: string) {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction FloatingMenu({\n align = Align.Left,\n children = null,\n content = null,\n isOpen = false,\n onOpenChange = () => {},\n dontCloseOnChildClick = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: FloatingMenuProps) {\n const menuContainerRef = useRef<HTMLDivElement>(null);\n const menuAnimRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const onOpenChangeRef = useRef(onOpenChange);\n const [triggerWidth, setTriggerWidth] = useState(10);\n\n const contentInteractedRef = useRef(false);\n function handleContentMouseUp() {\n contentInteractedRef.current = true;\n }\n\n useEffect(() => { onOpenChangeRef.current = onOpenChange; });\n\n function handleTriggerClick() {\n if (isOpen) {\n if (!dontCloseOnChildClick) onOpenChange(false);\n return;\n }\n const rect = triggerRef.current?.getBoundingClientRect();\n setTriggerWidth(rect?.width ?? 10);\n onOpenChange(true);\n }\n\n useFloatingPosition({\n isOpen,\n triggerRef,\n anchorRef: menuAnimRef,\n panelRef: menuContainerRef,\n flipClassName: styles.floatingMenuAnimFlip,\n });\n\n useEffect(() => {\n if (!isOpen) return;\n\n function onMouseUp(event: MouseEvent) {\n const menuElem = menuContainerRef.current;\n const triggerElem = triggerRef.current;\n if (!menuElem || !triggerElem) return;\n\n const target = event.target as Node;\n if (triggerElem === target || triggerElem.contains(target)) return;\n\n const contentInteracted = contentInteractedRef.current;\n contentInteractedRef.current = false;\n const clickedInMenu = contentInteracted || menuElem === target || menuElem.contains(target);\n\n if (!clickedInMenu || !dontCloseOnChildClick) {\n onOpenChangeRef.current(false);\n }\n }\n\n window.addEventListener('mouseup', onMouseUp);\n return () => window.removeEventListener('mouseup', onMouseUp);\n }, [isOpen, dontCloseOnChildClick]);\n\n const { restoreFocusToTrigger, focusAfterTrigger } = useFocusBoundary({\n triggerRef,\n contentRef: menuContainerRef,\n });\n\n // The menu is portaled to the end of the DOM, so Tab never flows into it naturally. When\n // `content` has real focusable elements, close on Tab out of either end and continue focus as\n // if the menu sat right after the trigger. Unlike Popover, this doesn't also auto-focus the\n // first element on open, content here ranges from menus to live controls like ColorPicker's\n // hue slider, where grabbing focus on open would let a stray arrow-key press nudge a value the\n // user never interacted with. Auto-focus-on-open is still worth doing per-consumer (e.g.\n // SplitButton focuses its first enabled action), just not assumed generically here.\n function handleMenuKeyDown(event: React.KeyboardEvent) {\n if (event.key === 'Escape') {\n event.preventDefault();\n restoreFocusToTrigger();\n onOpenChangeRef.current(false);\n return;\n }\n if (event.key !== 'Tab') return;\n const focusables = tabbablesIn(menuContainerRef.current);\n if (focusables.length === 0) return;\n const active = document.activeElement;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusAfterTrigger();\n onOpenChangeRef.current(false);\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n restoreFocusToTrigger();\n onOpenChangeRef.current(false);\n }\n }\n\n return (\n <div {...rest} className={cx(styles.floatingMenu, className, classNames?.root)} style={{ ...style, ...slotStyles?.root }}>\n <div\n className={cx(styles.floatingMenuContent, classNames?.trigger)}\n style={slotStyles?.trigger}\n ref={triggerRef}\n onClick={handleTriggerClick}\n >\n {children}\n </div>\n {isOpen && (\n <BodyEnd>\n <div\n ref={menuAnimRef}\n className={cx(styles.floatingMenuAnim, classNames?.menu)}\n style={{\n width: `${triggerWidth}px`,\n ...slotStyles?.menu,\n }}\n >\n <div className={cx(\n styles.floatingMenuContainerFlag,\n styles[`floatingMenuContainerFlagAlign${capitalize(align)}`],\n )} />\n <div\n ref={menuContainerRef}\n className={cx(\n styles.floatingMenuContainer,\n styles[`floatingMenuContainerAlign${capitalize(align)}`],\n classNames?.menuContainer,\n )}\n style={slotStyles?.menuContainer}\n onMouseUpCapture={handleContentMouseUp}\n onKeyDown={handleMenuKeyDown}\n >\n {content}\n </div>\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n\nexport default FloatingMenu;\n",".breadcrumb {\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n\n &-list {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n &-item {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n &-icon {\n margin-right: 6px;\n font-size: 0.9em;\n }\n\n &-link {\n display: flex;\n align-items: center;\n text-decoration: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: color 0.15s;\n\n /* Explicit :link/:visited beats the browser default a:visited { color: purple } on\n specificity, otherwise every crumb using the same href (e.g. \"#\") turns purple as\n soon as any one of them is clicked. */\n &:link,\n &:visited {\n color: var(--text-dark);\n }\n\n &:hover {\n color: var(--primary-color);\n }\n\n &-disabled {\n color: var(--text-dark);\n opacity: 0.5;\n cursor: default;\n pointer-events: none;\n }\n }\n\n &-current {\n display: flex;\n align-items: center;\n color: var(--text-color);\n font-weight: var(--header-font-weight, 600);\n }\n\n &-separator {\n display: flex;\n align-items: center;\n color: var(--text-dark);\n font-size: 0.75em;\n opacity: 0.7;\n }\n\n &-ellipsis {\n width: 1.8em;\n height: 1.8em;\n font-size: 1em;\n color: var(--text-dark);\n\n &:hover {\n color: var(--primary-color);\n }\n }\n\n &-hiddenList {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin: 0;\n padding: 6px;\n list-style: none;\n min-width: 160px;\n }\n\n &-hiddenItem {\n display: flex;\n\n .breadcrumb-link {\n width: 100%;\n padding: 6px 8px;\n border-radius: var(--default-border-radius);\n\n &:hover {\n background: var(--background-accent-light);\n }\n }\n }\n}\n","import { useState } from 'react';\nimport type { CSSProperties, ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronRight, faEllipsis } from '@fortawesome/free-solid-svg-icons';\n\nimport InteractableDiv from '../interactableDiv';\nimport ActionIcon from '../actionIcon';\nimport FloatingMenu from '../floatingMenu';\nimport { useComponentDefaults } from '../configProvider';\nimport type { BreadcrumbItem, BreadcrumbProps } from './breadcrumb.types';\n\nimport styles from './breadcrumb.module.pcss';\n\ninterface IndexedItem {\n item: BreadcrumbItem;\n index: number;\n}\n\nfunction getGroups(items: BreadcrumbItem[], maxItems?: number) {\n const indexed = items.map((item, index) => ({ item, index }));\n if (!maxItems || items.length <= maxItems) {\n return { leading: indexed, hidden: [] as IndexedItem[], trailing: [] as IndexedItem[] };\n }\n\n const trailingCount = Math.max(1, maxItems - 2);\n const hiddenCount = items.length - 1 - trailingCount;\n if (hiddenCount <= 0) {\n return { leading: indexed, hidden: [] as IndexedItem[], trailing: [] as IndexedItem[] };\n }\n\n return {\n leading: indexed.slice(0, 1),\n hidden: indexed.slice(1, 1 + hiddenCount),\n trailing: indexed.slice(1 + hiddenCount),\n };\n}\n\nfunction Breadcrumb(props: BreadcrumbProps): ReactElement {\n const {\n items = [],\n separator,\n maxItems,\n 'aria-label': ariaLabel = 'Breadcrumb',\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Breadcrumb', props);\n\n const [isHiddenMenuOpen, setIsHiddenMenuOpen] = useState(false);\n const { leading, hidden, trailing } = getGroups(items, maxItems);\n const lastIndex = items.length - 1;\n\n function renderSeparatorAfter(index: number) {\n if (index === lastIndex) return null;\n return (\n <span className={cx(styles.breadcrumbSeparator, classNames?.separator)} style={slotStyles?.separator}>\n {separator ?? <FontAwesomeIcon icon={faChevronRight} />}\n </span>\n );\n }\n\n function renderItem({ item, index }: IndexedItem) {\n return (\n <li key={item.id ?? index} className={cx(styles.breadcrumbItem, classNames?.item)} style={slotStyles?.item}>\n {renderCrumb(item, index === lastIndex, styles, classNames, slotStyles)}\n {renderSeparatorAfter(index)}\n </li>\n );\n }\n\n return (\n <nav\n {...rest}\n aria-label={ariaLabel}\n className={cx(styles.breadcrumb, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <ol className={cx(styles.breadcrumbList, classNames?.list)} style={slotStyles?.list}>\n {leading.map(renderItem)}\n\n {hidden.length > 0 && (\n <li className={cx(styles.breadcrumbItem, classNames?.item)} style={slotStyles?.item}>\n <FloatingMenu\n isOpen={isHiddenMenuOpen}\n onOpenChange={setIsHiddenMenuOpen}\n dontCloseOnChildClick\n content={\n <ul className={cx(styles.breadcrumbHiddenList, classNames?.hiddenList)} style={slotStyles?.hiddenList}>\n {hidden.map(({ item, index }) => (\n <li\n key={item.id ?? index}\n className={cx(styles.breadcrumbHiddenItem, classNames?.hiddenItem)}\n style={slotStyles?.hiddenItem}\n >\n {renderCrumb(\n {\n ...item,\n onClick: (event) => {\n item.onClick?.(event);\n setIsHiddenMenuOpen(false);\n },\n },\n false,\n styles,\n classNames,\n slotStyles\n )}\n </li>\n ))}\n </ul>\n }\n >\n <ActionIcon\n icon={faEllipsis}\n title=\"Show hidden breadcrumbs\"\n aria-label=\"Show hidden breadcrumbs\"\n className={cx(styles.breadcrumbEllipsis, classNames?.ellipsis)}\n style={slotStyles?.ellipsis}\n />\n </FloatingMenu>\n {renderSeparatorAfter(hidden[hidden.length - 1].index)}\n </li>\n )}\n\n {trailing.map(renderItem)}\n </ol>\n </nav>\n );\n}\n\nfunction renderCrumb(\n item: BreadcrumbItem,\n isCurrent: boolean,\n styles: Record<string, string>,\n classNames: BreadcrumbProps['classNames'],\n slotStyles: BreadcrumbProps['styles']\n) {\n const content = (\n <>\n {item.icon && (\n <FontAwesomeIcon\n icon={item.icon}\n className={cx(styles.breadcrumbIcon, classNames?.icon)}\n style={slotStyles?.icon as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n )}\n {item.label}\n </>\n );\n\n if (isCurrent) {\n return (\n <span\n aria-current=\"page\"\n className={cx(styles.breadcrumbCurrent, classNames?.current)}\n style={slotStyles?.current}\n >\n {content}\n </span>\n );\n }\n\n if (item.disabled) {\n return (\n <span className={cx(styles.breadcrumbLink, styles.breadcrumbLinkDisabled, classNames?.link)} style={slotStyles?.link}>\n {content}\n </span>\n );\n }\n\n if (item.href) {\n return (\n <a\n href={item.href}\n onClick={item.onClick}\n className={cx(styles.breadcrumbLink, classNames?.link)}\n style={slotStyles?.link}\n >\n {content}\n </a>\n );\n }\n\n if (item.onClick) {\n return (\n <InteractableDiv\n onClick={item.onClick}\n className={cx(styles.breadcrumbLink, classNames?.link)}\n style={slotStyles?.link}\n >\n {content}\n </InteractableDiv>\n );\n }\n\n return (\n <span className={cx(styles.breadcrumbLink, styles.breadcrumbLinkDisabled, classNames?.link)} style={slotStyles?.link}>\n {content}\n </span>\n );\n}\n\nexport default Breadcrumb;\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { HtmlProps } from '../types/slots.types';\n\nexport enum ButtonGroupOrientation {\n Horizontal = 'horizontal',\n Vertical = 'vertical',\n}\n\nexport interface ButtonGroupProps extends HtmlProps {\n children?: ReactNode;\n orientation?: ButtonGroupOrientation;\n className?: string;\n style?: CSSProperties;\n}\n",".buttonGroup {\n display: inline-flex;\n align-items: stretch;\n\n /* Each rule below targets its position with a pseudo-class (:first-child, :last-child, or\n :not()), which contributes extra specificity beyond a plain class selector. That's what\n reliably beats a child component's own base border-radius rule (e.g. Button's), regardless\n of which CSS module happens to load first in the final bundle — a plain \".buttonGroup > *\"\n reset would tie on specificity with Button's own class and depend on load order.\n\n A nested ButtonGroup (role=\"group\") is excluded throughout: it manages its own corners and\n spacing internally, so the outer group only arranges it as a self-contained unit rather than\n reaching into it. */\n > *:not(:first-child):not(:last-child):not([role='group']) {\n border-radius: 0;\n }\n\n > *:hover,\n > *:focus-within {\n z-index: 1;\n }\n\n &:not(&-vertical) {\n /* A separator (e.g. a vertical Divider) is meant to stay visible between two buttons, not\n merge into one of them, so it's excluded from the border-collapsing overlap below — and\n so is whatever comes right after one, since that overlap is only meant to collapse two\n adjacent button borders, not eat into the separator itself. A nested ButtonGroup is\n excluded the same way, and given real spacing instead, rather than being squeezed 1px\n into whatever's next to it. */\n > *:not(:first-child):not([role='separator']):not([role='group']) {\n margin-left: -1px;\n }\n\n /* Matches the specificity of the collapse rule above (three :not()s deep, not two) so this\n reliably wins the override regardless of source order — the collapse rule's own three\n :not()s (:first-child, [role=separator], [role=group]) outweigh an adjacency selector with\n only one, so a fourth, redundant :not() is added here purely to close that gap. The\n trailing :not([role='group']) on both lines also keeps this from matching when the\n following element is itself a nested group — that case must fall through to the dedicated\n 8px group-spacing rule below, not get zeroed. */\n > [role='separator'] + *:not(:first-child):not([role='group']),\n > [role='group'] + *:not(:first-child):not([role='separator']):not([role='group']) {\n margin-left: 0;\n }\n\n > [role='group']:not(:first-child) {\n margin-left: 8px;\n }\n\n > *:first-child:not(:last-child):not([role='group']) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n\n > *:last-child:not(:first-child):not([role='group']) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n }\n\n &-vertical {\n flex-direction: column;\n\n > *:not(:first-child):not([role='separator']):not([role='group']) {\n margin-top: -1px;\n }\n\n > [role='separator'] + *:not(:first-child):not([role='group']),\n > [role='group'] + *:not(:first-child):not([role='separator']):not([role='group']) {\n margin-top: 0;\n }\n\n > [role='group']:not(:first-child) {\n margin-top: 8px;\n }\n\n > *:first-child:not(:last-child):not([role='group']) {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n }\n\n > *:last-child:not(:first-child):not([role='group']) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n }\n}\n","import cx from 'classnames';\nimport type { ReactElement } from 'react';\n\nimport { ButtonGroupOrientation } from './buttonGroup.types';\nimport type { ButtonGroupProps } from './buttonGroup.types';\nimport styles from './buttonGroup.module.pcss';\n\nfunction ButtonGroup({\n children,\n orientation = ButtonGroupOrientation.Horizontal,\n className,\n style,\n ...rest\n}: ButtonGroupProps): ReactElement {\n return (\n <div\n {...rest}\n role=\"group\"\n className={cx(styles.buttonGroup, { [styles.buttonGroupVertical]: orientation === ButtonGroupOrientation.Vertical }, className)}\n style={style}\n >\n {children}\n </div>\n );\n}\n\nexport default ButtonGroup;\n","import type { ReactNode } from 'react';\nimport type { ButtonStyleType } from '../button/button.types';\nimport type { HtmlProps } from '../types/slots.types';\nimport type { IconAction } from '../types/actions.types';\n\nexport enum CardStyleType {\n Elevated = 'elevated',\n Outlined = 'outlined',\n Filled = 'filled',\n}\n\nexport interface CardProps extends HtmlProps {\n className?: string | undefined;\n children?: ReactNode;\n styleType?: CardStyleType;\n onClick?: () => void;\n tabIndex?: number | null;\n hoverEffect?: boolean;\n style?: React.CSSProperties;\n autoGap?: boolean;\n clip?: boolean;\n}\n\nexport type CardHeaderAction = IconAction;\n\nexport interface CardHeaderProps {\n className?: string;\n title?: ReactNode;\n subTitle?: ReactNode;\n /** URL string → rendered as background-image. Any other ReactNode → rendered inside the thumbnail div. */\n thumbnail?: string | ReactNode;\n actions?: CardHeaderAction[] | ReactNode;\n}\n\nexport interface CardMediaProps {\n src?: string;\n alt?: string;\n}\n\nexport interface CardContentProps {\n children?: ReactNode;\n}\n\nexport interface CardAction {\n id?: string;\n label?: string;\n styleType?: ButtonStyleType;\n onClick?: () => void;\n}\n\nexport interface CardActionsProps {\n className?: string;\n /** Renders a Button for each action object. Pass `children` for custom content instead. */\n actions?: CardAction[];\n children?: ReactNode;\n}\n",".card {\n border-radius: var(--default-border-radius);\n color: var(--text-color);\n border: 1px solid transparent;\n box-sizing: border-box;\n\n &-clip {\n overflow: hidden;\n }\n\n &-padding {\n padding: 16px;\n }\n\n &-gaps {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-s);\n }\n\n &-style {\n &-elevated {\n background: var(--background-card-elevated, var(--background-accent-light));\n box-shadow: var(--card-shadow);\n }\n\n &-outlined {\n background: var(--background-card-outlined, transparent);\n border-color: var(--border-color);\n }\n\n &-filled {\n background: var(--background-card-filled, var(--background-accent));\n }\n }\n\n &-interactable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-hover {\n transition:\n transform 0.15s ease,\n box-shadow 0.15s ease,\n filter 0.3s ease;\n\n &:hover {\n transform: translateY(-2px);\n background: var(--background-accent);\n }\n }\n}\n\n.cardHeader {\n display: flex;\n gap: 16px;\n align-items: center;\n\n &-thumbnail {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 40px;\n height: 40px;\n background: rgba(0, 0, 0, 0.08);\n border-radius: 40px;\n overflow: hidden;\n background-size: cover;\n background-position: center;\n flex-shrink: 0;\n }\n\n &-actions {\n display: flex;\n gap: var(--spacing-s);\n flex-wrap: wrap;\n flex-shrink: 1;\n align-items: center;\n justify-content: flex-end;\n }\n\n &-titles {\n display: flex;\n flex-flow: column;\n flex: 1;\n gap: 4px;\n overflow: hidden;\n\n &-main {\n font-size: 18px;\n font-weight: 600;\n min-width: 3ch;\n flex-shrink: 100000;\n overflow: hidden;\n text-overflow: ellipsis;\n\n &-container {\n display: flex;\n align-items: center;\n gap: var(--spacing-m);\n justify-content: space-between;\n }\n }\n\n &-sub {\n font-weight: 300;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n }\n}\n\n.cardMedia {\n width: calc(100% + 32px);\n margin: 0 -16px 0 -16px;\n}\n\n.cardActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n","import cx from 'classnames';\n\nimport { CardStyleType, type CardProps } from './card.types';\nimport styles from './card.module.pcss';\nimport InteractableDiv from '../interactableDiv';\nimport Ripple from '../ripple';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_STYLE: Record<CardStyleType, string> = {\n elevated: styles.cardStyleElevated,\n outlined: styles.cardStyleOutlined,\n filled: styles.cardStyleFilled,\n};\n\nfunction Card(props: CardProps) {\n const {\n className = undefined,\n children = null,\n styleType = CardStyleType.Elevated,\n onClick = undefined,\n tabIndex = null,\n hoverEffect = undefined,\n style = undefined,\n autoGap = true,\n clip = false,\n ...rest\n } = useComponentDefaults('Card', props);\n const isInteractable = !!onClick;\n\n return (\n <InteractableDiv\n {...rest}\n className={cx(\n styles.card,\n CLASS_BY_STYLE[styleType],\n clip && styles.cardClip,\n isInteractable && styles.cardInteractable,\n ((isInteractable && hoverEffect !== false) || hoverEffect) && styles.cardHover,\n className\n )}\n onClick={onClick}\n tabIndex={tabIndex ?? (isInteractable ? 0 : null)}\n style={style}\n >\n <Ripple\n disabled={!isInteractable}\n className={cx(styles.cardPadding, autoGap && styles.cardGaps)}\n style={{ borderRadius: 'inherit' }}\n >\n {children}\n </Ripple>\n </InteractableDiv>\n );\n}\n\nexport default Card;\n","import React from 'react';\nimport cx from 'classnames';\n\nimport type { CardHeaderProps } from './card.types';\nimport styles from './card.module.pcss';\nimport ActionIcon from '../actionIcon';\n\nfunction CardHeader({\n className = '',\n title = '',\n subTitle = '',\n thumbnail = '',\n actions = undefined,\n}: CardHeaderProps) {\n const thumbnailUrl =\n typeof thumbnail === 'string' && thumbnail.startsWith('http') ? thumbnail : undefined;\n\n return (\n <div className={cx(styles.cardHeader, className)}>\n {thumbnail && (\n <div\n className={styles.cardHeaderThumbnail}\n style={thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}}\n >\n {!thumbnailUrl && thumbnail}\n </div>\n )}\n <div className={styles.cardHeaderTitles}>\n <div className={styles.cardHeaderTitlesMainContainer}>\n <div className={styles.cardHeaderTitlesMain}>{title}</div>\n <div className={styles.cardHeaderActions}>\n {Array.isArray(actions)\n ? actions.map((action, index) => (\n <ActionIcon\n key={index}\n title={action.title}\n onClick={action.onClick ? (e: React.MouseEvent<HTMLDivElement>) => { e.stopPropagation(); action.onClick?.(e); } : undefined}\n icon={action.icon}\n />\n ))\n : actions}\n </div>\n </div>\n <div className={styles.cardHeaderTitlesSub}>{subTitle}</div>\n </div>\n </div>\n );\n}\n\nexport default CardHeader;\n","import React from 'react';\n\nimport type { CardMediaProps } from './card.types';\nimport styles from './card.module.pcss';\n\nfunction CardMedia({ src = '', alt = '' }: CardMediaProps) {\n return <img className={styles.cardMedia} src={src} alt={alt} />;\n}\n\nexport default CardMedia;\n","import React from 'react';\n\nimport type { CardContentProps } from './card.types';\n\nfunction CardContent({ children = null }: CardContentProps) {\n return <>{children}</>;\n}\n\nexport default CardContent;\n","import React from 'react';\nimport cx from 'classnames';\nimport Button from '../button';\nimport { ButtonStyleType } from '../button/button.types';\n\nimport type { CardActionsProps } from './card.types';\nimport styles from './card.module.pcss';\n\nfunction CardActions({ className = '', actions = [], children = null }: CardActionsProps) {\n return (\n <div className={cx(styles.cardActions, className)}>\n {actions.map(({ id, onClick, label, styleType = ButtonStyleType.Default }) => (\n <div key={id ?? label}>\n <Button onClick={onClick} styleType={styleType}>\n {label}\n </Button>\n </div>\n ))}\n {children}\n </div>\n );\n}\n\nexport default CardActions;\n",".carousel {\n position: relative;\n overflow: hidden;\n border-radius: var(--default-border-radius);\n\n &-track {\n display: flex;\n align-items: stretch;\n transition: transform 0.4s ease;\n touch-action: pan-y;\n user-select: none;\n }\n\n &-slide {\n flex-shrink: 0;\n box-sizing: border-box;\n }\n\n &-prevButton,\n &-nextButton {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n z-index: 1;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n background: var(--background-accent);\n color: var(--text-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: opacity 0.15s, background 0.15s;\n\n &:hover {\n background: var(--background-accent-light);\n }\n }\n\n &-buttonDisabled {\n opacity: 0.35;\n pointer-events: none;\n }\n\n &-prevButton {\n left: 12px;\n }\n\n &-nextButton {\n right: 12px;\n }\n\n &-dots {\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 1;\n display: flex;\n gap: 8px;\n }\n\n &-dot {\n width: 8px;\n height: 8px;\n border-radius: 2000px;\n background: var(--background-accent);\n opacity: 0.6;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: opacity 0.15s, background 0.15s, width 0.15s;\n\n &:hover {\n opacity: 0.85;\n }\n\n &-active {\n background: var(--primary-color);\n opacity: 1;\n width: 20px;\n }\n }\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults } from '../configProvider';\nimport type { CarouselProps } from './carousel.types';\n\nimport styles from './carousel.module.pcss';\n\nconst AXIS_LOCK_THRESHOLD = 10;\nconst DRAG_COMMIT_RATIO = 0.2;\n\nfunction Carousel(props: CarouselProps) {\n const {\n children,\n currentIndex,\n defaultIndex = 0,\n onChange = () => {},\n loop = true,\n autoPlay = false,\n autoPlayInterval = 4000,\n pauseOnHover = true,\n showArrows = true,\n showDots = true,\n swipeable = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Carousel', props);\n\n const slides = React.Children.toArray(children);\n const count = slides.length;\n const canLoop = loop && count > 1;\n const offset = canLoop ? 1 : 0;\n const extendedSlides = canLoop ? [slides[count - 1], ...slides, slides[0]] : slides;\n\n const isControlled = currentIndex !== undefined;\n const [internalIndex, setInternalIndex] = useState(() => clampIndex(defaultIndex, count, canLoop));\n const realIndex = clampIndex(isControlled ? currentIndex! : internalIndex, count, canLoop);\n\n const [displayIndex, setDisplayIndex] = useState(realIndex + offset);\n const [transitionEnabled, setTransitionEnabled] = useState(true);\n const prevRealIndexRef = useRef(realIndex);\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n const [dragging, setDragging] = useState(false);\n const [dragOffsetPercent, setDragOffsetPercent] = useState(0);\n\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const prevReal = prevRealIndexRef.current;\n prevRealIndexRef.current = realIndex;\n if (prevReal === realIndex) return;\n\n const forwardWrap = canLoop && prevReal === count - 1 && realIndex === 0;\n const backwardWrap = canLoop && prevReal === 0 && realIndex === count - 1;\n\n setTransitionEnabled(true);\n if (forwardWrap) {\n setDisplayIndex((d) => d + 1);\n } else if (backwardWrap) {\n setDisplayIndex((d) => d - 1);\n } else {\n setDisplayIndex(realIndex + offset);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [realIndex]);\n\n function goToIndex(nextIndex: number) {\n const clamped = clampIndex(nextIndex, count, canLoop);\n if (!isControlled) setInternalIndex(clamped);\n onChange(clamped);\n }\n\n function goNext() {\n if (!canLoop && realIndex >= count - 1) return;\n goToIndex(realIndex + 1);\n }\n\n function goPrev() {\n if (!canLoop && realIndex <= 0) return;\n goToIndex(realIndex - 1);\n }\n\n function handleTrackTransitionEnd(event: React.TransitionEvent<HTMLDivElement>) {\n if (event.target !== event.currentTarget || !canLoop) return;\n if (displayIndex === 0) {\n setTransitionEnabled(false);\n setDisplayIndex(count);\n } else if (displayIndex === extendedSlides.length - 1) {\n setTransitionEnabled(false);\n setDisplayIndex(1);\n }\n }\n\n const isPaused = (pauseOnHover && (hovered || focused)) || dragging;\n useEffect(() => {\n if (!autoPlay || count <= 1 || isPaused) return;\n const timer = setInterval(goNext, autoPlayInterval);\n return () => clearInterval(timer);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [autoPlay, autoPlayInterval, isPaused, realIndex, count]);\n\n const dragRef = useRef<{\n startX: number;\n startY: number;\n axisLocked: boolean;\n active: boolean;\n } | null>(null);\n\n function handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n if (!swipeable || count <= 1) return;\n dragRef.current = { startX: event.clientX, startY: event.clientY, axisLocked: false, active: true };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (!drag || !drag.active) return;\n\n const deltaX = event.clientX - drag.startX;\n const deltaY = event.clientY - drag.startY;\n\n if (!drag.axisLocked) {\n if (Math.abs(deltaX) < AXIS_LOCK_THRESHOLD && Math.abs(deltaY) < AXIS_LOCK_THRESHOLD) return;\n if (Math.abs(deltaY) > Math.abs(deltaX)) {\n drag.active = false;\n return;\n }\n drag.axisLocked = true;\n setDragging(true);\n setTransitionEnabled(false);\n }\n\n const width = containerRef.current?.getBoundingClientRect().width || 1;\n setDragOffsetPercent((deltaX / width) * 100);\n }\n\n function handlePointerUp() {\n const drag = dragRef.current;\n dragRef.current = null;\n if (!drag || !drag.axisLocked) {\n setDragging(false);\n return;\n }\n\n const committed = Math.abs(dragOffsetPercent) >= DRAG_COMMIT_RATIO * 100;\n setDragOffsetPercent(0);\n setTransitionEnabled(true);\n setDragging(false);\n if (committed) {\n if (dragOffsetPercent < 0) goNext();\n else goPrev();\n }\n }\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n goPrev();\n } else if (event.key === 'ArrowRight') {\n event.preventDefault();\n goNext();\n }\n }\n\n const isPrevDisabled = !canLoop && realIndex <= 0;\n const isNextDisabled = !canLoop && realIndex >= count - 1;\n\n const slideWidthPercent = extendedSlides.length > 0 ? 100 / extendedSlides.length : 100;\n const trackTransform = `translateX(calc(${-displayIndex * slideWidthPercent}% + ${dragOffsetPercent * (slideWidthPercent / 100)}%))`;\n\n return (\n <div\n {...rest}\n ref={containerRef}\n role=\"region\"\n aria-roledescription=\"carousel\"\n className={cx(styles.carousel, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n onMouseEnter={pauseOnHover ? () => setHovered(true) : undefined}\n onMouseLeave={pauseOnHover ? () => setHovered(false) : undefined}\n onFocus={pauseOnHover ? () => setFocused(true) : undefined}\n onBlur={pauseOnHover ? () => setFocused(false) : undefined}\n onKeyDown={handleKeyDown}\n >\n <div\n className={cx(styles.carouselTrack, classNames?.track)}\n style={{\n width: `${extendedSlides.length * 100}%`,\n transform: trackTransform,\n transition: transitionEnabled ? undefined : 'none',\n ...slotStyles?.track,\n }}\n onTransitionEnd={handleTrackTransitionEnd}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n {extendedSlides.map((slide, idx) => {\n const isClonePosition = canLoop && (idx === 0 || idx === extendedSlides.length - 1);\n const logicalIndex = idx - offset;\n const isActive = !isClonePosition && logicalIndex === realIndex;\n\n return (\n <div\n key={`carousel-slide-${idx}`}\n className={cx(styles.carouselSlide, classNames?.slide)}\n style={{ width: `${100 / extendedSlides.length}%`, ...slotStyles?.slide }}\n inert={isActive ? undefined : true}\n >\n {slide}\n </div>\n );\n })}\n </div>\n\n {showArrows && count > 1 && (\n <>\n <ActionIcon\n icon={faChevronLeft}\n title=\"Previous slide\"\n aria-label=\"Previous slide\"\n aria-disabled={isPrevDisabled || undefined}\n onClick={() => !isPrevDisabled && goPrev()}\n className={cx(styles.carouselPrevButton, isPrevDisabled && styles.carouselButtonDisabled, classNames?.prevButton)}\n style={slotStyles?.prevButton}\n />\n <ActionIcon\n icon={faChevronRight}\n title=\"Next slide\"\n aria-label=\"Next slide\"\n aria-disabled={isNextDisabled || undefined}\n onClick={() => !isNextDisabled && goNext()}\n className={cx(styles.carouselNextButton, isNextDisabled && styles.carouselButtonDisabled, classNames?.nextButton)}\n style={slotStyles?.nextButton}\n />\n </>\n )}\n\n {showDots && count > 1 && (\n <div className={cx(styles.carouselDots, classNames?.dots)} style={slotStyles?.dots}>\n {slides.map((_, index) => (\n <InteractableDiv\n key={`carousel-dot-${index}`}\n aria-label={`Go to slide ${index + 1}`}\n aria-current={index === realIndex}\n onClick={() => goToIndex(index)}\n className={cx(styles.carouselDot, index === realIndex && styles.carouselDotActive, classNames?.dot)}\n style={slotStyles?.dot}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction clampIndex(index: number, count: number, canLoop: boolean): number {\n if (count === 0) return 0;\n if (canLoop) return ((index % count) + count) % count;\n return Math.max(0, Math.min(count - 1, index));\n}\n\nexport default Carousel;\n","\n.checkbox {\n user-select: none;\n display: flex;\n align-items: center;\n column-gap: 10px;\n margin: -1px;\n border: 1px solid transparent;\n width: fit-content;\n\n &-icon {\n color: #a3a9b9;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n background-color: var(--light-background-color);\n width: fit-content;\n height: fit-content;\n /* width: 16px;\n height: 16px; */\n }\n\n &-loading {\n background: transparent;\n\n &-spinner {\n width: 100%;\n height: 100%;\n }\n }\n\n &-pointer {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &:focus-visible {\n outline: none;\n border: 1px solid var(--primary-color);\n border-radius: 6px;\n }\n\n &-disabled {\n filter: brightness(0.8);\n cursor: not-allowed;\n }\n\n &-checkmark {\n border: 1.8px solid var(--text-color);\n border-radius: var(--default-border-radius);\n position: relative;\n\n svg {\n stroke: var(--text-on-primary);\n stroke-dasharray: 5;\n stroke-dashoffset: 5;\n transition:\n transform 0.1s,\n stroke-dashoffset 0.4s;\n transition-delay: 0s, 0.2s;\n background: var(--primary-color);\n transform: scale(0);\n box-sizing: content-box;\n padding: 2px;\n border-radius: var(--default-border-radius);\n }\n\n &-checked {\n svg {\n stroke-dashoffset: 0;\n transform: scale(1) translate(-3px, -3px);\n }\n }\n }\n}\n","import { useRef, useEffect, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport Ripple from 'components/common/ripple';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport { useComponentDefaults } from '../configProvider';\n\nimport type { CheckboxProps } from './checkbox.types';\nimport styles from './checkbox.module.pcss';\n\nfunction Checkbox(props: CheckboxProps): ReactElement {\n const {\n label = '',\n selected = false,\n onToggle = () => {},\n className = '',\n style,\n disabled = false,\n lineHeight = '',\n title = '',\n tabIndex = 0,\n cursorDefault = false,\n width = '17px',\n height = '17px',\n formValidator = null,\n children = null,\n background = null,\n isLoading = false,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Checkbox', props);\n const rippleRef = useRef<{ addRipple: () => void }>(null);\n const [, forceUpdate] = useState(0);\n\n useEffect(() => {\n if (!formValidator) return;\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n function handleToggle(event?: React.MouseEvent | React.KeyboardEvent) {\n if (disabled || isLoading) return;\n rippleRef.current?.addRipple();\n if (formValidator) {\n formValidator.set(!formValidator.value);\n }\n onToggle(!selected, event);\n }\n\n const currSelected = (formValidator ? formValidator.value : selected) as boolean;\n\n return (\n <div\n {...rest}\n className={cx(\n styles.checkbox,\n {\n [styles.checkboxDisabled]: disabled,\n [styles.checkboxPointer]: !cursorDefault,\n },\n className\n )}\n style={style}\n onClick={handleToggle}\n onKeyPress={(e) => { if (e.key === 'Enter') handleToggle(e); }}\n role=\"checkbox\"\n aria-checked={currSelected}\n aria-disabled={disabled || undefined}\n tabIndex={tabIndex}\n >\n <div\n title={title}\n className={cx(styles.checkboxIcon, isLoading ? styles.checkboxLoading : null, classNames?.icon)}\n style={slotStyles?.icon}\n >\n {isLoading ? (\n <div style={{ width, height }}>\n <SpinnerLoading className={styles.checkboxLoadingSpinner} />\n </div>\n ) : (\n <div\n style={{ width, height, ...slotStyles?.checkmark }}\n className={cx(\n styles.checkboxCheckmark,\n currSelected && styles.checkboxCheckmarkChecked,\n classNames?.checkmark\n )}\n >\n <Ripple\n ref={rippleRef}\n manualOnly\n overflowHidden={false}\n rippleAnimationLength={0.3}\n rippleBackground=\"radial-gradient(transparent, var(--primary-color))\"\n />\n <svg\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"-0.5 -1.5 4 2.6\"\n width={`calc(${width} + 1px)`}\n height={`calc(${height} + 1px)`}\n {...(background ? { style: { background } } : {})}\n >\n <path d=\"M 0 0 l 1 1 l 2 -2\" strokeWidth=\"0.4\" fill=\"none\" />\n </svg>\n </div>\n )}\n </div>\n <div className={classNames?.label} style={{ lineHeight: lineHeight || '100%', ...slotStyles?.label }}>{children || label}</div>\n </div>\n );\n}\n\nexport default Checkbox;\n","import type { HtmlProps } from '../types/slots.types';\n\nexport enum ChipStyleType {\n Default = 'default',\n Primary = 'primary',\n Info = 'info',\n Warn = 'warn',\n Error = 'error',\n}\n\nexport interface ChipProps extends HtmlProps {\n className?: string;\n text?: string;\n thumbnail?: React.ReactNode;\n styleType?: ChipStyleType;\n showRemoveIcon?: boolean;\n onClick?: () => void;\n onRemove?: () => void;\n}\n\nexport interface ChipContainerProps extends HtmlProps {\n className?: string;\n children?: React.ReactNode;\n inline?: boolean;\n}\n",".chip {\n background: rgba(0, 0, 0, 0.08);\n border-radius: 99999px;\n width: fit-content;\n position: relative;\n box-sizing: border-box;\n max-width: 100%;\n\n &-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-style {\n &-default {\n background: rgba(0, 0, 0, 0.08);\n color: var(--text-color);\n }\n\n &-primary {\n background: var(--primary-color);\n color: var(--text-on-primary);\n }\n\n &-info {\n background: var(--info-lighter);\n color: var(--info-color);\n }\n\n &-warn {\n background: var(--warn-lighter);\n color: var(--warn-color);\n }\n\n &-error {\n background: var(--error-lighter);\n color: var(--error-color);\n }\n }\n\n &-inner {\n display: flex;\n gap: 8px;\n align-items: center;\n padding: 4px 8px;\n\n & > * {\n white-space: nowrap;\n }\n }\n\n &-text {\n text-overflow: ellipsis;\n overflow: hidden;\n }\n\n &-thumbnail {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 18px;\n height: 18px;\n background: rgba(0, 0, 0, 0.08);\n border-radius: 18px;\n overflow: hidden;\n background-size: cover;\n }\n\n &-container {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n\n &-inline {\n flex-wrap: nowrap;\n overflow: auto;\n }\n }\n}\n","import React, { useMemo } from 'react';\nimport { faXmarkCircle } from '@fortawesome/free-solid-svg-icons';\nimport cx from 'classnames';\n\nimport Ripple from '../ripple';\nimport ActionIcon from '../actionIcon';\nimport { ChipStyleType, ChipProps } from './chip.types';\nimport { useComponentDefaults } from '../configProvider';\n\nimport styles from './chip.module.pcss';\n\nconst CLASS_BY_STYLE: Record<ChipStyleType, string> = {\n default: styles.chipStyleDefault,\n primary: styles.chipStylePrimary,\n info: styles.chipStyleInfo,\n warn: styles.chipStyleWarn,\n error: styles.chipStyleError,\n};\n\nfunction Chip(props: ChipProps) {\n const {\n className = '',\n thumbnail = '',\n text = '',\n styleType = ChipStyleType.Default,\n showRemoveIcon = false,\n onClick,\n onRemove,\n ...rest\n } = useComponentDefaults('Chip', props);\n const thumbnailUrl = useMemo(() => {\n if (typeof thumbnail === 'string' && thumbnail.startsWith('http')) return thumbnail;\n return undefined;\n }, [thumbnail]);\n\n return (\n <div\n {...rest}\n className={cx(styles.chip, CLASS_BY_STYLE[styleType], onClick && styles.chipClickable, className)}\n onClick={onClick}\n >\n <Ripple disabled={!onClick} style={{ borderRadius: 'inherit' }}>\n <div className={styles.chipInner}>\n {thumbnail && (\n <div\n className={styles.chipThumbnail}\n style={thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}}\n >\n {!thumbnailUrl && thumbnail}\n </div>\n )}\n <div className={styles.chipText}>{text}</div>\n {showRemoveIcon && <ActionIcon icon={faXmarkCircle} onClick={(e) => { e.stopPropagation(); onRemove?.(); }} />}\n </div>\n </Ripple>\n </div>\n );\n}\n\nexport default Chip;\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { ChipContainerProps } from './chip.types';\nimport styles from './chip.module.pcss';\n\nfunction ChipContainer({\n className = undefined,\n children = null,\n inline = false,\n ...rest\n}: ChipContainerProps): ReactElement {\n return (\n <div {...rest} className={cx(styles.chipContainer, inline && styles.chipContainerInline, className)}>\n {children}\n </div>\n );\n}\n\nexport default ChipContainer;\n","\n.tooltipAnchor {\n position: fixed;\n z-index: 10;\n}\n\n.tooltipBubble {\n position: absolute;\n bottom: 0;\n margin-bottom: 6px;\n left: 0;\n border-radius: 3px;\n width: max-content;\n max-width: 200px;\n font-size: 12px;\n background-color: #454953;\n padding: 6px 9px;\n color: white;\n pointer-events: none;\n\n .tooltip-anchor-flip & {\n bottom: auto;\n top: 0;\n margin-bottom: 0;\n margin-top: 6px;\n }\n\n &:after {\n content: '';\n position: absolute;\n top: 100%;\n left: calc(var(--tooltip-trigger-width, 10px) / 2 - 5px);\n border-width: 5px;\n border-style: solid;\n border-color: #454953 transparent transparent transparent;\n }\n\n .tooltip-anchor-flip &:after {\n top: auto;\n bottom: 100%;\n border-color: transparent transparent #454953 transparent;\n }\n}\n\n.tooltipDetails {\n position: relative;\n display: inline-flex;\n align-items: center;\n\n &-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n font-size: 11px;\n font-weight: 700;\n background-color: #454953;\n color: white;\n cursor: default;\n user-select: none;\n }\n}\n\n.tooltipError {\n position: absolute;\n bottom: 0;\n margin-bottom: 6px;\n right: 0;\n width: max-content;\n border-radius: 3px;\n background-color: var(--error-lighter);\n color: var(--red);\n font-size: 10px;\n padding: 6px 9px;\n\n .tooltip-anchor-flip & {\n bottom: auto;\n top: 0;\n margin-bottom: 0;\n margin-top: 6px;\n }\n\n &:after {\n content: '';\n position: absolute;\n top: 100%;\n right: 12px;\n border-width: 5px;\n border-style: solid;\n border-color: var(--error-border-color) transparent transparent transparent;\n }\n\n .tooltip-anchor-flip &:after {\n top: auto;\n bottom: 100%;\n border-color: transparent transparent var(--error-border-color) transparent;\n }\n}\n","import React, { useLayoutEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\nimport { useFloatingPosition } from '../floatingMenu/useFloatingPosition';\nimport styles from './tooltip.module.pcss';\nimport type { TooltipProps } from './tooltip.types';\n\nexport default function Tooltip({\n variant,\n message = '',\n isVisible = true,\n tooltipPosition,\n onClick,\n}: TooltipProps) {\n const [detailsHovered, setDetailsHovered] = useState(false);\n\n const sentinelRef = useRef<HTMLSpanElement>(null);\n const detailsRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const [triggerWidth, setTriggerWidth] = useState(10);\n\n const shown = variant === 'details' ? detailsHovered : isVisible;\n\n useLayoutEffect(() => {\n triggerRef.current = variant === 'details' ? detailsRef.current : (sentinelRef.current?.parentElement ?? null);\n });\n\n useLayoutEffect(() => {\n if (shown) {\n const rect = triggerRef.current?.getBoundingClientRect();\n setTriggerWidth(rect?.width ?? 10);\n }\n }, [shown]);\n\n useFloatingPosition({\n isOpen: shown,\n triggerRef,\n anchorRef,\n panelRef,\n flipClassName: styles.tooltipAnchorFlip,\n placement: 'top',\n });\n\n const bubble = shown && (\n <BodyEnd>\n <div\n ref={anchorRef}\n className={styles.tooltipAnchor}\n style={{ width: `${triggerWidth}px`, '--tooltip-trigger-width': `${triggerWidth}px` } as React.CSSProperties}\n >\n <div\n ref={panelRef}\n className={cx(variant === 'error' ? styles.tooltipError : styles.tooltipBubble, tooltipPosition)}\n onClick={onClick}\n >\n {message}\n </div>\n </div>\n </BodyEnd>\n );\n\n if (variant === 'details') {\n return (\n <div ref={detailsRef} className={styles.tooltipDetails}>\n <span\n className={styles.tooltipDetailsIcon}\n onMouseEnter={() => setDetailsHovered(true)}\n onMouseLeave={() => setDetailsHovered(false)}\n >\n ?\n </span>\n {bubble}\n </div>\n );\n }\n\n if (variant === 'info' || variant === 'error') {\n return (\n <>\n <span ref={sentinelRef} style={{ display: 'none' }} />\n {bubble}\n </>\n );\n }\n\n return null;\n}\n",".animatedIcon {\n position: relative;\n display: inline-block;\n width: 1em;\n height: 1em;\n\n /* Fab's original technique: a single shared rotation on the whole icon, not per layer — both\n the outgoing and incoming icon sit at the exact same angle at every instant, only their\n opacity differs, which is what makes the spin read as one coherent piece rather than two\n icons independently rotating past each other. Always a further full turn per step (not\n Fab's 225°, which only worked there because its \"+\" icon looks identical rotated 45°) so an\n arbitrary icon always lands back upright, no matter how many times it's toggled. A real\n `transition`, so retapping mid-spin reverses smoothly from wherever it currently is instead\n of snapping. */\n &-spin {\n transition: transform var(--animated-icon-duration, 200ms) ease;\n transform: rotate(var(--animated-icon-spin-rotation, 0deg));\n\n /* The wrapper alone carries the rotation in this variant — the two layers underneath it\n only need to crossfade, not rotate individually. */\n .animatedIcon-layer {\n &:first-child,\n &:last-child {\n transform: none;\n }\n }\n }\n\n /* Two layers, always both mounted — never conditionally rendered. A `transition` only\n retargets smoothly when the property changes on an element already on screen; a freshly-\n mounted element with its \"final\" state applied in the same paint has no \"from\" state to\n animate from. Keeping both layers permanently in the DOM (like Fab does) and only ever\n toggling which one is `-front` is what makes this cancel cleanly mid-transition instead of\n jumping or finishing a stale animation. */\n &-layer {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n opacity: 0;\n transition: opacity var(--animated-icon-duration, 200ms) ease, transform var(--animated-icon-duration, 200ms) ease;\n\n /* Fixed per-layer resting pose (not per-toggle) — the first layer always approaches/leaves\n through +90°, the second always through -90°, so which direction a given swap rotates in\n depends only on which layer is taking over, the same way Fab's own icon always rotates\n between two fixed angles rather than accumulating. */\n &:first-child {\n transform: rotate(90deg) scale(0.5);\n\n &.animatedIcon-layer-front {\n transform: none;\n }\n }\n\n &:last-child {\n transform: rotate(-90deg) scale(0.5);\n\n &.animatedIcon-layer-front {\n transform: none;\n }\n }\n\n &-front {\n opacity: 1;\n }\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .animatedIcon-spin,\n .animatedIcon-layer {\n transition: none;\n }\n}\n","import { useState } from 'react';\nimport type { CSSProperties } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport type { IconDefinition } from '@fortawesome/fontawesome-svg-core';\nimport type { AnimatedIconProps } from './animatedIcon.types';\n\nimport styles from './animatedIcon.module.pcss';\n\nfunction iconKey(icon: IconDefinition) {\n return `${icon.prefix}:${icon.iconName}`;\n}\n\n// A full turn per step, not Fab's original 225° — 225° only looked right there because the\n// resting \"open\" icon (a \"+\") happens to look identical rotated 45° (it's 4-fold symmetric).\n// For arbitrary icon pairs a shared rotation has to land on a multiple of 360° every time, or\n// the new icon ends up sitting sideways.\nconst SPIN_DEGREES_PER_STEP = 360;\n\nfunction AnimatedIcon({\n icon,\n duration = 200,\n spin = false,\n className,\n style,\n onClick,\n onMouseEnter,\n onMouseLeave,\n classNames,\n styles: slotStyles,\n ...rest\n}: AnimatedIconProps) {\n // Two permanently-mounted layers, ping-ponging which one is the visible (\"front\") icon,\n // instead of conditionally mounting/unmounting an \"outgoing\" layer. That's what lets this use\n // a real CSS `transition` (which retargets smoothly from wherever it currently is) rather than\n // a keyframe `animation` (which, once started on a freshly-mounted element, plays to\n // completion regardless of what happens mid-flight): tap the toggle again before a transition\n // finishes and it reverses smoothly from its current position — the same thing that already\n // let Fab's own hand-rolled icon rotation cancel cleanly.\n const [slots, setSlots] = useState<[IconDefinition, IconDefinition]>([icon, icon]);\n const [activeIndex, setActiveIndex] = useState<0 | 1>(0);\n const [spinStep, setSpinStep] = useState(0);\n\n // Adjusting state during render (not in an effect) on a prop change: the documented React\n // pattern for reacting to a prop that changed since the last render, without an extra tick.\n if (iconKey(icon) !== iconKey(slots[activeIndex])) {\n const nextIndex = activeIndex === 0 ? 1 : 0;\n const nextSlots: [IconDefinition, IconDefinition] = [...slots];\n nextSlots[nextIndex] = icon;\n setSlots(nextSlots);\n setActiveIndex(nextIndex);\n if (spin) setSpinStep((step) => step + 1);\n }\n\n return (\n <span\n {...rest}\n className={cx(styles.animatedIcon, { [styles.animatedIconSpin]: spin }, classNames?.root, className)}\n style={{\n ...style,\n ...slotStyles?.root,\n '--animated-icon-duration': `${duration}ms`,\n '--animated-icon-spin-rotation': `${spinStep * SPIN_DEGREES_PER_STEP}deg`,\n } as CSSProperties & Record<'--animated-icon-duration' | '--animated-icon-spin-rotation', string>}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n <FontAwesomeIcon\n icon={slots[0]}\n className={cx(styles.animatedIconLayer, { [styles.animatedIconLayerFront]: activeIndex === 0 }, classNames?.icon)}\n style={slotStyles?.icon as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n <FontAwesomeIcon\n icon={slots[1]}\n className={cx(styles.animatedIconLayer, { [styles.animatedIconLayerFront]: activeIndex === 1 }, classNames?.icon)}\n style={slotStyles?.icon as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </span>\n );\n}\n\nexport default AnimatedIcon;\n","\n.required-mark {\n padding: 0px 0px 0px 4px;\n color: var(--required-mark-color, var(--error-color));\n}\n\n.input {\n position: relative;\n width: 100%;\n --input-notch-height: 1.75em;\n --input-icon-size: 1.2em;\n --input-icon-offset: 0.6em;\n --input-icon-gutter: 2.2em;\n\n &-placeholder {\n position: absolute;\n top: 50%;\n left: 7px;\n transform: translateY(-50%);\n transition: all 0.2s;\n opacity: 0;\n user-select: none;\n pointer-events: none;\n\n &-shown {\n animation: 0.2s fadeIn 0.3s forwards;\n }\n\n &-multiline {\n top: 14px;\n transform: translateY(0);\n }\n }\n\n &-matLabel {\n position: absolute;\n transition: all 0.3s;\n left: 7px;\n right: 0;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1em;\n color: var(--input-label-resting-color, var(--text-light));\n pointer-events: none;\n user-select: none;\n\n &-floating {\n top: 0;\n bottom: auto;\n left: 14px;\n right: 0;\n font-size: 0.8em;\n color: var(--input-label-floating-color, var(--text-color));\n transform: translateY(-50%);\n }\n\n &-multiline {\n top: 14px;\n transform: translateY(0);\n }\n }\n\n &-fieldset {\n position: absolute;\n width: 100%;\n margin: 0;\n padding: 0;\n min-width: 0;\n box-sizing: border-box;\n border-radius: var(--default-border-radius);\n font-size: 0.8em;\n inset: calc(var(--input-notch-height) / -2) 0 0 0;\n padding-left: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: var(--border-color);\n pointer-events: none;\n user-select: none;\n\n &-no-notch {\n /* Only Firefox actually renders the reserved notch space as a visible overlap on\n label-less inputs (e.g. crossing a divider directly above it in a tightly-packed\n layout like the sidebar search box); Chrome's rendering was never broken, just\n consistently sized with every other input. @supports (-moz-appearance: none) is a\n reliable Firefox-only feature query, so this scopes the fix to where it's needed\n instead of changing every browser's sizing. */\n @supports (-moz-appearance: none) {\n inset: 0;\n }\n }\n\n &-legend {\n display: block;\n max-width: 0;\n transition: max-width 0.2s;\n white-space: nowrap;\n padding: 0;\n\n &-active {\n max-width: 300px;\n }\n\n span {\n line-height: var(--input-notch-height);\n padding: 0 5px;\n opacity: 0;\n }\n\n span:empty {\n padding: 0.000001px;\n }\n }\n }\n\n &-iconLeft {\n .input-matLabel {\n left: var(--input-icon-gutter);\n\n &-floating {\n left: calc(var(--input-icon-gutter) + 0.5em);\n }\n }\n\n .input-placeholder {\n left: var(--input-icon-gutter);\n }\n\n .input-fieldset {\n padding-left: var(--input-icon-gutter);\n }\n }\n\n &-container {\n display: flex;\n align-items: center;\n border-radius: var(--default-border-radius);\n background-color: var(--input-background);\n transition: border-color;\n cursor: text;\n height: 100%;\n\n &-multiline {\n overflow: hidden;\n padding-top: 10px;\n align-items: flex-start;\n }\n\n &-border {\n outline: 1px solid var(--border-color);\n transition: border-color;\n background-color: var(--input-background);\n outline: none;\n\n &-focused {\n outline-color: var(--primary-color);\n border-color: var(--primary-color);\n }\n\n &-searchFocused {\n outline-color: var(--search-input-color);\n outline-width: 2px;\n border-color: var(--search-input-color);\n }\n\n &-invalid {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-invalid:hover {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-error {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n }\n }\n\n &-label {\n display: flex;\n color: var(--text-color);\n height: 100%;\n\n &-column {\n flex-direction: column;\n }\n\n &-text {\n white-space: nowrap;\n margin-right: 5px;\n margin-bottom: 6px;\n display: flex;\n align-items: center;\n color: color(var(--border-color) lightness(40%));\n background-color: transparent;\n font-size: 12px;\n position: absolute;\n top: -15px;\n white-space: nowrap;\n }\n }\n\n &-upper-right-label {\n position: absolute;\n transform: translateY(calc(-100% - 1.5px));\n right: 8px;\n min-height: 12px;\n font-size: 12px;\n color: color(var(--border-color) lightness(40%));\n }\n\n &-field {\n appearance: none;\n -webkit-appearance: none;\n font-family: inherit;\n font-size: inherit;\n box-sizing: border-box;\n resize: none;\n width: 100%;\n border: none;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n line-height: 1.25;\n color: var(--text-color);\n background: transparent;\n\n &:focus {\n outline: none;\n }\n\n &::placeholder {\n color: var(--text-light);\n }\n\n /* The browser's own search-cancel decoration doesn't match the theme — Search has its own\n themed clear icon (see isSearchCleared in input.tsx) that replaces it. */\n &::-webkit-search-cancel-button,\n &::-webkit-search-decoration {\n -webkit-appearance: none;\n appearance: none;\n display: none;\n }\n\n &-withIcon {\n padding-right: var(--input-icon-gutter) !important;\n\n &-left {\n padding-right: 0.643em !important;\n padding-left: var(--input-icon-gutter) !important;\n }\n }\n\n &-suffix {\n padding-right: 9px;\n }\n\n &-date {\n padding: 6px 9px;\n color-scheme: dark;\n\n svg {\n color: white;\n }\n }\n\n &-default {\n padding: 8px 7.5px 6px;\n }\n\n &[disabled] {\n background-color: var(--disabled-input-color);\n color: var(--disabled-font-color);\n -webkit-text-fill-color: var(--disabled-font-color);\n opacity: 1;\n\n &::placeholder {\n color: var(--disabled-font-color);\n -webkit-text-fill-color: var(--disabled-font-color);\n }\n }\n\n &-readOnly {\n cursor: default;\n color: var(--text-dark);\n -webkit-text-fill-color: var(--text-dark);\n }\n\n &-uppercase {\n text-transform: uppercase;\n }\n\n &-multiline {\n overflow-y: auto;\n resize: vertical;\n padding-top: 4px;\n min-height: 30px;\n\n &-autoResize {\n resize: none;\n overflow: hidden;\n }\n }\n\n &-icon {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: transparent;\n border: none;\n position: absolute;\n outline: none;\n right: var(--input-icon-offset);\n color: var(--input-icon-color);\n width: var(--input-icon-size) !important;\n height: var(--input-icon-size) !important;\n user-select: none;\n top: 50%;\n transform: translateY(-50%);\n\n &-left {\n left: var(--input-icon-offset);\n }\n\n &-notClickable {\n pointer-events: none;\n }\n }\n }\n\n &-error {\n height: 1em;\n padding-top: 3px;\n color: var(--error-font-color);\n font-size: 11px;\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 0.5;\n }\n }\n}\n","import React from 'react';\nimport type { FormValidator } from 'services/formValidation';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum InputType {\n Edit = 'edit',\n Phone = 'phone',\n Email = 'email',\n Iban = 'iban',\n Date = 'date',\n HasNoIcon = 'hasNoIcon',\n Search = 'searchInput',\n Password = 'password',\n}\n\nexport enum InputIconPosition {\n Left = 'left',\n Right = 'right',\n}\n\nexport type InputSlots = 'label' | 'container' | 'input' | 'suffix' | 'upperRightLabel' | 'fieldset';\n\ntype OverriddenInputAttributes =\n | 'onChange'\n | 'onFocus'\n | 'onBlur'\n | 'onMouseEnter'\n | 'onMouseLeave'\n | 'onClick'\n | 'type'\n | 'value'\n | 'min'\n | 'max'\n | 'autoComplete';\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, OverriddenInputAttributes>,\n HtmlProps {\n onMouseEnter?: ((event: React.MouseEvent) => void) | null;\n onMouseLeave?: ((event: React.MouseEvent) => void) | null;\n onFocus?: ((event: React.FocusEvent) => void) | null;\n onBlur?: ((event: React.FocusEvent) => void) | null;\n onChange?: ((value: string, event?: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement, Element>) => void) | null;\n errorMessage?: string;\n isValid?: boolean;\n isRequired?: boolean;\n label?: string;\n name?: string;\n className?: string;\n style?: React.CSSProperties;\n value?: string | number;\n icon?: React.ReactElement | null;\n iconPosition?: InputIconPosition;\n isUppercase?: boolean;\n isRow?: boolean;\n tabIndex?: number;\n type?: InputType;\n onIconClick?: (() => void) | null;\n parse?: ((value: string) => string) | null;\n suffix?: string | React.ReactNode;\n disabled?: boolean;\n upperRightLabel?: string | React.ReactNode;\n labelInBorder?: boolean;\n showCancel?: boolean;\n onClearClicked?: (() => void) | null;\n min?: string | number | null;\n max?: string | number | null;\n placeholder?: string;\n useMatLabelStyle?: boolean;\n alwaysFloatLabel?: boolean;\n autoComplete?: string | null;\n onClick?: (() => void) | null;\n readOnly?: boolean;\n customInput?: React.ReactElement | null;\n autoFocus?: boolean;\n alwaysShowCancel?: boolean;\n formValidator?: FormValidator | null;\n multiline?: boolean;\n rows?: number;\n autoResize?: boolean;\n classNames?: SlotClassNames<InputSlots>;\n styles?: SlotStyles<InputSlots>;\n}\n","import React, { useState, useEffect, useRef, useCallback, useId } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faPhone,\n faPen,\n faEnvelope,\n faSearch,\n faXmark,\n faEye as passwordHiddenIcon,\n faEyeSlash as passwordShownIcon,\n} from '@fortawesome/free-solid-svg-icons';\nimport Tooltip from 'components/common/tooltip';\nimport AnimatedIcon from 'components/common/animatedIcon';\nimport { useComponentDefaults } from 'components/common/configProvider';\nimport styles from './input.module.pcss';\nimport type { InputProps } from './input.types';\nimport { InputType, InputIconPosition } from './input.types';\n\nfunction Input(props: InputProps) {\n const {\n name = '',\n id,\n label = '',\n errorMessage = '',\n isValid = true,\n className = '',\n style,\n value = '',\n icon = null,\n iconPosition,\n onChange = () => {},\n onFocus: onFocusProp = null,\n onBlur: onBlurProp = null,\n onMouseEnter: onMouseEnterProp = null,\n onMouseLeave: onMouseLeaveProp = null,\n isUppercase = false,\n isRequired = false,\n tabIndex = 0,\n type = undefined,\n isRow = false,\n onIconClick = null,\n parse = null,\n formValidator = null,\n autoFocus = false,\n suffix = null,\n upperRightLabel = null,\n labelInBorder = false,\n showCancel = false,\n onClearClicked,\n min = null,\n max = null,\n placeholder = '',\n useMatLabelStyle = true,\n alwaysFloatLabel = false,\n autoComplete = null,\n onClick = () => null,\n readOnly = false,\n customInput,\n alwaysShowCancel = false,\n multiline = false,\n rows,\n autoResize = false,\n classNames,\n styles: slotStyles,\n disabled = false,\n ...rest\n } = useComponentDefaults('Input', props);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [isPasswordShown, setIsPasswordShown] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n const fvRef = useRef(formValidator);\n\n const generatedId = useId();\n const inputId = id || name || generatedId;\n\n const resizeTextarea = useCallback(() => {\n const el = inputRef.current;\n if (!el || !autoResize) return;\n el.style.height = 'auto';\n el.style.height = `${el.scrollHeight}px`;\n }, [autoResize]);\n\n useEffect(() => {\n resizeTextarea();\n }, []);\n\n useEffect(() => {\n if (autoFocus && inputRef.current) {\n setTimeout(() => { inputRef.current?.focus(); }, 1);\n }\n }, [autoFocus]);\n\n useEffect(() => {\n fvRef.current = formValidator;\n const fv = fvRef.current;\n if (!fv) return;\n fv.label = label ?? '';\n fv.validate();\n const listener = () => forceUpdate(n => n + 1);\n fv.registerOnUpdateListener(listener);\n return () => { fv.removeOnUpdateListener(listener); };\n }, [formValidator, label]);\n\n const hasError = (): boolean => {\n return formValidator\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n };\n\n const computedIsRequired = (): boolean => {\n return !!(isRequired || (formValidator && formValidator.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n )));\n };\n\n const onMouseEnterHandler = (event: React.MouseEvent) => {\n setIsHovered(true);\n if (onMouseEnterProp) onMouseEnterProp(event);\n };\n\n const onMouseLeaveHandler = (event: React.MouseEvent) => {\n setIsHovered(false);\n if (onMouseLeaveProp) onMouseLeaveProp(event);\n };\n\n const onFocusHandler = (event: React.FocusEvent) => {\n setIsFocused(true);\n if (onFocusProp) onFocusProp(event);\n };\n\n const onBlurHandler = (event: React.FocusEvent) => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n if (onBlurProp) onBlurProp(event);\n };\n\n const onChangeHandler = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | string): void => {\n let parsedEvent: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | undefined;\n let val: string;\n\n if (typeof event !== 'string') {\n parsedEvent = event;\n val = event.target.value;\n } else {\n val = event;\n }\n\n if (parse) val = parse(val);\n if (formValidator) formValidator.set(val);\n if (onChange) onChange(val, parsedEvent);\n resizeTextarea();\n };\n\n const getInputType = (): string | undefined => {\n if (type === InputType.Email) return undefined;\n if (type === InputType.Phone) return 'tel';\n if (type === InputType.Search) return 'search';\n if (type === 'password' && isPasswordShown) return 'text';\n return type;\n };\n\n const getInputMode = (): React.HTMLAttributes<HTMLInputElement>['inputMode'] => {\n if (type === InputType.Email) return 'email';\n if (type === InputType.Phone) return 'tel';\n if (type === InputType.Search) return 'search';\n return undefined;\n };\n\n const hasIcon =\n type &&\n type !== InputType.Date &&\n type !== InputType.Iban &&\n type !== InputType.HasNoIcon;\n\n const isFunctionalIconType = type === InputType.Search || type === InputType.Password;\n const hasCustomIcon = !!icon;\n const customIconApplies = hasCustomIcon && !isFunctionalIconType;\n\n const defaultsLeftWithoutMatLabel = type === InputType.Email || type === InputType.Phone || type === InputType.Search;\n const resolvedIconPosition = iconPosition ?? (!useMatLabelStyle && defaultsLeftWithoutMatLabel ? InputIconPosition.Left : InputIconPosition.Right);\n const iconIsLeft = resolvedIconPosition === InputIconPosition.Left;\n\n const iconProps = {\n className: cx(styles.inputFieldIcon, {\n [styles.inputFieldIconNotClickable]: !onIconClick,\n [styles.inputFieldIconLeft]: iconIsLeft,\n }),\n onClick: onIconClick ?? undefined,\n };\n\n const customIcon = icon as React.ReactElement<{ className?: string; onClick?: React.MouseEventHandler }> | null;\n const renderedIcon = customIconApplies && customIcon\n ? React.cloneElement(customIcon, {\n className: cx(\n styles.inputFieldIcon,\n {\n [styles.inputFieldIconNotClickable]: !onIconClick && !customIcon.props.onClick,\n [styles.inputFieldIconLeft]: iconIsLeft,\n },\n customIcon.props.className,\n ),\n onClick: onIconClick ?? customIcon.props.onClick,\n })\n : null;\n\n const hasLeftIcon = (hasIcon || hasCustomIcon) && iconIsLeft;\n\n const passwordIconProps = {\n className: cx(styles.inputFieldIcon, styles.inputFieldIconPassword, { [styles.inputFieldIconLeft]: iconIsLeft }),\n onClick: () => setIsPasswordShown(!isPasswordShown),\n };\n\n const hasErr = hasError();\n\n let editedLabel = label;\n if (editedLabel && computedIsRequired()) editedLabel = `${editedLabel} *`;\n const requiredMark = computedIsRequired() ? <span className={styles.requiredMark}>*</span> : null;\n\n const currVal = formValidator ? formValidator.value : value;\n const showFocus = isFocused && !readOnly;\n const shouldFloatLabel = useMatLabelStyle && (alwaysFloatLabel || showFocus || currVal || type === InputType.Date);\n\n const isSearchCleared = type === InputType.Search && !!currVal;\n\n function handleClear() {\n if (formValidator) formValidator.set('');\n onChange?.('');\n onClearClicked?.();\n }\n\n return (\n <div className={cx(styles.input, { [styles.inputIconLeft]: hasLeftIcon }, className)} style={style}>\n <label\n htmlFor={inputId}\n className={cx(styles.inputLabel, classNames?.label, {\n [styles.inputLabelColumn]: !isRow,\n [styles.inputLabelInBorder]: labelInBorder,\n })}\n style={slotStyles?.label}\n >\n {label && !useMatLabelStyle ? (\n <span className={styles.inputLabelText}>\n {label}\n {requiredMark}\n </span>\n ) : null}\n {upperRightLabel && (\n <div className={cx(styles.inputUpperRightLabel, classNames?.upperRightLabel)} style={slotStyles?.upperRightLabel}>\n {upperRightLabel}\n </div>\n )}\n <div\n className={cx(styles.inputContainer, { [styles.inputContainerMultiline]: multiline }, classNames?.container)}\n style={slotStyles?.container}\n onMouseEnter={onMouseEnterHandler}\n onMouseLeave={onMouseLeaveHandler}\n >\n {renderedIcon}\n {React.cloneElement(customInput || (multiline ? <textarea /> : <input />), {\n ...rest,\n className: cx(\n styles.inputField,\n {\n [styles.inputFieldUppercase]: isUppercase,\n [styles.inputFieldDate]: type === InputType.Date,\n [styles.inputFieldDefault]: type !== InputType.Date,\n [styles.inputFieldWithIcon]: hasIcon || hasCustomIcon,\n [styles.inputFieldWithIconLeft]: hasLeftIcon,\n [styles.inputFieldMultiline]: multiline,\n [styles.inputFieldMultilineAutoResize]: multiline && autoResize,\n [styles.inputFieldReadOnly]: readOnly && !disabled,\n },\n classNames?.input\n ),\n name,\n id: inputId,\n value: formValidator ? formValidator.value : value,\n tabIndex,\n ref: customInput ? undefined : inputRef,\n onChange: onChangeHandler,\n onFocus: onFocusHandler,\n onBlur: onBlurHandler,\n placeholder: !useMatLabelStyle ? placeholder : '',\n autoComplete,\n onClick,\n readOnly,\n disabled,\n ...(!multiline && { type: getInputType(), inputMode: rest.inputMode ?? getInputMode(), min, max }),\n ...(multiline && rows !== undefined && { rows }),\n })}\n {suffix && <div className={cx(styles.inputFieldSuffix, classNames?.suffix)} style={slotStyles?.suffix}>{suffix}</div>}\n </div>\n <fieldset\n className={cx(styles.inputFieldset, classNames?.fieldset, {\n [styles.inputFieldsetNoNotch]: !label,\n [styles.inputContainerBorderFocused]: showFocus,\n [styles.inputContainerBorderSearchFocused]:\n type === InputType.Search && (showFocus || value),\n [styles.inputContainerBorderInvalid]: hasErr,\n [styles.inputContainerBorderError]: hasErr,\n })}\n style={slotStyles?.fieldset}\n >\n <legend\n className={cx(styles.inputFieldsetLegend, {\n [styles.inputFieldsetLegendActive]: shouldFloatLabel,\n })}\n >\n <span>{editedLabel}</span>\n </legend>\n </fieldset>\n {useMatLabelStyle && label && (\n <div\n className={cx(styles.inputMatLabel, {\n [styles.inputMatLabelFloating]: shouldFloatLabel,\n [styles.inputMatLabelMultiline]: multiline && !shouldFloatLabel,\n })}\n >\n {label}\n {requiredMark}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.inputPlaceholder,\n showFocus && !currVal && styles.inputPlaceholderShown,\n multiline && styles.inputPlaceholderMultiline,\n )}\n >\n {placeholder}\n </div>\n )}\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() : (errorMessage || '')}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </label>\n\n {type === InputType.Phone && !hasCustomIcon && <FontAwesomeIcon icon={faPhone} {...iconProps} />}\n {type === InputType.Email && !hasCustomIcon && <FontAwesomeIcon icon={faEnvelope} {...iconProps} />}\n {type === InputType.Edit && !hasCustomIcon && <FontAwesomeIcon icon={faPen} {...iconProps} />}\n {type === InputType.Search && (\n <AnimatedIcon\n icon={isSearchCleared ? faXmark : faSearch}\n className={cx(styles.inputFieldIcon, {\n [styles.inputFieldIconNotClickable]: !isSearchCleared,\n [styles.inputFieldIconLeft]: iconIsLeft,\n })}\n onClick={isSearchCleared ? handleClear : undefined}\n />\n )}\n {type === InputType.Password && (\n <FontAwesomeIcon\n icon={isPasswordShown ? passwordShownIcon : passwordHiddenIcon}\n {...passwordIconProps}\n />\n )}\n\n {((showCancel && value && (isFocused || isHovered)) || alwaysShowCancel) && type !== InputType.Search && (\n <FontAwesomeIcon\n icon={faXmark}\n className={styles.inputFieldIcon}\n onClick={handleClear}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n )}\n </div>\n );\n}\n\nexport default Input;\n",".colorPicker {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.swatch {\n width: 32px;\n height: 32px;\n border-radius: var(--default-border-radius);\n position: relative;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n flex-shrink: 0;\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);\n /* checkerboard so transparency is visible */\n background-image:\n linear-gradient(45deg, #bbb 25%, transparent 25%),\n linear-gradient(-45deg, #bbb 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, #bbb 75%),\n linear-gradient(-45deg, transparent 75%, #bbb 75%);\n background-size: 8px 8px;\n background-position: 0 0, 0 4px, 4px -4px, -4px 0;\n background-color: white;\n\n &:hover {\n & .swatchHex {\n opacity: 1;\n }\n }\n}\n\n.swatchFill {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n}\n\n.swatchHex {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-family: monospace;\n background: rgba(0, 0, 0, 0.55);\n color: white;\n border-radius: inherit;\n opacity: 0;\n transition: opacity 0.15s;\n user-select: none;\n pointer-events: none;\n z-index: 1;\n}\n\n.panel {\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n width: 224px;\n}\n\n.gradientArea {\n width: 200px;\n height: 160px;\n position: relative;\n cursor: crosshair;\n border-radius: 4px;\n overflow: hidden;\n touch-action: none;\n background: linear-gradient(to right, white, hsl(calc(var(--hue) * 1deg), 100%, 50%));\n}\n\n.gradientOverlay {\n position: absolute;\n inset: 0;\n background: linear-gradient(to bottom, transparent, black);\n}\n\n.cursor {\n position: absolute;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n border: 2px solid white;\n box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: 1;\n}\n\n.hueSlider {\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n height: 10px;\n border-radius: var(--default-border-radius);\n outline: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background: linear-gradient(\n to right,\n hsl(0, 100%, 50%),\n hsl(60, 100%, 50%),\n hsl(120, 100%, 50%),\n hsl(180, 100%, 50%),\n hsl(240, 100%, 50%),\n hsl(300, 100%, 50%),\n hsl(360, 100%, 50%)\n );\n\n &::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 6px;\n height: 20px;\n border-radius: var(--default-border-radius);\n background: var(--primary-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &::-moz-range-thumb {\n width: 6px;\n height: 20px;\n border-radius: var(--default-border-radius);\n background: var(--primary-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n}\n\n.alphaSlider {\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n height: 10px;\n border-radius: var(--default-border-radius);\n outline: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n /* checkerboard base so transparency is visible under the gradient */\n background-image:\n linear-gradient(to right, transparent, var(--alpha-color)),\n linear-gradient(45deg, #bbb 25%, transparent 25%),\n linear-gradient(-45deg, #bbb 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, #bbb 75%),\n linear-gradient(-45deg, transparent 75%, #bbb 75%);\n background-size: 100% 100%, 8px 8px, 8px 8px, 8px 8px, 8px 8px;\n background-position: 0 0, 0 0, 0 4px, 4px -4px, -4px 0;\n background-color: white;\n\n &::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 6px;\n height: 20px;\n border-radius: var(--default-border-radius);\n background: var(--primary-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &::-moz-range-thumb {\n width: 6px;\n height: 20px;\n border-radius: var(--default-border-radius);\n background: var(--primary-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n}\n\n.hexRow {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.hexInput {\n width: 100%;\n padding: 5px 8px;\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n background: var(--input-background);\n color: var(--text-color);\n font-size: 13px;\n font-family: monospace;\n box-sizing: border-box;\n outline: none;\n\n &:focus {\n border-color: var(--primary-color);\n }\n}\n\n.eyeDropperButton {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 28px;\n height: 28px;\n padding: 0;\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n background: var(--input-background);\n color: var(--text-color);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover {\n border-color: var(--primary-color);\n color: var(--primary-color);\n }\n}\n","import { useState, useRef, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faEyeDropper } from '@fortawesome/free-solid-svg-icons';\n\nimport InteractableDiv from 'components/common/interactableDiv';\nimport FloatingMenu from 'components/common/floatingMenu';\nimport Input from 'components/common/input';\nimport { Align } from 'components/common/floatingMenu/floatingMenu.types';\nimport type { ColorPickerProps } from './colorPicker.types';\n\nimport styles from './colorPicker.module.pcss';\n\ninterface EyeDropperConstructor {\n new (): { open: (options?: { signal?: AbortSignal }) => Promise<{ sRGBHex: string }> };\n}\n\nconst eyeDropperSupported = typeof window !== 'undefined' && 'EyeDropper' in window;\n\nasync function pickColorFromScreen(): Promise<string | null> {\n const EyeDropperCtor = (window as unknown as { EyeDropper?: EyeDropperConstructor }).EyeDropper;\n if (!EyeDropperCtor) return null;\n try {\n const result = await new EyeDropperCtor().open();\n return result.sRGBHex;\n } catch {\n return null; // user cancelled or picker failed\n }\n}\n\n// ── Color utilities ──────────────────────────────────────────────────────────\n\nfunction isValidHex(s: string): boolean {\n return /^#[0-9a-fA-F]{6}$/.test(s) || /^#[0-9a-fA-F]{8}$/.test(s);\n}\n\n/** Split any valid hex into its 6-digit base and 0-100 alpha. */\nfunction parseHex(hex: string): { hex6: string; alpha: number } {\n if (/^#[0-9a-fA-F]{8}$/.test(hex)) {\n return {\n hex6: hex.slice(0, 7),\n alpha: Math.round((parseInt(hex.slice(7, 9), 16) / 255) * 100),\n };\n }\n return { hex6: hex.slice(0, 7), alpha: 100 };\n}\n\n/** Combine a 6-digit hex + 0-100 alpha into the right output format.\n * Full opacity (alpha === 100) is omitted — 6-digit hex implies opaque. */\nfunction buildValue(hex6: string, alpha: number, showAlpha: boolean): string {\n if (!showAlpha || alpha >= 100) return hex6;\n const a = Math.round((alpha / 100) * 255).toString(16).padStart(2, '0');\n return `${hex6}${a}`;\n}\n\nfunction hexToRgba(hex6: string, alpha: number): string {\n const r = parseInt(hex6.slice(1, 3), 16);\n const g = parseInt(hex6.slice(3, 5), 16);\n const b = parseInt(hex6.slice(5, 7), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha / 100})`;\n}\n\nfunction hexToHsv(hex6: string): { h: number; s: number; v: number } {\n const r = parseInt(hex6.slice(1, 3), 16) / 255;\n const g = parseInt(hex6.slice(3, 5), 16) / 255;\n const b = parseInt(hex6.slice(5, 7), 16) / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const delta = max - min;\n\n let h = 0;\n if (delta !== 0) {\n if (max === r) h = ((g - b) / delta) % 6;\n else if (max === g) h = (b - r) / delta + 2;\n else h = (r - g) / delta + 4;\n h = Math.round(h * 60);\n if (h < 0) h += 360;\n }\n\n const s = max === 0 ? 0 : Math.round((delta / max) * 100);\n const v = Math.round(max * 100);\n\n return { h, s, v };\n}\n\nfunction hsvToHex(h: number, s: number, v: number): string {\n const sv = s / 100;\n const vv = v / 100;\n const c = vv * sv;\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n const m = vv - c;\n\n let r = 0, g = 0, b = 0;\n if (h < 60) { r = c; g = x; b = 0; }\n else if (h < 120) { r = x; g = c; b = 0; }\n else if (h < 180) { r = 0; g = c; b = x; }\n else if (h < 240) { r = 0; g = x; b = c; }\n else if (h < 300) { r = x; g = 0; b = c; }\n else { r = c; g = 0; b = x; }\n\n const toHex = (n: number) => Math.round((n + m) * 255).toString(16).padStart(2, '0');\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n}\n\n// ── HexInput ─────────────────────────────────────────────────────────────────\n\ninterface HexInputProps {\n hex: string;\n onChange: (hex: string) => void;\n useInputComponent?: boolean;\n}\n\nfunction HexInput({ hex, onChange, useInputComponent = false }: HexInputProps): ReactElement {\n const [draft, setDraft] = useState(hex);\n\n const [prevHex, setPrevHex] = useState(hex);\n if (hex !== prevHex) {\n setPrevHex(hex);\n setDraft(hex);\n }\n\n function handleChange(raw: string) {\n setDraft(raw);\n const normalized = raw.startsWith('#') ? raw : `#${raw}`;\n if (isValidHex(normalized)) onChange(normalized);\n }\n\n function handleBlur() {\n const normalized = draft.startsWith('#') ? draft : `#${draft}`;\n if (!isValidHex(normalized)) setDraft(hex);\n }\n\n if (useInputComponent) {\n return (\n <Input\n value={draft}\n onChange={(value: string) => handleChange(value)}\n onBlur={handleBlur}\n />\n );\n }\n\n return (\n <input\n type=\"text\"\n value={draft}\n onChange={(e) => handleChange(e.target.value)}\n onBlur={handleBlur}\n className={styles.hexInput}\n spellCheck={false}\n />\n );\n}\n\n// ── Picker panel ─────────────────────────────────────────────────────────────\n\ninterface PickerPanelProps {\n hue: number;\n sat: number;\n val: number;\n alpha: number;\n onHueChange: (h: number) => void;\n onSVChange: (s: number, v: number) => void;\n onAlphaChange: (a: number) => void;\n showInput?: boolean;\n showAlpha?: boolean;\n}\n\nfunction PickerPanel({\n hue, sat, val, alpha,\n onHueChange, onSVChange, onAlphaChange,\n showInput = true, showAlpha = false,\n}: PickerPanelProps): ReactElement {\n const gradientRef = useRef<HTMLDivElement>(null);\n\n function getSVFromEvent(e: { clientX: number; clientY: number }): { s: number; v: number } {\n const rect = gradientRef.current!.getBoundingClientRect();\n const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));\n const y = Math.max(0, Math.min(1, (e.clientY - rect.top) / rect.height));\n return { s: x * 100, v: (1 - y) * 100 };\n }\n\n // Pointer Events (not mouse events) so dragging works for touch/pen too.\n function onGradientPointerDown(e: React.PointerEvent) {\n e.currentTarget.setPointerCapture(e.pointerId);\n const { s, v } = getSVFromEvent(e);\n onSVChange(s, v);\n\n const onMove = (ev: PointerEvent) => {\n const { s, v } = getSVFromEvent(ev);\n onSVChange(s, v);\n };\n const onUp = () => {\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', onUp);\n };\n window.addEventListener('pointermove', onMove);\n window.addEventListener('pointerup', onUp);\n }\n\n function onHexChange(normalized: string) {\n const { hex6, alpha: parsedAlpha } = parseHex(normalized);\n const { h, s, v } = hexToHsv(hex6);\n onHueChange(h);\n onSVChange(s, v);\n if (showAlpha) onAlphaChange(parsedAlpha);\n }\n\n const hex6 = hsvToHex(hue, sat, val);\n const hexInputValue = showAlpha ? buildValue(hex6, alpha, true) : hex6;\n\n return (\n <div className={styles.panel}>\n <div\n ref={gradientRef}\n className={styles.gradientArea}\n style={{ '--hue': hue } as React.CSSProperties}\n onPointerDown={onGradientPointerDown}\n >\n <div className={styles.gradientOverlay} />\n <div\n className={styles.cursor}\n style={{ left: `${sat}%`, top: `${100 - val}%` }}\n />\n </div>\n\n <input\n type=\"range\"\n min={0}\n max={359}\n value={hue}\n onChange={(e) => onHueChange(Number(e.target.value))}\n className={styles.hueSlider}\n />\n\n {showAlpha && (\n <input\n type=\"range\"\n min={0}\n max={100}\n value={alpha}\n onChange={(e) => onAlphaChange(Number(e.target.value))}\n className={styles.alphaSlider}\n style={{ '--alpha-color': hex6 } as React.CSSProperties}\n />\n )}\n\n {(showInput || eyeDropperSupported) && (\n <div className={styles.hexRow}>\n {showInput && <HexInput hex={hexInputValue} onChange={onHexChange} />}\n {eyeDropperSupported && (\n <button\n type=\"button\"\n className={styles.eyeDropperButton}\n onClick={async () => {\n const hex = await pickColorFromScreen();\n if (hex) onHexChange(hex);\n }}\n aria-label=\"Pick color from screen\"\n >\n <FontAwesomeIcon icon={faEyeDropper} />\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n\n// ── ColorPicker ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_COLOR = '#3b82f6';\n\nfunction ColorPicker({\n className,\n value = DEFAULT_COLOR,\n onChange,\n showInput = false,\n showAlpha = false,\n inline = false,\n ...rest\n}: ColorPickerProps): ReactElement {\n const [isOpen, setIsOpen] = useState(false);\n\n const initSafe = isValidHex(value) ? value : DEFAULT_COLOR;\n const { hex6: initHex6, alpha: initAlpha } = parseHex(initSafe);\n const initHsv = hexToHsv(initHex6);\n\n // Single state object so hue survives when saturation/value hit 0\n // (hexToHsv of any grey returns h=0, which would corrupt hue if derived from props).\n const [hsva, setHsva] = useState({ h: initHsv.h, s: initHsv.s, v: initHsv.v, a: initAlpha });\n\n // Ref mirrors state so drag callbacks never read stale closure values.\n const cur = useRef(hsva);\n\n // Sync from external prop changes: \"derive state during render\" pattern\n // avoids setState-in-effect. We compare the incoming hex against what our\n // current state produces — if they match, the change came from us and we skip.\n const [prevValue, setPrevValue] = useState(value);\n if (value !== prevValue) {\n setPrevValue(value);\n const safe = isValidHex(value) ? value : DEFAULT_COLOR;\n const { hex6: incomingHex6, alpha: incomingA } = parseHex(safe);\n const currentHex6 = hsvToHex(hsva.h, hsva.s, hsva.v);\n if (incomingHex6 !== currentHex6 || incomingA !== hsva.a) {\n const hsv = hexToHsv(incomingHex6);\n const next = { h: hsv.h, s: hsv.s, v: hsv.v, a: incomingA };\n setHsva(next);\n }\n }\n\n const { h: hue, s: sat, v: val, a: alpha } = hsva;\n\n function emit(h: number, s: number, v: number, a: number) {\n onChange?.(buildValue(hsvToHex(h, s, v), a, showAlpha));\n }\n\n function handleHueChange(h: number) {\n cur.current.h = h;\n setHsva(prev => ({ ...prev, h }));\n emit(h, cur.current.s, cur.current.v, cur.current.a);\n }\n\n function handleSVChange(s: number, v: number) {\n cur.current.s = s;\n cur.current.v = v;\n setHsva(prev => ({ ...prev, s, v }));\n emit(cur.current.h, s, v, cur.current.a);\n }\n\n function handleAlphaChange(a: number) {\n cur.current.a = a;\n setHsva(prev => ({ ...prev, a }));\n emit(cur.current.h, cur.current.s, cur.current.v, a);\n }\n\n const hex6 = hsvToHex(hue, sat, val);\n const swatchBackground = showAlpha ? hexToRgba(hex6, alpha) : hex6;\n const displayValue = buildValue(hex6, alpha, showAlpha);\n\n const pickerPanelProps: PickerPanelProps = {\n hue, sat, val, alpha,\n onHueChange: handleHueChange,\n onSVChange: handleSVChange,\n onAlphaChange: handleAlphaChange,\n showAlpha,\n };\n\n if (inline) {\n return (\n <div {...rest} className={cx(styles.colorPicker, className)}>\n <PickerPanel {...pickerPanelProps} showInput={showInput} />\n </div>\n );\n }\n\n return (\n <div {...rest} className={cx(styles.colorPicker, className)}>\n <FloatingMenu\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n dontCloseOnChildClick\n align={Align.Left}\n content={<PickerPanel {...pickerPanelProps} />}\n >\n <InteractableDiv className={styles.swatch}>\n <div className={styles.swatchFill} style={{ background: swatchBackground }} />\n <span className={styles.swatchHex}>{displayValue}</span>\n </InteractableDiv>\n </FloatingMenu>\n\n {showInput && (\n <HexInput\n hex={displayValue}\n onChange={(v) => onChange?.(v)}\n useInputComponent\n />\n )}\n </div>\n );\n}\n\nexport default ColorPicker;\n","\n.modal {\n padding: 16px;\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n color: var(--text-color);\n font-family: var(--default-font);\n box-sizing: border-box;\n position: relative;\n transform-origin: bottom center;\n animation:\n slideIn 0.2s,\n fadeIn 0.3s forwards;\n max-width: 95%;\n max-height: 95%;\n overflow: auto;\n\n @media not (--breakpoint-desktop) {\n max-width: 100%;\n max-height: 100%;\n }\n\n &-container {\n position: absolute;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n top: 0;\n left: 0;\n\n @media (--breakpoint-tablet) {\n z-index: 1;\n }\n }\n\n &-header {\n display: flex;\n gap: 8px;\n justify-content: space-between;\n margin-bottom: 16px;\n\n div {\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n svg {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n &-wrapper {\n position: fixed;\n width: 100%;\n height: 100%;\n background: #00000052;\n top: 0;\n left: 0;\n transition: all 0.3s ease-in-out;\n opacity: 0;\n\n &-shown {\n opacity: 1;\n }\n }\n}\n\n@keyframes slideIn {\n from {\n transform: scale(0);\n }\n to {\n transform: scale(0.99);\n }\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './modal.module.pcss';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faXmark as closeIcon } from '@fortawesome/free-solid-svg-icons';\nimport { ModalProps } from './modal.types';\nimport { useEffect, useState } from 'react';\n\nfunction Modal({\n children = null,\n title = '',\n isOpen = false,\n onClose = () => null,\n className = '',\n style,\n hideHeader = false,\n classNames,\n styles: slotStyles,\n}: ModalProps) {\n const [isRendered, setIsRendered] = useState(isOpen);\n const [animateIn, setAnimateIn] = useState(isOpen);\n\n useEffect(() => {\n if (isOpen) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setIsRendered(isOpen);\n setTimeout(() => setAnimateIn(true), 1);\n } else {\n setAnimateIn(false);\n setTimeout(() => setIsRendered(isOpen), 300);\n }\n }, [isOpen]);\n\n if (!isRendered) return null;\n\n return (\n <BodyEnd>\n <div className={cx(styles.modalContainer, classNames?.container)} style={slotStyles?.container}>\n <div\n className={cx(styles.modalWrapper, animateIn && styles.modalWrapperShown, classNames?.backdrop)}\n style={slotStyles?.backdrop}\n onClick={onClose}\n />\n {animateIn && (\n <div\n className={cx(styles.modal, animateIn && styles.modalShown, className, classNames?.modal)}\n style={{ ...style, ...slotStyles?.modal }}\n onClick={(e) => e.stopPropagation()}\n >\n {!hideHeader && (\n <div className={cx(styles.modalHeader, classNames?.header)} style={slotStyles?.header}>\n <div className={classNames?.title} style={slotStyles?.title}>{title}</div>\n <FontAwesomeIcon onClick={onClose} icon={closeIcon} className={classNames?.closeButton} style={slotStyles?.closeButton as React.CSSProperties & Record<`--fa-font-${string}`, string>} />\n </div>\n )}\n {children}\n </div>\n )}\n </div>\n </BodyEnd>\n );\n}\n\nexport default Modal;\n","import { useState, type ReactElement } from 'react';\n\nimport Modal from '../modal';\nimport { ActionButtons } from '../actionButtons';\nimport { ButtonStyleType } from '../button';\nimport { useComponentDefaults } from '../configProvider';\nimport type { ConfirmModalProps } from './confirmModal.types';\n\nfunction ConfirmModal(props: ConfirmModalProps): ReactElement {\n const {\n children = null,\n className = '',\n onClose = () => {},\n onConfirm = () => {},\n title = '',\n content = null,\n isOpen: propIsOpen = undefined,\n submitLabel = 'Confirm',\n cancelLabel = 'Cancel',\n isDelete = false,\n actionButtonsProps = {},\n } = useComponentDefaults('ConfirmModal', props);\n const [internalOpen, setInternalOpen] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n function handleClose(didSubmit = false) {\n setInternalOpen(false);\n onClose(didSubmit);\n }\n\n async function handleConfirm() {\n setIsSubmitting(true);\n try {\n await onConfirm();\n handleClose(true);\n } finally {\n setIsSubmitting(false);\n }\n }\n\n const isOpen = propIsOpen === undefined ? internalOpen : propIsOpen;\n\n const modal = (\n <Modal title={title} isOpen={isOpen} onClose={() => handleClose()} className={children ? undefined : className}>\n {content}\n <ActionButtons\n onClose={() => handleClose()}\n onSubmit={handleConfirm}\n submitLabel={submitLabel}\n cancelLabel={cancelLabel}\n submitButtonStyle={isDelete ? ButtonStyleType.Delete : undefined}\n isSubmitButtonLoading={isSubmitting}\n {...actionButtonsProps}\n />\n </Modal>\n );\n\n if (!children) return modal;\n\n return (\n <div className={className}>\n <span onClick={() => setInternalOpen(true)}>{children}</span>\n {modal}\n </div>\n );\n}\n\nexport default ConfirmModal;\n","\n.datePickerMonth {\n &-item {\n aspect-ratio: 1;\n display: flex;\n justify-content: center;\n align-items: center;\n margin: 1px 0;\n }\n\n &-content {\n display: grid;\n text-align: center;\n grid-template-columns: repeat(7, minmax(0, 1fr));\n gap: 0px;\n }\n\n &-day {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover {\n /* background-color: var(--primary-color);\n border-radius: 800px; */\n }\n\n &-today {\n background-color: var(--background-accent-light);\n border-radius: var(--default-border-radius);\n }\n\n &-selected {\n background-color: var(--primary-color);\n color: var(--text-on-primary);\n border-radius: 0;\n\n &-start {\n border-top-left-radius: var(--default-border-radius);\n border-bottom-left-radius: var(--default-border-radius);\n }\n\n &-end {\n border-top-right-radius: var(--default-border-radius);\n border-bottom-right-radius: var(--default-border-radius);\n }\n }\n\n &-disabled {\n filter: brightness(0.5);\n cursor: not-allowed;\n }\n }\n\n &-placeholder {\n user-select: none;\n pointer-events: none;\n }\n}\n","// import { Settings } from 'luxon';\n// import Polyglot from 'node-polyglot';\n\nconst supportedLocales: string[] = ['de_AT', 'de_CH', 'de_DE', 'en_US', 'en_GB', 'de', 'en'];\n\nconst defaultLocale = 'en_US';\n\nconst getCurrentLocale = (): string => {\n const locale = navigator.languages[0]?.replace('-', '_') || defaultLocale;\n\n if (!supportedLocales.includes(locale)) return defaultLocale;\n\n if (locale === 'en_GB' || locale === 'en') return 'en_US'; // Change GB to US. Alternatively, add GB File\n if (locale === 'de') return 'de_DE';\n\n return locale;\n};\n\nexport const mapLocale = (locale: string): string => {\n switch (locale) {\n case 'en_US':\n case 'en_GB':\n return 'en';\n case 'de_DE':\n case 'de_CH':\n case 'de_AT':\n return 'de';\n default:\n return 'de';\n }\n};\n\n// const getPolyglot = async (locale: string): Promise<Polyglot> => {\n// let phrases: object = {};\n// let extendPhrases: object = {};\n// const { default: impPhrasesLocale } = await import(`../locales/${locale || defaultLocale}.json`);\n// if ((locale || '').startsWith('de')) {\n// const { default: impPhrases } = await import('locales/de_DE.json');\n// phrases = impPhrases;\n// extendPhrases = impPhrasesLocale;\n// } else {\n// phrases = impPhrasesLocale;\n// }\n// const shortLocale: string = mapLocale(locale);\n// Settings.defaultLocale = shortLocale;\n\n// const polyglot: Polyglot = new Polyglot({\n// phrases: JSON.parse(JSON.stringify(phrases)),\n// locale: shortLocale,\n// });\n\n// polyglot.extend(JSON.parse(JSON.stringify(extendPhrases)));\n// return polyglot;\n// };\n\nlet currentLocale: string = getCurrentLocale();\n// let polyglot: Polyglot = await getPolyglot(currentLocale);\n\n// export default polyglot;\n\nexport async function setLocale(locale: string): Promise<void> {\n currentLocale = locale;\n // polyglot = await getPolyglot(locale);\n}\n\nexport function getLocale(delimiter = '_'): string {\n return currentLocale.replace('_', delimiter);\n}\n","import { getLocale } from 'services/localization';\n\nexport function getDaysInMonth(month: number, year: number): number {\n return new Date(year, month, 0).getDate();\n}\n\nexport function getDateFromDayMonthAndYear(day: number, month: number, year: number): Date {\n return new Date(Date.UTC(year, month - 1, day));\n}\n\nexport function getMonthName(locale: string, year: number, month: number, day: number, short = false): string {\n const currDate = new Date(Date.UTC(year, month - 1, day));\n return currDate.toLocaleDateString(locale, { month: short ? 'short' : 'long' });\n}\n\nexport function getMonthNames(locale = getLocale('-')): string[] {\n return Array.from(Array(12).keys()).map((index) => getMonthName(locale, 2023, index + 1, 1));\n}\n\nexport function getWeekDays(locale: string, short = true): string[] {\n const currDate = new Date(Date.UTC(2023, 3, 10)); // Random Monday - 10.4.2023\n const weekDays: string[] = [];\n for (let i = 0; i < 7; i++) {\n weekDays.push(currDate.toLocaleDateString(locale, { weekday: short ? 'short' : 'long' }));\n currDate.setDate(currDate.getDate() + 1);\n }\n return weekDays;\n}\n\nexport function getStartWeekDayOfMonth(month: number, year: number): number {\n const start = new Date(Date.UTC(year, month - 1, 1)).getDay();\n return start || 7;\n}\n\nexport function getDayMonthAndYearOfDate(date: Date): { day: number; month: number; year: number } {\n return {\n day: date.getDate(),\n month: date.getMonth() + 1,\n year: date.getFullYear(),\n };\n}\n\nexport function getDateString(date: Date): string {\n const day = date.getDate();\n const month = date.getMonth() + 1;\n const year = date.getFullYear();\n\n return `${day < 10 ? `0${day}` : day}.${month < 10 ? `0${month}` : month}.${year}`;\n}\n\nexport interface DateMaskSelection {\n start: number;\n end: number;\n}\n\nexport interface DateMaskState {\n value: string;\n selection: DateMaskSelection | null;\n}\n\n/**\n * Auto-corrects a partially typed `dd.mm.yyyy` mask value so a single out-of-range\n * digit doesn't force the user to backtrack:\n * - a day \"tens\" digit > 3 (e.g. typing `4`) becomes `04` and the caret jumps to the month\n * - a day of `3x` where x > 1 (e.g. `35`) becomes `0x`\n * - a month \"tens\" digit > 1 (e.g. `2`) becomes `02` and the caret jumps to the year\n * - a month `1x` where x > 2 (e.g. `13`) is clamped to `12`\n *\n * `previousValue` supplies the digits to retain for the part of the field that isn't\n * being rewritten. The returned `selection` is the adjusted caret position, or the\n * passed-in `selection` when no correction applies.\n */\nexport function correctDateMaskValue(\n nextValue: string,\n previousValue: string,\n selection: DateMaskSelection | null,\n): DateMaskState {\n let value = nextValue;\n let nextSelection = selection;\n\n if (value[0] !== '_') {\n if (value[0] > '3') {\n value = `0${value[0]}${previousValue.substring(2)}`;\n nextSelection = { start: 3, end: 3 };\n } else if (value[0] === '3') {\n if (value[1] !== '_' && value[1] > '1') {\n value = `0${value[1]}${previousValue.substring(2)}`;\n nextSelection = { start: 3, end: 3 };\n }\n }\n }\n if (value[3] !== '_' && value[3] > '1') {\n value = `${value.substring(0, 3)}0${value[3]}${previousValue.substring(5)}`;\n nextSelection = { start: 6, end: 6 };\n }\n if (value[3] === '1' && value[4] !== '_' && value[4] > '2') {\n value = `${value.substring(0, 3)}${value[3]}2${previousValue.substring(5)}`;\n }\n\n return { value, selection: nextSelection };\n}\n","import cx from 'classnames';\n\nimport styles from './datePickerMonth.module.pcss';\nimport { getLocale } from 'services/localization';\nimport InteractableDiv from 'components/common/interactableDiv';\nimport {\n getDateFromDayMonthAndYear,\n getDayMonthAndYearOfDate,\n getDaysInMonth,\n getStartWeekDayOfMonth,\n getWeekDays,\n} from '../../dateFunctions';\n\ninterface DatePickerMonthProps {\n className?: string;\n month?: number;\n year?: number;\n onSelect?: (date: Date) => void;\n selectionStart?: Date;\n selectionEnd?: Date;\n minDate?: Date | null;\n maxDate?: Date | null;\n}\n\nfunction checkSelected(\n day: number,\n month: number,\n year: number,\n selectionStart: Date | undefined,\n selectionEnd: Date | undefined,\n) {\n const { day: startDay, month: startMonth, year: startYear } = selectionStart\n ? getDayMonthAndYearOfDate(selectionStart)\n : { day: undefined, month: undefined, year: undefined };\n const { day: endDay, month: endMonth, year: endYear } = selectionEnd\n ? getDayMonthAndYearOfDate(selectionEnd)\n : { day: undefined, month: undefined, year: undefined };\n\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n const isStartDate = day === startDay && month === startMonth && year === startYear;\n const isEndDate = day === endDay && month === endMonth && year === endYear;\n\n let isInRange = false;\n if (startDay !== undefined && startMonth !== undefined && startYear !== undefined &&\n endDay !== undefined && endMonth !== undefined && endYear !== undefined) {\n const selectionStartNoTime = getDateFromDayMonthAndYear(startDay, startMonth, startYear);\n const selectionEndNoTime = getDateFromDayMonthAndYear(endDay, endMonth, endYear);\n isInRange =\n toCheckNoTime.getTime() >= selectionStartNoTime.getTime() &&\n toCheckNoTime.getTime() <= selectionEndNoTime.getTime();\n }\n\n return { isStartDate, isInRange, isEndDate };\n}\n\nfunction checkDisabled(\n day: number,\n month: number,\n year: number,\n minDate: Date | null | undefined,\n maxDate: Date | null | undefined,\n): boolean {\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n if (minDate) {\n const { day: minDay, month: minMonth, year: minYear } = getDayMonthAndYearOfDate(minDate);\n if (toCheckNoTime < getDateFromDayMonthAndYear(minDay, minMonth, minYear)) return true;\n }\n\n if (maxDate) {\n const { day: maxDay, month: maxMonth, year: maxYear } = getDayMonthAndYearOfDate(maxDate);\n if (toCheckNoTime > getDateFromDayMonthAndYear(maxDay, maxMonth, maxYear)) return true;\n }\n\n return false;\n}\n\nfunction checkIsToday(day: number, month: number, year: number): boolean {\n const { day: currDay, month: currMonth, year: currYear } = getDayMonthAndYearOfDate(new Date());\n return day === currDay && month === currMonth && year === currYear;\n}\n\nexport default function DatePickerMonth({\n className = '',\n month = new Date().getMonth() + 1,\n year = new Date().getFullYear(),\n onSelect = () => null,\n selectionStart,\n selectionEnd,\n minDate = null,\n maxDate = null,\n}: DatePickerMonthProps) {\n const locale = getLocale('-');\n const daysInMonth = getDaysInMonth(month, year);\n const startWeekDayOfMonth = getStartWeekDayOfMonth(month, year);\n\n return (\n <div className={cx(styles.datePickerMonth, className)}>\n <div className={cx(styles.datePickerMonthContent)}>\n {getWeekDays(locale).map((weekDay, index) => <div key={index}>{weekDay}</div>)}\n {Array.from(Array(startWeekDayOfMonth - 1).keys()).map((index) => (\n <div\n key={index}\n className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)}\n />\n ))}\n {Array.from(Array(daysInMonth).keys()).map((index) => {\n const day = index + 1;\n const selectedRes = checkSelected(day, month, year, selectionStart, selectionEnd);\n const isDisabled = checkDisabled(day, month, year, minDate, maxDate);\n const isToday = checkIsToday(day, month, year);\n\n return (\n <InteractableDiv\n key={day}\n onClick={() => isDisabled ? null : onSelect(getDateFromDayMonthAndYear(day, month, year))}\n className={cx(styles.datePickerMonthDay, styles.datePickerMonthItem, {\n [styles.datePickerMonthDaySelected]: selectedRes.isInRange,\n [styles.datePickerMonthDaySelectedStart]: selectedRes.isStartDate,\n [styles.datePickerMonthDaySelectedEnd]: selectedRes.isEndDate,\n [styles.datePickerMonthDayDisabled]: isDisabled,\n [styles.datePickerMonthDayToday]: isToday,\n })}\n >\n {day}\n </InteractableDiv>\n );\n })}\n {Array.from(Array(42 - (startWeekDayOfMonth + daysInMonth - 1)).keys()).map((index) => (\n <div\n key={index}\n className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)}\n >\n \n </div>\n ))}\n </div>\n </div>\n );\n}\n",".infiniteBlock {\n max-height: none;\n}\n\n.spinner-wrapper {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 4px 0;\n}\n\n.spinner {\n width: 32px;\n height: 32px;\n}\n","import React, { useState, useRef, useCallback } from 'react';\nimport cx from 'classnames';\n\nimport styles from './infiniteBlock.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport type { InfiniteBlockProps } from './infiniteBlock.types';\n\n// Walk down a React element tree until we reach a string leaf or an array of children.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction childStartsWithKey(child: React.ReactElement<any>, key: string): boolean {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let node: React.ReactElement<any> = child;\n\n while (\n node.props.children !== null &&\n typeof node.props.children === 'object' &&\n !Array.isArray(node.props.children)\n ) {\n node = node.props.children as typeof node;\n }\n\n const content: unknown = node.props.children;\n\n if (Array.isArray(content)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const arr = content as any[];\n // If the first element has no children of its own, scan for a raw string\n if (!arr[0]?.props?.children) {\n for (const item of arr) {\n if (typeof item === 'string' && item.trim().length > 0) {\n return item.toLowerCase().startsWith(key);\n }\n }\n }\n return String(arr[0].props.children).toLowerCase().startsWith(key);\n }\n\n return String(content).toLowerCase().startsWith(key);\n}\n\nfunction clampIndex(index: number, change: number, length: number): number {\n const next = index + change;\n if (next === length) return 0;\n if (next < -1) return length - 1;\n return next;\n}\n\nfunction InfiniteBlock({\n children,\n onScroll,\n className = '',\n isDataLoading = false,\n setHighlightedIndex = () => null,\n}: InfiniteBlockProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Use a ref (not state) for the scroll-guard so reads are always synchronous,\n // avoiding the React-batching race where two scroll events fire before the\n // first setState call has been committed.\n const isScrollLoadingRef = useRef(false);\n const [showScrollSpinner, setShowScrollSpinner] = useState(false);\n\n // Keyboard nav state lives in refs — it doesn't affect rendering.\n const indexRef = useRef(-1);\n const lastKeyRef = useRef<string | null>(null);\n\n const handleScroll = useCallback(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const { scrollTop, offsetHeight, scrollHeight } = el;\n\n // Browsers calculate scrollTop with a small floating-point error under zoom,\n // so we allow up to 5px of slack before deciding we are at the bottom.\n if (Math.abs(scrollTop + offsetHeight - scrollHeight) > 5) return;\n if (isScrollLoadingRef.current) return;\n\n isScrollLoadingRef.current = true;\n setShowScrollSpinner(true);\n onScroll().then(() => {\n isScrollLoadingRef.current = false;\n setShowScrollSpinner(false);\n });\n }, [onScroll]);\n\n const respondToUserInput = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n const el = containerRef.current;\n if (!el) return;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const childArray = React.Children.toArray(children) as React.ReactElement<any>[];\n let index = indexRef.current;\n\n switch (event.key) {\n case 'ArrowDown':\n index = clampIndex(index, 1, childArray.length);\n break;\n case 'ArrowUp':\n index = clampIndex(index, -1, childArray.length);\n break;\n default:\n for (let i = 0; i < childArray.length; i++) {\n if (childStartsWithKey(childArray[i], event.key)) {\n if (index >= i && lastKeyRef.current === event.key) {\n continue;\n }\n index = i;\n break;\n }\n }\n }\n\n indexRef.current = index;\n lastKeyRef.current = event.key;\n\n if (index >= 0) {\n const child = el.children[index] as HTMLElement | undefined;\n if (child) {\n const childTop = child.offsetTop;\n const childBottom = childTop + child.offsetHeight;\n if (childTop < el.scrollTop) {\n el.scrollTop = childTop;\n } else if (childBottom > el.scrollTop + el.clientHeight) {\n el.scrollTop = childBottom - el.clientHeight;\n }\n }\n setHighlightedIndex(index);\n }\n },\n [children, setHighlightedIndex]\n );\n\n return (\n <div\n className={cx(styles.infiniteBlock, className)}\n onScroll={handleScroll}\n onKeyDown={respondToUserInput}\n tabIndex={0}\n ref={containerRef}\n >\n {isDataLoading ? (\n <div className={styles.spinnerWrapper}>\n <SpinnerLoading className={styles.spinner} />\n </div>\n ) : children}\n {showScrollSpinner && (\n <div className={styles.spinnerWrapper}>\n <SpinnerLoading className={styles.spinner} />\n </div>\n )}\n </div>\n );\n}\n\nexport default InfiniteBlock;\n","\n.required-mark {\n padding: 0px 0px 0px 4px;\n color: var(--required-mark-color, var(--error-color));\n}\n\n.dropdown {\n position: relative;\n\n &-label {\n display: flex;\n\n &-column {\n flex-direction: column;\n }\n\n &-text {\n white-space: nowrap;\n margin-right: 5px;\n margin-bottom: 5px;\n display: flex;\n align-items: center;\n color: var(--text-color);\n font-size: 12px;\n position: absolute;\n top: -15px;\n }\n }\n\n &-input {\n position: relative;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: var(--input-background);\n border-radius: var(--default-border-radius);\n\n &-plain {\n background: transparent;\n }\n\n &-readOnly {\n cursor: default;\n }\n\n &:focus-within {\n outline: none;\n }\n\n &-button {\n padding: 7px 20% 7px 7.5px !important;\n background-color: transparent;\n border: none;\n font-family: inherit;\n font-size: inherit;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n text-align: left;\n width: 100%;\n line-height: 1.25;\n color: var(--text-color);\n\n &-disabled {\n background-color: var(--disabled-input-color);\n color: var(--disabled-font-color);\n border-radius: var(--default-border-radius);\n }\n\n &-readOnly {\n cursor: default;\n }\n\n &:focus {\n outline: none;\n }\n\n &-icon {\n float: right;\n background-color: transparent;\n border: none;\n position: absolute;\n outline: none;\n right: var(--spacing-s);\n top: 50%;\n transform: translateY(-50%);\n color: var(--text-color);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &-arrow {\n transition: transform 0.25s;\n pointer-events: none;\n\n &-open {\n transform: rotate(180deg);\n }\n }\n }\n }\n\n &-list-anim {\n position: fixed;\n z-index: 1;\n color: var(--text-color);\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n border-radius: var(--default-border-radius);\n overflow: hidden;\n transform: scaleY(1);\n transition: transform 0.25s;\n transform-origin: right top;\n\n &-flip {\n transform-origin: right bottom;\n }\n\n &-wider {\n width: max-content !important;\n }\n }\n\n &-list {\n width: 100%;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n max-height: 160px;\n list-style-type: none;\n\n &-item {\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: var(--background-modal);\n padding: 8px;\n text-align: left;\n border-radius: 0;\n transition: all 0.3s;\n\n &-active {\n background-color: var(--background-accent);\n }\n\n &-selected {\n font-weight: 500;\n }\n\n &:focus {\n outline: none;\n }\n\n &:hover {\n background-color: var(--background-accent);\n }\n\n &-disabled {\n background-color: var(--disabled-input-color);\n color: var(--disabled-font-color);\n cursor: not-allowed;\n\n &:hover {\n background-color: var(--disabled-input-color);\n }\n }\n }\n }\n }\n\n &-fieldset {\n position: absolute;\n width: 100%;\n margin: 0;\n box-sizing: border-box;\n border-radius: var(--default-border-radius);\n inset: -10px 0 0 0;\n padding-left: 8px;\n border-width: 1px;\n border-style: solid;\n border-color: var(--border-color);\n pointer-events: none;\n user-select: none;\n\n &-legend {\n display: block;\n max-width: 0;\n transition: max-width 0.2s;\n white-space: nowrap;\n padding: 0;\n\n &-active {\n max-width: 300px;\n }\n\n span {\n font-size: 13px;\n padding: 5px;\n opacity: 0;\n }\n\n /* With an empty label the span would still reserve its padding, leaving a gap in\n the fieldset's top border. Collapse it so the notch closes when there's no label. */\n span:empty {\n padding: 0.000001px;\n }\n }\n }\n\n &-placeholder {\n position: absolute;\n top: 8px;\n left: 7px;\n transition: all 0.2s;\n opacity: 0;\n\n &-shown {\n animation: 0.2s fadeIn 0.3s forwards;\n }\n }\n\n &-matLabel {\n position: absolute;\n transition: all 0.3s;\n inset: 9px 0 0 7px;\n font-size: 16px;\n color: var(--input-label-resting-color, var(--text-light));\n pointer-events: none;\n user-select: none;\n\n &-floating {\n inset: -9px 0 0 14px;\n font-size: 13px;\n color: var(--input-label-floating-color, var(--text-color));\n }\n }\n\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 0.5;\n }\n }\n\n &-border {\n &-focused {\n outline-color: var(--primary-color);\n border-color: var(--primary-color);\n }\n\n &-plain {\n border-color: transparent;\n outline-color: transparent;\n }\n\n &-invalid {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-invalid:hover {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n\n &-error {\n outline-color: var(--error-border-color);\n border-color: var(--error-border-color);\n }\n }\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport InfiniteBlock from 'components/common/infiniteBlock';\nimport BodyEnd from 'components/common/bodyEnd';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronDown as dropdownIcon } from '@fortawesome/free-solid-svg-icons';\nimport Downshift, { StateChangeOptions, DownshiftState } from 'downshift';\nimport Tooltip from 'components/common/tooltip';\n\nimport { useFloatingPosition } from '../floatingMenu/useFloatingPosition';\nimport { useComponentDefaults } from '../configProvider';\nimport styles from './dropdown.module.pcss';\nimport type { DropdownProps, DropdownItem } from './dropdown.types';\n\nfunction Dropdown(props: DropdownProps) {\n const {\n errorMessage = '',\n className = '',\n label = '',\n value = '',\n isValid = true,\n tabIndex = 0,\n isRequired = false,\n customProps = {},\n isRow = false,\n disabled = false,\n readOnly = false,\n onScroll = () => Promise.resolve(),\n onClick,\n onChange,\n onFocus: onFocusProp = null,\n onBlur: onBlurProp = null,\n onMouseEnter: onMouseEnterProp = null,\n onMouseLeave: onMouseLeaveProp = null,\n dropdownLabel: dropdownLabelProp,\n isDropdownListWider = false,\n inputClassName = '',\n dropDownIconClassName = '',\n dropDownClassName = '',\n formValidator = null,\n labelClassName = '',\n dropDownInputClassName = '',\n items = [],\n useMatLabelStyle = true,\n alwaysFloatLabel = false,\n placeholder = '',\n plainStyle = false,\n scrollToSelected = false,\n reactRef,\n ...rest\n } = useComponentDefaults('Dropdown', props);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const fvRef = useRef(formValidator);\n const triggerRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const [menuIsOpen, setMenuIsOpen] = useState(false);\n const [triggerWidth, setTriggerWidth] = useState(10);\n\n useEffect(() => {\n if (menuIsOpen) {\n const rect = triggerRef.current?.getBoundingClientRect();\n setTriggerWidth(rect?.width ?? 10);\n }\n }, [menuIsOpen]);\n\n useFloatingPosition({\n isOpen: menuIsOpen,\n triggerRef,\n anchorRef,\n panelRef: anchorRef,\n flipClassName: styles.dropdownInputListAnimFlip,\n });\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!fvRef.current) return;\n fvRef.current.label = label ?? '';\n fvRef.current.validate();\n const listener = () => forceUpdate(n => n + 1);\n fvRef.current.registerOnUpdateListener(listener);\n return () => fvRef.current?.removeOnUpdateListener(listener);\n }, [formValidator, label]);\n\n const onMouseEnterHandler = (event: React.MouseEvent) => {\n setIsHovered(true);\n onMouseEnterProp?.(event);\n };\n\n const onMouseLeaveHandler = (event: React.MouseEvent) => {\n setIsHovered(false);\n onMouseLeaveProp?.(event);\n };\n\n const onFocusHandler = (event: React.FocusEvent) => {\n setIsFocused(true);\n onFocusProp?.(event);\n };\n\n const onBlurHandler = (event: React.FocusEvent) => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n onBlurProp?.(event);\n };\n\n const hasError = (): boolean => {\n return formValidator\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n };\n\n const computedIsRequired = (): boolean => {\n return !!(isRequired || formValidator?.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n ));\n };\n\n const onChangeHandler = (val: string | number): void => {\n if (formValidator) {\n formValidator.set(val);\n onChange?.(formValidator.value, customProps);\n } else {\n onChange?.(val, customProps);\n }\n };\n\n let dropdownLabel = dropdownLabelProp;\n const currentValue = formValidator ? formValidator.value as string | number : value;\n const hasErr = hasError();\n\n items.forEach((item: DropdownItem) => {\n if (item.key === currentValue) {\n dropdownLabel = item.label as string;\n }\n });\n\n const displayValue = dropdownLabel || currentValue;\n const isDisplayBlank =\n displayValue == null ||\n (typeof displayValue === 'string' && displayValue.trim() === '');\n\n const requiredMark = computedIsRequired() ? <span className={styles.requiredMark}>*</span> : null;\n const editedLabel = label && computedIsRequired() ? `${label} *` : label;\n\n const showFocus = isFocused && !readOnly;\n\n return (\n <div\n {...rest}\n className={cx(className, styles.dropdownLabel, styles.dropdown, {\n [styles.dropdownLabelColumn]: !isRow,\n })}\n onMouseEnter={onMouseEnterHandler}\n onMouseLeave={onMouseLeaveHandler}\n >\n <Downshift\n {...(readOnly ? { isOpen: false } : {})}\n onChange={(selection: DropdownItem | null) => onChangeHandler((selection || { key: '' }).key)}\n itemToString={(item: DropdownItem | null) => (item ? String(item.key) : '')}\n selectedItem={items.find((el) => el.key === currentValue) ?? null}\n onStateChange={(changes: StateChangeOptions<DropdownItem>) => {\n if (typeof changes.isOpen === 'boolean') setMenuIsOpen(changes.isOpen);\n }}\n stateReducer={(state: DownshiftState<DropdownItem>, changes: StateChangeOptions<DropdownItem>) => {\n if (scrollToSelected && Object.prototype.hasOwnProperty.call(changes, 'isOpen')) {\n return {\n ...changes,\n highlightedIndex: changes.isOpen ? items.indexOf(state.selectedItem as DropdownItem) : null,\n };\n }\n return changes;\n }}\n >\n {({\n getItemProps,\n getMenuProps,\n getToggleButtonProps,\n isOpen,\n selectedItem,\n highlightedIndex,\n setHighlightedIndex,\n }) => (\n <div>\n <div\n ref={triggerRef}\n onFocus={onFocusHandler}\n onBlur={onBlurHandler}\n className={cx(\n styles.dropdownInput,\n {\n [styles.dropdownInputPlain]: plainStyle,\n [styles.dropdownInputReadOnly]: readOnly && !disabled,\n },\n dropDownInputClassName\n )}\n >\n <button\n tabIndex={tabIndex}\n type=\"button\"\n disabled={disabled}\n aria-readonly={readOnly || undefined}\n style={isDropdownListWider ? { padding: '6px', border: 'none' } : {}}\n className={cx(\n styles.dropdownInputButton,\n {\n [styles.dropdownInputButtonDisabled]: disabled,\n [styles.dropdownInputButtonReadOnly]: readOnly && !disabled,\n },\n inputClassName\n )}\n {...getToggleButtonProps()}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n getToggleButtonProps().onClick?.(e);\n onClick?.(e);\n }}\n ref={reactRef}\n >\n {/* Non-breaking space when blank (same text-node layout as a\n real value) so the button keeps a full line of height. */}\n {isDisplayBlank ? '\\u00A0' : displayValue}\n </button>\n <button\n type=\"button\"\n tabIndex={-1}\n disabled={disabled}\n className={cx(styles.dropdownInputButtonIcon, dropDownIconClassName)}\n {...getToggleButtonProps()}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n getToggleButtonProps().onClick?.(e);\n onClick?.(e);\n }}\n >\n {!disabled && !readOnly && (\n <FontAwesomeIcon\n icon={dropdownIcon}\n className={cx(styles.dropdownInputButtonIconArrow, {\n [styles.dropdownInputButtonIconArrowOpen]: isOpen,\n })}\n />\n )}\n </button>\n {!disabled && !readOnly && isOpen ? (\n <BodyEnd>\n <div\n {...getMenuProps(\n {\n ref: (node: HTMLDivElement | null) => {\n anchorRef.current = node;\n },\n 'aria-label': label || placeholder || undefined,\n },\n { suppressRefError: true }\n )}\n className={cx(styles.dropdownInputListAnim, {\n [styles.dropdownInputListAnimWider]: isDropdownListWider,\n })}\n style={{ width: `${triggerWidth}px` }}\n >\n <InfiniteBlock\n onScroll={onScroll}\n className={styles.dropdownInputList}\n setHighlightedIndex={setHighlightedIndex}\n >\n {items.map((item: DropdownItem, index: number) => (\n <div\n key={item.key}\n {...getItemProps({ index, item, disabled: !!item.disabled })}\n className={cx(styles.dropdownInputListItem, dropDownClassName, {\n [styles.dropdownInputListItemActive]: highlightedIndex === index,\n [styles.dropdownInputListItemSelected]: selectedItem === item,\n [styles.dropdownInputListItemDisabled]: !!item.disabled,\n })}\n >\n {item.label}\n </div>\n ))}\n </InfiniteBlock>\n </div>\n </BodyEnd>\n ) : null}\n <fieldset\n className={cx(styles.dropdownFieldset, {\n [styles.dropdownBorderPlain]: plainStyle,\n [styles.dropdownBorderFocused]: showFocus,\n [styles.dropdownBorderInvalid]: hasErr,\n [styles.dropdownBorderError]: hasErr,\n })}\n >\n <legend\n className={cx(styles.dropdownFieldsetLegend, {\n [styles.dropdownFieldsetLegendActive]:\n useMatLabelStyle && (alwaysFloatLabel || showFocus || !isDisplayBlank),\n })}\n >\n <span>{editedLabel}</span>\n </legend>\n </fieldset>\n {useMatLabelStyle && label && (\n <div\n className={cx(styles.dropdownMatLabel, {\n [styles.dropdownMatLabelFloating]: alwaysFloatLabel || showFocus || !isDisplayBlank,\n })}\n >\n {label}\n {requiredMark}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.dropdownPlaceholder,\n showFocus && !dropdownLabel && styles.dropdownPlaceholderShown\n )}\n >\n {placeholder}\n </div>\n )}\n </div>\n </div>\n )}\n </Downshift>\n {label && !useMatLabelStyle && (\n <div className={cx(styles.dropdownLabelText, labelClassName)}>\n {label}\n {requiredMark}\n </div>\n )}\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() : (errorMessage || '')}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n\nexport default Dropdown;\n",".datePicker {\n position: relative;\n width: 100%;\n flex: 1;\n min-width: 105px;\n\n &-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin: 8px 0;\n\n &-monthAndYear {\n display: flex;\n\n &-container {\n display: flex;\n gap: 16px;\n position: relative;\n }\n }\n\n &-month {\n width: 120px;\n }\n\n &-year {\n width: 75px;\n }\n }\n\n &-month {\n min-width: 185px;\n }\n\n &-modalInput {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n color: var(--text-color);\n -webkit-text-fill-color: var(--text-color);\n }\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport Input from '../input';\nimport { useComponentDefaults } from '../configProvider';\nimport DatePickerMonth from './components/datePickerMonth';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\nimport { getLocale } from 'services/localization';\nimport ActionIcon from '../actionIcon';\nimport Modal from '../modal';\nimport FloatingMenu from '../floatingMenu';\nimport Dropdown from '../dropdown';\nimport { Align } from '../floatingMenu/floatingMenu.types';\nimport InputMask, { InputState, BeforeMaskedStateChangeStates } from '@mona-health/react-input-mask';\nimport { getDateFromDayMonthAndYear, getMonthName, getMonthNames, getDateString, correctDateMaskValue } from './dateFunctions';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport type { FormValidator } from 'services/formValidation';\n\nimport styles from './datePicker.module.pcss';\n\nexport interface DatePickerProps {\n className?: string;\n selected?: Date;\n onSelect?: (date: Date | null) => void;\n formValidator?: FormValidator | null;\n noInput?: boolean;\n noHeader?: boolean;\n isModal?: boolean;\n isInline?: boolean;\n onChange?: (date: Date | null) => void;\n minDate?: Date | null;\n maxDate?: Date | null;\n children?: React.ReactNode;\n showClearButton?: boolean;\n label?: string;\n isValid?: boolean;\n errorMessage?: string;\n isRequired?: boolean;\n startDate?: Date;\n endDate?: Date;\n}\n\nexport default function DatePicker(props: DatePickerProps) {\n const {\n className = '',\n selected,\n onSelect = () => null,\n formValidator = null,\n noInput = false,\n noHeader = false,\n isModal = false,\n isInline = false,\n onChange = () => null,\n minDate = null,\n maxDate = null,\n children = null,\n showClearButton = false,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n startDate,\n endDate,\n } = useComponentDefaults('DatePicker', props);\n const getCurrValue = (): Date | undefined =>\n formValidator ? (formValidator.value as Date) : selected;\n\n const initialDate = getCurrValue() ?? new Date();\n\n const [currentMonth, setCurrentMonth] = useState(initialDate.getMonth() + 1);\n const [currentYear, setCurrentYear] = useState(initialDate.getFullYear());\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [currentDateString, setCurrentDateString] = useState(() =>\n getCurrValue() ? getDateString(initialDate) : ''\n );\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const [prevSelected, setPrevSelected] = useState(selected);\n\n const fvRef = useRef(formValidator);\n\n // Sync navigation view when `selected` prop changes externally\n if (prevSelected !== selected) {\n setPrevSelected(selected);\n const d = selected ?? new Date();\n setCurrentMonth(d.getMonth() + 1);\n setCurrentYear(d.getFullYear());\n setCurrentDateString(selected ? getDateString(selected) : '');\n }\n\n // Subscribe to formValidator updates (external system → setState in callback)\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n const val = formValidator.value as Date | undefined;\n if (val) {\n setCurrentMonth(val.getMonth() + 1);\n setCurrentYear(val.getFullYear());\n setCurrentDateString(getDateString(val));\n } else {\n setCurrentDateString('');\n }\n forceUpdate((n: number) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean => {\n return formValidator\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n };\n\n const computedIsRequired = (): boolean => {\n return !!(isRequired || formValidator?.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n ));\n };\n\n const handleChange = (date: Date | null) => {\n setCurrentDateString(date ? getDateString(date) : '');\n if (formValidator) formValidator.set(date);\n onChange(date);\n };\n\n const handleSelect = (date: Date | null) => {\n handleChange(date);\n onSelect(date);\n setIsPickerOpen(false);\n };\n\n const changeMonth = (delta: number) => {\n setCurrentMonth((prev) => {\n let next = prev + delta;\n if (next < 1) { next = 12; setCurrentYear((y) => y - 1); }\n else if (next > 12) { next = 1; setCurrentYear((y) => y + 1); }\n return next;\n });\n };\n\n const tryParseDateString = (dateString: string): Date | null => {\n if (dateString.match(/\\d{2}\\.\\d{2}\\.\\d{4}/gi)) {\n const [day, month, year] = dateString.split('.');\n const parsedDate = getDateFromDayMonthAndYear(Number(day), Number(month), Number(year));\n if (parsedDate && parsedDate.toString() !== 'Invalid Date') {\n const isSmallerThanMaxDate = !maxDate || parsedDate <= maxDate;\n const isBiggerThanMinDate = !minDate || parsedDate >= minDate;\n if (isSmallerThanMaxDate && isBiggerThanMinDate) return parsedDate;\n }\n }\n return null;\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): InputState => {\n // previousState is only supplied on user-driven change events; on mount/focus/blur\n // there is nothing to auto-correct, so the next state passes through unchanged.\n if (!previousState || nextState.value === previousState.value) return nextState;\n\n const corrected = correctDateMaskValue(nextState.value, previousState.value, nextState.selection ?? null);\n\n const parsedDate = tryParseDateString(corrected.value);\n if (parsedDate) handleChange(parsedDate);\n\n return corrected;\n };\n\n const getYearDropdownOptions = () => {\n let length = 400;\n let zeroOffset = new Date().getFullYear() - 200;\n if (minDate) zeroOffset = minDate.getFullYear();\n if (maxDate) length = maxDate.getFullYear() - zeroOffset + 1;\n return Array.from(Array(length).keys()).map((i) => ({ key: i + zeroOffset, label: i + zeroOffset }));\n };\n\n const currValue = getCurrValue();\n const hasErr = hasError();\n\n const header = noHeader ? null : (\n <div className={styles.datePickerHeader}>\n <ActionIcon icon={faChevronLeft} onClick={() => changeMonth(-1)} />\n <div className={styles.datePickerHeaderMonthAndYearContainer}>\n <div className={styles.datePickerHeaderMonthAndYear}>\n <Dropdown\n plainStyle\n scrollToSelected\n onChange={(v) => setCurrentMonth(v as number)}\n className={styles.datePickerHeaderMonth}\n value={getMonthName(getLocale('-'), currentYear, currentMonth, 1)}\n items={getMonthNames().map((month, index) => ({ key: index + 1, label: month }))}\n />\n <Dropdown\n plainStyle\n scrollToSelected\n useMatLabelStyle={false}\n className={styles.datePickerHeaderYear}\n onChange={(v) => setCurrentYear(v as number)}\n value={currentYear}\n items={getYearDropdownOptions()}\n />\n </div>\n </div>\n <ActionIcon icon={faChevronRight} onClick={() => changeMonth(1)} />\n </div>\n );\n\n const pickerContent = (\n <>\n {header}\n <DatePickerMonth\n className={styles.datePickerMonth}\n month={currentMonth}\n year={currentYear}\n onSelect={handleSelect}\n selectionStart={startDate ?? currValue}\n selectionEnd={endDate ?? currValue}\n minDate={minDate}\n maxDate={maxDate}\n />\n {showClearButton && <Button onClick={() => handleSelect(null)}>Clear</Button>}\n {children}\n </>\n );\n\n const input = noInput ? null : (\n <Input\n readOnly={isModal}\n classNames={isModal ? { input: styles.datePickerModalInput } : undefined}\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentDateString}\n onChange={(v) => setCurrentDateString(v as string)}\n onClick={() => setIsPickerOpen(true)}\n customInput={\n <InputMask mask=\"99.99.9999\" maskPlaceholder=\"_\" beforeMaskedStateChange={beforeMaskedStateChange} />\n }\n onBlur={() => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n handleChange(tryParseDateString(currentDateString));\n }}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n isValid={!hasErr}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <FloatingMenu\n isOpen={isPickerOpen}\n onOpenChange={(open: boolean) => setIsPickerOpen(open)}\n content={pickerContent}\n align={Align.Left}\n dontCloseOnChildClick\n >\n {input}\n </FloatingMenu>\n );\n })();\n\n return (\n <div className={cx(styles.datePicker, className)}>\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() : (errorMessage || '')}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum DividerTextPosition {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\nexport enum DividerOrientation {\n Horizontal = 'horizontal',\n Vertical = 'vertical',\n}\n\nexport type DividerSlots = 'root' | 'line' | 'content';\n\nexport interface DividerProps extends HtmlProps {\n text?: ReactNode;\n textPosition?: DividerTextPosition;\n orientation?: DividerOrientation;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<DividerSlots>;\n styles?: SlotStyles<DividerSlots>;\n}\n",".divider {\n display: flex;\n align-items: center;\n width: 100%;\n\n &-line {\n flex: 1 1 auto;\n height: 1px;\n background-color: var(--border-color);\n }\n\n &-content {\n flex: 0 0 auto;\n padding: 0 0.75em;\n color: var(--text-dark);\n font-size: 0.875em;\n white-space: nowrap;\n }\n\n &-text-left &-line:first-child {\n flex-grow: 0;\n flex-basis: 1.5em;\n }\n\n &-text-right &-line:last-child {\n flex-grow: 0;\n flex-basis: 1.5em;\n }\n\n &-vertical {\n flex-direction: column;\n width: auto;\n align-self: stretch;\n }\n\n &-vertical &-line {\n width: 1px;\n height: auto;\n }\n\n &-vertical &-content {\n padding: 0.75em 0;\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { DividerTextPosition, DividerOrientation } from './divider.types';\nimport type { DividerProps } from './divider.types';\nimport styles from './divider.module.pcss';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_TEXT_POSITION: Record<DividerTextPosition, string> = {\n [DividerTextPosition.Left]: styles.dividerTextLeft,\n [DividerTextPosition.Center]: styles.dividerTextCenter,\n [DividerTextPosition.Right]: styles.dividerTextRight,\n};\n\nfunction Divider(props: DividerProps): ReactElement {\n const {\n text,\n textPosition = DividerTextPosition.Center,\n orientation = DividerOrientation.Horizontal,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Divider', props);\n\n const hasText = text != null && text !== '';\n const isVertical = orientation === DividerOrientation.Vertical;\n\n return (\n <div\n {...rest}\n role=\"separator\"\n aria-orientation={isVertical ? 'vertical' : undefined}\n className={cx(\n styles.divider,\n isVertical && styles.dividerVertical,\n hasText && CLASS_BY_TEXT_POSITION[textPosition],\n className,\n classNames?.root,\n )}\n style={{ ...style, ...slotStyles?.root }}\n >\n <span className={cx(styles.dividerLine, classNames?.line)} style={slotStyles?.line} />\n {hasText && (\n <span className={cx(styles.dividerContent, classNames?.content)} style={slotStyles?.content}>\n {text}\n </span>\n )}\n {hasText && (\n <span className={cx(styles.dividerLine, classNames?.line)} style={slotStyles?.line} />\n )}\n </div>\n );\n}\n\nexport default Divider;\n",".drawer {\n height: 100%;\n overflow-x: hidden;\n width: var(--drawer-closed-width, 0px);\n transition: width 0.3s ease;\n background: var(--background-accent);\n\n &-open {\n width: var(--drawer-opened-width, var(--drawer-content-width, max-content));\n }\n\n &-content {\n width: max-content;\n height: 100%;\n pointer-events: all;\n\n &-inner {\n height: 100%;\n }\n }\n}\n","import type { ReactElement, CSSProperties } from 'react';\nimport { useRef, useEffect } from 'react';\nimport { DrawerProps } from './drawer.types';\nimport cx from 'classnames';\n\nimport styles from './drawer.module.pcss';\n\n\nfunction Drawer({\n className,\n isOpen = false,\n closedWidth,\n openedWidth,\n children,\n}: DrawerProps): ReactElement {\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const observer = new ResizeObserver(() => {\n if (containerRef.current && contentRef.current) {\n containerRef.current.style.setProperty(\n '--drawer-content-width',\n `${contentRef.current.scrollWidth}px`\n );\n }\n });\n if (contentRef.current) observer.observe(contentRef.current);\n return () => observer.disconnect();\n }, []);\n\n return (\n <div\n ref={containerRef}\n className={cx(styles.drawer, isOpen && styles.drawerOpen, className)}\n style={{\n ...(closedWidth !== undefined && { '--drawer-closed-width': closedWidth }),\n ...(openedWidth !== undefined && { '--drawer-opened-width': openedWidth }),\n } as CSSProperties}\n >\n <div ref={contentRef} className={styles.drawerContent}>\n <div className={styles.drawerContentInner}>\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nexport default Drawer;\n","import type React from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum DropZoneStatus {\n /** Nothing is happening. */\n Idle = 'idle',\n /** A file drag is somewhere in the window — the zone is \"armed\". */\n Dragging = 'dragging',\n /** A file drag is hovering directly over this zone. */\n Active = 'active',\n /** The last drop / selection was rejected. */\n Error = 'error',\n}\n\nexport enum DropZoneReturnType {\n /** Emit the raw `File` objects (default). */\n File = 'file',\n /** Read each file as a base64 data URL and emit `LoadedFile`. */\n Base64 = 'base64',\n /** Read each file as UTF-8 text and emit `LoadedFile`. */\n Text = 'text',\n}\n\nexport interface LoadedFile {\n name: string;\n size: number;\n type: string;\n lastModified: number;\n /** The FileReader result — a base64 data URL or text, depending on `returnType`. */\n data: string;\n}\n\nexport type DropZoneRejectionReason =\n /** File extension / mime type not in `acceptedTypes`. */\n | 'unacceptedType'\n /** File exceeds `maxSize`. */\n | 'tooLarge'\n /** More files than `maxFiles` were provided. */\n | 'tooMany'\n /** Reading the file (base64 / text) failed. */\n | 'readError';\n\nexport interface DropZoneRejection {\n file: File;\n reason: DropZoneRejectionReason;\n}\n\nexport interface DropZoneRenderState {\n status: DropZoneStatus;\n /** A drag is anywhere in the window (zone armed) or directly over it. */\n isDragging: boolean;\n /** A drag is directly over this zone. */\n isActive: boolean;\n disabled: boolean;\n}\n\nexport type DropZoneSlots = 'root' | 'content' | 'fileList' | 'fileItem' | 'input';\n\nexport interface DropZoneProps extends HtmlProps {\n /** Static content, or a render function that receives the live drop state. */\n children?: React.ReactNode | ((state: DropZoneRenderState) => React.ReactNode);\n\n /**\n * Accepted file types: extensions (`'.png'`), mime types (`'image/png'`),\n * or wildcards (`'image/*'`). Empty / omitted means accept everything.\n * Also drives the native picker's `accept` attribute.\n */\n acceptedTypes?: string[];\n /** Output shape for each accepted file. Default: `File`. */\n returnType?: DropZoneReturnType;\n\n /** Open the native file picker when the zone is clicked. */\n openPickerOnClick?: boolean;\n /** Allow more than one file. Default: `true`. */\n multiple?: boolean;\n /** Reject files beyond this count (extras reported via `onReject`). */\n maxFiles?: number;\n /** Reject files larger than this many bytes. */\n maxSize?: number;\n /** Accept files pasted from the clipboard while the zone is focused. */\n enablePaste?: boolean;\n /** Recurse into dropped directories. Default: `true`. */\n allowDirectories?: boolean;\n\n /** Native `capture` attribute (mobile camera / mic). */\n capture?: boolean | 'user' | 'environment';\n disabled?: boolean;\n\n /** Drop the built-in border / background styling; keep only base layout. */\n unstyled?: boolean;\n /** Render the names of `files` beneath the content. */\n showFileNames?: boolean;\n /** Files whose names are listed when `showFileNames` is set. */\n files?: (File | LoadedFile)[];\n\n onFilesChanged?: (files: (File | LoadedFile)[]) => void;\n onReject?: (rejections: DropZoneRejection[]) => void;\n onStatusChanged?: (status: DropZoneStatus) => void;\n\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<DropZoneSlots>;\n styles?: SlotStyles<DropZoneSlots>;\n}\n",".dropZone {\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n outline: none;\n\n &-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n &-default {\n padding: var(--spacing-l, 24px);\n border: 1px dashed var(--border-color);\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n transition: border-color 0.2s, background 0.2s, color 0.2s;\n }\n\n &-default&-clickable:hover {\n border-color: var(--primary-color);\n background: var(--background-accent-light);\n }\n\n /* A drag is somewhere in the window — the zone is armed. */\n &-dragging {\n border-color: var(--primary-color);\n }\n\n /* A drag is hovering directly over this zone. */\n &-active {\n border-width: 2px;\n border-color: var(--primary-color);\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n\n &-error {\n border-color: var(--error-color);\n color: var(--error-color);\n }\n\n &-error&-clickable:hover {\n border-color: var(--error-color);\n background: var(--error-lighter);\n }\n\n &-content {\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n\n /* While dragging, let drop events fall through to the root instead of child elements. */\n &-dragging {\n pointer-events: none;\n }\n }\n\n &-fileList {\n width: 100%;\n margin-top: var(--spacing-s, 8px);\n pointer-events: none;\n }\n\n &-fileItem {\n font-size: var(--text-small-font-size);\n color: var(--text-dark);\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n }\n\n &-input {\n display: none;\n }\n}\n","import React, { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport cx from 'classnames';\n\nimport {\n DropZoneProps,\n DropZoneReturnType,\n DropZoneStatus,\n DropZoneRejection,\n DropZoneRenderState,\n LoadedFile,\n} from './dropZone.types';\n\nimport styles from './dropZone.module.pcss';\n\n// ── Pure helpers ──────────────────────────────────────────────────────────────\n\n/** True when a file matches one of the accepted tokens (extension, mime, or wildcard). */\nfunction matchesAccepted(file: File, acceptedTypes: string[]): boolean {\n if (!acceptedTypes.length) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return acceptedTypes.some((raw) => {\n const accept = raw.trim().toLowerCase();\n if (!accept) return false;\n if (accept.startsWith('.')) return name.endsWith(accept); // extension\n if (accept.endsWith('/*')) return type.startsWith(accept.slice(0, -1)); // wildcard e.g. image/\n return type === accept; // exact mime type\n });\n}\n\ntype ReadResult = { ok: true; value: File | LoadedFile } | { ok: false };\n\n/** Read a single file into the requested return shape. Never rejects — failures resolve to `{ ok: false }`. */\nfunction readFile(file: File, returnType: DropZoneReturnType): Promise<ReadResult> {\n if (returnType === DropZoneReturnType.File) {\n return Promise.resolve({ ok: true, value: file });\n }\n return new Promise<ReadResult>((resolve) => {\n const reader = new FileReader();\n reader.onload = (event) => {\n const data = event.target?.result;\n if (typeof data !== 'string') {\n resolve({ ok: false });\n return;\n }\n resolve({\n ok: true,\n value: { name: file.name, size: file.size, type: file.type, lastModified: file.lastModified, data },\n });\n };\n reader.onerror = () => resolve({ ok: false });\n if (returnType === DropZoneReturnType.Base64) reader.readAsDataURL(file);\n else reader.readAsText(file);\n });\n}\n\n/** Recursively flatten a dropped file-system entry into a list of Files. */\nfunction readEntry(entry: FileSystemEntry): Promise<File[]> {\n return new Promise((resolve) => {\n if (entry.isFile) {\n (entry as FileSystemFileEntry).file(\n (file) => resolve([file]),\n () => resolve([])\n );\n } else if (entry.isDirectory) {\n const reader = (entry as FileSystemDirectoryEntry).createReader();\n const collected: FileSystemEntry[] = [];\n const readBatch = () => {\n // readEntries yields entries in chunks — keep calling until it returns empty.\n reader.readEntries((batch) => {\n if (!batch.length) {\n Promise.all(collected.map(readEntry)).then((nested) => resolve(nested.flat()));\n } else {\n collected.push(...batch);\n readBatch();\n }\n }, () => resolve([]));\n };\n readBatch();\n } else {\n resolve([]);\n }\n });\n}\n\n/**\n * Extract Files from a drop's DataTransfer. `webkitGetAsEntry()` must be called\n * synchronously within the drop handler, so all entries are captured before any await.\n */\nfunction gatherFiles(dataTransfer: DataTransfer, allowDirectories: boolean): Promise<File[]> {\n const items = dataTransfer.items;\n if (items && items.length) {\n if (allowDirectories && typeof items[0].webkitGetAsEntry === 'function') {\n const entries: FileSystemEntry[] = [];\n for (let i = 0; i < items.length; i += 1) {\n if (items[i].kind === 'file') {\n const entry = items[i].webkitGetAsEntry();\n if (entry) entries.push(entry);\n }\n }\n if (entries.length) {\n return Promise.all(entries.map(readEntry)).then((nested) => nested.flat());\n }\n }\n const files: File[] = [];\n for (let i = 0; i < items.length; i += 1) {\n if (items[i].kind === 'file') {\n const file = items[i].getAsFile();\n if (file) files.push(file);\n }\n }\n return Promise.resolve(files);\n }\n return Promise.resolve(Array.from(dataTransfer.files || []));\n}\n\n// ── Component ───────────────────────────────────────────────────────────────\n\nfunction DropZone({\n children,\n acceptedTypes = [],\n returnType = DropZoneReturnType.File,\n openPickerOnClick = false,\n multiple = true,\n maxFiles,\n maxSize,\n enablePaste = false,\n allowDirectories = true,\n capture,\n disabled = false,\n unstyled = false,\n showFileNames = false,\n files,\n onFilesChanged,\n onReject,\n onStatusChanged,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: DropZoneProps) {\n const [status, setStatus] = useState<DropZoneStatus>(DropZoneStatus.Idle);\n\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = useId();\n const statusRef = useRef(status);\n const windowDragDepth = useRef(0);\n const zoneDragDepth = useRef(0);\n\n // Latest props/callbacks, so the once-mounted window listeners never read stale values.\n const cfg = useRef({\n acceptedTypes, returnType, multiple, maxFiles, maxSize, allowDirectories,\n disabled, onFilesChanged, onReject, onStatusChanged,\n });\n cfg.current = {\n acceptedTypes, returnType, multiple, maxFiles, maxSize, allowDirectories,\n disabled, onFilesChanged, onReject, onStatusChanged,\n };\n\n const changeStatus = useCallback((next: DropZoneStatus) => {\n if (statusRef.current === next) return;\n statusRef.current = next;\n setStatus(next);\n cfg.current.onStatusChanged?.(next);\n }, []);\n\n const processFiles = useCallback(async (incoming: File[]) => {\n const c = cfg.current;\n const rejections: DropZoneRejection[] = [];\n let accepted: File[] = [];\n\n for (const file of incoming) {\n if (!matchesAccepted(file, c.acceptedTypes)) {\n rejections.push({ file, reason: 'unacceptedType' });\n } else if (c.maxSize != null && file.size > c.maxSize) {\n rejections.push({ file, reason: 'tooLarge' });\n } else {\n accepted.push(file);\n }\n }\n\n if (!c.multiple) accepted = accepted.slice(0, 1);\n if (c.maxFiles != null && accepted.length > c.maxFiles) {\n accepted.slice(c.maxFiles).forEach((file) => rejections.push({ file, reason: 'tooMany' }));\n accepted = accepted.slice(0, c.maxFiles);\n }\n\n // Read in input order — Promise.all preserves index regardless of completion order.\n const results = await Promise.all(accepted.map((file) => readFile(file, c.returnType)));\n const loaded: (File | LoadedFile)[] = [];\n results.forEach((result, index) => {\n if (result.ok) loaded.push(result.value);\n else rejections.push({ file: accepted[index], reason: 'readError' });\n });\n\n if (rejections.length) c.onReject?.(rejections);\n changeStatus(rejections.length && !loaded.length ? DropZoneStatus.Error : DropZoneStatus.Idle);\n if (loaded.length) c.onFilesChanged?.(loaded);\n }, [changeStatus]);\n\n // Window-level drag tracking via an enter/leave depth counter (robust against bubbling).\n useEffect(() => {\n const hasFiles = (dt: DataTransfer | null) =>\n !dt || Array.from(dt.types || []).includes('Files');\n\n const onWindowDragEnter = (e: DragEvent) => {\n if (cfg.current.disabled || !hasFiles(e.dataTransfer)) return;\n windowDragDepth.current += 1;\n if (statusRef.current === DropZoneStatus.Idle || statusRef.current === DropZoneStatus.Error) {\n changeStatus(DropZoneStatus.Dragging);\n }\n };\n const onWindowDragLeave = () => {\n windowDragDepth.current = Math.max(0, windowDragDepth.current - 1);\n if (windowDragDepth.current === 0 && statusRef.current === DropZoneStatus.Dragging) {\n changeStatus(DropZoneStatus.Idle);\n }\n };\n const onWindowDrop = () => {\n windowDragDepth.current = 0;\n zoneDragDepth.current = 0;\n if (statusRef.current === DropZoneStatus.Dragging) changeStatus(DropZoneStatus.Idle);\n };\n\n window.addEventListener('dragenter', onWindowDragEnter);\n window.addEventListener('dragleave', onWindowDragLeave);\n window.addEventListener('drop', onWindowDrop);\n return () => {\n window.removeEventListener('dragenter', onWindowDragEnter);\n window.removeEventListener('dragleave', onWindowDragLeave);\n window.removeEventListener('drop', onWindowDrop);\n };\n }, [changeStatus]);\n\n const onDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer) e.dataTransfer.dropEffect = disabled ? 'none' : 'copy';\n }, [disabled]);\n\n const onDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n if (disabled) return;\n zoneDragDepth.current += 1;\n changeStatus(DropZoneStatus.Active);\n }, [disabled, changeStatus]);\n\n const onDragLeave = useCallback((e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n zoneDragDepth.current = Math.max(0, zoneDragDepth.current - 1);\n if (zoneDragDepth.current === 0) {\n // Left the zone, but a drag may still be active elsewhere in the window.\n changeStatus(windowDragDepth.current > 0 ? DropZoneStatus.Dragging : DropZoneStatus.Idle);\n }\n }, [changeStatus]);\n\n const onDrop = useCallback((e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n zoneDragDepth.current = 0;\n windowDragDepth.current = 0;\n if (disabled || !e.dataTransfer) {\n changeStatus(DropZoneStatus.Idle);\n return;\n }\n changeStatus(DropZoneStatus.Idle);\n // gatherFiles captures any directory entries synchronously before awaiting.\n gatherFiles(e.dataTransfer, cfg.current.allowDirectories).then((collected) => {\n if (collected.length) processFiles(collected);\n });\n }, [disabled, changeStatus, processFiles]);\n\n const openPicker = useCallback(() => {\n if (disabled || !openPickerOnClick) return;\n inputRef.current?.click();\n }, [disabled, openPickerOnClick]);\n\n const onInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const selected = Array.from(e.target.files || []);\n // Reset so picking the same file again still fires onChange.\n e.target.value = '';\n if (selected.length) processFiles(selected);\n }, [processFiles]);\n\n const onPaste = useCallback((e: React.ClipboardEvent<HTMLDivElement>) => {\n if (!enablePaste || disabled) return;\n const pasted = Array.from(e.clipboardData?.files || []);\n if (pasted.length) {\n e.preventDefault();\n processFiles(pasted);\n }\n }, [enablePaste, disabled, processFiles]);\n\n const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (!openPickerOnClick || disabled) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n openPicker();\n }\n }, [openPickerOnClick, disabled, openPicker]);\n\n const isDragging = status === DropZoneStatus.Dragging || status === DropZoneStatus.Active;\n const renderState: DropZoneRenderState = {\n status,\n isDragging,\n isActive: status === DropZoneStatus.Active,\n disabled,\n };\n\n const acceptAttr = acceptedTypes.length ? acceptedTypes.join(',') : undefined;\n\n return (\n <div\n {...rest}\n className={cx(\n styles.dropZone,\n openPickerOnClick && styles.dropZoneClickable,\n disabled && styles.dropZoneDisabled,\n !unstyled && styles.dropZoneDefault,\n !unstyled && status === DropZoneStatus.Dragging && styles.dropZoneDragging,\n !unstyled && status === DropZoneStatus.Active && styles.dropZoneActive,\n !unstyled && status === DropZoneStatus.Error && styles.dropZoneError,\n classNames?.root,\n className\n )}\n style={{ ...slotStyles?.root, ...style }}\n onDragEnter={onDragEnter}\n onDragLeave={onDragLeave}\n onDragOver={onDragOver}\n onDrop={onDrop}\n onClick={openPicker}\n onKeyDown={onKeyDown}\n onPaste={enablePaste ? onPaste : undefined}\n role={openPickerOnClick ? 'button' : undefined}\n tabIndex={openPickerOnClick && !disabled ? 0 : undefined}\n aria-disabled={disabled || undefined}\n >\n <div\n className={cx(styles.dropZoneContent, isDragging && styles.dropZoneContentDragging, classNames?.content)}\n style={slotStyles?.content}\n >\n {typeof children === 'function' ? children(renderState) : children}\n </div>\n\n {showFileNames && files && files.length > 0 && (\n <div className={cx(styles.dropZoneFileList, classNames?.fileList)} style={slotStyles?.fileList}>\n {files.map((file, index) => (\n <div\n key={`${file.name}-${index}`}\n className={cx(styles.dropZoneFileItem, classNames?.fileItem)}\n style={slotStyles?.fileItem}\n >\n {file.name}\n </div>\n ))}\n </div>\n )}\n\n <input\n ref={inputRef}\n id={inputId}\n type=\"file\"\n className={cx(styles.dropZoneInput, classNames?.input)}\n style={slotStyles?.input}\n accept={acceptAttr}\n multiple={multiple}\n capture={capture}\n disabled={disabled}\n onChange={onInputChange}\n tabIndex={-1}\n aria-hidden=\"true\"\n />\n </div>\n );\n}\n\nexport default DropZone;\n",".emptyState {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-flow: column;\n gap: var(--spacing-m);\n}\n","import cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport type { ReactElement } from 'react';\nimport type { EmptyStateProps } from './emptyState.types';\nimport styles from './emptyState.module.pcss';\n\nexport default function EmptyState({ className, icon, children, ...rest }: EmptyStateProps): ReactElement {\n return (\n <div {...rest} className={cx(styles.emptyState, className)}>\n {icon && <FontAwesomeIcon icon={icon} />}\n <div>{children ?? 'No entries available'}</div>\n </div>\n );\n}\n",".fab {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n display: flex;\n align-items: stretch;\n padding: 0;\n\n --icon-size: 18px;\n\n /* Make the Ripple wrapper fill the full circular button */\n & > div {\n width: 100%;\n border-radius: 50%;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n &-content {\n font-size: var(--icon-size);\n width: var(--icon-size);\n height: var(--icon-size);\n\n svg {\n width: var(--icon-size);\n height: var(--icon-size);\n }\n\n &-container {\n display: flex;\n justify-content: center;\n align-items: center;\n }\n }\n\n &-size {\n &-mini {\n width: 40px;\n height: 40px;\n background: var(--background-accent-light);\n }\n }\n}\n","import cx from 'classnames';\n\nimport Button from 'components/common/button';\nimport { ButtonStyleType } from 'components/common/button/button.types';\nimport type { FabBaseProps, FabBaseSize } from './fabBase.types';\n\nimport styles from './fabBase.module.pcss';\n\nconst sizeClass: Record<FabBaseSize, string | null> = {\n default: null,\n mini: styles.fabSizeMini,\n};\n\nfunction FabBase({\n children = null,\n size = 'default',\n className = '',\n styleType = ButtonStyleType.Primary,\n onClick = () => {},\n}: FabBaseProps) {\n return (\n <Button\n styleType={styleType}\n className={cx(styles.fab, sizeClass[size], className)}\n onClick={onClick}\n >\n <div className={styles.fabContentContainer}>\n <div className={styles.fabContent}>{children}</div>\n </div>\n </Button>\n );\n}\n\nexport default FabBase;\n","\n.fab {\n animation: appear 0.3s forwards;\n opacity: 0;\n transform: scale(0);\n box-shadow:\n 0px 3px 5px -1px rgb(0 0 0 / 20%),\n 0px 6px 10px 0px rgb(0 0 0 / 14%),\n 0px 1px 18px 0px rgb(0 0 0 / 12%);\n border-radius: 50%;\n\n &-container {\n position: fixed;\n bottom: 16px;\n right: 16px;\n\n @media (--breakpoint-tablet) {\n z-index: 2;\n }\n }\n\n &-menu {\n position: absolute;\n top: 0;\n transform: translateY(calc(-100% - 16px));\n width: 100%;\n display: flex;\n flex-flow: column-reverse;\n gap: 16px;\n align-items: center;\n pointer-events: none;\n user-select: none;\n\n &-backdrop {\n width: 0%;\n height: 0%;\n position: fixed;\n top: 0;\n left: 0;\n background: black;\n opacity: 0;\n transition: opacity 0.4s;\n\n &-open {\n width: 100%;\n height: 100%;\n opacity: 0.5;\n }\n }\n\n &-entry {\n position: relative;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n opacity: 0;\n transform: scale(0);\n transition: all 0.2s;\n pointer-events: all;\n\n &:nth-child(2) {\n transition-delay: 0.05s;\n }\n\n &:nth-child(3) {\n transition-delay: 0.1s;\n }\n\n &:nth-child(4) {\n transition-delay: 0.15s;\n }\n\n &:nth-child(5) {\n transition-delay: 0.2s;\n }\n\n &:nth-child(6) {\n transition-delay: 0.25s;\n }\n\n &:nth-child(7) {\n transition-delay: 0.3s;\n }\n\n &-shown {\n opacity: 1;\n transform: scale(1);\n }\n\n &-label {\n background: var(--background-accent-light);\n border-radius: var(--default-border-radius);\n padding: 4px 8px;\n\n &-container {\n position: absolute;\n width: max-content;\n transform: translateX(-100%);\n height: 100%;\n margin-left: -8px;\n align-items: center;\n display: flex;\n }\n }\n }\n }\n\n &-icon {\n transition: all 0.4s;\n display: flex;\n justify-content: center;\n align-items: center;\n position: relative;\n width: 100%;\n height: 100%;\n\n &-menuOpen {\n transform: rotate(225deg);\n }\n\n &-content {\n position: absolute;\n width: 18px;\n height: 18px;\n opacity: 0;\n transition: opacity 0.3s;\n\n &-shown {\n opacity: 1;\n }\n }\n }\n\n @keyframes appear {\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n}\n","import { useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faPlus as addIcon } from '@fortawesome/free-solid-svg-icons';\nimport { ButtonStyleType } from '../button/button.types';\n\nimport FabBase from './components/fabBase';\nimport type { FabProps } from './fab.types';\n\nimport styles from './fab.module.pcss';\n\nfunction Fab({\n children = null,\n size = 'default',\n menuEntries = [],\n onMenuEntryClicked = () => {},\n onClick = () => {},\n closeMenuOnEntryClicked = true,\n ...rest\n}: FabProps) {\n const [menuOpen, setMenuOpen] = useState(false);\n\n function handleFabClick() {\n if (menuEntries.length > 0) setMenuOpen((prev) => !prev);\n onClick();\n }\n\n function handleEntryClick(e: React.MouseEvent, id: string) {\n e.stopPropagation();\n if (closeMenuOnEntryClicked) setMenuOpen(false);\n onMenuEntryClicked(id);\n }\n\n return (\n <div {...rest} className={styles.fabContainer}>\n <div\n className={cx(styles.fabMenuBackdrop, menuOpen && styles.fabMenuBackdropOpen)}\n onClick={(e) => { e.stopPropagation(); setMenuOpen(false); }}\n />\n <div onClick={(e) => e.stopPropagation()}>\n <FabBase className={styles.fab} size={size} onClick={handleFabClick}>\n <div className={cx(styles.fabIcon, menuOpen && styles.fabIconMenuOpen)}>\n <div className={cx(styles.fabIconContent, !menuOpen && styles.fabIconContentShown)}>\n {children}\n </div>\n <div className={cx(styles.fabIconContent, menuOpen && styles.fabIconContentShown)}>\n <FontAwesomeIcon icon={addIcon} />\n </div>\n </div>\n </FabBase>\n </div>\n <div className={styles.fabMenu}>\n {menuEntries.map(({ id, label, icon }) => (\n <div\n key={id}\n className={cx(styles.fabMenuEntry, menuOpen && styles.fabMenuEntryShown)}\n onClick={(e) => handleEntryClick(e, id)}\n >\n {label && (\n <div className={styles.fabMenuEntryLabelContainer}>\n <div className={styles.fabMenuEntryLabel}>{label}</div>\n </div>\n )}\n <FabBase size=\"mini\" styleType={ButtonStyleType.Default}>\n <FontAwesomeIcon icon={icon} />\n </FabBase>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport default Fab;\n",".iconPicker {\n border-width: 1px;\n border-radius: var(--default-border-radius);\n border-color: transparent;\n border-style: solid;\n\n &-label {\n font-size: var(--text-small-font-size);\n margin-bottom: 8px;\n }\n\n &-item {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 8px;\n width: 24px;\n height: 24px;\n background: var(--background-accent);\n border-radius: 200px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n stroke: var(--text-color);\n position: relative;\n\n &:focus-visible {\n outline: 1px solid var(--primary-color);\n }\n\n &-container {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-around;\n gap: 8px 14px;\n }\n\n &-selected {\n background: var(--primary-color);\n }\n }\n\n &-error {\n border-color: red;\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport styles from './iconPicker.module.pcss';\nimport Ripple from '../ripple';\nimport type { IconPickerItem, IconPickerProps } from './iconPicker.types';\n\nfunction hasError(props: IconPickerProps): boolean {\n const { formValidator } = props;\n return formValidator ? (formValidator.touched && formValidator.hasError()) : false;\n}\n\nfunction isRequired(props: IconPickerProps): boolean {\n const { isRequired: reqProp, formValidator } = props;\n return !!(reqProp || formValidator?.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n ));\n}\n\nexport default function IconPicker({\n data = [],\n selectedId = null,\n label = '',\n onChange,\n formValidator = null,\n isRequired: _isRequired,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: IconPickerProps) {\n const currentValue = formValidator ? (formValidator.value as string) ?? null : selectedId;\n const showError = hasError({ formValidator, isRequired: _isRequired });\n const required = isRequired({ formValidator, isRequired: _isRequired });\n\n function handleSelect(id: string) {\n if (formValidator) formValidator.set(id);\n onChange?.(id);\n }\n\n return (\n <div\n {...rest}\n className={cx(styles.iconPicker, { [styles.iconPickerError]: showError }, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n >\n {label && (\n <div className={cx(styles.iconPickerLabel, classNames?.label)} style={slotStyles?.label}>\n {label}\n {required && ' *'}\n </div>\n )}\n <div\n className={cx(styles.iconPickerItemContainer, classNames?.itemContainer)}\n style={slotStyles?.itemContainer}\n >\n {data.map(({ id, label: itemLabel, icon, customIcon }: IconPickerItem) => (\n <div\n key={id}\n className={cx(\n styles.iconPickerItem,\n { [styles.iconPickerItemSelected]: currentValue === id },\n classNames?.item\n )}\n style={slotStyles?.item}\n title={itemLabel}\n tabIndex={0}\n role=\"button\"\n onClick={() => handleSelect(id)}\n onKeyDown={({ key }) => { if (key === 'Enter') handleSelect(id); }}\n >\n {icon && <FontAwesomeIcon icon={icon} />}\n {customIcon ?? null}\n <Ripple />\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport type { IdleManagerProps } from './idleManager.types';\n\nconst ACTIVITY_EVENTS = ['click', 'mousemove', 'keydown', 'scroll', 'touchstart'] as const;\n\nfunction IdleManager({\n children = null,\n idleAfterSeconds = 600,\n renderCondition = true,\n}: IdleManagerProps) {\n const [isIdleContentShown, setIsIdleContentShown] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const resetIdleTimeout = useCallback(() => {\n if (timeoutRef.current !== null) clearTimeout(timeoutRef.current);\n setIsIdleContentShown(false);\n timeoutRef.current = setTimeout(() => {\n setIsIdleContentShown(true);\n }, idleAfterSeconds * 1000);\n }, [idleAfterSeconds]);\n\n // Re-run whenever idleAfterSeconds changes (or on first mount)\n useEffect(() => {\n resetIdleTimeout();\n }, [resetIdleTimeout]);\n\n // Register / unregister activity listeners\n useEffect(() => {\n for (const event of ACTIVITY_EVENTS) {\n document.addEventListener(event, resetIdleTimeout);\n }\n return () => {\n for (const event of ACTIVITY_EVENTS) {\n document.removeEventListener(event, resetIdleTimeout);\n }\n // Clear any pending timeout on unmount so it never fires after we're gone\n if (timeoutRef.current !== null) clearTimeout(timeoutRef.current);\n };\n }, [resetIdleTimeout]);\n\n return <>{renderCondition && isIdleContentShown && children}</>;\n}\n\nexport default IdleManager;\n",".inputDropdown {\n position: relative;\n}\n\n.dropdown {\n position: fixed;\n width: fit-content;\n max-width: 240px;\n color: var(--text-color);\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n box-sizing: border-box;\n overflow: hidden;\n transition: all 0.1s;\n transform-origin: top left;\n opacity: 0;\n transform: scale(0.95);\n z-index: 1;\n\n &-scroll {\n overflow: auto;\n max-height: 200px;\n }\n\n &-shown {\n transform: scale(1);\n opacity: 1;\n }\n\n &-flip {\n transform-origin: bottom left;\n }\n\n &-item {\n padding: 8px;\n z-index: 0;\n outline: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover,\n &:focus {\n background: var(--background-accent);\n }\n\n &-highlighted {\n background: var(--background-accent);\n }\n }\n\n &-category {\n padding: 16px 8px 4px 8px;\n }\n}\n","import React, { useCallback, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\nimport styles from './inputDropdown.module.pcss';\nimport Input from '../input';\nimport { useFloatingPosition } from '../floatingMenu/useFloatingPosition';\nimport { useComponentDefaults } from '../configProvider';\nimport type { InputDropdownItem, InputDropdownProps } from './inputDropdown.types';\n\nfunction getKeyFromProps(value: string | undefined, formValidator: InputDropdownProps['formValidator']): string {\n return formValidator ? (formValidator.value as string) ?? '' : (value ?? '');\n}\n\nfunction labelForKey(key: string, items: InputDropdownItem[]): string {\n const match = items.find((item) => item.value === key);\n return match ? (match.label ?? match.value) : key;\n}\n\nexport default function InputDropdown(props: InputDropdownProps) {\n const {\n label = '',\n value = '',\n formValidator = null,\n items = [],\n allowCustomValue = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n onSelect = () => null,\n onChange,\n placeholder = '',\n readOnly = false,\n ...rest\n } = useComponentDefaults('InputDropdown', props);\n const currentKey = getKeyFromProps(value, formValidator);\n\n const [inputText, setInputText] = useState(() => labelForKey(currentKey, items));\n const [prevKey, setPrevKey] = useState(currentKey);\n const [isMenuShown, setIsMenuShown] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState<number | null>(null);\n const hideTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n\n useFloatingPosition({\n isOpen: isMenuShown,\n triggerRef,\n anchorRef,\n panelRef: anchorRef,\n flipClassName: styles.dropdownFlip,\n });\n\n // Sync display text when the controlled key changes externally (e.g. parent reset).\n if (currentKey !== prevKey) {\n setPrevKey(currentKey);\n const match = items.find((item) => item.value === currentKey);\n if (match) setInputText(match.label ?? match.value);\n else if (allowCustomValue) setInputText(currentKey);\n }\n\n const currItems = items.filter((item) =>\n (item.label ?? item.value).toLowerCase().includes(inputText.toLowerCase())\n );\n\n const handleFocus = () => {\n if (readOnly) return;\n if (hideTimeoutRef.current) {\n clearTimeout(hideTimeoutRef.current);\n hideTimeoutRef.current = null;\n }\n setIsMenuShown(true);\n };\n\n const handleBlur = () => {\n hideTimeoutRef.current = setTimeout(() => {\n setIsMenuShown(false);\n hideTimeoutRef.current = null;\n // Without custom values, uncommitted typed text is invalid — snap the\n // display back to the currently selected item's label.\n if (!allowCustomValue) setInputText(labelForKey(currentKey, items));\n }, 100);\n };\n\n const handleSelect = useCallback((item: InputDropdownItem) => {\n setInputText(item.label ?? item.value);\n setIsMenuShown(false);\n setHighlightedIndex(null);\n if (formValidator) formValidator.set(item.value);\n if (onChange) onChange(item.value);\n onSelect(item.value);\n }, [formValidator, onChange, onSelect]);\n\n const onKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (readOnly) return;\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n setHighlightedIndex((idx) => (!idx ? null : idx - 1));\n } else if (event.key === 'ArrowDown') {\n event.preventDefault();\n setHighlightedIndex((idx) =>\n idx === null ? 0 : Math.min(idx + 1, currItems.length - 1)\n );\n } else if (event.key === 'Enter') {\n if (highlightedIndex !== null && currItems[highlightedIndex]) {\n handleSelect(currItems[highlightedIndex]);\n } else if (allowCustomValue) {\n setIsMenuShown(false);\n setHighlightedIndex(null);\n }\n }\n }, [currItems, highlightedIndex, handleSelect, allowCustomValue, readOnly]);\n\n return (\n <div\n {...rest}\n ref={triggerRef}\n className={cx(styles.inputDropdown, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={onKeyDown}\n >\n <Input\n label={label}\n value={inputText}\n readOnly={readOnly}\n onChange={(text) => {\n setInputText(text);\n setHighlightedIndex(null);\n setIsMenuShown(true);\n if (allowCustomValue) {\n if (formValidator) formValidator.set(text);\n if (onChange) onChange(text);\n } else if (text === '') {\n if (formValidator) formValidator.set('');\n if (onChange) onChange('');\n onSelect('');\n } else {\n // Emit when the typed text exactly matches an item's label/value.\n const match = items.find(\n (item) => (item.label ?? item.value).toLowerCase() === text.toLowerCase()\n );\n if (match) {\n if (formValidator) formValidator.set(match.value);\n if (onChange) onChange(match.value);\n onSelect(match.value);\n }\n }\n }}\n placeholder={placeholder}\n />\n {isMenuShown && !readOnly && (\n <BodyEnd>\n <div\n ref={anchorRef}\n className={cx(styles.dropdown, styles.dropdownShown, classNames?.dropdown)}\n style={slotStyles?.dropdown}\n >\n <div className={styles.dropdownScroll}>\n {currItems.map((item, key) => (\n <div\n key={`${key}_${item.label}_${item.value}`}\n className={cx(\n styles.dropdownItem,\n highlightedIndex === key && styles.dropdownItemHighlighted,\n classNames?.item\n )}\n style={slotStyles?.item}\n // Prevent the input from blurring before the click resolves.\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleSelect(item)}\n >\n {item.label ?? item.value}\n </div>\n ))}\n </div>\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n",".board {\n display: flex;\n gap: var(--spacing-s);\n overflow-x: auto;\n align-items: flex-start;\n width: 100%;\n}\n\n.column {\n background: var(--background-accent-light);\n border-radius: var(--default-border-radius);\n box-shadow: var(--card-shadow);\n flex: 1 1 0;\n display: flex;\n flex-direction: column;\n border: 2px solid transparent;\n transition: border-color 0.15s ease, background 0.15s ease;\n\n &-empty {\n flex: 0 1 0;\n min-width: var(--kanban-empty-column-width, 140px);\n }\n\n &-over {\n border-color: var(--primary-lighter);\n background: var(--background-accent);\n }\n\n &-over-limit {\n border-color: var(--warn-color);\n }\n\n /* A whole column being dragged over this one, reordering — distinct from -over (a card being\n dropped into this column's card list), even though both are dashed-free solid borders here;\n kept as a separate class so consumers can restyle one without affecting the other. */\n &-drop-target {\n border-color: var(--primary-color);\n background: var(--background-accent);\n }\n\n /* Dims only the cards area, not the header — header actions (e.g. an \"add card\" button) are\n consumer-controlled and often meant to stay fully interactive even while the column itself\n is frozen for dragging, and opacity on an ancestor can't be undone by a child's own opacity. */\n &-disabled &-items {\n opacity: 0.6;\n }\n\n &-dragging {\n opacity: 0.4;\n }\n\n &-drag-overlay {\n cursor: grabbing;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25), var(--card-shadow);\n min-width: 220px;\n }\n\n &-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-s);\n padding: var(--spacing-m) var(--spacing-l);\n background: var(--background-accent);\n border-radius: var(--default-border-radius) var(--default-border-radius) 0 0;\n font-size: var(--header-small-font-size);\n font-weight: var(--header-font-weight);\n color: var(--text-color);\n border-bottom: 1px solid var(--border-color);\n\n &-reorderable {\n cursor: grab;\n -webkit-tap-highlight-color: transparent;\n touch-action: none;\n\n &:active {\n cursor: grabbing;\n }\n }\n\n &-title {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &-count {\n flex-shrink: 0;\n font-size: var(--default-font-size);\n font-weight: var(--default-font-weight);\n color: var(--text-dark);\n\n &-over {\n color: var(--warn-color);\n font-weight: var(--header-font-weight);\n }\n }\n\n &-trailing {\n display: flex;\n align-items: center;\n gap: var(--spacing-s);\n flex-shrink: 0;\n }\n\n &-actions {\n display: flex;\n align-items: center;\n gap: var(--spacing-s);\n }\n }\n\n &-items {\n padding: var(--spacing-m);\n display: flex;\n flex-direction: column;\n gap: var(--spacing-m);\n min-height: 80px;\n flex: 1;\n }\n\n &-placeholder {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n color: var(--text-dark);\n font-size: var(--default-font-size);\n }\n}\n\n.item {\n cursor: grab;\n touch-action: none;\n\n &:active {\n cursor: grabbing;\n }\n\n &-dragging {\n opacity: 0.4;\n }\n\n &-handled {\n cursor: default;\n touch-action: auto;\n\n &:active {\n cursor: default;\n }\n\n [data-drag-handle] {\n cursor: grab;\n -webkit-tap-highlight-color: transparent;\n touch-action: none;\n }\n\n [data-drag-handle]:active {\n cursor: grabbing;\n }\n }\n\n &-disabled {\n cursor: not-allowed;\n\n &:active {\n cursor: not-allowed;\n }\n\n [data-drag-handle] {\n cursor: not-allowed;\n }\n\n [data-drag-handle]:active {\n cursor: not-allowed;\n }\n }\n}\n\n.dragOverlay {\n border-radius: var(--default-border-radius);\n cursor: grabbing;\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25), var(--card-shadow);\n}\n","import type { PointerEvent as ReactPointerEvent, PointerEventHandler } from 'react';\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport cx from 'classnames';\n\nimport type { KanbanItemProps } from './kanbanBoard.types';\nimport styles from './kanbanBoard.module.pcss';\n\n// Hoisted so these are referentially stable across renders — an inline object literal here would\n// give `useSortable` a new `disabled` value every render (every card re-renders on every\n// `dragOver` while a drag is in progress, via `shadowColumns`), which can spin dnd-kit's own\n// registration effect into a render loop that eventually trips React's \"Maximum update depth\n// exceeded\" guard. Same fix as the sensor options in `KanbanBoard.tsx` and `data`/`disabled` in\n// `KanbanColumn.tsx`. Only two shapes are ever needed, so both are hoisted rather than memoized.\nconst ITEM_DISABLED_DRAG_AND_DROP = { draggable: true, droppable: true };\nconst ITEM_DISABLED_DRAG_ONLY = { draggable: true, droppable: false };\n\nfunction KanbanItem({ id, dragHandle, disabled, preventAsDropTarget, children }: KanbanItemProps) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id,\n // The boolean shorthand only disables dragging *out* of the card — dnd-kit hard-codes\n // `droppable: false` for it either way (\"backwards compatibility\"). That's actually what we\n // want for a card pinned individually (`getItemDisabled`): it can't be dragged, but other\n // cards should still be able to land before/after it normally. Only a frozen *column*\n // (`preventAsDropTarget`) also disables droppable, so nothing can be dropped into it at all.\n disabled: disabled ? (preventAsDropTarget ? ITEM_DISABLED_DRAG_AND_DROP : ITEM_DISABLED_DRAG_ONLY) : undefined,\n });\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>) {\n if (!(event.target as HTMLElement).closest('[data-drag-handle]')) return;\n listeners?.onPointerDown?.(event);\n }\n\n return (\n <div\n ref={setNodeRef}\n style={{ transform: CSS.Transform.toString(transform), transition }}\n className={cx(\n styles.item,\n dragHandle && styles.itemHandled,\n isDragging && styles.itemDragging,\n disabled && styles.itemDisabled\n )}\n {...attributes}\n {...listeners}\n onPointerDown={dragHandle ? handlePointerDown : (listeners?.onPointerDown as PointerEventHandler<HTMLDivElement> | undefined)}\n >\n {children}\n </div>\n );\n}\n\nexport default KanbanItem;\n","import type { ReactNode } from 'react';\nimport { useDroppable } from '@dnd-kit/core';\nimport { SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport cx from 'classnames';\n\nimport type { KanbanColumnProps } from './kanbanBoard.types';\nimport styles from './kanbanBoard.module.pcss';\nimport KanbanItem from './KanbanItem';\n\n// Hoisted so these are referentially stable across renders — inline literals here would give\n// `useSortable` a new `data`/`disabled` object every render (every column re-renders on every\n// `dragOver` while a drag is in progress, via `shadowColumns`), which can spin dnd-kit's own\n// registration effect into a render loop that eventually trips React's \"Maximum update depth\n// exceeded\" guard. Same fix as the sensor options in `KanbanBoard.tsx`.\nconst COLUMN_SORTABLE_DATA = { type: 'column' };\nconst COLUMN_SORTABLE_DISABLED = { draggable: true, droppable: true };\n\ninterface KanbanColumnInternalProps<T> extends KanbanColumnProps {\n itemIds: string[];\n items: Record<string, T>;\n renderItem: (item: T, id: string) => ReactNode;\n dragHandle?: boolean;\n /**\n * Keep the column at its normal flex width even when `itemIds` is empty. Used while a drag\n * is in progress: the empty-column collapse is driven by transient shadow state during a\n * drag, and letting the column shrink mid-drag shifts every column's layout underneath the\n * pointer, which can flip the collision target back and forth forever.\n */\n preserveSizeWhileEmpty?: boolean;\n /** Shrink to a narrow strip when empty — see `KanbanBoardProps.collapseEmptyColumns`. Defaults to `true`. */\n collapseEmptyColumns?: boolean;\n /** Work-in-progress limit — see `KanbanColumnDef.maxItems`. Display-only. */\n maxItems?: number;\n /** Freezes the column — see `KanbanColumnDef.disabled`. */\n disabled?: boolean;\n /** Returns whether a specific card can't be picked up — see `KanbanBoardProps.getItemDisabled`. */\n getItemDisabled?: (item: T, id: string) => boolean;\n /** Custom content shown when the column has no cards — see `KanbanBoardProps.renderEmptyColumn`. */\n emptyPlaceholder?: ReactNode;\n /** Custom header actions — see `KanbanBoardProps.renderColumnActions`. */\n actions?: ReactNode;\n /** Allow the whole column to be dragged (by its header) to reorder it — see `KanbanBoardProps.reorderableColumns`. */\n reorderable?: boolean;\n /**\n * Whether the card currently being dragged (if any) is actually a column. Suppresses the\n * cards drop-target highlight, which otherwise lights up on every column a dragged column\n * passes over — that highlight means \"drop a card here\", which doesn't apply mid-column-drag.\n */\n activeIsColumn?: boolean;\n}\n\nfunction KanbanColumn<T>({\n id,\n title,\n itemIds,\n items,\n renderItem,\n dragHandle,\n preserveSizeWhileEmpty,\n collapseEmptyColumns = true,\n maxItems,\n disabled,\n getItemDisabled,\n emptyPlaceholder,\n actions,\n reorderable,\n activeIsColumn,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: KanbanColumnInternalProps<T>) {\n const droppableId = `column-${id}`;\n const { setNodeRef, isOver } = useDroppable({ id: droppableId, disabled });\n const isEmpty = collapseEmptyColumns && itemIds.length === 0 && !preserveSizeWhileEmpty;\n const isOverLimit = maxItems != null && itemIds.length > maxItems;\n\n const {\n attributes: columnAttributes,\n listeners: columnListeners,\n setNodeRef: setColumnNodeRef,\n transform: columnTransform,\n transition: columnTransition,\n isDragging: isColumnDragging,\n isOver: isColumnOver,\n } = useSortable({\n id,\n data: COLUMN_SORTABLE_DATA,\n disabled: reorderable ? false : COLUMN_SORTABLE_DISABLED,\n });\n\n return (\n <div\n {...rest}\n ref={setColumnNodeRef}\n id={id}\n className={cx(\n styles.column,\n isOver && !activeIsColumn && styles.columnOver,\n isColumnOver && styles.columnDropTarget,\n isEmpty && styles.columnEmpty,\n isOverLimit && styles.columnOverLimit,\n disabled && styles.columnDisabled,\n isColumnDragging && styles.columnDragging,\n className\n )}\n style={{ transform: CSS.Transform.toString(columnTransform), transition: columnTransition, ...style }}\n >\n <div\n className={cx(styles.columnHeader, reorderable && styles.columnHeaderReorderable, classNames?.header)}\n style={slotStyles?.header}\n {...(reorderable ? columnAttributes : undefined)}\n {...(reorderable ? columnListeners : undefined)}\n >\n <span className={styles.columnHeaderTitle}>{title}</span>\n <div className={styles.columnHeaderTrailing}>\n {maxItems != null && (\n <span\n className={cx(styles.columnHeaderCount, isOverLimit && styles.columnHeaderCountOver, classNames?.count)}\n style={slotStyles?.count}\n >\n {itemIds.length}/{maxItems}\n </span>\n )}\n {actions != null && (\n <div className={cx(styles.columnHeaderActions, classNames?.actions)} style={slotStyles?.actions}>\n {actions}\n </div>\n )}\n </div>\n </div>\n <SortableContext id={id} items={itemIds} strategy={verticalListSortingStrategy}>\n <div ref={setNodeRef} className={cx(styles.columnItems, classNames?.items)} style={slotStyles?.items}>\n {itemIds.length === 0 && emptyPlaceholder != null ? (\n <div className={cx(styles.columnPlaceholder, classNames?.placeholder)} style={slotStyles?.placeholder}>\n {emptyPlaceholder}\n </div>\n ) : null}\n {itemIds.map((itemId) => (\n <KanbanItem\n key={itemId}\n id={itemId}\n dragHandle={dragHandle}\n disabled={disabled || (items[itemId] !== undefined && (getItemDisabled?.(items[itemId], itemId) ?? false))}\n preventAsDropTarget={disabled}\n >\n {items[itemId] !== undefined ? renderItem(items[itemId], itemId) : null}\n </KanbanItem>\n ))}\n </div>\n </SortableContext>\n </div>\n );\n}\n\nexport default KanbanColumn;\n","import { arrayMove, hasSortableData } from '@dnd-kit/sortable';\nimport {\n closestCorners,\n KeyboardCode,\n type Announcements,\n type ClientRect,\n type CollisionDetection,\n type DroppableContainer,\n type KeyboardCoordinateGetter,\n type UniqueIdentifier,\n} from '@dnd-kit/core';\n\nimport type { KanbanColumnDef } from './kanbanBoard.types';\n\nexport function columnsEqual(a: KanbanColumnDef[], b: KanbanColumnDef[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((col, i) => {\n const other = b[i];\n return (\n col.id === other.id &&\n col.itemIds.length === other.itemIds.length &&\n col.itemIds.every((itemId, j) => itemId === other.itemIds[j])\n );\n });\n}\n\nexport function findColumnForItem(columns: KanbanColumnDef[], itemId: string): number {\n return columns.findIndex((col) => col.itemIds.includes(itemId));\n}\n\n/** Whether a drag's `active`/`over` participant is a whole column (vs. a card) — see `reorderableColumns`. */\nexport function isColumnDragData(data: unknown): boolean {\n return Boolean(data && typeof data === 'object' && (data as { type?: string }).type === 'column');\n}\n\n/**\n * Reorders whole columns: moves `activeColumnId` to `overColumnId`'s position. Returns the same\n * `columns` reference, unchanged, when either id doesn't resolve to a column or they're the same\n * — callers can use that to skip a state update.\n */\nexport function moveColumn(columns: KanbanColumnDef[], activeColumnId: string, overColumnId: string): KanbanColumnDef[] {\n const oldIndex = columns.findIndex((col) => col.id === activeColumnId);\n const overIndex = columns.findIndex((col) => col.id === overColumnId);\n if (oldIndex === -1 || overIndex === -1 || oldIndex === overIndex) return columns;\n\n return arrayMove(columns, oldIndex, overIndex);\n}\n\n/**\n * Collision detection for the board's shared `DndContext`, which has to pick between two very\n * differently-scaled sets of droppables at once: individual cards / a column's own card list\n * (small, numerous) and whole columns (large, few). Plain `closestCorners` weighs every\n * registered droppable together regardless of what's actually being dragged, so while dragging a\n * column it competes against every card and card-list droppable it happens to fly over too — the\n * column-level target only wins when the pointer lands somewhere that geometrically favors it,\n * which reads as needing to \"wiggle it around\" before the right drop target lights up. This\n * restricts the candidates to only the same kind as whatever is being dragged: a column drag only\n * considers other columns, a card drag only considers cards and card lists.\n */\nexport const kanbanCollisionDetection: CollisionDetection = (args) => {\n const draggingColumn = isColumnDragData(args.active.data.current);\n const droppableContainers = args.droppableContainers.filter((container) =>\n draggingColumn ? isColumnDragData(container.data.current) : !isColumnDragData(container.data.current)\n );\n\n return closestCorners({ ...args, droppableContainers });\n};\n\n/** Extracts the column id from a column droppable's `column-<id>` identifier, or `null` for a card id. */\nexport function resolveColumnDropId(overId: string): string | null {\n return overId.startsWith('column-') ? overId.slice('column-'.length) : null;\n}\n\nexport interface DragGeometry {\n /** The dragged card's current rect (translated by the drag delta), if measured. */\n activeRect: ClientRect | null;\n /** The rect of whatever `overId` refers to — a card, or a column's own droppable. */\n overRect: ClientRect;\n}\n\n/**\n * Computes the columns that result from dragging `activeItemId` over `overId` (a card id, or a\n * `column-<id>` droppable id for empty column space). Returns the same `columns` reference,\n * unchanged, when the drag doesn't resolve to a valid source/destination — callers can use that\n * to skip a state update.\n *\n * `geometry` resolves cross-column drops that land on a card or gap with more than one possible\n * position (see the two branches below for what each one decides).\n */\nexport function moveItem(\n columns: KanbanColumnDef[],\n activeItemId: string,\n overId: string,\n geometry: DragGeometry\n): KanbanColumnDef[] {\n // Only the source/destination column(s) actually change, so only those get new object/array\n // references — every other column keeps its exact `columns` reference. Cloning every column's\n // `itemIds` up front (as this used to) cost O(total cards across the whole board) on *every*\n // drag-over event, not just the couple of columns actually involved in the move.\n const sourceColIndex = findColumnForItem(columns, activeItemId);\n if (sourceColIndex === -1) return columns;\n\n const destColId = resolveColumnDropId(overId);\n const destColIndex =\n destColId !== null ? columns.findIndex((col) => col.id === destColId) : findColumnForItem(columns, overId);\n if (destColIndex === -1) return columns;\n\n if (sourceColIndex === destColIndex) {\n const col = columns[sourceColIndex];\n const oldIndex = col.itemIds.indexOf(activeItemId);\n if (oldIndex === -1) return columns;\n\n if (destColId !== null) {\n // over is the column's own droppable, not a card: nothing else claimed the collision,\n // which happens hovering the empty gap above/below the cards, or — critically — an edge\n // next to a disabled/pinned card with no other card nearby, since a disabled card's own\n // droppable is excluded from collision candidates entirely. Without this branch, that\n // case fell through to `col.itemIds.indexOf(overId)` below, which is always -1 for a\n // `column-<id>` id (it's not a card id), silently no-op-ing instead of reordering.\n const { activeRect, overRect } = geometry;\n const isBelowCenter = Boolean(\n activeRect && activeRect.top + activeRect.height / 2 > overRect.top + overRect.height / 2\n );\n const targetIndex = isBelowCenter ? col.itemIds.length - 1 : 0;\n if (targetIndex === oldIndex) return columns;\n\n const next = [...columns];\n next[sourceColIndex] = { ...col, itemIds: arrayMove(col.itemIds, oldIndex, targetIndex) };\n return next;\n }\n\n const newIndex = col.itemIds.indexOf(overId);\n if (newIndex === -1 || oldIndex === newIndex) return columns;\n\n const next = [...columns];\n next[sourceColIndex] = { ...col, itemIds: arrayMove(col.itemIds, oldIndex, newIndex) };\n return next;\n }\n\n const sourceCol = columns[sourceColIndex];\n const destCol = columns[destColIndex];\n const destItemIds = [...destCol.itemIds];\n const { activeRect, overRect } = geometry;\n\n let insertAt: number;\n if (destColId !== null) {\n // Hovering the column's own droppable directly, rather than a specific card: the empty gap\n // above the first card, the empty gap below the last card, or the whole area when the column\n // has no cards at all. Comparing centers against the *container's* full-height rect is a\n // coarse but reliable way to tell the top gap (insert at the start) from the bottom gap\n // (append at the end) — treating every container hover as \"append\" put a card dropped just\n // above the first item at the end of the column instead.\n const isBelowCenter = Boolean(\n activeRect && activeRect.top + activeRect.height / 2 > overRect.top + overRect.height / 2\n );\n insertAt = isBelowCenter ? destItemIds.length : 0;\n } else {\n const overIndex = destItemIds.indexOf(overId);\n\n // Only the last card's own drop zone extends past its bottom edge with nothing after it to\n // compete for the collision, so it's the one case where the dragged card can end up \"after\"\n // it. Requiring the dragged rect's *center* (not its top edge) to pass the hovered card's\n // bottom edge is deliberately more forgiving than requiring the whole dragged card to clear it\n // — that stricter version needs the user to drag a full card's height past the last item\n // before it registers, which in practice almost never happens before the drop, silently\n // landing the card second-to-last every time despite the live preview showing it last. A pure\n // center-to-center comparison is too lenient in the other direction: the dragged rect's center\n // still carries the grab offset from wherever in the source card it was originally picked up,\n // so a low enough grab point reads as \"past\" well before the drag is visually past the card at\n // all. Anchoring to the target's *bottom* edge (not its center) keeps that grab-offset problem\n // from creeping back in while still being achievable in a normal drag.\n const isLastItem = overIndex !== -1 && overIndex === destItemIds.length - 1;\n const hasClearedItem = Boolean(\n activeRect && activeRect.top + activeRect.height / 2 > overRect.top + overRect.height\n );\n insertAt = overIndex === -1 ? destItemIds.length : isLastItem && hasClearedItem ? overIndex + 1 : overIndex;\n }\n\n destItemIds.splice(insertAt, 0, activeItemId);\n\n const next = [...columns];\n next[sourceColIndex] = { ...sourceCol, itemIds: sourceCol.itemIds.filter((id) => id !== activeItemId) };\n next[destColIndex] = { ...destCol, itemIds: destItemIds };\n return next;\n}\n\n/**\n * Builds screen-reader drag announcements against the columns layout as currently understood\n * (the live shadow layout while a drag is in progress, or the settled `columns` prop otherwise).\n */\nexport function buildAnnouncements<T>(\n columns: KanbanColumnDef[],\n items: Record<string, T>,\n getItemLabel: (item: T, id: string) => string\n): Announcements {\n function labelFor(id: string): string {\n const item = items[id];\n return item !== undefined ? getItemLabel(item, id) : id;\n }\n\n function describeOver(overId: string): string {\n const destColId = resolveColumnDropId(overId);\n if (destColId !== null) {\n const col = columns.find((c) => c.id === destColId);\n return col ? `the ${col.title} column` : 'a column';\n }\n\n const col = columns.find((c) => c.itemIds.includes(overId));\n return col ? `${labelFor(overId)}, in the ${col.title} column` : labelFor(overId);\n }\n\n function columnTitle(id: string): string {\n return columns.find((c) => c.id === id)?.title ?? id;\n }\n\n return {\n onDragStart({ active }) {\n if (isColumnDragData(active.data.current)) return `Picked up column ${columnTitle(String(active.id))}.`;\n return `Picked up card ${labelFor(String(active.id))}.`;\n },\n onDragOver({ active, over }) {\n if (isColumnDragData(active.data.current)) {\n if (!over) return `Column ${columnTitle(String(active.id))} is no longer over a droppable area.`;\n return `Column ${columnTitle(String(active.id))} is over column ${columnTitle(String(over.id))}.`;\n }\n if (!over) return `Card ${labelFor(String(active.id))} is no longer over a droppable area.`;\n return `Card ${labelFor(String(active.id))} is over ${describeOver(String(over.id))}.`;\n },\n onDragEnd({ active, over }) {\n if (isColumnDragData(active.data.current)) {\n if (!over) return `Column ${columnTitle(String(active.id))} was dropped.`;\n return `Column ${columnTitle(String(active.id))} was dropped over column ${columnTitle(String(over.id))}.`;\n }\n if (!over) return `Card ${labelFor(String(active.id))} was dropped.`;\n return `Card ${labelFor(String(active.id))} was dropped over ${describeOver(String(over.id))}.`;\n },\n onDragCancel({ active }) {\n if (isColumnDragData(active.data.current)) {\n return `Dragging cancelled. Column ${columnTitle(String(active.id))} was returned to its original position.`;\n }\n return `Dragging cancelled. Card ${labelFor(String(active.id))} was returned to its original position.`;\n },\n };\n}\n\ninterface ContainerRect {\n container: DroppableContainer;\n rect: ClientRect;\n}\n\nfunction collectColumnItemRects(\n containers: DroppableContainer[],\n droppableRects: Map<UniqueIdentifier, ClientRect>,\n containerId: UniqueIdentifier\n): ContainerRect[] {\n const entries: ContainerRect[] = [];\n for (const container of containers) {\n if (!hasSortableData(container)) continue;\n if (container.data.current.sortable.containerId !== containerId) continue;\n const rect = droppableRects.get(container.id);\n if (!rect) continue;\n entries.push({ container, rect });\n }\n return entries.sort((a, b) => a.rect.top - b.rect.top);\n}\n\n/**\n * Custom keyboard coordinate getter for the board's multi-column, multi-`SortableContext`\n * layout. dnd-kit's default `sortableKeyboardCoordinates` picks the geometrically closest\n * droppable across the *entire* board — cards and column containers alike — which is unreliable\n * once cards live inside independent per-column `SortableContext`s: up/down and left/right end up\n * interchangeable depending on incidental rect positions. This instead restricts up/down to\n * reordering within the active card's own column, and left/right to moving into the adjacent\n * column (landing on the closest card there by vertical position, or the column itself when\n * empty). Requires each `KanbanColumn`'s `SortableContext` to be given an explicit `id` matching\n * its column id, so a card's `sortable.containerId` can be correlated with its `column-<id>`\n * droppable.\n */\nexport const kanbanKeyboardCoordinateGetter: KeyboardCoordinateGetter = (event, { context }) => {\n const { active, collisionRect, droppableRects, droppableContainers } = context;\n\n if (!active || !collisionRect || !hasSortableData(active)) return undefined;\n\n const isVertical = event.code === KeyboardCode.Down || event.code === KeyboardCode.Up;\n const isHorizontal = event.code === KeyboardCode.Left || event.code === KeyboardCode.Right;\n if (!isVertical && !isHorizontal) return undefined;\n\n event.preventDefault();\n\n const activeContainerId = active.data.current.sortable.containerId;\n const allContainers = droppableContainers.getEnabled();\n\n if (isColumnDragData(active.data.current)) {\n // Reordering a whole column: only left/right matters, moving it within the top-level\n // column `SortableContext` (siblings share its containerId, same as cards share their\n // own column's). Up/down has nothing to do — columns don't have a \"column above/below\".\n if (!isHorizontal) return undefined;\n\n const direction = event.code === KeyboardCode.Right ? 1 : -1;\n const siblings = collectColumnItemRects(allContainers, droppableRects, activeContainerId).sort(\n (a, b) => a.rect.left - b.rect.left\n );\n const currentIndex = siblings.findIndex((s) => s.container.id === active.id);\n if (currentIndex === -1) return undefined;\n\n const target = siblings[currentIndex + direction];\n if (!target) return undefined;\n\n return { x: target.rect.left, y: collisionRect.top };\n }\n\n if (isVertical) {\n const direction = event.code === KeyboardCode.Down ? 1 : -1;\n const siblings = collectColumnItemRects(allContainers, droppableRects, activeContainerId);\n const currentIndex = siblings.findIndex((s) => s.container.id === active.id);\n if (currentIndex === -1) return undefined;\n\n const target = siblings[currentIndex + direction];\n if (!target) return undefined;\n\n return { x: collisionRect.left, y: target.rect.top };\n }\n\n const direction = event.code === KeyboardCode.Right ? 1 : -1;\n\n const columns: ContainerRect[] = [];\n for (const container of allContainers) {\n const columnId = resolveColumnDropId(String(container.id));\n if (columnId === null) continue;\n const rect = droppableRects.get(container.id);\n if (!rect) continue;\n columns.push({ container, rect });\n }\n columns.sort((a, b) => a.rect.left - b.rect.left);\n\n const activeColumnIndex = columns.findIndex(\n (c) => resolveColumnDropId(String(c.container.id)) === activeContainerId\n );\n if (activeColumnIndex === -1) return undefined;\n\n const targetColumn = columns[activeColumnIndex + direction];\n if (!targetColumn) return undefined;\n\n const targetContainerId = resolveColumnDropId(String(targetColumn.container.id)) as UniqueIdentifier;\n const targetItems = collectColumnItemRects(allContainers, droppableRects, targetContainerId);\n\n let targetRect = targetColumn.rect;\n if (targetItems.length > 0) {\n targetRect = targetItems.reduce((closest, item) =>\n Math.abs(item.rect.top - collisionRect.top) < Math.abs(closest.rect.top - collisionRect.top) ? item : closest\n ).rect;\n }\n\n return { x: targetRect.left, y: targetRect.top };\n};\n","import { useMemo, useRef, useState } from 'react';\nimport {\n DndContext,\n DragOverlay,\n KeyboardSensor,\n MouseSensor,\n TouchSensor,\n useSensor,\n useSensors,\n type DragStartEvent,\n type DragOverEvent,\n type DragEndEvent,\n type ScreenReaderInstructions,\n} from '@dnd-kit/core';\nimport { SortableContext, horizontalListSortingStrategy } from '@dnd-kit/sortable';\nimport cx from 'classnames';\n\nimport type { KanbanBoardProps, KanbanColumnDef } from './kanbanBoard.types';\nimport styles from './kanbanBoard.module.pcss';\nimport KanbanColumn from './KanbanColumn';\nimport {\n buildAnnouncements,\n columnsEqual,\n isColumnDragData,\n kanbanCollisionDetection,\n kanbanKeyboardCoordinateGetter,\n moveColumn,\n moveItem,\n} from './kanbanBoard.utils';\n\nconst defaultGetItemLabel = <T,>(_item: T, id: string): string => id;\n\n// Hoisted so these are referentially stable across renders — inline literals here would give\n// `useSensor` a new options object every render (including every dragOver during an active\n// drag), which defeats its own memoization and makes `sensors` a new array each time too.\n//\n// Mouse and touch are split (rather than one combined `PointerSensor`) because they need\n// different activation constraints: a small movement threshold for mouse starts a drag\n// immediately without interfering with clicks, but the same threshold on a touchscreen would\n// hijack an ordinary scroll gesture as soon as the finger moves a few pixels. Touch instead\n// requires a brief press-and-hold before a drag arms, so a normal swipe-to-scroll passes through\n// untouched — the same pattern `VirtualList`'s `longPressDelay` uses.\nconst MOUSE_SENSOR_OPTIONS = { activationConstraint: { distance: 8 } };\nconst TOUCH_SENSOR_OPTIONS = { activationConstraint: { delay: 250, tolerance: 5 } };\nconst KEYBOARD_SENSOR_OPTIONS = { coordinateGetter: kanbanKeyboardCoordinateGetter };\n\nconst SCREEN_READER_INSTRUCTIONS: ScreenReaderInstructions = {\n draggable: `\n To pick up a card or column, press space or enter.\n While dragging, use the arrow keys to move it — for a card, between positions and columns;\n for a column, left/right to reorder it.\n Press space or enter again to drop it, or press escape to cancel.\n `,\n};\n\nfunction KanbanBoard<T = unknown>({\n columns,\n items,\n renderItem,\n onChange,\n dragHandle,\n getItemLabel = defaultGetItemLabel,\n getItemDisabled,\n renderEmptyColumn,\n renderColumnActions,\n reorderableColumns,\n collapseEmptyColumns,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: KanbanBoardProps<T>) {\n const [activeId, setActiveId] = useState<string | null>(null);\n const [activeIsColumn, setActiveIsColumn] = useState(false);\n const [shadowColumns, setShadowColumns] = useState<KanbanColumnDef[] | null>(null);\n\n // Guards against a self-sustaining reorder loop: applying a card move reflows the columns\n // involved, which can shift a *different* card under an otherwise-stationary pointer. dnd-kit\n // then re-fires `dragOver` with that new `over`, even though the user hasn't moved anything —\n // and if the geometry decision for that new target flips back once applied, the two states\n // (or more) can bounce forever, purely from our own layout changes, eventually tripping React's\n // \"Maximum update depth exceeded\" guard. `activeRect` only changes when the dragged card's own\n // position actually moves (real pointer/keyboard input), so it's used here as a proxy for \"did\n // anything the user did actually change\" — a reorder is only applied once per distinct\n // `activeRect`, which lets a drag settle and then holds still instead of oscillating.\n const lastAppliedActiveRectKeyRef = useRef<string | null>(null);\n\n const sensors = useSensors(\n useSensor(MouseSensor, MOUSE_SENSOR_OPTIONS),\n useSensor(TouchSensor, TOUCH_SENSOR_OPTIONS),\n useSensor(KeyboardSensor, KEYBOARD_SENSOR_OPTIONS)\n );\n\n const displayColumns = shadowColumns ?? columns;\n\n // `SortableContext` memoizes its own derived `items`/context value keyed on this array's\n // *reference*, not its contents — an inline `.map()` here would hand it a new array every\n // render (including every `dragOver` while a drag is in progress, via `shadowColumns`), forcing\n // every column's own `useSortable` to recompute and its whole subtree to re-render on every\n // board render, not just when the column order actually changes. Same class of bug as the\n // sensor options and the `data`/`disabled` objects in `KanbanColumn.tsx`/`KanbanItem.tsx`.\n const columnIds = useMemo(() => displayColumns.map((col) => col.id), [displayColumns]);\n\n const announcements = useMemo(\n () => buildAnnouncements(displayColumns, items, getItemLabel),\n [displayColumns, items, getItemLabel]\n );\n\n const accessibility = useMemo(\n () => ({ announcements, screenReaderInstructions: SCREEN_READER_INSTRUCTIONS }),\n [announcements]\n );\n\n function handleDragStart({ active }: DragStartEvent) {\n setActiveId(String(active.id));\n setActiveIsColumn(isColumnDragData(active.data.current));\n // `moveItem`/`moveColumn` never mutate what's passed in, only returning new objects/arrays\n // for the column(s) actually touched — so seeding the shadow state directly with `columns`\n // (rather than a full deep clone) is safe, and skips an O(total cards) clone on every drag.\n setShadowColumns(columns);\n lastAppliedActiveRectKeyRef.current = null;\n }\n\n function handleDragOver({ active, over }: DragOverEvent) {\n if (!over) return;\n\n if (isColumnDragData(active.data.current)) {\n const activeColumnId = String(active.id);\n const overColumnId = String(over.id);\n\n setShadowColumns((prev) => {\n const base = prev ?? columns;\n const next = moveColumn(base, activeColumnId, overColumnId);\n return next === base ? prev : next;\n });\n return;\n }\n\n const activeItemId = String(active.id);\n const overId = String(over.id);\n const activeRect = active.rect.current.translated ?? active.rect.current.initial;\n\n const activeRectKey = activeRect ? `${activeRect.top}:${activeRect.left}` : null;\n if (activeRectKey !== null && activeRectKey === lastAppliedActiveRectKeyRef.current) {\n return;\n }\n lastAppliedActiveRectKeyRef.current = activeRectKey;\n\n setShadowColumns((prev) => {\n const base = prev ?? columns;\n const next = moveItem(base, activeItemId, overId, { activeRect, overRect: over.rect });\n return next === base ? prev : next;\n });\n }\n\n function handleDragEnd({ over }: DragEndEvent) {\n setActiveId(null);\n setActiveIsColumn(false);\n\n if (!over || !shadowColumns) {\n setShadowColumns(null);\n return;\n }\n\n if (!columnsEqual(shadowColumns, columns)) {\n onChange(shadowColumns);\n }\n setShadowColumns(null);\n }\n\n function handleDragCancel() {\n setActiveId(null);\n setActiveIsColumn(false);\n setShadowColumns(null);\n }\n\n const activeColumn = activeId && activeIsColumn ? displayColumns.find((col) => col.id === activeId) : undefined;\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={kanbanCollisionDetection}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDragEnd={handleDragEnd}\n onDragCancel={handleDragCancel}\n accessibility={accessibility}\n >\n <SortableContext\n id=\"kanban-columns\"\n items={columnIds}\n strategy={horizontalListSortingStrategy}\n >\n <div {...rest} className={cx(styles.board, className)} style={style}>\n {displayColumns.map((col) => (\n <KanbanColumn\n key={col.id}\n id={col.id}\n title={col.title}\n itemIds={col.itemIds}\n maxItems={col.maxItems}\n disabled={col.disabled}\n getItemDisabled={getItemDisabled}\n emptyPlaceholder={renderEmptyColumn?.(col)}\n actions={renderColumnActions?.(col)}\n reorderable={reorderableColumns}\n activeIsColumn={activeId !== null && activeIsColumn}\n collapseEmptyColumns={collapseEmptyColumns}\n items={items}\n renderItem={renderItem}\n dragHandle={dragHandle}\n preserveSizeWhileEmpty={activeId !== null}\n />\n ))}\n </div>\n </SortableContext>\n <DragOverlay>\n {activeColumn ? (\n <div className={cx(styles.column, styles.columnDragOverlay)}>\n <div className={styles.columnHeader}>\n <span className={styles.columnHeaderTitle}>{activeColumn.title}</span>\n </div>\n </div>\n ) : activeId && !activeIsColumn && items[activeId] !== undefined ? (\n <div className={cx(styles.dragOverlay, classNames?.dragOverlay)} style={slotStyles?.dragOverlay}>{renderItem(items[activeId], activeId)}</div>\n ) : null}\n </DragOverlay>\n </DndContext>\n );\n}\n\nexport default KanbanBoard;\n","const BASE_URL = 'https://api.klipy.com/v2';\n\nexport interface KlipyMediaFormat {\n url: string;\n dims: [number, number];\n size: number;\n}\n\nexport interface KlipyResult {\n id: string;\n title: string;\n media_formats: {\n gif: KlipyMediaFormat;\n tinygif: KlipyMediaFormat;\n mediumgif: KlipyMediaFormat;\n mp4: KlipyMediaFormat;\n tinymp4: KlipyMediaFormat;\n };\n tags: string[];\n url: string;\n}\n\ninterface SearchOptions {\n limit?: number;\n contentfilter?: 'off' | 'low' | 'medium' | 'high';\n pos?: string;\n}\n\nexport default class KlipyService {\n private key: string;\n\n constructor(key: string) {\n this.key = key;\n }\n\n async search(\n query: string,\n options: SearchOptions = {},\n ): Promise<{ results: KlipyResult[]; next: string }> {\n const params = new URLSearchParams({ q: query, key: this.key });\n if (options.limit != null) params.set('limit', String(options.limit));\n if (options.contentfilter != null) params.set('contentfilter', options.contentfilter);\n if (options.pos != null) params.set('pos', options.pos);\n\n const res = await fetch(`${BASE_URL}/search?${params}`);\n return res.json();\n }\n\n async searchSuggestions(query: string): Promise<{ results: string[] }> {\n const params = new URLSearchParams({ q: query, key: this.key });\n const res = await fetch(`${BASE_URL}/search_suggestions?${params}`);\n return res.json();\n }\n\n registerShare(query: string, id: string): void {\n const params = new URLSearchParams({ id, q: query, key: this.key });\n fetch(`${BASE_URL}/registershare?${params}`).catch(() => null);\n }\n}\n",".resultCount {\n margin: 6px 0 0;\n font-size: 12px;\n color: var(--text-dark);\n}\n","import { useEffect, useRef, type ReactElement } from 'react';\nimport Input from 'components/common/input';\nimport { InputType } from 'components/common/input/input.types';\nimport styles from './searchInput.module.pcss';\nimport type { SearchInputProps } from './searchInput.types';\n\n\nexport default function SearchInput({\n value,\n onChange,\n onDebounce,\n placeholder,\n label,\n debounceMs = 500,\n totalAmount,\n showAmount = true,\n className,\n width,\n ...rest\n}: SearchInputProps): ReactElement {\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => () => {\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n }, []);\n\n function handleChange(val: unknown) {\n const str = val != null ? String(val) : '';\n const trimmed = str.trim() === '' ? '' : str;\n onChange(trimmed);\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => { onDebounce?.(trimmed); }, debounceMs);\n }\n\n const showCount = showAmount && typeof totalAmount === 'number' && !Number.isNaN(totalAmount);\n\n return (\n <div {...rest} className={className} style={width != null ? { width } : undefined}>\n <Input\n type={InputType.Search}\n label={label}\n placeholder={placeholder}\n value={value}\n onChange={handleChange}\n />\n {showCount && (\n <p className={styles.resultCount}>\n {totalAmount} {totalAmount === 1 ? 'result' : 'results'}\n </p>\n )}\n </div>\n );\n}\n","\n.gifPreview {\n width: min(420px, 90vw);\n aspect-ratio: 1;\n display: flex;\n flex-wrap: wrap;\n overflow: hidden;\n --gif-preview-gap-size: 5px;\n gap: var(--gif-preview-gap-size);\n position: relative;\n justify-content: center;\n overflow: auto;\n\n &-image {\n background-position: center;\n background-size: cover;\n width: 100%;\n height: 100%;\n\n &-container {\n width: min(140px, 33.3%);\n aspect-ratio: 1;\n background: linear-gradient(\n 45deg,\n var(--primary-color) 10%,\n var(--primary-lighter),\n var(--primary-accent),\n var(--primary-color) 85%\n );\n background-size: 500% 500%;\n animation: gradientBottomLeftToTopRight 1s infinite linear;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n width: min(\n calc(140px - var(--gif-preview-gap-size)),\n calc(33.3% - var(--gif-preview-gap-size))\n );\n }\n }\n}\n","import cx from 'classnames';\nimport type { ReactElement, UIEvent } from 'react';\nimport InteractableDiv from 'components/common/interactableDiv';\nimport type { GifPreviewProps } from './gifPreview.types';\nimport styles from './gifPreview.module.pcss';\n\nexport default function GifPreview({\n className,\n previewItems = [],\n onSelect,\n onLoadAdditional,\n}: GifPreviewProps): ReactElement {\n function handleScroll(event: UIEvent<HTMLDivElement>) {\n const el = event.currentTarget;\n const loadAdditionalHeight = el.scrollHeight - el.clientHeight * 1.5;\n if (el.scrollTop >= loadAdditionalHeight) {\n onLoadAdditional?.();\n }\n }\n\n return (\n <>\n {previewItems.length > 0 && (\n <div className={cx(styles.gifPreview, className)} onScroll={handleScroll}>\n {previewItems.map((preview, index) => (\n <InteractableDiv\n key={`${preview.id}_${index}`}\n className={styles.gifPreviewImageContainer}\n onClick={() => onSelect?.(preview)}\n >\n <div\n className={styles.gifPreviewImage}\n style={{ backgroundImage: `url(${preview.media_formats.tinygif.url})` }}\n />\n </InteractableDiv>\n ))}\n </div>\n )}\n </>\n );\n}\n","\n.gifView {\n display: flex;\n justify-content: center;\n align-items: center;\n position: relative;\n\n img {\n max-width: 100%;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n }\n\n &-loading {\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n background: linear-gradient(\n 45deg,\n var(--primary-color) 10%,\n var(--primary-lighter),\n var(--primary-accent),\n var(--primary-color) 85%\n );\n background-size: 500% 500%;\n animation: gradientBottomLeftToTopRight 1s infinite linear;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n }\n}\n","import { useEffect, useState } from 'react';\nimport cx from 'classnames';\nimport type { ReactElement } from 'react';\nimport type { GifViewProps } from './gifView.types';\nimport styles from './gifView.module.pcss';\n\nexport default function GifView({ className, src = '' }: GifViewProps): ReactElement {\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n setIsLoading(true);\n }, [src]);\n\n return (\n <div className={cx(styles.gifView, className)}>\n <img className={styles.klipyPickerSelected} src={src} onLoad={() => setIsLoading(false)} />\n {isLoading && <div className={styles.gifViewLoading} />}\n </div>\n );\n}\n",".klipyPicker {\n &-selected {\n margin-top: 8px;\n }\n\n &-modal {\n &-content {\n display: flex;\n flex-flow: column;\n gap: var(--spacing-m);\n }\n }\n\n &-suggestions {\n &-container {\n max-width: 420px;\n }\n\n &-item {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n }\n}\n","import { useMemo, useState } from 'react';\nimport cx from 'classnames';\nimport type { ReactElement, ReactNode } from 'react';\nimport KlipyService from 'services/klipy';\nimport type { KlipyResult } from 'services/klipy';\nimport SearchInput from '../searchInput';\nimport GifPreview from './components/gifPreview';\nimport FloatingMenu from '../floatingMenu';\nimport Button, { ButtonStyleType } from '../button';\nimport Modal from '../modal';\nimport Chip, { ChipContainer } from '../chip';\nimport GifView from './components/gifView';\nimport type { KlipyPickerProps } from './klipyPicker.types';\nimport styles from './klipyPicker.module.pcss';\nimport actionButtonStyles from 'components/common/actionButtons/actionButtons.module.pcss';\nimport { Align } from '../floatingMenu/floatingMenu.types';\n\nexport default function KlipyPicker({\n className,\n token = '',\n isModal = false,\n onSelect = () => undefined,\n selected = null,\n}: KlipyPickerProps): ReactElement {\n const klipyService = useMemo(() => new KlipyService(token), [token]);\n\n const [searchText, setSearchText] = useState('');\n const [currentPreviews, setCurrentPreviews] = useState<KlipyResult[]>([]);\n const [currentSuggestions, setCurrentSuggestions] = useState<string[]>([]);\n const [lastNext, setLastNext] = useState<string | null>(null);\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n async function searchFor(query: string) {\n setSearchText(query);\n if (!query.trim()) {\n setCurrentPreviews([]);\n setCurrentSuggestions([]);\n setLastNext(null);\n return;\n }\n const [{ results: searchResults = [], next = null }, { results: suggestionResults = [] }] =\n await Promise.all([\n klipyService.search(query, { limit: 18, contentfilter: 'medium' }),\n klipyService.searchSuggestions(query),\n ]);\n setCurrentPreviews(searchResults);\n setLastNext(next);\n setCurrentSuggestions(suggestionResults);\n }\n\n async function handleLoadAdditional() {\n const { results: searchResults = [], next = null } = await klipyService.search(searchText, {\n limit: 36,\n pos: lastNext ?? undefined,\n contentfilter: 'medium',\n });\n setLastNext(next);\n setCurrentPreviews((prev) => [...prev, ...searchResults]);\n }\n\n async function handlePreviewSelect(preview: KlipyResult | null) {\n await onSelect(preview);\n setIsMenuOpen(false);\n if (preview) klipyService.registerShare(searchText, preview.id);\n }\n\n function renderSuggestions(): ReactNode {\n return (\n <ChipContainer inline className={styles.klipyPickerSuggestionsContainer}>\n {currentSuggestions.map((suggestion) => (\n <Chip\n className={styles.klipyPickerSuggestionsItem}\n key={suggestion}\n text={suggestion}\n onClick={() => searchFor(suggestion)}\n />\n ))}\n </ChipContainer>\n );\n }\n\n function renderPreviewPicker(): ReactNode {\n return (\n <GifPreview\n previewItems={currentPreviews}\n onSelect={handlePreviewSelect}\n onLoadAdditional={handleLoadAdditional}\n />\n );\n }\n\n function renderSearchInput(): ReactNode {\n return (\n <SearchInput\n label=\"Pick gif\"\n value={searchText}\n onDebounce={searchFor}\n onChange={setSearchText}\n />\n );\n }\n\n if (isModal) {\n return (\n <div className={cx(styles.klipyPicker, className)}>\n <div className={actionButtonStyles.actionButtons}>\n <Button onClick={() => setIsMenuOpen(true)}>Pick gif</Button>\n {selected && (\n <Button styleType={ButtonStyleType.Delete} onClick={() => handlePreviewSelect(null)}>\n Remove gif\n </Button>\n )}\n </div>\n {selected && <GifView className={styles.klipyPickerSelected} src={selected} />}\n <Modal isOpen={isMenuOpen} onClose={() => setIsMenuOpen(false)}>\n <div className={styles.klipyPickerModalContent}>\n {renderSearchInput()}\n {renderSuggestions()}\n {renderPreviewPicker()}\n </div>\n </Modal>\n </div>\n );\n }\n\n return (\n <div className={cx(styles.klipyPicker, className)}>\n <FloatingMenu\n align={Align.Left}\n isOpen={currentPreviews.length > 0 && isMenuOpen}\n onOpenChange={setIsMenuOpen}\n dontCloseOnChildClick\n content={\n <>\n {renderSuggestions()}\n {renderPreviewPicker()}\n </>\n }\n >\n {renderSearchInput()}\n </FloatingMenu>\n {selected && (\n <Button styleType={ButtonStyleType.Delete} onClick={() => handlePreviewSelect(null)}>\n Remove gif\n </Button>\n )}\n {selected && <GifView className={styles.klipyPickerSelected} src={selected} />}\n </div>\n );\n}\n",".iconLoading {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 100%;\n position: absolute;\n left: 0;\n top: 0;\n user-select: none;\n pointer-events: none;\n\n --draw-duration: 0.8s;\n --delay: 0.4s;\n\n svg {\n stroke-dasharray: 14;\n stroke-dashoffset: 14;\n width: 200px;\n aspect-ratio: 1;\n animation: calc(var(--draw-duration) * 3) spin-to-oblivion var(--delay) infinite;\n transform: rotate(0deg);\n stroke: var(--primary-color);\n stroke-linecap: round;\n }\n\n &-first {\n animation: calc(var(--draw-duration) * 3) draw-line var(--delay) infinite;\n }\n\n &-second {\n animation: calc(var(--draw-duration) * 3) draw-line-two var(--delay) infinite;\n }\n\n @keyframes draw-line {\n 33% {\n stroke-dashoffset: 0;\n }\n 95% {\n stroke-dashoffset: 0;\n }\n 96% {\n stroke-dashoffset: 14;\n }\n }\n\n @keyframes draw-line-two {\n 33% {\n stroke-dashoffset: 14;\n }\n 66% {\n stroke-dashoffset: 0;\n }\n 95% {\n stroke-dashoffset: 0;\n }\n 96% {\n stroke-dashoffset: 14;\n }\n }\n\n @keyframes spin-to-oblivion {\n 50% {\n transform: rotate(180deg);\n }\n 75% {\n transform: rotate(180deg) scale(0);\n }\n 100% {\n transform: rotate(180deg) scale(0);\n }\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\n\nimport styles from './iconLoading.module.pcss';\n\nfunction IconLoading({ className = '' }) {\n return (\n <div className={cx(styles.iconLoading, className)}>\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-8 -1 16 14\">\n <path\n className={styles.iconLoadingFirst}\n d=\"M 0 0 C 3 5 6 5 6 12\"\n strokeWidth=\"1.7\"\n fill=\"none\"\n />\n <path\n className={styles.iconLoadingFirst}\n d=\"M 0 0 C -3 5 -6 5 -6 12\"\n strokeWidth=\"1.7\"\n fill=\"none\"\n />\n <path className={styles.iconLoadingFirst} d=\"M 0 0 L 0 10\" strokeWidth=\"1.7\" fill=\"none\" />\n <path\n className={styles.iconLoadingSecond}\n d=\"M 0.1 10 C -3 10 -4 10 -6 12\"\n strokeWidth=\"1.7\"\n fill=\"none\"\n />\n <path\n className={styles.iconLoadingSecond}\n d=\"M -0.1 10 C 3 10 4 10 6 12\"\n strokeWidth=\"1.7\"\n fill=\"none\"\n />\n </svg>\n </div>\n );\n}\n\nexport default IconLoading;\n","import IconLoading from './iconLoading.js';\n\nexport default IconLoading;\n",".numberInput {}\n\n.arrows {\n display: flex;\n flex-direction: column;\n align-self: stretch;\n border-left: 1px solid var(--border-color);\n margin: 4px 0;\n}\n\n.arrowBtn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n color: var(--text-dark);\n padding: 0 6px;\n font-size: 0.55rem;\n line-height: 1;\n transition: color 0.15s, background 0.15s;\n\n &:hover {\n color: var(--primary-color);\n background: var(--background-accent-light);\n }\n\n &:active {\n color: var(--primary-lighter);\n }\n}\n","import type { ReactElement } from 'react';\nimport React from 'react';\nimport cx from 'classnames';\nimport { NumericFormat, NumericFormatProps } from 'react-number-format';\nimport type { FormValidator } from 'services/formValidation';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './numberInput.module.pcss';\nimport Input from '../input';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults } from '../configProvider';\n\nexport interface NumberInputProps\n extends Omit<NumericFormatProps, 'onValueChange' | 'value' | 'customInput' | 'onChange' | 'step' | 'onKeyDown'> {\n value?: number | string;\n onChange?: (value: number | undefined) => void;\n formValidator?: FormValidator | null;\n label?: string;\n error?: string;\n className?: string;\n allowNegative?: boolean;\n decimalSeparator?: string;\n thousandSeparator?: string | boolean;\n prefix?: string;\n suffix?: string;\n decimalScale?: number;\n /**\n * Whether to pad the value to exactly `decimalScale` decimals. Default `true`\n * (e.g. with `decimalScale={2}`, `12` displays as `12.00`). Set `false` to make\n * `decimalScale` an upper limit only — the user may type fewer decimals and they\n * are kept as-is (`12` stays `12`, `12.1` stays `12.1`), while anything beyond\n * `decimalScale` is still truncated.\n */\n fixedDecimalScale?: boolean;\n placeholder?: string;\n sign?: '+' | '-';\n showArrows?: boolean;\n step?: number;\n readOnly?: boolean;\n onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n}\n\nfunction NumberInput(props: NumberInputProps): ReactElement {\n const {\n value,\n onChange,\n formValidator,\n label,\n error,\n className,\n allowNegative = false,\n decimalSeparator,\n thousandSeparator,\n prefix,\n suffix,\n decimalScale,\n fixedDecimalScale = true,\n placeholder,\n sign,\n showArrows = false,\n step = 1,\n readOnly = false,\n onKeyDown: onKeyDownProp,\n ...rest\n } = useComponentDefaults('NumberInput', props);\n const rawValue = formValidator != null ? formValidator.value as number | string : value;\n // When a sign is forced, display the absolute value — the prefix character carries the sign visually.\n const displayValue = sign != null && rawValue != null ? Math.abs(Number(rawValue)) : rawValue;\n const controlledValue = displayValue != null ? String(displayValue) : '';\n\n function handleValueChange(floatValue: number | undefined) {\n let out = floatValue;\n if (out !== undefined) {\n if (sign === '-') out = -Math.abs(out);\n if (sign === '+') out = Math.abs(out);\n }\n if (formValidator != null) formValidator.set(out ?? null);\n onChange?.(out);\n }\n\n function handleStep(delta: number) {\n if (readOnly) return;\n const current = rawValue != null && rawValue !== '' ? Number(rawValue) : 0;\n let next = current + delta;\n if (!allowNegative && sign !== '-') next = Math.max(0, next);\n if (sign === '-') next = Math.min(0, next);\n handleValueChange(next);\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if (readOnly) { onKeyDownProp?.(e); return; }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n handleStep(e.shiftKey ? step * 10 : step);\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n handleStep(e.shiftKey ? -step * 10 : -step);\n return;\n }\n onKeyDownProp?.(e);\n }\n\n const resolvedPrefix = sign === '-' ? '-' : sign === '+' ? '+' : prefix;\n\n const arrowSuffix = showArrows && !readOnly ? (\n <div className={styles.arrows}>\n <InteractableDiv\n className={styles.arrowBtn}\n tabIndex={-1}\n onMouseDown={(e) => { e.preventDefault(); handleStep(e.shiftKey ? step * 10 : step); }}\n >\n <FontAwesomeIcon icon={faChevronUp} />\n </InteractableDiv>\n <InteractableDiv\n className={styles.arrowBtn}\n tabIndex={-1}\n onMouseDown={(e) => { e.preventDefault(); handleStep(e.shiftKey ? -step * 10 : -step); }}\n >\n <FontAwesomeIcon icon={faChevronDown} />\n </InteractableDiv>\n </div>\n ) : null;\n\n return (\n <Input\n label={label}\n className={cx(styles.numberInput, className)}\n value={controlledValue}\n onChange={() => {}}\n formValidator={null}\n isValid={formValidator ? (formValidator.touched ? !formValidator.hasError() : true) : !error}\n errorMessage={formValidator ? (formValidator.getCurrentErrorMessage() ?? '') : (error ?? '')}\n placeholder={placeholder}\n readOnly={readOnly}\n suffix={arrowSuffix}\n inputMode={decimalScale === 0 ? 'numeric' : 'decimal'}\n customInput={\n <NumericFormat\n onValueChange={(vals) => handleValueChange(vals.floatValue)}\n allowNegative={sign != null ? false : allowNegative}\n decimalSeparator={decimalSeparator}\n thousandSeparator={thousandSeparator}\n decimalScale={decimalScale}\n fixedDecimalScale={fixedDecimalScale}\n prefix={resolvedPrefix}\n suffix={suffix}\n onKeyDown={showArrows ? handleKeyDown : onKeyDownProp}\n {...rest}\n />\n }\n />\n );\n}\n\nexport default NumberInput;\n","import NumberInput from './numberInput';\n\nexport default NumberInput;\n",".optionPicker{\n display: flex;\n width: 100%;\n gap: var(--spacing-m);\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n justify-content: space-around;\n position: relative;\n overflow: hidden;\n\n &-chip {\n position: absolute;\n height: 100%;\n top: 0;\n left: 0;\n background: var(--primary-color);\n border-radius: var(--default-border-radius);\n transition: left 0.25s ease-in-out, width 0.25s ease-in-out;\n }\n\n &-option {\n position: relative;\n width: 100%;\n height: 100%;\n display: block;\n text-align: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: var(--spacing-m);\n overflow: hidden;\n text-overflow: ellipsis;\n border-radius: var(--default-border-radius);\n transition: color 0.25s;\n\n &:focus {\n outline: var(--primary-color) solid 2px;\n outline-offset: -2px;\n }\n\n &-active {\n color: var(--text-on-primary);\n }\n }\n}\n","import type { ReactElement } from 'react';\nimport { OptionPickerProps } from './optionPicker.types';\nimport cx from 'classnames';\n\nimport styles from './optionPicker.module.pcss';\nimport InteractableDiv from '../interactableDiv';\n\n\nfunction OptionPicker({\n className = undefined,\n options,\n onChange,\n value,\n ...rest\n}: OptionPickerProps): ReactElement {\n const optionPickerLeft = options.findIndex((option) => option.key === value) * 100 / options.length;\n\n return (\n <div {...rest} className={cx(styles.optionPicker, className)}>\n <div className={styles.optionPickerChip} style={{ left: `${optionPickerLeft}%`, width: `${100 / options.length}%` }} />\n {options.map((option) => (\n <InteractableDiv\n onClick={(e) => onChange(option.key, e)}\n key={option.key}\n className={cx(\n styles.optionPickerOption,\n option.key === value && styles.optionPickerOptionActive\n )}\n tabIndex={option.key === value ? -1 : 0}\n >\n {option.label}\n </InteractableDiv>\n ))}\n </div>\n );\n}\n\nexport default OptionPicker;\n","import { useState, useEffect } from 'react';\n\nconst MOBILE_BREAKPOINT = 768;\n\nexport interface WindowSize {\n width: number;\n height: number;\n isMobileSize: boolean;\n}\n\nexport default function useWindowSize(): WindowSize {\n const [size, setSize] = useState<WindowSize>(() => ({\n width: window.innerWidth,\n height: window.innerHeight,\n isMobileSize: window.innerWidth < MOBILE_BREAKPOINT,\n }));\n\n useEffect(() => {\n function onResize() {\n setSize({\n width: window.innerWidth,\n height: window.innerHeight,\n isMobileSize: window.innerWidth < MOBILE_BREAKPOINT,\n });\n }\n window.addEventListener('resize', onResize);\n return () => window.removeEventListener('resize', onResize);\n }, []);\n\n return size;\n}\n",".overscroll {\n height: 100vh;\n overflow: auto;\n -ms-overflow-style: none; /* IE and Edge */\n scrollbar-width: none; /* Firefox */\n\n &::-webkit-scrollbar {\n display: none;\n }\n\n &-header {\n position: absolute;\n bottom: 0;\n width: 100%;\n\n &-centered {\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n &-container {\n position: relative;\n }\n }\n}\n","import { useRef, useEffect, useCallback } from 'react';\nimport cx from 'classnames';\nimport type { UIEvent } from 'react';\nimport useWindowSize from '../../hooks/useWindowSize';\nimport styles from './overscroll.module.pcss';\nimport type { OverscrollProps } from './overscroll.types';\n\nexport default function Overscroll({\n children = null,\n overscrollContent = null,\n overscrollContentDesktop = null,\n centerHeader = true,\n min = 10,\n max = 80,\n start = 30,\n unit = '%',\n mobileOnly = true,\n onScrollChange = () => {},\n scrollDisabled = false,\n}: OverscrollProps) {\n const { isMobileSize, height } = useWindowSize();\n\n const overscrollRef = useRef<HTMLDivElement>(null);\n const overscrollHeaderRef = useRef<HTMLDivElement>(null);\n const overscrollHeaderContainerRef = useRef<HTMLDivElement>(null);\n const isScrollingRef = useRef(false);\n const scrollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const onScrollChangeRef = useRef(onScrollChange);\n onScrollChangeRef.current = onScrollChange;\n\n const updateHeaderHeight = useCallback(\n (scrollTop: number) => {\n let h: number;\n if (unit === '%') {\n if (!overscrollHeaderContainerRef.current) return;\n const containerH = overscrollHeaderContainerRef.current.clientHeight;\n h = Math.max((containerH * min) / 100, containerH - scrollTop);\n } else {\n h = Math.max(min, max - scrollTop);\n }\n if (overscrollHeaderRef.current) {\n overscrollHeaderRef.current.style.height = `${h}px`;\n }\n },\n [min, max, unit],\n );\n\n const scrollToInitialPosition = useCallback(() => {\n let toScroll: number;\n if (unit === '%') {\n if (!overscrollHeaderContainerRef.current) return;\n const hundredPerc = (overscrollHeaderContainerRef.current.clientHeight / max) * 100;\n toScroll =\n overscrollHeaderContainerRef.current.clientHeight - hundredPerc * (start / 100);\n } else {\n toScroll = max - start;\n }\n if (overscrollRef.current) {\n overscrollRef.current.scrollTop = toScroll;\n updateHeaderHeight(toScroll);\n }\n }, [max, start, unit, updateHeaderHeight]);\n\n // Initial scroll position on mount (and if scroll-related props change)\n useEffect(() => {\n const id = setTimeout(scrollToInitialPosition, 100);\n return () => clearTimeout(id);\n }, [scrollToInitialPosition]);\n\n // Toggle overflow when scrollDisabled changes\n useEffect(() => {\n if (overscrollRef.current) {\n overscrollRef.current.style.overflow = scrollDisabled ? 'hidden' : 'auto';\n }\n }, [scrollDisabled]);\n\n // Scroll to initial position when entering mobile view\n const prevIsMobileRef = useRef(isMobileSize);\n useEffect(() => {\n if (isMobileSize && !prevIsMobileRef.current) scrollToInitialPosition();\n prevIsMobileRef.current = isMobileSize;\n }, [isMobileSize, scrollToInitialPosition]);\n\n // Scroll to initial position when mobileOnly is turned off (full overscroll DOM just mounted)\n const prevMobileOnlyRef = useRef(mobileOnly);\n useEffect(() => {\n if (!mobileOnly && prevMobileOnlyRef.current) scrollToInitialPosition();\n prevMobileOnlyRef.current = mobileOnly;\n }, [mobileOnly, scrollToInitialPosition]);\n\n // Update header height on window resize while in mobile view\n const prevHeightRef = useRef(height);\n useEffect(() => {\n if (isMobileSize && height !== prevHeightRef.current && overscrollRef.current) {\n updateHeaderHeight(overscrollRef.current.scrollTop);\n }\n prevHeightRef.current = height;\n }, [height, isMobileSize, updateHeaderHeight]);\n\n function handleScroll(e: UIEvent<HTMLDivElement>) {\n updateHeaderHeight(e.currentTarget.scrollTop);\n if (!isScrollingRef.current) {\n isScrollingRef.current = true;\n onScrollChangeRef.current(true);\n }\n if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);\n scrollTimeoutRef.current = setTimeout(() => {\n scrollTimeoutRef.current = null;\n isScrollingRef.current = false;\n onScrollChangeRef.current(false);\n }, 500);\n }\n\n if (mobileOnly && !isMobileSize) {\n if (overscrollContentDesktop) return <div>{overscrollContentDesktop}{children}</div>;\n return <>{children}</>;\n }\n\n const contentMinHeight = unit === '%' ? `${100 - min}%` : `calc(100% - ${min}px)`;\n\n return (\n <div className={styles.overscroll} ref={overscrollRef} onScroll={handleScroll}>\n <div\n className={styles.overscrollHeaderContainer}\n style={{ height: `${max}${unit}` }}\n ref={overscrollHeaderContainerRef}\n >\n <div\n className={cx(styles.overscrollHeader, centerHeader && styles.overscrollHeaderCentered)}\n ref={overscrollHeaderRef}\n >\n {overscrollContent}\n </div>\n </div>\n <div style={{ minHeight: contentMinHeight }}>{children}</div>\n </div>\n );\n}\n",".popover {\n position: relative;\n display: inline-flex;\n\n &-trigger {\n display: inline-flex;\n }\n\n &-floating {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 1000;\n /* Hidden until usePopoverPosition writes the first coordinates, to avoid a top-left flash. */\n visibility: hidden;\n }\n\n &-panel {\n position: relative;\n /* Above the arrow so the panel background hides the arrow's inner half — only the\n tip pokes out past the panel edge. */\n z-index: 1;\n color: var(--text-color);\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n border-radius: calc(var(--default-border-radius) + 4px);\n padding: 12px 14px;\n max-width: min(320px, calc(100vw - 24px));\n animation: popoverIn 0.12s ease forwards;\n }\n\n &-arrow {\n position: absolute;\n width: 10px;\n height: 10px;\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n transform: rotate(45deg);\n }\n\n /* Arrow sits on the panel edge facing the trigger; --arrow-x / --arrow-y centre it on the trigger. */\n &-floating[data-placement='bottom'] &-arrow {\n top: -5px;\n left: var(--arrow-x, 50%);\n margin-left: -5px;\n }\n &-floating[data-placement='top'] &-arrow {\n bottom: -5px;\n left: var(--arrow-x, 50%);\n margin-left: -5px;\n }\n &-floating[data-placement='right'] &-arrow {\n left: -5px;\n top: var(--arrow-y, 50%);\n margin-top: -5px;\n }\n &-floating[data-placement='left'] &-arrow {\n right: -5px;\n top: var(--arrow-y, 50%);\n margin-top: -5px;\n }\n\n /* Grow from the edge nearest the trigger. */\n &-floating[data-placement='bottom'] &-panel { transform-origin: top center; }\n &-floating[data-placement='top'] &-panel { transform-origin: bottom center; }\n &-floating[data-placement='right'] &-panel { transform-origin: center left; }\n &-floating[data-placement='left'] &-panel { transform-origin: center right; }\n\n @keyframes popoverIn {\n from {\n opacity: 0;\n transform: scale(0.94);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n}\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Preferred side of the trigger the panel opens on. Flips to the opposite side when there's no room. */\nexport enum PopoverPlacement {\n Top = 'top',\n Bottom = 'bottom',\n Left = 'left',\n Right = 'right',\n}\n\n/** Alignment along the trigger's cross axis (horizontal for top/bottom, vertical for left/right). */\nexport enum PopoverAlign {\n Start = 'start',\n Center = 'center',\n End = 'end',\n}\n\n/** What opens the popover. */\nexport enum PopoverTrigger {\n Click = 'click',\n Hover = 'hover',\n Focus = 'focus',\n}\n\nexport type PopoverSlots = 'root' | 'trigger' | 'floating' | 'panel' | 'arrow';\n\nexport interface PopoverProps extends HtmlProps {\n /** The trigger element. */\n children?: ReactNode;\n /** The popover body. */\n content?: ReactNode;\n /** Preferred side (default `Bottom`). */\n placement?: PopoverPlacement;\n /** Cross-axis alignment (default `Center`). */\n align?: PopoverAlign;\n /** What opens the popover (default `Click`). */\n trigger?: PopoverTrigger;\n /** Controlled open state. Omit for uncontrolled. */\n isOpen?: boolean;\n /** Initial open state when uncontrolled (default `false`). */\n defaultOpen?: boolean;\n /** Fires whenever the popover wants to open or close. */\n onOpenChange?: (isOpen: boolean) => void;\n /** Gap in px between trigger and panel (default `10`). */\n offset?: number;\n /** Render the arrow pointing at the trigger (default `true`). */\n withArrow?: boolean;\n /** Close when clicking outside the panel (default `true`). */\n closeOnOutsideClick?: boolean;\n /** Close when pressing Escape (default `true`). */\n closeOnEscape?: boolean;\n /** Delay in ms before a hover-triggered popover opens (default `100`). */\n openDelay?: number;\n /** Delay in ms before a hover-triggered popover closes (default `120`). */\n closeDelay?: number;\n /** Prevent the popover from opening. */\n disabled?: boolean;\n\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<PopoverSlots>;\n styles?: SlotStyles<PopoverSlots>;\n}\n","import { useLayoutEffect, type RefObject } from 'react';\nimport { getScrollableAncestors, isHiddenByAnyAncestor } from 'components/common/utils/scrollAncestors';\nimport { PopoverPlacement, PopoverAlign } from './popover.types';\n\ntype Axis = 'top' | 'bottom' | 'left' | 'right';\nconst OPPOSITE: Record<PopoverPlacement, Axis> = {\n [PopoverPlacement.Top]: 'bottom',\n [PopoverPlacement.Bottom]: 'top',\n [PopoverPlacement.Left]: 'right',\n [PopoverPlacement.Right]: 'left',\n};\n\nconst MARGIN = 8; // viewport gutter kept clear when shifting a panel back on-screen\n\nexport interface UsePopoverPositionArgs {\n isOpen: boolean;\n placement: PopoverPlacement;\n align: PopoverAlign;\n offset: number;\n triggerRef: RefObject<HTMLElement | null>;\n /** `position: fixed` wrapper that receives top/left/visibility and the resolved-placement data attribute. */\n floatingRef: RefObject<HTMLElement | null>;\n /** Visible panel, measured to decide flip and shift. */\n panelRef: RefObject<HTMLElement | null>;\n /** Arrow element; gets `--arrow-x` / `--arrow-y` written to it. Pass a null ref when `withArrow` is false. */\n arrowRef: RefObject<HTMLElement | null>;\n}\n\n/**\n * Positions a portaled, `position: fixed` popover on any of the four sides of its trigger with\n * start/center/end cross-axis alignment. Flips to the opposite side when the preferred one has no\n * room, shifts back on-screen along the cross axis, points the arrow at the trigger centre, and\n * hides (not closes) the panel once the trigger scrolls behind a clipping ancestor. Position is\n * written straight to the DOM via refs — going through setState lags the browser's scroll paint.\n */\nexport function usePopoverPosition({\n isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef,\n}: UsePopoverPositionArgs) {\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let rafId: number | undefined;\n let teardown: (() => void) | undefined;\n\n // The portal target (BodyEnd's #bodyEnd) can still be missing on the first commit, so the\n // floating ref lands one render later. Refs don't re-fire the effect, so retry each frame.\n function trySetup() {\n const trigger = triggerRef.current;\n const floating = floatingRef.current;\n const panel = panelRef.current;\n if (!trigger || !floating || !panel) {\n rafId = requestAnimationFrame(trySetup);\n return;\n }\n const ancestors = getScrollableAncestors(trigger);\n\n function updatePos() {\n const t = trigger!.getBoundingClientRect();\n const pw = panel!.offsetWidth;\n const ph = panel!.offsetHeight;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n // Resolve the main-axis side, flipping when the preferred side lacks room and the\n // opposite side has more.\n const room: Record<Axis, number> = {\n top: t.top,\n bottom: vh - t.bottom,\n left: t.left,\n right: vw - t.right,\n };\n const need = (placement === PopoverPlacement.Top || placement === PopoverPlacement.Bottom) ? ph : pw;\n let side: Axis = placement as unknown as Axis;\n const opp = OPPOSITE[placement];\n if (room[side] < need + offset && room[opp] > room[side]) side = opp;\n\n const vertical = side === 'top' || side === 'bottom';\n\n // Main axis: place the panel just outside the trigger on the resolved side.\n let top: number;\n let left: number;\n if (side === 'bottom') { top = t.bottom + offset; }\n else if (side === 'top') { top = t.top - offset - ph; }\n else if (side === 'right') { left = t.right + offset; }\n else { left = t.left - offset - pw; }\n\n // Cross axis: align start/center/end against the trigger, then shift on-screen.\n if (vertical) {\n if (align === PopoverAlign.Start) left = t.left;\n else if (align === PopoverAlign.End) left = t.right - pw;\n else left = t.left + t.width / 2 - pw / 2;\n left = Math.max(MARGIN, Math.min(left!, vw - pw - MARGIN));\n } else {\n if (align === PopoverAlign.Start) top = t.top;\n else if (align === PopoverAlign.End) top = t.bottom - ph;\n else top = t.top + t.height / 2 - ph / 2;\n top = Math.max(MARGIN, Math.min(top!, vh - ph - MARGIN));\n }\n\n floating!.style.top = `${top!}px`;\n floating!.style.left = `${left!}px`;\n floating!.style.visibility = isHiddenByAnyAncestor(t, ancestors) ? 'hidden' : 'visible';\n floating!.dataset.placement = side;\n\n // Arrow: centre it on the trigger along the cross axis, clamped inside the panel edges.\n const arrow = arrowRef.current;\n if (arrow) {\n const half = arrow.offsetWidth / 2 || 5;\n if (vertical) {\n const x = t.left + t.width / 2 - left!;\n arrow.style.setProperty('--arrow-x', `${Math.max(half + 2, Math.min(x, pw - half - 2))}px`);\n arrow.style.removeProperty('--arrow-y');\n } else {\n const y = t.top + t.height / 2 - top!;\n arrow.style.setProperty('--arrow-y', `${Math.max(half + 2, Math.min(y, ph - half - 2))}px`);\n arrow.style.removeProperty('--arrow-x');\n }\n }\n }\n\n updatePos();\n\n const scrollTargets: (Window | HTMLElement)[] = [window, ...ancestors];\n scrollTargets.forEach((tt) => tt.addEventListener('scroll', updatePos, { passive: true }));\n window.addEventListener('resize', updatePos);\n teardown = () => {\n scrollTargets.forEach((tt) => tt.removeEventListener('scroll', updatePos));\n window.removeEventListener('resize', updatePos);\n };\n }\n\n trySetup();\n\n return () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n teardown?.();\n };\n }, [isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef]);\n}\n","import { useRef, useEffect, useState, useCallback } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './popover.module.pcss';\nimport { usePopoverPosition } from './usePopoverPosition';\nimport { useFocusBoundary, tabbablesIn } from '../hooks/useFocusBoundary';\nimport { PopoverPlacement, PopoverAlign, PopoverTrigger, type PopoverProps } from './popover.types';\n\nfunction Popover({\n children = null,\n content = null,\n placement = PopoverPlacement.Bottom,\n align = PopoverAlign.Center,\n trigger = PopoverTrigger.Click,\n isOpen,\n defaultOpen = false,\n onOpenChange = () => {},\n offset = 10,\n withArrow = true,\n closeOnOutsideClick = true,\n closeOnEscape = true,\n openDelay = 100,\n closeDelay = 120,\n disabled = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: PopoverProps) {\n const triggerRef = useRef<HTMLDivElement>(null);\n const floatingRef = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const arrowRef = useRef<HTMLDivElement>(null);\n const hoverTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const isControlled = isOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = isControlled ? isOpen : internalOpen;\n\n // Keep the outside-click/Escape listeners pointed at the latest setter without re-subscribing.\n const onOpenChangeRef = useRef(onOpenChange);\n useEffect(() => { onOpenChangeRef.current = onOpenChange; });\n\n const setOpen = useCallback((next: boolean) => {\n if (disabled && next) return;\n if (!isControlled) setInternalOpen(next);\n onOpenChangeRef.current(next);\n }, [disabled, isControlled]);\n\n usePopoverPosition({\n isOpen: !!open,\n placement,\n align,\n offset,\n triggerRef,\n floatingRef,\n panelRef,\n arrowRef: withArrow ? arrowRef : { current: null },\n });\n\n const { restoreFocusToTrigger, focusAfterTrigger } = useFocusBoundary({\n triggerRef,\n contentRef: floatingRef,\n });\n\n // The panel is portaled to the end of the DOM, so Tab never flows into it naturally. When we\n // manage focus (click trigger + focusable content), move focus in on open and, on Tab out of\n // either end, close and continue focus as if the panel sat right after the trigger.\n useEffect(() => {\n if (!open || trigger !== PopoverTrigger.Click) return;\n const focusables = tabbablesIn(panelRef.current);\n if (focusables.length === 0) return;\n // Only claim the dialog role when we're actually managing focus for real content.\n floatingRef.current?.setAttribute('role', 'dialog');\n focusables[0].focus();\n }, [open, trigger]);\n\n function handleFloatingKeyDown(event: React.KeyboardEvent) {\n if (event.key !== 'Tab' || trigger !== PopoverTrigger.Click) return;\n const focusables = tabbablesIn(panelRef.current);\n if (focusables.length === 0) return;\n const active = document.activeElement;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusAfterTrigger();\n setOpen(false);\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n restoreFocusToTrigger();\n setOpen(false);\n }\n }\n\n // Outside click + Escape. Registered only while open and only for the relevant trigger mode.\n useEffect(() => {\n if (!open) return;\n\n function onMouseUp(event: MouseEvent) {\n const target = event.target as Node;\n const inPanel = floatingRef.current?.contains(target);\n const inTrigger = triggerRef.current?.contains(target);\n if (!inPanel && !inTrigger) setOpen(false);\n }\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== 'Escape') return;\n // Hand focus back to the trigger when it currently sits inside the panel.\n if (floatingRef.current?.contains(document.activeElement)) {\n (tabbablesIn(triggerRef.current)[0] ?? triggerRef.current)?.focus();\n }\n setOpen(false);\n }\n // Keyboard counterpart to the outside click: once focus leaves both the trigger\n // and the (portaled) panel — e.g. tabbing on to the next element — close.\n function onFocusIn(event: FocusEvent) {\n const target = event.target as Node;\n const inPanel = floatingRef.current?.contains(target);\n const inTrigger = triggerRef.current?.contains(target);\n if (!inPanel && !inTrigger) setOpen(false);\n }\n\n if (closeOnOutsideClick && trigger !== PopoverTrigger.Hover) {\n window.addEventListener('mouseup', onMouseUp);\n document.addEventListener('focusin', onFocusIn);\n }\n if (closeOnEscape) window.addEventListener('keydown', onKeyDown);\n return () => {\n window.removeEventListener('mouseup', onMouseUp);\n document.removeEventListener('focusin', onFocusIn);\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [open, closeOnOutsideClick, closeOnEscape, trigger, setOpen]);\n\n useEffect(() => () => clearTimeout(hoverTimer.current), []);\n\n function scheduleHover(next: boolean) {\n clearTimeout(hoverTimer.current);\n hoverTimer.current = setTimeout(() => setOpen(next), next ? openDelay : closeDelay);\n }\n\n const triggerHandlers =\n trigger === PopoverTrigger.Click\n ? { onClick: () => setOpen(!open) }\n : trigger === PopoverTrigger.Hover\n ? { onMouseEnter: () => scheduleHover(true), onMouseLeave: () => scheduleHover(false) }\n : { onFocus: () => setOpen(true), onBlur: () => setOpen(false) };\n\n const floatingHoverHandlers =\n trigger === PopoverTrigger.Hover\n ? { onMouseEnter: () => scheduleHover(true), onMouseLeave: () => scheduleHover(false) }\n : {};\n\n return (\n <div\n {...rest}\n className={cx(styles.popover, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div\n ref={triggerRef}\n className={cx(styles.popoverTrigger, classNames?.trigger)}\n style={slotStyles?.trigger}\n {...triggerHandlers}\n >\n {children}\n </div>\n {open && (\n <BodyEnd>\n <div\n ref={floatingRef}\n className={cx(styles.popoverFloating, classNames?.floating)}\n style={slotStyles?.floating}\n data-placement={placement}\n onKeyDown={handleFloatingKeyDown}\n {...floatingHoverHandlers}\n >\n <div\n ref={panelRef}\n className={cx(styles.popoverPanel, classNames?.panel)}\n style={slotStyles?.panel}\n >\n {content}\n </div>\n {withArrow && (\n <div\n ref={arrowRef}\n className={cx(styles.popoverArrow, classNames?.arrow)}\n style={slotStyles?.arrow}\n />\n )}\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n\nexport default Popover;\n",".progressBar{\n min-width: 100px;\n min-height: 10px;\n background-color: #e0e0e0;\n border-radius: var(--default-border-radius);\n overflow: hidden;\n display: flex;\n align-items: center;\n\n &-fill {\n height: stretch;\n background-color: var(--primary-color);\n width: 0;\n display: flex;\n align-items: center;\n overflow: hidden;\n transition: width .3s ease;\n\n &-end {\n border-radius: 0 var(--default-border-radius) var(--default-border-radius) 0;\n }\n }\n\n &-label {\n color: white;\n font-size: 12px;\n padding: 0 5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n &-custom {\n mix-blend-mode: difference;\n }\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { Progress, ProgressBarProps } from './progressBar.types';\n\nimport styles from './progressBar.module.pcss';\n\nexport function getContrastColor(hexColor: string): string {\n const hex = hexColor.replace('#', '');\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n \n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n return luminance > 0.5 ? '#000000' : '#ffffff';\n}\n\nfunction ProgressBar({\n className = undefined,\n total = 100,\n progress = 0,\n style = undefined,\n ...rest\n}: ProgressBarProps): ReactElement {\n\n function renderProgressBars() {\n const progressArray: Progress[] = [];\n\n if (Array.isArray(progress)) progressArray.push(...progress);\n else if (typeof progress === 'object') progressArray.push(progress);\n else progressArray.push({ amount: progress });\n\n return progressArray.map((prog, index) => {\n const widthPercentage = !total ? 0 : (prog.amount / total) * 100;\n\n return (\n <div\n key={index}\n className={cx(\n styles.progressBarFill,\n index === progressArray.length - 1 && styles.progressBarFillEnd,\n prog.class,\n )}\n style={{\n width: `${widthPercentage}%`,\n background: prog.color || undefined,\n ...(style || {}),\n }}\n title={prog.label ? `${prog.label}: ${prog.amount}` : undefined}\n >\n {prog.label && <div className={styles.progressBarLabel} style={prog.color ? { color: getContrastColor(prog.color) } : {}}>{prog.label}</div>}\n </div>\n );\n });\n }\n\n return (\n <div {...rest} className={cx(styles.progressBar, className)} style={style}>\n {renderProgressBars()}\n </div>\n );\n}\n\nexport default ProgressBar;\n","import type { CSSProperties, ReactNode } from 'react';\nimport type { FormValidator } from 'services/formValidation';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport type RadioValue = string | number;\n\nexport enum RadioGroupOrientation {\n Vertical = 'vertical',\n Horizontal = 'horizontal',\n}\n\nexport interface RadioOption {\n value: RadioValue;\n /** Visible label; falls back to `value` when omitted. */\n label?: ReactNode;\n /** Secondary description shown under the label. */\n description?: ReactNode;\n /** Disable just this option. */\n disabled?: boolean;\n}\n\nexport type RadioGroupSlots = 'root' | 'option' | 'radio' | 'dot' | 'label' | 'description';\n\nexport interface RadioGroupProps extends HtmlProps {\n /** The selectable options. */\n options: RadioOption[];\n /** Controlled selected value. Omit for uncontrolled. */\n value?: RadioValue;\n /** Initial value when uncontrolled. */\n defaultValue?: RadioValue;\n /** Fires with the newly selected value. */\n onChange?: (value: RadioValue, event?: React.MouseEvent | React.KeyboardEvent) => void;\n /** Layout direction (default `Vertical`). */\n orientation?: RadioGroupOrientation;\n /** Disable the whole group. */\n disabled?: boolean;\n /** Diameter of the radio circle (default `'18px'`). */\n size?: string;\n /** Tab index of the active (roving) option. */\n tabIndex?: number;\n formValidator?: FormValidator | null;\n /** Manual error message shown in a tooltip (used when there's no `formValidator`, or to force one). */\n errorMessage?: string;\n /** Manual valid state when not using a `formValidator` (default `true`). */\n isValid?: boolean;\n\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<RadioGroupSlots>;\n styles?: SlotStyles<RadioGroupSlots>;\n}\n",".radioGroup {\n --radio-size: 18px;\n user-select: none;\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: fit-content;\n\n &-horizontal {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 20px;\n }\n\n &-disabled {\n filter: brightness(0.85);\n cursor: not-allowed;\n }\n\n &-error &-radio:not(.radioGroup-radio-checked) {\n border-color: var(--error-color);\n }\n\n &-option {\n display: flex;\n align-items: flex-start;\n column-gap: 10px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n margin: -1px;\n color: var(--text-color);\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n\n &:focus-visible {\n outline: none;\n border-color: var(--primary-color);\n }\n\n &-disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n }\n\n &-radio {\n flex-shrink: 0;\n width: var(--radio-size);\n height: var(--radio-size);\n border-radius: 50%;\n border: 1.8px solid var(--border-color);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-top: 1px;\n transition: border-color 0.15s;\n\n &-checked {\n border-color: var(--primary-color);\n }\n }\n\n &-dot {\n width: calc(var(--radio-size) * 0.5);\n height: calc(var(--radio-size) * 0.5);\n border-radius: 50%;\n background-color: var(--primary-color);\n transform: scale(0);\n transition: transform 0.15s ease;\n\n &-checked {\n transform: scale(1);\n }\n }\n\n &-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n &-label {\n line-height: 1.2;\n color: var(--text-color);\n }\n\n &-description {\n font-size: 0.85em;\n line-height: 1.3;\n color: var(--text-dark);\n }\n}\n","import { useEffect, useRef, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport Tooltip from 'components/common/tooltip';\n\nimport { useComponentDefaults } from '../configProvider';\nimport { RadioGroupOrientation, type RadioGroupProps, type RadioValue } from './radioGroup.types';\nimport styles from './radioGroup.module.pcss';\n\nfunction RadioGroup(props: RadioGroupProps): ReactElement {\n const {\n options = [],\n value,\n defaultValue,\n onChange = () => {},\n orientation = RadioGroupOrientation.Vertical,\n disabled = false,\n size = '18px',\n tabIndex = 0,\n formValidator = null,\n errorMessage = '',\n isValid = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('RadioGroup', props);\n\n const optionRefs = useRef<(HTMLDivElement | null)[]>([]);\n const fvRef = useRef(formValidator);\n useEffect(() => { fvRef.current = formValidator; });\n const [, forceUpdate] = useState(0);\n const [internalValue, setInternalValue] = useState<RadioValue | undefined>(defaultValue);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n\n useEffect(() => {\n if (!formValidator) return;\n formValidator.validate();\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = formValidator\n ? formValidator.touched && formValidator.hasError()\n : !isValid || !!errorMessage;\n const errorText = formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || '';\n\n const isControlled = value !== undefined && !formValidator;\n const currentValue = (formValidator ? formValidator.value : isControlled ? value : internalValue) as\n | RadioValue\n | undefined;\n\n function select(next: RadioValue, event?: React.MouseEvent | React.KeyboardEvent) {\n if (formValidator) formValidator.set(next);\n else if (!isControlled) setInternalValue(next);\n onChange(next, event);\n }\n\n function handleBlur(event: React.FocusEvent<HTMLDivElement>) {\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) return;\n setIsFocused(false);\n if (fvRef.current) fvRef.current.touched = true;\n }\n\n const selectedIndex = options.findIndex((o) => o.value === currentValue);\n const firstEnabledIndex = options.findIndex((o) => !o.disabled);\n const rovingIndex = selectedIndex >= 0 ? selectedIndex : firstEnabledIndex;\n\n function focusOption(index: number) {\n optionRefs.current[index]?.focus();\n }\n\n function moveTo(step: 1 | -1, fromIndex: number, event: React.KeyboardEvent) {\n if (disabled || options.length === 0) return;\n let i = fromIndex;\n for (let count = 0; count < options.length; count++) {\n i = (i + step + options.length) % options.length;\n if (!options[i].disabled) {\n focusOption(i);\n select(options[i].value, event);\n return;\n }\n }\n }\n\n function handleKeyDown(event: React.KeyboardEvent, index: number) {\n const option = options[index];\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowRight':\n event.preventDefault();\n moveTo(1, index, event);\n break;\n case 'ArrowUp':\n case 'ArrowLeft':\n event.preventDefault();\n moveTo(-1, index, event);\n break;\n case ' ':\n case 'Enter':\n event.preventDefault();\n if (!disabled && !option.disabled) select(option.value, event);\n break;\n default:\n break;\n }\n }\n\n return (\n <div\n {...rest}\n role=\"radiogroup\"\n aria-orientation={orientation}\n aria-disabled={disabled || undefined}\n aria-invalid={hasError || undefined}\n className={cx(\n styles.radioGroup,\n orientation === RadioGroupOrientation.Horizontal && styles.radioGroupHorizontal,\n disabled && styles.radioGroupDisabled,\n hasError && styles.radioGroupError,\n className,\n classNames?.root,\n )}\n style={{ '--radio-size': size, ...style, ...slotStyles?.root } as React.CSSProperties}\n onFocus={() => setIsFocused(true)}\n onBlur={handleBlur}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {options.map((option, index) => {\n const checked = option.value === currentValue;\n const optionDisabled = disabled || !!option.disabled;\n return (\n <div\n key={String(option.value)}\n ref={(el) => { optionRefs.current[index] = el; }}\n role=\"radio\"\n aria-checked={checked}\n aria-disabled={optionDisabled || undefined}\n tabIndex={optionDisabled ? -1 : index === rovingIndex ? tabIndex : -1}\n className={cx(\n styles.radioGroupOption,\n checked && styles.radioGroupOptionChecked,\n optionDisabled && styles.radioGroupOptionDisabled,\n classNames?.option,\n )}\n style={slotStyles?.option}\n onClick={() => { if (!optionDisabled) select(option.value); }}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n <div\n className={cx(styles.radioGroupRadio, checked && styles.radioGroupRadioChecked, classNames?.radio)}\n style={slotStyles?.radio}\n >\n <div\n className={cx(styles.radioGroupDot, checked && styles.radioGroupDotChecked, classNames?.dot)}\n style={slotStyles?.dot}\n />\n </div>\n {(option.label ?? option.value) !== '' && (\n <div className={styles.radioGroupText}>\n <div className={cx(styles.radioGroupLabel, classNames?.label)} style={slotStyles?.label}>\n {option.label ?? option.value}\n </div>\n {option.description != null && (\n <div\n className={cx(styles.radioGroupDescription, classNames?.description)}\n style={slotStyles?.description}\n >\n {option.description}\n </div>\n )}\n </div>\n )}\n </div>\n );\n })}\n <Tooltip\n variant=\"error\"\n message={errorText}\n isVisible={hasError && (isFocused || isHovered)}\n />\n </div>\n );\n}\n\nexport default RadioGroup;\n",".rating {\n display: inline-flex;\n align-items: center;\n align-self: flex-start;\n width: fit-content;\n gap: 0.15em;\n font-size: 20px;\n outline: none;\n touch-action: pan-y;\n user-select: none;\n\n &:focus-visible {\n box-shadow: 0 0 0 2px var(--primary-lighter);\n border-radius: var(--default-border-radius);\n }\n\n &-disabled {\n opacity: 0.5;\n }\n\n &-disabled,\n &-readOnly {\n pointer-events: none;\n }\n\n &-item {\n position: relative;\n display: inline-flex;\n width: 1em;\n height: 1em;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-iconEmpty {\n width: 1em;\n height: 1em;\n color: var(--rating-empty-color, var(--background-accent-light));\n }\n\n &-iconFilledClip {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n overflow: hidden;\n pointer-events: none;\n }\n\n &-iconFilled {\n width: 1em;\n height: 1em;\n color: var(--rating-filled-color, var(--primary-color));\n }\n}\n","import { useRef, useState } from 'react';\nimport type { CSSProperties, ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faStar } from '@fortawesome/free-solid-svg-icons';\n\nimport { useComponentDefaults } from '../configProvider';\nimport type { RatingProps } from './rating.types';\n\nimport styles from './rating.module.pcss';\n\nconst DRAG_THRESHOLD = 4;\n\nfunction clampValue(value: number, max: number): number {\n return Math.max(0, Math.min(max, value));\n}\n\nfunction Rating(props: RatingProps): ReactElement {\n const {\n value: controlledValue,\n defaultValue = 0,\n onChange = () => {},\n max = 5,\n allowHalf = false,\n allowClear = true,\n readOnly = false,\n disabled = false,\n icon = faStar,\n 'aria-label': ariaLabel = 'Rating',\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Rating', props);\n\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState(defaultValue);\n const value = clampValue(isControlled ? controlledValue! : internalValue, max);\n\n const [hoverValue, setHoverValue] = useState<number | null>(null);\n const isInteractive = !readOnly && !disabled;\n const displayValue = hoverValue ?? value;\n\n const rootRef = useRef<HTMLDivElement>(null);\n const valueBeforeGestureRef = useRef(value);\n const draggingRef = useRef(false);\n const gestureStartXRef = useRef(0);\n const hasDraggedRef = useRef(false);\n\n function commit(nextValue: number) {\n const clamped = clampValue(nextValue, max);\n if (!isControlled) setInternalValue(clamped);\n onChange(clamped);\n }\n\n function getValueFromClientX(clientX: number): number | null {\n const rect = rootRef.current?.getBoundingClientRect();\n if (!rect || rect.width === 0) return null;\n const fraction = clampValue((clientX - rect.left) / rect.width, 1);\n const raw = fraction * max;\n return allowHalf ? Math.round(raw * 2) / 2 : Math.ceil(raw);\n }\n\n function handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n if (!isInteractive) return;\n event.currentTarget.setPointerCapture?.(event.pointerId);\n draggingRef.current = true;\n hasDraggedRef.current = false;\n gestureStartXRef.current = event.clientX;\n valueBeforeGestureRef.current = value;\n const next = getValueFromClientX(event.clientX);\n if (next !== null) setHoverValue(next);\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n if (!isInteractive) return;\n const next = getValueFromClientX(event.clientX);\n if (next === null) return;\n if (draggingRef.current) {\n event.preventDefault();\n if (Math.abs(event.clientX - gestureStartXRef.current) > DRAG_THRESHOLD) {\n hasDraggedRef.current = true;\n }\n }\n setHoverValue(next);\n }\n\n function handlePointerUp(event: React.PointerEvent<HTMLDivElement>) {\n if (!isInteractive || !draggingRef.current) return;\n event.currentTarget.releasePointerCapture?.(event.pointerId);\n draggingRef.current = false;\n const next = getValueFromClientX(event.clientX) ?? hoverValue;\n if (next !== null) {\n const isClick = !hasDraggedRef.current;\n commit(isClick && allowClear && next === valueBeforeGestureRef.current ? 0 : next);\n }\n setHoverValue(null);\n }\n\n function handlePointerLeave() {\n if (!isInteractive || draggingRef.current) return;\n setHoverValue(null);\n }\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n const step = allowHalf ? 0.5 : 1;\n if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {\n event.preventDefault();\n commit(value + step);\n } else if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {\n event.preventDefault();\n commit(value - step);\n } else if (event.key === 'Home') {\n event.preventDefault();\n commit(0);\n } else if (event.key === 'End') {\n event.preventDefault();\n commit(max);\n }\n }\n\n return (\n <div\n {...rest}\n ref={rootRef}\n role=\"slider\"\n aria-label={ariaLabel}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-valuetext={`${value} out of ${max}`}\n aria-readonly={readOnly || undefined}\n aria-disabled={disabled || undefined}\n tabIndex={isInteractive ? 0 : -1}\n className={cx(\n styles.rating,\n disabled && styles.ratingDisabled,\n readOnly && styles.ratingReadOnly,\n classNames?.root,\n className\n )}\n style={{ ...style, ...slotStyles?.root }}\n onKeyDown={isInteractive ? handleKeyDown : undefined}\n onPointerDown={isInteractive ? handlePointerDown : undefined}\n onPointerMove={isInteractive ? handlePointerMove : undefined}\n onPointerUp={isInteractive ? handlePointerUp : undefined}\n onPointerCancel={isInteractive ? handlePointerUp : undefined}\n onPointerLeave={isInteractive ? handlePointerLeave : undefined}\n >\n {Array.from({ length: max }, (_, index) => {\n const fillPercent = Math.round(Math.max(0, Math.min(1, displayValue - index)) * 100);\n\n return (\n <div key={index} className={cx(styles.ratingItem, classNames?.item)} style={slotStyles?.item}>\n <FontAwesomeIcon\n icon={icon}\n className={cx(styles.ratingIconEmpty, classNames?.iconEmpty)}\n style={slotStyles?.iconEmpty as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n <div className={styles.ratingIconFilledClip} style={{ width: `${fillPercent}%` }}>\n <FontAwesomeIcon\n icon={icon}\n className={cx(styles.ratingIconFilled, classNames?.iconFilled)}\n style={slotStyles?.iconFilled as CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport default Rating;\n","import type { Point, RoomData, DoorData } from './roomDrawer.types';\n\nexport const CANVAS_W = 400;\nexport const CANVAS_H = 300;\nexport const GRID = 5;\nexport const DOOR_WIDTH = 12;\nexport const CLOSE_THRESHOLD = 8; // px in SVG units to close a polygon\nexport const WALL_TOLERANCE = 8; // max distance to snap to a wall for door placement\n\n// ─── Coordinate helpers ────────────────────────────────────────────────────\n\nexport function snap(v: number): number {\n return Math.round(v / GRID) * GRID;\n}\n\nexport function snapPt(p: Point): Point {\n return { x: snap(p.x), y: snap(p.y) };\n}\n\nexport function clientToSVG(clientX: number, clientY: number, svg: SVGSVGElement): Point {\n const pt = svg.createSVGPoint();\n pt.x = clientX;\n pt.y = clientY;\n const m = svg.getScreenCTM();\n if (!m) return { x: 0, y: 0 };\n const raw = pt.matrixTransform(m.inverse());\n return snapPt({ x: raw.x, y: raw.y });\n}\n\n// ─── Geometry ──────────────────────────────────────────────────────────────\n\nexport function dist(a: Point, b: Point): number {\n return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);\n}\n\nexport function pointToSegment(p: Point, a: Point, b: Point): { dist: number; t: number } {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) return { dist: dist(p, a), t: 0 };\n const t = Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2));\n const px = a.x + t * dx;\n const py = a.y + t * dy;\n return { dist: Math.sqrt((p.x - px) ** 2 + (p.y - py) ** 2), t };\n}\n\nexport function nearestWall(pt: Point, rooms: RoomData[]): { roomId: string; wallIndex: number; t: number } | null {\n let best: { roomId: string; wallIndex: number; t: number; dist: number } | null = null;\n for (const room of rooms) {\n const pts = room.points;\n for (let i = 0; i < pts.length; i++) {\n const a = pts[i];\n const b = pts[(i + 1) % pts.length];\n const { dist: d, t } = pointToSegment(pt, a, b);\n if (d <= WALL_TOLERANCE && (!best || d < best.dist)) {\n best = { roomId: room.id, wallIndex: i, t, dist: d };\n }\n }\n }\n return best;\n}\n\nexport function pointInPolygon(pt: Point, poly: Point[]): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i].x, yi = poly[i].y;\n const xj = poly[j].x, yj = poly[j].y;\n if ((yi > pt.y) !== (yj > pt.y) && pt.x < ((xj - xi) * (pt.y - yi)) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}\n\nexport function centroid(pts: Point[]): Point {\n return {\n x: pts.reduce((s, p) => s + p.x, 0) / pts.length,\n y: pts.reduce((s, p) => s + p.y, 0) / pts.length,\n };\n}\n\nexport function rectToPoints(x: number, y: number, w: number, h: number): Point[] {\n return [\n { x, y },\n { x: x + w, y },\n { x: x + w, y: y + h },\n { x, y: y + h },\n ];\n}\n\n// Returns the two endpoints of the door opening and a perpendicular unit vector (for the swing arc).\nexport function doorEndpoints(\n a: Point,\n b: Point,\n t: number,\n width: number,\n): { p1: Point; p2: Point; perp: Point } | null {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n if (len < 0.001) return null;\n const nx = dx / len;\n const ny = dy / len;\n const cx = a.x + dx * t;\n const cy = a.y + dy * t;\n const hw = Math.min(width / 2, len / 2 - 0.001);\n return {\n p1: { x: cx - nx * hw, y: cy - ny * hw },\n p2: { x: cx + nx * hw, y: cy + ny * hw },\n perp: { x: -ny, y: nx },\n };\n}\n\n// ─── SVG export ────────────────────────────────────────────────────────────\n\nfunction escapeSVG(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\nfunction ptsToClosedPath(pts: Point[]): string {\n return pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(' ') + ' Z';\n}\n\n// Returns one path string per wall segment between door gaps.\n// 0 doors → [closed path] | N doors → N open paths\nexport function buildWallSegments(pts: Point[], wallDoors: DoorData[]): string[] {\n if (pts.length < 2) return [];\n\n if (wallDoors.length === 0) {\n return [pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(' ') + ' Z'];\n }\n\n const n = pts.length;\n const segments: string[][] = [];\n let current: string[] = [`M ${pts[0].x.toFixed(2)},${pts[0].y.toFixed(2)}`];\n\n for (let i = 0; i < n; i++) {\n const a = pts[i];\n const b = pts[(i + 1) % n];\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n const segs = wallDoors.filter((d) => d.wallIndex === i).sort((x, y) => x.t - y.t);\n\n if (segs.length === 0) {\n current.push(`L ${b.x.toFixed(2)},${b.y.toFixed(2)}`);\n } else {\n for (const door of segs) {\n const hw = door.width / 2;\n const t1 = Math.max(0, door.t - hw / len);\n const t2 = Math.min(1, door.t + hw / len);\n const gs = { x: a.x + dx * t1, y: a.y + dy * t1 };\n const ge = { x: a.x + dx * t2, y: a.y + dy * t2 };\n current.push(`L ${gs.x.toFixed(2)},${gs.y.toFixed(2)}`);\n segments.push(current);\n current = [`M ${ge.x.toFixed(2)},${ge.y.toFixed(2)}`];\n }\n current.push(`L ${b.x.toFixed(2)},${b.y.toFixed(2)}`);\n }\n }\n\n // Wrap-around: the last segment ends at pts[0] where segments[0] started —\n // merge them so each segment is one continuous open path.\n segments[0] = [...current, ...segments[0].slice(1)];\n\n return segments.map((s) => s.join(' '));\n}\n\nfunction buildDoorArcPath(a: Point, b: Point, door: DoorData): string {\n const ep = doorEndpoints(a, b, door.t, door.width);\n if (!ep) return '';\n const { p1, p2, perp } = ep;\n const swingEnd = { x: p1.x + perp.x * door.width, y: p1.y + perp.y * door.width };\n return [\n `M ${p1.x.toFixed(2)},${p1.y.toFixed(2)} L ${p2.x.toFixed(2)},${p2.y.toFixed(2)}`,\n `M ${p1.x.toFixed(2)},${p1.y.toFixed(2)} A ${door.width},${door.width} 0 0,1 ${swingEnd.x.toFixed(2)},${swingEnd.y.toFixed(2)}`,\n ].join(' ');\n}\n\nexport function generateSVG(rooms: RoomData[], doors: DoorData[]): string {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const r of rooms) {\n for (const p of r.points) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n }\n if (!isFinite(minX)) { minX = 0; minY = 0; maxX = CANVAS_W; maxY = CANVAS_H; }\n\n const pad = 5;\n const vb = [\n (minX - pad).toFixed(2),\n (minY - pad).toFixed(2),\n (maxX - minX + pad * 2).toFixed(2),\n (maxY - minY + pad * 2).toFixed(2),\n ].join(' ');\n\n const roomEls = rooms.map((room) => {\n const roomDoors = doors.filter((d) => d.roomId === room.id);\n const wallSegs = buildWallSegments(room.points, roomDoors);\n const bgPath = ptsToClosedPath(room.points);\n const c = centroid(room.points);\n\n const wallPaths = wallSegs.map((d) => ` <path d=\"${d}\" />`).join('\\n');\n\n const doorPaths = roomDoors\n .map((door) => {\n const a = room.points[door.wallIndex];\n const b = room.points[(door.wallIndex + 1) % room.points.length];\n const d = buildDoorArcPath(a, b, door);\n return d ? ` <path d=\"${d}\" fill=\"none\" />` : '';\n })\n .filter(Boolean)\n .join('\\n');\n\n const labelEl = room.name\n ? ` <text fontSize=\"5\" x=\"${c.x.toFixed(1)}\" y=\"${c.y.toFixed(1)}\">${escapeSVG(room.name)}</text>`\n : '';\n\n return [` <g id=\"${room.id}\">`, wallPaths, ` <path id=\"background\" d=\"${bgPath}\" />`, doorPaths, labelEl, ` </g>`]\n .filter(Boolean)\n .join('\\n');\n });\n\n return [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"${vb}\">`,\n ` <g id=\"layer1\">`,\n ...roomEls,\n ` </g>`,\n ` <use id=\"use\" href=\"\" />`,\n `</svg>`,\n ].join('\\n');\n}\n\n// ─── SVG import ────────────────────────────────────────────────────────────\n\nfunction parseClosedPath(d: string): Point[] {\n const points: Point[] = [];\n for (const m of d.matchAll(/[ML]\\s*([-\\d.]+)[,\\s]+([-\\d.]+)/gi)) {\n points.push({ x: parseFloat(m[1]), y: parseFloat(m[2]) });\n }\n return points;\n}\n\nexport function parseSVGRooms(svgString: string): RoomData[] {\n const doc = new DOMParser().parseFromString(svgString, 'image/svg+xml');\n const rooms: RoomData[] = [];\n doc.querySelectorAll('[id^=\"room\"]').forEach((group) => {\n const bg = group.querySelector('[id=\"background\"]');\n if (!bg) return;\n const d = bg.getAttribute('d');\n if (!d) return;\n const points = parseClosedPath(d);\n if (points.length < 3) return;\n const name = group.querySelector('text')?.textContent?.trim() ?? '';\n rooms.push({ id: group.id, name, points });\n });\n return rooms;\n}\n\nexport function downloadSVG(rooms: RoomData[], doors: DoorData[]): void {\n const svg = generateSVG(rooms, doors);\n const blob = new Blob([svg], { type: 'image/svg+xml' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'room-plan.svg';\n a.click();\n URL.revokeObjectURL(url);\n}\n",".roomDrawer {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n overflow: hidden;\n background: var(--background);\n user-select: none;\n\n &-toolbar {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 8px;\n background: var(--background-accent);\n border-bottom: 1px solid var(--border-color);\n\n &-sep {\n flex: 1;\n }\n\n &-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 13px;\n transition: background 0.12s, color 0.12s;\n\n &:hover:not(:disabled) {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n\n &-active {\n background: var(--primary-accent);\n color: var(--primary-color);\n border-color: var(--primary-lighter);\n }\n }\n\n &-zoomLabel {\n padding: 0 4px;\n min-width: 40px;\n height: 32px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 11px;\n text-align: center;\n\n &:hover {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n }\n }\n\n &-canvas {\n display: block;\n width: 100%;\n cursor: crosshair;\n user-select: none;\n\n &-select {\n cursor: default;\n }\n }\n\n &-info {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n background: var(--background-accent);\n border-top: 1px solid var(--border-color);\n\n &-label {\n font-size: 12px;\n color: var(--text-dark);\n white-space: nowrap;\n }\n\n &-input {\n flex: 1;\n max-width: 220px;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: var(--background);\n color: var(--text-color);\n font-size: 13px;\n\n &:focus {\n outline: none;\n border-color: var(--primary-color);\n }\n }\n\n &-spacer {\n flex: 1;\n }\n\n &-delete {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 12px;\n transition: background 0.12s, color 0.12s, border-color 0.12s;\n\n &:hover {\n background: #e53935;\n color: #fff;\n border-color: #e53935;\n }\n }\n }\n\n &-hint {\n padding: 4px 8px;\n font-size: 11px;\n color: var(--text-dark);\n background: var(--background-accent);\n border-top: 1px solid var(--border-color);\n }\n\n &-info {\n &-doorsBtn {\n display: flex;\n align-items: center;\n gap: 5px;\n height: 28px;\n padding: 0 8px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 12px;\n white-space: nowrap;\n transition: background 0.12s, color 0.12s;\n\n &:hover {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n }\n }\n\n &-doorPanel {\n display: flex;\n flex-direction: column;\n background: var(--background-accent);\n border-top: 1px solid var(--border-color);\n\n &-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-bottom: 1px solid var(--border-color);\n }\n\n &-icon {\n color: var(--text-dark);\n font-size: 12px;\n }\n\n &-title {\n flex: 1;\n font-size: 12px;\n color: var(--text-dark);\n }\n\n &-done {\n display: flex;\n align-items: center;\n gap: 5px;\n height: 26px;\n padding: 0 10px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n font-size: 12px;\n transition: background 0.12s, color 0.12s;\n\n &:hover {\n background: var(--primary-accent);\n color: var(--primary-color);\n border-color: var(--primary-lighter);\n }\n }\n\n &-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 6px 8px;\n max-height: 130px;\n overflow-y: auto;\n }\n\n &-item {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n &-label {\n font-size: 12px;\n color: var(--text-color);\n min-width: 48px;\n }\n\n &-widthLabel {\n font-size: 11px;\n color: var(--text-dark);\n }\n\n &-empty {\n font-size: 11px;\n color: var(--text-dark);\n font-style: italic;\n padding: 2px 0;\n }\n }\n\n &-canvas {\n &-door {\n cursor: crosshair;\n }\n }\n}\n\n/* ── SVG element classes ── */\n\n.doorGap {\n stroke: var(--background);\n stroke-width: 4;\n stroke-linecap: butt;\n pointer-events: none;\n}\n\n.doorMarker {\n fill: var(--primary-color);\n stroke: var(--background);\n stroke-width: 0.8;\n pointer-events: all;\n cursor: grab;\n\n &:active {\n cursor: grabbing;\n }\n}\n\n.gridLine {\n stroke: var(--text-color);\n stroke-width: 0.3;\n opacity: 0.12;\n}\n\n.roomFill {\n fill: var(--primary-accent);\n fill-opacity: 0.08;\n stroke: none;\n\n &-selected {\n fill-opacity: 0.22;\n }\n}\n\n.roomStroke {\n fill: none;\n stroke: var(--primary-color);\n stroke-width: 1.5;\n stroke-linejoin: round;\n\n &-selected {\n stroke: var(--primary-lighter);\n stroke-width: 2;\n }\n}\n\n.roomText {\n fill: var(--text-color);\n stroke: none;\n font-size: 7px;\n pointer-events: none;\n user-select: none;\n}\n\n.doorPanel {\n stroke: var(--primary-color);\n stroke-width: 1.5;\n stroke-linecap: round;\n\n &-selected {\n stroke: var(--primary-lighter);\n stroke-width: 2;\n }\n}\n\n.doorSwing {\n fill: none;\n stroke: var(--primary-color);\n stroke-width: 0.8;\n stroke-dasharray: 3 2;\n pointer-events: none;\n\n &-selected {\n stroke: var(--primary-lighter);\n }\n}\n\n.preview {\n fill: var(--primary-accent);\n stroke: var(--primary-color);\n stroke-width: 1;\n stroke-dasharray: 4 2;\n pointer-events: none;\n}\n\n.polyCloseTarget {\n fill: var(--primary-color);\n opacity: 0.5;\n pointer-events: none;\n}\n\n.polyVertex {\n fill: var(--primary-color);\n stroke: none;\n pointer-events: none;\n}\n\n.vertexHandle {\n fill: var(--background);\n stroke: var(--primary-color);\n stroke-width: 1.5;\n cursor: grab;\n pointer-events: all;\n\n &:hover {\n fill: var(--primary-accent);\n stroke: var(--primary-lighter);\n }\n}\n","import { useState, useRef, useEffect, useLayoutEffect } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faHandPointer,\n faSquare,\n faDrawPolygon,\n faTrash,\n faDownload,\n faUpload,\n faMagnifyingGlassPlus,\n faMagnifyingGlassMinus,\n faDoorOpen,\n faCheck,\n} from '@fortawesome/free-solid-svg-icons';\nimport type { MouseEvent, ReactElement } from 'react';\nimport type { Tool, Point, RoomData, DoorData, RoomDrawerProps } from './roomDrawer.types';\nimport {\n CANVAS_W,\n CANVAS_H,\n GRID,\n DOOR_WIDTH,\n CLOSE_THRESHOLD,\n clientToSVG,\n dist,\n pointToSegment,\n nearestWall,\n pointInPolygon,\n centroid,\n rectToPoints,\n doorEndpoints,\n buildWallSegments,\n downloadSVG,\n parseSVGRooms,\n snapPt,\n} from './roomDrawer.utils';\nimport styles from './roomDrawer.module.pcss';\n\nconst VERTEX_HIT = 6;\nconst WALL_HIT = 5;\nconst ZOOM_STEP = 1.25;\nconst ZOOM_MIN = 0.25;\nconst ZOOM_MAX = 12;\n\ntype DragState =\n | { type: 'room'; roomId: string; start: Point; origPoints: Point[] }\n | { type: 'vertex'; roomId: string; index: number; start: Point; origPt: Point };\n\nlet _seq = 0;\nfunction nextId(prefix: string): string {\n _seq += 1;\n return `${prefix}${_seq}`;\n}\n\nconst TOOL_HINTS: Record<Tool, string> = {\n select:\n 'Drag inside to move · Drag corner to reshape · Click wall to add corner · Dbl-click corner to remove · Delete to erase',\n rect: 'Drag to draw a rectangular room',\n polygon:\n 'Click to place corners · Click first point or Enter to close · Esc to cancel',\n};\n\nexport default function RoomDrawer({ className }: RoomDrawerProps): ReactElement {\n const [rooms, setRooms] = useState<RoomData[]>([]);\n const [doors, setDoors] = useState<DoorData[]>([]);\n const [tool, setTool] = useState<Tool>('rect');\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [editingDoorsForRoomId, setEditingDoorsForRoomId] = useState<string | null>(null);\n\n const [rectStart, setRectStart] = useState<Point | null>(null);\n const [rectCursor, setRectCursor] = useState<Point | null>(null);\n\n const [polyPoints, setPolyPoints] = useState<Point[]>([]);\n const [polyCursor, setPolyCursor] = useState<Point | null>(null);\n\n const [zoom, setZoom] = useState(1);\n const [pan, setPan] = useState<Point>({ x: 0, y: 0 });\n\n const dragRef = useRef<DragState | null>(null);\n const doorDragRef = useRef<string | null>(null); // door id being dragged\n const panDragRef = useRef<{ startClient: Point; origPan: Point; scaleX: number; scaleY: number } | null>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n const uploadRef = useRef<HTMLInputElement>(null);\n\n const stateRef = useRef({ rooms, doors, tool, selectedId, editingDoorsForRoomId, polyPoints, zoom, pan });\n useLayoutEffect(() => {\n stateRef.current = { rooms, doors, tool, selectedId, editingDoorsForRoomId, polyPoints, zoom, pan };\n });\n\n function commitPolygon(pts: Point[]) {\n if (pts.length < 3) return;\n setRooms((prev) => [\n ...prev,\n { id: nextId('room'), name: `Room ${prev.length + 1}`, points: pts },\n ]);\n setPolyPoints([]);\n setPolyCursor(null);\n }\n\n // Wheel zoom (passive: false so we can preventDefault)\n useEffect(() => {\n const svg = svgRef.current;\n if (!svg) return;\n function onWheel(e: WheelEvent) {\n e.preventDefault();\n const { zoom: z, pan: p } = stateRef.current;\n const pt = clientToSVG(e.clientX, e.clientY, svgRef.current!);\n if (!pt) return;\n const factor = e.deltaY < 0 ? ZOOM_STEP : 1 / ZOOM_STEP;\n const newZoom = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, z * factor));\n setPan({\n x: pt.x - (pt.x - p.x) * (z / newZoom),\n y: pt.y - (pt.y - p.y) * (z / newZoom),\n });\n setZoom(newZoom);\n }\n svg.addEventListener('wheel', onWheel, { passive: false });\n return () => svg.removeEventListener('wheel', onWheel);\n }, []);\n\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n const { tool: t, selectedId: sel, editingDoorsForRoomId: editDoors, polyPoints: pp, zoom: z, pan: p } = stateRef.current;\n\n if (e.key === 'Escape') {\n if (editDoors) { setEditingDoorsForRoomId(null); return; }\n if (t === 'polygon') { setPolyPoints([]); setPolyCursor(null); }\n setSelectedId(null);\n return;\n }\n if (e.key === 'Enter' && t === 'polygon' && pp.length >= 3) {\n commitPolygon(pp);\n return;\n }\n if ((e.key === '+' || e.key === '=') && !(e.target instanceof HTMLInputElement)) {\n const nz = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, z * ZOOM_STEP));\n const cx = p.x + CANVAS_W / z / 2; const cy = p.y + CANVAS_H / z / 2;\n setZoom(nz); setPan({ x: cx - CANVAS_W / nz / 2, y: cy - CANVAS_H / nz / 2 });\n return;\n }\n if (e.key === '-' && !(e.target instanceof HTMLInputElement)) {\n const nz = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, z / ZOOM_STEP));\n const cx = p.x + CANVAS_W / z / 2; const cy = p.y + CANVAS_H / z / 2;\n setZoom(nz); setPan({ x: cx - CANVAS_W / nz / 2, y: cy - CANVAS_H / nz / 2 });\n return;\n }\n if (e.key === '0' && !(e.target instanceof HTMLInputElement)) {\n setZoom(1); setPan({ x: 0, y: 0 });\n return;\n }\n if ((e.key === 'Delete' || e.key === 'Backspace') && sel && !editDoors && !(e.target instanceof HTMLInputElement)) {\n setRooms((prev) => prev.filter((r) => r.id !== sel));\n setDoors((prev) => prev.filter((d) => d.roomId !== sel));\n setSelectedId(null);\n }\n }\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, []);\n\n // ─── Zoom helpers ─────────────────────────────────────────────────────────\n\n function zoomBy(factor: number, currentZoom = zoom, currentPan = pan) {\n const newZoom = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, currentZoom * factor));\n const cx = currentPan.x + CANVAS_W / currentZoom / 2;\n const cy = currentPan.y + CANVAS_H / currentZoom / 2;\n setPan({\n x: cx - CANVAS_W / newZoom / 2,\n y: cy - CANVAS_H / newZoom / 2,\n });\n setZoom(newZoom);\n }\n\n // ─── Drawing helpers ──────────────────────────────────────────────────────\n\n function svgPt(e: MouseEvent): Point | null {\n if (!svgRef.current) return null;\n return clientToSVG(e.clientX, e.clientY, svgRef.current);\n }\n\n // ─── Vertex / wall editing helpers ───────────────────────────────────────\n\n function nearestVertex(pt: Point, room: RoomData): { index: number; d: number } | null {\n let best: { index: number; d: number } | null = null;\n for (let i = 0; i < room.points.length; i++) {\n const d = dist(pt, room.points[i]);\n if (d <= VERTEX_HIT && (!best || d < best.d)) best = { index: i, d };\n }\n return best;\n }\n\n function nearestWallSegment(\n pt: Point,\n room: RoomData,\n ): { index: number; t: number; d: number } | null {\n let best: { index: number; t: number; d: number } | null = null;\n for (let i = 0; i < room.points.length; i++) {\n const a = room.points[i];\n const b = room.points[(i + 1) % room.points.length];\n const { dist: d, t } = pointToSegment(pt, a, b);\n if (d <= WALL_HIT && (!best || d < best.d)) best = { index: i, t, d };\n }\n return best;\n }\n\n function insertVertex(roomId: string, wallIndex: number, t: number, newPt: Point): number {\n setRooms((prev) =>\n prev.map((r) => {\n if (r.id !== roomId) return r;\n const pts = [...r.points];\n pts.splice(wallIndex + 1, 0, newPt);\n return { ...r, points: pts };\n }),\n );\n setDoors((prev) =>\n prev.map((d) => {\n if (d.roomId !== roomId) return d;\n if (d.wallIndex === wallIndex) {\n if (d.t <= t) return { ...d, t: t > 0 ? d.t / t : 0 };\n return { ...d, wallIndex: wallIndex + 1, t: (d.t - t) / (1 - t) };\n }\n if (d.wallIndex > wallIndex) return { ...d, wallIndex: d.wallIndex + 1 };\n return d;\n }),\n );\n return wallIndex + 1;\n }\n\n function removeVertex(roomId: string, index: number) {\n const room = rooms.find((r) => r.id === roomId);\n if (!room || room.points.length <= 3) return;\n const n = room.points.length;\n setRooms((prev) =>\n prev.map((r) => {\n if (r.id !== roomId) return r;\n return { ...r, points: r.points.filter((_, i) => i !== index) };\n }),\n );\n setDoors((prev) =>\n prev.map((d) => {\n if (d.roomId !== roomId) return d;\n const prevWall = (index - 1 + n) % n;\n if (d.wallIndex === prevWall || d.wallIndex === index) return { ...d, wallIndex: -1 };\n if (d.wallIndex > index) return { ...d, wallIndex: d.wallIndex - 1 };\n return d;\n }).filter((d) => d.wallIndex !== -1),\n );\n }\n\n // ─── Mouse events ─────────────────────────────────────────────────────────\n\n function handleMouseDown(e: MouseEvent<SVGSVGElement>) {\n // Middle mouse → pan\n if (e.button === 1) {\n e.preventDefault();\n const svg = svgRef.current;\n if (svg) {\n const rect = svg.getBoundingClientRect();\n panDragRef.current = {\n startClient: { x: e.clientX, y: e.clientY },\n origPan: { ...pan },\n scaleX: (CANVAS_W / zoom) / rect.width,\n scaleY: (CANVAS_H / zoom) / rect.height,\n };\n }\n return;\n }\n\n if (e.button !== 0) return;\n e.preventDefault();\n const pt = svgPt(e);\n if (!pt) return;\n\n // Door editing mode: click a wall to add a door\n if (editingDoorsForRoomId) {\n const editingRoom = rooms.find((r) => r.id === editingDoorsForRoomId);\n if (editingRoom) {\n const wall = nearestWall(pt, [editingRoom]);\n if (wall) {\n setDoors((prev) => [\n ...prev,\n { id: nextId('door'), roomId: wall.roomId, wallIndex: wall.wallIndex, t: wall.t, width: DOOR_WIDTH },\n ]);\n }\n }\n return;\n }\n\n if (tool === 'rect') {\n setRectStart(pt); setRectCursor(pt); return;\n }\n\n if (tool === 'polygon') {\n if (polyPoints.length >= 3 && dist(pt, polyPoints[0]) <= CLOSE_THRESHOLD) {\n commitPolygon(polyPoints);\n } else {\n setPolyPoints((prev) => [...prev, pt]);\n }\n return;\n }\n\n if (tool === 'select') {\n const selRoom = rooms.find((r) => r.id === selectedId) ?? null;\n\n if (selRoom) {\n const vh = nearestVertex(pt, selRoom);\n if (vh) {\n dragRef.current = { type: 'vertex', roomId: selRoom.id, index: vh.index, start: pt, origPt: selRoom.points[vh.index] };\n return;\n }\n }\n\n if (selRoom) {\n const wh = nearestWallSegment(pt, selRoom);\n if (wh) {\n const a = selRoom.points[wh.index];\n const b = selRoom.points[(wh.index + 1) % selRoom.points.length];\n const newPt = snapPt({ x: a.x + (b.x - a.x) * wh.t, y: a.y + (b.y - a.y) * wh.t });\n const insertedIndex = insertVertex(selRoom.id, wh.index, wh.t, newPt);\n dragRef.current = { type: 'vertex', roomId: selRoom.id, index: insertedIndex, start: pt, origPt: newPt };\n return;\n }\n }\n\n const clickedRoom = rooms.find((r) => pointInPolygon(pt, r.points));\n if (clickedRoom) {\n setSelectedId(clickedRoom.id);\n dragRef.current = { type: 'room', roomId: clickedRoom.id, start: pt, origPoints: [...clickedRoom.points] };\n return;\n }\n\n setSelectedId(null);\n }\n }\n\n function handleDoubleClick(e: MouseEvent<SVGSVGElement>) {\n if (tool !== 'select' || editingDoorsForRoomId) return;\n const pt = svgPt(e);\n if (!pt) return;\n const selRoom = rooms.find((r) => r.id === selectedId);\n if (!selRoom) return;\n const vh = nearestVertex(pt, selRoom);\n if (vh) { e.preventDefault(); removeVertex(selRoom.id, vh.index); }\n }\n\n function handleMouseMove(e: MouseEvent<SVGSVGElement>) {\n if (panDragRef.current) {\n const { startClient, origPan, scaleX, scaleY } = panDragRef.current;\n setPan({\n x: origPan.x - (e.clientX - startClient.x) * scaleX,\n y: origPan.y - (e.clientY - startClient.y) * scaleY,\n });\n return;\n }\n\n const pt = svgPt(e);\n if (!pt) return;\n\n if (doorDragRef.current && editingDoorsForRoomId) {\n const editRoom = rooms.find((r) => r.id === editingDoorsForRoomId);\n if (editRoom) {\n const wall = nearestWall(pt, [editRoom]);\n if (wall) {\n setDoors((prev) => prev.map((d) =>\n d.id === doorDragRef.current ? { ...d, wallIndex: wall.wallIndex, t: wall.t } : d\n ));\n }\n }\n return;\n }\n\n if (tool === 'rect' && rectStart) { setRectCursor(pt); return; }\n if (tool === 'polygon') { setPolyCursor(pt); return; }\n\n if (tool === 'select' && !editingDoorsForRoomId && dragRef.current) {\n const drag = dragRef.current;\n if (drag.type === 'vertex') {\n const dx = pt.x - drag.start.x;\n const dy = pt.y - drag.start.y;\n const moved = snapPt({ x: drag.origPt.x + dx, y: drag.origPt.y + dy });\n setRooms((prev) =>\n prev.map((r) => {\n if (r.id !== drag.roomId) return r;\n const pts = [...r.points];\n pts[drag.index] = moved;\n return { ...r, points: pts };\n }),\n );\n } else {\n const dx = pt.x - drag.start.x;\n const dy = pt.y - drag.start.y;\n setRooms((prev) =>\n prev.map((r) =>\n r.id === drag.roomId\n ? { ...r, points: drag.origPoints.map((p) => ({ x: p.x + dx, y: p.y + dy })) }\n : r,\n ),\n );\n }\n }\n }\n\n function handleMouseUp(e: MouseEvent<SVGSVGElement>) {\n if (panDragRef.current) { panDragRef.current = null; return; }\n\n const pt = svgPt(e);\n if (!pt) return;\n\n if (tool === 'rect' && rectStart) {\n const x = Math.min(rectStart.x, pt.x);\n const y = Math.min(rectStart.y, pt.y);\n const w = Math.abs(pt.x - rectStart.x);\n const h = Math.abs(pt.y - rectStart.y);\n if (w >= GRID * 2 && h >= GRID * 2) {\n setRooms((prev) => [\n ...prev,\n { id: nextId('room'), name: `Room ${prev.length + 1}`, points: rectToPoints(x, y, w, h) },\n ]);\n }\n setRectStart(null); setRectCursor(null);\n }\n\n doorDragRef.current = null;\n dragRef.current = null;\n }\n\n // ─── Info bar handlers ────────────────────────────────────────────────────\n\n function handleRenameChange(value: string) {\n if (selectedId) setRooms((prev) => prev.map((r) => (r.id === selectedId ? { ...r, name: value } : r)));\n }\n\n function handleDoorWidthChange(doorId: string, value: string) {\n const w = parseFloat(value);\n if (isNaN(w) || w <= 0) return;\n setDoors((prev) => prev.map((d) => (d.id === doorId ? { ...d, width: w } : d)));\n }\n\n function handleDeleteRoom() {\n if (!selectedId) return;\n setRooms((prev) => prev.filter((r) => r.id !== selectedId));\n setDoors((prev) => prev.filter((d) => d.roomId !== selectedId));\n setEditingDoorsForRoomId(null);\n setSelectedId(null);\n }\n\n function handleDeleteDoor(doorId: string) {\n setDoors((prev) => prev.filter((d) => d.id !== doorId));\n }\n\n function switchTool(t: Tool) {\n setTool(t);\n setEditingDoorsForRoomId(null);\n setPolyPoints([]); setPolyCursor(null);\n setRectStart(null); setRectCursor(null);\n }\n\n function handleUploadChange(e: React.ChangeEvent<HTMLInputElement>) {\n const file = e.target.files?.[0];\n if (!file) return;\n e.target.value = '';\n const reader = new FileReader();\n reader.onload = (ev) => {\n const text = ev.target?.result;\n if (typeof text !== 'string') return;\n const loaded = parseSVGRooms(text);\n if (loaded.length === 0) return;\n const remapped = loaded.map((r) => ({ ...r, id: nextId('room') }));\n setRooms(remapped);\n setDoors([]);\n setSelectedId(null);\n setEditingDoorsForRoomId(null);\n setZoom(1);\n setPan({ x: 0, y: 0 });\n };\n reader.readAsText(file);\n }\n\n // ─── Derived values ───────────────────────────────────────────────────────\n\n const previewRect =\n tool === 'rect' && rectStart && rectCursor\n ? {\n x: Math.min(rectStart.x, rectCursor.x),\n y: Math.min(rectStart.y, rectCursor.y),\n w: Math.abs(rectCursor.x - rectStart.x),\n h: Math.abs(rectCursor.y - rectStart.y),\n }\n : null;\n\n const selectedRoom = selectedId ? (rooms.find((r) => r.id === selectedId) ?? null) : null;\n const editingRoom = editingDoorsForRoomId ? (rooms.find((r) => r.id === editingDoorsForRoomId) ?? null) : null;\n const editingRoomDoors = editingDoorsForRoomId ? doors.filter((d) => d.roomId === editingDoorsForRoomId) : [];\n\n const TOOLS = [\n { t: 'select' as Tool, icon: faHandPointer, label: 'Select & edit' },\n { t: 'rect' as Tool, icon: faSquare, label: 'Rectangle room' },\n { t: 'polygon' as Tool, icon: faDrawPolygon, label: 'Polygon room' },\n ] as const;\n\n const vw = CANVAS_W / zoom;\n const vh = CANVAS_H / zoom;\n\n const canvasCursor = editingDoorsForRoomId ? styles.roomDrawerCanvasDoor : tool === 'select' ? styles.roomDrawerCanvasSelect : undefined;\n\n // ─── Render ───────────────────────────────────────────────────────────────\n\n return (\n <div className={cx(styles.roomDrawer, className)}>\n {/* ── Toolbar ── */}\n <div className={styles.roomDrawerToolbar}>\n {TOOLS.map(({ t, icon, label }) => (\n <button\n key={t}\n title={label}\n className={cx(styles.roomDrawerToolbarBtn, t === tool && !editingDoorsForRoomId && styles.roomDrawerToolbarBtnActive)}\n onClick={() => switchTool(t)}\n >\n <FontAwesomeIcon icon={icon} />\n </button>\n ))}\n <div className={styles.roomDrawerToolbarSep} />\n <button title=\"Zoom in (+)\" className={styles.roomDrawerToolbarBtn} onClick={() => zoomBy(ZOOM_STEP)} disabled={zoom >= ZOOM_MAX}>\n <FontAwesomeIcon icon={faMagnifyingGlassPlus} />\n </button>\n <button\n title={`Reset zoom (0) — ${Math.round(zoom * 100)}%`}\n className={styles.roomDrawerToolbarZoomLabel}\n onClick={() => { setZoom(1); setPan({ x: 0, y: 0 }); }}\n >\n {Math.round(zoom * 100)}%\n </button>\n <button title=\"Zoom out (−)\" className={styles.roomDrawerToolbarBtn} onClick={() => zoomBy(1 / ZOOM_STEP)} disabled={zoom <= ZOOM_MIN}>\n <FontAwesomeIcon icon={faMagnifyingGlassMinus} />\n </button>\n <div className={styles.roomDrawerToolbarSep} />\n <button\n title=\"Upload SVG\"\n className={styles.roomDrawerToolbarBtn}\n onClick={() => uploadRef.current?.click()}\n >\n <FontAwesomeIcon icon={faUpload} />\n </button>\n <button\n title=\"Download SVG\"\n className={styles.roomDrawerToolbarBtn}\n onClick={() => downloadSVG(rooms, doors)}\n disabled={rooms.length === 0}\n >\n <FontAwesomeIcon icon={faDownload} />\n </button>\n <input ref={uploadRef} type=\"file\" accept=\".svg,image/svg+xml\" style={{ display: 'none' }} onChange={handleUploadChange} />\n </div>\n\n {/* ── SVG Canvas ── */}\n <svg\n ref={svgRef}\n className={cx(styles.roomDrawerCanvas, canvasCursor)}\n viewBox={`${pan.x} ${pan.y} ${vw} ${vh}`}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onDoubleClick={handleDoubleClick}\n >\n <defs>\n <pattern id=\"rd-grid\" width={GRID} height={GRID} patternUnits=\"userSpaceOnUse\">\n <path d={`M ${GRID} 0 L 0 0 0 ${GRID}`} fill=\"none\" className={styles.gridLine} />\n </pattern>\n </defs>\n <rect x={pan.x} y={pan.y} width={vw} height={vh} fill=\"url(#rd-grid)\" />\n\n {/* ── Rooms ── */}\n {rooms.map((room) => {\n const pts = room.points;\n const fillD = pts.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x},${p.y}`).join(' ') + ' Z';\n const wallSegs = buildWallSegments(pts, doors.filter((d) => d.roomId === room.id));\n const c = centroid(pts);\n const isSelected = selectedId === room.id;\n const isEditing = editingDoorsForRoomId === room.id;\n return (\n <g key={room.id}>\n <path d={fillD} className={cx(styles.roomFill, (isSelected || isEditing) && styles.roomFillSelected)} />\n {wallSegs.map((seg, si) => (\n <path key={si} d={seg} className={cx(styles.roomStroke, (isSelected || isEditing) && styles.roomStrokeSelected)} />\n ))}\n {room.name && (\n <text x={c.x} y={c.y} className={styles.roomText} textAnchor=\"middle\" dominantBaseline=\"middle\">\n {room.name}\n </text>\n )}\n </g>\n );\n })}\n\n {/* ── Door gap overlays — rendered after all rooms so they cut through adjacent walls ── */}\n {doors.map((door) => {\n const room = rooms.find((r) => r.id === door.roomId);\n if (!room) return null;\n const a = room.points[door.wallIndex];\n const b = room.points[(door.wallIndex + 1) % room.points.length];\n const ep = doorEndpoints(a, b, door.t, door.width);\n if (!ep) return null;\n return (\n <line\n key={door.id}\n x1={ep.p1.x} y1={ep.p1.y}\n x2={ep.p2.x} y2={ep.p2.y}\n className={styles.doorGap}\n />\n );\n })}\n\n {/* ── Door markers (visible in door editing mode) ── */}\n {editingDoorsForRoomId && editingRoomDoors.map((door) => {\n const room = rooms.find((r) => r.id === door.roomId);\n if (!room) return null;\n const a = room.points[door.wallIndex];\n const b = room.points[(door.wallIndex + 1) % room.points.length];\n const ep = doorEndpoints(a, b, door.t, door.width);\n if (!ep) return null;\n const mid = { x: (ep.p1.x + ep.p2.x) / 2, y: (ep.p1.y + ep.p2.y) / 2 };\n return (\n <circle\n key={door.id}\n cx={mid.x} cy={mid.y} r={2.5}\n className={styles.doorMarker}\n onMouseDown={(e) => {\n if (e.button !== 0) return;\n e.preventDefault();\n e.stopPropagation();\n doorDragRef.current = door.id;\n }}\n />\n );\n })}\n\n {/* ── Vertex handles ── */}\n {tool === 'select' && !editingDoorsForRoomId && selectedRoom &&\n selectedRoom.points.map((p, i) => (\n <circle key={i} cx={p.x} cy={p.y} r={3.5} className={styles.vertexHandle} />\n ))}\n\n {/* ── Rect preview ── */}\n {previewRect && (\n <rect x={previewRect.x} y={previewRect.y} width={previewRect.w} height={previewRect.h} className={styles.preview} />\n )}\n\n {/* ── Polygon preview ── */}\n {tool === 'polygon' && polyPoints.length > 0 && (\n <>\n <polyline\n points={[...polyPoints, polyCursor ?? polyPoints[polyPoints.length - 1]].map((p) => `${p.x},${p.y}`).join(' ')}\n className={styles.preview}\n />\n {polyPoints.length >= 3 && (\n <circle cx={polyPoints[0].x} cy={polyPoints[0].y} r={CLOSE_THRESHOLD / 2} className={styles.polyCloseTarget} />\n )}\n {polyPoints.map((p, i) => (\n <circle key={i} cx={p.x} cy={p.y} r={2} className={styles.polyVertex} />\n ))}\n </>\n )}\n </svg>\n\n {/* ── Room info bar ── */}\n {selectedRoom && !editingDoorsForRoomId && (\n <div className={styles.roomDrawerInfo}>\n <span className={styles.roomDrawerInfoLabel}>Name</span>\n <input\n className={styles.roomDrawerInfoInput}\n value={selectedRoom.name}\n onChange={(e) => handleRenameChange(e.target.value)}\n placeholder=\"Room name\"\n />\n <button\n className={styles.roomDrawerInfoDoorsBtn}\n onClick={() => setEditingDoorsForRoomId(selectedRoom.id)}\n title=\"Edit doors\"\n >\n <FontAwesomeIcon icon={faDoorOpen} />\n <span>{doors.filter((d) => d.roomId === selectedRoom.id).length}</span>\n </button>\n <button className={styles.roomDrawerInfoDelete} onClick={handleDeleteRoom} title=\"Delete room\">\n <FontAwesomeIcon icon={faTrash} />\n </button>\n </div>\n )}\n\n {/* ── Door editing panel ── */}\n {editingDoorsForRoomId && editingRoom && (\n <div className={styles.roomDrawerDoorPanel}>\n <div className={styles.roomDrawerDoorPanelHeader}>\n <FontAwesomeIcon icon={faDoorOpen} className={styles.roomDrawerDoorPanelIcon} />\n <span className={styles.roomDrawerDoorPanelTitle}>\n {editingRoom.name ? `Doors · ${editingRoom.name}` : 'Doors'}\n </span>\n <button\n className={styles.roomDrawerDoorPanelDone}\n onClick={() => setEditingDoorsForRoomId(null)}\n title=\"Done (Esc)\"\n >\n <FontAwesomeIcon icon={faCheck} />\n Done\n </button>\n </div>\n <div className={styles.roomDrawerDoorPanelList}>\n {editingRoomDoors.length === 0 && (\n <span className={styles.roomDrawerDoorPanelEmpty}>Click on a wall to add a door</span>\n )}\n {editingRoomDoors.map((door, i) => (\n <div key={door.id} className={styles.roomDrawerDoorPanelItem}>\n <span className={styles.roomDrawerDoorPanelLabel}>Door {i + 1}</span>\n <span className={styles.roomDrawerDoorPanelWidthLabel}>Width</span>\n <input\n className={styles.roomDrawerInfoInput}\n type=\"number\"\n min={1}\n value={door.width}\n onChange={(e) => handleDoorWidthChange(door.id, e.target.value)}\n />\n <button\n className={styles.roomDrawerInfoDelete}\n onClick={() => handleDeleteDoor(door.id)}\n title=\"Delete door\"\n >\n <FontAwesomeIcon icon={faTrash} />\n </button>\n </div>\n ))}\n </div>\n </div>\n )}\n\n <div className={styles.roomDrawerHint}>\n {editingDoorsForRoomId\n ? 'Click a wall to add a door · Adjust width or delete from the list · Done or Esc to finish'\n : `${TOOL_HINTS[tool]} · Scroll to zoom · Middle-drag to pan · 0 to reset`}\n </div>\n </div>\n );\n}\n",".roomViewer{\n &-container{\n &Loading {\n opacity: 0.4;\n pointer-events: none;\n }\n\n svg{\n stroke-width: 1px;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-opacity: 1;\n path {\n stroke: var(--primary-color);\n fill: transparent;\n }\n path[id=\"background\"] {\n stroke: none;\n fill: transparent;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n *[id^=\"room\"] {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n text{\n fill: var(--text-color);\n stroke: none;\n font-size: 5px;\n }\n }\n }\n\n &-active{\n stroke: #18f810 !important;\n fill: #20f81013 !important;\n path {\n stroke: #18f810 !important;\n fill: none !important;\n }\n path[id=\"background\"] {\n stroke: none !important;\n fill: #20f81013 !important;\n }\n }\n\n &-selected {\n stroke: #18f810 !important;\n path {\n stroke: #18f810 !important;\n fill: none !important;\n }\n path[id=\"background\"] {\n stroke: none !important;\n fill: #20f81013 !important;\n }\n\n text{\n stroke: none;\n fill: var(--text-color);\n }\n }\n\n &-tint {\n fill: #20f81013 !important;\n\n path{\n fill: #20f81013 !important;\n }\n\n text{\n stroke: none;\n fill: none;\n }\n }\n\n &-actions{\n display: flex;\n width: 100%;\n justify-content: center;\n gap: 8px;\n font-size: 16px;\n\n svg{\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n &-header{\n margin-bottom: 4px;\n }\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faChevronLeft as leftIcon,\n faChevronRight as rightIcon,\n faLayerGroup as layerIcon,\n} from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './roomViewer.module.pcss';\nimport type { RoomViewerProps } from './roomViewer.types';\n\nfunction RoomViewer({ data = [] }: RoomViewerProps) {\n const roomViewerRef = useRef<HTMLDivElement>(null);\n\n const [, setSelectedRoomId] = useState<string | null>(null);\n const [selectedDataId, setSelectedDataId] = useState(0);\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n const abortController = new AbortController();\n\n setSelectedRoomId(null);\n\n const container = roomViewerRef.current;\n\n if (selectedDataId > data.length - 1 || !container) {\n setIsLoading(false);\n return () => abortController.abort();\n }\n\n // useEffect fires after the DOM has been committed, so the SVG rendered\n // from data[selectedDataId].data is already in the container here.\n const rooms = container.querySelectorAll<Element>('[id^=\"room\"]');\n rooms.forEach((element) => {\n element.addEventListener(\n 'click',\n () => onRoomClicked(element.id, container),\n { signal: abortController.signal }\n );\n });\n setIsLoading(false);\n\n return () => abortController.abort();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [data, selectedDataId]);\n\n function onRoomClicked(roomId: string, container: Element) {\n const pureRoomId = roomId.substring(4);\n\n setSelectedRoomId((prevSelectedRoomId) => {\n if (pureRoomId === prevSelectedRoomId) return prevSelectedRoomId;\n\n const [use] = container.querySelectorAll<Element>('[id=\"use\"]');\n use?.setAttribute('href', `#${roomId}`);\n\n const [room] = container.querySelectorAll<Element>(`[id=\"${roomId}\"]`);\n\n if (prevSelectedRoomId) {\n const [prevRoom] = container.querySelectorAll<Element>(`[id=\"room${prevSelectedRoomId}\"]`);\n if (prevRoom) {\n prevRoom.classList.remove(styles.roomViewerSelected, styles.roomViewerTint);\n const [prevBackground] = prevRoom.querySelectorAll<Element>('[id=\"background\"]');\n if (prevBackground) prevBackground.classList.remove(styles.roomViewerTint);\n }\n }\n\n if (room) {\n room.classList.add(styles.roomViewerSelected);\n const [background] = room.querySelectorAll<Element>('[id=\"background\"]');\n (background ?? room).classList.add(styles.roomViewerTint);\n }\n\n return pureRoomId;\n });\n }\n\n function addToCurrentFloor(change: number) {\n setSelectedDataId((prev) => {\n const next = prev + change;\n if (next < 0 || next > data.length - 1) return prev;\n return next;\n });\n }\n\n const svgData = data[selectedDataId]?.data ?? null;\n\n return (\n <div className={styles.roomViewer} ref={roomViewerRef}>\n <h3 className={styles.roomViewerHeader}>{data[selectedDataId]?.label ?? ''}</h3>\n <div\n key={selectedDataId}\n className={cx(styles.roomViewerContainer, isLoading && styles.roomViewerContainerLoading)}\n >\n {svgData}\n </div>\n {data.length > 1 && (\n <div className={styles.roomViewerActions}>\n <FontAwesomeIcon icon={leftIcon} onClick={() => addToCurrentFloor(-1)} />\n <FontAwesomeIcon icon={layerIcon} />\n <FontAwesomeIcon icon={rightIcon} onClick={() => addToCurrentFloor(1)} />\n </div>\n )}\n </div>\n );\n}\n\nexport default RoomViewer;\n",".scrollbarProvider{\n display: contents;\n /* Firefox */\n * {\n scrollbar-width: thin;\n scrollbar-color: var(--background-accent-light) transparent;\n }\n\n /* Chrome, Edge, and Safari */\n *::-webkit-scrollbar {\n width: 12px;\n }\n\n *::-webkit-scrollbar-track {\n background: transparent;\n }\n\n *::-webkit-scrollbar-thumb {\n background-color: var(--background-accent-light);\n border-radius: 10px;\n border: 3px solid transparent;\n background-clip: padding-box;\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport styles from './scrollbarProvider.module.pcss';\n\ninterface Properties {\n className?: string | undefined;\n children?: React.ReactNode | undefined;\n};\n\nfunction ScrollbarProvider({\n className = undefined,\n children = undefined,\n}: Properties): ReactElement {\n return (\n <div className={cx(styles.scrollbarProvider, className)}>\n {children}\n </div>\n );\n}\n\nexport default ScrollbarProvider;\n","import ScrollbarProvider from './scrollbarProvider';\n\nexport default ScrollbarProvider;\n","import type { CSSProperties, ReactNode } from 'react';\nimport { IconDefinition } from '@fortawesome/free-solid-svg-icons';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\nimport type { IconAction } from '../types/actions.types';\n\nexport enum SectionHeaderSize {\n Small = 'small',\n Medium = 'medium',\n Large = 'large',\n}\n\nexport type SectionHeaderAction = IconAction;\n\nexport type SectionHeaderSlots =\n | 'root'\n | 'leading'\n | 'titles'\n | 'title'\n | 'subtitle'\n | 'trailing'\n | 'left'\n | 'center'\n | 'actions';\n\nexport interface SectionHeaderProps extends HtmlProps {\n title?: ReactNode;\n subtitle?: ReactNode;\n icon?: IconDefinition;\n thumbnail?: string | ReactNode;\n left?: ReactNode;\n center?: ReactNode;\n actions?: SectionHeaderAction[] | ReactNode;\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n size?: SectionHeaderSize;\n divider?: boolean;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<SectionHeaderSlots>;\n styles?: SlotStyles<SectionHeaderSlots>;\n}\n",".sectionHeader {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-m, 16px);\n align-items: center;\n color: var(--text-color);\n\n &-leading {\n display: flex;\n justify-content: center;\n align-items: center;\n width: var(--section-header-leading-size);\n height: var(--section-header-leading-size);\n color: var(--primary-color);\n background: var(--background-accent);\n border-radius: var(--default-border-radius);\n overflow: hidden;\n background-size: cover;\n background-position: center;\n flex-shrink: 0;\n font-size: calc(var(--section-header-leading-size) * 0.5);\n }\n\n &-titles {\n display: flex;\n flex-flow: column;\n flex: 0 1 auto;\n gap: 2px;\n min-width: 0;\n }\n\n &-title {\n margin: 0;\n font-size: var(--section-header-title-size);\n font-weight: var(--header-font-weight, 600);\n line-height: 1.2;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n &-subtitle {\n color: var(--text-dark);\n font-weight: 300;\n font-size: var(--section-header-subtitle-size);\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n &-trailing {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-m, 16px);\n flex: 1 1 auto;\n }\n\n &-left {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n &-center {\n display: flex;\n align-items: center;\n min-width: 0;\n }\n\n &-actions {\n display: flex;\n gap: var(--spacing-s, 8px);\n flex-wrap: wrap;\n flex-shrink: 0;\n align-items: center;\n justify-content: flex-end;\n }\n\n &-divider {\n margin-top: var(--spacing-s, 8px);\n }\n\n &-size {\n &-small {\n --section-header-title-size: var(--header-small-font-size, 16px);\n --section-header-subtitle-size: 12px;\n --section-header-leading-size: calc(var(--section-header-title-size) * 2.2);\n }\n\n &-medium {\n --section-header-title-size: var(--header-medium-font-size, 18px);\n --section-header-subtitle-size: 14px;\n --section-header-leading-size: calc(var(--section-header-title-size) * 2.2);\n }\n\n &-large {\n --section-header-title-size: var(--header-font-size, 24px);\n --section-header-subtitle-size: 15px;\n --section-header-leading-size: calc(var(--section-header-title-size) * 2.2);\n }\n }\n}\n\n@media (max-width: 640px) {\n .sectionHeader-center {\n flex: 1 1 100%;\n }\n}\n","import React from 'react';\nimport type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\n\nimport { SectionHeaderSize } from './sectionHeader.types';\nimport type { SectionHeaderProps, SectionHeaderAction } from './sectionHeader.types';\nimport styles from './sectionHeader.module.pcss';\nimport ActionIcon from '../actionIcon';\nimport Divider from '../divider';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_SIZE: Record<SectionHeaderSize, string> = {\n [SectionHeaderSize.Small]: styles.sectionHeaderSizeSmall,\n [SectionHeaderSize.Medium]: styles.sectionHeaderSizeMedium,\n [SectionHeaderSize.Large]: styles.sectionHeaderSizeLarge,\n};\n\nfunction SectionHeader(props: SectionHeaderProps): ReactElement {\n const {\n title,\n subtitle,\n icon,\n thumbnail,\n left,\n center,\n actions,\n level = 2,\n size = SectionHeaderSize.Medium,\n divider = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('SectionHeader', props);\n\n const thumbnailUrl =\n typeof thumbnail === 'string' && thumbnail.startsWith('http') ? thumbnail : undefined;\n const hasThumbnail = thumbnail != null && thumbnail !== '';\n const hasLeading = hasThumbnail || icon != null;\n\n const Heading = `h${level}` as keyof React.JSX.IntrinsicElements;\n\n return (\n <>\n <div\n {...rest}\n className={cx(\n styles.sectionHeader,\n CLASS_BY_SIZE[size],\n className,\n classNames?.root,\n )}\n style={{ ...style, ...slotStyles?.root }}\n >\n {hasLeading && (\n <div\n className={cx(styles.sectionHeaderLeading, classNames?.leading)}\n style={{\n ...(thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}),\n ...slotStyles?.leading,\n }}\n >\n {hasThumbnail\n ? !thumbnailUrl && thumbnail\n : icon && <FontAwesomeIcon icon={icon} />}\n </div>\n )}\n\n <div\n className={cx(styles.sectionHeaderTitles, classNames?.titles)}\n style={slotStyles?.titles}\n >\n <Heading\n className={cx(styles.sectionHeaderTitle, classNames?.title)}\n style={slotStyles?.title}\n >\n {title}\n </Heading>\n {subtitle != null && subtitle !== '' && (\n <div\n className={cx(styles.sectionHeaderSubtitle, classNames?.subtitle)}\n style={slotStyles?.subtitle}\n >\n {subtitle}\n </div>\n )}\n </div>\n\n <div\n className={cx(styles.sectionHeaderTrailing, classNames?.trailing)}\n style={slotStyles?.trailing}\n >\n <div className={cx(styles.sectionHeaderLeft, classNames?.left)} style={slotStyles?.left}>\n {left}\n </div>\n\n <div\n className={cx(styles.sectionHeaderCenter, classNames?.center)}\n style={slotStyles?.center}\n >\n {center}\n </div>\n\n <div\n className={cx(styles.sectionHeaderActions, classNames?.actions)}\n style={slotStyles?.actions}\n >\n {Array.isArray(actions)\n ? (actions as SectionHeaderAction[]).map((action, index) => (\n <ActionIcon\n key={index}\n title={action.title}\n onClick={\n action.onClick\n ? (e: React.MouseEvent<HTMLDivElement>) => {\n e.stopPropagation();\n action.onClick?.(e);\n }\n : undefined\n }\n icon={action.icon}\n />\n ))\n : (actions as React.ReactNode)}\n </div>\n </div>\n </div>\n {divider && <Divider className={styles.sectionHeaderDivider} />}\n </>\n );\n}\n\nexport default SectionHeader;\n","import type { CSSProperties } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport enum SkeletonVariant {\n Text = 'text',\n Circle = 'circle',\n Rectangular = 'rectangular',\n}\n\nexport enum SkeletonAnimation {\n Shimmer = 'shimmer',\n Pulse = 'pulse',\n None = 'none',\n}\n\nexport type SkeletonSlots = 'line';\n\nexport interface SkeletonProps extends HtmlProps {\n variant?: SkeletonVariant;\n animation?: SkeletonAnimation;\n lines?: number;\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<SkeletonSlots>;\n styles?: SlotStyles<SkeletonSlots>;\n}\n",".skeleton {\n display: block;\n background-color: var(--background-accent);\n border-radius: var(--default-border-radius);\n\n &-lines {\n display: flex;\n flex-direction: column;\n gap: 0.5em;\n }\n\n &-line-last {\n width: 60%;\n }\n\n &-text {\n width: 100%;\n height: 1em;\n }\n\n &-circle {\n border-radius: 50%;\n }\n\n &-rectangular {\n border-radius: var(--default-border-radius);\n }\n\n &-animation {\n &-pulse {\n animation: skeletonPulse 1.5s ease-in-out infinite;\n }\n\n &-shimmer {\n background-image: linear-gradient(\n 90deg,\n var(--background-accent) 25%,\n var(--background-accent-light) 50%,\n var(--background-accent) 75%\n );\n background-size: 200% 100%;\n animation: skeletonShimmer 1.5s ease-in-out infinite;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n &-animation-pulse,\n &-animation-shimmer {\n animation: none;\n }\n }\n}\n\n@keyframes skeletonPulse {\n 0%,\n 100% {\n opacity: 1;\n }\n\n 50% {\n opacity: 0.4;\n }\n}\n\n@keyframes skeletonShimmer {\n 0% {\n background-position: 200% 0;\n }\n\n 100% {\n background-position: -200% 0;\n }\n}\n","import type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { SkeletonVariant, SkeletonAnimation } from './skeleton.types';\nimport type { SkeletonProps } from './skeleton.types';\nimport styles from './skeleton.module.pcss';\nimport { useComponentDefaults } from '../configProvider';\n\nconst CLASS_BY_VARIANT: Record<SkeletonVariant, string> = {\n [SkeletonVariant.Text]: styles.skeletonText,\n [SkeletonVariant.Circle]: styles.skeletonCircle,\n [SkeletonVariant.Rectangular]: styles.skeletonRectangular,\n};\n\nconst CLASS_BY_ANIMATION: Record<SkeletonAnimation, string | undefined> = {\n [SkeletonAnimation.Shimmer]: styles.skeletonAnimationShimmer,\n [SkeletonAnimation.Pulse]: styles.skeletonAnimationPulse,\n [SkeletonAnimation.None]: undefined,\n};\n\nfunction Skeleton(props: SkeletonProps): ReactElement {\n const {\n variant = SkeletonVariant.Text,\n animation = SkeletonAnimation.Shimmer,\n lines = 1,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Skeleton', props);\n const variantClass = CLASS_BY_VARIANT[variant];\n const animationClass = CLASS_BY_ANIMATION[animation];\n\n if (variant !== SkeletonVariant.Text || lines <= 1) {\n return (\n <span\n {...rest}\n className={cx(styles.skeleton, variantClass, animationClass, className)}\n style={style}\n />\n );\n }\n\n return (\n <span {...rest} className={cx(styles.skeletonLines, className)} style={style}>\n {Array.from({ length: lines }, (_, index) => (\n <span\n key={index}\n className={cx(\n styles.skeleton,\n variantClass,\n animationClass,\n index === lines - 1 && styles.skeletonLineLast,\n classNames?.line\n )}\n style={slotStyles?.line}\n />\n ))}\n </span>\n );\n}\n\nexport default Skeleton;\n",".slider {\n /* Theme tokens resolved once, each with a built-in fallback. Set any of the\n public `--slider-*` variables via ThemeProvider or `style` to override. */\n --custom-slider-track-color: var(--slider-track-color, var(--background-accent-light));\n --custom-slider-range-color: var(--slider-range-color, var(--primary-color));\n --custom-slider-thumb-color: var(--slider-thumb-color, var(--primary-color));\n --custom-slider-thumb-size: var(--slider-thumb-size, 18px);\n --custom-slider-track-height: var(--slider-track-height, 6px);\n\n position: relative;\n display: flex;\n align-items: center;\n box-sizing: border-box;\n /* Fill the container, and allow shrinking when used inside a flex row so the\n track never collapses to nothing next to a sibling (e.g. a value readout). */\n width: 100%;\n min-width: 0;\n height: var(--custom-slider-thumb-size);\n padding: 0 calc(var(--custom-slider-thumb-size) / 2);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n touch-action: none;\n user-select: none;\n\n &:focus-visible {\n outline: none;\n }\n &:focus-visible .slider-thumb {\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--custom-slider-range-color) 30%, transparent);\n }\n\n &-disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n /* Reserve room under the track for mark labels. */\n &-has-mark-labels {\n margin-bottom: 22px;\n }\n\n &-track {\n position: relative;\n flex: 1;\n height: var(--custom-slider-track-height);\n background-color: var(--custom-slider-track-color);\n border-radius: 999px;\n }\n\n &-range {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n background-color: var(--custom-slider-range-color);\n border-radius: 999px;\n transition: width 0.12s ease;\n }\n\n &-thumb {\n position: absolute;\n top: 50%;\n width: var(--custom-slider-thumb-size);\n height: var(--custom-slider-thumb-size);\n transform: translate(-50%, -50%);\n background-color: var(--custom-slider-thumb-color);\n border-radius: 50%;\n box-shadow: var(--card-shadow);\n transition: left 0.12s ease, box-shadow 0.15s ease;\n }\n\n /* No lag between pointer and thumb/fill while dragging. */\n &-dragging &-range,\n &-dragging &-thumb {\n transition: box-shadow 0.15s ease;\n }\n\n &-mark {\n position: absolute;\n top: 50%;\n width: 3px;\n height: 3px;\n transform: translate(-50%, -50%);\n border-radius: 50%;\n background-color: var(--background);\n pointer-events: none;\n }\n\n &-mark-label {\n position: absolute;\n top: calc(50% + var(--custom-slider-thumb-size));\n transform: translateX(-50%);\n font-size: var(--text-small-font-size, 12px);\n color: var(--text-dark);\n white-space: nowrap;\n pointer-events: none;\n }\n\n &-value {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n padding: 2px 8px;\n border-radius: var(--default-border-radius);\n background-color: var(--background-accent-light);\n color: var(--text-color);\n font-size: var(--text-small-font-size, 12px);\n white-space: nowrap;\n pointer-events: none;\n font-variant-numeric: tabular-nums;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .slider-range,\n .slider-thumb {\n transition: none;\n }\n}\n","import React, { useEffect, useRef, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport styles from './slider.module.pcss';\nimport type { SliderProps } from './slider.types';\n\n/** Count decimal places in a step so snapped values don't accumulate float error. */\nfunction decimalsOf(step: number): number {\n const s = String(step);\n const dot = s.indexOf('.');\n return dot === -1 ? 0 : s.length - dot - 1;\n}\n\nexport default function Slider({\n value,\n defaultValue,\n onChange,\n onChangeEnd,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n marks,\n showValue = false,\n formatValue,\n size = '18px',\n tabIndex = 0,\n className,\n style,\n classNames,\n styles: slotStyles,\n 'aria-label': ariaLabel,\n ...rest\n}: SliderProps): ReactElement {\n const trackRef = useRef<HTMLDivElement>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const draggingRef = useRef(false);\n const [dragging, setDragging] = useState(false);\n\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<number>(defaultValue ?? min);\n\n const decimals = decimalsOf(step);\n\n function clamp(v: number): number {\n return Math.min(max, Math.max(min, v));\n }\n\n function snap(v: number): number {\n const snapped = Math.round((v - min) / step) * step + min;\n return Number(clamp(snapped).toFixed(decimals));\n }\n\n const current = clamp(isControlled ? (value as number) : internal);\n // Latest committed value, for reading inside pointer handlers without stale\n // closures. Synced after render (never written during render) and optimistically\n // in commit() so a drag burst dedupes before the next render lands.\n const currentRef = useRef(current);\n useEffect(() => {\n currentRef.current = current;\n }, [current]);\n\n const fraction = max > min ? (current - min) / (max - min) : 0;\n const percent = `${fraction * 100}%`;\n\n function commit(next: number, ended: boolean) {\n const snapped = snap(next);\n if (snapped !== currentRef.current) {\n currentRef.current = snapped;\n if (!isControlled) setInternal(snapped);\n onChange?.(snapped);\n }\n if (ended) onChangeEnd?.(snapped);\n }\n\n function valueFromClientX(clientX: number): number {\n const track = trackRef.current;\n if (!track) return currentRef.current;\n const rect = track.getBoundingClientRect();\n const ratio = rect.width ? (clientX - rect.left) / rect.width : 0;\n return min + Math.min(1, Math.max(0, ratio)) * (max - min);\n }\n\n function handlePointerDown(e: React.PointerEvent<HTMLDivElement>) {\n if (disabled) return;\n e.preventDefault();\n rootRef.current?.focus();\n rootRef.current?.setPointerCapture?.(e.pointerId);\n draggingRef.current = true;\n setDragging(true);\n commit(valueFromClientX(e.clientX), false);\n }\n\n function handlePointerMove(e: React.PointerEvent<HTMLDivElement>) {\n if (!draggingRef.current) return;\n commit(valueFromClientX(e.clientX), false);\n }\n\n function handlePointerUp(e: React.PointerEvent<HTMLDivElement>) {\n if (!draggingRef.current) return;\n draggingRef.current = false;\n setDragging(false);\n rootRef.current?.releasePointerCapture?.(e.pointerId);\n onChangeEnd?.(currentRef.current);\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>) {\n if (disabled) return;\n const page = step * 10;\n let next: number | null = null;\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + step;\n break;\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - step;\n break;\n case 'PageUp':\n next = current + page;\n break;\n case 'PageDown':\n next = current - page;\n break;\n case 'Home':\n next = min;\n break;\n case 'End':\n next = max;\n break;\n default:\n return;\n }\n e.preventDefault();\n commit(next, true);\n }\n\n const valueText = formatValue ? formatValue(current) : current;\n const hasMarkLabels = !!marks?.some((m) => m.label != null);\n\n return (\n <div\n {...rest}\n ref={rootRef}\n role=\"slider\"\n aria-label={ariaLabel}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={current}\n aria-valuetext={typeof valueText === 'string' || typeof valueText === 'number' ? String(valueText) : undefined}\n aria-orientation=\"horizontal\"\n aria-disabled={disabled || undefined}\n tabIndex={disabled ? -1 : tabIndex}\n className={cx(\n styles.slider,\n disabled && styles.sliderDisabled,\n dragging && styles.sliderDragging,\n hasMarkLabels && styles.sliderHasMarkLabels,\n className,\n classNames?.root,\n )}\n style={{ '--slider-thumb-size': size, ...style, ...slotStyles?.root } as React.CSSProperties}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onKeyDown={handleKeyDown}\n >\n <div ref={trackRef} className={cx(styles.sliderTrack, classNames?.track)} style={slotStyles?.track}>\n <div\n className={cx(styles.sliderRange, classNames?.range)}\n style={{ width: percent, ...slotStyles?.range }}\n />\n {marks?.map((mark) => {\n const markFraction = max > min ? (clamp(mark.value) - min) / (max - min) : 0;\n const left = `${markFraction * 100}%`;\n return (\n <React.Fragment key={mark.value}>\n <span\n className={cx(styles.sliderMark, classNames?.mark)}\n style={{ left, ...slotStyles?.mark }}\n />\n {mark.label != null && (\n <span\n className={cx(styles.sliderMarkLabel, classNames?.markLabel)}\n style={{ left, ...slotStyles?.markLabel }}\n >\n {mark.label}\n </span>\n )}\n </React.Fragment>\n );\n })}\n <div\n className={cx(styles.sliderThumb, classNames?.thumb)}\n style={{ left: percent, ...slotStyles?.thumb }}\n >\n {showValue && (\n <span className={cx(styles.sliderValue, classNames?.value)} style={slotStyles?.value}>\n {valueText}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n}\n",".splitButton {\n display: inline-flex;\n}\n\n/* The class is doubled to boost specificity above Button's own .button rule (both are plain\n single classes, so specificity would otherwise tie and the outcome would depend on which\n CSS module happens to load first in the bundle). This guarantees the flattened corner always\n wins regardless of load order. */\n.splitButtonPrimary.splitButtonPrimary {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.splitButtonTrigger.splitButtonTrigger {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n margin-left: -1px;\n}\n\n.splitButtonMenu {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin: 0;\n padding: 6px;\n list-style: none;\n min-width: 140px;\n}\n\n.splitButtonMenuItem {\n display: flex;\n align-items: center;\n padding: 8px 10px;\n border-radius: var(--default-border-radius);\n color: var(--text-color);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: background 0.15s;\n\n &:hover {\n background: var(--background-accent-light);\n }\n\n &-disabled {\n opacity: 0.5;\n cursor: default;\n pointer-events: none;\n }\n\n &-icon {\n width: 1em;\n flex: none;\n margin-right: 8px;\n }\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { KeyboardEvent } from 'react';\nimport cx from 'classnames';\nimport { faChevronDown } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\n\nimport Button from '../button';\nimport { ButtonStyleType, ButtonSize } from '../button/button.types';\nimport ButtonGroup from '../buttonGroup';\nimport FloatingMenu from '../floatingMenu';\nimport { Align } from '../floatingMenu/floatingMenu.types';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults } from '../configProvider';\nimport type { SplitButtonProps } from './splitButton.types';\n\nimport styles from './splitButton.module.pcss';\n\nfunction mod(n: number, m: number) {\n return ((n % m) + m) % m;\n}\n\nfunction SplitButton(props: SplitButtonProps) {\n const {\n children,\n onClick = () => {},\n actions = [],\n styleType = ButtonStyleType.Primary,\n size = ButtonSize.Default,\n disabled = false,\n isLoading = false,\n align = Align.Right,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('SplitButton', props);\n\n const [isOpen, setIsOpen] = useState(false);\n const itemRefs = useRef<(HTMLDivElement | null)[]>([]);\n\n // Adjusting state during render (not in an effect) on a prop change is the documented React\n // pattern for this: closing the menu as soon as `disabled` becomes true, without an extra\n // render tick or a setState-in-effect lint violation.\n const [prevDisabled, setPrevDisabled] = useState(disabled);\n if (disabled !== prevDisabled) {\n setPrevDisabled(disabled);\n if (disabled) setIsOpen(false);\n }\n\n useEffect(() => {\n if (!isOpen) return;\n const firstEnabled = actions.findIndex((action) => !action.disabled);\n if (firstEnabled !== -1) itemRefs.current[firstEnabled]?.focus();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n function focusEnabledItem(fromIndex: number, direction: 1 | -1) {\n const enabledIndexes = actions\n .map((action, index) => index)\n .filter((index) => !actions[index].disabled);\n if (enabledIndexes.length === 0) return;\n\n const currentPos = enabledIndexes.indexOf(fromIndex);\n const nextPos = currentPos === -1\n ? (direction === 1 ? 0 : enabledIndexes.length - 1)\n : mod(currentPos + direction, enabledIndexes.length);\n itemRefs.current[enabledIndexes[nextPos]]?.focus();\n }\n\n function handleMenuKeyDown(event: KeyboardEvent<HTMLUListElement>) {\n const activeIndex = itemRefs.current.findIndex((el) => el === document.activeElement);\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n focusEnabledItem(activeIndex, 1);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n focusEnabledItem(activeIndex, -1);\n } else if (event.key === 'Home') {\n event.preventDefault();\n focusEnabledItem(-1, 1);\n } else if (event.key === 'End') {\n event.preventDefault();\n focusEnabledItem(-1, -1);\n }\n // Escape and Tab-boundary handling live in FloatingMenu itself, since any menu content with\n // focusable elements needs the same treatment, not just this one.\n }\n\n return (\n <ButtonGroup\n {...rest}\n className={cx(styles.splitButton, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <Button\n styleType={styleType}\n size={size}\n disabled={disabled}\n isLoading={isLoading}\n onClick={onClick}\n className={cx(styles.splitButtonPrimary, classNames?.primaryButton)}\n style={slotStyles?.primaryButton}\n >\n {children}\n </Button>\n\n <FloatingMenu\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n align={align}\n dontCloseOnChildClick\n content={\n <ul\n className={cx(styles.splitButtonMenu, classNames?.menu)}\n style={slotStyles?.menu}\n role=\"menu\"\n onKeyDown={handleMenuKeyDown}\n >\n {actions.map((action, index) => (\n <li key={action.id} role=\"none\">\n <InteractableDiv\n ref={(el) => { itemRefs.current[index] = el; }}\n role=\"menuitem\"\n tabIndex={action.disabled ? -1 : 0}\n aria-disabled={action.disabled}\n className={cx(\n styles.splitButtonMenuItem,\n { [styles.splitButtonMenuItemDisabled]: action.disabled },\n classNames?.menuItem\n )}\n style={slotStyles?.menuItem}\n onClick={() => {\n if (disabled || action.disabled) return;\n action.onClick();\n setIsOpen(false);\n }}\n >\n {action.icon ? <FontAwesomeIcon icon={action.icon} className={styles.splitButtonMenuItemIcon} /> : null}\n {action.label}\n </InteractableDiv>\n </li>\n ))}\n </ul>\n }\n >\n <Button\n styleType={styleType}\n size={size}\n disabled={disabled}\n icon={faChevronDown}\n aria-label=\"More actions\"\n className={cx(styles.splitButtonTrigger, classNames?.triggerButton)}\n style={slotStyles?.triggerButton}\n />\n </FloatingMenu>\n </ButtonGroup>\n );\n}\n\nexport default SplitButton;\n",".stepper {\n /* Theme tokens resolved once, each with a built-in fallback. Set any of the\n public `--stepper-*` variables via ThemeProvider (theme-wide) or `style`\n (per instance) to override; unset ones fall back to the values below. */\n --custom-stepper-marker-size: var(--stepper-marker-size, 40px);\n --custom-stepper-marker-radius: var(--stepper-marker-radius, var(--default-border-radius));\n --custom-stepper-idle-color: var(--stepper-idle-color, var(--primary-lighter));\n --custom-stepper-active-color: var(--stepper-active-color, var(--primary-color));\n --custom-stepper-done-color: var(--stepper-done-color, var(--primary-color));\n --custom-stepper-error-color: var(--stepper-error-color, var(--error-color));\n --custom-stepper-connector-color: var(--stepper-connector-color, var(--primary-color));\n --custom-stepper-connector-thickness: var(--stepper-connector-thickness, 3px);\n --custom-stepper-connector-idle-thickness: var(--stepper-connector-idle-thickness, 1px);\n --custom-stepper-gap: var(--stepper-gap, 12px);\n --custom-stepper-text-on-marker: var(--stepper-text-on-marker, var(--text-on-primary));\n\n user-select: none;\n color: var(--text-color);\n\n &-vertical {\n display: flex;\n flex-flow: column;\n }\n\n &:not(.stepper-vertical) {\n display: flex;\n align-items: center;\n }\n &-label-bottom:not(.stepper-vertical) {\n padding-bottom: 46px;\n }\n &-label-top:not(.stepper-vertical) {\n padding-top: 46px;\n }\n\n /* Entry --------------------------------------------------------------- */\n &-entry {\n display: flex;\n align-items: flex-start;\n gap: var(--custom-stepper-gap);\n box-sizing: border-box;\n }\n &:not(.stepper-vertical) &-entry {\n position: relative;\n flex: 0 0 auto;\n align-items: center;\n gap: 0;\n }\n &-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n &-entry-disabled {\n opacity: 0.5;\n }\n\n &-entry-number {\n width: var(--custom-stepper-marker-size);\n height: var(--custom-stepper-marker-size);\n box-sizing: border-box;\n flex-shrink: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n border: 1px solid var(--custom-stepper-idle-color);\n color: var(--custom-stepper-idle-color);\n border-radius: var(--custom-stepper-marker-radius);\n font-weight: 600;\n font-size: calc(var(--custom-stepper-marker-size) * 0.4);\n box-shadow: inset 0px 0px 0px var(--custom-stepper-done-color);\n transition: all 0.4s;\n }\n &-entry-active &-entry-number {\n border: 2px solid var(--custom-stepper-active-color);\n color: var(--custom-stepper-active-color);\n transform: scale3d(1.1, 1.1, 1);\n }\n &-entry-done &-entry-number {\n border-color: var(--custom-stepper-done-color);\n color: var(--custom-stepper-text-on-marker);\n background-color: var(--custom-stepper-done-color);\n box-shadow: inset 0px 0px 0px 30px var(--custom-stepper-done-color);\n transform: none;\n }\n &-entry-error &-entry-number {\n border: 2px solid var(--custom-stepper-error-color);\n color: var(--custom-stepper-error-color);\n box-shadow: inset 0px 0px 0px var(--custom-stepper-error-color);\n transform: none;\n }\n\n &-checkmark path {\n stroke: var(--custom-stepper-text-on-marker);\n stroke-dasharray: 5;\n stroke-dashoffset: 5;\n animation: showCheckmark 0.4s 0.2s forwards;\n }\n\n &-marker-cell {\n display: flex;\n flex-direction: column;\n align-items: center;\n flex-shrink: 0;\n width: var(--custom-stepper-marker-size);\n }\n &-rail-segment {\n flex: 1 1 0;\n min-height: 0;\n width: var(--custom-stepper-connector-idle-thickness);\n background-size: 100% 200%;\n background-image: linear-gradient(\n 180deg,\n var(--custom-stepper-connector-color) 0 50%,\n var(--custom-stepper-idle-color) 50% 100%\n );\n background-position: 0 100%;\n transition: background-position 0.4s, width 0.4s;\n }\n &-rail-filled {\n width: var(--custom-stepper-connector-thickness);\n background-position: 0 0;\n }\n &-rail-hidden {\n background-image: none;\n background-color: transparent;\n }\n\n &-entry-labels {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n align-self: center;\n }\n &-entry-label {\n color: var(--text-color);\n }\n &-description {\n color: var(--text-dark);\n font-size: var(--text-small-font-size, 0.85em);\n }\n &-optional {\n color: var(--text-light);\n font-size: var(--text-small-font-size, 0.85em);\n font-style: italic;\n }\n\n &:not(.stepper-vertical) &-entry-labels {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n width: max-content;\n max-width: 160px;\n text-align: center;\n align-items: center;\n }\n &-label-bottom:not(.stepper-vertical) &-entry-labels {\n top: calc(var(--custom-stepper-marker-size) + 6px);\n }\n &-label-top:not(.stepper-vertical) &-entry-labels {\n bottom: calc(var(--custom-stepper-marker-size) + 6px);\n }\n\n &-connector {\n flex: 1 1 auto;\n min-width: 24px;\n height: var(--custom-stepper-connector-idle-thickness);\n background-size: 200% 100%;\n background-image: linear-gradient(\n 90deg,\n var(--custom-stepper-connector-color) 0 50%,\n var(--custom-stepper-idle-color) 50% 100%\n );\n background-position: 100% 0;\n transition: background-position 0.6s, height 0.4s, width 0.4s;\n\n &-filled {\n height: var(--custom-stepper-connector-thickness);\n background-position: 0 0;\n }\n }\n\n &-step {\n display: grid;\n grid-template-columns: var(--custom-stepper-marker-size) 1fr;\n column-gap: var(--custom-stepper-gap);\n }\n &-vertical &-entry {\n grid-column: 1 / -1;\n align-items: stretch;\n }\n &-vertical &-connector {\n grid-column: 1;\n justify-self: center;\n flex: none;\n width: var(--custom-stepper-connector-idle-thickness);\n min-width: 0;\n height: 100%;\n min-height: 24px;\n background-size: 100% 200%;\n background-image: linear-gradient(\n 180deg,\n var(--custom-stepper-connector-color) 0 50%,\n var(--custom-stepper-idle-color) 50% 100%\n );\n background-position: 0 100%;\n transition: background-position 0.4s, width 0.4s;\n\n &-filled {\n width: var(--custom-stepper-connector-thickness);\n background-position: 0 0;\n }\n }\n &-vertical &-content {\n grid-column: 2;\n }\n\n &-vertical.stepper-label-left &-step {\n grid-template-columns: 1fr var(--custom-stepper-marker-size);\n }\n &-vertical.stepper-label-left &-entry {\n flex-direction: row-reverse;\n }\n &-vertical.stepper-label-left &-connector {\n grid-column: 2;\n }\n &-vertical.stepper-label-left &-content {\n grid-column: 1;\n text-align: right;\n }\n\n &-content {\n overflow: hidden;\n transition: height 0.25s ease;\n }\n &-content-inner {\n padding: 4px 0 12px;\n }\n\n /* Outlined: completed markers stay ringed (a coloured check, no solid fill) */\n &-outlined {\n --stepper-text-on-marker: var(--custom-stepper-done-color);\n\n & .stepper-entry-done .stepper-entry-number {\n box-shadow: none;\n background-color: transparent;\n color: var(--custom-stepper-done-color);\n }\n }\n &-dots {\n --stepper-marker-size: 16px;\n --stepper-marker-radius: 50%;\n --stepper-gap: 10px;\n\n & .stepper-entry-number {\n font-size: 0;\n border-width: 2px;\n }\n & .stepper-entry-number svg {\n display: none;\n }\n }\n}\n\n@keyframes showCheckmark {\n to {\n stroke-dashoffset: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .stepper-content {\n transition: none;\n }\n .stepper-entry-number,\n .stepper-connector,\n .stepper-rail-segment {\n transition: none;\n }\n .stepper-checkmark path {\n animation: none;\n stroke-dashoffset: 0;\n }\n}\n","import type React from 'react';\nimport type { IconDefinition } from '@fortawesome/fontawesome-svg-core';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Layout direction of the stepper. */\nexport enum StepperAlignment {\n Horizontal = 'horizontal',\n Vertical = 'vertical',\n}\n\n/** Visual preset for the step markers and connectors. */\nexport enum StepperStyleType {\n /** Numbered markers, filled solid on completion (the default look). */\n Default = 'default',\n /** Numbered markers that stay ringed when completed (a coloured check, no solid fill). */\n Outlined = 'outlined',\n /** Minimal dots without numbers, for a compact onboarding or carousel style. */\n Dots = 'dots',\n}\n\n/**\n * Which step bodies (`step.content`) are expanded. Only affects vertical\n * steppers with per-step `content`; ignored otherwise.\n */\nexport enum StepperCollapse {\n /** Every step body stays expanded. */\n None = 'none',\n /** Only the current step's body is expanded (classic vertical wizard). */\n ActiveOnly = 'activeOnly',\n /** Completed (past) step bodies collapse; current and upcoming stay expanded. */\n Completed = 'completed',\n}\n\n/**\n * Where the label block sits relative to the marker. Horizontal steppers use\n * `Top`/`Bottom`; vertical steppers use `Left`/`Right`. An out-of-orientation\n * value falls back to that orientation's default.\n */\nexport enum StepperLabelPlacement {\n Top = 'top',\n Bottom = 'bottom',\n Left = 'left',\n Right = 'right',\n}\n\nexport type StepperSlots =\n | 'root'\n | 'entry'\n | 'entryNumber'\n | 'entryLabel'\n | 'connector'\n | 'description'\n | 'content'\n | 'optional'\n | 'icon';\n\nexport interface StepperStep {\n /** Primary label for the step. */\n label: React.ReactNode;\n /** Secondary line shown under the label. */\n description?: React.ReactNode;\n /** Collapsible body content, rendered under the label (vertical only). */\n content?: React.ReactNode;\n /** FontAwesome icon shown in the marker instead of the step number. */\n icon?: IconDefinition;\n /** Marks the step as errored, recolouring the marker with `--stepper-error-color`. */\n error?: boolean;\n /** `true` renders an \"Optional\" hint; a node renders custom hint text. */\n optional?: boolean | React.ReactNode;\n /** Disables this step: never clickable, dimmed. */\n disabled?: boolean;\n}\n\nexport interface StepperProps extends HtmlProps {\n steps?: StepperStep[];\n currentStep?: number;\n alignment?: StepperAlignment | 'horizontal' | 'vertical';\n onStepClicked?: ((index: number) => void) | null;\n /** Allow clicking any step, not just completed ones. */\n nonLinear?: boolean;\n /** Hide the label text (and description) beneath each step entry. */\n hideLabels?: boolean;\n /** Visual preset for markers and connectors (default `Default`). */\n styleType?: StepperStyleType;\n /** Which step bodies are expanded. Vertical `content` only (default `None`). */\n collapse?: StepperCollapse;\n /** Label position relative to the marker (default: horizontal `Bottom`, vertical `Right`). */\n labelPlacement?: StepperLabelPlacement;\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<StepperSlots>;\n styles?: SlotStyles<StepperSlots>;\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport styles from './stepper.module.pcss';\nimport {\n StepperAlignment,\n StepperCollapse,\n StepperLabelPlacement,\n StepperStyleType,\n type StepperProps,\n type StepperStep,\n} from './stepper.types';\n\nconst STYLE_CLASS: Record<StepperStyleType, string> = {\n [StepperStyleType.Default]: styles.stepperDefault,\n [StepperStyleType.Outlined]: styles.stepperOutlined,\n [StepperStyleType.Dots]: styles.stepperDots,\n};\n\nconst PLACEMENT_CLASS: Record<StepperLabelPlacement, string> = {\n [StepperLabelPlacement.Top]: styles.stepperLabelTop,\n [StepperLabelPlacement.Bottom]: styles.stepperLabelBottom,\n [StepperLabelPlacement.Left]: styles.stepperLabelLeft,\n [StepperLabelPlacement.Right]: styles.stepperLabelRight,\n};\n\nfunction Checkmark() {\n return (\n <svg\n className={styles.stepperCheckmark}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"-0.2 -1.2 3.4 2\"\n height=\"20px\"\n width=\"20px\"\n >\n <path d=\"M 0 0 l 1 1 l 2 -2\" strokeWidth=\"0.4\" fill=\"none\" />\n </svg>\n );\n}\n\nfunction StepBody({\n open,\n className,\n style,\n children,\n}: {\n open: boolean;\n className?: string;\n style?: React.CSSProperties;\n children: React.ReactNode;\n}) {\n const innerRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<number | null>(null);\n\n useEffect(() => {\n const el = innerRef.current;\n if (!el) return;\n const observer = new ResizeObserver(() => setHeight(el.offsetHeight));\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n return (\n <div\n className={cx(styles.stepperContent, className)}\n style={{ ...style, height: open ? (height ?? 'auto') : 0 }}\n aria-hidden={!open}\n >\n <div ref={innerRef} className={styles.stepperContentInner}>\n {children}\n </div>\n </div>\n );\n}\n\nfunction resolvePlacement(\n placement: StepperLabelPlacement | undefined,\n isVertical: boolean,\n): StepperLabelPlacement {\n const verticalValues = [StepperLabelPlacement.Left, StepperLabelPlacement.Right];\n if (isVertical) {\n return placement && verticalValues.includes(placement) ? placement : StepperLabelPlacement.Right;\n }\n return placement && !verticalValues.includes(placement) ? placement : StepperLabelPlacement.Bottom;\n}\n\nexport default function Stepper({\n steps = [],\n currentStep = 0,\n alignment = StepperAlignment.Horizontal,\n onStepClicked = null,\n nonLinear = false,\n hideLabels = false,\n styleType = StepperStyleType.Default,\n collapse = StepperCollapse.None,\n labelPlacement,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: StepperProps) {\n const isVertical = alignment === StepperAlignment.Vertical;\n const placement = resolvePlacement(labelPlacement, isVertical);\n\n return (\n <div\n {...rest}\n className={cx(\n styles.stepper,\n STYLE_CLASS[styleType],\n PLACEMENT_CLASS[placement],\n { [styles.stepperVertical]: isVertical },\n classNames?.root,\n className,\n )}\n style={{ ...slotStyles?.root, ...style }}\n >\n {steps.map((step: StepperStep, index: number) => {\n const isDone = index < currentStep;\n const isActive = index <= currentStep;\n const hasError = !!step.error;\n // nonLinear: every enabled step except the current one is clickable.\n // linear: only completed steps are clickable.\n const isClickable =\n !!onStepClicked && !step.disabled && (nonLinear ? index !== currentStep : isDone);\n\n const entryClassName = cx(\n styles.stepperEntry,\n { [styles.stepperEntryActive]: isActive },\n { [styles.stepperEntryDone]: isDone && !hasError },\n { [styles.stepperEntryError]: hasError },\n { [styles.stepperEntryDisabled]: step.disabled },\n { [styles.stepperClickable]: isClickable },\n classNames?.entry,\n );\n\n const markerContent = step.icon ? (\n <FontAwesomeIcon\n icon={step.icon}\n className={classNames?.icon}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n ) : isDone && !hasError ? (\n <Checkmark />\n ) : (\n index + 1\n );\n\n const marker = (\n <div\n className={cx(\n styles.stepperEntryNumber,\n { [styles.stepperEntryNumberDone]: isDone && !hasError },\n classNames?.entryNumber,\n )}\n style={slotStyles?.entryNumber}\n >\n {markerContent}\n </div>\n );\n\n const optionalNode =\n step.optional === true ? 'Optional' : step.optional !== false ? step.optional : null;\n\n const labels = !hideLabels && (\n <div className={styles.stepperEntryLabels}>\n <div\n className={cx(styles.stepperEntryLabel, classNames?.entryLabel)}\n style={slotStyles?.entryLabel}\n >\n {step.label}\n </div>\n {step.description != null && (\n <div\n className={cx(styles.stepperDescription, classNames?.description)}\n style={slotStyles?.description}\n >\n {step.description}\n </div>\n )}\n {optionalNode != null && (\n <div\n className={cx(styles.stepperOptional, classNames?.optional)}\n style={slotStyles?.optional}\n >\n {optionalNode}\n </div>\n )}\n </div>\n );\n\n const interactiveProps: React.HTMLAttributes<HTMLDivElement> = isClickable\n ? {\n role: 'button',\n tabIndex: 0,\n onClick: () => onStepClicked?.(index),\n onKeyDown: (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onStepClicked?.(index);\n }\n },\n }\n : {};\n\n const wrapHeader = (inner: React.ReactNode) => (\n <div\n className={entryClassName}\n style={slotStyles?.entry}\n aria-current={index === currentStep ? 'step' : undefined}\n aria-invalid={hasError || undefined}\n {...interactiveProps}\n >\n {inner}\n </div>\n );\n\n const connector = index < steps.length - 1 && (\n <div\n className={cx(\n styles.stepperConnector,\n { [styles.stepperConnectorFilled]: isDone },\n classNames?.connector,\n )}\n style={slotStyles?.connector}\n />\n );\n\n if (isVertical) {\n const isFirst = index === 0;\n const isLast = index === steps.length - 1;\n const bodyOpen =\n collapse === StepperCollapse.None\n ? true\n : collapse === StepperCollapse.ActiveOnly\n ? index === currentStep\n : !isDone;\n\n const railSegment = (variant: 'lead' | 'trail') => {\n const hidden = variant === 'lead' ? isFirst : isLast;\n const filled = variant === 'lead' ? isActive : isDone;\n return (\n <div\n className={cx(styles.stepperRailSegment, {\n [styles.stepperRailFilled]: !hidden && filled,\n [styles.stepperRailHidden]: hidden,\n })}\n />\n );\n };\n\n const markerCell = (\n <div className={styles.stepperMarkerCell}>\n {railSegment('lead')}\n {marker}\n {railSegment('trail')}\n </div>\n );\n\n return (\n <div key={index} className={styles.stepperStep}>\n {wrapHeader(\n <>\n {markerCell}\n {labels}\n </>,\n )}\n {connector}\n {step.content != null && !hideLabels && (\n <StepBody open={bodyOpen} className={classNames?.content} style={slotStyles?.content}>\n {step.content}\n </StepBody>\n )}\n </div>\n );\n }\n\n return (\n <React.Fragment key={index}>\n {wrapHeader(\n <>\n {marker}\n {labels}\n </>,\n )}\n {connector}\n </React.Fragment>\n );\n })}\n </div>\n );\n}\n","/**\n * Coordinates every mounted `Sticky` so ones that overlap horizontally stack\n * underneath each other (in DOM order) instead of pinning to the same spot.\n * Non-overlapping ones (e.g. side-by-side halves under a full-width one) land\n * at the same top instead of being pushed down by each other.\n */\n\nexport interface StickyStackMetrics {\n /** Current (unstuck-flow) top of the root element, from getBoundingClientRect. */\n top: number;\n left: number;\n width: number;\n contentHeight: number;\n}\n\nexport interface StickyStackEntry {\n node: HTMLElement;\n offsetTop: number;\n disabled: boolean;\n getMetrics: () => StickyStackMetrics | null;\n}\n\nexport interface StickyStackResult {\n isStuck: boolean;\n /** Effective `top` to pin at while stuck — offsetTop plus the height of any stuck, overlapping entries above it. */\n top: number;\n}\n\ntype ResultListener = (result: StickyStackResult) => void;\n\nfunction rangesOverlap(aLeft: number, aRight: number, bLeft: number, bRight: number): boolean {\n return aLeft < bRight && bLeft < aRight;\n}\n\nfunction compareDomOrder(a: HTMLElement, b: HTMLElement): number {\n if (a === b) return 0;\n const position = a.compareDocumentPosition(b);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;\n if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;\n return 0;\n}\n\nclass StickyStack {\n private entries = new Map<symbol, StickyStackEntry>();\n private listeners = new Map<symbol, ResultListener>();\n private results = new Map<symbol, StickyStackResult>();\n private rafId = 0;\n private listenerCount = 0;\n\n schedule = (): void => {\n cancelAnimationFrame(this.rafId);\n this.rafId = requestAnimationFrame(this.recompute);\n };\n\n register(entry: StickyStackEntry, onChange: ResultListener): symbol {\n const id = Symbol('sticky');\n this.entries.set(id, entry);\n this.listeners.set(id, onChange);\n this.startListening();\n return id;\n }\n\n updateEntry(id: symbol, patch: Partial<Pick<StickyStackEntry, 'offsetTop' | 'disabled'>>): void {\n const entry = this.entries.get(id);\n if (entry) Object.assign(entry, patch);\n }\n\n unregister(id: symbol): void {\n if (!this.entries.has(id)) return;\n this.entries.delete(id);\n this.listeners.delete(id);\n this.results.delete(id);\n this.stopListening();\n }\n\n recompute = (): void => {\n const ordered = [...this.entries.entries()].sort(([, a], [, b]) => compareDomOrder(a.node, b.node));\n const placed: { left: number; right: number; bottom: number }[] = [];\n\n for (const [id, entry] of ordered) {\n const metrics = entry.getMetrics();\n if (!metrics) continue;\n\n const overlapping = placed.filter((p) => rangesOverlap(p.left, p.right, metrics.left, metrics.left + metrics.width));\n const baseTop = overlapping.reduce((max, p) => Math.max(max, p.bottom), entry.offsetTop);\n const isStuck = !entry.disabled && metrics.top <= baseTop;\n const result: StickyStackResult = { isStuck, top: isStuck ? baseTop : entry.offsetTop };\n\n if (isStuck) {\n placed.push({ left: metrics.left, right: metrics.left + metrics.width, bottom: baseTop + metrics.contentHeight });\n }\n\n const prev = this.results.get(id);\n if (!prev || prev.isStuck !== result.isStuck || prev.top !== result.top) {\n this.results.set(id, result);\n this.listeners.get(id)?.(result);\n }\n }\n };\n\n private startListening(): void {\n if (this.listenerCount === 0) {\n window.addEventListener('scroll', this.schedule, { passive: true, capture: true });\n window.addEventListener('resize', this.schedule);\n }\n this.listenerCount++;\n }\n\n private stopListening(): void {\n this.listenerCount--;\n if (this.listenerCount === 0) {\n window.removeEventListener('scroll', this.schedule, { capture: true } as EventListenerOptions);\n window.removeEventListener('resize', this.schedule);\n }\n }\n}\n\nexport const stickyStack = new StickyStack();\n",".sticky {\n display: block;\n\n &-content {\n /* No positioning by default — the content lives in normal flow until it sticks. */\n }\n\n &-content-stuck {\n /* Positioning (position/top/left/width/z-index) is applied inline so it can be measured;\n this class is a styling hook for consumers (e.g. a shadow once stuck). */\n }\n\n &-placeholder {\n /* Reserves the exact space the content left behind, so nothing below jumps up. */\n pointer-events: none;\n }\n}\n","import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport type { StickyProps } from './sticky.types';\nimport { stickyStack } from './stickyStack';\nimport type { StickyStackResult } from './stickyStack';\n\nimport styles from './sticky.module.pcss';\n\ninterface Metrics {\n width: number;\n left: number;\n height: number;\n}\n\nexport default function Sticky({\n children,\n offsetTop = 0,\n zIndex = 20,\n disabled = false,\n onStuckChange,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: StickyProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const stackIdRef = useRef<symbol | null>(null);\n const [metrics, setMetrics] = useState<Metrics>({ width: 0, left: 0, height: 0 });\n const [stackResult, setStackResult] = useState<StickyStackResult>({ isStuck: false, top: offsetTop });\n\n const onStuckChangeRef = useRef(onStuckChange);\n useEffect(() => {\n onStuckChangeRef.current = onStuckChange;\n }, [onStuckChange]);\n\n // Local geometry (width/left/height) doesn't depend on other Stickies — only the\n // effective `top` and `isStuck` (from the stack coordinator) do.\n const measure = useCallback(() => {\n const root = rootRef.current;\n const content = contentRef.current;\n if (!root || !content) return;\n const rootRect = root.getBoundingClientRect();\n setMetrics({ width: root.clientWidth, left: rootRect.left, height: content.offsetHeight });\n stickyStack.schedule();\n }, []);\n\n useLayoutEffect(() => {\n const id = stickyStack.register(\n {\n node: rootRef.current as HTMLElement,\n offsetTop,\n disabled,\n getMetrics: () => {\n const root = rootRef.current;\n const content = contentRef.current;\n if (!root || !content) return null;\n const rect = root.getBoundingClientRect();\n return { top: rect.top, left: rect.left, width: root.clientWidth, contentHeight: content.offsetHeight };\n },\n },\n setStackResult,\n );\n stackIdRef.current = id;\n return () => {\n stickyStack.unregister(id);\n stackIdRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (stackIdRef.current) {\n stickyStack.updateEntry(stackIdRef.current, { offsetTop, disabled });\n }\n stickyStack.schedule();\n }, [offsetTop, disabled]);\n\n useLayoutEffect(() => {\n measure();\n }, [measure, children]);\n\n useEffect(() => {\n const ro = new ResizeObserver(measure);\n if (rootRef.current) ro.observe(rootRef.current);\n if (contentRef.current) ro.observe(contentRef.current);\n return () => ro.disconnect();\n }, [measure]);\n\n const firstRun = useRef(true);\n useEffect(() => {\n if (firstRun.current) {\n firstRun.current = false;\n return;\n }\n onStuckChangeRef.current?.(stackResult.isStuck);\n }, [stackResult.isStuck]);\n\n const contentStyle: React.CSSProperties | undefined = stackResult.isStuck\n ? {\n position: 'fixed',\n top: stackResult.top,\n left: metrics.left,\n width: metrics.width,\n zIndex,\n ...slotStyles?.content,\n }\n : slotStyles?.content;\n\n return (\n <div ref={rootRef} className={cx(styles.sticky, className, classNames?.root)} style={{ ...slotStyles?.root, ...style }} {...rest}>\n {stackResult.isStuck && (\n <div\n aria-hidden\n className={cx(styles.stickyPlaceholder, classNames?.placeholder)}\n style={{ height: metrics.height, ...slotStyles?.placeholder }}\n />\n )}\n <div\n ref={contentRef}\n className={cx(styles.stickyContent, stackResult.isStuck && styles.stickyContentStuck, classNames?.content)}\n style={contentStyle}\n >\n {children}\n </div>\n </div>\n );\n}\n",".switch {\n user-select: none;\n display: flex;\n align-items: center;\n column-gap: 0.625em;\n width: fit-content;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n border: 1px solid transparent;\n margin: -1px;\n\n &:focus-visible {\n outline: none;\n border: 1px solid var(--primary-color);\n border-radius: var(--default-border-radius);\n }\n\n &-disabled {\n filter: brightness(0.8);\n cursor: not-allowed;\n }\n\n &-track {\n width: 2.25em;\n height: 1.25em;\n flex-shrink: 0;\n border-radius: var(--default-border-radius);\n background-color: var(--border-color);\n position: relative;\n transition: background-color 0.2s;\n box-sizing: border-box;\n padding: 0.125em;\n\n &-checked {\n background-color: var(--primary-color);\n }\n }\n\n &-thumb {\n width: 1em;\n height: 1em;\n border-radius: var(--default-border-radius);\n background-color: var(--background);\n box-shadow: var(--card-shadow);\n transform: translateX(0);\n transition: transform 0.2s;\n\n &-checked {\n transform: translateX(1em);\n }\n }\n\n &-label {\n line-height: 100%;\n color: var(--text-color);\n }\n}\n","import { useEffect, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { useComponentDefaults } from '../configProvider';\nimport type { SwitchProps } from './switch.types';\nimport styles from './switch.module.pcss';\n\nfunction Switch(props: SwitchProps): ReactElement {\n const {\n label = '',\n selected = false,\n onToggle = () => {},\n className = '',\n style,\n disabled = false,\n title = '',\n tabIndex = 0,\n formValidator = null,\n children = null,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Switch', props);\n const [, forceUpdate] = useState(0);\n\n useEffect(() => {\n if (!formValidator) return;\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n function handleToggle(event?: React.MouseEvent | React.KeyboardEvent) {\n if (disabled) return;\n if (formValidator) {\n formValidator.set(!formValidator.value);\n }\n onToggle(!currSelected, event);\n }\n\n const currSelected = (formValidator ? formValidator.value : selected) as boolean;\n\n return (\n <div\n {...rest}\n title={title}\n className={cx(\n styles.switch,\n {\n [styles.switchDisabled]: disabled,\n },\n className\n )}\n style={style}\n onClick={handleToggle}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleToggle(e);\n }\n }}\n role=\"switch\"\n aria-checked={currSelected}\n tabIndex={disabled ? -1 : tabIndex}\n >\n <div\n className={cx(styles.switchTrack, currSelected && styles.switchTrackChecked, classNames?.track)}\n style={slotStyles?.track}\n >\n <div\n className={cx(styles.switchThumb, currSelected && styles.switchThumbChecked, classNames?.thumb)}\n style={slotStyles?.thumb}\n />\n </div>\n {(children || label) && (\n <div className={cx(styles.switchLabel, classNames?.label)} style={slotStyles?.label}>\n {children || label}\n </div>\n )}\n </div>\n );\n}\n\nexport default Switch;\n",".tabHeader {\n display: flex;\n align-items: stretch;\n gap: 4px;\n border-bottom: 1px solid var(--border-color);\n user-select: none;\n overflow-x: auto;\n\n &-tab {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n color: var(--text-dark);\n border-bottom: 2px solid transparent;\n border-radius: var(--default-border-radius) var(--default-border-radius) 0 0;\n transition: color 0.2s, background 0.2s, border-color 0.2s;\n white-space: nowrap;\n\n &:hover {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n\n &-active {\n color: var(--primary-color);\n border-bottom-color: var(--primary-color);\n\n &:hover {\n color: var(--primary-color);\n }\n }\n\n &-disabled {\n opacity: 0.5;\n pointer-events: none;\n cursor: default;\n }\n }\n\n &-icon {\n font-size: 18px;\n flex-shrink: 0;\n }\n\n &-labels {\n display: flex;\n flex-direction: column;\n text-align: left;\n line-height: 1.25;\n }\n\n &-title {\n font-weight: var(--header-font-weight, 600);\n font-size: var(--default-font-size);\n }\n\n &-subtitle {\n font-size: var(--text-small-font-size);\n color: var(--text-dark);\n }\n}\n\n@media (max-width: 640px) {\n .tabHeader-tab:not(.tabHeader-tab-active) .tabHeader-labels {\n display: none;\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\n\nimport InteractableDiv from '../interactableDiv';\nimport type { TabHeaderProps, TabHeaderTab } from './tabHeader.types';\n\nimport styles from './tabHeader.module.pcss';\n\nfunction TabHeader({\n tabs = [],\n currentTab,\n onChange,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TabHeaderProps) {\n return (\n <div\n {...rest}\n role=\"tablist\"\n className={cx(styles.tabHeader, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n >\n {tabs.map((tab: TabHeaderTab) => {\n const isActive = tab.id === currentTab;\n const hasLabels = !!tab.title || !!tab.subtitle;\n\n return (\n <InteractableDiv\n key={tab.id}\n role=\"tab\"\n aria-selected={isActive}\n aria-disabled={tab.disabled || undefined}\n tabIndex={tab.disabled ? -1 : 0}\n className={cx(\n styles.tabHeaderTab,\n { [styles.tabHeaderTabActive]: isActive },\n { [styles.tabHeaderTabDisabled]: tab.disabled },\n classNames?.tab\n )}\n style={slotStyles?.tab}\n onClick={() => {\n if (tab.disabled || isActive) return;\n onChange(tab.id);\n }}\n >\n <FontAwesomeIcon\n icon={tab.icon}\n className={cx(styles.tabHeaderIcon, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n {hasLabels && (\n <div className={cx(styles.tabHeaderLabels, classNames?.labels)} style={slotStyles?.labels}>\n {tab.title && (\n <span className={cx(styles.tabHeaderTitle, classNames?.title)} style={slotStyles?.title}>\n {tab.title}\n </span>\n )}\n {tab.subtitle && (\n <span className={cx(styles.tabHeaderSubtitle, classNames?.subtitle)} style={slotStyles?.subtitle}>\n {tab.subtitle}\n </span>\n )}\n </div>\n )}\n </InteractableDiv>\n );\n })}\n </div>\n );\n}\n\nexport default TabHeader;\n","import React from 'react';\nimport Input from 'components/common/input';\nimport { useComponentDefaults } from 'components/common/configProvider';\nimport type { TextareaProps } from './textarea.types';\n\nexport default function Textarea(props: TextareaProps) {\n return <Input {...useComponentDefaults('Textarea', props)} multiline />;\n}\n","import type { Theme } from './theme.types';\n\n/**\n * Built-in default theme used by ThemeProvider when no `themes` prop is\n * supplied. Provides a complete set of CSS variables so the component\n * library renders correctly out of the box.\n */\nexport const defaultTheme: Theme = {\n id: 'default',\n variables: {\n '--grey': '#8A8A8A',\n '--lightgrey': '#e0e0e0',\n '--lightergrey': '#B1B1B1',\n '--white': '#FFFFFF',\n '--red': '#D6002A',\n '--lighter-red': '#ffeae9',\n '--green': '#287626',\n '--lighter-green': '#C4FFC9',\n '--blue': '#5873d5',\n '--lighter-blue': '#C6DBFF',\n '--black': 'black',\n '--orange': '#ff7f50',\n '--lighter-orange': '#ffe5d9',\n\n '--primary-color': '#8184d6',\n '--primary-accent': '#90CAF9',\n '--primary-lighter': '#9a9ce4',\n '--accent-color': 'var(--grey)',\n '--accent-color-light': 'var(--lightgrey)',\n\n '--text-color': 'var(--white)',\n '--text-dark': 'var(--lightergrey)',\n '--text-light': 'var(--lightergrey)',\n '--text-on-primary': 'var(--white)',\n '--text-on-delete': 'var(--white)',\n '--border-color': '#656574',\n\n '--background': '#393945',\n '--background-accent': '#33333c',\n '--background-accent-dark': 'var(--grey)',\n '--background-accent-light': '#484856',\n '--background-modal': '#484856',\n\n '--success-color': 'var(--green)',\n '--success-lighter': 'var(--lighter-green)',\n '--error-color': 'var(--red)',\n '--error-lighter': 'var(--lighter-red)',\n '--required-mark-color': 'var(--error-color)',\n '--info-color': 'var(--blue)',\n '--info-lighter': 'var(--lighter-blue)',\n '--warn-color': 'var(--orange)',\n '--warn-lighter': 'var(--lighter-orange)',\n\n '--default-font-size': '14px',\n '--text-small-font-size': '12px',\n '--header-font-size': '24px',\n '--header-medium-font-size': '18px',\n '--header-small-font-size': '16px',\n\n '--default-font-weight': '400',\n '--header-font-weight': '600',\n\n '--input-background': 'transparent',\n '--input-icon-color': 'var(--text-color)',\n '--error-border-color': 'var(--red)',\n\n '--button-default-color': 'var(--primary-color)',\n '--button-default-border': '1px solid var(--primary-color)',\n\n '--default-border-radius': '8px',\n '--padding-sides': '15px',\n '--margin-top': '10px',\n\n '--default-font': \"'Inter', sans-serif\",\n '--themed-font': \"'Inter', sans-serif\",\n\n '--card-shadow':\n '0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%)',\n\n '--background-card-elevated': 'var(--background-accent-light)',\n '--background-card-outlined': 'transparent',\n '--background-card-filled': 'var(--background-accent)',\n\n '--spacing-s': '4px',\n '--spacing-m': '8px',\n '--spacing-l': '16px',\n },\n};\n",".themeRoot {\n font-family: var(--default-font);\n font-size: var(--default-font-size);\n font-weight: var(--default-font-weight);\n color: var(--text-color);\n}\n\n.colorFade * {\n transition: background 0.3s ease-in-out;\n}\n","import React, { Component } from 'react';\nimport cx from 'classnames';\n\nimport type { Theme } from './theme.types';\nimport { defaultTheme } from './defaultTheme';\nimport styles from './theme.module.pcss';\n\ninterface Props {\n children: React.ReactNode;\n themes?: Theme[];\n currentThemeId?: string;\n}\n\ninterface State {\n resolvedVariables: Record<string, string>;\n colorFadeActive: boolean;\n currentThemeColor: string | null;\n}\n\nclass ThemeProvider extends Component<Props, State> {\n state: State = {\n resolvedVariables: {},\n colorFadeActive: false,\n currentThemeColor: null,\n };\n\n private colorFadeTimeout: ReturnType<typeof setTimeout> | null = null;\n private wrapperRef = React.createRef<HTMLDivElement>();\n private themeColorMeta: HTMLMetaElement | null = null;\n private createdThemeColorMeta = false;\n\n componentDidMount() {\n this.applyTheme(this.props.currentThemeId);\n this.syncThemeColorMeta(this.state.currentThemeColor ?? '');\n }\n\n componentDidUpdate(prevProps: Props, prevState: State) {\n if (prevState.currentThemeColor !== this.state.currentThemeColor) {\n this.syncThemeColorMeta(this.state.currentThemeColor ?? '');\n }\n if (\n prevProps.currentThemeId !== this.props.currentThemeId ||\n prevProps.themes !== this.props.themes\n ) {\n this.applyTheme(this.props.currentThemeId);\n }\n }\n\n componentWillUnmount() {\n if (this.colorFadeTimeout) clearTimeout(this.colorFadeTimeout);\n // Only remove the meta tag if we created it; leave a host-app tag intact.\n // Also clear the cached refs — StrictMode's dev-only mount/unmount/remount\n // cycle reuses this instance, and a stale ref would otherwise point at a\n // detached element on remount instead of re-inserting into <head>.\n if (this.createdThemeColorMeta) {\n this.themeColorMeta?.remove();\n this.themeColorMeta = null;\n this.createdThemeColorMeta = false;\n }\n }\n\n /**\n * Replaces the former react-helmet usage: keep a single\n * <meta name=\"theme-color\"> in sync with the active theme's primary colour.\n * Reuses a tag the host app already declares; otherwise creates its own\n * (and removes it again on unmount).\n */\n private syncThemeColorMeta(color: string) {\n if (typeof document === 'undefined') return;\n\n if (!this.themeColorMeta) {\n const existing = document.head.querySelector<HTMLMetaElement>(\n 'meta[name=\"theme-color\"]',\n );\n if (existing) {\n this.themeColorMeta = existing;\n } else {\n const meta = document.createElement('meta');\n meta.setAttribute('name', 'theme-color');\n document.head.appendChild(meta);\n this.themeColorMeta = meta;\n this.createdThemeColorMeta = true;\n }\n }\n\n this.themeColorMeta.setAttribute('content', color);\n }\n\n /**\n * Resolves the full variable set for a given theme ID by walking up the\n * baseThemeId chain. Returns variables ordered from deepest ancestor to\n * the requested theme so callers can merge in order (later entries win).\n */\n private resolveChain(id: string): Record<string, string>[] {\n const themes = this.props.themes ?? [defaultTheme];\n const theme = themes.find((t) => t.id === id);\n if (!theme) return [];\n\n const parentVars = theme.baseThemeId ? this.resolveChain(theme.baseThemeId) : [];\n\n return [...parentVars, theme.variables as Record<string, string>];\n }\n\n private applyTheme = (currentThemeId: string | undefined) => {\n const themes = this.props.themes ?? [defaultTheme];\n\n // The root theme is the first theme without a baseThemeId.\n // It is always applied as the variable foundation.\n const rootTheme = themes.find((t) => !t.baseThemeId) ?? themes[0];\n const rootVars: Record<string, string> = rootTheme\n ? (rootTheme.variables as Record<string, string>)\n : {};\n\n // Resolve the selected theme's full inheritance chain.\n const selectedTheme = themes.find((t) => t.id === currentThemeId);\n const chainVars = selectedTheme ? this.resolveChain(selectedTheme.id) : [];\n\n // Merge: root foundation → ancestor chain → selected theme (each step overrides)\n const resolvedVariables = Object.assign({}, rootVars, ...chainVars);\n\n this.setState({ resolvedVariables, colorFadeActive: true });\n\n if (this.colorFadeTimeout) clearTimeout(this.colorFadeTimeout);\n this.colorFadeTimeout = setTimeout(() => {\n this.setState({ colorFadeActive: false });\n this.colorFadeTimeout = null;\n }, 500);\n\n // Read --primary-color after the new style is painted for the theme-color meta tag.\n setTimeout(() => {\n if (this.wrapperRef.current) {\n this.setState({\n currentThemeColor: getComputedStyle(this.wrapperRef.current)\n .getPropertyValue('--primary-color')\n .trim(),\n });\n }\n }, 1);\n };\n\n render() {\n const { children } = this.props;\n const { resolvedVariables, colorFadeActive } = this.state;\n\n return (\n <div\n ref={this.wrapperRef}\n id=\"themeProvider\"\n className={cx(styles.themeRoot, colorFadeActive && styles.colorFade)}\n style={resolvedVariables as React.CSSProperties}\n >\n {children}\n </div>\n );\n }\n}\n\nexport default ThemeProvider;\n","import { useState } from \"react\";\n\nexport function useTheme(defaultThemeId: string = 'default') {\n const [currentThemeId, setThemeId] = useState<string>(localStorage.getItem('theme') || defaultThemeId);\n\n const setCurrentThemeId = (themeId: string) => {\n setThemeId(themeId);\n localStorage.setItem('theme', themeId);\n };\n\n return { currentThemeId, setCurrentThemeId };\n}","export interface TimeValue {\n hours: number; // 0–23\n minutes: number; // 0–59\n}\n\nexport const clampHour = (h: number): number => ((Math.trunc(h) % 24) + 24) % 24;\nexport const clampMinute = (m: number): number => ((Math.trunc(m) % 60) + 60) % 60;\n\n/** Parse a \"HH:MM\" (24-hour) string. Returns null for anything that isn't a valid time. */\nexport function parseTimeString(value: string | null | undefined): TimeValue | null {\n if (!value) return null;\n const match = value.match(/^(\\d{1,2}):(\\d{1,2})$/);\n if (!match) return null;\n const hours = Number(match[1]);\n const minutes = Number(match[2]);\n if (hours > 23 || minutes > 59) return null;\n return { hours, minutes };\n}\n\n/** Format a TimeValue as a zero-padded \"HH:MM\" string. */\nexport function formatTime(time: TimeValue | null | undefined): string {\n if (!time) return '';\n const hh = String(clampHour(time.hours)).padStart(2, '0');\n const mm = String(clampMinute(time.minutes)).padStart(2, '0');\n return `${hh}:${mm}`;\n}\n\n/** Snap a minute value to the nearest multiple of `step` (step <= 1 is a no-op). */\nexport function snapMinute(minute: number, step: number): number {\n if (!step || step <= 1) return clampMinute(minute);\n return clampMinute(Math.round(clampMinute(minute) / step) * step);\n}\n\nexport const timeToMinutes = (time: TimeValue): number => time.hours * 60 + time.minutes;\n\n/** Clamp a time into [min, max] (both \"HH:MM\" strings, either optional). */\nexport function clampToRange(time: TimeValue, min?: string | null, max?: string | null): TimeValue {\n let total = timeToMinutes(time);\n const minVal = parseTimeString(min);\n const maxVal = parseTimeString(max);\n if (minVal) total = Math.max(total, timeToMinutes(minVal));\n if (maxVal) total = Math.min(total, timeToMinutes(maxVal));\n return { hours: Math.floor(total / 60), minutes: total % 60 };\n}\n\nexport function isWithinRange(time: TimeValue, min?: string | null, max?: string | null): boolean {\n const total = timeToMinutes(time);\n const minVal = parseTimeString(min);\n const maxVal = parseTimeString(max);\n if (minVal && total < timeToMinutes(minVal)) return false;\n if (maxVal && total > timeToMinutes(maxVal)) return false;\n return true;\n}\n\n/**\n * Auto-correct a masked \"HH:MM\" value as the user types: clamp the hour segment to 23\n * and the minute segment to 59 so the field can never hold an impossible time.\n */\nexport function correctTimeMaskValue(value: string): string {\n const digits = value.replace(/[^\\d]/g, '');\n if (!digits) return value;\n\n let hourDigits = digits.slice(0, 2);\n const minuteDigits = digits.slice(2, 4);\n\n // First hour digit > 2 → it can only be a single-digit hour (e.g. \"9\" → \"09\").\n if (hourDigits.length === 1 && Number(hourDigits) > 2) {\n hourDigits = `0${hourDigits}`;\n }\n if (hourDigits.length === 2 && Number(hourDigits) > 23) hourDigits = '23';\n\n let result = hourDigits;\n if (minuteDigits.length > 0 || /:/.test(value)) result += ':';\n if (minuteDigits.length > 0) {\n const clamped = minuteDigits.length === 2 && Number(minuteDigits) > 59 ? '59' : minuteDigits;\n result += clamped;\n }\n return result;\n}\n\n// ── Clock-dial geometry ─────────────────────────────────────────────────────\n\nexport interface DialPoint {\n x: number;\n y: number;\n}\n\n/**\n * Cartesian coordinates for a point on the dial. `slot` is the step index from the\n * top of the clock, going clockwise; `stepDegrees` is the angle between steps\n * (30° for hours, 6° for minutes). Returns coordinates relative to (cx, cy).\n */\nexport function polarPoint(cx: number, cy: number, radius: number, slot: number, stepDegrees: number): DialPoint {\n const theta = (slot * stepDegrees * Math.PI) / 180;\n return {\n x: cx + radius * Math.sin(theta),\n y: cy - radius * Math.cos(theta),\n };\n}\n\n/** Rotation (deg) of a hand pointing at `slot`. A 3-o'clock-default hand points up at slot 0. */\nexport const handAngle = (slot: number, stepDegrees: number): number => slot * stepDegrees - 90;\n\n/** Angle (0–360, clockwise from top) of a pointer at (dx, dy) relative to the dial centre. */\nexport function pointerAngle(dx: number, dy: number): number {\n const deg = (Math.atan2(dx, -dy) * 180) / Math.PI;\n return (deg + 360) % 360;\n}\n\nexport const pointerRadius = (dx: number, dy: number): number => Math.sqrt(dx * dx + dy * dy);\n",".clockFace {\n position: relative;\n width: var(--clock-size, 256px);\n height: var(--clock-size, 256px);\n margin: 4px auto;\n border-radius: 50%;\n background: var(--background-accent-light, var(--background-accent));\n touch-action: none;\n user-select: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n}\n\n.clockHand {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n overflow: visible;\n\n &-line {\n stroke: var(--primary-color);\n stroke-width: 0.7;\n }\n\n &-center {\n fill: var(--primary-color);\n }\n\n &-knob {\n fill: var(--primary-color);\n }\n}\n\n.clockNumber {\n position: absolute;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n color: var(--text-color);\n font-size: 15px;\n font-weight: 500;\n line-height: 1;\n /* Visual only — the face handles all pointer interaction. */\n pointer-events: none;\n z-index: 1;\n\n &-inner {\n font-size: 12px;\n color: var(--text-dark);\n }\n\n &-selected {\n color: var(--text-on-primary);\n font-weight: 600;\n }\n}\n","import React, { useRef } from 'react';\nimport cx from 'classnames';\nimport {\n type TimeValue,\n clampHour,\n snapMinute,\n polarPoint,\n pointerAngle,\n pointerRadius,\n} from '../../timeFunctions';\nimport type { ClockDialProps, DialNumber } from './clockDial.types';\n\nimport styles from './clockDial.module.pcss';\n\n// viewBox units (0–100). The face scales with its CSS box; geometry stays in this space.\nconst CENTER = 50;\nconst OUTER_RADIUS = 40;\nconst INNER_RADIUS = 25.5;\nconst RING_THRESHOLD = (OUTER_RADIUS + INNER_RADIUS) / 2;\n\nconst HOUR_STEP_DEG = 30;\nconst MINUTE_STEP_DEG = 6;\n\nconst to12 = (hour: number): number => ((hour + 11) % 12) + 1;\n\n/** Build the labelled numbers for the current mode/format. */\nfunction buildNumbers(mode: 'hours' | 'minutes', use24Hour: boolean): DialNumber[] {\n if (mode === 'minutes') {\n return Array.from({ length: 12 }, (_, slot) => {\n const value = slot * 5;\n return { label: String(value).padStart(2, '0'), slot, value, ring: 'outer' as const };\n });\n }\n\n if (!use24Hour) {\n return Array.from({ length: 12 }, (_, slot) => {\n const value = slot === 0 ? 12 : slot; // displayed hour (1–12)\n return { label: String(value), slot, value, ring: 'outer' as const };\n });\n }\n\n // 24-hour double ring: outer 1–12, inner 00/13–23.\n const outer = Array.from({ length: 12 }, (_, slot) => {\n const value = slot === 0 ? 12 : slot;\n return { label: String(value), slot, value, ring: 'outer' as const };\n });\n const inner = Array.from({ length: 12 }, (_, slot) => {\n const value = slot === 0 ? 0 : slot + 12;\n return { label: String(value).padStart(2, '0'), slot, value, ring: 'inner' as const };\n });\n return [...outer, ...inner];\n}\n\nexport default function ClockDial({\n time,\n mode,\n use24Hour,\n minuteStep,\n onChange,\n onCommit,\n classNames,\n styles: slotStyles,\n}: ClockDialProps) {\n const faceRef = useRef<HTMLDivElement>(null);\n const draggingRef = useRef(false);\n\n const numbers = buildNumbers(mode, use24Hour);\n\n // Resolve the active value and the hand geometry for the current time.\n const isPm = time.hours >= 12;\n const selectedHour12 = to12(time.hours);\n\n const hand = (() => {\n if (mode === 'minutes') {\n // 6° per minute → angle = minutes * MINUTE_STEP_DEG.\n return { slot: time.minutes, radius: OUTER_RADIUS };\n }\n if (!use24Hour) {\n return { slot: selectedHour12 % 12, radius: OUTER_RADIUS };\n }\n if (time.hours === 0) return { slot: 0, radius: INNER_RADIUS };\n if (time.hours <= 12) return { slot: time.hours % 12, radius: OUTER_RADIUS };\n return { slot: (time.hours - 12) % 12, radius: INNER_RADIUS };\n })();\n\n const knob = polarPoint(CENTER, CENTER, hand.radius, hand.slot, mode === 'minutes' ? MINUTE_STEP_DEG : HOUR_STEP_DEG);\n\n const isSelected = (n: DialNumber): boolean =>\n mode === 'minutes'\n ? snapMinute(time.minutes, minuteStep) === n.value || time.minutes === n.value\n : use24Hour\n ? time.hours === n.value\n : selectedHour12 === n.value;\n\n const valueFromPointer = (clientX: number, clientY: number): TimeValue => {\n const rect = faceRef.current?.getBoundingClientRect();\n if (!rect) return time;\n const dx = clientX - (rect.left + rect.width / 2);\n const dy = clientY - (rect.top + rect.height / 2);\n const angle = pointerAngle(dx, dy);\n\n if (mode === 'minutes') {\n const minutes = snapMinute(Math.round(angle / MINUTE_STEP_DEG), minuteStep);\n return { hours: time.hours, minutes };\n }\n\n const slot = Math.round(angle / HOUR_STEP_DEG) % 12;\n if (!use24Hour) {\n const display = slot === 0 ? 12 : slot;\n const hours = isPm ? (display % 12) + 12 : display % 12;\n return { hours: clampHour(hours), minutes: time.minutes };\n }\n\n // 24h: inner vs outer ring decided by pointer distance from centre.\n const radiusFrac = (pointerRadius(dx, dy) / (rect.width / 2)) * CENTER;\n const inner = radiusFrac < RING_THRESHOLD;\n const hours = inner ? (slot === 0 ? 0 : slot + 12) : slot === 0 ? 12 : slot;\n return { hours: clampHour(hours), minutes: time.minutes };\n };\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n draggingRef.current = true;\n // setPointerCapture keeps move/up events flowing to the face even when the\n // pointer started on (or drags over) a number. Guarded for jsdom.\n (e.currentTarget as HTMLElement).setPointerCapture?.(e.pointerId);\n onChange(valueFromPointer(e.clientX, e.clientY));\n };\n\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggingRef.current) return;\n onChange(valueFromPointer(e.clientX, e.clientY));\n };\n\n const handlePointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!draggingRef.current) return;\n draggingRef.current = false;\n onCommit(valueFromPointer(e.clientX, e.clientY));\n };\n\n return (\n <div\n ref={faceRef}\n className={cx(styles.clockFace, classNames?.clockFace)}\n style={slotStyles?.clockFace}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n role=\"slider\"\n aria-label={mode === 'minutes' ? 'Minutes' : 'Hours'}\n aria-valuetext={mode === 'minutes' ? `${time.minutes} minutes` : `${time.hours} hours`}\n >\n <svg className={styles.clockHand} viewBox=\"0 0 100 100\" aria-hidden>\n <circle cx={CENTER} cy={CENTER} r={1.8} className={styles.clockHandCenter} />\n <line x1={CENTER} y1={CENTER} x2={knob.x} y2={knob.y} className={styles.clockHandLine} />\n <circle\n cx={knob.x}\n cy={knob.y}\n r={7}\n className={cx(styles.clockHandKnob, classNames?.clockHand)}\n style={slotStyles?.clockHand as React.CSSProperties}\n />\n </svg>\n\n {numbers.map((n) => {\n const p = polarPoint(CENTER, CENTER, n.ring === 'inner' ? INNER_RADIUS : OUTER_RADIUS, n.slot, HOUR_STEP_DEG);\n const selected = isSelected(n);\n // Purely visual — the face owns all pointer handling so click and drag\n // behave identically whether the pointer lands on a number or between two.\n return (\n <div\n key={`${n.ring}-${n.value}`}\n className={cx(\n styles.clockNumber,\n n.ring === 'inner' && styles.clockNumberInner,\n selected && styles.clockNumberSelected,\n classNames?.clockNumber,\n )}\n style={{ left: `${p.x}%`, top: `${p.y}%`, ...slotStyles?.clockNumber }}\n >\n {n.label}\n </div>\n );\n })}\n </div>\n );\n}\n",".timeInput {\n position: relative;\n width: 100%;\n flex: 1;\n min-width: 105px;\n\n &-clock {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px;\n min-width: 280px;\n }\n\n &-clockHeader {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n margin-bottom: 4px;\n }\n\n &-headerSegment {\n border: none;\n background: var(--background-accent);\n color: var(--text-dark);\n font-size: 32px;\n font-weight: 600;\n line-height: 1;\n padding: 6px 10px;\n border-radius: var(--default-border-radius);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &-active {\n background: var(--primary-color);\n color: var(--text-on-primary);\n }\n }\n\n &-headerColon {\n font-size: 32px;\n font-weight: 600;\n color: var(--text-dark);\n }\n\n &-meridiem {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-left: 8px;\n\n & button {\n border: 1px solid var(--border-color);\n background: var(--background-accent);\n color: var(--text-dark);\n font-size: 12px;\n font-weight: 600;\n padding: 3px 8px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:first-child { border-radius: var(--default-border-radius) var(--default-border-radius) 0 0; }\n &:last-child { border-radius: 0 0 var(--default-border-radius) var(--default-border-radius); }\n }\n\n &-active {\n background: var(--primary-color) !important;\n color: var(--text-on-primary) !important;\n }\n }\n\n &-footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 4px;\n }\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport InputMask, { type BeforeMaskedStateChangeStates, type InputState } from '@mona-health/react-input-mask';\nimport { faClock } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport Input from '../input';\nimport Modal from '../modal';\nimport FloatingMenu from '../floatingMenu';\nimport Button from '../button';\nimport { ButtonStyleType } from '../button/button.types';\nimport Tooltip from '../tooltip';\nimport ClockDial from './components/clockDial';\nimport { Align } from '../floatingMenu/floatingMenu.types';\nimport {\n type TimeValue,\n parseTimeString,\n formatTime,\n snapMinute,\n clampToRange,\n clampHour,\n} from './timeFunctions';\nimport type { TimeInputProps } from './timeInput.types';\n\nimport styles from './timeInput.module.pcss';\n\ntype ClockMode = 'hours' | 'minutes';\n\nexport default function TimeInput({\n value,\n selected,\n onChange = () => null,\n onSelect = () => null,\n formValidator = null,\n isInline = false,\n isModal = false,\n noInput = false,\n noHeader = false,\n showClearButton = false,\n showNowButton = false,\n minuteStep = 1,\n use24Hour = true,\n minTime = null,\n maxTime = null,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n disabled = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimeInputProps) {\n const getExternalString = (): string => {\n if (formValidator) return (formValidator.value as string) || '';\n return value ?? selected ?? '';\n };\n\n const [currentTimeString, setCurrentTimeString] = useState(getExternalString);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [mode, setMode] = useState<ClockMode>('hours');\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const externalString = getExternalString();\n const [prevExternal, setPrevExternal] = useState(externalString);\n const fvRef = useRef(formValidator);\n\n // Sync when the controlled value changes externally.\n if (!formValidator && prevExternal !== externalString) {\n setPrevExternal(externalString);\n setCurrentTimeString(externalString);\n }\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n setCurrentTimeString((formValidator.value as string) || '');\n forceUpdate((n) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean =>\n formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n\n const computedIsRequired = (): boolean =>\n !!(isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'));\n\n /** Push a value out to formValidator/onChange without touching the input string. */\n const emit = (time: TimeValue | null) => {\n const str = time ? formatTime(time) : null;\n if (formValidator) formValidator.set(str);\n onChange?.(str);\n };\n\n const applyTime = (time: TimeValue | null) => {\n setCurrentTimeString(time ? formatTime(time) : '');\n emit(time);\n };\n\n const parsed = parseTimeString(currentTimeString);\n const dialTime: TimeValue = parsed ?? { hours: 12, minutes: 0 };\n\n const handleDialChange = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n applyTime(clampToRange(snapped, minTime, maxTime));\n };\n\n const handleDialCommit = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n const next = clampToRange(snapped, minTime, maxTime);\n applyTime(next);\n if (mode === 'hours') {\n setMode('minutes');\n return;\n }\n onSelect?.(formatTime(next));\n if (!isInline) setIsPickerOpen(false);\n };\n\n const openPicker = () => {\n if (disabled) return;\n setMode('hours');\n setIsPickerOpen(true);\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): InputState => {\n if (!previousState || nextState.value === previousState.value) return nextState;\n let v = nextState.value;\n const hourStr = v.slice(0, 2);\n if (/^\\d\\d$/.test(hourStr) && Number(hourStr) > 23) v = `23${v.slice(2)}`;\n const minStr = v.slice(3, 5);\n if (/^\\d\\d$/.test(minStr) && Number(minStr) > 59) v = `${v.slice(0, 3)}59`;\n return v === nextState.value ? nextState : { ...nextState, value: v };\n };\n\n const handleInputChange = (v: string) => {\n setCurrentTimeString(v);\n const t = parseTimeString(v);\n if (t) emit(t);\n };\n\n const handleBlur = () => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n emit(parseTimeString(currentTimeString));\n };\n\n const setMeridiem = (pm: boolean) => {\n const isPm = dialTime.hours >= 12;\n if (pm === isPm) return;\n applyTime({ hours: clampHour(dialTime.hours + (pm ? 12 : -12)), minutes: dialTime.minutes });\n };\n\n const hasErr = hasError();\n const displayHours = parsed ? String(use24Hour ? parsed.hours : ((parsed.hours + 11) % 12) + 1).padStart(2, '0') : '--';\n const displayMinutes = parsed ? String(parsed.minutes).padStart(2, '0') : '--';\n\n const header = noHeader ? null : (\n <div className={cx(styles.timeInputClockHeader, classNames?.clockHeader)} style={slotStyles?.clockHeader}>\n <button\n type=\"button\"\n className={cx(styles.timeInputHeaderSegment, mode === 'hours' && styles.timeInputHeaderSegmentActive, classNames?.headerSegment)}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('hours')}\n >\n {displayHours}\n </button>\n <span className={styles.timeInputHeaderColon}>:</span>\n <button\n type=\"button\"\n className={cx(styles.timeInputHeaderSegment, mode === 'minutes' && styles.timeInputHeaderSegmentActive, classNames?.headerSegment)}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('minutes')}\n >\n {displayMinutes}\n </button>\n {!use24Hour && (\n <div className={cx(styles.timeInputMeridiem, classNames?.meridiem)} style={slotStyles?.meridiem}>\n <button type=\"button\" className={cx(dialTime.hours < 12 && styles.timeInputMeridiemActive)} onClick={() => setMeridiem(false)}>AM</button>\n <button type=\"button\" className={cx(dialTime.hours >= 12 && styles.timeInputMeridiemActive)} onClick={() => setMeridiem(true)}>PM</button>\n </div>\n )}\n </div>\n );\n\n const footer =\n showClearButton || showNowButton ? (\n <div className={cx(styles.timeInputFooter, classNames?.footer)} style={slotStyles?.footer}>\n {showNowButton && (\n <Button\n styleType={ButtonStyleType.Default}\n onClick={() => {\n const now = new Date();\n handleDialChange({ hours: now.getHours(), minutes: now.getMinutes() });\n }}\n >\n Now\n </Button>\n )}\n {showClearButton && (\n <Button styleType={ButtonStyleType.Default} onClick={() => { applyTime(null); onSelect?.(null); }}>\n Clear\n </Button>\n )}\n </div>\n ) : null;\n\n const pickerContent = (\n <div className={cx(styles.timeInputClock, classNames?.clock)} style={slotStyles?.clock}>\n {header}\n <ClockDial\n time={dialTime}\n mode={mode}\n use24Hour={use24Hour}\n minuteStep={minuteStep}\n onChange={handleDialChange}\n onCommit={handleDialCommit}\n classNames={classNames}\n styles={slotStyles}\n />\n {footer}\n </div>\n );\n\n const input = noInput ? null : (\n <Input\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentTimeString}\n icon={<FontAwesomeIcon icon={faClock} />}\n onIconClick={openPicker}\n onClick={openPicker}\n readOnly={isModal}\n disabled={disabled}\n isValid={!hasErr}\n customInput={<InputMask mask=\"99:99\" maskPlaceholder=\"_\" beforeMaskedStateChange={beforeMaskedStateChange} />}\n onChange={(v) => handleInputChange(v as string)}\n onBlur={handleBlur}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <FloatingMenu\n isOpen={isPickerOpen}\n onOpenChange={setIsPickerOpen}\n content={pickerContent}\n align={Align.Left}\n dontCloseOnChildClick\n >\n {input}\n </FloatingMenu>\n );\n })();\n\n return (\n <div className={cx(styles.timeInput, classNames?.root, className)} style={{ ...slotStyles?.root, ...style }} {...rest}>\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() ?? '' : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n",".container {\n position: fixed;\n z-index: 9999;\n display: flex;\n flex-direction: column;\n gap: 8px;\n pointer-events: none;\n padding: 16px;\n box-sizing: border-box;\n\n &-top-left {\n top: 0;\n left: 0;\n align-items: flex-start;\n }\n\n &-top-center {\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n }\n\n &-top-right {\n top: 0;\n right: 0;\n align-items: flex-end;\n }\n\n &-bottom-left {\n bottom: 0;\n left: 0;\n align-items: flex-start;\n flex-direction: column-reverse;\n }\n\n &-bottom-center {\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n flex-direction: column-reverse;\n }\n\n &-bottom-right {\n bottom: 0;\n right: 0;\n align-items: flex-end;\n flex-direction: column-reverse;\n }\n}\n\n.toast {\n pointer-events: all;\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 14px;\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n color: var(--text-color);\n font-family: var(--default-font);\n box-shadow: var(--card-shadow);\n min-width: 240px;\n max-width: 380px;\n box-sizing: border-box;\n position: relative;\n /* Tells the browser vertical panning is native (so the page can still scroll behind the toast)\n while horizontal movement is left for useSwipeDismiss's own pointer handling to decide. */\n touch-action: pan-y;\n overflow: hidden;\n animation: toastSlideDown 0.25s ease forwards;\n\n &-bottom {\n animation: toastSlideUp 0.25s ease forwards;\n }\n\n &-dismissing {\n animation: toastFadeOut 0.2s ease forwards;\n }\n\n &-paused .toastProgressBar {\n animation-play-state: paused;\n }\n\n &-info {\n border-left: 3px solid var(--info-color, #3b82f6);\n\n .toastIcon {\n color: var(--info-color, #3b82f6);\n }\n }\n\n &-success {\n border-left: 3px solid var(--success-color);\n\n .toastIcon {\n color: var(--success-color);\n }\n }\n\n &-error {\n border-left: 3px solid var(--error-color, #ef4444);\n\n .toastIcon {\n color: var(--error-color, #ef4444);\n }\n }\n\n &-warn {\n border-left: 3px solid var(--warn-color);\n\n .toastIcon {\n color: var(--warn-color);\n }\n }\n\n &-default {\n border-left: 3px solid var(--primary-color);\n\n .toastIcon {\n color: var(--primary-color);\n }\n }\n}\n\n.toastIcon {\n flex-shrink: 0;\n margin-top: 1px;\n font-size: 15px;\n}\n\n.toastContent {\n flex: 1;\n font-size: 14px;\n line-height: 1.4;\n}\n\n.toastCloseButton {\n flex-shrink: 0;\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 0;\n color: var(--text-dark);\n font-size: 13px;\n opacity: 0.6;\n transition: opacity 0.15s;\n margin-top: 1px;\n\n &:hover {\n opacity: 1;\n }\n}\n\n.toastProgressBar {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 3px;\n width: 100%;\n background: currentColor;\n opacity: 0.35;\n transform-origin: left;\n animation: toastShrink var(--toast-duration) linear forwards;\n}\n\n@keyframes toastSlideDown {\n from {\n opacity: 0;\n transform: translateY(-12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastSlideUp {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastFadeOut {\n from {\n opacity: 1;\n transform: scale(1);\n }\n to {\n opacity: 0;\n transform: scale(0.92);\n }\n}\n\n@keyframes toastShrink {\n from {\n transform: scaleX(1);\n }\n to {\n transform: scaleX(0);\n }\n}\n","import { useEffect, useRef, useState } from 'react';\n\nexport interface UseSwipeDismissOptions {\n /** Called once the swipe commits (past the threshold) — after the exit transition finishes,\n * not the instant the pointer is released. */\n onDismiss: () => void;\n /** Which axis the drag tracks (default `'x'`, the natural direction for a toast/notification). */\n axis?: 'x' | 'y';\n /** Distance in px past which releasing counts as a commit, regardless of speed (default `80`). */\n distanceThreshold?: number;\n /** Speed in px/ms past which releasing counts as a commit, regardless of distance (default `0.5`) —\n * lets a fast flick dismiss even if the pointer didn't travel very far. */\n velocityThreshold?: number;\n /** Disables the gesture entirely — no listeners are attached. */\n disabled?: boolean;\n /** Restricts the gesture to coarse (touch) pointers, auto-detected via `matchMedia`. On a\n * mouse/trackpad device a drag is more likely to be a text selection than an intentional\n * dismiss, and other affordances (a close button, auto-dismiss) typically already cover that\n * case. Default `true`; set `false` to allow the gesture on any pointer type. */\n mobileOnly?: boolean;\n}\n\nexport interface UseSwipeDismissResult<T extends HTMLElement> {\n /** Attach to the element that should become draggable. The hook wires up its own pointer\n * listeners on this node directly (no handlers to spread), so this is the only thing to attach. */\n ref: React.RefObject<T | null>;\n /** True for the duration of an active drag — e.g. use it to pause an auto-dismiss timer. */\n isDragging: boolean;\n}\n\nconst EXIT_TRANSITION_MS = 180;\n// Below this many px of movement, direction intent isn't decided yet — lets a vertical scroll\n// gesture that merely starts on the element pass through instead of being hijacked as a swipe.\nconst AXIS_LOCK_THRESHOLD = 10;\n\n/**\n * Drag-to-dismiss on any pointer type (touch, mouse, pen) via the Pointer Events API. Applies the\n * drag offset and a fading opacity directly to the DOM node (bypassing React state) so the visual\n * tracks the pointer at native speed, then either springs back or animates fully off-screen and\n * calls `onDismiss` once that exit transition completes.\n */\nexport function useSwipeDismiss<T extends HTMLElement>({\n onDismiss,\n axis = 'x',\n distanceThreshold = 80,\n velocityThreshold = 0.5,\n disabled = false,\n mobileOnly = true,\n}: UseSwipeDismissOptions): UseSwipeDismissResult<T> {\n const ref = useRef<T>(null);\n const [isDragging, setIsDragging] = useState(false);\n\n const [isCoarsePointer, setIsCoarsePointer] = useState(\n () => typeof window !== 'undefined' && typeof window.matchMedia === 'function' && window.matchMedia('(pointer: coarse)').matches\n );\n useEffect(() => {\n if (typeof window.matchMedia !== 'function') return;\n const mql = window.matchMedia('(pointer: coarse)');\n const onChange = (event: MediaQueryListEvent) => setIsCoarsePointer(event.matches);\n mql.addEventListener('change', onChange);\n return () => mql.removeEventListener('change', onChange);\n }, []);\n\n const effectiveDisabled = disabled || (mobileOnly && !isCoarsePointer);\n\n // Mutable across the life of one drag; doesn't need to trigger re-renders.\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n startTime: number;\n offset: number;\n axisLocked: boolean;\n active: boolean;\n } | null>(null);\n\n const onDismissRef = useRef(onDismiss);\n useEffect(() => {\n onDismissRef.current = onDismiss;\n });\n\n useEffect(() => {\n const el = ref.current;\n if (!el || effectiveDisabled) return;\n\n function applyTransform(offset: number, transition: string) {\n if (!el) return;\n if (transition !== 'none') {\n // Switching straight from the live drag's `transition: none` to an animated one, in the\n // same tick as the transform change, can get coalesced into a single frame with no\n // animation in between — the element just jumps to its end state instead of sliding\n // there. Forcing a layout read first commits the current (pre-transition) position as\n // its own frame, so the transition below actually has something to animate from.\n void el.offsetHeight;\n }\n const translate = axis === 'x' ? `translateX(${offset}px)` : `translateY(${offset}px)`;\n el.style.transition = transition;\n el.style.transform = translate;\n const fade = Math.max(0, 1 - Math.abs(offset) / (distanceThreshold * 2.5));\n el.style.opacity = String(fade);\n }\n\n function onPointerMove(event: PointerEvent) {\n const drag = dragRef.current;\n if (!drag || event.pointerId !== drag.pointerId) return;\n\n const deltaX = event.clientX - drag.startX;\n const deltaY = event.clientY - drag.startY;\n\n if (!drag.axisLocked) {\n const primary = axis === 'x' ? deltaX : deltaY;\n const cross = axis === 'x' ? deltaY : deltaX;\n if (Math.abs(primary) < AXIS_LOCK_THRESHOLD && Math.abs(cross) < AXIS_LOCK_THRESHOLD) return;\n if (Math.abs(cross) > Math.abs(primary)) {\n // The gesture is mostly along the other axis (e.g. a page scroll) — hand it back.\n drag.active = false;\n return;\n }\n drag.axisLocked = true;\n setIsDragging(true);\n }\n\n if (!drag.active) return;\n event.preventDefault();\n drag.offset = axis === 'x' ? deltaX : deltaY;\n applyTransform(drag.offset, 'none');\n }\n\n function finishDrag() {\n const drag = dragRef.current;\n dragRef.current = null;\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', finishDrag);\n window.removeEventListener('pointercancel', finishDrag);\n if (!drag || !drag.active || !drag.axisLocked) {\n setIsDragging(false);\n return;\n }\n\n const elapsed = Math.max(1, Date.now() - drag.startTime);\n const velocity = drag.offset / elapsed;\n const committed =\n Math.abs(drag.offset) >= distanceThreshold || Math.abs(velocity) >= velocityThreshold;\n\n if (committed) {\n const width = el?.getBoundingClientRect().width ?? 0;\n const exitOffset = Math.sign(drag.offset || 1) * (width + 40);\n applyTransform(exitOffset, `transform ${EXIT_TRANSITION_MS}ms ease-out, opacity ${EXIT_TRANSITION_MS}ms ease-out`);\n setTimeout(() => onDismissRef.current(), EXIT_TRANSITION_MS);\n } else {\n applyTransform(0, `transform ${EXIT_TRANSITION_MS}ms ease-out, opacity ${EXIT_TRANSITION_MS}ms ease-out`);\n }\n setIsDragging(false);\n }\n\n function onPointerDown(event: PointerEvent) {\n if (dragRef.current || !el) return;\n // A still-\"forwards\"-filling CSS animation (e.g. the toast's entrance slide) wins the\n // cascade over an inline style.transform, so the drag offset below would silently never\n // show up on screen unless the animation is cleared first.\n el.style.animation = 'none';\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n startTime: Date.now(),\n offset: 0,\n axisLocked: false,\n active: true,\n };\n window.addEventListener('pointermove', onPointerMove, { passive: false });\n window.addEventListener('pointerup', finishDrag);\n window.addEventListener('pointercancel', finishDrag);\n }\n\n el.addEventListener('pointerdown', onPointerDown);\n return () => {\n el.removeEventListener('pointerdown', onPointerDown);\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', finishDrag);\n window.removeEventListener('pointercancel', finishDrag);\n };\n }, [axis, distanceThreshold, velocityThreshold, effectiveDisabled]);\n\n return { ref, isDragging };\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faCircleInfo,\n faCircleCheck,\n faCircleXmark,\n faTriangleExclamation,\n faBell,\n faXmark,\n} from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './toast.module.pcss';\nimport type { ToastItem } from './toast.types';\nimport ActionIcon from '../actionIcon';\nimport { useSwipeDismiss } from '../hooks/useSwipeDismiss';\n\ninterface ToastProps {\n item: ToastItem;\n isBottom: boolean;\n onDismiss: (id: string) => void;\n}\n\nconst typeIcons = {\n info: faCircleInfo,\n success: faCircleCheck,\n error: faCircleXmark,\n warn: faTriangleExclamation,\n default: faBell,\n};\n\nfunction Toast({ item, isBottom, onDismiss }: ToastProps) {\n const { id, content, options, dismissing } = item;\n const { duration, showRemainingTime, showCloseButton, pauseOnHover, type, classNames, styles: slotStyles } = options;\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n\n const [swiped, setSwiped] = useState(false);\n const { ref: swipeRef, isDragging } = useSwipeDismiss<HTMLDivElement>({\n onDismiss: () => {\n setSwiped(true);\n onDismiss(id);\n },\n });\n\n const paused = (pauseOnHover && (hovered || focused)) || isDragging;\n\n // Remaining time is carried across pause/resume cycles so the timer continues\n // where it left off instead of restarting on every hover.\n const remainingRef = useRef(duration);\n\n useEffect(() => {\n if (duration === 0 || paused) return;\n const start = Date.now();\n const timer = setTimeout(() => onDismiss(id), remainingRef.current);\n return () => {\n clearTimeout(timer);\n remainingRef.current -= Date.now() - start;\n };\n }, [id, duration, onDismiss, paused]);\n\n return (\n <div\n ref={swipeRef}\n className={cx(\n styles.toast,\n isBottom ? styles.toastBottom : null,\n styles[`toast-${type}`],\n dismissing && !swiped && styles.toastDismissing,\n paused && styles.toastPaused,\n classNames?.root,\n )}\n style={slotStyles?.root}\n onMouseEnter={pauseOnHover ? () => setHovered(true) : undefined}\n onMouseLeave={pauseOnHover ? () => setHovered(false) : undefined}\n onFocus={pauseOnHover ? () => setFocused(true) : undefined}\n onBlur={pauseOnHover ? () => setFocused(false) : undefined}\n >\n <FontAwesomeIcon\n icon={typeIcons[type]}\n className={cx(styles.toastIcon, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n\n <div className={cx(styles.toastContent, classNames?.content)} style={slotStyles?.content}>\n {content}\n </div>\n\n {showCloseButton && (\n <ActionIcon\n icon={faXmark}\n onClick={() => onDismiss(id)}\n className={cx(styles.toastCloseButton, classNames?.closeButton)}\n style={slotStyles?.closeButton}\n aria-label=\"Close\"\n />\n )}\n\n {showRemainingTime && duration > 0 && (\n <div\n className={cx(styles.toastProgressBar, classNames?.progressBar)}\n style={{ '--toast-duration': `${duration}ms`, ...slotStyles?.progressBar } as React.CSSProperties}\n />\n )}\n </div>\n );\n}\n\nexport default Toast;\n","import type { ReactNode } from 'react';\nimport type { ToastOptions } from './toast.types';\n\ntype ShowToastFn = (content: ReactNode, options?: ToastOptions) => void;\n\nlet _handler: ShowToastFn | null = null;\n\nexport function _registerToastHandler(fn: ShowToastFn): void {\n _handler = fn;\n}\n\nexport function _unregisterToastHandler(): void {\n _handler = null;\n}\n\nexport function showToast(content: ReactNode, options?: ToastOptions): void {\n if (!_handler) {\n console.error('[Toast] No ToastProvider found. Wrap your app with <ToastProvider>.');\n return;\n }\n _handler(content, options);\n}\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './toast.module.pcss';\nimport Toast from './toast';\nimport { _registerToastHandler, _unregisterToastHandler } from './toastService';\nimport type { ToastContextConfig, ToastItem, ToastOptions, ResolvedToastOptions, ToastPosition } from './toast.types';\nimport type { ReactNode } from 'react';\n\nconst DEFAULTS: Required<ToastContextConfig> = {\n position: 'top-right',\n duration: 4000,\n showRemainingTime: true,\n showCloseButton: true,\n allowStacking: true,\n pauseOnHover: true,\n};\n\nconst DISMISS_ANIMATION_MS = 220;\n\nfunction positionToClass(position: ToastPosition): string {\n return styles[`container-${position}`];\n}\n\ninterface ToastProviderProps extends ToastContextConfig {\n children: ReactNode;\n}\n\nfunction ToastProvider({\n children,\n position = DEFAULTS.position,\n duration = DEFAULTS.duration,\n showRemainingTime = DEFAULTS.showRemainingTime,\n showCloseButton = DEFAULTS.showCloseButton,\n allowStacking = DEFAULTS.allowStacking,\n pauseOnHover = DEFAULTS.pauseOnHover,\n}: ToastProviderProps) {\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n const counterRef = useRef(0);\n\n const dismiss = useCallback((id: string) => {\n setToasts((prev) =>\n prev.map((t) => (t.id === id ? { ...t, dismissing: true } : t)),\n );\n setTimeout(() => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, DISMISS_ANIMATION_MS);\n }, []);\n\n const addToast = useCallback(\n (content: ReactNode, options?: ToastOptions) => {\n const resolved: ResolvedToastOptions = {\n position: options?.position ?? position,\n duration: options?.duration ?? duration,\n showRemainingTime: options?.showRemainingTime ?? showRemainingTime,\n showCloseButton: options?.showCloseButton ?? showCloseButton,\n pauseOnHover: options?.pauseOnHover ?? pauseOnHover,\n type: options?.type ?? 'default',\n classNames: options?.classNames,\n styles: options?.styles,\n };\n\n counterRef.current += 1;\n const id = `toast-${counterRef.current}`;\n const newToast: ToastItem = { id, content, options: resolved, dismissing: false };\n\n setToasts((prev) => {\n if (!allowStacking && prev.length > 0) {\n // Mark all existing as dismissing, then replace\n setTimeout(() => {\n setToasts([newToast]);\n }, DISMISS_ANIMATION_MS);\n return prev.map((t) => ({ ...t, dismissing: true }));\n }\n return [...prev, newToast];\n });\n },\n [position, duration, showRemainingTime, showCloseButton, allowStacking, pauseOnHover],\n );\n\n useEffect(() => {\n _registerToastHandler(addToast);\n return () => _unregisterToastHandler();\n }, [addToast]);\n\n // Group toasts by position so per-toast position overrides work correctly\n const byPosition = toasts.reduce<Record<string, ToastItem[]>>((acc, t) => {\n const pos = t.options.position;\n if (!acc[pos]) acc[pos] = [];\n acc[pos].push(t);\n return acc;\n }, {});\n\n return (\n <>\n {children}\n <BodyEnd>\n {Object.entries(byPosition).map(([pos, items]) => (\n <div\n key={pos}\n className={cx(styles.container, positionToClass(pos as typeof position))}\n >\n {items.map((item) => (\n <Toast\n key={item.id}\n item={item}\n isBottom={pos.startsWith('bottom')}\n onDismiss={dismiss}\n />\n ))}\n </div>\n ))}\n </BodyEnd>\n </>\n );\n}\n\nexport default ToastProvider;\nexport type { ToastProviderProps };\n",".virtualList {\n overflow-y: auto;\n box-sizing: border-box;\n color: var(--text-color);\n font-family: var(--default-font);\n /* Disable the browser's own scroll anchoring — the component does its own\n scroll-position correction when row heights change, and the two fighting\n each other causes the thumb to desync while dragging. */\n overflow-anchor: none;\n /* Reserve the scrollbar gutter so rows don't re-wrap (and re-measure) when the\n vertical scrollbar appears/disappears as content grows. */\n scrollbar-gutter: stable;\n /* Establish a stacking context so every z-index inside the list (sticky\n header, toggle popover, drag clone) stays scoped to this component and\n can't paint over outside content like a modal. */\n isolation: isolate;\n\n &-drag-clone {\n box-sizing: border-box;\n contain: layout paint style;\n cursor: grabbing;\n /* It tracks the finger via transform — never animate that. */\n transition: none;\n }\n\n &-header {\n display: grid;\n position: sticky;\n top: 0;\n /* Above focused rows (z-index 1) so a focused row scrolled under the header\n never paints over it; the drag clone (z-index 3) still floats above both. */\n z-index: 2;\n background: var(--background-accent);\n border-bottom: 1px solid var(--border-color);\n box-sizing: border-box;\n\n &-cell {\n padding: 8px 12px;\n font-weight: 600;\n font-size: 13px;\n color: var(--text-dark);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n box-sizing: border-box;\n }\n\n &-toggle {\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 4px 8px;\n color: var(--text-dark);\n display: flex;\n align-items: center;\n border-radius: var(--default-border-radius);\n transition: background 0.15s;\n\n &:hover {\n background: var(--background-accent-light);\n color: var(--text-color);\n }\n }\n }\n\n &-toggle {\n &-wrapper {\n position: absolute;\n right: 0;\n top: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n padding: 0 4px;\n }\n\n /* Chrome (background, shadow, radius, positioning) is provided by the\n FloatingMenu container this renders inside — keep only sizing here. */\n &-popover {\n display: flex;\n flex-direction: column;\n min-width: 160px;\n }\n\n &-item {\n padding: 4px 12px;\n white-space: nowrap;\n transition: background 0.1s;\n font-size: 14px;\n\n &:hover {\n background: var(--background-accent-light);\n }\n }\n }\n\n /* Count badge on the column-toggle cog: how many columns the user has hidden.\n Positioned at the cog's upper-right corner; non-interactive. */\n &-column-chip {\n position: absolute;\n top: 0;\n right: 0;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--primary-color);\n color: var(--text-on-primary);\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n border-radius: 8px;\n pointer-events: none;\n }\n\n &-select-cell {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n box-sizing: border-box;\n }\n\n &-body {\n position: relative;\n box-sizing: border-box;\n }\n\n &-row {\n border-bottom: 1px solid var(--border-color);\n box-sizing: border-box;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: background 0.1s;\n /* Isolate each row's layout/style so measuring or restyling one row can't force\n the whole list to re-layout — keeps fast scrolling smooth. */\n contain: layout style;\n\n &-no-divider {\n border-bottom: none;\n }\n\n &:hover {\n background: var(--background-accent-light);\n }\n\n /* Opt out of the hover highlight (e.g. when each row is a Card that handles\n its own hover). Declared before the `-selected` rule below, so a selected\n row's highlight still wins on hover. */\n &-no-hover:hover {\n background: transparent;\n }\n\n &-selected {\n background: var(--primary-lighter);\n\n &:hover {\n background: var(--primary-lighter);\n }\n }\n\n &-draggable {\n cursor: grab;\n /* Stop the mobile long-press from selecting text or showing the callout. */\n user-select: none;\n -webkit-touch-callout: none;\n\n &:active {\n cursor: grabbing;\n }\n }\n\n &-dragging {\n opacity: 0.4;\n }\n\n /* Tree-reorder `inside` drop: the dragged node becomes a child of this row,\n so highlight the whole row instead of drawing a between-rows line. */\n &-drop-inside {\n background: var(--primary-lighter);\n box-shadow: inset 0 0 0 2px var(--primary-color);\n }\n }\n\n /* Tree-reorder `before`/`after` drop line. Positioned inside the (relatively\n positioned absolute) row; `left` is set inline to the target's indent so it\n starts where the dropped content will. */\n &-drop-line {\n position: absolute;\n right: 0;\n height: 2px;\n background: var(--primary-color);\n pointer-events: none;\n z-index: 1;\n\n /* A small knob at the line's start, the usual tree drop-indicator look. */\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 50%;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--primary-color);\n transform: translate(-50%, -50%);\n }\n\n &-before { top: -1px; }\n &-after { bottom: -1px; }\n }\n\n /* While a row is being dragged, suppress hover backgrounds so the pointer\n moving across rows doesn't light up the wrong one, and stop text selection.\n `touch-action: none` stops the touch drag from also scrolling the list\n (only active once the long-press has armed the drag). */\n &-reordering {\n touch-action: none;\n\n .virtualList-row {\n user-select: none;\n\n &:hover {\n background: transparent;\n }\n\n &.virtualList-row-selected:hover {\n background: var(--primary-lighter);\n }\n\n &.virtualList-row-dragging {\n background: transparent;\n }\n }\n }\n\n &-cell {\n padding: 8px 12px;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 14px;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n min-width: 0;\n\n /* `fit` columns are content-sized — keep their cells on a single line so the\n content can't wrap, and so the width measurement reads the true intrinsic\n width. (Other cells are free to wrap for variable-height rows.) */\n &[data-fit-key] {\n white-space: nowrap;\n }\n }\n\n &-loading {\n &-full {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n }\n\n &-indicator {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 8px 0;\n }\n }\n\n &-spinner {\n width: 32px;\n height: 32px;\n }\n}\n","import React, { useRef, useLayoutEffect } from 'react';\nimport cx from 'classnames';\n\nimport styles from './virtualList.module.pcss';\nimport type { TreeDropPosition } from './virtualList.types';\n\nexport interface VirtualRowProps {\n index: number;\n top: number;\n /** Padding applied to the row (already normalised to a CSS string). */\n padding?: string;\n columnTemplate: string | undefined;\n isSelected: boolean;\n showDivider: boolean;\n hover: boolean;\n onClick: () => void;\n observer: ResizeObserver | null;\n ariaRowIndex?: number;\n ariaPosInSet?: number;\n ariaSetSize?: number;\n rowRole: 'row' | 'listitem';\n reorderable?: boolean;\n /**\n * Native mouse DnD is active for the list. Distinct from `draggable`, which in\n * `dragHandle` mode is only set on the row the pointer has armed.\n */\n mouseDragEnabled?: boolean;\n draggable?: boolean;\n isDragging?: boolean;\n reserveToggleGutter?: boolean;\n onMouseDown?: (e: React.MouseEvent<HTMLDivElement>) => void;\n onMouseOver?: (e: React.MouseEvent<HTMLDivElement>) => void;\n onMouseLeave?: (e: React.MouseEvent<HTMLDivElement>) => void;\n onDragStart?: (e: React.DragEvent<HTMLDivElement>) => void;\n onDragOver?: (e: React.DragEvent<HTMLDivElement>) => void;\n onDragEnd?: () => void;\n onDrop?: (e: React.DragEvent<HTMLDivElement>) => void;\n onTouchStart?: (e: React.TouchEvent<HTMLDivElement>) => void;\n dropPosition?: TreeDropPosition;\n dropIndentPx?: number;\n dropIndicatorClassName?: string;\n dropIndicatorStyle?: React.CSSProperties;\n rowClassName?: string;\n rowStyle?: React.CSSProperties;\n children: React.ReactNode;\n}\n\n/**\n * A single virtualized row: absolutely positioned at its `top`, optionally a\n * grid (table mode), registering itself with the shared ResizeObserver and\n * carrying all the drag / drop-indicator wiring the parent assigns it.\n */\nfunction VirtualRow({\n index,\n top,\n padding,\n columnTemplate,\n isSelected,\n showDivider,\n hover,\n onClick,\n observer,\n ariaRowIndex,\n ariaPosInSet,\n ariaSetSize,\n rowRole,\n reorderable,\n mouseDragEnabled,\n draggable,\n isDragging,\n reserveToggleGutter,\n onMouseDown,\n onMouseOver,\n onMouseLeave,\n onDragStart,\n onDragOver,\n onDragEnd,\n onDrop,\n onTouchStart,\n dropPosition,\n dropIndentPx,\n dropIndicatorClassName,\n dropIndicatorStyle,\n rowClassName,\n rowStyle,\n children,\n}: VirtualRowProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n // A single observer is shared across all rows (created by the parent); each\n // row just registers/unregisters its element. The parent reads the row index\n // back from the `data-index` attribute when the observer fires.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || !observer) return;\n observer.observe(el);\n return () => observer.unobserve(el);\n }, [observer]);\n\n return (\n <div\n ref={ref}\n data-index={index}\n className={cx(\n styles.virtualListRow,\n isSelected && styles.virtualListRowSelected,\n !showDivider && styles.virtualListRowNoDivider,\n !hover && styles.virtualListRowNoHover,\n reorderable && styles.virtualListRowDraggable,\n isDragging && styles.virtualListRowDragging,\n dropPosition === 'inside' && styles.virtualListRowDropInside,\n rowClassName,\n )}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n transform: `translateY(${top}px)`,\n ...(padding != null ? { padding } : {}),\n ...(columnTemplate ? { display: 'grid', gridTemplateColumns: columnTemplate } : {}),\n // Match the header's reserved gutter for the column-toggle cog so row\n // cells line up with their header cells instead of drifting under it.\n // Applied after `padding` so the alignment gutter always wins on the right.\n ...(reserveToggleGutter ? { paddingRight: 32 } : {}),\n ...rowStyle,\n }}\n onClick={onClick}\n draggable={draggable}\n onMouseDown={onMouseDown}\n onMouseOver={onMouseOver}\n onMouseLeave={onMouseLeave}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDrop={onDrop ?? (mouseDragEnabled ? (e) => e.preventDefault() : undefined)}\n onTouchStart={onTouchStart}\n onContextMenu={mouseDragEnabled ? (e) => e.preventDefault() : undefined}\n aria-selected={isSelected}\n aria-rowindex={ariaRowIndex}\n aria-posinset={ariaPosInSet}\n aria-setsize={ariaSetSize}\n role={rowRole}\n >\n {(dropPosition === 'before' || dropPosition === 'after') && (\n <div\n data-drop-line={dropPosition}\n aria-hidden\n className={cx(\n styles.virtualListDropLine,\n dropPosition === 'before' ? styles.virtualListDropLineBefore : styles.virtualListDropLineAfter,\n dropIndicatorClassName,\n )}\n style={{ left: dropIndentPx ?? 0, ...dropIndicatorStyle }}\n />\n )}\n {children}\n </div>\n );\n}\n\nexport default VirtualRow;\n","import type { ColumnWidthSpec, VirtualListColumn } from './virtualList.types';\n\n// ─── Layout / windowing math ──────────────────────────────────────────────────\n\nexport function buildOffsets(\n keys: (string | number)[],\n heightsMap: Map<string | number, number>,\n estimatedRowHeight: number,\n rowGap = 0,\n): { offsets: number[]; totalHeight: number } {\n const itemCount = keys.length;\n const offsets = new Array<number>(itemCount + 1);\n offsets[0] = 0;\n for (let i = 0; i < itemCount; i++) {\n const gap = i < itemCount - 1 ? rowGap : 0;\n // Heights are cached by item key, not index, so a measured row keeps its\n // height across reorders/filters instead of inheriting its neighbour's.\n offsets[i + 1] = offsets[i] + (heightsMap.get(keys[i]) ?? estimatedRowHeight) + gap;\n }\n return { offsets, totalHeight: offsets[itemCount] };\n}\n\n/** Index of the row that sits at `scrollTop` — i.e. the first row whose bottom edge is below it. */\nexport function findStartIndex(offsets: number[], scrollTop: number, itemCount: number): number {\n if (itemCount <= 0) return 0;\n let lo = 0;\n let hi = itemCount - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (offsets[mid + 1] <= scrollTop) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\nexport function getVisibleRange(\n offsets: number[],\n scrollTop: number,\n containerHeight: number,\n overscan: number,\n itemCount: number,\n): { startIndex: number; endIndex: number } {\n if (itemCount === 0) return { startIndex: 0, endIndex: -1 };\n\n const lo = findStartIndex(offsets, scrollTop, itemCount);\n\n let end = lo;\n while (end < itemCount && offsets[end] < scrollTop + containerHeight) end++;\n\n return {\n startIndex: Math.max(0, lo - overscan),\n endIndex: Math.min(itemCount - 1, end + overscan - 1),\n };\n}\n\n// ─── Reorder / tree-drop math ─────────────────────────────────────────────────\n\n/**\n * Decides where a dragged row should move to, applying midpoint hysteresis: a\n * move only happens once the pointer has crossed the centre of the row it is\n * over (downwards when moving down, upwards when moving up). Returns the target\n * index, or null if no move should occur. Pure for easy unit testing.\n */\nexport function resolveReorderTarget(\n fromIndex: number,\n overIndex: number,\n pointerY: number,\n rowTop: number,\n rowHeight: number,\n): number | null {\n if (fromIndex === -1 || fromIndex === overIndex) return null;\n const midpoint = rowTop + rowHeight / 2;\n const movingDown = overIndex > fromIndex;\n if (movingDown ? pointerY >= midpoint : pointerY <= midpoint) return overIndex;\n return null;\n}\n\n/**\n * Decides where a tree-reorder drop should land relative to the row under the\n * pointer. Group rows expose three zones (top third → `before`, middle →\n * `inside`, bottom third → `after`); leaf rows split in half (`before`/`after`)\n * since they can't receive children. Pure for easy unit testing.\n */\nexport function resolveTreeDropTarget(\n pointerY: number,\n rowTop: number,\n rowHeight: number,\n isGroup: boolean,\n): 'before' | 'inside' | 'after' {\n if (rowHeight <= 0) return 'before';\n const rel = (pointerY - rowTop) / rowHeight;\n if (isGroup) {\n if (rel < 1 / 3) return 'before';\n if (rel > 2 / 3) return 'after';\n return 'inside';\n }\n return rel < 0.5 ? 'before' : 'after';\n}\n\n/**\n * Index of the last descendant of the node at `index` in a depth-tagged flat\n * list (a contiguous run of following rows with a greater depth). Returns\n * `index` itself when the node has no children. A drop is forbidden anywhere in\n * `[index, lastDescendantIndex]` — that's the node and its own subtree.\n */\nexport function lastDescendantIndex(index: number, depths: number[]): number {\n const d = depths[index];\n let i = index + 1;\n while (i < depths.length && depths[i] > d) i++;\n return i - 1;\n}\n\n// ─── Column template ──────────────────────────────────────────────────────────\n\nexport function buildColumnTemplate(\n columns: { key: string; width: ColumnWidthSpec }[],\n fitWidths?: Record<string, number>,\n): string {\n if (columns.length === 0) return '1fr';\n return columns\n .map((col) => {\n switch (col.width.type) {\n case 'fixed': return `${col.width.px}px`;\n case 'flex': return `${col.width.weight ?? 1}fr`;\n // A `fit` track is content-sized, so it resolves independently in each\n // grid (the header and every row are separate grids) and would drift\n // out of alignment. Once we've measured the column's natural width\n // across all those grids, pin it to that exact px so every grid uses an\n // identical track. Until then, fall back to content-sizing.\n case 'fit': {\n const w = fitWidths?.[col.key];\n return w != null ? `${w}px` : 'fit-content(100%)';\n }\n }\n })\n .join(' ');\n}\n\n// ─── Column-visibility persistence ────────────────────────────────────────────\n\nexport const COLUMN_STORAGE_PREFIX = 'ahroweui:virtuallist:columns:';\n\n// We persist both the visible keys and the full set of columns that existed at\n// save time. That lets us tell \"the user hid this column\" from \"this column\n// didn't exist yet\" when columns are added later — the former stays hidden, the\n// latter falls back to its defaultHidden value.\nexport interface PersistedColumns {\n visible: string[];\n known: string[];\n}\n\nexport function loadPersistedColumns(persistKey: string | undefined): PersistedColumns | null {\n if (!persistKey || typeof window === 'undefined') return null;\n try {\n const raw = window.localStorage.getItem(COLUMN_STORAGE_PREFIX + persistKey);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (parsed && Array.isArray(parsed.visible) && Array.isArray(parsed.known)) {\n return {\n visible: parsed.visible.filter((k: unknown): k is string => typeof k === 'string'),\n known: parsed.known.filter((k: unknown): k is string => typeof k === 'string'),\n };\n }\n } catch {\n // Corrupt/unavailable storage — fall back to defaults.\n }\n return null;\n}\n\n/** Whether a column should start visible, honouring saved settings then `defaultHidden`. */\nexport function isColumnInitiallyVisible<T>(col: VirtualListColumn<T>, persisted: PersistedColumns | null): boolean {\n // A locked column is always visible and can't be hidden — ignore saved state.\n if (col.lockVisible) return true;\n if (persisted && persisted.known.includes(col.key)) return persisted.visible.includes(col.key);\n return !col.defaultHidden;\n}\n","import React, { useState, useRef, useEffect, useLayoutEffect, useMemo, useCallback } from 'react';\n\nimport { buildOffsets, findStartIndex, getVisibleRange } from './virtualList.utils';\nimport type { VirtualListHandle, VirtualListScrollOptions } from './virtualList.types';\n\n/**\n * Resolve a `rowGap` value to pixels for the offset math. Numbers and plain\n * `px`/numeric strings parse directly (no DOM, SSR/test-safe); any other CSS\n * length (`em`, `rem`, `%`, `var(...)`) is resolved via a hidden probe appended\n * to `contextEl` so it inherits the list's font-size and custom properties.\n */\nfunction resolveCssLength(value: number | string, contextEl: HTMLElement | null): number {\n if (typeof value === 'number') return value;\n const trimmed = value.trim();\n if (trimmed === '') return 0;\n const asNumber = Number(trimmed);\n if (!Number.isNaN(asNumber)) return asNumber; // \"8\" → 8\n const pxMatch = /^(-?\\d*\\.?\\d+)px$/.exec(trimmed);\n if (pxMatch) return parseFloat(pxMatch[1]); // \"8px\" → 8\n if (typeof document === 'undefined' || !contextEl) return 0;\n const probe = document.createElement('div');\n probe.style.cssText = `position:absolute;visibility:hidden;height:${trimmed};`;\n contextEl.appendChild(probe);\n const px = probe.getBoundingClientRect().height;\n contextEl.removeChild(probe);\n return Number.isFinite(px) ? px : 0;\n}\n\ninterface UseVirtualWindowArgs<T> {\n items: T[];\n /** Stable key per row (already derived by the caller). */\n keys: (string | number)[];\n getItemKey?: (item: T, index: number) => string | number;\n estimatedRowHeight: number;\n rowGap: number | string;\n overscan: number;\n onLoadMore?: () => Promise<void>;\n loadMoreThreshold: number;\n /** Initial/filter load in progress — the body is replaced by a spinner. */\n isLoading: boolean;\n}\n\ninterface UseVirtualWindowResult {\n rootRef: React.RefObject<HTMLDivElement | null>;\n headerRef: React.RefObject<HTMLDivElement | null>;\n /** Shared by every row to measure its height (read back via `data-index`). */\n rowObserver: ResizeObserver | null;\n /** Latest index → key mapping, for async consumers (e.g. the drag hook). */\n keysRef: React.RefObject<(string | number)[]>;\n offsets: number[];\n totalHeight: number;\n containerHeight: number;\n containerWidth: number;\n startIndex: number;\n endIndex: number;\n handleScroll: (e: React.UIEvent<HTMLDivElement>) => void;\n showLoadMoreSpinner: boolean;\n /** The scroll-related imperative methods, for the component to compose into\n * the forwarded handle alongside column controls. */\n scrollApi: Omit<VirtualListHandle, 'recalculateColumns'>;\n}\n\n/**\n * The generic virtualization engine: viewport measurement, per-row height\n * caching, offset/visible-range computation, scroll coalescing, scroll\n * anchoring on height changes, infinite-load triggering, and the imperative\n * scroll handle. Mode-agnostic — knows nothing about columns, selection or\n * dragging.\n */\nexport function useVirtualWindow<T>({\n items,\n keys,\n getItemKey,\n estimatedRowHeight,\n rowGap,\n overscan,\n onLoadMore,\n loadMoreThreshold,\n isLoading,\n}: UseVirtualWindowArgs<T>): UseVirtualWindowResult {\n const [scrollTop, setScrollTop] = useState(0);\n const [containerHeight, setContainerHeight] = useState(0);\n const [containerWidth, setContainerWidth] = useState(0);\n // rowGap may be any CSS length; resolve it to px for the offset math. Seed with\n // the synchronous fast path (number / px), then refine before paint for units\n // that need the DOM (em/rem/%/var).\n const [resolvedRowGap, setResolvedRowGap] = useState<number>(() => resolveCssLength(rowGap, null));\n const [heightsMap, setHeightsMap] = useState<Map<string | number, number>>(new Map());\n const [showLoadMoreSpinner, setShowLoadMoreSpinner] = useState(false);\n const isLoadingMoreRef = useRef(false);\n\n const rootRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n const prevOffsetsRef = useRef<number[]>([]);\n const scrollRafRef = useRef<number | null>(null);\n const pendingScrollTopRef = useRef(0);\n const keysRef = useRef<(string | number)[]>([]);\n\n // One ResizeObserver shared by every row, created once via a lazy state\n // initializer so rows mounting in the same commit can register in their\n // layout effect. Batching all entries into a single setState avoids a\n // re-render per row when many rows enter the viewport at once (the main\n // source of scroll jank). The row index is read back from `data-index`.\n const [rowObserver] = useState<ResizeObserver | null>(() => {\n if (typeof ResizeObserver === 'undefined') return null;\n return new ResizeObserver((entries) => {\n setHeightsMap((prev) => {\n let next: Map<string | number, number> | null = null;\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const idx = Number(el.dataset.index);\n if (Number.isNaN(idx)) continue;\n // Resolve the row's stable key so the cache survives reorders/filters.\n const key = keysRef.current[idx];\n if (key === undefined) continue;\n // Prefer the size the observer already computed — reading offsetHeight\n // here would force a synchronous reflow on every measurement batch.\n const box = entry.borderBoxSize?.[0];\n const h = box ? Math.round(box.blockSize) : el.offsetHeight;\n if (prev.get(key) === h) continue;\n if (!next) next = new Map(prev);\n next.set(key, h);\n }\n return next ?? prev;\n });\n });\n });\n useEffect(() => () => rowObserver?.disconnect(), [rowObserver]);\n\n useLayoutEffect(() => {\n const el = rootRef.current;\n if (!el) return;\n // Measure synchronously before the first paint so the initial render fills\n // the viewport, instead of painting a few overscan rows and re-rendering.\n setContainerHeight(el.clientHeight);\n setContainerWidth(el.clientWidth);\n // Track width too: `fit` columns are measured against this box and capped at\n // its width, so when the container settles to its real width after a route\n // transition / async layout, that change has to re-trigger the measure —\n // otherwise an early measure against a 0/tiny width gets pinned and sticks.\n const observer = new ResizeObserver(() => {\n setContainerHeight(el.clientHeight);\n setContainerWidth(el.clientWidth);\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n // Read through a ref so the trigger below stays stable even when the consumer\n // passes a fresh `onLoadMore` closure on every render.\n const onLoadMoreRef = useRef(onLoadMore);\n useLayoutEffect(() => {\n onLoadMoreRef.current = onLoadMore;\n });\n\n /** Start a load unless one is already in flight (and drive the bottom spinner). */\n const triggerLoadMore = useCallback(() => {\n const load = onLoadMoreRef.current;\n if (!load || isLoadingMoreRef.current) return;\n isLoadingMoreRef.current = true;\n setShowLoadMoreSpinner(true);\n load().finally(() => {\n isLoadingMoreRef.current = false;\n setShowLoadMoreSpinner(false);\n });\n }, []);\n\n const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {\n const el = e.currentTarget;\n // Coalesce scroll-driven re-renders to at most one per animation frame.\n // Scroll events can fire several times per frame (especially while dragging\n // the scrollbar thumb); rendering the visible window once per frame keeps\n // the content in step with the cursor instead of lagging behind.\n pendingScrollTopRef.current = el.scrollTop;\n if (scrollRafRef.current == null) {\n scrollRafRef.current = requestAnimationFrame(() => {\n scrollRafRef.current = null;\n setScrollTop(pendingScrollTopRef.current);\n });\n }\n\n if (el.scrollTop + el.clientHeight >= el.scrollHeight - loadMoreThreshold) triggerLoadMore();\n }, [loadMoreThreshold, triggerLoadMore]);\n\n useEffect(() => () => {\n if (scrollRafRef.current != null) cancelAnimationFrame(scrollRafRef.current);\n }, []);\n\n useLayoutEffect(() => {\n keysRef.current = keys;\n });\n\n // Resolve the gap to px before paint, re-running when the value or the\n // container's layout changes (a theme/font change that alters em/var is caught\n // by the container ResizeObserver feeding containerWidth/Height).\n useLayoutEffect(() => {\n const px = resolveCssLength(rowGap, rootRef.current);\n setResolvedRowGap((prev) => (prev === px ? prev : px));\n }, [rowGap, containerWidth, containerHeight]);\n\n const { offsets, totalHeight } = useMemo(\n () => buildOffsets(keys, heightsMap, estimatedRowHeight, resolvedRowGap),\n [keys, heightsMap, estimatedRowHeight, resolvedRowGap],\n );\n\n // The scroll trigger above can only fire on a list that actually scrolls. When\n // a batch is smaller than the viewport there is no overflow, so no scroll event\n // ever happens and lazy loading dead-ends after the first batch. Keep asking\n // for more until the content overflows; the consumer ends the loop by appending\n // nothing (or by dropping `onLoadMore` once its source is exhausted).\n //\n // Each (row count, viewport height) pair is probed at most once, so rows\n // settling to their measured heights can't re-ask a source that already ran\n // dry, and progress depends entirely on the consumer appending rows.\n const fillProbeRef = useRef('');\n useEffect(() => {\n if (!onLoadMore || isLoading || showLoadMoreSpinner) return;\n // 0 while the list is unmeasured or `display: none` — nothing to fill yet.\n if (containerHeight === 0) return;\n // The sticky header eats into the scroll area, so it isn't usable space.\n const headerH = headerRef.current?.offsetHeight ?? 0;\n if (totalHeight >= containerHeight - headerH) return; // already scrollable\n const probe = `${items.length}:${containerHeight}`;\n if (fillProbeRef.current === probe) return;\n fillProbeRef.current = probe;\n triggerLoadMore();\n }, [\n onLoadMore, isLoading, showLoadMoreSpinner,\n items.length, totalHeight, containerHeight, triggerLoadMore,\n ]);\n\n useLayoutEffect(() => {\n const el = rootRef.current;\n const prevOffsets = prevOffsetsRef.current;\n prevOffsetsRef.current = offsets;\n\n // Nothing to anchor against on the first pass or when pinned at the top.\n if (!el || prevOffsets.length === 0) return;\n const curScrollTop = el.scrollTop;\n if (curScrollTop <= 0) return;\n\n // Scroll anchoring: pin the row at the top of the viewport. Find it under\n // the *previous* offsets, then re-derive scrollTop from its *new* offset so\n // it stays visually fixed when rows above it are measured or resized. This\n // is more robust than summing per-row height deltas — it can't drift, and\n // one correction covers any number of simultaneous changes above the fold.\n const prevCount = prevOffsets.length - 1;\n const anchor = findStartIndex(prevOffsets, curScrollTop, prevCount);\n if (anchor >= items.length) return;\n const within = curScrollTop - prevOffsets[anchor];\n const target = offsets[anchor] + within;\n if (Math.abs(target - curScrollTop) > 0.5) {\n el.scrollTop = target;\n pendingScrollTopRef.current = target;\n setScrollTop(target);\n }\n }, [offsets, items.length]);\n\n const scrollApi = useMemo<Omit<VirtualListHandle, 'recalculateColumns'>>(() => {\n function scrollToOffset(top: number, behavior?: ScrollBehavior) {\n const el = rootRef.current;\n if (!el) return;\n const clamped = Math.max(0, top);\n if (typeof el.scrollTo === 'function') el.scrollTo({ top: clamped, behavior: behavior ?? 'auto' });\n else el.scrollTop = clamped;\n }\n function scrollToIndex(index: number, options?: VirtualListScrollOptions) {\n const el = rootRef.current;\n if (!el || items.length === 0) return;\n const i = Math.max(0, Math.min(index, items.length - 1));\n const rowTop = offsets[i] ?? 0;\n const rowHeight = (offsets[i + 1] ?? rowTop) - rowTop;\n // The sticky header overlaps the top of the scroll area, so the usable\n // viewport starts below it — account for that when aligning.\n const headerH = headerRef.current?.offsetHeight ?? 0;\n const usable = Math.max(0, el.clientHeight - headerH);\n const align = options?.align ?? 'start';\n let top = rowTop - headerH;\n if (align === 'center') top -= (usable - rowHeight) / 2;\n else if (align === 'end') top -= usable - rowHeight;\n scrollToOffset(top, options?.behavior);\n }\n return {\n scrollToIndex,\n scrollToKey(key, options) {\n const i = items.findIndex((item, idx) => (getItemKey ? getItemKey(item, idx) : idx) === key);\n if (i >= 0) scrollToIndex(i, options);\n },\n scrollToTop(options) {\n scrollToOffset(0, options?.behavior);\n },\n getScrollElement: () => rootRef.current,\n };\n }, [items, offsets, getItemKey]);\n\n const { startIndex, endIndex } = useMemo(\n () => getVisibleRange(offsets, scrollTop, containerHeight, overscan, items.length),\n [offsets, scrollTop, containerHeight, overscan, items.length],\n );\n\n return {\n rootRef,\n headerRef,\n rowObserver,\n keysRef,\n offsets,\n totalHeight,\n containerHeight,\n containerWidth,\n startIndex,\n endIndex,\n handleScroll,\n showLoadMoreSpinner,\n scrollApi,\n };\n}\n","import { useState, useMemo } from 'react';\n\ninterface UseSelectionArgs<T> {\n items: T[];\n getKey: (item: T, index: number) => string | number;\n multiSelect: boolean;\n /** Controlled selected keys. When provided, internal state is ignored. */\n selectedKeys?: Set<string | number>;\n onSelectionChange?: (keys: Set<string | number>) => void;\n}\n\ninterface UseSelectionResult {\n effectiveSelectedKeys: Set<string | number>;\n /** Toggle one row's membership in the selection. */\n handleRowSelect: (key: string | number) => void;\n /** Select all rows, or clear if all are already selected. */\n handleSelectAll: () => void;\n allSelected: boolean;\n someSelected: boolean;\n}\n\n/**\n * Multi-row selection, controlled or uncontrolled. `allSelected`/`someSelected`\n * (for the header checkbox) are O(n) scans, so they're only computed when\n * `multiSelect` is on.\n */\nexport function useSelection<T>({\n items,\n getKey,\n multiSelect,\n selectedKeys,\n onSelectionChange,\n}: UseSelectionArgs<T>): UseSelectionResult {\n const isControlled = selectedKeys !== undefined;\n const [internalSelectedKeys, setInternalSelectedKeys] = useState<Set<string | number>>(new Set());\n const effectiveSelectedKeys = isControlled ? selectedKeys! : internalSelectedKeys;\n\n function applySelection(next: Set<string | number>) {\n if (!isControlled) setInternalSelectedKeys(next);\n onSelectionChange?.(next);\n }\n\n function handleRowSelect(key: string | number) {\n const next = new Set(effectiveSelectedKeys);\n if (next.has(key)) next.delete(key); else next.add(key);\n applySelection(next);\n }\n\n function handleSelectAll() {\n const allKeys = items.map((item, i) => getKey(item, i));\n const allChosen = allKeys.every((k) => effectiveSelectedKeys.has(k));\n applySelection(allChosen ? new Set() : new Set(allKeys));\n }\n\n // O(n) header-checkbox state. The component re-renders every scroll frame\n // (scrollTop is state), but these depend only on the items and the selection —\n // so memoise to keep two full-list scans off the scroll path.\n const { allSelected, someSelected } = useMemo(() => {\n if (!multiSelect || items.length === 0) return { allSelected: false, someSelected: false };\n const all = items.every((item, i) => effectiveSelectedKeys.has(getKey(item, i)));\n const some = !all && items.some((item, i) => effectiveSelectedKeys.has(getKey(item, i)));\n return { allSelected: all, someSelected: some };\n }, [multiSelect, items, effectiveSelectedKeys, getKey]);\n\n return { effectiveSelectedKeys, handleRowSelect, handleSelectAll, allSelected, someSelected };\n}\n","import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\n\nimport {\n buildColumnTemplate,\n loadPersistedColumns,\n isColumnInitiallyVisible,\n COLUMN_STORAGE_PREFIX,\n type PersistedColumns,\n} from './virtualList.utils';\nimport type { VirtualListColumn } from './virtualList.types';\n\ninterface UseColumnsArgs<T> {\n columns?: VirtualListColumn<T>[];\n items: T[];\n multiSelect: boolean;\n visibleColumnKeys?: string[];\n onVisibleColumnsChange?: (keys: string[]) => void;\n persistColumnsKey?: string;\n showColumnToggle?: boolean;\n rootRef: React.RefObject<HTMLDivElement | null>;\n /** Visible-window bounds — re-measure `fit` columns as new cells scroll in. */\n startIndex: number;\n endIndex: number;\n containerHeight: number;\n /** Re-measure `fit` columns when the container width settles (e.g. after a route transition). */\n containerWidth: number;\n}\n\ninterface UseColumnsResult<T> {\n hasColumns: boolean;\n visibleColumns: VirtualListColumn<T>[];\n columnTemplate: string | undefined;\n shouldShowToggle: boolean;\n effectiveVisible: Set<string>;\n /** How many default-visible columns the user has hidden (excludes defaultHidden). */\n manuallyHiddenCount: number;\n toggleOpen: boolean;\n setToggleOpen: React.Dispatch<React.SetStateAction<boolean>>;\n handleToggleColumn: (key: string) => void;\n /** Imperative escape hatch: drop fit-column pins so they re-measure on the\n * next layout. For out-of-band content changes that don't flow through a new\n * `items` array or `columns` set (which reset automatically). */\n recalculateColumns: () => void;\n}\n\n/**\n * Table-mode column logic: visibility (controlled or uncontrolled, with\n * localStorage persistence and runtime reconciliation), the toggle popover, and\n * `fit`-column width measurement that pins one shared px track across the header\n * and every row grid so they stay aligned.\n */\nexport function useColumns<T>({\n columns,\n items,\n multiSelect,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n rootRef,\n startIndex,\n endIndex,\n containerHeight,\n containerWidth,\n}: UseColumnsArgs<T>): UseColumnsResult<T> {\n const isControlled = visibleColumnKeys !== undefined;\n const [toggleOpen, setToggleOpen] = useState(false);\n // Measured px widths for `fit` columns, keyed by column key. Pinning these\n // into the shared column template keeps the header and rows aligned (a raw\n // `fit-content` track resolves per-grid and drifts). See the effects below.\n const [fitWidths, setFitWidths] = useState<Record<string, number>>({});\n\n const [internalVisibleKeys, setInternalVisibleKeys] = useState<Set<string>>(() => {\n const persisted = loadPersistedColumns(persistColumnsKey);\n return new Set((columns ?? []).filter((c) => isColumnInitiallyVisible(c, persisted)).map((c) => c.key));\n });\n // The set of column keys the internal visibility state was last reconciled\n // against. The lazy initializer above only runs at mount, so without this a\n // list that mounts in list mode (no columns) and later switches to table mode\n // would keep an empty visible set and render no columns.\n const knownColumnKeysRef = useRef<Set<string>>(new Set((columns ?? []).map((c) => c.key)));\n\n // Re-derive internal visibility when the column set changes at runtime: new\n // columns get their saved/default visibility, removed columns drop out, and\n // existing columns keep whatever the user toggled them to. This is also what\n // applies persisted settings when a list switches from list mode to table\n // mode (columns absent at mount, supplied later).\n useEffect(() => {\n if (isControlled) return;\n const cols = columns ?? [];\n const currentKeys = new Set(cols.map((c) => c.key));\n const known = knownColumnKeysRef.current;\n let identical = currentKeys.size === known.size;\n if (identical) for (const k of currentKeys) if (!known.has(k)) { identical = false; break; }\n if (identical) return;\n knownColumnKeysRef.current = currentKeys;\n const persisted = loadPersistedColumns(persistColumnsKey);\n setInternalVisibleKeys((prev) => {\n const next = new Set<string>();\n for (const c of cols) {\n if (known.has(c.key)) {\n if (prev.has(c.key)) next.add(c.key); // preserve the current-session choice\n } else if (isColumnInitiallyVisible(c, persisted)) {\n next.add(c.key); // newly-added column: saved setting, else defaultHidden\n }\n }\n return next;\n });\n }, [columns, isControlled, persistColumnsKey]);\n\n // Persist visibility whenever it changes (uncontrolled mode only). Skip while\n // there are no columns, or the transient empty state during a list→table\n // switch before the reconcile effect above has filled in the visible set —\n // writing then would clobber the saved config with an empty set.\n useEffect(() => {\n if (isControlled || !persistColumnsKey || typeof window === 'undefined') return;\n const cols = columns ?? [];\n if (cols.length === 0 || internalVisibleKeys.size === 0) return;\n try {\n window.localStorage.setItem(\n COLUMN_STORAGE_PREFIX + persistColumnsKey,\n JSON.stringify({ visible: [...internalVisibleKeys], known: cols.map((c) => c.key) } satisfies PersistedColumns),\n );\n } catch {\n // Storage full or unavailable — non-fatal, just don't persist.\n }\n }, [internalVisibleKeys, columns, isControlled, persistColumnsKey]);\n\n // Locked columns can never be hidden — force them into the visible set even if\n // a controlled `visibleColumnKeys` or persisted state omits them. Only clone\n // (rather than mutate the state Set) when a locked key is actually missing;\n // in uncontrolled mode they're already present via isColumnInitiallyVisible.\n const baseVisible: Set<string> = isControlled ? new Set(visibleColumnKeys) : internalVisibleKeys;\n const lockedKeys = (columns ?? []).filter((c) => c.lockVisible).map((c) => c.key);\n const effectiveVisible: Set<string> = lockedKeys.some((k) => !baseVisible.has(k))\n ? new Set([...baseVisible, ...lockedKeys])\n : baseVisible;\n\n const hasColumns = !!columns?.length;\n const visibleColumns = hasColumns ? columns!.filter((c) => effectiveVisible.has(c.key)) : [];\n // A column counts as \"manually hidden\" only if it's default-visible yet\n // currently hidden — a defaultHidden column being hidden is its default\n // state, not a user choice, so it never contributes to the chip.\n const manuallyHiddenCount = hasColumns\n ? columns!.filter((c) => !c.defaultHidden && !effectiveVisible.has(c.key)).length\n : 0;\n const selectPrefix = multiSelect && hasColumns ? '40px ' : '';\n const columnTemplate = hasColumns ? `${selectPrefix}${buildColumnTemplate(visibleColumns, fitWidths)}` : undefined;\n // Hide the gear entirely when nothing is left to toggle (every column opts out).\n const shouldShowToggle = showColumnToggle !== false && hasColumns && columns!.some((c) => !c.hideFromToggle);\n\n // ── `fit` column width measurement ──────────────────────────────────────────\n const fitColumns = visibleColumns.filter((c) => c.width.type === 'fit');\n const hasFit = fitColumns.length > 0;\n const fitColKey = fitColumns.map((c) => c.key).join('|');\n\n // Drop the measured pins when the data or the fit-column set changes, so the\n // measure effect below re-reads the true intrinsic width on the next pass —\n // this is what lets a column shrink (during scroll the effect only grows it,\n // to avoid jitter). Resetting state during render is React's recommended\n // pattern for \"reset on prop change\" and avoids a cascading effect render.\n const [fitReset, setFitReset] = useState<{ key: string; items: T[] }>({ key: fitColKey, items });\n if (fitReset.key !== fitColKey || fitReset.items !== items) {\n setFitReset({ key: fitColKey, items });\n if (Object.keys(fitWidths).length > 0) setFitWidths({});\n }\n\n // Measure every fit cell currently in the DOM (header + visible rows), keyed\n // by its `data-fit-key`, and grow each column's pin to the widest. Reading the\n // key off the DOM (rather than closing over `fitColumns`) keeps this a stable\n // callback the ResizeObserver below can reuse. `scrollWidth` reports the true\n // content width even when the cell is pinned narrower than its content, so a\n // later pass always recovers a column first measured while it was still empty\n // (e.g. an actions cell whose buttons mount a tick after the row commits — its\n // empty width is just the padding, ~24px, which \"only grow\" can't undo).\n const measureFitWidths = useCallback(() => {\n const root = rootRef.current;\n if (!root) return;\n const maxByKey = new Map<string, number>();\n root.querySelectorAll('[data-fit-key]').forEach((node) => {\n const el = node as HTMLElement;\n const key = el.getAttribute('data-fit-key');\n if (!key) return;\n const overflowing = el.scrollWidth > el.clientWidth;\n let w = el.scrollWidth;\n // Only resolve computed padding when we actually need it — the overflow\n // fix-up, or the collapse check below — so the hot scroll path stays cheap\n // for plain in-flow cells.\n if (overflowing || el.firstElementChild) {\n const cs = getComputedStyle(el);\n const padLeft = parseFloat(cs.paddingLeft) || 0;\n const padRight = parseFloat(cs.paddingRight) || 0;\n // scrollWidth includes the left padding but drops the right padding when\n // the content overflows — add it back.\n if (overflowing) w += padRight;\n // Collapsed-content case (FontAwesome icons etc.): element children are\n // present, yet scrollWidth is only the cell's padding because their boxes\n // overflow via `overflow: visible` and carry no intrinsic width, so they\n // don't count toward scrollWidth (and, when right-aligned, overflow to the\n // *left* into negative offsets). ONLY then walk the descendants for their\n // true span — once a real width pins, the cell is no longer collapsed, so\n // this stops running on every scroll frame.\n if (el.firstElementChild && !overflowing && el.scrollWidth <= padLeft + padRight + 1) {\n let minLeft = Infinity;\n let maxRight = -Infinity;\n el.querySelectorAll('*').forEach((d) => {\n const r = d.getBoundingClientRect();\n if (r.left < minLeft) minLeft = r.left;\n if (r.right > maxRight) maxRight = r.right;\n });\n if (maxRight > minLeft) {\n const span = Math.ceil(maxRight - minLeft) + padLeft + padRight;\n if (span > w) w = span;\n }\n }\n }\n if (w > (maxByKey.get(key) ?? 0)) maxByKey.set(key, w);\n });\n if (maxByKey.size === 0) return;\n setFitWidths((prev) => {\n let changed = false;\n const next = { ...prev };\n for (const [key, max] of maxByKey) {\n if (max <= 0) continue;\n // Cap at the viewport width so one oversized cell can't blow out layout.\n const pinned = Math.min(Math.ceil(max), root.clientWidth);\n if (pinned > (prev[key] ?? 0)) { next[key] = pinned; changed = true; }\n }\n return changed ? next : prev;\n });\n }, [rootRef]);\n\n // One ResizeObserver shared across all fit cells. It re-measures whenever a\n // cell's box changes — crucially when content first appears after mount (which\n // changes the cell's height even while its width is pinned), so a too-early or\n // empty-cell measure self-corrects instead of sticking. Its initial callback\n // also fires once after layout settles, covering route transitions and other\n // post-mount layout shifts without depending on font/rAF timing.\n const [fitObserver] = useState<ResizeObserver | null>(() =>\n typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => measureFitWidths()),\n );\n const observedRef = useRef<Set<Element>>(new Set());\n useEffect(() => () => { fitObserver?.disconnect(); observedRef.current.clear(); }, [fitObserver]);\n\n // Measure synchronously (before paint, so a wider row scrolling in never shows\n // a clipped frame), then *diff* the observed set rather than re-observing every\n // cell. Re-observing fires a redundant ResizeObserver callback per node, and\n // `startIndex`/`endIndex` change every scroll frame — so observing only the\n // cells that entered (and dropping the ones that left) keeps stable, already\n // pinned cells from generating any observer traffic while scrolling. A newly\n // entered cell still fires exactly once, which is when we want to measure it.\n useLayoutEffect(() => {\n if (!hasFit) return;\n const root = rootRef.current;\n if (!root) return;\n measureFitWidths();\n if (!fitObserver) return;\n const current = new Set<Element>(root.querySelectorAll('[data-fit-key]'));\n const observed = observedRef.current;\n for (const el of observed) if (!current.has(el)) { fitObserver.unobserve(el); observed.delete(el); }\n for (const el of current) if (!observed.has(el)) { fitObserver.observe(el); observed.add(el); }\n }, [hasFit, fitColKey, fitWidths, startIndex, endIndex, containerHeight, containerWidth, items, measureFitWidths, fitObserver]);\n\n // Cheap insurance: re-measure on the next two frames after mount / data /\n // fit-column changes, in case the icons (or the injected FontAwesome sizing\n // CSS) resolve a frame after the first synchronous pass. Safe and scoped —\n // measureFitWidths only ever grows a pin, and this runs on mount / data change\n // (not every scroll frame), so it keeps the diff-observe perf win.\n useEffect(() => {\n if (!hasFit) return;\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n measureFitWidths();\n raf2 = requestAnimationFrame(() => measureFitWidths());\n });\n return () => { cancelAnimationFrame(raf1); cancelAnimationFrame(raf2); };\n }, [hasFit, fitColKey, items, measureFitWidths]);\n\n // Force a fresh fit-column measure regardless of current pins. Always installs\n // a new empty object so the measure layout effect re-runs even when nothing\n // was pinned (e.g. content changed while the column was still fit-content).\n const recalculateColumns = useCallback(() => setFitWidths({}), []);\n\n function handleToggleColumn(key: string) {\n // Locked columns can't be toggled off.\n if (columns?.find((c) => c.key === key)?.lockVisible) return;\n const next = new Set(effectiveVisible);\n if (next.has(key)) {\n if (next.size <= 1) return;\n next.delete(key);\n } else {\n next.add(key);\n }\n const nextArray = [...next];\n if (!isControlled) setInternalVisibleKeys(next);\n onVisibleColumnsChange?.(nextArray);\n }\n\n return {\n hasColumns,\n visibleColumns,\n columnTemplate,\n shouldShowToggle,\n effectiveVisible,\n manuallyHiddenCount,\n toggleOpen,\n setToggleOpen,\n handleToggleColumn,\n recalculateColumns,\n };\n}\n","import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\n\nimport styles from './virtualList.module.pcss';\nimport { resolveReorderTarget, resolveTreeDropTarget, lastDescendantIndex } from './virtualList.utils';\nimport type { TreeDropPosition, TreeDropTarget } from './virtualList.types';\n\ninterface UseRowDragArgs {\n reorderable: boolean;\n treeReorder: boolean;\n onReorder?: (fromIndex: number, toIndex: number) => void;\n onTreeDrop?: (dragKey: string | number, target: TreeDropTarget) => void;\n longPressDelay: number;\n dragHandle: boolean;\n treeIndentPx: number;\n /** Current flat ordering and depth tags (mouse handlers read these directly). */\n keys: (string | number)[];\n depths: number[];\n isGroupAt: (index: number) => boolean;\n rootRef: React.RefObject<HTMLDivElement | null>;\n /** Latest keys for async (touch / rAF) consumers — owned by useVirtualWindow. */\n keysRef: React.RefObject<(string | number)[]>;\n}\n\n/** The drag-related props the parent spreads onto a given row. */\nexport interface RowDragProps {\n reorderable: boolean;\n /** Native mouse DnD is active for the list (independent of which row is armed). */\n mouseDragEnabled: boolean;\n draggable: boolean | undefined;\n isDragging: boolean;\n onMouseDown: ((e: React.MouseEvent<HTMLDivElement>) => void) | undefined;\n onMouseOver: ((e: React.MouseEvent<HTMLDivElement>) => void) | undefined;\n onMouseLeave: ((e: React.MouseEvent<HTMLDivElement>) => void) | undefined;\n onDragStart: ((e: React.DragEvent<HTMLDivElement>) => void) | undefined;\n onDragOver: ((e: React.DragEvent<HTMLDivElement>) => void) | undefined;\n onDragEnd: (() => void) | undefined;\n onDrop: ((e: React.DragEvent<HTMLDivElement>) => void) | undefined;\n onTouchStart: ((e: React.TouchEvent<HTMLDivElement>) => void) | undefined;\n dropPosition: TreeDropPosition | undefined;\n dropIndentPx: number | undefined;\n}\n\ninterface UseRowDragResult {\n /** True while a row is being dragged (for the root reordering style). */\n draggingKey: string | number | null;\n /** Whether either drag mode is active. */\n dragEnabled: boolean;\n /** Drag props for the row at `index` / `key`. */\n getRowDragProps: (index: number, key: string | number) => RowDragProps;\n /** Returns true (and resets) if the next click should be swallowed (post-drag). */\n consumeSuppressedClick: () => boolean;\n}\n\n/**\n * Row drag-and-drop for both modes:\n * - `reorderable` (flat): native HTML5 drag on desktop; rows move live via\n * `onReorder` with midpoint hysteresis.\n * - `treeReorder`: a drop indicator (before/after/inside) is shown during the\n * drag and `onTreeDrop` fires once on release; dropping onto the dragged\n * node's own subtree is forbidden.\n * Touch uses a long-press → lifted-clone → pointer-move path with edge\n * auto-scroll. `dragHandle` restricts initiation to `[data-drag-handle]`.\n */\nexport function useRowDrag({\n reorderable,\n treeReorder,\n onReorder,\n onTreeDrop,\n longPressDelay,\n dragHandle,\n treeIndentPx,\n keys,\n depths,\n isGroupAt,\n rootRef,\n keysRef,\n}: UseRowDragArgs): UseRowDragResult {\n // The dragged item is tracked by its stable key (indices shift after each\n // live reorder); the ref drives the logic, the state drives the row's style.\n const dragKeyRef = useRef<string | number | null>(null);\n const [draggingKey, setDraggingKey] = useState<string | number | null>(null);\n // Tree-reorder drop indicator. Unlike flat reorder (which moves rows live),\n // tree mode shows where the drop will land and commits once on release.\n const [dropTarget, setDropTarget] = useState<TreeDropTarget | null>(null);\n const dropTargetRef = useRef<TreeDropTarget | null>(null);\n const onReorderRef = useRef(onReorder);\n const onTreeDropRef = useRef(onTreeDrop);\n const treeModeRef = useRef(treeReorder);\n const depthsRef = useRef<number[]>(depths);\n const isGroupAtRef = useRef<(i: number) => boolean>(isGroupAt);\n // When `dragHandle` is on, a mousedown sets this to whether it landed on a\n // `[data-drag-handle]` element, gating whether the ensuing dragstart is honoured.\n const dragFromHandleRef = useRef(true);\n // In `dragHandle` mode the `draggable` attribute is only on the row whose\n // handle the pointer is currently over (\"armed\"). A permanently `draggable`\n // row breaks mouse text selection (caret placement, double-click word select,\n // drag select) inside any child input in Firefox — see Mozilla bugs 739071 /\n // 800050 / 1189486. Arming on hover rather than on mousedown means the\n // attribute is already in place before the press, so the browser never has to\n // notice it appearing mid-gesture, and any pointer move re-derives it.\n const armedKeyRef = useRef<string | number | null>(null);\n const [armedKey, setArmedKeyState] = useState<string | number | null>(null);\n const longPressRef = useRef<number | null>(null);\n const touchActiveRef = useRef(false);\n const touchStartYRef = useRef<number | null>(null);\n const pointerXRef = useRef(0);\n const pointerYRef = useRef(0);\n const autoScrollRef = useRef<number | null>(null);\n const suppressNextClickRef = useRef(false);\n // Floating clone that follows the finger during a touch drag.\n const dragCloneRef = useRef<HTMLElement | null>(null);\n const grabOffsetYRef = useRef(0);\n const cloneLeftRef = useRef(0);\n const dragHeightRef = useRef(0);\n // The native `draggable` attribute (mouse DnD) makes a long-press start the\n // browser's own drag on touch devices, which hijacks our touch handlers. So\n // expose it only where the primary pointer is fine (mouse/trackpad); touch\n // devices use the touch handlers below instead.\n const [isCoarsePointer] = useState(() =>\n typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n ? window.matchMedia('(pointer: coarse)').matches\n : false,\n );\n\n useLayoutEffect(() => {\n onReorderRef.current = onReorder;\n onTreeDropRef.current = onTreeDrop;\n treeModeRef.current = treeReorder;\n depthsRef.current = depths;\n dropTargetRef.current = dropTarget;\n isGroupAtRef.current = isGroupAt;\n });\n\n // ── Mouse / shared start ──────────────────────────────────────────────────\n\n /** Move the `draggable` attribute to `next` (or off entirely for `null`). */\n function arm(next: string | number | null) {\n // Arming exists purely to place the native `draggable` attribute, which is\n // never set on a coarse pointer (touch uses the handlers below instead). A\n // tap still synthesises mouseover/mousedown, so without this a touch device\n // would re-render the list on every handle tap to no effect whatsoever.\n if (isCoarsePointer) return;\n if (armedKeyRef.current === next) return; // mouseover fires constantly — no-op\n armedKeyRef.current = next;\n setArmedKeyState(next);\n }\n\n // Arm while the pointer rests on this row's handle, disarm as it moves off.\n // `buttons !== 0` means a press is already in progress: the pointer can drift\n // off the handle before the browser reaches its drag threshold, so hover is\n // ignored until release rather than disarming a drag that is about to start.\n function handleRowMouseOver(key: string | number, e: React.MouseEvent<HTMLDivElement>) {\n if (e.buttons !== 0) return;\n arm((e.target as HTMLElement).closest('[data-drag-handle]') ? key : null);\n }\n\n function handleRowMouseLeave(e: React.MouseEvent<HTMLDivElement>) {\n if (e.buttons !== 0) return;\n arm(null);\n }\n\n // With `dragHandle`, remember on mousedown whether the press landed on a\n // handle, so the dragstart that follows can be ignored if it didn't. Arming\n // here too covers a handle that came to sit under an already-stationary cursor\n // (the list scrolled), which produces no mouseover.\n function handleRowMouseDown(key: string | number, e: React.MouseEvent<HTMLDivElement>) {\n if (e.button !== 0) return; // only a primary press can begin a drag\n const fromHandle = !!(e.target as HTMLElement).closest('[data-drag-handle]');\n dragFromHandleRef.current = fromHandle;\n if (fromHandle) arm(key);\n }\n\n function handleReorderStart(key: string | number, e: React.DragEvent<HTMLDivElement>) {\n if (dragHandle && !dragFromHandleRef.current) {\n e.preventDefault(); // not started from a handle — let the row stay put\n return;\n }\n dragKeyRef.current = key;\n setDraggingKey(key);\n if (treeReorder) setDropTarget(null);\n }\n\n // ── Tree mode ─────────────────────────────────────────────────────────────\n\n /** Resolve the tree drop target for the row at `overIndex` under pointer `y`. */\n function computeTreeDrop(overIndex: number, y: number, rect: DOMRect): TreeDropTarget | null {\n const dragKey = dragKeyRef.current;\n if (dragKey == null) return null;\n const fromIndex = keys.indexOf(dragKey);\n // Forbid dropping onto the dragged node or anything in its own subtree.\n if (fromIndex !== -1 && overIndex >= fromIndex && overIndex <= lastDescendantIndex(fromIndex, depths)) {\n return null;\n }\n const position = resolveTreeDropTarget(y, rect.top, rect.height, isGroupAt(overIndex));\n return { key: keys[overIndex], position };\n }\n\n function handleTreeDragOver(overIndex: number, e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault(); // allow the drop\n const rect = e.currentTarget.getBoundingClientRect();\n const next = computeTreeDrop(overIndex, e.clientY, rect);\n setDropTarget((prev) =>\n prev?.key === next?.key && prev?.position === next?.position ? prev : next,\n );\n }\n\n function commitTreeDrop() {\n const dragKey = dragKeyRef.current;\n const target = dropTargetRef.current;\n if (dragKey != null && target && target.key !== dragKey) onTreeDrop?.(dragKey, target);\n }\n\n function handleTreeDrop(e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault();\n commitTreeDrop();\n setDropTarget(null);\n dragKeyRef.current = null;\n setDraggingKey(null);\n arm(null);\n }\n\n function handleTreeDragEnd() {\n // Fires after `drop` (or on its own when released off a valid target).\n setDropTarget(null);\n dragKeyRef.current = null;\n setDraggingKey(null);\n arm(null);\n }\n\n // ── Flat mode ─────────────────────────────────────────────────────────────\n\n function handleReorderOver(overIndex: number, e: React.DragEvent<HTMLDivElement>) {\n e.preventDefault(); // allow the drop\n const dragKey = dragKeyRef.current;\n if (dragKey == null) return;\n const fromIndex = keys.indexOf(dragKey);\n // Midpoint hysteresis (see resolveReorderTarget): a move only happens once\n // the pointer crosses the centre of the row it's over. After a swap the\n // dragged row sits under the cursor, so moving again needs real pointer\n // travel — this stops the oscillation that made dragging feel jumpy.\n const rect = e.currentTarget.getBoundingClientRect();\n const target = resolveReorderTarget(fromIndex, overIndex, e.clientY, rect.top, rect.height);\n if (target != null) onReorder?.(fromIndex, target);\n }\n\n function handleReorderEnd() {\n dragKeyRef.current = null;\n setDraggingKey(null);\n arm(null);\n }\n\n // ── Touch reordering (long-press to arm, then drag) ──────────────────────────\n // These handlers run from window listeners during a touch drag, so they read\n // mutable state from refs and are stable across renders.\n\n const reorderAtPoint = useCallback((x: number) => {\n const dragKey = dragKeyRef.current;\n const root = rootRef.current;\n if (dragKey == null || !root) return;\n // Reorder against the centre of the lifted clone, not the raw finger — the\n // finger sits below the clone's top by the grab offset, so using it would\n // make the top (and bottom) rows unreachable. The clone is what the user\n // aims with, so match it.\n const y = dragCloneRef.current\n ? pointerYRef.current - grabOffsetYRef.current + dragHeightRef.current / 2\n : pointerYRef.current;\n const el = document.elementFromPoint(x, y) as HTMLElement | null;\n const rowEl = el && root.contains(el) ? el.closest<HTMLElement>('[data-index]') : null;\n if (!rowEl) return;\n const overIndex = Number(rowEl.dataset.index);\n if (Number.isNaN(overIndex)) return;\n const fromIndex = keysRef.current.indexOf(dragKey);\n const rect = rowEl.getBoundingClientRect();\n if (treeModeRef.current) {\n // Tree mode: don't move live — just track where the drop will land.\n const ks = keysRef.current;\n const ds = depthsRef.current;\n if (fromIndex !== -1 && overIndex >= fromIndex && overIndex <= lastDescendantIndex(fromIndex, ds)) {\n setDropTarget(null);\n return;\n }\n const position = resolveTreeDropTarget(y, rect.top, rect.height, isGroupAtRef.current(overIndex));\n const next: TreeDropTarget = { key: ks[overIndex], position };\n setDropTarget((prev) => (prev?.key === next.key && prev?.position === next.position ? prev : next));\n return;\n }\n const target = resolveReorderTarget(fromIndex, overIndex, y, rect.top, rect.height);\n if (target != null) onReorderRef.current?.(fromIndex, target);\n }, [rootRef, keysRef]);\n\n // Keep the floating clone glued under the finger (same grab point).\n const positionDragClone = useCallback(() => {\n const clone = dragCloneRef.current;\n if (!clone) return;\n clone.style.transform = `translate(${cloneLeftRef.current}px, ${pointerYRef.current - grabOffsetYRef.current}px)`;\n }, []);\n\n // While the finger sits near a top/bottom edge (and within the list's width),\n // scroll the list and keep reordering against the rows now passing under it.\n const autoScrollTick = useCallback(() => {\n const root = rootRef.current;\n if (!root || !touchActiveRef.current) { autoScrollRef.current = null; return; }\n const rect = root.getBoundingClientRect();\n const x = pointerXRef.current;\n const y = pointerYRef.current;\n const EDGE = 48;\n let dy = 0;\n // Only auto-scroll while the finger is actually over the list — moving it\n // outside (any direction) stops the scroll instead of running away; pinning\n // the dragged row keeps touch events alive so it resumes when you come back.\n const inside = x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;\n if (inside) {\n if (y < rect.top + EDGE) dy = -Math.min(18, Math.ceil((rect.top + EDGE - y) / 3));\n else if (y > rect.bottom - EDGE) dy = Math.min(18, Math.ceil((y - (rect.bottom - EDGE)) / 3));\n }\n if (dy !== 0) {\n root.scrollTop += dy;\n reorderAtPoint(x);\n }\n autoScrollRef.current = requestAnimationFrame(autoScrollTick);\n }, [reorderAtPoint, rootRef]);\n\n const endTouchDrag = useCallback(() => {\n if (longPressRef.current != null) { clearTimeout(longPressRef.current); longPressRef.current = null; }\n window.removeEventListener('touchmove', handleTouchMove);\n window.removeEventListener('touchend', endTouchDrag);\n window.removeEventListener('touchcancel', endTouchDrag);\n if (autoScrollRef.current != null) { cancelAnimationFrame(autoScrollRef.current); autoScrollRef.current = null; }\n if (dragCloneRef.current) { dragCloneRef.current.remove(); dragCloneRef.current = null; }\n // Restore native scrolling that was locked for the duration of the drag.\n document.body.style.touchAction = '';\n document.body.style.overscrollBehavior = '';\n if (touchActiveRef.current) {\n // A real drag happened — swallow the click the browser fires afterwards\n // so it doesn't, e.g., toggle row selection.\n suppressNextClickRef.current = true;\n setTimeout(() => { suppressNextClickRef.current = false; }, 350);\n // Tree mode commits the pending drop on release (flat mode already moved\n // rows live during the drag, so there's nothing to commit here).\n if (treeModeRef.current) {\n const dk = dragKeyRef.current;\n const target = dropTargetRef.current;\n if (dk != null && target && target.key !== dk) onTreeDropRef.current?.(dk, target);\n }\n }\n setDropTarget(null);\n touchActiveRef.current = false;\n touchStartYRef.current = null;\n dragKeyRef.current = null;\n setDraggingKey(null);\n }, []);\n\n const handleTouchMove = useCallback((e: TouchEvent) => {\n const t = e.touches[0];\n if (!t) return;\n pointerXRef.current = t.clientX;\n pointerYRef.current = t.clientY;\n if (!touchActiveRef.current) {\n // Before the long-press fires: if the finger travels, the user means to\n // scroll, so disarm and let the browser handle it (we don't preventDefault).\n const sy = touchStartYRef.current;\n if (sy != null && Math.abs(t.clientY - sy) > 10 && longPressRef.current != null) {\n clearTimeout(longPressRef.current);\n longPressRef.current = null;\n }\n return;\n }\n // Non-passive listener: preventDefault cancels the native scroll for this\n // gesture — the only reliable way once touch-action has been latched at\n // touchstart. This is what makes the drag actually move on touch devices.\n if (e.cancelable) e.preventDefault();\n positionDragClone();\n reorderAtPoint(t.clientX);\n }, [reorderAtPoint, positionDragClone]);\n\n function handleRowTouchStart(key: string | number, e: React.TouchEvent<HTMLDivElement>) {\n if (!reorderable && !treeReorder) return;\n // With a drag handle, only a press that starts on it arms the drag, so the\n // rest of the row stays free for tapping/typing into inputs.\n if (dragHandle && !(e.target as HTMLElement).closest('[data-drag-handle]')) return;\n if (longPressRef.current != null || touchActiveRef.current) return; // ignore extra fingers\n const t = e.touches[0];\n if (!t) return;\n touchStartYRef.current = t.clientY;\n pointerXRef.current = t.clientX;\n pointerYRef.current = t.clientY;\n window.addEventListener('touchmove', handleTouchMove, { passive: false });\n window.addEventListener('touchend', endTouchDrag);\n window.addEventListener('touchcancel', endTouchDrag);\n longPressRef.current = window.setTimeout(() => {\n longPressRef.current = null;\n touchActiveRef.current = true;\n dragKeyRef.current = key;\n setDraggingKey(key);\n navigator.vibrate?.(10);\n // Lock native scrolling for the whole gesture — relying on per-move\n // preventDefault isn't enough once the finger leaves and re-enters the\n // list (the browser commits to a scroll and ignores it). We do all the\n // scrolling ourselves via autoScrollTick.\n document.body.style.touchAction = 'none';\n document.body.style.overscrollBehavior = 'none';\n createDragClone(key);\n if (autoScrollRef.current == null) autoScrollRef.current = requestAnimationFrame(autoScrollTick);\n }, longPressDelay);\n }\n\n // Build a floating copy of the picked-up row that tracks the finger, so the\n // drag has a visible \"lifted\" element (the original row stays dimmed in place\n // as a drop placeholder).\n function createDragClone(key: string | number) {\n const root = rootRef.current;\n if (!root) return;\n const idx = keysRef.current.indexOf(key);\n const src = root.querySelector<HTMLElement>(`[data-index=\"${idx}\"]`);\n if (!src) return;\n const r = src.getBoundingClientRect();\n grabOffsetYRef.current = pointerYRef.current - r.top;\n cloneLeftRef.current = r.left;\n dragHeightRef.current = r.height;\n const clone = src.cloneNode(true) as HTMLElement;\n clone.removeAttribute('data-index');\n clone.setAttribute('data-drag-clone', 'true');\n clone.setAttribute('aria-hidden', 'true');\n clone.classList.add(styles.virtualListDragClone);\n Object.assign(clone.style, {\n position: 'fixed',\n left: '0',\n top: '0',\n width: `${r.width}px`,\n height: `${r.height}px`,\n margin: '0',\n opacity: '1',\n pointerEvents: 'none',\n // Above the sticky header (z-index 2) and any focused row (z-index 1).\n zIndex: '3',\n background: 'var(--background)',\n boxShadow: 'var(--card-shadow)',\n borderRadius: 'var(--default-border-radius)',\n } as Partial<CSSStyleDeclaration>);\n // Appended inside the list so it inherits the active theme's CSS variables;\n // position:fixed keeps it in viewport coordinates regardless.\n root.appendChild(clone);\n dragCloneRef.current = clone;\n positionDragClone();\n }\n\n // Tear down any in-flight touch drag if the component unmounts mid-gesture.\n useEffect(() => endTouchDrag, [endTouchDrag]);\n\n // Either drag mode arms the same row gestures; the handlers above branch on\n // `treeReorder` for the differing target resolution / commit behaviour.\n const dragEnabled = reorderable || treeReorder;\n // Native mouse DnD is in play for this list. Row-level fallbacks that must\n // cover *every* row — swallowing the browser's own drop and context menu —\n // key off this, not off `draggable`, which in `dragHandle` mode is only ever\n // on the single armed row.\n const mouseDragEnabled = dragEnabled && !isCoarsePointer;\n\n function getRowDragProps(index: number, key: string | number): RowDragProps {\n // The drop indicator only renders on the row currently targeted. `before`/\n // `after` lines indent to the target's depth so they sit under where the\n // dropped content will start; `inside` highlights the whole row instead.\n const rowDrop = treeReorder && dropTarget?.key === key ? dropTarget.position : undefined;\n return {\n // Drives the row-wide grab cursor. With `dragHandle`, only the handle\n // initiates a drag, so the cursor belongs on the handle (styled by the\n // consumer), not across the whole row.\n reorderable: dragEnabled && !dragHandle,\n mouseDragEnabled,\n // In `dragHandle` mode the attribute only goes on the row the pointer has\n // armed, so rows stay text-selectable in Firefox the rest of the time.\n draggable: (mouseDragEnabled && (!dragHandle || key === armedKey)) || undefined,\n isDragging: dragEnabled && key === draggingKey,\n onMouseDown: dragEnabled && dragHandle ? (e) => handleRowMouseDown(key, e) : undefined,\n onMouseOver: dragEnabled && dragHandle ? (e) => handleRowMouseOver(key, e) : undefined,\n onMouseLeave: dragEnabled && dragHandle ? handleRowMouseLeave : undefined,\n onDragStart: dragEnabled ? (e) => handleReorderStart(key, e) : undefined,\n onDragOver:\n treeReorder ? (e) => handleTreeDragOver(index, e)\n : reorderable ? (e) => handleReorderOver(index, e)\n : undefined,\n onDragEnd: treeReorder ? handleTreeDragEnd : reorderable ? handleReorderEnd : undefined,\n onDrop: treeReorder ? handleTreeDrop : undefined,\n onTouchStart: dragEnabled ? (e) => handleRowTouchStart(key, e) : undefined,\n dropPosition: rowDrop,\n dropIndentPx: rowDrop ? (depths[index] ?? 0) * treeIndentPx : undefined,\n };\n }\n\n function consumeSuppressedClick(): boolean {\n if (suppressNextClickRef.current) { suppressNextClickRef.current = false; return true; }\n return false;\n }\n\n return { draggingKey, dragEnabled, getRowDragProps, consumeSuppressedClick };\n}\n","import React, { useMemo, useCallback, useImperativeHandle } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faGear } from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './virtualList.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport Checkbox from '../checkbox';\nimport FloatingMenu, { Align } from '../floatingMenu';\nimport VirtualRow from './virtualRow';\nimport { useVirtualWindow } from './useVirtualWindow';\nimport { useSelection } from './useSelection';\nimport { useColumns } from './useColumns';\nimport { useRowDrag } from './useRowDrag';\nimport type { VirtualListProps, VirtualListHandle } from './virtualList.types';\n\n// Pure helpers live in ./virtualList.utils; re-exported here so existing\n// imports (and unit tests) keep working against the component entry point.\nexport {\n buildOffsets,\n findStartIndex,\n getVisibleRange,\n resolveReorderTarget,\n resolveTreeDropTarget,\n lastDescendantIndex,\n buildColumnTemplate,\n} from './virtualList.utils';\n\n// ─── Orchestrator ─────────────────────────────────────────────────────────────\n// VirtualListInner wires four focused hooks together and renders. Each concern\n// lives in its own module:\n// useVirtualWindow — generic scroll / measurement / windowing (all modes)\n// useSelection — multi-row selection\n// useColumns — table mode: columns, visibility, persistence, fit widths\n// useRowDrag — reorder + tree drag-and-drop (mouse + touch)\n\nfunction VirtualListInner<T>({\n items,\n renderRow,\n columns,\n height = '100%',\n estimatedRowHeight = 40,\n overscan = 3,\n rowGap = 0,\n rowPadding,\n selectedKey,\n getItemKey,\n onRowClick,\n visibleColumnKeys,\n onVisibleColumnsChange,\n persistColumnsKey,\n showColumnToggle,\n onLoadMore,\n loadMoreThreshold = 100,\n isLoading = false,\n multiSelect = false,\n selectedKeys,\n onSelectionChange,\n reorderable = false,\n onReorder,\n longPressDelay = 400,\n treeReorder = false,\n getItemDepth,\n isGroup,\n onTreeDrop,\n treeIndentPx = 24,\n dragHandle = false,\n showDivider = true,\n rowHover = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: VirtualListProps<T>, ref: React.ForwardedRef<VirtualListHandle>) {\n const getKey = useCallback(\n (item: T, index: number): string | number => (getItemKey ? getItemKey(item, index) : index),\n [getItemKey],\n );\n const keys = useMemo(() => items.map((item, i) => getKey(item, i)), [items, getKey]);\n const depths = useMemo(\n () => (getItemDepth ? items.map((item, i) => getItemDepth(item, i)) : []),\n [items, getItemDepth],\n );\n const isGroupAt = useCallback(\n (i: number) => (isGroup ? isGroup(items[i], i) : false),\n [isGroup, items],\n );\n\n const win = useVirtualWindow<T>({\n items, keys, getItemKey, estimatedRowHeight, rowGap, overscan,\n onLoadMore, loadMoreThreshold, isLoading,\n });\n const { rootRef, headerRef, rowObserver, keysRef, offsets, totalHeight, startIndex, endIndex } = win;\n\n const selection = useSelection<T>({ items, getKey, multiSelect, selectedKeys, onSelectionChange });\n const { effectiveSelectedKeys } = selection;\n\n const cols = useColumns<T>({\n columns, items, multiSelect, visibleColumnKeys, onVisibleColumnsChange, persistColumnsKey,\n showColumnToggle, rootRef, startIndex, endIndex,\n containerHeight: win.containerHeight, containerWidth: win.containerWidth,\n });\n const {\n hasColumns, visibleColumns, columnTemplate, shouldShowToggle, effectiveVisible, manuallyHiddenCount,\n toggleOpen, setToggleOpen, handleToggleColumn, recalculateColumns,\n } = cols;\n\n // Compose the forwarded handle from both hooks: scroll methods come from the\n // windowing engine, column controls from the column hook.\n useImperativeHandle(\n ref,\n () => ({ ...win.scrollApi, recalculateColumns }),\n [win.scrollApi, recalculateColumns],\n );\n\n const drag = useRowDrag({\n reorderable, treeReorder, onReorder, onTreeDrop, longPressDelay, dragHandle, treeIndentPx,\n keys, depths, isGroupAt, rootRef, keysRef,\n });\n\n const rowPaddingValue = typeof rowPadding === 'number' ? `${rowPadding}px` : rowPadding;\n\n const renderRowAt = (i: number) => {\n const item = items[i];\n const key = getKey(item, i);\n const isSelected = (selectedKey != null && key === selectedKey) || effectiveSelectedKeys.has(key);\n const dragProps = drag.getRowDragProps(i, key);\n\n return (\n <VirtualRow\n key={key}\n index={i}\n top={offsets[i]}\n padding={rowPaddingValue}\n columnTemplate={columnTemplate}\n isSelected={isSelected}\n showDivider={showDivider}\n hover={rowHover}\n onClick={() => {\n if (drag.consumeSuppressedClick()) return;\n onRowClick?.(item, i);\n }}\n observer={rowObserver}\n ariaRowIndex={hasColumns ? i + 2 : undefined}\n ariaPosInSet={hasColumns ? undefined : i + 1}\n ariaSetSize={hasColumns ? undefined : items.length}\n rowRole={hasColumns ? 'row' : 'listitem'}\n reserveToggleGutter={shouldShowToggle}\n {...dragProps}\n dropIndicatorClassName={classNames?.dropIndicator}\n dropIndicatorStyle={slotStyles?.dropIndicator}\n rowClassName={classNames?.row}\n rowStyle={slotStyles?.row}\n >\n {hasColumns\n ? <>\n {multiSelect && (\n <div\n className={cx(styles.virtualListSelectCell, classNames?.selectCell)}\n style={slotStyles?.selectCell}\n role=\"gridcell\"\n onClick={(e) => e.stopPropagation()}\n >\n <Checkbox\n selected={effectiveSelectedKeys.has(key)}\n onToggle={() => selection.handleRowSelect(key)}\n aria-label=\"Select row\"\n />\n </div>\n )}\n {visibleColumns.map((col) => (\n <div\n key={col.key}\n className={cx(styles.virtualListCell, classNames?.cell)}\n style={slotStyles?.cell}\n role=\"gridcell\"\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.renderCell(item, i)}\n </div>\n ))}\n </>\n : renderRow?.(item, i)}\n </VirtualRow>\n );\n };\n\n const visibleRows: React.ReactNode[] = [];\n for (let i = startIndex; i <= endIndex; i++) visibleRows.push(renderRowAt(i));\n\n // Keep the row being touch-dragged mounted even if it scrolls out of the\n // window. Touch events are dispatched to the element under the finger at\n // touchstart; if that row unmounts, the browser stops delivering touchmove\n // and the drag freezes. Pinning its DOM node keeps the gesture alive.\n const draggedIndex = drag.draggingKey != null ? keys.indexOf(drag.draggingKey) : -1;\n if (draggedIndex >= 0 && (draggedIndex < startIndex || draggedIndex > endIndex)) {\n visibleRows.push(renderRowAt(draggedIndex));\n }\n\n return (\n <div\n {...rest}\n ref={rootRef}\n className={cx(styles.virtualList, drag.draggingKey != null && styles.virtualListReordering, className, classNames?.root)}\n style={{ height, ...style, ...slotStyles?.root }}\n onScroll={win.handleScroll}\n role={hasColumns ? 'grid' : 'list'}\n aria-rowcount={hasColumns ? items.length + 1 : undefined}\n >\n {hasColumns && (\n <div\n ref={headerRef}\n className={cx(styles.virtualListHeader, classNames?.header)}\n style={{ gridTemplateColumns: columnTemplate, ...(shouldShowToggle ? { paddingRight: 32 } : {}), ...slotStyles?.header }}\n role=\"row\"\n aria-rowindex={1}\n >\n {multiSelect && (\n <div\n className={cx(styles.virtualListSelectCell, classNames?.selectCell)}\n style={slotStyles?.selectCell}\n role=\"columnheader\"\n >\n <Checkbox\n selected={selection.allSelected || selection.someSelected}\n onToggle={selection.handleSelectAll}\n aria-label=\"Select all rows\"\n />\n </div>\n )}\n {visibleColumns.map((col) => (\n <div\n key={col.key}\n className={cx(styles.virtualListHeaderCell, classNames?.headerCell)}\n style={slotStyles?.headerCell}\n role=\"columnheader\"\n data-fit-key={col.width.type === 'fit' ? col.key : undefined}\n >\n {col.label}\n </div>\n ))}\n {shouldShowToggle && (\n <div className={styles.virtualListToggleWrapper}>\n <FloatingMenu\n isOpen={toggleOpen}\n onOpenChange={setToggleOpen}\n align={Align.Right}\n dontCloseOnChildClick\n content={\n <div\n className={cx(styles.virtualListTogglePopover, classNames?.togglePopover)}\n style={slotStyles?.togglePopover}\n >\n {columns!.filter((col) => !col.hideFromToggle).map((col) => (\n <Checkbox\n key={col.key}\n className={cx(styles.virtualListToggleItem, classNames?.toggleItem)}\n style={slotStyles?.toggleItem}\n selected={effectiveVisible.has(col.key)}\n onToggle={() => handleToggleColumn(col.key)}\n disabled={col.lockVisible}\n cursorDefault={false}\n >\n {col.toggleLabel ?? col.label}\n </Checkbox>\n ))}\n </div>\n }\n >\n <button\n type=\"button\"\n className={cx(styles.virtualListHeaderToggle, classNames?.headerToggle)}\n style={slotStyles?.headerToggle}\n aria-label=\"Toggle column visibility\"\n >\n <FontAwesomeIcon\n icon={faGear}\n style={slotStyles?.headerToggle as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n </button>\n </FloatingMenu>\n {manuallyHiddenCount > 0 && (\n <span\n className={cx(styles.virtualListColumnChip, classNames?.columnChip)}\n style={slotStyles?.columnChip}\n data-column-hidden-count={manuallyHiddenCount}\n aria-label={`${manuallyHiddenCount} columns hidden`}\n >\n {manuallyHiddenCount}\n </span>\n )}\n </div>\n )}\n </div>\n )}\n {isLoading ? (\n <div className={styles.virtualListLoadingFull}>\n <SpinnerLoading className={styles.virtualListSpinner} />\n </div>\n ) : (\n <div\n className={cx(styles.virtualListBody, classNames?.body)}\n style={{ height: totalHeight, ...slotStyles?.body }}\n >\n {visibleRows}\n </div>\n )}\n {win.showLoadMoreSpinner && (\n <div\n className={cx(styles.virtualListLoadingIndicator, classNames?.loadingIndicator)}\n style={slotStyles?.loadingIndicator}\n >\n <SpinnerLoading className={styles.virtualListSpinner} />\n </div>\n )}\n </div>\n );\n}\n\n// forwardRef erases the generic, so cast back to a generic-preserving signature.\nconst VirtualList = React.forwardRef(VirtualListInner) as <T>(\n props: VirtualListProps<T> & { ref?: React.Ref<VirtualListHandle> },\n) => React.ReactElement | null;\n\nexport default VirtualList;\n",".wizard {\n height: 100%;\n width: 100%;\n position: relative;\n overflow: hidden;\n transition: all 0.2s;\n padding: 1px;\n\n &-content {\n position: absolute;\n height: fit-content;\n\n &-outOfFrame {\n * {\n user-select: none;\n pointer-events: none;\n visibility: hidden;\n display: none;\n }\n }\n\n &-container {\n display: flex;\n transition: all 0.6s;\n position: relative;\n }\n }\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport styles from './wizard.module.pcss';\nimport type { WizardProps } from './wizard.types';\n\nexport default function Wizard({\n currentStep = 0,\n stepCount = 0,\n renderStep = () => null,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: WizardProps) {\n const [height, setHeight] = useState<number | undefined>(undefined);\n const [showOtherContent, setShowOtherContent] = useState(false);\n const [prevStep, setPrevStep] = useState(currentStep);\n const stepRefs = useRef<(HTMLDivElement | null)[]>([]);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n // When currentStep changes, briefly show off-screen steps so they animate out.\n if (currentStep !== prevStep) {\n setPrevStep(currentStep);\n setShowOtherContent(true);\n }\n\n useEffect(() => {\n if (!showOtherContent) return;\n const id = setTimeout(() => setShowOtherContent(false), 400);\n return () => clearTimeout(id);\n }, [showOtherContent]);\n\n // Track the height of the active step via ResizeObserver.\n useEffect(() => {\n resizeObserverRef.current?.disconnect();\n const el = stepRefs.current[currentStep];\n if (!el) return;\n setHeight(el.clientHeight);\n resizeObserverRef.current = new ResizeObserver(() => {\n setHeight(el.clientHeight);\n });\n resizeObserverRef.current.observe(el);\n return () => resizeObserverRef.current?.disconnect();\n }, [currentStep, stepCount]);\n\n const rootStyle: React.CSSProperties = {\n ...(height !== undefined ? { height: `${height}px` } : {}),\n ...slotStyles?.root,\n ...style,\n };\n\n return (\n <div\n {...rest}\n className={cx(styles.wizard, classNames?.root, className)}\n style={rootStyle}\n >\n <div\n className={cx(styles.wizardContentContainer, classNames?.container)}\n style={{\n width: `${stepCount * 100}%`,\n marginLeft: `-${currentStep * 100}%`,\n ...slotStyles?.container,\n }}\n >\n {Array.from({ length: stepCount }, (_, index) => (\n <div\n key={`wizardStep${index}`}\n ref={(ref) => { stepRefs.current[index] = ref; }}\n className={cx(styles.wizardContent, classNames?.step)}\n style={{\n width: `${100 / stepCount}%`,\n marginLeft: `${(100 / stepCount) * index}%`,\n ...slotStyles?.step,\n }}\n >\n <div\n className={cx(\n { [styles.wizardContentOutOfFrame]: currentStep !== index && !showOtherContent },\n classNames?.stepContent\n )}\n style={slotStyles?.stepContent}\n inert={currentStep !== index ? true : undefined}\n >\n {renderStep(index)}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { showToast } from 'components/common/toast';\nimport { FormValidatorGroup, createFormComponent } from '@ahrowe/form-validation';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues, ValidationError } from '@ahrowe/form-validation';\nimport type React from 'react';\n\n/** Default onSubmitError: surface the first error as an error toast. Callers can override via options.onSubmitError. */\nconst defaultOnSubmitError = (errors: ValidationError[]): void => {\n showToast(errors[0].message, { type: 'error' });\n};\n\n/**\n * FormValidatorGroup with `this.Form` automatically attached.\n * Kept in a .tsx file so formValidatorGroup.ts stays framework-agnostic.\n *\n * This is the class you should use everywhere — it is a drop-in replacement\n * for FormValidatorGroup with one extra property: `this.Form`.\n *\n * Also injects the default toast-based onSubmitError so both hook and class-component\n * consumers surface errors out of the box; pass options.onSubmitError to override.\n */\nexport default class FormValidatorGroupWithForm<\n TGroup extends FormGroup = FormGroup,\n TInitial = InferGroupValues<TGroup>\n> extends FormValidatorGroup<TGroup, TInitial> {\n Form: React.FC<React.FormHTMLAttributes<HTMLFormElement>>;\n\n constructor(\n groupDef: TGroup,\n component: { forceUpdate: () => void } | null = null,\n options?: FormValidatorGroupOptions<TGroup, TInitial>\n ) {\n super(groupDef, component, { ...options, onSubmitError: options?.onSubmitError ?? defaultOnSubmitError });\n this.Form = createFormComponent(this);\n }\n}\n","/* eslint-disable react/no-unused-state */\nimport React, { PureComponent } from 'react';\nimport { FormValidator } from '@ahrowe/form-validation';\nimport Tooltip from 'components/common/tooltip';\n\nexport interface ValidatableComponentProps {\n formValidator?: FormValidator | null;\n onMouseEnter?: ((event: React.MouseEvent) => void) | null;\n onMouseLeave?: ((event: React.MouseEvent) => void) | null;\n onFocus?: ((event: React.FocusEvent) => void) | null;\n onBlur?: ((event: React.FocusEvent) => void) | null;\n onChange?: ((value: unknown) => void) | null;\n errorMessage?: string;\n isValid?: boolean;\n isRequired?: boolean;\n label?: string;\n}\n\nexport interface ValidatableComponentState {\n isFocused: boolean;\n isHovered: boolean;\n}\n\n/**\n * Base class that extends PureComponent with FormValidator integration.\n * Manages hover/focus state and renders error tooltips.\n */\nexport default class ValidatableComponent<\n P extends ValidatableComponentProps = ValidatableComponentProps,\n S extends ValidatableComponentState = ValidatableComponentState,\n> extends PureComponent<P, S> {\n static defaultProps: Partial<ValidatableComponentProps> = {\n formValidator: null,\n onMouseEnter: null,\n onMouseLeave: null,\n onFocus: null,\n onBlur: null,\n onChange: null,\n errorMessage: '',\n isValid: false,\n isRequired: false,\n label: '',\n };\n\n constructor(props: P) {\n super(props);\n const { formValidator } = props;\n\n if (formValidator) {\n formValidator.label = props.label ?? '';\n formValidator.validate();\n formValidator.registerOnUpdateListener(() => { this.forceUpdate(); });\n }\n\n this.state = { isFocused: false, isHovered: false } as S;\n\n this.onMouseEnter = this.onMouseEnter.bind(this);\n this.onMouseLeave = this.onMouseLeave.bind(this);\n this.onFocus = this.onFocus.bind(this);\n this.onBlur = this.onBlur.bind(this);\n this.hasError = this.hasError.bind(this);\n this.renderTooltip = this.renderTooltip.bind(this);\n this.onChange = this.onChange.bind(this);\n }\n\n componentDidMount(): void {\n setTimeout(() => this.setState({ isFocused: false, isHovered: false } as S), 1);\n }\n\n componentDidUpdate(prevProps: P): void {\n const { formValidator } = this.props;\n if (prevProps.formValidator && formValidator && prevProps.formValidator !== formValidator) {\n formValidator.registerOnUpdateListener(() => { this.forceUpdate(); });\n }\n }\n\n onMouseEnter(event: React.MouseEvent): void {\n const { onMouseEnter } = this.props;\n this.setState({ isHovered: true } as unknown as S);\n if (onMouseEnter) onMouseEnter(event);\n }\n\n onMouseLeave(event: React.MouseEvent): void {\n const { onMouseLeave } = this.props;\n this.setState({ isHovered: false } as unknown as S);\n if (onMouseLeave) onMouseLeave(event);\n }\n\n onFocus(event: React.FocusEvent): void {\n const { onFocus } = this.props;\n this.setState({ isFocused: true } as unknown as S);\n if (onFocus) onFocus(event);\n }\n\n onBlur(event: React.FocusEvent): void {\n const { formValidator, onBlur } = this.props;\n if (formValidator) formValidator.touched = true;\n this.setState({ isFocused: false } as unknown as S);\n if (onBlur) onBlur(event);\n }\n\n hasError(): boolean {\n const { errorMessage, isValid, formValidator } = this.props;\n return formValidator\n ? (formValidator.touched && formValidator.hasError())\n : (!isValid || !!errorMessage);\n }\n\n isRequired(): boolean {\n const { isRequired, formValidator } = this.props;\n return !!(isRequired\n || (formValidator && formValidator.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')));\n }\n\n renderTooltip(): React.ReactNode {\n const { errorMessage, formValidator } = this.props;\n const { isHovered, isFocused } = this.state;\n return (\n <Tooltip\n variant=\"error\"\n message={formValidator ? formValidator.getCurrentErrorMessage() : (errorMessage || '')}\n isVisible={this.hasError() && (isFocused || isHovered)}\n />\n );\n }\n\n onChange(newVal: unknown): void {\n const { onChange, formValidator } = this.props;\n if (formValidator) {\n let extractedVal = newVal;\n if (newVal && (newVal as React.ChangeEvent<HTMLInputElement>).target) {\n extractedVal = (newVal as React.ChangeEvent<HTMLInputElement>).target.value;\n }\n formValidator.set(extractedVal);\n }\n if (onChange) onChange(newVal);\n }\n}\n","import { useFormValidatorGroupInstance } from '@ahrowe/form-validation';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues } from '@ahrowe/form-validation';\nimport FormValidatorGroupWithForm from './FormValidatorGroupWithForm';\n\n/**\n * @ahrowe/ui's flavour of useFormValidatorGroup: the group it creates has\n * `.Form` attached and defaults `onSubmitError` to an error toast (see\n * FormValidatorGroupWithForm). Reuses the core package's reactive wiring\n * (useFormValidatorGroupInstance) so this and the pure hook share one\n * implementation of \"subscribe a function component to a group\".\n */\nexport function useFormValidatorGroup<\nTGroup extends FormGroup = FormGroup,\nTInitial = InferGroupValues<TGroup>\n>(\n groupDef: TGroup,\n { initialValues, onSubmit, onValidate, errorParser, onSubmitError }: FormValidatorGroupOptions<TGroup, TInitial> = {}\n): FormValidatorGroupWithForm<TGroup, TInitial> {\n return useFormValidatorGroupInstance(\n () => new FormValidatorGroupWithForm(groupDef, null, { initialValues, errorParser, onSubmitError }),\n onSubmit,\n onValidate,\n );\n}\n"],"mappings":"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"}
|