tempest-react-sdk 0.39.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.cjs +1 -1
- package/dist/access/access-control-context.cjs.map +1 -1
- package/dist/access/use-can.cjs.map +1 -1
- package/dist/app/AppProviders.cjs.map +1 -1
- package/dist/app/AppProviders.js.map +1 -1
- package/dist/audio/use-audio-recorder.cjs.map +1 -1
- package/dist/audio/use-audio.cjs.map +1 -1
- package/dist/audio/use-microphone.cjs.map +1 -1
- package/dist/auth/create-auth-store.cjs.map +1 -1
- package/dist/auth/lazy-with-retry.cjs.map +1 -1
- package/dist/auth/passkey.cjs.map +1 -1
- package/dist/auth/passkey.js.map +1 -1
- package/dist/auth/use-passkey.cjs.map +1 -1
- package/dist/br/BrazilMap.cjs +1 -1
- package/dist/br/BrazilMap.cjs.map +1 -1
- package/dist/br/BrazilMap.js +2 -2
- package/dist/br/BrazilMap.js.map +1 -1
- package/dist/br/BrazilStateCitySelect.cjs.map +1 -1
- package/dist/br/BrazilStateCitySelect.js.map +1 -1
- package/dist/br/BrazilStateMap.cjs +1 -1
- package/dist/br/BrazilStateMap.cjs.map +1 -1
- package/dist/br/BrazilStateMap.js +2 -2
- package/dist/br/BrazilStateMap.js.map +1 -1
- package/dist/br/MapLegend.cjs.map +1 -1
- package/dist/br/MapLegend.js.map +1 -1
- package/dist/br/MapMarkers.cjs.map +1 -1
- package/dist/br/MapMarkers.js.map +1 -1
- package/dist/br/MunicipalitySearch.cjs.map +1 -1
- package/dist/br/MunicipalitySearch.js.map +1 -1
- package/dist/br/PixQRCode.cjs.map +1 -1
- package/dist/br/PixQRCode.js.map +1 -1
- package/dist/br/use-map-hover.cjs.map +1 -1
- package/dist/br/use-map-zoom.cjs.map +1 -1
- package/dist/capture/media-recorder.cjs +1 -1
- package/dist/capture/media-recorder.js +2 -2
- package/dist/capture/use-barcode-scanner.cjs +1 -1
- package/dist/capture/use-barcode-scanner.cjs.map +1 -1
- package/dist/capture/use-barcode-scanner.js +2 -2
- package/dist/capture/use-barcode-scanner.js.map +1 -1
- package/dist/capture/use-screen-capture.cjs.map +1 -1
- package/dist/capture/use-speech-recognition.cjs.map +1 -1
- package/dist/capture/use-torch.cjs.map +1 -1
- package/dist/capture/use-video-recorder.cjs.map +1 -1
- package/dist/charts/AreaChart.cjs.map +1 -1
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.cjs.map +1 -1
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/LineChart.cjs.map +1 -1
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/PieChart.cjs.map +1 -1
- package/dist/charts/PieChart.js.map +1 -1
- package/dist/charts/RadarChart.cjs.map +1 -1
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/use-chart-colors.cjs.map +1 -1
- package/dist/components/AIChat/AIChat.cjs.map +1 -1
- package/dist/components/AIChat/AIChat.js.map +1 -1
- package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
- package/dist/components/AIChat/AIChatComposer.js.map +1 -1
- package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
- package/dist/components/AIChat/AIChatTurn.js.map +1 -1
- package/dist/components/Accordion/Accordion.cjs.map +1 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/Alert/Alert.cjs.map +1 -1
- package/dist/components/Alert/Alert.js.map +1 -1
- package/dist/components/AppBar/AppBar.cjs.map +1 -1
- package/dist/components/AppBar/AppBar.js.map +1 -1
- package/dist/components/AppShell/AppShell.cjs.map +1 -1
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -1
- package/dist/components/Avatar/Avatar.cjs.map +1 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.cjs.map +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.js.map +1 -1
- package/dist/components/Badge/Badge.cjs.map +1 -1
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Banner/Banner.cjs.map +1 -1
- package/dist/components/Banner/Banner.js.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.cjs.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.js.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.cjs.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist/components/Button/Button.cjs.map +1 -1
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.cjs +1 -1
- package/dist/components/Calendar/Calendar.cjs.map +1 -1
- package/dist/components/Calendar/Calendar.js +38 -41
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Card/Card.cjs.map +1 -1
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Carousel/Carousel.cjs.map +1 -1
- package/dist/components/Carousel/Carousel.js.map +1 -1
- package/dist/components/Chat/Chat.cjs.map +1 -1
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/Chat/ChatComposer.cjs.map +1 -1
- package/dist/components/Chat/ChatComposer.js.map +1 -1
- package/dist/components/Chat/chat-groups.cjs +1 -1
- package/dist/components/Chat/chat-groups.cjs.map +1 -1
- package/dist/components/Chat/chat-groups.js +2 -2
- package/dist/components/Chat/chat-groups.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.cjs.map +1 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/ChipInput/ChipInput.cjs.map +1 -1
- package/dist/components/ChipInput/ChipInput.js.map +1 -1
- package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
- package/dist/components/CodeBlock/CodeBlock.cjs.map +1 -1
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -1
- package/dist/components/Collapsible/Collapsible.cjs.map +1 -1
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Combobox/Combobox.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.cjs.map +1 -1
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.cjs.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/CopyButton/CopyButton.cjs.map +1 -1
- package/dist/components/CopyButton/CopyButton.js.map +1 -1
- package/dist/components/DataList/DataList.cjs.map +1 -1
- package/dist/components/DataList/DataList.js.map +1 -1
- package/dist/components/DataTable/DataTable.cjs +1 -1
- package/dist/components/DataTable/DataTable.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.js +2 -2
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/EditableCell.cjs.map +1 -1
- package/dist/components/DataTable/EditableCell.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.cjs.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.cjs.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.cjs.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -1
- package/dist/components/Divider/Divider.cjs.map +1 -1
- package/dist/components/Divider/Divider.js.map +1 -1
- package/dist/components/Drawer/Drawer.cjs.map +1 -1
- package/dist/components/Drawer/Drawer.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/Dropzone/Dropzone.cjs.map +1 -1
- package/dist/components/Dropzone/Dropzone.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.cjs.map +1 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.cjs.map +1 -1
- package/dist/components/ErrorState/ErrorState.js.map +1 -1
- package/dist/components/FileUpload/FileUpload.cjs +1 -1
- package/dist/components/FileUpload/FileUpload.cjs.map +1 -1
- package/dist/components/FileUpload/FileUpload.js +1 -1
- package/dist/components/FileUpload/FileUpload.js.map +1 -1
- package/dist/components/FilterBar/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar/FilterBar.js.map +1 -1
- package/dist/components/FloatingActionButton/FloatingActionButton.cjs.map +1 -1
- package/dist/components/FloatingActionButton/FloatingActionButton.js.map +1 -1
- package/dist/components/Form/Form.cjs.map +1 -1
- package/dist/components/Form/Form.js.map +1 -1
- package/dist/components/HoverCard/HoverCard.cjs.map +1 -1
- package/dist/components/HoverCard/HoverCard.js.map +1 -1
- package/dist/components/Image/Image.cjs.map +1 -1
- package/dist/components/ImageCropper/ImageCropper.cjs +1 -1
- package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -1
- package/dist/components/ImageCropper/ImageCropper.js +1 -1
- package/dist/components/ImageCropper/ImageCropper.js.map +1 -1
- package/dist/components/Input/Input.cjs.map +1 -1
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.cjs.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.js.map +1 -1
- package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
- package/dist/components/InstallButton/InstallButton.js.map +1 -1
- package/dist/components/Kanban/Kanban.cjs.map +1 -1
- package/dist/components/Kanban/Kanban.js.map +1 -1
- package/dist/components/Label/Label.cjs.map +1 -1
- package/dist/components/Label/Label.js.map +1 -1
- package/dist/components/Lightbox/Lightbox.cjs.map +1 -1
- package/dist/components/Lightbox/Lightbox.js.map +1 -1
- package/dist/components/ListTile/ListTile.cjs.map +1 -1
- package/dist/components/ListTile/ListTile.js.map +1 -1
- package/dist/components/Markdown/Markdown.cjs +1 -1
- package/dist/components/Markdown/Markdown.cjs.map +1 -1
- package/dist/components/Markdown/Markdown.js +2 -2
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Masonry/Masonry.cjs.map +1 -1
- package/dist/components/Masonry/Masonry.js.map +1 -1
- package/dist/components/Menubar/Menubar.cjs.map +1 -1
- package/dist/components/Menubar/Menubar.js.map +1 -1
- package/dist/components/Modal/Modal.cjs.map +1 -1
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/ModalsManager/ModalsManager.cjs.map +1 -1
- package/dist/components/ModalsManager/ModalsManager.js.map +1 -1
- package/dist/components/Money/Money.cjs.map +1 -1
- package/dist/components/Money/Money.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/components/NProgress/NProgress.cjs.map +1 -1
- package/dist/components/Navbar/Navbar.cjs.map +1 -1
- package/dist/components/Navbar/Navbar.js.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.cjs.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.js.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.cjs.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.js.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.cjs.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -1
- package/dist/components/NotificationCenter/use-notification-inbox.cjs.map +1 -1
- package/dist/components/OfflineIndicator/OfflineIndicator.cjs.map +1 -1
- package/dist/components/OfflineIndicator/OfflineIndicator.js.map +1 -1
- package/dist/components/Page/Page.cjs.map +1 -1
- package/dist/components/Page/Page.js.map +1 -1
- package/dist/components/Pagination/Pagination.cjs.map +1 -1
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/PasswordInput/PasswordInput.cjs.map +1 -1
- package/dist/components/PasswordInput/PasswordInput.js.map +1 -1
- package/dist/components/PinInput/PinInput.cjs.map +1 -1
- package/dist/components/PinInput/PinInput.js.map +1 -1
- package/dist/components/Popover/Popover.cjs.map +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Portal/Portal.cjs.map +1 -1
- package/dist/components/Progress/Progress.cjs.map +1 -1
- package/dist/components/Progress/Progress.js.map +1 -1
- package/dist/components/QRCode/QRCode.cjs.map +1 -1
- package/dist/components/QRCode/QRCode.js.map +1 -1
- package/dist/components/Radio/Radio.cjs.map +1 -1
- package/dist/components/Radio/Radio.js.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.cjs.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.js.map +1 -1
- package/dist/components/RatingStars/RatingStars.cjs.map +1 -1
- package/dist/components/RatingStars/RatingStars.js.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.cjs.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.js.map +1 -1
- package/dist/components/RelativeTime/RelativeTime.cjs.map +1 -1
- package/dist/components/RelativeTime/RelativeTime.js.map +1 -1
- package/dist/components/Resizable/Resizable.cjs.map +1 -1
- package/dist/components/Resizable/Resizable.js.map +1 -1
- package/dist/components/Scheduler/Scheduler.cjs.map +1 -1
- package/dist/components/Scheduler/Scheduler.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.cjs.map +1 -1
- package/dist/components/SearchBar/SearchBar.cjs.map +1 -1
- package/dist/components/SearchBar/SearchBar.js.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.cjs.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
- package/dist/components/Select/Select.cjs.map +1 -1
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
- package/dist/components/Sidebar/Sidebar.js.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.js.map +1 -1
- package/dist/components/Slider/Slider.cjs.map +1 -1
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Sparkline/Sparkline.cjs.map +1 -1
- package/dist/components/Sparkline/Sparkline.js.map +1 -1
- package/dist/components/Spinner/Spinner.cjs.map +1 -1
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/Stat/Stat.cjs.map +1 -1
- package/dist/components/Stat/Stat.js.map +1 -1
- package/dist/components/Stepper/Stepper.cjs.map +1 -1
- package/dist/components/Stepper/Stepper.js.map +1 -1
- package/dist/components/StepperInput/StepperInput.cjs.map +1 -1
- package/dist/components/StepperInput/StepperInput.js.map +1 -1
- package/dist/components/Switch/Switch.cjs.map +1 -1
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
- package/dist/components/Table/Table.cjs.map +1 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Tabs/Tabs.cjs.map +1 -1
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Tag/Tag.cjs.map +1 -1
- package/dist/components/Tag/Tag.js.map +1 -1
- package/dist/components/Textarea/Textarea.cjs.map +1 -1
- package/dist/components/Textarea/Textarea.js.map +1 -1
- package/dist/components/TimePicker/TimePicker.cjs.map +1 -1
- package/dist/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/components/Timeline/Timeline.cjs.map +1 -1
- package/dist/components/Timeline/Timeline.js.map +1 -1
- package/dist/components/Toast/ToastProvider.cjs.map +1 -1
- package/dist/components/Toast/ToastProvider.js.map +1 -1
- package/dist/components/Toggle/Toggle.cjs.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.cjs.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tour/Tour.cjs.map +1 -1
- package/dist/components/Tour/Tour.js.map +1 -1
- package/dist/components/Transfer/Transfer.cjs.map +1 -1
- package/dist/components/Transfer/Transfer.js.map +1 -1
- package/dist/components/TreeView/TreeView.cjs +1 -1
- package/dist/components/TreeView/TreeView.cjs.map +1 -1
- package/dist/components/TreeView/TreeView.js +1 -4
- package/dist/components/TreeView/TreeView.js.map +1 -1
- package/dist/components/UpdatePrompt/UpdatePrompt.cjs.map +1 -1
- package/dist/components/UpdatePrompt/UpdatePrompt.js.map +1 -1
- package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
- package/dist/components/VirtualList/VirtualList.js.map +1 -1
- package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
- package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
- package/dist/components/VisuallyHidden/VisuallyHidden.cjs.map +1 -1
- package/dist/components/Wizard/Wizard.cjs.map +1 -1
- package/dist/components/Wizard/Wizard.js.map +1 -1
- package/dist/data/data-provider-context.cjs.map +1 -1
- package/dist/data/use-resource.cjs.map +1 -1
- package/dist/editor/RichTextEditor.cjs.map +1 -1
- package/dist/editor/RichTextEditor.js.map +1 -1
- package/dist/error-boundary/use-error-handler.cjs.map +1 -1
- package/dist/feature-flags/FeatureFlagsProvider.cjs.map +1 -1
- package/dist/forms/FormField.cjs.map +1 -1
- package/dist/forms/masked-inputs.cjs +1 -1
- package/dist/forms/masked-inputs.cjs.map +1 -1
- package/dist/forms/masked-inputs.js +1 -1
- package/dist/forms/masked-inputs.js.map +1 -1
- package/dist/forms/use-viacep.cjs.map +1 -1
- package/dist/forms/use-zod-form.cjs.map +1 -1
- package/dist/forms/zod-resolver.cjs.map +1 -1
- package/dist/forms/zod-resolver.js.map +1 -1
- package/dist/geo/TrajectoryMap.cjs.map +1 -1
- package/dist/geo/TrajectoryMap.js.map +1 -1
- package/dist/geo/leaflet-map.cjs.map +1 -1
- package/dist/geo/leaflet-map.js.map +1 -1
- package/dist/geo/use-position-tracker.cjs.map +1 -1
- package/dist/hooks/use-announce.cjs.map +1 -1
- package/dist/hooks/use-async.cjs.map +1 -1
- package/dist/hooks/use-before-install-prompt.cjs.map +1 -1
- package/dist/hooks/use-breakpoint.cjs.map +1 -1
- package/dist/hooks/use-click-outside.cjs.map +1 -1
- package/dist/hooks/use-client-filter.cjs.map +1 -1
- package/dist/hooks/use-clipboard.cjs.map +1 -1
- package/dist/hooks/use-counter.cjs.map +1 -1
- package/dist/hooks/use-debounce.cjs.map +1 -1
- package/dist/hooks/use-deep-memo.cjs.map +1 -1
- package/dist/hooks/use-disclosure.cjs.map +1 -1
- package/dist/hooks/use-document-visibility.cjs.map +1 -1
- package/dist/hooks/use-event-listener.cjs.map +1 -1
- package/dist/hooks/use-geolocation.cjs.map +1 -1
- package/dist/hooks/use-hover.cjs.map +1 -1
- package/dist/hooks/use-idle.cjs.map +1 -1
- package/dist/hooks/use-install-prompt.cjs +1 -1
- package/dist/hooks/use-install-prompt.cjs.map +1 -1
- package/dist/hooks/use-install-prompt.js +1 -1
- package/dist/hooks/use-install-prompt.js.map +1 -1
- package/dist/hooks/use-intersection-observer.cjs.map +1 -1
- package/dist/hooks/use-interval.cjs.map +1 -1
- package/dist/hooks/use-is-first-render.cjs.map +1 -1
- package/dist/hooks/use-keyboard-shortcut.cjs +1 -1
- package/dist/hooks/use-keyboard-shortcut.cjs.map +1 -1
- package/dist/hooks/use-keyboard-shortcut.js +1 -1
- package/dist/hooks/use-keyboard-shortcut.js.map +1 -1
- package/dist/hooks/use-list-state.cjs.map +1 -1
- package/dist/hooks/use-local-storage.cjs.map +1 -1
- package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
- package/dist/hooks/use-long-press.cjs.map +1 -1
- package/dist/hooks/use-map.cjs.map +1 -1
- package/dist/hooks/use-media-devices.cjs.map +1 -1
- package/dist/hooks/use-media-permission.cjs.map +1 -1
- package/dist/hooks/use-media-query.cjs.map +1 -1
- package/dist/hooks/use-object-url.cjs.map +1 -1
- package/dist/hooks/use-online.cjs.map +1 -1
- package/dist/hooks/use-pagination.cjs.map +1 -1
- package/dist/hooks/use-previous.cjs.map +1 -1
- package/dist/hooks/use-queue.cjs.map +1 -1
- package/dist/hooks/use-resize-observer.cjs.map +1 -1
- package/dist/hooks/use-scroll-overflow.cjs.map +1 -1
- package/dist/hooks/use-service-worker-update.cjs.map +1 -1
- package/dist/hooks/use-set.cjs.map +1 -1
- package/dist/hooks/use-sortable.cjs +1 -1
- package/dist/hooks/use-sortable.cjs.map +1 -1
- package/dist/hooks/use-sortable.js +0 -2
- package/dist/hooks/use-sortable.js.map +1 -1
- package/dist/hooks/use-stable-callback.cjs.map +1 -1
- package/dist/hooks/use-storage-estimate.cjs.map +1 -1
- package/dist/hooks/use-throttle.cjs.map +1 -1
- package/dist/hooks/use-timeout.cjs.map +1 -1
- package/dist/hooks/use-toggle.cjs.map +1 -1
- package/dist/hooks/use-window-size.cjs.map +1 -1
- package/dist/http/api-client.cjs +1 -1
- package/dist/http/api-client.cjs.map +1 -1
- package/dist/http/api-client.js +7 -5
- package/dist/http/api-client.js.map +1 -1
- package/dist/http/resumable-upload.cjs +1 -1
- package/dist/http/resumable-upload.cjs.map +1 -1
- package/dist/http/resumable-upload.js +1 -1
- package/dist/http/resumable-upload.js.map +1 -1
- package/dist/http/use-poll.cjs.map +1 -1
- package/dist/i18n/I18nProvider.cjs.map +1 -1
- package/dist/icons/Icon.cjs.map +1 -1
- package/dist/icons/IconProvider.cjs.map +1 -1
- package/dist/icons/icon-context.cjs.map +1 -1
- package/dist/icons/use-icon.cjs.map +1 -1
- package/dist/imaging/use-image-processing.cjs.map +1 -1
- package/dist/oauth/GoogleSignIn.cjs.map +1 -1
- package/dist/oauth/GoogleSignIn.js.map +1 -1
- package/dist/oauth/use-oauth-callback.cjs.map +1 -1
- package/dist/offline/use-offline-sync.cjs.map +1 -1
- package/dist/push/use-push-subscription.cjs.map +1 -1
- package/dist/query/QueryProvider.cjs.map +1 -1
- package/dist/query/constants.cjs +1 -1
- package/dist/query/constants.cjs.map +1 -1
- package/dist/query/constants.js +10 -10
- package/dist/query/constants.js.map +1 -1
- package/dist/query/create-query-keys.cjs +1 -1
- package/dist/query/create-query-keys.cjs.map +1 -1
- package/dist/query/create-query-keys.js +1 -1
- package/dist/query/create-query-keys.js.map +1 -1
- package/dist/query/offline-persistence.cjs.map +1 -1
- package/dist/query/use-cursor-query.cjs.map +1 -1
- package/dist/query/use-offline-mutation.cjs.map +1 -1
- package/dist/query/use-paginated-query.cjs.map +1 -1
- package/dist/router/AppRouter.cjs +1 -1
- package/dist/router/AppRouter.cjs.map +1 -1
- package/dist/router/AppRouter.js +7 -2
- package/dist/router/AppRouter.js.map +1 -1
- package/dist/sse/use-event-stream.cjs.map +1 -1
- package/dist/store/create-store.cjs.map +1 -1
- package/dist/tabular/use-tabular-predictor.cjs.map +1 -1
- package/dist/telemetry/TelemetryProvider.cjs.map +1 -1
- package/dist/tempest-react-sdk.d.ts +25 -26
- package/dist/theme/ThemeProvider.cjs.map +1 -1
- package/dist/theme/color.cjs +1 -1
- package/dist/theme/color.cjs.map +1 -1
- package/dist/theme/color.js +1 -1
- package/dist/theme/color.js.map +1 -1
- package/dist/utils/cn.cjs +1 -1
- package/dist/utils/cn.cjs.map +1 -1
- package/dist/utils/cn.js +1 -1
- package/dist/utils/cn.js.map +1 -1
- package/dist/utils/objects.cjs +1 -1
- package/dist/utils/objects.cjs.map +1 -1
- package/dist/utils/objects.js +1 -1
- package/dist/utils/objects.js.map +1 -1
- package/dist/utils/xlsx.cjs +1 -1
- package/dist/utils/xlsx.cjs.map +1 -1
- package/dist/utils/xlsx.js +3 -3
- package/dist/utils/xlsx.js.map +1 -1
- package/dist/vision/core/exceptions.cjs.map +1 -1
- package/dist/vision/core/exceptions.js.map +1 -1
- package/dist/vision/core/metadata.cjs +1 -1
- package/dist/vision/core/metadata.cjs.map +1 -1
- package/dist/vision/core/metadata.js +1 -1
- package/dist/vision/core/metadata.js.map +1 -1
- package/dist/vision/io/image.cjs +1 -1
- package/dist/vision/io/image.cjs.map +1 -1
- package/dist/vision/io/image.js +4 -2
- package/dist/vision/io/image.js.map +1 -1
- package/dist/vision/preprocess/image.cjs +1 -1
- package/dist/vision/preprocess/image.cjs.map +1 -1
- package/dist/vision/preprocess/image.js +4 -2
- package/dist/vision/preprocess/image.js.map +1 -1
- package/dist/vision/tasks/base.cjs +1 -1
- package/dist/vision/tasks/base.cjs.map +1 -1
- package/dist/vision/tasks/base.js +3 -1
- package/dist/vision/tasks/base.js.map +1 -1
- package/dist/vision/tasks/classifier.cjs +1 -1
- package/dist/vision/tasks/classifier.cjs.map +1 -1
- package/dist/vision/tasks/classifier.js +2 -2
- package/dist/vision/tasks/classifier.js.map +1 -1
- package/dist/vision/tasks/detectClassify.cjs +1 -1
- package/dist/vision/tasks/detectClassify.cjs.map +1 -1
- package/dist/vision/tasks/detectClassify.js +16 -15
- package/dist/vision/tasks/detectClassify.js.map +1 -1
- package/dist/vision/use-camera-stream.cjs.map +1 -1
- package/dist/vision/use-live-luminance.cjs.map +1 -1
- package/dist/vite/create-vite-config.cjs +1 -1
- package/dist/vite/create-vite-config.cjs.map +1 -1
- package/dist/vite/create-vite-config.js +3 -3
- package/dist/vite/create-vite-config.js.map +1 -1
- package/dist/vite/tempest-icons.cjs.map +1 -1
- package/dist/vite/tempest-pwa-dev-sw.cjs.map +1 -1
- package/dist/vite/tempest-pwa-icons.cjs.map +1 -1
- package/dist/ws/use-web-socket.cjs +1 -1
- package/dist/ws/use-web-socket.cjs.map +1 -1
- package/dist/ws/use-web-socket.js +5 -3
- package/dist/ws/use-web-socket.js.map +1 -1
- package/package.json +2 -2
- package/template/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.cjs","names":[],"sources":["../../../src/components/Page/Page.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — a page shell is slots: eyebrow, title, description,\n * actions, toolbar, footer and children, with padded as the one behavioural switch.\n * Slots are the component.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Page.module.css\";\n\nexport interface PageProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page title rendered as `<h1>`. */\n title?: ReactNode;\n /** Optional subtitle / breadcrumbs slot rendered above the title. */\n eyebrow?: ReactNode;\n /** Optional description rendered below the title. */\n description?: ReactNode;\n /** Right-side actions slot in the header (buttons, menus). */\n actions?: ReactNode;\n /** Sticky tab bar / filter row rendered just below the header. */\n toolbar?: ReactNode;\n /** Footer slot rendered at the bottom of the content area. */\n footer?: ReactNode;\n /** Page-level padding. Default `true`. */\n padded?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Page wrapper with header + (optional) toolbar + content + footer. Pairs\n * with `Container` when you want a max-width content well.\n *\n * @example\n * <Page title=\"Pedidos\" description=\"Acompanhe seus pedidos\" actions={<Button>Novo</Button>}>\n * <Table {...} />\n * </Page>\n */\nexport function Page({\n title,\n eyebrow,\n description,\n actions,\n toolbar,\n footer,\n padded = true,\n className,\n children,\n ...props\n}: PageProps) {\n const hasHeader = title || eyebrow || description || actions;\n return (\n <main className={cn(styles.page, padded && styles.padded, className)} {...props}>\n {hasHeader && (\n <header className={styles.header}>\n <div className={styles.headerText}>\n {eyebrow && <div className={styles.eyebrow}>{eyebrow}</div>}\n {title && <h1 className={styles.title}>{title}</h1>}\n {description && <p className={styles.description}>{description}</p>}\n </div>\n {actions && <div className={styles.actions}>{actions}</div>}\n </header>\n )}\n {toolbar && <div className={styles.toolbar}>{toolbar}</div>}\n <div className={styles.content}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </main>\n );\n}\n"],"mappings":"wGAoCA,SAAgB,EAAK,CACjB,QACA,UACA,cACA,UACA,UACA,SACA,SAAS,GACT,YACA,WACA,GAAG,GACO,CACV,IAAM,EAAY,GAAS,GAAW,GAAe,EACrD,OACI,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,GAAU,EAAA,QAAO,OAAQ,CAAS,EAAG,GAAI,
|
|
1
|
+
{"version":3,"file":"Page.cjs","names":[],"sources":["../../../src/components/Page/Page.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — a page shell is slots: eyebrow, title, description,\n * actions, toolbar, footer and children, with padded as the one behavioural switch.\n * Slots are the component.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Page.module.css\";\n\nexport interface PageProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page title rendered as `<h1>`. */\n title?: ReactNode;\n /** Optional subtitle / breadcrumbs slot rendered above the title. */\n eyebrow?: ReactNode;\n /** Optional description rendered below the title. */\n description?: ReactNode;\n /** Right-side actions slot in the header (buttons, menus). */\n actions?: ReactNode;\n /** Sticky tab bar / filter row rendered just below the header. */\n toolbar?: ReactNode;\n /** Footer slot rendered at the bottom of the content area. */\n footer?: ReactNode;\n /** Page-level padding. Default `true`. */\n padded?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Page wrapper with header + (optional) toolbar + content + footer. Pairs\n * with `Container` when you want a max-width content well.\n *\n * @example\n * <Page title=\"Pedidos\" description=\"Acompanhe seus pedidos\" actions={<Button>Novo</Button>}>\n * <Table {...} />\n * </Page>\n */\nexport function Page({\n title,\n eyebrow,\n description,\n actions,\n toolbar,\n footer,\n padded = true,\n className,\n children,\n ...props\n}: PageProps) {\n const hasHeader = title || eyebrow || description || actions;\n return (\n <main className={cn(styles.page, padded && styles.padded, className)} {...props}>\n {hasHeader && (\n <header className={styles.header}>\n <div className={styles.headerText}>\n {eyebrow && <div className={styles.eyebrow}>{eyebrow}</div>}\n {title && <h1 className={styles.title}>{title}</h1>}\n {description && <p className={styles.description}>{description}</p>}\n </div>\n {actions && <div className={styles.actions}>{actions}</div>}\n </header>\n )}\n {toolbar && <div className={styles.toolbar}>{toolbar}</div>}\n <div className={styles.content}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </main>\n );\n}\n"],"mappings":"wGAoCA,SAAgB,EAAK,CACjB,QACA,UACA,cACA,UACA,UACA,SACA,SAAS,GACT,YACA,WACA,GAAG,GACO,CACV,IAAM,EAAY,GAAS,GAAW,GAAe,EACrD,OACI,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,GAAU,EAAA,QAAO,OAAQ,CAAS,EAAG,GAAI,EAA1E,SAAA,CACK,IACG,EAAA,EAAA,KAAA,CAAC,SAAD,CAAQ,UAAW,EAAA,QAAO,OAA1B,SAAA,EACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,WAAvB,SAAA,CACK,IAAW,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,QAAU,SAAA,CAAa,CAAA,EACzD,IAAS,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAU,CAAA,EACjD,IAAe,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAA,QAAO,YAAc,SAAA,CAAe,CAAA,CACjE,CACJ,CAAA,EAAA,IAAW,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,QAAU,SAAA,CAAa,CAAA,CACtD,IAEX,IAAW,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,QAAU,SAAA,CAAa,CAAA,GAC1D,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,QAAU,UAAc,CAAA,EAC9C,IAAU,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,UAAW,EAAA,QAAO,OAAS,SAAA,CAAe,CAAA,CAC3D,GAEd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.js","names":[],"sources":["../../../src/components/Page/Page.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — a page shell is slots: eyebrow, title, description,\n * actions, toolbar, footer and children, with padded as the one behavioural switch.\n * Slots are the component.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Page.module.css\";\n\nexport interface PageProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page title rendered as `<h1>`. */\n title?: ReactNode;\n /** Optional subtitle / breadcrumbs slot rendered above the title. */\n eyebrow?: ReactNode;\n /** Optional description rendered below the title. */\n description?: ReactNode;\n /** Right-side actions slot in the header (buttons, menus). */\n actions?: ReactNode;\n /** Sticky tab bar / filter row rendered just below the header. */\n toolbar?: ReactNode;\n /** Footer slot rendered at the bottom of the content area. */\n footer?: ReactNode;\n /** Page-level padding. Default `true`. */\n padded?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Page wrapper with header + (optional) toolbar + content + footer. Pairs\n * with `Container` when you want a max-width content well.\n *\n * @example\n * <Page title=\"Pedidos\" description=\"Acompanhe seus pedidos\" actions={<Button>Novo</Button>}>\n * <Table {...} />\n * </Page>\n */\nexport function Page({\n title,\n eyebrow,\n description,\n actions,\n toolbar,\n footer,\n padded = true,\n className,\n children,\n ...props\n}: PageProps) {\n const hasHeader = title || eyebrow || description || actions;\n return (\n <main className={cn(styles.page, padded && styles.padded, className)} {...props}>\n {hasHeader && (\n <header className={styles.header}>\n <div className={styles.headerText}>\n {eyebrow && <div className={styles.eyebrow}>{eyebrow}</div>}\n {title && <h1 className={styles.title}>{title}</h1>}\n {description && <p className={styles.description}>{description}</p>}\n </div>\n {actions && <div className={styles.actions}>{actions}</div>}\n </header>\n )}\n {toolbar && <div className={styles.toolbar}>{toolbar}</div>}\n <div className={styles.content}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </main>\n );\n}\n"],"mappings":";;;;AAoCA,SAAgB,EAAK,EACjB,UACA,YACA,gBACA,YACA,YACA,WACA,YAAS,IACT,cACA,aACA,GAAG,KACO;CACV,IAAM,IAAY,KAAS,KAAW,KAAe;CACrD,OACI,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAO,MAAM,KAAU,EAAO,QAAQ,CAAS;EAAG,GAAI;
|
|
1
|
+
{"version":3,"file":"Page.js","names":[],"sources":["../../../src/components/Page/Page.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — a page shell is slots: eyebrow, title, description,\n * actions, toolbar, footer and children, with padded as the one behavioural switch.\n * Slots are the component.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Page.module.css\";\n\nexport interface PageProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page title rendered as `<h1>`. */\n title?: ReactNode;\n /** Optional subtitle / breadcrumbs slot rendered above the title. */\n eyebrow?: ReactNode;\n /** Optional description rendered below the title. */\n description?: ReactNode;\n /** Right-side actions slot in the header (buttons, menus). */\n actions?: ReactNode;\n /** Sticky tab bar / filter row rendered just below the header. */\n toolbar?: ReactNode;\n /** Footer slot rendered at the bottom of the content area. */\n footer?: ReactNode;\n /** Page-level padding. Default `true`. */\n padded?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Page wrapper with header + (optional) toolbar + content + footer. Pairs\n * with `Container` when you want a max-width content well.\n *\n * @example\n * <Page title=\"Pedidos\" description=\"Acompanhe seus pedidos\" actions={<Button>Novo</Button>}>\n * <Table {...} />\n * </Page>\n */\nexport function Page({\n title,\n eyebrow,\n description,\n actions,\n toolbar,\n footer,\n padded = true,\n className,\n children,\n ...props\n}: PageProps) {\n const hasHeader = title || eyebrow || description || actions;\n return (\n <main className={cn(styles.page, padded && styles.padded, className)} {...props}>\n {hasHeader && (\n <header className={styles.header}>\n <div className={styles.headerText}>\n {eyebrow && <div className={styles.eyebrow}>{eyebrow}</div>}\n {title && <h1 className={styles.title}>{title}</h1>}\n {description && <p className={styles.description}>{description}</p>}\n </div>\n {actions && <div className={styles.actions}>{actions}</div>}\n </header>\n )}\n {toolbar && <div className={styles.toolbar}>{toolbar}</div>}\n <div className={styles.content}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </main>\n );\n}\n"],"mappings":";;;;AAoCA,SAAgB,EAAK,EACjB,UACA,YACA,gBACA,YACA,YACA,WACA,YAAS,IACT,cACA,aACA,GAAG,KACO;CACV,IAAM,IAAY,KAAS,KAAW,KAAe;CACrD,OACI,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAO,MAAM,KAAU,EAAO,QAAQ,CAAS;EAAG,GAAI;EAA1E,UAAA;GACK,KACG,kBAAC,UAAD;IAAQ,WAAW,EAAO;IAA1B,UAAA,CACI,kBAAC,OAAD;KAAK,WAAW,EAAO;KAAvB,UAAA;MACK,KAAW,kBAAC,OAAD;OAAK,WAAW,EAAO;OAAU,UAAA;MAAa,CAAA;MACzD,KAAS,kBAAC,MAAD;OAAI,WAAW,EAAO;OAAQ,UAAA;MAAU,CAAA;MACjD,KAAe,kBAAC,KAAD;OAAG,WAAW,EAAO;OAAc,UAAA;MAAe,CAAA;KACjE;IACJ,CAAA,GAAA,KAAW,kBAAC,OAAD;KAAK,WAAW,EAAO;KAAU,UAAA;IAAa,CAAA,CACtD;;GAEX,KAAW,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAU,UAAA;GAAa,CAAA;GAC1D,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAU;GAAc,CAAA;GAC9C,KAAU,kBAAC,UAAD;IAAQ,WAAW,EAAO;IAAS,UAAA;GAAe,CAAA;EAC3D;;AAEd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.cjs","names":[],"sources":["../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — page/totalPages/onPageChange is the pager,\n * pageSize/onPageSizeChange/ pageSizeOptions is the size control that sits in the\n * same bar, and totalItems plus siblingCount decide the copy and how many page\n * buttons are rendered. They ship together because a footer that pages but cannot\n * resize is half a footer.\n */\nimport { useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Pagination.module.css\";\n\nexport interface PaginationProps {\n page: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n pageSize?: number;\n onPageSizeChange?: (size: number) => void;\n pageSizeOptions?: number[];\n /** Total items count; if provided, renders the summary text. */\n totalItems?: number;\n /** Max number of numbered page buttons to show. Default 7. */\n siblingCount?: number;\n className?: string;\n}\n\nfunction buildRange(page: number, totalPages: number, siblings: number): (number | \"...\")[] {\n const totalSlots = siblings + 4;\n if (totalPages <= totalSlots) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n const start = Math.max(2, page - Math.floor(siblings / 2));\n const end = Math.min(totalPages - 1, start + siblings - 1);\n const range: (number | \"...\")[] = [1];\n if (start > 2) range.push(\"...\");\n for (let i = start; i <= end; i++) range.push(i);\n if (end < totalPages - 1) range.push(\"...\");\n range.push(totalPages);\n return range;\n}\n\n/**\n * Numeric pagination controls. Pair with {@link usePagination} for state.\n */\nexport function Pagination({\n page,\n totalPages,\n onPageChange,\n pageSize,\n onPageSizeChange,\n pageSizeOptions = [10, 25, 50, 100],\n totalItems,\n siblingCount = 3,\n className,\n}: PaginationProps) {\n const pages = useMemo(\n () => buildRange(page, totalPages, siblingCount),\n [page, totalPages, siblingCount],\n );\n\n if (totalPages <= 1 && !onPageSizeChange) return null;\n\n return (\n <div className={cn(styles.wrapper, className)}>\n <div className={styles.summary}>\n {typeof totalItems === \"number\"\n ? `${totalItems} resultado${totalItems === 1 ? \"\" : \"s\"}`\n : `Página ${page} de ${totalPages}`}\n </div>\n <div className={styles.controls}>\n <button\n type=\"button\"\n className={styles.page}\n onClick={() => onPageChange(Math.max(1, page - 1))}\n disabled={page <= 1}\n aria-label=\"Página anterior\"\n >\n ‹\n </button>\n {pages.map((entry, index) =>\n entry === \"...\" ? (\n <span\n key={`ellipsis-${index}`}\n className={cn(styles.ellipsis, styles.numeric)}\n >\n …\n </span>\n ) : (\n <button\n type=\"button\"\n key={entry}\n className={cn(\n styles.page,\n styles.numeric,\n entry === page && styles.active,\n )}\n onClick={() => onPageChange(entry)}\n aria-current={entry === page ? \"page\" : undefined}\n >\n {entry}\n </button>\n ),\n )}\n <button\n type=\"button\"\n className={styles.page}\n onClick={() => onPageChange(Math.min(totalPages, page + 1))}\n disabled={page >= totalPages}\n aria-label=\"Próxima página\"\n >\n ›\n </button>\n {onPageSizeChange && (\n <select\n className={styles.sizeSelect}\n value={pageSize}\n onChange={(event) => onPageSizeChange(Number(event.target.value))}\n aria-label=\"Itens por página\"\n >\n {pageSizeOptions.map((opt) => (\n <option key={opt} value={opt}>\n {opt} / página\n </option>\n ))}\n </select>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"iIAyBA,SAAS,EAAW,EAAc,EAAoB,EAAsC,CAExF,GAAI,GADe,EAAW,EAE1B,OAAO,MAAM,KAAK,CAAE,OAAQ,CAAW,GAAI,EAAG,IAAM,EAAI,CAAC,EAE7D,IAAM,EAAQ,KAAK,IAAI,EAAG,EAAO,KAAK,MAAM,EAAW,CAAC,CAAC,EACnD,EAAM,KAAK,IAAI,EAAa,EAAG,EAAQ,EAAW,CAAC,EACnD,EAA4B,CAAC,CAAC,EAChC,EAAQ,GAAG,EAAM,KAAK,KAAK,EAC/B,IAAK,IAAI,EAAI,EAAO,GAAK,EAAK,IAAK,EAAM,KAAK,CAAC,EAG/C,OAFI,EAAM,EAAa,GAAG,EAAM,KAAK,KAAK,EAC1C,EAAM,KAAK,CAAU,EACd,CACX,CAKA,SAAgB,EAAW,CACvB,OACA,aACA,eACA,WACA,mBACA,kBAAkB,CAAC,GAAI,GAAI,GAAI,GAAG,EAClC,aACA,eAAe,EACf,aACgB,CAChB,IAAM,GAAA,
|
|
1
|
+
{"version":3,"file":"Pagination.cjs","names":[],"sources":["../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — page/totalPages/onPageChange is the pager,\n * pageSize/onPageSizeChange/ pageSizeOptions is the size control that sits in the\n * same bar, and totalItems plus siblingCount decide the copy and how many page\n * buttons are rendered. They ship together because a footer that pages but cannot\n * resize is half a footer.\n */\nimport { useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Pagination.module.css\";\n\nexport interface PaginationProps {\n page: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n pageSize?: number;\n onPageSizeChange?: (size: number) => void;\n pageSizeOptions?: number[];\n /** Total items count; if provided, renders the summary text. */\n totalItems?: number;\n /** Max number of numbered page buttons to show. Default 7. */\n siblingCount?: number;\n className?: string;\n}\n\nfunction buildRange(page: number, totalPages: number, siblings: number): (number | \"...\")[] {\n const totalSlots = siblings + 4;\n if (totalPages <= totalSlots) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n const start = Math.max(2, page - Math.floor(siblings / 2));\n const end = Math.min(totalPages - 1, start + siblings - 1);\n const range: (number | \"...\")[] = [1];\n if (start > 2) range.push(\"...\");\n for (let i = start; i <= end; i++) range.push(i);\n if (end < totalPages - 1) range.push(\"...\");\n range.push(totalPages);\n return range;\n}\n\n/**\n * Numeric pagination controls. Pair with {@link usePagination} for state.\n */\nexport function Pagination({\n page,\n totalPages,\n onPageChange,\n pageSize,\n onPageSizeChange,\n pageSizeOptions = [10, 25, 50, 100],\n totalItems,\n siblingCount = 3,\n className,\n}: PaginationProps) {\n const pages = useMemo(\n () => buildRange(page, totalPages, siblingCount),\n [page, totalPages, siblingCount],\n );\n\n if (totalPages <= 1 && !onPageSizeChange) return null;\n\n return (\n <div className={cn(styles.wrapper, className)}>\n <div className={styles.summary}>\n {typeof totalItems === \"number\"\n ? `${totalItems} resultado${totalItems === 1 ? \"\" : \"s\"}`\n : `Página ${page} de ${totalPages}`}\n </div>\n <div className={styles.controls}>\n <button\n type=\"button\"\n className={styles.page}\n onClick={() => onPageChange(Math.max(1, page - 1))}\n disabled={page <= 1}\n aria-label=\"Página anterior\"\n >\n ‹\n </button>\n {pages.map((entry, index) =>\n entry === \"...\" ? (\n <span\n key={`ellipsis-${index}`}\n className={cn(styles.ellipsis, styles.numeric)}\n >\n …\n </span>\n ) : (\n <button\n type=\"button\"\n key={entry}\n className={cn(\n styles.page,\n styles.numeric,\n entry === page && styles.active,\n )}\n onClick={() => onPageChange(entry)}\n aria-current={entry === page ? \"page\" : undefined}\n >\n {entry}\n </button>\n ),\n )}\n <button\n type=\"button\"\n className={styles.page}\n onClick={() => onPageChange(Math.min(totalPages, page + 1))}\n disabled={page >= totalPages}\n aria-label=\"Próxima página\"\n >\n ›\n </button>\n {onPageSizeChange && (\n <select\n className={styles.sizeSelect}\n value={pageSize}\n onChange={(event) => onPageSizeChange(Number(event.target.value))}\n aria-label=\"Itens por página\"\n >\n {pageSizeOptions.map((opt) => (\n <option key={opt} value={opt}>\n {opt} / página\n </option>\n ))}\n </select>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"iIAyBA,SAAS,EAAW,EAAc,EAAoB,EAAsC,CAExF,GAAI,GADe,EAAW,EAE1B,OAAO,MAAM,KAAK,CAAE,OAAQ,CAAW,GAAI,EAAG,IAAM,EAAI,CAAC,EAE7D,IAAM,EAAQ,KAAK,IAAI,EAAG,EAAO,KAAK,MAAM,EAAW,CAAC,CAAC,EACnD,EAAM,KAAK,IAAI,EAAa,EAAG,EAAQ,EAAW,CAAC,EACnD,EAA4B,CAAC,CAAC,EAChC,EAAQ,GAAG,EAAM,KAAK,KAAK,EAC/B,IAAK,IAAI,EAAI,EAAO,GAAK,EAAK,IAAK,EAAM,KAAK,CAAC,EAG/C,OAFI,EAAM,EAAa,GAAG,EAAM,KAAK,KAAK,EAC1C,EAAM,KAAK,CAAU,EACd,CACX,CAKA,SAAgB,EAAW,CACvB,OACA,aACA,eACA,WACA,mBACA,kBAAkB,CAAC,GAAI,GAAI,GAAI,GAAG,EAClC,aACA,eAAe,EACf,aACgB,CAChB,IAAM,GAAA,EAAQ,EAAA,QAAA,KACJ,EAAW,EAAM,EAAY,CAAY,EAC/C,CAAC,EAAM,EAAY,CAAY,CACnC,EAIA,OAFI,GAAc,GAAK,CAAC,EAAyB,MAG7C,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAA5C,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,QAClB,SAAA,OAAO,GAAe,SACjB,GAAG,EAAW,YAAY,IAAe,EAAI,GAAK,MAClD,UAAU,EAAK,MAAM,GAC1B,CAAA,GACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,SAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,KAClB,YAAe,EAAa,KAAK,IAAI,EAAG,EAAO,CAAC,CAAC,EACjD,SAAU,GAAQ,EAClB,aAAW,kBACd,SAAA,GAEO,CAAA,EACP,EAAM,KAAK,EAAO,IACf,IAAU,OACN,EAAA,EAAA,IAAA,CAAC,OAAD,CAEI,UAAW,EAAA,GAAG,EAAA,QAAO,SAAU,EAAA,QAAO,OAAO,EAChD,SAAA,GAEK,EAJG,YAAY,GAIf,GAEN,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SAEL,UAAW,EAAA,GACP,EAAA,QAAO,KACP,EAAA,QAAO,QACP,IAAU,GAAQ,EAAA,QAAO,MAC7B,EACA,YAAe,EAAa,CAAK,EACjC,eAAc,IAAU,EAAO,OAAS,IAAA,GAEvC,SAAA,CACG,EAVC,CAUD,CAEhB,GACA,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,KAClB,YAAe,EAAa,KAAK,IAAI,EAAY,EAAO,CAAC,CAAC,EAC1D,SAAU,GAAQ,EAClB,aAAW,iBACd,SAAA,GAEO,CAAA,EACP,IACG,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,UAAW,EAAA,QAAO,WAClB,MAAO,EACP,SAAW,GAAU,EAAiB,OAAO,EAAM,OAAO,KAAK,CAAC,EAChE,aAAW,mBAEV,SAAA,EAAgB,IAAK,IAClB,EAAA,EAAA,KAAA,CAAC,SAAD,CAAkB,MAAO,EAAzB,SAAA,CACK,EAAI,WACD,CAFK,EAAA,CAEL,CACX,CACG,CAAA,CAEX,CACJ,CAAA,CAAA,GAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.js","names":[],"sources":["../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — page/totalPages/onPageChange is the pager,\n * pageSize/onPageSizeChange/ pageSizeOptions is the size control that sits in the\n * same bar, and totalItems plus siblingCount decide the copy and how many page\n * buttons are rendered. They ship together because a footer that pages but cannot\n * resize is half a footer.\n */\nimport { useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Pagination.module.css\";\n\nexport interface PaginationProps {\n page: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n pageSize?: number;\n onPageSizeChange?: (size: number) => void;\n pageSizeOptions?: number[];\n /** Total items count; if provided, renders the summary text. */\n totalItems?: number;\n /** Max number of numbered page buttons to show. Default 7. */\n siblingCount?: number;\n className?: string;\n}\n\nfunction buildRange(page: number, totalPages: number, siblings: number): (number | \"...\")[] {\n const totalSlots = siblings + 4;\n if (totalPages <= totalSlots) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n const start = Math.max(2, page - Math.floor(siblings / 2));\n const end = Math.min(totalPages - 1, start + siblings - 1);\n const range: (number | \"...\")[] = [1];\n if (start > 2) range.push(\"...\");\n for (let i = start; i <= end; i++) range.push(i);\n if (end < totalPages - 1) range.push(\"...\");\n range.push(totalPages);\n return range;\n}\n\n/**\n * Numeric pagination controls. Pair with {@link usePagination} for state.\n */\nexport function Pagination({\n page,\n totalPages,\n onPageChange,\n pageSize,\n onPageSizeChange,\n pageSizeOptions = [10, 25, 50, 100],\n totalItems,\n siblingCount = 3,\n className,\n}: PaginationProps) {\n const pages = useMemo(\n () => buildRange(page, totalPages, siblingCount),\n [page, totalPages, siblingCount],\n );\n\n if (totalPages <= 1 && !onPageSizeChange) return null;\n\n return (\n <div className={cn(styles.wrapper, className)}>\n <div className={styles.summary}>\n {typeof totalItems === \"number\"\n ? `${totalItems} resultado${totalItems === 1 ? \"\" : \"s\"}`\n : `Página ${page} de ${totalPages}`}\n </div>\n <div className={styles.controls}>\n <button\n type=\"button\"\n className={styles.page}\n onClick={() => onPageChange(Math.max(1, page - 1))}\n disabled={page <= 1}\n aria-label=\"Página anterior\"\n >\n ‹\n </button>\n {pages.map((entry, index) =>\n entry === \"...\" ? (\n <span\n key={`ellipsis-${index}`}\n className={cn(styles.ellipsis, styles.numeric)}\n >\n …\n </span>\n ) : (\n <button\n type=\"button\"\n key={entry}\n className={cn(\n styles.page,\n styles.numeric,\n entry === page && styles.active,\n )}\n onClick={() => onPageChange(entry)}\n aria-current={entry === page ? \"page\" : undefined}\n >\n {entry}\n </button>\n ),\n )}\n <button\n type=\"button\"\n className={styles.page}\n onClick={() => onPageChange(Math.min(totalPages, page + 1))}\n disabled={page >= totalPages}\n aria-label=\"Próxima página\"\n >\n ›\n </button>\n {onPageSizeChange && (\n <select\n className={styles.sizeSelect}\n value={pageSize}\n onChange={(event) => onPageSizeChange(Number(event.target.value))}\n aria-label=\"Itens por página\"\n >\n {pageSizeOptions.map((opt) => (\n <option key={opt} value={opt}>\n {opt} / página\n </option>\n ))}\n </select>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAyBA,SAAS,EAAW,GAAc,GAAoB,GAAsC;CAExF,IAAI,KADe,IAAW,GAE1B,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAW,IAAI,GAAG,MAAM,IAAI,CAAC;CAE7D,IAAM,IAAQ,KAAK,IAAI,GAAG,IAAO,KAAK,MAAM,IAAW,CAAC,CAAC,GACnD,IAAM,KAAK,IAAI,IAAa,GAAG,IAAQ,IAAW,CAAC,GACnD,IAA4B,CAAC,CAAC;CACpC,AAAI,IAAQ,KAAG,EAAM,KAAK,KAAK;CAC/B,KAAK,IAAI,IAAI,GAAO,KAAK,GAAK,KAAK,EAAM,KAAK,CAAC;CAG/C,OAFI,IAAM,IAAa,KAAG,EAAM,KAAK,KAAK,GAC1C,EAAM,KAAK,CAAU,GACd;AACX;AAKA,SAAgB,EAAW,EACvB,SACA,eACA,iBACA,aACA,qBACA,qBAAkB;CAAC;CAAI;CAAI;CAAI;AAAG,GAClC,eACA,kBAAe,GACf,gBACgB;CAChB,IAAM,IAAQ,QACJ,EAAW,GAAM,GAAY,CAAY,GAC/C;EAAC;EAAM;EAAY;CAAY,CACnC;CAIA,OAFI,KAAc,KAAK,CAAC,IAAyB,OAG7C,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;
|
|
1
|
+
{"version":3,"file":"Pagination.js","names":[],"sources":["../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — page/totalPages/onPageChange is the pager,\n * pageSize/onPageSizeChange/ pageSizeOptions is the size control that sits in the\n * same bar, and totalItems plus siblingCount decide the copy and how many page\n * buttons are rendered. They ship together because a footer that pages but cannot\n * resize is half a footer.\n */\nimport { useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Pagination.module.css\";\n\nexport interface PaginationProps {\n page: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n pageSize?: number;\n onPageSizeChange?: (size: number) => void;\n pageSizeOptions?: number[];\n /** Total items count; if provided, renders the summary text. */\n totalItems?: number;\n /** Max number of numbered page buttons to show. Default 7. */\n siblingCount?: number;\n className?: string;\n}\n\nfunction buildRange(page: number, totalPages: number, siblings: number): (number | \"...\")[] {\n const totalSlots = siblings + 4;\n if (totalPages <= totalSlots) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n const start = Math.max(2, page - Math.floor(siblings / 2));\n const end = Math.min(totalPages - 1, start + siblings - 1);\n const range: (number | \"...\")[] = [1];\n if (start > 2) range.push(\"...\");\n for (let i = start; i <= end; i++) range.push(i);\n if (end < totalPages - 1) range.push(\"...\");\n range.push(totalPages);\n return range;\n}\n\n/**\n * Numeric pagination controls. Pair with {@link usePagination} for state.\n */\nexport function Pagination({\n page,\n totalPages,\n onPageChange,\n pageSize,\n onPageSizeChange,\n pageSizeOptions = [10, 25, 50, 100],\n totalItems,\n siblingCount = 3,\n className,\n}: PaginationProps) {\n const pages = useMemo(\n () => buildRange(page, totalPages, siblingCount),\n [page, totalPages, siblingCount],\n );\n\n if (totalPages <= 1 && !onPageSizeChange) return null;\n\n return (\n <div className={cn(styles.wrapper, className)}>\n <div className={styles.summary}>\n {typeof totalItems === \"number\"\n ? `${totalItems} resultado${totalItems === 1 ? \"\" : \"s\"}`\n : `Página ${page} de ${totalPages}`}\n </div>\n <div className={styles.controls}>\n <button\n type=\"button\"\n className={styles.page}\n onClick={() => onPageChange(Math.max(1, page - 1))}\n disabled={page <= 1}\n aria-label=\"Página anterior\"\n >\n ‹\n </button>\n {pages.map((entry, index) =>\n entry === \"...\" ? (\n <span\n key={`ellipsis-${index}`}\n className={cn(styles.ellipsis, styles.numeric)}\n >\n …\n </span>\n ) : (\n <button\n type=\"button\"\n key={entry}\n className={cn(\n styles.page,\n styles.numeric,\n entry === page && styles.active,\n )}\n onClick={() => onPageChange(entry)}\n aria-current={entry === page ? \"page\" : undefined}\n >\n {entry}\n </button>\n ),\n )}\n <button\n type=\"button\"\n className={styles.page}\n onClick={() => onPageChange(Math.min(totalPages, page + 1))}\n disabled={page >= totalPages}\n aria-label=\"Próxima página\"\n >\n ›\n </button>\n {onPageSizeChange && (\n <select\n className={styles.sizeSelect}\n value={pageSize}\n onChange={(event) => onPageSizeChange(Number(event.target.value))}\n aria-label=\"Itens por página\"\n >\n {pageSizeOptions.map((opt) => (\n <option key={opt} value={opt}>\n {opt} / página\n </option>\n ))}\n </select>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAyBA,SAAS,EAAW,GAAc,GAAoB,GAAsC;CAExF,IAAI,KADe,IAAW,GAE1B,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAW,IAAI,GAAG,MAAM,IAAI,CAAC;CAE7D,IAAM,IAAQ,KAAK,IAAI,GAAG,IAAO,KAAK,MAAM,IAAW,CAAC,CAAC,GACnD,IAAM,KAAK,IAAI,IAAa,GAAG,IAAQ,IAAW,CAAC,GACnD,IAA4B,CAAC,CAAC;CACpC,AAAI,IAAQ,KAAG,EAAM,KAAK,KAAK;CAC/B,KAAK,IAAI,IAAI,GAAO,KAAK,GAAK,KAAK,EAAM,KAAK,CAAC;CAG/C,OAFI,IAAM,IAAa,KAAG,EAAM,KAAK,KAAK,GAC1C,EAAM,KAAK,CAAU,GACd;AACX;AAKA,SAAgB,EAAW,EACvB,SACA,eACA,iBACA,aACA,qBACA,qBAAkB;CAAC;CAAI;CAAI;CAAI;AAAG,GAClC,eACA,kBAAe,GACf,gBACgB;CAChB,IAAM,IAAQ,QACJ,EAAW,GAAM,GAAY,CAAY,GAC/C;EAAC;EAAM;EAAY;CAAY,CACnC;CAIA,OAFI,KAAc,KAAK,CAAC,IAAyB,OAG7C,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;EAA5C,UAAA,CACI,kBAAC,OAAD;GAAK,WAAW,EAAO;GAClB,UAAA,OAAO,KAAe,WACjB,GAAG,EAAW,YAAY,MAAe,IAAI,KAAK,QAClD,UAAU,EAAK,MAAM;EAC1B,CAAA,GACL,kBAAC,OAAD;GAAK,WAAW,EAAO;GAAvB,UAAA;IACI,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,eAAe,EAAa,KAAK,IAAI,GAAG,IAAO,CAAC,CAAC;KACjD,UAAU,KAAQ;KAClB,cAAW;KACd,UAAA;IAEO,CAAA;IACP,EAAM,KAAK,GAAO,MACf,MAAU,QACN,kBAAC,QAAD;KAEI,WAAW,EAAG,EAAO,UAAU,EAAO,OAAO;KAChD,UAAA;IAEK,GAJG,YAAY,GAIf,IAEN,kBAAC,UAAD;KACI,MAAK;KAEL,WAAW,EACP,EAAO,MACP,EAAO,SACP,MAAU,KAAQ,EAAO,MAC7B;KACA,eAAe,EAAa,CAAK;KACjC,gBAAc,MAAU,IAAO,SAAS,KAAA;KAEvC,UAAA;IACG,GAVC,CAUD,CAEhB;IACA,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,eAAe,EAAa,KAAK,IAAI,GAAY,IAAO,CAAC,CAAC;KAC1D,UAAU,KAAQ;KAClB,cAAW;KACd,UAAA;IAEO,CAAA;IACP,KACG,kBAAC,UAAD;KACI,WAAW,EAAO;KAClB,OAAO;KACP,WAAW,MAAU,EAAiB,OAAO,EAAM,OAAO,KAAK,CAAC;KAChE,cAAW;KAEV,UAAA,EAAgB,KAAK,MAClB,kBAAC,UAAD;MAAkB,OAAO;MAAzB,UAAA,CACK,GAAI,WACD;KAFK,GAAA,CAEL,CACX;IACG,CAAA;GAEX;EACJ,CAAA,CAAA;;AAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasswordInput.cjs","names":[],"sources":["../../../src/components/PasswordInput/PasswordInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — on top of the SDK's shared field props,\n * showStrength/strength/strengthLabels are the meter and toggleLabels is the\n * show/hide button's accessible name — both need their copy from the app, since\n * neither can be translated by the SDK.\n */\nimport { forwardRef, useId, useState } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./PasswordInput.module.css\";\n\nexport type PasswordStrength = 0 | 1 | 2 | 3 | 4;\n\nexport interface PasswordInputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"size\"\n> {\n /** Label rendered above the input. */\n label?: ReactNode;\n /** Helper text below — replaced by `error` when set. */\n helperText?: ReactNode;\n /** Error message. Adds `aria-invalid` + red border. */\n error?: string;\n /** Visual size of the input. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Show a strength meter below the field. Default `false`. */\n showStrength?: boolean;\n /** Override the automatic strength calc (0–4). */\n strength?: PasswordStrength;\n /** Custom labels per strength level (5 entries). */\n strengthLabels?: readonly [string, string, string, string, string];\n /** Custom toggle button labels for accessibility. */\n toggleLabels?: { show: string; hide: string };\n}\n\nconst DEFAULT_STRENGTH_LABELS = [\"Muito fraca\", \"Fraca\", \"Razoável\", \"Forte\", \"Excelente\"] as const;\n\nexport function estimatePasswordStrength(value: string): PasswordStrength {\n if (!value) return 0;\n let score = 0;\n if (value.length >= 8) score += 1;\n if (value.length >= 12) score += 1;\n if (/[a-z]/.test(value) && /[A-Z]/.test(value)) score += 1;\n if (/[0-9]/.test(value)) score += 1;\n if (/[^A-Za-z0-9]/.test(value)) score += 1;\n return Math.min(4, score) as PasswordStrength;\n}\n\n/**\n * Password field with toggle-visibility button and optional strength meter.\n *\n * @example\n * <PasswordInput label=\"Senha\" showStrength autoComplete=\"new-password\" />\n */\nexport const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n function PasswordInput(\n {\n label,\n helperText,\n error,\n size = \"md\",\n showStrength = false,\n strength,\n strengthLabels = DEFAULT_STRENGTH_LABELS,\n toggleLabels = { show: \"Mostrar senha\", hide: \"Esconder senha\" },\n className,\n value,\n defaultValue,\n id,\n ...inputProps\n },\n ref,\n ) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const describedById = error\n ? `${inputId}-error`\n : helperText\n ? `${inputId}-helper`\n : undefined;\n const [revealed, setRevealed] = useState<boolean>(false);\n const stringValue = String((value ?? defaultValue ?? \"\") as string);\n const computedStrength: PasswordStrength =\n strength ?? estimatePasswordStrength(stringValue);\n\n return (\n <div className={cn(styles.wrapper, styles[size], error && styles.error, className)}>\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n </label>\n )}\n <div className={styles.field}>\n <input\n ref={ref}\n {...inputProps}\n id={inputId}\n value={value}\n defaultValue={defaultValue}\n type={revealed ? \"text\" : \"password\"}\n aria-invalid={!!error}\n aria-describedby={describedById}\n className={styles.input}\n />\n <button\n type=\"button\"\n className={styles.toggle}\n aria-label={revealed ? toggleLabels.hide : toggleLabels.show}\n aria-pressed={revealed}\n onClick={() => setRevealed((on) => !on)}\n >\n {revealed ? \"🙈\" : \"👁\"}\n </button>\n </div>\n {showStrength && (\n <div\n className={cn(styles.strength, styles[`level${computedStrength}`])}\n aria-label={strengthLabels[computedStrength]}\n >\n <div className={styles.strengthBar}>\n <span style={{ width: `${(computedStrength / 4) * 100}%` }} />\n </div>\n <span className={styles.strengthLabel}>\n {strengthLabels[computedStrength]}\n </span>\n </div>\n )}\n {error ? (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={`${inputId}-helper`} className={styles.helper}>\n {helperText}\n </span>\n ) : null}\n </div>\n );\n },\n);\n"],"mappings":"oIAmCA,IAAM,EAA0B,CAAC,cAAe,QAAS,WAAY,QAAS,WAAW,EAEzF,SAAgB,EAAyB,EAAiC,CACtE,GAAI,CAAC,EAAO,MAAO,GACnB,IAAI,EAAQ,EAMZ,OALI,EAAM,QAAU,IAAG,GAAS,GAC5B,EAAM,QAAU,KAAI,GAAS,GAC7B,QAAQ,KAAK,CAAK,GAAK,QAAQ,KAAK,CAAK,IAAG,GAAS,GACrD,QAAQ,KAAK,CAAK,IAAG,GAAS,GAC9B,eAAe,KAAK,CAAK,IAAG,GAAS,GAClC,KAAK,IAAI,EAAG,CAAK,CAC5B,CAQA,IAAa,GAAA,
|
|
1
|
+
{"version":3,"file":"PasswordInput.cjs","names":[],"sources":["../../../src/components/PasswordInput/PasswordInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — on top of the SDK's shared field props,\n * showStrength/strength/strengthLabels are the meter and toggleLabels is the\n * show/hide button's accessible name — both need their copy from the app, since\n * neither can be translated by the SDK.\n */\nimport { forwardRef, useId, useState } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./PasswordInput.module.css\";\n\nexport type PasswordStrength = 0 | 1 | 2 | 3 | 4;\n\nexport interface PasswordInputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"size\"\n> {\n /** Label rendered above the input. */\n label?: ReactNode;\n /** Helper text below — replaced by `error` when set. */\n helperText?: ReactNode;\n /** Error message. Adds `aria-invalid` + red border. */\n error?: string;\n /** Visual size of the input. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Show a strength meter below the field. Default `false`. */\n showStrength?: boolean;\n /** Override the automatic strength calc (0–4). */\n strength?: PasswordStrength;\n /** Custom labels per strength level (5 entries). */\n strengthLabels?: readonly [string, string, string, string, string];\n /** Custom toggle button labels for accessibility. */\n toggleLabels?: { show: string; hide: string };\n}\n\nconst DEFAULT_STRENGTH_LABELS = [\"Muito fraca\", \"Fraca\", \"Razoável\", \"Forte\", \"Excelente\"] as const;\n\nexport function estimatePasswordStrength(value: string): PasswordStrength {\n if (!value) return 0;\n let score = 0;\n if (value.length >= 8) score += 1;\n if (value.length >= 12) score += 1;\n if (/[a-z]/.test(value) && /[A-Z]/.test(value)) score += 1;\n if (/[0-9]/.test(value)) score += 1;\n if (/[^A-Za-z0-9]/.test(value)) score += 1;\n return Math.min(4, score) as PasswordStrength;\n}\n\n/**\n * Password field with toggle-visibility button and optional strength meter.\n *\n * @example\n * <PasswordInput label=\"Senha\" showStrength autoComplete=\"new-password\" />\n */\nexport const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n function PasswordInput(\n {\n label,\n helperText,\n error,\n size = \"md\",\n showStrength = false,\n strength,\n strengthLabels = DEFAULT_STRENGTH_LABELS,\n toggleLabels = { show: \"Mostrar senha\", hide: \"Esconder senha\" },\n className,\n value,\n defaultValue,\n id,\n ...inputProps\n },\n ref,\n ) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const describedById = error\n ? `${inputId}-error`\n : helperText\n ? `${inputId}-helper`\n : undefined;\n const [revealed, setRevealed] = useState<boolean>(false);\n const stringValue = String((value ?? defaultValue ?? \"\") as string);\n const computedStrength: PasswordStrength =\n strength ?? estimatePasswordStrength(stringValue);\n\n return (\n <div className={cn(styles.wrapper, styles[size], error && styles.error, className)}>\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n </label>\n )}\n <div className={styles.field}>\n <input\n ref={ref}\n {...inputProps}\n id={inputId}\n value={value}\n defaultValue={defaultValue}\n type={revealed ? \"text\" : \"password\"}\n aria-invalid={!!error}\n aria-describedby={describedById}\n className={styles.input}\n />\n <button\n type=\"button\"\n className={styles.toggle}\n aria-label={revealed ? toggleLabels.hide : toggleLabels.show}\n aria-pressed={revealed}\n onClick={() => setRevealed((on) => !on)}\n >\n {revealed ? \"🙈\" : \"👁\"}\n </button>\n </div>\n {showStrength && (\n <div\n className={cn(styles.strength, styles[`level${computedStrength}`])}\n aria-label={strengthLabels[computedStrength]}\n >\n <div className={styles.strengthBar}>\n <span style={{ width: `${(computedStrength / 4) * 100}%` }} />\n </div>\n <span className={styles.strengthLabel}>\n {strengthLabels[computedStrength]}\n </span>\n </div>\n )}\n {error ? (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={`${inputId}-helper`} className={styles.helper}>\n {helperText}\n </span>\n ) : null}\n </div>\n );\n },\n);\n"],"mappings":"oIAmCA,IAAM,EAA0B,CAAC,cAAe,QAAS,WAAY,QAAS,WAAW,EAEzF,SAAgB,EAAyB,EAAiC,CACtE,GAAI,CAAC,EAAO,MAAO,GACnB,IAAI,EAAQ,EAMZ,OALI,EAAM,QAAU,IAAG,GAAS,GAC5B,EAAM,QAAU,KAAI,GAAS,GAC7B,QAAQ,KAAK,CAAK,GAAK,QAAQ,KAAK,CAAK,IAAG,GAAS,GACrD,QAAQ,KAAK,CAAK,IAAG,GAAS,GAC9B,eAAe,KAAK,CAAK,IAAG,GAAS,GAClC,KAAK,IAAI,EAAG,CAAK,CAC5B,CAQA,IAAa,GAAA,EAAgB,EAAA,WAAA,CACzB,SACI,CACI,QACA,aACA,QACA,OAAO,KACP,eAAe,GACf,WACA,iBAAiB,EACjB,eAAe,CAAE,KAAM,gBAAiB,KAAM,gBAAiB,EAC/D,YACA,QACA,eACA,KACA,GAAG,GAEP,EACF,CACE,IAAM,GAAA,EAAc,EAAA,MAAA,CAAM,EACpB,EAAU,GAAM,EAChB,EAAgB,EAChB,GAAG,EAAQ,QACX,EACE,GAAG,EAAQ,SACX,IAAA,GACF,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAkB,EAAK,EAEjD,EACF,GAAY,EAFI,OAAQ,GAAS,GAAgB,EAEZ,CAAW,EAEpD,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,EAAA,QAAO,GAAO,GAAS,EAAA,QAAO,MAAO,CAAS,EAAjF,SAAA,CACK,IACG,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,QAAS,EAAS,UAAW,EAAA,QAAO,MACtC,SAAA,CACE,CAAA,GAEX,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,QAAD,CACS,MACL,GAAI,EACJ,GAAI,EACG,QACO,eACd,KAAM,EAAW,OAAS,WAC1B,eAAc,CAAC,CAAC,EAChB,mBAAkB,EAClB,UAAW,EAAA,QAAO,KACrB,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,OAClB,aAAY,EAAW,EAAa,KAAO,EAAa,KACxD,eAAc,EACd,YAAe,EAAa,GAAO,CAAC,CAAE,EAErC,SAAA,EAAW,KAAO,IACf,CAAA,CACP,IACJ,IACG,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,SAAU,EAAA,QAAO,QAAQ,IAAmB,EACjE,aAAY,EAAe,GAF/B,SAAA,EAII,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,YACnB,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,MAAO,CAAE,MAAO,GAAI,EAAmB,EAAK,IAAI,EAAG,CAAI,CAAA,CAC5D,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,cACnB,SAAA,EAAe,EACd,CAAA,CACL,IAER,GACG,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,GAAI,GAAG,EAAQ,QAAS,UAAW,EAAA,QAAO,UAC3C,SAAA,CACC,CAAA,EACN,GACA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,GAAI,GAAG,EAAQ,SAAU,UAAW,EAAA,QAAO,OAC5C,SAAA,CACC,CAAA,EACN,IACH,GAEb,CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasswordInput.js","names":[],"sources":["../../../src/components/PasswordInput/PasswordInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — on top of the SDK's shared field props,\n * showStrength/strength/strengthLabels are the meter and toggleLabels is the\n * show/hide button's accessible name — both need their copy from the app, since\n * neither can be translated by the SDK.\n */\nimport { forwardRef, useId, useState } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./PasswordInput.module.css\";\n\nexport type PasswordStrength = 0 | 1 | 2 | 3 | 4;\n\nexport interface PasswordInputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"size\"\n> {\n /** Label rendered above the input. */\n label?: ReactNode;\n /** Helper text below — replaced by `error` when set. */\n helperText?: ReactNode;\n /** Error message. Adds `aria-invalid` + red border. */\n error?: string;\n /** Visual size of the input. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Show a strength meter below the field. Default `false`. */\n showStrength?: boolean;\n /** Override the automatic strength calc (0–4). */\n strength?: PasswordStrength;\n /** Custom labels per strength level (5 entries). */\n strengthLabels?: readonly [string, string, string, string, string];\n /** Custom toggle button labels for accessibility. */\n toggleLabels?: { show: string; hide: string };\n}\n\nconst DEFAULT_STRENGTH_LABELS = [\"Muito fraca\", \"Fraca\", \"Razoável\", \"Forte\", \"Excelente\"] as const;\n\nexport function estimatePasswordStrength(value: string): PasswordStrength {\n if (!value) return 0;\n let score = 0;\n if (value.length >= 8) score += 1;\n if (value.length >= 12) score += 1;\n if (/[a-z]/.test(value) && /[A-Z]/.test(value)) score += 1;\n if (/[0-9]/.test(value)) score += 1;\n if (/[^A-Za-z0-9]/.test(value)) score += 1;\n return Math.min(4, score) as PasswordStrength;\n}\n\n/**\n * Password field with toggle-visibility button and optional strength meter.\n *\n * @example\n * <PasswordInput label=\"Senha\" showStrength autoComplete=\"new-password\" />\n */\nexport const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n function PasswordInput(\n {\n label,\n helperText,\n error,\n size = \"md\",\n showStrength = false,\n strength,\n strengthLabels = DEFAULT_STRENGTH_LABELS,\n toggleLabels = { show: \"Mostrar senha\", hide: \"Esconder senha\" },\n className,\n value,\n defaultValue,\n id,\n ...inputProps\n },\n ref,\n ) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const describedById = error\n ? `${inputId}-error`\n : helperText\n ? `${inputId}-helper`\n : undefined;\n const [revealed, setRevealed] = useState<boolean>(false);\n const stringValue = String((value ?? defaultValue ?? \"\") as string);\n const computedStrength: PasswordStrength =\n strength ?? estimatePasswordStrength(stringValue);\n\n return (\n <div className={cn(styles.wrapper, styles[size], error && styles.error, className)}>\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n </label>\n )}\n <div className={styles.field}>\n <input\n ref={ref}\n {...inputProps}\n id={inputId}\n value={value}\n defaultValue={defaultValue}\n type={revealed ? \"text\" : \"password\"}\n aria-invalid={!!error}\n aria-describedby={describedById}\n className={styles.input}\n />\n <button\n type=\"button\"\n className={styles.toggle}\n aria-label={revealed ? toggleLabels.hide : toggleLabels.show}\n aria-pressed={revealed}\n onClick={() => setRevealed((on) => !on)}\n >\n {revealed ? \"🙈\" : \"👁\"}\n </button>\n </div>\n {showStrength && (\n <div\n className={cn(styles.strength, styles[`level${computedStrength}`])}\n aria-label={strengthLabels[computedStrength]}\n >\n <div className={styles.strengthBar}>\n <span style={{ width: `${(computedStrength / 4) * 100}%` }} />\n </div>\n <span className={styles.strengthLabel}>\n {strengthLabels[computedStrength]}\n </span>\n </div>\n )}\n {error ? (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={`${inputId}-helper`} className={styles.helper}>\n {helperText}\n </span>\n ) : null}\n </div>\n );\n },\n);\n"],"mappings":";;;;;AAmCA,IAAM,IAA0B;CAAC;CAAe;CAAS;CAAY;CAAS;AAAW;AAEzF,SAAgB,EAAyB,GAAiC;CACtE,IAAI,CAAC,GAAO,OAAO;CACnB,IAAI,IAAQ;CAMZ,OALI,EAAM,UAAU,MAAG,KAAS,IAC5B,EAAM,UAAU,OAAI,KAAS,IAC7B,QAAQ,KAAK,CAAK,KAAK,QAAQ,KAAK,CAAK,MAAG,KAAS,IACrD,QAAQ,KAAK,CAAK,MAAG,KAAS,IAC9B,eAAe,KAAK,CAAK,MAAG,KAAS,IAClC,KAAK,IAAI,GAAG,CAAK;AAC5B;AAQA,IAAa,IAAgB,EACzB,SACI,EACI,UACA,eACA,UACA,UAAO,MACP,kBAAe,IACf,aACA,oBAAiB,GACjB,kBAAe;CAAE,MAAM;CAAiB,MAAM;AAAiB,GAC/D,cACA,UACA,iBACA,OACA,GAAG,KAEP,GACF;CACE,IAAM,IAAc,EAAM,GACpB,IAAU,KAAM,GAChB,IAAgB,IAChB,GAAG,EAAQ,UACX,IACE,GAAG,EAAQ,WACX,KAAA,GACF,CAAC,GAAU,KAAe,EAAkB,EAAK,GAEjD,IACF,KAAY,EAFI,OAAQ,KAAS,KAAgB,EAEZ,CAAW;CAEpD,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,EAAO,IAAO,KAAS,EAAO,OAAO,CAAS;
|
|
1
|
+
{"version":3,"file":"PasswordInput.js","names":[],"sources":["../../../src/components/PasswordInput/PasswordInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — on top of the SDK's shared field props,\n * showStrength/strength/strengthLabels are the meter and toggleLabels is the\n * show/hide button's accessible name — both need their copy from the app, since\n * neither can be translated by the SDK.\n */\nimport { forwardRef, useId, useState } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./PasswordInput.module.css\";\n\nexport type PasswordStrength = 0 | 1 | 2 | 3 | 4;\n\nexport interface PasswordInputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"size\"\n> {\n /** Label rendered above the input. */\n label?: ReactNode;\n /** Helper text below — replaced by `error` when set. */\n helperText?: ReactNode;\n /** Error message. Adds `aria-invalid` + red border. */\n error?: string;\n /** Visual size of the input. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Show a strength meter below the field. Default `false`. */\n showStrength?: boolean;\n /** Override the automatic strength calc (0–4). */\n strength?: PasswordStrength;\n /** Custom labels per strength level (5 entries). */\n strengthLabels?: readonly [string, string, string, string, string];\n /** Custom toggle button labels for accessibility. */\n toggleLabels?: { show: string; hide: string };\n}\n\nconst DEFAULT_STRENGTH_LABELS = [\"Muito fraca\", \"Fraca\", \"Razoável\", \"Forte\", \"Excelente\"] as const;\n\nexport function estimatePasswordStrength(value: string): PasswordStrength {\n if (!value) return 0;\n let score = 0;\n if (value.length >= 8) score += 1;\n if (value.length >= 12) score += 1;\n if (/[a-z]/.test(value) && /[A-Z]/.test(value)) score += 1;\n if (/[0-9]/.test(value)) score += 1;\n if (/[^A-Za-z0-9]/.test(value)) score += 1;\n return Math.min(4, score) as PasswordStrength;\n}\n\n/**\n * Password field with toggle-visibility button and optional strength meter.\n *\n * @example\n * <PasswordInput label=\"Senha\" showStrength autoComplete=\"new-password\" />\n */\nexport const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n function PasswordInput(\n {\n label,\n helperText,\n error,\n size = \"md\",\n showStrength = false,\n strength,\n strengthLabels = DEFAULT_STRENGTH_LABELS,\n toggleLabels = { show: \"Mostrar senha\", hide: \"Esconder senha\" },\n className,\n value,\n defaultValue,\n id,\n ...inputProps\n },\n ref,\n ) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const describedById = error\n ? `${inputId}-error`\n : helperText\n ? `${inputId}-helper`\n : undefined;\n const [revealed, setRevealed] = useState<boolean>(false);\n const stringValue = String((value ?? defaultValue ?? \"\") as string);\n const computedStrength: PasswordStrength =\n strength ?? estimatePasswordStrength(stringValue);\n\n return (\n <div className={cn(styles.wrapper, styles[size], error && styles.error, className)}>\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n </label>\n )}\n <div className={styles.field}>\n <input\n ref={ref}\n {...inputProps}\n id={inputId}\n value={value}\n defaultValue={defaultValue}\n type={revealed ? \"text\" : \"password\"}\n aria-invalid={!!error}\n aria-describedby={describedById}\n className={styles.input}\n />\n <button\n type=\"button\"\n className={styles.toggle}\n aria-label={revealed ? toggleLabels.hide : toggleLabels.show}\n aria-pressed={revealed}\n onClick={() => setRevealed((on) => !on)}\n >\n {revealed ? \"🙈\" : \"👁\"}\n </button>\n </div>\n {showStrength && (\n <div\n className={cn(styles.strength, styles[`level${computedStrength}`])}\n aria-label={strengthLabels[computedStrength]}\n >\n <div className={styles.strengthBar}>\n <span style={{ width: `${(computedStrength / 4) * 100}%` }} />\n </div>\n <span className={styles.strengthLabel}>\n {strengthLabels[computedStrength]}\n </span>\n </div>\n )}\n {error ? (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={`${inputId}-helper`} className={styles.helper}>\n {helperText}\n </span>\n ) : null}\n </div>\n );\n },\n);\n"],"mappings":";;;;;AAmCA,IAAM,IAA0B;CAAC;CAAe;CAAS;CAAY;CAAS;AAAW;AAEzF,SAAgB,EAAyB,GAAiC;CACtE,IAAI,CAAC,GAAO,OAAO;CACnB,IAAI,IAAQ;CAMZ,OALI,EAAM,UAAU,MAAG,KAAS,IAC5B,EAAM,UAAU,OAAI,KAAS,IAC7B,QAAQ,KAAK,CAAK,KAAK,QAAQ,KAAK,CAAK,MAAG,KAAS,IACrD,QAAQ,KAAK,CAAK,MAAG,KAAS,IAC9B,eAAe,KAAK,CAAK,MAAG,KAAS,IAClC,KAAK,IAAI,GAAG,CAAK;AAC5B;AAQA,IAAa,IAAgB,EACzB,SACI,EACI,UACA,eACA,UACA,UAAO,MACP,kBAAe,IACf,aACA,oBAAiB,GACjB,kBAAe;CAAE,MAAM;CAAiB,MAAM;AAAiB,GAC/D,cACA,UACA,iBACA,OACA,GAAG,KAEP,GACF;CACE,IAAM,IAAc,EAAM,GACpB,IAAU,KAAM,GAChB,IAAgB,IAChB,GAAG,EAAQ,UACX,IACE,GAAG,EAAQ,WACX,KAAA,GACF,CAAC,GAAU,KAAe,EAAkB,EAAK,GAEjD,IACF,KAAY,EAFI,OAAQ,KAAS,KAAgB,EAEZ,CAAW;CAEpD,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,EAAO,IAAO,KAAS,EAAO,OAAO,CAAS;EAAjF,UAAA;GACK,KACG,kBAAC,SAAD;IAAO,SAAS;IAAS,WAAW,EAAO;IACtC,UAAA;GACE,CAAA;GAEX,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA,CACI,kBAAC,SAAD;KACS;KACL,GAAI;KACJ,IAAI;KACG;KACO;KACd,MAAM,IAAW,SAAS;KAC1B,gBAAc,CAAC,CAAC;KAChB,oBAAkB;KAClB,WAAW,EAAO;IACrB,CAAA,GACD,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,cAAY,IAAW,EAAa,OAAO,EAAa;KACxD,gBAAc;KACd,eAAe,GAAa,MAAO,CAAC,CAAE;KAErC,UAAA,IAAW,OAAO;IACf,CAAA,CACP;;GACJ,KACG,kBAAC,OAAD;IACI,WAAW,EAAG,EAAO,UAAU,EAAO,QAAQ,IAAmB;IACjE,cAAY,EAAe;IAF/B,UAAA,CAII,kBAAC,OAAD;KAAK,WAAW,EAAO;KACnB,UAAA,kBAAC,QAAD,EAAM,OAAO,EAAE,OAAO,GAAI,IAAmB,IAAK,IAAI,GAAG,EAAI,CAAA;IAC5D,CAAA,GACL,kBAAC,QAAD;KAAM,WAAW,EAAO;KACnB,UAAA,EAAe;IACd,CAAA,CACL;;GAER,IACG,kBAAC,QAAD;IAAM,IAAI,GAAG,EAAQ;IAAS,WAAW,EAAO;IAC3C,UAAA;GACC,CAAA,IACN,IACA,kBAAC,QAAD;IAAM,IAAI,GAAG,EAAQ;IAAU,WAAW,EAAO;IAC5C,UAAA;GACC,CAAA,IACN;EACH;;AAEb,CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PinInput.cjs","names":[],"sources":["../../../src/components/PinInput/PinInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — one input per digit, so length,\n * type, masked and autoFocus shape the boxes while\n * value/defaultValue/onChange/onComplete drive them as a single value. The body owns\n * the per-box refs, paste distribution and backspace traversal, which only make\n * sense with the whole array in scope.\n */\nimport { forwardRef, useEffect, useId, useRef, useState } from \"react\";\nimport type { ChangeEvent, ClipboardEvent, KeyboardEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./PinInput.module.css\";\n\nexport type PinInputType = \"numeric\" | \"alphanumeric\";\nexport type PinInputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface PinInputProps {\n /** Number of cells. Default `6`. */\n length?: number;\n /** Allowed character set. `numeric` (default) rejects letters, `alphanumeric` allows both. */\n type?: PinInputType;\n /** Visual size. Default `\"md\"`. */\n size?: PinInputSize;\n /** Controlled value. */\n value?: string;\n /** Initial value (uncontrolled mode). */\n defaultValue?: string;\n /** Fires on every change with the current concatenated value. */\n onChange?: (value: string) => void;\n /** Fires when the user fills the last cell. */\n onComplete?: (value: string) => void;\n /** Show characters obscured (`*`). Default `false`. */\n masked?: boolean;\n /** Label rendered above the cells. */\n label?: string;\n /** Helper text below the cells. */\n helperText?: string;\n /** Error message — turns cells red and replaces helperText. */\n error?: string;\n /** Disable all cells. */\n disabled?: boolean;\n /** Auto-focus the first cell on mount. Default `false`. */\n autoFocus?: boolean;\n /** id for the wrapping group label association. */\n id?: string;\n className?: string;\n}\n\nconst NUMERIC = /[0-9]/;\nconst ALNUM = /[A-Za-z0-9]/;\n\n/**\n * One-time-password style input — N independent cells, paste support, auto-\n * advance on input, backspace flows back, arrow keys navigate.\n *\n * @example\n * <PinInput length={6} type=\"numeric\" onComplete={(otp) => verify(otp)} />\n */\nexport const PinInput = forwardRef<HTMLDivElement, PinInputProps>(function PinInput(\n {\n length = 6,\n type = \"numeric\",\n size = \"md\",\n value,\n defaultValue,\n onChange,\n onComplete,\n masked = false,\n label,\n helperText,\n error,\n disabled = false,\n autoFocus = false,\n id,\n className,\n },\n ref,\n) {\n const internalId = useId();\n const wrapperId = id ?? internalId;\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<string>(defaultValue ?? \"\");\n const current = isControlled ? (value ?? \"\") : internal;\n const cells = Array.from({ length }, (_, index) => current[index] ?? \"\");\n const inputsRef = useRef<(HTMLInputElement | null)[]>([]);\n const pattern = type === \"numeric\" ? NUMERIC : ALNUM;\n\n useEffect(() => {\n if (autoFocus) inputsRef.current[0]?.focus();\n }, [autoFocus]);\n\n const update = (next: string): void => {\n const trimmed = next.slice(0, length);\n if (!isControlled) setInternal(trimmed);\n onChange?.(trimmed);\n if (trimmed.length === length) onComplete?.(trimmed);\n };\n\n const focusCell = (index: number): void => {\n const safe = Math.max(0, Math.min(length - 1, index));\n inputsRef.current[safe]?.focus();\n inputsRef.current[safe]?.select();\n };\n\n const onCellChange = (index: number) => (event: ChangeEvent<HTMLInputElement>) => {\n const char = event.target.value.slice(-1);\n if (char && !pattern.test(char)) return;\n const next = cells.slice();\n next[index] = char;\n update(next.join(\"\"));\n if (char) focusCell(index + 1);\n };\n\n const onCellKeyDown = (index: number) => (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Backspace\") {\n if (!cells[index] && index > 0) {\n event.preventDefault();\n const next = cells.slice();\n next[index - 1] = \"\";\n update(next.join(\"\"));\n focusCell(index - 1);\n }\n } else if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n focusCell(index - 1);\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n focusCell(index + 1);\n }\n };\n\n const onPaste = (event: ClipboardEvent<HTMLInputElement>): void => {\n const text = event.clipboardData\n .getData(\"text\")\n .split(\"\")\n .filter((c) => pattern.test(c))\n .join(\"\");\n if (!text) return;\n event.preventDefault();\n update(text);\n focusCell(Math.min(length - 1, text.length));\n };\n\n return (\n <div\n ref={ref}\n className={cn(styles.wrapper, error && styles.error, className)}\n id={wrapperId}\n >\n {label && <label className={styles.label}>{label}</label>}\n <div className={cn(styles.cells, styles[size])} role=\"group\" aria-label={label}>\n {cells.map((cell, index) => (\n <input\n key={index}\n ref={(node) => {\n inputsRef.current[index] = node;\n }}\n type={masked ? \"password\" : \"text\"}\n inputMode={type === \"numeric\" ? \"numeric\" : \"text\"}\n autoComplete={index === 0 ? \"one-time-code\" : \"off\"}\n maxLength={1}\n value={cell}\n disabled={disabled}\n className={styles.cell}\n aria-label={`Dígito ${index + 1}`}\n aria-invalid={!!error}\n onChange={onCellChange(index)}\n onKeyDown={onCellKeyDown(index)}\n onPaste={onPaste}\n />\n ))}\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helper}>{helperText}</span>\n ) : null}\n </div>\n );\n});\n"],"mappings":"+HA+CA,IAAM,EAAU,QACV,EAAQ,cASD,GAAA,
|
|
1
|
+
{"version":3,"file":"PinInput.cjs","names":[],"sources":["../../../src/components/PinInput/PinInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — one input per digit, so length,\n * type, masked and autoFocus shape the boxes while\n * value/defaultValue/onChange/onComplete drive them as a single value. The body owns\n * the per-box refs, paste distribution and backspace traversal, which only make\n * sense with the whole array in scope.\n */\nimport { forwardRef, useEffect, useId, useRef, useState } from \"react\";\nimport type { ChangeEvent, ClipboardEvent, KeyboardEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./PinInput.module.css\";\n\nexport type PinInputType = \"numeric\" | \"alphanumeric\";\nexport type PinInputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface PinInputProps {\n /** Number of cells. Default `6`. */\n length?: number;\n /** Allowed character set. `numeric` (default) rejects letters, `alphanumeric` allows both. */\n type?: PinInputType;\n /** Visual size. Default `\"md\"`. */\n size?: PinInputSize;\n /** Controlled value. */\n value?: string;\n /** Initial value (uncontrolled mode). */\n defaultValue?: string;\n /** Fires on every change with the current concatenated value. */\n onChange?: (value: string) => void;\n /** Fires when the user fills the last cell. */\n onComplete?: (value: string) => void;\n /** Show characters obscured (`*`). Default `false`. */\n masked?: boolean;\n /** Label rendered above the cells. */\n label?: string;\n /** Helper text below the cells. */\n helperText?: string;\n /** Error message — turns cells red and replaces helperText. */\n error?: string;\n /** Disable all cells. */\n disabled?: boolean;\n /** Auto-focus the first cell on mount. Default `false`. */\n autoFocus?: boolean;\n /** id for the wrapping group label association. */\n id?: string;\n className?: string;\n}\n\nconst NUMERIC = /[0-9]/;\nconst ALNUM = /[A-Za-z0-9]/;\n\n/**\n * One-time-password style input — N independent cells, paste support, auto-\n * advance on input, backspace flows back, arrow keys navigate.\n *\n * @example\n * <PinInput length={6} type=\"numeric\" onComplete={(otp) => verify(otp)} />\n */\nexport const PinInput = forwardRef<HTMLDivElement, PinInputProps>(function PinInput(\n {\n length = 6,\n type = \"numeric\",\n size = \"md\",\n value,\n defaultValue,\n onChange,\n onComplete,\n masked = false,\n label,\n helperText,\n error,\n disabled = false,\n autoFocus = false,\n id,\n className,\n },\n ref,\n) {\n const internalId = useId();\n const wrapperId = id ?? internalId;\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<string>(defaultValue ?? \"\");\n const current = isControlled ? (value ?? \"\") : internal;\n const cells = Array.from({ length }, (_, index) => current[index] ?? \"\");\n const inputsRef = useRef<(HTMLInputElement | null)[]>([]);\n const pattern = type === \"numeric\" ? NUMERIC : ALNUM;\n\n useEffect(() => {\n if (autoFocus) inputsRef.current[0]?.focus();\n }, [autoFocus]);\n\n const update = (next: string): void => {\n const trimmed = next.slice(0, length);\n if (!isControlled) setInternal(trimmed);\n onChange?.(trimmed);\n if (trimmed.length === length) onComplete?.(trimmed);\n };\n\n const focusCell = (index: number): void => {\n const safe = Math.max(0, Math.min(length - 1, index));\n inputsRef.current[safe]?.focus();\n inputsRef.current[safe]?.select();\n };\n\n const onCellChange = (index: number) => (event: ChangeEvent<HTMLInputElement>) => {\n const char = event.target.value.slice(-1);\n if (char && !pattern.test(char)) return;\n const next = cells.slice();\n next[index] = char;\n update(next.join(\"\"));\n if (char) focusCell(index + 1);\n };\n\n const onCellKeyDown = (index: number) => (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Backspace\") {\n if (!cells[index] && index > 0) {\n event.preventDefault();\n const next = cells.slice();\n next[index - 1] = \"\";\n update(next.join(\"\"));\n focusCell(index - 1);\n }\n } else if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n focusCell(index - 1);\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n focusCell(index + 1);\n }\n };\n\n const onPaste = (event: ClipboardEvent<HTMLInputElement>): void => {\n const text = event.clipboardData\n .getData(\"text\")\n .split(\"\")\n .filter((c) => pattern.test(c))\n .join(\"\");\n if (!text) return;\n event.preventDefault();\n update(text);\n focusCell(Math.min(length - 1, text.length));\n };\n\n return (\n <div\n ref={ref}\n className={cn(styles.wrapper, error && styles.error, className)}\n id={wrapperId}\n >\n {label && <label className={styles.label}>{label}</label>}\n <div className={cn(styles.cells, styles[size])} role=\"group\" aria-label={label}>\n {cells.map((cell, index) => (\n <input\n key={index}\n ref={(node) => {\n inputsRef.current[index] = node;\n }}\n type={masked ? \"password\" : \"text\"}\n inputMode={type === \"numeric\" ? \"numeric\" : \"text\"}\n autoComplete={index === 0 ? \"one-time-code\" : \"off\"}\n maxLength={1}\n value={cell}\n disabled={disabled}\n className={styles.cell}\n aria-label={`Dígito ${index + 1}`}\n aria-invalid={!!error}\n onChange={onCellChange(index)}\n onKeyDown={onCellKeyDown(index)}\n onPaste={onPaste}\n />\n ))}\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helper}>{helperText}</span>\n ) : null}\n </div>\n );\n});\n"],"mappings":"+HA+CA,IAAM,EAAU,QACV,EAAQ,cASD,GAAA,EAAW,EAAA,WAAA,CAA0C,SAC9D,CACI,SAAS,EACT,OAAO,UACP,OAAO,KACP,QACA,eACA,WACA,aACA,SAAS,GACT,QACA,aACA,QACA,WAAW,GACX,YAAY,GACZ,KACA,aAEJ,EACF,CACE,IAAM,GAAA,EAAa,EAAA,MAAA,CAAM,EACnB,EAAY,GAAM,EAClB,EAAe,IAAU,IAAA,GACzB,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAiB,GAAgB,EAAE,EAC7D,EAAU,EAAgB,GAAS,GAAM,EACzC,EAAQ,MAAM,KAAK,CAAE,QAAO,GAAI,EAAG,IAAU,EAAQ,IAAU,EAAE,EACjE,GAAA,EAAY,EAAA,OAAA,CAAoC,CAAC,CAAC,EAClD,EAAU,IAAS,UAAY,EAAU,GAE/C,EAAA,EAAA,UAAA,KAAgB,CACR,GAAW,EAAU,QAAQ,EAAE,EAAE,MAAM,CAC/C,EAAG,CAAC,CAAS,CAAC,EAEd,IAAM,EAAU,GAAuB,CACnC,IAAM,EAAU,EAAK,MAAM,EAAG,CAAM,EAC/B,GAAc,EAAY,CAAO,EACtC,IAAW,CAAO,EACd,EAAQ,SAAW,GAAQ,IAAa,CAAO,CACvD,EAEM,EAAa,GAAwB,CACvC,IAAM,EAAO,KAAK,IAAI,EAAG,KAAK,IAAI,EAAS,EAAG,CAAK,CAAC,EACpD,EAAU,QAAQ,EAAK,EAAE,MAAM,EAC/B,EAAU,QAAQ,EAAK,EAAE,OAAO,CACpC,EAEM,EAAgB,GAAmB,GAAyC,CAC9E,IAAM,EAAO,EAAM,OAAO,MAAM,MAAM,EAAE,EACxC,GAAI,GAAQ,CAAC,EAAQ,KAAK,CAAI,EAAG,OACjC,IAAM,EAAO,EAAM,MAAM,EACzB,EAAK,GAAS,EACd,EAAO,EAAK,KAAK,EAAE,CAAC,EAChB,GAAM,EAAU,EAAQ,CAAC,CACjC,EAEM,EAAiB,GAAmB,GAA2C,CACjF,GAAI,EAAM,MAAQ,YACV,IAAA,CAAC,EAAM,IAAU,EAAQ,EAAG,CAC5B,EAAM,eAAe,EACrB,IAAM,EAAO,EAAM,MAAM,EACzB,EAAK,EAAQ,GAAK,GAClB,EAAO,EAAK,KAAK,EAAE,CAAC,EACpB,EAAU,EAAQ,CAAC,CACvB,OACO,EAAM,MAAQ,aACrB,EAAM,eAAe,EACrB,EAAU,EAAQ,CAAC,GACZ,EAAM,MAAQ,eACrB,EAAM,eAAe,EACrB,EAAU,EAAQ,CAAC,EAE3B,EAEM,EAAW,GAAkD,CAC/D,IAAM,EAAO,EAAM,cACd,QAAQ,MAAM,CAAC,CACf,MAAM,EAAE,CAAC,CACT,OAAQ,GAAM,EAAQ,KAAK,CAAC,CAAC,CAAC,CAC9B,KAAK,EAAE,EACP,IACL,EAAM,eAAe,EACrB,EAAO,CAAI,EACX,EAAU,KAAK,IAAI,EAAS,EAAG,EAAK,MAAM,CAAC,EAC/C,EAEA,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CACS,MACL,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,GAAS,EAAA,QAAO,MAAO,CAAS,EAC9D,GAAI,EAHR,SAAA,CAKK,IAAS,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAa,CAAA,GACxD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,MAAO,EAAA,QAAO,EAAK,EAAG,KAAK,QAAQ,aAAY,EACpE,SAAA,EAAM,KAAK,EAAM,KACd,EAAA,EAAA,IAAA,CAAC,QAAD,CAEI,IAAM,GAAS,CACX,EAAU,QAAQ,GAAS,CAC/B,EACA,KAAM,EAAS,WAAa,OAC5B,UAAW,IAAS,UAAY,UAAY,OAC5C,aAAc,IAAU,EAAI,gBAAkB,MAC9C,UAAW,EACX,MAAO,EACG,WACV,UAAW,EAAA,QAAO,KAClB,aAAY,UAAU,EAAQ,IAC9B,eAAc,CAAC,CAAC,EAChB,SAAU,EAAa,CAAK,EAC5B,UAAW,EAAc,CAAK,EACrB,SACZ,EAhBQ,CAgBR,CACJ,CACA,CAAA,EACJ,GACG,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,UAAY,SAAA,CAAY,CAAA,EAChD,GACA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,OAAS,SAAA,CAAiB,CAAA,EAClD,IACH,GAEb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PinInput.js","names":[],"sources":["../../../src/components/PinInput/PinInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — one input per digit, so length,\n * type, masked and autoFocus shape the boxes while\n * value/defaultValue/onChange/onComplete drive them as a single value. The body owns\n * the per-box refs, paste distribution and backspace traversal, which only make\n * sense with the whole array in scope.\n */\nimport { forwardRef, useEffect, useId, useRef, useState } from \"react\";\nimport type { ChangeEvent, ClipboardEvent, KeyboardEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./PinInput.module.css\";\n\nexport type PinInputType = \"numeric\" | \"alphanumeric\";\nexport type PinInputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface PinInputProps {\n /** Number of cells. Default `6`. */\n length?: number;\n /** Allowed character set. `numeric` (default) rejects letters, `alphanumeric` allows both. */\n type?: PinInputType;\n /** Visual size. Default `\"md\"`. */\n size?: PinInputSize;\n /** Controlled value. */\n value?: string;\n /** Initial value (uncontrolled mode). */\n defaultValue?: string;\n /** Fires on every change with the current concatenated value. */\n onChange?: (value: string) => void;\n /** Fires when the user fills the last cell. */\n onComplete?: (value: string) => void;\n /** Show characters obscured (`*`). Default `false`. */\n masked?: boolean;\n /** Label rendered above the cells. */\n label?: string;\n /** Helper text below the cells. */\n helperText?: string;\n /** Error message — turns cells red and replaces helperText. */\n error?: string;\n /** Disable all cells. */\n disabled?: boolean;\n /** Auto-focus the first cell on mount. Default `false`. */\n autoFocus?: boolean;\n /** id for the wrapping group label association. */\n id?: string;\n className?: string;\n}\n\nconst NUMERIC = /[0-9]/;\nconst ALNUM = /[A-Za-z0-9]/;\n\n/**\n * One-time-password style input — N independent cells, paste support, auto-\n * advance on input, backspace flows back, arrow keys navigate.\n *\n * @example\n * <PinInput length={6} type=\"numeric\" onComplete={(otp) => verify(otp)} />\n */\nexport const PinInput = forwardRef<HTMLDivElement, PinInputProps>(function PinInput(\n {\n length = 6,\n type = \"numeric\",\n size = \"md\",\n value,\n defaultValue,\n onChange,\n onComplete,\n masked = false,\n label,\n helperText,\n error,\n disabled = false,\n autoFocus = false,\n id,\n className,\n },\n ref,\n) {\n const internalId = useId();\n const wrapperId = id ?? internalId;\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<string>(defaultValue ?? \"\");\n const current = isControlled ? (value ?? \"\") : internal;\n const cells = Array.from({ length }, (_, index) => current[index] ?? \"\");\n const inputsRef = useRef<(HTMLInputElement | null)[]>([]);\n const pattern = type === \"numeric\" ? NUMERIC : ALNUM;\n\n useEffect(() => {\n if (autoFocus) inputsRef.current[0]?.focus();\n }, [autoFocus]);\n\n const update = (next: string): void => {\n const trimmed = next.slice(0, length);\n if (!isControlled) setInternal(trimmed);\n onChange?.(trimmed);\n if (trimmed.length === length) onComplete?.(trimmed);\n };\n\n const focusCell = (index: number): void => {\n const safe = Math.max(0, Math.min(length - 1, index));\n inputsRef.current[safe]?.focus();\n inputsRef.current[safe]?.select();\n };\n\n const onCellChange = (index: number) => (event: ChangeEvent<HTMLInputElement>) => {\n const char = event.target.value.slice(-1);\n if (char && !pattern.test(char)) return;\n const next = cells.slice();\n next[index] = char;\n update(next.join(\"\"));\n if (char) focusCell(index + 1);\n };\n\n const onCellKeyDown = (index: number) => (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Backspace\") {\n if (!cells[index] && index > 0) {\n event.preventDefault();\n const next = cells.slice();\n next[index - 1] = \"\";\n update(next.join(\"\"));\n focusCell(index - 1);\n }\n } else if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n focusCell(index - 1);\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n focusCell(index + 1);\n }\n };\n\n const onPaste = (event: ClipboardEvent<HTMLInputElement>): void => {\n const text = event.clipboardData\n .getData(\"text\")\n .split(\"\")\n .filter((c) => pattern.test(c))\n .join(\"\");\n if (!text) return;\n event.preventDefault();\n update(text);\n focusCell(Math.min(length - 1, text.length));\n };\n\n return (\n <div\n ref={ref}\n className={cn(styles.wrapper, error && styles.error, className)}\n id={wrapperId}\n >\n {label && <label className={styles.label}>{label}</label>}\n <div className={cn(styles.cells, styles[size])} role=\"group\" aria-label={label}>\n {cells.map((cell, index) => (\n <input\n key={index}\n ref={(node) => {\n inputsRef.current[index] = node;\n }}\n type={masked ? \"password\" : \"text\"}\n inputMode={type === \"numeric\" ? \"numeric\" : \"text\"}\n autoComplete={index === 0 ? \"one-time-code\" : \"off\"}\n maxLength={1}\n value={cell}\n disabled={disabled}\n className={styles.cell}\n aria-label={`Dígito ${index + 1}`}\n aria-invalid={!!error}\n onChange={onCellChange(index)}\n onKeyDown={onCellKeyDown(index)}\n onPaste={onPaste}\n />\n ))}\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helper}>{helperText}</span>\n ) : null}\n </div>\n );\n});\n"],"mappings":";;;;;AA+CA,IAAM,IAAU,SACV,IAAQ,eASD,IAAW,EAA0C,SAC9D,EACI,YAAS,GACT,UAAO,WACP,UAAO,MACP,UACA,iBACA,aACA,eACA,YAAS,IACT,UACA,eACA,UACA,cAAW,IACX,eAAY,IACZ,OACA,gBAEJ,GACF;CACE,IAAM,IAAa,EAAM,GACnB,IAAY,KAAM,GAClB,IAAe,MAAU,KAAA,GACzB,CAAC,GAAU,KAAe,EAAiB,KAAgB,EAAE,GAC7D,IAAU,IAAgB,KAAS,KAAM,GACzC,IAAQ,MAAM,KAAK,EAAE,UAAO,IAAI,GAAG,MAAU,EAAQ,MAAU,EAAE,GACjE,IAAY,EAAoC,CAAC,CAAC,GAClD,IAAU,MAAS,YAAY,IAAU;CAE/C,QAAgB;EACZ,AAAI,KAAW,EAAU,QAAQ,EAAE,EAAE,MAAM;CAC/C,GAAG,CAAC,CAAS,CAAC;CAEd,IAAM,KAAU,MAAuB;EACnC,IAAM,IAAU,EAAK,MAAM,GAAG,CAAM;EAGpC,AAFK,KAAc,EAAY,CAAO,GACtC,IAAW,CAAO,GACd,EAAQ,WAAW,KAAQ,IAAa,CAAO;CACvD,GAEM,KAAa,MAAwB;EACvC,IAAM,IAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAS,GAAG,CAAK,CAAC;EAEpD,AADA,EAAU,QAAQ,EAAK,EAAE,MAAM,GAC/B,EAAU,QAAQ,EAAK,EAAE,OAAO;CACpC,GAEM,KAAgB,OAAmB,MAAyC;EAC9E,IAAM,IAAO,EAAM,OAAO,MAAM,MAAM,EAAE;EACxC,IAAI,KAAQ,CAAC,EAAQ,KAAK,CAAI,GAAG;EACjC,IAAM,IAAO,EAAM,MAAM;EAGzB,AAFA,EAAK,KAAS,GACd,EAAO,EAAK,KAAK,EAAE,CAAC,GAChB,KAAM,EAAU,IAAQ,CAAC;CACjC,GAEM,KAAiB,OAAmB,MAA2C;EACjF,IAAI,EAAM,QAAQ;
|
|
1
|
+
{"version":3,"file":"PinInput.js","names":[],"sources":["../../../src/components/PinInput/PinInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — one input per digit, so length,\n * type, masked and autoFocus shape the boxes while\n * value/defaultValue/onChange/onComplete drive them as a single value. The body owns\n * the per-box refs, paste distribution and backspace traversal, which only make\n * sense with the whole array in scope.\n */\nimport { forwardRef, useEffect, useId, useRef, useState } from \"react\";\nimport type { ChangeEvent, ClipboardEvent, KeyboardEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./PinInput.module.css\";\n\nexport type PinInputType = \"numeric\" | \"alphanumeric\";\nexport type PinInputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface PinInputProps {\n /** Number of cells. Default `6`. */\n length?: number;\n /** Allowed character set. `numeric` (default) rejects letters, `alphanumeric` allows both. */\n type?: PinInputType;\n /** Visual size. Default `\"md\"`. */\n size?: PinInputSize;\n /** Controlled value. */\n value?: string;\n /** Initial value (uncontrolled mode). */\n defaultValue?: string;\n /** Fires on every change with the current concatenated value. */\n onChange?: (value: string) => void;\n /** Fires when the user fills the last cell. */\n onComplete?: (value: string) => void;\n /** Show characters obscured (`*`). Default `false`. */\n masked?: boolean;\n /** Label rendered above the cells. */\n label?: string;\n /** Helper text below the cells. */\n helperText?: string;\n /** Error message — turns cells red and replaces helperText. */\n error?: string;\n /** Disable all cells. */\n disabled?: boolean;\n /** Auto-focus the first cell on mount. Default `false`. */\n autoFocus?: boolean;\n /** id for the wrapping group label association. */\n id?: string;\n className?: string;\n}\n\nconst NUMERIC = /[0-9]/;\nconst ALNUM = /[A-Za-z0-9]/;\n\n/**\n * One-time-password style input — N independent cells, paste support, auto-\n * advance on input, backspace flows back, arrow keys navigate.\n *\n * @example\n * <PinInput length={6} type=\"numeric\" onComplete={(otp) => verify(otp)} />\n */\nexport const PinInput = forwardRef<HTMLDivElement, PinInputProps>(function PinInput(\n {\n length = 6,\n type = \"numeric\",\n size = \"md\",\n value,\n defaultValue,\n onChange,\n onComplete,\n masked = false,\n label,\n helperText,\n error,\n disabled = false,\n autoFocus = false,\n id,\n className,\n },\n ref,\n) {\n const internalId = useId();\n const wrapperId = id ?? internalId;\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<string>(defaultValue ?? \"\");\n const current = isControlled ? (value ?? \"\") : internal;\n const cells = Array.from({ length }, (_, index) => current[index] ?? \"\");\n const inputsRef = useRef<(HTMLInputElement | null)[]>([]);\n const pattern = type === \"numeric\" ? NUMERIC : ALNUM;\n\n useEffect(() => {\n if (autoFocus) inputsRef.current[0]?.focus();\n }, [autoFocus]);\n\n const update = (next: string): void => {\n const trimmed = next.slice(0, length);\n if (!isControlled) setInternal(trimmed);\n onChange?.(trimmed);\n if (trimmed.length === length) onComplete?.(trimmed);\n };\n\n const focusCell = (index: number): void => {\n const safe = Math.max(0, Math.min(length - 1, index));\n inputsRef.current[safe]?.focus();\n inputsRef.current[safe]?.select();\n };\n\n const onCellChange = (index: number) => (event: ChangeEvent<HTMLInputElement>) => {\n const char = event.target.value.slice(-1);\n if (char && !pattern.test(char)) return;\n const next = cells.slice();\n next[index] = char;\n update(next.join(\"\"));\n if (char) focusCell(index + 1);\n };\n\n const onCellKeyDown = (index: number) => (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Backspace\") {\n if (!cells[index] && index > 0) {\n event.preventDefault();\n const next = cells.slice();\n next[index - 1] = \"\";\n update(next.join(\"\"));\n focusCell(index - 1);\n }\n } else if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n focusCell(index - 1);\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n focusCell(index + 1);\n }\n };\n\n const onPaste = (event: ClipboardEvent<HTMLInputElement>): void => {\n const text = event.clipboardData\n .getData(\"text\")\n .split(\"\")\n .filter((c) => pattern.test(c))\n .join(\"\");\n if (!text) return;\n event.preventDefault();\n update(text);\n focusCell(Math.min(length - 1, text.length));\n };\n\n return (\n <div\n ref={ref}\n className={cn(styles.wrapper, error && styles.error, className)}\n id={wrapperId}\n >\n {label && <label className={styles.label}>{label}</label>}\n <div className={cn(styles.cells, styles[size])} role=\"group\" aria-label={label}>\n {cells.map((cell, index) => (\n <input\n key={index}\n ref={(node) => {\n inputsRef.current[index] = node;\n }}\n type={masked ? \"password\" : \"text\"}\n inputMode={type === \"numeric\" ? \"numeric\" : \"text\"}\n autoComplete={index === 0 ? \"one-time-code\" : \"off\"}\n maxLength={1}\n value={cell}\n disabled={disabled}\n className={styles.cell}\n aria-label={`Dígito ${index + 1}`}\n aria-invalid={!!error}\n onChange={onCellChange(index)}\n onKeyDown={onCellKeyDown(index)}\n onPaste={onPaste}\n />\n ))}\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helper}>{helperText}</span>\n ) : null}\n </div>\n );\n});\n"],"mappings":";;;;;AA+CA,IAAM,IAAU,SACV,IAAQ,eASD,IAAW,EAA0C,SAC9D,EACI,YAAS,GACT,UAAO,WACP,UAAO,MACP,UACA,iBACA,aACA,eACA,YAAS,IACT,UACA,eACA,UACA,cAAW,IACX,eAAY,IACZ,OACA,gBAEJ,GACF;CACE,IAAM,IAAa,EAAM,GACnB,IAAY,KAAM,GAClB,IAAe,MAAU,KAAA,GACzB,CAAC,GAAU,KAAe,EAAiB,KAAgB,EAAE,GAC7D,IAAU,IAAgB,KAAS,KAAM,GACzC,IAAQ,MAAM,KAAK,EAAE,UAAO,IAAI,GAAG,MAAU,EAAQ,MAAU,EAAE,GACjE,IAAY,EAAoC,CAAC,CAAC,GAClD,IAAU,MAAS,YAAY,IAAU;CAE/C,QAAgB;EACZ,AAAI,KAAW,EAAU,QAAQ,EAAE,EAAE,MAAM;CAC/C,GAAG,CAAC,CAAS,CAAC;CAEd,IAAM,KAAU,MAAuB;EACnC,IAAM,IAAU,EAAK,MAAM,GAAG,CAAM;EAGpC,AAFK,KAAc,EAAY,CAAO,GACtC,IAAW,CAAO,GACd,EAAQ,WAAW,KAAQ,IAAa,CAAO;CACvD,GAEM,KAAa,MAAwB;EACvC,IAAM,IAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAS,GAAG,CAAK,CAAC;EAEpD,AADA,EAAU,QAAQ,EAAK,EAAE,MAAM,GAC/B,EAAU,QAAQ,EAAK,EAAE,OAAO;CACpC,GAEM,KAAgB,OAAmB,MAAyC;EAC9E,IAAM,IAAO,EAAM,OAAO,MAAM,MAAM,EAAE;EACxC,IAAI,KAAQ,CAAC,EAAQ,KAAK,CAAI,GAAG;EACjC,IAAM,IAAO,EAAM,MAAM;EAGzB,AAFA,EAAK,KAAS,GACd,EAAO,EAAK,KAAK,EAAE,CAAC,GAChB,KAAM,EAAU,IAAQ,CAAC;CACjC,GAEM,KAAiB,OAAmB,MAA2C;EACjF,IAAI,EAAM,QAAQ,aACV;OAAA,CAAC,EAAM,MAAU,IAAQ,GAAG;IAC5B,EAAM,eAAe;IACrB,IAAM,IAAO,EAAM,MAAM;IAGzB,AAFA,EAAK,IAAQ,KAAK,IAClB,EAAO,EAAK,KAAK,EAAE,CAAC,GACpB,EAAU,IAAQ,CAAC;GACvB;SACG,AAAI,EAAM,QAAQ,eACrB,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAC,KACZ,EAAM,QAAQ,iBACrB,EAAM,eAAe,GACrB,EAAU,IAAQ,CAAC;CAE3B,GAEM,KAAW,MAAkD;EAC/D,IAAM,IAAO,EAAM,cACd,QAAQ,MAAM,CAAC,CACf,MAAM,EAAE,CAAC,CACT,QAAQ,MAAM,EAAQ,KAAK,CAAC,CAAC,CAAC,CAC9B,KAAK,EAAE;EACP,MACL,EAAM,eAAe,GACrB,EAAO,CAAI,GACX,EAAU,KAAK,IAAI,IAAS,GAAG,EAAK,MAAM,CAAC;CAC/C;CAEA,OACI,kBAAC,OAAD;EACS;EACL,WAAW,EAAG,EAAO,SAAS,KAAS,EAAO,OAAO,CAAS;EAC9D,IAAI;EAHR,UAAA;GAKK,KAAS,kBAAC,SAAD;IAAO,WAAW,EAAO;IAAQ,UAAA;GAAa,CAAA;GACxD,kBAAC,OAAD;IAAK,WAAW,EAAG,EAAO,OAAO,EAAO,EAAK;IAAG,MAAK;IAAQ,cAAY;IACpE,UAAA,EAAM,KAAK,GAAM,MACd,kBAAC,SAAD;KAEI,MAAM,MAAS;MACX,EAAU,QAAQ,KAAS;KAC/B;KACA,MAAM,IAAS,aAAa;KAC5B,WAAW,MAAS,YAAY,YAAY;KAC5C,cAAc,MAAU,IAAI,kBAAkB;KAC9C,WAAW;KACX,OAAO;KACG;KACV,WAAW,EAAO;KAClB,cAAY,UAAU,IAAQ;KAC9B,gBAAc,CAAC,CAAC;KAChB,UAAU,EAAa,CAAK;KAC5B,WAAW,EAAc,CAAK;KACrB;IACZ,GAhBQ,CAgBR,CACJ;GACA,CAAA;GACJ,IACG,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAY,UAAA;GAAY,CAAA,IAChD,IACA,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAS,UAAA;GAAiB,CAAA,IAClD;EACH;;AAEb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.cjs","names":[],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — trigger and children are the two halves, placement\n * is where it lands, and open/onOpenChange/defaultOpen is the standard controlled-\n * or-not pair. closeOnEsc and closeOnOutsideClick are separate because a popover\n * holding a form wants one and not the other.\n */\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Popover.module.css\";\n\nexport type PopoverPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface PopoverProps {\n /** Trigger element. Receives `onClick`/`aria-expanded`/`aria-controls`. */\n trigger: ReactElement<{\n onClick?: (e: React.MouseEvent) => void;\n \"aria-expanded\"?: boolean;\n \"aria-controls\"?: string;\n }>;\n children: ReactNode;\n placement?: PopoverPlacement;\n /** Controlled open state. */\n open?: boolean;\n /** Called when the user toggles or dismisses. */\n onOpenChange?: (open: boolean) => void;\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean;\n /** Close on Escape. Default true. */\n closeOnEsc?: boolean;\n /** Close on outside click. Default true. */\n closeOnOutsideClick?: boolean;\n className?: string;\n}\n\n/**\n * Lightweight popover. Renders a positioned panel anchored to a trigger,\n * dismissed on outside click / Escape. Does NOT include collision detection\n * or smart positioning — pair with Floating UI if you need that.\n */\nexport function Popover({\n trigger,\n children,\n placement = \"bottom\",\n open,\n onOpenChange,\n defaultOpen = false,\n closeOnEsc = true,\n closeOnOutsideClick = true,\n className,\n}: PopoverProps) {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState<boolean>(defaultOpen);\n const isOpen = isControlled ? open : internalOpen;\n const id = useId();\n const rootRef = useRef<HTMLSpanElement>(null);\n\n const setOpen = useCallback(\n (next: boolean): void => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n useEffect(() => {\n if (!isOpen) return;\n const onKey = (event: KeyboardEvent): void => {\n if (closeOnEsc && event.key === \"Escape\") setOpen(false);\n };\n const onDown = (event: MouseEvent): void => {\n if (!closeOnOutsideClick) return;\n if (rootRef.current && !rootRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n window.addEventListener(\"keydown\", onKey);\n window.addEventListener(\"mousedown\", onDown);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n window.removeEventListener(\"mousedown\", onDown);\n };\n }, [isOpen, closeOnEsc, closeOnOutsideClick, setOpen]);\n\n const handleTriggerClick = (event: React.MouseEvent): void => {\n trigger.props.onClick?.(event);\n setOpen(!isOpen);\n };\n\n const triggerClone = {\n ...trigger,\n props: {\n ...trigger.props,\n onClick: handleTriggerClick,\n \"aria-expanded\": isOpen,\n \"aria-controls\": id,\n },\n } as ReactElement;\n\n return (\n <span ref={rootRef} className={styles.root}>\n {triggerClone}\n {isOpen && (\n <div\n id={id}\n role=\"dialog\"\n className={cn(styles.popover, styles[placement], className)}\n >\n {children}\n </div>\n )}\n </span>\n );\n}\n"],"mappings":"8HAwCA,SAAgB,EAAQ,CACpB,UACA,WACA,YAAY,SACZ,OACA,eACA,cAAc,GACd,aAAa,GACb,sBAAsB,GACtB,aACa,CACb,IAAM,EAAe,IAAS,IAAA,GACxB,CAAC,EAAc,IAAA,
|
|
1
|
+
{"version":3,"file":"Popover.cjs","names":[],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — trigger and children are the two halves, placement\n * is where it lands, and open/onOpenChange/defaultOpen is the standard controlled-\n * or-not pair. closeOnEsc and closeOnOutsideClick are separate because a popover\n * holding a form wants one and not the other.\n */\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Popover.module.css\";\n\nexport type PopoverPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface PopoverProps {\n /** Trigger element. Receives `onClick`/`aria-expanded`/`aria-controls`. */\n trigger: ReactElement<{\n onClick?: (e: React.MouseEvent) => void;\n \"aria-expanded\"?: boolean;\n \"aria-controls\"?: string;\n }>;\n children: ReactNode;\n placement?: PopoverPlacement;\n /** Controlled open state. */\n open?: boolean;\n /** Called when the user toggles or dismisses. */\n onOpenChange?: (open: boolean) => void;\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean;\n /** Close on Escape. Default true. */\n closeOnEsc?: boolean;\n /** Close on outside click. Default true. */\n closeOnOutsideClick?: boolean;\n className?: string;\n}\n\n/**\n * Lightweight popover. Renders a positioned panel anchored to a trigger,\n * dismissed on outside click / Escape. Does NOT include collision detection\n * or smart positioning — pair with Floating UI if you need that.\n */\nexport function Popover({\n trigger,\n children,\n placement = \"bottom\",\n open,\n onOpenChange,\n defaultOpen = false,\n closeOnEsc = true,\n closeOnOutsideClick = true,\n className,\n}: PopoverProps) {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState<boolean>(defaultOpen);\n const isOpen = isControlled ? open : internalOpen;\n const id = useId();\n const rootRef = useRef<HTMLSpanElement>(null);\n\n const setOpen = useCallback(\n (next: boolean): void => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n useEffect(() => {\n if (!isOpen) return;\n const onKey = (event: KeyboardEvent): void => {\n if (closeOnEsc && event.key === \"Escape\") setOpen(false);\n };\n const onDown = (event: MouseEvent): void => {\n if (!closeOnOutsideClick) return;\n if (rootRef.current && !rootRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n window.addEventListener(\"keydown\", onKey);\n window.addEventListener(\"mousedown\", onDown);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n window.removeEventListener(\"mousedown\", onDown);\n };\n }, [isOpen, closeOnEsc, closeOnOutsideClick, setOpen]);\n\n const handleTriggerClick = (event: React.MouseEvent): void => {\n trigger.props.onClick?.(event);\n setOpen(!isOpen);\n };\n\n const triggerClone = {\n ...trigger,\n props: {\n ...trigger.props,\n onClick: handleTriggerClick,\n \"aria-expanded\": isOpen,\n \"aria-controls\": id,\n },\n } as ReactElement;\n\n return (\n <span ref={rootRef} className={styles.root}>\n {triggerClone}\n {isOpen && (\n <div\n id={id}\n role=\"dialog\"\n className={cn(styles.popover, styles[placement], className)}\n >\n {children}\n </div>\n )}\n </span>\n );\n}\n"],"mappings":"8HAwCA,SAAgB,EAAQ,CACpB,UACA,WACA,YAAY,SACZ,OACA,eACA,cAAc,GACd,aAAa,GACb,sBAAsB,GACtB,aACa,CACb,IAAM,EAAe,IAAS,IAAA,GACxB,CAAC,EAAc,IAAA,EAAmB,EAAA,SAAA,CAAkB,CAAW,EAC/D,EAAS,EAAe,EAAO,EAC/B,GAAA,EAAK,EAAA,MAAA,CAAM,EACX,GAAA,EAAU,EAAA,OAAA,CAAwB,IAAI,EAEtC,GAAA,EAAU,EAAA,YAAA,CACX,GAAwB,CAChB,GAAc,EAAgB,CAAI,EACvC,IAAe,CAAI,CACvB,EACA,CAAC,EAAc,CAAY,CAC/B,GAEA,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,CAAC,EAAQ,OACb,IAAM,EAAS,GAA+B,CACtC,GAAc,EAAM,MAAQ,UAAU,EAAQ,EAAK,CAC3D,EACM,EAAU,GAA4B,CACnC,GACD,EAAQ,SAAW,CAAC,EAAQ,QAAQ,SAAS,EAAM,MAAc,GACjE,EAAQ,EAAK,CAErB,EAGA,OAFA,OAAO,iBAAiB,UAAW,CAAK,EACxC,OAAO,iBAAiB,YAAa,CAAM,MAC9B,CACT,OAAO,oBAAoB,UAAW,CAAK,EAC3C,OAAO,oBAAoB,YAAa,CAAM,CAClD,CACJ,EAAG,CAAC,EAAQ,EAAY,EAAqB,CAAO,CAAC,EAErD,IAAM,EAAsB,GAAkC,CAC1D,EAAQ,MAAM,UAAU,CAAK,EAC7B,EAAQ,CAAC,CAAM,CACnB,EAEM,EAAe,CACjB,GAAG,EACH,MAAO,CACH,GAAG,EAAQ,MACX,QAAS,EACT,gBAAiB,EACjB,gBAAiB,CACrB,CACJ,EAEA,OACI,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,IAAK,EAAS,UAAW,EAAA,QAAO,KAAtC,SAAA,CACK,EACA,IACG,EAAA,EAAA,IAAA,CAAC,MAAD,CACQ,KACJ,KAAK,SACL,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,EAAA,QAAO,GAAY,CAAS,EAEzD,UACA,CAAA,CAEP,GAEd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","names":[],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — trigger and children are the two halves, placement\n * is where it lands, and open/onOpenChange/defaultOpen is the standard controlled-\n * or-not pair. closeOnEsc and closeOnOutsideClick are separate because a popover\n * holding a form wants one and not the other.\n */\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Popover.module.css\";\n\nexport type PopoverPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface PopoverProps {\n /** Trigger element. Receives `onClick`/`aria-expanded`/`aria-controls`. */\n trigger: ReactElement<{\n onClick?: (e: React.MouseEvent) => void;\n \"aria-expanded\"?: boolean;\n \"aria-controls\"?: string;\n }>;\n children: ReactNode;\n placement?: PopoverPlacement;\n /** Controlled open state. */\n open?: boolean;\n /** Called when the user toggles or dismisses. */\n onOpenChange?: (open: boolean) => void;\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean;\n /** Close on Escape. Default true. */\n closeOnEsc?: boolean;\n /** Close on outside click. Default true. */\n closeOnOutsideClick?: boolean;\n className?: string;\n}\n\n/**\n * Lightweight popover. Renders a positioned panel anchored to a trigger,\n * dismissed on outside click / Escape. Does NOT include collision detection\n * or smart positioning — pair with Floating UI if you need that.\n */\nexport function Popover({\n trigger,\n children,\n placement = \"bottom\",\n open,\n onOpenChange,\n defaultOpen = false,\n closeOnEsc = true,\n closeOnOutsideClick = true,\n className,\n}: PopoverProps) {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState<boolean>(defaultOpen);\n const isOpen = isControlled ? open : internalOpen;\n const id = useId();\n const rootRef = useRef<HTMLSpanElement>(null);\n\n const setOpen = useCallback(\n (next: boolean): void => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n useEffect(() => {\n if (!isOpen) return;\n const onKey = (event: KeyboardEvent): void => {\n if (closeOnEsc && event.key === \"Escape\") setOpen(false);\n };\n const onDown = (event: MouseEvent): void => {\n if (!closeOnOutsideClick) return;\n if (rootRef.current && !rootRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n window.addEventListener(\"keydown\", onKey);\n window.addEventListener(\"mousedown\", onDown);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n window.removeEventListener(\"mousedown\", onDown);\n };\n }, [isOpen, closeOnEsc, closeOnOutsideClick, setOpen]);\n\n const handleTriggerClick = (event: React.MouseEvent): void => {\n trigger.props.onClick?.(event);\n setOpen(!isOpen);\n };\n\n const triggerClone = {\n ...trigger,\n props: {\n ...trigger.props,\n onClick: handleTriggerClick,\n \"aria-expanded\": isOpen,\n \"aria-controls\": id,\n },\n } as ReactElement;\n\n return (\n <span ref={rootRef} className={styles.root}>\n {triggerClone}\n {isOpen && (\n <div\n id={id}\n role=\"dialog\"\n className={cn(styles.popover, styles[placement], className)}\n >\n {children}\n </div>\n )}\n </span>\n );\n}\n"],"mappings":";;;;;AAwCA,SAAgB,EAAQ,EACpB,YACA,aACA,eAAY,UACZ,SACA,iBACA,iBAAc,IACd,gBAAa,IACb,yBAAsB,IACtB,gBACa;CACb,IAAM,IAAe,MAAS,KAAA,GACxB,CAAC,GAAc,KAAmB,EAAkB,CAAW,GAC/D,IAAS,IAAe,IAAO,GAC/B,IAAK,EAAM,GACX,IAAU,EAAwB,IAAI,GAEtC,IAAU,GACX,MAAwB;EAErB,AADK,KAAc,EAAgB,CAAI,GACvC,IAAe,CAAI;CACvB,GACA,CAAC,GAAc,CAAY,CAC/B;CAEA,QAAgB;EACZ,IAAI,CAAC,GAAQ;EACb,IAAM,KAAS,MAA+B;GAC1C,AAAI,KAAc,EAAM,QAAQ,YAAU,EAAQ,EAAK;EAC3D,GACM,KAAU,MAA4B;GACnC,KACD,EAAQ,WAAW,CAAC,EAAQ,QAAQ,SAAS,EAAM,MAAc,KACjE,EAAQ,EAAK;EAErB;EAGA,OAFA,OAAO,iBAAiB,WAAW,CAAK,GACxC,OAAO,iBAAiB,aAAa,CAAM,SAC9B;GAET,AADA,OAAO,oBAAoB,WAAW,CAAK,GAC3C,OAAO,oBAAoB,aAAa,CAAM;EAClD;CACJ,GAAG;EAAC;EAAQ;EAAY;EAAqB;CAAO,CAAC;CAErD,IAAM,KAAsB,MAAkC;EAE1D,AADA,EAAQ,MAAM,UAAU,CAAK,GAC7B,EAAQ,CAAC,CAAM;CACnB,GAEM,IAAe;EACjB,GAAG;EACH,OAAO;GACH,GAAG,EAAQ;GACX,SAAS;GACT,iBAAiB;GACjB,iBAAiB;EACrB;CACJ;CAEA,OACI,kBAAC,QAAD;EAAM,KAAK;EAAS,WAAW,EAAO;
|
|
1
|
+
{"version":3,"file":"Popover.js","names":[],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — trigger and children are the two halves, placement\n * is where it lands, and open/onOpenChange/defaultOpen is the standard controlled-\n * or-not pair. closeOnEsc and closeOnOutsideClick are separate because a popover\n * holding a form wants one and not the other.\n */\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Popover.module.css\";\n\nexport type PopoverPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface PopoverProps {\n /** Trigger element. Receives `onClick`/`aria-expanded`/`aria-controls`. */\n trigger: ReactElement<{\n onClick?: (e: React.MouseEvent) => void;\n \"aria-expanded\"?: boolean;\n \"aria-controls\"?: string;\n }>;\n children: ReactNode;\n placement?: PopoverPlacement;\n /** Controlled open state. */\n open?: boolean;\n /** Called when the user toggles or dismisses. */\n onOpenChange?: (open: boolean) => void;\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean;\n /** Close on Escape. Default true. */\n closeOnEsc?: boolean;\n /** Close on outside click. Default true. */\n closeOnOutsideClick?: boolean;\n className?: string;\n}\n\n/**\n * Lightweight popover. Renders a positioned panel anchored to a trigger,\n * dismissed on outside click / Escape. Does NOT include collision detection\n * or smart positioning — pair with Floating UI if you need that.\n */\nexport function Popover({\n trigger,\n children,\n placement = \"bottom\",\n open,\n onOpenChange,\n defaultOpen = false,\n closeOnEsc = true,\n closeOnOutsideClick = true,\n className,\n}: PopoverProps) {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState<boolean>(defaultOpen);\n const isOpen = isControlled ? open : internalOpen;\n const id = useId();\n const rootRef = useRef<HTMLSpanElement>(null);\n\n const setOpen = useCallback(\n (next: boolean): void => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n useEffect(() => {\n if (!isOpen) return;\n const onKey = (event: KeyboardEvent): void => {\n if (closeOnEsc && event.key === \"Escape\") setOpen(false);\n };\n const onDown = (event: MouseEvent): void => {\n if (!closeOnOutsideClick) return;\n if (rootRef.current && !rootRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n window.addEventListener(\"keydown\", onKey);\n window.addEventListener(\"mousedown\", onDown);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n window.removeEventListener(\"mousedown\", onDown);\n };\n }, [isOpen, closeOnEsc, closeOnOutsideClick, setOpen]);\n\n const handleTriggerClick = (event: React.MouseEvent): void => {\n trigger.props.onClick?.(event);\n setOpen(!isOpen);\n };\n\n const triggerClone = {\n ...trigger,\n props: {\n ...trigger.props,\n onClick: handleTriggerClick,\n \"aria-expanded\": isOpen,\n \"aria-controls\": id,\n },\n } as ReactElement;\n\n return (\n <span ref={rootRef} className={styles.root}>\n {triggerClone}\n {isOpen && (\n <div\n id={id}\n role=\"dialog\"\n className={cn(styles.popover, styles[placement], className)}\n >\n {children}\n </div>\n )}\n </span>\n );\n}\n"],"mappings":";;;;;AAwCA,SAAgB,EAAQ,EACpB,YACA,aACA,eAAY,UACZ,SACA,iBACA,iBAAc,IACd,gBAAa,IACb,yBAAsB,IACtB,gBACa;CACb,IAAM,IAAe,MAAS,KAAA,GACxB,CAAC,GAAc,KAAmB,EAAkB,CAAW,GAC/D,IAAS,IAAe,IAAO,GAC/B,IAAK,EAAM,GACX,IAAU,EAAwB,IAAI,GAEtC,IAAU,GACX,MAAwB;EAErB,AADK,KAAc,EAAgB,CAAI,GACvC,IAAe,CAAI;CACvB,GACA,CAAC,GAAc,CAAY,CAC/B;CAEA,QAAgB;EACZ,IAAI,CAAC,GAAQ;EACb,IAAM,KAAS,MAA+B;GAC1C,AAAI,KAAc,EAAM,QAAQ,YAAU,EAAQ,EAAK;EAC3D,GACM,KAAU,MAA4B;GACnC,KACD,EAAQ,WAAW,CAAC,EAAQ,QAAQ,SAAS,EAAM,MAAc,KACjE,EAAQ,EAAK;EAErB;EAGA,OAFA,OAAO,iBAAiB,WAAW,CAAK,GACxC,OAAO,iBAAiB,aAAa,CAAM,SAC9B;GAET,AADA,OAAO,oBAAoB,WAAW,CAAK,GAC3C,OAAO,oBAAoB,aAAa,CAAM;EAClD;CACJ,GAAG;EAAC;EAAQ;EAAY;EAAqB;CAAO,CAAC;CAErD,IAAM,KAAsB,MAAkC;EAE1D,AADA,EAAQ,MAAM,UAAU,CAAK,GAC7B,EAAQ,CAAC,CAAM;CACnB,GAEM,IAAe;EACjB,GAAG;EACH,OAAO;GACH,GAAG,EAAQ;GACX,SAAS;GACT,iBAAiB;GACjB,iBAAiB;EACrB;CACJ;CAEA,OACI,kBAAC,QAAD;EAAM,KAAK;EAAS,WAAW,EAAO;EAAtC,UAAA,CACK,GACA,KACG,kBAAC,OAAD;GACQ;GACJ,MAAK;GACL,WAAW,EAAG,EAAO,SAAS,EAAO,IAAY,CAAS;GAEzD;EACA,CAAA,CAEP;;AAEd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Portal.cjs","names":[],"sources":["../../../src/components/Portal/Portal.tsx"],"sourcesContent":["import { useEffect, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport interface PortalProps {\n /** Content rendered through the portal. */\n children: ReactNode;\n /** Target DOM node to render into. Defaults to `document.body`. */\n container?: Element | null;\n}\n\n/**\n * Renders its children into a different part of the DOM tree via a React portal.\n *\n * Useful for overlays (modals, tooltips, dropdowns) that must escape parent\n * overflow/stacking contexts. Defaults to `document.body` when no `container`\n * is provided.\n *\n * SSR-safe: renders `null` on the server and on the first client render, then\n * mounts the portal after hydration (when `document` is available).\n *\n * @param props - The portal props.\n * @returns The portal node once mounted, otherwise `null`.\n */\nexport function Portal({ children, container }: PortalProps): ReactNode {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n return () => setMounted(false);\n }, []);\n\n if (!mounted || typeof document === \"undefined\") {\n return null;\n }\n\n return createPortal(children, container ?? document.body);\n}\n"],"mappings":"8CAuBA,SAAgB,EAAO,CAAE,WAAU,aAAqC,CACpE,GAAM,CAAC,EAAS,IAAA,
|
|
1
|
+
{"version":3,"file":"Portal.cjs","names":[],"sources":["../../../src/components/Portal/Portal.tsx"],"sourcesContent":["import { useEffect, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport interface PortalProps {\n /** Content rendered through the portal. */\n children: ReactNode;\n /** Target DOM node to render into. Defaults to `document.body`. */\n container?: Element | null;\n}\n\n/**\n * Renders its children into a different part of the DOM tree via a React portal.\n *\n * Useful for overlays (modals, tooltips, dropdowns) that must escape parent\n * overflow/stacking contexts. Defaults to `document.body` when no `container`\n * is provided.\n *\n * SSR-safe: renders `null` on the server and on the first client render, then\n * mounts the portal after hydration (when `document` is available).\n *\n * @param props - The portal props.\n * @returns The portal node once mounted, otherwise `null`.\n */\nexport function Portal({ children, container }: PortalProps): ReactNode {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n return () => setMounted(false);\n }, []);\n\n if (!mounted || typeof document === \"undefined\") {\n return null;\n }\n\n return createPortal(children, container ?? document.body);\n}\n"],"mappings":"8CAuBA,SAAgB,EAAO,CAAE,WAAU,aAAqC,CACpE,GAAM,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAS,EAAK,EAW5C,OATA,EAAA,EAAA,UAAA,MACI,EAAW,EAAI,MACF,EAAW,EAAK,GAC9B,CAAC,CAAC,EAED,CAAC,GAAW,OAAO,SAAa,IACzB,MAGX,EAAO,EAAA,aAAA,CAAa,EAAU,GAAa,SAAS,IAAI,CAC5D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Progress.cjs","names":[],"sources":["../../../src/components/Progress/Progress.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — value, max, indeterminate, size, tone, label,\n * showValue and className: a progress bar is one element with eight independent\n * presentation choices, and the destructuring counts them all because none has a\n * sensible sub-object.\n */\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Progress.module.css\";\n\nexport type ProgressVariant = \"primary\" | \"success\" | \"warning\" | \"danger\";\n\nexport interface ProgressProps {\n /** Value between 0 and `max` (or 0-100 by default). Ignored when `indeterminate`. */\n value?: number;\n max?: number;\n variant?: ProgressVariant;\n /** Show an animated indeterminate bar. Default: false. */\n indeterminate?: boolean;\n /** Render a numeric label \"x% / max\" above the bar. Default: false. */\n showLabel?: boolean;\n /** Optional left-aligned descriptor (e.g. \"Enviando arquivo…\"). */\n label?: string;\n /**\n * Accessible name for the bar. Defaults to `label` when that is set —\n * provide it explicitly whenever the bar renders without a visible label,\n * otherwise screen readers announce an unnamed progressbar.\n */\n \"aria-label\"?: string;\n /** Id of an existing element that names the bar (alternative to `aria-label`). */\n \"aria-labelledby\"?: string;\n className?: string;\n}\n\n/**\n * Linear progress bar with determinate / indeterminate modes.\n *\n * The `progressbar` role requires an accessible name: it comes from\n * `aria-labelledby`, then explicit `aria-label`, then the visible `label`.\n */\nexport function Progress({\n value = 0,\n max = 100,\n variant = \"primary\",\n indeterminate = false,\n showLabel = false,\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n className,\n}: ProgressProps) {\n const pct = indeterminate ? 0 : Math.max(0, Math.min(100, (value / max) * 100));\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {(showLabel || label) && (\n <div className={styles.label}>\n {label && <span>{label}</span>}\n {showLabel && !indeterminate && <span>{Math.round(pct)}%</span>}\n </div>\n )}\n <div\n role=\"progressbar\"\n aria-label={ariaLabelledBy ? undefined : (ariaLabel ?? label)}\n aria-labelledby={ariaLabelledBy}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={indeterminate ? undefined : value}\n className={cn(styles.bar, indeterminate && styles.indeterminate)}\n >\n <div\n className={cn(styles.fill, variant !== \"primary\" && styles[variant])}\n style={{ width: indeterminate ? undefined : `${pct}%` }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":"4GAuCA,SAAgB,EAAS,CACrB,QAAQ,EACR,MAAM,IACN,UAAU,UACV,gBAAgB,GAChB,YAAY,GACZ,QACA,aAAc,EACd,kBAAmB,EACnB,aACc,CACd,IAAM,EAAM,EAAgB,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,IAAM,EAAQ,EAAO,GAAG,CAAC,EAE9E,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,
|
|
1
|
+
{"version":3,"file":"Progress.cjs","names":[],"sources":["../../../src/components/Progress/Progress.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — value, max, indeterminate, size, tone, label,\n * showValue and className: a progress bar is one element with eight independent\n * presentation choices, and the destructuring counts them all because none has a\n * sensible sub-object.\n */\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Progress.module.css\";\n\nexport type ProgressVariant = \"primary\" | \"success\" | \"warning\" | \"danger\";\n\nexport interface ProgressProps {\n /** Value between 0 and `max` (or 0-100 by default). Ignored when `indeterminate`. */\n value?: number;\n max?: number;\n variant?: ProgressVariant;\n /** Show an animated indeterminate bar. Default: false. */\n indeterminate?: boolean;\n /** Render a numeric label \"x% / max\" above the bar. Default: false. */\n showLabel?: boolean;\n /** Optional left-aligned descriptor (e.g. \"Enviando arquivo…\"). */\n label?: string;\n /**\n * Accessible name for the bar. Defaults to `label` when that is set —\n * provide it explicitly whenever the bar renders without a visible label,\n * otherwise screen readers announce an unnamed progressbar.\n */\n \"aria-label\"?: string;\n /** Id of an existing element that names the bar (alternative to `aria-label`). */\n \"aria-labelledby\"?: string;\n className?: string;\n}\n\n/**\n * Linear progress bar with determinate / indeterminate modes.\n *\n * The `progressbar` role requires an accessible name: it comes from\n * `aria-labelledby`, then explicit `aria-label`, then the visible `label`.\n */\nexport function Progress({\n value = 0,\n max = 100,\n variant = \"primary\",\n indeterminate = false,\n showLabel = false,\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n className,\n}: ProgressProps) {\n const pct = indeterminate ? 0 : Math.max(0, Math.min(100, (value / max) * 100));\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {(showLabel || label) && (\n <div className={styles.label}>\n {label && <span>{label}</span>}\n {showLabel && !indeterminate && <span>{Math.round(pct)}%</span>}\n </div>\n )}\n <div\n role=\"progressbar\"\n aria-label={ariaLabelledBy ? undefined : (ariaLabel ?? label)}\n aria-labelledby={ariaLabelledBy}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={indeterminate ? undefined : value}\n className={cn(styles.bar, indeterminate && styles.indeterminate)}\n >\n <div\n className={cn(styles.fill, variant !== \"primary\" && styles[variant])}\n style={{ width: indeterminate ? undefined : `${pct}%` }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":"4GAuCA,SAAgB,EAAS,CACrB,QAAQ,EACR,MAAM,IACN,UAAU,UACV,gBAAgB,GAChB,YAAY,GACZ,QACA,aAAc,EACd,kBAAmB,EACnB,aACc,CACd,IAAM,EAAM,EAAgB,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,IAAM,EAAQ,EAAO,GAAG,CAAC,EAE9E,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAA5C,SAAA,EACM,GAAa,KACX,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAvB,SAAA,CACK,IAAS,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,CAAY,CAAA,EAC5B,GAAa,CAAC,IAAiB,EAAA,EAAA,KAAA,CAAC,OAAD,CAAA,SAAA,CAAO,KAAK,MAAM,CAAG,EAAE,GAAO,CAAA,CAAA,CAC7D,CAET,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,KAAK,cACL,aAAY,EAAiB,IAAA,GAAa,GAAa,EACvD,kBAAiB,EACjB,gBAAe,EACf,gBAAe,EACf,gBAAe,EAAgB,IAAA,GAAY,EAC3C,UAAW,EAAA,GAAG,EAAA,QAAO,IAAK,GAAiB,EAAA,QAAO,aAAa,EAE/D,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,IAAY,WAAa,EAAA,QAAO,EAAQ,EACnE,MAAO,CAAE,MAAO,EAAgB,IAAA,GAAY,GAAG,EAAI,EAAG,CACzD,CAAA,CACA,CAAA,CACJ,GAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Progress.js","names":[],"sources":["../../../src/components/Progress/Progress.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — value, max, indeterminate, size, tone, label,\n * showValue and className: a progress bar is one element with eight independent\n * presentation choices, and the destructuring counts them all because none has a\n * sensible sub-object.\n */\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Progress.module.css\";\n\nexport type ProgressVariant = \"primary\" | \"success\" | \"warning\" | \"danger\";\n\nexport interface ProgressProps {\n /** Value between 0 and `max` (or 0-100 by default). Ignored when `indeterminate`. */\n value?: number;\n max?: number;\n variant?: ProgressVariant;\n /** Show an animated indeterminate bar. Default: false. */\n indeterminate?: boolean;\n /** Render a numeric label \"x% / max\" above the bar. Default: false. */\n showLabel?: boolean;\n /** Optional left-aligned descriptor (e.g. \"Enviando arquivo…\"). */\n label?: string;\n /**\n * Accessible name for the bar. Defaults to `label` when that is set —\n * provide it explicitly whenever the bar renders without a visible label,\n * otherwise screen readers announce an unnamed progressbar.\n */\n \"aria-label\"?: string;\n /** Id of an existing element that names the bar (alternative to `aria-label`). */\n \"aria-labelledby\"?: string;\n className?: string;\n}\n\n/**\n * Linear progress bar with determinate / indeterminate modes.\n *\n * The `progressbar` role requires an accessible name: it comes from\n * `aria-labelledby`, then explicit `aria-label`, then the visible `label`.\n */\nexport function Progress({\n value = 0,\n max = 100,\n variant = \"primary\",\n indeterminate = false,\n showLabel = false,\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n className,\n}: ProgressProps) {\n const pct = indeterminate ? 0 : Math.max(0, Math.min(100, (value / max) * 100));\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {(showLabel || label) && (\n <div className={styles.label}>\n {label && <span>{label}</span>}\n {showLabel && !indeterminate && <span>{Math.round(pct)}%</span>}\n </div>\n )}\n <div\n role=\"progressbar\"\n aria-label={ariaLabelledBy ? undefined : (ariaLabel ?? label)}\n aria-labelledby={ariaLabelledBy}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={indeterminate ? undefined : value}\n className={cn(styles.bar, indeterminate && styles.indeterminate)}\n >\n <div\n className={cn(styles.fill, variant !== \"primary\" && styles[variant])}\n style={{ width: indeterminate ? undefined : `${pct}%` }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;AAuCA,SAAgB,EAAS,EACrB,WAAQ,GACR,SAAM,KACN,aAAU,WACV,mBAAgB,IAChB,eAAY,IACZ,UACA,cAAc,GACd,mBAAmB,GACnB,gBACc;CACd,IAAM,IAAM,IAAgB,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,KAAM,IAAQ,IAAO,GAAG,CAAC;CAE9E,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;
|
|
1
|
+
{"version":3,"file":"Progress.js","names":[],"sources":["../../../src/components/Progress/Progress.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — value, max, indeterminate, size, tone, label,\n * showValue and className: a progress bar is one element with eight independent\n * presentation choices, and the destructuring counts them all because none has a\n * sensible sub-object.\n */\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Progress.module.css\";\n\nexport type ProgressVariant = \"primary\" | \"success\" | \"warning\" | \"danger\";\n\nexport interface ProgressProps {\n /** Value between 0 and `max` (or 0-100 by default). Ignored when `indeterminate`. */\n value?: number;\n max?: number;\n variant?: ProgressVariant;\n /** Show an animated indeterminate bar. Default: false. */\n indeterminate?: boolean;\n /** Render a numeric label \"x% / max\" above the bar. Default: false. */\n showLabel?: boolean;\n /** Optional left-aligned descriptor (e.g. \"Enviando arquivo…\"). */\n label?: string;\n /**\n * Accessible name for the bar. Defaults to `label` when that is set —\n * provide it explicitly whenever the bar renders without a visible label,\n * otherwise screen readers announce an unnamed progressbar.\n */\n \"aria-label\"?: string;\n /** Id of an existing element that names the bar (alternative to `aria-label`). */\n \"aria-labelledby\"?: string;\n className?: string;\n}\n\n/**\n * Linear progress bar with determinate / indeterminate modes.\n *\n * The `progressbar` role requires an accessible name: it comes from\n * `aria-labelledby`, then explicit `aria-label`, then the visible `label`.\n */\nexport function Progress({\n value = 0,\n max = 100,\n variant = \"primary\",\n indeterminate = false,\n showLabel = false,\n label,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n className,\n}: ProgressProps) {\n const pct = indeterminate ? 0 : Math.max(0, Math.min(100, (value / max) * 100));\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {(showLabel || label) && (\n <div className={styles.label}>\n {label && <span>{label}</span>}\n {showLabel && !indeterminate && <span>{Math.round(pct)}%</span>}\n </div>\n )}\n <div\n role=\"progressbar\"\n aria-label={ariaLabelledBy ? undefined : (ariaLabel ?? label)}\n aria-labelledby={ariaLabelledBy}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={indeterminate ? undefined : value}\n className={cn(styles.bar, indeterminate && styles.indeterminate)}\n >\n <div\n className={cn(styles.fill, variant !== \"primary\" && styles[variant])}\n style={{ width: indeterminate ? undefined : `${pct}%` }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;AAuCA,SAAgB,EAAS,EACrB,WAAQ,GACR,SAAM,KACN,aAAU,WACV,mBAAgB,IAChB,eAAY,IACZ,UACA,cAAc,GACd,mBAAmB,GACnB,gBACc;CACd,IAAM,IAAM,IAAgB,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,KAAM,IAAQ,IAAO,GAAG,CAAC;CAE9E,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;EAA5C,UAAA,EACM,KAAa,MACX,kBAAC,OAAD;GAAK,WAAW,EAAO;GAAvB,UAAA,CACK,KAAS,kBAAC,QAAD,EAAA,UAAO,EAAY,CAAA,GAC5B,KAAa,CAAC,KAAiB,kBAAC,QAAD,EAAA,UAAA,CAAO,KAAK,MAAM,CAAG,GAAE,GAAO,EAAA,CAAA,CAC7D;EAET,CAAA,GAAA,kBAAC,OAAD;GACI,MAAK;GACL,cAAY,IAAiB,KAAA,IAAa,KAAa;GACvD,mBAAiB;GACjB,iBAAe;GACf,iBAAe;GACf,iBAAe,IAAgB,KAAA,IAAY;GAC3C,WAAW,EAAG,EAAO,KAAK,KAAiB,EAAO,aAAa;GAE/D,UAAA,kBAAC,OAAD;IACI,WAAW,EAAG,EAAO,MAAM,MAAY,aAAa,EAAO,EAAQ;IACnE,OAAO,EAAE,OAAO,IAAgB,KAAA,IAAY,GAAG,EAAI,GAAG;GACzD,CAAA;EACA,CAAA,CACJ;;AAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QRCode.cjs","names":[],"sources":["../../../src/components/QRCode/QRCode.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { encodeQR, matrixToPath } from \"./qr-encode\";\nimport type { QRErrorCorrection } from \"./qr-encode\";\nimport styles from \"./QRCode.module.css\";\n\nexport interface QRCodeProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The payload. Encoded as UTF-8 when it is not plain digits or upper-case text. */\n value: string;\n /** Rendered side in px, quiet zone included. Default `160`. */\n size?: number;\n /** Error correction level. Default `\"M\"`. */\n level?: QRErrorCorrection;\n /** Quiet zone in modules. The standard asks for 4; below that, scanners start to miss. */\n margin?: number;\n /** Module colour. Defaults to black — see the note on dark mode below. */\n color?: string;\n /** Background colour. Defaults to white. */\n background?: string;\n /**\n * Accessible name. Defaults to naming the payload, because a screen reader\n * user cannot scan the symbol: the content has to reach them as text.\n */\n label?: string;\n}\n\n/**\n * A QR symbol, encoded in the browser and drawn as SVG.\n *\n * No dependency and no network round trip: an image service would leak the\n * payload — a payment link, a session token, an invite — to a third party, and\n * the encoder is a few kilobytes.\n *\n * SVG rather than canvas so the symbol stays sharp at any size and prints at\n * the printer's resolution instead of the screen's. Everything is one path\n * (horizontal runs merged), because a version-10 symbol is 3 481 modules and\n * that many elements costs real paint time.\n *\n * The colours are **black on white in both themes, on purpose** — they are the\n * one part of the SDK that ignores the theme tokens. Scanners expect\n * dark-on-light, and the ones that cope with an inverted symbol do it slowly and\n * unreliably; a QR that looks integrated with a dark page and scans on the third\n * try is worse than one that looks pasted on. Wiring the modules to\n * `--tempest-text` would flip them light in dark mode and leave a light symbol\n * on the white background, which scans as nothing at all. Override\n * `color`/`background` only with a scanner in hand.\n *\n * @throws {QRCapacityError} When the payload is too long for a version-40\n * symbol at the chosen level. That is a programming error rather than a state\n * to render, so it surfaces instead of silently drawing nothing — wrap it in\n * `ErrorBoundary` if the payload comes from user input.\n *\n * @example\n * <QRCode value=\"https://tempest.dev\" />\n * <QRCode value={pixPayload} level=\"H\" size={220} label=\"QR do Pix\" />\n */\nexport function QRCode({\n value,\n size = 160,\n level = \"M\",\n margin = 4,\n color = \"#000000\",\n background = \"#ffffff\",\n label,\n className,\n style,\n ...rest\n}: QRCodeProps) {\n const { path, side } = useMemo(() => {\n const matrix = encodeQR(value, { level });\n return {\n path: matrixToPath(matrix, margin),\n side: matrix.size + margin * 2,\n };\n }, [value, level, margin]);\n\n return (\n <div\n className={cn(styles.wrapper, className)}\n style={{ width: size, height: size, ...style }}\n {...rest}\n >\n <svg\n className={styles.svg}\n viewBox={`0 0 ${side} ${side}`}\n width={size}\n height={size}\n role=\"img\"\n aria-label={label ?? `QR code: ${value}`}\n shapeRendering=\"crispEdges\"\n >\n <rect width={side} height={side} fill={background} />\n <path d={path} fill={color} />\n </svg>\n </div>\n );\n}\n"],"mappings":"0JA2DA,SAAgB,EAAO,CACnB,QACA,OAAO,IACP,QAAQ,IACR,SAAS,EACT,QAAQ,UACR,aAAa,UACb,QACA,YACA,QACA,GAAG,GACS,CACZ,GAAM,CAAE,OAAM,SAAA,
|
|
1
|
+
{"version":3,"file":"QRCode.cjs","names":[],"sources":["../../../src/components/QRCode/QRCode.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { encodeQR, matrixToPath } from \"./qr-encode\";\nimport type { QRErrorCorrection } from \"./qr-encode\";\nimport styles from \"./QRCode.module.css\";\n\nexport interface QRCodeProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The payload. Encoded as UTF-8 when it is not plain digits or upper-case text. */\n value: string;\n /** Rendered side in px, quiet zone included. Default `160`. */\n size?: number;\n /** Error correction level. Default `\"M\"`. */\n level?: QRErrorCorrection;\n /** Quiet zone in modules. The standard asks for 4; below that, scanners start to miss. */\n margin?: number;\n /** Module colour. Defaults to black — see the note on dark mode below. */\n color?: string;\n /** Background colour. Defaults to white. */\n background?: string;\n /**\n * Accessible name. Defaults to naming the payload, because a screen reader\n * user cannot scan the symbol: the content has to reach them as text.\n */\n label?: string;\n}\n\n/**\n * A QR symbol, encoded in the browser and drawn as SVG.\n *\n * No dependency and no network round trip: an image service would leak the\n * payload — a payment link, a session token, an invite — to a third party, and\n * the encoder is a few kilobytes.\n *\n * SVG rather than canvas so the symbol stays sharp at any size and prints at\n * the printer's resolution instead of the screen's. Everything is one path\n * (horizontal runs merged), because a version-10 symbol is 3 481 modules and\n * that many elements costs real paint time.\n *\n * The colours are **black on white in both themes, on purpose** — they are the\n * one part of the SDK that ignores the theme tokens. Scanners expect\n * dark-on-light, and the ones that cope with an inverted symbol do it slowly and\n * unreliably; a QR that looks integrated with a dark page and scans on the third\n * try is worse than one that looks pasted on. Wiring the modules to\n * `--tempest-text` would flip them light in dark mode and leave a light symbol\n * on the white background, which scans as nothing at all. Override\n * `color`/`background` only with a scanner in hand.\n *\n * @throws {QRCapacityError} When the payload is too long for a version-40\n * symbol at the chosen level. That is a programming error rather than a state\n * to render, so it surfaces instead of silently drawing nothing — wrap it in\n * `ErrorBoundary` if the payload comes from user input.\n *\n * @example\n * <QRCode value=\"https://tempest.dev\" />\n * <QRCode value={pixPayload} level=\"H\" size={220} label=\"QR do Pix\" />\n */\nexport function QRCode({\n value,\n size = 160,\n level = \"M\",\n margin = 4,\n color = \"#000000\",\n background = \"#ffffff\",\n label,\n className,\n style,\n ...rest\n}: QRCodeProps) {\n const { path, side } = useMemo(() => {\n const matrix = encodeQR(value, { level });\n return {\n path: matrixToPath(matrix, margin),\n side: matrix.size + margin * 2,\n };\n }, [value, level, margin]);\n\n return (\n <div\n className={cn(styles.wrapper, className)}\n style={{ width: size, height: size, ...style }}\n {...rest}\n >\n <svg\n className={styles.svg}\n viewBox={`0 0 ${side} ${side}`}\n width={size}\n height={size}\n role=\"img\"\n aria-label={label ?? `QR code: ${value}`}\n shapeRendering=\"crispEdges\"\n >\n <rect width={side} height={side} fill={background} />\n <path d={path} fill={color} />\n </svg>\n </div>\n );\n}\n"],"mappings":"0JA2DA,SAAgB,EAAO,CACnB,QACA,OAAO,IACP,QAAQ,IACR,SAAS,EACT,QAAQ,UACR,aAAa,UACb,QACA,YACA,QACA,GAAG,GACS,CACZ,GAAM,CAAE,OAAM,SAAA,EAAS,EAAA,QAAA,KAAc,CACjC,IAAM,EAAS,EAAA,SAAS,EAAO,CAAE,OAAM,CAAC,EACxC,MAAO,CACH,KAAM,EAAA,aAAa,EAAQ,CAAM,EACjC,KAAM,EAAO,KAAO,EAAS,CACjC,CACJ,EAAG,CAAC,EAAO,EAAO,CAAM,CAAC,EAEzB,OACI,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EACvC,MAAO,CAAE,MAAO,EAAM,OAAQ,EAAM,GAAG,CAAM,EAC7C,GAAI,EAEJ,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,IAClB,QAAS,OAAO,EAAK,GAAG,IACxB,MAAO,EACP,OAAQ,EACR,KAAK,MACL,aAAY,GAAS,YAAY,IACjC,eAAe,aAPnB,SAAA,EASI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,MAAO,EAAM,OAAQ,EAAM,KAAM,CAAa,CAAA,GACpD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAG,EAAM,KAAM,CAAQ,CAAA,CAC5B,GACJ,CAAA,CAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QRCode.js","names":[],"sources":["../../../src/components/QRCode/QRCode.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { encodeQR, matrixToPath } from \"./qr-encode\";\nimport type { QRErrorCorrection } from \"./qr-encode\";\nimport styles from \"./QRCode.module.css\";\n\nexport interface QRCodeProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The payload. Encoded as UTF-8 when it is not plain digits or upper-case text. */\n value: string;\n /** Rendered side in px, quiet zone included. Default `160`. */\n size?: number;\n /** Error correction level. Default `\"M\"`. */\n level?: QRErrorCorrection;\n /** Quiet zone in modules. The standard asks for 4; below that, scanners start to miss. */\n margin?: number;\n /** Module colour. Defaults to black — see the note on dark mode below. */\n color?: string;\n /** Background colour. Defaults to white. */\n background?: string;\n /**\n * Accessible name. Defaults to naming the payload, because a screen reader\n * user cannot scan the symbol: the content has to reach them as text.\n */\n label?: string;\n}\n\n/**\n * A QR symbol, encoded in the browser and drawn as SVG.\n *\n * No dependency and no network round trip: an image service would leak the\n * payload — a payment link, a session token, an invite — to a third party, and\n * the encoder is a few kilobytes.\n *\n * SVG rather than canvas so the symbol stays sharp at any size and prints at\n * the printer's resolution instead of the screen's. Everything is one path\n * (horizontal runs merged), because a version-10 symbol is 3 481 modules and\n * that many elements costs real paint time.\n *\n * The colours are **black on white in both themes, on purpose** — they are the\n * one part of the SDK that ignores the theme tokens. Scanners expect\n * dark-on-light, and the ones that cope with an inverted symbol do it slowly and\n * unreliably; a QR that looks integrated with a dark page and scans on the third\n * try is worse than one that looks pasted on. Wiring the modules to\n * `--tempest-text` would flip them light in dark mode and leave a light symbol\n * on the white background, which scans as nothing at all. Override\n * `color`/`background` only with a scanner in hand.\n *\n * @throws {QRCapacityError} When the payload is too long for a version-40\n * symbol at the chosen level. That is a programming error rather than a state\n * to render, so it surfaces instead of silently drawing nothing — wrap it in\n * `ErrorBoundary` if the payload comes from user input.\n *\n * @example\n * <QRCode value=\"https://tempest.dev\" />\n * <QRCode value={pixPayload} level=\"H\" size={220} label=\"QR do Pix\" />\n */\nexport function QRCode({\n value,\n size = 160,\n level = \"M\",\n margin = 4,\n color = \"#000000\",\n background = \"#ffffff\",\n label,\n className,\n style,\n ...rest\n}: QRCodeProps) {\n const { path, side } = useMemo(() => {\n const matrix = encodeQR(value, { level });\n return {\n path: matrixToPath(matrix, margin),\n side: matrix.size + margin * 2,\n };\n }, [value, level, margin]);\n\n return (\n <div\n className={cn(styles.wrapper, className)}\n style={{ width: size, height: size, ...style }}\n {...rest}\n >\n <svg\n className={styles.svg}\n viewBox={`0 0 ${side} ${side}`}\n width={size}\n height={size}\n role=\"img\"\n aria-label={label ?? `QR code: ${value}`}\n shapeRendering=\"crispEdges\"\n >\n <rect width={side} height={side} fill={background} />\n <path d={path} fill={color} />\n </svg>\n </div>\n );\n}\n"],"mappings":";;;;;;AA2DA,SAAgB,EAAO,EACnB,UACA,UAAO,KACP,WAAQ,KACR,YAAS,GACT,WAAQ,WACR,gBAAa,WACb,UACA,cACA,UACA,GAAG,KACS;CACZ,IAAM,EAAE,SAAM,YAAS,QAAc;EACjC,IAAM,IAAS,EAAS,GAAO,EAAE,SAAM,CAAC;EACxC,OAAO;GACH,MAAM,EAAa,GAAQ,CAAM;GACjC,MAAM,EAAO,OAAO,IAAS;EACjC;CACJ,GAAG;EAAC;EAAO;EAAO;CAAM,CAAC;CAEzB,OACI,kBAAC,OAAD;EACI,WAAW,EAAG,EAAO,SAAS,CAAS;EACvC,OAAO;GAAE,OAAO;GAAM,QAAQ;GAAM,GAAG;EAAM;EAC7C,GAAI;
|
|
1
|
+
{"version":3,"file":"QRCode.js","names":[],"sources":["../../../src/components/QRCode/QRCode.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { encodeQR, matrixToPath } from \"./qr-encode\";\nimport type { QRErrorCorrection } from \"./qr-encode\";\nimport styles from \"./QRCode.module.css\";\n\nexport interface QRCodeProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The payload. Encoded as UTF-8 when it is not plain digits or upper-case text. */\n value: string;\n /** Rendered side in px, quiet zone included. Default `160`. */\n size?: number;\n /** Error correction level. Default `\"M\"`. */\n level?: QRErrorCorrection;\n /** Quiet zone in modules. The standard asks for 4; below that, scanners start to miss. */\n margin?: number;\n /** Module colour. Defaults to black — see the note on dark mode below. */\n color?: string;\n /** Background colour. Defaults to white. */\n background?: string;\n /**\n * Accessible name. Defaults to naming the payload, because a screen reader\n * user cannot scan the symbol: the content has to reach them as text.\n */\n label?: string;\n}\n\n/**\n * A QR symbol, encoded in the browser and drawn as SVG.\n *\n * No dependency and no network round trip: an image service would leak the\n * payload — a payment link, a session token, an invite — to a third party, and\n * the encoder is a few kilobytes.\n *\n * SVG rather than canvas so the symbol stays sharp at any size and prints at\n * the printer's resolution instead of the screen's. Everything is one path\n * (horizontal runs merged), because a version-10 symbol is 3 481 modules and\n * that many elements costs real paint time.\n *\n * The colours are **black on white in both themes, on purpose** — they are the\n * one part of the SDK that ignores the theme tokens. Scanners expect\n * dark-on-light, and the ones that cope with an inverted symbol do it slowly and\n * unreliably; a QR that looks integrated with a dark page and scans on the third\n * try is worse than one that looks pasted on. Wiring the modules to\n * `--tempest-text` would flip them light in dark mode and leave a light symbol\n * on the white background, which scans as nothing at all. Override\n * `color`/`background` only with a scanner in hand.\n *\n * @throws {QRCapacityError} When the payload is too long for a version-40\n * symbol at the chosen level. That is a programming error rather than a state\n * to render, so it surfaces instead of silently drawing nothing — wrap it in\n * `ErrorBoundary` if the payload comes from user input.\n *\n * @example\n * <QRCode value=\"https://tempest.dev\" />\n * <QRCode value={pixPayload} level=\"H\" size={220} label=\"QR do Pix\" />\n */\nexport function QRCode({\n value,\n size = 160,\n level = \"M\",\n margin = 4,\n color = \"#000000\",\n background = \"#ffffff\",\n label,\n className,\n style,\n ...rest\n}: QRCodeProps) {\n const { path, side } = useMemo(() => {\n const matrix = encodeQR(value, { level });\n return {\n path: matrixToPath(matrix, margin),\n side: matrix.size + margin * 2,\n };\n }, [value, level, margin]);\n\n return (\n <div\n className={cn(styles.wrapper, className)}\n style={{ width: size, height: size, ...style }}\n {...rest}\n >\n <svg\n className={styles.svg}\n viewBox={`0 0 ${side} ${side}`}\n width={size}\n height={size}\n role=\"img\"\n aria-label={label ?? `QR code: ${value}`}\n shapeRendering=\"crispEdges\"\n >\n <rect width={side} height={side} fill={background} />\n <path d={path} fill={color} />\n </svg>\n </div>\n );\n}\n"],"mappings":";;;;;;AA2DA,SAAgB,EAAO,EACnB,UACA,UAAO,KACP,WAAQ,KACR,YAAS,GACT,WAAQ,WACR,gBAAa,WACb,UACA,cACA,UACA,GAAG,KACS;CACZ,IAAM,EAAE,SAAM,YAAS,QAAc;EACjC,IAAM,IAAS,EAAS,GAAO,EAAE,SAAM,CAAC;EACxC,OAAO;GACH,MAAM,EAAa,GAAQ,CAAM;GACjC,MAAM,EAAO,OAAO,IAAS;EACjC;CACJ,GAAG;EAAC;EAAO;EAAO;CAAM,CAAC;CAEzB,OACI,kBAAC,OAAD;EACI,WAAW,EAAG,EAAO,SAAS,CAAS;EACvC,OAAO;GAAE,OAAO;GAAM,QAAQ;GAAM,GAAG;EAAM;EAC7C,GAAI;EAEJ,UAAA,kBAAC,OAAD;GACI,WAAW,EAAO;GAClB,SAAS,OAAO,EAAK,GAAG;GACxB,OAAO;GACP,QAAQ;GACR,MAAK;GACL,cAAY,KAAS,YAAY;GACjC,gBAAe;GAPnB,UAAA,CASI,kBAAC,QAAD;IAAM,OAAO;IAAM,QAAQ;IAAM,MAAM;GAAa,CAAA,GACpD,kBAAC,QAAD;IAAM,GAAG;IAAM,MAAM;GAAQ,CAAA,CAC5B;;CACJ,CAAA;AAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Radio.cjs","names":[],"sources":["../../../src/components/Radio/Radio.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — RadioGroup carries the group semantics (name, value,\n * defaultValue, onChange, disabled) and its layout (horizontal, className,\n * children). The individual Radio is a separate component already — this is the\n * group, and a group needs the group's props.\n */\nimport { createContext, forwardRef, useContext, useId, useState } from \"react\";\nimport type { ChangeEvent, InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Radio.module.css\";\n\ninterface RadioGroupContextValue {\n name: string;\n value?: string;\n onChange?: (value: string) => void;\n disabled?: boolean;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue | null>(null);\n\nexport interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n label?: ReactNode;\n description?: ReactNode;\n value: string;\n wrapperClassName?: string;\n}\n\n/**\n * Single radio button. Inside a {@link RadioGroup}, name/checked/onChange are\n * managed by the group; outside, behaves as a regular radio input.\n */\nexport const Radio = forwardRef<HTMLInputElement, RadioProps>(function Radio(\n {\n label,\n description,\n value,\n disabled,\n name,\n checked,\n onChange,\n wrapperClassName,\n className,\n ...props\n },\n ref,\n) {\n const group = useContext(RadioGroupContext);\n const resolvedName = group?.name ?? name;\n const resolvedDisabled = group?.disabled ?? disabled;\n const isChecked = group ? group.value === value : checked;\n\n function handleChange(event: ChangeEvent<HTMLInputElement>): void {\n if (group) group.onChange?.(value);\n onChange?.(event);\n }\n\n return (\n <label\n className={cn(styles.wrapper, resolvedDisabled && styles.disabled, wrapperClassName)}\n >\n <input\n ref={ref}\n type=\"radio\"\n name={resolvedName}\n value={value}\n checked={isChecked}\n disabled={resolvedDisabled}\n onChange={handleChange}\n className={cn(styles.input, className)}\n {...props}\n />\n <span className={styles.dot} aria-hidden />\n {(label || description) && (\n <span className={styles.labelWrap}>\n {label && <span className={styles.label}>{label}</span>}\n {description && <span className={styles.description}>{description}</span>}\n </span>\n )}\n </label>\n );\n});\n\nexport interface RadioGroupProps {\n /** Selected value (controlled). */\n value?: string;\n /** Default selected value (uncontrolled). */\n defaultValue?: string;\n /** Called when the selection changes. */\n onChange?: (value: string) => void;\n /** `name` attribute applied to every Radio inside. Auto-generated if omitted. */\n name?: string;\n /** Disable every Radio inside. */\n disabled?: boolean;\n /** Lay out radios horizontally. Default: false (column). */\n horizontal?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Wraps multiple {@link Radio} children and coordinates selection via context.\n * Pass `value` for controlled mode or `defaultValue` for uncontrolled.\n */\nexport function RadioGroup({\n value,\n defaultValue,\n onChange,\n name,\n disabled,\n horizontal = false,\n className,\n children,\n}: RadioGroupProps) {\n const generatedName = useId();\n const resolvedName = name ?? generatedName;\n\n const [internal, setInternal] = useState<string | undefined>(defaultValue);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n function handleChange(next: string): void {\n if (!isControlled) setInternal(next);\n onChange?.(next);\n }\n\n return (\n <RadioGroupContext.Provider\n value={{ name: resolvedName, value: current, onChange: handleChange, disabled }}\n >\n <div\n role=\"radiogroup\"\n className={cn(styles.group, horizontal && styles.horizontal, className)}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n );\n}\n"],"mappings":"4HAkBA,IAAM,GAAA,
|
|
1
|
+
{"version":3,"file":"Radio.cjs","names":[],"sources":["../../../src/components/Radio/Radio.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — RadioGroup carries the group semantics (name, value,\n * defaultValue, onChange, disabled) and its layout (horizontal, className,\n * children). The individual Radio is a separate component already — this is the\n * group, and a group needs the group's props.\n */\nimport { createContext, forwardRef, useContext, useId, useState } from \"react\";\nimport type { ChangeEvent, InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Radio.module.css\";\n\ninterface RadioGroupContextValue {\n name: string;\n value?: string;\n onChange?: (value: string) => void;\n disabled?: boolean;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue | null>(null);\n\nexport interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n label?: ReactNode;\n description?: ReactNode;\n value: string;\n wrapperClassName?: string;\n}\n\n/**\n * Single radio button. Inside a {@link RadioGroup}, name/checked/onChange are\n * managed by the group; outside, behaves as a regular radio input.\n */\nexport const Radio = forwardRef<HTMLInputElement, RadioProps>(function Radio(\n {\n label,\n description,\n value,\n disabled,\n name,\n checked,\n onChange,\n wrapperClassName,\n className,\n ...props\n },\n ref,\n) {\n const group = useContext(RadioGroupContext);\n const resolvedName = group?.name ?? name;\n const resolvedDisabled = group?.disabled ?? disabled;\n const isChecked = group ? group.value === value : checked;\n\n function handleChange(event: ChangeEvent<HTMLInputElement>): void {\n if (group) group.onChange?.(value);\n onChange?.(event);\n }\n\n return (\n <label\n className={cn(styles.wrapper, resolvedDisabled && styles.disabled, wrapperClassName)}\n >\n <input\n ref={ref}\n type=\"radio\"\n name={resolvedName}\n value={value}\n checked={isChecked}\n disabled={resolvedDisabled}\n onChange={handleChange}\n className={cn(styles.input, className)}\n {...props}\n />\n <span className={styles.dot} aria-hidden />\n {(label || description) && (\n <span className={styles.labelWrap}>\n {label && <span className={styles.label}>{label}</span>}\n {description && <span className={styles.description}>{description}</span>}\n </span>\n )}\n </label>\n );\n});\n\nexport interface RadioGroupProps {\n /** Selected value (controlled). */\n value?: string;\n /** Default selected value (uncontrolled). */\n defaultValue?: string;\n /** Called when the selection changes. */\n onChange?: (value: string) => void;\n /** `name` attribute applied to every Radio inside. Auto-generated if omitted. */\n name?: string;\n /** Disable every Radio inside. */\n disabled?: boolean;\n /** Lay out radios horizontally. Default: false (column). */\n horizontal?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Wraps multiple {@link Radio} children and coordinates selection via context.\n * Pass `value` for controlled mode or `defaultValue` for uncontrolled.\n */\nexport function RadioGroup({\n value,\n defaultValue,\n onChange,\n name,\n disabled,\n horizontal = false,\n className,\n children,\n}: RadioGroupProps) {\n const generatedName = useId();\n const resolvedName = name ?? generatedName;\n\n const [internal, setInternal] = useState<string | undefined>(defaultValue);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n function handleChange(next: string): void {\n if (!isControlled) setInternal(next);\n onChange?.(next);\n }\n\n return (\n <RadioGroupContext.Provider\n value={{ name: resolvedName, value: current, onChange: handleChange, disabled }}\n >\n <div\n role=\"radiogroup\"\n className={cn(styles.group, horizontal && styles.horizontal, className)}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n );\n}\n"],"mappings":"4HAkBA,IAAM,GAAA,EAAoB,EAAA,cAAA,CAA6C,IAAI,EAa9D,GAAA,EAAQ,EAAA,WAAA,CAAyC,SAC1D,CACI,QACA,cACA,QACA,WACA,OACA,UACA,WACA,mBACA,YACA,GAAG,GAEP,EACF,CACE,IAAM,GAAA,EAAQ,EAAA,WAAA,CAAW,CAAiB,EACpC,EAAe,GAAO,MAAQ,EAC9B,EAAmB,GAAO,UAAY,EACtC,EAAY,EAAQ,EAAM,QAAU,EAAQ,EAElD,SAAS,EAAa,EAA4C,CAC1D,GAAO,EAAM,WAAW,CAAK,EACjC,IAAW,CAAK,CACpB,CAEA,OACI,EAAA,EAAA,KAAA,CAAC,QAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,GAAoB,EAAA,QAAO,SAAU,CAAgB,EADvF,SAAA,EAGI,EAAA,EAAA,IAAA,CAAC,QAAD,CACS,MACL,KAAK,QACL,KAAM,EACC,QACP,QAAS,EACT,SAAU,EACV,SAAU,EACV,UAAW,EAAA,GAAG,EAAA,QAAO,MAAO,CAAS,EACrC,GAAI,CACP,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,IAAK,cAAA,EAAa,CAAA,GACxC,GAAS,KACP,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,UAAxB,SAAA,CACK,IAAS,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAY,CAAA,EACrD,IAAe,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,YAAc,SAAA,CAAkB,CAAA,CACtE,GAEP,GAEf,CAAC,EAuBD,SAAgB,EAAW,CACvB,QACA,eACA,WACA,OACA,WACA,aAAa,GACb,YACA,YACgB,CAChB,IAAM,GAAA,EAAgB,EAAA,MAAA,CAAM,EACtB,EAAe,GAAQ,EAEvB,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAA6B,CAAY,EACnE,EAAe,IAAU,IAAA,GACzB,EAAU,EAAe,EAAQ,EAEvC,SAAS,EAAa,EAAoB,CACjC,GAAc,EAAY,CAAI,EACnC,IAAW,CAAI,CACnB,CAEA,OACI,EAAA,EAAA,IAAA,CAAC,EAAkB,SAAnB,CACI,MAAO,CAAE,KAAM,EAAc,MAAO,EAAS,SAAU,EAAc,UAAS,EAE9E,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,KAAK,aACL,UAAW,EAAA,GAAG,EAAA,QAAO,MAAO,GAAc,EAAA,QAAO,WAAY,CAAS,EAErE,UACA,CAAA,CACmB,CAAA,CAEpC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Radio.js","names":[],"sources":["../../../src/components/Radio/Radio.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — RadioGroup carries the group semantics (name, value,\n * defaultValue, onChange, disabled) and its layout (horizontal, className,\n * children). The individual Radio is a separate component already — this is the\n * group, and a group needs the group's props.\n */\nimport { createContext, forwardRef, useContext, useId, useState } from \"react\";\nimport type { ChangeEvent, InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Radio.module.css\";\n\ninterface RadioGroupContextValue {\n name: string;\n value?: string;\n onChange?: (value: string) => void;\n disabled?: boolean;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue | null>(null);\n\nexport interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n label?: ReactNode;\n description?: ReactNode;\n value: string;\n wrapperClassName?: string;\n}\n\n/**\n * Single radio button. Inside a {@link RadioGroup}, name/checked/onChange are\n * managed by the group; outside, behaves as a regular radio input.\n */\nexport const Radio = forwardRef<HTMLInputElement, RadioProps>(function Radio(\n {\n label,\n description,\n value,\n disabled,\n name,\n checked,\n onChange,\n wrapperClassName,\n className,\n ...props\n },\n ref,\n) {\n const group = useContext(RadioGroupContext);\n const resolvedName = group?.name ?? name;\n const resolvedDisabled = group?.disabled ?? disabled;\n const isChecked = group ? group.value === value : checked;\n\n function handleChange(event: ChangeEvent<HTMLInputElement>): void {\n if (group) group.onChange?.(value);\n onChange?.(event);\n }\n\n return (\n <label\n className={cn(styles.wrapper, resolvedDisabled && styles.disabled, wrapperClassName)}\n >\n <input\n ref={ref}\n type=\"radio\"\n name={resolvedName}\n value={value}\n checked={isChecked}\n disabled={resolvedDisabled}\n onChange={handleChange}\n className={cn(styles.input, className)}\n {...props}\n />\n <span className={styles.dot} aria-hidden />\n {(label || description) && (\n <span className={styles.labelWrap}>\n {label && <span className={styles.label}>{label}</span>}\n {description && <span className={styles.description}>{description}</span>}\n </span>\n )}\n </label>\n );\n});\n\nexport interface RadioGroupProps {\n /** Selected value (controlled). */\n value?: string;\n /** Default selected value (uncontrolled). */\n defaultValue?: string;\n /** Called when the selection changes. */\n onChange?: (value: string) => void;\n /** `name` attribute applied to every Radio inside. Auto-generated if omitted. */\n name?: string;\n /** Disable every Radio inside. */\n disabled?: boolean;\n /** Lay out radios horizontally. Default: false (column). */\n horizontal?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Wraps multiple {@link Radio} children and coordinates selection via context.\n * Pass `value` for controlled mode or `defaultValue` for uncontrolled.\n */\nexport function RadioGroup({\n value,\n defaultValue,\n onChange,\n name,\n disabled,\n horizontal = false,\n className,\n children,\n}: RadioGroupProps) {\n const generatedName = useId();\n const resolvedName = name ?? generatedName;\n\n const [internal, setInternal] = useState<string | undefined>(defaultValue);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n function handleChange(next: string): void {\n if (!isControlled) setInternal(next);\n onChange?.(next);\n }\n\n return (\n <RadioGroupContext.Provider\n value={{ name: resolvedName, value: current, onChange: handleChange, disabled }}\n >\n <div\n role=\"radiogroup\"\n className={cn(styles.group, horizontal && styles.horizontal, className)}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n );\n}\n"],"mappings":";;;;;AAkBA,IAAM,IAAoB,EAA6C,IAAI,GAa9D,IAAQ,EAAyC,SAC1D,EACI,UACA,gBACA,UACA,aACA,SACA,YACA,aACA,qBACA,cACA,GAAG,KAEP,GACF;CACE,IAAM,IAAQ,EAAW,CAAiB,GACpC,IAAe,GAAO,QAAQ,GAC9B,IAAmB,GAAO,YAAY,GACtC,IAAY,IAAQ,EAAM,UAAU,IAAQ;CAElD,SAAS,EAAa,GAA4C;EAE9D,AADI,KAAO,EAAM,WAAW,CAAK,GACjC,IAAW,CAAK;CACpB;CAEA,OACI,kBAAC,SAAD;EACI,WAAW,EAAG,EAAO,SAAS,KAAoB,EAAO,UAAU,CAAgB;
|
|
1
|
+
{"version":3,"file":"Radio.js","names":[],"sources":["../../../src/components/Radio/Radio.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — RadioGroup carries the group semantics (name, value,\n * defaultValue, onChange, disabled) and its layout (horizontal, className,\n * children). The individual Radio is a separate component already — this is the\n * group, and a group needs the group's props.\n */\nimport { createContext, forwardRef, useContext, useId, useState } from \"react\";\nimport type { ChangeEvent, InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Radio.module.css\";\n\ninterface RadioGroupContextValue {\n name: string;\n value?: string;\n onChange?: (value: string) => void;\n disabled?: boolean;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue | null>(null);\n\nexport interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n label?: ReactNode;\n description?: ReactNode;\n value: string;\n wrapperClassName?: string;\n}\n\n/**\n * Single radio button. Inside a {@link RadioGroup}, name/checked/onChange are\n * managed by the group; outside, behaves as a regular radio input.\n */\nexport const Radio = forwardRef<HTMLInputElement, RadioProps>(function Radio(\n {\n label,\n description,\n value,\n disabled,\n name,\n checked,\n onChange,\n wrapperClassName,\n className,\n ...props\n },\n ref,\n) {\n const group = useContext(RadioGroupContext);\n const resolvedName = group?.name ?? name;\n const resolvedDisabled = group?.disabled ?? disabled;\n const isChecked = group ? group.value === value : checked;\n\n function handleChange(event: ChangeEvent<HTMLInputElement>): void {\n if (group) group.onChange?.(value);\n onChange?.(event);\n }\n\n return (\n <label\n className={cn(styles.wrapper, resolvedDisabled && styles.disabled, wrapperClassName)}\n >\n <input\n ref={ref}\n type=\"radio\"\n name={resolvedName}\n value={value}\n checked={isChecked}\n disabled={resolvedDisabled}\n onChange={handleChange}\n className={cn(styles.input, className)}\n {...props}\n />\n <span className={styles.dot} aria-hidden />\n {(label || description) && (\n <span className={styles.labelWrap}>\n {label && <span className={styles.label}>{label}</span>}\n {description && <span className={styles.description}>{description}</span>}\n </span>\n )}\n </label>\n );\n});\n\nexport interface RadioGroupProps {\n /** Selected value (controlled). */\n value?: string;\n /** Default selected value (uncontrolled). */\n defaultValue?: string;\n /** Called when the selection changes. */\n onChange?: (value: string) => void;\n /** `name` attribute applied to every Radio inside. Auto-generated if omitted. */\n name?: string;\n /** Disable every Radio inside. */\n disabled?: boolean;\n /** Lay out radios horizontally. Default: false (column). */\n horizontal?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Wraps multiple {@link Radio} children and coordinates selection via context.\n * Pass `value` for controlled mode or `defaultValue` for uncontrolled.\n */\nexport function RadioGroup({\n value,\n defaultValue,\n onChange,\n name,\n disabled,\n horizontal = false,\n className,\n children,\n}: RadioGroupProps) {\n const generatedName = useId();\n const resolvedName = name ?? generatedName;\n\n const [internal, setInternal] = useState<string | undefined>(defaultValue);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n function handleChange(next: string): void {\n if (!isControlled) setInternal(next);\n onChange?.(next);\n }\n\n return (\n <RadioGroupContext.Provider\n value={{ name: resolvedName, value: current, onChange: handleChange, disabled }}\n >\n <div\n role=\"radiogroup\"\n className={cn(styles.group, horizontal && styles.horizontal, className)}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n );\n}\n"],"mappings":";;;;;AAkBA,IAAM,IAAoB,EAA6C,IAAI,GAa9D,IAAQ,EAAyC,SAC1D,EACI,UACA,gBACA,UACA,aACA,SACA,YACA,aACA,qBACA,cACA,GAAG,KAEP,GACF;CACE,IAAM,IAAQ,EAAW,CAAiB,GACpC,IAAe,GAAO,QAAQ,GAC9B,IAAmB,GAAO,YAAY,GACtC,IAAY,IAAQ,EAAM,UAAU,IAAQ;CAElD,SAAS,EAAa,GAA4C;EAE9D,AADI,KAAO,EAAM,WAAW,CAAK,GACjC,IAAW,CAAK;CACpB;CAEA,OACI,kBAAC,SAAD;EACI,WAAW,EAAG,EAAO,SAAS,KAAoB,EAAO,UAAU,CAAgB;EADvF,UAAA;GAGI,kBAAC,SAAD;IACS;IACL,MAAK;IACL,MAAM;IACC;IACP,SAAS;IACT,UAAU;IACV,UAAU;IACV,WAAW,EAAG,EAAO,OAAO,CAAS;IACrC,GAAI;GACP,CAAA;GACD,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAK,eAAA;GAAa,CAAA;IACxC,KAAS,MACP,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAxB,UAAA,CACK,KAAS,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAQ,UAAA;IAAY,CAAA,GACrD,KAAe,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAc,UAAA;IAAkB,CAAA,CACtE;;EAEP;;AAEf,CAAC;AAuBD,SAAgB,EAAW,EACvB,UACA,iBACA,aACA,SACA,aACA,gBAAa,IACb,cACA,eACgB;CAChB,IAAM,IAAgB,EAAM,GACtB,IAAe,KAAQ,GAEvB,CAAC,GAAU,KAAe,EAA6B,CAAY,GACnE,IAAe,MAAU,KAAA,GACzB,IAAU,IAAe,IAAQ;CAEvC,SAAS,EAAa,GAAoB;EAEtC,AADK,KAAc,EAAY,CAAI,GACnC,IAAW,CAAI;CACnB;CAEA,OACI,kBAAC,EAAkB,UAAnB;EACI,OAAO;GAAE,MAAM;GAAc,OAAO;GAAS,UAAU;GAAc;EAAS;EAE9E,UAAA,kBAAC,OAAD;GACI,MAAK;GACL,WAAW,EAAG,EAAO,OAAO,KAAc,EAAO,YAAY,CAAS;GAErE;EACA,CAAA;CACmB,CAAA;AAEpC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RangeSlider.cjs","names":[],"sources":["../../../src/components/RangeSlider/RangeSlider.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — min, max and step define the scale, value/onChange\n * the two thumbs, formatValue the readout, and label/helperText/disabled/className\n * the field around it. Same surface as Slider, one thumb more.\n */\nimport { useCallback, useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./RangeSlider.module.css\";\n\nexport type RangeValue = [number, number];\n\nexport interface RangeSliderProps {\n value: RangeValue;\n onChange: (value: RangeValue) => void;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n helperText?: string;\n disabled?: boolean;\n /** Formatter for the value badge next to the label. Defaults to `min – max`. */\n formatValue?: (value: RangeValue) => string;\n className?: string;\n}\n\n/**\n * Dual-thumb range slider. Built on two native `<input type=\"range\">` so it\n * stays accessible and works with keyboards/screen readers without\n * heavyweight positioning libs. The active fill is positioned via percentages.\n */\nexport function RangeSlider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n label,\n helperText,\n disabled = false,\n formatValue,\n className,\n}: RangeSliderProps) {\n const [low, high] = value;\n const range = max - min;\n\n const fillLeft = useMemo(() => ((low - min) / range) * 100, [low, min, range]);\n const fillRight = useMemo(() => ((high - min) / range) * 100, [high, min, range]);\n\n const valueText = formatValue?.(value) ?? `${low} – ${high}`;\n\n const handleLow = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n const next = Math.min(Number(event.target.value), high);\n onChange([next, high]);\n },\n [high, onChange],\n );\n\n const handleHigh = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n const next = Math.max(Number(event.target.value), low);\n onChange([low, next]);\n },\n [low, onChange],\n );\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {label && (\n <div className={styles.label}>\n <span>{label}</span>\n <span className={styles.value}>{valueText}</span>\n </div>\n )}\n <div className={styles.field}>\n <div className={styles.track} />\n <div\n className={styles.fill}\n style={{ left: `${fillLeft}%`, right: `${100 - fillRight}%` }}\n />\n <input\n type=\"range\"\n className={styles.input}\n min={min}\n max={max}\n step={step}\n value={low}\n onChange={handleLow}\n disabled={disabled}\n aria-label={label ? `${label} (mínimo)` : \"Mínimo\"}\n />\n <input\n type=\"range\"\n className={styles.input}\n min={min}\n max={max}\n step={step}\n value={high}\n onChange={handleHigh}\n disabled={disabled}\n aria-label={label ? `${label} (máximo)` : \"Máximo\"}\n />\n </div>\n {helperText && <span className={styles.helper}>{helperText}</span>}\n </div>\n );\n}\n"],"mappings":"kIA8BA,SAAgB,EAAY,CACxB,QACA,WACA,MAAM,EACN,MAAM,IACN,OAAO,EACP,QACA,aACA,WAAW,GACX,cACA,aACiB,CACjB,GAAM,CAAC,EAAK,GAAQ,EACd,EAAQ,EAAM,EAEd,GAAA,
|
|
1
|
+
{"version":3,"file":"RangeSlider.cjs","names":[],"sources":["../../../src/components/RangeSlider/RangeSlider.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — min, max and step define the scale, value/onChange\n * the two thumbs, formatValue the readout, and label/helperText/disabled/className\n * the field around it. Same surface as Slider, one thumb more.\n */\nimport { useCallback, useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./RangeSlider.module.css\";\n\nexport type RangeValue = [number, number];\n\nexport interface RangeSliderProps {\n value: RangeValue;\n onChange: (value: RangeValue) => void;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n helperText?: string;\n disabled?: boolean;\n /** Formatter for the value badge next to the label. Defaults to `min – max`. */\n formatValue?: (value: RangeValue) => string;\n className?: string;\n}\n\n/**\n * Dual-thumb range slider. Built on two native `<input type=\"range\">` so it\n * stays accessible and works with keyboards/screen readers without\n * heavyweight positioning libs. The active fill is positioned via percentages.\n */\nexport function RangeSlider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n label,\n helperText,\n disabled = false,\n formatValue,\n className,\n}: RangeSliderProps) {\n const [low, high] = value;\n const range = max - min;\n\n const fillLeft = useMemo(() => ((low - min) / range) * 100, [low, min, range]);\n const fillRight = useMemo(() => ((high - min) / range) * 100, [high, min, range]);\n\n const valueText = formatValue?.(value) ?? `${low} – ${high}`;\n\n const handleLow = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n const next = Math.min(Number(event.target.value), high);\n onChange([next, high]);\n },\n [high, onChange],\n );\n\n const handleHigh = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n const next = Math.max(Number(event.target.value), low);\n onChange([low, next]);\n },\n [low, onChange],\n );\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {label && (\n <div className={styles.label}>\n <span>{label}</span>\n <span className={styles.value}>{valueText}</span>\n </div>\n )}\n <div className={styles.field}>\n <div className={styles.track} />\n <div\n className={styles.fill}\n style={{ left: `${fillLeft}%`, right: `${100 - fillRight}%` }}\n />\n <input\n type=\"range\"\n className={styles.input}\n min={min}\n max={max}\n step={step}\n value={low}\n onChange={handleLow}\n disabled={disabled}\n aria-label={label ? `${label} (mínimo)` : \"Mínimo\"}\n />\n <input\n type=\"range\"\n className={styles.input}\n min={min}\n max={max}\n step={step}\n value={high}\n onChange={handleHigh}\n disabled={disabled}\n aria-label={label ? `${label} (máximo)` : \"Máximo\"}\n />\n </div>\n {helperText && <span className={styles.helper}>{helperText}</span>}\n </div>\n );\n}\n"],"mappings":"kIA8BA,SAAgB,EAAY,CACxB,QACA,WACA,MAAM,EACN,MAAM,IACN,OAAO,EACP,QACA,aACA,WAAW,GACX,cACA,aACiB,CACjB,GAAM,CAAC,EAAK,GAAQ,EACd,EAAQ,EAAM,EAEd,GAAA,EAAW,EAAA,QAAA,MAAgB,EAAM,GAAO,EAAS,IAAK,CAAC,EAAK,EAAK,CAAK,CAAC,EACvE,GAAA,EAAY,EAAA,QAAA,MAAgB,EAAO,GAAO,EAAS,IAAK,CAAC,EAAM,EAAK,CAAK,CAAC,EAE1E,EAAY,IAAc,CAAK,GAAK,GAAG,EAAI,KAAK,IAEhD,GAAA,EAAY,EAAA,YAAA,CACb,GAAqD,CAElD,EAAS,CADI,KAAK,IAAI,OAAO,EAAM,OAAO,KAAK,EAAG,CACxC,EAAM,CAAI,CAAC,CACzB,EACA,CAAC,EAAM,CAAQ,CACnB,EAEM,GAAA,EAAa,EAAA,YAAA,CACd,GAAqD,CAClD,IAAM,EAAO,KAAK,IAAI,OAAO,EAAM,OAAO,KAAK,EAAG,CAAG,EACrD,EAAS,CAAC,EAAK,CAAI,CAAC,CACxB,EACA,CAAC,EAAK,CAAQ,CAClB,EAEA,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAA5C,SAAA,CACK,IACG,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,CAAY,CAAA,GACnB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAgB,CAAA,CAC/C,KAET,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAQ,CAAA,GAC/B,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,KAClB,MAAO,CAAE,KAAM,GAAG,EAAS,GAAI,MAAO,GAAG,IAAM,EAAU,EAAG,CAC/D,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,QAAD,CACI,KAAK,QACL,UAAW,EAAA,QAAO,MACb,MACA,MACC,OACN,MAAO,EACP,SAAU,EACA,WACV,aAAY,EAAQ,GAAG,EAAM,WAAa,QAC7C,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,QAAD,CACI,KAAK,QACL,UAAW,EAAA,QAAO,MACb,MACA,MACC,OACN,MAAO,EACP,SAAU,EACA,WACV,aAAY,EAAQ,GAAG,EAAM,WAAa,QAC7C,CAAA,CACA,IACJ,IAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,OAAS,SAAA,CAAiB,CAAA,CAChE,GAEb"}
|