@skiddph/prui 0.1.0

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.
Files changed (69) hide show
  1. package/LICENSE +201 -0
  2. package/dist/app/app.d.ts +91 -0
  3. package/dist/app/auto-pages.d.ts +20 -0
  4. package/dist/app/form.d.ts +44 -0
  5. package/dist/app/index.d.ts +8 -0
  6. package/dist/app/resource.d.ts +61 -0
  7. package/dist/app/settings.d.ts +27 -0
  8. package/dist/app/stat-row.d.ts +20 -0
  9. package/dist/app.js +18 -0
  10. package/dist/chunks/data-table-toolbar-C9likJBN.js +430 -0
  11. package/dist/chunks/settings-DUz5nyX-.js +731 -0
  12. package/dist/core/button.d.ts +14 -0
  13. package/dist/core/button.js +58 -0
  14. package/dist/core/card.d.ts +24 -0
  15. package/dist/core/card.js +122 -0
  16. package/dist/core/cn.d.ts +3 -0
  17. package/dist/core/cn.js +8 -0
  18. package/dist/core/dialog.d.ts +25 -0
  19. package/dist/core/dialog.js +102 -0
  20. package/dist/core/dropdown.d.ts +24 -0
  21. package/dist/core/dropdown.js +89 -0
  22. package/dist/core/index.d.ts +14 -0
  23. package/dist/core/input.d.ts +8 -0
  24. package/dist/core/input.js +42 -0
  25. package/dist/core/label.d.ts +12 -0
  26. package/dist/core/label.js +52 -0
  27. package/dist/core/modal.d.ts +56 -0
  28. package/dist/core/modal.js +303 -0
  29. package/dist/core/props-meta.d.ts +26 -0
  30. package/dist/core/props-meta.js +1 -0
  31. package/dist/core/scroll-area.d.ts +8 -0
  32. package/dist/core/scroll-area.js +27 -0
  33. package/dist/core/select.d.ts +38 -0
  34. package/dist/core/select.js +157 -0
  35. package/dist/core/switch.d.ts +10 -0
  36. package/dist/core/switch.js +57 -0
  37. package/dist/core/tabs.d.ts +22 -0
  38. package/dist/core/tabs.js +94 -0
  39. package/dist/core.js +64 -0
  40. package/dist/data-table/data-table-daterange-filter.d.ts +14 -0
  41. package/dist/data-table/data-table-faceted-filter.d.ts +17 -0
  42. package/dist/data-table/data-table-number-range-filter.d.ts +14 -0
  43. package/dist/data-table/data-table-pagination.d.ts +24 -0
  44. package/dist/data-table/data-table-toolbar.d.ts +38 -0
  45. package/dist/data-table/data-table.d.ts +47 -0
  46. package/dist/data-table/index.d.ts +7 -0
  47. package/dist/data-table.js +12 -0
  48. package/dist/index.d.ts +5 -0
  49. package/dist/index.js +125 -0
  50. package/dist/pages/forgot-password.d.ts +21 -0
  51. package/dist/pages/index.d.ts +18 -0
  52. package/dist/pages/login.d.ts +24 -0
  53. package/dist/pages/logout.d.ts +12 -0
  54. package/dist/pages/otp.d.ts +18 -0
  55. package/dist/pages/profile-settings.d.ts +55 -0
  56. package/dist/pages/register.d.ts +19 -0
  57. package/dist/pages/reset-password.d.ts +20 -0
  58. package/dist/pages/shared.d.ts +55 -0
  59. package/dist/pages/status.d.ts +33 -0
  60. package/dist/pages.js +806 -0
  61. package/dist/prui.css +120 -0
  62. package/dist/theme/base.css +36 -0
  63. package/dist/theme/control.css +16 -0
  64. package/dist/theme/daylight.css +16 -0
  65. package/dist/theme/ember.css +16 -0
  66. package/dist/theme/index.d.ts +55 -0
  67. package/dist/theme/workshop.css +16 -0
  68. package/dist/theme.js +63 -0
  69. package/package.json +81 -0
@@ -0,0 +1,14 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ export type ButtonVariant = "primary" | "default" | "ghost" | "danger";
4
+ export type ButtonSize = "sm" | "md" | "lg" | "icon";
5
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
6
+ variant?: ButtonVariant;
7
+ size?: ButtonSize;
8
+ /** Render the single child instead of a button element. */
9
+ asChild?: boolean;
10
+ /** Show a spinner and disable the button. */
11
+ loading?: boolean;
12
+ }
13
+ export declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
14
+ export declare const buttonPropsMeta: PropsMeta;
@@ -0,0 +1,58 @@
1
+ import { jsx as r, jsxs as b, Fragment as g } from "react/jsx-runtime";
2
+ import * as n from "react";
3
+ import { Loader2 as h } from "lucide-react";
4
+ import { cn as i } from "./cn.js";
5
+ const v = {
6
+ primary: "bg-[var(--prui-brand)] text-[var(--prui-brand-fg)] hover:brightness-110 active:brightness-95",
7
+ default: "bg-[var(--prui-raise)] text-[var(--prui-fg)] border border-[var(--prui-line)] hover:border-[var(--prui-dim)]",
8
+ ghost: "bg-transparent text-[var(--prui-fg)] hover:bg-[var(--prui-raise)]",
9
+ danger: "bg-[var(--prui-danger)] text-white hover:brightness-110 active:brightness-95"
10
+ }, x = {
11
+ sm: "h-7 px-2.5 text-xs gap-1.5",
12
+ md: "h-9 px-3.5 text-sm gap-2",
13
+ lg: "h-11 px-5 text-base gap-2",
14
+ icon: "h-9 w-9 p-0"
15
+ }, y = n.forwardRef(
16
+ ({ className: d, variant: p = "default", size: c = "md", asChild: u = !1, loading: e = !1, disabled: m, children: t, ...o }, f) => {
17
+ const s = i(
18
+ "prui-button inline-flex items-center justify-center whitespace-nowrap font-medium select-none",
19
+ "transition-[filter,background-color,border-color] duration-150 outline-none cursor-pointer",
20
+ "focus-visible:ring-2 focus-visible:ring-[var(--prui-brand)] focus-visible:ring-offset-1",
21
+ "disabled:pointer-events-none disabled:opacity-50",
22
+ v[p],
23
+ x[c],
24
+ d
25
+ );
26
+ if (u && n.isValidElement(t)) {
27
+ const a = t;
28
+ return n.cloneElement(a, {
29
+ className: i(s, a.props.className),
30
+ ...o,
31
+ children: e ? /* @__PURE__ */ r(l, {}) : a.props.children
32
+ });
33
+ }
34
+ return /* @__PURE__ */ r("button", { ref: f, className: s, disabled: m || e, "data-loading": e || void 0, ...o, children: e ? /* @__PURE__ */ b(g, { children: [
35
+ /* @__PURE__ */ r(l, {}),
36
+ t
37
+ ] }) : t });
38
+ }
39
+ );
40
+ y.displayName = "Button";
41
+ function l() {
42
+ return /* @__PURE__ */ r(h, { className: "h-4 w-4 animate-spin", "aria-hidden": !0 });
43
+ }
44
+ const B = {
45
+ name: "Button",
46
+ props: [
47
+ { name: "variant", type: "'primary' | 'default' | 'ghost' | 'danger'", default: "'default'", control: "select", options: ["primary", "default", "ghost", "danger"] },
48
+ { name: "size", type: "'sm' | 'md' | 'lg' | 'icon'", default: "'md'", control: "select", options: ["sm", "md", "lg", "icon"] },
49
+ { name: "asChild", type: "boolean", default: "false", control: "boolean" },
50
+ { name: "loading", type: "boolean", default: "false", control: "boolean" },
51
+ { name: "disabled", type: "boolean", default: "false", control: "boolean" },
52
+ { name: "children", type: "ReactNode", default: null, control: "text" }
53
+ ]
54
+ };
55
+ export {
56
+ y as Button,
57
+ B as buttonPropsMeta
58
+ };
@@ -0,0 +1,24 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ export type BadgeVariant = "default" | "brand" | "ok" | "warn" | "danger" | "outline";
4
+ export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
5
+ variant?: BadgeVariant;
6
+ }
7
+ export declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
8
+ export declare const badgePropsMeta: PropsMeta;
9
+ export declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
10
+ export declare const CardHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
11
+ export declare const CardTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLHeadingElement>>;
12
+ export declare const CardDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
13
+ export declare const CardContent: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
14
+ export declare const CardFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
15
+ export declare const cardPropsMeta: PropsMeta;
16
+ export interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {
17
+ src?: string;
18
+ alt?: string;
19
+ /** Fallback initials when no image or image fails. */
20
+ fallback?: string;
21
+ size?: "sm" | "md" | "lg";
22
+ }
23
+ export declare const Avatar: React.ForwardRefExoticComponent<AvatarProps & React.RefAttributes<HTMLSpanElement>>;
24
+ export declare const avatarPropsMeta: PropsMeta;
@@ -0,0 +1,122 @@
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import * as n from "react";
3
+ import { cn as d } from "./cn.js";
4
+ const g = {
5
+ default: "bg-[var(--prui-raise)] text-[var(--prui-fg)] border-transparent",
6
+ brand: "bg-[var(--prui-brand)]/15 text-[var(--prui-brand)] border-transparent",
7
+ ok: "bg-[var(--prui-ok)]/15 text-[var(--prui-ok)] border-transparent",
8
+ warn: "bg-[var(--prui-warn)]/15 text-[var(--prui-warn)] border-transparent",
9
+ danger: "bg-[var(--prui-danger)]/15 text-[var(--prui-danger)] border-transparent",
10
+ outline: "bg-transparent text-[var(--prui-fg)] border-[var(--prui-line)]"
11
+ }, x = n.forwardRef(
12
+ ({ className: a, variant: e = "default", ...r }, i) => /* @__PURE__ */ t(
13
+ "span",
14
+ {
15
+ ref: i,
16
+ "data-variant": e,
17
+ className: d(
18
+ "prui-badge inline-flex items-center gap-1 rounded-[var(--prui-radius-full)] border px-2 py-0.5",
19
+ "text-xs font-medium whitespace-nowrap",
20
+ g[e],
21
+ a
22
+ ),
23
+ ...r
24
+ }
25
+ )
26
+ );
27
+ x.displayName = "Badge";
28
+ const B = {
29
+ name: "Badge",
30
+ props: [
31
+ { name: "variant", type: "'default' | 'brand' | 'ok' | 'warn' | 'danger' | 'outline'", default: "'default'", control: "select", options: ["default", "brand", "ok", "warn", "danger", "outline"] },
32
+ { name: "children", type: "ReactNode", default: null, control: "text" }
33
+ ]
34
+ }, b = n.forwardRef(
35
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t(
36
+ "div",
37
+ {
38
+ ref: r,
39
+ className: d(
40
+ "prui-card rounded-[var(--prui-radius)] border border-[var(--prui-line)] bg-[var(--prui-surface)]",
41
+ a
42
+ ),
43
+ ...e
44
+ }
45
+ )
46
+ );
47
+ b.displayName = "Card";
48
+ const w = n.forwardRef(
49
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: d("prui-card-header flex flex-col gap-1 p-4", a), ...e })
50
+ );
51
+ w.displayName = "CardHeader";
52
+ const N = n.forwardRef(
53
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("h3", { ref: r, className: d("prui-card-title text-base font-semibold text-[var(--prui-fg)]", a), ...e })
54
+ );
55
+ N.displayName = "CardTitle";
56
+ const y = n.forwardRef(
57
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("p", { ref: r, className: d("prui-card-description text-sm text-[var(--prui-dim)]", a), ...e })
58
+ );
59
+ y.displayName = "CardDescription";
60
+ const C = n.forwardRef(
61
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: d("prui-card-content p-4 pt-0", a), ...e })
62
+ );
63
+ C.displayName = "CardContent";
64
+ const h = n.forwardRef(
65
+ ({ className: a, ...e }, r) => /* @__PURE__ */ t("div", { ref: r, className: d("prui-card-footer flex items-center p-4 pt-0", a), ...e })
66
+ );
67
+ h.displayName = "CardFooter";
68
+ const F = {
69
+ name: "Card",
70
+ props: [
71
+ { name: "children", type: "ReactNode", default: null, control: "text" },
72
+ { name: "className", type: "string", default: "undefined", control: "text" }
73
+ ]
74
+ }, R = {
75
+ sm: "h-6 w-6 text-[10px]",
76
+ md: "h-8 w-8 text-xs",
77
+ lg: "h-12 w-12 text-base"
78
+ }, k = n.forwardRef(
79
+ ({ className: a, src: e, alt: r, fallback: i, size: s = "md", ...l }, p) => {
80
+ const [u, c] = n.useState(!1), f = e && !u, m = i ?? (r ? r.split(/\s+/).slice(0, 2).map((v) => {
81
+ var o;
82
+ return ((o = v[0]) == null ? void 0 : o.toUpperCase()) ?? "";
83
+ }).join("") : "");
84
+ return /* @__PURE__ */ t(
85
+ "span",
86
+ {
87
+ ref: p,
88
+ className: d(
89
+ "prui-avatar relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden",
90
+ "rounded-[var(--prui-radius-full)] bg-[var(--prui-raise)] text-[var(--prui-dim)] font-medium",
91
+ R[s],
92
+ a
93
+ ),
94
+ ...l,
95
+ children: f ? /* @__PURE__ */ t("img", { src: e, alt: r ?? "", className: "h-full w-full object-cover", onError: () => c(!0) }) : m
96
+ }
97
+ );
98
+ }
99
+ );
100
+ k.displayName = "Avatar";
101
+ const M = {
102
+ name: "Avatar",
103
+ props: [
104
+ { name: "src", type: "string", default: "undefined", control: "text" },
105
+ { name: "alt", type: "string", default: "undefined", control: "text" },
106
+ { name: "fallback", type: "string", default: "initials from alt", control: "text" },
107
+ { name: "size", type: "'sm' | 'md' | 'lg'", default: "'md'", control: "select", options: ["sm", "md", "lg"] }
108
+ ]
109
+ };
110
+ export {
111
+ k as Avatar,
112
+ x as Badge,
113
+ b as Card,
114
+ C as CardContent,
115
+ y as CardDescription,
116
+ h as CardFooter,
117
+ w as CardHeader,
118
+ N as CardTitle,
119
+ M as avatarPropsMeta,
120
+ B as badgePropsMeta,
121
+ F as cardPropsMeta
122
+ };
@@ -0,0 +1,3 @@
1
+ import { ClassValue } from 'clsx';
2
+ /** Merge class names; tailwind-aware. */
3
+ export declare function cn(...inputs: ClassValue[]): string;
@@ -0,0 +1,8 @@
1
+ import { clsx as o } from "clsx";
2
+ import { twMerge as t } from "tailwind-merge";
3
+ function n(...r) {
4
+ return t(o(r));
5
+ }
6
+ export {
7
+ n as cn
8
+ };
@@ -0,0 +1,25 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ export interface DialogProps {
4
+ open?: boolean;
5
+ defaultOpen?: boolean;
6
+ onOpenChange?: (open: boolean) => void;
7
+ /** Called to confirm a controlled close (X / backdrop / Escape). */
8
+ onClose?: () => void;
9
+ children?: React.ReactNode;
10
+ }
11
+ export declare const Dialog: {
12
+ ({ open: openProp, defaultOpen, onOpenChange, children }: DialogProps): React.JSX.Element;
13
+ displayName: string;
14
+ };
15
+ export interface DialogContentProps extends React.HTMLAttributes<HTMLDivElement> {
16
+ /** Accessibility label when no DialogTitle is rendered. */
17
+ ariaLabel?: string;
18
+ hideClose?: boolean;
19
+ }
20
+ export declare const DialogContent: React.ForwardRefExoticComponent<DialogContentProps & React.RefAttributes<HTMLDivElement>>;
21
+ export declare const DialogHeader: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => React.JSX.Element;
22
+ export declare const DialogTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLHeadingElement>>;
23
+ export declare const DialogDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
24
+ export declare const DialogFooter: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => React.JSX.Element;
25
+ export declare const dialogPropsMeta: PropsMeta;
@@ -0,0 +1,102 @@
1
+ import { jsx as a, jsxs as y } from "react/jsx-runtime";
2
+ import * as l from "react";
3
+ import { X as x } from "lucide-react";
4
+ import { cn as d } from "./cn.js";
5
+ const m = l.createContext(null);
6
+ function v() {
7
+ const e = l.useContext(m);
8
+ if (!e) throw new Error("Dialog parts must be used inside <Dialog>");
9
+ return e;
10
+ }
11
+ const w = ({ open: e, defaultOpen: o = !1, onOpenChange: t, children: n }) => {
12
+ const [c, p] = l.useState(o), u = e !== void 0, s = u ? e : c, i = l.useId(), f = (r) => {
13
+ u || p(r), t == null || t(r);
14
+ };
15
+ return /* @__PURE__ */ a(m.Provider, { value: { open: s, setOpen: f, labelId: i }, children: n });
16
+ };
17
+ w.displayName = "Dialog";
18
+ const D = l.forwardRef(
19
+ ({ className: e, children: o, ariaLabel: t, hideClose: n, onClick: c, ...p }, u) => {
20
+ const { open: s, setOpen: i, labelId: f } = v();
21
+ return l.useEffect(() => {
22
+ if (!s) return;
23
+ const r = (b) => {
24
+ b.key === "Escape" && i(!1);
25
+ };
26
+ document.addEventListener("keydown", r);
27
+ const g = document.body.style.overflow;
28
+ return document.body.style.overflow = "hidden", () => {
29
+ document.removeEventListener("keydown", r), document.body.style.overflow = g;
30
+ };
31
+ }, [s, i]), s ? /* @__PURE__ */ a(
32
+ "div",
33
+ {
34
+ className: "prui-dialog-overlay fixed inset-0 z-50 flex items-center justify-center p-4",
35
+ style: { backgroundColor: "rgba(0,0,0,0.55)" },
36
+ onMouseDown: (r) => {
37
+ r.target === r.currentTarget && i(!1);
38
+ },
39
+ children: /* @__PURE__ */ y(
40
+ "div",
41
+ {
42
+ ref: u,
43
+ role: "dialog",
44
+ "aria-modal": "true",
45
+ "aria-label": t,
46
+ "aria-labelledby": t ? void 0 : f,
47
+ className: d(
48
+ "prui-dialog-content relative z-10 w-full max-w-lg rounded-[var(--prui-radius)]",
49
+ "border border-[var(--prui-line)] bg-[var(--prui-surface)] shadow-xl",
50
+ "max-h-[85vh] overflow-auto outline-none",
51
+ e
52
+ ),
53
+ onClick: c,
54
+ ...p,
55
+ children: [
56
+ o,
57
+ n ? null : /* @__PURE__ */ a(
58
+ "button",
59
+ {
60
+ type: "button",
61
+ "aria-label": "Close",
62
+ onClick: () => i(!1),
63
+ className: "absolute right-3 top-3 rounded-[var(--prui-radius-1)] p-1 text-[var(--prui-dim)] hover:text-[var(--prui-fg)] hover:bg-[var(--prui-raise)] cursor-pointer",
64
+ children: /* @__PURE__ */ a(x, { className: "h-4 w-4", "aria-hidden": !0 })
65
+ }
66
+ )
67
+ ]
68
+ }
69
+ )
70
+ }
71
+ ) : null;
72
+ }
73
+ );
74
+ D.displayName = "DialogContent";
75
+ const j = ({ className: e, ...o }) => /* @__PURE__ */ a("div", { className: d("prui-dialog-header flex flex-col gap-1 p-4 pb-2", e), ...o }), h = l.forwardRef(
76
+ ({ className: e, ...o }, t) => {
77
+ const { labelId: n } = v();
78
+ return /* @__PURE__ */ a("h2", { ref: t, id: n, className: d("prui-dialog-title text-base font-semibold text-[var(--prui-fg)]", e), ...o });
79
+ }
80
+ );
81
+ h.displayName = "DialogTitle";
82
+ const N = l.forwardRef(
83
+ ({ className: e, ...o }, t) => /* @__PURE__ */ a("p", { ref: t, className: d("prui-dialog-description text-sm text-[var(--prui-dim)]", e), ...o })
84
+ );
85
+ N.displayName = "DialogDescription";
86
+ const I = ({ className: e, ...o }) => /* @__PURE__ */ a("div", { className: d("prui-dialog-footer flex items-center justify-end gap-2 p-4 pt-2", e), ...o }), R = {
87
+ name: "Dialog",
88
+ props: [
89
+ { name: "open", type: "boolean", default: "undefined", control: "boolean" },
90
+ { name: "defaultOpen", type: "boolean", default: "false", control: "boolean" },
91
+ { name: "onOpenChange", type: "(open: boolean) => void", default: null, control: "none" }
92
+ ]
93
+ };
94
+ export {
95
+ w as Dialog,
96
+ D as DialogContent,
97
+ N as DialogDescription,
98
+ I as DialogFooter,
99
+ j as DialogHeader,
100
+ h as DialogTitle,
101
+ R as dialogPropsMeta
102
+ };
@@ -0,0 +1,24 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ export interface DropdownItem {
4
+ label: string;
5
+ onSelect?: () => void;
6
+ danger?: boolean;
7
+ disabled?: boolean;
8
+ separatorBefore?: boolean;
9
+ }
10
+ export interface DropdownProps {
11
+ items?: DropdownItem[];
12
+ trigger?: React.ReactNode;
13
+ children?: React.ReactNode;
14
+ open?: boolean;
15
+ defaultOpen?: boolean;
16
+ onOpenChange?: (open: boolean) => void;
17
+ align?: "start" | "end";
18
+ className?: string;
19
+ }
20
+ export declare const Dropdown: {
21
+ ({ items, trigger, children, open: openProp, defaultOpen, onOpenChange, align, className, }: DropdownProps): React.JSX.Element;
22
+ displayName: string;
23
+ };
24
+ export declare const dropdownPropsMeta: PropsMeta;
@@ -0,0 +1,89 @@
1
+ import { jsxs as p, jsx as a } from "react/jsx-runtime";
2
+ import * as l from "react";
3
+ import { cn as i } from "./cn.js";
4
+ const k = ({
5
+ items: f,
6
+ trigger: m,
7
+ children: v,
8
+ open: u,
9
+ defaultOpen: b = !1,
10
+ onOpenChange: d,
11
+ align: y = "start",
12
+ className: w
13
+ }) => {
14
+ const [x, g] = l.useState(b), c = u !== void 0, n = c ? u : x, s = l.useRef(null), o = (e) => {
15
+ c || g(e), d == null || d(e);
16
+ };
17
+ return l.useEffect(() => {
18
+ if (!n) return;
19
+ const e = (r) => {
20
+ s.current && !s.current.contains(r.target) && o(!1);
21
+ }, t = (r) => {
22
+ r.key === "Escape" && o(!1);
23
+ };
24
+ return document.addEventListener("mousedown", e), document.addEventListener("keydown", t), () => {
25
+ document.removeEventListener("mousedown", e), document.removeEventListener("keydown", t);
26
+ };
27
+ }), /* @__PURE__ */ p("div", { ref: s, className: i("prui-dropdown relative inline-block", w), "data-state": n ? "open" : "closed", children: [
28
+ /* @__PURE__ */ a(
29
+ "div",
30
+ {
31
+ role: "button",
32
+ tabIndex: 0,
33
+ "aria-haspopup": "menu",
34
+ "aria-expanded": n,
35
+ onClick: () => o(!n),
36
+ onKeyDown: (e) => {
37
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), o(!n));
38
+ },
39
+ children: m
40
+ }
41
+ ),
42
+ n ? /* @__PURE__ */ a(
43
+ "div",
44
+ {
45
+ role: "menu",
46
+ className: i(
47
+ "prui-dropdown-menu absolute z-50 mt-1 min-w-40 rounded-[var(--prui-radius)] border border-[var(--prui-line)]",
48
+ "bg-[var(--prui-surface)] p-1 shadow-lg",
49
+ y === "end" ? "right-0" : "left-0"
50
+ ),
51
+ children: v ?? (f ?? []).map((e, t) => /* @__PURE__ */ p(l.Fragment, { children: [
52
+ e.separatorBefore ? /* @__PURE__ */ a("div", { className: "my-1 h-px bg-[var(--prui-line)]" }) : null,
53
+ /* @__PURE__ */ a(
54
+ "button",
55
+ {
56
+ type: "button",
57
+ role: "menuitem",
58
+ disabled: e.disabled,
59
+ onClick: () => {
60
+ var r;
61
+ e.disabled || (o(!1), (r = e.onSelect) == null || r.call(e));
62
+ },
63
+ className: i(
64
+ "flex w-full items-center rounded-[calc(var(--prui-radius)-1px)] px-2.5 py-1.5 text-left text-sm",
65
+ "hover:bg-[var(--prui-raise)] cursor-pointer disabled:opacity-50 disabled:pointer-events-none",
66
+ e.danger ? "text-[var(--prui-danger)]" : "text-[var(--prui-fg)]"
67
+ ),
68
+ children: e.label
69
+ }
70
+ )
71
+ ] }, `${e.label}-${t}`))
72
+ }
73
+ ) : null
74
+ ] });
75
+ };
76
+ k.displayName = "Dropdown";
77
+ const E = {
78
+ name: "Dropdown",
79
+ props: [
80
+ { name: "items", type: "DropdownItem[]", default: "[]", control: "object" },
81
+ { name: "trigger", type: "ReactNode", default: null, control: "none" },
82
+ { name: "align", type: "'start' | 'end'", default: "'start'", control: "select", options: ["start", "end"] },
83
+ { name: "onOpenChange", type: "(open: boolean) => void", default: null, control: "none" }
84
+ ]
85
+ };
86
+ export {
87
+ k as Dropdown,
88
+ E as dropdownPropsMeta
89
+ };
@@ -0,0 +1,14 @@
1
+ /** PRUI primitives layer: standard composition building blocks plus cn(). */
2
+ export { cn } from './cn';
3
+ export type { PropsMeta, PropMeta, PropControl } from './props-meta';
4
+ export { Button, buttonPropsMeta, type ButtonProps, type ButtonVariant, type ButtonSize, } from './button';
5
+ export { Input, inputPropsMeta, Textarea, textareaPropsMeta, type InputProps, type TextareaProps, } from './input';
6
+ export { Label, labelPropsMeta, Separator, separatorPropsMeta, type LabelProps, type SeparatorProps } from './label';
7
+ export { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, selectPropsMeta, type SelectProps, type SelectOption, type SelectTriggerProps, type SelectValueProps, type SelectContentProps, type SelectItemProps, } from './select';
8
+ export { Switch, switchPropsMeta, type SwitchProps } from './switch';
9
+ export { Tabs, TabsList, TabsTrigger, TabsContent, tabsPropsMeta, type TabsProps, type TabsListProps, type TabsTriggerProps, type TabsContentProps, } from './tabs';
10
+ export { Badge, badgePropsMeta, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, cardPropsMeta, Avatar, avatarPropsMeta, type BadgeProps, type BadgeVariant, type AvatarProps, } from './card';
11
+ export { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, dialogPropsMeta, type DialogProps, type DialogContentProps, } from './dialog';
12
+ export { Dropdown, dropdownPropsMeta, type DropdownProps, type DropdownItem, } from './dropdown';
13
+ export { ScrollArea, scrollAreaPropsMeta, type ScrollAreaProps } from './scroll-area';
14
+ export { Modal, confirmModal, modalPropsMeta, confirmModalPropsMeta, type ModalProps, type ModalSize, type ConfirmModalOptions, type ConfirmModalType, } from './modal';
@@ -0,0 +1,8 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
4
+ export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
5
+ export declare const inputPropsMeta: PropsMeta;
6
+ export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
7
+ export declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
8
+ export declare const textareaPropsMeta: PropsMeta;
@@ -0,0 +1,42 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import * as n from "react";
3
+ import { cn as o } from "./cn.js";
4
+ const l = "prui-input w-full bg-[var(--prui-background)] text-[var(--prui-fg)] placeholder:text-[var(--prui-dim)] border border-[var(--prui-line)] rounded-[var(--prui-radius)] px-3 h-9 text-sm outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30 disabled:opacity-50 disabled:cursor-not-allowed", u = n.forwardRef(
5
+ ({ className: e, type: t = "text", ...a }, p) => /* @__PURE__ */ r("input", { ref: p, type: t, className: o(l, e), ...a })
6
+ );
7
+ u.displayName = "Input";
8
+ const c = {
9
+ name: "Input",
10
+ props: [
11
+ { name: "type", type: "string", default: "'text'", control: "select", options: ["text", "password", "email", "number", "search"] },
12
+ { name: "value", type: "string", default: null, control: "text" },
13
+ { name: "placeholder", type: "string", default: "undefined", control: "text" },
14
+ { name: "disabled", type: "boolean", default: "false", control: "boolean" },
15
+ { name: "onChange", type: "(e) => void", default: null, control: "none" }
16
+ ]
17
+ }, i = n.forwardRef(
18
+ ({ className: e, ...t }, a) => /* @__PURE__ */ r(
19
+ "textarea",
20
+ {
21
+ ref: a,
22
+ className: o(l, "h-auto min-h-20 py-2 resize-y", e),
23
+ ...t
24
+ }
25
+ )
26
+ );
27
+ i.displayName = "Textarea";
28
+ const m = {
29
+ name: "Textarea",
30
+ props: [
31
+ { name: "value", type: "string", default: null, control: "textarea" },
32
+ { name: "placeholder", type: "string", default: "undefined", control: "text" },
33
+ { name: "rows", type: "number", default: "4", control: "number" },
34
+ { name: "onChange", type: "(e) => void", default: null, control: "none" }
35
+ ]
36
+ };
37
+ export {
38
+ u as Input,
39
+ i as Textarea,
40
+ c as inputPropsMeta,
41
+ m as textareaPropsMeta
42
+ };
@@ -0,0 +1,12 @@
1
+ import { PropsMeta } from './props-meta';
2
+ import * as React from "react";
3
+ export type LabelProps = React.LabelHTMLAttributes<HTMLLabelElement>;
4
+ export declare const Label: React.ForwardRefExoticComponent<LabelProps & React.RefAttributes<HTMLLabelElement>>;
5
+ export declare const labelPropsMeta: PropsMeta;
6
+ export type SeparatorProps = React.HTMLAttributes<HTMLDivElement> & {
7
+ orientation?: "horizontal" | "vertical";
8
+ };
9
+ export declare const Separator: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
10
+ orientation?: "horizontal" | "vertical";
11
+ } & React.RefAttributes<HTMLDivElement>>;
12
+ export declare const separatorPropsMeta: PropsMeta;
@@ -0,0 +1,52 @@
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import * as o from "react";
3
+ import { cn as l } from "./cn.js";
4
+ const i = o.forwardRef(
5
+ ({ className: e, ...a }, r) => /* @__PURE__ */ t(
6
+ "label",
7
+ {
8
+ ref: r,
9
+ className: l(
10
+ "prui-label block text-sm font-medium text-[var(--prui-fg)] select-none",
11
+ e
12
+ ),
13
+ ...a
14
+ }
15
+ )
16
+ );
17
+ i.displayName = "Label";
18
+ const c = {
19
+ name: "Label",
20
+ props: [
21
+ { name: "htmlFor", type: "string", default: "undefined", control: "text" },
22
+ { name: "children", type: "ReactNode", default: null, control: "text" }
23
+ ]
24
+ }, p = o.forwardRef(
25
+ ({ className: e, orientation: a = "horizontal", ...r }, n) => /* @__PURE__ */ t(
26
+ "div",
27
+ {
28
+ ref: n,
29
+ role: "separator",
30
+ "aria-orientation": a,
31
+ className: l(
32
+ "prui-separator shrink-0 bg-[var(--prui-line)]",
33
+ a === "horizontal" ? "h-px w-full" : "w-px h-full min-h-4",
34
+ e
35
+ ),
36
+ ...r
37
+ }
38
+ )
39
+ );
40
+ p.displayName = "Separator";
41
+ const f = {
42
+ name: "Separator",
43
+ props: [
44
+ { name: "orientation", type: "'horizontal' | 'vertical'", default: "'horizontal'", control: "select", options: ["horizontal", "vertical"] }
45
+ ]
46
+ };
47
+ export {
48
+ i as Label,
49
+ p as Separator,
50
+ c as labelPropsMeta,
51
+ f as separatorPropsMeta
52
+ };