@flikk/ui 1.0.0-beta.25 → 1.0.0-beta.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ai/CodeBlock/CodeBlock.theme.js +2 -2
- package/dist/components/ai/PromptInput/PromptInput.js +4 -0
- package/dist/components/ai/PromptInput/VoiceRecorder.js +4 -0
- package/dist/components/ai/StreamingResponse/MarkdownRenderer.js +1 -1
- package/dist/components/ai/TokenCounter/TokenCounter.theme.js +1 -1
- package/dist/components/charts/BarChart/BarChart.js +2 -2
- package/dist/components/charts/StackedBarChart/StackedBarChart.js +1 -1
- package/dist/components/charts/shared/BarRenderer/BarRenderer.js +2 -2
- package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +1 -1
- package/dist/components/core/Button/Button.js +1 -1
- package/dist/components/core/Button/Button.theme.js +5 -5
- package/dist/components/core/Calendar/Calendar.theme.js +1 -1
- package/dist/components/core/Calendar/CalendarMini/CalendarMini.theme.js +1 -1
- package/dist/components/core/CommandPalette/CommandItem.js +4 -5
- package/dist/components/core/CommandPalette/CommandPalette.js +1 -1
- package/dist/components/core/CommandPalette/CommandPalette.theme.js +11 -13
- package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +0 -2
- package/dist/components/core/ContextMenu/ContextMenu.theme.js +13 -14
- package/dist/components/core/DotSeparator/DotSeparator.d.ts +3 -0
- package/dist/components/core/DotSeparator/DotSeparator.js +19 -0
- package/dist/components/core/DotSeparator/DotSeparator.theme.d.ts +2 -0
- package/dist/components/core/DotSeparator/DotSeparator.theme.js +10 -0
- package/dist/components/core/DotSeparator/DotSeparator.types.d.ts +25 -0
- package/dist/components/core/DotSeparator/index.d.ts +3 -0
- package/dist/components/core/Drawer/Drawer.theme.js +2 -2
- package/dist/components/core/Dropdown/Dropdown.theme.js +4 -5
- package/dist/components/core/Dropdown/DropdownItem.js +1 -1
- package/dist/components/core/Dropdown/DropdownMenu.js +1 -1
- package/dist/components/core/Empty/Empty.js +1 -1
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.d.ts +14 -0
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.js +28 -0
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.theme.d.ts +6 -0
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.theme.js +8 -0
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.types.d.ts +32 -0
- package/dist/components/core/ImagePlaceholder/index.d.ts +2 -0
- package/dist/components/core/MenuItem/MenuItem.js +5 -2
- package/dist/components/core/MenuItem/MenuItem.theme.d.ts +6 -0
- package/dist/components/core/MenuItem/MenuItem.theme.js +19 -16
- package/dist/components/core/MenuItem/MenuItem.types.d.ts +2 -0
- package/dist/components/core/Message/Message.theme.js +1 -1
- package/dist/components/core/Modal/Modal.theme.js +1 -1
- package/dist/components/core/NavItem/NavItem.d.ts +1 -1
- package/dist/components/core/NavItem/NavItem.js +187 -68
- package/dist/components/core/NavItem/NavItem.theme.js +31 -12
- package/dist/components/core/NavItem/NavItem.types.d.ts +17 -39
- package/dist/components/core/Pagination/Pagination.theme.js +3 -3
- package/dist/components/core/Popover/Popover.theme.js +1 -1
- package/dist/components/core/Popover/Popover.types.d.ts +6 -2
- package/dist/components/core/Popover/PopoverBody.js +10 -3
- package/dist/components/core/Progress/Progress.theme.js +1 -1
- package/dist/components/core/ScrollArea/ScrollArea.js +2 -2
- package/dist/components/core/ScrollArea/ScrollArea.theme.js +1 -1
- package/dist/components/core/Segmented/Segmented.js +8 -6
- package/dist/components/core/Segmented/Segmented.theme.js +3 -3
- package/dist/components/core/Sidebar/Sidebar.d.ts +3 -1
- package/dist/components/core/Sidebar/Sidebar.js +53 -16
- package/dist/components/core/Sidebar/Sidebar.theme.js +5 -7
- package/dist/components/core/Sidebar/Sidebar.types.d.ts +125 -8
- package/dist/components/core/Sidebar/SidebarCard.d.ts +25 -0
- package/dist/components/core/Sidebar/SidebarCard.js +68 -0
- package/dist/components/core/Sidebar/SidebarCard.theme.d.ts +8 -0
- package/dist/components/core/Sidebar/SidebarCard.theme.js +18 -0
- package/dist/components/core/Sidebar/SidebarContent.js +10 -6
- package/dist/components/core/Sidebar/SidebarContext.d.ts +17 -16
- package/dist/components/core/Sidebar/SidebarContext.js +43 -20
- package/dist/components/core/Sidebar/SidebarFooter.js +4 -6
- package/dist/components/core/Sidebar/SidebarHeader.js +12 -9
- package/dist/components/core/Sidebar/SidebarLogo.js +39 -8
- package/dist/components/core/Sidebar/SidebarNav.js +4 -3
- package/dist/components/core/Sidebar/SidebarNavGroup.js +4 -7
- package/dist/components/core/Sidebar/SidebarSearch.d.ts +22 -0
- package/dist/components/core/Sidebar/SidebarSearch.js +135 -0
- package/dist/components/core/Sidebar/SidebarToggle.js +6 -1
- package/dist/components/core/Sidebar/SidebarUserProfile.js +33 -17
- package/dist/components/core/Sidebar/index.d.ts +4 -3
- package/dist/components/core/Skeleton/Skeleton.theme.js +1 -1
- package/dist/components/core/Spinner/Spinner.theme.js +1 -1
- package/dist/components/core/Tabs/Tabs.js +6 -1
- package/dist/components/core/Tabs/Tabs.types.d.ts +2 -0
- package/dist/components/core/Tabs/TabsBody.js +5 -3
- package/dist/components/core/Tag/Tag.js +29 -5
- package/dist/components/core/Tag/Tag.theme.js +14 -9
- package/dist/components/core/Tag/Tag.types.d.ts +7 -0
- package/dist/components/core/Tooltip/Tooltip.js +1 -1
- package/dist/components/core/Tooltip/Tooltip.theme.js +1 -2
- package/dist/components/core/index.d.ts +2 -0
- package/dist/components/core/index.js +6 -2
- package/dist/components/data-display/GanttChart/GanttChart.d.ts +1 -1
- package/dist/components/data-display/GanttChart/GanttChart.js +31 -4
- package/dist/components/data-display/GanttChart/GanttChart.theme.js +19 -17
- package/dist/components/data-display/GanttChart/GanttChart.types.d.ts +19 -0
- package/dist/components/data-display/GanttChart/GanttChart.utils.js +1 -1
- package/dist/components/data-display/GanttChart/GanttChartPanel.d.ts +1 -1
- package/dist/components/data-display/GanttChart/GanttChartPanel.js +3 -3
- package/dist/components/data-display/GanttChart/GanttDependencyArrows.js +7 -4
- package/dist/components/data-display/GanttChart/GanttMilestone.js +5 -5
- package/dist/components/data-display/GanttChart/GanttTableGroupRow.js +1 -1
- package/dist/components/data-display/GanttChart/GanttTablePanel.js +1 -1
- package/dist/components/data-display/GanttChart/GanttTableTaskRow.js +2 -2
- package/dist/components/data-display/GanttChart/GanttTaskBar.js +37 -16
- package/dist/components/data-display/GanttChart/GanttTimelineGrid.js +2 -1
- package/dist/components/data-display/GanttChart/GanttTimelineHeader.js +35 -11
- package/dist/components/data-display/GanttChart/GanttToolbar.js +2 -2
- package/dist/components/data-display/GanttChart/hooks/useGanttDrag.js +3 -2
- package/dist/components/data-display/GanttChart/index.d.ts +1 -1
- package/dist/components/data-display/KPI/KPI.js +13 -3
- package/dist/components/data-display/KPI/KPI.theme.js +3 -3
- package/dist/components/data-display/Metric/Metric.theme.js +3 -3
- package/dist/components/data-display/Table/Table.js +4 -3
- package/dist/components/data-display/Table/Table.theme.js +14 -6
- package/dist/components/data-display/Table/Table.types.d.ts +15 -0
- package/dist/components/data-display/Table/TableColumnManager.js +1 -1
- package/dist/components/data-display/Table/index.d.ts +2 -2
- package/dist/components/effects/Aurora/Aurora.d.ts +6 -17
- package/dist/components/effects/Aurora/Aurora.js +310 -105
- package/dist/components/effects/Aurora/Aurora.types.d.ts +6 -0
- package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.js +3 -3
- package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.js +13 -4
- package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.js +13 -4
- package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.js +14 -4
- package/dist/components/effects/MorphingText/MorphingText.js +40 -7
- package/dist/components/effects/StripePattern/StripePattern.d.ts +18 -0
- package/dist/components/effects/StripePattern/StripePattern.js +54 -0
- package/dist/components/effects/StripePattern/StripePattern.types.d.ts +53 -0
- package/dist/components/effects/StripePattern/index.d.ts +2 -0
- package/dist/components/effects/index.d.ts +2 -0
- package/dist/components/effects/index.js +1 -0
- package/dist/components/forms/Checkbox/Checkbox.theme.js +1 -1
- package/dist/components/forms/Combobox/Combobox.js +1 -1
- package/dist/components/forms/Combobox/Combobox.theme.js +2 -4
- package/dist/components/forms/CronInput/CronInput.js +1 -1
- package/dist/components/forms/CronInput/CronInput.theme.js +22 -31
- package/dist/components/forms/DatePicker/DatePicker.theme.js +11 -18
- package/dist/components/forms/DatePicker/DatePickerTrigger.js +1 -1
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +7 -14
- package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +1 -1
- package/dist/components/forms/FileUpload/FileUpload.animations.d.ts +29 -0
- package/dist/components/forms/FileUpload/FileUpload.animations.js +19 -0
- package/dist/components/forms/FileUpload/FileUpload.js +88 -49
- package/dist/components/forms/FileUpload/FileUpload.theme.d.ts +2 -10
- package/dist/components/forms/FileUpload/FileUpload.theme.js +16 -30
- package/dist/components/forms/FileUpload/FileUpload.types.d.ts +26 -10
- package/dist/components/forms/FileUpload/FileUploadProgress.js +27 -20
- package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +2 -2
- package/dist/components/forms/Input/Input.theme.js +16 -15
- package/dist/components/forms/InputCounter/InputCounter.theme.js +1 -1
- package/dist/components/forms/Mention/Mention.js +152 -57
- package/dist/components/forms/Mention/Mention.theme.js +16 -23
- package/dist/components/forms/Mention/Mention.types.d.ts +12 -12
- package/dist/components/forms/Mention/Mention.utils.js +32 -4
- package/dist/components/forms/Radio/Radio.theme.js +1 -1
- package/dist/components/forms/RichTextEditor/RichTextEditor.d.ts +18 -0
- package/dist/components/forms/RichTextEditor/RichTextEditor.js +1231 -236
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.d.ts +53 -1
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +99 -25
- package/dist/components/forms/RichTextEditor/RichTextEditor.types.d.ts +42 -3
- package/dist/components/forms/RichTextEditor/index.d.ts +2 -2
- package/dist/components/forms/Select/Select.js +2 -2
- package/dist/components/forms/Select/Select.theme.js +3 -3
- package/dist/components/forms/Slider/Slider.theme.js +1 -1
- package/dist/components/forms/Switch/Switch.theme.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +2 -2
- package/dist/components/forms/TimePicker/TimePickerContent.js +4 -0
- package/dist/components/forms/TimePicker/TimePickerTrigger.js +1 -1
- package/dist/components/forms/forms.theme.js +24 -19
- package/dist/components/forms/index.js +4 -0
- package/dist/components/layout/AppShell/AppShell.d.ts +10 -0
- package/dist/components/layout/AppShell/AppShell.js +84 -0
- package/dist/components/layout/AppShell/AppShell.theme.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShell.theme.js +42 -0
- package/dist/components/layout/AppShell/AppShell.types.d.ts +127 -0
- package/dist/components/layout/AppShell/AppShellContext.d.ts +14 -0
- package/dist/components/layout/AppShell/AppShellContext.js +19 -0
- package/dist/components/layout/AppShell/AppShellFooter.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellFooter.js +12 -0
- package/dist/components/layout/AppShell/AppShellHeader.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellHeader.js +12 -0
- package/dist/components/layout/AppShell/AppShellMain.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellMain.js +19 -0
- package/dist/components/layout/AppShell/AppShellRightPanel.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellRightPanel.js +16 -0
- package/dist/components/layout/AppShell/AppShellSidebar.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellSidebar.js +16 -0
- package/dist/components/layout/AppShell/AppShellTopbar.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellTopbar.js +12 -0
- package/dist/components/layout/AppShell/index.d.ts +3 -0
- package/dist/components/layout/FormLayout/FormLayout.js +9 -4
- package/dist/components/layout/FormLayout/FormLayout.types.d.ts +3 -3
- package/dist/components/layout/FormLayout/FormLayoutSection.js +6 -1
- package/dist/components/layout/PageLayout/PageLayout.d.ts +2 -2
- package/dist/components/layout/PageLayout/PageLayout.js +23 -5
- package/dist/components/layout/PageLayout/PageLayout.theme.d.ts +2 -1
- package/dist/components/layout/PageLayout/PageLayout.theme.js +35 -6
- package/dist/components/layout/PageLayout/PageLayout.types.d.ts +45 -0
- package/dist/components/layout/PageLayout/PageLayoutContent.js +6 -4
- package/dist/components/layout/PageLayout/PageLayoutHeader.js +3 -3
- package/dist/components/layout/PageLayout/PageLayoutSidebar.js +5 -3
- package/dist/components/layout/PageLayout/index.d.ts +1 -1
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/hooks/useSelectPortal.d.ts +10 -2
- package/dist/hooks/useSelectPortal.js +45 -24
- package/dist/index.js +8 -2
- package/dist/registry.json +10021 -0
- package/dist/styles.css +1 -1
- package/dist/utils/dateUtils.js +11 -1
- package/package.json +4 -2
- package/src/global.scss +29 -8
- package/src/styles/theme.css +174 -100
- package/dist/components/core/Sidebar/SidebarSubmenu.d.ts +0 -7
- package/dist/components/core/Sidebar/SidebarSubmenu.js +0 -12
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import React__default, {
|
|
3
|
-
import { useReducedMotion,
|
|
2
|
+
import React__default, { useState, useRef, useCallback, useEffect, useLayoutEffect } from 'react';
|
|
3
|
+
import { useReducedMotion, motion, AnimatePresence } from 'motion/react';
|
|
4
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
5
|
|
|
6
|
+
const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
|
|
6
7
|
/**
|
|
7
8
|
* MorphingText smoothly morphs between different text strings using a blur/fade
|
|
8
9
|
* transition. Two overlapping text layers cross-fade with a Gaussian blur effect
|
|
@@ -18,11 +19,12 @@ import { cn } from '../../../utils/cn.js';
|
|
|
18
19
|
* ```
|
|
19
20
|
*/
|
|
20
21
|
const MorphingText = React__default.forwardRef(({ texts, interval = 3000, transitionDuration = 800, loop = true, pauseOnHover = false, currentIndex: controlledIndex, onTextChange, className, ...props }, ref) => {
|
|
21
|
-
const filterId = useId();
|
|
22
22
|
const shouldReduceMotion = useReducedMotion();
|
|
23
23
|
const isControlled = controlledIndex !== undefined;
|
|
24
24
|
const [internalIndex, setInternalIndex] = useState(0);
|
|
25
25
|
const activeIndex = isControlled ? controlledIndex : internalIndex;
|
|
26
|
+
const measureRefs = useRef([]);
|
|
27
|
+
const [textRects, setTextRects] = useState([]);
|
|
26
28
|
const [isPaused, setIsPaused] = useState(false);
|
|
27
29
|
const intervalRef = useRef(null);
|
|
28
30
|
const hasReachedEnd = useRef(false);
|
|
@@ -59,6 +61,28 @@ const MorphingText = React__default.forwardRef(({ texts, interval = 3000, transi
|
|
|
59
61
|
useEffect(() => {
|
|
60
62
|
hasReachedEnd.current = false;
|
|
61
63
|
}, [loop, texts]);
|
|
64
|
+
useIsomorphicLayoutEffect(() => {
|
|
65
|
+
const measure = () => {
|
|
66
|
+
setTextRects(texts.map((_, index) => {
|
|
67
|
+
var _a, _b, _c;
|
|
68
|
+
const rect = (_a = measureRefs.current[index]) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
69
|
+
return {
|
|
70
|
+
width: (_b = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _b !== void 0 ? _b : 0,
|
|
71
|
+
height: (_c = rect === null || rect === void 0 ? void 0 : rect.height) !== null && _c !== void 0 ? _c : 0,
|
|
72
|
+
};
|
|
73
|
+
}));
|
|
74
|
+
};
|
|
75
|
+
measure();
|
|
76
|
+
if (typeof ResizeObserver === 'undefined') {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const observer = new ResizeObserver(measure);
|
|
80
|
+
measureRefs.current.forEach((element) => {
|
|
81
|
+
if (element)
|
|
82
|
+
observer.observe(element);
|
|
83
|
+
});
|
|
84
|
+
return () => observer.disconnect();
|
|
85
|
+
}, [texts]);
|
|
62
86
|
// Fire onTextChange for controlled index changes
|
|
63
87
|
useEffect(() => {
|
|
64
88
|
if (isControlled) {
|
|
@@ -78,14 +102,23 @@ const MorphingText = React__default.forwardRef(({ texts, interval = 3000, transi
|
|
|
78
102
|
}
|
|
79
103
|
const durationSeconds = transitionDuration / 1000;
|
|
80
104
|
const currentText = texts[safeIndex];
|
|
105
|
+
const currentRect = textRects[safeIndex];
|
|
106
|
+
const measuredSize = (currentRect === null || currentRect === void 0 ? void 0 : currentRect.width) && (currentRect === null || currentRect === void 0 ? void 0 : currentRect.height)
|
|
107
|
+
? { width: currentRect.width, height: currentRect.height }
|
|
108
|
+
: undefined;
|
|
81
109
|
// Reduced motion: instant swap with no animation
|
|
82
110
|
if (shouldReduceMotion) {
|
|
83
111
|
return (jsx("div", { ref: ref, className: cn('relative inline-block', className), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, "aria-live": "polite", "aria-atomic": "true", ...props, children: jsx("span", { children: currentText }) }));
|
|
84
112
|
}
|
|
85
|
-
return (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
113
|
+
return (jsx("div", { ref: ref, className: cn('relative inline-block align-bottom', className), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, "aria-live": "polite", "aria-atomic": "true", ...props, children: jsxs(motion.span, { className: "relative inline-block align-bottom", initial: false, animate: measuredSize, transition: {
|
|
114
|
+
duration: durationSeconds,
|
|
115
|
+
ease: 'easeInOut',
|
|
116
|
+
}, children: [jsx("span", { className: "pointer-events-none invisible absolute left-0 top-0 whitespace-nowrap", "aria-hidden": "true", children: texts.map((text, index) => (jsx("span", { ref: (element) => {
|
|
117
|
+
measureRefs.current[index] = element;
|
|
118
|
+
}, className: "block w-fit whitespace-nowrap", children: text }, `${text}-${index}`))) }), !measuredSize && (jsx("span", { className: "whitespace-nowrap", children: currentText })), measuredSize && (jsx(AnimatePresence, { mode: "popLayout", initial: false, children: jsx(motion.span, { className: "absolute left-0 top-0 flex whitespace-nowrap", initial: { opacity: 0, filter: 'blur(8px)' }, animate: { opacity: 1, filter: 'blur(0px)' }, exit: { opacity: 0, filter: 'blur(8px)' }, transition: {
|
|
119
|
+
duration: durationSeconds,
|
|
120
|
+
ease: 'easeInOut',
|
|
121
|
+
}, children: currentText }, safeIndex) }))] }) }));
|
|
89
122
|
});
|
|
90
123
|
MorphingText.displayName = "MorphingText";
|
|
91
124
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { StripePatternProps } from "./StripePattern.types";
|
|
3
|
+
/**
|
|
4
|
+
* StripePattern renders an SVG-based diagonal stripe background pattern.
|
|
5
|
+
*
|
|
6
|
+
* Use it as an absolute-positioned decorative or placeholder fill inside a
|
|
7
|
+
* container with `position: relative`. The pattern is non-interactive
|
|
8
|
+
* (`pointer-events: none`) and sits at `z-index: 0` by default.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <div className="relative overflow-hidden h-40 rounded-lg">
|
|
13
|
+
* <StripePattern />
|
|
14
|
+
* <div className="relative z-10">Empty cover slot</div>
|
|
15
|
+
* </div>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const StripePattern: React.ForwardRefExoticComponent<StripePatternProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import React__default, { useId, useMemo } from 'react';
|
|
3
|
+
import { useReducedMotion, motion } from 'motion/react';
|
|
4
|
+
import { cn } from '../../../utils/cn.js';
|
|
5
|
+
|
|
6
|
+
function buildMaskImage(direction, fadeSize) {
|
|
7
|
+
const stop = Math.max(0, Math.min(100, fadeSize));
|
|
8
|
+
if (direction === "radial") {
|
|
9
|
+
return `radial-gradient(ellipse at center, black ${100 - stop}%, transparent 100%)`;
|
|
10
|
+
}
|
|
11
|
+
const directionMap = {
|
|
12
|
+
top: "to top",
|
|
13
|
+
bottom: "to bottom",
|
|
14
|
+
left: "to left",
|
|
15
|
+
right: "to right",
|
|
16
|
+
};
|
|
17
|
+
return `linear-gradient(${directionMap[direction]}, black ${100 - stop}%, transparent 100%)`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* StripePattern renders an SVG-based diagonal stripe background pattern.
|
|
21
|
+
*
|
|
22
|
+
* Use it as an absolute-positioned decorative or placeholder fill inside a
|
|
23
|
+
* container with `position: relative`. The pattern is non-interactive
|
|
24
|
+
* (`pointer-events: none`) and sits at `z-index: 0` by default.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <div className="relative overflow-hidden h-40 rounded-lg">
|
|
29
|
+
* <StripePattern />
|
|
30
|
+
* <div className="relative z-10">Empty cover slot</div>
|
|
31
|
+
* </div>
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
const StripePattern = React__default.forwardRef(({ spacing = 12, strokeWidth = 6, angle = -45, color = "color-mix(in srgb, var(--color-border) 50%, transparent)", fade = false, fadeDirection = "radial", fadeSize = 50, animated = false, className, style, ...rest }, ref) => {
|
|
35
|
+
const patternId = useId();
|
|
36
|
+
const shouldReduceMotion = useReducedMotion();
|
|
37
|
+
const enableAnimation = animated && !shouldReduceMotion;
|
|
38
|
+
const maskImage = useMemo(() => (fade ? buildMaskImage(fadeDirection, fadeSize) : undefined), [fade, fadeDirection, fadeSize]);
|
|
39
|
+
const containerStyle = {
|
|
40
|
+
...style,
|
|
41
|
+
...(maskImage
|
|
42
|
+
? {
|
|
43
|
+
maskImage,
|
|
44
|
+
WebkitMaskImage: maskImage,
|
|
45
|
+
}
|
|
46
|
+
: {}),
|
|
47
|
+
};
|
|
48
|
+
const lineX = spacing / 2;
|
|
49
|
+
const lineElement = enableAnimation ? (jsx(motion.line, { x1: lineX, y1: 0, x2: lineX, y2: spacing, stroke: color, strokeWidth: strokeWidth, animate: { opacity: [0.4, 1, 0.4] }, transition: { duration: 4, ease: "easeInOut", repeat: Infinity } })) : (jsx("line", { x1: lineX, y1: 0, x2: lineX, y2: spacing, stroke: color, strokeWidth: strokeWidth }));
|
|
50
|
+
return (jsx("div", { ref: ref, className: cn("absolute inset-0 pointer-events-none z-0 overflow-hidden", className), style: containerStyle, ...rest, children: jsxs("svg", { "aria-hidden": "true", className: "absolute inset-0 w-full h-full", children: [jsx("defs", { children: jsx("pattern", { id: patternId, x: "0", y: "0", width: spacing, height: spacing, patternUnits: "userSpaceOnUse", patternTransform: `rotate(${angle})`, children: lineElement }) }), jsx("rect", { width: "100%", height: "100%", fill: `url(#${patternId})` })] }) }));
|
|
51
|
+
});
|
|
52
|
+
StripePattern.displayName = "StripePattern";
|
|
53
|
+
|
|
54
|
+
export { StripePattern };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/** Direction for the fade gradient mask */
|
|
3
|
+
export type StripePatternFadeDirection = "radial" | "top" | "bottom" | "left" | "right";
|
|
4
|
+
export interface StripePatternProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/**
|
|
6
|
+
* Distance between adjacent stripes in pixels (center to center).
|
|
7
|
+
* @default 12
|
|
8
|
+
*/
|
|
9
|
+
spacing?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Thickness of each stripe in pixels.
|
|
12
|
+
* @default 6
|
|
13
|
+
*/
|
|
14
|
+
strokeWidth?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Stripe rotation in degrees. `-45` runs bottom-left to top-right.
|
|
17
|
+
* @default -45
|
|
18
|
+
*/
|
|
19
|
+
angle?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Stroke color of the stripes.
|
|
22
|
+
* Accepts any valid CSS color value or CSS variable.
|
|
23
|
+
* @default "color-mix(in srgb, var(--color-border) 50%, transparent)"
|
|
24
|
+
*/
|
|
25
|
+
color?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to apply a gradient mask that fades the pattern at the edges.
|
|
28
|
+
* Defaults to `false` so the pattern reads as a flat fill — useful for
|
|
29
|
+
* placeholder surfaces. Set to `true` for decorative backgrounds.
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
fade?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Direction of the fade gradient.
|
|
35
|
+
* - "radial" fades from center outward
|
|
36
|
+
* - "top" | "bottom" | "left" | "right" fades toward that edge
|
|
37
|
+
* @default "radial"
|
|
38
|
+
*/
|
|
39
|
+
fadeDirection?: StripePatternFadeDirection;
|
|
40
|
+
/**
|
|
41
|
+
* Size of the fade area as a percentage (0-100).
|
|
42
|
+
* @default 50
|
|
43
|
+
*/
|
|
44
|
+
fadeSize?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Whether to apply a subtle pulse animation to the stripes.
|
|
47
|
+
* Respects prefers-reduced-motion automatically.
|
|
48
|
+
* @default false
|
|
49
|
+
*/
|
|
50
|
+
animated?: boolean;
|
|
51
|
+
/** Additional className for style overrides (shadcn pattern). */
|
|
52
|
+
className?: string;
|
|
53
|
+
}
|
|
@@ -20,6 +20,8 @@ export { GridPattern } from "./GridPattern";
|
|
|
20
20
|
export type { GridPatternProps, GridPatternFadeDirection, } from "./GridPattern";
|
|
21
21
|
export { DotPattern } from "./DotPattern";
|
|
22
22
|
export type { DotPatternProps, DotPatternFadeDirection, } from "./DotPattern";
|
|
23
|
+
export { StripePattern } from "./StripePattern";
|
|
24
|
+
export type { StripePatternProps, StripePatternFadeDirection, } from "./StripePattern";
|
|
23
25
|
export { NoiseOverlay } from "./NoiseOverlay";
|
|
24
26
|
export type { NoiseOverlayProps, NoiseBlendMode } from "./NoiseOverlay";
|
|
25
27
|
export { Spotlight } from "./Spotlight";
|
|
@@ -9,6 +9,7 @@ export { MagneticElement } from './MagneticElement/MagneticElement.js';
|
|
|
9
9
|
export { MorphingText } from './MorphingText/MorphingText.js';
|
|
10
10
|
export { GridPattern } from './GridPattern/GridPattern.js';
|
|
11
11
|
export { DotPattern } from './DotPattern/DotPattern.js';
|
|
12
|
+
export { StripePattern } from './StripePattern/StripePattern.js';
|
|
12
13
|
export { NoiseOverlay } from './NoiseOverlay/NoiseOverlay.js';
|
|
13
14
|
export { Spotlight } from './Spotlight/Spotlight.js';
|
|
14
15
|
export { SpotlightBorder } from './SpotlightBorder/SpotlightBorder.js';
|
|
@@ -10,7 +10,7 @@ const checkboxTheme = {
|
|
|
10
10
|
// Default state - light
|
|
11
11
|
"border-[var(--color-border)] bg-[var(--color-surface)] " +
|
|
12
12
|
// Default state - dark
|
|
13
|
-
"dark:bg-[var(--color-
|
|
13
|
+
"dark:bg-[var(--color-surface-raised)] " +
|
|
14
14
|
// Checked state - light
|
|
15
15
|
"checked:border-[var(--color-primary)] checked:bg-[var(--color-primary)] " +
|
|
16
16
|
// Checked state - dark
|
|
@@ -100,7 +100,7 @@ const ComboboxOptions = ({ isOpen, onClose, triggerRef, portal, placement, offse
|
|
|
100
100
|
}, children: isCreateOption ? (jsxs("span", { className: "flex items-center gap-1", children: [jsx(PlusIcon, { className: "size-4 shrink-0", strokeWidth: 2 }), jsx("span", { className: "block truncate", children: option.label })] })) : (jsx("span", { className: "block truncate", children: option.label })) }, option.id));
|
|
101
101
|
}), filteredOptions.length > 100 && (jsxs("div", { className: "px-3 py-2 text-xs text-[var(--color-text-muted)] text-center border-t border-[var(--color-border)]", children: ["Showing 100 of ", filteredOptions.length, " results \u2014 refine your search"] }))] })) })) }));
|
|
102
102
|
if (portal && isClient) {
|
|
103
|
-
return createPortal(jsx("div", { className: isDarkMode ? "dark" : undefined, children: optionsContent }), document.body);
|
|
103
|
+
return createPortal(jsx("div", { "data-flikkui-portal": "", className: isDarkMode ? "dark" : undefined, children: optionsContent }), document.body);
|
|
104
104
|
}
|
|
105
105
|
return optionsContent;
|
|
106
106
|
};
|
|
@@ -28,14 +28,12 @@ const comboboxTheme = {
|
|
|
28
28
|
focusStates: formsBaseTheme.focusStates,
|
|
29
29
|
// Icon positioning styles
|
|
30
30
|
iconStartStyle: formsBaseTheme.iconStyles.left,
|
|
31
|
-
iconEndStyle: "absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none text-[var(--color-text-muted)]
|
|
32
|
-
"dark:text-[var(--color-neutral-500)]",
|
|
31
|
+
iconEndStyle: "absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none text-[var(--color-text-muted)]",
|
|
33
32
|
// Icon padding configuration
|
|
34
33
|
iconPadding: formsBaseTheme.iconStyles.padding,
|
|
35
34
|
// Clear button styles
|
|
36
35
|
clearButtonStyle: "absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer " +
|
|
37
|
-
"text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] transition-colors z-10
|
|
38
|
-
"dark:text-[var(--color-neutral-500)] dark:hover:text-[var(--color-neutral-200)]",
|
|
36
|
+
"text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] transition-colors z-10",
|
|
39
37
|
clearIconStyle: "size-4",
|
|
40
38
|
// Dropdown styles - matches Select component for consistency
|
|
41
39
|
dropdownStyle: formsBaseTheme.dropdownStyles.container + " py-1",
|
|
@@ -104,7 +104,7 @@ const CronInput = React__default.forwardRef(({ value: controlledValue, defaultVa
|
|
|
104
104
|
const showVisual = mode === "visual" || (mode === "both" && activeMode === "visual");
|
|
105
105
|
const showRaw = mode === "raw" || (mode === "both" && activeMode === "raw");
|
|
106
106
|
const helperId = `${generatedId}-helper`;
|
|
107
|
-
return (jsxs("div", { ref: ref, className: cn(theme.baseStyle, className), role: "group", "aria-label": label || "Cron expression builder", ...props, children: [label && (jsx(FormLabel, { htmlFor: `${generatedId}-cron`, state: isDisabled ? "disabled" : isInvalid ? "invalid" : "default", children: label })), mode === "both" && (jsxs("div", { className: "flex items-center gap-1.5", children: [jsxs("button", { type: "button", onClick: () => setActiveMode("visual"), disabled: isDisabled, className: cn(theme.modeToggleStyle, activeMode === "visual" && theme.modeToggleActiveStyle), "aria-pressed": activeMode === "visual", children: [jsx(CalendarIcon, { className: "w-3.5 h-3.5 mr-1", "aria-hidden": "true" }), "Visual"] }), jsxs("button", { type: "button", onClick: () => setActiveMode("raw"), disabled: isDisabled, className: cn(theme.modeToggleStyle, activeMode === "raw" && theme.modeToggleActiveStyle), "aria-pressed": activeMode === "raw", children: [jsx(ClockIcon, { className: "w-3.5 h-3.5 mr-1", "aria-hidden": "true" }), "Cron"] })] })), showPresets && (jsxs("div", { children: [jsx("div", { className: cn(theme.sectionHeadingStyle, "mb-1.5"), children: "Presets" }), jsx("div", { className: "flex flex-wrap gap-1.5", children: CRON_PRESETS.map((preset) => (jsx("button", { type: "button", onClick: () => handlePresetClick(preset.value), disabled: isDisabled, className: cn(theme.presetButtonStyle, activePreset === preset.value && theme.presetButtonActiveStyle), title: preset.description, "aria-pressed": activePreset === preset.value, children: preset.label }, preset.value))) })] })), showVisual && (jsxs("div", { className: cn(theme.builderStyle, isInvalid && "ring-1 ring-[var(--color-danger)] rounded-[var(--form-radius)]"), children: [jsx(FieldSelect, { label: "Minute", value: fields.minute, options: minuteOptions, onChange: (v) => handleFieldChange("minute", v), disabled: isDisabled, size: size }), jsx(FieldSelect, { label: "Hour", value: fields.hour, options: hourOptions, onChange: (v) => handleFieldChange("hour", v), disabled: isDisabled, size: size }), jsx(FieldSelect, { label: "Day of Month", value: fields.dayOfMonth, options: dayOfMonthOptions, onChange: (v) => handleFieldChange("dayOfMonth", v), disabled: isDisabled, size: size }), jsx(FieldSelect, { label: "Month", value: fields.month, options: monthOptions, onChange: (v) => handleFieldChange("month", v), disabled: isDisabled, size: size }), jsx(FieldSelect, { label: "Day of Week", value: fields.dayOfWeek, options: dayOfWeekOptions, onChange: (v) => handleFieldChange("dayOfWeek", v), disabled: isDisabled, size: size })] })), showRaw && (jsxs("div", { children: [jsx("div", { className: cn(theme.sectionHeadingStyle, "mb-1.5"), children: "Cron Expression" }), jsx("input", { type: "text", value: rawInput, onChange: handleRawInputChange, onBlur: handleRawInputBlur, onKeyDown: handleRawKeyDown, disabled: isDisabled, placeholder: "* * * * *", className: cn(theme.rawInputStyle, theme.rawInputSizes[size], isInvalid && "border-[var(--color-danger)] focus:border-[var(--color-danger)] focus:ring-[var(--color-danger)]"), id: `${generatedId}-cron`, "aria-label": "Cron expression", "aria-invalid": isInvalid || !validateCron(rawInput), "aria-describedby": helperText ? helperId : undefined, spellCheck: false, autoComplete: "off" }), !validateCron(rawInput) && rawInput !== cronValue && (jsx("div", { className: cn(theme.errorStyle, "mt-1"), children: "Invalid cron expression. Format: minute hour day month weekday" }))] })), showVisual && !showRaw && (jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: cn(theme.fieldLabelStyle, "shrink-0"), children: "Expression:" }), jsx("code", { className: cn("font-mono text-sm px-2 py-1 rounded-[var(--form-radius)]", "bg-[var(--color-
|
|
107
|
+
return (jsxs("div", { ref: ref, className: cn(theme.baseStyle, className), role: "group", "aria-label": label || "Cron expression builder", ...props, children: [label && (jsx(FormLabel, { htmlFor: `${generatedId}-cron`, state: isDisabled ? "disabled" : isInvalid ? "invalid" : "default", children: label })), mode === "both" && (jsxs("div", { className: "flex items-center gap-1.5", children: [jsxs("button", { type: "button", onClick: () => setActiveMode("visual"), disabled: isDisabled, className: cn(theme.modeToggleStyle, activeMode === "visual" && theme.modeToggleActiveStyle), "aria-pressed": activeMode === "visual", children: [jsx(CalendarIcon, { className: "w-3.5 h-3.5 mr-1", "aria-hidden": "true" }), "Visual"] }), jsxs("button", { type: "button", onClick: () => setActiveMode("raw"), disabled: isDisabled, className: cn(theme.modeToggleStyle, activeMode === "raw" && theme.modeToggleActiveStyle), "aria-pressed": activeMode === "raw", children: [jsx(ClockIcon, { className: "w-3.5 h-3.5 mr-1", "aria-hidden": "true" }), "Cron"] })] })), showPresets && (jsxs("div", { children: [jsx("div", { className: cn(theme.sectionHeadingStyle, "mb-1.5"), children: "Presets" }), jsx("div", { className: "flex flex-wrap gap-1.5", children: CRON_PRESETS.map((preset) => (jsx("button", { type: "button", onClick: () => handlePresetClick(preset.value), disabled: isDisabled, className: cn(theme.presetButtonStyle, activePreset === preset.value && theme.presetButtonActiveStyle), title: preset.description, "aria-pressed": activePreset === preset.value, children: preset.label }, preset.value))) })] })), showVisual && (jsxs("div", { className: cn(theme.builderStyle, isInvalid && "ring-1 ring-[var(--color-danger)] rounded-[var(--form-radius)]"), children: [jsx(FieldSelect, { label: "Minute", value: fields.minute, options: minuteOptions, onChange: (v) => handleFieldChange("minute", v), disabled: isDisabled, size: size }), jsx(FieldSelect, { label: "Hour", value: fields.hour, options: hourOptions, onChange: (v) => handleFieldChange("hour", v), disabled: isDisabled, size: size }), jsx(FieldSelect, { label: "Day of Month", value: fields.dayOfMonth, options: dayOfMonthOptions, onChange: (v) => handleFieldChange("dayOfMonth", v), disabled: isDisabled, size: size }), jsx(FieldSelect, { label: "Month", value: fields.month, options: monthOptions, onChange: (v) => handleFieldChange("month", v), disabled: isDisabled, size: size }), jsx(FieldSelect, { label: "Day of Week", value: fields.dayOfWeek, options: dayOfWeekOptions, onChange: (v) => handleFieldChange("dayOfWeek", v), disabled: isDisabled, size: size })] })), showRaw && (jsxs("div", { children: [jsx("div", { className: cn(theme.sectionHeadingStyle, "mb-1.5"), children: "Cron Expression" }), jsx("input", { type: "text", value: rawInput, onChange: handleRawInputChange, onBlur: handleRawInputBlur, onKeyDown: handleRawKeyDown, disabled: isDisabled, placeholder: "* * * * *", className: cn(theme.rawInputStyle, theme.rawInputSizes[size], isInvalid && "border-[var(--color-danger)] focus:border-[var(--color-danger)] focus:ring-[var(--color-danger)]"), id: `${generatedId}-cron`, "aria-label": "Cron expression", "aria-invalid": isInvalid || !validateCron(rawInput), "aria-describedby": helperText ? helperId : undefined, spellCheck: false, autoComplete: "off" }), !validateCron(rawInput) && rawInput !== cronValue && (jsx("div", { className: cn(theme.errorStyle, "mt-1"), children: "Invalid cron expression. Format: minute hour day month weekday" }))] })), showVisual && !showRaw && (jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: cn(theme.fieldLabelStyle, "shrink-0"), children: "Expression:" }), jsx("code", { className: cn("font-mono text-sm px-2 py-1 rounded-[var(--form-radius)]", "bg-[var(--color-surface-sunken)] text-[var(--color-text-primary)]"), children: cronValue })] })), showDescription && isValid && (jsxs("div", { className: theme.descriptionStyle, children: [jsx(ClockIcon, { className: "w-4 h-4 shrink-0", "aria-hidden": "true" }), jsx("span", { children: description })] })), showNextRuns && isValid && nextRuns.length > 0 && (jsxs("div", { className: theme.nextRunsStyle, children: [jsx("div", { className: cn(theme.sectionHeadingStyle, "mb-1"), children: "Next runs" }), nextRuns.map((date, index) => (jsxs("div", { className: theme.nextRunItemStyle, children: [jsx(CalendarIcon, { className: "w-3.5 h-3.5 shrink-0", "aria-hidden": "true" }), jsx("span", { children: formatNextRun(date) })] }, index)))] })), helperText && (jsx("div", { id: helperId, className: cn("text-sm mt-1", isInvalid
|
|
108
108
|
? "text-[var(--color-danger)]"
|
|
109
109
|
: "text-[var(--color-text-muted)]"), children: helperText }))] }));
|
|
110
110
|
});
|
|
@@ -8,21 +8,20 @@ const cronInputTheme = {
|
|
|
8
8
|
// Outer wrapper
|
|
9
9
|
baseStyle: "relative w-full flex flex-col gap-3",
|
|
10
10
|
// Label
|
|
11
|
-
labelStyle: "text-sm font-medium text-[var(--color-text-primary)]
|
|
11
|
+
labelStyle: "text-sm font-medium text-[var(--color-text-primary)]",
|
|
12
12
|
// Visual builder grid
|
|
13
13
|
builderStyle: "grid grid-cols-5 gap-2",
|
|
14
14
|
// Individual field group
|
|
15
15
|
fieldGroupStyle: "flex flex-col gap-1",
|
|
16
16
|
// Field label
|
|
17
|
-
fieldLabelStyle: "text-xs font-medium text-[var(--color-text-secondary)]
|
|
17
|
+
fieldLabelStyle: "text-xs font-medium text-[var(--color-text-secondary)]",
|
|
18
18
|
// Select dropdown
|
|
19
|
-
fieldSelectStyle: "w-full rounded-[var(--form-radius)] outline
|
|
20
|
-
"bg-
|
|
21
|
-
"focus:
|
|
19
|
+
fieldSelectStyle: "w-full rounded-[var(--form-radius)] outline-none shadow-[inset_0_0_0_1px_var(--color-border)] " +
|
|
20
|
+
"bg-[var(--color-surface)] text-[var(--color-text-primary)] cursor-pointer transition-all " +
|
|
21
|
+
"focus:shadow-[inset_0_0_0_1px_var(--color-primary-600)] " +
|
|
22
22
|
"focus:ring-4 focus:ring-[var(--color-primary)]/10 " +
|
|
23
23
|
"disabled:cursor-not-allowed disabled:bg-[var(--color-background-disabled)] disabled:text-[var(--color-text-disabled)] " +
|
|
24
|
-
"dark:
|
|
25
|
-
"dark:focus:outline-[var(--color-primary-500)] dark:focus:ring-[var(--color-primary-500)]/20",
|
|
24
|
+
"dark:focus:shadow-[inset_0_0_0_1px_var(--color-primary-500)] dark:focus:ring-[var(--color-primary-500)]/20",
|
|
26
25
|
// Size variants for field selects
|
|
27
26
|
fieldSelectSizes: {
|
|
28
27
|
sm: `${formsBaseTheme.sizes.sm.text} ${formsBaseTheme.sizes.sm.padding} ${formsBaseTheme.sizes.sm.height}`,
|
|
@@ -30,14 +29,13 @@ const cronInputTheme = {
|
|
|
30
29
|
lg: `${formsBaseTheme.sizes.lg.text} ${formsBaseTheme.sizes.lg.padding} ${formsBaseTheme.sizes.lg.height}`,
|
|
31
30
|
},
|
|
32
31
|
// Raw input field
|
|
33
|
-
rawInputStyle: "w-full rounded-[var(--form-radius)] outline
|
|
34
|
-
"bg-
|
|
32
|
+
rawInputStyle: "w-full rounded-[var(--form-radius)] outline-none shadow-[inset_0_0_0_1px_var(--color-border)] " +
|
|
33
|
+
"bg-[var(--color-surface)] text-[var(--color-text-primary)] font-mono transition-all " +
|
|
35
34
|
"placeholder:text-[var(--color-text-placeholder)] focus:outline-none " +
|
|
36
|
-
"focus:
|
|
35
|
+
"focus:shadow-[inset_0_0_0_1px_var(--color-primary-600)] " +
|
|
37
36
|
"focus:ring-4 focus:ring-[var(--color-primary)]/10 " +
|
|
38
37
|
"disabled:cursor-not-allowed disabled:bg-[var(--color-background-disabled)] disabled:text-[var(--color-text-disabled)] " +
|
|
39
|
-
"dark:
|
|
40
|
-
"dark:focus:outline-[var(--color-primary-500)] dark:focus:ring-[var(--color-primary-500)]/20",
|
|
38
|
+
"dark:focus:shadow-[inset_0_0_0_1px_var(--color-primary-500)] dark:focus:ring-[var(--color-primary-500)]/20",
|
|
41
39
|
// Size variants for raw input
|
|
42
40
|
rawInputSizes: {
|
|
43
41
|
sm: `${formsBaseTheme.sizes.sm.text} ${formsBaseTheme.sizes.sm.padding} ${formsBaseTheme.sizes.sm.height}`,
|
|
@@ -46,37 +44,30 @@ const cronInputTheme = {
|
|
|
46
44
|
},
|
|
47
45
|
// Mode toggle button
|
|
48
46
|
modeToggleStyle: "inline-flex items-center justify-center rounded-[var(--form-radius)] px-3 py-1.5 text-xs font-medium " +
|
|
49
|
-
"cursor-pointer transition-all outline
|
|
50
|
-
"text-[var(--color-text-secondary)] bg-
|
|
51
|
-
"dark:bg-[var(--color-neutral-900)] dark:outline-[var(--color-neutral-700)] dark:text-[var(--color-neutral-400)] " +
|
|
52
|
-
"dark:hover:bg-[var(--color-neutral-800)]",
|
|
47
|
+
"cursor-pointer transition-all outline-none shadow-[inset_0_0_0_1px_var(--color-border)] " +
|
|
48
|
+
"text-[var(--color-text-secondary)] bg-[var(--color-surface)] hover:bg-[var(--color-surface-hover)]",
|
|
53
49
|
// Active mode toggle
|
|
54
|
-
modeToggleActiveStyle: "
|
|
50
|
+
modeToggleActiveStyle: "shadow-[inset_0_0_0_1px_var(--color-primary)] bg-[var(--color-primary-50)] text-[var(--color-primary)] " +
|
|
55
51
|
"hover:bg-[var(--color-primary-50)] " +
|
|
56
|
-
"dark:
|
|
52
|
+
"dark:shadow-[inset_0_0_0_1px_var(--color-primary-500)] dark:bg-[var(--color-primary-500)]/10 dark:text-[var(--color-primary-400)] " +
|
|
57
53
|
"dark:hover:bg-[var(--color-primary-500)]/15",
|
|
58
54
|
// Preset button
|
|
59
55
|
presetButtonStyle: "inline-flex items-center rounded-[var(--form-radius)] px-2.5 py-1 text-xs font-medium " +
|
|
60
|
-
"cursor-pointer transition-all outline
|
|
61
|
-
"text-[var(--color-text-secondary)] bg-
|
|
62
|
-
"hover:text-[var(--color-text-primary)]
|
|
63
|
-
"dark:bg-[var(--color-neutral-900)] dark:outline-[var(--color-neutral-700)] dark:text-[var(--color-neutral-400)] " +
|
|
64
|
-
"dark:hover:bg-[var(--color-neutral-800)] dark:hover:text-[var(--color-neutral-200)]",
|
|
56
|
+
"cursor-pointer transition-all outline-none shadow-[inset_0_0_0_1px_var(--color-border)] " +
|
|
57
|
+
"text-[var(--color-text-secondary)] bg-[var(--color-surface)] hover:bg-[var(--color-surface-hover)] " +
|
|
58
|
+
"hover:text-[var(--color-text-primary)]",
|
|
65
59
|
// Active preset button
|
|
66
|
-
presetButtonActiveStyle: "
|
|
60
|
+
presetButtonActiveStyle: "shadow-[inset_0_0_0_1px_var(--color-primary)] bg-[var(--color-primary-50)] text-[var(--color-primary)] " +
|
|
67
61
|
"hover:bg-[var(--color-primary-100)] " +
|
|
68
|
-
"dark:
|
|
62
|
+
"dark:shadow-[inset_0_0_0_1px_var(--color-primary-500)] dark:bg-[var(--color-primary-500)]/10 dark:text-[var(--color-primary-400)]",
|
|
69
63
|
// Human-readable description
|
|
70
|
-
descriptionStyle: "flex items-center gap-2 text-sm text-[var(--color-text-muted)]
|
|
71
|
-
"dark:text-[var(--color-neutral-400)]",
|
|
64
|
+
descriptionStyle: "flex items-center gap-2 text-sm text-[var(--color-text-muted)]",
|
|
72
65
|
// Next runs container
|
|
73
66
|
nextRunsStyle: "flex flex-col gap-1",
|
|
74
67
|
// Individual next run item
|
|
75
|
-
nextRunItemStyle: "flex items-center gap-2 text-xs text-[var(--color-text-muted)]
|
|
76
|
-
"dark:text-[var(--color-neutral-400)]",
|
|
68
|
+
nextRunItemStyle: "flex items-center gap-2 text-xs text-[var(--color-text-muted)]",
|
|
77
69
|
// Section heading
|
|
78
|
-
sectionHeadingStyle: "text-xs font-medium text-[var(--color-text-secondary)] uppercase tracking-wide
|
|
79
|
-
"dark:text-[var(--color-neutral-400)]",
|
|
70
|
+
sectionHeadingStyle: "text-xs font-medium text-[var(--color-text-secondary)] uppercase tracking-wide",
|
|
80
71
|
// Validation error
|
|
81
72
|
errorStyle: "text-xs text-[var(--color-danger)] dark:text-[var(--color-danger-400)]",
|
|
82
73
|
};
|
|
@@ -10,8 +10,8 @@ import { formsBaseTheme } from '../forms.theme.js';
|
|
|
10
10
|
const datePickerTheme = {
|
|
11
11
|
containerStyle: formsBaseTheme.wrapperStyle,
|
|
12
12
|
baseStyle: formsBaseTheme.inputGroupBaseStyle + " justify-between cursor-pointer",
|
|
13
|
-
// Trigger button style -
|
|
14
|
-
triggerButtonStyle: "w-full cursor-pointer bg-
|
|
13
|
+
// Trigger button style - surface flips automatically between light/dark
|
|
14
|
+
triggerButtonStyle: "w-full cursor-pointer bg-[var(--color-surface)]",
|
|
15
15
|
// Placeholder text style - matches Input placeholder styling
|
|
16
16
|
placeholderTextStyle: "text-[var(--color-text-placeholder)]",
|
|
17
17
|
// Selected value text style
|
|
@@ -26,23 +26,16 @@ const datePickerTheme = {
|
|
|
26
26
|
triggerFocusStates: formsBaseTheme.focusStates,
|
|
27
27
|
iconEndStyle: formsBaseTheme.iconStyles.right,
|
|
28
28
|
iconEndPadding: formsBaseTheme.iconStyles.padding.right,
|
|
29
|
-
// Dropdown body -
|
|
30
|
-
bodyStyle: "min-w-fit max-w-none bg-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
//
|
|
35
|
-
presetsContainerStyle: "flex flex-col gap-1 p-3 border-b sm:border-b-0 sm:border-r border-[var(--color-border)] bg-[var(--color-neutral-50)] sm:min-w-[180px] " +
|
|
36
|
-
"dark:bg-[var(--color-neutral-800)] dark:border-[var(--color-neutral-700)]",
|
|
37
|
-
// Preset button - with dark mode support
|
|
29
|
+
// Dropdown body - floating overlay surface flips automatically
|
|
30
|
+
bodyStyle: "min-w-fit max-w-none bg-[var(--color-surface-overlay)] border border-[var(--color-border)] rounded-[var(--popover-radius)] shadow-real-xl p-0 overflow-hidden z-[1000] fixed",
|
|
31
|
+
bodyWithPresetsStyle: "flex flex-col sm:flex-row w-fit max-w-[calc(100vw-2rem)] sm:max-w-none bg-[var(--color-surface-overlay)] border border-[var(--color-border)] rounded-[var(--popover-radius)] shadow-lg p-0 overflow-hidden z-[1000] fixed",
|
|
32
|
+
// Presets sidebar - recessed sunken panel flips automatically
|
|
33
|
+
presetsContainerStyle: "flex flex-col gap-1 p-3 border-b sm:border-b-0 sm:border-r border-[var(--color-border)] bg-[var(--color-surface-sunken)] sm:min-w-[180px]",
|
|
34
|
+
// Preset button - surface hover/active fills flip automatically
|
|
38
35
|
presetButtonStyle: "w-full text-left px-3 py-2 text-sm rounded-[calc(var(--radius-base)*0.75)] transition-colors cursor-pointer " +
|
|
39
|
-
"text-[var(--color-text-secondary)] hover:bg-
|
|
40
|
-
"focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 " +
|
|
41
|
-
"data-[active=true]:bg-
|
|
42
|
-
// Dark mode
|
|
43
|
-
"dark:text-[var(--color-neutral-400)] dark:hover:bg-[var(--color-neutral-700)] dark:hover:text-[var(--color-neutral-200)] " +
|
|
44
|
-
"dark:data-[active=true]:bg-[var(--color-neutral-700)] dark:data-[active=true]:text-[var(--color-neutral-100)] " +
|
|
45
|
-
"dark:focus-visible:ring-offset-[var(--color-neutral-800)]",
|
|
36
|
+
"text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-hover)] hover:text-[var(--color-text-primary)] " +
|
|
37
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-sunken)] " +
|
|
38
|
+
"data-[active=true]:bg-[var(--color-surface)] data-[active=true]:text-[var(--color-text-primary)] data-[active=true]:font-medium",
|
|
46
39
|
helperTextStyle: formsBaseTheme.helperText,
|
|
47
40
|
helperTextStates: {
|
|
48
41
|
default: "text-[var(--color-text-muted)] dark:text-[var(--color-neutral-400)]",
|
|
@@ -26,7 +26,7 @@ const DatePickerTrigger = ({ id, disabled, isOpen, state = "default", size = "md
|
|
|
26
26
|
// Apply focused styles when open - same pattern as SelectButton
|
|
27
27
|
const activeFocusState = isOpen
|
|
28
28
|
? focusStateStyle ||
|
|
29
|
-
"
|
|
29
|
+
"shadow-[inset_0_0_0_1px_var(--color-primary-600)] ring-4 ring-[var(--color-primary)]/10"
|
|
30
30
|
: "";
|
|
31
31
|
return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open calendar", "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, children: [children, jsx("span", { className: iconEndStyle, children: jsx(CalendarIcon, { className: "h-4 w-4" }) })] }) }));
|
|
32
32
|
};
|
|
@@ -6,7 +6,7 @@ import { formsBaseTheme } from '../forms.theme.js';
|
|
|
6
6
|
const dateRangePickerTheme = {
|
|
7
7
|
containerStyle: formsBaseTheme.wrapperStyle,
|
|
8
8
|
baseStyle: formsBaseTheme.inputGroupBaseStyle + " justify-between cursor-pointer",
|
|
9
|
-
triggerButtonStyle: "w-full cursor-pointer bg-
|
|
9
|
+
triggerButtonStyle: "w-full cursor-pointer bg-[var(--color-surface)]",
|
|
10
10
|
placeholderTextStyle: "text-[var(--color-text-placeholder)]",
|
|
11
11
|
valueTextStyle: "text-[var(--color-text-primary)]",
|
|
12
12
|
triggerSizes: {
|
|
@@ -19,26 +19,19 @@ const dateRangePickerTheme = {
|
|
|
19
19
|
triggerFocusStates: formsBaseTheme.focusStates,
|
|
20
20
|
iconEndStyle: formsBaseTheme.iconStyles.right,
|
|
21
21
|
iconEndPadding: formsBaseTheme.iconStyles.padding.right,
|
|
22
|
-
bodyStyle: "flex flex-col sm:flex-row w-fit max-w-[calc(100vw-2rem)] sm:max-w-none bg-
|
|
23
|
-
|
|
24
|
-
presetsContainerStyle: "hidden sm:flex flex-col gap-1 p-3 sm:border-r border-[var(--color-border)] bg-[var(--color-neutral-50)] sm:min-w-[180px] " +
|
|
25
|
-
"dark:bg-[var(--color-neutral-800)] ",
|
|
22
|
+
bodyStyle: "flex flex-col sm:flex-row w-fit max-w-[calc(100vw-2rem)] sm:max-w-none bg-[var(--color-surface-overlay)] border border-[var(--color-border)] rounded-[var(--popover-radius)] shadow-lg p-0 overflow-hidden z-[1000] fixed",
|
|
23
|
+
presetsContainerStyle: "hidden sm:flex flex-col gap-1 p-3 sm:border-r border-[var(--color-border)] bg-[var(--color-surface-sunken)] sm:min-w-[180px]",
|
|
26
24
|
presetButtonStyle: "w-full text-left px-3 py-2 text-sm font-medium rounded-[calc(var(--radius-base)*0.75)] transition-colors cursor-pointer " +
|
|
27
25
|
"flex items-center justify-between gap-2 " +
|
|
28
|
-
"text-[var(--color-text-secondary)] hover:bg-
|
|
29
|
-
"focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 " +
|
|
30
|
-
"data-[active=true]:bg-
|
|
31
|
-
"dark:hover:bg-[var(--color-neutral-700)] " +
|
|
32
|
-
"dark:data-[active=true]:bg-[var(--color-neutral-700)] dark:data-[active=true]:text-[var(--color-neutral-100)] " +
|
|
33
|
-
"dark:focus-visible:ring-offset-[var(--color-neutral-800)]",
|
|
26
|
+
"text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-hover)] hover:text-[var(--color-text-primary)] " +
|
|
27
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-surface-sunken)] " +
|
|
28
|
+
"data-[active=true]:bg-[var(--color-surface)] data-[active=true]:text-[var(--color-text-primary)] data-[active=true]:font-medium",
|
|
34
29
|
presetCheckmarkStyle: "size-4 text-[var(--color-primary)] shrink-0",
|
|
35
30
|
mobilePresetsContainerStyle: "sm:hidden px-3 pt-3 pb-1",
|
|
36
31
|
mobilePresetButtonStyle: "whitespace-nowrap px-3 py-1.5 text-xs font-medium rounded-full transition-colors cursor-pointer shrink-0 " +
|
|
37
32
|
"bg-[var(--color-background-secondary)] text-[var(--color-text-secondary)] " +
|
|
38
|
-
"hover:bg-[var(--color-
|
|
33
|
+
"hover:bg-[var(--color-surface-hover)] hover:text-[var(--color-text-primary)] " +
|
|
39
34
|
"data-[active=true]:bg-[var(--color-primary-50)] data-[active=true]:text-[var(--color-primary)] " +
|
|
40
|
-
"dark:bg-[var(--color-neutral-800)] dark:text-[var(--color-neutral-300)] " +
|
|
41
|
-
"dark:hover:bg-[var(--color-neutral-700)] " +
|
|
42
35
|
"dark:data-[active=true]:bg-[var(--color-primary-950)] dark:data-[active=true]:text-[var(--color-primary-300)]",
|
|
43
36
|
mobileRangeDisplayStyle: "sm:hidden text-xs text-center py-2 text-[var(--color-text-secondary)] dark:text-[var(--color-neutral-400)]",
|
|
44
37
|
helperTextStyle: formsBaseTheme.helperText,
|
|
@@ -24,7 +24,7 @@ const DateRangePickerTrigger = ({ id, disabled, isOpen, state = "default", size
|
|
|
24
24
|
const triggerButtonStyle = theme.triggerButtonStyle || "";
|
|
25
25
|
const activeFocusState = isOpen
|
|
26
26
|
? focusStateStyle ||
|
|
27
|
-
"
|
|
27
|
+
"shadow-[inset_0_0_0_1px_var(--color-primary-600)] ring-4 ring-[var(--color-primary)]/10"
|
|
28
28
|
: "";
|
|
29
29
|
return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open date range picker", "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, children: [children, jsx("span", { className: iconEndStyle, children: jsx(CalendarIcon, { className: "h-4 w-4" }) })] }) }));
|
|
30
30
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Spring used for thumbnail enter and for the layout reflow when items are removed. */
|
|
2
|
+
export declare const PREVIEW_LAYOUT_SPRING: {
|
|
3
|
+
type: "spring";
|
|
4
|
+
stiffness: number;
|
|
5
|
+
damping: number;
|
|
6
|
+
mass: number;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Enter / exit variants for a preview thumbnail.
|
|
10
|
+
* Exit shrinks + fades so the surrounding items can flow into the gap (driven
|
|
11
|
+
* by `layout` on each item). Pair with `AnimatePresence`.
|
|
12
|
+
*/
|
|
13
|
+
export declare const PREVIEW_ITEM: {
|
|
14
|
+
initial: {
|
|
15
|
+
opacity: number;
|
|
16
|
+
scale: number;
|
|
17
|
+
};
|
|
18
|
+
animate: {
|
|
19
|
+
opacity: number;
|
|
20
|
+
scale: number;
|
|
21
|
+
};
|
|
22
|
+
exit: {
|
|
23
|
+
opacity: number;
|
|
24
|
+
scale: number;
|
|
25
|
+
transition: {
|
|
26
|
+
duration: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Spring used for thumbnail enter and for the layout reflow when items are removed. */
|
|
2
|
+
const PREVIEW_LAYOUT_SPRING = {
|
|
3
|
+
type: "spring",
|
|
4
|
+
stiffness: 500,
|
|
5
|
+
damping: 38,
|
|
6
|
+
mass: 0.8,
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Enter / exit variants for a preview thumbnail.
|
|
10
|
+
* Exit shrinks + fades so the surrounding items can flow into the gap (driven
|
|
11
|
+
* by `layout` on each item). Pair with `AnimatePresence`.
|
|
12
|
+
*/
|
|
13
|
+
const PREVIEW_ITEM = {
|
|
14
|
+
initial: { opacity: 0, scale: 0.8 },
|
|
15
|
+
animate: { opacity: 1, scale: 1 },
|
|
16
|
+
exit: { opacity: 0, scale: 0.8, transition: { duration: 0.15 } },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { PREVIEW_ITEM, PREVIEW_LAYOUT_SPRING };
|