@webdevarif/dashui 0.3.2 → 0.3.4

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.d.mts CHANGED
@@ -543,7 +543,7 @@ interface HslColorInputProps {
543
543
  inputClassName?: string;
544
544
  disabled?: boolean;
545
545
  }
546
- declare function HslColorInput({ value, onChange, className, inputClassName, disabled, }: HslColorInputProps): react_jsx_runtime.JSX.Element;
546
+ declare function HslColorInput({ value, onChange, className, inputClassName, disabled }: HslColorInputProps): react_jsx_runtime.JSX.Element;
547
547
 
548
548
  declare function useDisclosure(initial?: boolean): {
549
549
  isOpen: boolean;
package/dist/index.d.ts CHANGED
@@ -543,7 +543,7 @@ interface HslColorInputProps {
543
543
  inputClassName?: string;
544
544
  disabled?: boolean;
545
545
  }
546
- declare function HslColorInput({ value, onChange, className, inputClassName, disabled, }: HslColorInputProps): react_jsx_runtime.JSX.Element;
546
+ declare function HslColorInput({ value, onChange, className, inputClassName, disabled }: HslColorInputProps): react_jsx_runtime.JSX.Element;
547
547
 
548
548
  declare function useDisclosure(initial?: boolean): {
549
549
  isOpen: boolean;
package/dist/index.js CHANGED
@@ -3309,74 +3309,104 @@ function PostSidebarSection({
3309
3309
 
3310
3310
  // src/components/ui/hsl-color-input.tsx
3311
3311
  var import_react = require("react");
3312
+ var import_react_dom = require("react-dom");
3312
3313
  var import_react_colorful = require("react-colorful");
3313
3314
  var import_jsx_runtime49 = require("react/jsx-runtime");
3314
3315
  function parseHsl(value) {
3315
3316
  if (!value) return { h: 0, s: 0, l: 0 };
3316
3317
  const parts = value.trim().split(/\s+/);
3317
- const h = parseFloat(parts[0]) || 0;
3318
- const s = parseFloat(parts[1]) || 0;
3319
- const l = parseFloat(parts[2]) || 0;
3320
- return { h, s, l };
3318
+ return {
3319
+ h: parseFloat(parts[0]) || 0,
3320
+ s: parseFloat(parts[1]) || 0,
3321
+ l: parseFloat(parts[2]) || 0
3322
+ };
3321
3323
  }
3322
- function formatHsl(color) {
3323
- return `${Math.round(color.h)} ${Math.round(color.s)}% ${Math.round(color.l)}%`;
3324
+ function formatHsl(c) {
3325
+ return `${Math.round(c.h)} ${Math.round(c.s)}% ${Math.round(c.l)}%`;
3324
3326
  }
3325
- function HslColorInput({
3326
- value,
3327
- onChange,
3328
- className,
3329
- inputClassName,
3330
- disabled
3331
- }) {
3327
+ function HslColorInput({ value, onChange, className, inputClassName, disabled }) {
3332
3328
  const [open, setOpen] = (0, import_react.useState)(false);
3329
+ const [pos, setPos] = (0, import_react.useState)({ top: 0, left: 0 });
3333
3330
  const [inputVal, setInputVal] = (0, import_react.useState)(value);
3334
- const containerRef = (0, import_react.useRef)(null);
3331
+ const [mounted, setMounted] = (0, import_react.useState)(false);
3332
+ const triggerRef = (0, import_react.useRef)(null);
3333
+ const pickerRef = (0, import_react.useRef)(null);
3334
+ (0, import_react.useEffect)(() => {
3335
+ setMounted(true);
3336
+ }, []);
3335
3337
  (0, import_react.useEffect)(() => {
3336
3338
  setInputVal(value);
3337
3339
  }, [value]);
3340
+ const openPicker = (0, import_react.useCallback)(() => {
3341
+ const rect = triggerRef.current?.getBoundingClientRect();
3342
+ if (!rect) return;
3343
+ const pickerW = 228;
3344
+ let left = rect.left;
3345
+ if (left + pickerW > window.innerWidth - 8) left = window.innerWidth - pickerW - 8;
3346
+ setPos({ top: rect.bottom + 6, left: Math.max(8, left) });
3347
+ setOpen(true);
3348
+ }, []);
3338
3349
  (0, import_react.useEffect)(() => {
3339
3350
  if (!open) return;
3340
3351
  const handler = (e) => {
3341
- if (containerRef.current && !containerRef.current.contains(e.target)) {
3342
- setOpen(false);
3343
- }
3352
+ const target = e.target;
3353
+ if (pickerRef.current?.contains(target)) return;
3354
+ if (triggerRef.current?.contains(target)) return;
3355
+ setOpen(false);
3344
3356
  };
3345
- document.addEventListener("mousedown", handler);
3346
- return () => document.removeEventListener("mousedown", handler);
3357
+ document.addEventListener("pointerdown", handler, true);
3358
+ return () => document.removeEventListener("pointerdown", handler, true);
3347
3359
  }, [open]);
3348
- const hslColor = parseHsl(value);
3349
3360
  const cssColor = value ? `hsl(${value})` : "transparent";
3350
- const handlePickerChange = (0, import_react.useCallback)((color) => {
3351
- const formatted = formatHsl(color);
3352
- setInputVal(formatted);
3353
- onChange(formatted);
3354
- }, [onChange]);
3355
- const handleInputChange = (e) => {
3356
- const v = e.target.value;
3357
- setInputVal(v);
3358
- if (/^\d+\s+\d+%?\s+\d+%?$/.test(v.trim()) || /^\d+(\.\d+)?\s+\d+(\.\d+)?%\s+\d+(\.\d+)?%$/.test(v.trim())) {
3359
- onChange(v);
3361
+ const picker = /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
3362
+ "div",
3363
+ {
3364
+ ref: pickerRef,
3365
+ style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 9999 },
3366
+ className: "bg-[#1a1c2e] border border-white/10 rounded-xl shadow-2xl p-3 flex flex-col gap-3",
3367
+ onPointerDown: (e) => e.stopPropagation(),
3368
+ children: [
3369
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3370
+ import_react_colorful.HslColorPicker,
3371
+ {
3372
+ color: parseHsl(value),
3373
+ onChange: (c) => {
3374
+ const formatted = formatHsl(c);
3375
+ setInputVal(formatted);
3376
+ onChange(formatted);
3377
+ }
3378
+ }
3379
+ ),
3380
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2 px-1", children: [
3381
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "w-5 h-5 rounded border border-white/10 shrink-0", style: { background: cssColor } }),
3382
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-xs font-mono text-white/40 flex-1 truncate", children: value || "none" }),
3383
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3384
+ "button",
3385
+ {
3386
+ onClick: () => setOpen(false),
3387
+ className: "text-white/30 hover:text-white/70 text-xs px-1.5 py-0.5 rounded hover:bg-white/5 transition-colors",
3388
+ children: "Done"
3389
+ }
3390
+ )
3391
+ ] })
3392
+ ]
3360
3393
  }
3361
- };
3362
- const handleInputBlur = () => {
3363
- setInputVal(value);
3364
- };
3365
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { ref: containerRef, className: cn("relative flex items-center gap-1.5", className), children: [
3394
+ );
3395
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: cn("flex items-center gap-1.5", className), children: [
3366
3396
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3367
3397
  "button",
3368
3398
  {
3399
+ ref: triggerRef,
3369
3400
  type: "button",
3370
3401
  disabled,
3371
- onClick: () => setOpen((o) => !o),
3402
+ onClick: () => open ? setOpen(false) : openPicker(),
3372
3403
  className: cn(
3373
3404
  "w-5 h-5 rounded border border-white/10 shrink-0 transition-all",
3374
- "hover:scale-110 hover:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20",
3405
+ "hover:scale-110 hover:border-white/30 focus:outline-none",
3375
3406
  disabled && "opacity-50 cursor-not-allowed"
3376
3407
  ),
3377
3408
  style: { background: cssColor },
3378
- title: value,
3379
- "aria-label": "Open color picker"
3409
+ "aria-label": "Pick color"
3380
3410
  }
3381
3411
  ),
3382
3412
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
@@ -3384,42 +3414,24 @@ function HslColorInput({
3384
3414
  {
3385
3415
  type: "text",
3386
3416
  value: inputVal,
3387
- onChange: handleInputChange,
3388
- onBlur: handleInputBlur,
3417
+ onChange: (e) => {
3418
+ setInputVal(e.target.value);
3419
+ if (/^\d+(\.\d+)?\s+\d+(\.\d+)?%\s+\d+(\.\d+)?%$/.test(e.target.value.trim())) {
3420
+ onChange(e.target.value.trim());
3421
+ }
3422
+ },
3423
+ onBlur: () => setInputVal(value),
3389
3424
  disabled,
3390
- placeholder: "0 0% 0%",
3425
+ placeholder: "H S% L%",
3391
3426
  className: cn(
3392
3427
  "w-28 bg-white/5 border border-white/10 rounded px-1.5 py-0.5",
3393
- "text-xs text-white/70 font-mono outline-none",
3394
- "focus:border-white/30 placeholder:text-white/20",
3395
- "disabled:opacity-50 disabled:cursor-not-allowed",
3428
+ "text-xs text-white/70 font-mono outline-none focus:border-white/30",
3429
+ "placeholder:text-white/20 disabled:opacity-50",
3396
3430
  inputClassName
3397
3431
  )
3398
3432
  }
3399
3433
  ),
3400
- open && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: cn(
3401
- "absolute z-50 top-full left-0 mt-2",
3402
- "bg-[#1a1c2e] border border-white/10 rounded-xl shadow-2xl p-3",
3403
- "flex flex-col gap-3"
3404
- ), children: [
3405
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3406
- import_react_colorful.HslColorPicker,
3407
- {
3408
- color: hslColor,
3409
- onChange: handlePickerChange
3410
- }
3411
- ),
3412
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2", children: [
3413
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3414
- "div",
3415
- {
3416
- className: "w-6 h-6 rounded border border-white/10 shrink-0",
3417
- style: { background: cssColor }
3418
- }
3419
- ),
3420
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-xs font-mono text-white/50 truncate", children: value || "none" })
3421
- ] })
3422
- ] })
3434
+ mounted && open && (0, import_react_dom.createPortal)(picker, document.body)
3423
3435
  ] });
3424
3436
  }
3425
3437