@stackone/malachite 2.52.0 → 2.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterSearch.js","sources":["../../src/components/FilterSearch.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useId,\n useInsertionEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport CaretDownIcon from './CustomIcons/CaretDownIcon';\nimport CheckmarkIcon from './CustomIcons/CheckmarkIcon';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport SearchIcon from './CustomIcons/SearchIcon';\nimport Spinner from './Spinner';\nimport { CONTROL_TEXT_SIZE, CONTROL_TEXT_SIZE_CLASS, type ControlSize } from './controlTextSize';\nimport { type ControlWidth, controlWidthStyle } from './controlWidth';\nimport { DROPDOWN_TRIGGER_ATTR, getTriggerVisual } from './dropdownTriggerStyle';\nimport { pushEscapeLayer } from './escapeLayers';\nimport {\n type FilterSearchChange,\n type FilterSearchFilter,\n type FilterSearchItemRow,\n type FilterSearchSelection,\n type FilterSearchToggle,\n type FilterSearchUpdate,\n chipText,\n clearAll,\n deselectAll,\n filterRows,\n orderSelections,\n removeFilter,\n resolveMode,\n searchRows,\n selectAll,\n toggleValue,\n} from './filterSearchModel';\nimport { FILTER_SEARCH_CLASS, ensureFilterSearchStyles } from './filterSearchStyles';\nimport {\n MENU_MAX_HEIGHT_PX,\n MENU_SPECS,\n type MenuGeometry,\n measureMenuGeometry,\n} from './floatingMenuGeometry';\nimport { FOCUS_RING } from './focusRing';\nimport { usePopupLayer } from './overlayLayers';\nimport { useTopLayer } from './topLayer';\nimport { useLatestRef } from './useLatestRef';\n\nexport type FilterSearchSize = ControlSize;\n\nexport interface FilterSearchProps {\n filters: FilterSearchFilter[];\n /** Controlled: the bar always shows `value`, so a URL-backed selection needs no syncing. */\n value: FilterSearchSelection[];\n /** `changes` lists only the filters that moved; an empty `items` means that filter was removed. */\n onChange: (next: FilterSearchSelection[], changes: FilterSearchChange[]) => void;\n /** Called when the clear control empties the bar, after `onChange`. */\n onClear?: () => void;\n /** The filter whose values are open, or `null` on the filter list — for loading values lazily. */\n onActiveFilterChange?: (filter: string | null) => void;\n placeholder?: string;\n size?: FilterSearchSize;\n width?: ControlWidth;\n loading?: boolean;\n disabled?: boolean;\n clearable?: boolean;\n /** Chips past this count collapse into `+N`. */\n maxVisibleChips?: number;\n className?: string;\n style?: React.CSSProperties;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n}\n\nconst FIELD_SIZE_CLASSES: Record<FilterSearchSize, string> = {\n small: `min-h-[var(--malachite-control-height-small,28px)] gap-1 px-2.5 py-[2px] ${CONTROL_TEXT_SIZE_CLASS.small} rounded-[var(--malachite-radius-10,10px)]`,\n medium: `min-h-[var(--malachite-control-height-medium,32px)] gap-1 px-3 py-[3px] ${CONTROL_TEXT_SIZE_CLASS.medium} rounded-xl`,\n large: `min-h-[var(--malachite-control-height-large,42px)] gap-1.5 px-4 py-[6px] ${CONTROL_TEXT_SIZE_CLASS.large} rounded-[var(--malachite-radius-xxl,14px)]`,\n};\n\nconst CHIP_GAP: Record<FilterSearchSize, string> = {\n small: 'gap-1',\n medium: 'gap-1',\n large: 'gap-1.5',\n};\n\nconst CHIP_CLASSES = {\n resting:\n 'bg-[var(--malachite-tag-default-background,rgba(123,123,123,0.1))] text-[var(--malachite-text-primary,rgb(10,10,10))]',\n active: 'bg-[var(--malachite-accent-background,rgb(0,175,102))] text-[var(--malachite-card-background,rgb(255,255,255))]',\n};\n\nconst LOADING_ROWS = 5;\n\ntype Row =\n | { kind: 'filter'; filter: FilterSearchFilter }\n | { kind: 'toggle'; toggle: FilterSearchToggle }\n | { kind: 'item'; row: FilterSearchItemRow };\n\ninterface Chip {\n filter: string;\n text: string;\n}\n\ntype LabelMap = Map<string, { label: string; items: Map<string, string> }>;\n\nconst isEnabled = (row: Row | undefined) =>\n !!row && !(row.kind === 'item' && row.row.item.disabled);\n\nconst firstEnabledFrom = (rows: Row[], start: number): number => {\n for (let index = Math.max(start, 0); index < rows.length; index++) {\n if (isEnabled(rows[index])) return index;\n }\n return -1;\n};\n\nconst rowStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n width: '100%',\n flexShrink: 0,\n border: 'none',\n textAlign: 'left',\n borderRadius: 8,\n padding: '6px 10px',\n font: 'inherit',\n cursor: 'pointer',\n minWidth: 0,\n};\n\nconst pillStyle: React.CSSProperties = {\n borderRadius: 6,\n padding: '2px 6px',\n flexShrink: 0,\n whiteSpace: 'nowrap',\n};\n\nconst ellipsis: React.CSSProperties = {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n};\n\nconst trailing: React.CSSProperties = { ...ellipsis, marginLeft: 'auto', flexShrink: 1 };\n\nconst keepFocus = (event: React.MouseEvent) => event.preventDefault();\n\n// A chip's own buttons decide whether the menu opens; the field's mousedown must not.\nconst keepChipClick = (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n};\n\nconst RowContent: React.FC<{ row: Row; showFilter: boolean }> = ({ row, showFilter }) => {\n if (row.kind === 'filter') {\n return (\n <>\n <span className={FILTER_SEARCH_CLASS.pill} style={pillStyle}>\n {row.filter.label}\n </span>\n {row.filter.info && <span style={ellipsis}>{row.filter.info}</span>}\n {row.filter.example && (\n <span className={FILTER_SEARCH_CLASS.hint} style={trailing}>\n {row.filter.example}\n </span>\n )}\n </>\n );\n }\n\n if (row.kind === 'toggle') {\n return (\n <span style={{ color: 'var(--malachite-text-primary, rgb(10, 10, 10))' }}>\n {row.toggle === 'select' ? 'Select All' : 'Deselect All'}\n </span>\n );\n }\n\n const { item, filter, selected } = row.row;\n return (\n <>\n {showFilter && (\n <span className={FILTER_SEARCH_CLASS.pill} style={pillStyle}>\n {filter.label}\n </span>\n )}\n <span style={ellipsis}>{item.label}</span>\n {selected ? (\n <CheckmarkIcon\n size={16}\n style={{\n marginLeft: 'auto',\n flexShrink: 0,\n color: 'var(--malachite-accent-background, rgb(0, 175, 102))',\n }}\n />\n ) : (\n showFilter &&\n filter.info && (\n <span className={FILTER_SEARCH_CLASS.hint} style={trailing}>\n {filter.info}\n </span>\n )\n )}\n </>\n );\n};\n\nconst FilterSearch: React.FC<FilterSearchProps> = ({\n filters,\n value,\n onChange,\n onClear,\n onActiveFilterChange,\n placeholder = 'Search',\n size = 'medium',\n width,\n loading = false,\n disabled = false,\n clearable = false,\n maxVisibleChips = 4,\n className = '',\n style,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n}) => {\n const instanceId = useId();\n const listboxId = `${instanceId}-listbox`;\n const optionId = (index: number) => `${instanceId}-option-${index}`;\n\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [activeFilter, setActiveFilterState] = useState<string | null>(null);\n const [highlighted, setHighlighted] = useState(0);\n const [position, setPosition] = useState<MenuGeometry | null>(null);\n\n const fieldRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const popoverRef = useRef<HTMLDivElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const optionRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n useTopLayer(popoverRef, open);\n const popupIdentity = usePopupLayer('multiselect', open, popoverRef);\n\n // Labels outlive a reload of `filters`, so applied chips keep their names while it is in flight.\n const previousLabels = useRef<LabelMap>(new Map());\n const labels = useMemo(() => {\n const next: LabelMap = new Map(previousLabels.current);\n for (const filter of filters) {\n // Merged, not replaced: a filter can reload with its values still in flight.\n const known = next.get(filter.value)?.items ?? new Map<string, string>();\n next.set(filter.value, {\n label: filter.label,\n items: new Map([\n ...known,\n ...filter.items.map((item) => [item.value, item.label] as const),\n ]),\n });\n }\n return next;\n }, [filters]);\n useEffect(() => {\n previousLabels.current = labels;\n }, [labels]);\n\n const previousOrder = useRef<string[]>([]);\n const order = useMemo(\n () => orderSelections(value, previousOrder.current, activeFilter),\n [value, activeFilter],\n );\n useEffect(() => {\n previousOrder.current = order;\n }, [order]);\n\n const mode = resolveMode(activeFilter, query);\n const activeFilterDef = filters.find((filter) => filter.value === activeFilter);\n\n const activeFilterRef = useRef(activeFilter);\n // Through a ref so an inline callback does not re-bind the open menu's listeners every render.\n const onActiveFilterChangeRef = useLatestRef(onActiveFilterChange);\n const setActiveFilter = useCallback(\n (next: string | null) => {\n if (activeFilterRef.current === next) return;\n activeFilterRef.current = next;\n setActiveFilterState(next);\n onActiveFilterChangeRef.current?.(next);\n },\n [onActiveFilterChangeRef],\n );\n\n const rows = useMemo<Row[]>(() => {\n if (loading) return [];\n if (mode === 'filters') return filters.map((filter) => ({ kind: 'filter', filter }));\n const { toggle, items } =\n mode === 'items'\n ? filterRows(activeFilterDef, value, query)\n : searchRows(filters, value, query);\n return [\n ...(toggle ? [{ kind: 'toggle' as const, toggle }] : []),\n ...items.map((row) => ({ kind: 'item' as const, row })),\n ];\n }, [loading, mode, filters, activeFilterDef, value, query]);\n\n // In `order`, so a filter emptied while it is being edited keeps its place in the row.\n const chips = useMemo<Chip[]>(() => {\n const applied = new Map(value.map((selection) => [selection.filter, selection.items]));\n const chipFor = (filter: string): Chip[] => {\n const entry = labels.get(filter);\n const items = applied.get(filter);\n if (!items) {\n return filter === activeFilter ? [{ filter, text: entry?.label ?? filter }] : [];\n }\n if (!entry && loading) return [];\n const itemLabels = items.map((item) => entry?.items.get(item) ?? item);\n return [{ filter, text: chipText(entry?.label ?? filter, itemLabels) }];\n };\n const pendingIsNew = activeFilter !== null && !order.includes(activeFilter);\n return [...order, ...(pendingIsNew ? [activeFilter] : [])].flatMap(chipFor);\n }, [order, value, labels, loading, activeFilter]);\n\n const visibleChips = chips.slice(0, maxVisibleChips);\n const hiddenChipCount = chips.length - visibleChips.length;\n\n const emit = useCallback(\n ({ next, changes }: FilterSearchUpdate) => {\n if (changes.length > 0) onChange(next, changes);\n },\n [onChange],\n );\n\n const close = useCallback(() => {\n setOpen(false);\n setQuery('');\n setActiveFilter(null);\n setPosition(null);\n }, [setActiveFilter]);\n\n const openMenu = () => {\n if (disabled || open) return;\n setHighlighted(0);\n setOpen(true);\n };\n\n const updatePosition = useCallback(() => {\n const field = fieldRef.current;\n if (!field) return;\n setPosition(\n measureMenuGeometry(popoverRef.current, {\n triggerRect: field.getBoundingClientRect(),\n preset: 'standard',\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n }),\n );\n }, []);\n\n useEffect(() => {\n if (disabled && open) close();\n }, [disabled, open, close]);\n\n useEffect(() => {\n if (!open) return;\n const handleClickOutside = (event: MouseEvent) => {\n const path = event.composedPath();\n const field = fieldRef.current;\n const popover = popoverRef.current;\n if ((!field || !path.includes(field)) && (!popover || !path.includes(popover))) {\n close();\n }\n };\n let frame: number | null = null;\n const handleScrollOrResize = () => {\n if (frame !== null) return;\n frame = requestAnimationFrame(() => {\n frame = null;\n updatePosition();\n });\n };\n const popEscapeLayer = pushEscapeLayer(close);\n document.addEventListener('mousedown', handleClickOutside);\n window.addEventListener('scroll', handleScrollOrResize, true);\n window.addEventListener('resize', handleScrollOrResize);\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n window.removeEventListener('scroll', handleScrollOrResize, true);\n window.removeEventListener('resize', handleScrollOrResize);\n if (frame !== null) cancelAnimationFrame(frame);\n popEscapeLayer();\n };\n }, [open, close, updatePosition]);\n\n // Chips wrap onto a second line as they are added, which moves the menu's anchor.\n useLayoutEffect(() => {\n if (!open) return;\n updatePosition();\n if (typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => updatePosition());\n if (popoverRef.current) observer.observe(popoverRef.current);\n if (fieldRef.current) observer.observe(fieldRef.current);\n return () => observer.disconnect();\n }, [open, updatePosition]);\n\n // Every mode reuses one list element, so a new list would otherwise open at the old offset.\n // biome-ignore lint/correctness/useExhaustiveDependencies: the reset is keyed on what the list shows\n useLayoutEffect(() => {\n if (listRef.current) listRef.current.scrollTop = 0;\n }, [mode, activeFilter, query]);\n\n useInsertionEffect(() => {\n if (open) ensureFilterSearchStyles();\n }, [open]);\n\n const scrollToRow = (index: number) => {\n requestAnimationFrame(() => {\n const row = optionRefs.current[index];\n const list = listRef.current;\n if (!row || !list) return;\n const top = row.offsetTop;\n const bottom = top + row.offsetHeight;\n if (bottom > list.scrollTop + list.clientHeight) {\n list.scrollTop = bottom - list.clientHeight;\n } else if (top < list.scrollTop) {\n list.scrollTop = top;\n }\n });\n };\n\n const choose = (row: Row) => {\n if (row.kind === 'filter') {\n setActiveFilter(row.filter.value);\n setQuery('');\n setHighlighted(0);\n return;\n }\n\n if (row.kind === 'toggle') {\n const scope = mode === 'items' && activeFilterDef ? [activeFilterDef] : filters;\n emit(\n row.toggle === 'select'\n ? selectAll(scope, value, query)\n : deselectAll(scope, value, query),\n );\n setQuery('');\n setHighlighted(0);\n return;\n }\n\n const { item, filter } = row.row;\n if (item.disabled) return;\n const update = toggleValue(value, filter.value, item.value);\n emit(update);\n setQuery('');\n\n if (mode !== 'items') {\n setHighlighted(0);\n return;\n }\n // The query is cleared, so the list grows back: keep the cursor on the value just chosen.\n const { toggle, items } = filterRows(filter, update.next, '');\n const index = items.findIndex((candidate) => candidate.item.value === item.value);\n const nextIndex = index < 0 ? 0 : index + (toggle ? 1 : 0);\n setHighlighted(nextIndex);\n scrollToRow(nextIndex);\n };\n\n const moveHighlight = (direction: 1 | -1) => {\n if (rows.length === 0) return;\n let next = activeRow < 0 ? highlighted : activeRow;\n for (let step = 0; step < rows.length; step++) {\n next = (next + direction + rows.length) % rows.length;\n if (isEnabled(rows[next])) {\n setHighlighted(next);\n scrollToRow(next);\n return;\n }\n }\n };\n\n const removeChip = (filter: string) => {\n if (filter === activeFilter) setActiveFilter(null);\n emit(removeFilter(value, filter));\n };\n\n const editChip = (filter: string) => {\n if (disabled || loading) return;\n setActiveFilter(filter);\n setQuery('');\n setHighlighted(0);\n setOpen(true);\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n // Enter and the arrows belong to the input method while a composition is in progress;\n // Safari reports the committing Enter as keyCode 229 with `isComposing` already false.\n if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return;\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n event.preventDefault();\n if (!open) {\n openMenu();\n return;\n }\n moveHighlight(event.key === 'ArrowDown' ? 1 : -1);\n return;\n }\n case 'Enter': {\n event.preventDefault();\n if (!open) {\n openMenu();\n return;\n }\n const row = rows[activeRow];\n if (isEnabled(row)) choose(row as Row);\n return;\n }\n case 'Backspace': {\n if (query !== '') return;\n const pending =\n activeFilter !== null && !value.some((s) => s.filter === activeFilter);\n if (pending) {\n event.preventDefault();\n setActiveFilter(null);\n setHighlighted(0);\n return;\n }\n // The last chip on screen: one hidden while its labels load cannot be removed unseen.\n const shown = chips.filter((chip) => value.some((s) => s.filter === chip.filter));\n const last = shown[shown.length - 1];\n if (!last) return;\n event.preventDefault();\n removeChip(last.filter);\n return;\n }\n }\n };\n\n const handleClear = (event: React.MouseEvent) => {\n event.stopPropagation();\n emit(clearAll(value));\n setActiveFilter(null);\n setQuery('');\n onClear?.();\n };\n\n const backToFilters = () => {\n setActiveFilter(null);\n setQuery('');\n setHighlighted(0);\n };\n\n const showsClear = clearable && value.length > 0 && !disabled && !loading;\n // A disabled row cannot hold the cursor: it falls through to the next enabled one.\n const activeRow = open ? firstEnabledFrom(rows, highlighted) : -1;\n\n const triggerVisual = getTriggerVisual({ disabled, open });\n\n const emptyMessage = mode === 'filters' ? 'No filters available' : 'No matching values';\n\n const popoverStyle: React.CSSProperties = {\n position: 'fixed',\n top: position?.top ?? 0,\n left: position?.left ?? 0,\n width: position?.width,\n background: MENU_SPECS.standard.background,\n border: MENU_SPECS.standard.border,\n borderRadius: MENU_SPECS.standard.radius,\n boxShadow: MENU_SPECS.standard.shadow,\n padding: MENU_SPECS.standard.padding,\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n maxHeight: position?.maxHeight ?? MENU_MAX_HEIGHT_PX,\n fontSize: CONTROL_TEXT_SIZE[size],\n visibility: position ? 'visible' : 'hidden',\n opacity: position ? 1 : 0,\n };\n\n return (\n <>\n <div\n className={`relative min-w-0 ${className}`}\n style={{ ...controlWidthStyle(width), ...style }}\n >\n <div\n ref={fieldRef}\n {...{ [DROPDOWN_TRIGGER_ATTR]: '' }}\n data-open={open || undefined}\n // On the field, not the input: focus can move on to a chip's own buttons.\n onBlur={(event) => {\n const next = event.relatedTarget as Node | null;\n if (\n next &&\n (fieldRef.current?.contains(next) || popoverRef.current?.contains(next))\n ) {\n return;\n }\n close();\n }}\n onMouseDown={(event) => {\n if (disabled) return;\n if (event.target !== inputRef.current) event.preventDefault();\n inputRef.current?.focus();\n openMenu();\n }}\n style={{\n transition: 'border-color 0.15s ease, box-shadow 0.15s ease',\n ...triggerVisual,\n }}\n className={`w-full min-w-0 flex items-center border border-solid font-normal ${FIELD_SIZE_CLASSES[size]} ${disabled ? 'cursor-not-allowed' : 'cursor-text'}`}\n >\n <SearchIcon\n size={13}\n className=\"shrink-0 mr-1\"\n style={{ color: 'var(--malachite-text-placeholder, rgb(187, 187, 187))' }}\n />\n {/* Chips wrap here, never into the icon or caret; the reserve keeps the clear button off them. */}\n <div\n className={`flex flex-1 min-w-0 flex-wrap items-center ${CHIP_GAP[size]} ${showsClear ? 'pr-[18px]' : ''}`}\n >\n {visibleChips.map((chip) => {\n const active = open && chip.filter === activeFilter;\n return (\n <span\n key={chip.filter}\n onMouseDown={keepChipClick}\n className={`inline-flex items-center gap-1 max-w-[max(60px,calc(100%-64px))] min-w-0 h-[22px] pl-1.5 pr-1 rounded-md text-xs ${active ? CHIP_CLASSES.active : CHIP_CLASSES.resting}`}\n >\n <button\n type=\"button\"\n disabled={disabled}\n title={chip.text}\n aria-label={`Edit filter ${chip.text}`}\n onClick={() => editChip(chip.filter)}\n className={`truncate min-w-0 bg-transparent border-none p-0 text-[length:inherit] text-current ${disabled || loading ? 'cursor-default' : 'cursor-pointer'} ${FOCUS_RING}`}\n >\n {chip.text}\n </button>\n {!disabled && (\n <button\n type=\"button\"\n aria-label={`Remove filter ${chip.text}`}\n onClick={(event) => {\n event.stopPropagation();\n removeChip(chip.filter);\n // The button unmounts with its chip; keep focus in the field.\n inputRef.current?.focus();\n }}\n className={`flex items-center justify-center shrink-0 bg-transparent border-none p-0 text-current opacity-70 hover:opacity-100 cursor-pointer ${FOCUS_RING}`}\n >\n <DismissIcon size={10} />\n </button>\n )}\n </span>\n );\n })}\n {hiddenChipCount > 0 && (\n <span\n className={`inline-flex items-center h-[22px] px-1.5 rounded-md text-xs ${CHIP_CLASSES.resting}`}\n >\n +{hiddenChipCount}\n </span>\n )}\n <input\n ref={inputRef}\n id={id}\n type=\"text\"\n role=\"combobox\"\n value={query}\n disabled={disabled}\n placeholder={chips.length === 0 ? placeholder : ''}\n autoComplete=\"off\"\n spellCheck={false}\n aria-label={ariaLabelledBy ? undefined : (ariaLabel ?? placeholder)}\n aria-labelledby={ariaLabelledBy}\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-expanded={open}\n aria-controls={open ? listboxId : undefined}\n aria-activedescendant={activeRow >= 0 ? optionId(activeRow) : undefined}\n aria-busy={loading || undefined}\n onChange={(event) => {\n setQuery(event.target.value);\n setHighlighted(0);\n openMenu();\n }}\n onKeyDown={handleKeyDown}\n className=\"flex-1 min-w-[60px] border-none outline-none bg-transparent p-0 text-[length:inherit] text-[var(--malachite-text-primary,rgb(10,10,10))] placeholder:text-[var(--malachite-text-placeholder,rgb(187,187,187))] disabled:cursor-not-allowed\"\n />\n </div>\n <span className=\"flex items-center justify-center shrink-0 size-[14px] ml-1\">\n {loading ? (\n <Spinner size=\"xxxsmall\" />\n ) : (\n <CaretDownIcon\n size={13}\n style={{\n color: open\n ? 'var(--malachite-text-primary, rgb(10, 10, 10))'\n : 'var(--malachite-text-placeholder, rgb(187, 187, 187))',\n transition: 'transform 0.2s ease, color 0.2s ease',\n transform: open ? 'rotate(180deg)' : 'rotate(0deg)',\n }}\n />\n )}\n </span>\n </div>\n {showsClear && (\n <button\n type=\"button\"\n aria-label=\"Clear filters\"\n onMouseDown={keepFocus}\n onClick={handleClear}\n className={`absolute top-0 bottom-0 right-[30px] flex items-center justify-center px-[2px] bg-transparent border-none text-[var(--malachite-text-placeholder)] hover:text-[var(--malachite-text-primary)] cursor-pointer ${FOCUS_RING}`}\n >\n <DismissIcon size={10} />\n </button>\n )}\n </div>\n {open &&\n createPortal(\n <div\n ref={popoverRef}\n {...popupIdentity}\n style={popoverStyle}\n onMouseDown={keepFocus}\n >\n <div\n style={{\n padding: '4px 10px 2px',\n color: 'var(--malachite-text-placeholder, rgb(187, 187, 187))',\n display: 'flex',\n gap: 4,\n minWidth: 0,\n }}\n >\n {mode === 'items' ? (\n <>\n <button\n type=\"button\"\n tabIndex={-1}\n onClick={backToFilters}\n className={FILTER_SEARCH_CLASS.crumb}\n style={{\n background: 'none',\n border: 'none',\n padding: 0,\n font: 'inherit',\n cursor: 'pointer',\n }}\n >\n Filters\n </button>\n <span style={ellipsis}>\n {`> ${activeFilterDef?.label ?? labels.get(activeFilter ?? '')?.label ?? ''}`}\n </span>\n </>\n ) : (\n 'Filters'\n )}\n </div>\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-multiselectable={mode !== 'filters'}\n aria-label={ariaLabel ?? placeholder}\n aria-busy={loading || undefined}\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n overflowY: 'auto',\n overscrollBehavior: 'contain',\n minHeight: 0,\n flex: 1,\n scrollbarWidth: 'thin',\n }}\n >\n {loading &&\n Array.from({ length: LOADING_ROWS }, (_, index) => (\n <div\n key={index}\n role=\"presentation\"\n className={FILTER_SEARCH_CLASS.loading}\n style={{\n height: 24,\n margin: '4px 10px',\n borderRadius: 6,\n background:\n 'var(--malachite-tag-default-background, rgba(123, 123, 123, 0.1))',\n }}\n />\n ))}\n {!loading && rows.length === 0 && (\n <div\n role=\"presentation\"\n style={{\n padding: '6px 10px',\n color: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n }}\n >\n {emptyMessage}\n </div>\n )}\n {rows.map((row, index) => {\n const key =\n row.kind === 'filter'\n ? `filter:${row.filter.value}`\n : row.kind === 'toggle'\n ? 'toggle'\n : `item:${row.row.filter.value}:${row.row.item.value}`;\n const itemDisabled = row.kind === 'item' && !!row.row.item.disabled;\n return (\n <button\n key={key}\n id={optionId(index)}\n ref={(element) => {\n optionRefs.current[index] = element;\n }}\n type=\"button\"\n tabIndex={-1}\n role=\"option\"\n aria-selected={\n row.kind === 'item' ? row.row.selected : false\n }\n aria-disabled={itemDisabled || undefined}\n data-highlighted={index === activeRow}\n data-disabled={itemDisabled}\n className={FILTER_SEARCH_CLASS.row}\n // Exception to \"no JS for styling\": the highlight IS the\n // keyboard cursor, so a bare :hover would light a second row.\n onMouseEnter={() => {\n if (!itemDisabled) setHighlighted(index);\n }}\n onClick={() => choose(row)}\n style={rowStyle}\n >\n <RowContent row={row} showFilter={mode === 'search'} />\n </button>\n );\n })}\n </div>\n </div>,\n document.body,\n )}\n </>\n );\n};\n\nexport default FilterSearch;\nexport { FilterSearch };\nexport type {\n FilterSearchChange,\n FilterSearchFilter,\n FilterSearchItem,\n FilterSearchSelection,\n} from './filterSearchModel';\n"],"names":["FIELD_SIZE_CLASSES","CONTROL_TEXT_SIZE_CLASS","CHIP_GAP","CHIP_CLASSES","LOADING_ROWS","isEnabled","row","firstEnabledFrom","rows","start","index","rowStyle","pillStyle","ellipsis","trailing","keepFocus","event","keepChipClick","RowContent","showFilter","jsxs","Fragment","jsx","FILTER_SEARCH_CLASS","item","filter","selected","CheckmarkIcon","FilterSearch","filters","value","onChange","onClear","onActiveFilterChange","placeholder","size","width","loading","disabled","clearable","maxVisibleChips","className","style","id","ariaLabel","ariaLabelledBy","instanceId","useId","listboxId","optionId","open","setOpen","useState","query","setQuery","activeFilter","setActiveFilterState","highlighted","setHighlighted","position","setPosition","fieldRef","useRef","inputRef","popoverRef","listRef","optionRefs","useTopLayer","popupIdentity","usePopupLayer","previousLabels","labels","useMemo","next","known","_a","useEffect","previousOrder","order","orderSelections","mode","resolveMode","activeFilterDef","activeFilterRef","onActiveFilterChangeRef","useLatestRef","setActiveFilter","useCallback","toggle","items","filterRows","searchRows","chips","applied","selection","chipFor","entry","itemLabels","chipText","pendingIsNew","visibleChips","hiddenChipCount","emit","changes","close","openMenu","updatePosition","field","measureMenuGeometry","handleClickOutside","path","popover","frame","handleScrollOrResize","popEscapeLayer","pushEscapeLayer","useLayoutEffect","observer","useInsertionEffect","ensureFilterSearchStyles","scrollToRow","list","top","bottom","choose","scope","selectAll","deselectAll","update","toggleValue","candidate","nextIndex","moveHighlight","direction","activeRow","step","removeChip","removeFilter","editChip","handleKeyDown","s","shown","chip","last","handleClear","clearAll","backToFilters","showsClear","triggerVisual","getTriggerVisual","emptyMessage","popoverStyle","MENU_SPECS","MENU_MAX_HEIGHT_PX","CONTROL_TEXT_SIZE","controlWidthStyle","DROPDOWN_TRIGGER_ATTR","_b","SearchIcon","active","FOCUS_RING","DismissIcon","Spinner","CaretDownIcon","createPortal","_","key","itemDisabled","element"],"mappings":"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"}