@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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Variants } from "motion/react";
|
|
2
|
+
import type { OfflineIndicatorPosition, OfflineIndicatorVariant } from "./OfflineIndicator.types";
|
|
3
|
+
/**
|
|
4
|
+
* Custom spring preset for offline indicator to give it a satisfying, subtle bounce.
|
|
5
|
+
*/
|
|
6
|
+
export declare const indicatorSpring: {
|
|
7
|
+
type: "spring";
|
|
8
|
+
stiffness: number;
|
|
9
|
+
damping: number;
|
|
10
|
+
mass: number;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Generates context-aware animation variants for OfflineIndicator.
|
|
14
|
+
* Dynamically adjusts translation side/axis based on screen placement.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Fade-only variants for prefers-reduced-motion users — the status pill
|
|
18
|
+
* still appears/disappears (it's a role="status" signal), just without
|
|
19
|
+
* translation, scale, or bounce.
|
|
20
|
+
*/
|
|
21
|
+
export declare const reducedMotionIndicatorVariants: Variants;
|
|
22
|
+
export declare const getOfflineIndicatorVariants: (position: OfflineIndicatorPosition, variant: OfflineIndicatorVariant) => Variants;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/**
|
|
3
|
+
* Custom spring preset for offline indicator to give it a satisfying, subtle bounce.
|
|
4
|
+
*/
|
|
5
|
+
const indicatorSpring = {
|
|
6
|
+
type: "spring",
|
|
7
|
+
stiffness: 260,
|
|
8
|
+
damping: 26,
|
|
9
|
+
mass: 1,
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Generates context-aware animation variants for OfflineIndicator.
|
|
13
|
+
* Dynamically adjusts translation side/axis based on screen placement.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Fade-only variants for prefers-reduced-motion users — the status pill
|
|
17
|
+
* still appears/disappears (it's a role="status" signal), just without
|
|
18
|
+
* translation, scale, or bounce.
|
|
19
|
+
*/
|
|
20
|
+
const reducedMotionIndicatorVariants = {
|
|
21
|
+
initial: { opacity: 0 },
|
|
22
|
+
animate: { opacity: 1, transition: { duration: 0.15 } },
|
|
23
|
+
exit: { opacity: 0, transition: { duration: 0.15 } },
|
|
24
|
+
};
|
|
25
|
+
const getOfflineIndicatorVariants = (position, variant) => {
|
|
26
|
+
const isTop = position.startsWith("top");
|
|
27
|
+
// Toast variants slide and scale, Banner variants just slide to maintain bleed styling
|
|
28
|
+
const yOffset = isTop ? -24 : 24;
|
|
29
|
+
const initialScale = variant === "banner" ? 1 : 0.92;
|
|
30
|
+
return {
|
|
31
|
+
initial: {
|
|
32
|
+
opacity: 0,
|
|
33
|
+
y: yOffset,
|
|
34
|
+
scale: initialScale,
|
|
35
|
+
},
|
|
36
|
+
animate: {
|
|
37
|
+
opacity: 1,
|
|
38
|
+
y: 0,
|
|
39
|
+
scale: 1,
|
|
40
|
+
transition: indicatorSpring,
|
|
41
|
+
},
|
|
42
|
+
exit: {
|
|
43
|
+
opacity: 0,
|
|
44
|
+
y: yOffset,
|
|
45
|
+
scale: initialScale,
|
|
46
|
+
transition: {
|
|
47
|
+
duration: 0.18,
|
|
48
|
+
ease: "easeIn",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export { getOfflineIndicatorVariants, indicatorSpring, reducedMotionIndicatorVariants };
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import React__default, { useState, useEffect, useMemo } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
import { AnimatePresence, motion } from 'motion/react';
|
|
4
|
+
import { WifiSlash, CheckCircle } from '@phosphor-icons/react';
|
|
5
|
+
import { useReducedMotion, AnimatePresence, motion } from 'motion/react';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { useNetworkStatus } from '../../../hooks/useNetworkStatus.js';
|
|
8
8
|
import { getDefaultQueue } from '../../../utils/actionQueue.js';
|
|
9
|
+
import { Link } from '../Link/Link.js';
|
|
10
|
+
import { reducedMotionIndicatorVariants, getOfflineIndicatorVariants } from './OfflineIndicator.animations.js';
|
|
9
11
|
import { offlineIndicatorTheme } from './OfflineIndicator.theme.js';
|
|
10
12
|
|
|
13
|
+
const isOfflineIndicatorAction = (action) => typeof action === "object" &&
|
|
14
|
+
action !== null &&
|
|
15
|
+
"label" in action &&
|
|
16
|
+
"onClick" in action;
|
|
11
17
|
/**
|
|
12
18
|
* OfflineIndicator - Visual indicator for offline status
|
|
13
19
|
*
|
|
@@ -21,9 +27,10 @@ import { offlineIndicatorTheme } from './OfflineIndicator.theme.js';
|
|
|
21
27
|
* // Custom position and variant
|
|
22
28
|
* <OfflineIndicator position="bottom-right" variant="badge" />
|
|
23
29
|
*/
|
|
24
|
-
const OfflineIndicator = React__default.forwardRef(({ position = "top", showQueueCount = false, queue, variant = "toast", autoHideOnline = true, autoHideDelay = 5000, offlineMessage = "You're offline", onlineMessage = "Back online", className, }, ref) => {
|
|
25
|
-
var _a, _b;
|
|
30
|
+
const OfflineIndicator = React__default.forwardRef(({ position = "top", showQueueCount = false, queue, variant = "toast", autoHideOnline = true, autoHideDelay = 5000, offlineMessage = "You're offline", onlineMessage = "Back online", action, className, }, ref) => {
|
|
31
|
+
var _a, _b, _c;
|
|
26
32
|
const theme = offlineIndicatorTheme;
|
|
33
|
+
const shouldReduceMotion = useReducedMotion();
|
|
27
34
|
const { isOnline, wasOffline } = useNetworkStatus();
|
|
28
35
|
const [isVisible, setIsVisible] = useState(false);
|
|
29
36
|
const [queueSize, setQueueSize] = useState(0);
|
|
@@ -73,29 +80,21 @@ const OfflineIndicator = React__default.forwardRef(({ position = "top", showQueu
|
|
|
73
80
|
autoHideOnline,
|
|
74
81
|
autoHideDelay,
|
|
75
82
|
]);
|
|
76
|
-
// Animation variants
|
|
77
|
-
const animationVariants = useMemo(() =>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
y: position.startsWith("top") ? -20 : 20,
|
|
81
|
-
scale: 0.95,
|
|
82
|
-
},
|
|
83
|
-
animate: {
|
|
84
|
-
opacity: 1,
|
|
85
|
-
y: 0,
|
|
86
|
-
scale: 1,
|
|
87
|
-
},
|
|
88
|
-
exit: {
|
|
89
|
-
opacity: 0,
|
|
90
|
-
y: position.startsWith("top") ? -20 : 20,
|
|
91
|
-
scale: 0.95,
|
|
92
|
-
},
|
|
93
|
-
}), [position]);
|
|
83
|
+
// Animation variants — fade-only under prefers-reduced-motion (§12)
|
|
84
|
+
const animationVariants = useMemo(() => shouldReduceMotion
|
|
85
|
+
? reducedMotionIndicatorVariants
|
|
86
|
+
: getOfflineIndicatorVariants(position, variant), [shouldReduceMotion, position, variant]);
|
|
94
87
|
const isOffline = !isOnline;
|
|
95
|
-
const Icon = isOffline ?
|
|
88
|
+
const Icon = isOffline ? WifiSlash : CheckCircle;
|
|
96
89
|
const message = isOffline ? offlineMessage : onlineMessage;
|
|
97
90
|
const stateStyle = isOffline ? theme.offline : theme.online;
|
|
98
|
-
|
|
91
|
+
// No `layout` on the root motion.div: its FLIP transform would fight the
|
|
92
|
+
// y/scale enter/exit variants on the same element (the documented
|
|
93
|
+
// concurrent layout+transform trap). Content-size changes animate via the
|
|
94
|
+
// children's layout="position" instead.
|
|
95
|
+
return (jsx(AnimatePresence, { children: isVisible && (jsxs(motion.div, { ref: ref, initial: "initial", animate: "animate", exit: "exit", variants: animationVariants, className: cn(theme.base, variant === "banner"
|
|
96
|
+
? (_a = theme.bannerPositions) === null || _a === void 0 ? void 0 : _a[position]
|
|
97
|
+
: (_b = theme.positions) === null || _b === void 0 ? void 0 : _b[position], (_c = theme.variants) === null || _c === void 0 ? void 0 : _c[variant], stateStyle, className), role: "status", "aria-live": "polite", children: [jsx("div", { className: "relative size-3.5 flex-shrink-0", children: jsx(AnimatePresence, { mode: "popLayout", children: jsx(motion.div, { initial: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.5, rotate: -45 }, animate: shouldReduceMotion ? { opacity: 1 } : { opacity: 1, scale: 1, rotate: 0 }, exit: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.5, rotate: 45 }, transition: { duration: 0.25 }, className: "absolute inset-0 flex items-center justify-center", children: jsx(Icon, { className: "size-full", "aria-hidden": "true" }) }, isOffline ? "offline" : "online") }) }), jsxs(motion.span, { layout: shouldReduceMotion ? false : "position", className: theme.message, children: [message, jsx(AnimatePresence, { mode: "popLayout", children: showQueueCount && queueSize > 0 && isOffline && (jsxs(motion.span, { initial: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.8 }, animate: shouldReduceMotion ? { opacity: 1 } : { opacity: 1, scale: 1 }, exit: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.8 }, transition: { duration: 0.18 }, className: theme.queueCount, children: ["(", queueSize, " action", queueSize !== 1 ? "s" : "", " queued)"] })) })] }), jsx(AnimatePresence, { children: action != null && isOffline && (jsx(motion.div, { layout: shouldReduceMotion ? false : "position", initial: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.9 }, animate: shouldReduceMotion ? { opacity: 1 } : { opacity: 1, scale: 1 }, exit: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.9 }, transition: { duration: 0.2 }, className: "inline-flex items-center flex-shrink-0", children: isOfflineIndicatorAction(action) ? (jsx(Link, { size: "sm", onClick: action.onClick, className: theme.action, children: action.label })) : (action) })) })] })) }));
|
|
99
98
|
});
|
|
100
99
|
OfflineIndicator.displayName = "OfflineIndicator";
|
|
101
100
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const offlineIndicatorTheme = {
|
|
2
|
-
base: "fixed z-50 flex items-center gap-
|
|
2
|
+
base: "fixed z-50 flex items-center gap-1.5 transition-colors duration-300 select-none",
|
|
3
3
|
positions: {
|
|
4
4
|
top: "top-4 left-1/2 -translate-x-1/2",
|
|
5
5
|
bottom: "bottom-4 left-1/2 -translate-x-1/2",
|
|
@@ -8,14 +8,33 @@ const offlineIndicatorTheme = {
|
|
|
8
8
|
"bottom-left": "bottom-4 left-4",
|
|
9
9
|
"bottom-right": "bottom-4 right-4",
|
|
10
10
|
},
|
|
11
|
+
// Banner is an edge-to-edge bar, so it collapses every position to the
|
|
12
|
+
// flush viewport edge — only the top/bottom half of `position` matters.
|
|
13
|
+
bannerPositions: {
|
|
14
|
+
top: "top-0",
|
|
15
|
+
bottom: "bottom-0",
|
|
16
|
+
"top-left": "top-0",
|
|
17
|
+
"top-right": "top-0",
|
|
18
|
+
"bottom-left": "bottom-0",
|
|
19
|
+
"bottom-right": "bottom-0",
|
|
20
|
+
},
|
|
11
21
|
variants: {
|
|
12
|
-
|
|
13
|
-
|
|
22
|
+
// translate-x-0 cancels the centered positions' -translate-x-1/2 (cn's
|
|
23
|
+
// tailwind-merge lets the variant win) — without it the full-width bar
|
|
24
|
+
// is dragged left by half its own width and clips off-screen.
|
|
25
|
+
banner: "w-full left-0 right-0 translate-x-0 px-4 py-1 justify-center rounded-none shadow-real-lg",
|
|
26
|
+
toast: "px-3 py-2 rounded-[var(--toast-radius)] shadow-real-xl",
|
|
14
27
|
},
|
|
15
|
-
|
|
28
|
+
// Filled-neutral pill: the bare neutral token flips light/dark on its own
|
|
29
|
+
// (dark near-black pill in light mode, light pill in dark mode) and
|
|
30
|
+
// -contrast auto-derives — no hand-picked rungs or dark: inversions (§3).
|
|
31
|
+
offline: "bg-[var(--color-mono)]/90 backdrop-blur-sm text-[var(--color-mono-contrast)]",
|
|
16
32
|
online: "bg-[var(--color-success)]/90 backdrop-blur-sm text-[var(--color-success-contrast)]",
|
|
17
|
-
|
|
18
|
-
|
|
33
|
+
// text-inherit keeps the link legible on the inverse pill in BOTH modes
|
|
34
|
+
// (near-black in light, near-white in dark) — a fixed Link color can't.
|
|
35
|
+
action: "text-xs font-semibold text-inherit",
|
|
36
|
+
icon: "size-3.5 flex-shrink-0",
|
|
37
|
+
message: "text-xs font-medium -tracking-[0.025em]",
|
|
19
38
|
queueCount: "text-xs opacity-80 ml-1",
|
|
20
39
|
};
|
|
21
40
|
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
1
2
|
import type { ActionQueue } from "../../../utils/actionQueue";
|
|
3
|
+
/**
|
|
4
|
+
* Declarative action rendered after the offline message (e.g. a retry link)
|
|
5
|
+
*/
|
|
6
|
+
export interface OfflineIndicatorAction {
|
|
7
|
+
label: string;
|
|
8
|
+
onClick: () => void;
|
|
9
|
+
}
|
|
2
10
|
/**
|
|
3
11
|
* Position options for OfflineIndicator
|
|
4
12
|
*/
|
|
@@ -27,6 +35,11 @@ export interface OfflineIndicatorProps {
|
|
|
27
35
|
offlineMessage?: string;
|
|
28
36
|
/** Custom online message (shown briefly when reconnecting) */
|
|
29
37
|
onlineMessage?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Action shown next to the message while offline — pass `{ label, onClick }`
|
|
40
|
+
* for a link-styled button (mirrors Toast's `action`), or any ReactNode.
|
|
41
|
+
*/
|
|
42
|
+
action?: OfflineIndicatorAction | ReactNode;
|
|
30
43
|
/** Additional class names */
|
|
31
44
|
className?: string;
|
|
32
45
|
}
|
|
@@ -38,6 +51,8 @@ export interface OfflineIndicatorTheme {
|
|
|
38
51
|
base?: string;
|
|
39
52
|
/** Position-specific styles */
|
|
40
53
|
positions?: Record<OfflineIndicatorPosition, string>;
|
|
54
|
+
/** Position overrides for the full-bleed banner variant (flush to the viewport edge, no inset) */
|
|
55
|
+
bannerPositions?: Record<OfflineIndicatorPosition, string>;
|
|
41
56
|
/** Variant-specific styles */
|
|
42
57
|
variants?: {
|
|
43
58
|
banner?: string;
|
|
@@ -48,6 +63,8 @@ export interface OfflineIndicatorTheme {
|
|
|
48
63
|
offline?: string;
|
|
49
64
|
/** Online (reconnected) state styles */
|
|
50
65
|
online?: string;
|
|
66
|
+
/** Action link styles */
|
|
67
|
+
action?: string;
|
|
51
68
|
/** Icon styles */
|
|
52
69
|
icon?: string;
|
|
53
70
|
/** Message text styles */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const pageHeadingTheme = {
|
|
2
2
|
baseStyle: "flex flex-col pb-6 mb-6",
|
|
3
3
|
headerStyle: "flex flex-col items-start sm:flex-row sm:items-center gap-4",
|
|
4
|
-
titleStyle: "text-
|
|
4
|
+
titleStyle: "text-[length:var(--page-heading-title-size)] leading-[1.4] font-bold text-[var(--color-text-primary)]",
|
|
5
5
|
subtitleStyle: "text-sm text-[var(--color-text-secondary)] mt-1",
|
|
6
6
|
actionsStyle: "sm:ml-auto flex items-center gap-2 shrink-0",
|
|
7
7
|
iconStyle: "flex items-center justify-center shrink-0 text-[var(--color-text-muted)]",
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default from 'react';
|
|
4
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
|
-
import {
|
|
5
|
+
import { ArrowLeft } from '@phosphor-icons/react';
|
|
6
6
|
import { Link } from '../Link/Link.js';
|
|
7
7
|
|
|
8
8
|
const PageHeadingBackButton = React__default.forwardRef(({ label = "Back", onClick, className, ...props }, ref) => {
|
|
9
|
-
return (jsxs(Link, { ref: ref, color: "
|
|
9
|
+
return (jsxs(Link, { ref: ref, color: "mono", size: "sm", onClick: onClick, className: cn("mb-2 w-fit", className), ...props, children: [jsx(ArrowLeft, { className: "size-4" }), typeof label === 'string'
|
|
10
10
|
? jsx("span", { children: label })
|
|
11
11
|
: label] }));
|
|
12
12
|
});
|
|
@@ -3,7 +3,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
3
3
|
import React__default, { useMemo, useCallback } from 'react';
|
|
4
4
|
import { paginationTheme } from './Pagination.theme.js';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
|
-
import {
|
|
6
|
+
import { CaretDoubleLeft, CaretLeft, CaretRight, CaretDoubleRight } from '@phosphor-icons/react';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Internal PaginationItem component for page numbers and ellipsis
|
|
@@ -83,14 +83,14 @@ const Pagination = React__default.forwardRef(({ currentPage, totalPages, onPageC
|
|
|
83
83
|
// on page 1, or "(totalPages + 1)" on the last page).
|
|
84
84
|
const previousPageLabelNumber = Math.max(currentPage - 1, 1);
|
|
85
85
|
const nextPageLabelNumber = Math.min(currentPage + 1, totalPages);
|
|
86
|
-
return (jsxs("nav", { ref: ref, role: "navigation", "aria-label": "Pagination Navigation", className: cn(theme.baseStyle, className), ...props, children: [showFirstLast && (jsxs(PaginationItem, { size: size, isDisabled: isFirstPage, onClick: () => handlePageChange(1), "aria-label": "Go to first page", children: [jsx(
|
|
86
|
+
return (jsxs("nav", { ref: ref, role: "navigation", "aria-label": "Pagination Navigation", className: cn(theme.baseStyle, className), ...props, children: [showFirstLast && (jsxs(PaginationItem, { size: size, isDisabled: isFirstPage, onClick: () => handlePageChange(1), "aria-label": "Go to first page", children: [jsx(CaretDoubleLeft, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "First" })] })), showPrevNext && (jsxs(PaginationItem, { size: size, isDisabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "aria-label": `Go to previous page (${previousPageLabelNumber})`, children: [jsx(CaretLeft, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Previous" })] })), paginationRange.map((pageNumber, index) => {
|
|
87
87
|
if (pageNumber === "...") {
|
|
88
88
|
return (jsx("span", { role: "separator", "aria-hidden": "true", children: "\u2026" }, `ellipsis-${index}`));
|
|
89
89
|
}
|
|
90
90
|
const page = pageNumber;
|
|
91
91
|
const isActive = page === currentPage;
|
|
92
92
|
return (jsxs(PaginationItem, { size: size, variant: "page", isActive: isActive, onClick: () => handlePageChange(page), "aria-label": isActive ? `Page ${page}, current page` : `Go to page ${page}`, children: [page, isActive && jsx("span", { className: "sr-only", children: "(current)" })] }, page));
|
|
93
|
-
}), showPrevNext && (jsxs(PaginationItem, { size: size, isDisabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "aria-label": `Go to next page (${nextPageLabelNumber})`, children: [jsx(
|
|
93
|
+
}), showPrevNext && (jsxs(PaginationItem, { size: size, isDisabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "aria-label": `Go to next page (${nextPageLabelNumber})`, children: [jsx(CaretRight, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Next" })] })), showFirstLast && (jsxs(PaginationItem, { size: size, isDisabled: isLastPage, onClick: () => handlePageChange(totalPages), "aria-label": "Go to last page", children: [jsx(CaretDoubleRight, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Last" })] }))] }));
|
|
94
94
|
});
|
|
95
95
|
Pagination.displayName = "Pagination";
|
|
96
96
|
|
|
@@ -9,7 +9,7 @@ const paginationTheme = {
|
|
|
9
9
|
// Dark mode: neutral-800 background, lighter text, neutral-600 borders
|
|
10
10
|
itemStyle: "inline-flex items-center justify-center font-medium rounded-[var(--form-radius)] transition-all duration-200 ease-in-out " +
|
|
11
11
|
// Focus styles
|
|
12
|
-
"focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 dark:focus-visible:ring-offset-[var(--color-
|
|
12
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 dark:focus-visible:ring-offset-[var(--color-mono-900)] " +
|
|
13
13
|
// Base state - light
|
|
14
14
|
"cursor-pointer bg-white border border-transparent text-[var(--color-text-muted)] " +
|
|
15
15
|
// Base state - dark
|
|
@@ -21,7 +21,7 @@ const paginationTheme = {
|
|
|
21
21
|
// Active state - light
|
|
22
22
|
"data-[active=true]:bg-white data-[active=true]:border-[var(--color-border)] data-[active=true]:text-[var(--color-text-primary)] " +
|
|
23
23
|
// Active state - dark (uses primary color accent)
|
|
24
|
-
"dark:data-[active=true]:bg-[var(--color-
|
|
24
|
+
"dark:data-[active=true]:bg-[var(--color-mono-800)] dark:data-[active=true]:border-none dark:data-[active=true]:text-[var(--color-text-primary)] " +
|
|
25
25
|
// Disabled state
|
|
26
26
|
"data-[disabled=true]:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:pointer-events-none",
|
|
27
27
|
// Unified item sizes
|
|
@@ -30,7 +30,7 @@ const paginationTheme = {
|
|
|
30
30
|
md: "size-10 min-w-[2.5rem] text-sm",
|
|
31
31
|
},
|
|
32
32
|
// Ellipsis styles
|
|
33
|
-
ellipsisStyle: "inline-flex items-center justify-center font-medium text-[var(--color-text-muted)]
|
|
33
|
+
ellipsisStyle: "inline-flex items-center justify-center font-medium text-[var(--color-text-muted)] cursor-default pointer-events-none",
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
export { paginationTheme };
|
|
@@ -3,9 +3,11 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
3
3
|
import React__default, { useState, useEffect, useCallback } from 'react';
|
|
4
4
|
import { useReducedMotion, motion } from 'motion/react';
|
|
5
5
|
import { pillTheme } from './Pill.theme.js';
|
|
6
|
-
import {
|
|
6
|
+
import { createPressVariants } from '../shared/interaction.animations.js';
|
|
7
7
|
import { cn } from '../../../utils/cn.js';
|
|
8
8
|
|
|
9
|
+
// Shared press physics + subtle hover lift (module-level constant)
|
|
10
|
+
const PILL_PRESS_VARIANTS = createPressVariants(0.97, 1.02);
|
|
9
11
|
/**
|
|
10
12
|
* Pill component - Simplified selectable chip for filters and tags
|
|
11
13
|
*
|
|
@@ -120,7 +122,7 @@ const Pill = React__default.forwardRef((props, ref) => {
|
|
|
120
122
|
// Accessibility
|
|
121
123
|
role: isSelectable && !readOnly ? "button" : undefined, tabIndex: isInteractive ? 0 : undefined, "aria-pressed": isSelectable && !readOnly ? isSelected : undefined, "aria-readonly": readOnly || undefined,
|
|
122
124
|
// Animation
|
|
123
|
-
whileTap: isInteractive && !shouldReduceMotion ?
|
|
125
|
+
variants: PILL_PRESS_VARIANTS, animate: "rest", whileHover: isInteractive && !shouldReduceMotion ? "hover" : undefined, whileTap: isInteractive && !shouldReduceMotion ? "press" : undefined, ...restProps, children: [renderStartIcon(), children] }));
|
|
124
126
|
});
|
|
125
127
|
Pill.displayName = "Pill";
|
|
126
128
|
|
|
@@ -9,7 +9,7 @@ const pillTheme = {
|
|
|
9
9
|
* Base pill style - structure and default colors (no hover)
|
|
10
10
|
*/
|
|
11
11
|
baseStyle: "inline-flex items-center justify-center font-medium rounded-full select-none whitespace-nowrap " +
|
|
12
|
-
"ring-1 bg-[var(--color-surface)] transition-
|
|
12
|
+
"ring-1 bg-[var(--color-surface)] transition-[color,background-color,box-shadow] duration-150 ease-out " +
|
|
13
13
|
"text-[var(--color-text-primary)] ring-[var(--color-border)] " +
|
|
14
14
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]",
|
|
15
15
|
/**
|
|
@@ -26,10 +26,12 @@ const pillTheme = {
|
|
|
26
26
|
/**
|
|
27
27
|
* Size variants
|
|
28
28
|
*/
|
|
29
|
+
// Paddings tokenised (--pill-px-*/--pill-py-*) so a theme can grow the chip
|
|
30
|
+
// tier alongside its controls — defaults are px-2.5/px-3 + py-0.5/py-1.
|
|
29
31
|
sizes: {
|
|
30
|
-
sm: "text-xs px-
|
|
31
|
-
md: "text-sm px-
|
|
32
|
-
lg: "text-sm px-
|
|
32
|
+
sm: "text-xs px-[var(--pill-px-sm)] py-[var(--pill-py-sm)] gap-0.5",
|
|
33
|
+
md: "text-sm px-[var(--pill-px-md)] py-[var(--pill-py-md)] gap-1",
|
|
34
|
+
lg: "text-sm px-[var(--pill-px-lg)] py-[var(--pill-py-lg)] gap-1.5",
|
|
33
35
|
},
|
|
34
36
|
/**
|
|
35
37
|
* Icon sizes for iconStart and CheckIcon
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import React__default, { useState, useMemo, useCallback } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
import { StarIcon as StarIcon$1 } from '@heroicons/react/24/outline';
|
|
4
|
+
import { Star } from '@phosphor-icons/react';
|
|
6
5
|
import { cn } from '../../../utils/cn.js';
|
|
7
6
|
import { ratingTheme } from './Rating.theme.js';
|
|
8
7
|
|
|
@@ -147,14 +146,14 @@ const Rating = React__default.memo(React__default.forwardRef(({ value: controlle
|
|
|
147
146
|
// Determine which icon to render based on fill state
|
|
148
147
|
const renderStarIcon = () => {
|
|
149
148
|
if (fillState === "full") {
|
|
150
|
-
return iconFilled ? (jsx("span", { className: cn(starSizeClass, filledColorClass), "aria-hidden": "true", children: iconFilled })) : (jsx(
|
|
149
|
+
return iconFilled ? (jsx("span", { className: cn(starSizeClass, filledColorClass), "aria-hidden": "true", children: iconFilled })) : (jsx(Star, { className: cn(starSizeClass, filledColorClass), "aria-hidden": "true" }));
|
|
151
150
|
}
|
|
152
151
|
if (fillState === "half") {
|
|
153
152
|
// Half star: clip a filled star to the left half, overlay on empty star
|
|
154
|
-
return (jsxs("span", { className: cn("relative inline-flex", starSizeClass), "aria-hidden": "true", children: [iconEmpty ? (jsx("span", { className: cn("absolute inset-0", emptyColorClass), children: iconEmpty })) : (jsx(
|
|
153
|
+
return (jsxs("span", { className: cn("relative inline-flex", starSizeClass), "aria-hidden": "true", children: [iconEmpty ? (jsx("span", { className: cn("absolute inset-0", emptyColorClass), children: iconEmpty })) : (jsx(Star, { className: cn("absolute inset-0", starSizeClass, emptyColorClass) })), jsx("span", { className: "absolute inset-0 overflow-hidden", style: { width: "50%" }, children: iconFilled ? (jsx("span", { className: cn(filledColorClass), children: iconFilled })) : (jsx(Star, { className: cn(starSizeClass, filledColorClass) })) })] }));
|
|
155
154
|
}
|
|
156
155
|
// Empty star
|
|
157
|
-
return iconEmpty ? (jsx("span", { className: cn(starSizeClass, emptyColorClass), "aria-hidden": "true", children: iconEmpty })) : (jsx(
|
|
156
|
+
return iconEmpty ? (jsx("span", { className: cn(starSizeClass, emptyColorClass), "aria-hidden": "true", children: iconEmpty })) : (jsx(Star, { className: cn(starSizeClass, emptyColorClass), "aria-hidden": "true" }));
|
|
158
157
|
};
|
|
159
158
|
if (!isInteractive) {
|
|
160
159
|
// Read-only or disabled: render as a non-interactive span
|
|
@@ -27,7 +27,7 @@ const ratingTheme = {
|
|
|
27
27
|
danger: "text-[var(--color-danger)]",
|
|
28
28
|
},
|
|
29
29
|
// Empty star color
|
|
30
|
-
emptyColor: "text-[var(--color-
|
|
30
|
+
emptyColor: "text-[var(--color-mono-300)]",
|
|
31
31
|
// State styles
|
|
32
32
|
states: {
|
|
33
33
|
disabled: "opacity-50 cursor-not-allowed pointer-events-none",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
const segmentedTheme = {
|
|
5
5
|
// Base styles for the segmented container
|
|
6
|
-
baseStyle: "relative flex rounded-[var(--segmented-radius)] bg-
|
|
6
|
+
baseStyle: "relative flex w-fit rounded-[var(--segmented-radius)] bg-[var(--color-surface-sunken)] border border-[var(--color-border)] p-[var(--segmented-padding)] shadow-inner-real-md",
|
|
7
7
|
// Size variants using CSS variables
|
|
8
8
|
sizes: {
|
|
9
9
|
sm: "min-h-[var(--segmented-min-h-sm)]",
|
|
@@ -15,7 +15,7 @@ const segmentedTheme = {
|
|
|
15
15
|
// Disabled style
|
|
16
16
|
disabledStyle: "opacity-50 cursor-not-allowed pointer-events-none",
|
|
17
17
|
// Sliding background style with CSS variables
|
|
18
|
-
slidingBackgroundStyle: "absolute top-[0px] left-[0px] rounded-[var(--segmented-inner-radius)] transition-transform duration-200 ease-out pointer-events-none z-0 bg-[var(--color-surface)] shadow-real-md
|
|
18
|
+
slidingBackgroundStyle: "absolute top-[0px] left-[0px] rounded-[var(--segmented-inner-radius)] transition-transform duration-200 ease-out pointer-events-none z-0 bg-[var(--color-surface)] shadow-real-md",
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
21
|
* Default theme for the SegmentedItem component
|
|
@@ -23,11 +23,14 @@ const segmentedTheme = {
|
|
|
23
23
|
const segmentedItemTheme = {
|
|
24
24
|
// Base styles for the segmented item
|
|
25
25
|
baseStyle: "relative flex min-w-fit flex-1 items-center justify-center whitespace-nowrap transition-all duration-200 rounded-[var(--segmented-inner-radius)] font-medium cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary-500)] focus-visible:ring-offset-1",
|
|
26
|
-
// Size variants using CSS variables
|
|
26
|
+
// Size variants using CSS variables. Type reads --segmented-text-size-*
|
|
27
|
+
// (which aliases the shared --form-text-size-* ramp) so lg steps up with its
|
|
28
|
+
// box — it was pinned at text-sm across all three sizes while Button/Input,
|
|
29
|
+
// whose height tokens Segmented literally aliases, both stepped up at lg.
|
|
27
30
|
sizes: {
|
|
28
|
-
sm: "text-sm px-[var(--segmented-px-sm)]",
|
|
29
|
-
md: "text-
|
|
30
|
-
lg: "text-
|
|
31
|
+
sm: "text-[length:var(--segmented-text-size-sm)]/[var(--segmented-line-height-sm)] px-[var(--segmented-px-sm)]",
|
|
32
|
+
md: "text-[length:var(--segmented-text-size-md)]/[var(--segmented-line-height-md)] px-[var(--segmented-px-md)]",
|
|
33
|
+
lg: "text-[length:var(--segmented-text-size-lg)]/[var(--segmented-line-height-lg)] px-[var(--segmented-px-lg)]",
|
|
31
34
|
},
|
|
32
35
|
// Selected state
|
|
33
36
|
selectedStyle: "text-[var(--color-text-primary)] z-10",
|
|
@@ -133,11 +133,13 @@ export interface SidebarNavGroupProps extends React.HTMLAttributes<HTMLDivElemen
|
|
|
133
133
|
}
|
|
134
134
|
export interface SidebarToggleProps extends React.HTMLAttributes<HTMLButtonElement> {
|
|
135
135
|
/**
|
|
136
|
-
*
|
|
136
|
+
* Icon shown while the sidebar is COLLAPSED — clicking it expands.
|
|
137
|
+
* Falls back to the default chevron.
|
|
137
138
|
*/
|
|
138
139
|
expandIcon?: ReactNode;
|
|
139
140
|
/**
|
|
140
|
-
*
|
|
141
|
+
* Icon shown while the sidebar is EXPANDED — clicking it collapses.
|
|
142
|
+
* Falls back to the default chevron.
|
|
141
143
|
*/
|
|
142
144
|
collapseIcon?: ReactNode;
|
|
143
145
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import React__default from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { X } from '@phosphor-icons/react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { useSidebarContext, useSidebarCollapsed } from './SidebarContext.js';
|
|
7
7
|
import { SidebarToggle } from './SidebarToggle.js';
|
|
@@ -22,7 +22,7 @@ const SidebarHeader = React__default.forwardRef(({ logo, showToggle = true, cust
|
|
|
22
22
|
// fills the interior exactly. Left-pinned in both states (no
|
|
23
23
|
// `justify-*` toggle) so nothing jumps mid-animation. Same value
|
|
24
24
|
// for collapsed + expanded → no padding transition needed.
|
|
25
|
-
"px-3", className), ...props, children: [jsx("div", { className: "flex items-center min-w-0 flex-1", children: logo }), isMobile && isMobileOpen && (jsx(Button, { variant: "ghost", size: "sm", className: "size-7 p-0 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]", onClick: () => sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.setMobileOpen(false), "aria-label": "Close navigation", children: jsx(
|
|
25
|
+
"px-3", className), ...props, children: [jsx("div", { className: "flex items-center min-w-0 flex-1", children: logo }), isMobile && isMobileOpen && (jsx(Button, { variant: "ghost", size: "sm", className: "size-7 p-0 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]", onClick: () => sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.setMobileOpen(false), "aria-label": "Close navigation", children: jsx(X, { className: "size-4" }) })), !isMobile && showToggle && (customToggle || jsx(SidebarToggle, {}))] }));
|
|
26
26
|
});
|
|
27
27
|
SidebarHeader.displayName = "SidebarHeader";
|
|
28
28
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { List } from '@phosphor-icons/react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { useSidebarContext } from './SidebarContext.js';
|
|
7
7
|
import { Button } from '../Button/Button.js';
|
|
@@ -23,7 +23,7 @@ const SidebarMobileTrigger = React__default.forwardRef(({ icon, className, onCli
|
|
|
23
23
|
onClick === null || onClick === void 0 ? void 0 : onClick(e);
|
|
24
24
|
};
|
|
25
25
|
const { onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, color: _color, ...buttonProps } = props;
|
|
26
|
-
return (jsx(Button, { ref: ref, variant: "soft", size: "sm", className: cn("size-9 p-0", className), onClick: handleClick, "aria-label": "Open navigation menu", ...buttonProps, children: icon || jsx(
|
|
26
|
+
return (jsx(Button, { ref: ref, variant: "soft", size: "sm", className: cn("size-9 p-0", className), onClick: handleClick, "aria-label": "Open navigation menu", ...buttonProps, children: icon || jsx(List, { className: "size-5" }) }));
|
|
27
27
|
});
|
|
28
28
|
SidebarMobileTrigger.displayName = "SidebarMobileTrigger";
|
|
29
29
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default, { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { motion, AnimatePresence } from 'motion/react';
|
|
5
|
-
import {
|
|
5
|
+
import { MagnifyingGlass } from '@phosphor-icons/react';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { Tooltip } from '../Tooltip/Tooltip.js';
|
|
8
8
|
import '../Tooltip/Tooltip.animations.js';
|
|
@@ -106,7 +106,7 @@ const SidebarSearch = React__default.forwardRef(({ value: controlledValue, defau
|
|
|
106
106
|
// width) and the input fading in/out via AnimatePresence. Adding
|
|
107
107
|
// a justify-* toggle here would snap the icon by 4px on frame 0
|
|
108
108
|
// of every transition.
|
|
109
|
-
"transition-[background-color,box-shadow] duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]", "overflow-hidden", isCollapsedView ? shellCollapsed : shellExpanded, inputGroupClassName), children: [jsx("span", { className: cn("flex items-center justify-center flex-shrink-0 pl-2", "text-[var(--color-text-muted)] transition-colors duration-200"), "aria-hidden": !isCollapsedView || undefined, children: iconStart !== null && iconStart !== void 0 ? iconStart : jsx(
|
|
109
|
+
"transition-[background-color,box-shadow] duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]", "overflow-hidden", isCollapsedView ? shellCollapsed : shellExpanded, inputGroupClassName), children: [jsx("span", { className: cn("flex items-center justify-center flex-shrink-0 pl-2", "text-[var(--color-text-muted)] transition-colors duration-200"), "aria-hidden": !isCollapsedView || undefined, children: iconStart !== null && iconStart !== void 0 ? iconStart : jsx(MagnifyingGlass, { className: "size-5" }) }), jsx(AnimatePresence, { initial: false, children: !isCollapsedView && (jsx(motion.div, { initial: { opacity: 0, x: -4 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -4 }, transition: {
|
|
110
110
|
opacity: { duration: 0.15, ease: [0.4, 0, 0.2, 1] },
|
|
111
111
|
x: { duration: 0.2, ease: [0.4, 0, 0.2, 1] },
|
|
112
112
|
}, className: "flex-1 min-w-0 flex items-center overflow-hidden", children: jsx("input", { ref: setInputRef, type: "search", value: value, onChange: handleChange, placeholder: placeholder, "aria-label": collapsedLabel, className: cn(
|
|
@@ -114,7 +114,7 @@ const SidebarSearch = React__default.forwardRef(({ value: controlledValue, defau
|
|
|
114
114
|
// Input pl-3 (12) → text starts at field-x = 28 + 12 = 40,
|
|
115
115
|
// giving a 12px icon→text gap (matches <Input iconStart>'s
|
|
116
116
|
// pl-3 + pl-10 = 12px convention).
|
|
117
|
-
"w-full bg-transparent border-0 outline-none text-sm py-2 pl-3 pr-3", "text-[var(--color-text-primary)] placeholder:text-[var(--color-text-placeholder)]"
|
|
117
|
+
"w-full bg-transparent border-0 outline-none text-sm py-2 pl-3 pr-3", "text-[var(--color-text-primary)] placeholder:text-[var(--color-text-placeholder)]") }) }, "search-input")) })] }));
|
|
118
118
|
return (
|
|
119
119
|
// Outer horizontal padding mirrors Sidebar.Content (px-3 collapsed,
|
|
120
120
|
// px-2.5 expanded) so the search row sits on the exact same horizontal
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { CaretLeft } from '@phosphor-icons/react';
|
|
5
5
|
import { motion } from 'motion/react';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { useSidebarContext } from './SidebarContext.js';
|
|
8
8
|
import { Button } from '../Button/Button.js';
|
|
9
9
|
|
|
10
10
|
const SidebarToggle = React__default.forwardRef(({ expandIcon, collapseIcon, className, onClick, ...props }, ref) => {
|
|
11
|
-
var _a;
|
|
11
|
+
var _a, _b;
|
|
12
12
|
const sidebarContext = useSidebarContext();
|
|
13
13
|
if (!sidebarContext) {
|
|
14
14
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -26,7 +26,7 @@ const SidebarToggle = React__default.forwardRef(({ expandIcon, collapseIcon, cla
|
|
|
26
26
|
const positionClasses = side === "left"
|
|
27
27
|
? "absolute right-0 translate-x-1/2 top-4 z-50"
|
|
28
28
|
: "absolute left-0 -translate-x-1/2 top-4 z-50";
|
|
29
|
-
return (jsx(Button, { ref: ref, iconOnly: true, variant: "ghost", className: cn("size-6 p-0 rounded-full border border-[var(--color-border)] bg-[var(--color-background)]/50 backdrop-blur-sm text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:shadow-md hover:bg-[var(--color-surface-hover)] opacity-100 transition-all duration-400", positionClasses, className), onClick: handleClick, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", title: collapsed ? "Expand sidebar" : "Collapse sidebar", ...buttonProps, children: jsx(motion.div, { initial: false, animate: { rotate: collapsed ? 180 : 0 }, transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, className: "flex items-center justify-center", children: jsx(
|
|
29
|
+
return (jsx(Button, { ref: ref, iconOnly: true, variant: "ghost", className: cn("size-6 p-0 rounded-full border border-[var(--color-border)] bg-[var(--color-background)]/50 backdrop-blur-sm text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:shadow-md hover:bg-[var(--color-surface-hover)] opacity-100 transition-all duration-400", positionClasses, className), onClick: handleClick, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", title: collapsed ? "Expand sidebar" : "Collapse sidebar", ...buttonProps, children: (_b = (collapsed ? expandIcon : collapseIcon)) !== null && _b !== void 0 ? _b : (jsx(motion.div, { initial: false, animate: { rotate: collapsed ? 180 : 0 }, transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, className: "flex items-center justify-center", children: jsx(CaretLeft, { className: "size-3", weight: "bold" }) })) }));
|
|
30
30
|
});
|
|
31
31
|
SidebarToggle.displayName = "SidebarToggle";
|
|
32
32
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import React__default from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { CaretUpDown } from '@phosphor-icons/react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { motion, AnimatePresence } from 'motion/react';
|
|
7
7
|
import { useSidebarCollapsed } from './SidebarContext.js';
|
|
@@ -37,7 +37,7 @@ const SidebarUserProfile = React__default.forwardRef(({ name, email, avatar, sta
|
|
|
37
37
|
className: "flex-shrink-0", children: avatarElement }), jsx(AnimatePresence, { initial: false, children: !isCollapsedView && (jsxs(motion.div, { className: "flex flex-row items-center gap-2 flex-1 min-w-0 overflow-hidden whitespace-nowrap", initial: { opacity: 0, x: -4 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -4 }, transition: {
|
|
38
38
|
opacity: { duration: 0.15, ease: [0.4, 0, 0.2, 1] },
|
|
39
39
|
x: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }
|
|
40
|
-
}, children: [children !== null && children !== void 0 ? children : (jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name }), email && (jsx("div", { className: "text-xs text-[var(--color-text-secondary)]/80 truncate", children: email }))] })), dropdownContent && (jsx(
|
|
40
|
+
}, children: [children !== null && children !== void 0 ? children : (jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name }), email && (jsx("div", { className: "text-xs text-[var(--color-text-secondary)]/80 truncate", children: email }))] })), dropdownContent && (jsx(CaretUpDown, { className: "size-4 flex-shrink-0 text-[var(--color-text-muted)]" }))] }, "profile-text")) })] }));
|
|
41
41
|
// When dropdownContent is provided, the profile acts as a menu trigger.
|
|
42
42
|
if (dropdownContent) {
|
|
43
43
|
return (jsxs(Dropdown, { placement: "right-end", offset: 8, children: [jsx(Dropdown.Trigger, { children: content }), jsx(Dropdown.Menu, { "aria-label": `${name} menu`, children: dropdownContent })] }));
|