@particle-network/ui-react 0.5.1-beta.1 → 0.5.1-beta.10
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/ProgressWrapper/index.d.ts +2 -2
- package/dist/components/ProgressWrapper/index.js +1 -1
- package/dist/components/UXAutocomplete/index.js +1 -2
- package/dist/components/UXButton/button-theme.js +38 -2
- package/dist/components/UXButton/button.js +1 -1
- package/dist/components/UXCheckbox/checkbox.extend.js +16 -13
- package/dist/components/UXChip/chip.extend.d.ts +2 -1
- package/dist/components/UXChip/index.d.ts +1 -1
- package/dist/components/UXColorPicker/color-fields.d.ts +3 -0
- package/dist/components/UXColorPicker/color-fields.js +142 -0
- package/dist/components/UXColorPicker/color-input.d.ts +7 -0
- package/dist/components/UXColorPicker/color-input.js +12 -0
- package/dist/components/UXColorPicker/color-picker.d.ts +3 -0
- package/dist/components/UXColorPicker/color-picker.js +228 -0
- package/dist/components/UXColorPicker/index.d.ts +5 -0
- package/dist/components/UXColorPicker/index.js +3 -0
- package/dist/components/UXColorPicker/types.d.ts +51 -0
- package/dist/components/UXColorPicker/types.js +0 -0
- package/dist/components/UXColorPicker/utils.d.ts +7 -0
- package/dist/components/UXColorPicker/utils.js +6 -0
- package/dist/components/UXCopy/index.js +2 -2
- package/dist/components/UXEmpty/index.js +2 -2
- package/dist/components/UXHint/index.js +1 -1
- package/dist/components/UXInput/index.d.ts +6 -6
- package/dist/components/UXInput/input.extend.d.ts +6 -6
- package/dist/components/UXRadio/radio.extend.js +3 -3
- package/dist/components/UXSlider/use-slider.d.ts +1 -1
- package/dist/components/UXSlider/use-slider.js +1 -1
- package/dist/components/UXSpinner/spinner.d.ts +1 -5
- package/dist/components/UXSpinner/spinner.js +3 -4
- package/dist/components/UXSwitch/index.d.ts +2 -2
- package/dist/components/UXSwitch/switch.extend.d.ts +2 -2
- package/dist/components/UXSwitch/switch.extend.js +6 -6
- package/dist/components/UXTabs/tabs.classes.js +4 -4
- package/dist/components/UXThemeSwitch/constants.d.ts +9 -0
- package/dist/components/UXThemeSwitch/constants.js +3 -0
- package/dist/components/UXThemeSwitch/custom-theme-config.d.ts +2 -0
- package/dist/components/UXThemeSwitch/custom-theme-config.js +171 -0
- package/dist/components/UXThemeSwitch/theme-item.js +94 -15
- package/dist/components/UXThemeSwitch/theme-switch.js +26 -5
- package/dist/components/UXThemeSwitch/use-color-scheme.js +11 -8
- package/dist/components/UXThemeSwitch/use-theme-color.d.ts +1 -22
- package/dist/components/UXThemeSwitch/use-theme-color.js +3 -7
- package/dist/components/UXThemeSwitch/use-theme-store.d.ts +5 -0
- package/dist/components/UXThemeSwitch/use-theme-store.js +9 -3
- package/dist/components/UXThemeSwitch/use-theme.d.ts +2 -0
- package/dist/components/UXThemeSwitch/use-theme.js +10 -53
- package/dist/components/UXThemeSwitch/utils.d.ts +28 -0
- package/dist/components/UXThemeSwitch/utils.js +222 -0
- package/dist/components/UXToast/index.js +3 -3
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/layout/Box/box-theme.d.ts +2225 -0
- package/dist/components/layout/Box/box-theme.js +348 -0
- package/dist/components/layout/Box/box.d.ts +14 -0
- package/dist/components/layout/Box/box.js +99 -0
- package/dist/components/layout/Circle.js +2 -3
- package/dist/components/layout/Flex.d.ts +3 -27
- package/dist/components/layout/Flex.js +6 -19
- package/dist/components/layout/HStack.d.ts +1 -1
- package/dist/components/layout/Square.js +3 -3
- package/dist/components/layout/VStack.d.ts +1 -1
- package/dist/components/layout/VStack.js +2 -2
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/layout/index.js +1 -0
- package/dist/components/typography/Text.js +22 -7
- package/dist/components/typography/Text.type.d.ts +3 -26
- package/dist/components/typography/Text.type.js +0 -47
- package/dist/components/typography/text-theme.d.ts +178 -0
- package/dist/components/typography/text-theme.js +79 -0
- package/dist/heroui/constants.d.ts +18 -0
- package/dist/heroui/constants.js +98 -0
- package/dist/heroui/types.d.ts +91 -0
- package/dist/heroui/types.js +0 -0
- package/dist/heroui/utils/colors.d.ts +34 -0
- package/dist/heroui/utils/colors.js +121 -0
- package/dist/heroui/utils/object.d.ts +1 -0
- package/dist/heroui/utils/object.js +17 -0
- package/dist/hooks/useI18n.d.ts +133 -25
- package/dist/hooks/useI18n.js +84 -2
- package/dist/hooks/useLang.d.ts +5 -1
- package/dist/hooks/useLang.js +13 -1
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.js +258 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +2 -1
- package/dist/utils/input-classes.js +2 -2
- package/package.json +8 -5
- package/tailwind-preset.js +84 -160
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { type
|
|
2
|
+
import { type HexColor, type UXComponentColor, type UXRadius } from '@particle-network/ui-shared';
|
|
3
3
|
export interface ProgressWrapperProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
4
|
/**
|
|
5
5
|
* 进度 (%)
|
|
@@ -24,7 +24,7 @@ export interface ProgressWrapperProps extends React.HTMLAttributes<HTMLDivElemen
|
|
|
24
24
|
/**
|
|
25
25
|
* 进度条颜色
|
|
26
26
|
*/
|
|
27
|
-
color?:
|
|
27
|
+
color?: UXComponentColor | 'transparent' | HexColor;
|
|
28
28
|
/**
|
|
29
29
|
* 进度条 SVG 样式
|
|
30
30
|
*/
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useMemo, useRef } from "react";
|
|
4
|
-
import { cn } from "@heroui/theme";
|
|
5
4
|
import { radiusMap } from "@particle-network/ui-shared";
|
|
6
5
|
import { useSize } from "ahooks";
|
|
6
|
+
import { cn } from "../../utils/index.js";
|
|
7
7
|
import { Center } from "../layout/index.js";
|
|
8
8
|
import { useThemeColor } from "../UXThemeSwitch/use-theme-color.js";
|
|
9
9
|
const ProgressWrapper = ({ className, value = 0, width, height, radius = 'sm', strokeWidth = 1, color = 'primary', children, svgClassName, ...restProps })=>{
|
|
@@ -3,10 +3,9 @@ import "react";
|
|
|
3
3
|
import { Autocomplete, AutocompleteItem, AutocompleteSection } from "@heroui/autocomplete";
|
|
4
4
|
import ChevronDownIcon from "@particle-network/icons/web/ChevronDownIcon";
|
|
5
5
|
const UXAutocomplete = (props)=>{
|
|
6
|
-
const {
|
|
6
|
+
const { classNames = {}, radius = 'sm', labelPlacement = 'outside-top', ...restProps } = props;
|
|
7
7
|
const { base, popoverContent, selectorButton, endContentWrapper, clearButton, listboxWrapper } = classNames;
|
|
8
8
|
return /*#__PURE__*/ jsx(Autocomplete, {
|
|
9
|
-
fullWidth: fullWidth,
|
|
10
9
|
classNames: {
|
|
11
10
|
base: [
|
|
12
11
|
'ux-base',
|
|
@@ -381,13 +381,13 @@ const button_theme_button = tv({
|
|
|
381
381
|
isSelected: true,
|
|
382
382
|
color: 'default',
|
|
383
383
|
variant: 'solid',
|
|
384
|
-
class: 'bg-
|
|
384
|
+
class: 'bg-cursor text-cursor-foreground'
|
|
385
385
|
},
|
|
386
386
|
{
|
|
387
387
|
isSelected: true,
|
|
388
388
|
color: 'secondary',
|
|
389
389
|
variant: 'solid',
|
|
390
|
-
class: 'bg-
|
|
390
|
+
class: 'bg-cursor text-cursor-foreground'
|
|
391
391
|
},
|
|
392
392
|
{
|
|
393
393
|
isSelected: true,
|
|
@@ -618,31 +618,67 @@ const button_theme_button = tv({
|
|
|
618
618
|
},
|
|
619
619
|
{
|
|
620
620
|
isIconOnly: true,
|
|
621
|
+
variant: [
|
|
622
|
+
'solid',
|
|
623
|
+
'flat',
|
|
624
|
+
'light',
|
|
625
|
+
'bordered'
|
|
626
|
+
],
|
|
621
627
|
size: 'xs',
|
|
622
628
|
class: 'min-w-5 w-5 h-5'
|
|
623
629
|
},
|
|
624
630
|
{
|
|
625
631
|
isIconOnly: true,
|
|
632
|
+
variant: [
|
|
633
|
+
'solid',
|
|
634
|
+
'flat',
|
|
635
|
+
'light',
|
|
636
|
+
'bordered'
|
|
637
|
+
],
|
|
626
638
|
size: 'sm',
|
|
627
639
|
class: 'min-w-6 w-6 h-6'
|
|
628
640
|
},
|
|
629
641
|
{
|
|
630
642
|
isIconOnly: true,
|
|
643
|
+
variant: [
|
|
644
|
+
'solid',
|
|
645
|
+
'flat',
|
|
646
|
+
'light',
|
|
647
|
+
'bordered'
|
|
648
|
+
],
|
|
631
649
|
size: 'md',
|
|
632
650
|
class: 'min-w-[30px] w-[30px] h-[30px]'
|
|
633
651
|
},
|
|
634
652
|
{
|
|
635
653
|
isIconOnly: true,
|
|
654
|
+
variant: [
|
|
655
|
+
'solid',
|
|
656
|
+
'flat',
|
|
657
|
+
'light',
|
|
658
|
+
'bordered'
|
|
659
|
+
],
|
|
636
660
|
size: 'lg',
|
|
637
661
|
class: 'min-w-9 w-9 h-9'
|
|
638
662
|
},
|
|
639
663
|
{
|
|
640
664
|
isIconOnly: true,
|
|
665
|
+
variant: [
|
|
666
|
+
'solid',
|
|
667
|
+
'flat',
|
|
668
|
+
'light',
|
|
669
|
+
'bordered'
|
|
670
|
+
],
|
|
641
671
|
size: 'xl',
|
|
642
672
|
class: 'min-w-11 w-11 h-11'
|
|
643
673
|
},
|
|
644
674
|
{
|
|
645
675
|
isIconOnly: true,
|
|
676
|
+
variant: [
|
|
677
|
+
'solid',
|
|
678
|
+
'flat',
|
|
679
|
+
'light',
|
|
680
|
+
'bordered'
|
|
681
|
+
],
|
|
646
682
|
size: 'auto',
|
|
647
683
|
class: ''
|
|
648
684
|
},
|
|
@@ -5,7 +5,7 @@ import { UXSpinner } from "../UXSpinner/index.js";
|
|
|
5
5
|
import { useButton } from "./use-button.js";
|
|
6
6
|
const Button = forwardRef((props, ref)=>{
|
|
7
7
|
const { Component, domRef, children, spinnerSize, spinner = /*#__PURE__*/ jsx(UXSpinner, {
|
|
8
|
-
color: "
|
|
8
|
+
color: "current",
|
|
9
9
|
size: spinnerSize
|
|
10
10
|
}), spinnerPlacement, startContent, endContent, isLoading, disableRipple, getButtonProps, getRippleProps, isIconOnly } = useButton({
|
|
11
11
|
...props,
|
|
@@ -7,7 +7,7 @@ const ExtendedCheckbox = extendVariants(Checkbox, {
|
|
|
7
7
|
wrapper: 'after:bg-primary after:text-primary-foreground text-primary-foreground'
|
|
8
8
|
},
|
|
9
9
|
secondary: {
|
|
10
|
-
wrapper: 'after:bg-
|
|
10
|
+
wrapper: 'after:bg-cursor after:text-cursor-foreground text-cursor-foreground'
|
|
11
11
|
},
|
|
12
12
|
success: {
|
|
13
13
|
wrapper: 'after:bg-success after:text-success-foreground text-success-foreground'
|
|
@@ -27,34 +27,37 @@ const ExtendedCheckbox = extendVariants(Checkbox, {
|
|
|
27
27
|
},
|
|
28
28
|
size: {
|
|
29
29
|
sm: {
|
|
30
|
+
base: 'gap-1.5',
|
|
30
31
|
wrapper: [
|
|
31
32
|
'w-3.5 h-3.5 me-0',
|
|
32
33
|
'rounded-[calc(theme(borderRadius.medium)*0.2)]',
|
|
33
34
|
'before:rounded-[calc(theme(borderRadius.medium)*0.2)] before:border-secondary before:border-1',
|
|
34
35
|
'after:rounded-[calc(theme(borderRadius.medium)*0.2)]'
|
|
35
36
|
],
|
|
36
|
-
label: '!text-
|
|
37
|
-
icon: 'h-2
|
|
37
|
+
label: '!text-body2 font-medium',
|
|
38
|
+
icon: 'h-2'
|
|
38
39
|
},
|
|
39
40
|
md: {
|
|
41
|
+
base: 'gap-2',
|
|
40
42
|
wrapper: [
|
|
41
43
|
'w-4 h-4 me-0',
|
|
42
|
-
'rounded-[calc(theme(borderRadius.medium)*0.
|
|
43
|
-
'before:rounded-[calc(theme(borderRadius.medium)*0.
|
|
44
|
-
'after:rounded-[calc(theme(borderRadius.medium)*0.
|
|
44
|
+
'rounded-[calc(theme(borderRadius.medium)*0.3)]',
|
|
45
|
+
'before:rounded-[calc(theme(borderRadius.medium)*0.3)] before:border-secondary before:border-1.5',
|
|
46
|
+
'after:rounded-[calc(theme(borderRadius.medium)*0.3)]'
|
|
45
47
|
],
|
|
46
48
|
label: '!text-body2 font-medium',
|
|
47
|
-
icon: 'h-
|
|
49
|
+
icon: 'h-2.5'
|
|
48
50
|
},
|
|
49
51
|
lg: {
|
|
52
|
+
base: 'gap-2',
|
|
50
53
|
wrapper: [
|
|
51
54
|
'w-[18px] h-[18px] me-0',
|
|
52
|
-
'rounded-[calc(theme(borderRadius.medium)*0.
|
|
53
|
-
'before:rounded-[calc(theme(borderRadius.medium)*0.
|
|
54
|
-
'after:rounded-[calc(theme(borderRadius.medium)*0.
|
|
55
|
+
'rounded-[calc(theme(borderRadius.medium)*0.4)]',
|
|
56
|
+
'before:rounded-[calc(theme(borderRadius.medium)*0.4)] before:border-secondary before:border-1.5',
|
|
57
|
+
'after:rounded-[calc(theme(borderRadius.medium)*0.4)]'
|
|
55
58
|
],
|
|
56
59
|
label: '!text-body1 font-medium',
|
|
57
|
-
icon: 'h-3
|
|
60
|
+
icon: 'h-3'
|
|
58
61
|
}
|
|
59
62
|
},
|
|
60
63
|
radius: {
|
|
@@ -144,10 +147,10 @@ const ExtendedCheckbox = extendVariants(Checkbox, {
|
|
|
144
147
|
},
|
|
145
148
|
labelPlacement: {
|
|
146
149
|
left: {
|
|
147
|
-
base: 'flex-row-reverse
|
|
150
|
+
base: 'flex-row-reverse'
|
|
148
151
|
},
|
|
149
152
|
right: {
|
|
150
|
-
base: 'flex-row
|
|
153
|
+
base: 'flex-row'
|
|
151
154
|
}
|
|
152
155
|
}
|
|
153
156
|
},
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { type ChipProps } from '@heroui/chip';
|
|
3
|
+
import type { HexColor } from '@particle-network/ui-shared';
|
|
3
4
|
type ExtendedChipProps = Omit<ChipProps, 'color'> & {
|
|
4
|
-
color?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'alert' | 'danger' | 'bullish' | 'bearish' |
|
|
5
|
+
color?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'alert' | 'danger' | 'bullish' | 'bearish' | HexColor;
|
|
5
6
|
};
|
|
6
7
|
declare const ExtendedChip: React.ForwardRefExoticComponent<ExtendedChipProps>;
|
|
7
8
|
export default ExtendedChip;
|
|
@@ -2,5 +2,5 @@ import React from 'react';
|
|
|
2
2
|
import ExtendedChip from './chip.extend';
|
|
3
3
|
export type UXChipProps = React.ComponentPropsWithRef<typeof ExtendedChip>;
|
|
4
4
|
export declare const UXChip: import("@heroui/system-rsc").InternalForwardRefRenderFunction<"div", Omit<import("@heroui/chip").ChipProps, "color"> & {
|
|
5
|
-
color?: "default" | "primary" | "secondary" | "success" | "warning" | "alert" | "danger" | "bullish" | "bearish" |
|
|
5
|
+
color?: "default" | "primary" | "secondary" | "success" | "warning" | "alert" | "danger" | "bullish" | "bearish" | import("@particle-network/ui-shared").HexColor;
|
|
6
6
|
}, never>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { Switch3Icon } from "@particle-network/icons/web";
|
|
5
|
+
import { Flex, VStack } from "../layout/index.js";
|
|
6
|
+
import { Text } from "../typography/Text.js";
|
|
7
|
+
import { UXButton } from "../UXButton/index.js";
|
|
8
|
+
import { ColorInput } from "./color-input.js";
|
|
9
|
+
const ColorFields = ({ value, defaultValue, onChange })=>{
|
|
10
|
+
const [format, setFormat] = useState('hex');
|
|
11
|
+
const handleFormatToggle = useCallback(()=>{
|
|
12
|
+
const formats = [
|
|
13
|
+
'hex',
|
|
14
|
+
'rgb',
|
|
15
|
+
'hsl'
|
|
16
|
+
];
|
|
17
|
+
const currentIndex = formats.indexOf(format);
|
|
18
|
+
const nextIndex = (currentIndex + 1) % formats.length;
|
|
19
|
+
setFormat(formats[nextIndex]);
|
|
20
|
+
}, [
|
|
21
|
+
format
|
|
22
|
+
]);
|
|
23
|
+
return /*#__PURE__*/ jsxs(Flex, {
|
|
24
|
+
gap: "md",
|
|
25
|
+
children: [
|
|
26
|
+
'hex' === format && /*#__PURE__*/ jsxs(VStack, {
|
|
27
|
+
gap: 1,
|
|
28
|
+
className: "flex-1",
|
|
29
|
+
children: [
|
|
30
|
+
/*#__PURE__*/ jsx(ColorInput, {
|
|
31
|
+
className: "w-full",
|
|
32
|
+
defaultValue: defaultValue,
|
|
33
|
+
value: value,
|
|
34
|
+
onChange: onChange
|
|
35
|
+
}),
|
|
36
|
+
/*#__PURE__*/ jsx(Text, {
|
|
37
|
+
color: "secondary",
|
|
38
|
+
align: "center",
|
|
39
|
+
children: "HEX"
|
|
40
|
+
})
|
|
41
|
+
]
|
|
42
|
+
}),
|
|
43
|
+
'rgb' === format && /*#__PURE__*/ jsxs("div", {
|
|
44
|
+
className: "grid flex-1 grid-cols-3 gap-1",
|
|
45
|
+
children: [
|
|
46
|
+
/*#__PURE__*/ jsx(ColorInput, {
|
|
47
|
+
channel: "red",
|
|
48
|
+
className: "w-full",
|
|
49
|
+
colorSpace: "rgb",
|
|
50
|
+
defaultValue: defaultValue,
|
|
51
|
+
value: value,
|
|
52
|
+
onChange: onChange
|
|
53
|
+
}),
|
|
54
|
+
/*#__PURE__*/ jsx(ColorInput, {
|
|
55
|
+
channel: "green",
|
|
56
|
+
className: "w-full",
|
|
57
|
+
colorSpace: "rgb",
|
|
58
|
+
defaultValue: defaultValue,
|
|
59
|
+
value: value,
|
|
60
|
+
onChange: onChange
|
|
61
|
+
}),
|
|
62
|
+
/*#__PURE__*/ jsx(ColorInput, {
|
|
63
|
+
channel: "blue",
|
|
64
|
+
className: "w-full",
|
|
65
|
+
colorSpace: "rgb",
|
|
66
|
+
defaultValue: defaultValue,
|
|
67
|
+
value: value,
|
|
68
|
+
onChange: onChange
|
|
69
|
+
}),
|
|
70
|
+
/*#__PURE__*/ jsx(Text, {
|
|
71
|
+
color: "secondary",
|
|
72
|
+
align: "center",
|
|
73
|
+
children: "R"
|
|
74
|
+
}),
|
|
75
|
+
/*#__PURE__*/ jsx(Text, {
|
|
76
|
+
color: "secondary",
|
|
77
|
+
align: "center",
|
|
78
|
+
children: "G"
|
|
79
|
+
}),
|
|
80
|
+
/*#__PURE__*/ jsx(Text, {
|
|
81
|
+
color: "secondary",
|
|
82
|
+
align: "center",
|
|
83
|
+
children: "B"
|
|
84
|
+
})
|
|
85
|
+
]
|
|
86
|
+
}),
|
|
87
|
+
'hsl' === format && /*#__PURE__*/ jsxs("div", {
|
|
88
|
+
className: "grid flex-1 grid-cols-3 gap-1",
|
|
89
|
+
children: [
|
|
90
|
+
/*#__PURE__*/ jsx(ColorInput, {
|
|
91
|
+
channel: "hue",
|
|
92
|
+
className: "w-full",
|
|
93
|
+
colorSpace: "hsl",
|
|
94
|
+
defaultValue: defaultValue,
|
|
95
|
+
value: value,
|
|
96
|
+
onChange: onChange
|
|
97
|
+
}),
|
|
98
|
+
/*#__PURE__*/ jsx(ColorInput, {
|
|
99
|
+
channel: "saturation",
|
|
100
|
+
className: "w-full",
|
|
101
|
+
colorSpace: "hsl",
|
|
102
|
+
defaultValue: defaultValue,
|
|
103
|
+
value: value,
|
|
104
|
+
onChange: onChange
|
|
105
|
+
}),
|
|
106
|
+
/*#__PURE__*/ jsx(ColorInput, {
|
|
107
|
+
channel: "lightness",
|
|
108
|
+
className: "w-full",
|
|
109
|
+
colorSpace: "hsl",
|
|
110
|
+
defaultValue: defaultValue,
|
|
111
|
+
value: value,
|
|
112
|
+
onChange: onChange
|
|
113
|
+
}),
|
|
114
|
+
/*#__PURE__*/ jsx(Text, {
|
|
115
|
+
color: "secondary",
|
|
116
|
+
align: "center",
|
|
117
|
+
children: "H"
|
|
118
|
+
}),
|
|
119
|
+
/*#__PURE__*/ jsx(Text, {
|
|
120
|
+
color: "secondary",
|
|
121
|
+
align: "center",
|
|
122
|
+
children: "S"
|
|
123
|
+
}),
|
|
124
|
+
/*#__PURE__*/ jsx(Text, {
|
|
125
|
+
color: "secondary",
|
|
126
|
+
align: "center",
|
|
127
|
+
children: "L"
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
}),
|
|
131
|
+
/*#__PURE__*/ jsx(UXButton, {
|
|
132
|
+
isIconOnly: true,
|
|
133
|
+
className: "shrink-0",
|
|
134
|
+
variant: "light",
|
|
135
|
+
onPress: handleFormatToggle,
|
|
136
|
+
children: /*#__PURE__*/ jsx(Switch3Icon, {})
|
|
137
|
+
})
|
|
138
|
+
]
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
ColorFields.displayName = 'ColorInputFields';
|
|
142
|
+
export { ColorFields };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import { ColorField, Input } from "react-aria-components";
|
|
4
|
+
import { cn } from "../../utils/index.js";
|
|
5
|
+
const inputClassName = 'w-full h-[30px] rounded-small border-none bg-background-200 px-2.5 text-tiny text-foreground focus:outline-none focus:ring-1 focus:ring-foreground text-center';
|
|
6
|
+
const ColorInput = (props)=>/*#__PURE__*/ jsx(ColorField, {
|
|
7
|
+
...props,
|
|
8
|
+
children: /*#__PURE__*/ jsx(Input, {
|
|
9
|
+
className: cn(inputClassName, props.inputClassName)
|
|
10
|
+
})
|
|
11
|
+
});
|
|
12
|
+
export { ColorInput };
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { ColorArea, ColorPicker, ColorSlider, ColorSwatch, ColorThumb, SliderTrack, parseColor } from "react-aria-components";
|
|
5
|
+
import ColorPickerIcon from "@particle-network/icons/web/ColorPickerIcon";
|
|
6
|
+
import RefreshCcwIcon from "@particle-network/icons/web/RefreshCcwIcon";
|
|
7
|
+
import { cn } from "../../utils/index.js";
|
|
8
|
+
import { HStack } from "../layout/index.js";
|
|
9
|
+
import { UXButton } from "../UXButton/index.js";
|
|
10
|
+
import { UXPopover, UXPopoverContent, UXPopoverTrigger } from "../UXPopover/index.js";
|
|
11
|
+
import { useThemeColor } from "../UXThemeSwitch/index.js";
|
|
12
|
+
import { ColorFields } from "./color-fields.js";
|
|
13
|
+
import { ColorInput } from "./color-input.js";
|
|
14
|
+
import { normalizeColor } from "./utils.js";
|
|
15
|
+
const UXColorPicker = ({ className, isDisabled, placement = 'bottom-start', value, defaultValue, onChange, onChangeEnd, onValueChange, onValueChangeEnd, isChanged, onReset })=>{
|
|
16
|
+
const colors = useThemeColor();
|
|
17
|
+
const isControlled = void 0 !== value;
|
|
18
|
+
const [pickerKey, setPickerKey] = useState(0);
|
|
19
|
+
const [isInputFocused, setIsInputFocused] = useState(false);
|
|
20
|
+
const getInitialColor = ()=>{
|
|
21
|
+
if (isControlled && value) return normalizeColor(value);
|
|
22
|
+
if (defaultValue) return normalizeColor(defaultValue);
|
|
23
|
+
return parseColor('#000000');
|
|
24
|
+
};
|
|
25
|
+
const initialColorRef = useRef(getInitialColor());
|
|
26
|
+
const [internalColor, setInternalColor] = useState(()=>{
|
|
27
|
+
if (isControlled) {
|
|
28
|
+
if (value) return normalizeColor(value);
|
|
29
|
+
}
|
|
30
|
+
if (defaultValue) return normalizeColor(defaultValue);
|
|
31
|
+
return parseColor('#000000');
|
|
32
|
+
});
|
|
33
|
+
const currentColor = useMemo(()=>{
|
|
34
|
+
if (isControlled && value) return normalizeColor(value);
|
|
35
|
+
return internalColor;
|
|
36
|
+
}, [
|
|
37
|
+
value,
|
|
38
|
+
internalColor,
|
|
39
|
+
isControlled
|
|
40
|
+
]);
|
|
41
|
+
useEffect(()=>{
|
|
42
|
+
const initialColor = getInitialColor();
|
|
43
|
+
initialColorRef.current = initialColor;
|
|
44
|
+
}, []);
|
|
45
|
+
useEffect(()=>{
|
|
46
|
+
if (!isControlled && defaultValue) {
|
|
47
|
+
const newColor = normalizeColor(defaultValue);
|
|
48
|
+
setInternalColor(newColor);
|
|
49
|
+
}
|
|
50
|
+
}, [
|
|
51
|
+
defaultValue,
|
|
52
|
+
isControlled
|
|
53
|
+
]);
|
|
54
|
+
useEffect(()=>{
|
|
55
|
+
if (isControlled && value) {
|
|
56
|
+
const newColor = normalizeColor(value);
|
|
57
|
+
setInternalColor(newColor);
|
|
58
|
+
}
|
|
59
|
+
}, [
|
|
60
|
+
value,
|
|
61
|
+
isControlled
|
|
62
|
+
]);
|
|
63
|
+
const handleChange = useCallback((color)=>{
|
|
64
|
+
if (color) {
|
|
65
|
+
setInternalColor(color);
|
|
66
|
+
onChange?.(color);
|
|
67
|
+
onValueChange?.(color.toString('hex'));
|
|
68
|
+
}
|
|
69
|
+
}, [
|
|
70
|
+
onChange,
|
|
71
|
+
onValueChange,
|
|
72
|
+
isControlled
|
|
73
|
+
]);
|
|
74
|
+
const handleEyedropper = useCallback(()=>{
|
|
75
|
+
if ('EyeDropper' in window) {
|
|
76
|
+
const eyeDropper = new window.EyeDropper();
|
|
77
|
+
eyeDropper.open().then((result)=>{
|
|
78
|
+
try {
|
|
79
|
+
const newColor = parseColor(result.sRGBHex);
|
|
80
|
+
if (newColor) handleChange(newColor);
|
|
81
|
+
} catch {}
|
|
82
|
+
}).catch(()=>{});
|
|
83
|
+
} else console.warn('EyeDropper API is not supported in this browser');
|
|
84
|
+
}, [
|
|
85
|
+
handleChange
|
|
86
|
+
]);
|
|
87
|
+
const handleChangeEnd = useCallback((color)=>{
|
|
88
|
+
if (color) {
|
|
89
|
+
onChangeEnd?.(color);
|
|
90
|
+
onValueChangeEnd?.(color.toString('hex'));
|
|
91
|
+
}
|
|
92
|
+
}, [
|
|
93
|
+
onChangeEnd,
|
|
94
|
+
onValueChangeEnd
|
|
95
|
+
]);
|
|
96
|
+
const hasChanged = useMemo(()=>{
|
|
97
|
+
if (void 0 !== isChanged) return isChanged;
|
|
98
|
+
const initialHex = initialColorRef.current.toString('hex');
|
|
99
|
+
const currentHex = currentColor.toString('hex');
|
|
100
|
+
return initialHex !== currentHex;
|
|
101
|
+
}, [
|
|
102
|
+
currentColor,
|
|
103
|
+
isChanged
|
|
104
|
+
]);
|
|
105
|
+
const handleReset = ()=>{
|
|
106
|
+
if (onReset) return void onReset();
|
|
107
|
+
const resetColor = initialColorRef.current;
|
|
108
|
+
if (!isControlled) {
|
|
109
|
+
setInternalColor(resetColor);
|
|
110
|
+
setPickerKey((prev)=>prev + 1);
|
|
111
|
+
}
|
|
112
|
+
onChange?.(resetColor);
|
|
113
|
+
onValueChange?.(resetColor.toString('hex'));
|
|
114
|
+
onChangeEnd?.(resetColor);
|
|
115
|
+
onValueChangeEnd?.(resetColor.toString('hex'));
|
|
116
|
+
};
|
|
117
|
+
const handleColorFieldsChange = useCallback((color)=>{
|
|
118
|
+
if (!color) return;
|
|
119
|
+
handleChange(color);
|
|
120
|
+
handleChangeEnd(color);
|
|
121
|
+
}, [
|
|
122
|
+
handleChange,
|
|
123
|
+
handleChangeEnd
|
|
124
|
+
]);
|
|
125
|
+
return /*#__PURE__*/ jsx(ColorPicker, {
|
|
126
|
+
value: value,
|
|
127
|
+
defaultValue: !isControlled && pickerKey > 0 ? internalColor : defaultValue,
|
|
128
|
+
onChange: handleChange,
|
|
129
|
+
children: /*#__PURE__*/ jsxs(HStack, {
|
|
130
|
+
gap: 2,
|
|
131
|
+
className: cn('rounded-small bg-background-200 px-md h-[30px] w-[8.5rem]', isDisabled && 'opacity-disabled', isInputFocused && 'ring-foreground ring-1', className),
|
|
132
|
+
children: [
|
|
133
|
+
/*#__PURE__*/ jsxs(UXPopover, {
|
|
134
|
+
placement: placement,
|
|
135
|
+
children: [
|
|
136
|
+
/*#__PURE__*/ jsx(UXPopoverTrigger, {
|
|
137
|
+
children: /*#__PURE__*/ jsx(UXButton, {
|
|
138
|
+
radius: "none",
|
|
139
|
+
size: "auto",
|
|
140
|
+
isDisabled: isDisabled,
|
|
141
|
+
children: /*#__PURE__*/ jsx(ColorSwatch, {
|
|
142
|
+
className: cn('h-4 w-4 rounded-[4px]', internalColor.toString('hex') === colors.bg200 && 'border-foreground/10 border')
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
}),
|
|
146
|
+
/*#__PURE__*/ jsx(UXPopoverContent, {
|
|
147
|
+
className: "p-3",
|
|
148
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
149
|
+
className: cn('flex w-[240px] flex-col gap-3'),
|
|
150
|
+
children: [
|
|
151
|
+
/*#__PURE__*/ jsx(ColorArea, {
|
|
152
|
+
colorSpace: "hsb",
|
|
153
|
+
xChannel: "saturation",
|
|
154
|
+
yChannel: "brightness",
|
|
155
|
+
className: "aspect-square w-full overflow-hidden rounded-lg",
|
|
156
|
+
onChangeEnd: handleChangeEnd,
|
|
157
|
+
children: /*#__PURE__*/ jsx(ColorThumb, {
|
|
158
|
+
className: "h-4 w-4 rounded-full border-2 border-white shadow-[0_2px_4px_rgba(0,0,0,0.2)]"
|
|
159
|
+
})
|
|
160
|
+
}),
|
|
161
|
+
/*#__PURE__*/ jsxs(HStack, {
|
|
162
|
+
gap: "md",
|
|
163
|
+
items: "center",
|
|
164
|
+
children: [
|
|
165
|
+
'EyeDropper' in window && /*#__PURE__*/ jsx(UXButton, {
|
|
166
|
+
isIconOnly: true,
|
|
167
|
+
"aria-label": "Pick color from screen",
|
|
168
|
+
size: "sm",
|
|
169
|
+
variant: "light",
|
|
170
|
+
color: "secondary",
|
|
171
|
+
onPress: handleEyedropper,
|
|
172
|
+
children: /*#__PURE__*/ jsx(ColorPickerIcon, {})
|
|
173
|
+
}),
|
|
174
|
+
/*#__PURE__*/ jsx(ColorSwatch, {
|
|
175
|
+
className: "h-6 w-6 shrink-0 rounded-full"
|
|
176
|
+
}),
|
|
177
|
+
/*#__PURE__*/ jsx(ColorSlider, {
|
|
178
|
+
channel: "hue",
|
|
179
|
+
className: "min-w-0 flex-1",
|
|
180
|
+
colorSpace: "hsl",
|
|
181
|
+
orientation: "horizontal",
|
|
182
|
+
onChangeEnd: handleChangeEnd,
|
|
183
|
+
children: /*#__PURE__*/ jsx(SliderTrack, {
|
|
184
|
+
className: "h-3 rounded-full",
|
|
185
|
+
children: /*#__PURE__*/ jsx(ColorThumb, {
|
|
186
|
+
className: "top-[50%] z-10 h-4 w-4 rounded-full border-2 border-white shadow-[0_2px_4px_rgba(0,0,0,0.2)]"
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
]
|
|
191
|
+
}),
|
|
192
|
+
/*#__PURE__*/ jsx(ColorFields, {
|
|
193
|
+
defaultValue: !isControlled && pickerKey > 0 ? internalColor : defaultValue,
|
|
194
|
+
value: value,
|
|
195
|
+
onChange: handleColorFieldsChange
|
|
196
|
+
})
|
|
197
|
+
]
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
]
|
|
201
|
+
}),
|
|
202
|
+
/*#__PURE__*/ jsx(ColorInput, {
|
|
203
|
+
isDisabled: isDisabled,
|
|
204
|
+
inputClassName: "focus:ring-0 px-0 text-left flex-1 relative bg-transparent",
|
|
205
|
+
value: value,
|
|
206
|
+
defaultValue: !isControlled && pickerKey > 0 ? internalColor : defaultValue,
|
|
207
|
+
onChange: handleColorFieldsChange,
|
|
208
|
+
onFocus: ()=>setIsInputFocused(true),
|
|
209
|
+
onBlur: ()=>setIsInputFocused(false)
|
|
210
|
+
}),
|
|
211
|
+
hasChanged ? /*#__PURE__*/ jsx(UXButton, {
|
|
212
|
+
isIconOnly: true,
|
|
213
|
+
"aria-label": "Reset color",
|
|
214
|
+
isDisabled: isDisabled,
|
|
215
|
+
size: "sm",
|
|
216
|
+
variant: "light",
|
|
217
|
+
color: "secondary",
|
|
218
|
+
onPress: handleReset,
|
|
219
|
+
children: /*#__PURE__*/ jsx(RefreshCcwIcon, {})
|
|
220
|
+
}) : /*#__PURE__*/ jsx("div", {
|
|
221
|
+
className: "size-4 shrink-0"
|
|
222
|
+
})
|
|
223
|
+
]
|
|
224
|
+
})
|
|
225
|
+
}, isControlled ? void 0 : pickerKey);
|
|
226
|
+
};
|
|
227
|
+
UXColorPicker.displayName = 'UXColorPicker';
|
|
228
|
+
export { UXColorPicker };
|