@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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default, { createContext, useState, useRef, useId, useMemo, useCallback, useEffect, useContext } from 'react';
|
|
4
4
|
import { Reorder, useDragControls, motion } from 'motion/react';
|
|
5
|
-
import {
|
|
5
|
+
import { Lock, List } from '@phosphor-icons/react';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { sortableTheme } from './Sortable.theme.js';
|
|
8
8
|
import { sortableAnimations } from './Sortable.animations.js';
|
|
@@ -212,7 +212,7 @@ const SortableItem = React__default.forwardRef(({ id, children, className, theme
|
|
|
212
212
|
}
|
|
213
213
|
}, value: value || id, id: id, dragListener: !context.showDragHandle && !disabled, dragControls: context.showDragHandle ? dragControls : undefined, onDragStart: handleDragStart, onDragEnd: handleDragEnd, onPointerDown: handlePointerDown, tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown, onFocus: () => setIsFocused(true), onBlur: () => setIsFocused(false), className: cn(theme.itemStyle, context.showDragHandle && 'flex items-center gap-2', disabled && 'opacity-50 cursor-not-allowed', !disabled && !context.showDragHandle && 'cursor-grab active:cursor-grabbing', isBeingDragged && 'shadow-lg z-50', isFocused && !disabled && 'ring-2 ring-blue-500 ring-offset-2', className), style: {
|
|
214
214
|
position: 'relative',
|
|
215
|
-
}, variants: sortableAnimations.variants, animate: isBeingDragged ? 'dragging' : 'idle', transition: sortableAnimations.layout.layout, children: [context.showDragHandle && (jsx(motion.div, { onPointerDown: handleDragHandlePointerDown, className: cn(theme.dragHandleStyle, disabled && 'cursor-not-allowed opacity-60', !disabled && 'cursor-grab active:cursor-grabbing'), whileHover: !disabled ? sortableAnimations.dragHandle.hover : undefined, whileTap: !disabled ? sortableAnimations.dragHandle.tap : undefined, children: disabled ? (jsx(
|
|
215
|
+
}, variants: sortableAnimations.variants, animate: isBeingDragged ? 'dragging' : 'idle', transition: sortableAnimations.layout.layout, children: [context.showDragHandle && (jsx(motion.div, { onPointerDown: handleDragHandlePointerDown, className: cn(theme.dragHandleStyle, disabled && 'cursor-not-allowed opacity-60', !disabled && 'cursor-grab active:cursor-grabbing'), whileHover: !disabled ? sortableAnimations.dragHandle.hover : undefined, whileTap: !disabled ? sortableAnimations.dragHandle.tap : undefined, children: disabled ? (jsx(Lock, { className: "w-4 h-4 text-gray-500" })) : (jsx(List, { className: "w-4 h-4" })) })), jsx("div", { className: "flex-1", children: children })] }));
|
|
216
216
|
});
|
|
217
217
|
SortableItem.displayName = 'SortableItem';
|
|
218
218
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default from 'react';
|
|
4
4
|
import { motion } from 'motion/react';
|
|
5
|
-
import {
|
|
5
|
+
import { X } from '@phosphor-icons/react';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { Avatar } from '../Avatar/Avatar.js';
|
|
8
8
|
import { tagTheme } from './Tag.theme.js';
|
|
@@ -64,7 +64,7 @@ const Tag = React__default.forwardRef(({ children, size = "md", removable = true
|
|
|
64
64
|
}
|
|
65
65
|
return null;
|
|
66
66
|
};
|
|
67
|
-
const content = (jsxs(Fragment, { children: [renderLeadingContent(), children, showRemoveButton && (jsx("button", { type: "button", onClick: handleRemove, className: theme.removeButtonStyle, "aria-label": `Remove ${typeof children === "string" ? children : "tag"}`, children: jsx(
|
|
67
|
+
const content = (jsxs(Fragment, { children: [renderLeadingContent(), children, showRemoveButton && (jsx("button", { type: "button", onClick: handleRemove, className: theme.removeButtonStyle, "aria-label": `Remove ${typeof children === "string" ? children : "tag"}`, children: jsx(X, { className: theme.removeIconSizes[size] }) }))] }));
|
|
68
68
|
const sharedProps = {
|
|
69
69
|
ref,
|
|
70
70
|
className: cn(theme.baseStyle, theme.sizes[size], hasLeadingContent && "pl-1", showRemoveButton && "pr-0.5", disabled && theme.disabledStyle, className),
|
|
@@ -2,9 +2,11 @@ const tagTheme = {
|
|
|
2
2
|
baseStyle: "inline-flex items-center gap-1.5 font-medium rounded-full " +
|
|
3
3
|
"bg-[var(--color-surface-raised)] border border-[var(--color-border)] " +
|
|
4
4
|
"text-[var(--color-text-primary)]",
|
|
5
|
+
// Paddings tokenised (--tag-px-*/--tag-py-*, + --tag-pl-md for md's larger
|
|
6
|
+
// left inset) so a theme can grow the chip tier — defaults px-2/px-2+pl-2.5.
|
|
5
7
|
sizes: {
|
|
6
|
-
sm: "text-xs px-
|
|
7
|
-
md: "text-sm px-
|
|
8
|
+
sm: "text-xs px-[var(--tag-px-sm)] py-[var(--tag-py-sm)]",
|
|
9
|
+
md: "text-sm px-[var(--tag-px-md)] pl-[var(--tag-pl-md)] py-[var(--tag-py-md)]",
|
|
8
10
|
},
|
|
9
11
|
// No left margin here: the avatar/icon's left inset is owned by the tag's
|
|
10
12
|
// `pl-1` (applied when there's leading content), not by a per-size `ml-*`.
|
|
@@ -6,7 +6,7 @@ import { cn } from '../../../utils/cn.js';
|
|
|
6
6
|
import { useSurfaceElevation, SurfaceProvider, surfaceClasses } from '../../../theme/SurfaceContext.js';
|
|
7
7
|
import { toastTheme } from './Toast.theme.js';
|
|
8
8
|
import { getToastStackingAnimation, toastAnimations } from './Toast.animations.js';
|
|
9
|
-
import {
|
|
9
|
+
import { ArrowsClockwise, Info, X } from '@phosphor-icons/react';
|
|
10
10
|
import { Link } from '../Link/Link.js';
|
|
11
11
|
|
|
12
12
|
const isToastAction = (action) => typeof action === "object" &&
|
|
@@ -40,7 +40,7 @@ const Toast = React__default.forwardRef(({ toast, className, onDismiss, index =
|
|
|
40
40
|
// so assistive tech announces it exactly once, using this more specific
|
|
41
41
|
// role/urgency rather than the container's generic "polite" default.
|
|
42
42
|
const toastRole = color === "danger" || color === "warning" ? "alert" : "status";
|
|
43
|
-
const defaultIcon = state === "loading" ? (jsx(motion.div, { animate: { rotate: 360 }, transition: { repeat: Infinity, duration: 1, ease: "linear" }, children: jsx(
|
|
43
|
+
const defaultIcon = state === "loading" ? (jsx(motion.div, { animate: { rotate: 360 }, transition: { repeat: Infinity, duration: 1, ease: "linear" }, children: jsx(ArrowsClockwise, { className: "w-5 h-5" }) })) : (jsx(Info, { className: "w-5 h-5" }));
|
|
44
44
|
const resolvedIcon = icon || defaultIcon;
|
|
45
45
|
// Auto-dismiss after duration (pauses when hovered/expanded, then RESUMES the remaining
|
|
46
46
|
// time rather than restarting the full countdown — otherwise intermittent hover keeps
|
|
@@ -108,7 +108,7 @@ const Toast = React__default.forwardRef(({ toast, className, onDismiss, index =
|
|
|
108
108
|
}, [stackingStyle.zIndex, index, position]);
|
|
109
109
|
const toastNode = (jsx(motion.div, { ref: setRefs, role: toastRole, layout: true, initial: shouldReduceMotion ? false : toastAnimations.initial, animate: animateValue, exit: shouldReduceMotion
|
|
110
110
|
? { ...toastAnimations.exit, transition: { duration: 0 } }
|
|
111
|
-
: toastAnimations.exit, transition: shouldReduceMotion ? { duration: 0 } : toastAnimations.transition, className: cn(surfaceClasses(surfaceLevel, { translucent: true, shadow: true }), toastTheme.baseStyle, isTextOnly && "items-center", "pointer-events-auto", index > 0 && !isExpanded && "absolute top-0 left-0", className), style: styleValue, children: jsxs(SurfaceProvider, { level: surfaceLevel, children: [jsx("div", { className: cn(toastTheme.iconStyle, !isTextOnly && "mt-0.5"), children: resolvedIcon }), jsxs("div", { className: "flex-1 min-w-0", children: [title && jsx("div", { className: toastTheme.titleStyle, children: title }), subtitle && (jsx("div", { className: toastTheme.subtitleStyle, children: subtitle })), action && (jsx("div", { className: "mt-4", children: isToastAction(action) ? (jsx(Link, { color: "primary", size: "sm", onClick: handleActionClick, children: action.label })) : (action) })), children] }), dismissible && (jsx("button", { type: "button", className: cn(toastTheme.closeButtonStyle, !isTextOnly && "mt-0.5"), onClick: handleDismiss, "aria-label": "Dismiss notification", children: jsx(
|
|
111
|
+
: toastAnimations.exit, transition: shouldReduceMotion ? { duration: 0 } : toastAnimations.transition, className: cn(surfaceClasses(surfaceLevel, { translucent: true, shadow: true }), toastTheme.baseStyle, isTextOnly && "items-center", "pointer-events-auto", index > 0 && !isExpanded && "absolute top-0 left-0", className), style: styleValue, children: jsxs(SurfaceProvider, { level: surfaceLevel, children: [jsx("div", { className: cn(toastTheme.iconStyle, !isTextOnly && "mt-0.5"), children: resolvedIcon }), jsxs("div", { className: "flex-1 min-w-0", children: [title && jsx("div", { className: toastTheme.titleStyle, children: title }), subtitle && (jsx("div", { className: toastTheme.subtitleStyle, children: subtitle })), action && (jsx("div", { className: "mt-4", children: isToastAction(action) ? (jsx(Link, { color: "primary", size: "sm", onClick: handleActionClick, children: action.label })) : (action) })), children] }), dismissible && (jsx("button", { type: "button", className: cn(toastTheme.closeButtonStyle, !isTextOnly && "mt-0.5"), onClick: handleDismiss, "aria-label": "Dismiss notification", children: jsx(X, { className: "size-5" }) }))] }) }));
|
|
112
112
|
if (darkMode) {
|
|
113
113
|
return jsx("div", { className: "dark", children: toastNode });
|
|
114
114
|
}
|
|
@@ -25,7 +25,7 @@ export interface ToastData {
|
|
|
25
25
|
* Semantic severity of the toast. Drives the per-toast live-region role
|
|
26
26
|
* (`danger`/`warning` -> `role="alert"`, everything else -> `role="status"`)
|
|
27
27
|
* as well as `useToast()`'s convenience-method icon color.
|
|
28
|
-
* @default "
|
|
28
|
+
* @default "mono"
|
|
29
29
|
*/
|
|
30
30
|
color?: SemanticColor;
|
|
31
31
|
title?: ReactNode;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import React__default, { useCallback } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { Info, Warning, XCircle, CheckCircle } from '@phosphor-icons/react';
|
|
4
4
|
import { useToastContext } from './ToastProvider.js';
|
|
5
5
|
|
|
6
6
|
const createSemanticIcon = (IconComponent, colorClass) => {
|
|
@@ -30,7 +30,7 @@ const useToast = () => {
|
|
|
30
30
|
duration: options === null || options === void 0 ? void 0 : options.duration,
|
|
31
31
|
dismissible: options === null || options === void 0 ? void 0 : options.dismissible,
|
|
32
32
|
action: options === null || options === void 0 ? void 0 : options.action,
|
|
33
|
-
icon: (options === null || options === void 0 ? void 0 : options.icon) || createSemanticIcon(
|
|
33
|
+
icon: (options === null || options === void 0 ? void 0 : options.icon) || createSemanticIcon(CheckCircle, 'text-[var(--color-success)]'),
|
|
34
34
|
});
|
|
35
35
|
}, [addToast]);
|
|
36
36
|
const error = useCallback((title, options) => {
|
|
@@ -42,7 +42,7 @@ const useToast = () => {
|
|
|
42
42
|
duration: options === null || options === void 0 ? void 0 : options.duration,
|
|
43
43
|
dismissible: options === null || options === void 0 ? void 0 : options.dismissible,
|
|
44
44
|
action: options === null || options === void 0 ? void 0 : options.action,
|
|
45
|
-
icon: (options === null || options === void 0 ? void 0 : options.icon) || createSemanticIcon(
|
|
45
|
+
icon: (options === null || options === void 0 ? void 0 : options.icon) || createSemanticIcon(XCircle, 'text-[var(--color-danger)]'),
|
|
46
46
|
});
|
|
47
47
|
}, [addToast]);
|
|
48
48
|
const warning = useCallback((title, options) => {
|
|
@@ -54,7 +54,7 @@ const useToast = () => {
|
|
|
54
54
|
duration: options === null || options === void 0 ? void 0 : options.duration,
|
|
55
55
|
dismissible: options === null || options === void 0 ? void 0 : options.dismissible,
|
|
56
56
|
action: options === null || options === void 0 ? void 0 : options.action,
|
|
57
|
-
icon: (options === null || options === void 0 ? void 0 : options.icon) || createSemanticIcon(
|
|
57
|
+
icon: (options === null || options === void 0 ? void 0 : options.icon) || createSemanticIcon(Warning, 'text-[var(--color-warning)]'),
|
|
58
58
|
});
|
|
59
59
|
}, [addToast]);
|
|
60
60
|
const info = useCallback((title, options) => {
|
|
@@ -66,7 +66,7 @@ const useToast = () => {
|
|
|
66
66
|
duration: options === null || options === void 0 ? void 0 : options.duration,
|
|
67
67
|
dismissible: options === null || options === void 0 ? void 0 : options.dismissible,
|
|
68
68
|
action: options === null || options === void 0 ? void 0 : options.action,
|
|
69
|
-
icon: (options === null || options === void 0 ? void 0 : options.icon) || createSemanticIcon(
|
|
69
|
+
icon: (options === null || options === void 0 ? void 0 : options.icon) || createSemanticIcon(Info, 'text-[var(--color-primary)]'),
|
|
70
70
|
});
|
|
71
71
|
}, [addToast]);
|
|
72
72
|
const loading = useCallback((title, options) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TooltipProps } from "./Tooltip.types";
|
|
2
2
|
declare const Tooltip: {
|
|
3
|
-
({ content, children, placement, delay, disabled, className, triggerClassName, maxWidth, minWidth, showOnFocus, wrapText, id, theme: themeOverrides, "aria-label": ariaLabel, role, offset, darkMode, elevation, lift, }: TooltipProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
({ content, children, placement, delay, disabled, className, triggerClassName, maxWidth, minWidth, showOnFocus, wrapText, id, theme: themeOverrides, "aria-label": ariaLabel, role, offset, darkMode, elevation, lift, isOpen, defaultIsOpen, onOpenChange, recalcTrigger, }: TooltipProps): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
displayName: string;
|
|
5
5
|
};
|
|
6
6
|
export { Tooltip };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import React__default, { useId, useState,
|
|
3
|
+
import React__default, { useId, useState, useCallback, useRef, useEffect } from 'react';
|
|
4
4
|
import { useReducedMotion, AnimatePresence, motion } from 'motion/react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
@@ -11,7 +11,7 @@ import { useIsClient } from '../../../hooks/useIsClient.js';
|
|
|
11
11
|
import { useDarkMode } from '../../../hooks/useDarkMode.js';
|
|
12
12
|
import { useSurfaceElevation, SurfaceProvider, surfaceClasses } from '../../../theme/SurfaceContext.js';
|
|
13
13
|
|
|
14
|
-
const Tooltip = ({ content, children, placement = "top", delay = 300, disabled = false, className, triggerClassName, maxWidth = "360px", minWidth = "fit-content", showOnFocus = true, wrapText = false, id, theme: themeOverrides, "aria-label": ariaLabel, role = "tooltip", offset = 8, darkMode = false, elevation, lift, }) => {
|
|
14
|
+
const Tooltip = ({ content, children, placement = "top", delay = 300, disabled = false, className, triggerClassName, maxWidth = "360px", minWidth = "fit-content", showOnFocus = true, wrapText = false, id, theme: themeOverrides, "aria-label": ariaLabel, role = "tooltip", offset = 8, darkMode = false, elevation, lift, isOpen, defaultIsOpen = false, onOpenChange, recalcTrigger, }) => {
|
|
15
15
|
// Relative elevation: lift above the host surface (overlay base = 5).
|
|
16
16
|
const surfaceLevel = useSurfaceElevation({ baseRung: 5, offset: 2, elevation, lift });
|
|
17
17
|
// Stable id for the aria-describedby linkage — auto-generated via useId()
|
|
@@ -20,7 +20,14 @@ const Tooltip = ({ content, children, placement = "top", delay = 300, disabled =
|
|
|
20
20
|
// when the consumer doesn't pass an explicit `id`.
|
|
21
21
|
const generatedId = useId();
|
|
22
22
|
const tooltipId = id || `tooltip-${generatedId}`;
|
|
23
|
-
const
|
|
23
|
+
const isControlled = isOpen !== undefined;
|
|
24
|
+
const [internalVisible, setInternalVisible] = useState(defaultIsOpen);
|
|
25
|
+
const isVisible = isControlled ? isOpen : internalVisible;
|
|
26
|
+
const setVisible = useCallback((next) => {
|
|
27
|
+
if (!isControlled)
|
|
28
|
+
setInternalVisible(next);
|
|
29
|
+
onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(next);
|
|
30
|
+
}, [isControlled, onOpenChange]);
|
|
24
31
|
const tooltipRef = useRef(null);
|
|
25
32
|
const triggerRef = useRef(null);
|
|
26
33
|
const timerRef = useRef(null);
|
|
@@ -40,25 +47,42 @@ const Tooltip = ({ content, children, placement = "top", delay = 300, disabled =
|
|
|
40
47
|
placement: placement,
|
|
41
48
|
offset,
|
|
42
49
|
autoWidth: true,
|
|
50
|
+
recalcTrigger,
|
|
43
51
|
});
|
|
44
|
-
//
|
|
52
|
+
// Dev warning (§9): controlled + uncontrolled props together — controlled wins.
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (process.env.NODE_ENV !== "production") {
|
|
55
|
+
if (isControlled && defaultIsOpen) {
|
|
56
|
+
console.warn("[Tooltip]: Both `isOpen` and `defaultIsOpen` provided. Tooltip is controlled — `defaultIsOpen` is ignored.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60
|
+
}, []);
|
|
61
|
+
// Event handlers - simplified timer management.
|
|
62
|
+
// In controlled mode visibility is driven ENTIRELY by `isOpen` (see
|
|
63
|
+
// Tooltip.types.ts) — hover/focus/Escape must not fight the consumer's
|
|
64
|
+
// state, so both handlers bail. (`isOpen` without `onOpenChange` is a
|
|
65
|
+
// first-class display-only pattern — e.g. Slider's drag bubble — so no
|
|
66
|
+
// missing-handler warning here, unlike form controls.)
|
|
45
67
|
const handleShowTooltip = useCallback(() => {
|
|
46
|
-
if (disabled)
|
|
68
|
+
if (disabled || isControlled)
|
|
47
69
|
return;
|
|
48
70
|
if (timerRef.current) {
|
|
49
71
|
clearTimeout(timerRef.current);
|
|
50
72
|
}
|
|
51
73
|
timerRef.current = setTimeout(() => {
|
|
52
|
-
|
|
74
|
+
setVisible(true);
|
|
53
75
|
}, delay);
|
|
54
|
-
}, [disabled, delay]);
|
|
76
|
+
}, [disabled, isControlled, delay, setVisible]);
|
|
55
77
|
const handleHideTooltip = useCallback(() => {
|
|
78
|
+
if (isControlled)
|
|
79
|
+
return;
|
|
56
80
|
if (timerRef.current) {
|
|
57
81
|
clearTimeout(timerRef.current);
|
|
58
82
|
}
|
|
59
83
|
// Immediate hide for better responsiveness
|
|
60
|
-
|
|
61
|
-
}, []);
|
|
84
|
+
setVisible(false);
|
|
85
|
+
}, [isControlled, setVisible]);
|
|
62
86
|
// Clean up timeout on unmount
|
|
63
87
|
useEffect(() => {
|
|
64
88
|
return () => {
|
|
@@ -118,6 +142,14 @@ const Tooltip = ({ content, children, placement = "top", delay = 300, disabled =
|
|
|
118
142
|
// valid element to clone (e.g. plain text) and there is no other place to
|
|
119
143
|
// put the attribute.
|
|
120
144
|
const isElementChild = React__default.isValidElement(children);
|
|
145
|
+
// Merge with any aria-describedby the child already carries (e.g. a form
|
|
146
|
+
// control describing itself via its own helper/error text) instead of
|
|
147
|
+
// clobbering it — ARIA allows a space-separated list of ids.
|
|
148
|
+
const existingDescribedBy = isElementChild
|
|
149
|
+
? children.props["aria-describedby"]
|
|
150
|
+
: undefined;
|
|
151
|
+
const mergedDescribedBy = [existingDescribedBy, isVisible ? tooltipId : undefined].filter(Boolean).join(" ") ||
|
|
152
|
+
undefined;
|
|
121
153
|
const childWithFocusHandlers = isElementChild
|
|
122
154
|
? React__default.cloneElement(children, {
|
|
123
155
|
...(childCanReceiveFocus && {
|
|
@@ -132,7 +164,7 @@ const Tooltip = ({ content, children, placement = "top", delay = 300, disabled =
|
|
|
132
164
|
(_b = (_a = children.props).onBlur) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
|
133
165
|
},
|
|
134
166
|
}),
|
|
135
|
-
"aria-describedby":
|
|
167
|
+
"aria-describedby": mergedDescribedBy,
|
|
136
168
|
})
|
|
137
169
|
: children;
|
|
138
170
|
return (jsxs("div", { className: cn("relative inline-block", triggerClassName), ref: triggerRef, ...triggerHandlers, "aria-describedby": !isElementChild && isVisible ? tooltipId : undefined, children: [childWithFocusHandlers, isClient &&
|
|
@@ -107,4 +107,29 @@ export interface TooltipProps {
|
|
|
107
107
|
elevation?: SurfaceElevation;
|
|
108
108
|
/** `false` opts out of the relative lift — paints at the tooltip's base rung. */
|
|
109
109
|
lift?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Controlled visibility — when provided, visibility is driven entirely by
|
|
112
|
+
* this prop instead of internal hover/focus state (delay is bypassed).
|
|
113
|
+
* Use for triggers whose "show tooltip" moment isn't a plain hover, e.g. a
|
|
114
|
+
* value bubble shown only while dragging a Slider thumb.
|
|
115
|
+
*/
|
|
116
|
+
isOpen?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Initial visibility for uncontrolled usage.
|
|
119
|
+
* @default false
|
|
120
|
+
*/
|
|
121
|
+
defaultIsOpen?: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Called when internal hover/focus logic changes visibility (uncontrolled
|
|
124
|
+
* mode). In controlled mode visibility is owned by `isOpen` and the
|
|
125
|
+
* internal triggers are bypassed entirely, so this never fires — update
|
|
126
|
+
* your own state instead.
|
|
127
|
+
*/
|
|
128
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
129
|
+
/**
|
|
130
|
+
* Opt-in escape hatch for triggers that move on their own (e.g. a dragged
|
|
131
|
+
* slider thumb) without a scroll/resize/content-resize event to key off
|
|
132
|
+
* of. Position recalculates whenever this value changes.
|
|
133
|
+
*/
|
|
134
|
+
recalcTrigger?: unknown;
|
|
110
135
|
}
|
|
@@ -5,7 +5,7 @@ import { motion, AnimatePresence, useReducedMotion } from 'motion/react';
|
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { treeTheme } from './Tree.theme.js';
|
|
7
7
|
import { Checkbox } from '../../forms/Checkbox/Checkbox.js';
|
|
8
|
-
import {
|
|
8
|
+
import { CaretRight, File } from '@phosphor-icons/react';
|
|
9
9
|
import { getReducedMotionVariants, treeNodeVariants, expandIconVariants, childNodeVariants } from './Tree.animations.js';
|
|
10
10
|
|
|
11
11
|
// Build a flat ordered list of visible (non-collapsed) node ids via depth-first traversal.
|
|
@@ -200,7 +200,7 @@ const InternalTreeNode = React__default.memo(({ node, level, expanded, selected,
|
|
|
200
200
|
const labelStyle = cn(theme.labelStyle, {
|
|
201
201
|
'text-[var(--color-text-muted)]': node.disabled,
|
|
202
202
|
});
|
|
203
|
-
return (jsxs("div", { children: [jsxs("div", { ref: itemRef, className: nodeStyle, style: { paddingLeft: `calc(${level} * ${theme.indentSize} + 0.25rem)` }, onClick: handleNodeClick, onKeyDown: handleKeyDown, onFocus: handleFocus, tabIndex: tabIndexValue, role: "treeitem", "aria-expanded": isExpandable ? expanded : undefined, "aria-selected": selectable ? selected : undefined, "aria-disabled": node.disabled, children: [isExpandable ? (jsx(motion.span, { className: cn(theme.expandIconStyle), variants: iconVariants, initial: "collapsed", animate: expanded ? "expanded" : "collapsed", onClick: handleExpandClick, "aria-label": expanded ? 'Collapse' : 'Expand', "aria-hidden": "true", tabIndex: -1, children: jsx(
|
|
203
|
+
return (jsxs("div", { children: [jsxs("div", { ref: itemRef, className: nodeStyle, style: { paddingLeft: `calc(${level} * ${theme.indentSize} + 0.25rem)` }, onClick: handleNodeClick, onKeyDown: handleKeyDown, onFocus: handleFocus, tabIndex: tabIndexValue, role: "treeitem", "aria-expanded": isExpandable ? expanded : undefined, "aria-selected": selectable ? selected : undefined, "aria-disabled": node.disabled, children: [isExpandable ? (jsx(motion.span, { className: cn(theme.expandIconStyle), variants: iconVariants, initial: "collapsed", animate: expanded ? "expanded" : "collapsed", onClick: handleExpandClick, "aria-label": expanded ? 'Collapse' : 'Expand', "aria-hidden": "true", tabIndex: -1, children: jsx(CaretRight, { className: "size-4", weight: "bold" }) })) : (jsx("span", { className: "w-4 mr-1" })), checkable && (jsx(Checkbox, { size: 'sm', id: `tree-checkbox-${node.id}`, name: `tree-checkbox-${node.id}`, value: node.id, checked: selected, indeterminate: hierarchicalSelection && isIndeterminate, onChange: () => onNodeClick(node), state: node.disabled ? "disabled" : "default", className: "flex-shrink-0", onClick: (e) => e.stopPropagation() })), (node.icon || !isExpandable) && (jsx("span", { className: cn(theme.iconStyle), children: node.icon || jsx(File, { className: "w-4 h-4" }) })), jsx("span", { className: labelStyle, title: node.label, children: node.label })] }), hasChildren && (jsx(AnimatePresence, { initial: false, children: expanded && (jsx(motion.div, { role: "group", variants: nodeVariants, initial: "collapsed", animate: "expanded", exit: "collapsed", style: { overflow: 'hidden' }, children: (_a = node.children) === null || _a === void 0 ? void 0 : _a.map((childNode) => (
|
|
204
204
|
// No initial/animate/exit here on purpose: the child inherits its
|
|
205
205
|
// animation state from the container above so staggerChildren can
|
|
206
206
|
// cascade them in/out one after another.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Variants, Transition } from "motion/react";
|
|
2
|
+
/**
|
|
3
|
+
* Shared press/hover interaction physics for clickable core components
|
|
4
|
+
* (Button, Pill, Badge dismiss). One source of truth so every pressable
|
|
5
|
+
* surface in the library reacts with the same speed and character.
|
|
6
|
+
*
|
|
7
|
+
* Press-down is a fast tween — feedback must land within ~1 frame of the
|
|
8
|
+
* pointer, so no spring ramp-up on the way in. Release is a stiff spring
|
|
9
|
+
* with a hint of overshoot for tactile character on the way out.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: pair with CSS transitions that do NOT include `transform`
|
|
12
|
+
* (no `transition-all`) — motion drives transform directly every frame,
|
|
13
|
+
* and a CSS transition on transform re-interpolates those per-frame
|
|
14
|
+
* values and makes the press feel mushy.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PRESS_TRANSITION: Transition;
|
|
17
|
+
export declare const RELEASE_TRANSITION: Transition;
|
|
18
|
+
export declare const HOVER_TRANSITION: Transition;
|
|
19
|
+
/**
|
|
20
|
+
* Build press variants for a pressable component.
|
|
21
|
+
* Use with `animate="rest"` (so release uses RELEASE_TRANSITION) and
|
|
22
|
+
* `whileTap="press"`; pass `hoverScale` and `whileHover="hover"` for
|
|
23
|
+
* components that should also lift on hover.
|
|
24
|
+
*/
|
|
25
|
+
export declare const createPressVariants: (pressScale?: number, hoverScale?: number) => Variants;
|
|
26
|
+
/**
|
|
27
|
+
* Selection ripple for choice controls (Checkbox, Radio): a soft primary
|
|
28
|
+
* pulse that expands out of the control when it becomes checked.
|
|
29
|
+
*
|
|
30
|
+
* Spread onto a `motion.div` rendered inside `<AnimatePresence initial={false}>`
|
|
31
|
+
* gated on the checked state — `initial={false}` is required so a control
|
|
32
|
+
* that MOUNTS already checked (controlled/defaultChecked) doesn't fire the
|
|
33
|
+
* burst; only user-visible state changes do.
|
|
34
|
+
*/
|
|
35
|
+
export declare const CHECK_RIPPLE_MOTION: {
|
|
36
|
+
readonly initial: {
|
|
37
|
+
readonly scale: 0.5;
|
|
38
|
+
readonly opacity: 0.8;
|
|
39
|
+
};
|
|
40
|
+
readonly animate: {
|
|
41
|
+
readonly scale: 2;
|
|
42
|
+
readonly opacity: 0;
|
|
43
|
+
};
|
|
44
|
+
readonly exit: {
|
|
45
|
+
readonly opacity: 0;
|
|
46
|
+
};
|
|
47
|
+
readonly transition: {
|
|
48
|
+
duration: number;
|
|
49
|
+
ease: "easeOut";
|
|
50
|
+
};
|
|
51
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/**
|
|
3
|
+
* Shared press/hover interaction physics for clickable core components
|
|
4
|
+
* (Button, Pill, Badge dismiss). One source of truth so every pressable
|
|
5
|
+
* surface in the library reacts with the same speed and character.
|
|
6
|
+
*
|
|
7
|
+
* Press-down is a fast tween — feedback must land within ~1 frame of the
|
|
8
|
+
* pointer, so no spring ramp-up on the way in. Release is a stiff spring
|
|
9
|
+
* with a hint of overshoot for tactile character on the way out.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: pair with CSS transitions that do NOT include `transform`
|
|
12
|
+
* (no `transition-all`) — motion drives transform directly every frame,
|
|
13
|
+
* and a CSS transition on transform re-interpolates those per-frame
|
|
14
|
+
* values and makes the press feel mushy.
|
|
15
|
+
*/
|
|
16
|
+
const PRESS_TRANSITION = {
|
|
17
|
+
duration: 0.08,
|
|
18
|
+
ease: "easeOut",
|
|
19
|
+
};
|
|
20
|
+
const RELEASE_TRANSITION = {
|
|
21
|
+
type: "spring",
|
|
22
|
+
stiffness: 600,
|
|
23
|
+
damping: 25,
|
|
24
|
+
mass: 0.6,
|
|
25
|
+
};
|
|
26
|
+
const HOVER_TRANSITION = {
|
|
27
|
+
duration: 0.15,
|
|
28
|
+
ease: "easeOut",
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Build press variants for a pressable component.
|
|
32
|
+
* Use with `animate="rest"` (so release uses RELEASE_TRANSITION) and
|
|
33
|
+
* `whileTap="press"`; pass `hoverScale` and `whileHover="hover"` for
|
|
34
|
+
* components that should also lift on hover.
|
|
35
|
+
*/
|
|
36
|
+
const createPressVariants = (pressScale = 0.97, hoverScale) => ({
|
|
37
|
+
rest: { scale: 1, transition: RELEASE_TRANSITION },
|
|
38
|
+
...(hoverScale !== undefined
|
|
39
|
+
? { hover: { scale: hoverScale, transition: HOVER_TRANSITION } }
|
|
40
|
+
: {}),
|
|
41
|
+
press: { scale: pressScale, transition: PRESS_TRANSITION },
|
|
42
|
+
});
|
|
43
|
+
/**
|
|
44
|
+
* Selection ripple for choice controls (Checkbox, Radio): a soft primary
|
|
45
|
+
* pulse that expands out of the control when it becomes checked.
|
|
46
|
+
*
|
|
47
|
+
* Spread onto a `motion.div` rendered inside `<AnimatePresence initial={false}>`
|
|
48
|
+
* gated on the checked state — `initial={false}` is required so a control
|
|
49
|
+
* that MOUNTS already checked (controlled/defaultChecked) doesn't fire the
|
|
50
|
+
* burst; only user-visible state changes do.
|
|
51
|
+
*/
|
|
52
|
+
const CHECK_RIPPLE_MOTION = {
|
|
53
|
+
initial: { scale: 0.5, opacity: 0.8 },
|
|
54
|
+
animate: { scale: 2.0, opacity: 0 },
|
|
55
|
+
exit: { opacity: 0 },
|
|
56
|
+
transition: { duration: 0.35, ease: "easeOut" },
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export { CHECK_RIPPLE_MOTION, HOVER_TRANSITION, PRESS_TRANSITION, RELEASE_TRANSITION, createPressVariants };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default, { createContext, useMemo, useState, useCallback, useContext } from 'react';
|
|
4
4
|
import { useReducedMotion, motion } from 'motion/react';
|
|
5
|
-
import {
|
|
5
|
+
import { CaretUpDown } from '@phosphor-icons/react';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { feedTheme } from './Feed.theme.js';
|
|
8
8
|
import { collapseLayerExitTiming, collapseLayerEnterTiming, EASE, expandLayerEnterTiming, expandLayerExitTiming, STAGGER_BASE_DELAY, STAGGER_IN, STAGGER_OUT } from './Feed.animations.js';
|
|
@@ -106,7 +106,7 @@ const FeedCollapse = ({ label = "Show {count} more", icon, defaultExpanded = fal
|
|
|
106
106
|
}
|
|
107
107
|
return child;
|
|
108
108
|
});
|
|
109
|
-
const collapseIcon = icon !== null && icon !== void 0 ? icon : (jsx(
|
|
109
|
+
const collapseIcon = icon !== null && icon !== void 0 ? icon : (jsx(CaretUpDown, { className: "size-4 text-[var(--color-primary)]" }));
|
|
110
110
|
/* ---- Reduced motion: instant toggle, no staged animations ---- */
|
|
111
111
|
if (shouldReduceMotion) {
|
|
112
112
|
return (jsxs("li", { className: cn(theme.collapseStyle, className), children: [expanded && (jsx("span", { "aria-hidden": "true", className: "absolute left-5 -translate-x-1/2 top-0 h-full w-0.5 bg-[var(--color-border)]/60" })), !expanded ? (jsxs("div", { className: "relative", style: { height: COLLAPSED_HEIGHT }, children: [jsx("svg", { "aria-hidden": "true", className: theme.collapseSvgStyle, style: { left: "calc(1.25rem - 1px)" }, width: SVG_WIDTH, height: COLLAPSED_HEIGHT, fill: "none", children: jsx("path", { d: CURVE_PATH, stroke: "var(--color-border)", strokeOpacity: "0.6", strokeWidth: STROKE_WIDTH }) }), jsxs("button", { type: "button", className: "absolute top-1/2 -translate-y-1/2 flex items-center gap-2.5 cursor-pointer bg-transparent border-none p-0", style: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const ganttChartTheme = {
|
|
2
|
-
baseStyle: "flex flex-col w-full overflow-hidden rounded-
|
|
2
|
+
baseStyle: "flex flex-col w-full overflow-hidden rounded-[var(--gantt-chart-radius)] border border-[var(--color-border)] bg-[var(--color-background)] text-sm shadow-sm",
|
|
3
3
|
toolbarStyle: "flex flex-wrap items-center justify-between gap-2 px-3 py-2 border-b border-[var(--color-border)] bg-[var(--color-background-secondary)]/80",
|
|
4
4
|
tablePanelStyle: "flex flex-col shrink-0 overflow-hidden border-r border-[var(--color-border)] bg-[var(--color-background)]",
|
|
5
5
|
chartPanelStyle: "flex flex-col flex-1 min-w-0 overflow-hidden",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import { forwardRef, useEffect, useCallback } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { CalendarDots } from '@phosphor-icons/react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { useGanttContext, useGanttInteraction } from './GanttChartContext.js';
|
|
7
7
|
import { GanttTimelineHeader } from './GanttTimelineHeader.js';
|
|
@@ -65,7 +65,7 @@ const GanttChartPanel = forwardRef(({ onScroll, days, monthSpans }, ref) => {
|
|
|
65
65
|
}
|
|
66
66
|
}, [rows, focusedTaskId, setFocusedTaskId, onTaskClick]);
|
|
67
67
|
if (tasks.length === 0) {
|
|
68
|
-
return (jsx("div", { className: cn(theme.chartPanelStyle, "items-center justify-center"), children: emptyState !== null && emptyState !== void 0 ? emptyState : (jsxs("div", { className: cn(theme.emptyStateStyle), children: [jsx(
|
|
68
|
+
return (jsx("div", { className: cn(theme.chartPanelStyle, "items-center justify-center"), children: emptyState !== null && emptyState !== void 0 ? emptyState : (jsxs("div", { className: cn(theme.emptyStateStyle), children: [jsx(CalendarDots, { className: "size-10 opacity-40" }), jsx("div", { className: "text-base font-medium text-[var(--color-text-secondary)]", children: "No tasks to display" }), jsx("div", { className: "text-sm opacity-70", children: "Add tasks to see them on the timeline" })] })) }));
|
|
69
69
|
}
|
|
70
70
|
return (jsx("div", { className: cn(theme.chartPanelStyle), children: jsx("div", { ref: ref, className: "overflow-auto flex-1 min-h-0 focus:outline-none", onScroll: onScroll, onKeyDown: handleKeyDown, tabIndex: 0, role: "grid", "aria-label": "Gantt chart timeline", "data-gantt-chart-scroll": true, children: jsxs("div", { style: { width: totalWidth }, children: [jsx("div", { className: "sticky top-0 z-10", children: jsx(GanttTimelineHeader, { days: days, monthSpans: monthSpans }) }), jsxs("div", { className: "relative", style: { height: bodyHeight }, children: [jsx(GanttTimelineGrid, { days: days, height: bodyHeight }), showDependencies && jsx(GanttDependencyArrows, {}), rows.map((row, i) => {
|
|
71
71
|
const top = i * rowHeight;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default from 'react';
|
|
4
4
|
import { motion } from 'motion/react';
|
|
5
|
-
import {
|
|
5
|
+
import { CaretRight, Plus } from '@phosphor-icons/react';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { useGanttContext } from './GanttChartContext.js';
|
|
8
8
|
import { chevronVariants } from './GanttChart.animations.js';
|
|
@@ -15,10 +15,10 @@ const GanttTableGroupRow = React__default.memo(({ row, }) => {
|
|
|
15
15
|
e.preventDefault();
|
|
16
16
|
toggleGroup(row.group.id);
|
|
17
17
|
}
|
|
18
|
-
}, role: "button", tabIndex: 0, "aria-expanded": !isCollapsed, "aria-label": `${row.group.title} — ${row.completedCount} of ${row.taskCount} completed`, children: [jsxs("div", { className: "flex items-center gap-2 px-3 flex-1 min-w-0", children: [jsx(motion.div, { variants: chevronVariants, animate: isCollapsed ? "collapsed" : "open", children: jsx(
|
|
18
|
+
}, role: "button", tabIndex: 0, "aria-expanded": !isCollapsed, "aria-label": `${row.group.title} — ${row.completedCount} of ${row.taskCount} completed`, children: [jsxs("div", { className: "flex items-center gap-2 px-3 flex-1 min-w-0", children: [jsx(motion.div, { variants: chevronVariants, animate: isCollapsed ? "collapsed" : "open", children: jsx(CaretRight, { className: "size-4 text-[var(--color-text-muted)]" }) }), jsx("div", { className: "size-2.5 rounded-full shrink-0", style: { backgroundColor: row.group.color } }), jsx("span", { className: "font-medium text-[var(--color-text-primary)] truncate", children: row.group.title }), jsxs("span", { className: "text-sm text-[var(--color-text-muted)] shrink-0", children: [row.completedCount, "/", row.taskCount] })] }), onTaskAdd && !readonly && (jsx("button", { className: "p-1 mr-2 rounded hover:bg-[var(--color-surface-hover)] text-[var(--color-text-muted)] opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity", "aria-label": `Add task to ${row.group.title}`, onClick: (e) => {
|
|
19
19
|
e.stopPropagation();
|
|
20
20
|
onTaskAdd(row.group.id);
|
|
21
|
-
}, children: jsx(
|
|
21
|
+
}, children: jsx(Plus, { className: "size-4" }) }))] }));
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
export { GanttTableGroupRow };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import {
|
|
3
|
+
import { CheckCircle, Copy, Trash } from '@phosphor-icons/react';
|
|
4
4
|
import { ContextMenu } from '../../core/ContextMenu/ContextMenu.js';
|
|
5
5
|
import '../../core/ContextMenu/ContextMenu.theme.js';
|
|
6
6
|
import { useGanttContext } from './GanttChartContext.js';
|
|
@@ -12,7 +12,7 @@ const GanttTaskContextMenu = ({ task, children, }) => {
|
|
|
12
12
|
if (readonly || (!onTaskUpdate && !onTaskDuplicate && !onTaskDelete)) {
|
|
13
13
|
return jsx(Fragment, { children: children });
|
|
14
14
|
}
|
|
15
|
-
return (jsxs(ContextMenu, { children: [jsx(ContextMenu.Trigger, { children: children }), jsxs(ContextMenu.Body, { children: [onTaskUpdate && (
|
|
15
|
+
return (jsxs(ContextMenu, { children: [jsx(ContextMenu.Trigger, { children: children }), jsxs(ContextMenu.Body, { children: [onTaskUpdate && (jsx(ContextMenu.Item, { onSelect: () => onTaskUpdate(task.id, { completed: !task.completed, progress: task.completed ? 0 : 100 }), startContent: jsx(CheckCircle, { className: "size-4" }), children: task.completed ? "Mark as incomplete" : "Mark as done" })), onTaskUpdate && (jsxs(ContextMenu.Sub, { children: [jsx(ContextMenu.SubTrigger, { children: "Progress" }), jsx(ContextMenu.SubBody, { children: PROGRESS_STEPS.map((val) => (jsxs(ContextMenu.Item, { onSelect: () => onTaskUpdate(task.id, { progress: val, completed: val === 100 }), children: [val, "%"] }, val))) })] })), (onTaskDuplicate || onTaskDelete) && jsx(ContextMenu.Separator, {}), onTaskDuplicate && (jsx(ContextMenu.Item, { onSelect: () => onTaskDuplicate(task.id), startContent: jsx(Copy, { className: "size-4" }), children: "Duplicate" })), onTaskDelete && (jsx(ContextMenu.Item, { onSelect: () => onTaskDelete(task.id), className: "text-[var(--color-danger)]", startContent: jsx(Trash, { className: "size-4" }), children: "Delete" }))] })] }));
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
export { GanttTaskContextMenu };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import {
|
|
3
|
+
import { Calendar, Plus } from '@phosphor-icons/react';
|
|
4
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
5
|
import { useGanttContext } from './GanttChartContext.js';
|
|
6
6
|
import { Segmented } from '../../core/Segmented/Segmented.js';
|
|
@@ -24,7 +24,7 @@ const GanttToolbar = () => {
|
|
|
24
24
|
const targetScroll = todayOffset * dayWidth - container.clientWidth / 2;
|
|
25
25
|
container.scrollTo({ left: targetScroll, behavior: "smooth" });
|
|
26
26
|
};
|
|
27
|
-
return (jsxs("div", { className: cn(theme.toolbarStyle), children: [jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [toolbar.today && todayOffset !== null && (jsxs(Button, { variant: "outline", color: "
|
|
27
|
+
return (jsxs("div", { className: cn(theme.toolbarStyle), children: [jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [toolbar.today && todayOffset !== null && (jsxs(Button, { variant: "outline", color: "mono", size: "sm", onClick: handleScrollToToday, children: [jsx(Calendar, { className: "size-4" }), "Today"] })), toolbar.zoom && (jsx(Segmented, { value: zoom, onChange: (val) => setZoom(val), size: "sm", "aria-label": "Gantt zoom", className: "max-w-full overflow-x-auto", children: ZOOM_OPTIONS.map((opt) => (jsx(Segmented.Item, { value: opt.value, children: opt.label }, opt.value))) })), toolbar.hideCompleted && (jsx(Checkbox, { id: "gantt-hide-completed", name: "hideCompleted", value: "hideCompleted", checked: hideCompleted, onChange: (checked) => setHideCompleted(checked), label: "Hide completed", size: "sm" }))] }), jsx("div", { className: "flex items-center gap-2", children: toolbar.addGroup && onGroupAdd && !readonly && (jsxs(Button, { variant: "soft", size: "sm", onClick: onGroupAdd, children: [jsx(Plus, { className: "size-3.5" }), "Add group"] })) })] }));
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export { GanttToolbar };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import React__default, { useMemo } from 'react';
|
|
4
4
|
import { motion } from 'motion/react';
|
|
5
|
-
import {
|
|
5
|
+
import { ArrowUpRight, ArrowDownRight } from '@phosphor-icons/react';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { kpiTheme } from './KPI.theme.js';
|
|
8
8
|
|
|
@@ -42,7 +42,7 @@ const KPI = React__default.forwardRef(({ value, label, trend, trendLabel, progre
|
|
|
42
42
|
return (jsxs("div", { ref: ref, className: cn(theme.baseStyle, className), ...props, children: [jsxs("div", { className: "flex items-start justify-between", children: [jsxs("div", { className: "flex items-baseline gap-2", children: [jsx("span", { className: cn(theme.valueSizes[size]), children: value }), label &&
|
|
43
43
|
(typeof label === "string" ? (jsxs("span", { className: cn(theme.labelStyle, theme.labelSizes[size]), children: [icon && (jsx("span", { className: "inline-flex items-center mr-1", children: icon })), label] })) : (label))] }), formattedTrend &&
|
|
44
44
|
trendDirection &&
|
|
45
|
-
(typeof formattedTrend === "string" ? (jsxs("span", { className: cn("inline-flex items-center gap-0.5 font-medium", theme.trendSizes[size], trendDirection === "up" && theme.trendPositive, trendDirection === "down" && theme.trendNegative, trendDirection === "neutral" && theme.trendNeutral), children: [formattedTrend, trendDirection === "up" && (jsx(
|
|
45
|
+
(typeof formattedTrend === "string" ? (jsxs("span", { className: cn("inline-flex items-center gap-0.5 font-medium", theme.trendSizes[size], trendDirection === "up" && theme.trendPositive, trendDirection === "down" && theme.trendNegative, trendDirection === "neutral" && theme.trendNeutral), children: [formattedTrend, trendDirection === "up" && (jsx(ArrowUpRight, { className: "size-4" })), trendDirection === "down" && (jsx(ArrowDownRight, { className: "size-4" }))] })) : (formattedTrend))] }), progress !== undefined && (jsx("div", { className: cn("flex items-end", barSize.gap), role: "img", "aria-label": `Progress: ${progress}%`, children: Array.from({ length: barCount }, (_, i) => {
|
|
46
46
|
const isFilled = i < filledBars;
|
|
47
47
|
const fadeDistance = filledBars - i;
|
|
48
48
|
const fillOpacity = isFilled && fadeDistance <= 3
|
|
@@ -3,9 +3,9 @@ import { semanticBgColors } from '../../../utils/colorUtils.js';
|
|
|
3
3
|
const kpiTheme = {
|
|
4
4
|
baseStyle: "flex flex-col gap-3",
|
|
5
5
|
valueSizes: {
|
|
6
|
-
sm: "text-
|
|
7
|
-
md: "text-
|
|
8
|
-
lg: "text-
|
|
6
|
+
sm: "text-[length:var(--kpi-value-size-sm)] leading-[1.4] font-bold text-[var(--color-text-primary)]",
|
|
7
|
+
md: "text-[length:var(--kpi-value-size-md)] leading-[1.333] font-bold text-[var(--color-text-primary)]",
|
|
8
|
+
lg: "text-[length:var(--kpi-value-size-lg)] leading-[1.2] font-bold text-[var(--color-text-primary)]",
|
|
9
9
|
},
|
|
10
10
|
labelStyle: "text-[var(--color-text-primary)] font-medium",
|
|
11
11
|
labelSizes: {
|
|
@@ -23,7 +23,7 @@ const kpiTheme = {
|
|
|
23
23
|
},
|
|
24
24
|
barFilledColors: {
|
|
25
25
|
...semanticBgColors,
|
|
26
|
-
|
|
26
|
+
mono: "bg-[var(--color-text-secondary)]",
|
|
27
27
|
},
|
|
28
28
|
barEmptyColor: "bg-[var(--color-surface-sunken)]",
|
|
29
29
|
barSizes: {
|
|
@@ -4,10 +4,10 @@ import { cn } from '../../../utils/cn.js';
|
|
|
4
4
|
import { metricTheme } from './Metric.theme.js';
|
|
5
5
|
import { Badge } from '../../core/Badge/Badge.js';
|
|
6
6
|
import { Card } from '../../core/Card/Card.js';
|
|
7
|
-
import {
|
|
7
|
+
import { TrendUp, TrendDown } from '@phosphor-icons/react';
|
|
8
8
|
|
|
9
9
|
const Metric = React__default.forwardRef(({ value, label, subtitle, trendValue, trendDirection = "up", trendChart, size = "md", variant = "filled", color = "primary", icon, className, ...props }, ref) => {
|
|
10
|
-
const trendIcon = trendDirection === "up" ? (jsx(
|
|
10
|
+
const trendIcon = trendDirection === "up" ? (jsx(TrendUp, { className: "size-3", weight: "bold" })) : (jsx(TrendDown, { className: "size-3", weight: "bold" }));
|
|
11
11
|
const variantStyles = metricTheme.variants[variant];
|
|
12
12
|
// Ghost has no surface, so it renders flush (no inset) to align with
|
|
13
13
|
// surrounding content; filled keeps its size-based content padding.
|