@flikk/ui 1.0.0-beta.20 → 1.0.0-beta.22
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.theme.js +3 -3
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +1 -1
- package/dist/components/ai/StreamingResponse/StreamingResponse.theme.js +4 -4
- package/dist/components/ai/TokenCounter/TokenCounter.theme.js +6 -6
- package/dist/components/charts/ActivityRings/ActivityRings.theme.js +2 -2
- package/dist/components/charts/DonutChart/DonutChart.theme.js +2 -2
- package/dist/components/charts/DonutChart/MultiSegmentDonutChart.theme.js +1 -1
- package/dist/components/charts/Heatmap/Heatmap.theme.js +1 -1
- package/dist/components/charts/RadarChart/RadarChart.theme.js +2 -2
- package/dist/components/charts/ScatterPlot/ScatterPlot.theme.js +2 -2
- package/dist/components/charts/shared/ChartText/ChartText.theme.js +1 -1
- package/dist/components/charts/shared/ChartTooltip/ChartTooltip.theme.js +4 -4
- package/dist/components/core/Alert/Alert.theme.js +1 -1
- package/dist/components/core/Avatar/Avatar.theme.js +10 -10
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +1 -1
- package/dist/components/core/Badge/Badge.js +2 -12
- package/dist/components/core/Badge/Badge.theme.js +2 -2
- package/dist/components/core/Button/Button.theme.js +6 -6
- package/dist/components/core/ButtonGroup/ButtonGroup.theme.js +1 -1
- package/dist/components/core/Calendar/Calendar.theme.js +5 -5
- package/dist/components/core/Card/Card.theme.js +2 -2
- package/dist/components/core/CommandPalette/CommandPalette.theme.js +4 -4
- package/dist/components/core/Drawer/Drawer.animations.js +5 -4
- package/dist/components/core/Drawer/Drawer.theme.js +2 -2
- package/dist/components/core/Dropdown/Dropdown.theme.js +1 -1
- package/dist/components/core/Empty/Empty.theme.js +2 -2
- package/dist/components/core/Icon/Icon.d.ts +3 -0
- package/dist/components/core/Icon/Icon.js +70 -0
- package/dist/components/core/Icon/Icon.theme.d.ts +2 -0
- package/dist/components/core/Icon/Icon.theme.js +19 -0
- package/dist/components/core/Icon/Icon.types.d.ts +32 -0
- package/dist/components/core/{FileTypeIcon → Icon/data}/fileTypes.d.ts +1 -1
- package/dist/components/core/Icon/data/paymentMethods.d.ts +27 -0
- package/dist/components/core/Icon/data/paymentMethods.js +169 -0
- package/dist/components/core/Icon/index.d.ts +4 -0
- package/dist/components/core/Kbd/Kbd.theme.js +2 -2
- package/dist/components/core/MenuItem/MenuItem.theme.js +2 -2
- package/dist/components/core/Message/Message.theme.js +6 -6
- package/dist/components/core/Modal/Modal.animations.js +3 -1
- package/dist/components/core/Modal/Modal.theme.js +2 -2
- package/dist/components/core/Modal/ModalBody.js +7 -8
- package/dist/components/core/NavItem/NavItem.theme.js +1 -1
- package/dist/components/core/OfflineIndicator/OfflineIndicator.theme.js +2 -2
- package/dist/components/core/PageHeading/PageHeading.theme.js +2 -2
- package/dist/components/core/Pagination/Pagination.theme.js +2 -2
- package/dist/components/core/Pill/Pill.theme.js +3 -3
- package/dist/components/core/Progress/Progress.theme.js +2 -2
- package/dist/components/core/Segmented/Segmented.theme.js +3 -3
- package/dist/components/core/Tabs/Tabs.theme.js +2 -2
- package/dist/components/core/Tag/Tag.theme.js +2 -2
- package/dist/components/core/Toast/Toast.theme.js +2 -2
- package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
- package/dist/components/core/Tree/Tree.theme.js +1 -1
- package/dist/components/core/index.d.ts +1 -2
- package/dist/components/core/index.js +2 -2
- package/dist/components/data-display/DescriptionList/DescriptionList.theme.js +2 -2
- package/dist/components/data-display/Feed/Feed.theme.js +1 -1
- package/dist/components/data-display/GanttChart/GanttChart.theme.js +2 -2
- package/dist/components/data-display/KPI/KPI.theme.js +9 -9
- package/dist/components/data-display/Metric/Metric.theme.js +9 -9
- package/dist/components/data-display/Table/Table.animations.js +16 -10
- package/dist/components/data-display/Table/Table.filterUtils.js +8 -1
- package/dist/components/data-display/Table/Table.js +10 -14
- package/dist/components/data-display/Table/Table.theme.js +3 -3
- package/dist/components/data-display/Table/Table.types.d.ts +2 -0
- package/dist/components/data-display/Table/TableActions.js +3 -3
- package/dist/components/data-display/Table/TableActionsMenu.js +2 -3
- package/dist/components/data-display/Table/TableCell.js +6 -3
- package/dist/components/data-display/Table/TableDeclarative.js +5 -7
- package/dist/components/data-display/Table/TableHeader.js +5 -2
- package/dist/components/data-display/Table/TablePagination.js +2 -6
- package/dist/components/data-display/Table/TableRow.js +2 -6
- package/dist/components/data-display/Table/index.js +1 -0
- package/dist/components/effects/Animated/Animated.animations.js +29 -10
- package/dist/components/effects/Animated/Animated.d.ts +2 -2
- package/dist/components/effects/Animated/Animated.js +4 -3
- package/dist/components/effects/Animated/AnimatedItem.d.ts +1 -1
- package/dist/components/effects/Animated/AnimatedItem.js +5 -4
- package/dist/components/effects/CustomCursor/CustomCursor.theme.js +1 -1
- package/dist/components/effects/Overlay/Overlay.js +50 -21
- package/dist/components/forms/Checkbox/Checkbox.theme.js +3 -7
- package/dist/components/forms/ColorPicker/ColorPicker.d.ts +5 -9
- package/dist/components/forms/ColorPicker/ColorPicker.js +126 -22
- package/dist/components/forms/ColorPicker/ColorPicker.theme.js +9 -6
- package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +99 -0
- package/dist/components/forms/ColorPicker/ColorPicker2DCanvas.js +43 -6
- package/dist/components/forms/ColorPicker/ColorPickerBody.js +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerContext.d.ts +4 -0
- package/dist/components/forms/ColorPicker/ColorPickerContext.js +12 -0
- package/dist/components/forms/ColorPicker/ColorPickerEyeDropper.js +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerFormatSelector.js +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerGradient.d.ts +7 -0
- package/dist/components/forms/ColorPicker/ColorPickerGradient.js +186 -0
- package/dist/components/forms/ColorPicker/ColorPickerHeader.d.ts +14 -0
- package/dist/components/forms/ColorPicker/ColorPickerHeader.js +31 -0
- package/dist/components/forms/ColorPicker/ColorPickerImage.d.ts +6 -0
- package/dist/components/forms/ColorPicker/ColorPickerImage.js +154 -0
- package/dist/components/forms/ColorPicker/ColorPickerInput.d.ts +0 -4
- package/dist/components/forms/ColorPicker/ColorPickerInput.js +53 -61
- package/dist/components/forms/ColorPicker/ColorPickerPresets.js +13 -12
- package/dist/components/forms/ColorPicker/ColorPickerSavedColors.d.ts +3 -0
- package/dist/components/forms/ColorPicker/ColorPickerSavedColors.js +69 -0
- package/dist/components/forms/ColorPicker/ColorPickerSliders.d.ts +1 -2
- package/dist/components/forms/ColorPicker/ColorPickerSliders.js +84 -23
- package/dist/components/forms/ColorPicker/ColorPickerSwatch.d.ts +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerSwatch.js +10 -9
- package/dist/components/forms/ColorPicker/ColorPickerTrigger.js +7 -3
- package/dist/components/forms/ColorPicker/index.d.ts +8 -2
- package/dist/components/forms/CronInput/CronInput.theme.js +8 -8
- package/dist/components/forms/DatePicker/DatePicker.theme.js +1 -1
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +3 -3
- package/dist/components/forms/FileUpload/FileUpload.theme.js +4 -4
- package/dist/components/forms/FileUpload/FileUploadProgress.js +3 -3
- package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +2 -2
- package/dist/components/forms/FormLabel/FormLabel.theme.js +1 -1
- package/dist/components/forms/Input/Input.js +3 -3
- package/dist/components/forms/Input/Input.theme.js +1 -1
- package/dist/components/forms/Input/Input.types.d.ts +2 -0
- package/dist/components/forms/InputCounter/InputCounter.theme.js +1 -1
- package/dist/components/forms/InputOTP/InputOTP.theme.js +1 -1
- package/dist/components/forms/Mention/Mention.theme.js +3 -3
- package/dist/components/forms/Radio/Radio.animations.js +6 -2
- package/dist/components/forms/Radio/Radio.js +1 -1
- package/dist/components/forms/Radio/Radio.theme.js +11 -11
- package/dist/components/forms/Radio/Radio.types.d.ts +1 -0
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +1 -1
- package/dist/components/forms/Select/Select.theme.js +1 -1
- package/dist/components/forms/SelectableCard/SelectableCard.js +42 -27
- package/dist/components/forms/SelectableCard/SelectableCard.theme.js +15 -25
- package/dist/components/forms/SelectableCard/SelectableCard.types.d.ts +16 -3
- package/dist/components/forms/SelectableCard/SelectableCardContext.d.ts +1 -0
- package/dist/components/forms/SelectableCard/SelectableCardContext.js +4 -7
- package/dist/components/forms/SelectableCard/SelectableCardGroup.js +31 -10
- package/dist/components/forms/SelectableCard/index.d.ts +1 -1
- package/dist/components/forms/Signature/Signature.theme.js +1 -1
- package/dist/components/forms/Slider/Slider.theme.js +3 -3
- package/dist/components/forms/Switch/Switch.theme.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +2 -2
- package/dist/components/forms/forms.theme.js +6 -6
- package/dist/components/forms/index.js +6 -1
- package/dist/components/layout/FormLayout/FormLayout.theme.js +2 -2
- package/dist/hooks/useOverlay.d.ts +2 -0
- package/dist/hooks/useOverlay.js +34 -4
- package/dist/index.js +8 -3
- package/dist/styles.css +1 -1
- package/package.json +2 -1
- package/src/global.scss +1 -1
- package/src/styles/theme.css +1 -1
- package/dist/bg/bg/1.jpg +0 -0
- package/dist/bg/bg/10.jpg +0 -0
- package/dist/bg/bg/11.jpg +0 -0
- package/dist/bg/bg/14.jpg +0 -0
- package/dist/bg/bg/15.jpg +0 -0
- package/dist/bg/bg/16.jpg +0 -0
- package/dist/bg/bg/17.jpg +0 -0
- package/dist/bg/bg/18.jpg +0 -0
- package/dist/bg/bg/19.jpg +0 -0
- package/dist/bg/bg/2.jpg +0 -0
- package/dist/bg/bg/20.jpg +0 -0
- package/dist/bg/bg/21.jpg +0 -0
- package/dist/bg/bg/22.jpg +0 -0
- package/dist/bg/bg/23.jpg +0 -0
- package/dist/bg/bg/24.jpg +0 -0
- package/dist/bg/bg/3.jpg +0 -0
- package/dist/bg/bg/4.jpg +0 -0
- package/dist/bg/bg/5.jpg +0 -0
- package/dist/bg/bg/6.jpg +0 -0
- package/dist/bg/bg/7.jpg +0 -0
- package/dist/bg/bg/8.jpg +0 -0
- package/dist/bg/bg/9.jpg +0 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.d.ts +0 -3
- package/dist/components/core/FileTypeIcon/FileTypeIcon.js +0 -33
- package/dist/components/core/FileTypeIcon/FileTypeIcon.theme.d.ts +0 -2
- package/dist/components/core/FileTypeIcon/FileTypeIcon.theme.js +0 -12
- package/dist/components/core/FileTypeIcon/FileTypeIcon.types.d.ts +0 -19
- package/dist/components/core/FileTypeIcon/index.d.ts +0 -2
- package/dist/components/core/SocialIcon/SocialIcon.d.ts +0 -3
- package/dist/components/core/SocialIcon/SocialIcon.js +0 -30
- package/dist/components/core/SocialIcon/SocialIcon.theme.d.ts +0 -2
- package/dist/components/core/SocialIcon/SocialIcon.theme.js +0 -12
- package/dist/components/core/SocialIcon/SocialIcon.types.d.ts +0 -18
- package/dist/components/core/SocialIcon/index.d.ts +0 -2
- /package/dist/components/core/{FileTypeIcon → Icon/data}/fileTypes.js +0 -0
- /package/dist/components/core/{SocialIcon → Icon/data}/platforms.d.ts +0 -0
- /package/dist/components/core/{SocialIcon → Icon/data}/platforms.js +0 -0
|
@@ -11,13 +11,9 @@ const radioTheme = {
|
|
|
11
11
|
// Default state - dark
|
|
12
12
|
"dark:bg-[var(--color-background-tertiary)] " +
|
|
13
13
|
// Checked state - light
|
|
14
|
-
"checked:border-[var(--color-primary)]
|
|
14
|
+
"checked:border-[var(--color-primary)] checked:bg-white " +
|
|
15
15
|
// Checked state - dark
|
|
16
|
-
"checked:bg-[var(--color-
|
|
17
|
-
// Checked outline - light
|
|
18
|
-
"checked:outline-2 checked:outline-[var(--color-primary-100)] checked:outline-offset-1 " +
|
|
19
|
-
// Checked outline - dark
|
|
20
|
-
"dark:checked:outline-[var(--color-primary-900)] " +
|
|
16
|
+
"dark:checked:bg-[var(--color-surface)] " +
|
|
21
17
|
// Focus visible - light
|
|
22
18
|
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-primary-600)] " +
|
|
23
19
|
// Focus visible - dark
|
|
@@ -28,17 +24,21 @@ const radioTheme = {
|
|
|
28
24
|
// Disabled state - dark
|
|
29
25
|
"dark:disabled:bg-[var(--color-neutral-700)] dark:disabled:border-[var(--color-neutral-600)] " +
|
|
30
26
|
"dark:data-[state=disabled]:bg-[var(--color-neutral-700)] dark:data-[state=disabled]:border-[var(--color-neutral-600)]",
|
|
31
|
-
dotStyle: "absolute
|
|
32
|
-
|
|
27
|
+
dotStyle: "absolute top-1/2 left-1/2 pointer-events-none rounded-full bg-[var(--color-primary)]",
|
|
28
|
+
dotSizes: {
|
|
29
|
+
sm: "size-2.5 mt-0.25",
|
|
30
|
+
md: "size-3",
|
|
31
|
+
},
|
|
32
|
+
descriptionStyle: "text-sm text-[var(--color-text-secondary)]/80 mt-0",
|
|
33
33
|
sizes: {
|
|
34
|
-
sm: "size-5 mt-0.
|
|
34
|
+
sm: "size-5 mt-0.5",
|
|
35
35
|
md: "size-6",
|
|
36
36
|
},
|
|
37
37
|
// Group styles
|
|
38
38
|
groupStyle: "flex flex-col gap-1.5",
|
|
39
39
|
groupHorizontalStyle: "flex-row flex-wrap gap-x-6 gap-y-3",
|
|
40
|
-
groupDescriptionStyle: "text-
|
|
41
|
-
groupErrorStyle: "text-
|
|
40
|
+
groupDescriptionStyle: "text-sm text-[var(--color-text-secondary)]/80 -mt-0.5 mb-1",
|
|
41
|
+
groupErrorStyle: "text-sm text-[var(--color-danger)] mt-1.5",
|
|
42
42
|
groupItemsStyle: "flex flex-col gap-3",
|
|
43
43
|
};
|
|
44
44
|
|
|
@@ -32,7 +32,7 @@ const richTextEditorTheme = {
|
|
|
32
32
|
// Dropdown styling (font size, color picker)
|
|
33
33
|
dropdownStyle: "fixed z-[1000] min-w-[120px] py-1 bg-white/90 backdrop-blur-md rounded-[var(--form-radius)] shadow-xl ring-1 ring-[var(--color-border)] focus:outline-none",
|
|
34
34
|
// Dropdown item styling
|
|
35
|
-
dropdownItemStyle: "block w-full px-3 py-2 text-left text-
|
|
35
|
+
dropdownItemStyle: "block w-full px-3 py-2 text-left text-sm text-[var(--color-text-primary)] hover:bg-[var(--color-background-tertiary)] transition-colors duration-150 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
36
36
|
// Separator between toolbar sections
|
|
37
37
|
separatorStyle: "w-px h-6 bg-[var(--color-border)] mx-1",
|
|
38
38
|
// Color picker grid layout
|
|
@@ -60,7 +60,7 @@ const selectTheme = {
|
|
|
60
60
|
iconPadding: formsBaseTheme.iconStyles.padding,
|
|
61
61
|
// Multi-select chip styles
|
|
62
62
|
chipContainerStyle: "flex flex-nowrap gap-1 items-center min-w-0 overflow-hidden -ml-2",
|
|
63
|
-
chipOverflowStyle: "inline-flex items-center shrink-0 whitespace-nowrap px-1.5 py-0.5 text-
|
|
63
|
+
chipOverflowStyle: "inline-flex items-center shrink-0 whitespace-nowrap px-1.5 py-0.5 text-xs font-medium " +
|
|
64
64
|
"text-[var(--color-text-muted)]",
|
|
65
65
|
};
|
|
66
66
|
|
|
@@ -1,53 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import React__default, { useId } from 'react';
|
|
3
3
|
import { useReducedMotion, motion } from 'motion/react';
|
|
4
|
-
import { CheckIcon } from '@heroicons/react/24/outline';
|
|
5
4
|
import { cn } from '../../../utils/cn.js';
|
|
6
|
-
import {
|
|
5
|
+
import { Radio } from '../Radio/Radio.js';
|
|
6
|
+
import { Checkbox } from '../Checkbox/Checkbox.js';
|
|
7
|
+
import { useOptionalSelectableCardContext } from './SelectableCardContext.js';
|
|
8
|
+
import { selectableCardTheme } from './SelectableCard.theme.js';
|
|
7
9
|
import { SelectableCardGroup } from './SelectableCardGroup.js';
|
|
8
10
|
import { cardVariants } from './SelectableCard.animations.js';
|
|
9
11
|
|
|
10
|
-
// ─── Radio Indicator ─────────────────────────────────────────────────────────
|
|
11
|
-
const RadioIndicator = ({ checked }) => (jsxs("div", { className: "relative flex-shrink-0 flex items-center justify-center size-5", children: [jsx("div", { className: cn("size-5 rounded-full border-2 transition-colors duration-200", checked
|
|
12
|
-
? "border-[var(--color-primary)]"
|
|
13
|
-
: "border-[var(--color-border)]") }), jsx("div", { className: cn("absolute inset-0 m-auto rounded-full bg-[var(--color-primary)] transition-all duration-200", checked ? "size-2.5 opacity-100" : "size-0 opacity-0") })] }));
|
|
14
|
-
// ─── Checkbox Indicator ──────────────────────────────────────────────────────
|
|
15
|
-
const CheckboxIndicator = ({ checked }) => (jsx("div", { className: cn("flex-shrink-0 flex items-center justify-center size-5 rounded-[4px] border-2 transition-colors duration-200", checked
|
|
16
|
-
? "border-[var(--color-primary)] bg-[var(--color-primary)]"
|
|
17
|
-
: "border-[var(--color-border)] bg-[var(--color-background)]"), children: checked && jsx(CheckIcon, { className: "size-3.5 stroke-white", strokeWidth: 3 }) }));
|
|
18
12
|
// ─── SelectableCard ──────────────────────────────────────────────────────────
|
|
19
|
-
const SelectableCardRoot = React__default.forwardRef(({ value, disabled: cardDisabled, className, children, onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, ...props }, ref) => {
|
|
20
|
-
|
|
21
|
-
const ctx =
|
|
13
|
+
const SelectableCardRoot = React__default.forwardRef(({ value, disabled: cardDisabled, checked: standaloneChecked, onChange: standaloneOnChange, indicator: standaloneIndicator, indicatorPosition: cardIndicatorPosition, size: cardSize, className, children, onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, ...props }, ref) => {
|
|
14
|
+
var _a;
|
|
15
|
+
const ctx = useOptionalSelectableCardContext();
|
|
16
|
+
const isStandalone = ctx === undefined;
|
|
22
17
|
const inputId = useId();
|
|
23
18
|
const shouldReduceMotion = useReducedMotion();
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
const theme = isStandalone ? selectableCardTheme : ctx.theme;
|
|
20
|
+
const isDisabled = cardDisabled || (!isStandalone && ctx.disabled);
|
|
21
|
+
const isSelected = isStandalone
|
|
22
|
+
? (standaloneChecked !== null && standaloneChecked !== void 0 ? standaloneChecked : false)
|
|
23
|
+
: ctx.type === "single"
|
|
24
|
+
? ctx.value === value
|
|
25
|
+
: Array.isArray(ctx.value) && ctx.value.includes(value);
|
|
26
|
+
const resolvedIndicator = isStandalone
|
|
27
|
+
? (standaloneIndicator !== null && standaloneIndicator !== void 0 ? standaloneIndicator : "radio")
|
|
28
|
+
: ctx.indicator;
|
|
29
|
+
const resolvedIndicatorPosition = cardIndicatorPosition !== null && cardIndicatorPosition !== void 0 ? cardIndicatorPosition : (isStandalone ? "end" : ctx.indicatorPosition);
|
|
30
|
+
const resolvedSize = cardSize !== null && cardSize !== void 0 ? cardSize : (isStandalone ? "md" : ctx.size);
|
|
31
|
+
const indicatorSize = "sm";
|
|
28
32
|
const handleClick = () => {
|
|
29
33
|
if (isDisabled)
|
|
30
34
|
return;
|
|
31
|
-
|
|
35
|
+
if (isStandalone) {
|
|
36
|
+
standaloneOnChange === null || standaloneOnChange === void 0 ? void 0 : standaloneOnChange(!isSelected, value);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
ctx.onChange(value);
|
|
40
|
+
}
|
|
32
41
|
};
|
|
33
42
|
const handleKeyDown = (e) => {
|
|
34
43
|
if (isDisabled)
|
|
35
44
|
return;
|
|
36
45
|
if (e.key === " " || e.key === "Enter") {
|
|
37
46
|
e.preventDefault();
|
|
38
|
-
|
|
47
|
+
handleClick();
|
|
39
48
|
}
|
|
40
49
|
};
|
|
41
|
-
const inputType =
|
|
50
|
+
const inputType = isStandalone
|
|
51
|
+
? "checkbox"
|
|
52
|
+
: ctx.type === "single"
|
|
53
|
+
? "radio"
|
|
54
|
+
: "checkbox";
|
|
55
|
+
const role = isStandalone
|
|
56
|
+
? "checkbox"
|
|
57
|
+
: ctx.type === "single"
|
|
58
|
+
? "radio"
|
|
59
|
+
: "checkbox";
|
|
42
60
|
const animated = !shouldReduceMotion && !isDisabled;
|
|
43
61
|
const motionProps = animated
|
|
44
|
-
? {
|
|
45
|
-
variants: cardVariants,
|
|
46
|
-
initial: "idle",
|
|
47
|
-
whileTap: "tap",
|
|
48
|
-
}
|
|
62
|
+
? { variants: cardVariants, initial: "idle", whileTap: "tap" }
|
|
49
63
|
: {};
|
|
50
|
-
|
|
64
|
+
const indicatorNode = resolvedIndicator !== "none" && (jsx("div", { className: cn(theme.indicator, "pointer-events-none"), "aria-hidden": "true", children: resolvedIndicator === "radio" ? (jsx(Radio, { value: value, checked: isSelected, onChange: () => { }, state: isDisabled ? "disabled" : "default", size: indicatorSize })) : (jsx(Checkbox, { value: value, checked: isSelected, onChange: () => { }, state: isDisabled ? "disabled" : "default", size: indicatorSize })) }));
|
|
65
|
+
return (jsxs(motion.div, { ref: ref, role: role, "aria-checked": isSelected, "aria-disabled": isDisabled || undefined, tabIndex: isDisabled ? -1 : 0, "data-selected": isSelected, "data-disabled": isDisabled || undefined, className: cn(theme.card, (_a = theme.cardSizes) === null || _a === void 0 ? void 0 : _a[resolvedSize], isSelected && theme.selectedCard, isDisabled && theme.disabledCard, className), onClick: handleClick, onKeyDown: handleKeyDown, ...motionProps, ...props, children: [jsx("input", { type: inputType, id: inputId, name: isStandalone ? undefined : ctx === null || ctx === void 0 ? void 0 : ctx.name, value: value, checked: isSelected, disabled: isDisabled, onChange: () => { }, className: "sr-only", tabIndex: -1, "aria-hidden": true }), resolvedIndicatorPosition === "start" && indicatorNode, jsx("div", { className: theme.contentWrapper, children: children }), resolvedIndicatorPosition === "end" && indicatorNode] }));
|
|
51
66
|
});
|
|
52
67
|
SelectableCardRoot.displayName = "SelectableCard";
|
|
53
68
|
// ─── Compound Export ─────────────────────────────────────────────────────────
|
|
@@ -1,38 +1,28 @@
|
|
|
1
1
|
const selectableCardTheme = {
|
|
2
2
|
group: "flex flex-col gap-3",
|
|
3
3
|
card:
|
|
4
|
-
// Base layout
|
|
5
|
-
"relative flex items-
|
|
6
|
-
// Default state
|
|
4
|
+
// Base layout — no justify-between; indicator position handled by render order
|
|
5
|
+
"relative flex items-start gap-3 rounded-[var(--radius-base)] cursor-pointer transition-[border-color,background-color,box-shadow,outline] duration-200 " +
|
|
6
|
+
// Default state
|
|
7
7
|
"border border-[var(--color-border)] bg-[var(--color-surface)] " +
|
|
8
|
-
// Default state - dark
|
|
9
8
|
"dark:bg-[var(--color-background)] " +
|
|
10
|
-
// Hover
|
|
9
|
+
// Hover
|
|
11
10
|
"hover:border-[var(--color-border-secondary)] " +
|
|
12
|
-
//
|
|
13
|
-
" " +
|
|
14
|
-
// Focus visible - light
|
|
11
|
+
// Focus visible
|
|
15
12
|
"focus-visible:outline focus-visible:outline-offset-1 focus-visible:outline-[var(--color-primary)] " +
|
|
16
|
-
// Focus visible - dark
|
|
17
13
|
"dark:focus-visible:outline-[var(--color-primary)]/50",
|
|
18
|
-
selectedCard:
|
|
19
|
-
|
|
20
|
-
"border-[var(--color-primary)] ring-2 ring-[var(--color-primary)]/10 " +
|
|
21
|
-
// Selected border & ring - dark
|
|
22
|
-
"dark:border-[var(--color-primary)] dark:ring-[var(--color-primary)]/20 " +
|
|
23
|
-
// Selected background gradient - light
|
|
24
|
-
"bg-[var(--color-primary-50)] " +
|
|
25
|
-
// Selected background gradient - dark
|
|
26
|
-
"dark:bg-[var(--color-background-secondary)] " +
|
|
27
|
-
// Selected hover - light
|
|
14
|
+
selectedCard: "border-[var(--color-primary)] ring-2 ring-[var(--color-primary)]/10 " +
|
|
15
|
+
"dark:border-[var(--color-primary)] dark:ring-[var(--color-primary)]/20 " +
|
|
28
16
|
"hover:border-[var(--color-primary)] " +
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
disabledCard:
|
|
32
|
-
// Disabled state
|
|
33
|
-
"opacity-50 cursor-not-allowed pointer-events-none",
|
|
17
|
+
"dark:hover:border-[var(--color-primary)]",
|
|
18
|
+
disabledCard: "opacity-50 cursor-not-allowed pointer-events-none",
|
|
34
19
|
contentWrapper: "flex-1 min-w-0",
|
|
35
|
-
indicator: "flex-shrink-0",
|
|
20
|
+
indicator: "flex-shrink-0 -mt-0.5",
|
|
21
|
+
cardSizes: {
|
|
22
|
+
sm: "p-3",
|
|
23
|
+
md: "p-4",
|
|
24
|
+
lg: "p-5",
|
|
25
|
+
},
|
|
36
26
|
};
|
|
37
27
|
|
|
38
28
|
export { selectableCardTheme };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
export type SelectableCardType = "single" | "multiple";
|
|
3
3
|
export type SelectableCardIndicator = "radio" | "checkbox" | "none";
|
|
4
|
+
export type SelectableCardIndicatorPosition = "start" | "end";
|
|
5
|
+
export type SelectableCardSize = "sm" | "md" | "lg";
|
|
4
6
|
export interface SelectableCardTheme {
|
|
5
7
|
group?: string;
|
|
6
8
|
card?: string;
|
|
@@ -8,10 +10,13 @@ export interface SelectableCardTheme {
|
|
|
8
10
|
disabledCard?: string;
|
|
9
11
|
contentWrapper?: string;
|
|
10
12
|
indicator?: string;
|
|
13
|
+
cardSizes?: Record<SelectableCardSize, string>;
|
|
11
14
|
}
|
|
12
15
|
export interface SelectableCardContextValue {
|
|
13
16
|
type: SelectableCardType;
|
|
14
17
|
indicator: SelectableCardIndicator;
|
|
18
|
+
indicatorPosition: SelectableCardIndicatorPosition;
|
|
19
|
+
size: SelectableCardSize;
|
|
15
20
|
value: string | string[];
|
|
16
21
|
onChange: (cardValue: string) => void;
|
|
17
22
|
disabled: boolean;
|
|
@@ -20,14 +25,22 @@ export interface SelectableCardContextValue {
|
|
|
20
25
|
}
|
|
21
26
|
export interface SelectableCardGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
22
27
|
type?: SelectableCardType;
|
|
23
|
-
value
|
|
24
|
-
|
|
28
|
+
value?: string | string[];
|
|
29
|
+
defaultValue?: string | string[];
|
|
30
|
+
onChange?: (value: string | string[]) => void;
|
|
25
31
|
indicator?: SelectableCardIndicator;
|
|
32
|
+
indicatorPosition?: SelectableCardIndicatorPosition;
|
|
33
|
+
size?: SelectableCardSize;
|
|
26
34
|
disabled?: boolean;
|
|
27
35
|
name?: string;
|
|
28
36
|
theme?: Partial<SelectableCardTheme>;
|
|
29
37
|
}
|
|
30
|
-
export interface SelectableCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "value"> {
|
|
38
|
+
export interface SelectableCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "value" | "onChange"> {
|
|
31
39
|
value: string;
|
|
32
40
|
disabled?: boolean;
|
|
41
|
+
checked?: boolean;
|
|
42
|
+
onChange?: (checked: boolean, value: string) => void;
|
|
43
|
+
indicator?: SelectableCardIndicator;
|
|
44
|
+
indicatorPosition?: SelectableCardIndicatorPosition;
|
|
45
|
+
size?: SelectableCardSize;
|
|
33
46
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { SelectableCardContextValue } from "./SelectableCard.types";
|
|
2
2
|
export declare const SelectableCardContext: import("react").Context<SelectableCardContextValue | undefined>;
|
|
3
3
|
export declare function useSelectableCardContext(): SelectableCardContextValue;
|
|
4
|
+
export declare function useOptionalSelectableCardContext(): SelectableCardContextValue | undefined;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { createContext, useContext } from 'react';
|
|
2
2
|
|
|
3
3
|
const SelectableCardContext = createContext(undefined);
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
throw new Error("SelectableCard must be used within a SelectableCard.Group");
|
|
8
|
-
}
|
|
9
|
-
return context;
|
|
4
|
+
// Used by SelectableCard itself — returns undefined when used standalone
|
|
5
|
+
function useOptionalSelectableCardContext() {
|
|
6
|
+
return useContext(SelectableCardContext);
|
|
10
7
|
}
|
|
11
8
|
|
|
12
|
-
export { SelectableCardContext,
|
|
9
|
+
export { SelectableCardContext, useOptionalSelectableCardContext };
|
|
@@ -1,35 +1,56 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import React__default, { useId, useMemo } from 'react';
|
|
2
|
+
import React__default, { useId, useState, useMemo, useCallback } from 'react';
|
|
3
3
|
import { cn } from '../../../utils/cn.js';
|
|
4
4
|
import { selectableCardTheme } from './SelectableCard.theme.js';
|
|
5
5
|
import { SelectableCardContext } from './SelectableCardContext.js';
|
|
6
6
|
|
|
7
|
-
const SelectableCardGroup = React__default.forwardRef(({ type = "single", value, onChange, indicator, disabled = false, name, className, theme: customTheme, children, ...props }, ref) => {
|
|
7
|
+
const SelectableCardGroup = React__default.forwardRef(({ type = "single", value, defaultValue, onChange, indicator, indicatorPosition = "end", size = "md", disabled = false, name, className, theme: customTheme, children, ...props }, ref) => {
|
|
8
8
|
const autoId = useId();
|
|
9
9
|
const groupName = name !== null && name !== void 0 ? name : `selectable-card-${autoId}`;
|
|
10
|
+
const isControlled = value !== undefined;
|
|
11
|
+
const [internalValue, setInternalValue] = useState(() => {
|
|
12
|
+
if (defaultValue !== undefined) {
|
|
13
|
+
if (process.env.NODE_ENV !== "production") {
|
|
14
|
+
if (type === "single" && Array.isArray(defaultValue)) {
|
|
15
|
+
console.warn("[SelectableCard.Group]: defaultValue is an array but type is 'single'. Use a string.");
|
|
16
|
+
}
|
|
17
|
+
if (type === "multiple" && typeof defaultValue === "string") {
|
|
18
|
+
console.warn("[SelectableCard.Group]: defaultValue is a string but type is 'multiple'. Use an array.");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return defaultValue;
|
|
22
|
+
}
|
|
23
|
+
return type === "single" ? "" : [];
|
|
24
|
+
});
|
|
25
|
+
const resolvedValue = value !== undefined ? value : internalValue;
|
|
10
26
|
const resolvedIndicator = indicator !== null && indicator !== void 0 ? indicator : (type === "single" ? "radio" : "checkbox");
|
|
11
27
|
const theme = useMemo(() => ({ ...selectableCardTheme, ...customTheme }), [customTheme]);
|
|
12
|
-
const handleChange = (cardValue) => {
|
|
28
|
+
const handleChange = useCallback((cardValue) => {
|
|
29
|
+
let next;
|
|
13
30
|
if (type === "single") {
|
|
14
|
-
|
|
31
|
+
next = cardValue;
|
|
15
32
|
}
|
|
16
33
|
else {
|
|
17
|
-
const current = Array.isArray(
|
|
18
|
-
|
|
34
|
+
const current = Array.isArray(resolvedValue) ? resolvedValue : [];
|
|
35
|
+
next = current.includes(cardValue)
|
|
19
36
|
? current.filter((v) => v !== cardValue)
|
|
20
37
|
: [...current, cardValue];
|
|
21
|
-
onChange(next);
|
|
22
38
|
}
|
|
23
|
-
|
|
39
|
+
if (!isControlled)
|
|
40
|
+
setInternalValue(next);
|
|
41
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(next);
|
|
42
|
+
}, [type, resolvedValue, isControlled, onChange]);
|
|
24
43
|
const contextValue = useMemo(() => ({
|
|
25
44
|
type,
|
|
26
45
|
indicator: resolvedIndicator,
|
|
27
|
-
|
|
46
|
+
indicatorPosition,
|
|
47
|
+
size,
|
|
48
|
+
value: resolvedValue,
|
|
28
49
|
onChange: handleChange,
|
|
29
50
|
disabled,
|
|
30
51
|
name: groupName,
|
|
31
52
|
theme,
|
|
32
|
-
}), [type, resolvedIndicator,
|
|
53
|
+
}), [type, resolvedIndicator, indicatorPosition, size, resolvedValue, handleChange, disabled, groupName, theme]);
|
|
33
54
|
return (jsx(SelectableCardContext.Provider, { value: contextValue, children: jsx("div", { ref: ref, role: type === "single" ? "radiogroup" : "group", className: cn(theme.group, className), ...props, children: children }) }));
|
|
34
55
|
});
|
|
35
56
|
SelectableCardGroup.displayName = "SelectableCard.Group";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { SelectableCard } from "./SelectableCard";
|
|
2
|
-
export type { SelectableCardProps, SelectableCardGroupProps, SelectableCardType, SelectableCardIndicator, SelectableCardTheme, } from "./SelectableCard.types";
|
|
2
|
+
export type { SelectableCardProps, SelectableCardGroupProps, SelectableCardType, SelectableCardIndicator, SelectableCardIndicatorPosition, SelectableCardSize, SelectableCardTheme, } from "./SelectableCard.types";
|
|
3
3
|
export { selectableCardTheme } from "./SelectableCard.theme";
|
|
@@ -14,7 +14,7 @@ const signatureTheme = {
|
|
|
14
14
|
// Canvas element style
|
|
15
15
|
canvasStyle: "block w-full h-full cursor-crosshair touch-none focus:outline-none",
|
|
16
16
|
// Placeholder text style
|
|
17
|
-
placeholderStyle: "absolute inset-0 flex items-center justify-center pointer-events-none text-[var(--color-text-placeholder)] text-
|
|
17
|
+
placeholderStyle: "absolute inset-0 flex items-center justify-center pointer-events-none text-[var(--color-text-placeholder)] text-sm",
|
|
18
18
|
// Control buttons container style
|
|
19
19
|
controlsStyle: "absolute bottom-2 right-2 flex gap-2 z-10",
|
|
20
20
|
// Size variants - use shared padding system
|
|
@@ -4,7 +4,7 @@ const sliderTheme = {
|
|
|
4
4
|
// Wrapper styles
|
|
5
5
|
wrapperStyle: formsBaseTheme.wrapperStyle,
|
|
6
6
|
// Label styles
|
|
7
|
-
labelStyle: "block text-
|
|
7
|
+
labelStyle: "block text-sm font-medium text-[var(--color-text-primary)] mb-2",
|
|
8
8
|
// Helper text styles
|
|
9
9
|
helperTextStyle: formsBaseTheme.helperText,
|
|
10
10
|
// Root container with layout
|
|
@@ -16,9 +16,9 @@ const sliderTheme = {
|
|
|
16
16
|
// Thumb (draggable handle)
|
|
17
17
|
thumbStyle: "block h-5 w-7 rounded-full bg-transparent overflow-hidden cursor-grab active:cursor-grabbing active:scale-x-110 active:scale-y-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border)] focus-visible:ring-offset-2 transition-all hover:scale-110 data-[disabled]:cursor-not-allowed data-[disabled]:hover:scale-100 data-[invalid]:focus-visible:ring-[var(--color-danger)]",
|
|
18
18
|
// Value display
|
|
19
|
-
valueDisplayStyle: "text-
|
|
19
|
+
valueDisplayStyle: "text-sm font-medium text-[var(--color-text-secondary)] w-fit min-w-12",
|
|
20
20
|
// Min/max labels
|
|
21
|
-
minMaxLabelStyle: "text-
|
|
21
|
+
minMaxLabelStyle: "text-sm font-medium text-[var(--color-text-muted)]",
|
|
22
22
|
// Tick marks
|
|
23
23
|
tickStyle: "absolute w-0.5 h-2 bg-[var(--color-border)] -translate-x-0.5 pointer-events-none",
|
|
24
24
|
};
|
|
@@ -5,7 +5,7 @@ const switchTheme = {
|
|
|
5
5
|
container: "flex w-full justify-between items-center gap-4",
|
|
6
6
|
track: "w-12 h-6 rounded-full cursor-pointer shadow-inner bg-[var(--color-background-tertiary)] data-[state=checked]:bg-[var(--color-primary)] data-[state=disabled]:bg-[var(--color-background-disabled)] data-[state=disabled]:cursor-not-allowed data-[state=invalid]:border-2 data-[state=invalid]:border-[var(--color-danger)] outline outline-[var(--color-border)] transition-colors duration-300",
|
|
7
7
|
thumb: "w-7 h-5 rounded-full bg-transparent overflow-hidden border border-[var(--color-border)]/40 shadow-lg",
|
|
8
|
-
description: "text-
|
|
8
|
+
description: "text-sm text-[var(--color-text-muted)] -mt-1.5",
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* Thumb position values for animation
|
|
@@ -62,7 +62,7 @@ const timePickerTheme = {
|
|
|
62
62
|
// Individual wheel column - relative positioning for highlight overlay
|
|
63
63
|
wheelColumnStyle: "flex-1 flex flex-col relative",
|
|
64
64
|
// Wheel column header label
|
|
65
|
-
wheelHeaderStyle: "text-center py-2 text-
|
|
65
|
+
wheelHeaderStyle: "text-center py-2 text-xs font-semibold text-[var(--color-text-muted)] uppercase",
|
|
66
66
|
// Center highlight row - positioned behind selected item
|
|
67
67
|
wheelHighlightStyle: "absolute -mt-4 inset-x-0 bg-[var(--color-border)] pointer-events-none z-0",
|
|
68
68
|
// Wheel item - centered with transition for smooth opacity/color changes
|
|
@@ -77,7 +77,7 @@ const timePickerTheme = {
|
|
|
77
77
|
"text-[var(--color-text-primary)] placeholder:text-[var(--color-text-placeholder)] " +
|
|
78
78
|
"dark:text-[var(--color-neutral-200)] dark:placeholder:text-[var(--color-neutral-500)]",
|
|
79
79
|
// AM/PM period toggle button
|
|
80
|
-
periodToggleStyle: "px-1.5 py-0.5 text-
|
|
80
|
+
periodToggleStyle: "px-1.5 py-0.5 text-xs font-semibold rounded " +
|
|
81
81
|
"bg-[var(--color-background-tertiary)] text-[var(--color-text-primary)] " +
|
|
82
82
|
"hover:bg-[var(--color-background-quaternary)] transition-colors cursor-pointer select-none " +
|
|
83
83
|
"dark:bg-[var(--color-neutral-700)] dark:text-[var(--color-neutral-200)] " +
|
|
@@ -15,7 +15,7 @@ const formsBaseTheme = {
|
|
|
15
15
|
"dark:bg-[var(--color-neutral-900)] dark:outline-[var(--color-neutral-700)] " +
|
|
16
16
|
"dark:focus-within:outline-[var(--color-primary-500)] dark:focus-within:ring-[var(--color-primary-500)]/20",
|
|
17
17
|
// Common base input/control style
|
|
18
|
-
controlBaseStyle: "w-full bg-transparent text-
|
|
18
|
+
controlBaseStyle: "w-full bg-transparent text-sm text-[var(--color-text-primary)] " +
|
|
19
19
|
"placeholder:text-[var(--color-text-placeholder)] focus:outline-none " +
|
|
20
20
|
// Dark mode
|
|
21
21
|
"dark:text-[var(--color-text-primary)] dark:placeholder:text-[var(--color-neutral-500)]",
|
|
@@ -23,19 +23,19 @@ const formsBaseTheme = {
|
|
|
23
23
|
// These tokens can be composed together or used individually for maximum flexibility
|
|
24
24
|
sizes: {
|
|
25
25
|
sm: {
|
|
26
|
-
text: "text-
|
|
26
|
+
text: "text-sm",
|
|
27
27
|
padding: "py-[var(--form-py-sm)] px-[var(--form-px-sm)]",
|
|
28
28
|
height: "h-[var(--form-min-h-sm)]",
|
|
29
29
|
textareaHeight: "min-h-[calc(var(--form-min-h-sm)*2)]",
|
|
30
30
|
},
|
|
31
31
|
md: {
|
|
32
|
-
text: "text-
|
|
32
|
+
text: "text-sm",
|
|
33
33
|
padding: "py-[var(--form-py-md)] px-[var(--form-px-md)]",
|
|
34
34
|
height: "h-[var(--form-min-h-md)]",
|
|
35
35
|
textareaHeight: "min-h-[calc(var(--form-min-h-md)*2)]",
|
|
36
36
|
},
|
|
37
37
|
lg: {
|
|
38
|
-
text: "text-
|
|
38
|
+
text: "text-base",
|
|
39
39
|
padding: "py-[var(--form-py-lg)] px-[var(--form-px-lg)]",
|
|
40
40
|
height: "h-[var(--form-min-h-lg)]",
|
|
41
41
|
textareaHeight: "min-h-[calc(var(--form-min-h-lg)*2)]",
|
|
@@ -72,7 +72,7 @@ const formsBaseTheme = {
|
|
|
72
72
|
invalid: "",
|
|
73
73
|
},
|
|
74
74
|
// Common helper text style with state variations
|
|
75
|
-
helperText: "text-
|
|
75
|
+
helperText: "text-xs text-[var(--color-text-muted)] mt-1.5 [.state-disabled_&]:text-[var(--color-text-disabled)] [.state-invalid_&]:text-[var(--color-danger-500)] " +
|
|
76
76
|
"dark:text-[var(--color-neutral-400)] dark:[.state-invalid_&]:text-[var(--color-danger-400)]",
|
|
77
77
|
// Common icon styles
|
|
78
78
|
iconStyles: {
|
|
@@ -89,7 +89,7 @@ const formsBaseTheme = {
|
|
|
89
89
|
dropdownStyles: {
|
|
90
90
|
// Container for dropdown panel
|
|
91
91
|
container: "fixed z-[1000] max-h-[var(--select-content-available-height,20rem)] overflow-auto overscroll-contain " +
|
|
92
|
-
"rounded-[var(--form-radius)] bg-white/90 backdrop-blur-md text-
|
|
92
|
+
"rounded-[var(--form-radius)] bg-white/90 backdrop-blur-md text-sm border border-[var(--color-border)] " +
|
|
93
93
|
"shadow-real-lg ring-1 ring-[var(--color-border)] focus:outline-none " +
|
|
94
94
|
"dark:bg-[var(--color-neutral-900)]/90 dark:ring-[var(--color-neutral-700)]",
|
|
95
95
|
// Base option style
|
|
@@ -52,7 +52,8 @@ export { InputTag } from './InputTag/InputTag.js';
|
|
|
52
52
|
export { inputTagTheme } from './InputTag/InputTag.theme.js';
|
|
53
53
|
export { Combobox } from './Combobox/Combobox.js';
|
|
54
54
|
export { comboboxTheme } from './Combobox/Combobox.theme.js';
|
|
55
|
-
export { ColorPicker
|
|
55
|
+
export { ColorPicker } from './ColorPicker/ColorPicker.js';
|
|
56
|
+
export { ColorPickerContext, useColorPicker } from './ColorPicker/ColorPickerContext.js';
|
|
56
57
|
export { ColorPickerTrigger } from './ColorPicker/ColorPickerTrigger.js';
|
|
57
58
|
export { ColorPickerBody } from './ColorPicker/ColorPickerBody.js';
|
|
58
59
|
export { ColorPicker2DCanvas } from './ColorPicker/ColorPicker2DCanvas.js';
|
|
@@ -62,6 +63,10 @@ export { ColorPickerInput } from './ColorPicker/ColorPickerInput.js';
|
|
|
62
63
|
export { ColorPickerFormatSelector } from './ColorPicker/ColorPickerFormatSelector.js';
|
|
63
64
|
export { ColorPickerEyeDropper } from './ColorPicker/ColorPickerEyeDropper.js';
|
|
64
65
|
export { ColorPickerPresets } from './ColorPicker/ColorPickerPresets.js';
|
|
66
|
+
export { ColorPickerSavedColors } from './ColorPicker/ColorPickerSavedColors.js';
|
|
67
|
+
export { ColorPickerHeader } from './ColorPicker/ColorPickerHeader.js';
|
|
68
|
+
export { ColorPickerGradient } from './ColorPicker/ColorPickerGradient.js';
|
|
69
|
+
export { ColorPickerImage } from './ColorPicker/ColorPickerImage.js';
|
|
65
70
|
export { formatHex, formatHsl, formatRgb, hexToRgb, hslToRgb, hsvToRgb, parseColor, rgbToHex, rgbToHsl, rgbToHsv, validateHex, validateRgb } from './ColorPicker/colorUtils.js';
|
|
66
71
|
export { SelectableCard } from './SelectableCard/SelectableCard.js';
|
|
67
72
|
export { selectableCardTheme } from './SelectableCard/SelectableCard.theme.js';
|
|
@@ -2,8 +2,8 @@ const formLayoutTheme = {
|
|
|
2
2
|
root: "flex flex-col gap-6",
|
|
3
3
|
section: "grid grid-cols-1 md:grid-cols-6 gap-6 md:gap-10",
|
|
4
4
|
sectionSidebar: "col-span-full md:col-span-2",
|
|
5
|
-
sectionTitle: "text-
|
|
6
|
-
sectionSubtitle: "text-
|
|
5
|
+
sectionTitle: "text-base font-semibold text-[var(--color-text-primary)]",
|
|
6
|
+
sectionSubtitle: "text-sm text-[var(--color-text-muted)] mt-1",
|
|
7
7
|
sectionAction: "mt-4",
|
|
8
8
|
sectionContent: "col-span-full md:col-span-4 grid grid-cols-1 sm:grid-cols-2 gap-4",
|
|
9
9
|
sectionContentFull: "col-span-full grid grid-cols-1 sm:grid-cols-2 gap-4",
|
package/dist/hooks/useOverlay.js
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
import { useCallback, useEffect } from 'react';
|
|
2
2
|
|
|
3
|
+
// ── Scroll-lock manager (ref-counted) ──────────────────────────────────
|
|
4
|
+
// Supports nested overlays: only the first lock measures the scrollbar
|
|
5
|
+
// and compensates; subsequent locks just bump the counter.
|
|
6
|
+
let lockCount = 0;
|
|
7
|
+
let savedOverflow = '';
|
|
8
|
+
let savedPaddingRight = '';
|
|
9
|
+
function lockScroll() {
|
|
10
|
+
lockCount++;
|
|
11
|
+
if (lockCount === 1) {
|
|
12
|
+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
13
|
+
// Save originals before mutating
|
|
14
|
+
savedOverflow = document.body.style.overflow;
|
|
15
|
+
savedPaddingRight = document.body.style.paddingRight;
|
|
16
|
+
// Expose width as CSS variable so fixed-position elements can compensate
|
|
17
|
+
// e.g. position: fixed; padding-right: var(--scrollbar-width, 0px);
|
|
18
|
+
document.documentElement.style.setProperty('--scrollbar-width', `${scrollbarWidth}px`);
|
|
19
|
+
if (scrollbarWidth > 0) {
|
|
20
|
+
document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
21
|
+
}
|
|
22
|
+
document.body.style.overflow = 'hidden';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function unlockScroll() {
|
|
26
|
+
lockCount = Math.max(0, lockCount - 1);
|
|
27
|
+
if (lockCount === 0) {
|
|
28
|
+
document.body.style.overflow = savedOverflow;
|
|
29
|
+
document.body.style.paddingRight = savedPaddingRight;
|
|
30
|
+
document.documentElement.style.removeProperty('--scrollbar-width');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
3
33
|
/**
|
|
4
34
|
* Shared hook for overlay behavior (escape key, scroll lock, click handling)
|
|
5
35
|
*
|
|
@@ -49,15 +79,15 @@ const useOverlay = ({ isOpen, onClose, closeOnEsc = true, closeOnOverlayClick =
|
|
|
49
79
|
if (isOpen) {
|
|
50
80
|
// Add Escape key listener
|
|
51
81
|
document.addEventListener('keydown', handleEscKey);
|
|
52
|
-
// Lock body scroll
|
|
82
|
+
// Lock body scroll (ref-counted so nested overlays work)
|
|
53
83
|
if (enableScrollLock) {
|
|
54
|
-
|
|
84
|
+
lockScroll();
|
|
55
85
|
}
|
|
56
86
|
// Cleanup on unmount or when overlay closes
|
|
57
87
|
return () => {
|
|
58
88
|
document.removeEventListener('keydown', handleEscKey);
|
|
59
89
|
if (enableScrollLock) {
|
|
60
|
-
|
|
90
|
+
unlockScroll();
|
|
61
91
|
}
|
|
62
92
|
};
|
|
63
93
|
}
|
|
@@ -68,4 +98,4 @@ const useOverlay = ({ isOpen, onClose, closeOnEsc = true, closeOnOverlayClick =
|
|
|
68
98
|
};
|
|
69
99
|
};
|
|
70
100
|
|
|
71
|
-
export { useOverlay };
|
|
101
|
+
export { lockScroll, unlockScroll, useOverlay };
|