@flikk/ui 1.0.0-beta.30 → 1.0.0-beta.31
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/CHANGELOG.md +97 -0
- package/dist/components/ai/AgentStatus/AgentStatus.d.ts +3 -0
- package/dist/components/ai/AgentStatus/AgentStatus.js +144 -0
- package/dist/components/ai/AgentStatus/AgentStatus.theme.d.ts +2 -0
- package/dist/components/ai/AgentStatus/AgentStatus.theme.js +37 -0
- package/dist/components/ai/AgentStatus/AgentStatus.types.d.ts +116 -0
- package/dist/components/ai/AgentStatus/index.d.ts +3 -0
- package/dist/components/ai/CodeBlock/CodeBlock.js +3 -3
- package/dist/components/ai/CodeBlock/CodeBlock.theme.js +1 -1
- package/dist/components/ai/PromptInput/PromptInput.js +13 -14
- package/dist/components/ai/PromptInput/PromptInput.theme.js +1 -1
- package/dist/components/ai/PromptInput/VoiceRecorder.js +3 -3
- package/dist/components/ai/Reasoning/Reasoning.d.ts +5 -0
- package/dist/components/ai/Reasoning/Reasoning.js +16 -0
- package/dist/components/ai/Reasoning/Reasoning.types.d.ts +20 -0
- package/dist/components/ai/Reasoning/index.d.ts +2 -0
- package/dist/components/ai/SourceCitation/SourceCitation.d.ts +4 -0
- package/dist/components/ai/SourceCitation/SourceCitation.js +29 -0
- package/dist/components/ai/SourceCitation/SourceCitation.theme.d.ts +2 -0
- package/dist/components/ai/SourceCitation/SourceCitation.theme.js +23 -0
- package/dist/components/ai/SourceCitation/SourceCitation.types.d.ts +55 -0
- package/dist/components/ai/SourceCitation/index.d.ts +3 -0
- package/dist/components/ai/StreamingResponse/ErrorDisplay.js +2 -2
- package/dist/components/ai/StreamingResponse/StreamingResponse.js +1 -3
- package/dist/components/ai/StreamingResponse/StreamingResponse.theme.js +3 -1
- package/dist/components/ai/TokenCounter/TokenCounter.js +2 -2
- package/dist/components/ai/index.d.ts +3 -0
- package/dist/components/ai/index.js +6 -3
- package/dist/components/ai/shared/StatusIndicator.d.ts +8 -0
- package/dist/components/ai/shared/StatusIndicator.js +34 -0
- package/dist/components/canvas/CanvasToolbar.js +2 -2
- package/dist/components/canvas/NodeControls.js +2 -2
- package/dist/components/canvas/NodeRenderer.js +2 -2
- package/dist/components/charts/ActivityRings/ActivityRings.js +2 -2
- package/dist/components/charts/AreaChart/AreaChart.js +21 -32
- package/dist/components/charts/AreaChart/AreaChart.theme.d.ts +1 -6
- package/dist/components/charts/AreaChart/AreaChart.theme.js +7 -19
- package/dist/components/charts/AreaChart/AreaChart.types.d.ts +18 -11
- package/dist/components/charts/AreaChart/AreaChart.types.js +10 -3
- package/dist/components/charts/AreaChart/index.d.ts +1 -1
- package/dist/components/charts/BarChart/BarChart.js +9 -28
- package/dist/components/charts/BarChart/BarChart.types.d.ts +20 -16
- package/dist/components/charts/BarChart/BarChart.types.js +11 -4
- package/dist/components/charts/ComboChart/BarRenderer.js +8 -5
- package/dist/components/charts/ComboChart/ComboChart.js +11 -24
- package/dist/components/charts/ComboChart/ComboChart.types.d.ts +15 -13
- package/dist/components/charts/ComboChart/ComboChart.types.js +14 -2
- package/dist/components/charts/ComboChart/LineRenderer.js +15 -10
- package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.d.ts +16 -0
- package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.js +237 -0
- package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.types.d.ts +62 -0
- package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.types.js +21 -0
- package/dist/components/charts/HorizontalBarChart/index.d.ts +3 -0
- package/dist/components/charts/LineChart/LineChart.js +9 -26
- package/dist/components/charts/LineChart/LineChart.types.d.ts +11 -14
- package/dist/components/charts/LineChart/LineChart.types.js +11 -3
- package/dist/components/charts/LollipopChart/LollipopChart.d.ts +3 -0
- package/dist/components/charts/LollipopChart/LollipopChart.js +361 -0
- package/dist/components/charts/LollipopChart/LollipopChart.types.d.ts +42 -0
- package/dist/components/charts/LollipopChart/LollipopChart.types.js +12 -0
- package/dist/components/charts/LollipopChart/index.d.ts +3 -0
- package/dist/components/charts/ScatterPlot/ScatterPlot.js +5 -4
- package/dist/components/charts/ScatterPlot/ScatterPlot.types.d.ts +14 -19
- package/dist/components/charts/ScatterPlot/ScatterPlot.types.js +9 -2
- package/dist/components/charts/StackedBarChart/StackedBarChart.js +150 -132
- package/dist/components/charts/StackedBarChart/StackedBarChart.types.d.ts +20 -18
- package/dist/components/charts/StackedBarChart/StackedBarChart.types.js +10 -4
- package/dist/components/charts/hooks/useChartAccessibility.d.ts +1 -1
- package/dist/components/charts/hooks/useChartAccessibility.js +3 -0
- package/dist/components/charts/hooks/useTooltipPosition.js +18 -6
- package/dist/components/charts/index.d.ts +6 -0
- package/dist/components/charts/index.js +6 -0
- package/dist/components/charts/shared/ChartAxis/CategoryYAxis.d.ts +14 -0
- package/dist/components/charts/shared/ChartAxis/CategoryYAxis.js +35 -0
- package/dist/components/charts/shared/ChartAxis/ChartAxis.types.d.ts +69 -8
- package/dist/components/charts/shared/ChartAxis/ValueXAxis.d.ts +14 -0
- package/dist/components/charts/shared/ChartAxis/ValueXAxis.js +64 -0
- package/dist/components/charts/shared/ChartAxis/XAxis.js +1 -1
- package/dist/components/charts/shared/ChartAxis/YAxis.js +2 -2
- package/dist/components/charts/shared/ChartAxis/index.d.ts +3 -1
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.d.ts +0 -2
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +1 -1
- package/dist/components/charts/shared/ChartGrid/VerticalGrid.d.ts +29 -0
- package/dist/components/charts/shared/ChartGrid/VerticalGrid.js +26 -0
- package/dist/components/charts/shared/ChartGrid/index.d.ts +2 -0
- package/dist/components/charts/shared/ChartMarker/ChartMarker.js +7 -1
- package/dist/components/charts/theme/chart.theme.js +18 -23
- package/dist/components/charts/types/chart.types.d.ts +9 -5
- package/dist/components/charts/types/chart.types.js +1 -7
- package/dist/components/charts/utils/animation-utils.js +1 -3
- package/dist/components/charts/utils/bar-emphasis.d.ts +32 -3
- package/dist/components/charts/utils/bar-emphasis.js +24 -8
- package/dist/components/charts/utils/index.d.ts +1 -0
- package/dist/components/charts/utils/series-color.d.ts +7 -0
- package/dist/components/charts/utils/series-color.js +20 -0
- package/dist/components/core/Accordion/Accordion.theme.js +2 -2
- package/dist/components/core/Accordion/AccordionTrigger.js +2 -2
- package/dist/components/core/Alert/Alert.animations.d.ts +2 -1
- package/dist/components/core/Alert/Alert.animations.js +21 -6
- package/dist/components/core/Alert/Alert.js +7 -7
- package/dist/components/core/Avatar/Avatar.js +50 -42
- package/dist/components/core/Avatar/Avatar.theme.d.ts +8 -4
- package/dist/components/core/Avatar/Avatar.theme.js +64 -8
- package/dist/components/core/Avatar/Avatar.types.d.ts +13 -2
- package/dist/components/core/Avatar/index.d.ts +1 -1
- package/dist/components/core/AvatarGroup/AvatarGroup.js +6 -8
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.d.ts +1 -2
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +2 -6
- package/dist/components/core/AvatarGroup/AvatarGroup.types.d.ts +0 -6
- package/dist/components/core/AvatarGroup/index.d.ts +1 -1
- package/dist/components/core/Badge/Badge.animations.js +4 -2
- package/dist/components/core/Badge/Badge.js +9 -4
- package/dist/components/core/Badge/Badge.theme.js +18 -12
- package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.d.ts +1 -4
- package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +2 -2
- package/dist/components/core/Button/Button.js +9 -17
- package/dist/components/core/Button/Button.ripple.js +2 -2
- package/dist/components/core/Button/Button.theme.d.ts +2 -0
- package/dist/components/core/Button/Button.theme.js +34 -21
- package/dist/components/core/Button/Button.types.d.ts +18 -1
- package/dist/components/core/Calendar/Calendar.js +20 -5
- package/dist/components/core/Calendar/Calendar.theme.js +14 -22
- package/dist/components/core/Calendar/Calendar.types.d.ts +0 -1
- package/dist/components/core/Calendar/CalendarMini/CalendarMini.js +3 -3
- package/dist/components/core/Card/Card.theme.js +12 -4
- package/dist/components/core/Card/CardBody.js +1 -1
- package/dist/components/core/Card/CardFooter.js +1 -1
- package/dist/components/core/Card/CardHeader.js +1 -1
- package/dist/components/core/Carousel/CarouselNext.js +2 -2
- package/dist/components/core/Carousel/CarouselPrevious.js +2 -2
- package/dist/components/core/CommandPalette/CommandPalette.js +5 -4
- package/dist/components/core/CommandPalette/CommandPalette.theme.js +3 -7
- package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +2 -0
- package/dist/components/core/ContextMenu/ContextMenuItem.js +2 -2
- package/dist/components/core/ContextMenu/ContextMenuSubTrigger.js +2 -2
- package/dist/components/core/Drawer/Drawer.theme.js +7 -4
- package/dist/components/core/Drawer/DrawerHeader.js +2 -2
- package/dist/components/core/Dropdown/Dropdown.theme.js +3 -1
- package/dist/components/core/Dropdown/DropdownItem.js +2 -2
- package/dist/components/core/Dropdown/DropdownTrigger.js +16 -5
- package/dist/components/core/HeroCard/HeroCard.theme.js +5 -2
- package/dist/components/core/Kbd/Kbd.theme.js +4 -2
- package/dist/components/core/Link/Link.js +6 -4
- package/dist/components/core/Message/Message.js +2 -2
- package/dist/components/core/Message/Message.theme.js +5 -7
- package/dist/components/core/Message/MessageAudio.js +2 -2
- package/dist/components/core/Message/MessageFile.js +2 -2
- package/dist/components/core/Message/MessageLink.js +2 -2
- package/dist/components/core/Message/MessageStatusIndicator.js +5 -5
- package/dist/components/core/Modal/Modal.d.ts +1 -1
- package/dist/components/core/Modal/Modal.js +2 -2
- package/dist/components/core/Modal/Modal.theme.js +9 -4
- package/dist/components/core/Modal/ModalHeader.js +2 -2
- package/dist/components/core/ModalStack/ModalStackModal.js +2 -2
- package/dist/components/core/NavItem/NavItem.js +6 -6
- package/dist/components/core/OfflineIndicator/OfflineIndicator.animations.d.ts +22 -0
- package/dist/components/core/OfflineIndicator/OfflineIndicator.animations.js +54 -0
- package/dist/components/core/OfflineIndicator/OfflineIndicator.js +23 -24
- package/dist/components/core/OfflineIndicator/OfflineIndicator.theme.js +25 -6
- package/dist/components/core/OfflineIndicator/OfflineIndicator.types.d.ts +17 -0
- package/dist/components/core/PageHeading/PageHeading.theme.js +1 -1
- package/dist/components/core/PageHeading/PageHeadingBackButton.js +2 -2
- package/dist/components/core/Pagination/Pagination.js +3 -3
- package/dist/components/core/Pagination/Pagination.theme.js +3 -3
- package/dist/components/core/Pill/Pill.js +4 -2
- package/dist/components/core/Pill/Pill.theme.js +6 -4
- package/dist/components/core/Rating/Rating.js +4 -5
- package/dist/components/core/Rating/Rating.theme.js +1 -1
- package/dist/components/core/Segmented/Segmented.theme.js +9 -6
- package/dist/components/core/Sidebar/Sidebar.types.d.ts +4 -2
- package/dist/components/core/Sidebar/SidebarHeader.js +2 -2
- package/dist/components/core/Sidebar/SidebarMobileTrigger.js +2 -2
- package/dist/components/core/Sidebar/SidebarSearch.js +3 -3
- package/dist/components/core/Sidebar/SidebarToggle.js +3 -3
- package/dist/components/core/Sidebar/SidebarUserProfile.js +2 -2
- package/dist/components/core/Sortable/Sortable.js +2 -2
- package/dist/components/core/Tag/Tag.js +2 -2
- package/dist/components/core/Tag/Tag.theme.js +4 -2
- package/dist/components/core/Toast/Toast.js +3 -3
- package/dist/components/core/Toast/Toast.types.d.ts +1 -1
- package/dist/components/core/Toast/useToast.js +5 -5
- package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/core/Tooltip/Tooltip.js +42 -10
- package/dist/components/core/Tooltip/Tooltip.types.d.ts +25 -0
- package/dist/components/core/Tree/Tree.js +2 -2
- package/dist/components/core/shared/interaction.animations.d.ts +51 -0
- package/dist/components/core/shared/interaction.animations.js +59 -0
- package/dist/components/data-display/Feed/Feed.js +2 -2
- package/dist/components/data-display/GanttChart/GanttChart.theme.js +1 -1
- package/dist/components/data-display/GanttChart/GanttChartPanel.js +2 -2
- package/dist/components/data-display/GanttChart/GanttTableGroupRow.js +3 -3
- package/dist/components/data-display/GanttChart/GanttTaskContextMenu.js +2 -2
- package/dist/components/data-display/GanttChart/GanttToolbar.js +2 -2
- package/dist/components/data-display/KPI/KPI.js +2 -2
- package/dist/components/data-display/KPI/KPI.theme.js +4 -4
- package/dist/components/data-display/Metric/Metric.js +2 -2
- package/dist/components/data-display/Metric/Metric.theme.js +25 -8
- package/dist/components/data-display/Metric/Metric.types.d.ts +1 -1
- package/dist/components/data-display/Table/Table.theme.js +9 -9
- package/dist/components/data-display/Table/TableActions.js +2 -2
- package/dist/components/data-display/Table/TableActionsMenu.js +1 -1
- package/dist/components/data-display/Table/TableColumnManager.js +2 -2
- package/dist/components/data-display/Table/TableDeclarative.js +3 -3
- package/dist/components/data-display/Table/TableFilter.js +4 -4
- package/dist/components/data-display/Table/TableHeader.js +3 -3
- package/dist/components/data-display/Table/TableRow.js +2 -2
- package/dist/components/data-display/Table/TableSelectionHeader.js +3 -3
- package/dist/components/data-display/Timeline/TimelineMarker.js +2 -2
- package/dist/components/effects/CustomCursor/CustomCursor.js +2 -2
- package/dist/components/effects/CustomCursor/CustomCursor.theme.js +2 -2
- package/dist/components/effects/DotPattern/DotPattern.js +6 -0
- package/dist/components/effects/DotPattern/DotPattern.types.d.ts +4 -2
- package/dist/components/effects/MeshGradient/MeshGradient.utils.d.ts +1 -1
- package/dist/components/effects/MeshGradient/MeshGradient.utils.js +1 -1
- package/dist/components/forms/Checkbox/Checkbox.js +2 -1
- package/dist/components/forms/Checkbox/Checkbox.theme.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerEyeDropper.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerGradient.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerHeader.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerImage.js +3 -3
- package/dist/components/forms/ColorPicker/ColorPickerInput.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerPresets.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerSavedColors.js +2 -2
- package/dist/components/forms/Combobox/Combobox.js +3 -3
- package/dist/components/forms/Combobox/Combobox.theme.js +2 -2
- package/dist/components/forms/DatePicker/DatePicker.animations.js +16 -25
- package/dist/components/forms/DatePicker/DatePicker.theme.js +2 -2
- package/dist/components/forms/DatePicker/DatePickerBody.js +1 -1
- package/dist/components/forms/DatePicker/DatePickerTrigger.js +2 -2
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +3 -3
- package/dist/components/forms/DateRangePicker/DateRangePickerBody.js +1 -1
- package/dist/components/forms/DateRangePicker/DateRangePickerPresets.js +2 -2
- package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +2 -2
- package/dist/components/forms/FileUpload/FileUpload.js +4 -4
- package/dist/components/forms/FileUpload/FileUpload.theme.js +5 -1
- package/dist/components/forms/FileUpload/FileUploadProgress.js +7 -7
- package/dist/components/forms/Input/Input.js +6 -7
- package/dist/components/forms/Input/Input.theme.js +19 -15
- package/dist/components/forms/InputAddress/InputAddress.js +10 -3
- package/dist/components/forms/InputCounter/InputCounter.js +3 -3
- package/dist/components/forms/InputOTP/InputOTP.d.ts +3 -12
- package/dist/components/forms/InputOTP/InputOTP.js +140 -151
- package/dist/components/forms/InputOTP/InputOTP.theme.d.ts +5 -1
- package/dist/components/forms/InputOTP/InputOTP.theme.js +40 -5
- package/dist/components/forms/InputOTP/InputOTP.types.d.ts +45 -2
- package/dist/components/forms/InputOTP/index.d.ts +1 -1
- package/dist/components/forms/InputTag/InputTag.js +5 -5
- package/dist/components/forms/InputTag/InputTag.theme.js +1 -2
- package/dist/components/forms/Mention/Mention.theme.js +3 -5
- package/dist/components/forms/Radio/Radio.js +3 -2
- package/dist/components/forms/Radio/Radio.theme.js +2 -2
- package/dist/components/forms/RichTextEditor/RichTextEditor.js +22 -23
- package/dist/components/forms/Select/Select.d.ts +5 -1
- package/dist/components/forms/Select/Select.js +12 -11
- package/dist/components/forms/Select/Select.theme.js +4 -4
- package/dist/components/forms/Select/Select.types.d.ts +4 -1
- package/dist/components/forms/SelectableCard/SelectableCard.animations.d.ts +1 -2
- package/dist/components/forms/SelectableCard/SelectableCard.animations.js +6 -7
- package/dist/components/forms/SelectableCard/SelectableCard.js +1 -1
- package/dist/components/forms/Signature/Signature.js +1 -1
- package/dist/components/forms/Slider/Slider.js +24 -11
- package/dist/components/forms/Slider/Slider.theme.js +9 -3
- package/dist/components/forms/Switch/Switch.theme.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +6 -7
- package/dist/components/forms/TimePicker/TimePickerContent.js +1 -1
- package/dist/components/forms/TimePicker/TimePickerTrigger.js +3 -3
- package/dist/components/forms/forms.theme.js +23 -12
- package/dist/components/forms/index.js +1 -1
- package/dist/components/generative/registry.js +195 -2
- package/dist/components/generative/resolvers.js +16 -16
- package/dist/components/generative/schema.generated.js +2687 -379
- package/dist/components/layout/Section/Section.theme.js +1 -1
- package/dist/generative.schema.json +2687 -379
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/useElapsedTime.d.ts +28 -0
- package/dist/hooks/useElapsedTime.js +37 -0
- package/dist/hooks/useSelectPortal.d.ts +10 -2
- package/dist/hooks/useSelectPortal.js +6 -3
- package/dist/index.js +1 -1
- package/dist/registry.json +835 -261
- package/dist/shadcn-compat.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/theme.css +5 -1
- package/dist/themes/ember.css +131 -0
- package/dist/themes/iris.css +94 -0
- package/dist/themes/jade.css +139 -0
- package/dist/tools.json +2705 -361
- package/dist/utils/colorUtils.d.ts +6 -6
- package/dist/utils/colorUtils.js +8 -8
- package/package.json +9 -6
- package/src/global.scss +15 -4
- package/src/styles/theme.css +440 -152
- package/tailwind.preset.cjs +52 -34
- package/dist/components/core/Pill/Pill.animations.d.ts +0 -32
- package/dist/components/core/Pill/Pill.animations.js +0 -16
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useContext } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { Check } from '@phosphor-icons/react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { ColorPickerContext } from './ColorPickerContext.js';
|
|
7
7
|
import { parseColor } from './colorUtils.js';
|
|
@@ -50,7 +50,7 @@ const ColorPickerPresets = ({ colors: customColors, label = 'Preset colors', cla
|
|
|
50
50
|
backgroundSize: '8px 8px',
|
|
51
51
|
} }), jsx("div", { className: "absolute inset-0 rounded", style: {
|
|
52
52
|
backgroundColor: presetColor,
|
|
53
|
-
} }), selected && (jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsx(
|
|
53
|
+
} }), selected && (jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsx(Check, { className: "size-3.5 text-white drop-shadow-[0_1px_2px_rgba(0,0,0,0.5)]" }) }))] }, `${presetColor}-${index}`));
|
|
54
54
|
}) })] }));
|
|
55
55
|
};
|
|
56
56
|
ColorPickerPresets.displayName = 'ColorPickerPresets';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import {
|
|
3
|
+
import { Plus } from '@phosphor-icons/react';
|
|
4
4
|
import { useContext } from 'react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { Button } from '../../core/Button/Button.js';
|
|
@@ -53,7 +53,7 @@ const ColorPickerSavedColors = ({ label = 'Saved', maxColors = 16, className, ..
|
|
|
53
53
|
const handleDoubleClick = (index) => {
|
|
54
54
|
removeSavedColor(index);
|
|
55
55
|
};
|
|
56
|
-
return (jsxs("div", { className: cn(className), ...props, children: [jsxs("div", { className: "flex items-center justify-between mb-2", children: [label !== false && (jsx("span", { className: "text-sm font-medium text-[var(--color-text-primary)]", children: label })), savedColors.length < maxColors && (jsxs(Button, { variant: "ghost", size: "sm", color: "
|
|
56
|
+
return (jsxs("div", { className: cn(className), ...props, children: [jsxs("div", { className: "flex items-center justify-between mb-2", children: [label !== false && (jsx("span", { className: "text-sm font-medium text-[var(--color-text-primary)]", children: label })), savedColors.length < maxColors && (jsxs(Button, { variant: "ghost", size: "sm", color: "mono", onClick: handleSaveColor, "aria-label": "Save current color", className: "!px-2 !py-1 !text-sm !font-medium", children: [jsx(Plus, { className: "size-4" }), "Add"] }))] }), savedColors.length > 0 && (jsx("div", { className: "flex items-center gap-2 flex-wrap", children: savedColors.map((colorValue, index) => {
|
|
57
57
|
const gradient = isGradientValue(colorValue);
|
|
58
58
|
const selected = isSelected(colorValue);
|
|
59
59
|
return (jsx("button", { type: "button", tabIndex: 0, onClick: () => handleSelectColor(colorValue), onDoubleClick: () => handleDoubleClick(index), onKeyDown: (e) => handleKeyDown(e, colorValue), className: cn('size-7 rounded-full cursor-pointer transition-all flex-shrink-0', 'hover:scale-110 focus:outline-none', selected
|
|
@@ -3,7 +3,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
3
3
|
import React__default, { useId, useRef, useState, useEffect, useCallback } from 'react';
|
|
4
4
|
import { AnimatePresence, motion } from 'motion/react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
|
-
import {
|
|
6
|
+
import { X, Plus, Check } from '@phosphor-icons/react';
|
|
7
7
|
import { comboboxTheme } from './Combobox.theme.js';
|
|
8
8
|
import { FormLabel } from '../FormLabel/FormLabel.js';
|
|
9
9
|
import { createDropdownAnimations } from '../Select/Select.animations.js';
|
|
@@ -104,7 +104,7 @@ const ComboboxOptions = ({ isOpen, onClose, triggerRef, portal, placement, offse
|
|
|
104
104
|
selectOption(option.value, isCreateOption);
|
|
105
105
|
onClose();
|
|
106
106
|
}
|
|
107
|
-
}, children: [isCreateOption ? (jsxs("span", { className: "flex items-center gap-1", children: [jsx(
|
|
107
|
+
}, children: [isCreateOption ? (jsxs("span", { className: "flex items-center gap-1", children: [jsx(Plus, { className: "size-4 shrink-0", weight: "bold" }), jsx("span", { className: "block truncate", children: option.label })] })) : (jsx("span", { className: "block truncate", children: option.label })), isSelected && !isCreateOption && (jsx("span", { className: "absolute inset-y-0 right-0 flex items-center pr-3 text-[var(--color-primary)] dark:text-[var(--color-primary-400)]", children: jsx(Check, { className: "size-4", weight: "bold" }) }))] }, option.id));
|
|
108
108
|
}), filteredOptions.length > 100 && (jsxs("div", { className: "px-3 py-2 text-xs text-[var(--color-text-muted)] text-center border-t border-[var(--color-border)]", children: ["Showing 100 of ", filteredOptions.length, " results \u2014 refine your search"] }))] })) }) })) }));
|
|
109
109
|
if (portal && isClient) {
|
|
110
110
|
return createPortal(jsx("div", { "data-flikkui-portal": "", className: isDarkMode ? "dark" : undefined, children: optionsContent }), document.body);
|
|
@@ -414,7 +414,7 @@ const ComboboxInner = ({ options, value, onChange, placeholder = "Search...", la
|
|
|
414
414
|
return (jsx(SelectProvider, { selectState: modifiedSelectState, size: size, componentState: state, theme: theme, searchable: true, enableTypeahead: false, children: jsxs("div", { ref: ref, className: cn("relative", containerClasses, stateClass, wrapperClassName), ...props, children: [label && (typeof label === 'string' ? (jsx(FormLabel, { htmlFor: comboboxId, state: state, required: required, children: label })) : (label)), jsxs("div", { ref: wrapperRef, className: theme.wrapperStyle, children: [jsx("div", { className: cn(inputGroupClasses, stateClasses, className), children: jsxs("div", { className: "relative flex-1", children: [jsx("input", { ref: inputRef, id: comboboxId, type: "text", role: "combobox", "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-controls": listboxId, "aria-activedescendant": highlightedIndex >= 0 &&
|
|
415
415
|
customFilteredOptions[highlightedIndex]
|
|
416
416
|
? `${comboboxId}-option-${customFilteredOptions[highlightedIndex].id}`
|
|
417
|
-
: undefined, "aria-autocomplete": "list", "aria-invalid": isInvalid, "aria-describedby": helperText ? `${comboboxId}-helper` : undefined, autoComplete: "off", className: cn(inputClasses, sizeClasses, iconStartPadding, (hasRightIcon || showClearButton) && iconEndPadding, showClearButton && "pr-8", inputClassName), value: searchValue, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: isDisabled, required: required }), hasLeftIcon && (jsx("div", { className: theme.iconStartStyle, children: iconStart })), showClearButton && (jsx("button", { type: "button", className: theme.clearButtonStyle, onClick: handleClear, "aria-label": "Clear selection", tabIndex: -1, children: jsx(
|
|
417
|
+
: undefined, "aria-autocomplete": "list", "aria-invalid": isInvalid, "aria-describedby": helperText ? `${comboboxId}-helper` : undefined, autoComplete: "off", className: cn(inputClasses, sizeClasses, iconStartPadding, (hasRightIcon || showClearButton) && iconEndPadding, showClearButton && "pr-8", inputClassName), value: searchValue, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: isDisabled, required: required }), hasLeftIcon && (jsx("div", { className: theme.iconStartStyle, children: iconStart })), showClearButton && (jsx("button", { type: "button", className: theme.clearButtonStyle, onClick: handleClear, "aria-label": "Clear selection", tabIndex: -1, children: jsx(X, { className: theme.clearIconStyle }) })), hasRightIcon && !showClearButton && (jsx("div", { className: theme.iconEndStyle, children: iconEnd }))] }) }), jsx(ComboboxOptions, { isOpen: isOpen, onClose: () => setIsOpen(false), triggerRef: wrapperRef, portal: portal, placement: placement, offset: offset, emptyMessage: emptyMessage, className: dropdownClassName, listboxId: listboxId, comboboxId: comboboxId, elevation: elevation, lift: lift })] }), helperText && (typeof helperText === 'string' ? (jsx("p", { id: `${comboboxId}-helper`, className: cn(helperTextClasses, helperTextStateClasses), children: helperText })) : (helperText)), name && (jsx("input", { type: "hidden", name: name, value: value !== undefined ? String(value) : "" }))] }) }));
|
|
418
418
|
};
|
|
419
419
|
const ComboboxForwarded = React__default.forwardRef(ComboboxInner);
|
|
420
420
|
ComboboxForwarded.displayName = "Combobox";
|
|
@@ -35,8 +35,8 @@ const comboboxTheme = {
|
|
|
35
35
|
clearButtonStyle: "absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer " +
|
|
36
36
|
"text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] transition-colors z-10",
|
|
37
37
|
clearIconStyle: "size-4",
|
|
38
|
-
// Dropdown styles -
|
|
39
|
-
dropdownStyle: formsBaseTheme.dropdownStyles.container
|
|
38
|
+
// Dropdown styles - the shared base carries the whole listbox treatment
|
|
39
|
+
dropdownStyle: formsBaseTheme.dropdownStyles.container,
|
|
40
40
|
// Individual option style
|
|
41
41
|
optionStyle: formsBaseTheme.dropdownStyles.option,
|
|
42
42
|
// Selected option style
|
|
@@ -1,34 +1,25 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import '../../../theme/ThemeContext.js';
|
|
3
|
+
import '../../../theme/SurfaceContext.js';
|
|
4
|
+
import { getOverlayMenuVariants } from '../../../theme/animations.js';
|
|
5
|
+
|
|
2
6
|
/**
|
|
3
7
|
* Creates direction-aware dropdown animation variants for the DatePicker component
|
|
4
8
|
* Matches Select component animation pattern for consistency
|
|
5
9
|
* @param isFlipped - Whether the dropdown is positioned above (flipped) or below the trigger
|
|
6
10
|
* @returns Animation variants that match the positioning direction
|
|
7
11
|
*/
|
|
8
|
-
const createDropdownAnimations = (isFlipped) =>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
ease: 'easeOut'
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
exit: {
|
|
24
|
-
opacity: 0,
|
|
25
|
-
y: isFlipped ? 10 : -10, // Exit in same direction as entry
|
|
26
|
-
scale: 0.95,
|
|
27
|
-
transition: {
|
|
28
|
-
duration: 0.15,
|
|
29
|
-
ease: 'easeIn'
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
});
|
|
12
|
+
const createDropdownAnimations = (isFlipped) => {
|
|
13
|
+
const side = isFlipped ? 'top' : 'bottom';
|
|
14
|
+
return getOverlayMenuVariants(side, {
|
|
15
|
+
scale: 0.97,
|
|
16
|
+
shift: 6,
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Default dropdown animation variants for backward compatibility
|
|
21
|
+
* @deprecated Use createDropdownAnimations() for better UX with direction awareness
|
|
22
|
+
*/
|
|
23
|
+
createDropdownAnimations(false);
|
|
33
24
|
|
|
34
25
|
export { createDropdownAnimations };
|
|
@@ -38,8 +38,8 @@ const datePickerTheme = {
|
|
|
38
38
|
"data-[active=true]:bg-[var(--color-surface)] data-[active=true]:text-[var(--color-text-primary)] data-[active=true]:font-medium",
|
|
39
39
|
helperTextStyle: formsBaseTheme.helperText,
|
|
40
40
|
helperTextStates: {
|
|
41
|
-
default: "text-[var(--color-text-muted)]
|
|
42
|
-
disabled: "text-[var(--color-text-disabled)]
|
|
41
|
+
default: "text-[var(--color-text-muted)]",
|
|
42
|
+
disabled: "text-[var(--color-text-disabled)]",
|
|
43
43
|
invalid: "text-[var(--color-danger)] dark:text-[var(--color-danger-400)]",
|
|
44
44
|
},
|
|
45
45
|
};
|
|
@@ -190,7 +190,7 @@ const DatePickerBody = ({ isOpen, className, onClose, portal = true, placement =
|
|
|
190
190
|
const adjustedLeft = new Date(newDate);
|
|
191
191
|
adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
|
|
192
192
|
setLeftCalendarDate(adjustedLeft);
|
|
193
|
-
}, onNavigatePrev: null, onNavigateNext: handleNavigateNext, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: false, weekdays: weekdays, months: months, yearRange: yearRange, size: "md" }) })] })) }), jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-[var(--color-border)]", children: [jsx("div", { className: "text-sm text-[var(--color-text-muted)]", children: formatRangeDisplay(tempRange) }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Button, { variant: "outline", color: "
|
|
193
|
+
}, onNavigatePrev: null, onNavigateNext: handleNavigateNext, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: false, weekdays: weekdays, months: months, yearRange: yearRange, size: "md" }) })] })) }), jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-[var(--color-border)]", children: [jsx("div", { className: "text-sm text-[var(--color-text-muted)]", children: formatRangeDisplay(tempRange) }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Button, { variant: "outline", color: "mono", size: "sm", onClick: handleCancel, children: "Cancel" }), jsx(Button, { variant: "filled", size: "sm", onClick: handleApply, disabled: !(tempRange === null || tempRange === void 0 ? void 0 : tempRange.start) || !(tempRange === null || tempRange === void 0 ? void 0 : tempRange.end), children: "Apply" })] })] })] })) : (
|
|
194
194
|
// Single calendar for single mode
|
|
195
195
|
jsx("div", { className: "flex-1 p-4", children: children || (jsx(Calendar, { mode: "single", value: selectedValue, onChange: (value) => {
|
|
196
196
|
handleDateSelect(value);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import { useContext } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { Calendar } from '@phosphor-icons/react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { DatePickerContext } from './DatePickerContext.js';
|
|
7
7
|
|
|
@@ -29,7 +29,7 @@ const DatePickerTrigger = ({ id, disabled, isOpen, state = "default", size = "md
|
|
|
29
29
|
? focusStateStyle ||
|
|
30
30
|
"shadow-[inset_0_0_0_1px_var(--color-primary-600)] ring-4 ring-[var(--color-primary)]/10"
|
|
31
31
|
: "";
|
|
32
|
-
return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open calendar", "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, children: [children, jsx("span", { className: iconEndStyle, children: jsx(
|
|
32
|
+
return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open calendar", "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, children: [children, jsx("span", { className: iconEndStyle, children: jsx(Calendar, { className: "h-4 w-4" }) })] }) }));
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
export { DatePickerTrigger };
|
|
@@ -33,11 +33,11 @@ const dateRangePickerTheme = {
|
|
|
33
33
|
"hover:bg-[var(--color-surface-hover)] hover:text-[var(--color-text-primary)] " +
|
|
34
34
|
"data-[active=true]:bg-[var(--color-primary-50)] data-[active=true]:text-[var(--color-primary)] " +
|
|
35
35
|
"dark:data-[active=true]:bg-[var(--color-primary-950)] dark:data-[active=true]:text-[var(--color-primary-300)]",
|
|
36
|
-
mobileRangeDisplayStyle: "sm:hidden text-xs text-center py-2 text-[var(--color-text-secondary)]
|
|
36
|
+
mobileRangeDisplayStyle: "sm:hidden text-xs text-center py-2 text-[var(--color-text-secondary)]",
|
|
37
37
|
helperTextStyle: formsBaseTheme.helperText,
|
|
38
38
|
helperTextStates: {
|
|
39
|
-
default: "text-[var(--color-text-muted)]
|
|
40
|
-
disabled: "text-[var(--color-text-disabled)]
|
|
39
|
+
default: "text-[var(--color-text-muted)]",
|
|
40
|
+
disabled: "text-[var(--color-text-disabled)]",
|
|
41
41
|
invalid: "text-[var(--color-danger)] dark:text-[var(--color-danger-400)]",
|
|
42
42
|
},
|
|
43
43
|
};
|
|
@@ -175,7 +175,7 @@ const DateRangePickerBody = ({ isOpen, className, onClose, portal = true, placem
|
|
|
175
175
|
const adjustedLeft = new Date(newDate);
|
|
176
176
|
adjustedLeft.setMonth(adjustedLeft.getMonth() - 1);
|
|
177
177
|
setLeftCalendarDate(adjustedLeft);
|
|
178
|
-
}, onNavigatePrev: null, onNavigateNext: handleNavigateNext, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: false, weekdays: weekdays, months: months, yearRange: yearRange, showOtherMonthDays: false, headerMode: "static", size: "md" }) })] }), jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 px-3 sm:px-4 py-3 border-t border-[var(--color-border)]", children: [jsx("div", { className: "text-sm text-center sm:text-left text-[var(--color-text-muted)]", children: formatRangeDisplay(tempRange) }), jsxs("div", { className: "flex w-full sm:w-auto items-center gap-2", children: [jsx(Button, { variant: "outline", color: "
|
|
178
|
+
}, onNavigatePrev: null, onNavigateNext: handleNavigateNext, minDate: minDate, maxDate: maxDate, isDateDisabled: isDateDisabled, showToday: showToday, selectTodayByDefault: false, weekdays: weekdays, months: months, yearRange: yearRange, showOtherMonthDays: false, headerMode: "static", size: "md" }) })] }), jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 px-3 sm:px-4 py-3 border-t border-[var(--color-border)]", children: [jsx("div", { className: "text-sm text-center sm:text-left text-[var(--color-text-muted)]", children: formatRangeDisplay(tempRange) }), jsxs("div", { className: "flex w-full sm:w-auto items-center gap-2", children: [jsx(Button, { variant: "outline", color: "mono", size: "sm", className: "flex-1 sm:flex-initial", onClick: handleCancel, children: "Cancel" }), jsx(Button, { variant: "filled", size: "sm", className: "flex-1 sm:flex-initial", onClick: handleApply, disabled: !(tempRange === null || tempRange === void 0 ? void 0 : tempRange.start) || !(tempRange === null || tempRange === void 0 ? void 0 : tempRange.end), children: "Apply" })] })] })] })] }) })) }));
|
|
179
179
|
if (portal && isClient) {
|
|
180
180
|
return createPortal(jsx("div", { "data-flikkui-portal": "", className: isDarkMode ? "dark" : undefined, children: contentElement }), document.body);
|
|
181
181
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import { useContext } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { Check } from '@phosphor-icons/react';
|
|
5
5
|
import { DateRangePickerContext } from './DateRangePickerContext.js';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
|
|
@@ -35,7 +35,7 @@ const DateRangePickerPresets = ({ presets, className, tempRange, setTempRange, o
|
|
|
35
35
|
};
|
|
36
36
|
return (jsx("div", { className: cn(theme.presetsContainerStyle, className), children: presets.map((preset, index) => {
|
|
37
37
|
const active = isPresetActive(preset);
|
|
38
|
-
return (jsxs("button", { type: "button", onClick: () => handlePresetClick(preset), className: theme.presetButtonStyle, "data-active": active, children: [jsx("span", { children: preset.label }), active && jsx(
|
|
38
|
+
return (jsxs("button", { type: "button", onClick: () => handlePresetClick(preset), className: theme.presetButtonStyle, "data-active": active, children: [jsx("span", { children: preset.label }), active && jsx(Check, { className: theme.presetCheckmarkStyle })] }, index));
|
|
39
39
|
}) }));
|
|
40
40
|
};
|
|
41
41
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import { useContext } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { Calendar } from '@phosphor-icons/react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { DateRangePickerContext } from './DateRangePickerContext.js';
|
|
7
7
|
|
|
@@ -27,7 +27,7 @@ const DateRangePickerTrigger = ({ id, disabled, isOpen, state = "default", size
|
|
|
27
27
|
? focusStateStyle ||
|
|
28
28
|
"shadow-[inset_0_0_0_1px_var(--color-primary-600)] ring-4 ring-[var(--color-primary)]/10"
|
|
29
29
|
: "";
|
|
30
|
-
return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open date range picker", "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, children: [children, jsx("span", { className: iconEndStyle, children: jsx(
|
|
30
|
+
return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open date range picker", "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, children: [children, jsx("span", { className: iconEndStyle, children: jsx(Calendar, { className: "h-4 w-4" }) })] }) }));
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export { DateRangePickerTrigger };
|
|
@@ -5,7 +5,7 @@ import { useReducedMotion, AnimatePresence, motion } from 'motion/react';
|
|
|
5
5
|
import { fileUploadTheme } from './FileUpload.theme.js';
|
|
6
6
|
import { PREVIEW_LAYOUT_SPRING, PREVIEW_ITEM } from './FileUpload.animations.js';
|
|
7
7
|
import { cn } from '../../../utils/cn.js';
|
|
8
|
-
import {
|
|
8
|
+
import { CloudArrowUp, File, X } from '@phosphor-icons/react';
|
|
9
9
|
import { Button } from '../../core/Button/Button.js';
|
|
10
10
|
import { FormLabel } from '../FormLabel/FormLabel.js';
|
|
11
11
|
|
|
@@ -239,13 +239,13 @@ const FileUpload = React__default.forwardRef(({ accept, multiple = false, maxSiz
|
|
|
239
239
|
e.preventDefault();
|
|
240
240
|
handleClick();
|
|
241
241
|
}
|
|
242
|
-
}, children: jsxs("div", { className: "flex flex-col items-center text-center pointer-events-none", children: [showIcon && (jsx("div", { className: "size-10 border border-[var(--color-border)] bg-[var(--color-surface-raised)] rounded-full flex items-center justify-center mb-3", children: jsx(
|
|
242
|
+
}, children: jsxs("div", { className: "flex flex-col items-center text-center pointer-events-none", children: [showIcon && (jsx("div", { className: "size-10 border border-[var(--color-border)] bg-[var(--color-surface-raised)] rounded-full flex items-center justify-center mb-3", children: jsx(CloudArrowUp, { className: "size-6 text-[var(--color-text-secondary)]" }) })), jsxs("p", { className: "text-sm font-medium text-[var(--color-text-primary)]/80", children: [jsx("span", { className: "text-[var(--color-primary)]", children: buttonText }), " ", helperText] }), description && (jsx("p", { id: `${generatedId}-description`, className: "text-xs text-[var(--color-text-muted)] mt-0.5", children: description }))] }) }), errorMessage && (jsx("div", { id: `${generatedId}-error`, className: "text-sm mt-1 text-[var(--color-danger)]", children: errorMessage })), showPreview && selectedFiles.length > 0 && (jsx("div", { className: theme.previewContainerStyle, children: jsx(AnimatePresence, { initial: false, children: selectedFiles.map((file) => {
|
|
243
243
|
const previewUrl = previewUrls.get(file);
|
|
244
244
|
const isImage = file.type.startsWith("image/");
|
|
245
|
-
return (jsxs(motion.div, { layout: !shouldReduceMotion, initial: shouldReduceMotion ? false : PREVIEW_ITEM.initial, animate: PREVIEW_ITEM.animate, exit: shouldReduceMotion ? { opacity: 0 } : PREVIEW_ITEM.exit, transition: PREVIEW_LAYOUT_SPRING, className: theme.previewItemStyle, children: [isImage && previewUrl ? (jsx("img", { src: previewUrl, alt: file.name, className: theme.previewImageStyle })) : (jsx("div", { className: theme.previewFileStyle, title: file.name, children: jsx(
|
|
245
|
+
return (jsxs(motion.div, { layout: !shouldReduceMotion, initial: shouldReduceMotion ? false : PREVIEW_ITEM.initial, animate: PREVIEW_ITEM.animate, exit: shouldReduceMotion ? { opacity: 0 } : PREVIEW_ITEM.exit, transition: PREVIEW_LAYOUT_SPRING, className: theme.previewItemStyle, children: [isImage && previewUrl ? (jsx("img", { src: previewUrl, alt: file.name, className: theme.previewImageStyle })) : (jsx("div", { className: theme.previewFileStyle, title: file.name, children: jsx(File, { className: "size-6" }) })), jsx(Button, { variant: "soft", color: "danger", size: "sm", iconOnly: true, onClick: (e) => {
|
|
246
246
|
e.stopPropagation();
|
|
247
247
|
handleRemoveFile(file);
|
|
248
|
-
}, "aria-label": `Remove ${file.name}`, className: cn(theme.removeButtonStyle, "rounded-full !p-0 size-6"), children: jsx(
|
|
248
|
+
}, "aria-label": `Remove ${file.name}`, className: cn(theme.removeButtonStyle, "rounded-full !p-0 size-6"), children: jsx(X, { className: "size-4", weight: "bold" }) })] }, getFileKey(file)));
|
|
249
249
|
}) }) }))] }));
|
|
250
250
|
});
|
|
251
251
|
FileUpload.displayName = "FileUpload";
|
|
@@ -9,7 +9,11 @@ const fileUploadTheme = {
|
|
|
9
9
|
dropzoneDisabledStyle: "cursor-not-allowed opacity-60 hover:bg-[var(--color-surface)] hover:border-[var(--color-border)]",
|
|
10
10
|
// Wrapping row of fixed-width thumbnails (not a stretch grid)
|
|
11
11
|
previewContainerStyle: "flex flex-wrap gap-1 mt-2",
|
|
12
|
-
// Fixed responsive thumbnail — stays small on large containers, wraps to more-per-row
|
|
12
|
+
// Fixed responsive thumbnail — stays small on large containers, wraps to more-per-row.
|
|
13
|
+
// Intentionally uncapped (unlike the surface-radius-cap system in theme.css): the image
|
|
14
|
+
// fills the box edge-to-edge with no padding for a curve to eat into, so this behaves like
|
|
15
|
+
// a control (Avatar/Badge), not a content-bearing container — safe to go fully circular at
|
|
16
|
+
// an extreme --radius-base, same as Checkbox/Avatar.
|
|
13
17
|
previewItemStyle: "relative group shrink-0 size-10 sm:size-12 md:size-16 rounded-[var(--radius-base)] border border-[var(--color-border)] overflow-hidden bg-[var(--color-surface)]",
|
|
14
18
|
// Image fills the thumbnail box
|
|
15
19
|
previewImageStyle: "size-full object-cover",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import React__default, { useState, useEffect } from 'react';
|
|
4
4
|
import { useReducedMotion, motion, AnimatePresence } from 'motion/react';
|
|
5
|
-
import {
|
|
5
|
+
import { File, Trash, ArrowsClockwise, X, Check } from '@phosphor-icons/react';
|
|
6
6
|
import { Icon } from '../../core/Icon/Icon.js';
|
|
7
7
|
import { fileTypes } from '../../core/Icon/data/fileTypes.js';
|
|
8
8
|
import { cn } from '../../../utils/cn.js';
|
|
@@ -61,13 +61,13 @@ const RadialProgress = ({ progress, status, strokeWidth, trackColor, progressCol
|
|
|
61
61
|
setConfirmOpen(open);
|
|
62
62
|
if (!open)
|
|
63
63
|
setIsHovered(false);
|
|
64
|
-
}, placement: "bottom-end", offset: offsetValue, triggerType: "click", children: [jsx(Popover.Trigger, { children: trigger }), jsxs(Popover.Body, { className: "flex items-center p-1 border-[0.5px] rounded-xl gap-0.5 bg-opacity-50 backdrop-blur-md", children: [jsx("span", { className: "text-sm font-semibold text-[var(--color-text-secondary)] px-3", children: label }), jsxs("div", { className: "flex gap-1", children: [jsx(Button, { size: "sm", color: "danger", variant: "filled", onClick: handleConfirm, children: "Yesss" }), jsx(Button, { size: "sm", variant: "soft", color: "
|
|
64
|
+
}, placement: "bottom-end", offset: offsetValue, triggerType: "click", children: [jsx(Popover.Trigger, { children: trigger }), jsxs(Popover.Body, { className: "flex items-center p-1 border-[0.5px] rounded-xl gap-0.5 bg-opacity-50 backdrop-blur-md", children: [jsx("span", { className: "text-sm font-semibold text-[var(--color-text-secondary)] px-3", children: label }), jsxs("div", { className: "flex gap-1", children: [jsx(Button, { size: "sm", color: "danger", variant: "filled", onClick: handleConfirm, children: "Yesss" }), jsx(Button, { size: "sm", variant: "soft", color: "mono", onClick: () => setConfirmOpen(false), children: "No" })] })] })] }));
|
|
65
65
|
// Shared remove button used after completion tick
|
|
66
|
-
const removeButton = (jsx(motion.div, { initial: shouldReduceMotion ? false : REMOVE_BUTTON_ENTER.initial, animate: REMOVE_BUTTON_ENTER.animate, transition: REMOVE_BUTTON_ENTER.transition, className: "shrink-0", children: jsx(Button, { size: "sm", variant: "soft", color: "
|
|
66
|
+
const removeButton = (jsx(motion.div, { initial: shouldReduceMotion ? false : REMOVE_BUTTON_ENTER.initial, animate: REMOVE_BUTTON_ENTER.animate, transition: REMOVE_BUTTON_ENTER.transition, className: "shrink-0", children: jsx(Button, { size: "sm", variant: "soft", color: "mono", "aria-label": "Remove file", iconOnly: true, className: "rounded-full size-8", onClick: confirmRemove ? undefined : () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(), children: jsx(Trash, { className: "size-3.5", weight: "bold" }) }) }, "remove-btn"));
|
|
67
67
|
// Error state: retry + delete buttons (no progress arc/percentage).
|
|
68
68
|
if (isError) {
|
|
69
|
-
const deleteButton = onRemove ? (jsx(Button, { size: "sm", variant: "soft", color: "
|
|
70
|
-
return (jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [onRetry && (jsx(Button, { size: "sm", variant: "soft", color: "
|
|
69
|
+
const deleteButton = onRemove ? (jsx(Button, { size: "sm", variant: "soft", color: "mono", "aria-label": "Remove file", iconOnly: true, className: "rounded-full size-8", onClick: confirmRemove ? undefined : () => onRemove(), children: jsx(Trash, { className: "size-3.5", weight: "bold" }) })) : null;
|
|
70
|
+
return (jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [onRetry && (jsx(Button, { size: "sm", variant: "soft", color: "mono", "aria-label": "Retry upload", iconOnly: true, className: "rounded-full size-8", onClick: () => onRetry(), children: jsx(ArrowsClockwise, { className: "size-3.5", weight: "bold" }) })), deleteButton &&
|
|
71
71
|
(confirmRemove
|
|
72
72
|
? confirmPopover(deleteButton, "Remove file?", 6)
|
|
73
73
|
: deleteButton)] }));
|
|
@@ -82,7 +82,7 @@ const RadialProgress = ({ progress, status, strokeWidth, trackColor, progressCol
|
|
|
82
82
|
handleClick();
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
: undefined, children: [jsxs("svg", { viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`, className: "w-full h-full -rotate-90", children: [jsx("circle", { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: trackColor, strokeWidth: strokeWidth }), jsx(motion.circle, { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: progressColor, strokeWidth: strokeWidth, strokeLinecap: "round", strokeDasharray: circumference, initial: { strokeDashoffset: circumference }, animate: { strokeDashoffset: isComplete ? 0 : offset }, transition: shouldReduceMotion ? { duration: 0 } : PROGRESS_SPRING })] }), jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsxs(AnimatePresence, { mode: "wait", initial: false, children: [isUploading && !isHovered && (jsx(motion.span, { className: centerTextStyle, ...(shouldReduceMotion ? {} : CROSSFADE), children: progress }, "percent")), isUploading && isHovered && onRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx(
|
|
85
|
+
: undefined, children: [jsxs("svg", { viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`, className: "w-full h-full -rotate-90", children: [jsx("circle", { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: trackColor, strokeWidth: strokeWidth }), jsx(motion.circle, { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: progressColor, strokeWidth: strokeWidth, strokeLinecap: "round", strokeDasharray: circumference, initial: { strokeDashoffset: circumference }, animate: { strokeDashoffset: isComplete ? 0 : offset }, transition: shouldReduceMotion ? { duration: 0 } : PROGRESS_SPRING })] }), jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsxs(AnimatePresence, { mode: "wait", initial: false, children: [isUploading && !isHovered && (jsx(motion.span, { className: centerTextStyle, ...(shouldReduceMotion ? {} : CROSSFADE), children: progress }, "percent")), isUploading && isHovered && onRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx(X, { className: "size-4 text-[var(--color-text-muted)]", weight: "bold" }) }, "close")), isComplete && !showRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx(Check, { className: cn("size-4", statusIconColor), weight: "bold" }) }, "check"))] }) })] }));
|
|
86
86
|
// Determine what to render: radial indicator or remove button
|
|
87
87
|
const showRemoveButton = isComplete && showRemove && onRemove;
|
|
88
88
|
const triggerElement = showRemoveButton ? removeButton : radialElement;
|
|
@@ -111,7 +111,7 @@ const FileUploadProgress = React__default.forwardRef(({ items, onRemove, onRetry
|
|
|
111
111
|
const clampedProgress = Math.min(100, Math.max(0, item.progress));
|
|
112
112
|
const ext = getFileExtension(item.file.name);
|
|
113
113
|
const hasFileTypeIcon = ext !== null && isKnownFileType(ext);
|
|
114
|
-
return (jsxs("div", { className: (_a = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.itemStyle) !== null && _a !== void 0 ? _a : t.itemStyle, children: [hasFileTypeIcon ? (jsx("span", { className: "shrink-0", children: jsx(Icon, { icon: ext, size: "lg" }) })) : (jsx("span", { className: cn((_b = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconContainerStyle) !== null && _b !== void 0 ? _b : t.iconContainerStyle, t.iconSize), children: jsx(
|
|
114
|
+
return (jsxs("div", { className: (_a = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.itemStyle) !== null && _a !== void 0 ? _a : t.itemStyle, children: [hasFileTypeIcon ? (jsx("span", { className: "shrink-0", children: jsx(Icon, { icon: ext, size: "lg" }) })) : (jsx("span", { className: cn((_b = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconContainerStyle) !== null && _b !== void 0 ? _b : t.iconContainerStyle, t.iconSize), children: jsx(File, { className: (_c = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconStyle) !== null && _c !== void 0 ? _c : t.iconStyle }) })), jsxs("div", { className: (_d = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileInfoStyle) !== null && _d !== void 0 ? _d : t.fileInfoStyle, children: [jsx("p", { className: (_e = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileNameStyle) !== null && _e !== void 0 ? _e : t.fileNameStyle, children: item.file.name }), item.status === "error" && item.error ? (jsx("p", { className: (_f = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.errorTextStyle) !== null && _f !== void 0 ? _f : t.errorTextStyle, children: item.error })) : (showFileSize && (jsx("p", { className: (_g = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileSizeStyle) !== null && _g !== void 0 ? _g : t.fileSizeStyle, children: formatFileSize(item.file.size) })))] }), jsx(RadialProgress, { progress: clampedProgress, status: item.status, strokeWidth: t.radialStroke, trackColor: (_h = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialTrackColor) !== null && _h !== void 0 ? _h : t.radialTrackColor, progressColor: radialProgressColors[item.status], centerTextStyle: (_j = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialCenterTextStyle) !== null && _j !== void 0 ? _j : t.radialCenterTextStyle, statusIconColor: statusIconColors[item.status], sizeClass: t.radialSize, shouldReduceMotion: shouldReduceMotion, confirmRemove: confirmRemove, completionDelay: completionDelay, onRemove: onRemove ? () => onRemove(item.id) : undefined, onRetry: onRetry ? () => onRetry(item.id) : undefined })] }, item.id));
|
|
115
115
|
}) }));
|
|
116
116
|
});
|
|
117
117
|
FileUploadProgress.displayName = "FileUploadProgress";
|
|
@@ -4,8 +4,7 @@ import React__default, { useState, useRef, useEffect, useCallback } from 'react'
|
|
|
4
4
|
import { FormLabel } from '../FormLabel/FormLabel.js';
|
|
5
5
|
import { inputTheme } from './Input.theme.js';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
|
-
import {
|
|
8
|
-
import { MagnifyingGlassIcon, MinusIcon, PlusIcon } from '@heroicons/react/24/outline';
|
|
7
|
+
import { Lock, MagnifyingGlass, EyeSlash, Eye, Minus, Plus } from '@phosphor-icons/react';
|
|
9
8
|
import { validateMaskedInput, applyInputMask, getAdjustedCursorPosition } from './inputMasks.js';
|
|
10
9
|
|
|
11
10
|
const PasswordToggleButton = ({ showPassword, onToggle, passwordToggleClasses, }) => {
|
|
@@ -19,7 +18,7 @@ const PasswordToggleButton = ({ showPassword, onToggle, passwordToggleClasses, }
|
|
|
19
18
|
e.preventDefault();
|
|
20
19
|
onToggle();
|
|
21
20
|
}
|
|
22
|
-
}, children: showPassword ? (jsx(
|
|
21
|
+
}, children: showPassword ? (jsx(EyeSlash, { className: toggleIconActive, "aria-hidden": "true" })) : (jsx(Eye, { className: toggleIconInactive, "aria-hidden": "true" })) }));
|
|
23
22
|
};
|
|
24
23
|
const NumberButtons = ({ isDisabled, isAtMax, isAtMin, onIncrement, onDecrement, numberButtonsContainerClasses, numberButtonClasses, }) => {
|
|
25
24
|
const incrementIconStyle = inputTheme.typeStyles.number.incrementIconStyle;
|
|
@@ -27,10 +26,10 @@ const NumberButtons = ({ isDisabled, isAtMax, isAtMin, onIncrement, onDecrement,
|
|
|
27
26
|
return (jsxs("div", { className: numberButtonsContainerClasses, children: [jsx("button", { type: "button", className: `${numberButtonClasses}`, onClick: (e) => {
|
|
28
27
|
e.stopPropagation();
|
|
29
28
|
onDecrement();
|
|
30
|
-
}, disabled: isDisabled || isAtMin, "aria-label": "Decrease value", tabIndex: -1, children: jsx(
|
|
29
|
+
}, disabled: isDisabled || isAtMin, "aria-label": "Decrease value", tabIndex: -1, children: jsx(Minus, { className: cn("size-4", decrementIconStyle), "aria-hidden": "true" }) }), jsx("button", { type: "button", className: `${numberButtonClasses}`, onClick: (e) => {
|
|
31
30
|
e.stopPropagation();
|
|
32
31
|
onIncrement();
|
|
33
|
-
}, disabled: isDisabled || isAtMax, "aria-label": "Increase value", tabIndex: -1, children: jsx(
|
|
32
|
+
}, disabled: isDisabled || isAtMax, "aria-label": "Increase value", tabIndex: -1, children: jsx(Plus, { className: cn("size-4", incrementIconStyle), "aria-hidden": "true" }) })] }));
|
|
34
33
|
};
|
|
35
34
|
const getActiveDots = (strength) => {
|
|
36
35
|
switch (strength) {
|
|
@@ -83,8 +82,8 @@ const Input = React__default.forwardRef(({ size = "md", state = "default", class
|
|
|
83
82
|
const inputRef = useRef(null);
|
|
84
83
|
const cursorPositionRef = useRef(null);
|
|
85
84
|
// Default icons based on input type
|
|
86
|
-
const defaultPasswordIcon = showTypeIcon && type === "password" && !iconStart ? (jsx(
|
|
87
|
-
const defaultSearchIcon = showTypeIcon && type === "search" && !iconStart ? (jsx(
|
|
85
|
+
const defaultPasswordIcon = showTypeIcon && type === "password" && !iconStart ? (jsx(Lock, { className: "size-5 text-[var(--color-text-muted)]" })) : null;
|
|
86
|
+
const defaultSearchIcon = showTypeIcon && type === "search" && !iconStart ? (jsx(MagnifyingGlass, { className: cn("size-5", inputTheme.typeStyles.search.iconStyle) })) : null;
|
|
88
87
|
// Use the provided iconStart or the default icon based on input type
|
|
89
88
|
const finalLeftIcon = iconStart || defaultPasswordIcon || defaultSearchIcon;
|
|
90
89
|
// Derived state flags for internal use
|
|
@@ -49,9 +49,9 @@ const inputTheme = {
|
|
|
49
49
|
iconPadding: formsBaseTheme.iconStyles.padding,
|
|
50
50
|
// Content styles - prefix/suffix content with size-aware font sizes
|
|
51
51
|
contentStyle: {
|
|
52
|
-
sm: `flex items-center px-3 ${formsBaseTheme.sizes.sm.text} text-[var(--color-text-muted)] shrink-0
|
|
53
|
-
md: `flex items-center px-3 ${formsBaseTheme.sizes.md.text} text-[var(--color-text-muted)] shrink-0
|
|
54
|
-
lg: `flex items-center px-3 ${formsBaseTheme.sizes.lg.text} text-[var(--color-text-muted)] shrink-0
|
|
52
|
+
sm: `flex items-center px-3 ${formsBaseTheme.sizes.sm.text} text-[var(--color-text-muted)] shrink-0`,
|
|
53
|
+
md: `flex items-center px-3 ${formsBaseTheme.sizes.md.text} text-[var(--color-text-muted)] shrink-0`,
|
|
54
|
+
lg: `flex items-center px-3 ${formsBaseTheme.sizes.lg.text} text-[var(--color-text-muted)] shrink-0`,
|
|
55
55
|
},
|
|
56
56
|
contentStartStyle: "pr-0 " +
|
|
57
57
|
"[&:has([aria-haspopup])]:pl-0 " +
|
|
@@ -67,29 +67,33 @@ const inputTheme = {
|
|
|
67
67
|
"[&_[aria-haspopup]]:border-none [&_[aria-haspopup]]:rounded-none [&_[aria-haspopup]]:bg-transparent " +
|
|
68
68
|
"[&_[aria-haspopup]]:min-h-0 [&_[aria-haspopup]]:h-full",
|
|
69
69
|
// Keyboard shortcut display
|
|
70
|
-
keyboardShortcutStyle: "absolute inset-y-0 right-0 flex items-center pr-3 text-[var(--color-text-muted)] z-10
|
|
71
|
-
"dark:text-[var(--color-neutral-500)]",
|
|
70
|
+
keyboardShortcutStyle: "absolute inset-y-0 right-0 flex items-center pr-3 text-[var(--color-text-muted)] z-10",
|
|
72
71
|
// Password toggle button with hover states
|
|
73
72
|
passwordToggleStyle: "absolute inset-y-0 right-0 flex items-center pr-3 cursor-pointer " +
|
|
74
|
-
"text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] transition-colors z-10
|
|
75
|
-
"dark:text-[var(--color-neutral-500)] dark:hover:text-[var(--color-neutral-200)]",
|
|
73
|
+
"text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] transition-colors z-10",
|
|
76
74
|
// Number input controls
|
|
77
75
|
numberButtonsContainerStyle: "absolute inset-y-0 right-0 flex flex-row items-center pr-2 z-10 gap-1",
|
|
78
|
-
|
|
76
|
+
// In-field micro-affordance (like the password toggle) — deliberately a plain
|
|
77
|
+
// <button>, NOT the Button component (form-control heights don't fit in the
|
|
78
|
+
// field). --checkbox-radius = the capped small-control radius, so it follows
|
|
79
|
+
// --radius-base without going full pill at 24px.
|
|
80
|
+
numberButtonStyle: "bg-[var(--color-surface-sunken)] flex items-center justify-center " +
|
|
79
81
|
"text-[var(--color-text-muted)] hover:bg-[var(--color-surface-hover)] " +
|
|
80
|
-
"hover:text-[var(--color-text-primary)] cursor-pointer size-6 rounded-
|
|
82
|
+
"hover:text-[var(--color-text-primary)] cursor-pointer size-6 rounded-[var(--checkbox-radius)] transition-colors " +
|
|
83
|
+
"outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] " +
|
|
84
|
+
"disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-[var(--color-surface-sunken)]",
|
|
81
85
|
// Type-specific styles organized by input type
|
|
82
86
|
typeStyles: {
|
|
83
87
|
password: {
|
|
84
|
-
toggleIconActive: "size-5 text-[var(--color-text-primary)]
|
|
85
|
-
toggleIconInactive: "size-5 text-[var(--color-text-muted)]
|
|
88
|
+
toggleIconActive: "size-5 text-[var(--color-text-primary)]",
|
|
89
|
+
toggleIconInactive: "size-5 text-[var(--color-text-muted)]",
|
|
86
90
|
},
|
|
87
91
|
search: {
|
|
88
|
-
iconStyle: "text-[var(--color-text-muted)]
|
|
92
|
+
iconStyle: "text-[var(--color-text-muted)]",
|
|
89
93
|
},
|
|
90
94
|
number: {
|
|
91
|
-
incrementIconStyle: "text-[var(--color-text-muted)]
|
|
92
|
-
decrementIconStyle: "text-[var(--color-text-muted)]
|
|
95
|
+
incrementIconStyle: "text-[var(--color-text-muted)]",
|
|
96
|
+
decrementIconStyle: "text-[var(--color-text-muted)]",
|
|
93
97
|
},
|
|
94
98
|
},
|
|
95
99
|
// Password strength indicator with design tokens
|
|
@@ -98,7 +102,7 @@ const inputTheme = {
|
|
|
98
102
|
labelStyle: "text-xs font-semibold mr-1",
|
|
99
103
|
dotStyle: "size-1.5 rounded-full",
|
|
100
104
|
dotActiveStyle: "bg-current",
|
|
101
|
-
dotInactiveStyle: "bg-[var(--color-border)] dark:bg-[var(--color-
|
|
105
|
+
dotInactiveStyle: "bg-[var(--color-border)] dark:bg-[var(--color-mono-700)]",
|
|
102
106
|
strengthStyles: {
|
|
103
107
|
weak: {
|
|
104
108
|
label: "Weak",
|
|
@@ -75,7 +75,7 @@ const DEFAULT_COUNTRIES = [
|
|
|
75
75
|
* />
|
|
76
76
|
* ```
|
|
77
77
|
*/
|
|
78
|
-
const InputAddress = React__default.forwardRef(({ state = 'default', errorMessage, availableCountries = [], defaultCountry = "United States", onCountryChange, onPostalCodeChange, countryLabel = "Country", postalCodeLabel = "ZIP / Postal code", legendText = "Billing address", streetInputProps = {}, stateInputProps = {}, countryInputProps = {}, postalCodeInputProps = {}, className = "", theme = {}, }, ref) => {
|
|
78
|
+
const InputAddress = React__default.forwardRef(({ state = 'default', errorMessage, showCountrySelector = true, showPostalCode = true, availableCountries = [], defaultCountry = "United States", onCountryChange, onPostalCodeChange, countryLabel = "Country", postalCodeLabel = "ZIP / Postal code", legendText = "Billing address", streetInputProps = {}, stateInputProps = {}, countryInputProps = {}, postalCodeInputProps = {}, className = "", theme = {}, }, ref) => {
|
|
79
79
|
var _a;
|
|
80
80
|
const isDisabled = state === 'disabled';
|
|
81
81
|
// Clear the error visually as soon as the user starts re-entering after an error.
|
|
@@ -133,17 +133,24 @@ const InputAddress = React__default.forwardRef(({ state = 'default', errorMessag
|
|
|
133
133
|
// Children are NEVER given `invalid` — the single red perimeter overlay carries the error
|
|
134
134
|
// (see formsBaseTheme.groupInvalidOverlayStyle). Only disabled propagates to the fields.
|
|
135
135
|
const fieldState = isDisabled ? 'disabled' : 'default';
|
|
136
|
+
// The fields render as ONE merged perimeter, so the radii are positional: only the
|
|
137
|
+
// last visible field carries the bottom corners. Hiding country/postal moves that
|
|
138
|
+
// responsibility up the stack, and a lone bottom field spans the full row.
|
|
139
|
+
const showBottomRow = showCountrySelector || showPostalCode;
|
|
140
|
+
const isBottomRowSplit = showCountrySelector && showPostalCode;
|
|
136
141
|
// Merge group state into each field's props; strip per-field helperText so only the
|
|
137
142
|
// consolidated message shows at the bottom.
|
|
138
143
|
const { helperText: _st, onChange: _stOnChange, ...streetProps } = { state: fieldState, ...streetInputProps };
|
|
139
144
|
const { helperText: _sa, onChange: _saOnChange, ...stateProps } = { state: fieldState, ...stateInputProps };
|
|
140
145
|
const { helperText: _co, className: _coClass, ...countryProps } = { state: fieldState, ...countryInputProps };
|
|
141
146
|
const { helperText: _pc, ...postalProps } = { state: fieldState, ...postalCodeInputProps };
|
|
142
|
-
return (jsxs("fieldset", { ref: ref, className: `w-full border-0 m-0 p-0 ${isInvalid ? 'state-invalid' : ''} ${className}`, "data-testid": "input-address-fieldset", "aria-invalid": isInvalid || undefined, "aria-errormessage": isInvalid && errorMessage ? errorId : undefined, children: [jsx("legend", { className: `block text-sm/6 font-medium mb-2 text-[var(--color-text-primary)] ${(_a = mergedTheme.legendStyles) !== null && _a !== void 0 ? _a : ""}`, children: legendText }), jsxs("div", { className: `relative grid gap-0 ${mergedTheme.contentStyles}`, "data-testid": "input-address-content", children: [jsx("div", { className: "w-full relative focus-within:z-10 hover:z-10", "data-testid": "input-address-street", children: jsx(Input, { id: streetId, type: "text", placeholder: "Street address", "aria-label": "street address", inputGroupClassName: "rounded-b-none", ...streetProps, onChange: markDirty(_stOnChange) }) }), jsx("div", { className: "w-full -mt-[0.5px] relative focus-within:z-10 hover:z-10", "data-testid": "input-address-state", children: jsx(Input, { id: stateId, type: "text", placeholder: "State", "aria-label": "state", inputGroupClassName: "rounded-none", ...stateProps, onChange: markDirty(_saOnChange) }) }), jsxs("div", { className: "grid grid-cols-1
|
|
147
|
+
return (jsxs("fieldset", { ref: ref, className: `w-full border-0 m-0 p-0 ${isInvalid ? 'state-invalid' : ''} ${className}`, "data-testid": "input-address-fieldset", "aria-invalid": isInvalid || undefined, "aria-errormessage": isInvalid && errorMessage ? errorId : undefined, children: [jsx("legend", { className: `block text-sm/6 font-medium mb-2 text-[var(--color-text-primary)] ${(_a = mergedTheme.legendStyles) !== null && _a !== void 0 ? _a : ""}`, children: legendText }), jsxs("div", { className: `relative grid gap-0 ${mergedTheme.contentStyles}`, "data-testid": "input-address-content", children: [jsx("div", { className: "w-full relative focus-within:z-10 hover:z-10", "data-testid": "input-address-street", children: jsx(Input, { id: streetId, type: "text", placeholder: "Street address", "aria-label": "street address", inputGroupClassName: "rounded-b-none", ...streetProps, onChange: markDirty(_stOnChange) }) }), jsx("div", { className: "w-full -mt-[0.5px] relative focus-within:z-10 hover:z-10", "data-testid": "input-address-state", children: jsx(Input, { id: stateId, type: "text", placeholder: "State", "aria-label": "state", inputGroupClassName: showBottomRow ? "rounded-none" : "rounded-t-none", ...stateProps, onChange: markDirty(_saOnChange) }) }), showBottomRow && (jsxs("div", { className: cn("grid grid-cols-1 w-full -mt-px relative focus-within:z-10 hover:z-10", isBottomRowSplit && "sm:grid-cols-2"), children: [showCountrySelector && (jsx("div", { className: `${mergedTheme.countryWrapperStyles} w-full sm:pr-0 relative focus-within:z-10 hover:z-10`, "data-testid": "input-address-country", children: jsx(Select, { id: countryId, options: countryOptions, value: country, onChange: handleCountryChange, placeholder: countryLabel, searchable: true, searchPlaceholder: `Search ${countryLabel.toLowerCase()}`, disabled: isDisabled,
|
|
143
148
|
// className lands on the Select trigger button (which carries the same
|
|
144
149
|
// inputGroup border/radius as Input's inputGroupClassName target), so the
|
|
145
150
|
// outer styling and the merged border seams are identical to the old Input.
|
|
146
|
-
className: cn("
|
|
151
|
+
className: cn("rounded-t-none", isBottomRowSplit &&
|
|
152
|
+
"sm:rounded-bl-[var(--form-radius)] sm:rounded-tr-none sm:rounded-br-none", _coClass), ...countryProps }) })), showPostalCode && (jsx("div", { className: cn(mergedTheme.postalCodeWrapperStyles, "w-full relative focus-within:z-10 hover:z-10", isBottomRowSplit && "-mt-px sm:mt-0 sm:-ml-px sm:w-[calc(100%+1px)]"), "data-testid": "input-address-postal", children: jsx(Input, { id: postalCodeId, type: "text", value: postalCode, onChange: handlePostalCodeChange, placeholder: postalCodeLabel, "aria-label": postalCodeLabel, inputGroupClassName: cn("rounded-t-none", isBottomRowSplit &&
|
|
153
|
+
"sm:rounded-br-[var(--form-radius)] rounded-tl-none rounded-bl-[var(--form-radius)] sm:rounded-bl-none"), ...postalProps }) }))] })), isInvalid && jsx("div", { "aria-hidden": "true", className: formsBaseTheme.groupInvalidOverlayStyle })] }), isInvalid && errorMessage && (jsx("p", { id: errorId, role: "alert", className: formsBaseTheme.helperText, children: errorMessage }))] }));
|
|
147
154
|
});
|
|
148
155
|
InputAddress.displayName = "InputAddress";
|
|
149
156
|
|
|
@@ -6,7 +6,7 @@ import { inputCounterTheme } from './InputCounter.theme.js';
|
|
|
6
6
|
import { Button } from '../../core/Button/Button.js';
|
|
7
7
|
import { SlidingNumber } from '../../core/SlidingNumber/SlidingNumber.js';
|
|
8
8
|
import { cn } from '../../../utils/cn.js';
|
|
9
|
-
import {
|
|
9
|
+
import { Minus, Plus } from '@phosphor-icons/react';
|
|
10
10
|
import { FormLabel } from '../FormLabel/FormLabel.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -175,7 +175,7 @@ const InputCounter = React__default.forwardRef(({ value, onChange, state = "defa
|
|
|
175
175
|
// focusable <Button>, so an explicit tabIndex={-1} keeps it out
|
|
176
176
|
// of the tab order (motion.js only adds its own when the
|
|
177
177
|
// attribute is absent).
|
|
178
|
-
tabIndex: -1, whileHover: !isDisabled && !shouldDisableAnimations ? { scale: 1.05 } : undefined, whileTap: !isDisabled && !shouldDisableAnimations ? { scale: 0.95 } : undefined, children: jsx(Button, { size: "sm", variant: "ghost", iconOnly: true, ...buttonProps, onClick: handleDecrement, disabled: !canDecrement, "aria-label": "Decrement", children: jsx(
|
|
178
|
+
tabIndex: -1, whileHover: !isDisabled && !shouldDisableAnimations ? { scale: 1.05 } : undefined, whileTap: !isDisabled && !shouldDisableAnimations ? { scale: 0.95 } : undefined, children: jsx(Button, { size: "sm", variant: "ghost", iconOnly: true, ...buttonProps, onClick: handleDecrement, disabled: !canDecrement, "aria-label": "Decrement", children: jsx(Minus, { className: "size-4 text-[var(--color-text-primary)]", weight: "bold" }) }) }), jsx(SlidingNumber, { value: value, decimalPlaces: autoDecimalPlaces, className: mergedTheme.numberStyle, transition: transition }), jsx(motion.div, { className: mergedTheme.buttonWrapperStyle,
|
|
179
179
|
// Framer Motion's press gesture (triggered by `whileTap`) adds
|
|
180
180
|
// `tabIndex=0` to any non-natively-focusable element that
|
|
181
181
|
// doesn't already declare a `tabindex`, to make tap gestures
|
|
@@ -184,7 +184,7 @@ const InputCounter = React__default.forwardRef(({ value, onChange, state = "defa
|
|
|
184
184
|
// focusable <Button>, so an explicit tabIndex={-1} keeps it out
|
|
185
185
|
// of the tab order (motion.js only adds its own when the
|
|
186
186
|
// attribute is absent).
|
|
187
|
-
tabIndex: -1, whileHover: !isDisabled && !shouldDisableAnimations ? { scale: 1.05 } : undefined, whileTap: !isDisabled && !shouldDisableAnimations ? { scale: 0.95 } : undefined, children: jsx(Button, { size: "sm", variant: "ghost", iconOnly: true, ...buttonProps, onClick: handleIncrement, disabled: !canIncrement, "aria-label": "Increment", children: jsx(
|
|
187
|
+
tabIndex: -1, whileHover: !isDisabled && !shouldDisableAnimations ? { scale: 1.05 } : undefined, whileTap: !isDisabled && !shouldDisableAnimations ? { scale: 0.95 } : undefined, children: jsx(Button, { size: "sm", variant: "ghost", iconOnly: true, ...buttonProps, onClick: handleIncrement, disabled: !canIncrement, "aria-label": "Increment", children: jsx(Plus, { className: "size-4 text-[var(--color-text-primary)]", weight: "bold" }) }) })] }), displayedMessage && (jsx("div", { id: helperId, role: isInvalid ? "alert" : undefined, className: cn("text-sm mt-1", isInvalid
|
|
188
188
|
? "text-[var(--color-danger)]"
|
|
189
189
|
: "text-[var(--color-text-muted)]"), children: displayedMessage }))] }));
|
|
190
190
|
});
|
|
@@ -2,17 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { InputOTPProps } from './InputOTP.types';
|
|
3
3
|
/**
|
|
4
4
|
* InputOTP component for entering one-time passwords or verification codes.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* ```tsx
|
|
9
|
-
* <InputOTP
|
|
10
|
-
* length={6}
|
|
11
|
-
* value={otpValue}
|
|
12
|
-
* onChange={setOtpValue}
|
|
13
|
-
* onComplete={handleOtpComplete}
|
|
14
|
-
* label="Enter verification code"
|
|
15
|
-
* />
|
|
16
|
-
* ```
|
|
5
|
+
* One invisible native input overlays the rendered slots: focus, typing,
|
|
6
|
+
* paste, and autofill all go through it, and the caret is pinned to the end
|
|
7
|
+
* of the value so the highlighted slot always matches where edits land.
|
|
17
8
|
*/
|
|
18
9
|
export declare const InputOTP: React.ForwardRefExoticComponent<InputOTPProps & React.RefAttributes<HTMLDivElement>>;
|