@pixpilot/shadcn-ui 0.14.0 → 0.15.1

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.
@@ -2,7 +2,6 @@
2
2
 
3
3
 
4
4
  const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
5
- const require_PaletteSwatch = require('../ColorPickerBase/PaletteSwatch.cjs');
6
5
  const require_ColorPickerBase = require('../ColorPickerBase/ColorPickerBase.cjs');
7
6
  require('../ColorPickerBase/index.cjs');
8
7
  let __pixpilot_shadcn = require("@pixpilot/shadcn");
@@ -14,9 +13,9 @@ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
14
13
 
15
14
  //#region src/ColorPicker/ColorPicker.tsx
16
15
  function Swatch(props) {
17
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PaletteSwatch.PaletteSwatch, {
16
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.ColorPickerSwatch, {
18
17
  color: props.color,
19
- className: "rounded-sm"
18
+ className: (0, __pixpilot_shadcn.cn)("rounded-sm w-6.5 h-6.5 p-0 -ml-1 cursor-pointer", props.className)
20
19
  });
21
20
  }
22
21
  const ColorPicker = (props) => {
@@ -26,7 +25,7 @@ const ColorPicker = (props) => {
26
25
  children: ({ value, onValueChange, isPickerOpen }) => {
27
26
  if (variant === "input") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.InputGroup, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.InputGroupAddon, {
28
27
  align: "inline-start",
29
- className: "pl-1",
28
+ className: "pl-0",
30
29
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Swatch, { color: value })
31
30
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.InputGroupInput, {
32
31
  value: value ?? "",
@@ -46,7 +45,7 @@ const ColorPicker = (props) => {
46
45
  children: [
47
46
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.InputGroupAddon, {
48
47
  align: "inline-start",
49
- className: "pl-1",
48
+ className: "pl-0",
50
49
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Swatch, { color: value })
51
50
  }),
52
51
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.InputGroupText, {
@@ -1,18 +1,17 @@
1
1
  'use client';
2
2
 
3
3
 
4
- import { PaletteSwatch } from "../ColorPickerBase/PaletteSwatch.js";
5
4
  import { ColorPickerBase } from "../ColorPickerBase/ColorPickerBase.js";
6
5
  import "../ColorPickerBase/index.js";
7
- import { InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, cn } from "@pixpilot/shadcn";
6
+ import { ColorPickerSwatch, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, cn } from "@pixpilot/shadcn";
8
7
  import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
9
8
  import { jsx, jsxs } from "react/jsx-runtime";
10
9
 
11
10
  //#region src/ColorPicker/ColorPicker.tsx
12
11
  function Swatch(props) {
13
- return /* @__PURE__ */ jsx(PaletteSwatch, {
12
+ return /* @__PURE__ */ jsx(ColorPickerSwatch, {
14
13
  color: props.color,
15
- className: "rounded-sm"
14
+ className: cn("rounded-sm w-6.5 h-6.5 p-0 -ml-1 cursor-pointer", props.className)
16
15
  });
17
16
  }
18
17
  const ColorPicker$1 = (props) => {
@@ -22,7 +21,7 @@ const ColorPicker$1 = (props) => {
22
21
  children: ({ value, onValueChange, isPickerOpen }) => {
23
22
  if (variant === "input") return /* @__PURE__ */ jsxs(InputGroup, { children: [/* @__PURE__ */ jsx(InputGroupAddon, {
24
23
  align: "inline-start",
25
- className: "pl-1",
24
+ className: "pl-0",
26
25
  children: /* @__PURE__ */ jsx(Swatch, { color: value })
27
26
  }), /* @__PURE__ */ jsx(InputGroupInput, {
28
27
  value: value ?? "",
@@ -42,7 +41,7 @@ const ColorPicker$1 = (props) => {
42
41
  children: [
43
42
  /* @__PURE__ */ jsx(InputGroupAddon, {
44
43
  align: "inline-start",
45
- className: "pl-1",
44
+ className: "pl-0",
46
45
  children: /* @__PURE__ */ jsx(Swatch, { color: value })
47
46
  }),
48
47
  /* @__PURE__ */ jsx(InputGroupText, {
@@ -2,10 +2,10 @@
2
2
 
3
3
 
4
4
  const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
5
- const require_use_controlled = require('../hooks/src/use-controlled.cjs');
6
- require('../hooks/src/index.cjs');
7
5
  const require_ColorPickerCompact = require('./ColorPickerCompact.cjs');
8
6
  const require_ColorPickerFull = require('./ColorPickerFull.cjs');
7
+ const require_use_color_picker_base_swatch = require('./hooks/use-color-picker-base-swatch.cjs');
8
+ const require_use_color_picker_base_value = require('./hooks/use-color-picker-base-value.cjs');
9
9
  let __pixpilot_shadcn = require("@pixpilot/shadcn");
10
10
  __pixpilot_shadcn = require_rolldown_runtime.__toESM(__pixpilot_shadcn);
11
11
  let react = require("react");
@@ -15,7 +15,7 @@ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
15
15
 
16
16
  //#region src/ColorPickerBase/ColorPickerBase.tsx
17
17
  const commonColors = [
18
- "transparent",
18
+ "#00000000",
19
19
  "#000000",
20
20
  "#FFFFFF",
21
21
  "#808080",
@@ -34,52 +34,21 @@ const commonColors = [
34
34
  ];
35
35
  const DEFAULT_COLOR = "#000000";
36
36
  const ColorPickerBase = (props) => {
37
- const { value: propValue, onChange, onValueChange, layout = "full", presetColors, children,...rest } = props;
38
- const [currentValue, setCurrentValue] = require_use_controlled.default({
39
- controlled: propValue,
40
- default: DEFAULT_COLOR,
41
- name: "ColorPickerBase",
42
- state: "value"
43
- });
44
- const [open, setOpen] = (0, react.useState)(false);
45
- /**
46
- * Prevent "Maximum update depth exceeded" in controlled mode.
47
- *
48
- * The underlying @pixpilot/shadcn ColorPicker calls onValueChange inside a layout-effect
49
- * when syncing a controlled 'value' prop (it calls both store.setColor() and store.setHsv(),
50
- * each of which emits onValueChange). This can create a feedback loop if the parent
51
- * re-renders and passes back the same normalized value, causing infinite re-renders
52
- * during fast pointer moves.
53
- *
54
- * We guard against this by:
55
- * - Ignoring onValueChange events that occur immediately after a prop change.
56
- * - Deduping repeated notifications of the same value.
57
- */
58
- const isApplyingControlledValueRef = (0, react.useRef)(false);
59
- const lastPropValueRef = (0, react.useRef)(propValue);
60
- const lastNotifiedValueRef = (0, react.useRef)(void 0);
61
- if (propValue !== lastPropValueRef.current) {
62
- lastPropValueRef.current = propValue;
63
- isApplyingControlledValueRef.current = true;
64
- }
65
- (0, react.useEffect)(() => {
66
- isApplyingControlledValueRef.current = false;
67
- }, [propValue]);
68
- const handleValueChange = (0, react.useCallback)((value) => {
69
- if (isApplyingControlledValueRef.current) return;
70
- if (lastNotifiedValueRef.current === value) {
71
- setCurrentValue(value);
72
- return;
73
- }
74
- setCurrentValue(value);
75
- onChange?.(value);
76
- onValueChange?.(value);
77
- lastNotifiedValueRef.current = value;
78
- }, [
79
- setCurrentValue,
37
+ const { value: propValue, onChange, onValueChange, layout = "full", presetColors, format, defaultFormat = "hex", onFormatChange, children,...rest } = props;
38
+ const { currentValue, handleValueChange } = require_use_color_picker_base_value.useColorPickerBaseValue({
39
+ value: propValue,
40
+ defaultValue: DEFAULT_COLOR,
80
41
  onChange,
81
42
  onValueChange
82
- ]);
43
+ });
44
+ const { valueForPicker, handleFormatChange, handleSwatchSelect } = require_use_color_picker_base_swatch.useColorPickerBaseSwatch({
45
+ currentValue,
46
+ format,
47
+ defaultFormat,
48
+ onFormatChange,
49
+ handleValueChange
50
+ });
51
+ const [open, setOpen] = (0, react.useState)(false);
83
52
  let colors = presetColors || commonColors;
84
53
  const handleOpen = (0, react.useCallback)((isOpen) => {
85
54
  setOpen(isOpen);
@@ -87,7 +56,10 @@ const ColorPickerBase = (props) => {
87
56
  if (layout === "compact" && !presetColors) colors = colors.slice(0, -1);
88
57
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.ColorPicker, {
89
58
  ...rest,
90
- value: currentValue,
59
+ format,
60
+ defaultFormat,
61
+ onFormatChange: handleFormatChange,
62
+ value: valueForPicker,
91
63
  onValueChange: handleValueChange,
92
64
  onOpenChange: handleOpen,
93
65
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.ColorPickerTrigger, {
@@ -99,11 +71,11 @@ const ColorPickerBase = (props) => {
99
71
  isPickerOpen: open
100
72
  })
101
73
  }), layout === "compact" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ColorPickerCompact.ColorPickerCompact, {
102
- onValueChange: handleValueChange,
74
+ onValueChange: handleSwatchSelect,
103
75
  layout,
104
76
  presetColors: colors
105
77
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ColorPickerFull.ColorPickerFull, {
106
- onValueChange: handleValueChange,
78
+ onValueChange: handleSwatchSelect,
107
79
  layout,
108
80
  presetColors: colors
109
81
  })]
@@ -1,17 +1,17 @@
1
1
  'use client';
2
2
 
3
3
 
4
- import useControlled from "../hooks/src/use-controlled.js";
5
- import "../hooks/src/index.js";
6
4
  import { ColorPickerCompact } from "./ColorPickerCompact.js";
7
5
  import { ColorPickerFull } from "./ColorPickerFull.js";
6
+ import { useColorPickerBaseSwatch } from "./hooks/use-color-picker-base-swatch.js";
7
+ import { useColorPickerBaseValue } from "./hooks/use-color-picker-base-value.js";
8
8
  import { ColorPicker, ColorPickerTrigger } from "@pixpilot/shadcn";
9
- import { useCallback, useEffect, useRef, useState } from "react";
9
+ import { useCallback, useState } from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
 
12
12
  //#region src/ColorPickerBase/ColorPickerBase.tsx
13
13
  const commonColors = [
14
- "transparent",
14
+ "#00000000",
15
15
  "#000000",
16
16
  "#FFFFFF",
17
17
  "#808080",
@@ -30,52 +30,21 @@ const commonColors = [
30
30
  ];
31
31
  const DEFAULT_COLOR = "#000000";
32
32
  const ColorPickerBase = (props) => {
33
- const { value: propValue, onChange, onValueChange, layout = "full", presetColors, children,...rest } = props;
34
- const [currentValue, setCurrentValue] = useControlled({
35
- controlled: propValue,
36
- default: DEFAULT_COLOR,
37
- name: "ColorPickerBase",
38
- state: "value"
39
- });
40
- const [open, setOpen] = useState(false);
41
- /**
42
- * Prevent "Maximum update depth exceeded" in controlled mode.
43
- *
44
- * The underlying @pixpilot/shadcn ColorPicker calls onValueChange inside a layout-effect
45
- * when syncing a controlled 'value' prop (it calls both store.setColor() and store.setHsv(),
46
- * each of which emits onValueChange). This can create a feedback loop if the parent
47
- * re-renders and passes back the same normalized value, causing infinite re-renders
48
- * during fast pointer moves.
49
- *
50
- * We guard against this by:
51
- * - Ignoring onValueChange events that occur immediately after a prop change.
52
- * - Deduping repeated notifications of the same value.
53
- */
54
- const isApplyingControlledValueRef = useRef(false);
55
- const lastPropValueRef = useRef(propValue);
56
- const lastNotifiedValueRef = useRef(void 0);
57
- if (propValue !== lastPropValueRef.current) {
58
- lastPropValueRef.current = propValue;
59
- isApplyingControlledValueRef.current = true;
60
- }
61
- useEffect(() => {
62
- isApplyingControlledValueRef.current = false;
63
- }, [propValue]);
64
- const handleValueChange = useCallback((value) => {
65
- if (isApplyingControlledValueRef.current) return;
66
- if (lastNotifiedValueRef.current === value) {
67
- setCurrentValue(value);
68
- return;
69
- }
70
- setCurrentValue(value);
71
- onChange?.(value);
72
- onValueChange?.(value);
73
- lastNotifiedValueRef.current = value;
74
- }, [
75
- setCurrentValue,
33
+ const { value: propValue, onChange, onValueChange, layout = "full", presetColors, format, defaultFormat = "hex", onFormatChange, children,...rest } = props;
34
+ const { currentValue, handleValueChange } = useColorPickerBaseValue({
35
+ value: propValue,
36
+ defaultValue: DEFAULT_COLOR,
76
37
  onChange,
77
38
  onValueChange
78
- ]);
39
+ });
40
+ const { valueForPicker, handleFormatChange, handleSwatchSelect } = useColorPickerBaseSwatch({
41
+ currentValue,
42
+ format,
43
+ defaultFormat,
44
+ onFormatChange,
45
+ handleValueChange
46
+ });
47
+ const [open, setOpen] = useState(false);
79
48
  let colors = presetColors || commonColors;
80
49
  const handleOpen = useCallback((isOpen) => {
81
50
  setOpen(isOpen);
@@ -83,7 +52,10 @@ const ColorPickerBase = (props) => {
83
52
  if (layout === "compact" && !presetColors) colors = colors.slice(0, -1);
84
53
  return /* @__PURE__ */ jsxs(ColorPicker, {
85
54
  ...rest,
86
- value: currentValue,
55
+ format,
56
+ defaultFormat,
57
+ onFormatChange: handleFormatChange,
58
+ value: valueForPicker,
87
59
  onValueChange: handleValueChange,
88
60
  onOpenChange: handleOpen,
89
61
  children: [/* @__PURE__ */ jsx(ColorPickerTrigger, {
@@ -95,11 +67,11 @@ const ColorPickerBase = (props) => {
95
67
  isPickerOpen: open
96
68
  })
97
69
  }), layout === "compact" ? /* @__PURE__ */ jsx(ColorPickerCompact, {
98
- onValueChange: handleValueChange,
70
+ onValueChange: handleSwatchSelect,
99
71
  layout,
100
72
  presetColors: colors
101
73
  }) : /* @__PURE__ */ jsx(ColorPickerFull, {
102
- onValueChange: handleValueChange,
74
+ onValueChange: handleSwatchSelect,
103
75
  layout,
104
76
  presetColors: colors
105
77
  })]
@@ -8,15 +8,13 @@ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
8
8
  //#region src/ColorPickerBase/PaletteSwatch.tsx
9
9
  const PaletteSwatch = ({ color, onSelect, className }) => {
10
10
  const handleClick = (0, react.useCallback)(() => {
11
- if (onSelect) onSelect(color ?? "transparent");
11
+ if (onSelect) onSelect(color ?? "rgb(0,0,0,0)");
12
12
  }, [color, onSelect]);
13
13
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PaletteButton.PaletteButton, {
14
- style: color == null || color === "transparent" ? {
15
- backgroundColor: "transparent",
16
- backgroundImage: "linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(-45deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(-45deg, transparent 75%, #ccc 75%)",
17
- backgroundSize: "4px 4px",
18
- backgroundPosition: "0 0, 0 2px, 2px -2px, -2px 0px"
19
- } : { backgroundColor: color },
14
+ style: {
15
+ backgroundImage: `linear-gradient(${color}, ${color}), repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%)`,
16
+ backgroundSize: "auto, 8px 8px"
17
+ },
20
18
  className,
21
19
  onClick: handleClick
22
20
  });
@@ -5,15 +5,13 @@ import { jsx } from "react/jsx-runtime";
5
5
  //#region src/ColorPickerBase/PaletteSwatch.tsx
6
6
  const PaletteSwatch = ({ color, onSelect, className }) => {
7
7
  const handleClick = useCallback(() => {
8
- if (onSelect) onSelect(color ?? "transparent");
8
+ if (onSelect) onSelect(color ?? "rgb(0,0,0,0)");
9
9
  }, [color, onSelect]);
10
10
  return /* @__PURE__ */ jsx(PaletteButton, {
11
- style: color == null || color === "transparent" ? {
12
- backgroundColor: "transparent",
13
- backgroundImage: "linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(-45deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(-45deg, transparent 75%, #ccc 75%)",
14
- backgroundSize: "4px 4px",
15
- backgroundPosition: "0 0, 0 2px, 2px -2px, -2px 0px"
16
- } : { backgroundColor: color },
11
+ style: {
12
+ backgroundImage: `linear-gradient(${color}, ${color}), repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%)`,
13
+ backgroundSize: "auto, 8px 8px"
14
+ },
17
15
  className,
18
16
  onClick: handleClick
19
17
  });
@@ -0,0 +1,41 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ const require_color_picker_base_utils = require('../utils/color-picker-base-utils.cjs');
3
+ let react = require("react");
4
+ react = require_rolldown_runtime.__toESM(react);
5
+
6
+ //#region src/ColorPickerBase/hooks/use-color-picker-base-swatch.ts
7
+ function useColorPickerBaseSwatch(params) {
8
+ const { currentValue, format, defaultFormat, onFormatChange, handleValueChange } = params;
9
+ const currentFormatRef = (0, react.useRef)(format ?? defaultFormat);
10
+ if (format !== void 0) currentFormatRef.current = format;
11
+ const [forceOpaqueHex, setForceOpaqueHex] = (0, react.useState)(null);
12
+ const handleFormatChange = (0, react.useCallback)((nextFormat) => {
13
+ currentFormatRef.current = nextFormat;
14
+ onFormatChange?.(nextFormat);
15
+ }, [onFormatChange]);
16
+ const handleSwatchSelect = (0, react.useCallback)((value) => {
17
+ const desiredFormat = currentFormatRef.current;
18
+ const result = require_color_picker_base_utils.getSwatchSelectionResult({
19
+ swatchValue: value,
20
+ desiredFormat
21
+ });
22
+ if (result.forceOpaqueHex !== null) setForceOpaqueHex(result.forceOpaqueHex);
23
+ handleValueChange(result.value);
24
+ }, [handleValueChange]);
25
+ (0, react.useLayoutEffect)(() => {
26
+ if (forceOpaqueHex === null) return;
27
+ if (currentValue.trim().toLowerCase() === forceOpaqueHex) setForceOpaqueHex(null);
28
+ }, [currentValue, forceOpaqueHex]);
29
+ return {
30
+ valueForPicker: require_color_picker_base_utils.toPickerValue({
31
+ currentValue,
32
+ currentFormat: currentFormatRef.current,
33
+ forceOpaqueHex
34
+ }),
35
+ handleFormatChange,
36
+ handleSwatchSelect
37
+ };
38
+ }
39
+
40
+ //#endregion
41
+ exports.useColorPickerBaseSwatch = useColorPickerBaseSwatch;
@@ -0,0 +1,39 @@
1
+ import { getSwatchSelectionResult, toPickerValue } from "../utils/color-picker-base-utils.js";
2
+ import { useCallback, useLayoutEffect, useRef, useState } from "react";
3
+
4
+ //#region src/ColorPickerBase/hooks/use-color-picker-base-swatch.ts
5
+ function useColorPickerBaseSwatch(params) {
6
+ const { currentValue, format, defaultFormat, onFormatChange, handleValueChange } = params;
7
+ const currentFormatRef = useRef(format ?? defaultFormat);
8
+ if (format !== void 0) currentFormatRef.current = format;
9
+ const [forceOpaqueHex, setForceOpaqueHex] = useState(null);
10
+ const handleFormatChange = useCallback((nextFormat) => {
11
+ currentFormatRef.current = nextFormat;
12
+ onFormatChange?.(nextFormat);
13
+ }, [onFormatChange]);
14
+ const handleSwatchSelect = useCallback((value) => {
15
+ const desiredFormat = currentFormatRef.current;
16
+ const result = getSwatchSelectionResult({
17
+ swatchValue: value,
18
+ desiredFormat
19
+ });
20
+ if (result.forceOpaqueHex !== null) setForceOpaqueHex(result.forceOpaqueHex);
21
+ handleValueChange(result.value);
22
+ }, [handleValueChange]);
23
+ useLayoutEffect(() => {
24
+ if (forceOpaqueHex === null) return;
25
+ if (currentValue.trim().toLowerCase() === forceOpaqueHex) setForceOpaqueHex(null);
26
+ }, [currentValue, forceOpaqueHex]);
27
+ return {
28
+ valueForPicker: toPickerValue({
29
+ currentValue,
30
+ currentFormat: currentFormatRef.current,
31
+ forceOpaqueHex
32
+ }),
33
+ handleFormatChange,
34
+ handleSwatchSelect
35
+ };
36
+ }
37
+
38
+ //#endregion
39
+ export { useColorPickerBaseSwatch };
@@ -0,0 +1,56 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ const require_use_controlled = require('../../hooks/src/use-controlled.cjs');
3
+ require('../../hooks/src/index.cjs');
4
+ let react = require("react");
5
+ react = require_rolldown_runtime.__toESM(react);
6
+
7
+ //#region src/ColorPickerBase/hooks/use-color-picker-base-value.ts
8
+ function useColorPickerBaseValue(params) {
9
+ const { value: propValue, defaultValue, onChange, onValueChange } = params;
10
+ const [currentValue, setCurrentValue] = require_use_controlled.default({
11
+ controlled: propValue,
12
+ default: defaultValue,
13
+ name: "ColorPickerBase",
14
+ state: "value"
15
+ });
16
+ /**
17
+ * Prevent "Maximum update depth exceeded" in controlled mode.
18
+ *
19
+ * The underlying @pixpilot/shadcn ColorPicker calls onValueChange inside a layout-effect
20
+ * when syncing a controlled 'value' prop (it calls both store.setColor() and store.setHsv(),
21
+ * each of which emits onValueChange). This can create a feedback loop if the parent
22
+ * re-renders and passes back the same normalized value, causing infinite re-renders
23
+ * during fast pointer moves.
24
+ */
25
+ const isApplyingControlledValueRef = (0, react.useRef)(false);
26
+ const lastPropValueRef = (0, react.useRef)(propValue);
27
+ const lastNotifiedValueRef = (0, react.useRef)(void 0);
28
+ if (propValue !== lastPropValueRef.current) {
29
+ lastPropValueRef.current = propValue;
30
+ isApplyingControlledValueRef.current = true;
31
+ }
32
+ (0, react.useEffect)(() => {
33
+ isApplyingControlledValueRef.current = false;
34
+ }, [propValue]);
35
+ return {
36
+ currentValue,
37
+ handleValueChange: (0, react.useCallback)((value) => {
38
+ if (isApplyingControlledValueRef.current) return;
39
+ if (lastNotifiedValueRef.current === value) {
40
+ setCurrentValue(value);
41
+ return;
42
+ }
43
+ setCurrentValue(value);
44
+ onChange?.(value);
45
+ onValueChange?.(value);
46
+ lastNotifiedValueRef.current = value;
47
+ }, [
48
+ setCurrentValue,
49
+ onChange,
50
+ onValueChange
51
+ ])
52
+ };
53
+ }
54
+
55
+ //#endregion
56
+ exports.useColorPickerBaseValue = useColorPickerBaseValue;
@@ -0,0 +1,54 @@
1
+ import useControlled from "../../hooks/src/use-controlled.js";
2
+ import "../../hooks/src/index.js";
3
+ import { useCallback, useEffect, useRef } from "react";
4
+
5
+ //#region src/ColorPickerBase/hooks/use-color-picker-base-value.ts
6
+ function useColorPickerBaseValue(params) {
7
+ const { value: propValue, defaultValue, onChange, onValueChange } = params;
8
+ const [currentValue, setCurrentValue] = useControlled({
9
+ controlled: propValue,
10
+ default: defaultValue,
11
+ name: "ColorPickerBase",
12
+ state: "value"
13
+ });
14
+ /**
15
+ * Prevent "Maximum update depth exceeded" in controlled mode.
16
+ *
17
+ * The underlying @pixpilot/shadcn ColorPicker calls onValueChange inside a layout-effect
18
+ * when syncing a controlled 'value' prop (it calls both store.setColor() and store.setHsv(),
19
+ * each of which emits onValueChange). This can create a feedback loop if the parent
20
+ * re-renders and passes back the same normalized value, causing infinite re-renders
21
+ * during fast pointer moves.
22
+ */
23
+ const isApplyingControlledValueRef = useRef(false);
24
+ const lastPropValueRef = useRef(propValue);
25
+ const lastNotifiedValueRef = useRef(void 0);
26
+ if (propValue !== lastPropValueRef.current) {
27
+ lastPropValueRef.current = propValue;
28
+ isApplyingControlledValueRef.current = true;
29
+ }
30
+ useEffect(() => {
31
+ isApplyingControlledValueRef.current = false;
32
+ }, [propValue]);
33
+ return {
34
+ currentValue,
35
+ handleValueChange: useCallback((value) => {
36
+ if (isApplyingControlledValueRef.current) return;
37
+ if (lastNotifiedValueRef.current === value) {
38
+ setCurrentValue(value);
39
+ return;
40
+ }
41
+ setCurrentValue(value);
42
+ onChange?.(value);
43
+ onValueChange?.(value);
44
+ lastNotifiedValueRef.current = value;
45
+ }, [
46
+ setCurrentValue,
47
+ onChange,
48
+ onValueChange
49
+ ])
50
+ };
51
+ }
52
+
53
+ //#endregion
54
+ export { useColorPickerBaseValue };
@@ -0,0 +1,48 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ let __pixpilot_shadcn = require("@pixpilot/shadcn");
3
+ __pixpilot_shadcn = require_rolldown_runtime.__toESM(__pixpilot_shadcn);
4
+
5
+ //#region src/ColorPickerBase/utils/color-picker-base-utils.ts
6
+ const HEX_WITHOUT_ALPHA_SHORT_TOTAL_LENGTH = 4;
7
+ const HEX_WITHOUT_ALPHA_LONG_TOTAL_LENGTH = 7;
8
+ const OPAQUE_ALPHA_HEX = "ff";
9
+ function isHexWithoutAlphaString(value) {
10
+ const trimmed = value.trim().toLowerCase();
11
+ if (!trimmed.startsWith("#")) return false;
12
+ return trimmed.length === HEX_WITHOUT_ALPHA_SHORT_TOTAL_LENGTH || trimmed.length === HEX_WITHOUT_ALPHA_LONG_TOTAL_LENGTH;
13
+ }
14
+ function toPickerValue(params) {
15
+ const { currentValue, currentFormat, forceOpaqueHex } = params;
16
+ if (forceOpaqueHex === null) return currentValue;
17
+ if (currentFormat !== "hex") return currentValue;
18
+ if (currentValue.trim().toLowerCase() !== forceOpaqueHex) return currentValue;
19
+ return `${forceOpaqueHex}${OPAQUE_ALPHA_HEX}`;
20
+ }
21
+ function getSwatchSelectionResult(params) {
22
+ const { swatchValue, desiredFormat } = params;
23
+ const parsed = __pixpilot_shadcn.colorUtils.parseColorString(swatchValue);
24
+ if (!parsed) return {
25
+ value: swatchValue,
26
+ forceOpaqueHex: null
27
+ };
28
+ const isHexWithoutAlpha = isHexWithoutAlphaString(swatchValue);
29
+ const normalizedColor = isHexWithoutAlpha ? {
30
+ ...parsed,
31
+ a: 1
32
+ } : parsed;
33
+ if (desiredFormat === "hex" && isHexWithoutAlpha) {
34
+ const baseHex = __pixpilot_shadcn.colorUtils.colorToString(normalizedColor, "hex");
35
+ return {
36
+ value: baseHex,
37
+ forceOpaqueHex: baseHex.trim().toLowerCase()
38
+ };
39
+ }
40
+ return {
41
+ value: __pixpilot_shadcn.colorUtils.colorToString(normalizedColor, desiredFormat),
42
+ forceOpaqueHex: null
43
+ };
44
+ }
45
+
46
+ //#endregion
47
+ exports.getSwatchSelectionResult = getSwatchSelectionResult;
48
+ exports.toPickerValue = toPickerValue;
@@ -0,0 +1,45 @@
1
+ import { colorUtils } from "@pixpilot/shadcn";
2
+
3
+ //#region src/ColorPickerBase/utils/color-picker-base-utils.ts
4
+ const HEX_WITHOUT_ALPHA_SHORT_TOTAL_LENGTH = 4;
5
+ const HEX_WITHOUT_ALPHA_LONG_TOTAL_LENGTH = 7;
6
+ const OPAQUE_ALPHA_HEX = "ff";
7
+ function isHexWithoutAlphaString(value) {
8
+ const trimmed = value.trim().toLowerCase();
9
+ if (!trimmed.startsWith("#")) return false;
10
+ return trimmed.length === HEX_WITHOUT_ALPHA_SHORT_TOTAL_LENGTH || trimmed.length === HEX_WITHOUT_ALPHA_LONG_TOTAL_LENGTH;
11
+ }
12
+ function toPickerValue(params) {
13
+ const { currentValue, currentFormat, forceOpaqueHex } = params;
14
+ if (forceOpaqueHex === null) return currentValue;
15
+ if (currentFormat !== "hex") return currentValue;
16
+ if (currentValue.trim().toLowerCase() !== forceOpaqueHex) return currentValue;
17
+ return `${forceOpaqueHex}${OPAQUE_ALPHA_HEX}`;
18
+ }
19
+ function getSwatchSelectionResult(params) {
20
+ const { swatchValue, desiredFormat } = params;
21
+ const parsed = colorUtils.parseColorString(swatchValue);
22
+ if (!parsed) return {
23
+ value: swatchValue,
24
+ forceOpaqueHex: null
25
+ };
26
+ const isHexWithoutAlpha = isHexWithoutAlphaString(swatchValue);
27
+ const normalizedColor = isHexWithoutAlpha ? {
28
+ ...parsed,
29
+ a: 1
30
+ } : parsed;
31
+ if (desiredFormat === "hex" && isHexWithoutAlpha) {
32
+ const baseHex = colorUtils.colorToString(normalizedColor, "hex");
33
+ return {
34
+ value: baseHex,
35
+ forceOpaqueHex: baseHex.trim().toLowerCase()
36
+ };
37
+ }
38
+ return {
39
+ value: colorUtils.colorToString(normalizedColor, desiredFormat),
40
+ forceOpaqueHex: null
41
+ };
42
+ }
43
+
44
+ //#endregion
45
+ export { getSwatchSelectionResult, toPickerValue };
package/dist/Select.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Select } from "@pixpilot/shadcn";
2
2
  import { ComponentProps } from "react";
3
- import * as react_jsx_runtime4 from "react/jsx-runtime";
3
+ import * as react_jsx_runtime3 from "react/jsx-runtime";
4
4
 
5
5
  //#region src/Select.d.ts
6
6
  interface SelectOption {
@@ -13,6 +13,6 @@ type BaseSelectProps = {
13
13
  onChange?: (value: string) => void;
14
14
  placeholder?: string;
15
15
  } & Omit<ComponentProps<typeof Select>, 'value' | 'onValueChange' | 'children'>;
16
- declare function Select$1(props: BaseSelectProps): react_jsx_runtime4.JSX.Element;
16
+ declare function Select$1(props: BaseSelectProps): react_jsx_runtime3.JSX.Element;
17
17
  //#endregion
18
18
  export { Select$1 as Select, SelectOption };
@@ -1,5 +1,5 @@
1
1
  import { CommandOptionListItem } from "./CommandOptionList.js";
2
- import * as react_jsx_runtime3 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime4 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/tags-input.d.ts
5
5
  interface TagsInputProps {
@@ -55,6 +55,6 @@ declare function TagsInput({
55
55
  addOnPaste,
56
56
  addOnTab,
57
57
  onValidate
58
- }: TagsInputProps): react_jsx_runtime3.JSX.Element;
58
+ }: TagsInputProps): react_jsx_runtime4.JSX.Element;
59
59
  //#endregion
60
60
  export { TagsInput, TagsInputProps };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pixpilot/shadcn-ui",
3
3
  "type": "module",
4
- "version": "0.14.0",
4
+ "version": "0.15.1",
5
5
  "description": "Custom UI components and utilities built with shadcn/ui.",
6
6
  "author": "m.doaie <m.doaie@hotmail.com>",
7
7
  "license": "MIT",
@@ -44,8 +44,7 @@
44
44
  "pretty-bytes": "^7.1.0",
45
45
  "react-responsive": "^10.0.1",
46
46
  "sonner": "2.0.7",
47
- "@internal/hooks": "0.0.0",
48
- "@pixpilot/shadcn": "0.5.0"
47
+ "@pixpilot/shadcn": "0.6.1"
49
48
  },
50
49
  "devDependencies": {
51
50
  "@storybook/react": "^8.6.14",
@@ -59,6 +58,7 @@
59
58
  "tsdown": "^0.15.12",
60
59
  "typescript": "^5.9.3",
61
60
  "@internal/eslint-config": "0.3.0",
61
+ "@internal/hooks": "0.0.0",
62
62
  "@internal/prettier-config": "0.0.1",
63
63
  "@internal/tsconfig": "0.1.0",
64
64
  "@internal/tsdown-config": "0.1.0",