@ahrowe/ui 0.4.1 → 0.4.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["#valuesAfterCreation","#initialValues","#updateListeners","#isSubmitting","#notifyListeners","#debounceTimer","#errors","#value","#touched","#dirty","#label"],"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/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/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/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/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/floatingMenu/floatingMenu.module.pcss","../package/common/floatingMenu/useFloatingPosition.ts","../package/common/floatingMenu/floatingMenu.types.ts","../package/common/floatingMenu/floatingMenu.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/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/progressBar/progressBar.module.pcss","../package/common/progressBar/progressBar.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/skeleton/skeleton.types.ts","../package/common/skeleton/skeleton.module.pcss","../package/common/skeleton/skeleton.tsx","../package/common/stepper/stepper.module.pcss","../package/common/stepper/stepper.tsx","../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/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/formValidatorGroup.ts","../package/services/formValidation/FormValidatorGroupForm.tsx","../package/services/formValidation/FormValidatorGroupWithForm.tsx","../package/services/formValidation/formValidator.ts","../package/services/regexp.ts","../package/services/formValidation/validators.ts","../package/services/formValidation/validatableComponent.tsx","../package/services/formValidation/useFormValidator.ts","../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 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 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 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, { 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';\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({\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}: AccordionProps): ReactElement {\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 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';\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({\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}: ButtonProps): ReactElement {\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 { ActionButtonsProps } from './actionButtons.types';\n\nexport default function ActionButtons({\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}: ActionButtonsProps) {\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 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 { 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';\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({\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}: BadgeProps): ReactElement {\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","import type { ReactNode } from 'react';\nimport { IconDefinition } from '@fortawesome/free-solid-svg-icons';\nimport type { ButtonStyleType } from '../button/button.types';\nimport type { HtmlProps } from '../types/slots.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 interface CardHeaderAction {\n title?: string;\n onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;\n icon: IconDefinition;\n}\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 }\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';\n\nconst CLASS_BY_STYLE: Record<CardStyleType, string> = {\n elevated: styles.cardStyleElevated,\n outlined: styles.cardStyleOutlined,\n filled: styles.cardStyleFilled,\n};\n\nfunction Card({\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}: CardProps) {\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","\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 }\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';\n\nimport type { CheckboxProps } from './checkbox.types';\nimport styles from './checkbox.module.pcss';\n\nfunction Checkbox({\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}: CheckboxProps): ReactElement {\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 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 }\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';\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({\n className = '',\n thumbnail = '',\n text = '',\n styleType = ChipStyleType.Default,\n showRemoveIcon = false,\n onClick,\n onRemove,\n ...rest\n}: ChipProps) {\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",".floatingMenu {\n position: relative;\n\n &-content {\n cursor: pointer;\n }\n\n &-container {\n color: var(--text-color);\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","import { useLayoutEffect, type RefObject } from 'react';\n\n// Scrollable ancestors up to (not including) <body> — computed once per open, not on\n// every scroll tick, since walking the tree and reading computed style forces layout\n// and is too expensive to repeat at scroll frequency (this is what Floating UI's\n// autoUpdate does too: it resolves the ancestor list once via getOverflowAncestors).\n// Plain page/viewport scroll deliberately isn't included: a trigger that scrolls off\n// the top of the page already renders its fixed-position anchor off-screen for free.\nfunction 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\nfunction isHiddenByAnyAncestor(rect: DOMRect, ancestors: HTMLElement[]) {\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\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 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 menuClicked = 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 >\n {content}\n </div>\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n\nexport default FloatingMenu;\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(--error-font-color);\n}\n\n.isRequired {\n color: var(--message-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 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 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 &-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 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 FormValidator from 'services/formValidation/formValidator';\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 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 styles from './input.module.pcss';\nimport type { InputProps } from './input.types';\nimport { InputType } from './input.types';\n\nfunction Input({\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 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}: InputProps) {\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\n const currVal = formValidator ? formValidator.value : value;\n const shouldFloatLabel = useMatLabelStyle && (isFocused || 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 {editedLabel && !useMatLabelStyle ? (\n <span className={styles.inputLabelText}>\n {`${editedLabel} `}\n {computedIsRequired() ? <span className={cx(styles.isRequired)}>&nbsp; *</span> : null}\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 },\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]: isFocused,\n [styles.inputContainerBorderSearchFocused]:\n type === InputType.Search && (isFocused || 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 {editedLabel}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.inputPlaceholder,\n isFocused && !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 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 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 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 }\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 }\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 /* 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 }\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 }\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","import { useState, useRef, useEffect, type ReactElement } from 'react';\nimport cx from 'classnames';\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\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 useEffect(() => {\n setDraft(hex);\n }, [hex]);\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: MouseEvent): { 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 function onGradientMouseDown(e: React.MouseEvent) {\n const { s, v } = getSVFromEvent(e.nativeEvent);\n onSVChange(s, v);\n\n const onMove = (ev: MouseEvent) => {\n const { s, v } = getSVFromEvent(ev);\n onSVChange(s, v);\n };\n const onUp = () => {\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n };\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', 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 onMouseDown={onGradientMouseDown}\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 && <HexInput hex={hexInputValue} onChange={onHexChange} />}\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 }\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 type { ConfirmModalProps } from './confirmModal.types';\n\nfunction ConfirmModal({\n children = null,\n className = '',\n onClose = () => {},\n onConfirm = () => {},\n title = '',\n content = null,\n isOpen: propIsOpen = undefined,\n actionButtonsProps = {},\n}: ConfirmModalProps): ReactElement {\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=\"Confirm\"\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\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 &nbsp;\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(--error-font-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 background-color: var(--input-background);\n border-radius: var(--default-border-radius);\n\n &-plain {\n background: transparent;\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 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 &: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\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 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 pointer-events: none;\n user-select: none;\n\n &-floating {\n inset: -9px 0 0 14px;\n font-size: 13px;\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 styles from './dropdown.module.pcss';\nimport type { DropdownProps, DropdownItem } from './dropdown.types';\n\nfunction Dropdown({\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 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 placeholder = '',\n plainStyle = false,\n scrollToSelected = false,\n reactRef,\n ...rest\n}: DropdownProps) {\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 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 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 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 { [styles.dropdownInputPlain]: plainStyle },\n dropDownInputClassName\n )}\n >\n <button\n tabIndex={tabIndex}\n type=\"button\"\n disabled={disabled}\n style={isDropdownListWider ? { padding: '6px', border: 'none' } : {}}\n className={cx(\n styles.dropdownInputButton,\n { [styles.dropdownInputButtonDisabled]: disabled },\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 && (\n <FontAwesomeIcon\n icon={dropdownIcon}\n className={cx(styles.dropdownInputButtonIconArrow, {\n [styles.dropdownInputButtonIconArrowOpen]: isOpen,\n })}\n />\n )}\n </button>\n {!disabled && isOpen ? (\n <BodyEnd>\n <div\n ref={anchorRef}\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]: isFocused,\n [styles.dropdownBorderInvalid]: hasErr,\n [styles.dropdownBorderError]: hasErr,\n })}\n >\n <legend\n className={cx(styles.dropdownFieldsetLegend, {\n [styles.dropdownFieldsetLegendActive]:\n useMatLabelStyle && (isFocused || !isDisplayBlank),\n })}\n >\n <span>{label}</span>\n </legend>\n </fieldset>\n {useMatLabelStyle && label && (\n <div\n className={cx(styles.dropdownMatLabel, {\n [styles.dropdownMatLabelFloating]: isFocused || !isDisplayBlank,\n })}\n >\n {label}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.dropdownPlaceholder,\n isFocused && !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 {computedIsRequired() ? <div className={styles.requiredMark}>*</div> : null}\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","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport Input from '../input';\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/formValidator';\n\nimport styles from './datePicker.module.pcss';\n\ninterface 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({\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}: DatePickerProps) {\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 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",".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 }\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(--primary-lighter);\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 &:hover {\n border-color: var(--primary-color);\n background: var(--background-accent-light);\n }\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 &:hover {\n border-color: var(--error-color);\n background: var(--error-lighter);\n }\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 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 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\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 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({\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 ...rest\n}: InputDropdownProps) {\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 (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 (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]);\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 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 && (\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 }\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 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/formValidator';\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';\n\ninterface Properties\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 placeholder?: string;\n sign?: '+' | '-';\n showArrows?: boolean;\n step?: number;\n onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n}\n\nfunction NumberInput({\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 placeholder,\n sign,\n showArrows = false,\n step = 1,\n onKeyDown: onKeyDownProp,\n ...rest\n}: Properties): ReactElement {\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 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 (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 ? (\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 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\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 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",".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 { 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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\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 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 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 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 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 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 }\n *[id^=\"room\"] {\n cursor: pointer;\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 }\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) var(--background);\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 var(--background);\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 } 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';\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({\n variant = SkeletonVariant.Text,\n animation = SkeletonAnimation.Shimmer,\n lines = 1,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: SkeletonProps): ReactElement {\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",".stepper {\n display: flex;\n align-items: center;\n margin-bottom: 30px;\n user-select: none;\n\n &-clickable {\n cursor: pointer;\n }\n\n &-vertical {\n flex-flow: column;\n }\n\n &-connector {\n width: 50px;\n height: 1px;\n background-position: 0% 50%;\n transition: all 0.6s;\n background-size: 200% 200%;\n background-image: repeating-linear-gradient(\n 90deg,\n var(--primary-lighter) 0%,\n var(--primary-lighter) 50%,\n var(--primary-color) 50%,\n var(--primary-color) 100%\n );\n\n &-vertical {\n width: 3px;\n height: 100px;\n background-position: 0% 100%;\n background-image: repeating-linear-gradient(\n 0deg,\n var(--primary-lighter) 0%,\n var(--primary-lighter) 50%,\n var(--primary-color) 50%,\n var(--primary-color) 100%\n );\n }\n\n &-filled {\n background-position: -100% 0%;\n height: 3px;\n }\n }\n\n &-entry {\n width: 40px;\n height: 40px;\n box-sizing: border-box;\n border: 1px solid var(--primary-lighter);\n color: var(--primary-lighter);\n position: relative;\n border-radius: var(--default-border-radius);\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: inset 0px 0px 0px var(--primary-color);\n transform: none;\n transition: all 0.4s;\n\n &-active {\n border: 2px solid var(--primary-color);\n color: var(--primary-color);\n transform: scale3d(1.1, 1.1, 1);\n }\n\n &-done {\n box-shadow: inset 0px 0px 0px 30px var(--primary-color);\n transform: none;\n }\n\n &-number {\n stroke-dasharray: 5;\n stroke-dashoffset: 5;\n\n &-done {\n animation: 0.4s 0.2s forwards showCheckmark;\n }\n }\n\n @keyframes showCheckmark {\n from {\n stroke-dashoffset: 5;\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n\n &-label {\n position: absolute;\n top: 45px;\n left: 0px;\n width: 140px;\n transform: translate(-50px);\n text-align: center;\n\n &-vertical {\n top: 0px;\n left: 100px;\n text-align: left;\n }\n }\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport styles from './stepper.module.pcss';\nimport InteractableDiv from '../interactableDiv';\nimport type { StepperProps, StepperStep } from './stepper.types';\n\nfunction Checkmark() {\n return (\n <svg\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\" stroke=\"white\" strokeWidth=\"0.4\" fill=\"none\" />\n </svg>\n );\n}\n\nexport default function Stepper({\n steps = [],\n currentStep = 0,\n alignment = 'horizontal',\n onStepClicked = null,\n nonLinear = false,\n hideLabels = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: StepperProps) {\n const isVertical = alignment === 'vertical';\n\n return (\n <div\n {...rest}\n className={cx(styles.stepper, { [styles.stepperVertical]: isVertical }, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n >\n {steps.map((step: StepperStep, index: number) => {\n const isDone = index < currentStep;\n const isActive = index <= currentStep;\n // nonLinear: every step except the current one is clickable\n // linear: only completed steps are clickable\n const isClickable = !!onStepClicked && (nonLinear ? index !== currentStep : isDone);\n\n const entryClassName = cx(\n styles.stepperEntry,\n { [styles.stepperEntryActive]: isActive },\n { [styles.stepperEntryDone]: isDone },\n { [styles.stepperClickable]: isClickable },\n classNames?.entry\n );\n\n const entryContent = (\n <>\n <div\n className={cx(\n styles.stepperEntryNumber,\n { [styles.stepperEntryNumberDone]: isDone },\n classNames?.entryNumber\n )}\n style={slotStyles?.entryNumber}\n >\n {isDone ? <Checkmark /> : index + 1}\n </div>\n {!hideLabels && (\n <div\n className={cx(\n styles.stepperEntryLabel,\n { [styles.stepperEntryLabelVertical]: isVertical },\n classNames?.entryLabel\n )}\n style={slotStyles?.entryLabel}\n >\n {step.label}\n </div>\n )}\n </>\n );\n\n return (\n <React.Fragment key={index}>\n {isClickable ? (\n <InteractableDiv\n className={entryClassName}\n style={slotStyles?.entry}\n onClick={() => onStepClicked(index)}\n aria-current={index === currentStep ? 'step' : undefined}\n >\n {entryContent}\n </InteractableDiv>\n ) : (\n <div\n className={entryClassName}\n style={slotStyles?.entry}\n aria-current={index === currentStep ? 'step' : undefined}\n >\n {entryContent}\n </div>\n )}\n\n {index < steps.length - 1 && (\n <div\n className={cx(\n styles.stepperConnector,\n { [styles.stepperConnectorFilled]: isDone },\n { [styles.stepperConnectorVertical]: isVertical },\n classNames?.connector\n )}\n style={slotStyles?.connector}\n />\n )}\n </React.Fragment>\n );\n })}\n </div>\n );\n}\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';\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 [isStuck, setIsStuck] = useState(false);\n const [metrics, setMetrics] = useState<Metrics>({ width: 0, left: 0, height: 0 });\n\n const onStuckChangeRef = useRef(onStuckChange);\n useEffect(() => {\n onStuckChangeRef.current = onStuckChange;\n }, [onStuckChange]);\n\n const update = 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 setIsStuck(!disabled && rootRect.top <= offsetTop);\n }, [disabled, offsetTop]);\n\n useLayoutEffect(() => {\n update();\n }, [update, children]);\n\n useEffect(() => {\n let raf = 0;\n const schedule = () => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(update);\n };\n window.addEventListener('scroll', schedule, { passive: true, capture: true });\n window.addEventListener('resize', schedule);\n\n const ro = new ResizeObserver(schedule);\n if (rootRef.current) ro.observe(rootRef.current);\n if (contentRef.current) ro.observe(contentRef.current);\n\n return () => {\n cancelAnimationFrame(raf);\n window.removeEventListener('scroll', schedule, { capture: true } as EventListenerOptions);\n window.removeEventListener('resize', schedule);\n ro.disconnect();\n };\n }, [update]);\n\n const firstRun = useRef(true);\n useEffect(() => {\n if (firstRun.current) {\n firstRun.current = false;\n return;\n }\n onStuckChangeRef.current?.(isStuck);\n }, [isStuck]);\n\n const contentStyle: React.CSSProperties | undefined = isStuck\n ? {\n position: 'fixed',\n top: offsetTop,\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 {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, 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 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 type { SwitchProps } from './switch.types';\nimport styles from './switch.module.pcss';\n\nfunction Switch({\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}: SwitchProps): ReactElement {\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 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 type { TextareaProps } from './textarea.types';\n\nexport default function Textarea(props: TextareaProps) {\n return <Input {...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 '--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",".colorFade * {\n transition: background 0.3s ease-in-out;\n}\n","import React, { Component } from 'react';\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 if (this.createdThemeColorMeta) this.themeColorMeta?.remove();\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={colorFadeActive ? styles.colorFade : undefined}\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}\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\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\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 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 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 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';\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 const paused = pauseOnHover && (hovered || focused);\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 className={cx(\n styles.toast,\n isBottom ? styles.toastBottom : null,\n styles[`toast-${type}`],\n dismissing && 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 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 &-popover {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n box-shadow: var(--card-shadow);\n min-width: 160px;\n padding: 4px 0;\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 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 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 toggleRef: React.RefObject<HTMLDivElement | null>;\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 const toggleRef = useRef<HTMLDivElement>(null);\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 const effectiveVisible: Set<string> = isControlled ? new Set(visibleColumnKeys) : internalVisibleKeys;\n\n useEffect(() => {\n if (!toggleOpen) return;\n function onMouseDown(e: MouseEvent) {\n if (toggleRef.current && !toggleRef.current.contains(e.target as Node)) {\n setToggleOpen(false);\n }\n }\n document.addEventListener('mousedown', onMouseDown);\n return () => document.removeEventListener('mousedown', onMouseDown);\n }, [toggleOpen]);\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 const shouldShowToggle = showColumnToggle !== false && hasColumns;\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 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 toggleRef,\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 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, toggleRef, 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 ref={toggleRef} className={styles.virtualListToggleWrapper}>\n <button\n type=\"button\"\n className={cx(styles.virtualListHeaderToggle, classNames?.headerToggle)}\n style={slotStyles?.headerToggle}\n onClick={() => setToggleOpen((v) => !v)}\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 {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 {toggleOpen && (\n <div\n className={cx(styles.virtualListTogglePopover, classNames?.togglePopover)}\n style={slotStyles?.togglePopover}\n >\n {columns!.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 cursorDefault={false}\n >\n {col.label}\n </Checkbox>\n ))}\n </div>\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 polyglot from 'services/localization';\n\nimport type FormValidator from './formValidator';\nimport type { ValidationError, ErrorParser, UpdateListener } from './types';\n\n/** @internal */\nfunction defaultErrorParser(err: unknown): ValidationError[] {\n const e = err as { errors?: Record<string, string>[] };\n if (e?.errors && Array.isArray(e.errors)) {\n return e.errors.flatMap((errorObj) =>\n Object.entries(errorObj).map(([id, message]) => ({ id, message }))\n );\n }\n return [];\n}\n\nexport type FormGroup = Record<string, FormValidator<any>>; // eslint-disable-line @typescript-eslint/no-explicit-any\nexport type FormValues = Record<string, unknown>;\n\nexport type InferGroupValues<TGroup extends FormGroup> = {\n [K in keyof TGroup]: TGroup[K] extends FormValidator<infer V> ? V : never;\n};\n\n/**\n * The submitted result type: TInitial with all group-field keys replaced by\n * their typed validator values.\n */\nexport type MergedValues<TInitial, TGroup extends FormGroup> =\n Omit<TInitial, keyof TGroup & string> & InferGroupValues<TGroup>;\n\nexport interface FormValidatorGroupOptions<\n TGroup extends FormGroup = FormGroup,\n TInitial = InferGroupValues<TGroup>\n> {\n initialValues?: TInitial;\n onSubmit?: (\n values: MergedValues<TInitial, TGroup>,\n group: FormValidatorGroup<TGroup, TInitial>\n ) => Promise<void> | void;\n onValidate?: (group: FormValidatorGroup<TGroup, TInitial>) => ValidationError | null | void;\n errorParser?: ErrorParser;\n onSubmitError?: (errors: ValidationError[]) => void;\n}\n\ninterface ComponentLike {\n forceUpdate: () => void;\n}\n\nexport default class FormValidatorGroup<\n TGroup extends FormGroup = FormGroup,\n TInitial = InferGroupValues<TGroup>\n> {\n #initialValues: TInitial;\n #isSubmitting: boolean = false;\n #debounceTimer: ReturnType<typeof setTimeout> | undefined;\n #valuesAfterCreation: FormValues;\n #updateListeners: UpdateListener[] = [];\n\n group: TGroup;\n component: ComponentLike | null;\n onSubmitCallback: (values: MergedValues<TInitial, TGroup>, group: FormValidatorGroup<TGroup, TInitial>) => Promise<void> | void;\n onValidateCallback: (group: FormValidatorGroup<TGroup, TInitial>) => ValidationError | null | void;\n errorParser: ErrorParser;\n onSubmitError: (errors: ValidationError[]) => void;\n submitCount: number;\n onDebounce: (values: MergedValues<TInitial, TGroup>) => void;\n onReset: (group: FormValidatorGroup<TGroup, TInitial>, valuesAfterCreation: FormValues, initialValues: TInitial) => void;\n\n /**\n * @param formValidatorGroup - Map of field name → FormValidator\n * @param component - Class component instance for forceUpdate (pass null when using hooks)\n * @param options - initialValues, onSubmit, onValidate, errorParser\n */\n constructor(\n formValidatorGroup: TGroup,\n component: ComponentLike | null = null,\n {\n initialValues,\n onSubmit = () => undefined,\n onValidate = () => undefined,\n errorParser = defaultErrorParser,\n onSubmitError = () => undefined,\n }: FormValidatorGroupOptions<TGroup, TInitial> = {}\n ) {\n this.group = formValidatorGroup;\n this.#initialValues = (initialValues ?? {}) as TInitial;\n this.#valuesAfterCreation = {};\n this.submitCount = 0;\n this.onDebounce = () => {};\n this.onReset = () => {};\n\n Object.keys(this.group).forEach((validatorKey) => {\n const currentValidator = this.group[validatorKey];\n const iv = this.#initialValues as FormValues;\n if (iv[validatorKey] !== undefined) {\n currentValidator.set(iv[validatorKey], false);\n }\n this.#valuesAfterCreation[validatorKey] = currentValidator.value;\n this.group[validatorKey].registerOnUpdateListener(() => {\n this.#notifyListeners();\n this.submitCount = 0;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#debounceTimer = setTimeout(() => this.onDebounce(this.getValues()), 500);\n });\n });\n\n this.component = component;\n this.onSubmitCallback = onSubmit as typeof this.onSubmitCallback;\n this.onValidateCallback = onValidate as typeof this.onValidateCallback;\n this.errorParser = errorParser;\n this.onSubmitError = onSubmitError;\n this.setSubmitting(false);\n }\n\n get isSubmitting(): boolean { return this.#isSubmitting; }\n\n get wasTouched(): boolean {\n return Object.keys(this.group).some((key) => this.group[key].touched);\n }\n\n get isDirty(): boolean {\n return Object.keys(this.group).some((key) => this.group[key].dirty);\n }\n\n get hasErrors(): boolean {\n return Object.keys(this.group).some((key) => this.group[key].errors.length > 0);\n }\n\n get initialValues(): TInitial {\n return { ...this.#initialValues } as TInitial;\n }\n\n getFormError = (): ValidationError | null => {\n const groupKeys = Object.keys(this.group);\n for (let i = 0; i < groupKeys.length; i += 1) {\n const key = groupKeys[i];\n if (this.group[key].errors.length > 0) return this.group[key].errors[0];\n }\n return null;\n };\n\n set = (validatorName: keyof TGroup & string, value: unknown): this => {\n this.group[validatorName].set(value);\n return this;\n };\n\n reset = (toOverride: FormValues = {}): void => {\n this.submitCount = 0;\n const toOverrideKeys = Object.keys(toOverride);\n Object.keys(this.group).forEach((validatorKey) => {\n this.group[validatorKey].set(\n toOverrideKeys.includes(validatorKey)\n ? toOverride[validatorKey]\n : this.#valuesAfterCreation[validatorKey],\n false\n );\n });\n this.resetDirtyAndTouched();\n if (this.onReset) this.onReset(this, this.#valuesAfterCreation, this.#initialValues);\n };\n\n resetDirtyAndTouched = (): void => {\n Object.keys(this.group).forEach((key) => {\n this.group[key].dirty = false;\n this.group[key].touched = false;\n });\n };\n\n /**\n * Parses an API error and pushes field-level errors into the matching validators.\n * When field errors are found and isInternal is set, surfaces the first field message.\n * When the error shape isn't recognised (no field errors), always surfaces a generic message.\n */\n parseError = (err: unknown, isInternal: boolean = false): void => {\n const fieldErrors = this.errorParser(err);\n if (fieldErrors.length > 0) {\n fieldErrors.forEach(({ id, message }) => {\n if (this.group[id]) this.group[id].addError({ id, message });\n });\n if (isInternal) {\n this.onSubmitError(fieldErrors);\n }\n } else {\n this.onSubmitError([{ id: 'generic', message: 'An error occurred' }]);\n }\n };\n\n #notifyListeners = (): void => {\n if (this.component) this.component.forceUpdate();\n this.#updateListeners.forEach((cb) => cb());\n };\n\n registerOnUpdateListener = (callback: UpdateListener): void => {\n this.#updateListeners.push(callback);\n };\n\n removeOnUpdateListener = (callback: UpdateListener): void => {\n this.#updateListeners.splice(this.#updateListeners.indexOf(callback), 1);\n };\n\n setSubmitting = (isSubmitting: boolean): void => {\n if (this.#isSubmitting !== isSubmitting) {\n this.#isSubmitting = isSubmitting;\n this.#notifyListeners();\n }\n };\n\n submit = async (event?: Event | React.SyntheticEvent | null): Promise<void> => {\n if (event) {\n if ((event as Event).preventDefault) (event as Event).preventDefault();\n if ((event as Event).stopPropagation) (event as Event).stopPropagation();\n }\n this.setSubmitting(true);\n\n let customError: ValidationError | null | void = null;\n if (this.submitCount === 0) {\n customError = await Promise.resolve(this.validate());\n } else if (this.onValidateCallback) {\n customError = await Promise.resolve(this.onValidateCallback(this));\n }\n const currentError = this.getFormError() || customError;\n\n if (currentError) {\n this.setSubmitting(false);\n if (this.submitCount > -1) {\n this.onSubmitError([currentError]);\n }\n this.submitCount += 1;\n this.#notifyListeners();\n return;\n }\n\n try {\n await this.onSubmitCallback(this.getValues(), this);\n this.resetDirtyAndTouched();\n } catch (err) {\n this.parseError(err, true);\n }\n this.setSubmitting(false);\n this.#notifyListeners();\n this.submitCount += 1;\n };\n\n getValues = (): MergedValues<TInitial, TGroup> => {\n const retObj: FormValues = {};\n Object.keys(this.group).forEach((key) => {\n retObj[key] = this.group[key].value;\n });\n return { ...this.#initialValues, ...retObj } as MergedValues<TInitial, TGroup>;\n };\n\n validate = (): ValidationError | null | void => {\n Object.keys(this.group).forEach((validator) => {\n this.group[validator].validate();\n this.group[validator].touched = true;\n });\n if (this.onValidateCallback) return this.onValidateCallback(this);\n };\n\n setValidator = <K extends keyof TGroup & string>(validatorName: K, validator: TGroup[K]): this => {\n this.group[validatorName] = validator;\n return this;\n };\n}\n\n// Needed for the submit method's event type\nimport type React from 'react';\n","import React from 'react';\nimport type FormValidatorGroup from './formValidatorGroup';\n\n/**\n * Creates the Form component for a FormValidatorGroup instance.\n * Kept in a separate .tsx file so formValidatorGroup.ts stays framework-agnostic.\n */\nexport function createFormComponent(group: Pick<FormValidatorGroup, 'submit'>): React.FC<React.FormHTMLAttributes<HTMLFormElement>> {\n return function Form({ children, ...rest }) {\n return (\n <form onSubmit={group.submit} noValidate {...rest}>\n {children}\n </form>\n );\n };\n}\n","import { showToast } from 'components/common/toast';\nimport FormValidatorGroup from './formValidatorGroup';\nimport { createFormComponent } from './FormValidatorGroupForm';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues } from './formValidatorGroup';\nimport type { ValidationError } from './types';\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","import type { ValidatorFunction, ValidationError, UpdateListener } from './types';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport default class FormValidator<T = any> {\n #value: T;\n #touched: boolean;\n #dirty: boolean;\n #errors: ValidationError[];\n #label: string;\n\n validators: ValidatorFunction[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onUpdateCallbacks: Array<(validator: FormValidator<any>) => void>;\n\n /**\n * Create a FormValidator to use standalone or inside a FormValidatorGroup.\n * @param initialValue - Default value of the field\n * @param validators - Array of validator functions\n */\n constructor(initialValue: T, validators?: ValidatorFunction[]) {\n this.#value = initialValue;\n this.validators = validators ?? [];\n this.#touched = false;\n this.#dirty = false;\n this.#errors = [];\n this.#label = '';\n this.onUpdateCallbacks = [];\n this.validate();\n }\n\n /** Whether the user has entered and left the field. */\n get touched(): boolean { return this.#touched; }\n set touched(value: boolean) { this.#touched = value; this.onUpdate(); }\n\n get label(): string { return this.#label; }\n set label(value: string) { this.#label = value; }\n\n /** Whether the user has changed the value since initialisation. */\n get dirty(): boolean { return this.#dirty; }\n set dirty(value: boolean) { this.#dirty = value; this.onUpdate(); }\n\n get value(): T { return this.#value; }\n /** Sets value without validation (use `set()` for validated updates). */\n set value(val: T) { this.#value = val; this.onUpdate(); }\n\n get errors(): ValidationError[] { return this.#errors; }\n\n addError = (error: ValidationError): void => {\n this.#errors.push(error);\n this.onUpdate();\n };\n\n removeErrors = (errorIds: string[]): void => {\n this.#errors = this.#errors.filter((error) => !errorIds.includes(error.id));\n this.onUpdate();\n };\n\n clearErrors = (): void => {\n this.#errors = [];\n this.onUpdate();\n };\n\n hasError = (error?: string): boolean => {\n if (!error && this.errors.length > 0) return true;\n return !!(this.errors.find((err) => err.id === error));\n };\n\n getCurrentErrorMessage = (): string | null => {\n if (this.errors.length === 0) return null;\n return this.errors[0].message;\n };\n\n validate = (): void => {\n this.clearErrors();\n this.validators.forEach((validator) => {\n const res = validator(this.value, this.label);\n if (res) this.addError(res);\n });\n };\n\n onUpdate = (): void => {\n this.onUpdateCallbacks.forEach((cb) => cb(this));\n };\n\n registerOnUpdateListener = (callback: UpdateListener): void => {\n this.onUpdateCallbacks.push(callback);\n };\n\n removeOnUpdateListener = (callback: UpdateListener): void => {\n this.onUpdateCallbacks.splice(this.onUpdateCallbacks.indexOf(callback), 1);\n };\n\n /**\n * Sets the field value with optional dirty tracking and re-validates.\n * @param newValue - New field value\n * @param wasUser - Whether the change was user-initiated (marks field dirty). Defaults to true.\n */\n set = (newValue: T, wasUser: boolean = true): this => {\n this.value = newValue;\n if (wasUser && !this.dirty) this.dirty = true;\n this.validate();\n return this;\n };\n}\n\nFormValidator.prototype.toString = function getValidatorValue() {\n return `${this.value}`;\n};\n","export function isNumber(string: string): boolean {\n return /^[0-9]+$/.test(string);\n}\n\nexport function isDate(string: string): boolean {\n return /^[0-9]{2}.[0-9]{2}.[0-9]{4}$/.test(string);\n}\n\nexport function isISODate(string: string): boolean {\n return /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}Z$/.test(string);\n}\n\nexport function isEmail(string: string): boolean {\n return /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-ZöäüÜÖÄß\\-0-9]+\\.)+[a-zA-Z]{2,}))$/.test(string);\n}\n\nexport function isBic(string: string): boolean {\n return /^[A-Z]{6}[A-Z\\d]{2}([A-Z\\d]{3})?$/.test(string);\n}\n\nexport function isURL(string: string): boolean {\n return /[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,63}(\\/[-a-zA-Z0-9@:%_+.~#?&//=]*)?$/.test(string);\n}\n\nexport function hasEightPasswordChars(string: string): boolean {\n return /^[\\w!@#$%^&*?±§~`'\"/\\\\[\\]{}\\-,.();:><+=|öäüÖÄÜß €μ]{8,}$/.test(string);\n}\n\nexport function hasOnePasswordLetter(string: string): boolean {\n return /^(?=.*[a-zöäüA-ZÖÄÜß])/.test(string);\n}\n\nexport function hasOnePasswordDigit(string: string): boolean {\n return /^(?=.*\\d)/.test(string);\n}\n\nexport function isPassword(string: string): boolean {\n return hasEightPasswordChars(string) && hasOnePasswordLetter(string) && hasOnePasswordDigit(string);\n}\n","import { isEmail, isDate, isISODate, isURL, isBic } from 'services/regexp';\nimport type { ValidatorFunction, ValidationError } from './types';\n\nconst polyglot = {\n t: (key: string, options?: Record<string, unknown>): string => {\n const translations: Record<string, string> = {\n 'formValidators.minLength': `Must be at least ${options?.min} characters long`,\n 'formValidators.maxLength': `Must be at most ${options?.max} characters long`,\n 'formValidators.email': 'Must be a valid email address',\n 'formValidators.required': `${options?.label || 'Value'} is required`,\n 'formValidators.value': 'Value',\n 'formValidators.mustBeNumber': 'Must be a number',\n 'formValidators.oneOf': `Must be one of the following values: ${options?.allowedValues}`,\n 'formValidators.typeOf': `Must have type of ${options?.allowedTypes}`,\n 'formValidators.multiEmail': 'Must be a comma or semicolon separated list of valid email addresses',\n 'formValidators.date': 'Must be a valid date',\n 'garages.errors.website': 'Must be a valid URL',\n 'garages.errors.bic': 'Must be a valid BIC',\n 'formValidators.minLetters': `Must contain at least ${options?.smart_count} letters`,\n 'formValidators.minDigits': `Must contain at least ${options?.smart_count} digits`,\n };\n return translations[key] || key;\n },\n};\n\nexport default class Validators {\n static minLength = (min: number, errorMsg?: string): ValidatorFunction => (value) => {\n if (!value || (value as string).length < min) return { id: 'minLength', message: errorMsg || polyglot.t('formValidators.minLength', { min }) };\n return null;\n };\n\n static maxLength = (max: number, errorMsg?: string): ValidatorFunction => (value) => {\n if (value && (value as string).length > max) return { id: 'maxLength', message: errorMsg || polyglot.t('formValidators.maxLength', { max }) };\n return null;\n };\n\n static email = (errorMsg?: string): ValidatorFunction => (value) => {\n if (value && !isEmail(value as string)) return { id: 'email', message: errorMsg || polyglot.t('formValidators.email') };\n return null;\n };\n\n static required = (errorMsg?: string): ValidatorFunction & { validatorId: string } => {\n function required(value: unknown, label?: string): ValidationError | null {\n if (!value && value !== 0) return { id: 'required', message: errorMsg || polyglot.t('formValidators.required', { label: label || polyglot.t('formValidators.value') }) };\n return null;\n }\n required.validatorId = 'required';\n return required;\n };\n\n static mustBeNumber = (errorMsg?: string): ValidatorFunction => (value) => {\n if (value && Number.isNaN(+(value as string))) return { id: 'mustBeNumber', message: errorMsg || polyglot.t('formValidators.mustBeNumber') };\n return null;\n };\n\n static oneOf = (allowedValues: unknown[], errorMsg?: string): ValidatorFunction => (value) => {\n if (value && !allowedValues.includes(value)) return { id: 'oneOf', message: errorMsg || polyglot.t('formValidators.oneOf', { allowedValues }) };\n return null;\n };\n\n static typeOf = (allowedTypes: string | string[], errorMsg?: string): ValidatorFunction => (value) => {\n if (Array.isArray(allowedTypes)) {\n for (let i = 0; i < allowedTypes.length; i += 1) {\n if (typeof value === allowedTypes[i]) return null;\n }\n } else if (typeof value === allowedTypes) {\n return null;\n }\n return { id: 'typeOf', message: errorMsg || `Must have type of ${allowedTypes}` };\n };\n\n static multiEmail = (errorMessage?: string): ValidatorFunction => (value) => {\n if (value) {\n const emailParts = (value as string).replace(/ /g, '').replace(/,/g, ';').split(';');\n for (let i = 0; i < emailParts.length; i += 1) {\n if (!isEmail(emailParts[i])) {\n return { id: 'multiEmail', message: errorMessage || polyglot.t('formValidators.multiEmail') };\n }\n }\n }\n return null;\n };\n\n static date = (errorMessage?: string): ValidatorFunction => (value) => {\n if (value && (!isDate(value as string) && !isISODate(value as string))) return { id: 'date', message: errorMessage || polyglot.t('formValidators.date') };\n return null;\n };\n\n static dateObject = (errorMessage?: string): ValidatorFunction => (value) => {\n if (value && !(value as { isValid: boolean }).isValid) return { id: 'date', message: errorMessage || polyglot.t('formValidators.date') };\n return null;\n };\n\n static website = (errorMsg?: string): ValidatorFunction => (value) => {\n if (value && !isURL(value as string)) return { id: 'website', message: errorMsg || polyglot.t('garages.errors.website') };\n return null;\n };\n\n static bic = (errorMsg?: string): ValidatorFunction => (value) => {\n if (value && !isBic(value as string)) return { id: 'bic', message: errorMsg || polyglot.t('garages.errors.bic') };\n return null;\n };\n\n static minLetters = (min: number, errorMsg?: string): ValidatorFunction => (value) => {\n if (value && (value as string).replace(/[^a-zöäüA-ZÖÄÜß]/g, '').length < min) return { id: 'minLetters', message: errorMsg || polyglot.t('formValidators.minLetters', { smart_count: min }) };\n return null;\n };\n\n static minDigits = (min: number, errorMsg?: string): ValidatorFunction => (value) => {\n if (value && (value as string).replace(/[\\D]/g, '').length < min) return { id: 'minDigits', message: errorMsg || polyglot.t('formValidators.minDigits', { smart_count: min }) };\n return null;\n };\n\n static password = (errorMsg?: string): ValidatorFunction => (value) => {\n const result = Validators.minLength(8)(value)\n || Validators.minLetters(1)(value)\n || Validators.minDigits(1)(value);\n if (result) return errorMsg ? { id: 'password', message: errorMsg } : result;\n return null;\n };\n}\n","/* eslint-disable react/no-unused-state */\nimport React, { PureComponent } from 'react';\nimport FormValidator from 'services/formValidation/formValidator';\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 { useEffect, useReducer } from 'react';\nimport type FormValidator from './formValidator';\n\n/**\n * Subscribes a function component to a FormValidator instance.\n * Triggers a re-render whenever value, errors, touched, or dirty changes.\n *\n * @param formValidator - The FormValidator instance to subscribe to (or null)\n * @returns The same formValidator for convenience\n */\nexport function useFormValidator<T extends FormValidator | null>(formValidator: T): T {\n const [, rerender] = useReducer((n: number) => n + 1, 0);\n\n useEffect(() => {\n if (!formValidator) return;\n formValidator.registerOnUpdateListener(rerender);\n return () => formValidator.removeOnUpdateListener(rerender);\n }, [formValidator]);\n\n return formValidator;\n}\n","import { useEffect, useReducer, useRef } from 'react';\nimport FormValidatorGroup from './FormValidatorGroupWithForm';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues } from './formValidatorGroup';\n\n/**\n * Creates and subscribes a function component to a FormValidatorGroup.\n * Triggers a re-render whenever any field, submit state, or validation state changes.\n *\n * The group is created once on mount from the provided field map.\n * onSubmit / onValidate are kept fresh via refs — they always reflect the latest\n * closure without needing to be listed in effect dependencies.\n *\n * onSubmitError defaults to showing the message as an error toast (provided by FormValidatorGroupWithForm);\n * pass options.onSubmitError to override.\n *\n * @param groupDef - Map of field name → FormValidator instance\n * @param options - initialValues, onSubmit, onValidate, errorParser, onSubmitError\n *\n * @example\n * const form = useFormValidatorGroup(\n * { name: new FormValidator('', [Validators.required('Required')]) },\n * {\n * initialValues: { name: 'Jane' },\n * onSubmit: async (values) => save(values),\n * },\n * );\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): FormValidatorGroup<TGroup, TInitial> {\n const [, rerender] = useReducer((n: number) => n + 1, 0);\n\n const groupRef = useRef<FormValidatorGroup<TGroup, TInitial> | null>(null);\n if (!groupRef.current) {\n groupRef.current = new FormValidatorGroup(groupDef, null, {\n initialValues,\n errorParser,\n onSubmitError,\n });\n }\n const group = groupRef.current;\n\n const onSubmitRef = useRef(onSubmit);\n const onValidateRef = useRef(onValidate);\n onSubmitRef.current = onSubmit;\n onValidateRef.current = onValidate;\n\n useEffect(() => {\n if (onSubmit !== undefined) {\n group.onSubmitCallback = (...args) => onSubmitRef.current?.(...args);\n }\n if (onValidate !== undefined) {\n group.onValidateCallback = (...args) => onValidateRef.current?.(...args);\n }\n group.registerOnUpdateListener(rerender);\n return () => group.removeOnUpdateListener(rerender);\n }, []);\n\n return group;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["#valuesAfterCreation","#initialValues","#updateListeners","#isSubmitting","#notifyListeners","#debounceTimer","#errors","#value","#touched","#dirty","#label"],"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/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/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/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/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/floatingMenu/floatingMenu.module.pcss","../package/common/floatingMenu/useFloatingPosition.ts","../package/common/floatingMenu/floatingMenu.types.ts","../package/common/floatingMenu/floatingMenu.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/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/progressBar/progressBar.module.pcss","../package/common/progressBar/progressBar.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/skeleton/skeleton.types.ts","../package/common/skeleton/skeleton.module.pcss","../package/common/skeleton/skeleton.tsx","../package/common/stepper/stepper.module.pcss","../package/common/stepper/stepper.tsx","../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/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/formValidatorGroup.ts","../package/services/formValidation/FormValidatorGroupForm.tsx","../package/services/formValidation/FormValidatorGroupWithForm.tsx","../package/services/formValidation/formValidator.ts","../package/services/regexp.ts","../package/services/formValidation/validators.ts","../package/services/formValidation/validatableComponent.tsx","../package/services/formValidation/useFormValidator.ts","../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 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 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 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, { 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';\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({\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}: AccordionProps): ReactElement {\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 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';\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({\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}: ButtonProps): ReactElement {\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 { ActionButtonsProps } from './actionButtons.types';\n\nexport default function ActionButtons({\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}: ActionButtonsProps) {\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 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 { 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';\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({\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}: BadgeProps): ReactElement {\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","import type { ReactNode } from 'react';\nimport { IconDefinition } from '@fortawesome/free-solid-svg-icons';\nimport type { ButtonStyleType } from '../button/button.types';\nimport type { HtmlProps } from '../types/slots.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 interface CardHeaderAction {\n title?: string;\n onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;\n icon: IconDefinition;\n}\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 }\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';\n\nconst CLASS_BY_STYLE: Record<CardStyleType, string> = {\n elevated: styles.cardStyleElevated,\n outlined: styles.cardStyleOutlined,\n filled: styles.cardStyleFilled,\n};\n\nfunction Card({\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}: CardProps) {\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","\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 }\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';\n\nimport type { CheckboxProps } from './checkbox.types';\nimport styles from './checkbox.module.pcss';\n\nfunction Checkbox({\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}: CheckboxProps): ReactElement {\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 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 }\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';\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({\n className = '',\n thumbnail = '',\n text = '',\n styleType = ChipStyleType.Default,\n showRemoveIcon = false,\n onClick,\n onRemove,\n ...rest\n}: ChipProps) {\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",".floatingMenu {\n position: relative;\n\n &-content {\n cursor: pointer;\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","import { useLayoutEffect, type RefObject } from 'react';\n\n// Scrollable ancestors up to (not including) <body> — computed once per open, not on\n// every scroll tick, since walking the tree and reading computed style forces layout\n// and is too expensive to repeat at scroll frequency (this is what Floating UI's\n// autoUpdate does too: it resolves the ancestor list once via getOverflowAncestors).\n// Plain page/viewport scroll deliberately isn't included: a trigger that scrolls off\n// the top of the page already renders its fixed-position anchor off-screen for free.\nfunction 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\nfunction isHiddenByAnyAncestor(rect: DOMRect, ancestors: HTMLElement[]) {\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\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 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 menuClicked = 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 >\n {content}\n </div>\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n\nexport default FloatingMenu;\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(--error-font-color);\n}\n\n.isRequired {\n color: var(--message-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 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 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 &-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 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 FormValidator from 'services/formValidation/formValidator';\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 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 styles from './input.module.pcss';\nimport type { InputProps } from './input.types';\nimport { InputType } from './input.types';\n\nfunction Input({\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 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}: InputProps) {\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\n const currVal = formValidator ? formValidator.value : value;\n const shouldFloatLabel = useMatLabelStyle && (isFocused || 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 {editedLabel && !useMatLabelStyle ? (\n <span className={styles.inputLabelText}>\n {`${editedLabel} `}\n {computedIsRequired() ? <span className={cx(styles.isRequired)}>&nbsp; *</span> : null}\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 },\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]: isFocused,\n [styles.inputContainerBorderSearchFocused]:\n type === InputType.Search && (isFocused || 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 {editedLabel}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.inputPlaceholder,\n isFocused && !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 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 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 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 }\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 }\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 /* 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 }\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 }\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","import { useState, useRef, useEffect, type ReactElement } from 'react';\nimport cx from 'classnames';\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\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 useEffect(() => {\n setDraft(hex);\n }, [hex]);\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: MouseEvent): { 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 function onGradientMouseDown(e: React.MouseEvent) {\n const { s, v } = getSVFromEvent(e.nativeEvent);\n onSVChange(s, v);\n\n const onMove = (ev: MouseEvent) => {\n const { s, v } = getSVFromEvent(ev);\n onSVChange(s, v);\n };\n const onUp = () => {\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n };\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', 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 onMouseDown={onGradientMouseDown}\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 && <HexInput hex={hexInputValue} onChange={onHexChange} />}\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 }\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 type { ConfirmModalProps } from './confirmModal.types';\n\nfunction ConfirmModal({\n children = null,\n className = '',\n onClose = () => {},\n onConfirm = () => {},\n title = '',\n content = null,\n isOpen: propIsOpen = undefined,\n actionButtonsProps = {},\n}: ConfirmModalProps): ReactElement {\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=\"Confirm\"\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\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 &nbsp;\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(--error-font-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 background-color: var(--input-background);\n border-radius: var(--default-border-radius);\n\n &-plain {\n background: transparent;\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 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 &: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\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 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 pointer-events: none;\n user-select: none;\n\n &-floating {\n inset: -9px 0 0 14px;\n font-size: 13px;\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 styles from './dropdown.module.pcss';\nimport type { DropdownProps, DropdownItem } from './dropdown.types';\n\nfunction Dropdown({\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 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 placeholder = '',\n plainStyle = false,\n scrollToSelected = false,\n reactRef,\n ...rest\n}: DropdownProps) {\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 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 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 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 { [styles.dropdownInputPlain]: plainStyle },\n dropDownInputClassName\n )}\n >\n <button\n tabIndex={tabIndex}\n type=\"button\"\n disabled={disabled}\n style={isDropdownListWider ? { padding: '6px', border: 'none' } : {}}\n className={cx(\n styles.dropdownInputButton,\n { [styles.dropdownInputButtonDisabled]: disabled },\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 && (\n <FontAwesomeIcon\n icon={dropdownIcon}\n className={cx(styles.dropdownInputButtonIconArrow, {\n [styles.dropdownInputButtonIconArrowOpen]: isOpen,\n })}\n />\n )}\n </button>\n {!disabled && isOpen ? (\n <BodyEnd>\n <div\n ref={anchorRef}\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]: isFocused,\n [styles.dropdownBorderInvalid]: hasErr,\n [styles.dropdownBorderError]: hasErr,\n })}\n >\n <legend\n className={cx(styles.dropdownFieldsetLegend, {\n [styles.dropdownFieldsetLegendActive]:\n useMatLabelStyle && (isFocused || !isDisplayBlank),\n })}\n >\n <span>{label}</span>\n </legend>\n </fieldset>\n {useMatLabelStyle && label && (\n <div\n className={cx(styles.dropdownMatLabel, {\n [styles.dropdownMatLabelFloating]: isFocused || !isDisplayBlank,\n })}\n >\n {label}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.dropdownPlaceholder,\n isFocused && !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 {computedIsRequired() ? <div className={styles.requiredMark}>*</div> : null}\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","import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport Input from '../input';\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/formValidator';\n\nimport styles from './datePicker.module.pcss';\n\ninterface 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({\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}: DatePickerProps) {\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 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",".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 }\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(--primary-lighter);\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 &:hover {\n border-color: var(--primary-color);\n background: var(--background-accent-light);\n }\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 &:hover {\n border-color: var(--error-color);\n background: var(--error-lighter);\n }\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 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 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\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 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({\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 ...rest\n}: InputDropdownProps) {\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 (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 (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]);\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 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 && (\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 }\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 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/formValidator';\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';\n\ninterface Properties\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 placeholder?: string;\n sign?: '+' | '-';\n showArrows?: boolean;\n step?: number;\n onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n}\n\nfunction NumberInput({\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 placeholder,\n sign,\n showArrows = false,\n step = 1,\n onKeyDown: onKeyDownProp,\n ...rest\n}: Properties): ReactElement {\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 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 (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 ? (\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 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\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 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",".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 { 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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\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 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 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 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 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 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 }\n *[id^=\"room\"] {\n cursor: pointer;\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 }\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) var(--background);\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 var(--background);\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 } 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';\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({\n variant = SkeletonVariant.Text,\n animation = SkeletonAnimation.Shimmer,\n lines = 1,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: SkeletonProps): ReactElement {\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",".stepper {\n display: flex;\n align-items: center;\n margin-bottom: 30px;\n user-select: none;\n\n &-clickable {\n cursor: pointer;\n }\n\n &-vertical {\n flex-flow: column;\n }\n\n &-connector {\n width: 50px;\n height: 1px;\n background-position: 0% 50%;\n transition: all 0.6s;\n background-size: 200% 200%;\n background-image: repeating-linear-gradient(\n 90deg,\n var(--primary-lighter) 0%,\n var(--primary-lighter) 50%,\n var(--primary-color) 50%,\n var(--primary-color) 100%\n );\n\n &-vertical {\n width: 3px;\n height: 100px;\n background-position: 0% 100%;\n background-image: repeating-linear-gradient(\n 0deg,\n var(--primary-lighter) 0%,\n var(--primary-lighter) 50%,\n var(--primary-color) 50%,\n var(--primary-color) 100%\n );\n }\n\n &-filled {\n background-position: -100% 0%;\n height: 3px;\n }\n }\n\n &-entry {\n width: 40px;\n height: 40px;\n box-sizing: border-box;\n border: 1px solid var(--primary-lighter);\n color: var(--primary-lighter);\n position: relative;\n border-radius: var(--default-border-radius);\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: inset 0px 0px 0px var(--primary-color);\n transform: none;\n transition: all 0.4s;\n\n &-active {\n border: 2px solid var(--primary-color);\n color: var(--primary-color);\n transform: scale3d(1.1, 1.1, 1);\n }\n\n &-done {\n box-shadow: inset 0px 0px 0px 30px var(--primary-color);\n transform: none;\n }\n\n &-number {\n stroke-dasharray: 5;\n stroke-dashoffset: 5;\n\n &-done {\n animation: 0.4s 0.2s forwards showCheckmark;\n }\n }\n\n @keyframes showCheckmark {\n from {\n stroke-dashoffset: 5;\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n\n &-label {\n position: absolute;\n top: 45px;\n left: 0px;\n width: 140px;\n transform: translate(-50px);\n text-align: center;\n\n &-vertical {\n top: 0px;\n left: 100px;\n text-align: left;\n }\n }\n }\n}\n","import React from 'react';\nimport cx from 'classnames';\nimport styles from './stepper.module.pcss';\nimport InteractableDiv from '../interactableDiv';\nimport type { StepperProps, StepperStep } from './stepper.types';\n\nfunction Checkmark() {\n return (\n <svg\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\" stroke=\"white\" strokeWidth=\"0.4\" fill=\"none\" />\n </svg>\n );\n}\n\nexport default function Stepper({\n steps = [],\n currentStep = 0,\n alignment = 'horizontal',\n onStepClicked = null,\n nonLinear = false,\n hideLabels = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: StepperProps) {\n const isVertical = alignment === 'vertical';\n\n return (\n <div\n {...rest}\n className={cx(styles.stepper, { [styles.stepperVertical]: isVertical }, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n >\n {steps.map((step: StepperStep, index: number) => {\n const isDone = index < currentStep;\n const isActive = index <= currentStep;\n // nonLinear: every step except the current one is clickable\n // linear: only completed steps are clickable\n const isClickable = !!onStepClicked && (nonLinear ? index !== currentStep : isDone);\n\n const entryClassName = cx(\n styles.stepperEntry,\n { [styles.stepperEntryActive]: isActive },\n { [styles.stepperEntryDone]: isDone },\n { [styles.stepperClickable]: isClickable },\n classNames?.entry\n );\n\n const entryContent = (\n <>\n <div\n className={cx(\n styles.stepperEntryNumber,\n { [styles.stepperEntryNumberDone]: isDone },\n classNames?.entryNumber\n )}\n style={slotStyles?.entryNumber}\n >\n {isDone ? <Checkmark /> : index + 1}\n </div>\n {!hideLabels && (\n <div\n className={cx(\n styles.stepperEntryLabel,\n { [styles.stepperEntryLabelVertical]: isVertical },\n classNames?.entryLabel\n )}\n style={slotStyles?.entryLabel}\n >\n {step.label}\n </div>\n )}\n </>\n );\n\n return (\n <React.Fragment key={index}>\n {isClickable ? (\n <InteractableDiv\n className={entryClassName}\n style={slotStyles?.entry}\n onClick={() => onStepClicked(index)}\n aria-current={index === currentStep ? 'step' : undefined}\n >\n {entryContent}\n </InteractableDiv>\n ) : (\n <div\n className={entryClassName}\n style={slotStyles?.entry}\n aria-current={index === currentStep ? 'step' : undefined}\n >\n {entryContent}\n </div>\n )}\n\n {index < steps.length - 1 && (\n <div\n className={cx(\n styles.stepperConnector,\n { [styles.stepperConnectorFilled]: isDone },\n { [styles.stepperConnectorVertical]: isVertical },\n classNames?.connector\n )}\n style={slotStyles?.connector}\n />\n )}\n </React.Fragment>\n );\n })}\n </div>\n );\n}\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';\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 [isStuck, setIsStuck] = useState(false);\n const [metrics, setMetrics] = useState<Metrics>({ width: 0, left: 0, height: 0 });\n\n const onStuckChangeRef = useRef(onStuckChange);\n useEffect(() => {\n onStuckChangeRef.current = onStuckChange;\n }, [onStuckChange]);\n\n const update = 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 setIsStuck(!disabled && rootRect.top <= offsetTop);\n }, [disabled, offsetTop]);\n\n useLayoutEffect(() => {\n update();\n }, [update, children]);\n\n useEffect(() => {\n let raf = 0;\n const schedule = () => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(update);\n };\n window.addEventListener('scroll', schedule, { passive: true, capture: true });\n window.addEventListener('resize', schedule);\n\n const ro = new ResizeObserver(schedule);\n if (rootRef.current) ro.observe(rootRef.current);\n if (contentRef.current) ro.observe(contentRef.current);\n\n return () => {\n cancelAnimationFrame(raf);\n window.removeEventListener('scroll', schedule, { capture: true } as EventListenerOptions);\n window.removeEventListener('resize', schedule);\n ro.disconnect();\n };\n }, [update]);\n\n const firstRun = useRef(true);\n useEffect(() => {\n if (firstRun.current) {\n firstRun.current = false;\n return;\n }\n onStuckChangeRef.current?.(isStuck);\n }, [isStuck]);\n\n const contentStyle: React.CSSProperties | undefined = isStuck\n ? {\n position: 'fixed',\n top: offsetTop,\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 {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, 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 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 type { SwitchProps } from './switch.types';\nimport styles from './switch.module.pcss';\n\nfunction Switch({\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}: SwitchProps): ReactElement {\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 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 type { TextareaProps } from './textarea.types';\n\nexport default function Textarea(props: TextareaProps) {\n return <Input {...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 '--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 if (this.createdThemeColorMeta) this.themeColorMeta?.remove();\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}\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\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\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 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 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 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';\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 const paused = pauseOnHover && (hovered || focused);\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 className={cx(\n styles.toast,\n isBottom ? styles.toastBottom : null,\n styles[`toast-${type}`],\n dismissing && 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 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 &-popover {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n box-shadow: var(--card-shadow);\n min-width: 160px;\n padding: 4px 0;\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 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 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 toggleRef: React.RefObject<HTMLDivElement | null>;\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 const toggleRef = useRef<HTMLDivElement>(null);\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 const effectiveVisible: Set<string> = isControlled ? new Set(visibleColumnKeys) : internalVisibleKeys;\n\n useEffect(() => {\n if (!toggleOpen) return;\n function onMouseDown(e: MouseEvent) {\n if (toggleRef.current && !toggleRef.current.contains(e.target as Node)) {\n setToggleOpen(false);\n }\n }\n document.addEventListener('mousedown', onMouseDown);\n return () => document.removeEventListener('mousedown', onMouseDown);\n }, [toggleOpen]);\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 const shouldShowToggle = showColumnToggle !== false && hasColumns;\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 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 toggleRef,\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 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, toggleRef, 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 ref={toggleRef} className={styles.virtualListToggleWrapper}>\n <button\n type=\"button\"\n className={cx(styles.virtualListHeaderToggle, classNames?.headerToggle)}\n style={slotStyles?.headerToggle}\n onClick={() => setToggleOpen((v) => !v)}\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 {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 {toggleOpen && (\n <div\n className={cx(styles.virtualListTogglePopover, classNames?.togglePopover)}\n style={slotStyles?.togglePopover}\n >\n {columns!.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 cursorDefault={false}\n >\n {col.label}\n </Checkbox>\n ))}\n </div>\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 polyglot from 'services/localization';\n\nimport type FormValidator from './formValidator';\nimport type { ValidationError, ErrorParser, UpdateListener } from './types';\n\n/** @internal */\nfunction defaultErrorParser(err: unknown): ValidationError[] {\n const e = err as { errors?: Record<string, string>[] };\n if (e?.errors && Array.isArray(e.errors)) {\n return e.errors.flatMap((errorObj) =>\n Object.entries(errorObj).map(([id, message]) => ({ id, message }))\n );\n }\n return [];\n}\n\nexport type FormGroup = Record<string, FormValidator<any>>; // eslint-disable-line @typescript-eslint/no-explicit-any\nexport type FormValues = Record<string, unknown>;\n\nexport type InferGroupValues<TGroup extends FormGroup> = {\n [K in keyof TGroup]: TGroup[K] extends FormValidator<infer V> ? V : never;\n};\n\n/**\n * The submitted result type: TInitial with all group-field keys replaced by\n * their typed validator values.\n */\nexport type MergedValues<TInitial, TGroup extends FormGroup> =\n Omit<TInitial, keyof TGroup & string> & InferGroupValues<TGroup>;\n\nexport interface FormValidatorGroupOptions<\n TGroup extends FormGroup = FormGroup,\n TInitial = InferGroupValues<TGroup>\n> {\n initialValues?: TInitial;\n onSubmit?: (\n values: MergedValues<TInitial, TGroup>,\n group: FormValidatorGroup<TGroup, TInitial>\n ) => Promise<void> | void;\n onValidate?: (group: FormValidatorGroup<TGroup, TInitial>) => ValidationError | null | void;\n errorParser?: ErrorParser;\n onSubmitError?: (errors: ValidationError[]) => void;\n}\n\ninterface ComponentLike {\n forceUpdate: () => void;\n}\n\nexport default class FormValidatorGroup<\n TGroup extends FormGroup = FormGroup,\n TInitial = InferGroupValues<TGroup>\n> {\n #initialValues: TInitial;\n #isSubmitting: boolean = false;\n #debounceTimer: ReturnType<typeof setTimeout> | undefined;\n #valuesAfterCreation: FormValues;\n #updateListeners: UpdateListener[] = [];\n\n group: TGroup;\n component: ComponentLike | null;\n onSubmitCallback: (values: MergedValues<TInitial, TGroup>, group: FormValidatorGroup<TGroup, TInitial>) => Promise<void> | void;\n onValidateCallback: (group: FormValidatorGroup<TGroup, TInitial>) => ValidationError | null | void;\n errorParser: ErrorParser;\n onSubmitError: (errors: ValidationError[]) => void;\n submitCount: number;\n onDebounce: (values: MergedValues<TInitial, TGroup>) => void;\n onReset: (group: FormValidatorGroup<TGroup, TInitial>, valuesAfterCreation: FormValues, initialValues: TInitial) => void;\n\n /**\n * @param formValidatorGroup - Map of field name → FormValidator\n * @param component - Class component instance for forceUpdate (pass null when using hooks)\n * @param options - initialValues, onSubmit, onValidate, errorParser\n */\n constructor(\n formValidatorGroup: TGroup,\n component: ComponentLike | null = null,\n {\n initialValues,\n onSubmit = () => undefined,\n onValidate = () => undefined,\n errorParser = defaultErrorParser,\n onSubmitError = () => undefined,\n }: FormValidatorGroupOptions<TGroup, TInitial> = {}\n ) {\n this.group = formValidatorGroup;\n this.#initialValues = (initialValues ?? {}) as TInitial;\n this.#valuesAfterCreation = {};\n this.submitCount = 0;\n this.onDebounce = () => {};\n this.onReset = () => {};\n\n Object.keys(this.group).forEach((validatorKey) => {\n const currentValidator = this.group[validatorKey];\n const iv = this.#initialValues as FormValues;\n if (iv[validatorKey] !== undefined) {\n currentValidator.set(iv[validatorKey], false);\n }\n this.#valuesAfterCreation[validatorKey] = currentValidator.value;\n this.group[validatorKey].registerOnUpdateListener(() => {\n this.#notifyListeners();\n this.submitCount = 0;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#debounceTimer = setTimeout(() => this.onDebounce(this.getValues()), 500);\n });\n });\n\n this.component = component;\n this.onSubmitCallback = onSubmit as typeof this.onSubmitCallback;\n this.onValidateCallback = onValidate as typeof this.onValidateCallback;\n this.errorParser = errorParser;\n this.onSubmitError = onSubmitError;\n this.setSubmitting(false);\n }\n\n get isSubmitting(): boolean { return this.#isSubmitting; }\n\n get wasTouched(): boolean {\n return Object.keys(this.group).some((key) => this.group[key].touched);\n }\n\n get isDirty(): boolean {\n return Object.keys(this.group).some((key) => this.group[key].dirty);\n }\n\n get hasErrors(): boolean {\n return Object.keys(this.group).some((key) => this.group[key].errors.length > 0);\n }\n\n get initialValues(): TInitial {\n return { ...this.#initialValues } as TInitial;\n }\n\n getFormError = (): ValidationError | null => {\n const groupKeys = Object.keys(this.group);\n for (let i = 0; i < groupKeys.length; i += 1) {\n const key = groupKeys[i];\n if (this.group[key].errors.length > 0) return this.group[key].errors[0];\n }\n return null;\n };\n\n set = (validatorName: keyof TGroup & string, value: unknown): this => {\n this.group[validatorName].set(value);\n return this;\n };\n\n reset = (toOverride: FormValues = {}): void => {\n this.submitCount = 0;\n const toOverrideKeys = Object.keys(toOverride);\n Object.keys(this.group).forEach((validatorKey) => {\n this.group[validatorKey].set(\n toOverrideKeys.includes(validatorKey)\n ? toOverride[validatorKey]\n : this.#valuesAfterCreation[validatorKey],\n false\n );\n });\n this.resetDirtyAndTouched();\n if (this.onReset) this.onReset(this, this.#valuesAfterCreation, this.#initialValues);\n };\n\n resetDirtyAndTouched = (): void => {\n Object.keys(this.group).forEach((key) => {\n this.group[key].dirty = false;\n this.group[key].touched = false;\n });\n };\n\n /**\n * Parses an API error and pushes field-level errors into the matching validators.\n * When field errors are found and isInternal is set, surfaces the first field message.\n * When the error shape isn't recognised (no field errors), always surfaces a generic message.\n */\n parseError = (err: unknown, isInternal: boolean = false): void => {\n const fieldErrors = this.errorParser(err);\n if (fieldErrors.length > 0) {\n fieldErrors.forEach(({ id, message }) => {\n if (this.group[id]) this.group[id].addError({ id, message });\n });\n if (isInternal) {\n this.onSubmitError(fieldErrors);\n }\n } else {\n this.onSubmitError([{ id: 'generic', message: 'An error occurred' }]);\n }\n };\n\n #notifyListeners = (): void => {\n if (this.component) this.component.forceUpdate();\n this.#updateListeners.forEach((cb) => cb());\n };\n\n registerOnUpdateListener = (callback: UpdateListener): void => {\n this.#updateListeners.push(callback);\n };\n\n removeOnUpdateListener = (callback: UpdateListener): void => {\n this.#updateListeners.splice(this.#updateListeners.indexOf(callback), 1);\n };\n\n setSubmitting = (isSubmitting: boolean): void => {\n if (this.#isSubmitting !== isSubmitting) {\n this.#isSubmitting = isSubmitting;\n this.#notifyListeners();\n }\n };\n\n submit = async (event?: Event | React.SyntheticEvent | null): Promise<void> => {\n if (event) {\n if ((event as Event).preventDefault) (event as Event).preventDefault();\n if ((event as Event).stopPropagation) (event as Event).stopPropagation();\n }\n this.setSubmitting(true);\n\n let customError: ValidationError | null | void = null;\n if (this.submitCount === 0) {\n customError = await Promise.resolve(this.validate());\n } else if (this.onValidateCallback) {\n customError = await Promise.resolve(this.onValidateCallback(this));\n }\n const currentError = this.getFormError() || customError;\n\n if (currentError) {\n this.setSubmitting(false);\n if (this.submitCount > -1) {\n this.onSubmitError([currentError]);\n }\n this.submitCount += 1;\n this.#notifyListeners();\n return;\n }\n\n try {\n await this.onSubmitCallback(this.getValues(), this);\n this.resetDirtyAndTouched();\n } catch (err) {\n this.parseError(err, true);\n }\n this.setSubmitting(false);\n this.#notifyListeners();\n this.submitCount += 1;\n };\n\n getValues = (): MergedValues<TInitial, TGroup> => {\n const retObj: FormValues = {};\n Object.keys(this.group).forEach((key) => {\n retObj[key] = this.group[key].value;\n });\n return { ...this.#initialValues, ...retObj } as MergedValues<TInitial, TGroup>;\n };\n\n validate = (): ValidationError | null | void => {\n Object.keys(this.group).forEach((validator) => {\n this.group[validator].validate();\n this.group[validator].touched = true;\n });\n if (this.onValidateCallback) return this.onValidateCallback(this);\n };\n\n setValidator = <K extends keyof TGroup & string>(validatorName: K, validator: TGroup[K]): this => {\n this.group[validatorName] = validator;\n return this;\n };\n}\n\n// Needed for the submit method's event type\nimport type React from 'react';\n","import React from 'react';\nimport type FormValidatorGroup from './formValidatorGroup';\n\n/**\n * Creates the Form component for a FormValidatorGroup instance.\n * Kept in a separate .tsx file so formValidatorGroup.ts stays framework-agnostic.\n */\nexport function createFormComponent(group: Pick<FormValidatorGroup, 'submit'>): React.FC<React.FormHTMLAttributes<HTMLFormElement>> {\n return function Form({ children, ...rest }) {\n return (\n <form onSubmit={group.submit} noValidate {...rest}>\n {children}\n </form>\n );\n };\n}\n","import { showToast } from 'components/common/toast';\nimport FormValidatorGroup from './formValidatorGroup';\nimport { createFormComponent } from './FormValidatorGroupForm';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues } from './formValidatorGroup';\nimport type { ValidationError } from './types';\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","import type { ValidatorFunction, ValidationError, UpdateListener } from './types';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport default class FormValidator<T = any> {\n #value: T;\n #touched: boolean;\n #dirty: boolean;\n #errors: ValidationError[];\n #label: string;\n\n validators: ValidatorFunction[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onUpdateCallbacks: Array<(validator: FormValidator<any>) => void>;\n\n /**\n * Create a FormValidator to use standalone or inside a FormValidatorGroup.\n * @param initialValue - Default value of the field\n * @param validators - Array of validator functions\n */\n constructor(initialValue: T, validators?: ValidatorFunction[]) {\n this.#value = initialValue;\n this.validators = validators ?? [];\n this.#touched = false;\n this.#dirty = false;\n this.#errors = [];\n this.#label = '';\n this.onUpdateCallbacks = [];\n this.validate();\n }\n\n /** Whether the user has entered and left the field. */\n get touched(): boolean { return this.#touched; }\n set touched(value: boolean) { this.#touched = value; this.onUpdate(); }\n\n get label(): string { return this.#label; }\n set label(value: string) { this.#label = value; }\n\n /** Whether the user has changed the value since initialisation. */\n get dirty(): boolean { return this.#dirty; }\n set dirty(value: boolean) { this.#dirty = value; this.onUpdate(); }\n\n get value(): T { return this.#value; }\n /** Sets value without validation (use `set()` for validated updates). */\n set value(val: T) { this.#value = val; this.onUpdate(); }\n\n get errors(): ValidationError[] { return this.#errors; }\n\n addError = (error: ValidationError): void => {\n this.#errors.push(error);\n this.onUpdate();\n };\n\n removeErrors = (errorIds: string[]): void => {\n this.#errors = this.#errors.filter((error) => !errorIds.includes(error.id));\n this.onUpdate();\n };\n\n clearErrors = (): void => {\n this.#errors = [];\n this.onUpdate();\n };\n\n hasError = (error?: string): boolean => {\n if (!error && this.errors.length > 0) return true;\n return !!(this.errors.find((err) => err.id === error));\n };\n\n getCurrentErrorMessage = (): string | null => {\n if (this.errors.length === 0) return null;\n return this.errors[0].message;\n };\n\n validate = (): void => {\n this.clearErrors();\n this.validators.forEach((validator) => {\n const res = validator(this.value, this.label);\n if (res) this.addError(res);\n });\n };\n\n onUpdate = (): void => {\n this.onUpdateCallbacks.forEach((cb) => cb(this));\n };\n\n registerOnUpdateListener = (callback: UpdateListener): void => {\n this.onUpdateCallbacks.push(callback);\n };\n\n removeOnUpdateListener = (callback: UpdateListener): void => {\n this.onUpdateCallbacks.splice(this.onUpdateCallbacks.indexOf(callback), 1);\n };\n\n /**\n * Sets the field value with optional dirty tracking and re-validates.\n * @param newValue - New field value\n * @param wasUser - Whether the change was user-initiated (marks field dirty). Defaults to true.\n */\n set = (newValue: T, wasUser: boolean = true): this => {\n this.value = newValue;\n if (wasUser && !this.dirty) this.dirty = true;\n this.validate();\n return this;\n };\n}\n\nFormValidator.prototype.toString = function getValidatorValue() {\n return `${this.value}`;\n};\n","export function isNumber(string: string): boolean {\n return /^[0-9]+$/.test(string);\n}\n\nexport function isDate(string: string): boolean {\n return /^[0-9]{2}.[0-9]{2}.[0-9]{4}$/.test(string);\n}\n\nexport function isISODate(string: string): boolean {\n return /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}Z$/.test(string);\n}\n\nexport function isEmail(string: string): boolean {\n return /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-ZöäüÜÖÄß\\-0-9]+\\.)+[a-zA-Z]{2,}))$/.test(string);\n}\n\nexport function isBic(string: string): boolean {\n return /^[A-Z]{6}[A-Z\\d]{2}([A-Z\\d]{3})?$/.test(string);\n}\n\nexport function isURL(string: string): boolean {\n return /[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,63}(\\/[-a-zA-Z0-9@:%_+.~#?&//=]*)?$/.test(string);\n}\n\nexport function hasEightPasswordChars(string: string): boolean {\n return /^[\\w!@#$%^&*?±§~`'\"/\\\\[\\]{}\\-,.();:><+=|öäüÖÄÜß €μ]{8,}$/.test(string);\n}\n\nexport function hasOnePasswordLetter(string: string): boolean {\n return /^(?=.*[a-zöäüA-ZÖÄÜß])/.test(string);\n}\n\nexport function hasOnePasswordDigit(string: string): boolean {\n return /^(?=.*\\d)/.test(string);\n}\n\nexport function isPassword(string: string): boolean {\n return hasEightPasswordChars(string) && hasOnePasswordLetter(string) && hasOnePasswordDigit(string);\n}\n","import { isEmail, isDate, isISODate, isURL, isBic } from 'services/regexp';\nimport type { ValidatorFunction, ValidationError } from './types';\n\nconst polyglot = {\n t: (key: string, options?: Record<string, unknown>): string => {\n const translations: Record<string, string> = {\n 'formValidators.minLength': `Must be at least ${options?.min} characters long`,\n 'formValidators.maxLength': `Must be at most ${options?.max} characters long`,\n 'formValidators.email': 'Must be a valid email address',\n 'formValidators.required': `${options?.label || 'Value'} is required`,\n 'formValidators.value': 'Value',\n 'formValidators.mustBeNumber': 'Must be a number',\n 'formValidators.oneOf': `Must be one of the following values: ${options?.allowedValues}`,\n 'formValidators.typeOf': `Must have type of ${options?.allowedTypes}`,\n 'formValidators.multiEmail': 'Must be a comma or semicolon separated list of valid email addresses',\n 'formValidators.date': 'Must be a valid date',\n 'garages.errors.website': 'Must be a valid URL',\n 'garages.errors.bic': 'Must be a valid BIC',\n 'formValidators.minLetters': `Must contain at least ${options?.smart_count} letters`,\n 'formValidators.minDigits': `Must contain at least ${options?.smart_count} digits`,\n };\n return translations[key] || key;\n },\n};\n\nexport default class Validators {\n static minLength = (min: number, errorMsg?: string): ValidatorFunction => (value) => {\n if (!value || (value as string).length < min) return { id: 'minLength', message: errorMsg || polyglot.t('formValidators.minLength', { min }) };\n return null;\n };\n\n static maxLength = (max: number, errorMsg?: string): ValidatorFunction => (value) => {\n if (value && (value as string).length > max) return { id: 'maxLength', message: errorMsg || polyglot.t('formValidators.maxLength', { max }) };\n return null;\n };\n\n static email = (errorMsg?: string): ValidatorFunction => (value) => {\n if (value && !isEmail(value as string)) return { id: 'email', message: errorMsg || polyglot.t('formValidators.email') };\n return null;\n };\n\n static required = (errorMsg?: string): ValidatorFunction & { validatorId: string } => {\n function required(value: unknown, label?: string): ValidationError | null {\n if (!value && value !== 0) return { id: 'required', message: errorMsg || polyglot.t('formValidators.required', { label: label || polyglot.t('formValidators.value') }) };\n return null;\n }\n required.validatorId = 'required';\n return required;\n };\n\n static mustBeNumber = (errorMsg?: string): ValidatorFunction => (value) => {\n if (value && Number.isNaN(+(value as string))) return { id: 'mustBeNumber', message: errorMsg || polyglot.t('formValidators.mustBeNumber') };\n return null;\n };\n\n static oneOf = (allowedValues: unknown[], errorMsg?: string): ValidatorFunction => (value) => {\n if (value && !allowedValues.includes(value)) return { id: 'oneOf', message: errorMsg || polyglot.t('formValidators.oneOf', { allowedValues }) };\n return null;\n };\n\n static typeOf = (allowedTypes: string | string[], errorMsg?: string): ValidatorFunction => (value) => {\n if (Array.isArray(allowedTypes)) {\n for (let i = 0; i < allowedTypes.length; i += 1) {\n if (typeof value === allowedTypes[i]) return null;\n }\n } else if (typeof value === allowedTypes) {\n return null;\n }\n return { id: 'typeOf', message: errorMsg || `Must have type of ${allowedTypes}` };\n };\n\n static multiEmail = (errorMessage?: string): ValidatorFunction => (value) => {\n if (value) {\n const emailParts = (value as string).replace(/ /g, '').replace(/,/g, ';').split(';');\n for (let i = 0; i < emailParts.length; i += 1) {\n if (!isEmail(emailParts[i])) {\n return { id: 'multiEmail', message: errorMessage || polyglot.t('formValidators.multiEmail') };\n }\n }\n }\n return null;\n };\n\n static date = (errorMessage?: string): ValidatorFunction => (value) => {\n if (value && (!isDate(value as string) && !isISODate(value as string))) return { id: 'date', message: errorMessage || polyglot.t('formValidators.date') };\n return null;\n };\n\n static dateObject = (errorMessage?: string): ValidatorFunction => (value) => {\n if (value && !(value as { isValid: boolean }).isValid) return { id: 'date', message: errorMessage || polyglot.t('formValidators.date') };\n return null;\n };\n\n static website = (errorMsg?: string): ValidatorFunction => (value) => {\n if (value && !isURL(value as string)) return { id: 'website', message: errorMsg || polyglot.t('garages.errors.website') };\n return null;\n };\n\n static bic = (errorMsg?: string): ValidatorFunction => (value) => {\n if (value && !isBic(value as string)) return { id: 'bic', message: errorMsg || polyglot.t('garages.errors.bic') };\n return null;\n };\n\n static minLetters = (min: number, errorMsg?: string): ValidatorFunction => (value) => {\n if (value && (value as string).replace(/[^a-zöäüA-ZÖÄÜß]/g, '').length < min) return { id: 'minLetters', message: errorMsg || polyglot.t('formValidators.minLetters', { smart_count: min }) };\n return null;\n };\n\n static minDigits = (min: number, errorMsg?: string): ValidatorFunction => (value) => {\n if (value && (value as string).replace(/[\\D]/g, '').length < min) return { id: 'minDigits', message: errorMsg || polyglot.t('formValidators.minDigits', { smart_count: min }) };\n return null;\n };\n\n static password = (errorMsg?: string): ValidatorFunction => (value) => {\n const result = Validators.minLength(8)(value)\n || Validators.minLetters(1)(value)\n || Validators.minDigits(1)(value);\n if (result) return errorMsg ? { id: 'password', message: errorMsg } : result;\n return null;\n };\n}\n","/* eslint-disable react/no-unused-state */\nimport React, { PureComponent } from 'react';\nimport FormValidator from 'services/formValidation/formValidator';\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 { useEffect, useReducer } from 'react';\nimport type FormValidator from './formValidator';\n\n/**\n * Subscribes a function component to a FormValidator instance.\n * Triggers a re-render whenever value, errors, touched, or dirty changes.\n *\n * @param formValidator - The FormValidator instance to subscribe to (or null)\n * @returns The same formValidator for convenience\n */\nexport function useFormValidator<T extends FormValidator | null>(formValidator: T): T {\n const [, rerender] = useReducer((n: number) => n + 1, 0);\n\n useEffect(() => {\n if (!formValidator) return;\n formValidator.registerOnUpdateListener(rerender);\n return () => formValidator.removeOnUpdateListener(rerender);\n }, [formValidator]);\n\n return formValidator;\n}\n","import { useEffect, useReducer, useRef } from 'react';\nimport FormValidatorGroup from './FormValidatorGroupWithForm';\nimport type { FormGroup, FormValidatorGroupOptions, InferGroupValues } from './formValidatorGroup';\n\n/**\n * Creates and subscribes a function component to a FormValidatorGroup.\n * Triggers a re-render whenever any field, submit state, or validation state changes.\n *\n * The group is created once on mount from the provided field map.\n * onSubmit / onValidate are kept fresh via refs — they always reflect the latest\n * closure without needing to be listed in effect dependencies.\n *\n * onSubmitError defaults to showing the message as an error toast (provided by FormValidatorGroupWithForm);\n * pass options.onSubmitError to override.\n *\n * @param groupDef - Map of field name → FormValidator instance\n * @param options - initialValues, onSubmit, onValidate, errorParser, onSubmitError\n *\n * @example\n * const form = useFormValidatorGroup(\n * { name: new FormValidator('', [Validators.required('Required')]) },\n * {\n * initialValues: { name: 'Jane' },\n * onSubmit: async (values) => save(values),\n * },\n * );\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): FormValidatorGroup<TGroup, TInitial> {\n const [, rerender] = useReducer((n: number) => n + 1, 0);\n\n const groupRef = useRef<FormValidatorGroup<TGroup, TInitial> | null>(null);\n if (!groupRef.current) {\n groupRef.current = new FormValidatorGroup(groupDef, null, {\n initialValues,\n errorParser,\n onSubmitError,\n });\n }\n const group = groupRef.current;\n\n const onSubmitRef = useRef(onSubmit);\n const onValidateRef = useRef(onValidate);\n onSubmitRef.current = onSubmit;\n onValidateRef.current = onValidate;\n\n useEffect(() => {\n if (onSubmit !== undefined) {\n group.onSubmitCallback = (...args) => onSubmitRef.current?.(...args);\n }\n if (onValidate !== undefined) {\n group.onValidateCallback = (...args) => onValidateRef.current?.(...args);\n }\n group.registerOnUpdateListener(rerender);\n return () => group.removeOnUpdateListener(rerender);\n }, []);\n\n return group;\n}\n"],"mappings":"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"}