@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.
Files changed (89) hide show
  1. package/dist/components/ProgressWrapper/index.d.ts +2 -2
  2. package/dist/components/ProgressWrapper/index.js +1 -1
  3. package/dist/components/UXAutocomplete/index.js +1 -2
  4. package/dist/components/UXButton/button-theme.js +38 -2
  5. package/dist/components/UXButton/button.js +1 -1
  6. package/dist/components/UXCheckbox/checkbox.extend.js +16 -13
  7. package/dist/components/UXChip/chip.extend.d.ts +2 -1
  8. package/dist/components/UXChip/index.d.ts +1 -1
  9. package/dist/components/UXColorPicker/color-fields.d.ts +3 -0
  10. package/dist/components/UXColorPicker/color-fields.js +142 -0
  11. package/dist/components/UXColorPicker/color-input.d.ts +7 -0
  12. package/dist/components/UXColorPicker/color-input.js +12 -0
  13. package/dist/components/UXColorPicker/color-picker.d.ts +3 -0
  14. package/dist/components/UXColorPicker/color-picker.js +228 -0
  15. package/dist/components/UXColorPicker/index.d.ts +5 -0
  16. package/dist/components/UXColorPicker/index.js +3 -0
  17. package/dist/components/UXColorPicker/types.d.ts +51 -0
  18. package/dist/components/UXColorPicker/types.js +0 -0
  19. package/dist/components/UXColorPicker/utils.d.ts +7 -0
  20. package/dist/components/UXColorPicker/utils.js +6 -0
  21. package/dist/components/UXCopy/index.js +2 -2
  22. package/dist/components/UXEmpty/index.js +2 -2
  23. package/dist/components/UXHint/index.js +1 -1
  24. package/dist/components/UXInput/index.d.ts +6 -6
  25. package/dist/components/UXInput/input.extend.d.ts +6 -6
  26. package/dist/components/UXRadio/radio.extend.js +3 -3
  27. package/dist/components/UXSlider/use-slider.d.ts +1 -1
  28. package/dist/components/UXSlider/use-slider.js +1 -1
  29. package/dist/components/UXSpinner/spinner.d.ts +1 -5
  30. package/dist/components/UXSpinner/spinner.js +3 -4
  31. package/dist/components/UXSwitch/index.d.ts +2 -2
  32. package/dist/components/UXSwitch/switch.extend.d.ts +2 -2
  33. package/dist/components/UXSwitch/switch.extend.js +6 -6
  34. package/dist/components/UXTabs/tabs.classes.js +4 -4
  35. package/dist/components/UXThemeSwitch/constants.d.ts +9 -0
  36. package/dist/components/UXThemeSwitch/constants.js +3 -0
  37. package/dist/components/UXThemeSwitch/custom-theme-config.d.ts +2 -0
  38. package/dist/components/UXThemeSwitch/custom-theme-config.js +171 -0
  39. package/dist/components/UXThemeSwitch/theme-item.js +94 -15
  40. package/dist/components/UXThemeSwitch/theme-switch.js +26 -5
  41. package/dist/components/UXThemeSwitch/use-color-scheme.js +11 -8
  42. package/dist/components/UXThemeSwitch/use-theme-color.d.ts +1 -22
  43. package/dist/components/UXThemeSwitch/use-theme-color.js +3 -7
  44. package/dist/components/UXThemeSwitch/use-theme-store.d.ts +5 -0
  45. package/dist/components/UXThemeSwitch/use-theme-store.js +9 -3
  46. package/dist/components/UXThemeSwitch/use-theme.d.ts +2 -0
  47. package/dist/components/UXThemeSwitch/use-theme.js +10 -53
  48. package/dist/components/UXThemeSwitch/utils.d.ts +28 -0
  49. package/dist/components/UXThemeSwitch/utils.js +222 -0
  50. package/dist/components/UXToast/index.js +3 -3
  51. package/dist/components/index.d.ts +1 -0
  52. package/dist/components/index.js +1 -0
  53. package/dist/components/layout/Box/box-theme.d.ts +2225 -0
  54. package/dist/components/layout/Box/box-theme.js +348 -0
  55. package/dist/components/layout/Box/box.d.ts +14 -0
  56. package/dist/components/layout/Box/box.js +99 -0
  57. package/dist/components/layout/Circle.js +2 -3
  58. package/dist/components/layout/Flex.d.ts +3 -27
  59. package/dist/components/layout/Flex.js +6 -19
  60. package/dist/components/layout/HStack.d.ts +1 -1
  61. package/dist/components/layout/Square.js +3 -3
  62. package/dist/components/layout/VStack.d.ts +1 -1
  63. package/dist/components/layout/VStack.js +2 -2
  64. package/dist/components/layout/index.d.ts +1 -0
  65. package/dist/components/layout/index.js +1 -0
  66. package/dist/components/typography/Text.js +22 -7
  67. package/dist/components/typography/Text.type.d.ts +3 -26
  68. package/dist/components/typography/Text.type.js +0 -47
  69. package/dist/components/typography/text-theme.d.ts +178 -0
  70. package/dist/components/typography/text-theme.js +79 -0
  71. package/dist/heroui/constants.d.ts +18 -0
  72. package/dist/heroui/constants.js +98 -0
  73. package/dist/heroui/types.d.ts +91 -0
  74. package/dist/heroui/types.js +0 -0
  75. package/dist/heroui/utils/colors.d.ts +34 -0
  76. package/dist/heroui/utils/colors.js +121 -0
  77. package/dist/heroui/utils/object.d.ts +1 -0
  78. package/dist/heroui/utils/object.js +17 -0
  79. package/dist/hooks/useI18n.d.ts +133 -25
  80. package/dist/hooks/useI18n.js +84 -2
  81. package/dist/hooks/useLang.d.ts +5 -1
  82. package/dist/hooks/useLang.js +13 -1
  83. package/dist/utils/cn.d.ts +2 -0
  84. package/dist/utils/cn.js +258 -0
  85. package/dist/utils/index.d.ts +1 -0
  86. package/dist/utils/index.js +2 -1
  87. package/dist/utils/input-classes.js +2 -2
  88. package/package.json +8 -5
  89. package/tailwind-preset.js +84 -160
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { type UXForegroundColor, type UXRadius } from '@particle-network/ui-shared';
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?: UXForegroundColor | 'transparent' | `#${string}`;
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 { fullWidth = false, classNames = {}, radius = 'sm', labelPlacement = 'outside-top', ...restProps } = props;
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-tertiary text-tertiary-foreground'
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-tertiary text-tertiary-foreground'
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: "currentColor",
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-tertiary after:text-tertiary-foreground text-tertiary-foreground'
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-body3 font-medium',
37
- icon: 'h-2.5'
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.2)]',
43
- 'before:rounded-[calc(theme(borderRadius.medium)*0.2)] before:border-secondary before:border-1.5',
44
- 'after:rounded-[calc(theme(borderRadius.medium)*0.2)]'
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-3'
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.3)]',
53
- 'before:rounded-[calc(theme(borderRadius.medium)*0.3)] before:border-secondary before:border-1.5',
54
- 'after:rounded-[calc(theme(borderRadius.medium)*0.3)]'
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.5'
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 gap-2'
150
+ base: 'flex-row-reverse'
148
151
  },
149
152
  right: {
150
- base: 'flex-row gap-2'
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' | `#${string}`;
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" | `#${string}`;
5
+ color?: "default" | "primary" | "secondary" | "success" | "warning" | "alert" | "danger" | "bullish" | "bearish" | import("@particle-network/ui-shared").HexColor;
6
6
  }, never>;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { ColorFieldsProps } from './types';
3
+ export declare const ColorFields: React.FC<ColorFieldsProps>;
@@ -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,7 @@
1
+ import React from 'react';
2
+ import { type ColorFieldProps } from 'react-aria-components';
3
+ interface ColorInputProps extends ColorFieldProps {
4
+ inputClassName?: string;
5
+ }
6
+ export declare const ColorInput: React.FC<ColorInputProps>;
7
+ export {};
@@ -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,3 @@
1
+ import React from 'react';
2
+ import type { UXColorPickerProps } from './types';
3
+ export declare const UXColorPicker: React.FC<UXColorPickerProps>;
@@ -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 };
@@ -0,0 +1,5 @@
1
+ import { parseColor } from 'react-aria-components';
2
+ import type { Color } from 'react-stately';
3
+ export { UXColorPicker } from './color-picker';
4
+ export type * from './types';
5
+ export { type Color, parseColor };
@@ -0,0 +1,3 @@
1
+ import { parseColor } from "react-aria-components";
2
+ import { UXColorPicker } from "./color-picker.js";
3
+ export { UXColorPicker, parseColor };