@webdevarif/dashui 0.3.4 → 0.3.6

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,137 +3165,385 @@ function PostSidebarSection({
3165
3165
  }
3166
3166
 
3167
3167
  // src/components/ui/hsl-color-input.tsx
3168
- import { useState as useState7, useRef as useRef4, useEffect as useEffect5, useCallback } from "react";
3169
- import { createPortal } from "react-dom";
3170
- import { HslColorPicker } from "react-colorful";
3168
+ import { useState as useState8, useRef as useRef5, useEffect as useEffect6, useCallback as useCallback2 } from "react";
3169
+ import Color2 from "color";
3170
+ import * as Popover2 from "@radix-ui/react-popover";
3171
+
3172
+ // src/components/ui/color-picker.tsx
3173
+ import Color from "color";
3174
+ import {
3175
+ createContext,
3176
+ memo,
3177
+ useCallback,
3178
+ useContext,
3179
+ useEffect as useEffect5,
3180
+ useMemo as useMemo2,
3181
+ useRef as useRef4,
3182
+ useState as useState7
3183
+ } from "react";
3184
+ import * as Slider from "@radix-ui/react-slider";
3171
3185
  import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
3172
- function parseHsl(value) {
3173
- if (!value) return { h: 0, s: 0, l: 0 };
3174
- const parts = value.trim().split(/\s+/);
3175
- return {
3176
- h: parseFloat(parts[0]) || 0,
3177
- s: parseFloat(parts[1]) || 0,
3178
- l: parseFloat(parts[2]) || 0
3179
- };
3180
- }
3181
- function formatHsl(c) {
3182
- return `${Math.round(c.h)} ${Math.round(c.s)}% ${Math.round(c.l)}%`;
3183
- }
3184
- function HslColorInput({ value, onChange, className, inputClassName, disabled }) {
3185
- const [open, setOpen] = useState7(false);
3186
- const [pos, setPos] = useState7({ top: 0, left: 0 });
3187
- const [inputVal, setInputVal] = useState7(value);
3188
- const [mounted, setMounted] = useState7(false);
3189
- const triggerRef = useRef4(null);
3190
- const pickerRef = useRef4(null);
3191
- useEffect5(() => {
3192
- setMounted(true);
3193
- }, []);
3186
+ var ColorPickerContext = createContext(void 0);
3187
+ var useColorPicker = () => {
3188
+ const ctx = useContext(ColorPickerContext);
3189
+ if (!ctx) throw new Error("useColorPicker must be used within ColorPicker");
3190
+ return ctx;
3191
+ };
3192
+ var ColorPicker = ({
3193
+ defaultValue = "#000000",
3194
+ onChange,
3195
+ className,
3196
+ children,
3197
+ ...props
3198
+ }) => {
3199
+ const initial = (() => {
3200
+ try {
3201
+ return Color(defaultValue);
3202
+ } catch {
3203
+ return Color("#000000");
3204
+ }
3205
+ })();
3206
+ const [hue, setHueState] = useState7(initial.hue());
3207
+ const [saturation, setSaturationState] = useState7(initial.saturationl());
3208
+ const [lightness, setLightnessState] = useState7(initial.lightness());
3209
+ const [alpha, setAlphaState] = useState7(initial.alpha() * 100);
3210
+ const [mode, setMode] = useState7("HEX");
3211
+ const notifyRef = useRef4(onChange);
3194
3212
  useEffect5(() => {
3195
- setInputVal(value);
3196
- }, [value]);
3197
- const openPicker = useCallback(() => {
3198
- const rect = triggerRef.current?.getBoundingClientRect();
3199
- if (!rect) return;
3200
- const pickerW = 228;
3201
- let left = rect.left;
3202
- if (left + pickerW > window.innerWidth - 8) left = window.innerWidth - pickerW - 8;
3203
- setPos({ top: rect.bottom + 6, left: Math.max(8, left) });
3204
- setOpen(true);
3213
+ notifyRef.current = onChange;
3214
+ }, [onChange]);
3215
+ const notify = useCallback((h, s, l, a) => {
3216
+ const hex = Color.hsl(h, s, l).alpha(a / 100).hexa();
3217
+ notifyRef.current?.(hex);
3205
3218
  }, []);
3219
+ const setHue = useCallback((h) => {
3220
+ setHueState(h);
3221
+ notify(h, saturation, lightness, alpha);
3222
+ }, [saturation, lightness, alpha, notify]);
3223
+ const setSaturation = useCallback((s) => {
3224
+ setSaturationState(s);
3225
+ notify(hue, s, lightness, alpha);
3226
+ }, [hue, lightness, alpha, notify]);
3227
+ const setLightness = useCallback((l) => {
3228
+ setLightnessState(l);
3229
+ notify(hue, saturation, l, alpha);
3230
+ }, [hue, saturation, alpha, notify]);
3231
+ const setAlpha = useCallback((a) => {
3232
+ setAlphaState(a);
3233
+ notify(hue, saturation, lightness, a);
3234
+ }, [hue, saturation, lightness, notify]);
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 }) });
3236
+ };
3237
+ var ColorPickerSelection = memo(({ className, ...props }) => {
3238
+ const containerRef = useRef4(null);
3239
+ const [isDragging, setIsDragging] = useState7(false);
3240
+ const [posX, setPosX] = useState7(0);
3241
+ const [posY, setPosY] = useState7(0);
3242
+ const { hue, setSaturation, setLightness } = useColorPicker();
3243
+ const bg = useMemo2(
3244
+ () => `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%)`,
3245
+ [hue]
3246
+ );
3247
+ const handleMove = useCallback((e) => {
3248
+ if (!isDragging || !containerRef.current) return;
3249
+ const rect = containerRef.current.getBoundingClientRect();
3250
+ const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
3251
+ const y = Math.max(0, Math.min(1, (e.clientY - rect.top) / rect.height));
3252
+ setPosX(x);
3253
+ setPosY(y);
3254
+ setSaturation(x * 100);
3255
+ const topL = x < 0.01 ? 100 : 50 + 50 * (1 - x);
3256
+ setLightness(topL * (1 - y));
3257
+ }, [isDragging, setSaturation, setLightness]);
3206
3258
  useEffect5(() => {
3207
- if (!open) return;
3208
- const handler = (e) => {
3209
- const target = e.target;
3210
- if (pickerRef.current?.contains(target)) return;
3211
- if (triggerRef.current?.contains(target)) return;
3212
- setOpen(false);
3259
+ if (!isDragging) return;
3260
+ const up = () => setIsDragging(false);
3261
+ window.addEventListener("pointermove", handleMove);
3262
+ window.addEventListener("pointerup", up);
3263
+ return () => {
3264
+ window.removeEventListener("pointermove", handleMove);
3265
+ window.removeEventListener("pointerup", up);
3213
3266
  };
3214
- document.addEventListener("pointerdown", handler, true);
3215
- return () => document.removeEventListener("pointerdown", handler, true);
3216
- }, [open]);
3217
- const cssColor = value ? `hsl(${value})` : "transparent";
3218
- const picker = /* @__PURE__ */ jsxs33(
3267
+ }, [isDragging, handleMove]);
3268
+ return /* @__PURE__ */ jsx49(
3219
3269
  "div",
3220
3270
  {
3221
- ref: pickerRef,
3222
- style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 9999 },
3223
- className: "bg-[#1a1c2e] border border-white/10 rounded-xl shadow-2xl p-3 flex flex-col gap-3",
3224
- onPointerDown: (e) => e.stopPropagation(),
3271
+ ref: containerRef,
3272
+ className: cn("relative w-full cursor-crosshair rounded-lg", className),
3273
+ style: { background: bg },
3274
+ onPointerDown: (e) => {
3275
+ e.preventDefault();
3276
+ setIsDragging(true);
3277
+ handleMove(e.nativeEvent);
3278
+ },
3279
+ ...props,
3280
+ children: /* @__PURE__ */ jsx49(
3281
+ "div",
3282
+ {
3283
+ className: "pointer-events-none absolute h-4 w-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white",
3284
+ style: {
3285
+ left: `${posX * 100}%`,
3286
+ top: `${posY * 100}%`,
3287
+ boxShadow: "0 0 0 1px rgba(0,0,0,0.6)"
3288
+ }
3289
+ }
3290
+ )
3291
+ }
3292
+ );
3293
+ });
3294
+ ColorPickerSelection.displayName = "ColorPickerSelection";
3295
+ var ColorPickerHue = ({ className, ...props }) => {
3296
+ const { hue, setHue } = useColorPicker();
3297
+ return /* @__PURE__ */ jsxs33(
3298
+ Slider.Root,
3299
+ {
3300
+ className: cn("relative flex h-4 w-full touch-none items-center", className),
3301
+ max: 360,
3302
+ step: 1,
3303
+ value: [hue],
3304
+ onValueChange: ([h]) => setHue(h),
3305
+ ...props,
3306
+ children: [
3307
+ /* @__PURE__ */ jsx49(Slider.Track, { className: "relative h-3 w-full grow rounded-full bg-[linear-gradient(90deg,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)]", children: /* @__PURE__ */ jsx49(Slider.Range, { className: "absolute h-full" }) }),
3308
+ /* @__PURE__ */ jsx49(Slider.Thumb, { className: "block h-4 w-4 rounded-full border-2 border-white shadow-md focus:outline-none", style: { boxShadow: "0 0 0 1px rgba(0,0,0,0.4)" } })
3309
+ ]
3310
+ }
3311
+ );
3312
+ };
3313
+ var ColorPickerAlpha = ({ className, ...props }) => {
3314
+ const { alpha, setAlpha, hue, saturation, lightness } = useColorPicker();
3315
+ const solidColor = `hsl(${hue},${saturation}%,${lightness}%)`;
3316
+ return /* @__PURE__ */ jsxs33(
3317
+ Slider.Root,
3318
+ {
3319
+ className: cn("relative flex h-4 w-full touch-none items-center", className),
3320
+ max: 100,
3321
+ step: 1,
3322
+ value: [alpha],
3323
+ onValueChange: ([a]) => setAlpha(a),
3324
+ ...props,
3225
3325
  children: [
3226
3326
  /* @__PURE__ */ jsx49(
3227
- HslColorPicker,
3327
+ Slider.Track,
3228
3328
  {
3229
- color: parseHsl(value),
3230
- onChange: (c) => {
3231
- const formatted = formatHsl(c);
3232
- setInputVal(formatted);
3233
- onChange(formatted);
3234
- }
3329
+ className: "relative h-3 w-full grow rounded-full",
3330
+ style: {
3331
+ backgroundImage: `linear-gradient(90deg, transparent, ${solidColor}), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==")`
3332
+ },
3333
+ children: /* @__PURE__ */ jsx49(Slider.Range, { className: "absolute h-full" })
3235
3334
  }
3236
3335
  ),
3237
- /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-2 px-1", children: [
3238
- /* @__PURE__ */ jsx49("div", { className: "w-5 h-5 rounded border border-white/10 shrink-0", style: { background: cssColor } }),
3239
- /* @__PURE__ */ jsx49("span", { className: "text-xs font-mono text-white/40 flex-1 truncate", children: value || "none" }),
3240
- /* @__PURE__ */ jsx49(
3241
- "button",
3242
- {
3243
- onClick: () => setOpen(false),
3244
- className: "text-white/30 hover:text-white/70 text-xs px-1.5 py-0.5 rounded hover:bg-white/5 transition-colors",
3245
- children: "Done"
3246
- }
3247
- )
3248
- ] })
3336
+ /* @__PURE__ */ jsx49(Slider.Thumb, { className: "block h-4 w-4 rounded-full border-2 border-white shadow-md focus:outline-none", style: { boxShadow: "0 0 0 1px rgba(0,0,0,0.4)" } })
3249
3337
  ]
3250
3338
  }
3251
3339
  );
3252
- return /* @__PURE__ */ jsxs33("div", { className: cn("flex items-center gap-1.5", className), children: [
3253
- /* @__PURE__ */ jsx49(
3340
+ };
3341
+ var ColorPickerHexOutput = ({ className, ...props }) => {
3342
+ const { hue, saturation, lightness, alpha } = useColorPicker();
3343
+ const hex = Color.hsl(hue, saturation, lightness).alpha(alpha / 100).hex();
3344
+ return /* @__PURE__ */ jsxs33("div", { className: cn("flex items-center gap-1.5 px-1", className), ...props, children: [
3345
+ /* @__PURE__ */ jsx49("div", { className: "w-5 h-5 rounded border border-white/20 shrink-0", style: { background: `hsl(${hue},${saturation}%,${lightness}%)` } }),
3346
+ /* @__PURE__ */ jsx49("span", { className: "text-xs font-mono text-white/50 flex-1", children: hex })
3347
+ ] });
3348
+ };
3349
+ var ColorPickerEyeDropper = ({ className, ...props }) => {
3350
+ const { setHue, setSaturation, setLightness, setAlpha } = useColorPicker();
3351
+ const pick = async () => {
3352
+ try {
3353
+ const result = await new EyeDropper().open();
3354
+ const c = Color(result.sRGBHex);
3355
+ setHue(c.hue());
3356
+ setSaturation(c.saturationl());
3357
+ setLightness(c.lightness());
3358
+ setAlpha(100);
3359
+ } catch {
3360
+ }
3361
+ };
3362
+ return /* @__PURE__ */ jsx49(
3363
+ "button",
3364
+ {
3365
+ type: "button",
3366
+ onClick: pick,
3367
+ title: "Eye dropper",
3368
+ className: cn(
3369
+ "w-7 h-7 flex items-center justify-center rounded-md",
3370
+ "border border-white/10 text-white/40 hover:text-white/70 hover:border-white/25",
3371
+ "transition-colors shrink-0",
3372
+ className
3373
+ ),
3374
+ ...props,
3375
+ children: /* @__PURE__ */ jsxs33("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
3376
+ /* @__PURE__ */ jsx49("path", { d: "M9.53 16.122a3 3 0 0 0-5.78 1.128 2.25 2.25 0 0 1-2.4 2.245 4.5 4.5 0 0 0 8.4-2.245c0-.399-.078-.78-.22-1.128Z" }),
3377
+ /* @__PURE__ */ jsx49("path", { d: "m13.5 10.5 2.25-2.25m0 0 2.25-2.25M15.75 8.25l2.25 2.25M15.75 8.25 13.5 6m4.5-1.5 1.5-1.5" }),
3378
+ /* @__PURE__ */ jsx49("path", { d: "M6.75 7.5 10.5 4.5c.5-.375 1.25-.375 1.5 0l6.75 6.75c.375.5.375 1.25 0 1.5L15 16.5" })
3379
+ ] })
3380
+ }
3381
+ );
3382
+ };
3383
+ var ColorPickerOutput = ({ className, ...props }) => {
3384
+ const { mode, setMode } = useColorPicker();
3385
+ return /* @__PURE__ */ jsx49(
3386
+ "select",
3387
+ {
3388
+ value: mode,
3389
+ onChange: (e) => setMode(e.target.value),
3390
+ className: cn(
3391
+ "h-7 bg-white/5 border border-white/10 rounded-md text-xs text-white/60 px-1.5 outline-none",
3392
+ "hover:border-white/20 focus:border-white/30 cursor-pointer shrink-0",
3393
+ className
3394
+ ),
3395
+ children: ["HEX", "HSL", "RGB"].map((f) => /* @__PURE__ */ jsx49("option", { value: f, className: "bg-[#1a1c2e]", children: f }, f))
3396
+ }
3397
+ );
3398
+ };
3399
+ var ColorPickerFormat = ({ className, ...props }) => {
3400
+ const { hue, saturation, lightness, alpha, mode } = useColorPicker();
3401
+ let displayValue = "";
3402
+ try {
3403
+ const c = Color.hsl(hue, saturation, lightness).alpha(alpha / 100);
3404
+ if (mode === "HEX") displayValue = c.hex();
3405
+ else if (mode === "HSL") displayValue = `${Math.round(hue)} ${Math.round(saturation)}% ${Math.round(lightness)}%`;
3406
+ else if (mode === "RGB") {
3407
+ const rgb = c.rgb().array().map(Math.round);
3408
+ displayValue = `${rgb[0]}, ${rgb[1]}, ${rgb[2]}`;
3409
+ }
3410
+ } catch {
3411
+ displayValue = "";
3412
+ }
3413
+ return /* @__PURE__ */ jsx49(
3414
+ "input",
3415
+ {
3416
+ readOnly: true,
3417
+ type: "text",
3418
+ value: displayValue,
3419
+ className: cn(
3420
+ "flex-1 h-7 bg-white/5 border border-white/10 rounded-md px-2 text-xs text-white/50 font-mono outline-none",
3421
+ className
3422
+ ),
3423
+ ...props
3424
+ }
3425
+ );
3426
+ };
3427
+
3428
+ // src/components/ui/hsl-color-input.tsx
3429
+ import { jsx as jsx50, jsxs as jsxs34 } from "react/jsx-runtime";
3430
+ function hslToHex(hsl) {
3431
+ if (!hsl) return "#000000";
3432
+ try {
3433
+ const parts = hsl.trim().split(/\s+/);
3434
+ const h = parseFloat(parts[0]) || 0;
3435
+ const s = parseFloat(parts[1]) || 0;
3436
+ const l = parseFloat(parts[2]) || 0;
3437
+ return Color2.hsl(h, s, l).hex();
3438
+ } catch {
3439
+ return "#000000";
3440
+ }
3441
+ }
3442
+ function hexToHsl(hex) {
3443
+ try {
3444
+ const c = Color2(hex.startsWith("#") ? hex : `#${hex}`);
3445
+ return `${Math.round(c.hue())} ${Math.round(c.saturationl())}% ${Math.round(c.lightness())}%`;
3446
+ } catch {
3447
+ return "0 0% 0%";
3448
+ }
3449
+ }
3450
+ function ColorReader({ onHexChange }) {
3451
+ const { hue, saturation, lightness, alpha } = useColorPicker();
3452
+ useEffect6(() => {
3453
+ try {
3454
+ const hex = Color2.hsl(hue, saturation, lightness).alpha(alpha / 100).hex();
3455
+ onHexChange(hex);
3456
+ } catch {
3457
+ }
3458
+ }, [hue, saturation, lightness, alpha, onHexChange]);
3459
+ return null;
3460
+ }
3461
+ function HslColorInput({ value, onChange, className, inputClassName, disabled }) {
3462
+ const [open, setOpen] = useState8(false);
3463
+ const hexValue = hslToHex(value);
3464
+ const cssColor = value ? `hsl(${value})` : "transparent";
3465
+ const pendingHexRef = useRef5(hexValue);
3466
+ const onChangeRef = useRef5(onChange);
3467
+ useEffect6(() => {
3468
+ onChangeRef.current = onChange;
3469
+ }, [onChange]);
3470
+ useEffect6(() => {
3471
+ if (open) pendingHexRef.current = hexValue;
3472
+ }, [open, hexValue]);
3473
+ const handleHexChange = useCallback2((hex) => {
3474
+ pendingHexRef.current = hex;
3475
+ }, []);
3476
+ const handleOpenChange = useCallback2((newOpen) => {
3477
+ if (!newOpen && open) {
3478
+ const pending = pendingHexRef.current;
3479
+ if (pending && pending !== hexValue) {
3480
+ onChangeRef.current(hexToHsl(pending));
3481
+ }
3482
+ }
3483
+ setOpen(newOpen);
3484
+ }, [open, hexValue]);
3485
+ return /* @__PURE__ */ jsxs34(Popover2.Root, { open, onOpenChange: disabled ? void 0 : handleOpenChange, children: [
3486
+ /* @__PURE__ */ jsx50(Popover2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs34(
3254
3487
  "button",
3255
3488
  {
3256
- ref: triggerRef,
3257
3489
  type: "button",
3258
3490
  disabled,
3259
- onClick: () => open ? setOpen(false) : openPicker(),
3260
3491
  className: cn(
3261
- "w-5 h-5 rounded border border-white/10 shrink-0 transition-all",
3262
- "hover:scale-110 hover:border-white/30 focus:outline-none",
3263
- disabled && "opacity-50 cursor-not-allowed"
3492
+ "flex items-center gap-2 px-2 py-1 rounded-lg border border-white/10",
3493
+ "bg-white/5 hover:border-white/20 hover:bg-white/[0.08] transition-colors",
3494
+ "text-xs text-white/60 font-mono min-w-[7.5rem] justify-start",
3495
+ "focus:outline-none focus:border-white/30",
3496
+ disabled && "opacity-50 cursor-not-allowed",
3497
+ className
3264
3498
  ),
3265
- style: { background: cssColor },
3266
- "aria-label": "Pick color"
3499
+ "aria-label": "Pick color",
3500
+ children: [
3501
+ /* @__PURE__ */ jsx50(
3502
+ "span",
3503
+ {
3504
+ className: "w-4 h-4 rounded-full border border-white/20 shrink-0 inline-block",
3505
+ style: { background: cssColor }
3506
+ }
3507
+ ),
3508
+ /* @__PURE__ */ jsx50("span", { children: hexValue.toUpperCase() })
3509
+ ]
3267
3510
  }
3268
- ),
3269
- /* @__PURE__ */ jsx49(
3270
- "input",
3511
+ ) }),
3512
+ /* @__PURE__ */ jsx50(Popover2.Portal, { children: /* @__PURE__ */ jsx50(
3513
+ Popover2.Content,
3271
3514
  {
3272
- type: "text",
3273
- value: inputVal,
3274
- onChange: (e) => {
3275
- setInputVal(e.target.value);
3276
- if (/^\d+(\.\d+)?\s+\d+(\.\d+)?%\s+\d+(\.\d+)?%$/.test(e.target.value.trim())) {
3277
- onChange(e.target.value.trim());
3278
- }
3279
- },
3280
- onBlur: () => setInputVal(value),
3281
- disabled,
3282
- placeholder: "H S% L%",
3515
+ sideOffset: 6,
3516
+ align: "start",
3283
3517
  className: cn(
3284
- "w-28 bg-white/5 border border-white/10 rounded px-1.5 py-0.5",
3285
- "text-xs text-white/70 font-mono outline-none focus:border-white/30",
3286
- "placeholder:text-white/20 disabled:opacity-50",
3287
- inputClassName
3288
- )
3518
+ "z-[9999] rounded-xl shadow-2xl p-3 w-[14rem]",
3519
+ "bg-[#0f1117] border border-white/10",
3520
+ "focus:outline-none"
3521
+ ),
3522
+ onInteractOutside: () => handleOpenChange(false),
3523
+ children: open && /* @__PURE__ */ jsxs34(ColorPicker, { defaultValue: hexValue, className: "gap-2.5", children: [
3524
+ /* @__PURE__ */ jsx50(ColorReader, { onHexChange: handleHexChange }),
3525
+ /* @__PURE__ */ jsx50(ColorPickerSelection, { className: "h-32 w-full rounded-lg" }),
3526
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-3", children: [
3527
+ /* @__PURE__ */ jsx50(ColorPickerEyeDropper, {}),
3528
+ /* @__PURE__ */ jsxs34("div", { className: "flex flex-col gap-1.5 flex-1", children: [
3529
+ /* @__PURE__ */ jsx50(ColorPickerHue, {}),
3530
+ /* @__PURE__ */ jsx50(ColorPickerAlpha, {})
3531
+ ] })
3532
+ ] }),
3533
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-1.5", children: [
3534
+ /* @__PURE__ */ jsx50(ColorPickerOutput, {}),
3535
+ /* @__PURE__ */ jsx50(ColorPickerFormat, {})
3536
+ ] })
3537
+ ] }, hexValue)
3289
3538
  }
3290
- ),
3291
- mounted && open && createPortal(picker, document.body)
3539
+ ) })
3292
3540
  ] });
3293
3541
  }
3294
3542
 
3295
3543
  // src/hooks/index.ts
3296
- import { useState as useState8 } from "react";
3544
+ import { useState as useState9 } from "react";
3297
3545
  function useDisclosure(initial = false) {
3298
- const [isOpen, setIsOpen] = useState8(initial);
3546
+ const [isOpen, setIsOpen] = useState9(initial);
3299
3547
  return {
3300
3548
  isOpen,
3301
3549
  open: () => setIsOpen(true),
@@ -3305,15 +3553,15 @@ function useDisclosure(initial = false) {
3305
3553
  };
3306
3554
  }
3307
3555
  function usePagination(total, pageSize = 20) {
3308
- const [page, setPage] = useState8(1);
3556
+ const [page, setPage] = useState9(1);
3309
3557
  const totalPages = Math.ceil(total / pageSize);
3310
3558
  return { page, setPage, pageSize, total, totalPages };
3311
3559
  }
3312
3560
 
3313
3561
  // src/components/auth/AuthShell.tsx
3314
- import { jsx as jsx50, jsxs as jsxs34 } from "react/jsx-runtime";
3562
+ import { jsx as jsx51, jsxs as jsxs35 } from "react/jsx-runtime";
3315
3563
  function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
3316
- return /* @__PURE__ */ jsxs34(
3564
+ return /* @__PURE__ */ jsxs35(
3317
3565
  "div",
3318
3566
  {
3319
3567
  style: {
@@ -3328,7 +3576,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
3328
3576
  overflow: "hidden"
3329
3577
  },
3330
3578
  children: [
3331
- pattern === "dots" && /* @__PURE__ */ jsx50(
3579
+ pattern === "dots" && /* @__PURE__ */ jsx51(
3332
3580
  "div",
3333
3581
  {
3334
3582
  "aria-hidden": true,
@@ -3342,7 +3590,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
3342
3590
  }
3343
3591
  }
3344
3592
  ),
3345
- pattern === "grid" && /* @__PURE__ */ jsx50(
3593
+ pattern === "grid" && /* @__PURE__ */ jsx51(
3346
3594
  "div",
3347
3595
  {
3348
3596
  "aria-hidden": true,
@@ -3356,16 +3604,16 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
3356
3604
  }
3357
3605
  }
3358
3606
  ),
3359
- /* @__PURE__ */ jsx50("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
3607
+ /* @__PURE__ */ jsx51("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
3360
3608
  ]
3361
3609
  }
3362
3610
  );
3363
3611
  }
3364
3612
 
3365
3613
  // src/components/auth/AuthCard.tsx
3366
- import { jsx as jsx51 } from "react/jsx-runtime";
3614
+ import { jsx as jsx52 } from "react/jsx-runtime";
3367
3615
  function AuthCard({ children, padding = "24px 28px" }) {
3368
- return /* @__PURE__ */ jsx51(
3616
+ return /* @__PURE__ */ jsx52(
3369
3617
  "div",
3370
3618
  {
3371
3619
  style: {
@@ -3382,10 +3630,10 @@ function AuthCard({ children, padding = "24px 28px" }) {
3382
3630
  }
3383
3631
 
3384
3632
  // src/components/auth/AuthLogo.tsx
3385
- import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
3633
+ import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
3386
3634
  function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }) {
3387
- return /* @__PURE__ */ jsxs35("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
3388
- imageUrl ? /* @__PURE__ */ jsx52(
3635
+ return /* @__PURE__ */ jsxs36("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
3636
+ imageUrl ? /* @__PURE__ */ jsx53(
3389
3637
  "img",
3390
3638
  {
3391
3639
  src: imageUrl,
@@ -3394,7 +3642,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
3394
3642
  height: size,
3395
3643
  style: { borderRadius: "calc(var(--radius, 0.5rem) * 1.2)", flexShrink: 0, display: "block" }
3396
3644
  }
3397
- ) : /* @__PURE__ */ jsx52(
3645
+ ) : /* @__PURE__ */ jsx53(
3398
3646
  "div",
3399
3647
  {
3400
3648
  style: {
@@ -3413,7 +3661,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
3413
3661
  children: letter
3414
3662
  }
3415
3663
  ),
3416
- /* @__PURE__ */ jsx52(
3664
+ /* @__PURE__ */ jsx53(
3417
3665
  "span",
3418
3666
  {
3419
3667
  style: {
@@ -3429,10 +3677,10 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
3429
3677
  }
3430
3678
 
3431
3679
  // src/components/auth/AuthHeader.tsx
3432
- import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
3680
+ import { jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
3433
3681
  function AuthHeader({ title, description }) {
3434
- return /* @__PURE__ */ jsxs36("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
3435
- /* @__PURE__ */ jsx53(
3682
+ return /* @__PURE__ */ jsxs37("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
3683
+ /* @__PURE__ */ jsx54(
3436
3684
  "h1",
3437
3685
  {
3438
3686
  style: {
@@ -3445,7 +3693,7 @@ function AuthHeader({ title, description }) {
3445
3693
  children: title
3446
3694
  }
3447
3695
  ),
3448
- description && /* @__PURE__ */ jsx53(
3696
+ description && /* @__PURE__ */ jsx54(
3449
3697
  "p",
3450
3698
  {
3451
3699
  style: {
@@ -3461,12 +3709,12 @@ function AuthHeader({ title, description }) {
3461
3709
  }
3462
3710
 
3463
3711
  // src/components/auth/AuthField.tsx
3464
- import { jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
3712
+ import { jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
3465
3713
  function AuthField({ label, error, hint, rightLabel, id, ...props }) {
3466
3714
  const fieldId = id ?? label.toLowerCase().replace(/\s+/g, "-");
3467
- return /* @__PURE__ */ jsxs37("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
3468
- /* @__PURE__ */ jsxs37("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
3469
- /* @__PURE__ */ jsx54(
3715
+ return /* @__PURE__ */ jsxs38("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
3716
+ /* @__PURE__ */ jsxs38("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
3717
+ /* @__PURE__ */ jsx55(
3470
3718
  "label",
3471
3719
  {
3472
3720
  htmlFor: fieldId,
@@ -3478,9 +3726,9 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
3478
3726
  children: label
3479
3727
  }
3480
3728
  ),
3481
- rightLabel && /* @__PURE__ */ jsx54("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
3729
+ rightLabel && /* @__PURE__ */ jsx55("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
3482
3730
  ] }),
3483
- /* @__PURE__ */ jsx54(
3731
+ /* @__PURE__ */ jsx55(
3484
3732
  "input",
3485
3733
  {
3486
3734
  id: fieldId,
@@ -3510,13 +3758,13 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
3510
3758
  ...props
3511
3759
  }
3512
3760
  ),
3513
- error && /* @__PURE__ */ jsx54("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
3514
- hint && !error && /* @__PURE__ */ jsx54("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
3761
+ error && /* @__PURE__ */ jsx55("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
3762
+ hint && !error && /* @__PURE__ */ jsx55("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
3515
3763
  ] });
3516
3764
  }
3517
3765
 
3518
3766
  // src/components/auth/AuthButton.tsx
3519
- import { Fragment as Fragment5, jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
3767
+ import { Fragment as Fragment5, jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
3520
3768
  function AuthButton({
3521
3769
  loading,
3522
3770
  variant = "primary",
@@ -3559,7 +3807,7 @@ function AuthButton({
3559
3807
  color: "var(--foreground)"
3560
3808
  }
3561
3809
  };
3562
- return /* @__PURE__ */ jsx55(
3810
+ return /* @__PURE__ */ jsx56(
3563
3811
  "button",
3564
3812
  {
3565
3813
  disabled: loading || disabled,
@@ -3571,8 +3819,8 @@ function AuthButton({
3571
3819
  e.currentTarget.style.filter = "none";
3572
3820
  },
3573
3821
  ...props,
3574
- children: loading ? /* @__PURE__ */ jsxs38(Fragment5, { children: [
3575
- /* @__PURE__ */ jsx55(
3822
+ children: loading ? /* @__PURE__ */ jsxs39(Fragment5, { children: [
3823
+ /* @__PURE__ */ jsx56(
3576
3824
  "span",
3577
3825
  {
3578
3826
  style: {
@@ -3593,19 +3841,19 @@ function AuthButton({
3593
3841
  }
3594
3842
 
3595
3843
  // src/components/auth/AuthDivider.tsx
3596
- import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
3844
+ import { jsx as jsx57, jsxs as jsxs40 } from "react/jsx-runtime";
3597
3845
  function AuthDivider({ label = "or" }) {
3598
- return /* @__PURE__ */ jsxs39("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
3599
- /* @__PURE__ */ jsx56("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
3600
- /* @__PURE__ */ jsx56("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
3601
- /* @__PURE__ */ jsx56("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
3846
+ return /* @__PURE__ */ jsxs40("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
3847
+ /* @__PURE__ */ jsx57("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
3848
+ /* @__PURE__ */ jsx57("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
3849
+ /* @__PURE__ */ jsx57("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
3602
3850
  ] });
3603
3851
  }
3604
3852
 
3605
3853
  // src/components/auth/AuthFootnote.tsx
3606
- import { jsx as jsx57, jsxs as jsxs40 } from "react/jsx-runtime";
3854
+ import { jsx as jsx58, jsxs as jsxs41 } from "react/jsx-runtime";
3607
3855
  function AuthFootnote({ text, linkText, linkHref }) {
3608
- return /* @__PURE__ */ jsxs40("p", { style: {
3856
+ return /* @__PURE__ */ jsxs41("p", { style: {
3609
3857
  textAlign: "center",
3610
3858
  marginTop: "20px",
3611
3859
  fontSize: "0.8125rem",
@@ -3613,7 +3861,7 @@ function AuthFootnote({ text, linkText, linkHref }) {
3613
3861
  }, children: [
3614
3862
  text,
3615
3863
  " ",
3616
- /* @__PURE__ */ jsx57(
3864
+ /* @__PURE__ */ jsx58(
3617
3865
  "a",
3618
3866
  {
3619
3867
  href: linkHref,
@@ -3652,6 +3900,14 @@ export {
3652
3900
  CardHeader,
3653
3901
  CardTitle,
3654
3902
  Checkbox,
3903
+ ColorPicker,
3904
+ ColorPickerAlpha,
3905
+ ColorPickerEyeDropper,
3906
+ ColorPickerFormat,
3907
+ ColorPickerHexOutput,
3908
+ ColorPickerHue,
3909
+ ColorPickerOutput,
3910
+ ColorPickerSelection,
3655
3911
  ConfirmDialog,
3656
3912
  DashboardLayout,
3657
3913
  DataTable,
@@ -3738,6 +3994,7 @@ export {
3738
3994
  badgeVariants,
3739
3995
  buttonVariants,
3740
3996
  cn,
3997
+ useColorPicker,
3741
3998
  useDisclosure,
3742
3999
  usePagination,
3743
4000
  useTheme2 as useTheme