@webdevarif/dashui 0.3.0 → 0.3.2

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
@@ -1065,7 +1065,7 @@ function NotificationBell({
1065
1065
  import * as React17 from "react";
1066
1066
  import { useTheme } from "next-themes";
1067
1067
  import { jsx as jsx24, jsxs as jsxs11 } from "react/jsx-runtime";
1068
- function ThemeToggle({ className }) {
1068
+ function ThemeToggle({ className, theme: externalTheme, onToggle }) {
1069
1069
  const { resolvedTheme, setTheme } = useTheme();
1070
1070
  const [mounted, setMounted] = React17.useState(false);
1071
1071
  React17.useEffect(() => {
@@ -1084,11 +1084,12 @@ function ThemeToggle({ className }) {
1084
1084
  }
1085
1085
  );
1086
1086
  }
1087
- const isDark = resolvedTheme === "dark";
1087
+ const isDark = externalTheme !== void 0 ? externalTheme === "dark" : resolvedTheme === "dark";
1088
+ const handleToggle = onToggle ?? (() => setTheme(isDark ? "light" : "dark"));
1088
1089
  return /* @__PURE__ */ jsx24(
1089
1090
  "button",
1090
1091
  {
1091
- onClick: () => setTheme(isDark ? "light" : "dark"),
1092
+ onClick: handleToggle,
1092
1093
  className: cn(
1093
1094
  "flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
1094
1095
  className
@@ -3163,10 +3164,126 @@ function PostSidebarSection({
3163
3164
  ] });
3164
3165
  }
3165
3166
 
3167
+ // src/components/ui/hsl-color-input.tsx
3168
+ import { useState as useState7, useRef as useRef4, useEffect as useEffect5, useCallback } from "react";
3169
+ import { HslColorPicker } from "react-colorful";
3170
+ import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
3171
+ function parseHsl(value) {
3172
+ if (!value) return { h: 0, s: 0, l: 0 };
3173
+ const parts = value.trim().split(/\s+/);
3174
+ const h = parseFloat(parts[0]) || 0;
3175
+ const s = parseFloat(parts[1]) || 0;
3176
+ const l = parseFloat(parts[2]) || 0;
3177
+ return { h, s, l };
3178
+ }
3179
+ function formatHsl(color) {
3180
+ return `${Math.round(color.h)} ${Math.round(color.s)}% ${Math.round(color.l)}%`;
3181
+ }
3182
+ function HslColorInput({
3183
+ value,
3184
+ onChange,
3185
+ className,
3186
+ inputClassName,
3187
+ disabled
3188
+ }) {
3189
+ const [open, setOpen] = useState7(false);
3190
+ const [inputVal, setInputVal] = useState7(value);
3191
+ const containerRef = useRef4(null);
3192
+ useEffect5(() => {
3193
+ setInputVal(value);
3194
+ }, [value]);
3195
+ useEffect5(() => {
3196
+ if (!open) return;
3197
+ const handler = (e) => {
3198
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
3199
+ setOpen(false);
3200
+ }
3201
+ };
3202
+ document.addEventListener("mousedown", handler);
3203
+ return () => document.removeEventListener("mousedown", handler);
3204
+ }, [open]);
3205
+ const hslColor = parseHsl(value);
3206
+ const cssColor = value ? `hsl(${value})` : "transparent";
3207
+ const handlePickerChange = useCallback((color) => {
3208
+ const formatted = formatHsl(color);
3209
+ setInputVal(formatted);
3210
+ onChange(formatted);
3211
+ }, [onChange]);
3212
+ const handleInputChange = (e) => {
3213
+ const v = e.target.value;
3214
+ setInputVal(v);
3215
+ if (/^\d+\s+\d+%?\s+\d+%?$/.test(v.trim()) || /^\d+(\.\d+)?\s+\d+(\.\d+)?%\s+\d+(\.\d+)?%$/.test(v.trim())) {
3216
+ onChange(v);
3217
+ }
3218
+ };
3219
+ const handleInputBlur = () => {
3220
+ setInputVal(value);
3221
+ };
3222
+ return /* @__PURE__ */ jsxs33("div", { ref: containerRef, className: cn("relative flex items-center gap-1.5", className), children: [
3223
+ /* @__PURE__ */ jsx49(
3224
+ "button",
3225
+ {
3226
+ type: "button",
3227
+ disabled,
3228
+ onClick: () => setOpen((o) => !o),
3229
+ className: cn(
3230
+ "w-5 h-5 rounded border border-white/10 shrink-0 transition-all",
3231
+ "hover:scale-110 hover:border-white/30 focus:outline-none focus:ring-1 focus:ring-white/20",
3232
+ disabled && "opacity-50 cursor-not-allowed"
3233
+ ),
3234
+ style: { background: cssColor },
3235
+ title: value,
3236
+ "aria-label": "Open color picker"
3237
+ }
3238
+ ),
3239
+ /* @__PURE__ */ jsx49(
3240
+ "input",
3241
+ {
3242
+ type: "text",
3243
+ value: inputVal,
3244
+ onChange: handleInputChange,
3245
+ onBlur: handleInputBlur,
3246
+ disabled,
3247
+ placeholder: "0 0% 0%",
3248
+ className: cn(
3249
+ "w-28 bg-white/5 border border-white/10 rounded px-1.5 py-0.5",
3250
+ "text-xs text-white/70 font-mono outline-none",
3251
+ "focus:border-white/30 placeholder:text-white/20",
3252
+ "disabled:opacity-50 disabled:cursor-not-allowed",
3253
+ inputClassName
3254
+ )
3255
+ }
3256
+ ),
3257
+ open && /* @__PURE__ */ jsxs33("div", { className: cn(
3258
+ "absolute z-50 top-full left-0 mt-2",
3259
+ "bg-[#1a1c2e] border border-white/10 rounded-xl shadow-2xl p-3",
3260
+ "flex flex-col gap-3"
3261
+ ), children: [
3262
+ /* @__PURE__ */ jsx49(
3263
+ HslColorPicker,
3264
+ {
3265
+ color: hslColor,
3266
+ onChange: handlePickerChange
3267
+ }
3268
+ ),
3269
+ /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-2", children: [
3270
+ /* @__PURE__ */ jsx49(
3271
+ "div",
3272
+ {
3273
+ className: "w-6 h-6 rounded border border-white/10 shrink-0",
3274
+ style: { background: cssColor }
3275
+ }
3276
+ ),
3277
+ /* @__PURE__ */ jsx49("span", { className: "text-xs font-mono text-white/50 truncate", children: value || "none" })
3278
+ ] })
3279
+ ] })
3280
+ ] });
3281
+ }
3282
+
3166
3283
  // src/hooks/index.ts
3167
- import { useState as useState7 } from "react";
3284
+ import { useState as useState8 } from "react";
3168
3285
  function useDisclosure(initial = false) {
3169
- const [isOpen, setIsOpen] = useState7(initial);
3286
+ const [isOpen, setIsOpen] = useState8(initial);
3170
3287
  return {
3171
3288
  isOpen,
3172
3289
  open: () => setIsOpen(true),
@@ -3176,15 +3293,15 @@ function useDisclosure(initial = false) {
3176
3293
  };
3177
3294
  }
3178
3295
  function usePagination(total, pageSize = 20) {
3179
- const [page, setPage] = useState7(1);
3296
+ const [page, setPage] = useState8(1);
3180
3297
  const totalPages = Math.ceil(total / pageSize);
3181
3298
  return { page, setPage, pageSize, total, totalPages };
3182
3299
  }
3183
3300
 
3184
3301
  // src/components/auth/AuthShell.tsx
3185
- import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
3302
+ import { jsx as jsx50, jsxs as jsxs34 } from "react/jsx-runtime";
3186
3303
  function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
3187
- return /* @__PURE__ */ jsxs33(
3304
+ return /* @__PURE__ */ jsxs34(
3188
3305
  "div",
3189
3306
  {
3190
3307
  style: {
@@ -3199,7 +3316,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
3199
3316
  overflow: "hidden"
3200
3317
  },
3201
3318
  children: [
3202
- pattern === "dots" && /* @__PURE__ */ jsx49(
3319
+ pattern === "dots" && /* @__PURE__ */ jsx50(
3203
3320
  "div",
3204
3321
  {
3205
3322
  "aria-hidden": true,
@@ -3213,7 +3330,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
3213
3330
  }
3214
3331
  }
3215
3332
  ),
3216
- pattern === "grid" && /* @__PURE__ */ jsx49(
3333
+ pattern === "grid" && /* @__PURE__ */ jsx50(
3217
3334
  "div",
3218
3335
  {
3219
3336
  "aria-hidden": true,
@@ -3227,16 +3344,16 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
3227
3344
  }
3228
3345
  }
3229
3346
  ),
3230
- /* @__PURE__ */ jsx49("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
3347
+ /* @__PURE__ */ jsx50("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
3231
3348
  ]
3232
3349
  }
3233
3350
  );
3234
3351
  }
3235
3352
 
3236
3353
  // src/components/auth/AuthCard.tsx
3237
- import { jsx as jsx50 } from "react/jsx-runtime";
3354
+ import { jsx as jsx51 } from "react/jsx-runtime";
3238
3355
  function AuthCard({ children, padding = "24px 28px" }) {
3239
- return /* @__PURE__ */ jsx50(
3356
+ return /* @__PURE__ */ jsx51(
3240
3357
  "div",
3241
3358
  {
3242
3359
  style: {
@@ -3253,10 +3370,10 @@ function AuthCard({ children, padding = "24px 28px" }) {
3253
3370
  }
3254
3371
 
3255
3372
  // src/components/auth/AuthLogo.tsx
3256
- import { jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
3373
+ import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
3257
3374
  function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }) {
3258
- return /* @__PURE__ */ jsxs34("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
3259
- imageUrl ? /* @__PURE__ */ jsx51(
3375
+ return /* @__PURE__ */ jsxs35("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
3376
+ imageUrl ? /* @__PURE__ */ jsx52(
3260
3377
  "img",
3261
3378
  {
3262
3379
  src: imageUrl,
@@ -3265,7 +3382,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
3265
3382
  height: size,
3266
3383
  style: { borderRadius: "calc(var(--radius, 0.5rem) * 1.2)", flexShrink: 0, display: "block" }
3267
3384
  }
3268
- ) : /* @__PURE__ */ jsx51(
3385
+ ) : /* @__PURE__ */ jsx52(
3269
3386
  "div",
3270
3387
  {
3271
3388
  style: {
@@ -3284,7 +3401,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
3284
3401
  children: letter
3285
3402
  }
3286
3403
  ),
3287
- /* @__PURE__ */ jsx51(
3404
+ /* @__PURE__ */ jsx52(
3288
3405
  "span",
3289
3406
  {
3290
3407
  style: {
@@ -3300,10 +3417,10 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
3300
3417
  }
3301
3418
 
3302
3419
  // src/components/auth/AuthHeader.tsx
3303
- import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
3420
+ import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
3304
3421
  function AuthHeader({ title, description }) {
3305
- return /* @__PURE__ */ jsxs35("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
3306
- /* @__PURE__ */ jsx52(
3422
+ return /* @__PURE__ */ jsxs36("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
3423
+ /* @__PURE__ */ jsx53(
3307
3424
  "h1",
3308
3425
  {
3309
3426
  style: {
@@ -3316,7 +3433,7 @@ function AuthHeader({ title, description }) {
3316
3433
  children: title
3317
3434
  }
3318
3435
  ),
3319
- description && /* @__PURE__ */ jsx52(
3436
+ description && /* @__PURE__ */ jsx53(
3320
3437
  "p",
3321
3438
  {
3322
3439
  style: {
@@ -3332,12 +3449,12 @@ function AuthHeader({ title, description }) {
3332
3449
  }
3333
3450
 
3334
3451
  // src/components/auth/AuthField.tsx
3335
- import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
3452
+ import { jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
3336
3453
  function AuthField({ label, error, hint, rightLabel, id, ...props }) {
3337
3454
  const fieldId = id ?? label.toLowerCase().replace(/\s+/g, "-");
3338
- return /* @__PURE__ */ jsxs36("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
3339
- /* @__PURE__ */ jsxs36("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
3340
- /* @__PURE__ */ jsx53(
3455
+ return /* @__PURE__ */ jsxs37("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
3456
+ /* @__PURE__ */ jsxs37("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
3457
+ /* @__PURE__ */ jsx54(
3341
3458
  "label",
3342
3459
  {
3343
3460
  htmlFor: fieldId,
@@ -3349,9 +3466,9 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
3349
3466
  children: label
3350
3467
  }
3351
3468
  ),
3352
- rightLabel && /* @__PURE__ */ jsx53("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
3469
+ rightLabel && /* @__PURE__ */ jsx54("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
3353
3470
  ] }),
3354
- /* @__PURE__ */ jsx53(
3471
+ /* @__PURE__ */ jsx54(
3355
3472
  "input",
3356
3473
  {
3357
3474
  id: fieldId,
@@ -3381,13 +3498,13 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
3381
3498
  ...props
3382
3499
  }
3383
3500
  ),
3384
- error && /* @__PURE__ */ jsx53("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
3385
- hint && !error && /* @__PURE__ */ jsx53("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
3501
+ error && /* @__PURE__ */ jsx54("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
3502
+ hint && !error && /* @__PURE__ */ jsx54("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
3386
3503
  ] });
3387
3504
  }
3388
3505
 
3389
3506
  // src/components/auth/AuthButton.tsx
3390
- import { Fragment as Fragment5, jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
3507
+ import { Fragment as Fragment5, jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
3391
3508
  function AuthButton({
3392
3509
  loading,
3393
3510
  variant = "primary",
@@ -3430,7 +3547,7 @@ function AuthButton({
3430
3547
  color: "var(--foreground)"
3431
3548
  }
3432
3549
  };
3433
- return /* @__PURE__ */ jsx54(
3550
+ return /* @__PURE__ */ jsx55(
3434
3551
  "button",
3435
3552
  {
3436
3553
  disabled: loading || disabled,
@@ -3442,8 +3559,8 @@ function AuthButton({
3442
3559
  e.currentTarget.style.filter = "none";
3443
3560
  },
3444
3561
  ...props,
3445
- children: loading ? /* @__PURE__ */ jsxs37(Fragment5, { children: [
3446
- /* @__PURE__ */ jsx54(
3562
+ children: loading ? /* @__PURE__ */ jsxs38(Fragment5, { children: [
3563
+ /* @__PURE__ */ jsx55(
3447
3564
  "span",
3448
3565
  {
3449
3566
  style: {
@@ -3464,19 +3581,19 @@ function AuthButton({
3464
3581
  }
3465
3582
 
3466
3583
  // src/components/auth/AuthDivider.tsx
3467
- import { jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
3584
+ import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
3468
3585
  function AuthDivider({ label = "or" }) {
3469
- return /* @__PURE__ */ jsxs38("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
3470
- /* @__PURE__ */ jsx55("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
3471
- /* @__PURE__ */ jsx55("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
3472
- /* @__PURE__ */ jsx55("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
3586
+ return /* @__PURE__ */ jsxs39("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
3587
+ /* @__PURE__ */ jsx56("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
3588
+ /* @__PURE__ */ jsx56("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
3589
+ /* @__PURE__ */ jsx56("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
3473
3590
  ] });
3474
3591
  }
3475
3592
 
3476
3593
  // src/components/auth/AuthFootnote.tsx
3477
- import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
3594
+ import { jsx as jsx57, jsxs as jsxs40 } from "react/jsx-runtime";
3478
3595
  function AuthFootnote({ text, linkText, linkHref }) {
3479
- return /* @__PURE__ */ jsxs39("p", { style: {
3596
+ return /* @__PURE__ */ jsxs40("p", { style: {
3480
3597
  textAlign: "center",
3481
3598
  marginTop: "20px",
3482
3599
  fontSize: "0.8125rem",
@@ -3484,7 +3601,7 @@ function AuthFootnote({ text, linkText, linkHref }) {
3484
3601
  }, children: [
3485
3602
  text,
3486
3603
  " ",
3487
- /* @__PURE__ */ jsx56(
3604
+ /* @__PURE__ */ jsx57(
3488
3605
  "a",
3489
3606
  {
3490
3607
  href: linkHref,
@@ -3555,6 +3672,7 @@ export {
3555
3672
  FormField,
3556
3673
  FormLayout,
3557
3674
  FormSection,
3675
+ HslColorInput,
3558
3676
  ImagePickerField,
3559
3677
  Input,
3560
3678
  Label2 as Label,