@webdevarif/dashui 0.3.5 → 0.3.7

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/index.mjs CHANGED
@@ -3165,7 +3165,7 @@ function PostSidebarSection({
3165
3165
  }
3166
3166
 
3167
3167
  // src/components/ui/hsl-color-input.tsx
3168
- import { useState as useState8, useEffect as useEffect6, useCallback as useCallback2 } from "react";
3168
+ import { useState as useState8, useRef as useRef5, useEffect as useEffect6, useCallback as useCallback2 } from "react";
3169
3169
  import Color2 from "color";
3170
3170
  import * as Popover2 from "@radix-ui/react-popover";
3171
3171
 
@@ -3207,6 +3207,7 @@ var ColorPicker = ({
3207
3207
  const [saturation, setSaturationState] = useState7(initial.saturationl());
3208
3208
  const [lightness, setLightnessState] = useState7(initial.lightness());
3209
3209
  const [alpha, setAlphaState] = useState7(initial.alpha() * 100);
3210
+ const [mode, setMode] = useState7("HEX");
3210
3211
  const notifyRef = useRef4(onChange);
3211
3212
  useEffect5(() => {
3212
3213
  notifyRef.current = onChange;
@@ -3231,14 +3232,18 @@ var ColorPicker = ({
3231
3232
  setAlphaState(a);
3232
3233
  notify(hue, saturation, lightness, a);
3233
3234
  }, [hue, saturation, lightness, notify]);
3234
- return /* @__PURE__ */ jsx49(ColorPickerContext.Provider, { value: { hue, saturation, lightness, alpha, setHue, setSaturation, setLightness, setAlpha }, children: /* @__PURE__ */ jsx49("div", { className: cn("flex flex-col gap-3", className), ...props, children }) });
3235
+ return /* @__PURE__ */ jsx49(ColorPickerContext.Provider, { value: { hue, saturation, lightness, alpha, setHue, setSaturation, setLightness, setAlpha, mode, setMode }, children: /* @__PURE__ */ jsx49("div", { className: cn("flex flex-col gap-3", className), ...props, children }) });
3235
3236
  };
3236
3237
  var ColorPickerSelection = memo(({ className, ...props }) => {
3237
3238
  const containerRef = useRef4(null);
3238
3239
  const [isDragging, setIsDragging] = useState7(false);
3239
- const [posX, setPosX] = useState7(0);
3240
- const [posY, setPosY] = useState7(0);
3241
- const { hue, setSaturation, setLightness } = useColorPicker();
3240
+ const { hue, saturation, lightness, setSaturation, setLightness } = useColorPicker();
3241
+ const [posX, setPosX] = useState7(() => saturation / 100);
3242
+ const [posY, setPosY] = useState7(() => {
3243
+ const x = saturation / 100;
3244
+ const topL = x < 0.01 ? 100 : 50 + 50 * (1 - x);
3245
+ return topL > 0 ? Math.max(0, Math.min(1, 1 - lightness / topL)) : 0;
3246
+ });
3242
3247
  const bg = useMemo2(
3243
3248
  () => `linear-gradient(0deg,rgba(0,0,0,1),rgba(0,0,0,0)),linear-gradient(90deg,rgba(255,255,255,1),rgba(255,255,255,0)),hsl(${hue},100%,50%)`,
3244
3249
  [hue]
@@ -3379,10 +3384,54 @@ var ColorPickerEyeDropper = ({ className, ...props }) => {
3379
3384
  }
3380
3385
  );
3381
3386
  };
3387
+ var ColorPickerOutput = ({ className, ...props }) => {
3388
+ const { mode, setMode } = useColorPicker();
3389
+ return /* @__PURE__ */ jsx49(
3390
+ "select",
3391
+ {
3392
+ value: mode,
3393
+ onChange: (e) => setMode(e.target.value),
3394
+ className: cn(
3395
+ "h-7 bg-white/5 border border-white/10 rounded-md text-xs text-white/60 px-1.5 outline-none",
3396
+ "hover:border-white/20 focus:border-white/30 cursor-pointer shrink-0",
3397
+ className
3398
+ ),
3399
+ children: ["HEX", "HSL", "RGB"].map((f) => /* @__PURE__ */ jsx49("option", { value: f, className: "bg-[#1a1c2e]", children: f }, f))
3400
+ }
3401
+ );
3402
+ };
3403
+ var ColorPickerFormat = ({ className, ...props }) => {
3404
+ const { hue, saturation, lightness, alpha, mode } = useColorPicker();
3405
+ let displayValue = "";
3406
+ try {
3407
+ const c = Color.hsl(hue, saturation, lightness).alpha(alpha / 100);
3408
+ if (mode === "HEX") displayValue = c.hex();
3409
+ else if (mode === "HSL") displayValue = `${Math.round(hue)} ${Math.round(saturation)}% ${Math.round(lightness)}%`;
3410
+ else if (mode === "RGB") {
3411
+ const rgb = c.rgb().array().map(Math.round);
3412
+ displayValue = `${rgb[0]}, ${rgb[1]}, ${rgb[2]}`;
3413
+ }
3414
+ } catch {
3415
+ displayValue = "";
3416
+ }
3417
+ return /* @__PURE__ */ jsx49(
3418
+ "input",
3419
+ {
3420
+ readOnly: true,
3421
+ type: "text",
3422
+ value: displayValue,
3423
+ className: cn(
3424
+ "flex-1 h-7 bg-white/5 border border-white/10 rounded-md px-2 text-xs text-white/50 font-mono outline-none",
3425
+ className
3426
+ ),
3427
+ ...props
3428
+ }
3429
+ );
3430
+ };
3382
3431
 
3383
3432
  // src/components/ui/hsl-color-input.tsx
3384
3433
  import { jsx as jsx50, jsxs as jsxs34 } from "react/jsx-runtime";
3385
- function hslStringToHex(hsl) {
3434
+ function hslToHex(hsl) {
3386
3435
  if (!hsl) return "#000000";
3387
3436
  try {
3388
3437
  const parts = hsl.trim().split(/\s+/);
@@ -3394,13 +3443,10 @@ function hslStringToHex(hsl) {
3394
3443
  return "#000000";
3395
3444
  }
3396
3445
  }
3397
- function hexToHslString(hex) {
3446
+ function hexToHsl(hex) {
3398
3447
  try {
3399
- const c = Color2(hex);
3400
- const h = Math.round(c.hue());
3401
- const s = Math.round(c.saturationl());
3402
- const l = Math.round(c.lightness());
3403
- return `${h} ${s}% ${l}%`;
3448
+ const c = Color2(hex.startsWith("#") ? hex : `#${hex}`);
3449
+ return `${Math.round(c.hue())} ${Math.round(c.saturationl())}% ${Math.round(c.lightness())}%`;
3404
3450
  } catch {
3405
3451
  return "0 0% 0%";
3406
3452
  }
@@ -3408,88 +3454,93 @@ function hexToHslString(hex) {
3408
3454
  function ColorReader({ onHexChange }) {
3409
3455
  const { hue, saturation, lightness, alpha } = useColorPicker();
3410
3456
  useEffect6(() => {
3411
- const hex = Color2.hsl(hue, saturation, lightness).alpha(alpha / 100).hex();
3412
- onHexChange(hex);
3457
+ try {
3458
+ const hex = Color2.hsl(hue, saturation, lightness).alpha(alpha / 100).hex();
3459
+ onHexChange(hex);
3460
+ } catch {
3461
+ }
3413
3462
  }, [hue, saturation, lightness, alpha, onHexChange]);
3414
3463
  return null;
3415
3464
  }
3416
3465
  function HslColorInput({ value, onChange, className, inputClassName, disabled }) {
3417
3466
  const [open, setOpen] = useState8(false);
3418
- const [inputVal, setInputVal] = useState8(value);
3419
- useEffect6(() => {
3420
- setInputVal(value);
3421
- }, [value]);
3422
- const hexValue = hslStringToHex(value);
3467
+ const hexValue = hslToHex(value);
3423
3468
  const cssColor = value ? `hsl(${value})` : "transparent";
3424
- const handlePickerHex = useCallback2((hex) => {
3425
- const hsl = hexToHslString(hex);
3426
- setInputVal(hsl);
3427
- onChange(hsl);
3469
+ const pendingHexRef = useRef5(hexValue);
3470
+ const onChangeRef = useRef5(onChange);
3471
+ useEffect6(() => {
3472
+ onChangeRef.current = onChange;
3428
3473
  }, [onChange]);
3429
- return /* @__PURE__ */ jsxs34("div", { className: cn("flex items-center gap-1.5", className), children: [
3430
- /* @__PURE__ */ jsxs34(Popover2.Root, { open, onOpenChange: disabled ? void 0 : setOpen, children: [
3431
- /* @__PURE__ */ jsx50(Popover2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx50(
3432
- "button",
3433
- {
3434
- type: "button",
3435
- disabled,
3436
- className: cn(
3437
- "w-5 h-5 rounded border border-white/10 shrink-0 transition-all",
3438
- "hover:scale-110 hover:border-white/30 focus:outline-none",
3439
- disabled && "opacity-50 cursor-not-allowed"
3440
- ),
3441
- style: { background: cssColor },
3442
- "aria-label": "Pick color"
3443
- }
3444
- ) }),
3445
- /* @__PURE__ */ jsx50(Popover2.Portal, { children: /* @__PURE__ */ jsx50(
3446
- Popover2.Content,
3447
- {
3448
- sideOffset: 8,
3449
- align: "start",
3450
- className: cn(
3451
- "z-[9999] rounded-xl shadow-2xl p-3 w-[220px]",
3452
- "bg-[#1a1c2e] border border-white/10",
3453
- "focus:outline-none"
3454
- ),
3455
- onInteractOutside: () => setOpen(false),
3456
- children: open && /* @__PURE__ */ jsxs34(ColorPicker, { defaultValue: hexValue, children: [
3457
- /* @__PURE__ */ jsx50(ColorReader, { onHexChange: handlePickerHex }),
3458
- /* @__PURE__ */ jsx50(ColorPickerSelection, { className: "h-36 rounded-lg" }),
3459
- /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2", children: [
3460
- /* @__PURE__ */ jsx50(ColorPickerEyeDropper, {}),
3461
- /* @__PURE__ */ jsxs34("div", { className: "flex flex-col gap-1.5 flex-1", children: [
3462
- /* @__PURE__ */ jsx50(ColorPickerHue, {}),
3463
- /* @__PURE__ */ jsx50(ColorPickerAlpha, {})
3464
- ] })
3465
- ] }),
3466
- /* @__PURE__ */ jsx50(ColorPickerHexOutput, {})
3467
- ] })
3468
- }
3469
- ) })
3470
- ] }),
3471
- /* @__PURE__ */ jsx50(
3472
- "input",
3474
+ useEffect6(() => {
3475
+ if (open) pendingHexRef.current = hexValue;
3476
+ }, [open, hexValue]);
3477
+ const handleHexChange = useCallback2((hex) => {
3478
+ pendingHexRef.current = hex;
3479
+ }, []);
3480
+ const handleOpenChange = useCallback2((newOpen) => {
3481
+ if (!newOpen && open) {
3482
+ const pending = pendingHexRef.current;
3483
+ if (pending && pending !== hexValue) {
3484
+ onChangeRef.current(hexToHsl(pending));
3485
+ }
3486
+ }
3487
+ setOpen(newOpen);
3488
+ }, [open, hexValue]);
3489
+ return /* @__PURE__ */ jsxs34(Popover2.Root, { open, onOpenChange: disabled ? void 0 : handleOpenChange, children: [
3490
+ /* @__PURE__ */ jsx50(Popover2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs34(
3491
+ "button",
3473
3492
  {
3474
- type: "text",
3475
- value: inputVal,
3476
- onChange: (e) => {
3477
- setInputVal(e.target.value);
3478
- if (/^\d+(\.\d+)?\s+\d+(\.\d+)?%\s+\d+(\.\d+)?%$/.test(e.target.value.trim())) {
3479
- onChange(e.target.value.trim());
3480
- }
3481
- },
3482
- onBlur: () => setInputVal(value),
3493
+ type: "button",
3483
3494
  disabled,
3484
- placeholder: "H S% L%",
3485
3495
  className: cn(
3486
- "w-28 bg-white/5 border border-white/10 rounded px-1.5 py-0.5",
3487
- "text-xs text-white/70 font-mono outline-none focus:border-white/30",
3488
- "placeholder:text-white/20 disabled:opacity-50",
3489
- inputClassName
3490
- )
3496
+ "flex items-center gap-2 px-2 py-1 rounded-lg border border-white/10",
3497
+ "bg-white/5 hover:border-white/20 hover:bg-white/[0.08] transition-colors",
3498
+ "text-xs text-white/60 font-mono min-w-[7.5rem] justify-start",
3499
+ "focus:outline-none focus:border-white/30",
3500
+ disabled && "opacity-50 cursor-not-allowed",
3501
+ className
3502
+ ),
3503
+ "aria-label": "Pick color",
3504
+ children: [
3505
+ /* @__PURE__ */ jsx50(
3506
+ "span",
3507
+ {
3508
+ className: "w-4 h-4 rounded-full border border-white/20 shrink-0 inline-block",
3509
+ style: { background: cssColor }
3510
+ }
3511
+ ),
3512
+ /* @__PURE__ */ jsx50("span", { children: hexValue.toUpperCase() })
3513
+ ]
3491
3514
  }
3492
- )
3515
+ ) }),
3516
+ /* @__PURE__ */ jsx50(Popover2.Portal, { children: /* @__PURE__ */ jsx50(
3517
+ Popover2.Content,
3518
+ {
3519
+ sideOffset: 6,
3520
+ align: "start",
3521
+ className: cn(
3522
+ "z-[9999] rounded-xl shadow-2xl p-3 w-[14rem]",
3523
+ "bg-[#0f1117] border border-white/10",
3524
+ "focus:outline-none"
3525
+ ),
3526
+ onInteractOutside: () => handleOpenChange(false),
3527
+ children: open && /* @__PURE__ */ jsxs34(ColorPicker, { defaultValue: hexValue, className: "gap-2.5", children: [
3528
+ /* @__PURE__ */ jsx50(ColorReader, { onHexChange: handleHexChange }),
3529
+ /* @__PURE__ */ jsx50(ColorPickerSelection, { className: "h-32 w-full rounded-lg" }),
3530
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-3", children: [
3531
+ /* @__PURE__ */ jsx50(ColorPickerEyeDropper, {}),
3532
+ /* @__PURE__ */ jsxs34("div", { className: "flex flex-col gap-1.5 flex-1", children: [
3533
+ /* @__PURE__ */ jsx50(ColorPickerHue, {}),
3534
+ /* @__PURE__ */ jsx50(ColorPickerAlpha, {})
3535
+ ] })
3536
+ ] }),
3537
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-1.5", children: [
3538
+ /* @__PURE__ */ jsx50(ColorPickerOutput, {}),
3539
+ /* @__PURE__ */ jsx50(ColorPickerFormat, {})
3540
+ ] })
3541
+ ] }, hexValue)
3542
+ }
3543
+ ) })
3493
3544
  ] });
3494
3545
  }
3495
3546
 
@@ -3856,8 +3907,10 @@ export {
3856
3907
  ColorPicker,
3857
3908
  ColorPickerAlpha,
3858
3909
  ColorPickerEyeDropper,
3910
+ ColorPickerFormat,
3859
3911
  ColorPickerHexOutput,
3860
3912
  ColorPickerHue,
3913
+ ColorPickerOutput,
3861
3914
  ColorPickerSelection,
3862
3915
  ConfirmDialog,
3863
3916
  DashboardLayout,