@pk-design/react-tailwind 1.12.0 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"SelectBox.js","sources":["../../../../../src/components/SelectBox/SelectBox.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport {\n Combobox,\n ComboboxButton,\n ComboboxInput,\n ComboboxOption,\n ComboboxOptions,\n} from '@headlessui/react'\n\nimport { Label } from '../Label'\nimport { Badge } from '../Badge'\nimport { Loader } from '../Loader'\nimport { TextContent } from '../TextContent'\nimport { Button } from '../Button'\nimport { MobilePicker } from '../MobilePicker'\n\nimport { isArray } from '../../utils/is-array'\nimport { buildClassName } from '../../utils/build-classname'\nimport { isEmpty } from '../../utils/is-empty'\nimport { useDebounce } from '../../hooks/use-debounce'\n\nimport CheckIcon from '../Icons/Check.svg'\nimport ChevronDownIcon from '../Icons/ChevronDown.svg'\nimport XIcon from '../Icons/X.svg'\nimport CirclePlusIcon from '../Icons/CirclePlus.svg'\nimport type { BaseOption, SelectBoxProps, SelectBoxSize } from './SelectBox.types'\nimport { buildInputClass } from '../Input'\nimport { BodyText } from '../BodyText'\n\nconst NOOP = () => {}\nconst EMPTY_ARRAY: any[] = []\n\nconst sizeClasses: Record<\n SelectBoxSize,\n { input: string; group: string; icon: string; badgeSize: 'sm' | 'md' }\n> = {\n sm: {\n input: 'px-2.5 py-1.5 text-xs leading-5 min-h-[32px]',\n group: 'w-8 text-xs',\n icon: 'size-3.5',\n badgeSize: 'sm',\n },\n md: {\n input: 'px-3.5 py-2 text-sm leading-6 min-h-[38px]',\n group: 'w-10 text-sm',\n icon: 'size-4',\n badgeSize: 'md',\n },\n lg: {\n input: 'px-4 py-2.5 text-base leading-7 min-h-[46px]',\n group: 'w-12 text-base',\n icon: 'size-5',\n badgeSize: 'md',\n },\n}\n\nexport const SelectBox = forwardRef(\n <T extends BaseOption | string = BaseOption>(\n props: SelectBoxProps<T>,\n forwardedRef: React.Ref<HTMLInputElement | HTMLDivElement | null>,\n ) => {\n const {\n labelKey = 'label',\n valueKey = 'value',\n name,\n id = name,\n options = EMPTY_ARRAY,\n groups,\n selected: selectedProp,\n defaultSelected,\n size = 'md',\n label = null,\n labelWrapperClass = '',\n labelClass = '',\n labelHint = null,\n disabled = false,\n containerClass = '',\n onChange: onChangeProp = NOOP,\n placeholder,\n dropdownContainerClass = 'z-20',\n dropdownMinWidth,\n multiple = false,\n maxSelection,\n showSelectAll = false,\n immediate = true,\n showErrorMessage = true,\n error = null,\n helperText,\n leftGroup,\n renderOption,\n async = false,\n searchable = true,\n required = false,\n allowAdd = false,\n addNewText = 'Create',\n onAdd = NOOP,\n allowClear = false,\n allowFreeText = false,\n modalDropdown = false,\n noOptionsText = 'No options available',\n } = props\n\n // Uncontrolled when `selected` is not passed: keep the selection internally.\n const isControlled = selectedProp !== undefined\n const [internalSelected, setInternalSelected] = useState<T | T[] | null>(\n defaultSelected ?? null,\n )\n const selected = isControlled ? selectedProp : internalSelected\n\n const onChange = useCallback(\n (value: T | T[] | null) => {\n if (!isControlled) setInternalSelected(value)\n onChangeProp(value)\n },\n [isControlled, onChangeProp],\n )\n\n if (props.asBottomSheet || props.mobileMode === 'sheet') {\n return <MobilePicker {...(props as any)} selected={selected} onChange={onChange} />\n }\n\n const hasError = Boolean(error)\n const [query, setQuery] = useState('')\n const debouncedQuery = useDebounce(query, 500)\n const [optionsLoading, setOptionsLoading] = useState(false)\n\n // Normalize options from options prop or groups prop\n const allOptions = useMemo(() => {\n if (groups?.length) {\n return groups.flatMap((g) => g.options)\n }\n return options\n }, [groups, options])\n\n const shouldShowTypeToSearch = async && !query && !optionsLoading && allOptions.length === 0\n const currentSize = sizeClasses[size] || sizeClasses.md\n\n const baseInputClass = useMemo(\n () => buildInputClass('', { disabled, hasError, size }),\n [disabled, hasError, size],\n )\n\n const chevronIconClass = useMemo(\n () =>\n buildClassName(\n currentSize.icon,\n 'stroke-gray-500 group-data-[hover]:stroke-gray-800',\n 'dark:stroke-gray-300 dark:group-data-[hover]:stroke-gray-100',\n disabled && 'dark:stroke-gray-600 stroke-gray-400',\n ),\n [currentSize.icon, disabled],\n )\n\n const inputRef = useRef<HTMLInputElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n useImperativeHandle(forwardedRef, () => inputRef.current!, [inputRef])\n\n const filteredOptions = useMemo(() => {\n if (query === '' || async) return allOptions\n return allOptions.filter((opt) => {\n const lbl = typeof opt === 'string' ? opt : (opt as BaseOption)[labelKey]\n return lbl?.toLowerCase().includes(query.toLowerCase())\n })\n }, [allOptions, query, async, labelKey])\n\n const filteredGroups = useMemo(() => {\n if (!groups?.length) return null\n if (query === '' || async) return groups\n\n return groups\n .map((g) => ({\n ...g,\n options: g.options.filter((opt) => {\n const lbl = typeof opt === 'string' ? opt : (opt as BaseOption)[labelKey]\n return lbl?.toLowerCase().includes(query.toLowerCase())\n }),\n }))\n .filter((g) => g.options.length > 0)\n }, [groups, query, async, labelKey])\n\n const getDisplayValue = useCallback(\n (opt: T) => {\n return typeof opt === 'string' ? opt : opt[labelKey]\n },\n [labelKey],\n )\n\n const getValue = useCallback(\n (opt: T) => {\n return typeof opt === 'string' ? opt : opt[valueKey]\n },\n [valueKey],\n )\n\n const createFreeTextOption = useCallback(\n (text: string): T => {\n const sample = allOptions[0] || (Array.isArray(selected) ? selected[0] : selected)\n if (\n typeof sample === 'string' ||\n (!sample && typeof labelKey === 'string' && labelKey === 'label')\n ) {\n return text as unknown as T\n }\n return {\n [labelKey]: text,\n [valueKey]: text,\n } as unknown as T\n },\n [allOptions, selected, labelKey, valueKey],\n )\n\n const handleFreeTextCommit = useCallback(\n (queryText: string) => {\n const trimmed = queryText.trim()\n if (!trimmed) return\n\n const existing = allOptions.find((opt) => {\n const display = getDisplayValue(opt)\n return display?.toLowerCase() === trimmed.toLowerCase()\n })\n\n const valueToCommit = existing || createFreeTextOption(trimmed)\n\n if (multiple) {\n const current = isArray(selected) ? selected : []\n const alreadySelected = current.some(\n (item) => getDisplayValue(item)?.toLowerCase() === trimmed.toLowerCase(),\n )\n if (!alreadySelected) {\n if (maxSelection && current.length >= maxSelection) return\n onChange([...current, valueToCommit] as unknown as T[])\n }\n setQuery('')\n } else {\n onChange(valueToCommit)\n setQuery('')\n }\n },\n [\n allOptions,\n getDisplayValue,\n createFreeTextOption,\n multiple,\n selected,\n maxSelection,\n onChange,\n ],\n )\n\n const removeSelection = useCallback(\n (idx: number) => {\n if (!isArray(selected)) return\n const next = [...selected]\n next.splice(idx, 1)\n onChange(next)\n inputRef.current?.focus()\n },\n [selected, onChange],\n )\n\n const handleOnChangeInternal = useCallback(\n (value: T | T[] | null) => {\n if (value === null) {\n onChange(multiple ? ([] as T[]) : null)\n setQuery('')\n return\n }\n\n if (multiple && Array.isArray(value) && maxSelection && value.length > maxSelection) {\n return\n }\n\n onChange(value as T | T[])\n setQuery('')\n },\n [onChange, multiple, maxSelection],\n )\n\n const comboboxOnChangeWrapper = useCallback(\n (raw: unknown) => {\n if (raw === null || raw === undefined) {\n handleOnChangeInternal(null)\n return\n }\n\n if (Array.isArray(raw)) {\n const allNulls = raw.length > 0 && raw.every((v) => v === null)\n if (allNulls) {\n handleOnChangeInternal([] as unknown as T[])\n return\n }\n handleOnChangeInternal(raw as unknown as T[])\n return\n }\n\n handleOnChangeInternal(raw as unknown as T)\n },\n [handleOnChangeInternal],\n )\n\n const handleAddAndSelect = useCallback(\n async (valueToAdd: string) => {\n try {\n const result = await onAdd(valueToAdd)\n if (result) {\n handleOnChangeInternal(result as unknown as T)\n } else {\n handleOnChangeInternal(valueToAdd as unknown as T)\n }\n } catch (err) {\n console.error('onAdd handler error', err)\n }\n },\n [onAdd, handleOnChangeInternal],\n )\n\n const onSearchRef = useRef(props.onSearch)\n onSearchRef.current = props.onSearch\n\n const handleSearch = useCallback(async (searchString: string) => {\n try {\n setOptionsLoading(true)\n await onSearchRef.current?.(searchString)\n } catch (err) {\n console.error('Error loading options:', err)\n } finally {\n setOptionsLoading(false)\n }\n }, [])\n\n useEffect(() => {\n if (async && debouncedQuery) handleSearch(debouncedQuery)\n }, [debouncedQuery, async, handleSearch])\n\n const normalizedSelected = useMemo(() => {\n if (multiple) {\n if (Array.isArray(selected)) return selected\n if (selected !== null && selected !== undefined) return [selected as T]\n return [] as T[]\n } else {\n if (Array.isArray(selected)) return selected.length > 0 ? selected[0] : null\n return selected ?? null\n }\n }, [multiple, selected])\n\n const selectedValueSet = useMemo(() => {\n if (!normalizedSelected) return new Set<any>()\n if (Array.isArray(normalizedSelected)) {\n return new Set(normalizedSelected.map((s) => getValue(s)))\n }\n return new Set([getValue(normalizedSelected as T)])\n }, [normalizedSelected, getValue])\n\n const isAllSelected = useMemo(() => {\n if (!multiple || !Array.isArray(normalizedSelected) || !allOptions.length) return false\n return allOptions.length === normalizedSelected.length\n }, [multiple, normalizedSelected, allOptions])\n\n const handleToggleSelectAll = useCallback(() => {\n if (isAllSelected) {\n onChange([] as unknown as T[])\n } else {\n onChange(allOptions as unknown as T[])\n }\n }, [isAllSelected, onChange, allOptions])\n\n const hasLeftGroup = leftGroup != null && leftGroup !== undefined\n\n // Reserve room for the chevron (and the clear button when shown) so long values\n // don't run underneath them.\n const showClearButton = allowClear && !multiple && !isEmpty(normalizedSelected)\n const rightPaddingClass = showClearButton\n ? 'pe-16'\n : size === 'lg'\n ? 'pe-11'\n : size === 'sm'\n ? 'pe-9'\n : 'pe-10'\n\n const hasFreeTextOption = Boolean(\n allowFreeText &&\n query.trim() &&\n !allOptions.some(\n (opt) => getDisplayValue(opt)?.toLowerCase() === query.trim().toLowerCase(),\n ),\n )\n\n const hasAddOption = Boolean(!allowFreeText && allowAdd && query.trim())\n const hasGroupOptions = Boolean(filteredGroups && filteredGroups.length > 0)\n const hasFlatOptions = filteredOptions.length > 0\n\n const hasAnyOptionsToDisplay =\n hasFlatOptions || hasGroupOptions || hasFreeTextOption || hasAddOption\n\n const renderOptionItem = (option: T) => {\n const optVal = getValue(option)\n const isOptSelected = selectedValueSet.has(optVal)\n\n return (\n <ComboboxOption\n key={optVal}\n disabled={(option as BaseOption).disabled}\n value={option}\n className=\"group rounded-lg py-1.5 px-3 select-none data-[focus]:bg-gray-100 dark:data-[focus]:bg-white/10 data-disabled:opacity-50 cursor-pointer data-disabled:pointer-events-none\"\n >\n {renderOption ? (\n renderOption(option, Boolean(isOptSelected))\n ) : (\n <div className=\"flex items-center justify-between gap-2 text-gray-900 dark:text-white group-data-[selected]:text-blue-600\">\n <span className=\"text-sm/6\">{getDisplayValue(option)}</span>\n <CheckIcon className=\"invisible size-5 dark:stroke-gray-300 group-data-[selected]:visible\" />\n </div>\n )}\n </ComboboxOption>\n )\n }\n\n return (\n <div\n className={buildClassName('group space-y-2', hasError && 'has-error', containerClass)}\n ref={containerRef}\n >\n {label && (\n <div className={buildClassName('flex items-center justify-between', labelWrapperClass)}>\n <Label className={labelClass} htmlFor={id} aria-required={required}>\n {label}\n </Label>\n {labelHint && <TextContent xsmall>{labelHint}</TextContent>}\n </div>\n )}\n\n <Combobox\n multiple={multiple}\n immediate={immediate}\n name={name}\n value={normalizedSelected as any}\n onChange={comboboxOnChangeWrapper as any}\n onClose={() => setQuery('')}\n disabled={disabled}\n by={(a: any, b: any) => (a && b ? getValue(a) === getValue(b) : a === b)}\n >\n {multiple ? (\n <div\n className={buildClassName(\n baseInputClass,\n 'flex flex-wrap gap-2 peer relative',\n rightPaddingClass,\n hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : '',\n )}\n ref={forwardedRef as any}\n >\n {hasLeftGroup && (\n <span\n className={buildClassName(\n 'absolute left-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500',\n currentSize.group,\n )}\n >\n {leftGroup}\n </span>\n )}\n\n {isArray(normalizedSelected) &&\n normalizedSelected?.length > 0 &&\n normalizedSelected.map((option, idx) => (\n <Badge\n key={`${getValue(option)}-${idx}`}\n theme=\"secondary\"\n size={currentSize.badgeSize}\n removable={!disabled}\n onRemove={() => removeSelection(idx)}\n >\n {getDisplayValue(option)}\n </Badge>\n ))}\n\n <ComboboxInput\n className=\"outline-none flex-1 dark:placeholder-gray-400 placeholder-gray-400 bg-transparent\"\n aria-label={name}\n value={query}\n autoComplete=\"off\"\n placeholder={normalizedSelected?.length ? '' : placeholder}\n onChange={(e) => {\n const val = e.target.value\n if (allowFreeText && multiple && val.includes(',')) {\n const parts = val.split(',')\n parts.forEach((p) => {\n if (p.trim()) handleFreeTextCommit(p.trim())\n })\n setQuery('')\n } else {\n setQuery(val)\n }\n }}\n id={id}\n ref={inputRef}\n onKeyDown={(e) => {\n if (allowFreeText && (e.key === 'Enter' || e.key === ',') && query.trim()) {\n e.preventDefault()\n handleFreeTextCommit(query.replace(/,/g, ''))\n } else if (multiple && e.key === 'Backspace' && !query) {\n if (Array.isArray(normalizedSelected) && normalizedSelected.length > 0) {\n removeSelection(normalizedSelected.length - 1)\n }\n }\n }}\n onBlur={() => {\n if (allowFreeText && query.trim()) {\n handleFreeTextCommit(query.replace(/,/g, ''))\n }\n }}\n data-testid=\"combobox-input\"\n />\n\n <ComboboxButton\n className=\"group absolute inset-y-0 right-0 px-2.5 flex items-center justify-center\"\n data-testid=\"combobox-button\"\n >\n <ChevronDownIcon className={chevronIconClass} />\n </ComboboxButton>\n </div>\n ) : (\n <div className=\"relative\" ref={forwardedRef as any}>\n {hasLeftGroup && (\n <span\n className={buildClassName(\n 'absolute left-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500 z-10',\n currentSize.group,\n )}\n >\n {leftGroup}\n </span>\n )}\n\n <ComboboxInput\n aria-label={name}\n displayValue={(option: any) => (option ? getDisplayValue(option) : null)}\n autoComplete=\"off\"\n placeholder={placeholder}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={(e) => {\n if (allowFreeText && e.key === 'Enter' && query.trim()) {\n e.preventDefault()\n handleFreeTextCommit(query)\n }\n }}\n onBlur={() => {\n if (allowFreeText && query.trim()) {\n handleFreeTextCommit(query)\n }\n }}\n onFocus={() => {\n setQuery('')\n }}\n className={buildClassName(\n baseInputClass,\n 'text-ellipsis',\n rightPaddingClass,\n hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : '',\n )}\n disabled={disabled}\n id={id}\n readOnly={!searchable}\n ref={inputRef}\n data-testid=\"combobox-input\"\n />\n\n {showClearButton && (\n <Button\n size=\"xs\"\n iconOnly\n aria-label=\"Clear selection\"\n theme=\"secondary\"\n variant=\"plain\"\n className=\"group absolute inset-y-0 right-8 h-6 top-2\"\n onClick={() => handleOnChangeInternal(multiple ? ([] as T[]) : null)}\n disabled={disabled}\n data-testid=\"combobox-clear-button\"\n >\n <XIcon className=\"size-4 stroke-gray-500 dark:stroke-gray-300\" />\n </Button>\n )}\n\n <ComboboxButton\n className=\"group absolute inset-y-0 right-0 px-2.5 flex items-center justify-center\"\n data-testid=\"combobox-button\"\n >\n <ChevronDownIcon className={chevronIconClass} />\n </ComboboxButton>\n </div>\n )}\n\n <ComboboxOptions\n anchor={{ to: 'bottom start', gap: 5, padding: 8 }}\n as=\"div\"\n modal={modalDropdown}\n // Matches the input width by default; min-width lets the panel grow wider than a narrow input.\n style={dropdownMinWidth != null ? { minWidth: dropdownMinWidth } : undefined}\n className={buildClassName(\n 'w-[var(--input-width)] rounded-lg border border-[var(--ui-border)] bg-white dark:bg-gray-800 p-1 shadow-lg max-h-80 overflow-y-auto z-50 [--anchor-gap:var(--spacing-1)]',\n '[--anchor-max-height:20rem]',\n 'origin-top border transition duration-200 ease-[cubic-bezier(0.4, 0.0, 0.2, 1)] data-[closed]:translate-y-[-15%] data-[closed]:opacity-0',\n dropdownContainerClass,\n )}\n transition\n data-testid=\"combobox-options\"\n >\n {/* Multi-Select \"Select All\" Action Bar */}\n {multiple && showSelectAll && allOptions.length > 0 && (\n <div className=\"pb-1 mb-1 border-b border-[var(--ui-border-muted)] px-3 pt-1 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={handleToggleSelectAll}\n className=\"text-xs font-semibold text-blue-600 dark:text-blue-400 hover:underline cursor-pointer\"\n >\n {isAllSelected ? 'Deselect All' : 'Select All'}\n </button>\n <span className=\"text-[11px] font-medium text-gray-400\">\n {Array.isArray(normalizedSelected) ? normalizedSelected.length : 0} of{' '}\n {allOptions.length}\n </span>\n </div>\n )}\n\n {optionsLoading ? (\n <BodyText\n data-testid=\"options-loading\"\n className=\"flex items-center justify-center py-2 px-3 select-none\"\n >\n <Loader size=\"sm\" />\n </BodyText>\n ) : shouldShowTypeToSearch ? (\n <BodyText className=\"flex items-center justify-between py-2 px-3 select-none\">\n Type to search...\n </BodyText>\n ) : (\n <div>\n {/* Render Free-Text Option if query does not match an option exactly */}\n {allowFreeText &&\n query.trim() &&\n !allOptions.some(\n (opt) => getDisplayValue(opt)?.toLowerCase() === query.trim().toLowerCase(),\n ) && (\n <ComboboxOption\n key={`freetext-${query.trim()}`}\n value={createFreeTextOption(query.trim()) as any}\n className=\"group flex items-center gap-2 rounded-lg py-1.5 px-3 select-none text-sm data-[focus]:bg-blue-50 dark:data-[focus]:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-medium cursor-pointer w-full\"\n data-testid=\"freetext-option\"\n >\n <span>Use \"{query.trim()}\"</span>\n </ComboboxOption>\n )}\n\n {/* Render Grouped Options */}\n {filteredGroups\n ? filteredGroups.map((grp, gIdx) => (\n <div key={gIdx}>\n <div className=\"text-[11px] font-bold uppercase tracking-wider text-gray-400 dark:text-gray-500 px-3 py-1 select-none\">\n {grp.group}\n </div>\n {grp.options.map(renderOptionItem)}\n </div>\n ))\n : /* Render Standard Flat Options */\n filteredOptions.map(renderOptionItem)}\n\n {!hasAnyOptionsToDisplay && Boolean(noOptionsText) && (\n <div\n data-testid=\"no-result-found\"\n className=\"flex items-center gap-2 py-1.5 px-3 select-none\"\n >\n <TextContent muted small>\n {noOptionsText}\n </TextContent>\n {Boolean(query.trim()) && (\n <TextContent strong small>\n \"{query.trim()}\"\n </TextContent>\n )}\n </div>\n )}\n\n {/* Creatable option (allowAdd) - suppressed when allowFreeText is true */}\n {!allowFreeText && allowAdd && Boolean(query.trim()) && (\n <ComboboxOption\n key={`add-${query.trim()}`}\n value={query}\n className=\"group rounded-lg py-1.5 px-3 cursor-pointer text-gray-700 dark:text-gray-300 data-[focus]:bg-gray-100 dark:data-[focus]:bg-gray-700\"\n onClick={() => void handleAddAndSelect(query)}\n >\n <div className=\"flex items-center gap-2\">\n <CirclePlusIcon className=\"size-4.5\" />\n <TextContent>\n {addNewText} \"{query}\"\n </TextContent>\n </div>\n </ComboboxOption>\n )}\n </div>\n )}\n </ComboboxOptions>\n </Combobox>\n\n {showErrorMessage && error && (\n <div className=\"mt-1\">\n <TextContent error small>\n {error}\n </TextContent>\n </div>\n )}\n\n {!error && helperText && (\n <div className=\"mt-1\">\n <TextContent muted small>\n {helperText}\n </TextContent>\n </div>\n )}\n </div>\n )\n },\n)\n\nSelectBox.displayName = 'SelectBox'\n"],"names":["forwardRef","useState","useCallback","_jsx","MobilePicker","useDebounce","useMemo","buildInputClass","buildClassName","useRef","useImperativeHandle","isArray","useEffect","isEmpty","ComboboxOption","_jsxs","CheckIcon","Label","TextContent","Combobox","Badge","ComboboxInput","ComboboxButton","ChevronDownIcon","Button","XIcon","ComboboxOptions","BodyText","Loader","CirclePlusIcon"],"mappings":"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"}
1
+ {"version":3,"file":"SelectBox.js","sources":["../../../../../src/components/SelectBox/SelectBox.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport {\n Combobox,\n ComboboxButton,\n ComboboxInput,\n ComboboxOption,\n ComboboxOptions,\n} from '@headlessui/react'\n\nimport { Label } from '../Label'\nimport { Badge } from '../Badge'\nimport { Loader } from '../Loader'\nimport { TextContent } from '../TextContent'\nimport { Button } from '../Button'\nimport { MobilePicker } from '../MobilePicker'\n\nimport { isArray } from '../../utils/is-array'\nimport { buildClassName } from '../../utils/build-classname'\nimport { isEmpty } from '../../utils/is-empty'\nimport { useDebounce } from '../../hooks/use-debounce'\n\nimport CheckIcon from '../Icons/Check.svg'\nimport ChevronDownIcon from '../Icons/ChevronDown.svg'\nimport XIcon from '../Icons/X.svg'\nimport CirclePlusIcon from '../Icons/CirclePlus.svg'\nimport type { BaseOption, SelectBoxProps, SelectBoxSize } from './SelectBox.types'\nimport { buildInputClass } from '../Input'\nimport { BodyText } from '../BodyText'\n\nconst NOOP = () => {}\nconst EMPTY_ARRAY: any[] = []\n\nconst sizeClasses: Record<\n SelectBoxSize,\n { input: string; group: string; icon: string; badgeSize: 'sm' | 'md' }\n> = {\n sm: {\n input: 'px-2.5 py-1.5 text-xs leading-5 min-h-[32px]',\n group: 'w-8 text-xs',\n icon: 'size-3.5',\n badgeSize: 'sm',\n },\n md: {\n input: 'px-3.5 py-2 text-sm leading-6 min-h-[38px]',\n group: 'w-10 text-sm',\n icon: 'size-4',\n badgeSize: 'md',\n },\n lg: {\n input: 'px-4 py-2.5 text-base leading-7 min-h-[46px]',\n group: 'w-12 text-base',\n icon: 'size-5',\n badgeSize: 'md',\n },\n}\n\nexport const SelectBox = forwardRef(\n <T extends BaseOption | string = BaseOption>(\n props: SelectBoxProps<T>,\n forwardedRef: React.Ref<HTMLInputElement | HTMLDivElement | null>,\n ) => {\n const {\n labelKey = 'label',\n valueKey = 'value',\n name,\n id = name,\n options = EMPTY_ARRAY,\n groups,\n selected: selectedProp,\n defaultSelected,\n size = 'md',\n label = null,\n labelWrapperClass = '',\n labelClass = '',\n labelHint = null,\n disabled = false,\n containerClass = '',\n onChange: onChangeProp = NOOP,\n placeholder,\n dropdownContainerClass = 'z-20',\n dropdownMinWidth,\n multiple = false,\n maxSelection,\n showSelectAll = false,\n immediate = true,\n showErrorMessage = true,\n error = null,\n helperText,\n leftGroup,\n renderOption,\n async = false,\n searchable = true,\n required = false,\n allowAdd = false,\n addNewText = 'Create',\n onAdd = NOOP,\n allowClear = false,\n allowFreeText = false,\n modalDropdown = false,\n noOptionsText = 'No options available',\n } = props\n\n // Uncontrolled when `selected` is not passed: keep the selection internally.\n const isControlled = selectedProp !== undefined\n const [internalSelected, setInternalSelected] = useState<T | T[] | null>(\n defaultSelected ?? null,\n )\n const selected = isControlled ? selectedProp : internalSelected\n\n const onChange = useCallback(\n (value: T | T[] | null) => {\n if (!isControlled) setInternalSelected(value)\n onChangeProp(value)\n },\n [isControlled, onChangeProp],\n )\n\n if (props.asBottomSheet || props.mobileMode === 'sheet') {\n return <MobilePicker {...(props as any)} selected={selected} onChange={onChange} />\n }\n\n const hasError = Boolean(error)\n const [query, setQuery] = useState('')\n const debouncedQuery = useDebounce(query, 500)\n const [optionsLoading, setOptionsLoading] = useState(false)\n\n // Normalize options from options prop or groups prop\n const allOptions = useMemo(() => {\n if (groups?.length) {\n return groups.flatMap((g) => g.options)\n }\n return options\n }, [groups, options])\n\n const shouldShowTypeToSearch = async && !query && !optionsLoading && allOptions.length === 0\n const currentSize = sizeClasses[size] || sizeClasses.md\n\n const baseInputClass = useMemo(\n () => buildInputClass('', { disabled, hasError, size }),\n [disabled, hasError, size],\n )\n\n const chevronIconClass = useMemo(\n () =>\n buildClassName(\n currentSize.icon,\n 'stroke-gray-500 group-data-[hover]:stroke-gray-800',\n 'dark:stroke-gray-300 dark:group-data-[hover]:stroke-gray-100',\n disabled && 'dark:stroke-gray-600 stroke-gray-400',\n ),\n [currentSize.icon, disabled],\n )\n\n const inputRef = useRef<HTMLInputElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n useImperativeHandle(forwardedRef, () => inputRef.current!, [inputRef])\n\n const filteredOptions = useMemo(() => {\n if (query === '' || async) return allOptions\n return allOptions.filter((opt) => {\n const lbl = typeof opt === 'string' ? opt : (opt as BaseOption)[labelKey]\n return lbl?.toLowerCase().includes(query.toLowerCase())\n })\n }, [allOptions, query, async, labelKey])\n\n const filteredGroups = useMemo(() => {\n if (!groups?.length) return null\n if (query === '' || async) return groups\n\n return groups\n .map((g) => ({\n ...g,\n options: g.options.filter((opt) => {\n const lbl = typeof opt === 'string' ? opt : (opt as BaseOption)[labelKey]\n return lbl?.toLowerCase().includes(query.toLowerCase())\n }),\n }))\n .filter((g) => g.options.length > 0)\n }, [groups, query, async, labelKey])\n\n const getDisplayValue = useCallback(\n (opt: T) => {\n return typeof opt === 'string' ? opt : opt[labelKey]\n },\n [labelKey],\n )\n\n const getValue = useCallback(\n (opt: T) => {\n return typeof opt === 'string' ? opt : opt[valueKey]\n },\n [valueKey],\n )\n\n const createFreeTextOption = useCallback(\n (text: string): T => {\n const sample = allOptions[0] || (Array.isArray(selected) ? selected[0] : selected)\n if (\n typeof sample === 'string' ||\n (!sample && typeof labelKey === 'string' && labelKey === 'label')\n ) {\n return text as unknown as T\n }\n return {\n [labelKey]: text,\n [valueKey]: text,\n } as unknown as T\n },\n [allOptions, selected, labelKey, valueKey],\n )\n\n const handleFreeTextCommit = useCallback(\n (queryText: string) => {\n const trimmed = queryText.trim()\n if (!trimmed) return\n\n const existing = allOptions.find((opt) => {\n const display = getDisplayValue(opt)\n return display?.toLowerCase() === trimmed.toLowerCase()\n })\n\n const valueToCommit = existing || createFreeTextOption(trimmed)\n\n if (multiple) {\n const current = isArray(selected) ? selected : []\n const alreadySelected = current.some(\n (item) => getDisplayValue(item)?.toLowerCase() === trimmed.toLowerCase(),\n )\n if (!alreadySelected) {\n if (maxSelection && current.length >= maxSelection) return\n onChange([...current, valueToCommit] as unknown as T[])\n }\n setQuery('')\n } else {\n onChange(valueToCommit)\n setQuery('')\n }\n },\n [\n allOptions,\n getDisplayValue,\n createFreeTextOption,\n multiple,\n selected,\n maxSelection,\n onChange,\n ],\n )\n\n const removeSelection = useCallback(\n (idx: number) => {\n if (!isArray(selected)) return\n const next = [...selected]\n next.splice(idx, 1)\n onChange(next)\n inputRef.current?.focus()\n },\n [selected, onChange],\n )\n\n const handleOnChangeInternal = useCallback(\n (value: T | T[] | null) => {\n if (value === null) {\n onChange(multiple ? ([] as T[]) : null)\n setQuery('')\n return\n }\n\n if (multiple && Array.isArray(value) && maxSelection && value.length > maxSelection) {\n return\n }\n\n onChange(value as T | T[])\n setQuery('')\n },\n [onChange, multiple, maxSelection],\n )\n\n const comboboxOnChangeWrapper = useCallback(\n (raw: unknown) => {\n if (raw === null || raw === undefined) {\n handleOnChangeInternal(null)\n return\n }\n\n if (Array.isArray(raw)) {\n const allNulls = raw.length > 0 && raw.every((v) => v === null)\n if (allNulls) {\n handleOnChangeInternal([] as unknown as T[])\n return\n }\n handleOnChangeInternal(raw as unknown as T[])\n return\n }\n\n handleOnChangeInternal(raw as unknown as T)\n },\n [handleOnChangeInternal],\n )\n\n const handleAddAndSelect = useCallback(\n async (valueToAdd: string) => {\n try {\n const result = await onAdd(valueToAdd)\n if (result) {\n handleOnChangeInternal(result as unknown as T)\n } else {\n handleOnChangeInternal(valueToAdd as unknown as T)\n }\n } catch (err) {\n console.error('onAdd handler error', err)\n }\n },\n [onAdd, handleOnChangeInternal],\n )\n\n const onSearchRef = useRef(props.onSearch)\n onSearchRef.current = props.onSearch\n\n const handleSearch = useCallback(async (searchString: string) => {\n try {\n setOptionsLoading(true)\n await onSearchRef.current?.(searchString)\n } catch (err) {\n console.error('Error loading options:', err)\n } finally {\n setOptionsLoading(false)\n }\n }, [])\n\n useEffect(() => {\n if (async && debouncedQuery) handleSearch(debouncedQuery)\n }, [debouncedQuery, async, handleSearch])\n\n const normalizedSelected = useMemo(() => {\n if (multiple) {\n if (Array.isArray(selected)) return selected\n if (selected !== null && selected !== undefined) return [selected as T]\n return [] as T[]\n } else {\n if (Array.isArray(selected)) return selected.length > 0 ? selected[0] : null\n return selected ?? null\n }\n }, [multiple, selected])\n\n const selectedValueSet = useMemo(() => {\n if (!normalizedSelected) return new Set<any>()\n if (Array.isArray(normalizedSelected)) {\n return new Set(normalizedSelected.map((s) => getValue(s)))\n }\n return new Set([getValue(normalizedSelected as T)])\n }, [normalizedSelected, getValue])\n\n const isAllSelected = useMemo(() => {\n if (!multiple || !Array.isArray(normalizedSelected) || !allOptions.length) return false\n return allOptions.length === normalizedSelected.length\n }, [multiple, normalizedSelected, allOptions])\n\n const handleToggleSelectAll = useCallback(() => {\n if (isAllSelected) {\n onChange([] as unknown as T[])\n } else {\n onChange(allOptions as unknown as T[])\n }\n }, [isAllSelected, onChange, allOptions])\n\n const hasLeftGroup = leftGroup != null && leftGroup !== undefined\n\n // Reserve room for the chevron (and the clear button when shown) so long values\n // don't run underneath them.\n const showClearButton = allowClear && !multiple && !isEmpty(normalizedSelected)\n const rightPaddingClass = showClearButton\n ? 'pe-16'\n : size === 'lg'\n ? 'pe-11'\n : size === 'sm'\n ? 'pe-9'\n : 'pe-10'\n\n const hasFreeTextOption = Boolean(\n allowFreeText &&\n query.trim() &&\n !allOptions.some(\n (opt) => getDisplayValue(opt)?.toLowerCase() === query.trim().toLowerCase(),\n ),\n )\n\n const hasAddOption = Boolean(!allowFreeText && allowAdd && query.trim())\n const hasGroupOptions = Boolean(filteredGroups && filteredGroups.length > 0)\n const hasFlatOptions = filteredOptions.length > 0\n\n const hasAnyOptionsToDisplay =\n hasFlatOptions || hasGroupOptions || hasFreeTextOption || hasAddOption\n\n const renderOptionItem = (option: T) => {\n const optVal = getValue(option)\n const isOptSelected = selectedValueSet.has(optVal)\n\n return (\n <ComboboxOption\n key={optVal}\n disabled={(option as BaseOption).disabled}\n value={option}\n className=\"group rounded-lg py-1.5 px-3 select-none data-[focus]:bg-gray-100 dark:data-[focus]:bg-white/10 data-disabled:opacity-50 cursor-pointer data-disabled:pointer-events-none\"\n >\n {renderOption ? (\n renderOption(option, Boolean(isOptSelected))\n ) : (\n <div className=\"flex items-center justify-between gap-2 text-gray-900 dark:text-white group-data-[selected]:text-blue-600\">\n <span className=\"text-sm/6\">{getDisplayValue(option)}</span>\n <CheckIcon className=\"invisible size-5 dark:stroke-gray-300 group-data-[selected]:visible\" />\n </div>\n )}\n </ComboboxOption>\n )\n }\n\n return (\n <div\n className={buildClassName('group', hasError && 'has-error', containerClass)}\n ref={containerRef}\n >\n {label && (\n <div\n className={buildClassName(\n 'flex items-center justify-between mb-1.5',\n labelWrapperClass,\n )}\n >\n <Label className={labelClass} htmlFor={id} aria-required={required}>\n {label}\n </Label>\n {labelHint && <TextContent xsmall>{labelHint}</TextContent>}\n </div>\n )}\n\n <Combobox\n multiple={multiple}\n immediate={immediate}\n name={name}\n value={normalizedSelected as any}\n onChange={comboboxOnChangeWrapper as any}\n onClose={() => setQuery('')}\n disabled={disabled}\n by={(a: any, b: any) => (a && b ? getValue(a) === getValue(b) : a === b)}\n >\n {multiple ? (\n <div\n className={buildClassName(\n baseInputClass,\n 'flex flex-wrap gap-2 peer relative',\n rightPaddingClass,\n hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : '',\n )}\n ref={forwardedRef as any}\n >\n {hasLeftGroup && (\n <span\n className={buildClassName(\n 'absolute left-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500',\n currentSize.group,\n )}\n >\n {leftGroup}\n </span>\n )}\n\n {isArray(normalizedSelected) &&\n normalizedSelected?.length > 0 &&\n normalizedSelected.map((option, idx) => (\n <Badge\n key={`${getValue(option)}-${idx}`}\n theme=\"secondary\"\n size={currentSize.badgeSize}\n removable={!disabled}\n onRemove={() => removeSelection(idx)}\n >\n {getDisplayValue(option)}\n </Badge>\n ))}\n\n <ComboboxInput\n className=\"outline-none flex-1 dark:placeholder-gray-400 placeholder-gray-400 bg-transparent\"\n aria-label={name}\n value={query}\n autoComplete=\"off\"\n placeholder={normalizedSelected?.length ? '' : placeholder}\n onChange={(e) => {\n const val = e.target.value\n if (allowFreeText && multiple && val.includes(',')) {\n const parts = val.split(',')\n parts.forEach((p) => {\n if (p.trim()) handleFreeTextCommit(p.trim())\n })\n setQuery('')\n } else {\n setQuery(val)\n }\n }}\n id={id}\n ref={inputRef}\n onKeyDown={(e) => {\n if (allowFreeText && (e.key === 'Enter' || e.key === ',') && query.trim()) {\n e.preventDefault()\n handleFreeTextCommit(query.replace(/,/g, ''))\n } else if (multiple && e.key === 'Backspace' && !query) {\n if (Array.isArray(normalizedSelected) && normalizedSelected.length > 0) {\n removeSelection(normalizedSelected.length - 1)\n }\n }\n }}\n onBlur={() => {\n if (allowFreeText && query.trim()) {\n handleFreeTextCommit(query.replace(/,/g, ''))\n }\n }}\n data-testid=\"combobox-input\"\n />\n\n <ComboboxButton\n className=\"group absolute inset-y-0 right-0 px-2.5 flex items-center justify-center\"\n data-testid=\"combobox-button\"\n >\n <ChevronDownIcon className={chevronIconClass} />\n </ComboboxButton>\n </div>\n ) : (\n <div className=\"relative\" ref={forwardedRef as any}>\n {hasLeftGroup && (\n <span\n className={buildClassName(\n 'absolute left-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500 z-10',\n currentSize.group,\n )}\n >\n {leftGroup}\n </span>\n )}\n\n <ComboboxInput\n aria-label={name}\n displayValue={(option: any) => (option ? getDisplayValue(option) : null)}\n autoComplete=\"off\"\n placeholder={placeholder}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={(e) => {\n if (allowFreeText && e.key === 'Enter' && query.trim()) {\n e.preventDefault()\n handleFreeTextCommit(query)\n }\n }}\n onBlur={() => {\n if (allowFreeText && query.trim()) {\n handleFreeTextCommit(query)\n }\n }}\n onFocus={() => {\n setQuery('')\n }}\n className={buildClassName(\n baseInputClass,\n 'text-ellipsis',\n rightPaddingClass,\n hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : '',\n )}\n disabled={disabled}\n id={id}\n readOnly={!searchable}\n ref={inputRef}\n data-testid=\"combobox-input\"\n />\n\n {showClearButton && (\n <Button\n size=\"xs\"\n iconOnly\n aria-label=\"Clear selection\"\n theme=\"secondary\"\n variant=\"plain\"\n className=\"group absolute inset-y-0 right-8 h-6 top-2\"\n onClick={() => handleOnChangeInternal(multiple ? ([] as T[]) : null)}\n disabled={disabled}\n data-testid=\"combobox-clear-button\"\n >\n <XIcon className=\"size-4 stroke-gray-500 dark:stroke-gray-300\" />\n </Button>\n )}\n\n <ComboboxButton\n className=\"group absolute inset-y-0 right-0 px-2.5 flex items-center justify-center\"\n data-testid=\"combobox-button\"\n >\n <ChevronDownIcon className={chevronIconClass} />\n </ComboboxButton>\n </div>\n )}\n\n <ComboboxOptions\n anchor={{ to: 'bottom start', gap: 5, padding: 8 }}\n as=\"div\"\n modal={modalDropdown}\n // Matches the input width by default; min-width lets the panel grow wider than a narrow input.\n style={dropdownMinWidth != null ? { minWidth: dropdownMinWidth } : undefined}\n className={buildClassName(\n 'w-[var(--input-width)] rounded-lg border border-[var(--ui-border)] bg-white dark:bg-gray-800 p-1 shadow-lg max-h-80 overflow-y-auto z-50 [--anchor-gap:var(--spacing-1)]',\n '[--anchor-max-height:20rem]',\n 'origin-top border transition duration-200 ease-[cubic-bezier(0.4, 0.0, 0.2, 1)] data-[closed]:translate-y-[-15%] data-[closed]:opacity-0',\n dropdownContainerClass,\n )}\n transition\n data-testid=\"combobox-options\"\n >\n {/* Multi-Select \"Select All\" Action Bar */}\n {multiple && showSelectAll && allOptions.length > 0 && (\n <div className=\"pb-1 mb-1 border-b border-[var(--ui-border-muted)] px-3 pt-1 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={handleToggleSelectAll}\n className=\"text-xs font-semibold text-blue-600 dark:text-blue-400 hover:underline cursor-pointer\"\n >\n {isAllSelected ? 'Deselect All' : 'Select All'}\n </button>\n <span className=\"text-[11px] font-medium text-gray-400\">\n {Array.isArray(normalizedSelected) ? normalizedSelected.length : 0} of{' '}\n {allOptions.length}\n </span>\n </div>\n )}\n\n {optionsLoading ? (\n <BodyText\n data-testid=\"options-loading\"\n className=\"flex items-center justify-center py-2 px-3 select-none\"\n >\n <Loader size=\"sm\" />\n </BodyText>\n ) : shouldShowTypeToSearch ? (\n <BodyText className=\"flex items-center justify-between py-2 px-3 select-none\">\n Type to search...\n </BodyText>\n ) : (\n <div>\n {/* Render Free-Text Option if query does not match an option exactly */}\n {allowFreeText &&\n query.trim() &&\n !allOptions.some(\n (opt) => getDisplayValue(opt)?.toLowerCase() === query.trim().toLowerCase(),\n ) && (\n <ComboboxOption\n key={`freetext-${query.trim()}`}\n value={createFreeTextOption(query.trim()) as any}\n className=\"group flex items-center gap-2 rounded-lg py-1.5 px-3 select-none text-sm data-[focus]:bg-blue-50 dark:data-[focus]:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-medium cursor-pointer w-full\"\n data-testid=\"freetext-option\"\n >\n <span>Use \"{query.trim()}\"</span>\n </ComboboxOption>\n )}\n\n {/* Render Grouped Options */}\n {filteredGroups\n ? filteredGroups.map((grp, gIdx) => (\n <div key={gIdx}>\n <div className=\"text-[11px] font-bold uppercase tracking-wider text-gray-400 dark:text-gray-500 px-3 py-1 select-none\">\n {grp.group}\n </div>\n {grp.options.map(renderOptionItem)}\n </div>\n ))\n : /* Render Standard Flat Options */\n filteredOptions.map(renderOptionItem)}\n\n {!hasAnyOptionsToDisplay && Boolean(noOptionsText) && (\n <div\n data-testid=\"no-result-found\"\n className=\"flex items-center gap-2 py-1.5 px-3 select-none\"\n >\n <TextContent muted small>\n {noOptionsText}\n </TextContent>\n {Boolean(query.trim()) && (\n <TextContent strong small>\n \"{query.trim()}\"\n </TextContent>\n )}\n </div>\n )}\n\n {/* Creatable option (allowAdd) - suppressed when allowFreeText is true */}\n {!allowFreeText && allowAdd && Boolean(query.trim()) && (\n <ComboboxOption\n key={`add-${query.trim()}`}\n value={query}\n className=\"group rounded-lg py-1.5 px-3 cursor-pointer text-gray-700 dark:text-gray-300 data-[focus]:bg-gray-100 dark:data-[focus]:bg-gray-700\"\n onClick={() => void handleAddAndSelect(query)}\n >\n <div className=\"flex items-center gap-2\">\n <CirclePlusIcon className=\"size-4.5\" />\n <TextContent>\n {addNewText} \"{query}\"\n </TextContent>\n </div>\n </ComboboxOption>\n )}\n </div>\n )}\n </ComboboxOptions>\n </Combobox>\n\n {showErrorMessage && error && (\n <div className=\"mt-1\">\n <TextContent error small>\n {error}\n </TextContent>\n </div>\n )}\n\n {!error && helperText && (\n <div className=\"mt-1\">\n <TextContent muted small>\n {helperText}\n </TextContent>\n </div>\n )}\n </div>\n )\n },\n)\n\nSelectBox.displayName = 'SelectBox'\n"],"names":["forwardRef","useState","useCallback","_jsx","MobilePicker","useDebounce","useMemo","buildInputClass","buildClassName","useRef","useImperativeHandle","isArray","useEffect","isEmpty","ComboboxOption","_jsxs","CheckIcon","Label","TextContent","Combobox","Badge","ComboboxInput","ComboboxButton","ChevronDownIcon","Button","XIcon","ComboboxOptions","BodyText","Loader","CirclePlusIcon"],"mappings":"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"}
@@ -5,7 +5,7 @@ import { buildClassName } from '../../utils/build-classname.js';
5
5
  import { Button } from '../Button/Button.js';
6
6
  import SvgChevronLeft from '../Icons/ChevronLeft.svg.js';
7
7
  import SvgX from '../Icons/X.svg.js';
8
- import { useResponsiveValue } from '../../hooks/use-breakpoint.js';
8
+ import { useResponsiveValue, useBreakpoint } from '../../hooks/use-breakpoint.js';
9
9
 
10
10
  const alignmentMap = {
11
11
  center: 'items-center justify-center h-full',
@@ -19,8 +19,10 @@ const panelAlignmentMap = {
19
19
  start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',
20
20
  end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',
21
21
  top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',
22
- // Bottom sheets clear the home indicator on notched phones (0 elsewhere).
23
- bottom: 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh] pb-[env(safe-area-inset-bottom,0px)]',
22
+ // Bottom sheets clear the home indicator on notched phones (0 elsewhere). Never
23
+ // taller than the container: with the keyboard up it's shorter than 88dvh, and a
24
+ // bottom-anchored panel past its top is off screen and can't be scrolled to.
25
+ bottom: 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[min(88dvh,100%)] pb-[env(safe-area-inset-bottom,0px)]',
24
26
  };
25
27
  const panelSizeMap = {
26
28
  xs: 'max-w-xs',
@@ -31,27 +33,58 @@ const panelSizeMap = {
31
33
  '2xl': 'max-w-2xl',
32
34
  full: 'w-full',
33
35
  };
34
- const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align: alignProp = 'end', size: sizeProp = 'md', backdrop = true, title, description, children, footer, footerSticky = false, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, showCloseButton = true, dragHandle, }) => {
36
+ // How much shorter than the window the visual viewport must be before it's
37
+ // taken to be the on-screen keyboard rather than the URL bar (≈ 56px).
38
+ const KEYBOARD_THRESHOLD = 150;
39
+ const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align: alignProp = 'end', size: sizeProp = 'md', backdrop = true, title, description, children, footer, footerSticky = false, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, showCloseButton = true, dragHandle, phoneLayout = 'default', headerAction, }) => {
35
40
  const align = useResponsiveValue(alignProp);
36
41
  const size = useResponsiveValue(sizeProp);
42
+ const breakpoint = useBreakpoint();
43
+ const fullscreen = phoneLayout === 'fullscreen' && breakpoint === 'compact';
37
44
  const showTitleSection = Boolean(title || description || showBackButton || showCloseButton);
38
- const shouldShowDragHandle = dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom';
39
- const [viewportHeight, setViewportHeight] = React__default.useState(null);
45
+ const shouldShowDragHandle = !fullscreen && (dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom');
46
+ useCloseOnBack(fullscreen && isOpen, onClose);
47
+ // The visible area while the on-screen keyboard is open; null otherwise.
48
+ const [keyboardViewport, setKeyboardViewport] = React__default.useState(null);
40
49
  React__default.useEffect(() => {
41
50
  if (!isOpen) {
42
- setViewportHeight(null);
51
+ setKeyboardViewport(null);
43
52
  return;
44
53
  }
54
+ // Follow the visual viewport only while the on-screen keyboard takes space
55
+ // (it's then much shorter than the window), so the drawer and its footer
56
+ // stay above the keyboard. Otherwise it's pinned to the edges: tracking every resize and
57
+ // scroll in state re-rendered the drawer on each frame as the browser's
58
+ // URL bar moved, and its sticky header and footer jumped while scrolling.
59
+ let frame = 0;
60
+ const measure = () => {
61
+ frame = 0;
62
+ const vv = window.visualViewport;
63
+ if (!vv)
64
+ return;
65
+ const keyboardOpen = window.innerHeight - vv.height > KEYBOARD_THRESHOLD;
66
+ const top = Math.round(vv.offsetTop);
67
+ const height = Math.round(vv.height);
68
+ // The browser scrolls the visible area to the focused field, so the
69
+ // drawer follows its offset as well as its height. An unchanged value
70
+ // doesn't re-render.
71
+ setKeyboardViewport((current) => !keyboardOpen
72
+ ? null
73
+ : current && current.top === top && current.height === height
74
+ ? current
75
+ : { top, height });
76
+ };
45
77
  const updateHeight = () => {
46
- if (typeof window !== 'undefined' && window.visualViewport) {
47
- setViewportHeight(window.visualViewport.height);
48
- }
78
+ if (!frame)
79
+ frame = window.requestAnimationFrame(measure);
49
80
  };
50
- updateHeight();
81
+ measure();
51
82
  const vv = typeof window !== 'undefined' ? window.visualViewport : null;
52
83
  vv === null || vv === void 0 ? void 0 : vv.addEventListener('resize', updateHeight);
53
84
  vv === null || vv === void 0 ? void 0 : vv.addEventListener('scroll', updateHeight);
54
85
  return () => {
86
+ if (frame)
87
+ window.cancelAnimationFrame(frame);
55
88
  vv === null || vv === void 0 ? void 0 : vv.removeEventListener('resize', updateHeight);
56
89
  vv === null || vv === void 0 ? void 0 : vv.removeEventListener('scroll', updateHeight);
57
90
  };
@@ -61,9 +94,96 @@ const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align
61
94
  onClose === null || onClose === void 0 ? void 0 : onClose();
62
95
  }
63
96
  };
64
- return (jsxs(Dialog, { open: isOpen, as: "div", className: "relative z-50 focus:outline-none", onClose: handleDialogClose, transition: true, children: [backdrop && (jsx(DialogBackdrop, { className: "fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200" })), jsx("div", { className: "fixed left-0 top-0 w-full", style: { height: viewportHeight ? `${viewportHeight}px` : '100dvh' }, children: jsx("div", { className: buildClassName('flex', alignmentMap[align]), children: jsxs(DialogPanel, { transition: true, className: buildClassName('w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0', 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0', panelAlignmentMap[align], panelSizeMap[size], panelClass), children: [shouldShowDragHandle && (jsx("div", { className: "w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab", "data-testid": "drawer-drag-handle" })), showTitleSection && (jsxs("div", { className: buildClassName('space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0', titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10'), children: [jsxs("div", { className: "flex items-center justify-between gap-3 min-w-0", children: [jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [showBackButton && (jsx(Button, { iconOnly: true, "aria-label": "Back", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, children: jsx(SvgChevronLeft, { className: "size-4" }) })), title && (jsx(DialogTitle, { as: "h3", className: buildClassName('text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0', titleClass), children: title }))] }), showCloseButton && (jsx(Button, { iconOnly: true, "aria-label": "Close drawer", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, className: "rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0", children: jsx(SvgX, { className: "size-4" }) }))] }), description && (jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal truncate', descriptionClass), children: description }))] })), jsx("div", { className: buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass), children: children }), footer && (jsx("div", { className: buildClassName('p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0', footerSticky && 'sticky bottom-0 z-10'), children: footer }))] }) }) })] }));
97
+ return (jsxs(Dialog, { open: isOpen, as: "div", className: "relative z-50 focus:outline-none", onClose: handleDialogClose, transition: true, children: [backdrop && (jsx(DialogBackdrop, { className: "fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200" })), jsx("div", { className: "fixed inset-0", style: keyboardViewport
98
+ ? {
99
+ top: `${keyboardViewport.top}px`,
100
+ height: `${keyboardViewport.height}px`,
101
+ bottom: 'auto',
102
+ }
103
+ : undefined, "data-testid": "drawer-viewport", children: jsx("div", { className: buildClassName('flex', fullscreen ? 'h-full' : alignmentMap[align]), children: jsxs(DialogPanel, { transition: true, className: buildClassName('w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0', 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0', ...(fullscreen
104
+ ? ['h-full data-[closed]:translate-y-4']
105
+ : [panelAlignmentMap[align], panelSizeMap[size], panelClass])), "data-layout": fullscreen ? 'fullscreen' : undefined, children: [shouldShowDragHandle && (jsx("div", { className: "w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab", "data-testid": "drawer-drag-handle" })), fullscreen && (jsxs("div", { className: "sticky top-0 z-10 flex h-14 shrink-0 items-center gap-1 border-b border-[var(--ui-border)] bg-white pl-1 pr-3 pt-[env(safe-area-inset-top,0px)] box-content dark:bg-gray-800", children: [jsx(Button, { iconOnly: true, "aria-label": "Close", variant: "plain", theme: "secondary", onClick: onClose, className: "shrink-0", children: jsx(SvgX, { className: "size-5" }) }), title && (jsx(DialogTitle, { as: "h3", className: "min-w-0 flex-1 truncate text-base font-semibold text-gray-900 dark:text-white", children: title })), headerAction && jsx("div", { className: "ml-auto shrink-0", children: headerAction })] })), !fullscreen && showTitleSection && (jsxs("div", { className: buildClassName('space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0', titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10'), children: [jsxs("div", { className: "flex items-center justify-between gap-3 min-w-0", children: [jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [showBackButton && (jsx(Button, { iconOnly: true, "aria-label": "Back", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, children: jsx(SvgChevronLeft, { className: "size-4" }) })), title && (jsx(DialogTitle, { as: "h3", className: buildClassName('text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0', titleClass), children: title }))] }), showCloseButton && (jsx(Button, { iconOnly: true, "aria-label": "Close drawer", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, className: "rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0", children: jsx(SvgX, { className: "size-4" }) }))] }), description && (jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal truncate', descriptionClass), children: description }))] })), jsxs("div", { className: buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass, fullscreen && 'pb-[calc(1rem+env(safe-area-inset-bottom,0px))]'), children: [fullscreen && description && (jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400', descriptionClass), children: description })), children] }), !fullscreen && footer && (jsx("div", { className: buildClassName('p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0', footerSticky && 'sticky bottom-0 z-10'), children: footer }))] }) }) })] }));
65
106
  };
66
107
  Drawer.displayName = 'Drawer';
108
+ // history.back() lands later, so a drawer opening meanwhile (one replacing another,
109
+ // or React re-running effects under StrictMode) would have its new entry removed
110
+ // instead, and close at once. Removals are counted, and an opening drawer waits for them.
111
+ let pendingBacks = 0;
112
+ const afterBacks = [];
113
+ function settleBack() {
114
+ pendingBacks = Math.max(0, pendingBacks - 1);
115
+ if (pendingBacks === 0)
116
+ afterBacks.splice(0).forEach((run) => run());
117
+ }
118
+ function removeEntry() {
119
+ pendingBacks += 1;
120
+ let settled = false;
121
+ const settle = () => {
122
+ if (settled)
123
+ return;
124
+ settled = true;
125
+ window.removeEventListener('popstate', settle);
126
+ settleBack();
127
+ };
128
+ window.addEventListener('popstate', settle);
129
+ // A back that never reports (nothing to go back to) mustn't hold others up.
130
+ window.setTimeout(settle, 500);
131
+ window.history.back();
132
+ }
133
+ /**
134
+ * While `active`, the browser's back button (and Android's back gesture)
135
+ * closes the drawer instead of leaving the page: opening adds a history entry
136
+ * (keeping the current state, so routers see the same location), and back
137
+ * removes it. Closed any other way, the entry is removed too, but only if it's
138
+ * still the latest one, so a form that saves and then navigates isn't undone.
139
+ */
140
+ function useCloseOnBack(active, onClose) {
141
+ const onCloseRef = React__default.useRef(onClose);
142
+ React__default.useEffect(() => {
143
+ onCloseRef.current = onClose;
144
+ });
145
+ const token = React__default.useId();
146
+ React__default.useEffect(() => {
147
+ if (!active || typeof window === 'undefined')
148
+ return;
149
+ const pushEntry = () => { var _a; return window.history.pushState({ ...((_a = window.history.state) !== null && _a !== void 0 ? _a : {}), drawer: token }, ''); };
150
+ let entryPresent = false;
151
+ let disposed = false;
152
+ const handlePop = () => {
153
+ var _a;
154
+ if (((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
155
+ return;
156
+ entryPresent = false;
157
+ onCloseRef.current();
158
+ // onClose may step back within the drawer instead of closing it; if it's
159
+ // still open afterwards, take back its entry so the next back works too.
160
+ window.setTimeout(() => {
161
+ if (disposed)
162
+ return;
163
+ pushEntry();
164
+ entryPresent = true;
165
+ }, 0);
166
+ };
167
+ const start = () => {
168
+ if (disposed)
169
+ return;
170
+ pushEntry();
171
+ entryPresent = true;
172
+ window.addEventListener('popstate', handlePop);
173
+ };
174
+ if (pendingBacks > 0)
175
+ afterBacks.push(start);
176
+ else
177
+ start();
178
+ return () => {
179
+ var _a;
180
+ disposed = true;
181
+ window.removeEventListener('popstate', handlePop);
182
+ if (entryPresent && ((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
183
+ removeEntry();
184
+ };
185
+ }, [active, token]);
186
+ }
67
187
 
68
188
  export { Drawer };
69
189
  //# sourceMappingURL=Drawer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.js","sources":["../../../../../src/components/Drawer/Drawer.tsx"],"sourcesContent":["import React from 'react'\nimport { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Button } from '../Button'\nimport ChevronLeftIcon from '../Icons/ChevronLeft.svg'\nimport XIcon from '../Icons/X.svg'\nimport { useResponsiveValue } from '../../hooks/use-breakpoint'\nimport type { AlignmentMap, DrawerProps, SizeMap } from './Drawer.types'\n\nconst alignmentMap: AlignmentMap = {\n center: 'items-center justify-center h-full',\n start: 'justify-start h-full',\n end: 'justify-end h-full',\n top: 'items-start justify-center w-full',\n bottom: 'items-end justify-center h-full',\n}\n\nconst panelAlignmentMap: AlignmentMap = {\n center: 'data-[closed]:scale-95 rounded-2xl',\n start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',\n end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',\n top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',\n // Bottom sheets clear the home indicator on notched phones (0 elsewhere).\n bottom:\n 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh] pb-[env(safe-area-inset-bottom,0px)]',\n}\n\nconst panelSizeMap: SizeMap = {\n xs: 'max-w-xs',\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl',\n '2xl': 'max-w-2xl',\n full: 'w-full',\n}\n\nexport const Drawer: React.FC<DrawerProps> = ({\n isOpen,\n onClose = () => {},\n closeOnOutsideClick = true,\n align: alignProp = 'end',\n size: sizeProp = 'md',\n backdrop = true,\n title,\n description,\n children,\n footer,\n footerSticky = false,\n panelClass = '',\n contentClass = '',\n titleClass = '',\n descriptionClass = '',\n titleSticky = false,\n showBackButton = false,\n showCloseButton = true,\n dragHandle,\n}) => {\n const align = useResponsiveValue(alignProp)\n const size = useResponsiveValue(sizeProp)\n const showTitleSection = Boolean(title || description || showBackButton || showCloseButton)\n const shouldShowDragHandle = dragHandle ?? align === 'bottom'\n const [viewportHeight, setViewportHeight] = React.useState<number | null>(null)\n\n React.useEffect(() => {\n if (!isOpen) {\n setViewportHeight(null)\n return\n }\n\n const updateHeight = () => {\n if (typeof window !== 'undefined' && window.visualViewport) {\n setViewportHeight(window.visualViewport.height)\n }\n }\n\n updateHeight()\n const vv = typeof window !== 'undefined' ? window.visualViewport : null\n vv?.addEventListener('resize', updateHeight)\n vv?.addEventListener('scroll', updateHeight)\n\n return () => {\n vv?.removeEventListener('resize', updateHeight)\n vv?.removeEventListener('scroll', updateHeight)\n }\n }, [isOpen])\n\n const handleDialogClose = () => {\n if (closeOnOutsideClick) {\n onClose?.()\n }\n }\n\n return (\n <Dialog\n open={isOpen}\n as=\"div\"\n className=\"relative z-50 focus:outline-none\"\n onClose={handleDialogClose}\n transition\n >\n {backdrop && (\n <DialogBackdrop className=\"fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200\" />\n )}\n\n <div\n className=\"fixed left-0 top-0 w-full\"\n style={{ height: viewportHeight ? `${viewportHeight}px` : '100dvh' }}\n >\n <div className={buildClassName('flex', alignmentMap[align])}>\n <DialogPanel\n transition\n className={buildClassName(\n 'w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0',\n 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0',\n panelAlignmentMap[align],\n panelSizeMap[size],\n panelClass,\n )}\n >\n {/* Top drag handle indicator for mobile bottom sheet */}\n {shouldShowDragHandle && (\n <div\n className=\"w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab\"\n data-testid=\"drawer-drag-handle\"\n />\n )}\n\n {/* Header Section */}\n {showTitleSection && (\n <div\n className={buildClassName(\n 'space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0',\n titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10',\n )}\n >\n <div className=\"flex items-center justify-between gap-3 min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0 flex-1\">\n {showBackButton && (\n <Button\n iconOnly\n aria-label=\"Back\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n >\n <ChevronLeftIcon className=\"size-4\" />\n </Button>\n )}\n {title && (\n <DialogTitle\n as=\"h3\"\n className={buildClassName(\n 'text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0',\n titleClass,\n )}\n >\n {title}\n </DialogTitle>\n )}\n </div>\n\n {showCloseButton && (\n <Button\n iconOnly\n aria-label=\"Close drawer\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n className=\"rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0\"\n >\n <XIcon className=\"size-4\" />\n </Button>\n )}\n </div>\n\n {description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400 font-normal truncate',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n </div>\n )}\n\n {/* Content Body */}\n <div className={buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass)}>\n {children}\n </div>\n\n {/* Footer Section */}\n {footer && (\n <div\n className={buildClassName(\n 'p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0',\n footerSticky && 'sticky bottom-0 z-10',\n )}\n >\n {footer}\n </div>\n )}\n </DialogPanel>\n </div>\n </div>\n </Dialog>\n )\n}\n\nDrawer.displayName = 'Drawer'\n"],"names":["React","_jsxs","_jsx","ChevronLeftIcon","XIcon"],"mappings":";;;;;;;;;AASA,MAAM,YAAY,GAAiB;AACjC,IAAA,MAAM,EAAE,oCAAoC;AAC5C,IAAA,KAAK,EAAE,sBAAsB;AAC7B,IAAA,GAAG,EAAE,oBAAoB;AACzB,IAAA,GAAG,EAAE,mCAAmC;AACxC,IAAA,MAAM,EAAE,iCAAiC;CAC1C;AAED,MAAM,iBAAiB,GAAiB;AACtC,IAAA,MAAM,EAAE,oCAAoC;AAC5C,IAAA,KAAK,EAAE,8CAA8C;AACrD,IAAA,GAAG,EAAE,6CAA6C;AAClD,IAAA,GAAG,EAAE,8CAA8C;;AAEnD,IAAA,MAAM,EACJ,+HAA+H;CAClI;AAED,MAAM,YAAY,GAAY;AAC5B,IAAA,EAAE,EAAE,UAAU;AACd,IAAA,EAAE,EAAE,UAAU;AACd,IAAA,EAAE,EAAE,UAAU;AACd,IAAA,EAAE,EAAE,UAAU;AACd,IAAA,EAAE,EAAE,UAAU;AACd,IAAA,KAAK,EAAE,WAAW;AAClB,IAAA,IAAI,EAAE,QAAQ;CACf;AAEM,MAAM,MAAM,GAA0B,CAAC,EAC5C,MAAM,EACN,OAAO,GAAG,MAAK,EAAE,CAAC,EAClB,mBAAmB,GAAG,IAAI,EAC1B,KAAK,EAAE,SAAS,GAAG,KAAK,EACxB,IAAI,EAAE,QAAQ,GAAG,IAAI,EACrB,QAAQ,GAAG,IAAI,EACf,KAAK,EACL,WAAW,EACX,QAAQ,EACR,MAAM,EACN,YAAY,GAAG,KAAK,EACpB,UAAU,GAAG,EAAE,EACf,YAAY,GAAG,EAAE,EACjB,UAAU,GAAG,EAAE,EACf,gBAAgB,GAAG,EAAE,EACrB,WAAW,GAAG,KAAK,EACnB,cAAc,GAAG,KAAK,EACtB,eAAe,GAAG,IAAI,EACtB,UAAU,GACX,KAAI;AACH,IAAA,MAAM,KAAK,GAAG,kBAAkB,CAAC,SAAS,CAAC;AAC3C,IAAA,MAAM,IAAI,GAAG,kBAAkB,CAAC,QAAQ,CAAC;AACzC,IAAA,MAAM,gBAAgB,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,IAAI,cAAc,IAAI,eAAe,CAAC;IAC3F,MAAM,oBAAoB,GAAG,UAAU,KAAA,IAAA,IAAV,UAAU,KAAA,MAAA,GAAV,UAAU,GAAI,KAAK,KAAK,QAAQ;AAC7D,IAAA,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAGA,cAAK,CAAC,QAAQ,CAAgB,IAAI,CAAC;AAE/E,IAAAA,cAAK,CAAC,SAAS,CAAC,MAAK;QACnB,IAAI,CAAC,MAAM,EAAE;YACX,iBAAiB,CAAC,IAAI,CAAC;YACvB;QACF;QAEA,MAAM,YAAY,GAAG,MAAK;YACxB,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,cAAc,EAAE;AAC1D,gBAAA,iBAAiB,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC;YACjD;AACF,QAAA,CAAC;AAED,QAAA,YAAY,EAAE;AACd,QAAA,MAAM,EAAE,GAAG,OAAO,MAAM,KAAK,WAAW,GAAG,MAAM,CAAC,cAAc,GAAG,IAAI;QACvE,EAAE,KAAA,IAAA,IAAF,EAAE,KAAA,MAAA,GAAA,MAAA,GAAF,EAAE,CAAE,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC;QAC5C,EAAE,KAAA,IAAA,IAAF,EAAE,KAAA,MAAA,GAAA,MAAA,GAAF,EAAE,CAAE,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC;AAE5C,QAAA,OAAO,MAAK;YACV,EAAE,KAAA,IAAA,IAAF,EAAE,KAAA,MAAA,GAAA,MAAA,GAAF,EAAE,CAAE,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC;YAC/C,EAAE,KAAA,IAAA,IAAF,EAAE,KAAA,MAAA,GAAA,MAAA,GAAF,EAAE,CAAE,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC;AACjD,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IAEZ,MAAM,iBAAiB,GAAG,MAAK;QAC7B,IAAI,mBAAmB,EAAE;AACvB,YAAA,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,EAAI;QACb;AACF,IAAA,CAAC;AAED,IAAA,QACEC,IAAA,CAAC,MAAM,EAAA,EACL,IAAI,EAAE,MAAM,EACZ,EAAE,EAAC,KAAK,EACR,SAAS,EAAC,kCAAkC,EAC5C,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAA,IAAA,EAAA,QAAA,EAAA,CAET,QAAQ,KACPC,GAAA,CAAC,cAAc,EAAA,EAAC,SAAS,EAAC,4EAA4E,GAAG,CAC1G,EAEDA,GAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAC,2BAA2B,EACrC,KAAK,EAAE,EAAE,MAAM,EAAE,cAAc,GAAG,CAAA,EAAG,cAAc,CAAA,EAAA,CAAI,GAAG,QAAQ,EAAE,EAAA,QAAA,EAEpEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAA,QAAA,EACzDD,IAAA,CAAC,WAAW,EAAA,EACV,UAAU,EAAA,IAAA,EACV,SAAS,EAAE,cAAc,CACvB,6EAA6E,EAC7E,mJAAmJ,EACnJ,iBAAiB,CAAC,KAAK,CAAC,EACxB,YAAY,CAAC,IAAI,CAAC,EAClB,UAAU,CACX,aAGA,oBAAoB,KACnBC,GAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAC,0FAA0F,EAAA,aAAA,EACxF,oBAAoB,EAAA,CAChC,CACH,EAGA,gBAAgB,KACfD,IAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,cAAc,CACvB,uFAAuF,EACvF,WAAW,IAAI,6CAA6C,CAC7D,aAEDA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,iDAAiD,EAAA,QAAA,EAAA,CAC9DA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,wCAAwC,EAAA,QAAA,EAAA,CACpD,cAAc,KACbC,IAAC,MAAM,EAAA,EACL,QAAQ,EAAA,IAAA,EAAA,YAAA,EACG,MAAM,EACjB,OAAO,EAAC,OAAO,EACf,KAAK,EAAC,WAAW,EACjB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,OAAO,EAAA,QAAA,EAEhBA,IAACC,cAAe,EAAA,EAAC,SAAS,EAAC,QAAQ,EAAA,CAAG,EAAA,CAC/B,CACV,EACA,KAAK,KACJD,GAAA,CAAC,WAAW,EAAA,EACV,EAAE,EAAC,IAAI,EACP,SAAS,EAAE,cAAc,CACvB,qFAAqF,EACrF,UAAU,CACX,EAAA,QAAA,EAEA,KAAK,EAAA,CACM,CACf,CAAA,EAAA,CACG,EAEL,eAAe,KACdA,GAAA,CAAC,MAAM,EAAA,EACL,QAAQ,EAAA,IAAA,EAAA,YAAA,EACG,cAAc,EACzB,OAAO,EAAC,OAAO,EACf,KAAK,EAAC,WAAW,EACjB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,kFAAkF,EAAA,QAAA,EAE5FA,IAACE,IAAK,EAAA,EAAC,SAAS,EAAC,QAAQ,EAAA,CAAG,EAAA,CACrB,CACV,IACG,EAEL,WAAW,KACVF,GAAA,CAAA,GAAA,EAAA,EACE,SAAS,EAAE,cAAc,CACvB,+DAA+D,EAC/D,gBAAgB,CACjB,YAEA,WAAW,EAAA,CACV,CACL,CAAA,EAAA,CACG,CACP,EAGDA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,cAAc,CAAC,qCAAqC,EAAE,YAAY,CAAC,EAAA,QAAA,EAChF,QAAQ,EAAA,CACL,EAGL,MAAM,KACLA,aACE,SAAS,EAAE,cAAc,CACvB,yFAAyF,EACzF,YAAY,IAAI,sBAAsB,CACvC,EAAA,QAAA,EAEA,MAAM,EAAA,CACH,CACP,CAAA,EAAA,CACW,EAAA,CACV,EAAA,CACF,CAAA,EAAA,CACC;AAEb;AAEA,MAAM,CAAC,WAAW,GAAG,QAAQ;;;;"}
1
+ {"version":3,"file":"Drawer.js","sources":["../../../../../src/components/Drawer/Drawer.tsx"],"sourcesContent":["import React from 'react'\nimport { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Button } from '../Button'\nimport ChevronLeftIcon from '../Icons/ChevronLeft.svg'\nimport XIcon from '../Icons/X.svg'\nimport { useBreakpoint, useResponsiveValue } from '../../hooks/use-breakpoint'\nimport type { AlignmentMap, DrawerProps, SizeMap } from './Drawer.types'\n\nconst alignmentMap: AlignmentMap = {\n center: 'items-center justify-center h-full',\n start: 'justify-start h-full',\n end: 'justify-end h-full',\n top: 'items-start justify-center w-full',\n bottom: 'items-end justify-center h-full',\n}\n\nconst panelAlignmentMap: AlignmentMap = {\n center: 'data-[closed]:scale-95 rounded-2xl',\n start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',\n end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',\n top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',\n // Bottom sheets clear the home indicator on notched phones (0 elsewhere). Never\n // taller than the container: with the keyboard up it's shorter than 88dvh, and a\n // bottom-anchored panel past its top is off screen and can't be scrolled to.\n bottom:\n 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[min(88dvh,100%)] pb-[env(safe-area-inset-bottom,0px)]',\n}\n\nconst panelSizeMap: SizeMap = {\n xs: 'max-w-xs',\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl',\n '2xl': 'max-w-2xl',\n full: 'w-full',\n}\n\n// How much shorter than the window the visual viewport must be before it's\n// taken to be the on-screen keyboard rather than the URL bar (≈ 56px).\nconst KEYBOARD_THRESHOLD = 150\nexport const Drawer: React.FC<DrawerProps> = ({\n isOpen,\n onClose = () => {},\n closeOnOutsideClick = true,\n align: alignProp = 'end',\n size: sizeProp = 'md',\n backdrop = true,\n title,\n description,\n children,\n footer,\n footerSticky = false,\n panelClass = '',\n contentClass = '',\n titleClass = '',\n descriptionClass = '',\n titleSticky = false,\n showBackButton = false,\n showCloseButton = true,\n dragHandle,\n phoneLayout = 'default',\n headerAction,\n}) => {\n const align = useResponsiveValue(alignProp)\n const size = useResponsiveValue(sizeProp)\n const breakpoint = useBreakpoint()\n const fullscreen = phoneLayout === 'fullscreen' && breakpoint === 'compact'\n const showTitleSection = Boolean(title || description || showBackButton || showCloseButton)\n const shouldShowDragHandle = !fullscreen && (dragHandle ?? align === 'bottom')\n useCloseOnBack(fullscreen && isOpen, onClose)\n // The visible area while the on-screen keyboard is open; null otherwise.\n const [keyboardViewport, setKeyboardViewport] = React.useState<{\n top: number\n height: number\n } | null>(null)\n\n React.useEffect(() => {\n if (!isOpen) {\n setKeyboardViewport(null)\n return\n }\n\n // Follow the visual viewport only while the on-screen keyboard takes space\n // (it's then much shorter than the window), so the drawer and its footer\n // stay above the keyboard. Otherwise it's pinned to the edges: tracking every resize and\n // scroll in state re-rendered the drawer on each frame as the browser's\n // URL bar moved, and its sticky header and footer jumped while scrolling.\n let frame = 0\n const measure = () => {\n frame = 0\n const vv = window.visualViewport\n if (!vv) return\n const keyboardOpen = window.innerHeight - vv.height > KEYBOARD_THRESHOLD\n const top = Math.round(vv.offsetTop)\n const height = Math.round(vv.height)\n // The browser scrolls the visible area to the focused field, so the\n // drawer follows its offset as well as its height. An unchanged value\n // doesn't re-render.\n setKeyboardViewport((current) =>\n !keyboardOpen\n ? null\n : current && current.top === top && current.height === height\n ? current\n : { top, height },\n )\n }\n const updateHeight = () => {\n if (!frame) frame = window.requestAnimationFrame(measure)\n }\n\n measure()\n const vv = typeof window !== 'undefined' ? window.visualViewport : null\n vv?.addEventListener('resize', updateHeight)\n vv?.addEventListener('scroll', updateHeight)\n\n return () => {\n if (frame) window.cancelAnimationFrame(frame)\n vv?.removeEventListener('resize', updateHeight)\n vv?.removeEventListener('scroll', updateHeight)\n }\n }, [isOpen])\n\n const handleDialogClose = () => {\n if (closeOnOutsideClick) {\n onClose?.()\n }\n }\n\n return (\n <Dialog\n open={isOpen}\n as=\"div\"\n className=\"relative z-50 focus:outline-none\"\n onClose={handleDialogClose}\n transition\n >\n {backdrop && (\n <DialogBackdrop className=\"fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200\" />\n )}\n\n {/* Pinned to all four edges rather than given a height: mobile browsers\n move fixed edges with the URL bar on every frame, while 100dvh only\n updates once its animation ends (the drawer briefly came up short).\n With the keyboard open it takes the visible area's offset and height. */}\n <div\n className=\"fixed inset-0\"\n style={\n keyboardViewport\n ? {\n top: `${keyboardViewport.top}px`,\n height: `${keyboardViewport.height}px`,\n bottom: 'auto',\n }\n : undefined\n }\n data-testid=\"drawer-viewport\"\n >\n <div className={buildClassName('flex', fullscreen ? 'h-full' : alignmentMap[align])}>\n <DialogPanel\n transition\n className={buildClassName(\n 'w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0',\n 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0',\n ...(fullscreen\n ? ['h-full data-[closed]:translate-y-4']\n : [panelAlignmentMap[align], panelSizeMap[size], panelClass]),\n )}\n data-layout={fullscreen ? 'fullscreen' : undefined}\n >\n {/* Top drag handle indicator for mobile bottom sheet */}\n {shouldShowDragHandle && (\n <div\n className=\"w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab\"\n data-testid=\"drawer-drag-handle\"\n />\n )}\n\n {/* Phone full-screen bar: the only fixed part, so the fields keep the room. */}\n {fullscreen && (\n <div className=\"sticky top-0 z-10 flex h-14 shrink-0 items-center gap-1 border-b border-[var(--ui-border)] bg-white pl-1 pr-3 pt-[env(safe-area-inset-top,0px)] box-content dark:bg-gray-800\">\n <Button\n iconOnly\n aria-label=\"Close\"\n variant=\"plain\"\n theme=\"secondary\"\n onClick={onClose}\n className=\"shrink-0\"\n >\n <XIcon className=\"size-5\" />\n </Button>\n {title && (\n <DialogTitle\n as=\"h3\"\n className=\"min-w-0 flex-1 truncate text-base font-semibold text-gray-900 dark:text-white\"\n >\n {title}\n </DialogTitle>\n )}\n {headerAction && <div className=\"ml-auto shrink-0\">{headerAction}</div>}\n </div>\n )}\n\n {/* Header Section */}\n {!fullscreen && showTitleSection && (\n <div\n className={buildClassName(\n 'space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0',\n titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10',\n )}\n >\n <div className=\"flex items-center justify-between gap-3 min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0 flex-1\">\n {showBackButton && (\n <Button\n iconOnly\n aria-label=\"Back\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n >\n <ChevronLeftIcon className=\"size-4\" />\n </Button>\n )}\n {title && (\n <DialogTitle\n as=\"h3\"\n className={buildClassName(\n 'text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0',\n titleClass,\n )}\n >\n {title}\n </DialogTitle>\n )}\n </div>\n\n {showCloseButton && (\n <Button\n iconOnly\n aria-label=\"Close drawer\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n className=\"rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0\"\n >\n <XIcon className=\"size-4\" />\n </Button>\n )}\n </div>\n\n {description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400 font-normal truncate',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n </div>\n )}\n\n {/* Content Body */}\n <div\n className={buildClassName(\n 'flex-1 p-4 md:p-6 space-y-4 min-w-0',\n contentClass,\n fullscreen && 'pb-[calc(1rem+env(safe-area-inset-bottom,0px))]',\n )}\n >\n {fullscreen && description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n {children}\n </div>\n\n {/* Footer Section (the phone full-screen bar carries the action instead) */}\n {!fullscreen && footer && (\n <div\n className={buildClassName(\n 'p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0',\n footerSticky && 'sticky bottom-0 z-10',\n )}\n >\n {footer}\n </div>\n )}\n </DialogPanel>\n </div>\n </div>\n </Dialog>\n )\n}\n\nDrawer.displayName = 'Drawer'\n\n// history.back() lands later, so a drawer opening meanwhile (one replacing another,\n// or React re-running effects under StrictMode) would have its new entry removed\n// instead, and close at once. Removals are counted, and an opening drawer waits for them.\nlet pendingBacks = 0\nconst afterBacks: Array<() => void> = []\n\nfunction settleBack() {\n pendingBacks = Math.max(0, pendingBacks - 1)\n if (pendingBacks === 0) afterBacks.splice(0).forEach((run) => run())\n}\n\nfunction removeEntry() {\n pendingBacks += 1\n let settled = false\n const settle = () => {\n if (settled) return\n settled = true\n window.removeEventListener('popstate', settle)\n settleBack()\n }\n window.addEventListener('popstate', settle)\n // A back that never reports (nothing to go back to) mustn't hold others up.\n window.setTimeout(settle, 500)\n window.history.back()\n}\n\n/**\n * While `active`, the browser's back button (and Android's back gesture)\n * closes the drawer instead of leaving the page: opening adds a history entry\n * (keeping the current state, so routers see the same location), and back\n * removes it. Closed any other way, the entry is removed too, but only if it's\n * still the latest one, so a form that saves and then navigates isn't undone.\n */\nfunction useCloseOnBack(active: boolean, onClose: () => void) {\n const onCloseRef = React.useRef(onClose)\n React.useEffect(() => {\n onCloseRef.current = onClose\n })\n const token = React.useId()\n\n React.useEffect(() => {\n if (!active || typeof window === 'undefined') return\n const pushEntry = () =>\n window.history.pushState({ ...(window.history.state ?? {}), drawer: token }, '')\n let entryPresent = false\n let disposed = false\n const handlePop = () => {\n if (window.history.state?.drawer === token) return\n entryPresent = false\n onCloseRef.current()\n // onClose may step back within the drawer instead of closing it; if it's\n // still open afterwards, take back its entry so the next back works too.\n window.setTimeout(() => {\n if (disposed) return\n pushEntry()\n entryPresent = true\n }, 0)\n }\n const start = () => {\n if (disposed) return\n pushEntry()\n entryPresent = true\n window.addEventListener('popstate', handlePop)\n }\n if (pendingBacks > 0) afterBacks.push(start)\n else start()\n return () => {\n disposed = true\n window.removeEventListener('popstate', handlePop)\n if (entryPresent && window.history.state?.drawer === token) removeEntry()\n }\n }, [active, token])\n}\n"],"names":["React","_jsxs","_jsx","XIcon","ChevronLeftIcon"],"mappings":"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"}
@@ -56,7 +56,7 @@ const QuantityStepper = forwardRef((props, ref) => {
56
56
  };
57
57
  const isAtMin = disabled || value <= min;
58
58
  const isAtMax = disabled || value >= max;
59
- return (jsxs("div", { className: buildClassName('flex flex-col gap-1 inline-flex', className), children: [label && (jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsx(Label, { htmlFor: stepperId, className: disabled ? 'opacity-70 cursor-not-allowed' : '', children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs("div", { className: buildClassName('inline-flex items-center rounded-lg shadow-2xs transition-all duration-150', 'outline outline-1 -outline-offset-1', CONTAINER_SIZE_CLASS[size], hasError
59
+ return (jsxs("div", { className: buildClassName('flex flex-col gap-1.5 inline-flex', className), children: [label && (jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsx(Label, { htmlFor: stepperId, className: disabled ? 'opacity-70 cursor-not-allowed' : '', children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs("div", { className: buildClassName('inline-flex items-center rounded-lg shadow-2xs transition-all duration-150', 'outline outline-1 -outline-offset-1', CONTAINER_SIZE_CLASS[size], hasError
60
60
  ? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'
61
61
  : 'outline-[var(--ui-border)]', disabled
62
62
  ? 'pointer-events-none bg-gray-100 dark:bg-gray-800 outline-[var(--ui-border-muted)]'
@@ -1 +1 @@
1
- {"version":3,"file":"QuantityStepper.js","sources":["../../../../../src/components/QuantityStepper/QuantityStepper.tsx"],"sourcesContent":["import React, { forwardRef, useId } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Label } from '../Label'\nimport { TextContent } from '../TextContent'\nimport type { QuantityStepperProps, QuantityStepperSize } from './QuantityStepper.types'\n\nconst MinusIcon = ({ className }: { className?: string }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n)\n\nconst PlusIcon = ({ className }: { className?: string }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n)\n\nconst CONTAINER_SIZE_CLASS: Record<QuantityStepperSize, string> = {\n sm: 'h-8 text-xs',\n md: 'h-10 text-sm',\n lg: 'h-12 text-base',\n}\n\nconst BUTTON_SIZE_CLASS: Record<QuantityStepperSize, string> = {\n sm: 'w-7.5 h-full',\n md: 'w-9.5 h-full',\n lg: 'w-11 h-full',\n}\n\nconst ICON_SIZE_CLASS: Record<QuantityStepperSize, string> = {\n sm: 'size-3.5',\n md: 'size-4',\n lg: 'size-4.5',\n}\n\nconst INPUT_TEXT_CLASS: Record<QuantityStepperSize, string> = {\n sm: 'w-12 text-xs',\n md: 'w-16 text-sm',\n lg: 'w-20 text-base',\n}\n\nexport const QuantityStepper = forwardRef<HTMLInputElement, QuantityStepperProps>((props, ref) => {\n const {\n value,\n onChange,\n min = 0,\n max = 99999,\n step = 1,\n label,\n labelHint,\n helperText,\n error,\n showErrorMessage = true,\n size = 'md',\n prefix,\n suffix,\n disabled = false,\n className,\n onFocus,\n id: customId,\n ...restProps\n } = props\n\n const autoId = useId()\n const stepperId = customId || `stepper-${autoId}`\n const hasError = Boolean(error)\n\n const handleDecrement = () => {\n if (disabled) return\n const next = Math.max(min, Number((value - step).toFixed(4)))\n onChange(next)\n }\n\n const handleIncrement = () => {\n if (disabled) return\n const next = Math.min(max, Number((value + step).toFixed(4)))\n onChange(next)\n }\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value\n if (raw === '') {\n onChange(0)\n return\n }\n const parsed = parseFloat(raw)\n if (!isNaN(parsed)) {\n onChange(Math.max(min, Math.min(max, parsed)))\n }\n }\n\n const isAtMin = disabled || value <= min\n const isAtMax = disabled || value >= max\n\n return (\n <div className={buildClassName('flex flex-col gap-1 inline-flex', className)}>\n {/* Label Header Row matching Input */}\n {label && (\n <div className=\"flex items-center justify-between gap-2\">\n <Label htmlFor={stepperId} className={disabled ? 'opacity-70 cursor-not-allowed' : ''}>\n {label}\n </Label>\n {labelHint && <TextContent xsmall>{labelHint}</TextContent>}\n </div>\n )}\n\n {/* Input Container Frame matching Input outline & focus ring */}\n <div\n className={buildClassName(\n 'inline-flex items-center rounded-lg shadow-2xs transition-all duration-150',\n 'outline outline-1 -outline-offset-1',\n CONTAINER_SIZE_CLASS[size],\n hasError\n ? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'\n : 'outline-[var(--ui-border)]',\n disabled\n ? 'pointer-events-none bg-gray-100 dark:bg-gray-800 outline-[var(--ui-border-muted)]'\n : 'bg-white dark:bg-gray-700',\n 'focus-within:outline-[var(--ui-focus-ring)] focus-within:outline-2 focus-within:-outline-offset-2',\n )}\n data-testid=\"quantity-stepper\"\n >\n {/* Decrement Button */}\n <button\n type=\"button\"\n disabled={isAtMin}\n onClick={handleDecrement}\n tabIndex={-1}\n aria-label=\"Decrease quantity\"\n className={buildClassName(\n 'flex items-center justify-center rounded-l-lg text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-white transition-colors shrink-0',\n BUTTON_SIZE_CLASS[size],\n isAtMin\n ? 'opacity-30 hover:bg-transparent cursor-not-allowed'\n : 'cursor-pointer hover:bg-gray-100/80 dark:hover:bg-gray-600/60',\n )}\n data-testid=\"stepper-decrement\"\n >\n <MinusIcon className={ICON_SIZE_CLASS[size]} />\n </button>\n\n {prefix && (\n <span className=\"pl-1 text-gray-400 dark:text-gray-400 select-none text-xs shrink-0\">\n {prefix}\n </span>\n )}\n\n {/* Number Input */}\n <input\n ref={ref}\n id={stepperId}\n type=\"number\"\n min={min}\n max={max}\n step={step}\n value={value === 0 ? '' : value}\n placeholder=\"0\"\n disabled={disabled}\n onFocus={(e) => {\n e.target.select()\n onFocus?.(e)\n }}\n onChange={handleInputChange}\n className={buildClassName(\n 'text-center font-semibold text-gray-900 dark:text-white bg-transparent focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',\n INPUT_TEXT_CLASS[size],\n )}\n data-testid=\"stepper-input\"\n {...restProps}\n />\n\n {suffix && (\n <span className=\"pr-1 text-gray-500 dark:text-gray-400 select-none text-xs shrink-0\">\n {suffix}\n </span>\n )}\n\n {/* Increment Button */}\n <button\n type=\"button\"\n disabled={isAtMax}\n onClick={handleIncrement}\n tabIndex={-1}\n aria-label=\"Increase quantity\"\n className={buildClassName(\n 'flex items-center justify-center rounded-r-lg text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-white transition-colors shrink-0',\n BUTTON_SIZE_CLASS[size],\n isAtMax\n ? 'opacity-30 hover:bg-transparent cursor-not-allowed'\n : 'cursor-pointer hover:bg-gray-100/80 dark:hover:bg-gray-600/60',\n )}\n data-testid=\"stepper-increment\"\n >\n <PlusIcon className={ICON_SIZE_CLASS[size]} />\n </button>\n </div>\n\n {/* Footer Row matching Input error / helper text */}\n {(showErrorMessage && error) || helperText ? (\n <div className=\"flex items-center justify-between gap-2 mt-0.5\">\n {showErrorMessage && error ? (\n <TextContent xsmall className=\"text-red-500 dark:text-red-400 font-medium\">\n {error}\n </TextContent>\n ) : helperText ? (\n <TextContent xsmall muted>\n {helperText}\n </TextContent>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n})\n\nQuantityStepper.displayName = 'QuantityStepper'\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"QuantityStepper.js","sources":["../../../../../src/components/QuantityStepper/QuantityStepper.tsx"],"sourcesContent":["import React, { forwardRef, useId } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Label } from '../Label'\nimport { TextContent } from '../TextContent'\nimport type { QuantityStepperProps, QuantityStepperSize } from './QuantityStepper.types'\n\nconst MinusIcon = ({ className }: { className?: string }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n)\n\nconst PlusIcon = ({ className }: { className?: string }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n)\n\nconst CONTAINER_SIZE_CLASS: Record<QuantityStepperSize, string> = {\n sm: 'h-8 text-xs',\n md: 'h-10 text-sm',\n lg: 'h-12 text-base',\n}\n\nconst BUTTON_SIZE_CLASS: Record<QuantityStepperSize, string> = {\n sm: 'w-7.5 h-full',\n md: 'w-9.5 h-full',\n lg: 'w-11 h-full',\n}\n\nconst ICON_SIZE_CLASS: Record<QuantityStepperSize, string> = {\n sm: 'size-3.5',\n md: 'size-4',\n lg: 'size-4.5',\n}\n\nconst INPUT_TEXT_CLASS: Record<QuantityStepperSize, string> = {\n sm: 'w-12 text-xs',\n md: 'w-16 text-sm',\n lg: 'w-20 text-base',\n}\n\nexport const QuantityStepper = forwardRef<HTMLInputElement, QuantityStepperProps>((props, ref) => {\n const {\n value,\n onChange,\n min = 0,\n max = 99999,\n step = 1,\n label,\n labelHint,\n helperText,\n error,\n showErrorMessage = true,\n size = 'md',\n prefix,\n suffix,\n disabled = false,\n className,\n onFocus,\n id: customId,\n ...restProps\n } = props\n\n const autoId = useId()\n const stepperId = customId || `stepper-${autoId}`\n const hasError = Boolean(error)\n\n const handleDecrement = () => {\n if (disabled) return\n const next = Math.max(min, Number((value - step).toFixed(4)))\n onChange(next)\n }\n\n const handleIncrement = () => {\n if (disabled) return\n const next = Math.min(max, Number((value + step).toFixed(4)))\n onChange(next)\n }\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value\n if (raw === '') {\n onChange(0)\n return\n }\n const parsed = parseFloat(raw)\n if (!isNaN(parsed)) {\n onChange(Math.max(min, Math.min(max, parsed)))\n }\n }\n\n const isAtMin = disabled || value <= min\n const isAtMax = disabled || value >= max\n\n return (\n <div className={buildClassName('flex flex-col gap-1.5 inline-flex', className)}>\n {/* Label Header Row matching Input */}\n {label && (\n <div className=\"flex items-center justify-between gap-2\">\n <Label htmlFor={stepperId} className={disabled ? 'opacity-70 cursor-not-allowed' : ''}>\n {label}\n </Label>\n {labelHint && <TextContent xsmall>{labelHint}</TextContent>}\n </div>\n )}\n\n {/* Input Container Frame matching Input outline & focus ring */}\n <div\n className={buildClassName(\n 'inline-flex items-center rounded-lg shadow-2xs transition-all duration-150',\n 'outline outline-1 -outline-offset-1',\n CONTAINER_SIZE_CLASS[size],\n hasError\n ? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'\n : 'outline-[var(--ui-border)]',\n disabled\n ? 'pointer-events-none bg-gray-100 dark:bg-gray-800 outline-[var(--ui-border-muted)]'\n : 'bg-white dark:bg-gray-700',\n 'focus-within:outline-[var(--ui-focus-ring)] focus-within:outline-2 focus-within:-outline-offset-2',\n )}\n data-testid=\"quantity-stepper\"\n >\n {/* Decrement Button */}\n <button\n type=\"button\"\n disabled={isAtMin}\n onClick={handleDecrement}\n tabIndex={-1}\n aria-label=\"Decrease quantity\"\n className={buildClassName(\n 'flex items-center justify-center rounded-l-lg text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-white transition-colors shrink-0',\n BUTTON_SIZE_CLASS[size],\n isAtMin\n ? 'opacity-30 hover:bg-transparent cursor-not-allowed'\n : 'cursor-pointer hover:bg-gray-100/80 dark:hover:bg-gray-600/60',\n )}\n data-testid=\"stepper-decrement\"\n >\n <MinusIcon className={ICON_SIZE_CLASS[size]} />\n </button>\n\n {prefix && (\n <span className=\"pl-1 text-gray-400 dark:text-gray-400 select-none text-xs shrink-0\">\n {prefix}\n </span>\n )}\n\n {/* Number Input */}\n <input\n ref={ref}\n id={stepperId}\n type=\"number\"\n min={min}\n max={max}\n step={step}\n value={value === 0 ? '' : value}\n placeholder=\"0\"\n disabled={disabled}\n onFocus={(e) => {\n e.target.select()\n onFocus?.(e)\n }}\n onChange={handleInputChange}\n className={buildClassName(\n 'text-center font-semibold text-gray-900 dark:text-white bg-transparent focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',\n INPUT_TEXT_CLASS[size],\n )}\n data-testid=\"stepper-input\"\n {...restProps}\n />\n\n {suffix && (\n <span className=\"pr-1 text-gray-500 dark:text-gray-400 select-none text-xs shrink-0\">\n {suffix}\n </span>\n )}\n\n {/* Increment Button */}\n <button\n type=\"button\"\n disabled={isAtMax}\n onClick={handleIncrement}\n tabIndex={-1}\n aria-label=\"Increase quantity\"\n className={buildClassName(\n 'flex items-center justify-center rounded-r-lg text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-white transition-colors shrink-0',\n BUTTON_SIZE_CLASS[size],\n isAtMax\n ? 'opacity-30 hover:bg-transparent cursor-not-allowed'\n : 'cursor-pointer hover:bg-gray-100/80 dark:hover:bg-gray-600/60',\n )}\n data-testid=\"stepper-increment\"\n >\n <PlusIcon className={ICON_SIZE_CLASS[size]} />\n </button>\n </div>\n\n {/* Footer Row matching Input error / helper text */}\n {(showErrorMessage && error) || helperText ? (\n <div className=\"flex items-center justify-between gap-2 mt-0.5\">\n {showErrorMessage && error ? (\n <TextContent xsmall className=\"text-red-500 dark:text-red-400 font-medium\">\n {error}\n </TextContent>\n ) : helperText ? (\n <TextContent xsmall muted>\n {helperText}\n </TextContent>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n})\n\nQuantityStepper.displayName = 'QuantityStepper'\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;AAMA,MAAM,SAAS,GAAG,CAAC,EAAE,SAAS,EAA0B,MACtDA,GAAA,CAAA,KAAA,EAAA,EACE,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,SAAS,EAAE,SAAS,EAAA,aAAA,EACR,MAAM,EAAA,QAAA,EAElBA,GAAA,CAAA,MAAA,EAAA,EAAM,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,EAAA,CACnC,CACP;AAED,MAAM,QAAQ,GAAG,CAAC,EAAE,SAAS,EAA0B,MACrDC,cACE,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,SAAS,EAAE,SAAS,EAAA,aAAA,EACR,MAAM,EAAA,QAAA,EAAA,CAElBD,cAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,EACvCA,GAAA,CAAA,MAAA,EAAA,EAAM,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,CAAA,EAAA,CACnC,CACP;AAED,MAAM,oBAAoB,GAAwC;AAChE,IAAA,EAAE,EAAE,aAAa;AACjB,IAAA,EAAE,EAAE,cAAc;AAClB,IAAA,EAAE,EAAE,gBAAgB;CACrB;AAED,MAAM,iBAAiB,GAAwC;AAC7D,IAAA,EAAE,EAAE,cAAc;AAClB,IAAA,EAAE,EAAE,cAAc;AAClB,IAAA,EAAE,EAAE,aAAa;CAClB;AAED,MAAM,eAAe,GAAwC;AAC3D,IAAA,EAAE,EAAE,UAAU;AACd,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,UAAU;CACf;AAED,MAAM,gBAAgB,GAAwC;AAC5D,IAAA,EAAE,EAAE,cAAc;AAClB,IAAA,EAAE,EAAE,cAAc;AAClB,IAAA,EAAE,EAAE,gBAAgB;CACrB;AAEM,MAAM,eAAe,GAAG,UAAU,CAAyC,CAAC,KAAK,EAAE,GAAG,KAAI;IAC/F,MAAM,EACJ,KAAK,EACL,QAAQ,EACR,GAAG,GAAG,CAAC,EACP,GAAG,GAAG,KAAK,EACX,IAAI,GAAG,CAAC,EACR,KAAK,EACL,SAAS,EACT,UAAU,EACV,KAAK,EACL,gBAAgB,GAAG,IAAI,EACvB,IAAI,GAAG,IAAI,EACX,MAAM,EACN,MAAM,EACN,QAAQ,GAAG,KAAK,EAChB,SAAS,EACT,OAAO,EACP,EAAE,EAAE,QAAQ,EACZ,GAAG,SAAS,EACb,GAAG,KAAK;AAET,IAAA,MAAM,MAAM,GAAG,KAAK,EAAE;AACtB,IAAA,MAAM,SAAS,GAAG,QAAQ,IAAI,CAAA,QAAA,EAAW,MAAM,EAAE;AACjD,IAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAE/B,MAAM,eAAe,GAAG,MAAK;AAC3B,QAAA,IAAI,QAAQ;YAAE;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,QAAQ,CAAC,IAAI,CAAC;AAChB,IAAA,CAAC;IAED,MAAM,eAAe,GAAG,MAAK;AAC3B,QAAA,IAAI,QAAQ;YAAE;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,QAAQ,CAAC,IAAI,CAAC;AAChB,IAAA,CAAC;AAED,IAAA,MAAM,iBAAiB,GAAG,CAAC,CAAsC,KAAI;AACnE,QAAA,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK;AAC1B,QAAA,IAAI,GAAG,KAAK,EAAE,EAAE;YACd,QAAQ,CAAC,CAAC,CAAC;YACX;QACF;AACA,QAAA,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC;AAC9B,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;AAClB,YAAA,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;QAChD;AACF,IAAA,CAAC;AAED,IAAA,MAAM,OAAO,GAAG,QAAQ,IAAI,KAAK,IAAI,GAAG;AACxC,IAAA,MAAM,OAAO,GAAG,QAAQ,IAAI,KAAK,IAAI,GAAG;AAExC,IAAA,QACEC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,cAAc,CAAC,mCAAmC,EAAE,SAAS,CAAC,EAAA,QAAA,EAAA,CAE3E,KAAK,KACJA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yCAAyC,EAAA,QAAA,EAAA,CACtDD,GAAA,CAAC,KAAK,IAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,GAAG,+BAA+B,GAAG,EAAE,EAAA,QAAA,EAClF,KAAK,GACA,EACP,SAAS,IAAIA,GAAA,CAAC,WAAW,EAAA,EAAC,MAAM,EAAA,IAAA,EAAA,QAAA,EAAE,SAAS,EAAA,CAAe,CAAA,EAAA,CACvD,CACP,EAGDC,IAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,cAAc,CACvB,4EAA4E,EAC5E,qCAAqC,EACrC,oBAAoB,CAAC,IAAI,CAAC,EAC1B;AACE,sBAAE;sBACA,4BAA4B,EAChC;AACE,sBAAE;AACF,sBAAE,2BAA2B,EAC/B,mGAAmG,CACpG,iBACW,kBAAkB,EAAA,QAAA,EAAA,CAG9BD,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,EAAE,EAAA,YAAA,EACD,mBAAmB,EAC9B,SAAS,EAAE,cAAc,CACvB,qJAAqJ,EACrJ,iBAAiB,CAAC,IAAI,CAAC,EACvB;AACE,8BAAE;AACF,8BAAE,+DAA+D,CACpE,EAAA,aAAA,EACW,mBAAmB,YAE/BA,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAE,eAAe,CAAC,IAAI,CAAC,EAAA,CAAI,GACxC,EAER,MAAM,KACLA,cAAM,SAAS,EAAC,oEAAoE,EAAA,QAAA,EACjF,MAAM,GACF,CACR,EAGDA,GAAA,CAAA,OAAA,EAAA,EACE,GAAG,EAAE,GAAG,EACR,EAAE,EAAE,SAAS,EACb,IAAI,EAAC,QAAQ,EACb,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,EAC/B,WAAW,EAAC,GAAG,EACf,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,CAAC,CAAC,KAAI;AACb,4BAAA,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE;AACjB,4BAAA,OAAO,aAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAG,CAAC,CAAC;AACd,wBAAA,CAAC,EACD,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,cAAc,CACvB,gNAAgN,EAChN,gBAAgB,CAAC,IAAI,CAAC,CACvB,EAAA,aAAA,EACW,eAAe,EAAA,GACvB,SAAS,EAAA,CACb,EAED,MAAM,KACLA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,oEAAoE,YACjF,MAAM,EAAA,CACF,CACR,EAGDA,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,EAAE,EAAA,YAAA,EACD,mBAAmB,EAC9B,SAAS,EAAE,cAAc,CACvB,qJAAqJ,EACrJ,iBAAiB,CAAC,IAAI,CAAC,EACvB;AACE,8BAAE;AACF,8BAAE,+DAA+D,CACpE,iBACW,mBAAmB,EAAA,QAAA,EAE/BA,IAAC,QAAQ,EAAA,EAAC,SAAS,EAAE,eAAe,CAAC,IAAI,CAAC,EAAA,CAAI,EAAA,CACvC,IACL,EAGL,CAAC,gBAAgB,IAAI,KAAK,KAAK,UAAU,IACxCA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,gDAAgD,EAAA,QAAA,EAC5D,gBAAgB,IAAI,KAAK,IACxBA,GAAA,CAAC,WAAW,IAAC,MAAM,EAAA,IAAA,EAAC,SAAS,EAAC,4CAA4C,YACvE,KAAK,EAAA,CACM,IACZ,UAAU,IACZA,GAAA,CAAC,WAAW,EAAA,EAAC,MAAM,QAAC,KAAK,EAAA,IAAA,EAAA,QAAA,EACtB,UAAU,EAAA,CACC,IACZ,IAAI,EAAA,CACJ,IACJ,IAAI,CAAA,EAAA,CACJ;AAEV,CAAC;AAED,eAAe,CAAC,WAAW,GAAG,iBAAiB;;;;"}