@plexui/ui 0.19.0 → 0.20.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/README.md +1 -3
- package/dist/es/components/Accordion/Accordion.js +2 -2
- package/dist/es/components/Accordion/Accordion.js.map +1 -1
- package/dist/es/components/Accordion/index.js +1 -1
- package/dist/es/components/Alert/Alert.js +6 -6
- package/dist/es/components/Alert/Alert.js.map +1 -1
- package/dist/es/components/Alert/index.js +1 -1
- package/dist/es/components/Avatar/Avatar.js +12 -5
- package/dist/es/components/Avatar/Avatar.js.map +1 -1
- package/dist/es/components/Avatar/AvatarGroup.js +2 -2
- package/dist/es/components/Avatar/AvatarGroup.js.map +1 -1
- package/dist/es/components/Avatar/index.js +2 -2
- package/dist/es/components/Badge/index.js +3 -3
- package/dist/es/components/Badge/index.js.map +1 -1
- package/dist/es/components/Breadcrumb/Breadcrumb.js +34 -0
- package/dist/es/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/es/components/Breadcrumb/index.js +2 -0
- package/dist/es/components/Breadcrumb/index.js.map +1 -0
- package/dist/es/components/Button/Button.js +7 -7
- package/dist/es/components/Button/Button.js.map +1 -1
- package/dist/es/components/Button/CopyButton.js +25 -13
- package/dist/es/components/Button/CopyButton.js.map +1 -1
- package/dist/es/components/Button/index.js +2 -2
- package/dist/es/components/ButtonGroup/ButtonGroup.js +2 -2
- package/dist/es/components/ButtonGroup/ButtonGroup.js.map +1 -1
- package/dist/es/components/ButtonGroup/index.js +1 -1
- package/dist/es/components/Card/Card.js +4 -3
- package/dist/es/components/Card/Card.js.map +1 -1
- package/dist/es/components/Card/index.js +1 -1
- package/dist/es/components/Checkbox/Checkbox.js +12 -6
- package/dist/es/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/es/components/Checkbox/index.js +1 -1
- package/dist/es/components/CodeBlock/CodeBlock.js +25 -25
- package/dist/es/components/CodeBlock/CodeBlock.js.map +1 -1
- package/dist/es/components/CodeBlock/CollapsibleCodeBlock.js +6 -4
- package/dist/es/components/CodeBlock/CollapsibleCodeBlock.js.map +1 -1
- package/dist/es/components/CodeBlock/index.js +2 -2
- package/dist/es/components/DataTable/DataTable.js +108 -27
- package/dist/es/components/DataTable/DataTable.js.map +1 -1
- package/dist/es/components/DataTable/DataTableColumnHeader.js +2 -2
- package/dist/es/components/DataTable/DataTableColumnHeader.js.map +1 -1
- package/dist/es/components/DataTable/DataTablePagination.js +8 -4
- package/dist/es/components/DataTable/DataTablePagination.js.map +1 -1
- package/dist/es/components/DataTable/columnHelpers.js +3 -3
- package/dist/es/components/DataTable/index.js +4 -4
- package/dist/es/components/DateInput/DateInput.js +21 -13
- package/dist/es/components/DateInput/DateInput.js.map +1 -1
- package/dist/es/components/DateInput/index.js +1 -1
- package/dist/es/components/DatePicker/Calendar.js +136 -32
- package/dist/es/components/DatePicker/Calendar.js.map +1 -1
- package/dist/es/components/DatePicker/DatePicker.js +15 -11
- package/dist/es/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/es/components/DatePicker/index.js +1 -1
- package/dist/es/components/DateRangePicker/Calendar.js +125 -22
- package/dist/es/components/DateRangePicker/Calendar.js.map +1 -1
- package/dist/es/components/DateRangePicker/DateRangePicker.js +10 -9
- package/dist/es/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/es/components/DateRangePicker/Trigger.js +12 -9
- package/dist/es/components/DateRangePicker/Trigger.js.map +1 -1
- package/dist/es/components/DateRangePicker/index.js +2 -2
- package/dist/es/components/Dialog/Dialog.js +11 -6
- package/dist/es/components/Dialog/Dialog.js.map +1 -1
- package/dist/es/components/Dialog/index.js +1 -1
- package/dist/es/components/Dialog/index.js.map +1 -1
- package/dist/es/components/EmptyMessage/EmptyMessage.js +4 -4
- package/dist/es/components/EmptyMessage/EmptyMessage.js.map +1 -1
- package/dist/es/components/EmptyMessage/index.js +1 -1
- package/dist/es/components/Field/Field.js +22 -7
- package/dist/es/components/Field/Field.js.map +1 -1
- package/dist/es/components/Field/index.js +1 -1
- package/dist/es/components/FieldError/FieldError.js +4 -4
- package/dist/es/components/FieldError/FieldError.js.map +1 -1
- package/dist/es/components/FieldError/index.js +1 -1
- package/dist/es/components/FileUpload/FileUpload.js +12 -9
- package/dist/es/components/FileUpload/FileUpload.js.map +1 -1
- package/dist/es/components/FileUpload/index.js +1 -1
- package/dist/es/components/FloatingLabelInput/FloatingLabelInput.js +31 -4
- package/dist/es/components/FloatingLabelInput/FloatingLabelInput.js.map +1 -1
- package/dist/es/components/FloatingLabelInput/index.js +1 -1
- package/dist/es/components/FloatingLabelSelect/FloatingLabelSelect.js +28 -8
- package/dist/es/components/FloatingLabelSelect/FloatingLabelSelect.js.map +1 -1
- package/dist/es/components/FloatingLabelSelect/index.js +1 -1
- package/dist/es/components/Icon/aliases.js +20 -20
- package/dist/es/components/Icon/index.js +653 -653
- package/dist/es/components/Image/Image.js +19 -7
- package/dist/es/components/Image/Image.js.map +1 -1
- package/dist/es/components/Image/index.js +1 -1
- package/dist/es/components/Indicator/CircularProgress.js +3 -3
- package/dist/es/components/Indicator/CircularProgress.js.map +1 -1
- package/dist/es/components/Indicator/LoadingDots.js +1 -1
- package/dist/es/components/Indicator/LoadingDots.js.map +1 -1
- package/dist/es/components/Indicator/LoadingIndicator.js +2 -2
- package/dist/es/components/Indicator/LoadingIndicator.js.map +1 -1
- package/dist/es/components/Indicator/index.js +3 -3
- package/dist/es/components/Input/Input.js +16 -5
- package/dist/es/components/Input/Input.js.map +1 -1
- package/dist/es/components/Input/index.js +1 -1
- package/dist/es/components/InputGroup/InputGroup.js +60 -0
- package/dist/es/components/InputGroup/InputGroup.js.map +1 -0
- package/dist/es/components/InputGroup/index.js +2 -0
- package/dist/es/components/InputGroup/index.js.map +1 -0
- package/dist/es/components/Kbd/Kbd.js +13 -0
- package/dist/es/components/Kbd/Kbd.js.map +1 -0
- package/dist/es/components/Kbd/index.js +2 -0
- package/dist/es/components/Kbd/index.js.map +1 -0
- package/dist/es/components/Label/Label.js +1 -1
- package/dist/es/components/Label/Label.js.map +1 -1
- package/dist/es/components/Label/index.js +1 -1
- package/dist/es/components/Markdown/Markdown.js +8 -8
- package/dist/es/components/Markdown/Markdown.js.map +1 -1
- package/dist/es/components/Markdown/directives.js +2 -2
- package/dist/es/components/Markdown/index.js +4 -5
- package/dist/es/components/Markdown/index.js.map +1 -1
- package/dist/es/components/MarkdownEditor/MarkdownEditor.js +35 -11
- package/dist/es/components/MarkdownEditor/MarkdownEditor.js.map +1 -1
- package/dist/es/components/MarkdownEditor/index.js +1 -1
- package/dist/es/components/Menu/Menu.js +26 -18
- package/dist/es/components/Menu/Menu.js.map +1 -1
- package/dist/es/components/Menu/index.js +1 -1
- package/dist/es/components/OTPInput/OTPInput.js +51 -34
- package/dist/es/components/OTPInput/OTPInput.js.map +1 -1
- package/dist/es/components/OTPInput/index.js +1 -1
- package/dist/es/components/PlexUIProvider/PlexUIProvider.js +3 -1
- package/dist/es/components/PlexUIProvider/PlexUIProvider.js.map +1 -1
- package/dist/es/components/PlexUIProvider/index.js +1 -1
- package/dist/es/components/PlexUIProvider/internal.js +1 -1
- package/dist/es/components/Popover/Popover.js +7 -7
- package/dist/es/components/Popover/Popover.js.map +1 -1
- package/dist/es/components/Popover/index.js +2 -3
- package/dist/es/components/Popover/index.js.map +1 -1
- package/dist/es/components/Popover/usePopoverController.js +2 -2
- package/dist/es/components/Progress/Progress.js +1 -1
- package/dist/es/components/Progress/Progress.js.map +1 -1
- package/dist/es/components/Progress/index.js +1 -1
- package/dist/es/components/ProgressSteps/ProgressSteps.js +6 -4
- package/dist/es/components/ProgressSteps/ProgressSteps.js.map +1 -1
- package/dist/es/components/ProgressSteps/index.js +1 -1
- package/dist/es/components/RadioGroup/RadioGroup.js +10 -6
- package/dist/es/components/RadioGroup/RadioGroup.js.map +1 -1
- package/dist/es/components/RadioGroup/index.js +1 -1
- package/dist/es/components/SegmentedControl/index.js +1 -1
- package/dist/es/components/Select/Select.js +104 -67
- package/dist/es/components/Select/Select.js.map +1 -1
- package/dist/es/components/Select/index.js +1 -1
- package/dist/es/components/SelectControl/SelectControl.js +10 -5
- package/dist/es/components/SelectControl/SelectControl.js.map +1 -1
- package/dist/es/components/SelectControl/index.js +1 -1
- package/dist/es/components/Separator/Separator.js +1 -1
- package/dist/es/components/Separator/Separator.js.map +1 -1
- package/dist/es/components/Separator/index.js +1 -1
- package/dist/es/components/ShimmerText/ShimmerText.js +1 -1
- package/dist/es/components/ShimmerText/ShimmerText.js.map +1 -1
- package/dist/es/components/ShimmerText/index.js +1 -1
- package/dist/es/components/Sidebar/Sidebar.js +37 -29
- package/dist/es/components/Sidebar/Sidebar.js.map +1 -1
- package/dist/es/components/Sidebar/index.js +2 -2
- package/dist/es/components/Sidebar/useSidebarContext.js +17 -19
- package/dist/es/components/Sidebar/useSidebarContext.js.map +1 -1
- package/dist/es/components/Skeleton/index.js +1 -1
- package/dist/es/components/Skeleton/index.js.map +1 -1
- package/dist/es/components/Slider/Slider.js +48 -19
- package/dist/es/components/Slider/Slider.js.map +1 -1
- package/dist/es/components/Slider/index.js +1 -1
- package/dist/es/components/StatCard/StatCard.js +5 -5
- package/dist/es/components/StatCard/StatCard.js.map +1 -1
- package/dist/es/components/StatCard/index.js +1 -1
- package/dist/es/components/Switch/Switch.js +7 -3
- package/dist/es/components/Switch/Switch.js.map +1 -1
- package/dist/es/components/Switch/index.js +1 -1
- package/dist/es/components/Table/Table.js +1 -1
- package/dist/es/components/Table/Table.js.map +1 -1
- package/dist/es/components/Table/index.js +1 -1
- package/dist/es/components/Tabs/Tabs.js +154 -6
- package/dist/es/components/Tabs/Tabs.js.map +1 -1
- package/dist/es/components/Tabs/index.js +1 -1
- package/dist/es/components/Tabs/overflow.js +44 -0
- package/dist/es/components/Tabs/overflow.js.map +1 -0
- package/dist/es/components/TagInput/TagInput.js +47 -23
- package/dist/es/components/TagInput/TagInput.js.map +1 -1
- package/dist/es/components/TagInput/index.js +1 -1
- package/dist/es/components/TextLink/TextLink.js +16 -5
- package/dist/es/components/TextLink/TextLink.js.map +1 -1
- package/dist/es/components/TextLink/index.js +1 -1
- package/dist/es/components/Textarea/Textarea.js +4 -4
- package/dist/es/components/Textarea/Textarea.js.map +1 -1
- package/dist/es/components/Textarea/index.js +1 -1
- package/dist/es/components/Toast/Toaster.js +2 -2
- package/dist/es/components/Toast/Toaster.js.map +1 -1
- package/dist/es/components/Toast/index.js +1 -1
- package/dist/es/components/Tooltip/CopyTooltip.js +30 -9
- package/dist/es/components/Tooltip/CopyTooltip.js.map +1 -1
- package/dist/es/components/Tooltip/Tooltip.js +3 -3
- package/dist/es/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/es/components/Tooltip/index.js +2 -2
- package/dist/es/components/Transition/Animate.js +4 -4
- package/dist/es/components/Transition/Animate.js.map +1 -1
- package/dist/es/components/Transition/AnimateLayout.js +4 -4
- package/dist/es/components/Transition/AnimateLayout.js.map +1 -1
- package/dist/es/components/Transition/AnimateLayoutGroup.js +12 -8
- package/dist/es/components/Transition/AnimateLayoutGroup.js.map +1 -1
- package/dist/es/components/Transition/SlotTransitionGroup.js +4 -4
- package/dist/es/components/Transition/TransitionGroup.js +5 -5
- package/dist/es/components/Transition/TransitionGroup.js.map +1 -1
- package/dist/es/components/Transition/getDisableAnimations.js +1 -1
- package/dist/es/components/Transition/index.js +5 -5
- package/dist/es/components/Transition/shared.js +7 -5
- package/dist/es/components/Transition/shared.js.map +1 -1
- package/dist/es/components/UIProvider/UIProvider.js +1 -1
- package/dist/es/components/UIProvider/index.js +1 -1
- package/dist/es/components/UIProvider/internal.js +1 -1
- package/dist/es/hooks/useAnimatedScrollTo.js +1 -1
- package/dist/es/hooks/useBreakpoints.js +8 -2
- package/dist/es/hooks/useBreakpoints.js.map +1 -1
- package/dist/es/hooks/useEscCloseStack.js +1 -1
- package/dist/es/hooks/usePrevious.js +7 -5
- package/dist/es/hooks/usePrevious.js.map +1 -1
- package/dist/es/hooks/useTextSelection.js +2 -2
- package/dist/es/hooks/useTrailingValue.js +1 -1
- package/dist/es/lib/constants.js +1 -1
- package/dist/es/lib/helpers.js +1 -1
- package/dist/es/lib/helpers.js.map +1 -1
- package/dist/es/lib/renderHelpers.js +15 -6
- package/dist/es/lib/renderHelpers.js.map +1 -1
- package/dist/es/lib/theme.js +16 -16
- package/dist/es/lib/theme.js.map +1 -1
- package/dist/es/lib/userAgent.js +3 -2
- package/dist/es/lib/userAgent.js.map +1 -1
- package/dist/es/styles/base.css +1 -102
- package/dist/es/styles/globals.css +1 -50
- package/dist/es/styles/index.css +1 -25
- package/dist/es/styles/katex.min.css +1 -1296
- package/dist/es/styles/tailwind-utilities.css +1 -1316
- package/dist/es/styles/variables-components.css +1 -626
- package/dist/es/styles/variables-primitive.css +1 -327
- package/dist/es/styles/variables-semantic.css +1 -609
- package/dist/es/styles/variables-tailwind-theme.css +1 -34
- package/dist/es/styles/variables-tokens-root.css +1 -41
- package/dist/es/types.js +1 -1
- package/dist/es/types.js.map +1 -1
- package/dist/es/vite/index.js +3 -53
- package/dist/es/vite/index.js.map +1 -1
- package/dist/types/components/Accordion/index.d.ts +1 -1
- package/dist/types/components/Alert/Alert.d.ts +8 -2
- package/dist/types/components/Alert/index.d.ts +1 -1
- package/dist/types/components/Avatar/Avatar.d.ts +1 -1
- package/dist/types/components/Avatar/index.d.ts +2 -2
- package/dist/types/components/Badge/index.d.ts +1 -1
- package/dist/types/components/Breadcrumb/Breadcrumb.d.ts +34 -0
- package/dist/types/components/Breadcrumb/index.d.ts +1 -0
- package/dist/types/components/Button/Button.d.ts +3 -3
- package/dist/types/components/Button/CopyButton.d.ts +9 -4
- package/dist/types/components/Button/index.d.ts +2 -2
- package/dist/types/components/ButtonGroup/ButtonGroup.d.ts +4 -3
- package/dist/types/components/ButtonGroup/index.d.ts +1 -1
- package/dist/types/components/Card/index.d.ts +1 -1
- package/dist/types/components/Checkbox/Checkbox.d.ts +3 -1
- package/dist/types/components/Checkbox/index.d.ts +1 -1
- package/dist/types/components/CodeBlock/index.d.ts +2 -2
- package/dist/types/components/DataTable/DataTable.d.ts +3 -2
- package/dist/types/components/DataTable/index.d.ts +4 -4
- package/dist/types/components/DateInput/DateInput.d.ts +1 -1
- package/dist/types/components/DateInput/index.d.ts +1 -1
- package/dist/types/components/DatePicker/DatePicker.d.ts +7 -6
- package/dist/types/components/DatePicker/context.d.ts +1 -1
- package/dist/types/components/DatePicker/index.d.ts +2 -2
- package/dist/types/components/DateRangePicker/Calendar.d.ts +1 -1
- package/dist/types/components/DateRangePicker/DateRangePicker.d.ts +5 -5
- package/dist/types/components/DateRangePicker/context.d.ts +2 -2
- package/dist/types/components/DateRangePicker/index.d.ts +2 -2
- package/dist/types/components/Dialog/Dialog.d.ts +19 -1
- package/dist/types/components/Dialog/index.d.ts +1 -1
- package/dist/types/components/EmptyMessage/EmptyMessage.d.ts +15 -3
- package/dist/types/components/EmptyMessage/index.d.ts +1 -1
- package/dist/types/components/Field/Field.d.ts +14 -4
- package/dist/types/components/Field/index.d.ts +1 -1
- package/dist/types/components/FieldError/FieldError.d.ts +7 -1
- package/dist/types/components/FieldError/index.d.ts +1 -1
- package/dist/types/components/FileUpload/index.d.ts +1 -1
- package/dist/types/components/FloatingLabelInput/index.d.ts +1 -1
- package/dist/types/components/FloatingLabelSelect/index.d.ts +1 -1
- package/dist/types/components/Icon/aliases.d.ts +20 -20
- package/dist/types/components/Icon/index.d.ts +653 -653
- package/dist/types/components/Image/Image.d.ts +1 -1
- package/dist/types/components/Image/index.d.ts +1 -1
- package/dist/types/components/Indicator/index.d.ts +3 -3
- package/dist/types/components/Input/Input.d.ts +2 -2
- package/dist/types/components/Input/index.d.ts +1 -1
- package/dist/types/components/InputGroup/InputGroup.d.ts +78 -0
- package/dist/types/components/InputGroup/index.d.ts +1 -0
- package/dist/types/components/Kbd/Kbd.d.ts +20 -0
- package/dist/types/components/Kbd/index.d.ts +1 -0
- package/dist/types/components/Label/index.d.ts +1 -1
- package/dist/types/components/Markdown/Markdown.d.ts +1 -1
- package/dist/types/components/Markdown/index.d.ts +4 -4
- package/dist/types/components/MarkdownEditor/MarkdownEditor.d.ts +6 -2
- package/dist/types/components/MarkdownEditor/index.d.ts +1 -1
- package/dist/types/components/Menu/Menu.d.ts +11 -3
- package/dist/types/components/Menu/index.d.ts +1 -1
- package/dist/types/components/OTPInput/index.d.ts +1 -1
- package/dist/types/components/PlexUIProvider/PlexUIProvider.d.ts +0 -11
- package/dist/types/components/PlexUIProvider/index.d.ts +1 -1
- package/dist/types/components/Popover/index.d.ts +2 -2
- package/dist/types/components/Progress/index.d.ts +1 -1
- package/dist/types/components/ProgressSteps/ProgressSteps.d.ts +1 -1
- package/dist/types/components/ProgressSteps/index.d.ts +1 -1
- package/dist/types/components/RadioGroup/RadioGroup.d.ts +3 -1
- package/dist/types/components/RadioGroup/index.d.ts +1 -1
- package/dist/types/components/SegmentedControl/index.d.ts +2 -2
- package/dist/types/components/Select/Select.d.ts +8 -1
- package/dist/types/components/Select/index.d.ts +1 -1
- package/dist/types/components/SelectControl/SelectControl.d.ts +1 -1
- package/dist/types/components/SelectControl/index.d.ts +1 -1
- package/dist/types/components/Separator/index.d.ts +1 -1
- package/dist/types/components/ShimmerText/index.d.ts +1 -1
- package/dist/types/components/Sidebar/Sidebar.d.ts +4 -8
- package/dist/types/components/Sidebar/index.d.ts +4 -4
- package/dist/types/components/Slider/Slider.d.ts +8 -0
- package/dist/types/components/Slider/index.d.ts +2 -2
- package/dist/types/components/StatCard/index.d.ts +1 -1
- package/dist/types/components/Switch/index.d.ts +1 -1
- package/dist/types/components/Table/index.d.ts +1 -1
- package/dist/types/components/Tabs/Tabs.d.ts +15 -2
- package/dist/types/components/Tabs/index.d.ts +2 -2
- package/dist/types/components/Tabs/overflow.d.ts +17 -0
- package/dist/types/components/TagInput/TagInput.d.ts +1 -1
- package/dist/types/components/TagInput/index.d.ts +1 -1
- package/dist/types/components/TextLink/index.d.ts +1 -1
- package/dist/types/components/Textarea/Textarea.d.ts +1 -1
- package/dist/types/components/Textarea/index.d.ts +1 -1
- package/dist/types/components/Toast/index.d.ts +1 -1
- package/dist/types/components/Tooltip/CopyTooltip.d.ts +6 -1
- package/dist/types/components/Tooltip/index.d.ts +2 -2
- package/dist/types/components/Transition/Animate.d.ts +2 -2
- package/dist/types/components/Transition/AnimateLayout.d.ts +2 -2
- package/dist/types/components/Transition/AnimateLayoutGroup.d.ts +2 -2
- package/dist/types/components/Transition/SlotTransitionGroup.d.ts +1 -1
- package/dist/types/components/Transition/TransitionGroup.d.ts +1 -1
- package/dist/types/components/Transition/index.d.ts +5 -5
- package/dist/types/components/UIProvider/index.d.ts +1 -1
- package/dist/types/global.d.ts +5 -1
- package/dist/types/lib/constants.d.ts +1 -1
- package/dist/types/lib/helpers.d.ts +4 -4
- package/dist/types/lib/theme.d.ts +1 -1
- package/dist/types/types.d.ts +2 -15
- package/dist/types/vite/index.d.ts +2 -55
- package/package.json +10 -18
- package/dist/es/components/Accordion/Accordion.module.css +0 -89
- package/dist/es/components/Alert/Alert.module.css +0 -187
- package/dist/es/components/Avatar/Avatar.module.css +0 -168
- package/dist/es/components/Avatar/AvatarGroup.module.css +0 -26
- package/dist/es/components/Badge/Badge.module.css +0 -196
- package/dist/es/components/Button/Button.module.css +0 -859
- package/dist/es/components/ButtonGroup/ButtonGroup.module.css +0 -159
- package/dist/es/components/Card/Card.module.css +0 -125
- package/dist/es/components/Checkbox/Checkbox.module.css +0 -198
- package/dist/es/components/CodeBlock/CodeBlock.module.css +0 -137
- package/dist/es/components/DataTable/DataTable.module.css +0 -108
- package/dist/es/components/DatePicker/Calendar.module.css +0 -271
- package/dist/es/components/DateRangePicker/Calendar.module.css +0 -295
- package/dist/es/components/DateRangePicker/Trigger.module.css +0 -25
- package/dist/es/components/Dialog/Dialog.module.css +0 -133
- package/dist/es/components/EmptyMessage/EmptyMessage.module.css +0 -82
- package/dist/es/components/Field/Field.module.css +0 -137
- package/dist/es/components/FieldError/FieldError.module.css +0 -22
- package/dist/es/components/FileUpload/FileUpload.module.css +0 -133
- package/dist/es/components/FloatingLabelInput/FloatingLabelInput.module.css +0 -220
- package/dist/es/components/FloatingLabelSelect/FloatingLabelSelect.module.css +0 -146
- package/dist/es/components/Image/Image.module.css +0 -9
- package/dist/es/components/Indicator/CircularProgress.module.css +0 -28
- package/dist/es/components/Indicator/LoadingDots.module.css +0 -35
- package/dist/es/components/Indicator/LoadingIndicator.module.css +0 -41
- package/dist/es/components/Input/Input.module.css +0 -507
- package/dist/es/components/Label/Label.module.css +0 -16
- package/dist/es/components/Markdown/Markdown.module.css +0 -233
- package/dist/es/components/MarkdownEditor/MarkdownEditor.module.css +0 -297
- package/dist/es/components/Menu/Menu.module.css +0 -377
- package/dist/es/components/OTPInput/OTPInput.module.css +0 -66
- package/dist/es/components/Popover/Popover.module.css +0 -82
- package/dist/es/components/Progress/Progress.module.css +0 -34
- package/dist/es/components/ProgressSteps/ProgressSteps.module.css +0 -246
- package/dist/es/components/RadioGroup/RadioGroup.module.css +0 -137
- package/dist/es/components/Select/Select.module.css +0 -310
- package/dist/es/components/SelectControl/SelectControl.module.css +0 -558
- package/dist/es/components/Separator/Separator.module.css +0 -16
- package/dist/es/components/ShimmerText/ShimmerText.module.css +0 -43
- package/dist/es/components/Sidebar/Sidebar.module.css +0 -909
- package/dist/es/components/Skeleton/Skeleton.module.css +0 -17
- package/dist/es/components/Slider/Slider.module.css +0 -203
- package/dist/es/components/StatCard/StatCard.module.css +0 -234
- package/dist/es/components/Switch/Switch.module.css +0 -121
- package/dist/es/components/Table/Table.module.css +0 -56
- package/dist/es/components/Tabs/Tabs.module.css +0 -672
- package/dist/es/components/TagInput/TagInput.module.css +0 -320
- package/dist/es/components/TextLink/TextLink.module.css +0 -50
- package/dist/es/components/Textarea/Textarea.module.css +0 -272
- package/dist/es/components/Toast/Toast.module.css +0 -84
- package/dist/es/components/Tooltip/Tooltip.module.css +0 -91
- package/dist/es/components/Transition/Animate.module.css +0 -54
- package/dist/es/components/Transition/AnimateLayout.module.css +0 -101
- package/dist/es/components/Transition/AnimateLayoutGroup.module.css +0 -72
- package/dist/es/components/Transition/TransitionGroup.module.css +0 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Field.js","sourceRoot":"","sources":["../../../../src/components/Field/Field.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAG3D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"Field.js","sourceRoot":"","sources":["../../../../src/components/Field/Field.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { cloneElement, isValidElement, useId } from \"react\"\n\nimport type { ControlSize } from \"../../types\"\nimport { FieldError } from \"../FieldError\"\n\nimport s from \"@plexui/styles/components/Field/Field.module.css\"\n\nexport type FieldChildProps = {\n id: string\n /** The label's id. Spread onto a control that the label's `for` cannot name, such as a Select trigger. */\n \"aria-labelledby\"?: string\n \"aria-describedby\"?: string\n \"aria-invalid\"?: boolean\n opticallyAlign?: \"start\" | \"end\"\n}\n\nconst CONTROL_SIZES: ReadonlySet<unknown> = new Set([\"3xs\", \"2xs\", \"xs\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\"])\n\nexport type FieldProps = {\n /**\n * Label text for the field\n */\n label: React.ReactNode\n /**\n * Helper/description text displayed below the label.\n * Automatically linked via aria-describedby.\n */\n description?: React.ReactNode\n /**\n * Error message displayed below the control.\n * When provided, the child control receives aria-invalid=\"true\".\n * Uses the existing FieldError component internally.\n */\n errorMessage?: React.ReactNode\n /**\n * Content placed at the end of the label row, such as a link that acts on\n * the field (\"Forgot password?\", \"Replace\").\n */\n labelAction?: React.ReactNode\n /**\n * Controls the font size of the label to visually match the child control's size.\n * Matches the ControlSize scale used by Input, Select, etc.\n * @default the child control's `size`, else \"md\"\n */\n size?: ControlSize\n /**\n * Display a required indicator (asterisk) after the label.\n * This is purely visual — it does not add the `required` HTML attribute.\n * @default false\n */\n required?: boolean\n /**\n * Layout direction of label and control.\n * - \"vertical\": label stacked above control (default)\n * - \"horizontal\": label beside control\n * @default \"vertical\"\n */\n orientation?: \"vertical\" | \"horizontal\"\n /**\n * Allows overriding the auto-generated `id`. When provided, this becomes\n * the id set on the child control and the `htmlFor` on the label.\n */\n id?: string\n /**\n * Applies a negative margin on the child control using its gutter to\n * optically align the control's text with surrounding content.\n * Passed through to the child control via cloneElement / render prop.\n */\n opticallyAlign?: \"start\" | \"end\"\n /**\n * CSS class applied to the root wrapper\n */\n className?: string\n /**\n * The form control(s) to render.\n * - If a single ReactElement, Field clones it with { id, aria-describedby, aria-invalid }.\n * A child without its own `aria-label`, `aria-labelledby` or `label` also gets\n * `aria-labelledby` pointing at the label, which names controls the label's\n * `for` cannot reach, such as the Select and DatePicker triggers.\n * - If a function (render prop), it is called with { id, \"aria-labelledby\", \"aria-describedby\", \"aria-invalid\" }.\n */\n children: React.ReactElement | ((fieldProps: FieldChildProps) => React.ReactNode)\n}\n\nexport function Field({\n label,\n description,\n errorMessage,\n labelAction,\n size: sizeProp,\n required = false,\n orientation = \"vertical\",\n opticallyAlign,\n id: idProp,\n className,\n children,\n}: FieldProps) {\n const generatedId = useId()\n const fieldId = idProp || `field-${generatedId}`\n const labelId = `${fieldId}-label`\n const childSize = isValidElement<{ size?: unknown }>(children) ? children.props.size : undefined\n const size = sizeProp ?? (CONTROL_SIZES.has(childSize) ? (childSize as ControlSize) : \"md\")\n const descriptionId = description ? `${fieldId}-description` : undefined\n const errorId = errorMessage ? `${fieldId}-error` : undefined\n\n // Build aria-describedby from description + error IDs\n const ariaDescribedBy =\n [descriptionId, errorId].filter(Boolean).join(\" \") || undefined\n\n const invalid = !!errorMessage\n\n // Props to inject into the child control (`aria-labelledby` is added below:\n // to a render prop's props, and to a cloned child without a name of its own)\n const fieldChildProps: FieldChildProps = {\n id: fieldId,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-invalid\": invalid || undefined,\n ...(opticallyAlign && { opticallyAlign }),\n }\n\n // Resolve the children\n let resolvedChildren: React.ReactNode\n if (typeof children === \"function\") {\n resolvedChildren = children({ ...fieldChildProps, \"aria-labelledby\": labelId })\n } else if (isValidElement(children)) {\n const child = children as React.ReactElement<Record<string, unknown>>\n // Merge with the child's own associations instead of overwriting them\n const childDescribedBy = child.props[\"aria-describedby\"] as string | undefined\n const childNamed =\n child.props[\"aria-label\"] != null || child.props[\"aria-labelledby\"] != null || child.props.label != null\n resolvedChildren = cloneElement(child, {\n ...fieldChildProps,\n \"aria-describedby\":\n [childDescribedBy, ariaDescribedBy].filter(Boolean).join(\" \") || undefined,\n \"aria-invalid\": child.props[\"aria-invalid\"] ?? fieldChildProps[\"aria-invalid\"],\n ...(!childNamed && { \"aria-labelledby\": labelId }),\n })\n } else {\n resolvedChildren = children\n }\n\n const labelElement = (\n <label className={s.Label} id={labelId} htmlFor={fieldId}>\n {label}\n {required && (\n <span className={s.RequiredIndicator} aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )\n\n return (\n <div\n className={clsx(s.Field, className)}\n data-size={size}\n data-orientation={orientation}\n data-optically-align={opticallyAlign}\n >\n <div className={s.LabelGroup}>\n {labelAction ? (\n <div className={s.LabelRow}>\n {labelElement}\n <div className={s.LabelAction}>{labelAction}</div>\n </div>\n ) : (\n labelElement\n )}\n {description && (\n <div className={s.Description} id={descriptionId}>\n {description}\n </div>\n )}\n </div>\n <div className={s.Content}>\n <div className={s.Control}>{resolvedChildren}</div>\n {errorMessage && (\n <FieldError id={errorId}>{errorMessage}</FieldError>\n )}\n </div>\n </div>\n )\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Field } from "./Field";
|
|
1
|
+
export { Field } from "./Field.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import clsx from "clsx";
|
|
3
|
-
import { ExclamationMarkCircle } from "../Icon";
|
|
4
|
-
import s from "
|
|
5
|
-
export function FieldError({ children, className, id }) {
|
|
6
|
-
return (_jsxs("div", { className: clsx(s.FieldError, className), id: id, role: "alert", children: [_jsx(ExclamationMarkCircle, { className: s.Icon }), _jsx("span", { children: children })] }));
|
|
3
|
+
import { ExclamationMarkCircle } from "../Icon/index.js";
|
|
4
|
+
import s from "@plexui/styles/components/FieldError/FieldError.module.css";
|
|
5
|
+
export function FieldError({ children, className, id, icon = true }) {
|
|
6
|
+
return (_jsxs("div", { className: clsx(s.FieldError, className), id: id, role: "alert", children: [icon && _jsx(ExclamationMarkCircle, { className: s.Icon }), _jsx("span", { children: children })] }));
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=FieldError.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldError.js","sourceRoot":"","sources":["../../../../src/components/FieldError/FieldError.tsx"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAE/C,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"FieldError.js","sourceRoot":"","sources":["../../../../src/components/FieldError/FieldError.tsx"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAE/C,OAAO,CAAC,MAAM,4DAA4D,CAAA;AAc1E,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,GAAG,IAAI,EAAmB;IAClF,OAAO,CACL,eAAK,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAC,OAAO,aAChE,IAAI,IAAI,KAAC,qBAAqB,IAAC,SAAS,EAAE,CAAC,CAAC,IAAI,GAAI,EACrD,yBAAO,QAAQ,GAAQ,IACnB,CACP,CAAA;AACH,CAAC","sourcesContent":["import clsx from \"clsx\"\n\nimport { ExclamationMarkCircle } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/FieldError/FieldError.module.css\"\n\nexport type FieldErrorProps = {\n children: React.ReactNode\n className?: string\n id?: string\n /**\n * Shows the error icon before the message. Turn it off where the message\n * stands alone, such as under a centered code input.\n * @default true\n */\n icon?: boolean\n}\n\nexport function FieldError({ children, className, id, icon = true }: FieldErrorProps) {\n return (\n <div className={clsx(s.FieldError, className)} id={id} role=\"alert\">\n {icon && <ExclamationMarkCircle className={s.Icon} />}\n <span>{children}</span>\n </div>\n )\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { FieldError } from "./FieldError";
|
|
1
|
+
export { FieldError } from "./FieldError.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import clsx from "clsx";
|
|
4
4
|
import { useCallback, useId, useRef, useState } from "react";
|
|
5
|
-
import { FileDocument, ImageSquare, FileBlank, UploadDocuments, X, } from "../Icon";
|
|
6
|
-
import { Button } from "../Button";
|
|
7
|
-
import { FieldError } from "../FieldError";
|
|
8
|
-
import s from "
|
|
5
|
+
import { FileDocument, ImageSquare, FileBlank, UploadDocuments, X, } from "../Icon/index.js";
|
|
6
|
+
import { Button } from "../Button/index.js";
|
|
7
|
+
import { FieldError } from "../FieldError/index.js";
|
|
8
|
+
import s from "@plexui/styles/components/FileUpload/FileUpload.module.css";
|
|
9
9
|
function getFileIcon(file) {
|
|
10
10
|
const type = file.type;
|
|
11
11
|
const name = file.name.toLowerCase();
|
|
@@ -63,7 +63,7 @@ function matchesAccept(file, accept) {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
export const FileUpload = (props) => {
|
|
66
|
-
const { variant = "compact", label, description, accept, multiple = false, maxFiles, maxSize, value: controlledValue, onValueChange, onFileReject, errorMessage, "invalid": invalidProp, disabled = false, className, id: idProp, "aria-describedby": ariaDescribedByProp, } = props;
|
|
66
|
+
const { variant = "compact", label, description, accept, multiple = false, maxFiles, maxSize, value: controlledValue, onValueChange, onFileReject, errorMessage, "invalid": invalidProp, disabled = false, className, id: idProp, "aria-describedby": ariaDescribedByProp, "aria-invalid": ariaInvalidProp, } = props;
|
|
67
67
|
const [internalFiles, setInternalFiles] = useState([]);
|
|
68
68
|
const inputRef = useRef(null);
|
|
69
69
|
const generatedId = useId();
|
|
@@ -72,6 +72,7 @@ export const FileUpload = (props) => {
|
|
|
72
72
|
const files = controlledValue ?? internalFiles;
|
|
73
73
|
const isControlled = controlledValue !== undefined;
|
|
74
74
|
const invalid = invalidProp ?? !!errorMessage;
|
|
75
|
+
const ariaInvalid = ariaInvalidProp ?? (invalid || undefined);
|
|
75
76
|
const ariaDescribedBy = [ariaDescribedByProp, errorMessage ? errorId : undefined].filter(Boolean).join(" ") ||
|
|
76
77
|
undefined;
|
|
77
78
|
const updateFiles = useCallback((next) => {
|
|
@@ -82,6 +83,8 @@ export const FileUpload = (props) => {
|
|
|
82
83
|
}, [onValueChange, isControlled]);
|
|
83
84
|
const handleFileSelect = useCallback((e) => {
|
|
84
85
|
const selected = Array.from(e.target.files || []);
|
|
86
|
+
// Without `multiple`, a pick replaces the file instead of adding to it
|
|
87
|
+
const kept = multiple ? files : [];
|
|
85
88
|
const accepted = [];
|
|
86
89
|
for (const file of selected) {
|
|
87
90
|
if (accept && !matchesAccept(file, accept)) {
|
|
@@ -92,17 +95,17 @@ export const FileUpload = (props) => {
|
|
|
92
95
|
onFileReject?.(file, `File too large: ${file.name} (${formatFileSize(file.size)})`);
|
|
93
96
|
continue;
|
|
94
97
|
}
|
|
95
|
-
if (maxFiles &&
|
|
98
|
+
if (maxFiles && kept.length + accepted.length >= maxFiles) {
|
|
96
99
|
onFileReject?.(file, `Maximum ${maxFiles} files allowed`);
|
|
97
100
|
continue;
|
|
98
101
|
}
|
|
99
102
|
accepted.push(file);
|
|
100
103
|
}
|
|
101
104
|
if (accepted.length > 0) {
|
|
102
|
-
updateFiles([...
|
|
105
|
+
updateFiles([...kept, ...accepted]);
|
|
103
106
|
}
|
|
104
107
|
e.target.value = "";
|
|
105
|
-
}, [accept, maxSize, maxFiles, files, updateFiles, onFileReject]);
|
|
108
|
+
}, [accept, maxSize, maxFiles, multiple, files, updateFiles, onFileReject]);
|
|
106
109
|
const removeFile = useCallback((index) => {
|
|
107
110
|
const next = files.filter((_, i) => i !== index);
|
|
108
111
|
updateFiles(next);
|
|
@@ -111,6 +114,6 @@ export const FileUpload = (props) => {
|
|
|
111
114
|
inputRef.current?.click();
|
|
112
115
|
}, []);
|
|
113
116
|
const atLimit = !!maxFiles && files.length >= maxFiles;
|
|
114
|
-
return (_jsxs("div", { className: clsx(s.Root, className), children: [variant === "area" ? (_jsxs("button", { type: "button", className: s.AreaTrigger, "data-invalid": invalid ? "" : undefined, onClick: openPicker, disabled: disabled || atLimit, children: [_jsx(UploadDocuments, { className: s.AreaIcon }), _jsx("span", { className: s.AreaLabel, children: label || "Tap to upload files" }), description && _jsx("span", { className: s.AreaDescription, children: description })] })) : (_jsx(Button, { color: "secondary", variant: "soft", size: "3xl", pill: true, block: true, disabled: disabled || atLimit, onClick: openPicker, className: "h-[3.25rem]", children: label || "Upload file" })), files.length > 0 && (_jsx("ul", { className: s.FileList, "data-variant": variant, "aria-label": "Attached files", children: files.map((file, index) => (_jsx("li", { children: _jsx(FileCard, { file: file, onRemove: () => removeFile(index), disabled: disabled }) }, `${file.name}-${file.size}-${file.lastModified}`))) })), _jsx("input", { ref: inputRef, type: "file", className: s.HiddenInput, accept: accept, multiple: multiple, onChange: handleFileSelect, disabled: disabled, id: inputId, "aria-describedby": ariaDescribedBy, tabIndex: -1 }), errorMessage && (_jsx(FieldError, { id: errorId, className: s.ErrorMessage, children: errorMessage }))] }));
|
|
117
|
+
return (_jsxs("div", { className: clsx(s.Root, className), children: [variant === "area" ? (_jsxs("button", { type: "button", className: s.AreaTrigger, "data-invalid": invalid ? "" : undefined, onClick: openPicker, disabled: disabled || atLimit, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, children: [_jsx(UploadDocuments, { className: s.AreaIcon }), _jsx("span", { className: s.AreaLabel, children: label || "Tap to upload files" }), description && _jsx("span", { className: s.AreaDescription, children: description })] })) : (_jsx(Button, { color: "secondary", variant: "soft", size: "3xl", pill: true, block: true, disabled: disabled || atLimit, onClick: openPicker, className: "h-[3.25rem]", "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, children: label || "Upload file" })), files.length > 0 && (_jsx("ul", { className: s.FileList, "data-variant": variant, "aria-label": "Attached files", children: files.map((file, index) => (_jsx("li", { children: _jsx(FileCard, { file: file, onRemove: () => removeFile(index), disabled: disabled }) }, `${file.name}-${file.size}-${file.lastModified}`))) })), _jsx("input", { ref: inputRef, type: "file", className: s.HiddenInput, accept: accept, multiple: multiple, onChange: handleFileSelect, disabled: disabled, id: inputId, "aria-describedby": ariaDescribedBy, tabIndex: -1 }), errorMessage && (_jsx(FieldError, { id: errorId, className: s.ErrorMessage, children: errorMessage }))] }));
|
|
115
118
|
};
|
|
116
119
|
//# sourceMappingURL=FileUpload.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUpload.js","sourceRoot":"","sources":["../../../../src/components/FileUpload/FileUpload.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { useCallback, useId, useRef, useState } from \"react\"\nimport {\n FileDocument,\n ImageSquare,\n FileBlank,\n UploadDocuments,\n X,\n} from \"../Icon\"\nimport { Button } from \"../Button\"\nimport { FieldError } from \"../FieldError\"\nimport s from \"./FileUpload.module.css\"\n\nexport type FileUploadProps = {\n variant?: \"compact\" | \"area\"\n label?: string\n description?: string\n accept?: string\n multiple?: boolean\n maxFiles?: number\n maxSize?: number\n value?: File[]\n onValueChange?: (files: File[]) => void\n onFileReject?: (file: File, reason: string) => void\n errorMessage?: string\n invalid?: boolean\n disabled?: boolean\n id?: string\n className?: string\n \"aria-describedby\"?: string\n \"aria-invalid\"?: boolean\n}\n\nfunction getFileIcon(file: File) {\n const type = file.type\n const name = file.name.toLowerCase()\n\n if (\n type === \"application/pdf\" ||\n name.endsWith(\".pdf\") ||\n name.endsWith(\".doc\") ||\n name.endsWith(\".docx\") ||\n name.endsWith(\".txt\") ||\n name.endsWith(\".rtf\")\n ) {\n return <FileDocument />\n }\n\n if (type.startsWith(\"image/\") || /\\.(png|jpe?g|gif|svg|webp|bmp|ico)$/.test(name)) {\n return <ImageSquare />\n }\n\n return <FileBlank />\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes === 0) return \"0 B\"\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction splitFileName(name: string): { stem: string; ext: string } {\n const lastDot = name.lastIndexOf(\".\")\n if (lastDot <= 0) return { stem: name, ext: \"\" }\n return {\n stem: name.slice(0, lastDot),\n ext: name.slice(lastDot),\n }\n}\n\nexport type FileCardGroupProps = {\n children: React.ReactNode\n className?: string\n}\n\nexport const FileCardGroup = ({ children, className }: FileCardGroupProps) => {\n return <div className={clsx(s.FileCardGroup, className)}>{children}</div>\n}\n\nexport type FileCardProps = {\n file: File\n onRemove?: () => void\n disabled?: boolean\n className?: string\n}\n\nexport const FileCard = ({ file, onRemove, disabled, className }: FileCardProps) => {\n const { stem, ext } = splitFileName(file.name)\n\n return (\n <div className={clsx(s.FileItem, className)}>\n <div className={s.FileIcon}>{getFileIcon(file)}</div>\n <div className={s.FileInfo}>\n <div className={s.FileNameRow}>\n <span className={s.FileNameStem}>{stem}</span>\n {ext && <span className={s.FileNameExt}>{ext}</span>}\n </div>\n <span className={s.FileSize}>{formatFileSize(file.size)}</span>\n </div>\n {onRemove && (\n <button\n type=\"button\"\n className={s.FileRemove}\n onClick={onRemove}\n aria-label={`Remove ${file.name}`}\n disabled={disabled}\n >\n <X />\n </button>\n )}\n </div>\n )\n}\n\nfunction matchesAccept(file: File, accept: string): boolean {\n const acceptTypes = accept.split(\",\").map((t) => t.trim().toLowerCase())\n const fileName = file.name.toLowerCase()\n const fileType = file.type.toLowerCase()\n\n return acceptTypes.some((acceptType) => {\n if (acceptType.startsWith(\".\")) {\n return fileName.endsWith(acceptType)\n }\n if (acceptType.endsWith(\"/*\")) {\n const prefix = acceptType.slice(0, -1)\n return fileType.startsWith(prefix)\n }\n return fileType === acceptType\n })\n}\n\nexport const FileUpload = (props: FileUploadProps) => {\n const {\n variant = \"compact\",\n label,\n description,\n accept,\n multiple = false,\n maxFiles,\n maxSize,\n value: controlledValue,\n onValueChange,\n onFileReject,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n className,\n id: idProp,\n \"aria-describedby\": ariaDescribedByProp,\n } = props\n\n const [internalFiles, setInternalFiles] = useState<File[]>([])\n const inputRef = useRef<HTMLInputElement>(null)\n const generatedId = useId()\n const inputId = idProp || `file-upload-${generatedId}`\n const errorId = `${inputId}-error`\n\n const files = controlledValue ?? internalFiles\n const isControlled = controlledValue !== undefined\n const invalid = invalidProp ?? !!errorMessage\n\n const ariaDescribedBy =\n [ariaDescribedByProp, errorMessage ? errorId : undefined].filter(Boolean).join(\" \") ||\n undefined\n\n const updateFiles = useCallback(\n (next: File[]) => {\n onValueChange?.(next)\n if (!isControlled) {\n setInternalFiles(next)\n }\n },\n [onValueChange, isControlled],\n )\n\n const handleFileSelect = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const selected = Array.from(e.target.files || [])\n const accepted: File[] = []\n\n for (const file of selected) {\n if (accept && !matchesAccept(file, accept)) {\n onFileReject?.(file, `File type not accepted: ${file.name}`)\n continue\n }\n if (maxSize && file.size > maxSize) {\n onFileReject?.(file, `File too large: ${file.name} (${formatFileSize(file.size)})`)\n continue\n }\n if (maxFiles && files.length + accepted.length >= maxFiles) {\n onFileReject?.(file, `Maximum ${maxFiles} files allowed`)\n continue\n }\n accepted.push(file)\n }\n\n if (accepted.length > 0) {\n updateFiles([...files, ...accepted])\n }\n\n e.target.value = \"\"\n },\n [accept, maxSize, maxFiles, files, updateFiles, onFileReject],\n )\n\n const removeFile = useCallback(\n (index: number) => {\n const next = files.filter((_, i) => i !== index)\n updateFiles(next)\n },\n [files, updateFiles],\n )\n\n const openPicker = useCallback(() => {\n inputRef.current?.click()\n }, [])\n\n const atLimit = !!maxFiles && files.length >= maxFiles\n\n return (\n <div className={clsx(s.Root, className)}>\n {variant === \"area\" ? (\n <button\n type=\"button\"\n className={s.AreaTrigger}\n data-invalid={invalid ? \"\" : undefined}\n onClick={openPicker}\n disabled={disabled || atLimit}\n >\n <UploadDocuments className={s.AreaIcon} />\n <span className={s.AreaLabel}>{label || \"Tap to upload files\"}</span>\n {description && <span className={s.AreaDescription}>{description}</span>}\n </button>\n ) : (\n <Button\n color=\"secondary\"\n variant=\"soft\"\n size=\"3xl\"\n pill\n block\n disabled={disabled || atLimit}\n onClick={openPicker}\n className=\"h-[3.25rem]\"\n >\n {label || \"Upload file\"}\n </Button>\n )}\n\n {files.length > 0 && (\n <ul\n className={s.FileList}\n data-variant={variant}\n aria-label=\"Attached files\"\n >\n {files.map((file, index) => (\n <li key={`${file.name}-${file.size}-${file.lastModified}`}>\n <FileCard\n file={file}\n onRemove={() => removeFile(index)}\n disabled={disabled}\n />\n </li>\n ))}\n </ul>\n )}\n\n <input\n ref={inputRef}\n type=\"file\"\n className={s.HiddenInput}\n accept={accept}\n multiple={multiple}\n onChange={handleFileSelect}\n disabled={disabled}\n id={inputId}\n aria-describedby={ariaDescribedBy}\n tabIndex={-1}\n />\n\n {errorMessage && (\n <FieldError id={errorId} className={s.ErrorMessage}>\n {errorMessage}\n </FieldError>\n )}\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FileUpload.js","sourceRoot":"","sources":["../../../../src/components/FileUpload/FileUpload.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { useCallback, useId, useRef, useState } from \"react\"\nimport {\n FileDocument,\n ImageSquare,\n FileBlank,\n UploadDocuments,\n X,\n} from \"../Icon\"\nimport { Button } from \"../Button\"\nimport { FieldError } from \"../FieldError\"\nimport s from \"@plexui/styles/components/FileUpload/FileUpload.module.css\"\n\nexport type FileUploadProps = {\n variant?: \"compact\" | \"area\"\n label?: string\n description?: string\n accept?: string\n multiple?: boolean\n maxFiles?: number\n maxSize?: number\n value?: File[]\n onValueChange?: (files: File[]) => void\n onFileReject?: (file: File, reason: string) => void\n errorMessage?: string\n invalid?: boolean\n disabled?: boolean\n id?: string\n className?: string\n \"aria-describedby\"?: string\n \"aria-invalid\"?: boolean\n}\n\nfunction getFileIcon(file: File) {\n const type = file.type\n const name = file.name.toLowerCase()\n\n if (\n type === \"application/pdf\" ||\n name.endsWith(\".pdf\") ||\n name.endsWith(\".doc\") ||\n name.endsWith(\".docx\") ||\n name.endsWith(\".txt\") ||\n name.endsWith(\".rtf\")\n ) {\n return <FileDocument />\n }\n\n if (type.startsWith(\"image/\") || /\\.(png|jpe?g|gif|svg|webp|bmp|ico)$/.test(name)) {\n return <ImageSquare />\n }\n\n return <FileBlank />\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes === 0) return \"0 B\"\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction splitFileName(name: string): { stem: string; ext: string } {\n const lastDot = name.lastIndexOf(\".\")\n if (lastDot <= 0) return { stem: name, ext: \"\" }\n return {\n stem: name.slice(0, lastDot),\n ext: name.slice(lastDot),\n }\n}\n\nexport type FileCardGroupProps = {\n children: React.ReactNode\n className?: string\n}\n\nexport const FileCardGroup = ({ children, className }: FileCardGroupProps) => {\n return <div className={clsx(s.FileCardGroup, className)}>{children}</div>\n}\n\nexport type FileCardProps = {\n file: File\n onRemove?: () => void\n disabled?: boolean\n className?: string\n}\n\nexport const FileCard = ({ file, onRemove, disabled, className }: FileCardProps) => {\n const { stem, ext } = splitFileName(file.name)\n\n return (\n <div className={clsx(s.FileItem, className)}>\n <div className={s.FileIcon}>{getFileIcon(file)}</div>\n <div className={s.FileInfo}>\n <div className={s.FileNameRow}>\n <span className={s.FileNameStem}>{stem}</span>\n {ext && <span className={s.FileNameExt}>{ext}</span>}\n </div>\n <span className={s.FileSize}>{formatFileSize(file.size)}</span>\n </div>\n {onRemove && (\n <button\n type=\"button\"\n className={s.FileRemove}\n onClick={onRemove}\n aria-label={`Remove ${file.name}`}\n disabled={disabled}\n >\n <X />\n </button>\n )}\n </div>\n )\n}\n\nfunction matchesAccept(file: File, accept: string): boolean {\n const acceptTypes = accept.split(\",\").map((t) => t.trim().toLowerCase())\n const fileName = file.name.toLowerCase()\n const fileType = file.type.toLowerCase()\n\n return acceptTypes.some((acceptType) => {\n if (acceptType.startsWith(\".\")) {\n return fileName.endsWith(acceptType)\n }\n if (acceptType.endsWith(\"/*\")) {\n const prefix = acceptType.slice(0, -1)\n return fileType.startsWith(prefix)\n }\n return fileType === acceptType\n })\n}\n\nexport const FileUpload = (props: FileUploadProps) => {\n const {\n variant = \"compact\",\n label,\n description,\n accept,\n multiple = false,\n maxFiles,\n maxSize,\n value: controlledValue,\n onValueChange,\n onFileReject,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n className,\n id: idProp,\n \"aria-describedby\": ariaDescribedByProp,\n \"aria-invalid\": ariaInvalidProp,\n } = props\n\n const [internalFiles, setInternalFiles] = useState<File[]>([])\n const inputRef = useRef<HTMLInputElement>(null)\n const generatedId = useId()\n const inputId = idProp || `file-upload-${generatedId}`\n const errorId = `${inputId}-error`\n\n const files = controlledValue ?? internalFiles\n const isControlled = controlledValue !== undefined\n const invalid = invalidProp ?? !!errorMessage\n const ariaInvalid = ariaInvalidProp ?? (invalid || undefined)\n\n const ariaDescribedBy =\n [ariaDescribedByProp, errorMessage ? errorId : undefined].filter(Boolean).join(\" \") ||\n undefined\n\n const updateFiles = useCallback(\n (next: File[]) => {\n onValueChange?.(next)\n if (!isControlled) {\n setInternalFiles(next)\n }\n },\n [onValueChange, isControlled],\n )\n\n const handleFileSelect = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const selected = Array.from(e.target.files || [])\n // Without `multiple`, a pick replaces the file instead of adding to it\n const kept = multiple ? files : []\n const accepted: File[] = []\n\n for (const file of selected) {\n if (accept && !matchesAccept(file, accept)) {\n onFileReject?.(file, `File type not accepted: ${file.name}`)\n continue\n }\n if (maxSize && file.size > maxSize) {\n onFileReject?.(file, `File too large: ${file.name} (${formatFileSize(file.size)})`)\n continue\n }\n if (maxFiles && kept.length + accepted.length >= maxFiles) {\n onFileReject?.(file, `Maximum ${maxFiles} files allowed`)\n continue\n }\n accepted.push(file)\n }\n\n if (accepted.length > 0) {\n updateFiles([...kept, ...accepted])\n }\n\n e.target.value = \"\"\n },\n [accept, maxSize, maxFiles, multiple, files, updateFiles, onFileReject],\n )\n\n const removeFile = useCallback(\n (index: number) => {\n const next = files.filter((_, i) => i !== index)\n updateFiles(next)\n },\n [files, updateFiles],\n )\n\n const openPicker = useCallback(() => {\n inputRef.current?.click()\n }, [])\n\n const atLimit = !!maxFiles && files.length >= maxFiles\n\n return (\n <div className={clsx(s.Root, className)}>\n {variant === \"area\" ? (\n <button\n type=\"button\"\n className={s.AreaTrigger}\n data-invalid={invalid ? \"\" : undefined}\n onClick={openPicker}\n disabled={disabled || atLimit}\n // The visible trigger is what keyboard and screen-reader users reach\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n >\n <UploadDocuments className={s.AreaIcon} />\n <span className={s.AreaLabel}>{label || \"Tap to upload files\"}</span>\n {description && <span className={s.AreaDescription}>{description}</span>}\n </button>\n ) : (\n <Button\n color=\"secondary\"\n variant=\"soft\"\n size=\"3xl\"\n pill\n block\n disabled={disabled || atLimit}\n onClick={openPicker}\n className=\"h-[3.25rem]\"\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n >\n {label || \"Upload file\"}\n </Button>\n )}\n\n {files.length > 0 && (\n <ul\n className={s.FileList}\n data-variant={variant}\n aria-label=\"Attached files\"\n >\n {files.map((file, index) => (\n <li key={`${file.name}-${file.size}-${file.lastModified}`}>\n <FileCard\n file={file}\n onRemove={() => removeFile(index)}\n disabled={disabled}\n />\n </li>\n ))}\n </ul>\n )}\n\n <input\n ref={inputRef}\n type=\"file\"\n className={s.HiddenInput}\n accept={accept}\n multiple={multiple}\n onChange={handleFileSelect}\n disabled={disabled}\n id={inputId}\n aria-describedby={ariaDescribedBy}\n tabIndex={-1}\n />\n\n {errorMessage && (\n <FieldError id={errorId} className={s.ErrorMessage}>\n {errorMessage}\n </FieldError>\n )}\n </div>\n )\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { FileUpload, FileCard, FileCardGroup, } from "./FileUpload";
|
|
1
|
+
export { FileUpload, FileCard, FileCardGroup, } from "./FileUpload.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -3,8 +3,22 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import clsx from "clsx";
|
|
4
4
|
import { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
5
5
|
import { mergeRefs } from "react-merge-refs";
|
|
6
|
-
import { Eye, EyeOff, X } from "../Icon";
|
|
7
|
-
import s from "
|
|
6
|
+
import { Eye, EyeOff, X } from "../Icon/index.js";
|
|
7
|
+
import s from "@plexui/styles/components/FloatingLabelInput/FloatingLabelInput.module.css";
|
|
8
|
+
// Attributes that only mean something on <input>; everything else (required,
|
|
9
|
+
// maxLength, placeholder, key and clipboard handlers, aria-*, data-*) also
|
|
10
|
+
// applies to the multiline <textarea>
|
|
11
|
+
const INPUT_ONLY_PROPS = [
|
|
12
|
+
"accept", "alt", "capture", "checked", "height", "list", "max", "min", "multiple",
|
|
13
|
+
"pattern", "size", "src", "step", "width", "formAction", "formEncType",
|
|
14
|
+
"formMethod", "formNoValidate", "formTarget",
|
|
15
|
+
];
|
|
16
|
+
const textareaProps = (props) => {
|
|
17
|
+
const rest = { ...props };
|
|
18
|
+
for (const key of INPUT_ONLY_PROPS)
|
|
19
|
+
delete rest[key];
|
|
20
|
+
return rest;
|
|
21
|
+
};
|
|
8
22
|
export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props, ref) {
|
|
9
23
|
const { label, description, errorMessage, "invalid": invalidProp, disabled = false, readOnly = false, onClear, onAutofill, allowAutofillExtensions = false, startAdornment, endAdornment, revealable: revealableProp, onRevealedChange, multiline = false, rows = 2, className, "id": idProp, name, type = "text", value, defaultValue, onChange, onFocus, onBlur, onAnimationStart, "aria-describedby": ariaDescribedByProp, ...restProps } = props;
|
|
10
24
|
const inputRef = useRef(null);
|
|
@@ -30,7 +44,10 @@ export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props,
|
|
|
30
44
|
el.style.height = "auto";
|
|
31
45
|
el.style.height = `${el.scrollHeight}px`;
|
|
32
46
|
}, [multiline]);
|
|
33
|
-
|
|
47
|
+
// Also resize when a controlled value or rows changes without a keystroke
|
|
48
|
+
useLayoutEffect(() => {
|
|
49
|
+
autoResize();
|
|
50
|
+
}, [autoResize, value, rows]);
|
|
34
51
|
const invalid = invalidProp ?? !!errorMessage;
|
|
35
52
|
// Determine if clear button should be shown
|
|
36
53
|
const showClearButton = !!onClear && hasValue && !disabled && !readOnly;
|
|
@@ -41,6 +58,8 @@ export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props,
|
|
|
41
58
|
const effectiveType = isPassword && revealed ? "text" : type;
|
|
42
59
|
// Merge aria-describedby with error id
|
|
43
60
|
const ariaDescribedBy = [ariaDescribedByProp, errorId, descriptionId].filter(Boolean).join(" ") || undefined;
|
|
61
|
+
// An explicit aria-invalid (e.g. from Field) wins over the computed state
|
|
62
|
+
const ariaInvalid = restProps["aria-invalid"] ?? (invalid ? true : undefined);
|
|
44
63
|
// Handle clicks on the container to focus the input
|
|
45
64
|
const handleContainerMouseDown = useCallback((evt) => {
|
|
46
65
|
const input = inputRef.current;
|
|
@@ -57,9 +76,17 @@ export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props,
|
|
|
57
76
|
if (document.activeElement !== input) {
|
|
58
77
|
input.focus();
|
|
59
78
|
}
|
|
79
|
+
// email, number and other types without the selection API throw on setSelectionRange
|
|
80
|
+
if (input.selectionStart === null)
|
|
81
|
+
return;
|
|
60
82
|
const length = input.value.length;
|
|
61
83
|
input.setSelectionRange(length, length);
|
|
62
84
|
}, []);
|
|
85
|
+
// The clear button unmounts once the value is gone, so keep focus in the field
|
|
86
|
+
const handleClear = useCallback((evt) => {
|
|
87
|
+
inputRef.current?.focus();
|
|
88
|
+
onClear?.(evt);
|
|
89
|
+
}, [onClear]);
|
|
63
90
|
const handleFocus = useCallback((evt) => {
|
|
64
91
|
setFocused(true);
|
|
65
92
|
onFocus?.(evt);
|
|
@@ -90,7 +117,7 @@ export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props,
|
|
|
90
117
|
}, [onRevealedChange]);
|
|
91
118
|
return (_jsxs("div", { className: clsx(s.Root, className), children: [_jsxs("div", { className: clsx(s.FieldFootprint, {
|
|
92
119
|
[s.HasValue]: hasValue || !!startAdornment,
|
|
93
|
-
}), "data-focused": focused ? "" : undefined, "data-has-value": hasValue ? "" : undefined, "data-invalid": invalid ? "" : undefined, "data-disabled": disabled ? "" : undefined, "data-readonly": readOnly ? "" : undefined, "data-multiline": multiline ? "" : undefined, onMouseDown: handleContainerMouseDown, children: [_jsx("label", { className: s.TypeableLabel, htmlFor: inputId, children: _jsx("div", { className: s.LabelPositioner, children: _jsx("div", { className: s.LabelText, children: label }) }) }), startAdornment && (_jsx("div", { className: s.StartAdornment, children: startAdornment })), multiline ? (_jsx("textarea", { ref: mergeRefs([ref, inputRef]), id: inputId, name: name, rows: rows, className: s.Textarea, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid":
|
|
120
|
+
}), "data-focused": focused ? "" : undefined, "data-has-value": hasValue ? "" : undefined, "data-invalid": invalid ? "" : undefined, "data-disabled": disabled ? "" : undefined, "data-readonly": readOnly ? "" : undefined, "data-multiline": multiline ? "" : undefined, onMouseDown: handleContainerMouseDown, children: [_jsx("label", { className: s.TypeableLabel, htmlFor: inputId, children: _jsx("div", { className: s.LabelPositioner, children: _jsx("div", { className: s.LabelText, children: label }) }) }), startAdornment && (_jsx("div", { className: s.StartAdornment, children: startAdornment })), multiline ? (_jsx("textarea", { ...textareaProps(restProps), ref: mergeRefs([ref, inputRef]), id: inputId, name: name, rows: rows, className: s.Textarea, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur })) : (_jsx("input", { ...restProps, ref: mergeRefs([ref, inputRef]), id: inputId, name: name, type: effectiveType, className: s.Input, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, onAnimationStart: handleAnimationStart, "data-lpignore": allowAutofillExtensions ? undefined : true, "data-1p-ignore": allowAutofillExtensions ? undefined : true })), endAdornment && (_jsx("div", { className: s.EndAdornment, children: endAdornment })), showClearButton && (_jsx("button", { type: "button", "aria-label": "Clear input", className: s.ClearButton, onClick: handleClear, children: _jsx(X, {}) })), showRevealButton && (_jsx("button", { type: "button", "aria-label": revealed ? "Hide" : "Show", className: s.RevealButton, onClick: handleRevealToggle, children: revealed ? _jsx(EyeOff, {}) : _jsx(Eye, {}) }))] }), errorMessage && (_jsx("div", { id: errorId, className: s.ErrorMessage, role: "alert", children: errorMessage })), description && (_jsx("div", { id: descriptionId, className: s.Description, children: description }))] }));
|
|
94
121
|
});
|
|
95
122
|
FloatingLabelInput.displayName = "FloatingLabelInput";
|
|
96
123
|
//# sourceMappingURL=FloatingLabelInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FloatingLabelInput.js","sourceRoot":"","sources":["../../../../src/components/FloatingLabelInput/FloatingLabelInput.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from \"react\"\nimport { mergeRefs } from \"react-merge-refs\"\n\nimport { Eye, EyeOff, X } from \"../Icon\"\n\nimport s from \"./FloatingLabelInput.module.css\"\n\nexport type FloatingLabelInputProps = {\n /**\n * Label text for the floating label\n */\n label: string\n /**\n * Error message to display below the input\n */\n errorMessage?: string\n /**\n * Mark the input as invalid\n * @default false (or true if errorMessage is provided)\n */\n invalid?: boolean\n /**\n * Disables the input visually and from interactions\n * @default false\n */\n disabled?: boolean\n /**\n * Makes the input read-only\n * @default false\n */\n readOnly?: boolean\n /**\n * Callback invoked when the clear button is clicked\n */\n onClear?: () => void\n /**\n * Callback invoked when the input is autofilled by the browser\n */\n onAutofill?: () => void\n /**\n * Allow autofill extensions to appear in the input\n * @default false\n */\n allowAutofillExtensions?: boolean\n /**\n * Helper/description text displayed below the input.\n * Shown alongside the error message when both are present.\n */\n description?: React.ReactNode\n /**\n * Content rendered before the input.\n */\n startAdornment?: React.ReactNode\n /**\n * Content rendered after the input, before the clear button.\n * For password fields the reveal toggle is built in — see `revealable`.\n */\n endAdornment?: React.ReactNode\n /**\n * Render a built-in reveal/hide toggle (eye icon) inside the field.\n * For `type=\"password\"` it swaps the input between `password` and `text`.\n * Defaults to `true` for password inputs that don't supply their own\n * `endAdornment`. Pass it explicitly to add the toggle to other sensitive\n * fields (e.g. a masked SSN) and react to it via `onRevealedChange`.\n * @default true when type=\"password\" and no endAdornment is provided\n */\n revealable?: boolean\n /**\n * Called with the new revealed state each time the reveal toggle is clicked.\n */\n onRevealedChange?: (revealed: boolean) => void\n /**\n * Render as a multi-line textarea instead of a single-line input.\n * @default false\n */\n multiline?: boolean\n /**\n * Number of visible text lines when `multiline` is true.\n * @default 2\n */\n rows?: number\n} & React.InputHTMLAttributes<HTMLInputElement>\n\nexport const FloatingLabelInput = forwardRef<HTMLInputElement, FloatingLabelInputProps>(\n function FloatingLabelInput(props, ref) {\n const {\n label,\n description,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n readOnly = false,\n onClear,\n onAutofill,\n allowAutofillExtensions = false,\n startAdornment,\n endAdornment,\n revealable: revealableProp,\n onRevealedChange,\n multiline = false,\n rows = 2,\n className,\n \"id\": idProp,\n name,\n type = \"text\",\n value,\n defaultValue,\n onChange,\n onFocus,\n onBlur,\n onAnimationStart,\n \"aria-describedby\": ariaDescribedByProp,\n ...restProps\n } = props\n\n const inputRef = useRef<HTMLInputElement | null>(null)\n const generatedId = useId()\n const inputId = idProp || `floating-label-input-${generatedId}`\n const descriptionId = description ? `${inputId}-description` : undefined\n const errorId = errorMessage ? `${inputId}-error` : undefined\n\n const [focused, setFocused] = useState(false)\n const [hasValue, setHasValue] = useState(() => {\n return !!(value !== undefined ? value : defaultValue)\n })\n const [revealed, setRevealed] = useState(false)\n\n // Sync hasValue with controlled value prop\n useEffect(() => {\n if (value !== undefined) {\n setHasValue(!!value)\n }\n }, [value])\n\n const autoResize = useCallback(() => {\n const el = inputRef.current\n if (!multiline || !el) return\n el.style.height = \"auto\"\n el.style.height = `${el.scrollHeight}px`\n }, [multiline])\n\n useLayoutEffect(autoResize, [autoResize])\n\n const invalid = invalidProp ?? !!errorMessage\n\n // Determine if clear button should be shown\n const showClearButton = !!onClear && hasValue && !disabled && !readOnly\n\n // Built-in password reveal toggle\n const isPassword = type === \"password\"\n const revealable = revealableProp ?? (isPassword && !endAdornment)\n const showRevealButton = revealable && !disabled\n const effectiveType = isPassword && revealed ? \"text\" : type\n\n // Merge aria-describedby with error id\n const ariaDescribedBy =\n [ariaDescribedByProp, errorId, descriptionId].filter(Boolean).join(\" \") || undefined\n\n // Handle clicks on the container to focus the input\n const handleContainerMouseDown = useCallback((evt: React.MouseEvent<HTMLDivElement>) => {\n const input = inputRef.current\n if (!evt.target || !(evt.target instanceof Element) || !input) {\n return\n }\n if (input.contains(evt.target)) {\n return\n }\n if (evt.target.closest(\"button, [type='button'], [role='button']\")) {\n return\n }\n evt.preventDefault()\n if (document.activeElement !== input) {\n input.focus()\n }\n const length = input.value.length\n input.setSelectionRange(length, length)\n }, [])\n\n const handleFocus = useCallback(\n (evt: React.FocusEvent<HTMLInputElement>) => {\n setFocused(true)\n onFocus?.(evt)\n },\n [onFocus],\n )\n\n const handleBlur = useCallback(\n (evt: React.FocusEvent<HTMLInputElement>) => {\n setFocused(false)\n onBlur?.(evt)\n },\n [onBlur],\n )\n\n const handleChange = useCallback(\n (evt: React.ChangeEvent<HTMLInputElement>) => {\n setHasValue(!!evt.currentTarget.value)\n onChange?.(evt)\n autoResize()\n },\n [onChange, autoResize],\n )\n\n const handleAnimationStart = useCallback(\n (evt: React.AnimationEvent<HTMLInputElement>) => {\n onAnimationStart?.(evt)\n // Detect browser autofill\n if (evt.animationName === \"native-autofill-in\") {\n setHasValue(true)\n onAutofill?.()\n }\n },\n [onAnimationStart, onAutofill],\n )\n\n const handleRevealToggle = useCallback(() => {\n setRevealed((prev) => {\n const next = !prev\n onRevealedChange?.(next)\n return next\n })\n }, [onRevealedChange])\n\n return (\n <div className={clsx(s.Root, className)}>\n <div\n className={clsx(s.FieldFootprint, {\n [s.HasValue]: hasValue || !!startAdornment,\n })}\n data-focused={focused ? \"\" : undefined}\n data-has-value={hasValue ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n data-disabled={disabled ? \"\" : undefined}\n data-readonly={readOnly ? \"\" : undefined}\n data-multiline={multiline ? \"\" : undefined}\n onMouseDown={handleContainerMouseDown}\n >\n <label className={s.TypeableLabel} htmlFor={inputId}>\n <div className={s.LabelPositioner}>\n <div className={s.LabelText}>{label}</div>\n </div>\n </label>\n {startAdornment && (\n <div className={s.StartAdornment}>{startAdornment}</div>\n )}\n {multiline ? (\n <textarea\n ref={mergeRefs([ref, inputRef]) as React.Ref<HTMLTextAreaElement>}\n id={inputId}\n name={name}\n rows={rows}\n className={s.Textarea}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n onChange={handleChange as unknown as React.ChangeEventHandler<HTMLTextAreaElement>}\n onFocus={handleFocus as unknown as React.FocusEventHandler<HTMLTextAreaElement>}\n onBlur={handleBlur as unknown as React.FocusEventHandler<HTMLTextAreaElement>}\n />\n ) : (\n <input\n {...restProps}\n ref={mergeRefs([ref, inputRef])}\n id={inputId}\n name={name}\n type={effectiveType}\n className={s.Input}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onAnimationStart={handleAnimationStart}\n data-lpignore={allowAutofillExtensions ? undefined : true}\n data-1p-ignore={allowAutofillExtensions ? undefined : true}\n />\n )}\n {endAdornment && (\n <div className={s.EndAdornment}>\n {endAdornment}\n </div>\n )}\n {showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Clear input\"\n className={s.ClearButton}\n onClick={onClear}\n >\n <X />\n </button>\n )}\n {showRevealButton && (\n <button\n type=\"button\"\n aria-label={revealed ? \"Hide\" : \"Show\"}\n className={s.RevealButton}\n onClick={handleRevealToggle}\n >\n {revealed ? <EyeOff /> : <Eye />}\n </button>\n )}\n </div>\n {errorMessage && (\n <div id={errorId} className={s.ErrorMessage} role=\"alert\">\n {errorMessage}\n </div>\n )}\n {description && (\n <div id={descriptionId} className={s.Description}>\n {description}\n </div>\n )}\n </div>\n )\n },\n)\n\nFloatingLabelInput.displayName = \"FloatingLabelInput\"\n"]}
|
|
1
|
+
{"version":3,"file":"FloatingLabelInput.js","sourceRoot":"","sources":["../../../../src/components/FloatingLabelInput/FloatingLabelInput.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from \"react\"\nimport { mergeRefs } from \"react-merge-refs\"\n\nimport { Eye, EyeOff, X } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/FloatingLabelInput/FloatingLabelInput.module.css\"\n\nexport type FloatingLabelInputProps = {\n /**\n * Label text for the floating label\n */\n label: string\n /**\n * Error message to display below the input\n */\n errorMessage?: string\n /**\n * Mark the input as invalid\n * @default false (or true if errorMessage is provided)\n */\n invalid?: boolean\n /**\n * Disables the input visually and from interactions\n * @default false\n */\n disabled?: boolean\n /**\n * Makes the input read-only\n * @default false\n */\n readOnly?: boolean\n /**\n * Callback invoked when the clear button is clicked\n */\n onClear?: () => void\n /**\n * Callback invoked when the input is autofilled by the browser\n */\n onAutofill?: () => void\n /**\n * Allow autofill extensions to appear in the input\n * @default false\n */\n allowAutofillExtensions?: boolean\n /**\n * Helper/description text displayed below the input.\n * Shown alongside the error message when both are present.\n */\n description?: React.ReactNode\n /**\n * Content rendered before the input.\n */\n startAdornment?: React.ReactNode\n /**\n * Content rendered after the input, before the clear button.\n * For password fields the reveal toggle is built in — see `revealable`.\n */\n endAdornment?: React.ReactNode\n /**\n * Render a built-in reveal/hide toggle (eye icon) inside the field.\n * For `type=\"password\"` it swaps the input between `password` and `text`.\n * Defaults to `true` for password inputs that don't supply their own\n * `endAdornment`. Pass it explicitly to add the toggle to other sensitive\n * fields (e.g. a masked SSN) and react to it via `onRevealedChange`.\n * @default true when type=\"password\" and no endAdornment is provided\n */\n revealable?: boolean\n /**\n * Called with the new revealed state each time the reveal toggle is clicked.\n */\n onRevealedChange?: (revealed: boolean) => void\n /**\n * Render as a multi-line textarea instead of a single-line input.\n * @default false\n */\n multiline?: boolean\n /**\n * Number of visible text lines when `multiline` is true.\n * @default 2\n */\n rows?: number\n} & React.InputHTMLAttributes<HTMLInputElement>\n\n// Attributes that only mean something on <input>; everything else (required,\n// maxLength, placeholder, key and clipboard handlers, aria-*, data-*) also\n// applies to the multiline <textarea>\nconst INPUT_ONLY_PROPS = [\n \"accept\", \"alt\", \"capture\", \"checked\", \"height\", \"list\", \"max\", \"min\", \"multiple\",\n \"pattern\", \"size\", \"src\", \"step\", \"width\", \"formAction\", \"formEncType\",\n \"formMethod\", \"formNoValidate\", \"formTarget\",\n] as const\n\nconst textareaProps = (props: Record<string, unknown>) => {\n const rest = { ...props }\n for (const key of INPUT_ONLY_PROPS) delete rest[key]\n return rest\n}\n\nexport const FloatingLabelInput = forwardRef<HTMLInputElement, FloatingLabelInputProps>(\n function FloatingLabelInput(props, ref) {\n const {\n label,\n description,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n readOnly = false,\n onClear,\n onAutofill,\n allowAutofillExtensions = false,\n startAdornment,\n endAdornment,\n revealable: revealableProp,\n onRevealedChange,\n multiline = false,\n rows = 2,\n className,\n \"id\": idProp,\n name,\n type = \"text\",\n value,\n defaultValue,\n onChange,\n onFocus,\n onBlur,\n onAnimationStart,\n \"aria-describedby\": ariaDescribedByProp,\n ...restProps\n } = props\n\n const inputRef = useRef<HTMLInputElement | null>(null)\n const generatedId = useId()\n const inputId = idProp || `floating-label-input-${generatedId}`\n const descriptionId = description ? `${inputId}-description` : undefined\n const errorId = errorMessage ? `${inputId}-error` : undefined\n\n const [focused, setFocused] = useState(false)\n const [hasValue, setHasValue] = useState(() => {\n return !!(value !== undefined ? value : defaultValue)\n })\n const [revealed, setRevealed] = useState(false)\n\n // Sync hasValue with controlled value prop\n useEffect(() => {\n if (value !== undefined) {\n setHasValue(!!value)\n }\n }, [value])\n\n const autoResize = useCallback(() => {\n const el = inputRef.current\n if (!multiline || !el) return\n el.style.height = \"auto\"\n el.style.height = `${el.scrollHeight}px`\n }, [multiline])\n\n // Also resize when a controlled value or rows changes without a keystroke\n useLayoutEffect(() => {\n autoResize()\n }, [autoResize, value, rows])\n\n const invalid = invalidProp ?? !!errorMessage\n\n // Determine if clear button should be shown\n const showClearButton = !!onClear && hasValue && !disabled && !readOnly\n\n // Built-in password reveal toggle\n const isPassword = type === \"password\"\n const revealable = revealableProp ?? (isPassword && !endAdornment)\n const showRevealButton = revealable && !disabled\n const effectiveType = isPassword && revealed ? \"text\" : type\n\n // Merge aria-describedby with error id\n const ariaDescribedBy =\n [ariaDescribedByProp, errorId, descriptionId].filter(Boolean).join(\" \") || undefined\n // An explicit aria-invalid (e.g. from Field) wins over the computed state\n const ariaInvalid = restProps[\"aria-invalid\"] ?? (invalid ? true : undefined)\n\n // Handle clicks on the container to focus the input\n const handleContainerMouseDown = useCallback((evt: React.MouseEvent<HTMLDivElement>) => {\n const input = inputRef.current\n if (!evt.target || !(evt.target instanceof Element) || !input) {\n return\n }\n if (input.contains(evt.target)) {\n return\n }\n if (evt.target.closest(\"button, [type='button'], [role='button']\")) {\n return\n }\n evt.preventDefault()\n if (document.activeElement !== input) {\n input.focus()\n }\n // email, number and other types without the selection API throw on setSelectionRange\n if (input.selectionStart === null) return\n const length = input.value.length\n input.setSelectionRange(length, length)\n }, [])\n\n // The clear button unmounts once the value is gone, so keep focus in the field\n const handleClear = useCallback(\n (evt: React.MouseEvent<HTMLButtonElement>) => {\n inputRef.current?.focus()\n ;(onClear as React.MouseEventHandler<HTMLButtonElement> | undefined)?.(evt)\n },\n [onClear],\n )\n\n const handleFocus = useCallback(\n (evt: React.FocusEvent<HTMLInputElement>) => {\n setFocused(true)\n onFocus?.(evt)\n },\n [onFocus],\n )\n\n const handleBlur = useCallback(\n (evt: React.FocusEvent<HTMLInputElement>) => {\n setFocused(false)\n onBlur?.(evt)\n },\n [onBlur],\n )\n\n const handleChange = useCallback(\n (evt: React.ChangeEvent<HTMLInputElement>) => {\n setHasValue(!!evt.currentTarget.value)\n onChange?.(evt)\n autoResize()\n },\n [onChange, autoResize],\n )\n\n const handleAnimationStart = useCallback(\n (evt: React.AnimationEvent<HTMLInputElement>) => {\n onAnimationStart?.(evt)\n // Detect browser autofill\n if (evt.animationName === \"native-autofill-in\") {\n setHasValue(true)\n onAutofill?.()\n }\n },\n [onAnimationStart, onAutofill],\n )\n\n const handleRevealToggle = useCallback(() => {\n setRevealed((prev) => {\n const next = !prev\n onRevealedChange?.(next)\n return next\n })\n }, [onRevealedChange])\n\n return (\n <div className={clsx(s.Root, className)}>\n <div\n className={clsx(s.FieldFootprint, {\n [s.HasValue]: hasValue || !!startAdornment,\n })}\n data-focused={focused ? \"\" : undefined}\n data-has-value={hasValue ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n data-disabled={disabled ? \"\" : undefined}\n data-readonly={readOnly ? \"\" : undefined}\n data-multiline={multiline ? \"\" : undefined}\n onMouseDown={handleContainerMouseDown}\n >\n <label className={s.TypeableLabel} htmlFor={inputId}>\n <div className={s.LabelPositioner}>\n <div className={s.LabelText}>{label}</div>\n </div>\n </label>\n {startAdornment && (\n <div className={s.StartAdornment}>{startAdornment}</div>\n )}\n {multiline ? (\n <textarea\n {...(textareaProps(restProps) as React.TextareaHTMLAttributes<HTMLTextAreaElement>)}\n ref={mergeRefs([ref, inputRef]) as React.Ref<HTMLTextAreaElement>}\n id={inputId}\n name={name}\n rows={rows}\n className={s.Textarea}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={ariaInvalid}\n aria-describedby={ariaDescribedBy}\n onChange={handleChange as unknown as React.ChangeEventHandler<HTMLTextAreaElement>}\n onFocus={handleFocus as unknown as React.FocusEventHandler<HTMLTextAreaElement>}\n onBlur={handleBlur as unknown as React.FocusEventHandler<HTMLTextAreaElement>}\n />\n ) : (\n <input\n {...restProps}\n ref={mergeRefs([ref, inputRef])}\n id={inputId}\n name={name}\n type={effectiveType}\n className={s.Input}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={ariaInvalid}\n aria-describedby={ariaDescribedBy}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onAnimationStart={handleAnimationStart}\n data-lpignore={allowAutofillExtensions ? undefined : true}\n data-1p-ignore={allowAutofillExtensions ? undefined : true}\n />\n )}\n {endAdornment && (\n <div className={s.EndAdornment}>\n {endAdornment}\n </div>\n )}\n {showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Clear input\"\n className={s.ClearButton}\n onClick={handleClear}\n >\n <X />\n </button>\n )}\n {showRevealButton && (\n <button\n type=\"button\"\n aria-label={revealed ? \"Hide\" : \"Show\"}\n className={s.RevealButton}\n onClick={handleRevealToggle}\n >\n {revealed ? <EyeOff /> : <Eye />}\n </button>\n )}\n </div>\n {errorMessage && (\n <div id={errorId} className={s.ErrorMessage} role=\"alert\">\n {errorMessage}\n </div>\n )}\n {description && (\n <div id={descriptionId} className={s.Description}>\n {description}\n </div>\n )}\n </div>\n )\n },\n)\n\nFloatingLabelInput.displayName = \"FloatingLabelInput\"\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { FloatingLabelInput } from "./FloatingLabelInput";
|
|
1
|
+
export { FloatingLabelInput } from "./FloatingLabelInput.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import clsx from "clsx";
|
|
4
4
|
import { forwardRef, useCallback, useId } from "react";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import s from "./FloatingLabelSelect.module.css";
|
|
5
|
+
import { Button } from "../Button/index.js";
|
|
6
|
+
import { Dropdown, X } from "../Icon/index.js";
|
|
7
|
+
import s from "@plexui/styles/components/FloatingLabelSelect/FloatingLabelSelect.module.css";
|
|
9
8
|
export const FloatingLabelSelect = forwardRef(function FloatingLabelSelect(props, ref) {
|
|
10
9
|
const { label, selected = false, errorMessage, "invalid": invalidProp, disabled = false, open = false, onInteract, onClearClick, children, className, "aria-describedby": ariaDescribedByProp, onKeyDown, ...restProps } = props;
|
|
11
10
|
const generatedId = useId();
|
|
@@ -21,16 +20,33 @@ export const FloatingLabelSelect = forwardRef(function FloatingLabelSelect(props
|
|
|
21
20
|
onInteract?.();
|
|
22
21
|
}, [disabled, onInteract]);
|
|
23
22
|
const handleKeyDown = useCallback((evt) => {
|
|
23
|
+
// Enter and Space on a nested control (the clear button) activate that
|
|
24
|
+
// control: neither this handler nor a wrapping trigger's may take them
|
|
25
|
+
if (evt.target !== evt.currentTarget && (evt.key === " " || evt.key === "Enter"))
|
|
26
|
+
return;
|
|
24
27
|
onKeyDown?.(evt);
|
|
25
|
-
|
|
28
|
+
// A handler that prevented the default (the caller's, or a wrapping
|
|
29
|
+
// Menu.Trigger's that opened its menu) cancels the built-in handling
|
|
30
|
+
if (disabled || evt.defaultPrevented)
|
|
26
31
|
return;
|
|
27
32
|
switch (evt.key) {
|
|
28
33
|
case "ArrowDown":
|
|
29
34
|
case "ArrowUp":
|
|
30
35
|
case " ":
|
|
36
|
+
case "Enter":
|
|
37
|
+
// Enter activates the field only without onInteract, as it
|
|
38
|
+
// would the button a wrapping trigger usually renders
|
|
39
|
+
if (evt.key === "Enter" && onInteract)
|
|
40
|
+
break;
|
|
31
41
|
evt.stopPropagation();
|
|
32
42
|
evt.preventDefault();
|
|
33
|
-
onInteract
|
|
43
|
+
if (onInteract) {
|
|
44
|
+
onInteract();
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// A wrapping trigger (Select's `trigger`, a Popover.Trigger) opens on click
|
|
48
|
+
evt.currentTarget.click();
|
|
49
|
+
}
|
|
34
50
|
break;
|
|
35
51
|
}
|
|
36
52
|
}, [disabled, onInteract, onKeyDown]);
|
|
@@ -42,9 +58,13 @@ export const FloatingLabelSelect = forwardRef(function FloatingLabelSelect(props
|
|
|
42
58
|
evt.preventDefault();
|
|
43
59
|
onClearClick?.();
|
|
44
60
|
}, [onClearClick]);
|
|
45
|
-
return (_jsxs("div", { className: clsx(s.Root, className),
|
|
61
|
+
return (_jsxs("div", { className: clsx(s.Root, className), children: [_jsxs("div", {
|
|
62
|
+
// The ref is the focusable field: a wrapping trigger returns focus to it and anchors to it
|
|
63
|
+
ref: ref, className: clsx(s.FieldFootprint, {
|
|
46
64
|
[s.HasValue]: selected,
|
|
47
|
-
}), role: "button", tabIndex: disabled ? -1 : 0, "data-open": open ? "" : undefined, "data-invalid": invalid ? "" : undefined, "data-disabled": disabled ? "" : undefined, "aria-expanded": open, "aria-haspopup": "listbox", "aria-invalid": invalid ? true : undefined, "aria-describedby": ariaDescribedBy, "aria-disabled": disabled || undefined, onPointerDown: handlePointerDown, onKeyDown: handleKeyDown, ...restProps, children: [_jsx("div", { className: s.TypeableLabel, children: _jsx("div", { className: s.LabelPositioner, children: _jsx("div", { className: s.LabelText, children: label }) }) }), _jsx("span", { className: s.Content, children: selected ? children : null }), _jsxs("div", { className: s.IndicatorWrapper, children: [showClearButton && (_jsx(Button, { "aria-label": "Clear selection", className: s.Clear, onPointerDown: handleClearPointerDown, onClick: handleClearClick, color: "secondary", variant: "ghost", size: "3xs", uniform: true, pill: true, children: _jsx(X, {}) })), _jsx(Dropdown, { className: s.DropdownIcon })] })] }), errorMessage && (
|
|
65
|
+
}), role: "button", tabIndex: disabled ? -1 : 0, "data-open": open ? "" : undefined, "data-invalid": invalid ? "" : undefined, "data-disabled": disabled ? "" : undefined, "aria-expanded": open, "aria-haspopup": "listbox", "aria-invalid": invalid ? true : undefined, "aria-describedby": ariaDescribedBy, "aria-disabled": disabled || undefined, onPointerDown: handlePointerDown, onKeyDown: handleKeyDown, ...restProps, children: [_jsx("div", { className: s.TypeableLabel, children: _jsx("div", { className: s.LabelPositioner, children: _jsx("div", { className: s.LabelText, children: label }) }) }), _jsx("span", { className: s.Content, children: selected ? children : null }), _jsxs("div", { className: s.IndicatorWrapper, children: [showClearButton && (_jsx(Button, { "aria-label": "Clear selection", className: s.Clear, onPointerDown: handleClearPointerDown, onClick: handleClearClick, color: "secondary", variant: "ghost", size: "3xs", uniform: true, pill: true, children: _jsx(X, {}) })), _jsx(Dropdown, { className: s.DropdownIcon })] })] }), errorMessage && (
|
|
66
|
+
// Same plain line as FloatingLabelInput, so the two read alike on one form
|
|
67
|
+
_jsx("div", { id: errorId, className: s.ErrorMessage, role: "alert", children: errorMessage }))] }));
|
|
48
68
|
});
|
|
49
69
|
FloatingLabelSelect.displayName = "FloatingLabelSelect";
|
|
50
70
|
//# sourceMappingURL=FloatingLabelSelect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FloatingLabelSelect.js","sourceRoot":"","sources":["../../../../src/components/FloatingLabelSelect/FloatingLabelSelect.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"FloatingLabelSelect.js","sourceRoot":"","sources":["../../../../src/components/FloatingLabelSelect/FloatingLabelSelect.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,CAAC,MAAM,8EAA8E,CAAA;AAmB5F,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAC3C,SAAS,mBAAmB,CAAC,KAAK,EAAE,GAAG;IACrC,MAAM,EACJ,KAAK,EACL,QAAQ,GAAG,KAAK,EAChB,YAAY,EACZ,SAAS,EAAE,WAAW,EACtB,QAAQ,GAAG,KAAK,EAChB,IAAI,GAAG,KAAK,EACZ,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,kBAAkB,EAAE,mBAAmB,EACvC,SAAS,EACT,GAAG,SAAS,EACb,GAAG,KAAK,CAAA;IAET,MAAM,WAAW,GAAG,KAAK,EAAE,CAAA;IAC3B,MAAM,OAAO,GAAG,yBAAyB,WAAW,QAAQ,CAAA;IAE5D,MAAM,OAAO,GAAG,WAAW,IAAI,CAAC,CAAC,YAAY,CAAA;IAE7C,MAAM,eAAe,GAAG,CAAC,CAAC,YAAY,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAA;IAE/D,MAAM,eAAe,GACnB,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACnF,SAAS,CAAA;IAEX,MAAM,iBAAiB,GAAG,WAAW,CACnC,CAAC,GAAuC,EAAE,EAAE;QAC1C,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ;YAAE,OAAM;QACxC,GAAG,CAAC,cAAc,EAAE,CAAA;QACpB,UAAU,EAAE,EAAE,CAAA;IAChB,CAAC,EACD,CAAC,QAAQ,EAAE,UAAU,CAAC,CACvB,CAAA;IAED,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,GAAwC,EAAE,EAAE;QAC3C,uEAAuE;QACvE,uEAAuE;QACvE,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,aAAa,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,CAAC;YAAE,OAAM;QACxF,SAAS,EAAE,CAAC,GAAG,CAAC,CAAA;QAChB,oEAAoE;QACpE,qEAAqE;QACrE,IAAI,QAAQ,IAAI,GAAG,CAAC,gBAAgB;YAAE,OAAM;QAE5C,QAAQ,GAAG,CAAC,GAAG,EAAE,CAAC;YAChB,KAAK,WAAW,CAAC;YACjB,KAAK,SAAS,CAAC;YACf,KAAK,GAAG,CAAC;YACT,KAAK,OAAO;gBACV,2DAA2D;gBAC3D,sDAAsD;gBACtD,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,IAAI,UAAU;oBAAE,MAAK;gBAC5C,GAAG,CAAC,eAAe,EAAE,CAAA;gBACrB,GAAG,CAAC,cAAc,EAAE,CAAA;gBACpB,IAAI,UAAU,EAAE,CAAC;oBACf,UAAU,EAAE,CAAA;gBACd,CAAC;qBAAM,CAAC;oBACN,4EAA4E;oBAC5E,GAAG,CAAC,aAAa,CAAC,KAAK,EAAE,CAAA;gBAC3B,CAAC;gBACD,MAAK;QACT,CAAC;IACH,CAAC,EACD,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAClC,CAAA;IAED,MAAM,sBAAsB,GAAG,WAAW,CAAC,CAAC,GAA0C,EAAE,EAAE;QACxF,GAAG,CAAC,eAAe,EAAE,CAAA;IACvB,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,gBAAgB,GAAG,WAAW,CAClC,CAAC,GAAwC,EAAE,EAAE;QAC3C,GAAG,CAAC,eAAe,EAAE,CAAA;QACrB,GAAG,CAAC,cAAc,EAAE,CAAA;QACpB,YAAY,EAAE,EAAE,CAAA;IAClB,CAAC,EACD,CAAC,YAAY,CAAC,CACf,CAAA;IAED,OAAO,CACL,eAAK,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,aACrC;gBACE,2FAA2F;gBAC3F,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE;oBAChC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,QAAQ;iBACvB,CAAC,EACF,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAChB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,kBAClB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,mBACvB,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,mBACzB,IAAI,mBACL,SAAS,kBACT,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,sBACtB,eAAe,mBAClB,QAAQ,IAAI,SAAS,EACpC,aAAa,EAAE,iBAAiB,EAChC,SAAS,EAAE,aAAa,KACpB,SAAS,aAEb,cAAK,SAAS,EAAE,CAAC,CAAC,aAAa,YAC7B,cAAK,SAAS,EAAE,CAAC,CAAC,eAAe,YAC/B,cAAK,SAAS,EAAE,CAAC,CAAC,SAAS,YAAG,KAAK,GAAO,GACtC,GACF,EACN,eAAM,SAAS,EAAE,CAAC,CAAC,OAAO,YAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAQ,EAC/D,eAAK,SAAS,EAAE,CAAC,CAAC,gBAAgB,aAC/B,eAAe,IAAI,CAClB,KAAC,MAAM,kBACM,iBAAiB,EAC5B,SAAS,EAAE,CAAC,CAAC,KAAK,EAClB,aAAa,EAAE,sBAAsB,EACrC,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAC,WAAW,EACjB,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,KAAK,EACV,OAAO,QACP,IAAI,kBAEJ,KAAC,CAAC,KAAG,GACE,CACV,EACD,KAAC,QAAQ,IAAC,SAAS,EAAE,CAAC,CAAC,YAAY,GAAI,IACnC,IACF,EACL,YAAY,IAAI;YACf,2EAA2E;YAC3E,cAAK,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,YAAY,EAAE,IAAI,EAAC,OAAO,YACtD,YAAY,GACT,CACP,IACG,CACP,CAAA;AACH,CAAC,CACF,CAAA;AAED,mBAAmB,CAAC,WAAW,GAAG,qBAAqB,CAAA","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { forwardRef, useCallback, useId } from \"react\"\n\nimport { Button } from \"../Button\"\nimport { Dropdown, X } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/FloatingLabelSelect/FloatingLabelSelect.module.css\"\n\nexport type FloatingLabelSelectProps = {\n label: string\n selected?: boolean\n errorMessage?: string\n invalid?: boolean\n disabled?: boolean\n open?: boolean\n onInteract?: () => void\n onClearClick?: () => void\n children?: React.ReactNode\n className?: string\n \"aria-describedby\"?: string\n} & Omit<\n React.HTMLAttributes<HTMLDivElement>,\n \"children\" | \"role\" | \"tabIndex\" | \"aria-describedby\"\n>\n\nexport const FloatingLabelSelect = forwardRef<HTMLDivElement, FloatingLabelSelectProps>(\n function FloatingLabelSelect(props, ref) {\n const {\n label,\n selected = false,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n open = false,\n onInteract,\n onClearClick,\n children,\n className,\n \"aria-describedby\": ariaDescribedByProp,\n onKeyDown,\n ...restProps\n } = props\n\n const generatedId = useId()\n const errorId = `floating-label-select-${generatedId}-error`\n\n const invalid = invalidProp ?? !!errorMessage\n\n const showClearButton = !!onClearClick && selected && !disabled\n\n const ariaDescribedBy =\n [ariaDescribedByProp, errorMessage ? errorId : undefined].filter(Boolean).join(\" \") ||\n undefined\n\n const handlePointerDown = useCallback(\n (evt: React.PointerEvent<HTMLDivElement>) => {\n if (evt.button === 2 || disabled) return\n evt.preventDefault()\n onInteract?.()\n },\n [disabled, onInteract],\n )\n\n const handleKeyDown = useCallback(\n (evt: React.KeyboardEvent<HTMLDivElement>) => {\n // Enter and Space on a nested control (the clear button) activate that\n // control: neither this handler nor a wrapping trigger's may take them\n if (evt.target !== evt.currentTarget && (evt.key === \" \" || evt.key === \"Enter\")) return\n onKeyDown?.(evt)\n // A handler that prevented the default (the caller's, or a wrapping\n // Menu.Trigger's that opened its menu) cancels the built-in handling\n if (disabled || evt.defaultPrevented) return\n\n switch (evt.key) {\n case \"ArrowDown\":\n case \"ArrowUp\":\n case \" \":\n case \"Enter\":\n // Enter activates the field only without onInteract, as it\n // would the button a wrapping trigger usually renders\n if (evt.key === \"Enter\" && onInteract) break\n evt.stopPropagation()\n evt.preventDefault()\n if (onInteract) {\n onInteract()\n } else {\n // A wrapping trigger (Select's `trigger`, a Popover.Trigger) opens on click\n evt.currentTarget.click()\n }\n break\n }\n },\n [disabled, onInteract, onKeyDown],\n )\n\n const handleClearPointerDown = useCallback((evt: React.PointerEvent<HTMLButtonElement>) => {\n evt.stopPropagation()\n }, [])\n\n const handleClearClick = useCallback(\n (evt: React.MouseEvent<HTMLButtonElement>) => {\n evt.stopPropagation()\n evt.preventDefault()\n onClearClick?.()\n },\n [onClearClick],\n )\n\n return (\n <div className={clsx(s.Root, className)}>\n <div\n // The ref is the focusable field: a wrapping trigger returns focus to it and anchors to it\n ref={ref}\n className={clsx(s.FieldFootprint, {\n [s.HasValue]: selected,\n })}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n data-open={open ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n data-disabled={disabled ? \"\" : undefined}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n aria-disabled={disabled || undefined}\n onPointerDown={handlePointerDown}\n onKeyDown={handleKeyDown}\n {...restProps}\n >\n <div className={s.TypeableLabel}>\n <div className={s.LabelPositioner}>\n <div className={s.LabelText}>{label}</div>\n </div>\n </div>\n <span className={s.Content}>{selected ? children : null}</span>\n <div className={s.IndicatorWrapper}>\n {showClearButton && (\n <Button\n aria-label=\"Clear selection\"\n className={s.Clear}\n onPointerDown={handleClearPointerDown}\n onClick={handleClearClick}\n color=\"secondary\"\n variant=\"ghost\"\n size=\"3xs\"\n uniform\n pill\n >\n <X />\n </Button>\n )}\n <Dropdown className={s.DropdownIcon} />\n </div>\n </div>\n {errorMessage && (\n // Same plain line as FloatingLabelInput, so the two read alike on one form\n <div id={errorId} className={s.ErrorMessage} role=\"alert\">\n {errorMessage}\n </div>\n )}\n </div>\n )\n },\n)\n\nFloatingLabelSelect.displayName = \"FloatingLabelSelect\"\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { FloatingLabelSelect } from "./FloatingLabelSelect";
|
|
1
|
+
export { FloatingLabelSelect } from "./FloatingLabelSelect.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
// Icon aliases for backward compatibility
|
|
2
2
|
// Maps old icon names to new icon names
|
|
3
|
-
export { default as ArrowRight } from "./svg/ArrowRightSm";
|
|
4
|
-
export { default as ArrowUpRight } from "./svg/ArrowTopRightSm";
|
|
5
|
-
export { default as ArrowUp } from "./svg/ArrowUpSm";
|
|
6
|
-
export { default as CalendarAlt } from "./svg/Calendar";
|
|
7
|
-
export { default as Check } from "./svg/CheckMd";
|
|
8
|
-
export { default as ChevronDownVector } from "./svg/ChevronDown";
|
|
9
|
-
export { default as ChevronLeft } from "./svg/ChevronLeftMd";
|
|
10
|
-
export { default as ChevronRight } from "./svg/ChevronRightMd";
|
|
11
|
-
export { default as DropdownVector } from "./svg/Dropdown";
|
|
12
|
-
export { default as Documentation } from "./svg/FileDocument";
|
|
13
|
-
export { default as Delete } from "./svg/RemoveTrash";
|
|
14
|
-
export { default as Clear } from "./svg/X";
|
|
15
|
-
export { default as Explore } from "./svg/AllProductsExplore";
|
|
16
|
-
export { default as Workspace } from "./svg/BuildingWorkspace";
|
|
17
|
-
export { default as Mail } from "./svg/Email";
|
|
18
|
-
export { default as Functions } from "./svg/Function";
|
|
19
|
-
export { default as History } from "./svg/HistoryOn";
|
|
20
|
-
export { default as Info } from "./svg/InfoCircle";
|
|
21
|
-
export { default as Wave } from "./svg/PhoneWaves";
|
|
22
|
-
export { default as Trash } from "./svg/RemoveTrash";
|
|
3
|
+
export { default as ArrowRight } from "./svg/ArrowRightSm.js";
|
|
4
|
+
export { default as ArrowUpRight } from "./svg/ArrowTopRightSm.js";
|
|
5
|
+
export { default as ArrowUp } from "./svg/ArrowUpSm.js";
|
|
6
|
+
export { default as CalendarAlt } from "./svg/Calendar.js";
|
|
7
|
+
export { default as Check } from "./svg/CheckMd.js";
|
|
8
|
+
export { default as ChevronDownVector } from "./svg/ChevronDown.js";
|
|
9
|
+
export { default as ChevronLeft } from "./svg/ChevronLeftMd.js";
|
|
10
|
+
export { default as ChevronRight } from "./svg/ChevronRightMd.js";
|
|
11
|
+
export { default as DropdownVector } from "./svg/Dropdown.js";
|
|
12
|
+
export { default as Documentation } from "./svg/FileDocument.js";
|
|
13
|
+
export { default as Delete } from "./svg/RemoveTrash.js";
|
|
14
|
+
export { default as Clear } from "./svg/X.js";
|
|
15
|
+
export { default as Explore } from "./svg/AllProductsExplore.js";
|
|
16
|
+
export { default as Workspace } from "./svg/BuildingWorkspace.js";
|
|
17
|
+
export { default as Mail } from "./svg/Email.js";
|
|
18
|
+
export { default as Functions } from "./svg/Function.js";
|
|
19
|
+
export { default as History } from "./svg/HistoryOn.js";
|
|
20
|
+
export { default as Info } from "./svg/InfoCircle.js";
|
|
21
|
+
export { default as Wave } from "./svg/PhoneWaves.js";
|
|
22
|
+
export { default as Trash } from "./svg/RemoveTrash.js";
|
|
23
23
|
// Note: Beta icon is not available in new set - uses need to be replaced manually
|
|
24
24
|
// IconName is a TypeScript type, not an actual icon export
|
|
25
25
|
//# sourceMappingURL=aliases.js.map
|