@spear-ai/spectral 1.22.4 → 1.22.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Accordion.d.ts.map +1 -1
- package/dist/Accordion.js +1 -1
- package/dist/Accordion.js.map +1 -1
- package/dist/Alert/AlertBase.d.ts.map +1 -1
- package/dist/Alert/AlertBase.js +2 -3
- package/dist/Alert/AlertBase.js.map +1 -1
- package/dist/Alert.js.map +1 -1
- package/dist/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog.js +8 -8
- package/dist/AlertDialog.js.map +1 -1
- package/dist/Avatar.js +4 -4
- package/dist/Avatar.js.map +1 -1
- package/dist/Badge.d.ts.map +1 -1
- package/dist/Badge.js.map +1 -1
- package/dist/Button.d.ts +2 -2
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +6 -9
- package/dist/Button.js.map +1 -1
- package/dist/ButtonGroup/ButtonGroupButton.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroupButton.js +1 -2
- package/dist/ButtonGroup/ButtonGroupButton.js.map +1 -1
- package/dist/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup.js +1 -1
- package/dist/ButtonGroup.js.map +1 -1
- package/dist/ButtonIcon.js.map +1 -1
- package/dist/Checkbox/CheckboxBase.js +1 -1
- package/dist/Checkbox/CheckboxBase.js.map +1 -1
- package/dist/Checkbox.js +1 -1
- package/dist/Checkbox.js.map +1 -1
- package/dist/Combobox.js.map +1 -1
- package/dist/ControlGroup/ControlGroupSelect.js.map +1 -1
- package/dist/ControlGroup.d.ts.map +1 -1
- package/dist/ControlGroup.js +1 -1
- package/dist/ControlGroup.js.map +1 -1
- package/dist/DataCard/Card.d.ts.map +1 -1
- package/dist/DataCard/Card.js.map +1 -1
- package/dist/DataCard.d.ts +1 -1
- package/dist/DataCard.js +1 -1
- package/dist/DataCard.js.map +1 -1
- package/dist/DateTimePicker/Calendar.js.map +1 -1
- package/dist/DateTimePicker/DateTimeDisplayInput.js.map +1 -1
- package/dist/DateTimePicker/TimePeriodSelect.js +1 -1
- package/dist/DateTimePicker/TimePeriodSelect.js.map +1 -1
- package/dist/DateTimePicker/TimePicker.js.map +1 -1
- package/dist/DateTimePicker.d.ts +1 -1
- package/dist/DateTimePicker.js.map +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +3 -3
- package/dist/Dialog.js.map +1 -1
- package/dist/Drawer.d.ts.map +1 -1
- package/dist/Drawer.js.map +1 -1
- package/dist/DropdownMenu.js.map +1 -1
- package/dist/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard.js.map +1 -1
- package/dist/Icons/AdjustmentsIcon.d.ts.map +1 -1
- package/dist/Icons/AdjustmentsIcon.js +11 -20
- package/dist/Icons/AdjustmentsIcon.js.map +1 -1
- package/dist/Icons/AnalyzeIcon.d.ts.map +1 -1
- package/dist/Icons/AnalyzeIcon.js +4 -9
- package/dist/Icons/AnalyzeIcon.js.map +1 -1
- package/dist/Icons/AnnotationsIcon.d.ts +2 -17
- package/dist/Icons/AnnotationsIcon.js +2 -25
- package/dist/Icons/ApprovedIcon.d.ts.map +1 -1
- package/dist/Icons/ApprovedIcon.js +4 -6
- package/dist/Icons/ApprovedIcon.js.map +1 -1
- package/dist/Icons/ArrowDownIcon.d.ts.map +1 -1
- package/dist/Icons/ArrowDownIcon.js +24 -11
- package/dist/Icons/ArrowDownIcon.js.map +1 -1
- package/dist/Icons/ArrowUpIcon.d.ts.map +1 -1
- package/dist/Icons/ArrowUpIcon.js +24 -11
- package/dist/Icons/ArrowUpIcon.js.map +1 -1
- package/dist/Icons/BoxToolIcon.d.ts.map +1 -1
- package/dist/Icons/BoxToolIcon.js +2 -2
- package/dist/Icons/BoxToolIcon.js.map +1 -1
- package/dist/Icons/{PanelIconOpen.d.ts → BuoyIcon.d.ts} +4 -4
- package/dist/Icons/BuoyIcon.d.ts.map +1 -0
- package/dist/Icons/BuoyIcon.js +40 -0
- package/dist/Icons/BuoyIcon.js.map +1 -0
- package/dist/Icons/CalendarIcon.d.ts.map +1 -1
- package/dist/Icons/CalendarIcon.js +5 -9
- package/dist/Icons/CalendarIcon.js.map +1 -1
- package/dist/Icons/CheckCircleIcon.d.ts.map +1 -1
- package/dist/Icons/CheckCircleIcon.js +13 -15
- package/dist/Icons/CheckCircleIcon.js.map +1 -1
- package/dist/Icons/CheckSquareIcon.d.ts.map +1 -1
- package/dist/Icons/CheckSquareIcon.js +25 -17
- package/dist/Icons/CheckSquareIcon.js.map +1 -1
- package/dist/Icons/CheckmarkIcon.d.ts +0 -1
- package/dist/Icons/CheckmarkIcon.d.ts.map +1 -1
- package/dist/Icons/CheckmarkIcon.js +11 -14
- package/dist/Icons/CheckmarkIcon.js.map +1 -1
- package/dist/Icons/ChevronDownIcon.d.ts.map +1 -1
- package/dist/Icons/ChevronDownIcon.js +10 -13
- package/dist/Icons/ChevronDownIcon.js.map +1 -1
- package/dist/Icons/ChevronUpIcon.d.ts.map +1 -1
- package/dist/Icons/ChevronUpIcon.js +10 -13
- package/dist/Icons/ChevronUpIcon.js.map +1 -1
- package/dist/Icons/{PanelIconClose.d.ts → CircleDotIcon.d.ts} +4 -4
- package/dist/Icons/CircleDotIcon.d.ts.map +1 -0
- package/dist/Icons/CircleDotIcon.js +31 -0
- package/dist/Icons/CircleDotIcon.js.map +1 -0
- package/dist/Icons/ClockIcon.d.ts.map +1 -1
- package/dist/Icons/ClockIcon.js +2 -4
- package/dist/Icons/ClockIcon.js.map +1 -1
- package/dist/Icons/CloseCircleIcon.d.ts.map +1 -1
- package/dist/Icons/CloseCircleIcon.js +19 -12
- package/dist/Icons/CloseCircleIcon.js.map +1 -1
- package/dist/Icons/CloseIcon.d.ts.map +1 -1
- package/dist/Icons/CloseIcon.js +13 -7
- package/dist/Icons/CloseIcon.js.map +1 -1
- package/dist/Icons/Crosshairs2Icon.d.ts.map +1 -1
- package/dist/Icons/Crosshairs2Icon.js +2 -7
- package/dist/Icons/Crosshairs2Icon.js.map +1 -1
- package/dist/Icons/CrosshairsIcon.d.ts.map +1 -1
- package/dist/Icons/CrosshairsIcon.js +2 -3
- package/dist/Icons/CrosshairsIcon.js.map +1 -1
- package/dist/Icons/DashboardIcon.d.ts.map +1 -1
- package/dist/Icons/DashboardIcon.js +2 -5
- package/dist/Icons/DashboardIcon.js.map +1 -1
- package/dist/Icons/DatabaseIcon.d.ts.map +1 -1
- package/dist/Icons/DatabaseIcon.js +2 -5
- package/dist/Icons/DatabaseIcon.js.map +1 -1
- package/dist/Icons/DeleteIcon.d.ts.map +1 -1
- package/dist/Icons/DeleteIcon.js +5 -8
- package/dist/Icons/DeleteIcon.js.map +1 -1
- package/dist/Icons/DotIcon.d.ts +18 -0
- package/dist/Icons/DotIcon.d.ts.map +1 -0
- package/dist/Icons/DotIcon.js +24 -0
- package/dist/Icons/DotIcon.js.map +1 -0
- package/dist/Icons/DurationIcon.d.ts.map +1 -1
- package/dist/Icons/DurationIcon.js +2 -8
- package/dist/Icons/DurationIcon.js.map +1 -1
- package/dist/Icons/EditIcon.d.ts.map +1 -1
- package/dist/Icons/EditIcon.js +7 -14
- package/dist/Icons/EditIcon.js.map +1 -1
- package/dist/Icons/EmailIcon.d.ts.map +1 -1
- package/dist/Icons/EmailIcon.js +13 -15
- package/dist/Icons/EmailIcon.js.map +1 -1
- package/dist/Icons/EraserIcon.d.ts.map +1 -1
- package/dist/Icons/EraserIcon.js +7 -11
- package/dist/Icons/EraserIcon.js.map +1 -1
- package/dist/Icons/ErrorIcon.d.ts.map +1 -1
- package/dist/Icons/ErrorIcon.js +18 -12
- package/dist/Icons/ErrorIcon.js.map +1 -1
- package/dist/Icons/EyeClosedIcon.d.ts.map +1 -1
- package/dist/Icons/EyeClosedIcon.js +30 -14
- package/dist/Icons/EyeClosedIcon.js.map +1 -1
- package/dist/Icons/EyeClosedIcon2.d.ts.map +1 -1
- package/dist/Icons/EyeClosedIcon2.js +24 -12
- package/dist/Icons/EyeClosedIcon2.js.map +1 -1
- package/dist/Icons/EyeOpenIcon.d.ts.map +1 -1
- package/dist/Icons/EyeOpenIcon.js +12 -10
- package/dist/Icons/EyeOpenIcon.js.map +1 -1
- package/dist/Icons/FileDownloadIcon.d.ts.map +1 -1
- package/dist/Icons/FileDownloadIcon.js +2 -6
- package/dist/Icons/FileDownloadIcon.js.map +1 -1
- package/dist/Icons/GeofenceIcon.d.ts +18 -0
- package/dist/Icons/GeofenceIcon.d.ts.map +1 -0
- package/dist/Icons/GeofenceIcon.js +38 -0
- package/dist/Icons/GeofenceIcon.js.map +1 -0
- package/dist/Icons/GlobeIcon.d.ts +18 -0
- package/dist/Icons/GlobeIcon.d.ts.map +1 -0
- package/dist/Icons/GlobeIcon.js +52 -0
- package/dist/Icons/GlobeIcon.js.map +1 -0
- package/dist/Icons/GoToFirstIcon.d.ts.map +1 -1
- package/dist/Icons/GoToFirstIcon.js +2 -4
- package/dist/Icons/GoToFirstIcon.js.map +1 -1
- package/dist/Icons/GoToLastIcon.d.ts.map +1 -1
- package/dist/Icons/GoToLastIcon.js +2 -4
- package/dist/Icons/GoToLastIcon.js.map +1 -1
- package/dist/Icons/GpsIcon.d.ts +18 -0
- package/dist/Icons/GpsIcon.d.ts.map +1 -0
- package/dist/Icons/GpsIcon.js +31 -0
- package/dist/Icons/GpsIcon.js.map +1 -0
- package/dist/Icons/HarmonicCursorsIcon.d.ts.map +1 -1
- package/dist/Icons/HarmonicCursorsIcon.js +2 -2
- package/dist/Icons/HarmonicCursorsIcon.js.map +1 -1
- package/dist/Icons/IconBase.d.ts +11 -8
- package/dist/Icons/IconBase.d.ts.map +1 -1
- package/dist/Icons/IconBase.js +3 -2
- package/dist/Icons/IconBase.js.map +1 -1
- package/dist/Icons/InfoIcon.d.ts.map +1 -1
- package/dist/Icons/InfoIcon.js +33 -26
- package/dist/Icons/InfoIcon.js.map +1 -1
- package/dist/Icons/IterationArrowIcon.d.ts.map +1 -1
- package/dist/Icons/IterationArrowIcon.js +2 -5
- package/dist/Icons/IterationArrowIcon.js.map +1 -1
- package/dist/Icons/KeyIcon.d.ts +18 -0
- package/dist/Icons/KeyIcon.d.ts.map +1 -0
- package/dist/Icons/KeyIcon.js +46 -0
- package/dist/Icons/KeyIcon.js.map +1 -0
- package/dist/Icons/KeyboardIcon.d.ts.map +1 -1
- package/dist/Icons/KeyboardIcon.js +4 -4
- package/dist/Icons/KeyboardIcon.js.map +1 -1
- package/dist/Icons/LabelIcon.d.ts.map +1 -1
- package/dist/Icons/LabelIcon.js +2 -3
- package/dist/Icons/LabelIcon.js.map +1 -1
- package/dist/Icons/LassoIcon.d.ts.map +1 -1
- package/dist/Icons/LassoIcon.js +5 -8
- package/dist/Icons/LassoIcon.js.map +1 -1
- package/dist/Icons/LineDashedIcon.d.ts +18 -0
- package/dist/Icons/LineDashedIcon.d.ts.map +1 -0
- package/dist/Icons/LineDashedIcon.js +50 -0
- package/dist/Icons/LineDashedIcon.js.map +1 -0
- package/dist/Icons/LineToolIcon.d.ts.map +1 -1
- package/dist/Icons/LineToolIcon.js +11 -14
- package/dist/Icons/LineToolIcon.js.map +1 -1
- package/dist/Icons/LinkIcon.d.ts.map +1 -1
- package/dist/Icons/LinkIcon.js +5 -8
- package/dist/Icons/LinkIcon.js.map +1 -1
- package/dist/Icons/LiveViewIcon.d.ts.map +1 -1
- package/dist/Icons/LiveViewIcon.js +2 -7
- package/dist/Icons/LiveViewIcon.js.map +1 -1
- package/dist/Icons/LoaderIcon.d.ts.map +1 -1
- package/dist/Icons/LoaderIcon.js +5 -7
- package/dist/Icons/LoaderIcon.js.map +1 -1
- package/dist/Icons/LocationIcon.d.ts.map +1 -1
- package/dist/Icons/LocationIcon.js +2 -4
- package/dist/Icons/LocationIcon.js.map +1 -1
- package/dist/Icons/LockIcon.d.ts.map +1 -1
- package/dist/Icons/LockIcon.js +2 -3
- package/dist/Icons/LockIcon.js.map +1 -1
- package/dist/Icons/LogoutIcon.d.ts.map +1 -1
- package/dist/Icons/LogoutIcon.js +3 -4
- package/dist/Icons/LogoutIcon.js.map +1 -1
- package/dist/Icons/MapIcon.d.ts +18 -0
- package/dist/Icons/MapIcon.d.ts.map +1 -0
- package/dist/Icons/MapIcon.js +40 -0
- package/dist/Icons/MapIcon.js.map +1 -0
- package/dist/Icons/MapPinIcon.d.ts +18 -0
- package/dist/Icons/MapPinIcon.d.ts.map +1 -0
- package/dist/Icons/MapPinIcon.js +31 -0
- package/dist/Icons/MapPinIcon.js.map +1 -0
- package/dist/Icons/MaximizeIcon.d.ts.map +1 -1
- package/dist/Icons/MaximizeIcon.js +2 -6
- package/dist/Icons/MaximizeIcon.js.map +1 -1
- package/dist/Icons/MeasureIcon.d.ts.map +1 -1
- package/dist/Icons/MeasureIcon.js +2 -11
- package/dist/Icons/MeasureIcon.js.map +1 -1
- package/dist/Icons/MenuDotsIcon.d.ts.map +1 -1
- package/dist/Icons/MenuDotsIcon.js +2 -5
- package/dist/Icons/MenuDotsIcon.js.map +1 -1
- package/dist/Icons/MenuIcon.d.ts.map +1 -1
- package/dist/Icons/MenuIcon.js +5 -8
- package/dist/Icons/MenuIcon.js.map +1 -1
- package/dist/Icons/MessagesIcon.d.ts.map +1 -1
- package/dist/Icons/MessagesIcon.js +5 -8
- package/dist/Icons/MessagesIcon.js.map +1 -1
- package/dist/Icons/MetadataIcon.d.ts.map +1 -1
- package/dist/Icons/MetadataIcon.js +2 -3
- package/dist/Icons/MetadataIcon.js.map +1 -1
- package/dist/Icons/MinimizeIcon.d.ts.map +1 -1
- package/dist/Icons/MinimizeIcon.js +2 -6
- package/dist/Icons/MinimizeIcon.js.map +1 -1
- package/dist/Icons/MinusIcon.d.ts.map +1 -1
- package/dist/Icons/MinusIcon.js +8 -7
- package/dist/Icons/MinusIcon.js.map +1 -1
- package/dist/Icons/OntologyIcon.d.ts.map +1 -1
- package/dist/Icons/OntologyIcon.js +8 -19
- package/dist/Icons/OntologyIcon.js.map +1 -1
- package/dist/Icons/PanelCloseIcon.d.ts +18 -0
- package/dist/Icons/PanelCloseIcon.d.ts.map +1 -0
- package/dist/Icons/PanelCloseIcon.js +40 -0
- package/dist/Icons/PanelCloseIcon.js.map +1 -0
- package/dist/Icons/PanelOpenIcon.d.ts +18 -0
- package/dist/Icons/PanelOpenIcon.d.ts.map +1 -0
- package/dist/Icons/PanelOpenIcon.js +40 -0
- package/dist/Icons/PanelOpenIcon.js.map +1 -0
- package/dist/Icons/PaperclipIcon.d.ts +18 -0
- package/dist/Icons/PaperclipIcon.d.ts.map +1 -0
- package/dist/Icons/PaperclipIcon.js +26 -0
- package/dist/Icons/PaperclipIcon.js.map +1 -0
- package/dist/Icons/PathIcon.d.ts +18 -0
- package/dist/Icons/PathIcon.d.ts.map +1 -0
- package/dist/Icons/PathIcon.js +86 -0
- package/dist/Icons/PathIcon.js.map +1 -0
- package/dist/Icons/PauseIcon.d.ts.map +1 -1
- package/dist/Icons/PauseIcon.js +4 -6
- package/dist/Icons/PauseIcon.js.map +1 -1
- package/dist/Icons/PdfIcon.d.ts.map +1 -1
- package/dist/Icons/PdfIcon.js +3 -8
- package/dist/Icons/PdfIcon.js.map +1 -1
- package/dist/Icons/PinIcon.d.ts +18 -0
- package/dist/Icons/PinIcon.d.ts.map +1 -0
- package/dist/Icons/PinIcon.js +40 -0
- package/dist/Icons/PinIcon.js.map +1 -0
- package/dist/Icons/PlayIcon.d.ts.map +1 -1
- package/dist/Icons/PlayIcon.js +3 -5
- package/dist/Icons/PlayIcon.js.map +1 -1
- package/dist/Icons/PlusIcon.d.ts.map +1 -1
- package/dist/Icons/PlusIcon.js +5 -6
- package/dist/Icons/PlusIcon.js.map +1 -1
- package/dist/Icons/PolygonIcon.d.ts +0 -1
- package/dist/Icons/PolygonIcon.d.ts.map +1 -1
- package/dist/Icons/PolygonIcon.js +28 -15
- package/dist/Icons/PolygonIcon.js.map +1 -1
- package/dist/Icons/PrinterIcon.d.ts.map +1 -1
- package/dist/Icons/PrinterIcon.js +3 -4
- package/dist/Icons/PrinterIcon.js.map +1 -1
- package/dist/Icons/ProgressArrowIcon.d.ts.map +1 -1
- package/dist/Icons/ProgressArrowIcon.js +20 -14
- package/dist/Icons/ProgressArrowIcon.js.map +1 -1
- package/dist/Icons/ProgressCheckIcon.d.ts.map +1 -1
- package/dist/Icons/ProgressCheckIcon.js +5 -11
- package/dist/Icons/ProgressCheckIcon.js.map +1 -1
- package/dist/Icons/ResetIcon.d.ts.map +1 -1
- package/dist/Icons/ResetIcon.js +2 -2
- package/dist/Icons/ResetIcon.js.map +1 -1
- package/dist/Icons/ReviewedIcon.d.ts.map +1 -1
- package/dist/Icons/ReviewedIcon.js +2 -5
- package/dist/Icons/ReviewedIcon.js.map +1 -1
- package/dist/Icons/Route2Icon.d.ts +18 -0
- package/dist/Icons/Route2Icon.d.ts.map +1 -0
- package/dist/Icons/Route2Icon.js +40 -0
- package/dist/Icons/Route2Icon.js.map +1 -0
- package/dist/Icons/Route3Icon.d.ts +18 -0
- package/dist/Icons/Route3Icon.d.ts.map +1 -0
- package/dist/Icons/Route3Icon.js +40 -0
- package/dist/Icons/Route3Icon.js.map +1 -0
- package/dist/Icons/RouteIcon.d.ts +18 -0
- package/dist/Icons/RouteIcon.d.ts.map +1 -0
- package/dist/Icons/RouteIcon.js +40 -0
- package/dist/Icons/RouteIcon.js.map +1 -0
- package/dist/Icons/SaveIcon.d.ts +18 -0
- package/dist/Icons/SaveIcon.d.ts.map +1 -0
- package/dist/Icons/SaveIcon.js +26 -0
- package/dist/Icons/SaveIcon.js.map +1 -0
- package/dist/Icons/ScissorsIcon.d.ts.map +1 -1
- package/dist/Icons/ScissorsIcon.js +6 -6
- package/dist/Icons/ScissorsIcon.js.map +1 -1
- package/dist/Icons/SearchIcon.d.ts.map +1 -1
- package/dist/Icons/SearchIcon.js +4 -6
- package/dist/Icons/SearchIcon.js.map +1 -1
- package/dist/Icons/SettingsIcon.d.ts.map +1 -1
- package/dist/Icons/SettingsIcon.js +3 -5
- package/dist/Icons/SettingsIcon.js.map +1 -1
- package/dist/Icons/SortAscendingIcon.d.ts.map +1 -1
- package/dist/Icons/SortAscendingIcon.js +7 -12
- package/dist/Icons/SortAscendingIcon.js.map +1 -1
- package/dist/Icons/SortAtoZIcon.d.ts.map +1 -1
- package/dist/Icons/SortAtoZIcon.js +2 -7
- package/dist/Icons/SortAtoZIcon.js.map +1 -1
- package/dist/Icons/SortDescendingIcon.d.ts.map +1 -1
- package/dist/Icons/SortDescendingIcon.js +6 -11
- package/dist/Icons/SortDescendingIcon.js.map +1 -1
- package/dist/Icons/SortZtoAIcon.d.ts.map +1 -1
- package/dist/Icons/SortZtoAIcon.js +2 -7
- package/dist/Icons/SortZtoAIcon.js.map +1 -1
- package/dist/Icons/SparklesIcon.d.ts.map +1 -1
- package/dist/Icons/SparklesIcon.js +2 -3
- package/dist/Icons/SparklesIcon.js.map +1 -1
- package/dist/Icons/StackIcon.d.ts.map +1 -1
- package/dist/Icons/StackIcon.js +3 -5
- package/dist/Icons/StackIcon.js.map +1 -1
- package/dist/Icons/StarIcon.d.ts.map +1 -1
- package/dist/Icons/StarIcon.js +2 -3
- package/dist/Icons/StarIcon.js.map +1 -1
- package/dist/Icons/SyncIcon.d.ts.map +1 -1
- package/dist/Icons/SyncIcon.js +2 -4
- package/dist/Icons/SyncIcon.js.map +1 -1
- package/dist/Icons/SyncOffIcon.d.ts.map +1 -1
- package/dist/Icons/SyncOffIcon.js +3 -6
- package/dist/Icons/SyncOffIcon.js.map +1 -1
- package/dist/Icons/ToolsIcon.d.ts +18 -0
- package/dist/Icons/ToolsIcon.d.ts.map +1 -0
- package/dist/Icons/ToolsIcon.js +58 -0
- package/dist/Icons/ToolsIcon.js.map +1 -0
- package/dist/Icons/TrashIcon.d.ts.map +1 -1
- package/dist/Icons/TrashIcon.js +2 -2
- package/dist/Icons/TrashIcon.js.map +1 -1
- package/dist/Icons/UndoIcon.d.ts.map +1 -1
- package/dist/Icons/UndoIcon.js +3 -4
- package/dist/Icons/UndoIcon.js.map +1 -1
- package/dist/Icons/UnlinkIcon.d.ts.map +1 -1
- package/dist/Icons/UnlinkIcon.js +46 -65
- package/dist/Icons/UnlinkIcon.js.map +1 -1
- package/dist/Icons/UnlockIcon.d.ts.map +1 -1
- package/dist/Icons/UnlockIcon.js +3 -4
- package/dist/Icons/UnlockIcon.js.map +1 -1
- package/dist/Icons/UploadIcon.d.ts.map +1 -1
- package/dist/Icons/UploadIcon.js +3 -6
- package/dist/Icons/UploadIcon.js.map +1 -1
- package/dist/Icons/User2Icon.d.ts.map +1 -1
- package/dist/Icons/User2Icon.js +13 -15
- package/dist/Icons/User2Icon.js.map +1 -1
- package/dist/Icons/UserAddIcon.d.ts +18 -0
- package/dist/Icons/UserAddIcon.d.ts.map +1 -0
- package/dist/Icons/UserAddIcon.js +46 -0
- package/dist/Icons/UserAddIcon.js.map +1 -0
- package/dist/Icons/UserDeleteIcon.d.ts +18 -0
- package/dist/Icons/UserDeleteIcon.d.ts.map +1 -0
- package/dist/Icons/UserDeleteIcon.js +46 -0
- package/dist/Icons/UserDeleteIcon.js.map +1 -0
- package/dist/Icons/UserEditIcon.d.ts +18 -0
- package/dist/Icons/UserEditIcon.d.ts.map +1 -0
- package/dist/Icons/UserEditIcon.js +40 -0
- package/dist/Icons/UserEditIcon.js.map +1 -0
- package/dist/Icons/UserIcon.d.ts.map +1 -1
- package/dist/Icons/UserIcon.js +3 -4
- package/dist/Icons/UserIcon.js.map +1 -1
- package/dist/Icons/UserSearchIcon.d.ts +18 -0
- package/dist/Icons/UserSearchIcon.d.ts.map +1 -0
- package/dist/Icons/UserSearchIcon.js +56 -0
- package/dist/Icons/UserSearchIcon.js.map +1 -0
- package/dist/Icons/UserSquareIcon.d.ts +18 -0
- package/dist/Icons/UserSquareIcon.d.ts.map +1 -0
- package/dist/Icons/UserSquareIcon.js +40 -0
- package/dist/Icons/UserSquareIcon.js.map +1 -0
- package/dist/Icons/UsersIcon.d.ts +18 -0
- package/dist/Icons/UsersIcon.d.ts.map +1 -0
- package/dist/Icons/UsersIcon.js +46 -0
- package/dist/Icons/UsersIcon.js.map +1 -0
- package/dist/Icons/WarningIcon.d.ts.map +1 -1
- package/dist/Icons/WarningIcon.js +2 -3
- package/dist/Icons/WarningIcon.js.map +1 -1
- package/dist/Icons/ZoomAllIcon.d.ts.map +1 -1
- package/dist/Icons/ZoomAllIcon.js +6 -38
- package/dist/Icons/ZoomAllIcon.js.map +1 -1
- package/dist/Icons/ZoomXIcon.d.ts.map +1 -1
- package/dist/Icons/ZoomXIcon.js +5 -8
- package/dist/Icons/ZoomXIcon.js.map +1 -1
- package/dist/Icons/ZoomYIcon.d.ts.map +1 -1
- package/dist/Icons/ZoomYIcon.js +5 -8
- package/dist/Icons/ZoomYIcon.js.map +1 -1
- package/dist/Icons.d.ts +28 -5
- package/dist/Icons.js +28 -5
- package/dist/IconsAnimated/PanelLeftCloseIcon.js.map +1 -1
- package/dist/IconsAnimated/PanelLeftOpenIcon.js.map +1 -1
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +2 -2
- package/dist/Input.js.map +1 -1
- package/dist/InputNumeric.d.ts.map +1 -1
- package/dist/InputNumeric.js.map +1 -1
- package/dist/InputOTP.d.ts.map +1 -1
- package/dist/InputOTP.js +1 -1
- package/dist/InputOTP.js.map +1 -1
- package/dist/InputSearch.d.ts.map +1 -1
- package/dist/InputSearch.js +7 -7
- package/dist/InputSearch.js.map +1 -1
- package/dist/Kbd.d.ts.map +1 -1
- package/dist/Kbd.js.map +1 -1
- package/dist/Label.js.map +1 -1
- package/dist/Meter.js +4 -4
- package/dist/Meter.js.map +1 -1
- package/dist/MultiSelect/MultiSelectBase.js.map +1 -1
- package/dist/MultiSelect.js.map +1 -1
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Popover.js.map +1 -1
- package/dist/RadialMenu.d.ts.map +1 -1
- package/dist/RadialMenu.js.map +1 -1
- package/dist/RadioButton.js +1 -4
- package/dist/RadioButton.js.map +1 -1
- package/dist/RadioButtonGroup/RadioButtonGroupBase.d.ts.map +1 -1
- package/dist/RadioButtonGroup/RadioButtonGroupBase.js +2 -5
- package/dist/RadioButtonGroup/RadioButtonGroupBase.js.map +1 -1
- package/dist/RadioButtonGroup.d.ts.map +1 -1
- package/dist/RadioButtonGroup.js.map +1 -1
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +4 -4
- package/dist/RadioGroup.js.map +1 -1
- package/dist/Select.js +2 -2
- package/dist/Select.js.map +1 -1
- package/dist/Skeleton.js.map +1 -1
- package/dist/Slider.js.map +1 -1
- package/dist/Switch/SwitchBase.d.ts.map +1 -1
- package/dist/Switch/SwitchBase.js.map +1 -1
- package/dist/Switch.js.map +1 -1
- package/dist/Tabs/TabsBase.d.ts.map +1 -1
- package/dist/Tabs/TabsBase.js.map +1 -1
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/Tabs.js.map +1 -1
- package/dist/Textarea.js.map +1 -1
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toast.js +2 -2
- package/dist/Toast.js.map +1 -1
- package/dist/Toggle/ToggleBase.js.map +1 -1
- package/dist/Toggle.d.ts.map +1 -1
- package/dist/Toggle.js +2 -6
- package/dist/Toggle.js.map +1 -1
- package/dist/ToggleGroup/ToggleGroupBase.d.ts.map +1 -1
- package/dist/ToggleGroup/ToggleGroupBase.js.map +1 -1
- package/dist/ToggleGroup/ToggleGroupItem.js +1 -1
- package/dist/ToggleGroup/ToggleGroupItem.js.map +1 -1
- package/dist/ToggleGroup/ToggleGroupSplitMenuItem.js +1 -1
- package/dist/ToggleGroup/ToggleGroupSplitMenuItem.js.map +1 -1
- package/dist/ToggleGroup.js +1 -9
- package/dist/ToggleGroup.js.map +1 -1
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip.js +1 -4
- package/dist/Tooltip.js.map +1 -1
- package/dist/Tray.d.ts.map +1 -1
- package/dist/Tray.js +2 -2
- package/dist/Tray.js.map +1 -1
- package/dist/index.d.ts +28 -5
- package/dist/index.js +28 -5
- package/dist/primitives/button.js +1 -1
- package/dist/primitives/button.js.map +1 -1
- package/dist/styles/spectral.css +1 -1
- package/package.json +1 -1
- package/dist/Icons/AnnotationsIcon.d.ts.map +0 -1
- package/dist/Icons/AnnotationsIcon.js.map +0 -1
- package/dist/Icons/PanelIconClose.d.ts.map +0 -1
- package/dist/Icons/PanelIconClose.js +0 -35
- package/dist/Icons/PanelIconClose.js.map +0 -1
- package/dist/Icons/PanelIconOpen.d.ts.map +0 -1
- package/dist/Icons/PanelIconOpen.js +0 -35
- package/dist/Icons/PanelIconOpen.js.map +0 -1
package/dist/InputNumeric.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputNumeric.js","names":[],"sources":["../src/components/InputNumeric/InputNumeric.tsx"],"sourcesContent":["import { Input, type InputProps } from '@components/Input/Input'\nimport { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { cn } from '@utils/twUtils'\nimport { useCallback, type ClipboardEvent, type KeyboardEvent, type ReactElement } from 'react'\n\ntype NumericKeyDownEvent = KeyboardEvent<HTMLInputElement>\ntype NumericPasteEvent = ClipboardEvent<HTMLInputElement>\n\nconst DIGIT_REGEX = /^\\d$/\nconst DISALLOWED_SPECIAL_KEYS = new Set(['e', 'E', '+'])\nconst ALLOWED_CONTROL_KEYS = new Set(['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End', 'Tab', 'Enter', 'Escape'])\n\nconst getDecimalSeparator = (locale?: string): string => {\n try {\n const formattedNumber = new Intl.NumberFormat(locale).formatToParts(1.1)\n return formattedNumber.find((part) => part.type === 'decimal')?.value ?? '.'\n } catch {\n return '.'\n }\n}\n\nconst normalizeDecimalSeparator = (value: string, decimalSeparator: string): string => {\n if (decimalSeparator === '.') return value\n return value.replaceAll(decimalSeparator, '.')\n}\n\nconst sanitizeNumericValue = (value: string, allowDecimal: boolean, allowNegative: boolean, decimalSeparator: string): string => {\n if (!value) return ''\n\n let sanitized = normalizeDecimalSeparator(value, decimalSeparator).replace(/[^\\d.-]/g, '')\n\n if (!allowNegative) {\n sanitized = sanitized.replace(/-/g, '')\n } else {\n sanitized = sanitized.replace(/(?!^)-/g, '')\n if (sanitized.startsWith('--')) {\n sanitized = `-${sanitized.replace(/-/g, '')}`\n }\n }\n\n if (!allowDecimal) {\n sanitized = sanitized.replace(/\\./g, '')\n } else {\n const firstDecimalIndex = sanitized.indexOf('.')\n if (firstDecimalIndex >= 0) {\n const integerPart = sanitized.slice(0, firstDecimalIndex + 1)\n const fractionalPart = sanitized.slice(firstDecimalIndex + 1).replace(/\\./g, '')\n sanitized = `${integerPart}${fractionalPart}`\n }\n }\n\n return sanitized\n}\n\nconst shouldAllowDecimalInput = (target: HTMLInputElement): boolean => {\n if (target.selectionStart === null || target.selectionEnd === null) {\n return !target.value.includes('.')\n }\n\n const selectedText = target.value.slice(target.selectionStart, target.selectionEnd)\n return !target.value.includes('.') || selectedText.includes('.')\n}\n\nconst shouldAllowNegativeInput = (target: HTMLInputElement): boolean => {\n if (target.selectionStart === null || target.selectionEnd === null) {\n return target.value.length === 0\n }\n\n const isAtStart = target.selectionStart === 0\n const selectedText = target.value.slice(target.selectionStart, target.selectionEnd)\n return isAtStart && (!target.value.includes('-') || selectedText.includes('-'))\n}\n\nconst parseNumericProp = (value: number | string | undefined): number | undefined => {\n if (value === undefined || value === null || value === '') return undefined\n const parsed = typeof value === 'number' ? value : Number.parseFloat(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nconst getDecimalPlaces = (value: number): number => {\n const valueString = value.toString()\n if (!valueString.includes('.')) return 0\n return valueString.split('.')[1]?.length ?? 0\n}\n\nconst roundToPrecision = (value: number, precision: number): number => {\n if (precision <= 0) return value\n const factor = 10 ** precision\n return Math.round(value * factor) / factor\n}\n\nexport type InputNumericProps = Omit<InputProps, 'inputMode' | 'onChange' | 'pattern' | 'type'> & {\n allowDecimal?: boolean\n allowNegative?: boolean\n locale?: string\n /** Number of message lines to reserve (default: 1). */\n messageReserveLines?: number\n /** Whether to keep message space reserved when hidden (default: false). */\n messageReserveSpace?: boolean\n onChange?: (value: string) => void\n value?: string\n}\n\nexport const InputNumeric = ({\n allowDecimal = true,\n allowNegative = false,\n className,\n defaultValue = '',\n locale,\n max,\n messageReserveLines = 1,\n messageReserveSpace = false,\n min,\n onChange,\n onKeyDown,\n onPaste,\n step,\n value: valueProp,\n ...props\n}: InputNumericProps): ReactElement => {\n const normalizedDefaultValue = typeof defaultValue === 'string' ? defaultValue : defaultValue !== undefined && defaultValue !== null ? String(defaultValue) : ''\n const [value, setValue] = useUncontrolledState<string>({\n value: valueProp,\n defaultValue: normalizedDefaultValue,\n onChange,\n })\n const decimalSeparator = getDecimalSeparator(locale)\n const parsedMin = parseNumericProp(min)\n const parsedMax = parseNumericProp(max)\n const parsedStep = parseNumericProp(step)\n const stepValue = parsedStep && parsedStep > 0 ? parsedStep : 1\n const effectiveMin = parsedMin ?? (!allowNegative ? 0 : undefined)\n\n const handleKeyDown = useCallback(\n (event: NumericKeyDownEvent): void => {\n onKeyDown?.(event)\n if (event.defaultPrevented || event.nativeEvent.isComposing) return\n\n if (event.metaKey || event.ctrlKey || event.altKey) return\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n event.preventDefault()\n\n const direction = event.key === 'ArrowUp' ? 1 : -1\n const normalizedValue = normalizeDecimalSeparator(value, decimalSeparator)\n const currentValue = Number.parseFloat(normalizedValue)\n const hasCurrentValue = Number.isFinite(currentValue)\n const baseValue = hasCurrentValue ? currentValue : (effectiveMin ?? 0)\n\n let nextValue = baseValue + direction * stepValue\n if (effectiveMin !== undefined) {\n nextValue = Math.max(effectiveMin, nextValue)\n }\n if (parsedMax !== undefined) {\n nextValue = Math.min(parsedMax, nextValue)\n }\n\n if (!allowDecimal) {\n nextValue = Math.trunc(nextValue)\n }\n\n const precision = allowDecimal ? getDecimalPlaces(stepValue) : 0\n const roundedValue = roundToPrecision(nextValue, precision)\n const safeValue = Object.is(roundedValue, -0) ? 0 : roundedValue\n const nextString = precision > 0 ? safeValue.toFixed(precision).replace(/\\.?0+$/, '') : safeValue.toString()\n setValue(sanitizeNumericValue(nextString, allowDecimal, allowNegative, decimalSeparator))\n return\n }\n\n if (ALLOWED_CONTROL_KEYS.has(event.key)) return\n if (DIGIT_REGEX.test(event.key)) return\n\n if (DISALLOWED_SPECIAL_KEYS.has(event.key)) {\n event.preventDefault()\n return\n }\n\n const isDecimalKey = event.key === '.' || event.key === decimalSeparator\n\n if (isDecimalKey) {\n if (!allowDecimal || !shouldAllowDecimalInput(event.currentTarget)) {\n event.preventDefault()\n }\n return\n }\n\n if (event.key === '-') {\n if (!allowNegative || !shouldAllowNegativeInput(event.currentTarget)) {\n event.preventDefault()\n }\n return\n }\n\n event.preventDefault()\n },\n [allowDecimal, allowNegative, decimalSeparator, effectiveMin, onKeyDown, parsedMax, setValue, stepValue, value],\n )\n\n const handlePaste = useCallback(\n (event: NumericPasteEvent): void => {\n onPaste?.(event)\n },\n [onPaste],\n )\n\n const handleChange = useCallback(\n (newValue: string): void => {\n setValue(sanitizeNumericValue(newValue, allowDecimal, allowNegative, decimalSeparator))\n },\n [allowDecimal, allowNegative, decimalSeparator, setValue],\n )\n\n const inputMode = allowDecimal ? 'decimal' : 'numeric'\n const pattern = allowDecimal ? '[0-9]*[.]?[0-9]*' : '[0-9]*'\n\n return (\n <Input\n {...props}\n className={cn('tabular-nums', className)}\n inputMode={inputMode}\n max={max}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace}\n min={min}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n pattern={pattern}\n step={step}\n type='text'\n value={value}\n />\n )\n}\n\nInputNumeric.displayName = 'InputNumeric'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InputNumeric.js","names":[],"sources":["../src/components/InputNumeric/InputNumeric.tsx"],"sourcesContent":["import { Input, type InputProps } from '@components/Input/Input'\nimport { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { cn } from '@utils/twUtils'\nimport { useCallback, type ClipboardEvent, type KeyboardEvent, type ReactElement } from 'react'\n\ntype NumericKeyDownEvent = KeyboardEvent<HTMLInputElement>\ntype NumericPasteEvent = ClipboardEvent<HTMLInputElement>\n\nconst DIGIT_REGEX = /^\\d$/\nconst DISALLOWED_SPECIAL_KEYS = new Set(['e', 'E', '+'])\nconst ALLOWED_CONTROL_KEYS = new Set(['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End', 'Tab', 'Enter', 'Escape'])\n\nconst getDecimalSeparator = (locale?: string): string => {\n try {\n const formattedNumber = new Intl.NumberFormat(locale).formatToParts(1.1)\n return formattedNumber.find((part) => part.type === 'decimal')?.value ?? '.'\n } catch {\n return '.'\n }\n}\n\nconst normalizeDecimalSeparator = (value: string, decimalSeparator: string): string => {\n if (decimalSeparator === '.') return value\n return value.replaceAll(decimalSeparator, '.')\n}\n\nconst sanitizeNumericValue = (value: string, allowDecimal: boolean, allowNegative: boolean, decimalSeparator: string): string => {\n if (!value) return ''\n\n let sanitized = normalizeDecimalSeparator(value, decimalSeparator).replace(/[^\\d.-]/g, '')\n\n if (!allowNegative) {\n sanitized = sanitized.replace(/-/g, '')\n } else {\n sanitized = sanitized.replace(/(?!^)-/g, '')\n if (sanitized.startsWith('--')) {\n sanitized = `-${sanitized.replace(/-/g, '')}`\n }\n }\n\n if (!allowDecimal) {\n sanitized = sanitized.replace(/\\./g, '')\n } else {\n const firstDecimalIndex = sanitized.indexOf('.')\n if (firstDecimalIndex >= 0) {\n const integerPart = sanitized.slice(0, firstDecimalIndex + 1)\n const fractionalPart = sanitized.slice(firstDecimalIndex + 1).replace(/\\./g, '')\n sanitized = `${integerPart}${fractionalPart}`\n }\n }\n\n return sanitized\n}\n\nconst shouldAllowDecimalInput = (target: HTMLInputElement): boolean => {\n if (target.selectionStart === null || target.selectionEnd === null) {\n return !target.value.includes('.')\n }\n\n const selectedText = target.value.slice(target.selectionStart, target.selectionEnd)\n return !target.value.includes('.') || selectedText.includes('.')\n}\n\nconst shouldAllowNegativeInput = (target: HTMLInputElement): boolean => {\n if (target.selectionStart === null || target.selectionEnd === null) {\n return target.value.length === 0\n }\n\n const isAtStart = target.selectionStart === 0\n const selectedText = target.value.slice(target.selectionStart, target.selectionEnd)\n return isAtStart && (!target.value.includes('-') || selectedText.includes('-'))\n}\n\nconst parseNumericProp = (value: number | string | undefined): number | undefined => {\n if (value === undefined || value === null || value === '') return undefined\n const parsed = typeof value === 'number' ? value : Number.parseFloat(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nconst getDecimalPlaces = (value: number): number => {\n const valueString = value.toString()\n if (!valueString.includes('.')) return 0\n return valueString.split('.')[1]?.length ?? 0\n}\n\nconst roundToPrecision = (value: number, precision: number): number => {\n if (precision <= 0) return value\n const factor = 10 ** precision\n return Math.round(value * factor) / factor\n}\n\nexport type InputNumericProps = Omit<InputProps, 'inputMode' | 'onChange' | 'pattern' | 'type'> & {\n allowDecimal?: boolean\n allowNegative?: boolean\n locale?: string\n /** Number of message lines to reserve (default: 1). */\n messageReserveLines?: number\n /** Whether to keep message space reserved when hidden (default: false). */\n messageReserveSpace?: boolean\n onChange?: (value: string) => void\n value?: string\n}\n\nexport const InputNumeric = ({ allowDecimal = true, allowNegative = false, className, defaultValue = '', locale, max, messageReserveLines = 1, messageReserveSpace = false, min, onChange, onKeyDown, onPaste, step, value: valueProp, ...props }: InputNumericProps): ReactElement => {\n const normalizedDefaultValue = typeof defaultValue === 'string' ? defaultValue : defaultValue !== undefined && defaultValue !== null ? String(defaultValue) : ''\n const [value, setValue] = useUncontrolledState<string>({\n value: valueProp,\n defaultValue: normalizedDefaultValue,\n onChange,\n })\n const decimalSeparator = getDecimalSeparator(locale)\n const parsedMin = parseNumericProp(min)\n const parsedMax = parseNumericProp(max)\n const parsedStep = parseNumericProp(step)\n const stepValue = parsedStep && parsedStep > 0 ? parsedStep : 1\n const effectiveMin = parsedMin ?? (!allowNegative ? 0 : undefined)\n\n const handleKeyDown = useCallback(\n (event: NumericKeyDownEvent): void => {\n onKeyDown?.(event)\n if (event.defaultPrevented || event.nativeEvent.isComposing) return\n\n if (event.metaKey || event.ctrlKey || event.altKey) return\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n event.preventDefault()\n\n const direction = event.key === 'ArrowUp' ? 1 : -1\n const normalizedValue = normalizeDecimalSeparator(value, decimalSeparator)\n const currentValue = Number.parseFloat(normalizedValue)\n const hasCurrentValue = Number.isFinite(currentValue)\n const baseValue = hasCurrentValue ? currentValue : (effectiveMin ?? 0)\n\n let nextValue = baseValue + direction * stepValue\n if (effectiveMin !== undefined) {\n nextValue = Math.max(effectiveMin, nextValue)\n }\n if (parsedMax !== undefined) {\n nextValue = Math.min(parsedMax, nextValue)\n }\n\n if (!allowDecimal) {\n nextValue = Math.trunc(nextValue)\n }\n\n const precision = allowDecimal ? getDecimalPlaces(stepValue) : 0\n const roundedValue = roundToPrecision(nextValue, precision)\n const safeValue = Object.is(roundedValue, -0) ? 0 : roundedValue\n const nextString = precision > 0 ? safeValue.toFixed(precision).replace(/\\.?0+$/, '') : safeValue.toString()\n setValue(sanitizeNumericValue(nextString, allowDecimal, allowNegative, decimalSeparator))\n return\n }\n\n if (ALLOWED_CONTROL_KEYS.has(event.key)) return\n if (DIGIT_REGEX.test(event.key)) return\n\n if (DISALLOWED_SPECIAL_KEYS.has(event.key)) {\n event.preventDefault()\n return\n }\n\n const isDecimalKey = event.key === '.' || event.key === decimalSeparator\n\n if (isDecimalKey) {\n if (!allowDecimal || !shouldAllowDecimalInput(event.currentTarget)) {\n event.preventDefault()\n }\n return\n }\n\n if (event.key === '-') {\n if (!allowNegative || !shouldAllowNegativeInput(event.currentTarget)) {\n event.preventDefault()\n }\n return\n }\n\n event.preventDefault()\n },\n [allowDecimal, allowNegative, decimalSeparator, effectiveMin, onKeyDown, parsedMax, setValue, stepValue, value],\n )\n\n const handlePaste = useCallback(\n (event: NumericPasteEvent): void => {\n onPaste?.(event)\n },\n [onPaste],\n )\n\n const handleChange = useCallback(\n (newValue: string): void => {\n setValue(sanitizeNumericValue(newValue, allowDecimal, allowNegative, decimalSeparator))\n },\n [allowDecimal, allowNegative, decimalSeparator, setValue],\n )\n\n const inputMode = allowDecimal ? 'decimal' : 'numeric'\n const pattern = allowDecimal ? '[0-9]*[.]?[0-9]*' : '[0-9]*'\n\n return (\n <Input\n {...props}\n className={cn('tabular-nums', className)}\n inputMode={inputMode}\n max={max}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace}\n min={min}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n pattern={pattern}\n step={step}\n type='text'\n value={value}\n />\n )\n}\n\nInputNumeric.displayName = 'InputNumeric'\n"],"mappings":"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"}
|
package/dist/InputOTP.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputOTP.d.ts","names":[],"sources":["../src/components/InputOTP/InputOTP.tsx"],"mappings":";;;;;;;UAMiB,iBAAA,SAA0B,IAAA,CAAK,aAAA;EAC9C,UAAA,OAAiB,IAAA;EACjB,SAAA;EACA,YAAA;EACA,SAAA;EACA,mBAAA;EACA,mBAAA;EAQQ;;;;;EAFR,OAAA;EACA,SAAA;EACA,KAAA,GAAQ,cAAA;EACR,OAAA;EACA,cAAA;AAAA;AAAA,KAGU,aAAA,GAAgB,iBAAA;EAAuB,KAAA;EAAwB,QAAA,GAAW,QAAA;AAAA;EAAyC,KAAA;EAAe,QAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"InputOTP.d.ts","names":[],"sources":["../src/components/InputOTP/InputOTP.tsx"],"mappings":";;;;;;;UAMiB,iBAAA,SAA0B,IAAA,CAAK,aAAA;EAC9C,UAAA,OAAiB,IAAA;EACjB,SAAA;EACA,YAAA;EACA,SAAA;EACA,mBAAA;EACA,mBAAA;EAQQ;;;;;EAFR,OAAA;EACA,SAAA;EACA,KAAA,GAAQ,cAAA;EACR,OAAA;EACA,cAAA;AAAA;AAAA,KAGU,aAAA,GAAgB,iBAAA;EAAuB,KAAA;EAAwB,QAAA,GAAW,QAAA;AAAA;EAAyC,KAAA;EAAe,QAAA;AAAA;AAAA,UAiLpI,UAAA;EACR,SAAA;EACA,KAAA;EACA,KAAA;AAAA;AAAA,cAuEW,QAAA;EAAA;;;;;;;;;;;;;;;;;;;;KArNV,aAAA;IACD,GAAA,GAAM,GAAA,CAAI,YAAA,QAAoB,QAAA;EAAA,IAC/B,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;OAoFE,wBAAA;MACD,GAAA,GAAM,GAAA,CAAI,YAAA;IAAA,IACX,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;;;OAeE,wBAAA;MACD,KAAA;MACA,GAAA,GAAM,GAAA,CAAI,YAAA;IAAA,IACX,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;;OA+D+C,UAAA,GAAU,oBAAA,CAAA,GAAA,CAAA,OAAA;;;;;;;OAsBvD,wBAAA;MACD,GAAA,GAAM,GAAA,CAAI,YAAA;IAAA,IACX,oBAAA,CAAA,GAAA,CAAA,OAAA"}
|
package/dist/InputOTP.js
CHANGED
|
@@ -97,7 +97,7 @@ const Slot = ({ className, index, ref, ...props }) => {
|
|
|
97
97
|
isActive: false
|
|
98
98
|
};
|
|
99
99
|
return /* @__PURE__ */ jsxs("div", {
|
|
100
|
-
className: cn("h-12 w-10 relative z-10 flex items-center justify-center rounded-[8px] border tabular-nums transition duration-200 focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent", variant === "filled" ? "border-level-one bg-level-one" : "border-input-otp-border bg-transparent", !isInvalid && "border", isInvalid && "border-2 border-danger-400", slot.isActive && !isInvalid && "z-10 border-input-otp-border--focus
|
|
100
|
+
className: cn("h-12 w-10 relative z-10 flex items-center justify-center rounded-[8px] border tabular-nums transition duration-200 focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent", variant === "filled" ? "border-level-one bg-level-one" : "border-input-otp-border bg-transparent", !isInvalid && "border", isInvalid && "border-2 border-danger-400", slot.isActive && !isInvalid && "z-10 border-2 border-input-otp-border--focus", slot.isActive && isInvalid && "z-10 border-danger-400 focus-visible:outline-1 focus-visible:outline-offset-1 focus-visible:outline-danger-400", className),
|
|
101
101
|
"data-index": index,
|
|
102
102
|
"data-variant": variant,
|
|
103
103
|
ref,
|
package/dist/InputOTP.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputOTP.js","names":[],"sources":["../src/components/InputOTP/InputOTP.tsx"],"sourcesContent":["import { MinusIcon } from '@components/Icons'\nimport { ErrorMessage, getErrorMessageId, getWarningMessageId, useFormFieldId, useFormFieldState, WarningMessage, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { OTPInput, REGEXP_ONLY_DIGITS, type OTPInputProps } from 'input-otp'\nimport { createContext, useContext, type ClipboardEvent, type ComponentPropsWithoutRef, type ComponentRef, type Ref } from 'react'\n\nexport interface InputOTPBaseProps extends Omit<OTPInputProps, 'textAlign' | 'pushPasswordManagerStrategy' | 'pasteTransformer' | 'noScriptCSSFallback' | 'placeholder' | 'containerClassName' | 'render' | 'pattern'> {\n onComplete?: (...args: unknown[]) => void\n className?: string\n errorMessage?: string | undefined\n inputMode?: 'numeric' | 'text' | 'decimal' | 'tel' | 'search' | 'email' | 'url'\n messageReserveLines?: number\n messageReserveSpace?: boolean\n /**\n * Regex pattern string to restrict allowed characters.\n * When `inputMode=\"numeric\"`, defaults to digits-only pattern.\n * Set to `undefined` to allow any characters.\n */\n pattern?: string | undefined\n separator?: boolean\n state?: FormFieldState\n variant?: 'outlined' | 'filled'\n warningMessage?: string | undefined\n}\n\nexport type InputOTPProps = InputOTPBaseProps & ({ value: number | string; onChange: (newValue: number | string) => void } | { value?: never; onChange?: never })\n\nconst InputOTPStateContext = createContext<{ isInvalid?: boolean }>({})\n\nconst OTPInputContext = createContext<{\n maxLength?: number\n slots?: { char: string | null; hasFakeCaret: boolean; isActive: boolean }[]\n variant?: 'outlined' | 'filled'\n} | null>(null)\n\nconst useRoot = () => {\n const context = useContext(OTPInputContext)\n if (!context) {\n throw new Error('useRoot must be used within an InputOTP')\n }\n return context\n}\n\nconst Root = ({\n autoFocus = false,\n children,\n className,\n errorMessage,\n id,\n inputMode = 'numeric',\n messageReserveLines = 1,\n messageReserveSpace = false,\n maxLength,\n name,\n onChange,\n onComplete,\n pattern,\n ref,\n state = 'default',\n value,\n variant = 'outlined',\n warningMessage,\n ...props\n}: InputOTPProps & {\n ref?: Ref<ComponentRef<typeof OTPInput>>\n}) => {\n const inputId = useFormFieldId(id, name)\n const errorMessageId = getErrorMessageId(inputId)\n const warningMessageId = getWarningMessageId(inputId)\n const { isInvalid } = useFormFieldState(false, state)\n\n // Apply digits-only pattern when inputMode is numeric (unless explicitly overridden)\n const effectivePattern = pattern ?? (inputMode === 'numeric' ? REGEXP_ONLY_DIGITS : undefined)\n\n const describedBy = [isInvalid && errorMessage ? errorMessageId : undefined, state === 'warning' && warningMessage ? warningMessageId : undefined].filter(Boolean).join(' ') || undefined\n\n const handlePaste = (e: ClipboardEvent<HTMLDivElement>): void => {\n let pasteData = e.clipboardData.getData('text/plain').trim().replaceAll('-', '')\n\n // Filter to digits only when in numeric mode\n if (inputMode === 'numeric') {\n pasteData = pasteData.replace(/\\D/g, '')\n }\n\n if (pasteData.length === maxLength && typeof onChange === 'function') {\n onChange(pasteData)\n }\n }\n\n return (\n <InputOTPStateContext.Provider value={{ isInvalid }}>\n <div className='gap-y-1 flex w-max flex-col'>\n <OTPInput\n aria-describedby={describedBy}\n aria-invalid={isInvalid}\n /* eslint-disable-next-line jsx-a11y/no-autofocus -- intentional: consumers can opt in for OTP-first flows; defaults to false */\n autoFocus={autoFocus}\n containerClassName={cn('gap-2 flex items-center has-[:disabled]:cursor-not-allowed has-[disabled]:opacity-50', className)}\n data-1p-ignore='true'\n data-dashlane-disabled-on-field='true'\n data-lpignore='true'\n data-protonpass-ignore='true'\n data-testid='spectral-input-otp'\n id={inputId}\n inputMode={inputMode}\n maxLength={maxLength}\n onChange={onChange}\n onComplete={onComplete}\n onPaste={handlePaste}\n pasteTransformer={(pasted) => pasted.replaceAll('-', '')}\n pattern={effectivePattern}\n pushPasswordManagerStrategy='none'\n ref={ref}\n textAlign='center'\n value={value}\n {...props}\n render={({ slots }) => (\n <OTPInputContext.Provider value={{ slots, variant, maxLength }}>\n {children ?? (\n <Group>\n <Slots />\n </Group>\n )}\n </OTPInputContext.Provider>\n )}\n />\n <ErrorMessage\n dataTestId='spectral-input-otp-error-message'\n id={errorMessageId}\n message={isInvalid ? errorMessage : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace}\n />\n <WarningMessage\n dataTestId='spectral-input-otp-warning-message'\n id={warningMessageId}\n message={state === 'warning' ? warningMessage : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace}\n />\n </div>\n </InputOTPStateContext.Provider>\n )\n}\nRoot.displayName = 'InputOTP'\n\nconst Group = ({\n ref,\n ...props\n}: ComponentPropsWithoutRef<'div'> & {\n ref?: Ref<ComponentRef<'div'>>\n}) => <div className='gap-x-2 flex items-center justify-center' data-testid='spectral-input-otp-group' ref={ref} {...props} />\nGroup.displayName = 'InputOTP.Group'\n\nconst Slot = ({\n className,\n index,\n ref,\n ...props\n}: ComponentPropsWithoutRef<'div'> & {\n index: number\n ref?: Ref<ComponentRef<'div'>>\n}) => {\n const { variant = 'outlined', slots = [] } = useRoot()\n const { isInvalid } = useContext(InputOTPStateContext)\n const slot = slots[index] || { char: '', hasFakeCaret: true, isActive: false }\n\n return (\n <div\n className={cn(\n 'h-12 w-10 relative z-10 flex items-center justify-center rounded-[8px] border tabular-nums transition duration-200 focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n variant === 'filled' ? 'border-level-one bg-level-one' : 'border-input-otp-border bg-transparent',\n !isInvalid && 'border',\n isInvalid && 'border-2 border-danger-400',\n slot.isActive && !isInvalid && 'z-10 border-input-otp-border--focus border-2',\n slot.isActive && isInvalid && 'z-10 border-danger-400 focus-visible:outline-1 focus-visible:outline-offset-1 focus-visible:outline-danger-400',\n className,\n )}\n data-index={index}\n data-testid='spectral-input-otp-slot'\n data-variant={variant}\n ref={ref}\n {...props}\n >\n {slot.char}\n {slot.hasFakeCaret && (\n <div className='inset-0 pointer-events-none absolute flex items-center justify-center motion-safe:animate-caret-blink'>\n <div className='h-8 w-px bg-input-otp-caret' />\n </div>\n )}\n </div>\n )\n}\nSlot.displayName = 'InputOTP.Slot'\n\ninterface SlotsProps {\n className?: string\n count?: number\n start?: number\n}\n\n/**\n * Helper component that automatically renders multiple InputOTP.Slot components.\n * Uses the maxLength from the parent InputOTP to determine how many slots to render.\n *\n * @example\n * // Render all 6 slots\n * <InputOTP maxLength={6}>\n * <InputOTP.Group>\n * <InputOTP.Slots />\n * </InputOTP.Group>\n * </InputOTP>\n *\n * @example\n * // Render slots in groups with a separator (3-3 split)\n * <InputOTP maxLength={6}>\n * <InputOTP.Group>\n * <InputOTP.Slots count={3} />\n * </InputOTP.Group>\n * <InputOTP.Separator />\n * <InputOTP.Group>\n * <InputOTP.Slots start={3} />\n * </InputOTP.Group>\n * </InputOTP>\n */\nconst Slots = ({ start = 0, count, className }: SlotsProps) => {\n const { maxLength = 0 } = useRoot()\n const end = count !== undefined ? start + count : maxLength\n const indices = Array.from({ length: end - start }, (_, i) => start + i)\n\n return (\n <>\n {indices.map((index) => (\n <Slot key={index} index={index} className={className} />\n ))}\n </>\n )\n}\nSlots.displayName = 'InputOTP.Slots'\n\nconst Separator = ({\n ref,\n ...props\n}: ComponentPropsWithoutRef<'div'> & {\n ref?: Ref<ComponentRef<'div'>>\n}) => {\n const { variant = 'outlined' } = useRoot()\n\n return (\n <div ref={ref} role='separator' {...props} data-testid='spectral-input-otp-separator' data-variant={variant}>\n <MinusIcon size={24} color={variant === 'filled' ? 'var(--color-input-otp-filled-separator)' : 'var(--color-input-otp-border)'} />\n </div>\n )\n}\nSeparator.displayName = 'InputOTP.Separator'\n\nexport const InputOTP = Object.assign(Root, {\n Group,\n Slot,\n Slots,\n Separator,\n})\n"],"mappings":";;;;;;;;;;AA2BA,MAAM,uBAAuB,cAAuC,EAAE,CAAA;AAEtE,MAAM,kBAAkB,cAId,KAAI;AAEd,MAAM,gBAAgB;CACpB,MAAM,UAAU,WAAW,gBAAe;AAC1C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,0CAAyC;AAE3D,QAAO;;AAGT,MAAM,QAAQ,EACZ,YAAY,OACZ,UACA,WACA,cACA,IACA,YAAY,WACZ,sBAAsB,GACtB,sBAAsB,OACtB,WACA,MACA,UACA,YACA,SACA,KACA,QAAQ,WACR,OACA,UAAU,YACV,gBACA,GAAG,YAGC;CACJ,MAAM,UAAU,eAAe,IAAI,KAAI;CACvC,MAAM,iBAAiB,kBAAkB,QAAO;CAChD,MAAM,mBAAmB,oBAAoB,QAAO;CACpD,MAAM,EAAE,cAAc,kBAAkB,OAAO,MAAK;CAGpD,MAAM,mBAAmB,YAAY,cAAc,YAAY,qBAAqB;CAEpF,MAAM,cAAc,CAAC,aAAa,eAAe,iBAAiB,QAAW,UAAU,aAAa,iBAAiB,mBAAmB,OAAU,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI,IAAI;CAEhL,MAAM,eAAe,MAA4C;EAC/D,IAAI,YAAY,EAAE,cAAc,QAAQ,aAAa,CAAC,MAAM,CAAC,WAAW,KAAK,GAAE;AAG/E,MAAI,cAAc,UAChB,aAAY,UAAU,QAAQ,OAAO,GAAE;AAGzC,MAAI,UAAU,WAAW,aAAa,OAAO,aAAa,WACxD,UAAS,UAAS;;AAItB,QACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO,EAAE,WAAW;YACjD,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,UAAD;KACE,oBAAkB;KAClB,gBAAc;KAEH;KACX,oBAAoB,GAAG,wFAAwF,UAAU;KACzH,kBAAe;KACf,mCAAgC;KAChC,iBAAc;KACd,0BAAuB;KAEvB,IAAI;KACO;KACA;KACD;KACE;KACZ,SAAS;KACT,mBAAmB,WAAW,OAAO,WAAW,KAAK,GAAG;KACxD,SAAS;KACT,6BAA4B;KACvB;KACL,WAAU;KACH;KACP,GAAI;KACJ,SAAS,EAAE,YACT,oBAAC,gBAAgB,UAAjB;MAA0B,OAAO;OAAE;OAAO;OAAS;OAAW;gBAC3D,YACC,oBAAC,OAAD,YACE,oBAAC,OAAD,EAAQ,GACH;MAEe;KAE7B;IACD,oBAAC,cAAD;KACE,YAAW;KACX,IAAI;KACJ,SAAS,YAAY,eAAe;KACf;KACA;KACtB;IACD,oBAAC,gBAAD;KACE,YAAW;KACX,IAAI;KACJ,SAAS,UAAU,YAAY,iBAAiB;KAC3B;KACA;KACtB;IACE;;EACwB;;AAGnC,KAAK,cAAc;AAEnB,MAAM,SAAS,EACb,KACA,GAAG,YAGC,oBAAC,OAAD;CAAK,WAAU;CAAuF;CAAK,GAAI;CAAQ;AAC7H,MAAM,cAAc;AAEpB,MAAM,QAAQ,EACZ,WACA,OACA,KACA,GAAG,YAIC;CACJ,MAAM,EAAE,UAAU,YAAY,QAAQ,EAAE,KAAK,SAAQ;CACrD,MAAM,EAAE,cAAc,WAAW,qBAAoB;CACrD,MAAM,OAAO,MAAM,UAAU;EAAE,MAAM;EAAI,cAAc;EAAM,UAAU;EAAM;AAE7E,QACE,qBAAC,OAAD;EACE,WAAW,GACT,6NACA,YAAY,WAAW,kCAAkC,0CACzD,CAAC,aAAa,UACd,aAAa,8BACb,KAAK,YAAY,CAAC,aAAa,gDAC/B,KAAK,YAAY,aAAa,kHAC9B,UACD;EACD,cAAY;EAEZ,gBAAc;EACT;EACL,GAAI;YAdN,CAgBG,KAAK,MACL,KAAK,gBACJ,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,OAAD,EAAK,WAAU,+BAA+B;GAC3C,EAEJ;;;AAGT,KAAK,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;AAgCnB,MAAM,SAAS,EAAE,QAAQ,GAAG,OAAO,gBAA4B;CAC7D,MAAM,EAAE,YAAY,MAAM,SAAQ;CAClC,MAAM,MAAM,UAAU,SAAY,QAAQ,QAAQ;AAGlD,QACE,4CAHc,MAAM,KAAK,EAAE,QAAQ,MAAM,OAAO,GAAG,GAAG,MAAM,QAAQ,EAI1D,CAAC,KAAK,UACZ,oBAAC,MAAD;EAAyB;EAAkB;EAAY,EAA5C,MAA4C,CACvD,EACF;;AAGN,MAAM,cAAc;AAEpB,MAAM,aAAa,EACjB,KACA,GAAG,YAGC;CACJ,MAAM,EAAE,UAAU,eAAe,SAAQ;AAEzC,QACE,oBAAC,OAAD;EAAU;EAAK,MAAK;EAAY,GAAI;EAAkD,gBAAc;YAClG,oBAAC,WAAD;GAAW,MAAM;GAAI,OAAO,YAAY,WAAW,4CAA4C;GAAkC;EAC9H;;AAGT,UAAU,cAAc;AAExB,MAAa,WAAW,OAAO,OAAO,MAAM;CAC1C;CACA;CACA;CACA;CACD,CAAA"}
|
|
1
|
+
{"version":3,"file":"InputOTP.js","names":[],"sources":["../src/components/InputOTP/InputOTP.tsx"],"sourcesContent":["import { MinusIcon } from '@components/Icons'\nimport { ErrorMessage, getErrorMessageId, getWarningMessageId, useFormFieldId, useFormFieldState, WarningMessage, type FormFieldState } from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { OTPInput, REGEXP_ONLY_DIGITS, type OTPInputProps } from 'input-otp'\nimport { createContext, useContext, type ClipboardEvent, type ComponentPropsWithoutRef, type ComponentRef, type Ref } from 'react'\n\nexport interface InputOTPBaseProps extends Omit<OTPInputProps, 'textAlign' | 'pushPasswordManagerStrategy' | 'pasteTransformer' | 'noScriptCSSFallback' | 'placeholder' | 'containerClassName' | 'render' | 'pattern'> {\n onComplete?: (...args: unknown[]) => void\n className?: string\n errorMessage?: string | undefined\n inputMode?: 'numeric' | 'text' | 'decimal' | 'tel' | 'search' | 'email' | 'url'\n messageReserveLines?: number\n messageReserveSpace?: boolean\n /**\n * Regex pattern string to restrict allowed characters.\n * When `inputMode=\"numeric\"`, defaults to digits-only pattern.\n * Set to `undefined` to allow any characters.\n */\n pattern?: string | undefined\n separator?: boolean\n state?: FormFieldState\n variant?: 'outlined' | 'filled'\n warningMessage?: string | undefined\n}\n\nexport type InputOTPProps = InputOTPBaseProps & ({ value: number | string; onChange: (newValue: number | string) => void } | { value?: never; onChange?: never })\n\nconst InputOTPStateContext = createContext<{ isInvalid?: boolean }>({})\n\nconst OTPInputContext = createContext<{\n maxLength?: number\n slots?: { char: string | null; hasFakeCaret: boolean; isActive: boolean }[]\n variant?: 'outlined' | 'filled'\n} | null>(null)\n\nconst useRoot = () => {\n const context = useContext(OTPInputContext)\n if (!context) {\n throw new Error('useRoot must be used within an InputOTP')\n }\n return context\n}\n\nconst Root = ({\n autoFocus = false,\n children,\n className,\n errorMessage,\n id,\n inputMode = 'numeric',\n messageReserveLines = 1,\n messageReserveSpace = false,\n maxLength,\n name,\n onChange,\n onComplete,\n pattern,\n ref,\n state = 'default',\n value,\n variant = 'outlined',\n warningMessage,\n ...props\n}: InputOTPProps & {\n ref?: Ref<ComponentRef<typeof OTPInput>>\n}) => {\n const inputId = useFormFieldId(id, name)\n const errorMessageId = getErrorMessageId(inputId)\n const warningMessageId = getWarningMessageId(inputId)\n const { isInvalid } = useFormFieldState(false, state)\n\n // Apply digits-only pattern when inputMode is numeric (unless explicitly overridden)\n const effectivePattern = pattern ?? (inputMode === 'numeric' ? REGEXP_ONLY_DIGITS : undefined)\n\n const describedBy = [isInvalid && errorMessage ? errorMessageId : undefined, state === 'warning' && warningMessage ? warningMessageId : undefined].filter(Boolean).join(' ') || undefined\n\n const handlePaste = (e: ClipboardEvent<HTMLDivElement>): void => {\n let pasteData = e.clipboardData.getData('text/plain').trim().replaceAll('-', '')\n\n // Filter to digits only when in numeric mode\n if (inputMode === 'numeric') {\n pasteData = pasteData.replace(/\\D/g, '')\n }\n\n if (pasteData.length === maxLength && typeof onChange === 'function') {\n onChange(pasteData)\n }\n }\n\n return (\n <InputOTPStateContext.Provider value={{ isInvalid }}>\n <div className='gap-y-1 flex w-max flex-col'>\n <OTPInput\n aria-describedby={describedBy}\n aria-invalid={isInvalid}\n /* eslint-disable-next-line jsx-a11y/no-autofocus -- intentional: consumers can opt in for OTP-first flows; defaults to false */\n autoFocus={autoFocus}\n containerClassName={cn('gap-2 flex items-center has-[:disabled]:cursor-not-allowed has-[disabled]:opacity-50', className)}\n data-1p-ignore='true'\n data-dashlane-disabled-on-field='true'\n data-lpignore='true'\n data-protonpass-ignore='true'\n data-testid='spectral-input-otp'\n id={inputId}\n inputMode={inputMode}\n maxLength={maxLength}\n onChange={onChange}\n onComplete={onComplete}\n onPaste={handlePaste}\n pasteTransformer={(pasted) => pasted.replaceAll('-', '')}\n pattern={effectivePattern}\n pushPasswordManagerStrategy='none'\n ref={ref}\n textAlign='center'\n value={value}\n {...props}\n render={({ slots }) => (\n <OTPInputContext.Provider value={{ slots, variant, maxLength }}>\n {children ?? (\n <Group>\n <Slots />\n </Group>\n )}\n </OTPInputContext.Provider>\n )}\n />\n <ErrorMessage\n dataTestId='spectral-input-otp-error-message'\n id={errorMessageId}\n message={isInvalid ? errorMessage : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace}\n />\n <WarningMessage\n dataTestId='spectral-input-otp-warning-message'\n id={warningMessageId}\n message={state === 'warning' ? warningMessage : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace}\n />\n </div>\n </InputOTPStateContext.Provider>\n )\n}\nRoot.displayName = 'InputOTP'\n\nconst Group = ({\n ref,\n ...props\n}: ComponentPropsWithoutRef<'div'> & {\n ref?: Ref<ComponentRef<'div'>>\n}) => (\n <div\n className='gap-x-2 flex items-center justify-center'\n data-testid='spectral-input-otp-group'\n ref={ref}\n {...props}\n />\n)\nGroup.displayName = 'InputOTP.Group'\n\nconst Slot = ({\n className,\n index,\n ref,\n ...props\n}: ComponentPropsWithoutRef<'div'> & {\n index: number\n ref?: Ref<ComponentRef<'div'>>\n}) => {\n const { variant = 'outlined', slots = [] } = useRoot()\n const { isInvalid } = useContext(InputOTPStateContext)\n const slot = slots[index] || { char: '', hasFakeCaret: true, isActive: false }\n\n return (\n <div\n className={cn(\n 'h-12 w-10 relative z-10 flex items-center justify-center rounded-[8px] border tabular-nums transition duration-200 focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n variant === 'filled' ? 'border-level-one bg-level-one' : 'border-input-otp-border bg-transparent',\n !isInvalid && 'border',\n isInvalid && 'border-2 border-danger-400',\n slot.isActive && !isInvalid && 'z-10 border-2 border-input-otp-border--focus',\n slot.isActive && isInvalid && 'z-10 border-danger-400 focus-visible:outline-1 focus-visible:outline-offset-1 focus-visible:outline-danger-400',\n className,\n )}\n data-index={index}\n data-testid='spectral-input-otp-slot'\n data-variant={variant}\n ref={ref}\n {...props}\n >\n {slot.char}\n {slot.hasFakeCaret && (\n <div className='inset-0 pointer-events-none absolute flex items-center justify-center motion-safe:animate-caret-blink'>\n <div className='h-8 w-px bg-input-otp-caret' />\n </div>\n )}\n </div>\n )\n}\nSlot.displayName = 'InputOTP.Slot'\n\ninterface SlotsProps {\n className?: string\n count?: number\n start?: number\n}\n\n/**\n * Helper component that automatically renders multiple InputOTP.Slot components.\n * Uses the maxLength from the parent InputOTP to determine how many slots to render.\n *\n * @example\n * // Render all 6 slots\n * <InputOTP maxLength={6}>\n * <InputOTP.Group>\n * <InputOTP.Slots />\n * </InputOTP.Group>\n * </InputOTP>\n *\n * @example\n * // Render slots in groups with a separator (3-3 split)\n * <InputOTP maxLength={6}>\n * <InputOTP.Group>\n * <InputOTP.Slots count={3} />\n * </InputOTP.Group>\n * <InputOTP.Separator />\n * <InputOTP.Group>\n * <InputOTP.Slots start={3} />\n * </InputOTP.Group>\n * </InputOTP>\n */\nconst Slots = ({ start = 0, count, className }: SlotsProps) => {\n const { maxLength = 0 } = useRoot()\n const end = count !== undefined ? start + count : maxLength\n const indices = Array.from({ length: end - start }, (_, i) => start + i)\n\n return (\n <>\n {indices.map((index) => (\n <Slot\n key={index}\n index={index}\n className={className}\n />\n ))}\n </>\n )\n}\nSlots.displayName = 'InputOTP.Slots'\n\nconst Separator = ({\n ref,\n ...props\n}: ComponentPropsWithoutRef<'div'> & {\n ref?: Ref<ComponentRef<'div'>>\n}) => {\n const { variant = 'outlined' } = useRoot()\n\n return (\n <div\n ref={ref}\n role='separator'\n {...props}\n data-testid='spectral-input-otp-separator'\n data-variant={variant}\n >\n <MinusIcon\n size={24}\n color={variant === 'filled' ? 'var(--color-input-otp-filled-separator)' : 'var(--color-input-otp-border)'}\n />\n </div>\n )\n}\nSeparator.displayName = 'InputOTP.Separator'\n\nexport const InputOTP = Object.assign(Root, {\n Group,\n Slot,\n Slots,\n Separator,\n})\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputSearch.d.ts","names":[],"sources":["../src/components/InputSearch/InputSearch.tsx"],"mappings":";;;;;;KA4BY,iBAAA,GAAoB,UAAA;AAAA,UAEf,gBAAA,SAAyB,IAAA,CAAK,kBAAA;EAC7C,SAAA;EACA,iBAAA,IAAqB,KAAA,aAAkB,SAAA;EACvC,aAAA;EACA,YAAA;EACA,aAAA,GAAgB,aAAA;EAChB,YAAA;EACA,cAAA;EACA,UAAA;EACA,cAAA;EACA,QAAA,IAAY,KAAA;EACZ,QAAA,IAAY,KAAA;EACZ,aAAA,IAAiB,KAAA;EACjB,WAAA;EACA,OAAA,EAAS,iBAAA;EACT,WAAA;EACA,YAAA,IAAgB,MAAA,EAAQ,iBAAA,KAAsB,SAAA;EAC9C,KAAA,GAAQ,OAAA,CAAQ,cAAA;EAChB,KAAA;EACA,cAAA,GAAiB,kBAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"file":"InputSearch.d.ts","names":[],"sources":["../src/components/InputSearch/InputSearch.tsx"],"mappings":";;;;;;KA4BY,iBAAA,GAAoB,UAAA;AAAA,UAEf,gBAAA,SAAyB,IAAA,CAAK,kBAAA;EAC7C,SAAA;EACA,iBAAA,IAAqB,KAAA,aAAkB,SAAA;EACvC,aAAA;EACA,YAAA;EACA,aAAA,GAAgB,aAAA;EAChB,YAAA;EACA,cAAA;EACA,UAAA;EACA,cAAA;EACA,QAAA,IAAY,KAAA;EACZ,QAAA,IAAY,KAAA;EACZ,aAAA,IAAiB,KAAA;EACjB,WAAA;EACA,OAAA,EAAS,iBAAA;EACT,WAAA;EACA,YAAA,IAAgB,MAAA,EAAQ,iBAAA,KAAsB,SAAA;EAC9C,KAAA,GAAQ,OAAA,CAAQ,cAAA;EAChB,KAAA;EACA,cAAA,GAAiB,kBAAA;AAAA;AAAA;EAgBjB,SAAA;EACA,iBAAA;EACA,aAAA;EACA,YAAA;EACA,QAAA;EACA,aAAA;EACA,YAAA;EACA,YAAA;EACA,cAAA;EACA,EAAA;EACA,UAAA;EACA,KAAA;EACA,cAAA;EACA,mBAAA;EACA,mBAAA;EACA,IAAA;EACA,QAAA;EACA,QAAA;EACA,aAAA;EACA,WAAA;EACA,OAAA;EACA,WAAA;EACA,GAAA;EACA,YAAA;EACA,QAAA;EACA,KAAA;EACA,KAAA,EAAO,SAAA;EACP,cAAA;EAAA,oBACoB,eAAA;EAAA,cACN;AAAA,GACb,gBAAA;EAAqB,GAAA,GAAM,GAAA,CAAI,cAAA;AAAA,IAAiB,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA"}
|
package/dist/InputSearch.js
CHANGED
|
@@ -250,7 +250,7 @@ const InputSearch = ({ className, createOptionLabel = defaultCreateOptionLabel,
|
|
|
250
250
|
}),
|
|
251
251
|
showClearButton ? /* @__PURE__ */ jsx("button", {
|
|
252
252
|
"aria-label": `Clear ${label ?? "search"}`,
|
|
253
|
-
className: "right-4 text-input-icon hover:text-input-icon--hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-input-border--focus
|
|
253
|
+
className: "right-4 text-input-icon hover:text-input-icon--hover rounded-sm absolute top-1/2 -translate-y-1/2 cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-input-border--focus",
|
|
254
254
|
onClick: handleClear,
|
|
255
255
|
onMouseDown: (event) => event.preventDefault(),
|
|
256
256
|
type: "button",
|
|
@@ -262,17 +262,17 @@ const InputSearch = ({ className, createOptionLabel = defaultCreateOptionLabel,
|
|
|
262
262
|
size: 20
|
|
263
263
|
})
|
|
264
264
|
}) : state === "error" ? /* @__PURE__ */ jsx("div", {
|
|
265
|
-
className: "right-4
|
|
265
|
+
className: "right-4 absolute top-1/2 -translate-y-1/2 text-danger-400",
|
|
266
266
|
children: /* @__PURE__ */ jsx(ErrorIcon, { size: 20 })
|
|
267
267
|
}) : state === "warning" ? /* @__PURE__ */ jsx("div", {
|
|
268
|
-
className: "right-4
|
|
268
|
+
className: "right-4 absolute top-1/2 -translate-y-1/2 text-warning-400",
|
|
269
269
|
children: /* @__PURE__ */ jsx(WarningIcon, { size: 20 })
|
|
270
270
|
}) : null
|
|
271
271
|
]
|
|
272
272
|
})
|
|
273
273
|
}),
|
|
274
274
|
showDropdown && dropdownPosition && typeof document !== "undefined" ? createPortal(/* @__PURE__ */ jsx("div", {
|
|
275
|
-
className: cn("
|
|
275
|
+
className: cn("p-1 fixed z-50 origin-top", getDropdownSurfaceClasses(), "max-h-72 overflow-hidden", "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-top-2 motion-safe:zoom-in-95"),
|
|
276
276
|
"data-dropdown-width-mode": dropdownWidthMode,
|
|
277
277
|
"data-dropdown-width-value": dropdownWidthMode === "custom" ? dropdownWidth : void 0,
|
|
278
278
|
ref: setDropdownElement,
|
|
@@ -312,7 +312,7 @@ const InputSearch = ({ className, createOptionLabel = defaultCreateOptionLabel,
|
|
|
312
312
|
}, option.value);
|
|
313
313
|
}), showCreateOption && /* @__PURE__ */ jsx("button", {
|
|
314
314
|
"aria-selected": createOptionIndex === highlightedIndex,
|
|
315
|
-
className: cn(getOptionClasses(isCreating, createOptionIndex === highlightedIndex, false), "gap-2 text-left text-accent
|
|
315
|
+
className: cn(getOptionClasses(isCreating, createOptionIndex === highlightedIndex, false), "gap-2 font-medium text-left text-accent"),
|
|
316
316
|
"data-highlighted": createOptionIndex === highlightedIndex ? "" : void 0,
|
|
317
317
|
"data-index": createOptionIndex,
|
|
318
318
|
disabled: isCreating,
|
|
@@ -328,11 +328,11 @@ const InputSearch = ({ className, createOptionLabel = defaultCreateOptionLabel,
|
|
|
328
328
|
children: isCreating ? /* @__PURE__ */ jsxs("span", {
|
|
329
329
|
className: "gap-2 flex items-center",
|
|
330
330
|
children: [/* @__PURE__ */ jsx(LoaderIcon, {
|
|
331
|
-
className: "
|
|
331
|
+
className: "motion-safe:animate-spin shrink-0",
|
|
332
332
|
size: 16
|
|
333
333
|
}), /* @__PURE__ */ jsx("span", { children: creatingLabel })]
|
|
334
334
|
}) : /* @__PURE__ */ jsx("span", {
|
|
335
|
-
className: "gap-2 flex items-center
|
|
335
|
+
className: "gap-2 min-w-0 flex items-center",
|
|
336
336
|
children: createOptionLabel(trimmedQuery)
|
|
337
337
|
})
|
|
338
338
|
})] })
|
package/dist/InputSearch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputSearch.js","names":[],"sources":["../src/components/InputSearch/InputSearch.tsx"],"sourcesContent":["import { CloseCircleIcon, ErrorIcon, LoaderIcon, PlusIcon, SearchIcon, WarningIcon } from '@components/Icons'\nimport { Label } from '@components/Label/Label'\nimport { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { useAutoDropdownHorizontalShift } from '@utils/dropdownPositioning'\nimport {\n EmptyState,\n ErrorMessage,\n WarningMessage,\n getAriaProps,\n getDropdownSurfaceClasses,\n getDropdownWidthStyles,\n getErrorMessageId,\n getFormFieldCSSProperties,\n getInputClasses,\n getOptionClasses,\n getPasswordManagerIgnoreProps,\n getWarningMessageId,\n useFormFieldId,\n useFormFieldState,\n type BaseFormFieldProps,\n type BaseOption,\n type DropdownWidth,\n type FormFieldState,\n} from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, type CSSProperties, type KeyboardEvent, type ReactNode, type Ref } from 'react'\nimport { createPortal } from 'react-dom'\n\nexport type InputSearchOption = BaseOption\n\nexport interface InputSearchProps extends Omit<BaseFormFieldProps, 'onChange' | 'state'> {\n className?: string\n createOptionLabel?: (query: string) => ReactNode\n creatingLabel?: string\n defaultValue?: string\n dropdownWidth?: DropdownWidth\n emptyMessage?: string\n hideSearchIcon?: boolean\n isCreating?: boolean\n labelClassName?: string\n onChange?: (value: string) => void\n onCreate?: (query: string) => void\n onValueChange?: (value: string) => void\n openOnFocus?: boolean\n options: InputSearchOption[]\n placeholder?: string\n renderOption?: (option: InputSearchOption) => ReactNode\n state?: Exclude<FormFieldState, 'disabled'>\n value?: string\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nconst defaultCreateOptionLabel = (query: string): ReactNode => (\n <>\n <PlusIcon size={16} className='shrink-0' />\n <span className='truncate'>\n Create <span className='font-semibold'>“{query}”</span>\n </span>\n </>\n)\n\nexport const InputSearch = ({\n className,\n createOptionLabel = defaultCreateOptionLabel,\n creatingLabel = 'Creating…',\n defaultValue = '',\n disabled,\n dropdownWidth = 'trigger',\n emptyMessage = 'No options found',\n errorMessage,\n hideSearchIcon = false,\n id,\n isCreating = false,\n label,\n labelClassName,\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n onCreate,\n onValueChange,\n openOnFocus = false,\n options,\n placeholder = 'Search…',\n ref,\n renderOption,\n required,\n state = 'default',\n value: valueProp,\n warningMessage,\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n}: InputSearchProps & { ref?: Ref<HTMLDivElement> }) => {\n if (process.env.NODE_ENV !== 'production' && !label && !ariaLabel) {\n // eslint-disable-next-line no-console\n console.warn('InputSearch: provide either `label` or `aria-label` for an accessible name.')\n }\n\n const fieldId = useFormFieldId(id, name)\n const listboxId = `${fieldId}-listbox`\n const errorMessageId = getErrorMessageId(fieldId)\n const warningMessageId = getWarningMessageId(fieldId)\n const messageId = state === 'error' ? errorMessageId : state === 'warning' && warningMessage ? warningMessageId : undefined\n const { isDisabled, isLoading, isInvalid } = useFormFieldState(disabled, state)\n const ariaProps = getAriaProps(state, ariaDescribedBy, required, messageId)\n\n const [value, setValue] = useUncontrolledState<string>({\n value: valueProp,\n defaultValue,\n onChange: (nextValue) => {\n if (onChange) {\n onChange(nextValue)\n } else {\n onValueChange?.(nextValue)\n }\n },\n })\n\n const [query, setQuery] = useState('')\n const [isFocused, setIsFocused] = useState(false)\n const [highlightedIndex, setHighlightedIndex] = useState(-1)\n const [dropdownPosition, setDropdownPosition] = useState<{ top: number; left: number; width: number } | null>(null)\n const inputRef = useRef<HTMLInputElement>(null)\n const listRef = useRef<HTMLDivElement>(null)\n const blurTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const triggerRef = useRef<HTMLDivElement>(null)\n\n const selectedOption = useMemo(() => options.find((option) => option.value === value) ?? null, [options, value])\n\n useEffect(() => {\n if (!isFocused) {\n setQuery(selectedOption?.label ?? '')\n }\n }, [selectedOption, isFocused])\n\n const trimmedQuery = query.trim()\n\n const filteredOptions = useMemo(() => {\n if (trimmedQuery.length === 0) return options\n const lower = trimmedQuery.toLowerCase()\n return options.filter((option) => option.label.toLowerCase().includes(lower))\n }, [trimmedQuery, options])\n\n const exactMatch = useMemo(() => options.some((option) => option.label.toLowerCase() === trimmedQuery.toLowerCase()), [options, trimmedQuery])\n\n const showCreateOption = onCreate !== undefined && trimmedQuery.length > 0 && !exactMatch\n const createOptionIndex = showCreateOption ? filteredOptions.length : -1\n const totalItems = filteredOptions.length + (showCreateOption ? 1 : 0)\n const showDropdown = isFocused && !isDisabled && !isLoading && (openOnFocus || trimmedQuery.length > 0)\n const showEmptyState = showDropdown && totalItems === 0\n\n const { dropdownShiftStyle, recalculateDropdownPosition, setDropdownElement } = useAutoDropdownHorizontalShift(showDropdown)\n\n const updateDropdownPosition = useCallback(() => {\n const trigger = triggerRef.current\n if (!trigger) return\n const rect = trigger.getBoundingClientRect()\n setDropdownPosition({\n top: rect.bottom + 4,\n left: rect.left,\n width: rect.width,\n })\n recalculateDropdownPosition()\n }, [recalculateDropdownPosition])\n\n useLayoutEffect(() => {\n if (!showDropdown) {\n setDropdownPosition(null)\n return\n }\n updateDropdownPosition()\n const handle = () => updateDropdownPosition()\n window.addEventListener('scroll', handle, true)\n window.addEventListener('resize', handle)\n return () => {\n window.removeEventListener('scroll', handle, true)\n window.removeEventListener('resize', handle)\n }\n }, [showDropdown, updateDropdownPosition])\n\n useLayoutEffect(() => {\n if (!showDropdown) return\n updateDropdownPosition()\n }, [showDropdown, updateDropdownPosition, filteredOptions.length, showCreateOption])\n\n useEffect(() => {\n setHighlightedIndex(-1)\n }, [filteredOptions.length, showCreateOption])\n\n useEffect(() => {\n if (highlightedIndex < 0 || !listRef.current) return\n const element = listRef.current.querySelector<HTMLElement>(`[data-index='${highlightedIndex}']`)\n element?.scrollIntoView({ block: 'nearest' })\n }, [highlightedIndex])\n\n useEffect(\n () => () => {\n if (blurTimeoutRef.current !== null) {\n clearTimeout(blurTimeoutRef.current)\n }\n },\n [],\n )\n\n const commitSelection = useCallback(\n (option: InputSearchOption) => {\n if (option.disabled) return\n setValue(option.value)\n setQuery(option.label)\n setIsFocused(false)\n setHighlightedIndex(-1)\n inputRef.current?.blur()\n },\n [setValue],\n )\n\n const commitCreate = useCallback(() => {\n if (!onCreate || isCreating || trimmedQuery.length === 0) return\n onCreate(trimmedQuery)\n }, [onCreate, isCreating, trimmedQuery])\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n switch (event.key) {\n case 'ArrowDown': {\n if (totalItems === 0) return\n event.preventDefault()\n setHighlightedIndex((prev) => (prev < totalItems - 1 ? prev + 1 : prev))\n break\n }\n case 'ArrowUp': {\n if (totalItems === 0) return\n event.preventDefault()\n setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : 0))\n break\n }\n case 'Enter': {\n if (totalItems === 0) return\n event.preventDefault()\n if (highlightedIndex >= 0 && highlightedIndex < filteredOptions.length) {\n const option = filteredOptions[highlightedIndex]\n if (option) commitSelection(option)\n } else if (highlightedIndex === createOptionIndex && !isCreating) {\n commitCreate()\n }\n break\n }\n case 'Escape': {\n event.preventDefault()\n setIsFocused(false)\n setHighlightedIndex(-1)\n if (selectedOption) setQuery(selectedOption.label)\n inputRef.current?.blur()\n break\n }\n default:\n break\n }\n },\n [totalItems, filteredOptions, highlightedIndex, createOptionIndex, commitSelection, commitCreate, isCreating, selectedOption],\n )\n\n const handleFocus = useCallback(() => {\n if (blurTimeoutRef.current !== null) {\n clearTimeout(blurTimeoutRef.current)\n blurTimeoutRef.current = null\n }\n setIsFocused(true)\n setQuery('')\n }, [])\n\n const handleBlur = useCallback(() => {\n if (blurTimeoutRef.current !== null) {\n clearTimeout(blurTimeoutRef.current)\n }\n blurTimeoutRef.current = setTimeout(() => {\n blurTimeoutRef.current = null\n // Don't write to `query` here — the useEffect tied to selectedOption + isFocused\n // is the single source of truth for the visible query when the field isn't focused.\n // Setting it from this stale closure causes off-by-one display after selection.\n setIsFocused(false)\n setHighlightedIndex(-1)\n }, 150)\n }, [])\n\n const handleClear = useCallback(() => {\n setValue('')\n setQuery('')\n inputRef.current?.focus()\n }, [setValue])\n\n const showClearButton = !isLoading && !isDisabled && (value.length > 0 || (isFocused && query.length > 0))\n\n const { dropdownWidthMode, dropdownWidthStyle } = getDropdownWidthStyles({\n dropdownWidth,\n triggerWidth: '100%',\n })\n\n const inputClasses = cn(getInputClasses(state, className), 'pe-4', !hideSearchIcon && 'ps-11', showClearButton && 'pe-10!', state === 'loading' && 'cursor-wait')\n\n return (\n <div className='flex w-full flex-col' data-testid='spectral-input-search-container' ref={ref}>\n {label && (\n <Label className={cn('mb-2 block', labelClassName, isDisabled && 'cursor-not-allowed text-input-text--disabled')} data-testid='spectral-input-search-label' htmlFor={fieldId}>\n {label}\n </Label>\n )}\n\n <div className='relative' data-testid='spectral-input-search-wrapper' ref={triggerRef}>\n <div className='relative'>\n {!hideSearchIcon && (\n <span aria-hidden='true' className={cn('left-4 text-input-icon absolute top-1/2 -translate-y-1/2', isDisabled && 'text-input-text--disabled')} data-testid='spectral-input-search-icon'>\n <SearchIcon size={20} />\n </span>\n )}\n\n <input\n aria-activedescendant={highlightedIndex >= 0 ? `${fieldId}-option-${highlightedIndex}` : undefined}\n aria-autocomplete='list'\n aria-controls={listboxId}\n aria-expanded={showDropdown}\n // oxlint-disable-next-line jsx-a11y/role-supports-aria-props -- Valid per WAI-ARIA 1.2 Combobox pattern\n aria-haspopup='listbox'\n aria-label={ariaLabel ?? label}\n autoComplete='off'\n className={inputClasses}\n data-state={state}\n data-testid='spectral-input-search'\n disabled={isDisabled || isLoading}\n id={fieldId}\n name={name}\n onBlur={handleBlur}\n onChange={(event) => {\n setQuery(event.target.value)\n if (!isFocused) setIsFocused(true)\n }}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n ref={inputRef}\n required={required}\n role='combobox'\n style={getFormFieldCSSProperties() as CSSProperties}\n type='text'\n value={query}\n {...getPasswordManagerIgnoreProps('text')}\n {...ariaProps}\n />\n\n {showClearButton ? (\n <button\n aria-label={`Clear ${label ?? 'search'}`}\n className='right-4 text-input-icon hover:text-input-icon--hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-input-border--focus rounded-sm absolute top-1/2 -translate-y-1/2 cursor-pointer'\n data-testid='spectral-input-search-clear-button'\n onClick={handleClear}\n // Prevent input blur from firing before click resolves\n onMouseDown={(event) => event.preventDefault()}\n type='button'\n >\n <CloseCircleIcon size={20} />\n </button>\n ) : state === 'loading' ? (\n <div className='right-4 text-input-icon absolute top-1/2 -translate-y-1/2' data-testid='spectral-input-search-loading-icon'>\n <LoaderIcon className='motion-safe:animate-spin' size={20} />\n </div>\n ) : state === 'error' ? (\n <div className='right-4 text-danger-400 absolute top-1/2 -translate-y-1/2' data-testid='spectral-input-search-error-icon'>\n <ErrorIcon size={20} />\n </div>\n ) : state === 'warning' ? (\n <div className='right-4 text-warning-400 absolute top-1/2 -translate-y-1/2' data-testid='spectral-input-search-warning-icon'>\n <WarningIcon size={20} />\n </div>\n ) : null}\n </div>\n\n </div>\n\n {showDropdown && dropdownPosition && typeof document !== 'undefined'\n ? createPortal(\n <div\n className={cn('origin-top p-1 z-50 fixed', getDropdownSurfaceClasses(), 'max-h-72 overflow-hidden', 'motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:slide-in-from-top-2')}\n data-dropdown-width-mode={dropdownWidthMode}\n data-dropdown-width-value={dropdownWidthMode === 'custom' ? dropdownWidth : undefined}\n data-testid='spectral-input-search-content'\n ref={setDropdownElement}\n style={{\n top: `${dropdownPosition.top}px`,\n left: `${dropdownPosition.left}px`,\n ...(dropdownWidthMode === 'trigger' ? { width: `${dropdownPosition.width}px` } : (dropdownWidthStyle as CSSProperties)),\n ...dropdownShiftStyle,\n }}\n >\n <div\n className='max-h-[17.5rem] overflow-y-auto'\n id={listboxId}\n ref={listRef}\n // oxlint-disable-next-line jsx-a11y/prefer-tag-over-role -- WAI-ARIA combobox pattern requires role='listbox' on the popup\n role='listbox'\n >\n {showEmptyState ? (\n <EmptyState message={emptyMessage} />\n ) : (\n <>\n {filteredOptions.map((option, index) => {\n const isHighlighted = index === highlightedIndex\n const isSelected = option.value === value\n return (\n <button\n aria-selected={isSelected}\n className={cn(getOptionClasses(!!option.disabled, isHighlighted, isSelected), 'text-left')}\n data-highlighted={isHighlighted ? '' : undefined}\n data-index={index}\n data-testid='spectral-input-search-item'\n disabled={option.disabled}\n id={`${fieldId}-option-${index}`}\n key={option.value}\n onMouseDown={(event) => {\n event.preventDefault()\n commitSelection(option)\n }}\n onMouseEnter={() => setHighlightedIndex(index)}\n role='option'\n tabIndex={-1}\n type='button'\n >\n <span className='min-w-0 flex-1 truncate'>{renderOption ? renderOption(option) : option.label}</span>\n </button>\n )\n })}\n\n {showCreateOption && (\n <button\n aria-selected={createOptionIndex === highlightedIndex}\n className={cn(getOptionClasses(isCreating, createOptionIndex === highlightedIndex, false), 'gap-2 text-left text-accent font-medium')}\n data-highlighted={createOptionIndex === highlightedIndex ? '' : undefined}\n data-index={createOptionIndex}\n data-testid='spectral-input-search-create-option'\n disabled={isCreating}\n id={`${fieldId}-option-${createOptionIndex}`}\n onMouseDown={(event) => {\n event.preventDefault()\n commitCreate()\n }}\n onMouseEnter={() => setHighlightedIndex(createOptionIndex)}\n role='option'\n tabIndex={-1}\n type='button'\n >\n {isCreating ? (\n <span className='gap-2 flex items-center'>\n <LoaderIcon className='shrink-0 motion-safe:animate-spin' size={16} />\n <span>{creatingLabel}</span>\n </span>\n ) : (\n <span className='gap-2 flex items-center min-w-0'>{createOptionLabel(trimmedQuery)}</span>\n )}\n </button>\n )}\n </>\n )}\n </div>\n </div>,\n document.body,\n )\n : null}\n\n <ErrorMessage\n dataTestId='spectral-input-search-error-message'\n id={errorMessageId}\n message={isInvalid ? (errorMessage ?? null) : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'error'}\n />\n <WarningMessage\n dataTestId='spectral-input-search-warning-message'\n id={warningMessageId}\n message={state === 'warning' ? (warningMessage ?? null) : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'warning'}\n />\n </div>\n )\n}\nInputSearch.displayName = 'InputSearch'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InputSearch.js","names":[],"sources":["../src/components/InputSearch/InputSearch.tsx"],"sourcesContent":["import { CloseCircleIcon, ErrorIcon, LoaderIcon, PlusIcon, SearchIcon, WarningIcon } from '@components/Icons'\nimport { Label } from '@components/Label/Label'\nimport { useUncontrolledState } from '@hooks/useUncontrolledState'\nimport { useAutoDropdownHorizontalShift } from '@utils/dropdownPositioning'\nimport {\n EmptyState,\n ErrorMessage,\n WarningMessage,\n getAriaProps,\n getDropdownSurfaceClasses,\n getDropdownWidthStyles,\n getErrorMessageId,\n getFormFieldCSSProperties,\n getInputClasses,\n getOptionClasses,\n getPasswordManagerIgnoreProps,\n getWarningMessageId,\n useFormFieldId,\n useFormFieldState,\n type BaseFormFieldProps,\n type BaseOption,\n type DropdownWidth,\n type FormFieldState,\n} from '@utils/formFieldUtils'\nimport { cn } from '@utils/twUtils'\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, type CSSProperties, type KeyboardEvent, type ReactNode, type Ref } from 'react'\nimport { createPortal } from 'react-dom'\n\nexport type InputSearchOption = BaseOption\n\nexport interface InputSearchProps extends Omit<BaseFormFieldProps, 'onChange' | 'state'> {\n className?: string\n createOptionLabel?: (query: string) => ReactNode\n creatingLabel?: string\n defaultValue?: string\n dropdownWidth?: DropdownWidth\n emptyMessage?: string\n hideSearchIcon?: boolean\n isCreating?: boolean\n labelClassName?: string\n onChange?: (value: string) => void\n onCreate?: (query: string) => void\n onValueChange?: (value: string) => void\n openOnFocus?: boolean\n options: InputSearchOption[]\n placeholder?: string\n renderOption?: (option: InputSearchOption) => ReactNode\n state?: Exclude<FormFieldState, 'disabled'>\n value?: string\n warningMessage?: BaseFormFieldProps['errorMessage']\n}\n\nconst defaultCreateOptionLabel = (query: string): ReactNode => (\n <>\n <PlusIcon\n size={16}\n className='shrink-0'\n />\n <span className='truncate'>\n Create <span className='font-semibold'>“{query}”</span>\n </span>\n </>\n)\n\nexport const InputSearch = ({\n className,\n createOptionLabel = defaultCreateOptionLabel,\n creatingLabel = 'Creating…',\n defaultValue = '',\n disabled,\n dropdownWidth = 'trigger',\n emptyMessage = 'No options found',\n errorMessage,\n hideSearchIcon = false,\n id,\n isCreating = false,\n label,\n labelClassName,\n messageReserveLines = 1,\n messageReserveSpace = false,\n name,\n onChange,\n onCreate,\n onValueChange,\n openOnFocus = false,\n options,\n placeholder = 'Search…',\n ref,\n renderOption,\n required,\n state = 'default',\n value: valueProp,\n warningMessage,\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n}: InputSearchProps & { ref?: Ref<HTMLDivElement> }) => {\n if (process.env.NODE_ENV !== 'production' && !label && !ariaLabel) {\n // eslint-disable-next-line no-console\n console.warn('InputSearch: provide either `label` or `aria-label` for an accessible name.')\n }\n\n const fieldId = useFormFieldId(id, name)\n const listboxId = `${fieldId}-listbox`\n const errorMessageId = getErrorMessageId(fieldId)\n const warningMessageId = getWarningMessageId(fieldId)\n const messageId = state === 'error' ? errorMessageId : state === 'warning' && warningMessage ? warningMessageId : undefined\n const { isDisabled, isLoading, isInvalid } = useFormFieldState(disabled, state)\n const ariaProps = getAriaProps(state, ariaDescribedBy, required, messageId)\n\n const [value, setValue] = useUncontrolledState<string>({\n value: valueProp,\n defaultValue,\n onChange: (nextValue) => {\n if (onChange) {\n onChange(nextValue)\n } else {\n onValueChange?.(nextValue)\n }\n },\n })\n\n const [query, setQuery] = useState('')\n const [isFocused, setIsFocused] = useState(false)\n const [highlightedIndex, setHighlightedIndex] = useState(-1)\n const [dropdownPosition, setDropdownPosition] = useState<{ top: number; left: number; width: number } | null>(null)\n const inputRef = useRef<HTMLInputElement>(null)\n const listRef = useRef<HTMLDivElement>(null)\n const blurTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const triggerRef = useRef<HTMLDivElement>(null)\n\n const selectedOption = useMemo(() => options.find((option) => option.value === value) ?? null, [options, value])\n\n useEffect(() => {\n if (!isFocused) {\n setQuery(selectedOption?.label ?? '')\n }\n }, [selectedOption, isFocused])\n\n const trimmedQuery = query.trim()\n\n const filteredOptions = useMemo(() => {\n if (trimmedQuery.length === 0) return options\n const lower = trimmedQuery.toLowerCase()\n return options.filter((option) => option.label.toLowerCase().includes(lower))\n }, [trimmedQuery, options])\n\n const exactMatch = useMemo(() => options.some((option) => option.label.toLowerCase() === trimmedQuery.toLowerCase()), [options, trimmedQuery])\n\n const showCreateOption = onCreate !== undefined && trimmedQuery.length > 0 && !exactMatch\n const createOptionIndex = showCreateOption ? filteredOptions.length : -1\n const totalItems = filteredOptions.length + (showCreateOption ? 1 : 0)\n const showDropdown = isFocused && !isDisabled && !isLoading && (openOnFocus || trimmedQuery.length > 0)\n const showEmptyState = showDropdown && totalItems === 0\n\n const { dropdownShiftStyle, recalculateDropdownPosition, setDropdownElement } = useAutoDropdownHorizontalShift(showDropdown)\n\n const updateDropdownPosition = useCallback(() => {\n const trigger = triggerRef.current\n if (!trigger) return\n const rect = trigger.getBoundingClientRect()\n setDropdownPosition({\n top: rect.bottom + 4,\n left: rect.left,\n width: rect.width,\n })\n recalculateDropdownPosition()\n }, [recalculateDropdownPosition])\n\n useLayoutEffect(() => {\n if (!showDropdown) {\n setDropdownPosition(null)\n return\n }\n updateDropdownPosition()\n const handle = () => updateDropdownPosition()\n window.addEventListener('scroll', handle, true)\n window.addEventListener('resize', handle)\n return () => {\n window.removeEventListener('scroll', handle, true)\n window.removeEventListener('resize', handle)\n }\n }, [showDropdown, updateDropdownPosition])\n\n useLayoutEffect(() => {\n if (!showDropdown) return\n updateDropdownPosition()\n }, [showDropdown, updateDropdownPosition, filteredOptions.length, showCreateOption])\n\n useEffect(() => {\n setHighlightedIndex(-1)\n }, [filteredOptions.length, showCreateOption])\n\n useEffect(() => {\n if (highlightedIndex < 0 || !listRef.current) return\n const element = listRef.current.querySelector<HTMLElement>(`[data-index='${highlightedIndex}']`)\n element?.scrollIntoView({ block: 'nearest' })\n }, [highlightedIndex])\n\n useEffect(\n () => () => {\n if (blurTimeoutRef.current !== null) {\n clearTimeout(blurTimeoutRef.current)\n }\n },\n [],\n )\n\n const commitSelection = useCallback(\n (option: InputSearchOption) => {\n if (option.disabled) return\n setValue(option.value)\n setQuery(option.label)\n setIsFocused(false)\n setHighlightedIndex(-1)\n inputRef.current?.blur()\n },\n [setValue],\n )\n\n const commitCreate = useCallback(() => {\n if (!onCreate || isCreating || trimmedQuery.length === 0) return\n onCreate(trimmedQuery)\n }, [onCreate, isCreating, trimmedQuery])\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n switch (event.key) {\n case 'ArrowDown': {\n if (totalItems === 0) return\n event.preventDefault()\n setHighlightedIndex((prev) => (prev < totalItems - 1 ? prev + 1 : prev))\n break\n }\n case 'ArrowUp': {\n if (totalItems === 0) return\n event.preventDefault()\n setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : 0))\n break\n }\n case 'Enter': {\n if (totalItems === 0) return\n event.preventDefault()\n if (highlightedIndex >= 0 && highlightedIndex < filteredOptions.length) {\n const option = filteredOptions[highlightedIndex]\n if (option) commitSelection(option)\n } else if (highlightedIndex === createOptionIndex && !isCreating) {\n commitCreate()\n }\n break\n }\n case 'Escape': {\n event.preventDefault()\n setIsFocused(false)\n setHighlightedIndex(-1)\n if (selectedOption) setQuery(selectedOption.label)\n inputRef.current?.blur()\n break\n }\n default:\n break\n }\n },\n [totalItems, filteredOptions, highlightedIndex, createOptionIndex, commitSelection, commitCreate, isCreating, selectedOption],\n )\n\n const handleFocus = useCallback(() => {\n if (blurTimeoutRef.current !== null) {\n clearTimeout(blurTimeoutRef.current)\n blurTimeoutRef.current = null\n }\n setIsFocused(true)\n setQuery('')\n }, [])\n\n const handleBlur = useCallback(() => {\n if (blurTimeoutRef.current !== null) {\n clearTimeout(blurTimeoutRef.current)\n }\n blurTimeoutRef.current = setTimeout(() => {\n blurTimeoutRef.current = null\n // Don't write to `query` here — the useEffect tied to selectedOption + isFocused\n // is the single source of truth for the visible query when the field isn't focused.\n // Setting it from this stale closure causes off-by-one display after selection.\n setIsFocused(false)\n setHighlightedIndex(-1)\n }, 150)\n }, [])\n\n const handleClear = useCallback(() => {\n setValue('')\n setQuery('')\n inputRef.current?.focus()\n }, [setValue])\n\n const showClearButton = !isLoading && !isDisabled && (value.length > 0 || (isFocused && query.length > 0))\n\n const { dropdownWidthMode, dropdownWidthStyle } = getDropdownWidthStyles({\n dropdownWidth,\n triggerWidth: '100%',\n })\n\n const inputClasses = cn(getInputClasses(state, className), 'pe-4', !hideSearchIcon && 'ps-11', showClearButton && 'pe-10!', state === 'loading' && 'cursor-wait')\n\n return (\n <div\n className='flex w-full flex-col'\n data-testid='spectral-input-search-container'\n ref={ref}\n >\n {label && (\n <Label\n className={cn('mb-2 block', labelClassName, isDisabled && 'cursor-not-allowed text-input-text--disabled')}\n data-testid='spectral-input-search-label'\n htmlFor={fieldId}\n >\n {label}\n </Label>\n )}\n\n <div\n className='relative'\n data-testid='spectral-input-search-wrapper'\n ref={triggerRef}\n >\n <div className='relative'>\n {!hideSearchIcon && (\n <span\n aria-hidden='true'\n className={cn('left-4 text-input-icon absolute top-1/2 -translate-y-1/2', isDisabled && 'text-input-text--disabled')}\n data-testid='spectral-input-search-icon'\n >\n <SearchIcon size={20} />\n </span>\n )}\n\n <input\n aria-activedescendant={highlightedIndex >= 0 ? `${fieldId}-option-${highlightedIndex}` : undefined}\n aria-autocomplete='list'\n aria-controls={listboxId}\n aria-expanded={showDropdown}\n // oxlint-disable-next-line jsx-a11y/role-supports-aria-props -- Valid per WAI-ARIA 1.2 Combobox pattern\n aria-haspopup='listbox'\n aria-label={ariaLabel ?? label}\n autoComplete='off'\n className={inputClasses}\n data-state={state}\n data-testid='spectral-input-search'\n disabled={isDisabled || isLoading}\n id={fieldId}\n name={name}\n onBlur={handleBlur}\n onChange={(event) => {\n setQuery(event.target.value)\n if (!isFocused) setIsFocused(true)\n }}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n ref={inputRef}\n required={required}\n role='combobox'\n style={getFormFieldCSSProperties() as CSSProperties}\n type='text'\n value={query}\n {...getPasswordManagerIgnoreProps('text')}\n {...ariaProps}\n />\n\n {showClearButton ? (\n <button\n aria-label={`Clear ${label ?? 'search'}`}\n className='right-4 text-input-icon hover:text-input-icon--hover rounded-sm absolute top-1/2 -translate-y-1/2 cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-input-border--focus'\n data-testid='spectral-input-search-clear-button'\n onClick={handleClear}\n // Prevent input blur from firing before click resolves\n onMouseDown={(event) => event.preventDefault()}\n type='button'\n >\n <CloseCircleIcon size={20} />\n </button>\n ) : state === 'loading' ? (\n <div\n className='right-4 text-input-icon absolute top-1/2 -translate-y-1/2'\n data-testid='spectral-input-search-loading-icon'\n >\n <LoaderIcon\n className='motion-safe:animate-spin'\n size={20}\n />\n </div>\n ) : state === 'error' ? (\n <div\n className='right-4 absolute top-1/2 -translate-y-1/2 text-danger-400'\n data-testid='spectral-input-search-error-icon'\n >\n <ErrorIcon size={20} />\n </div>\n ) : state === 'warning' ? (\n <div\n className='right-4 absolute top-1/2 -translate-y-1/2 text-warning-400'\n data-testid='spectral-input-search-warning-icon'\n >\n <WarningIcon size={20} />\n </div>\n ) : null}\n </div>\n </div>\n\n {showDropdown && dropdownPosition && typeof document !== 'undefined'\n ? createPortal(\n <div\n className={cn('p-1 fixed z-50 origin-top', getDropdownSurfaceClasses(), 'max-h-72 overflow-hidden', 'motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-top-2 motion-safe:zoom-in-95')}\n data-dropdown-width-mode={dropdownWidthMode}\n data-dropdown-width-value={dropdownWidthMode === 'custom' ? dropdownWidth : undefined}\n data-testid='spectral-input-search-content'\n ref={setDropdownElement}\n style={{\n top: `${dropdownPosition.top}px`,\n left: `${dropdownPosition.left}px`,\n ...(dropdownWidthMode === 'trigger' ? { width: `${dropdownPosition.width}px` } : (dropdownWidthStyle as CSSProperties)),\n ...dropdownShiftStyle,\n }}\n >\n <div\n className='max-h-[17.5rem] overflow-y-auto'\n id={listboxId}\n ref={listRef}\n // oxlint-disable-next-line jsx-a11y/prefer-tag-over-role -- WAI-ARIA combobox pattern requires role='listbox' on the popup\n role='listbox'\n >\n {showEmptyState ? (\n <EmptyState message={emptyMessage} />\n ) : (\n <>\n {filteredOptions.map((option, index) => {\n const isHighlighted = index === highlightedIndex\n const isSelected = option.value === value\n return (\n <button\n aria-selected={isSelected}\n className={cn(getOptionClasses(!!option.disabled, isHighlighted, isSelected), 'text-left')}\n data-highlighted={isHighlighted ? '' : undefined}\n data-index={index}\n data-testid='spectral-input-search-item'\n disabled={option.disabled}\n id={`${fieldId}-option-${index}`}\n key={option.value}\n onMouseDown={(event) => {\n event.preventDefault()\n commitSelection(option)\n }}\n onMouseEnter={() => setHighlightedIndex(index)}\n role='option'\n tabIndex={-1}\n type='button'\n >\n <span className='min-w-0 flex-1 truncate'>{renderOption ? renderOption(option) : option.label}</span>\n </button>\n )\n })}\n\n {showCreateOption && (\n <button\n aria-selected={createOptionIndex === highlightedIndex}\n className={cn(getOptionClasses(isCreating, createOptionIndex === highlightedIndex, false), 'gap-2 font-medium text-left text-accent')}\n data-highlighted={createOptionIndex === highlightedIndex ? '' : undefined}\n data-index={createOptionIndex}\n data-testid='spectral-input-search-create-option'\n disabled={isCreating}\n id={`${fieldId}-option-${createOptionIndex}`}\n onMouseDown={(event) => {\n event.preventDefault()\n commitCreate()\n }}\n onMouseEnter={() => setHighlightedIndex(createOptionIndex)}\n role='option'\n tabIndex={-1}\n type='button'\n >\n {isCreating ? (\n <span className='gap-2 flex items-center'>\n <LoaderIcon\n className='motion-safe:animate-spin shrink-0'\n size={16}\n />\n <span>{creatingLabel}</span>\n </span>\n ) : (\n <span className='gap-2 min-w-0 flex items-center'>{createOptionLabel(trimmedQuery)}</span>\n )}\n </button>\n )}\n </>\n )}\n </div>\n </div>,\n document.body,\n )\n : null}\n\n <ErrorMessage\n dataTestId='spectral-input-search-error-message'\n id={errorMessageId}\n message={isInvalid ? (errorMessage ?? null) : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'error'}\n />\n <WarningMessage\n dataTestId='spectral-input-search-warning-message'\n id={warningMessageId}\n message={state === 'warning' ? (warningMessage ?? null) : null}\n messageReserveLines={messageReserveLines}\n messageReserveSpace={messageReserveSpace && state === 'warning'}\n />\n </div>\n )\n}\nInputSearch.displayName = 'InputSearch'\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoDA,MAAM,4BAA4B,UAChC,8CACE,oBAAC,UAAD;CACE,MAAM;CACN,WAAU;CACX,GACD,qBAAC,QAAD;CAAM,WAAU;WAAhB,CAA0B,WACjB,qBAAC,QAAD;EAAM,WAAU;YAAhB;GAAgC;GAAQ;GAAM;GAAa;IAC9D;GACN;AAGJ,MAAa,eAAe,EAC1B,WACA,oBAAoB,0BACpB,gBAAgB,aAChB,eAAe,IACf,UACA,gBAAgB,WAChB,eAAe,oBACf,cACA,iBAAiB,OACjB,IACA,aAAa,OACb,OACA,gBACA,sBAAsB,GACtB,sBAAsB,OACtB,MACA,UACA,UACA,eACA,cAAc,OACd,SACA,cAAc,WACd,KACA,cACA,UACA,QAAQ,WACR,OAAO,WACP,gBACA,oBAAoB,iBACpB,cAAc,gBACwC;AACtD,KAA6C,CAAC,SAAS,CAAC,UAEtD,SAAQ,KAAK,8EAA6E;CAG5F,MAAM,UAAU,eAAe,IAAI,KAAI;CACvC,MAAM,YAAY,GAAG,QAAQ;CAC7B,MAAM,iBAAiB,kBAAkB,QAAO;CAChD,MAAM,mBAAmB,oBAAoB,QAAO;CACpD,MAAM,YAAY,UAAU,UAAU,iBAAiB,UAAU,aAAa,iBAAiB,mBAAmB;CAClH,MAAM,EAAE,YAAY,WAAW,cAAc,kBAAkB,UAAU,MAAK;CAC9E,MAAM,YAAY,aAAa,OAAO,iBAAiB,UAAU,UAAS;CAE1E,MAAM,CAAC,OAAO,YAAY,qBAA6B;EACrD,OAAO;EACP;EACA,WAAW,cAAc;AACvB,OAAI,SACF,UAAS,UAAS;OAElB,iBAAgB,UAAS;;EAG9B,CAAA;CAED,MAAM,CAAC,OAAO,YAAY,SAAS,GAAE;CACrC,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAK;CAChD,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,GAAE;CAC3D,MAAM,CAAC,kBAAkB,uBAAuB,SAA8D,KAAI;CAClH,MAAM,WAAW,OAAyB,KAAI;CAC9C,MAAM,UAAU,OAAuB,KAAI;CAC3C,MAAM,iBAAiB,OAA6C,KAAI;CACxE,MAAM,aAAa,OAAuB,KAAI;CAE9C,MAAM,iBAAiB,cAAc,QAAQ,MAAM,WAAW,OAAO,UAAU,MAAM,IAAI,MAAM,CAAC,SAAS,MAAM,CAAA;AAE/G,iBAAgB;AACd,MAAI,CAAC,UACH,UAAS,gBAAgB,SAAS,GAAE;IAErC,CAAC,gBAAgB,UAAU,CAAA;CAE9B,MAAM,eAAe,MAAM,MAAK;CAEhC,MAAM,kBAAkB,cAAc;AACpC,MAAI,aAAa,WAAW,EAAG,QAAO;EACtC,MAAM,QAAQ,aAAa,aAAY;AACvC,SAAO,QAAQ,QAAQ,WAAW,OAAO,MAAM,aAAa,CAAC,SAAS,MAAM,CAAA;IAC3E,CAAC,cAAc,QAAQ,CAAA;CAE1B,MAAM,aAAa,cAAc,QAAQ,MAAM,WAAW,OAAO,MAAM,aAAa,KAAK,aAAa,aAAa,CAAC,EAAE,CAAC,SAAS,aAAa,CAAA;CAE7I,MAAM,mBAAmB,aAAa,UAAa,aAAa,SAAS,KAAK,CAAC;CAC/E,MAAM,oBAAoB,mBAAmB,gBAAgB,SAAS;CACtE,MAAM,aAAa,gBAAgB,UAAU,mBAAmB,IAAI;CACpE,MAAM,eAAe,aAAa,CAAC,cAAc,CAAC,cAAc,eAAe,aAAa,SAAS;CACrG,MAAM,iBAAiB,gBAAgB,eAAe;CAEtD,MAAM,EAAE,oBAAoB,6BAA6B,uBAAuB,+BAA+B,aAAY;CAE3H,MAAM,yBAAyB,kBAAkB;EAC/C,MAAM,UAAU,WAAW;AAC3B,MAAI,CAAC,QAAS;EACd,MAAM,OAAO,QAAQ,uBAAsB;AAC3C,sBAAoB;GAClB,KAAK,KAAK,SAAS;GACnB,MAAM,KAAK;GACX,OAAO,KAAK;GACb,CAAA;AACD,+BAA4B;IAC3B,CAAC,4BAA4B,CAAA;AAEhC,uBAAsB;AACpB,MAAI,CAAC,cAAc;AACjB,uBAAoB,KAAI;AACxB;;AAEF,0BAAuB;EACvB,MAAM,eAAe,wBAAuB;AAC5C,SAAO,iBAAiB,UAAU,QAAQ,KAAI;AAC9C,SAAO,iBAAiB,UAAU,OAAM;AACxC,eAAa;AACX,UAAO,oBAAoB,UAAU,QAAQ,KAAI;AACjD,UAAO,oBAAoB,UAAU,OAAM;;IAE5C,CAAC,cAAc,uBAAuB,CAAA;AAEzC,uBAAsB;AACpB,MAAI,CAAC,aAAc;AACnB,0BAAuB;IACtB;EAAC;EAAc;EAAwB,gBAAgB;EAAQ;EAAiB,CAAA;AAEnF,iBAAgB;AACd,sBAAoB,GAAE;IACrB,CAAC,gBAAgB,QAAQ,iBAAiB,CAAA;AAE7C,iBAAgB;AACd,MAAI,mBAAmB,KAAK,CAAC,QAAQ,QAAS;AAE9C,EADgB,QAAQ,QAAQ,cAA2B,gBAAgB,iBAAiB,IACrF,EAAE,eAAe,EAAE,OAAO,WAAW,CAAA;IAC3C,CAAC,iBAAiB,CAAA;AAErB,uBACc;AACV,MAAI,eAAe,YAAY,KAC7B,cAAa,eAAe,QAAO;IAGvC,EAAE,CACJ;CAEA,MAAM,kBAAkB,aACrB,WAA8B;AAC7B,MAAI,OAAO,SAAU;AACrB,WAAS,OAAO,MAAK;AACrB,WAAS,OAAO,MAAK;AACrB,eAAa,MAAK;AAClB,sBAAoB,GAAE;AACtB,WAAS,SAAS,MAAK;IAEzB,CAAC,SAAS,CACZ;CAEA,MAAM,eAAe,kBAAkB;AACrC,MAAI,CAAC,YAAY,cAAc,aAAa,WAAW,EAAG;AAC1D,WAAS,aAAY;IACpB;EAAC;EAAU;EAAY;EAAa,CAAA;CAEvC,MAAM,gBAAgB,aACnB,UAA2C;AAC1C,UAAQ,MAAM,KAAd;GACE,KAAK;AACH,QAAI,eAAe,EAAG;AACtB,UAAM,gBAAe;AACrB,yBAAqB,SAAU,OAAO,aAAa,IAAI,OAAO,IAAI,KAAK;AACvE;GAEF,KAAK;AACH,QAAI,eAAe,EAAG;AACtB,UAAM,gBAAe;AACrB,yBAAqB,SAAU,OAAO,IAAI,OAAO,IAAI,EAAE;AACvD;GAEF,KAAK;AACH,QAAI,eAAe,EAAG;AACtB,UAAM,gBAAe;AACrB,QAAI,oBAAoB,KAAK,mBAAmB,gBAAgB,QAAQ;KACtE,MAAM,SAAS,gBAAgB;AAC/B,SAAI,OAAQ,iBAAgB,OAAM;eACzB,qBAAqB,qBAAqB,CAAC,WACpD,eAAa;AAEf;GAEF,KAAK;AACH,UAAM,gBAAe;AACrB,iBAAa,MAAK;AAClB,wBAAoB,GAAE;AACtB,QAAI,eAAgB,UAAS,eAAe,MAAK;AACjD,aAAS,SAAS,MAAK;AACvB;GAEF,QACE;;IAGN;EAAC;EAAY;EAAiB;EAAkB;EAAmB;EAAiB;EAAc;EAAY;EAAe,CAC/H;CAEA,MAAM,cAAc,kBAAkB;AACpC,MAAI,eAAe,YAAY,MAAM;AACnC,gBAAa,eAAe,QAAO;AACnC,kBAAe,UAAU;;AAE3B,eAAa,KAAI;AACjB,WAAS,GAAE;IACV,EAAE,CAAA;CAEL,MAAM,aAAa,kBAAkB;AACnC,MAAI,eAAe,YAAY,KAC7B,cAAa,eAAe,QAAO;AAErC,iBAAe,UAAU,iBAAiB;AACxC,kBAAe,UAAU;AAIzB,gBAAa,MAAK;AAClB,uBAAoB,GAAE;KACrB,IAAG;IACL,EAAE,CAAA;CAEL,MAAM,cAAc,kBAAkB;AACpC,WAAS,GAAE;AACX,WAAS,GAAE;AACX,WAAS,SAAS,OAAM;IACvB,CAAC,SAAS,CAAA;CAEb,MAAM,kBAAkB,CAAC,aAAa,CAAC,eAAe,MAAM,SAAS,KAAM,aAAa,MAAM,SAAS;CAEvG,MAAM,EAAE,mBAAmB,uBAAuB,uBAAuB;EACvE;EACA,cAAc;EACf,CAAA;CAED,MAAM,eAAe,GAAG,gBAAgB,OAAO,UAAU,EAAE,QAAQ,CAAC,kBAAkB,SAAS,mBAAmB,UAAU,UAAU,aAAa,cAAa;AAEhK,QACE,qBAAC,OAAD;EACE,WAAU;EAEL;YAHP;GAKG,SACC,oBAAC,OAAD;IACE,WAAW,GAAG,cAAc,gBAAgB,cAAc,+CAA+C;IAEzG,SAAS;cAER;IACI;GAGT,oBAAC,OAAD;IACE,WAAU;IAEV,KAAK;cAEL,qBAAC,OAAD;KAAK,WAAU;eAAf;MACG,CAAC,kBACA,oBAAC,QAAD;OACE,eAAY;OACZ,WAAW,GAAG,4DAA4D,cAAc,4BAA4B;iBAGpH,oBAAC,YAAD,EAAY,MAAM,IAAK;OACnB;MAGR,oBAAC,SAAD;OACE,yBAAuB,oBAAoB,IAAI,GAAG,QAAQ,UAAU,qBAAqB;OACzF,qBAAkB;OAClB,iBAAe;OACf,iBAAe;OAEf,iBAAc;OACd,cAAY,aAAa;OACzB,cAAa;OACb,WAAW;OACX,cAAY;OAEZ,UAAU,cAAc;OACxB,IAAI;OACE;OACN,QAAQ;OACR,WAAW,UAAU;AACnB,iBAAS,MAAM,OAAO,MAAK;AAC3B,YAAI,CAAC,UAAW,cAAa,KAAI;;OAEnC,SAAS;OACT,WAAW;OACE;OACb,KAAK;OACK;OACV,MAAK;OACL,OAAO,2BAA2B;OAClC,MAAK;OACL,OAAO;OACP,GAAI,8BAA8B,OAAO;OACzC,GAAI;OACL;MAEA,kBACC,oBAAC,UAAD;OACE,cAAY,SAAS,SAAS;OAC9B,WAAU;OAEV,SAAS;OAET,cAAc,UAAU,MAAM,gBAAgB;OAC9C,MAAK;iBAEL,oBAAC,iBAAD,EAAiB,MAAM,IAAK;OACtB,IACN,UAAU,YACZ,oBAAC,OAAD;OACE,WAAU;iBAGV,oBAAC,YAAD;QACE,WAAU;QACV,MAAM;QACP;OACE,IACH,UAAU,UACZ,oBAAC,OAAD;OACE,WAAU;iBAGV,oBAAC,WAAD,EAAW,MAAM,IAAK;OACnB,IACH,UAAU,YACZ,oBAAC,OAAD;OACE,WAAU;iBAGV,oBAAC,aAAD,EAAa,MAAM,IAAK;OACrB,IACH;MACD;;IACF;GAEJ,gBAAgB,oBAAoB,OAAO,aAAa,cACrD,aACE,oBAAC,OAAD;IACE,WAAW,GAAG,6BAA6B,2BAA2B,EAAE,4BAA4B,sGAAsG;IAC1M,4BAA0B;IAC1B,6BAA2B,sBAAsB,WAAW,gBAAgB;IAE5E,KAAK;IACL,OAAO;KACL,KAAK,GAAG,iBAAiB,IAAI;KAC7B,MAAM,GAAG,iBAAiB,KAAK;KAC/B,GAAI,sBAAsB,YAAY,EAAE,OAAO,GAAG,iBAAiB,MAAM,KAAK,GAAI;KAClF,GAAG;KACJ;cAED,oBAAC,OAAD;KACE,WAAU;KACV,IAAI;KACJ,KAAK;KAEL,MAAK;eAEJ,iBACC,oBAAC,YAAD,EAAY,SAAS,cAAe,IAEpC,8CACG,gBAAgB,KAAK,QAAQ,UAAU;MACtC,MAAM,gBAAgB,UAAU;MAChC,MAAM,aAAa,OAAO,UAAU;AACpC,aACE,oBAAC,UAAD;OACE,iBAAe;OACf,WAAW,GAAG,iBAAiB,CAAC,CAAC,OAAO,UAAU,eAAe,WAAW,EAAE,YAAY;OAC1F,oBAAkB,gBAAgB,KAAK;OACvC,cAAY;OAEZ,UAAU,OAAO;OACjB,IAAI,GAAG,QAAQ,UAAU;OAEzB,cAAc,UAAU;AACtB,cAAM,gBAAe;AACrB,wBAAgB,OAAM;;OAExB,oBAAoB,oBAAoB,MAAM;OAC9C,MAAK;OACL,UAAU;OACV,MAAK;iBAEL,oBAAC,QAAD;QAAM,WAAU;kBAA2B,eAAe,aAAa,OAAO,GAAG,OAAO;QAAY;OAC9F,EAXD,OAAO,MAWN;OAEV,EAED,oBACC,oBAAC,UAAD;MACE,iBAAe,sBAAsB;MACrC,WAAW,GAAG,iBAAiB,YAAY,sBAAsB,kBAAkB,MAAM,EAAE,0CAA0C;MACrI,oBAAkB,sBAAsB,mBAAmB,KAAK;MAChE,cAAY;MAEZ,UAAU;MACV,IAAI,GAAG,QAAQ,UAAU;MACzB,cAAc,UAAU;AACtB,aAAM,gBAAe;AACrB,qBAAa;;MAEf,oBAAoB,oBAAoB,kBAAkB;MAC1D,MAAK;MACL,UAAU;MACV,MAAK;gBAEJ,aACC,qBAAC,QAAD;OAAM,WAAU;iBAAhB,CACE,oBAAC,YAAD;QACE,WAAU;QACV,MAAM;QACP,GACD,oBAAC,QAAD,YAAO,eAAoB,EACvB;WAEN,oBAAC,QAAD;OAAM,WAAU;iBAAmC,kBAAkB,aAAa;OAAO;MAErF,EAEV;KAED;IACD,GACN,SAAS,KACX,GACA;GAEJ,oBAAC,cAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,YAAa,gBAAgB,OAAQ;IACzB;IACrB,qBAAqB,uBAAuB,UAAU;IACvD;GACD,oBAAC,gBAAD;IACE,YAAW;IACX,IAAI;IACJ,SAAS,UAAU,YAAa,kBAAkB,OAAQ;IACrC;IACrB,qBAAqB,uBAAuB,UAAU;IACvD;GACE;;;AAGT,YAAY,cAAc"}
|
package/dist/Kbd.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Kbd.d.ts","names":[],"sources":["../src/components/Kbd/Kbd.tsx"],"mappings":";;;;;KAGY,SAAA;AAAA,UAEK,QAAA;EACf,SAAA;EACA,MAAA,GAAS,SAAA;EACT,cAAA;AAAA;AAAA,UAGe,aAAA;EACf,SAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"file":"Kbd.d.ts","names":[],"sources":["../src/components/Kbd/Kbd.tsx"],"mappings":";;;;;KAGY,SAAA;AAAA,UAEK,QAAA;EACf,SAAA;EACA,MAAA,GAAS,SAAA;EACT,cAAA;AAAA;AAAA,UAGe,aAAA;EACf,SAAA;AAAA;AAAA;EA4LoB,SAAA;EAAW,MAAA;EAAQ,cAAA;EAA0B,QAAA;EAAA,GAAa;AAAA,GAAS,QAAA,GAAW,cAAA,UAAqB,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA;;;;EA6B9F,SAAA;EAAA,GAAc;AAAA,GAAS,aAAA,GAAgB,cAAA,UAAqB,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA"}
|
package/dist/Kbd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Kbd.js","names":[],"sources":["../src/components/Kbd/Kbd.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ComponentProps } from 'react'\n\nexport type KbdSymbol = 'arrowLeft' | 'arrowRight' | 'arrowUp' | 'arrowDown' | 'command' | 'option' | 'shift' | 'control' | 'return' | 'delete'\n\nexport interface KbdProps {\n className?: string\n symbol?: KbdSymbol\n symbolPosition?: 'start' | 'end'\n}\n\nexport interface KbdGroupProps {\n className?: string\n}\n\nconst symbolMap = {\n arrowLeft: (\n <svg
|
|
1
|
+
{"version":3,"file":"Kbd.js","names":[],"sources":["../src/components/Kbd/Kbd.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ComponentProps } from 'react'\n\nexport type KbdSymbol = 'arrowLeft' | 'arrowRight' | 'arrowUp' | 'arrowDown' | 'command' | 'option' | 'shift' | 'control' | 'return' | 'delete'\n\nexport interface KbdProps {\n className?: string\n symbol?: KbdSymbol\n symbolPosition?: 'start' | 'end'\n}\n\nexport interface KbdGroupProps {\n className?: string\n}\n\nconst symbolMap = {\n arrowLeft: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M10 5.75L3.75 12L10 18.25M4.5 12H20.25'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n ),\n arrowRight: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M14 5.75L20.25 12L14 18.25M19.5 12H3.75'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n ),\n arrowUp: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M5.75 10L12 3.75L18.25 10M12 20.25V4.5'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n ),\n arrowDown: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M18 14L12 20L6 14M12 19V4'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n ),\n command: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M9.25 9.25V6.5C9.25 4.98122 8.01878 3.75 6.5 3.75C4.98122 3.75 3.75 4.98122 3.75 6.5C3.75 8.01878 4.98122 9.25 6.5 9.25H9.25ZM9.25 9.25H14.75M9.25 9.25V14.75M14.75 9.25V6.5C14.75 4.98122 15.9812 3.75 17.5 3.75C19.0188 3.75 20.25 4.98122 20.25 6.5C20.25 8.01878 19.0188 9.25 17.5 9.25H14.75ZM14.75 9.25V14.75M14.75 14.75H9.25M14.75 14.75V17.5C14.75 19.0188 15.9812 20.25 17.5 20.25C19.0188 20.25 20.25 19.0188 20.25 17.5C20.25 15.9812 19.0188 14.75 17.5 14.75H14.75ZM9.25 14.75V17.5C9.25 19.0188 8.01878 20.25 6.5 20.25C4.98122 20.25 3.75 19.0188 3.75 17.5C3.75 15.9812 4.98122 14.75 6.5 14.75H9.25Z'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='square'\n />\n </svg>\n ),\n option: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M3.75 4.75H7.40962C7.77384 4.75 8.10925 4.94802 8.2852 5.26692L15.7148 18.7331C15.8907 19.052 16.2262 19.25 16.5904 19.25H20.25M15.75 4.75H20.25'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n ),\n shift: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M2.91032 11.5511L11.2848 2.98182C11.6771 2.5804 12.3229 2.5804 12.7152 2.98182L21.0897 11.5511C21.7085 12.1843 21.2599 13.25 20.3745 13.25H17.1316V19.25C17.1316 19.8023 16.6839 20.25 16.1316 20.25H7.86842C7.31614 20.25 6.86842 19.8023 6.86842 19.25V13.25H3.62551C2.74013 13.25 2.2915 12.1843 2.91032 11.5511Z'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='square'\n strokeLinejoin='round'\n />\n </svg>\n ),\n control: (\n <svg\n className='-translate-y-0.5'\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M8 13.9999L11.6464 10.3535C11.8417 10.1582 12.1583 10.1582 12.3536 10.3535L16 13.9999'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n ),\n return: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n fillRule='evenodd'\n clipRule='evenodd'\n d='M20.25 4C19.8358 4 19.5 4.33579 19.5 4.75V14.25C19.5 14.3881 19.3881 14.5 19.25 14.5H5.56066L8.28033 11.7803C8.57322 11.4874 8.57322 11.0126 8.28033 10.7197C7.98744 10.4268 7.51256 10.4268 7.21967 10.7197L3.21967 14.7197C2.92678 15.0126 2.92678 15.4874 3.21967 15.7803L7.21967 19.7803C7.51256 20.0732 7.98744 20.0732 8.28033 19.7803C8.57322 19.4874 8.57322 19.0126 8.28033 18.7197L5.56066 16H19.25C20.2165 16 21 15.2165 21 14.25V4.75C21 4.33579 20.6642 4 20.25 4Z'\n fill='currentColor'\n />\n </svg>\n ),\n delete: (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n >\n <path\n d='M14.9988 9.75L12.7488 12M12.7488 12L10.4988 14.25M12.7488 12L10.4988 9.75M12.7488 12L14.9988 14.25M6.55509 4.75H20.2488C20.8011 4.75 21.2488 5.19772 21.2488 5.75V18.25C21.2488 18.8023 20.8011 19.25 20.2488 19.25H6.55509C6.2092 19.25 5.88786 19.0712 5.70545 18.7774L1.82614 12.5274C1.62566 12.2044 1.62566 11.7956 1.82614 11.4726L5.70545 5.22264C5.88786 4.92875 6.2092 4.75 6.55509 4.75Z'\n stroke='currentColor'\n strokeWidth='1.5'\n strokeLinecap='round'\n strokeLinejoin='round'\n />\n </svg>\n ),\n} as const\n\nconst symbolLabelMap: Record<KbdSymbol, string> = {\n arrowLeft: 'Left Arrow',\n arrowRight: 'Right Arrow',\n arrowUp: 'Up Arrow',\n arrowDown: 'Down Arrow',\n command: 'Command',\n option: 'Option',\n shift: 'Shift',\n control: 'Control',\n return: 'Return',\n delete: 'Delete',\n}\n\nexport const Kbd = ({ className, symbol, symbolPosition = 'start', children, ...props }: KbdProps & ComponentProps<'kbd'>) => {\n const hasChildren = children !== undefined && children !== null && children !== ''\n const symbolElement = symbol && <span aria-hidden='true'>{symbolMap[symbol]}</span>\n\n // Derive aria-label from symbol when no children are provided, unless explicitly overridden\n const derivedAriaLabel = !hasChildren && symbol ? symbolLabelMap[symbol] : undefined\n const ariaLabel = props['aria-label'] ?? derivedAriaLabel\n\n return (\n <kbd\n className={cn(\n 'h-5 min-w-5 gap-1 rounded-sm px-1 text-xs font-medium pointer-events-none inline-flex w-fit items-center justify-center bg-kbd-bg font-mono! text-kbd-text select-none',\n `[&_svg:not([class*='size-'])]:size-3 in-data-[slot=tooltip-content]:bg-level-three`,\n className,\n )}\n data-slot='kbd'\n data-testid='spectral-kbd'\n {...props}\n aria-label={ariaLabel}\n >\n {symbolPosition === 'start' && symbolElement}\n {children}\n {symbolPosition === 'end' && symbolElement}\n </kbd>\n )\n}\n\nKbd.displayName = 'Kbd'\n\nexport const KbdGroup = ({ className, ...props }: KbdGroupProps & ComponentProps<'kbd'>) => {\n return (\n <kbd\n className={cn('gap-1 inline-flex items-center', className)}\n data-slot='kbd-group'\n data-testid='spectral-kbd-group'\n {...props}\n />\n )\n}\n\nKbdGroup.displayName = 'KbdGroup'\n"],"mappings":"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"}
|
package/dist/Label.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Label.js","names":[],"sources":["../src/components/Label/Label.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ComponentPropsWithoutRef, type Ref } from 'react'\n\nexport interface LabelProps extends ComponentPropsWithoutRef<'label'> {\n ref?: Ref<HTMLLabelElement>\n}\n\nexport const Label = ({\n className,\n ref,\n ...props\n}: LabelProps & {\n ref?: Ref<HTMLLabelElement>\n}) => {\n return (\n // eslint-disable-next-line jsx-a11y/label-has-associated-control\n <label
|
|
1
|
+
{"version":3,"file":"Label.js","names":[],"sources":["../src/components/Label/Label.tsx"],"sourcesContent":["import { cn } from '@utils/twUtils'\nimport { type ComponentPropsWithoutRef, type Ref } from 'react'\n\nexport interface LabelProps extends ComponentPropsWithoutRef<'label'> {\n ref?: Ref<HTMLLabelElement>\n}\n\nexport const Label = ({\n className,\n ref,\n ...props\n}: LabelProps & {\n ref?: Ref<HTMLLabelElement>\n}) => {\n return (\n // eslint-disable-next-line jsx-a11y/label-has-associated-control\n <label\n className={cn('text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', className)}\n data-slot='label'\n ref={ref}\n {...props}\n />\n )\n}\nLabel.displayName = 'Label'\n"],"mappings":";;;;;;AAOA,MAAa,SAAS,EACpB,WACA,KACA,GAAG,YAGC;AACJ,QAEE,oBAAC,SAAD;EACE,WAAW,GAAG,8FAA8F,UAAU;EACtH,aAAU;EACL;EACL,GAAI;EACJ;;AAGN,MAAM,cAAc"}
|
package/dist/Meter.js
CHANGED
|
@@ -10,7 +10,7 @@ const Meter = ({ className, dataTestId = "spectral-meter", label, max = 100, min
|
|
|
10
10
|
return /* @__PURE__ */ jsxs(Meter$1.Root, {
|
|
11
11
|
"aria-valuetext": `${value}%`,
|
|
12
12
|
...props,
|
|
13
|
-
className: cn("w-full flex
|
|
13
|
+
className: cn("gap-2 flex w-full flex-col", className),
|
|
14
14
|
"data-slot": "meter",
|
|
15
15
|
max,
|
|
16
16
|
min,
|
|
@@ -22,14 +22,14 @@ const Meter = ({ className, dataTestId = "spectral-meter", label, max = 100, min
|
|
|
22
22
|
"data-slot": "meter-label",
|
|
23
23
|
children: label
|
|
24
24
|
}), /* @__PURE__ */ jsx(Meter$1.Value, {
|
|
25
|
-
className: "text-text-
|
|
25
|
+
className: "text-xs text-text-primary tabular-nums",
|
|
26
26
|
"data-slot": "meter-value"
|
|
27
27
|
})]
|
|
28
28
|
}), /* @__PURE__ */ jsx(Meter$1.Track, {
|
|
29
|
-
className: "h-2 w-full
|
|
29
|
+
className: "h-2 flex w-full items-center overflow-hidden rounded-full bg-meter-track",
|
|
30
30
|
"data-slot": "meter-track",
|
|
31
31
|
children: /* @__PURE__ */ jsx(Meter$1.Indicator, {
|
|
32
|
-
className: "h-full origin-left transform-gpu transition-transform duration-150 ease-out
|
|
32
|
+
className: "h-full origin-left transform-gpu bg-meter-indicator transition-transform duration-150 ease-out",
|
|
33
33
|
"data-slot": "meter-indicator",
|
|
34
34
|
style: {
|
|
35
35
|
transform: `scaleX(${scale})`,
|
package/dist/Meter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Meter.js","names":[],"sources":["../src/components/Meter/Meter.tsx"],"sourcesContent":["import { Meter as MeterPrimitive } from '@base-ui/react/meter'\nimport { cn } from '@utils/twUtils'\nimport { type ComponentProps, type ReactNode } from 'react'\n\nexport interface MeterProps extends ComponentProps<typeof MeterPrimitive.Root> {\n dataTestId?: string\n label: ReactNode\n value: number\n}\n\nexport const Meter = ({ className, dataTestId = 'spectral-meter', label, max = 100, min = 0, value, ...props }: MeterProps) => {\n const scale = max === min ? 0 : Math.min(1, Math.max(0, (value - min) / (max - min)))\n\n return (\n <MeterPrimitive.Root
|
|
1
|
+
{"version":3,"file":"Meter.js","names":[],"sources":["../src/components/Meter/Meter.tsx"],"sourcesContent":["import { Meter as MeterPrimitive } from '@base-ui/react/meter'\nimport { cn } from '@utils/twUtils'\nimport { type ComponentProps, type ReactNode } from 'react'\n\nexport interface MeterProps extends ComponentProps<typeof MeterPrimitive.Root> {\n dataTestId?: string\n label: ReactNode\n value: number\n}\n\nexport const Meter = ({ className, dataTestId = 'spectral-meter', label, max = 100, min = 0, value, ...props }: MeterProps) => {\n const scale = max === min ? 0 : Math.min(1, Math.max(0, (value - min) / (max - min)))\n\n return (\n <MeterPrimitive.Root\n aria-valuetext={`${value}%`}\n {...props}\n className={cn('gap-2 flex w-full flex-col', className)}\n data-slot='meter'\n data-testid={dataTestId}\n max={max}\n min={min}\n value={value}\n >\n <div className='gap-2 flex items-center justify-between'>\n <MeterPrimitive.Label\n className='text-sm font-medium'\n data-slot='meter-label'\n >\n {label}\n </MeterPrimitive.Label>\n <MeterPrimitive.Value\n className='text-xs text-text-primary tabular-nums'\n data-slot='meter-value'\n />\n </div>\n <MeterPrimitive.Track\n className='h-2 flex w-full items-center overflow-hidden rounded-full bg-meter-track'\n data-slot='meter-track'\n >\n <MeterPrimitive.Indicator\n className='h-full origin-left transform-gpu bg-meter-indicator transition-transform duration-150 ease-out'\n data-slot='meter-indicator'\n style={{ transform: `scaleX(${scale})`, width: '100%' }}\n />\n </MeterPrimitive.Track>\n </MeterPrimitive.Root>\n )\n}\n"],"mappings":";;;;;;;AAUA,MAAa,SAAS,EAAE,WAAW,aAAa,kBAAkB,OAAO,MAAM,KAAK,MAAM,GAAG,OAAO,GAAG,YAAwB;CAC7H,MAAM,QAAQ,QAAQ,MAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,QAAQ,QAAQ,MAAM,KAAK,CAAA;AAEpF,QACE,qBAAC,QAAe,MAAhB;EACE,kBAAgB,GAAG,MAAM;EACzB,GAAI;EACJ,WAAW,GAAG,8BAA8B,UAAU;EACtD,aAAU;EAEL;EACA;EACE;YART,CAUE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,QAAe,OAAhB;IACE,WAAU;IACV,aAAU;cAET;IACmB,GACtB,oBAAC,QAAe,OAAhB;IACE,WAAU;IACV,aAAU;IACX,EACE;MACL,oBAAC,QAAe,OAAhB;GACE,WAAU;GACV,aAAU;aAEV,oBAAC,QAAe,WAAhB;IACE,WAAU;IACV,aAAU;IACV,OAAO;KAAE,WAAW,UAAU,MAAM;KAAI,OAAO;KAAQ;IACxD;GACmB,EACH"}
|