@waveinno/ui 0.0.0-stage → 0.1.1
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/CHANGELOG.md +39 -0
- package/LICENSE +5 -0
- package/README.md +64 -2
- package/dist/brand/waveinno-logo.svg +1 -0
- package/dist/components/brand/index.d.ts +3 -0
- package/dist/components/brand/index.js +1 -0
- package/dist/components/brand/logo.d.ts +89 -0
- package/dist/components/brand/logo.js +1 -0
- package/dist/components/brand/waveinno-logo.d.ts +52 -0
- package/dist/components/brand/waveinno-logo.js +1 -0
- package/dist/components/charts/bar-chart.d.ts +20 -0
- package/dist/components/charts/bar-chart.js +1 -0
- package/dist/components/charts/bar-list.d.ts +27 -0
- package/dist/components/charts/bar-list.js +1 -0
- package/dist/components/charts/chart-card.d.ts +32 -0
- package/dist/components/charts/chart-card.js +1 -0
- package/dist/components/charts/donut-chart.d.ts +29 -0
- package/dist/components/charts/donut-chart.js +1 -0
- package/dist/components/charts/gauge-chart.d.ts +21 -0
- package/dist/components/charts/gauge-chart.js +1 -0
- package/dist/components/charts/heatmap.d.ts +23 -0
- package/dist/components/charts/heatmap.js +1 -0
- package/dist/components/charts/index.d.ts +10 -0
- package/dist/components/charts/index.js +1 -0
- package/dist/components/charts/line-chart.d.ts +24 -0
- package/dist/components/charts/line-chart.js +1 -0
- package/dist/components/charts/palette.d.ts +39 -0
- package/dist/components/charts/palette.js +1 -0
- package/dist/components/charts/trend-chart.d.ts +22 -0
- package/dist/components/charts/trend-chart.js +1 -0
- package/dist/components/patterns/activity-feed.d.ts +28 -0
- package/dist/components/patterns/activity-feed.js +1 -0
- package/dist/components/patterns/data-table-cells.d.ts +39 -0
- package/dist/components/patterns/data-table-cells.js +1 -0
- package/dist/components/patterns/data-table-edit.d.ts +56 -0
- package/dist/components/patterns/data-table-edit.js +1 -0
- package/dist/components/patterns/data-table-filters.d.ts +84 -0
- package/dist/components/patterns/data-table-filters.js +1 -0
- package/dist/components/patterns/data-table.d.ts +76 -0
- package/dist/components/patterns/data-table.js +2 -0
- package/dist/components/patterns/index.d.ts +16 -0
- package/dist/components/patterns/index.js +1 -0
- package/dist/components/patterns/kanban.d.ts +28 -0
- package/dist/components/patterns/kanban.js +1 -0
- package/dist/components/patterns/kpi-card.d.ts +22 -0
- package/dist/components/patterns/kpi-card.js +1 -0
- package/dist/components/patterns/money.d.ts +28 -0
- package/dist/components/patterns/money.js +1 -0
- package/dist/components/patterns/page-header.d.ts +38 -0
- package/dist/components/patterns/page-header.js +1 -0
- package/dist/components/patterns/page-hero.d.ts +50 -0
- package/dist/components/patterns/page-hero.js +1 -0
- package/dist/components/patterns/page-shell.d.ts +27 -0
- package/dist/components/patterns/page-shell.js +1 -0
- package/dist/components/patterns/stat-card.d.ts +56 -0
- package/dist/components/patterns/stat-card.js +1 -0
- package/dist/components/patterns/states.d.ts +27 -0
- package/dist/components/patterns/states.js +1 -0
- package/dist/components/patterns/timeline.d.ts +100 -0
- package/dist/components/patterns/timeline.js +1 -0
- package/dist/components/ui/avatar.d.ts +37 -0
- package/dist/components/ui/avatar.js +1 -0
- package/dist/components/ui/badge.d.ts +41 -0
- package/dist/components/ui/badge.js +1 -0
- package/dist/components/ui/button.d.ts +25 -0
- package/dist/components/ui/button.js +1 -0
- package/dist/components/ui/calendar.d.ts +42 -0
- package/dist/components/ui/calendar.js +1 -0
- package/dist/components/ui/card.d.ts +11 -0
- package/dist/components/ui/card.js +1 -0
- package/dist/components/ui/checkbox.d.ts +3 -0
- package/dist/components/ui/checkbox.js +1 -0
- package/dist/components/ui/combobox.d.ts +47 -0
- package/dist/components/ui/combobox.js +1 -0
- package/dist/components/ui/confirm-dialog.d.ts +34 -0
- package/dist/components/ui/confirm-dialog.js +1 -0
- package/dist/components/ui/date-picker.d.ts +80 -0
- package/dist/components/ui/date-picker.js +1 -0
- package/dist/components/ui/dialog.d.ts +54 -0
- package/dist/components/ui/dialog.js +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +44 -0
- package/dist/components/ui/dropdown-menu.js +1 -0
- package/dist/components/ui/form-field.d.ts +27 -0
- package/dist/components/ui/form-field.js +1 -0
- package/dist/components/ui/index.d.ts +26 -0
- package/dist/components/ui/index.js +1 -0
- package/dist/components/ui/input.d.ts +21 -0
- package/dist/components/ui/input.js +1 -0
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/label.js +1 -0
- package/dist/components/ui/popover.d.ts +22 -0
- package/dist/components/ui/popover.js +1 -0
- package/dist/components/ui/progress.d.ts +43 -0
- package/dist/components/ui/progress.js +1 -0
- package/dist/components/ui/segmented.d.ts +42 -0
- package/dist/components/ui/segmented.js +1 -0
- package/dist/components/ui/select.d.ts +10 -0
- package/dist/components/ui/select.js +1 -0
- package/dist/components/ui/separator.d.ts +3 -0
- package/dist/components/ui/separator.js +1 -0
- package/dist/components/ui/sheet.d.ts +19 -0
- package/dist/components/ui/sheet.js +1 -0
- package/dist/components/ui/skeleton.d.ts +10 -0
- package/dist/components/ui/skeleton.js +1 -0
- package/dist/components/ui/switch.d.ts +3 -0
- package/dist/components/ui/switch.js +1 -0
- package/dist/components/ui/tabs.d.ts +19 -0
- package/dist/components/ui/tabs.js +1 -0
- package/dist/components/ui/time-picker.d.ts +52 -0
- package/dist/components/ui/time-picker.js +1 -0
- package/dist/components/ui/tooltip.d.ts +13 -0
- package/dist/components/ui/tooltip.js +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/use-hotkey.d.ts +16 -0
- package/dist/hooks/use-hotkey.js +1 -0
- package/dist/hooks/use-media-query.d.ts +4 -0
- package/dist/hooks/use-media-query.js +1 -0
- package/dist/hooks/use-mounted.d.ts +2 -0
- package/dist/hooks/use-mounted.js +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +1 -0
- package/dist/lib/boot-script.d.ts +15 -0
- package/dist/lib/boot-script.js +12 -0
- package/dist/lib/currency.d.ts +55 -0
- package/dist/lib/currency.js +1 -0
- package/dist/lib/format.d.ts +28 -0
- package/dist/lib/format.js +1 -0
- package/dist/lib/index.d.ts +5 -0
- package/dist/lib/index.js +1 -0
- package/dist/lib/utils.d.ts +7 -0
- package/dist/lib/utils.js +1 -0
- package/dist/shell/app-shell.d.ts +18 -0
- package/dist/shell/app-shell.js +1 -0
- package/dist/shell/app-switcher.d.ts +9 -0
- package/dist/shell/app-switcher.js +1 -0
- package/dist/shell/appearance-controls.d.ts +13 -0
- package/dist/shell/appearance-controls.js +1 -0
- package/dist/shell/command-palette.d.ts +9 -0
- package/dist/shell/command-palette.js +1 -0
- package/dist/shell/config.d.ts +66 -0
- package/dist/shell/config.js +1 -0
- package/dist/shell/icon-rail.d.ts +2 -0
- package/dist/shell/icon-rail.js +1 -0
- package/dist/shell/index.d.ts +7 -0
- package/dist/shell/index.js +1 -0
- package/dist/shell/mobile-nav.d.ts +7 -0
- package/dist/shell/mobile-nav.js +1 -0
- package/dist/shell/module-sidebar.d.ts +9 -0
- package/dist/shell/module-sidebar.js +1 -0
- package/dist/shell/notifications.d.ts +5 -0
- package/dist/shell/notifications.js +1 -0
- package/dist/shell/placeholder-screen.d.ts +11 -0
- package/dist/shell/placeholder-screen.js +1 -0
- package/dist/shell/record-drawer.d.ts +32 -0
- package/dist/shell/record-drawer.js +1 -0
- package/dist/shell/registry.d.ts +24 -0
- package/dist/shell/registry.js +1 -0
- package/dist/shell/topbar.d.ts +9 -0
- package/dist/shell/topbar.js +1 -0
- package/dist/shell/use-active.d.ts +21 -0
- package/dist/shell/use-active.js +1 -0
- package/dist/shell/user-menu.d.ts +5 -0
- package/dist/shell/user-menu.js +1 -0
- package/dist/store/app-store.d.ts +10 -0
- package/dist/store/app-store.js +1 -0
- package/dist/store/drawer-store.d.ts +22 -0
- package/dist/store/drawer-store.js +1 -0
- package/dist/store/index.d.ts +5 -0
- package/dist/store/index.js +1 -0
- package/dist/store/settings-store.d.ts +22 -0
- package/dist/store/settings-store.js +1 -0
- package/dist/store/ui-store.d.ts +28 -0
- package/dist/store/ui-store.js +1 -0
- package/dist/styles.css +658 -0
- package/dist/types.d.ts +140 -0
- package/dist/types.js +0 -0
- package/package.json +98 -4
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Confirmation for actions that cannot be taken back — delete, suspend,
|
|
4
|
+
* void, revoke.
|
|
5
|
+
*
|
|
6
|
+
* Built to slow the hand down just enough: a clear icon in a halo of its
|
|
7
|
+
* tone, the consequence in one sentence, the actual things that will go
|
|
8
|
+
* (first few by name, then "+ n more"), and — for big or irreversible
|
|
9
|
+
* actions — a word to type before the button unlocks. The confirm button
|
|
10
|
+
* names the action and the count ("Delete 12 rows"), never just "OK".
|
|
11
|
+
* Focus starts on Cancel, so Enter alone never destroys anything.
|
|
12
|
+
*/
|
|
13
|
+
export interface ConfirmDialogProps {
|
|
14
|
+
open: boolean;
|
|
15
|
+
onOpenChange: (open: boolean) => void;
|
|
16
|
+
title: React.ReactNode;
|
|
17
|
+
description?: React.ReactNode;
|
|
18
|
+
/** What goes: names shown in a list (first `previewCount`, then "+ n more"). */
|
|
19
|
+
items?: string[];
|
|
20
|
+
previewCount?: number;
|
|
21
|
+
/** Require typing this word (e.g. "DELETE") before the button unlocks. */
|
|
22
|
+
confirmWord?: string;
|
|
23
|
+
confirmLabel: React.ReactNode;
|
|
24
|
+
cancelLabel?: React.ReactNode;
|
|
25
|
+
tone?: "danger" | "warning";
|
|
26
|
+
icon?: React.ReactNode;
|
|
27
|
+
/** Runs on confirm; the button spins until it settles, the dialog closes on success. */
|
|
28
|
+
onConfirm: () => void | Promise<void>;
|
|
29
|
+
labels?: {
|
|
30
|
+
typeToConfirm?: (word: string) => string;
|
|
31
|
+
more?: (n: number) => string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export declare function ConfirmDialog({ open, onOpenChange, title, description, items, previewCount, confirmWord, confirmLabel, cancelLabel, tone, icon, onConfirm, labels, }: ConfirmDialogProps): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as i from"@radix-ui/react-dialog";import{CircleAlert as L,ShieldAlert as $,Trash2 as A}from"lucide-react";import*as s from"react";import{cn as n}from"../../lib/utils.js";import{Button as C}from"./button.js";import{DialogOverlay as F}from"./dialog.js";import{Input as O}from"./input.js";function q({open:d,onOpenChange:p,title:R,description:x,items:b,previewCount:D=3,confirmWord:l,confirmLabel:P,cancelLabel:k="Cancel",tone:T="danger",icon:z,onConfirm:B,labels:S}){const[c,f]=s.useState(""),[m,v]=s.useState(!1),[N,g]=s.useState(null),_=s.useRef(null);s.useEffect(()=>{d&&(f(""),g(null))},[d]);const y=!!l&&c.trim().toUpperCase()!==l.toUpperCase(),h={typeToConfirm:t=>`Type ${t} to confirm`,more:t=>`+ ${t} more`,...S},r=T==="danger",u=b?.slice(0,D)??[],w=(b?.length??0)-u.length;return e(i.Root,{open:d,onOpenChange:t=>!m&&p(t),children:a(i.Portal,{children:[e(F,{}),a(i.Content,{"data-dialog":"",onOpenAutoFocus:t=>{t.preventDefault(),_.current?.focus()},className:"fixed left-1/2 top-1/2 z-50 w-[calc(100vw-32px)] max-w-[440px] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-[18px] border border-border bg-raised outline-none",children:[e("div",{"aria-hidden":!0,className:n("pointer-events-none absolute inset-x-0 top-0 h-28",r?"bg-[radial-gradient(70%_100%_at_50%_0%,var(--danger-subtle),transparent)]":"bg-[radial-gradient(70%_100%_at_50%_0%,var(--warning-subtle),transparent)]")}),a("div",{className:"relative px-6 pb-5 pt-7 text-center",children:[a("div",{className:"relative mx-auto mb-4 grid size-14 place-items-center",children:[e("span",{className:n("absolute inset-0 rounded-full",r?"bg-danger/10":"bg-warning/10")}),e("span",{className:n("absolute inset-[7px] rounded-full",r?"bg-danger/15":"bg-warning/15")}),e("span",{className:n("relative grid size-9 place-items-center rounded-full text-white shadow-[inset_0_1px_0_rgba(255,255,255,.3)]",r?"bg-[linear-gradient(180deg,#ef4444,#dc2626)] shadow-[0_6px_16px_-6px_rgba(220,38,38,.7)]":"bg-[linear-gradient(180deg,#f59e0b,#b45309)] shadow-[0_6px_16px_-6px_rgba(180,83,9,.7)]","[&_svg]:size-[18px]"),children:z??(r?e(A,{}):e($,{}))})]}),e(i.Title,{className:"disp text-[17px] font-semibold leading-6 text-text",children:R}),x?e(i.Description,{className:"mx-auto mt-1.5 max-w-[34ch] text-[13px] leading-5 text-muted",children:x}):null,u.length?a("ul",{className:"mt-4 space-y-1 rounded-[12px] border border-border bg-surface p-2 text-left",children:[u.map((t,o)=>a("li",{className:"flex items-center gap-2 rounded-[8px] px-2 py-1.5 text-[13px] text-body",children:[e("span",{className:n("size-1.5 shrink-0 rounded-full",r?"bg-danger":"bg-warning")}),e("span",{className:"truncate",children:t})]},`${t}-${o}`)),w>0?e("li",{className:"px-2 py-1 text-[12px] font-medium text-muted",children:h.more(w)}):null]}):null,l?a("div",{className:"mt-4 text-left",children:[e("label",{className:"mb-1.5 block text-[12px] font-medium text-muted",children:h.typeToConfirm(l).split(l).map((t,o,E)=>a(s.Fragment,{children:[t,o<E.length-1?e("b",{className:n("font-semibold",r?"text-danger":"text-warning"),children:l}):null]},o))}),e(O,{value:c,onChange:t=>f(t.target.value),autoComplete:"off",spellCheck:!1,className:"text-center font-medium tracking-[0.2em] uppercase",state:!y&&c?"success":"default"})]}):null,N?a("p",{role:"alert",className:"mt-3 flex items-center justify-center gap-1.5 text-[12.5px] text-danger",children:[e(L,{className:"size-3.5"})," ",N]}):null]}),a("div",{className:"relative grid grid-cols-2 gap-2 border-t border-border bg-surface/70 px-6 py-4",children:[e(C,{ref:_,disabled:m,onClick:()=>p(!1),children:k}),e(C,{variant:r?"danger":"primary",disabled:y,loading:m,className:n(r&&"shadow-[0_6px_16px_-8px_rgba(220,38,38,.8)]"),onClick:async()=>{v(!0),g(null);try{await B(),p(!1)}catch(t){g(t instanceof Error?t.message:String(t))}finally{v(!1)}},children:P})]})]})]})})}export{q as ConfirmDialog};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type Weekday } from "./calendar";
|
|
3
|
+
/**
|
|
4
|
+
* Date controls — DatePicker, DateTimePicker and DateRangePicker, all on the
|
|
5
|
+
* same Calendar so they look and behave as one family.
|
|
6
|
+
*
|
|
7
|
+
* Values are plain strings, exactly what an API takes, so forms never deal with
|
|
8
|
+
* time zones: "2026-10-10" for a day, "2026-10-10T14:30" for a local date and
|
|
9
|
+
* time (like <input type="datetime-local">), { from, to } of days for a range.
|
|
10
|
+
* "" means empty.
|
|
11
|
+
*/
|
|
12
|
+
interface Shared {
|
|
13
|
+
id?: string;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
clearable?: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
/** Month and weekday names and digits, e.g. "bn-BD". */
|
|
19
|
+
locale?: string;
|
|
20
|
+
/** 0 = Sunday … 6 = Saturday. */
|
|
21
|
+
weekStartsOn?: Weekday;
|
|
22
|
+
}
|
|
23
|
+
export declare function DatePicker({ value, onChange, id, placeholder, min, max, disabled, clearable, className, locale, weekStartsOn, labels, }: Shared & {
|
|
24
|
+
/** "2026-10-10" or "". */
|
|
25
|
+
value: string;
|
|
26
|
+
onChange: (value: string) => void;
|
|
27
|
+
min?: string;
|
|
28
|
+
max?: string;
|
|
29
|
+
labels?: {
|
|
30
|
+
today?: string;
|
|
31
|
+
clear?: string;
|
|
32
|
+
};
|
|
33
|
+
}): React.JSX.Element;
|
|
34
|
+
export declare function DateTimePicker({ value, onChange, id, placeholder, min, max, step, hourCycle, defaultTime, disabled, clearable, className, locale, weekStartsOn, labels, }: Shared & {
|
|
35
|
+
/** "2026-10-10T14:30" (local wall time) or "". */
|
|
36
|
+
value: string;
|
|
37
|
+
onChange: (value: string) => void;
|
|
38
|
+
/** Earliest / latest, "YYYY-MM-DDTHH:mm". */
|
|
39
|
+
min?: string;
|
|
40
|
+
max?: string;
|
|
41
|
+
step?: number;
|
|
42
|
+
hourCycle?: 12 | 24;
|
|
43
|
+
/** Time used when a day is picked before any time. */
|
|
44
|
+
defaultTime?: string;
|
|
45
|
+
labels?: {
|
|
46
|
+
now?: string;
|
|
47
|
+
done?: string;
|
|
48
|
+
clear?: string;
|
|
49
|
+
time?: string;
|
|
50
|
+
};
|
|
51
|
+
}): React.JSX.Element;
|
|
52
|
+
export interface DateRangeValue {
|
|
53
|
+
/** "2026-10-01" or "". */
|
|
54
|
+
from: string;
|
|
55
|
+
/** "2026-10-07" or "". */
|
|
56
|
+
to: string;
|
|
57
|
+
}
|
|
58
|
+
export interface DateRangePreset {
|
|
59
|
+
label: string;
|
|
60
|
+
range: () => {
|
|
61
|
+
from: Date;
|
|
62
|
+
to: Date;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** The presets reports reach for most. Pass your own (translated) list to replace them. */
|
|
66
|
+
export declare const DEFAULT_RANGE_PRESETS: DateRangePreset[];
|
|
67
|
+
export declare function DateRangePicker({ value, onChange, id, placeholder, min, max, presets, numberOfMonths, disabled, clearable, className, locale, weekStartsOn, labels, }: Shared & {
|
|
68
|
+
value: DateRangeValue;
|
|
69
|
+
onChange: (value: DateRangeValue) => void;
|
|
70
|
+
min?: string;
|
|
71
|
+
max?: string;
|
|
72
|
+
/** Quick ranges on the left; [] hides the list. */
|
|
73
|
+
presets?: DateRangePreset[];
|
|
74
|
+
numberOfMonths?: 1 | 2;
|
|
75
|
+
labels?: {
|
|
76
|
+
clear?: string;
|
|
77
|
+
pickEnd?: string;
|
|
78
|
+
};
|
|
79
|
+
}): React.JSX.Element;
|
|
80
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import*as g from"@radix-ui/react-popover";import{CalendarClock as j,CalendarDays as W,CalendarRange as _,X as H}from"lucide-react";import*as A from"react";import{cn as v}from"../../lib/utils.js";import{addDays as E,addMonths as G,Calendar as I,parseIsoDay as x,toIsoDay as r}from"./calendar.js";import{inputClass as U}from"./input.js";import{formatTime as X,parseTime as q,TimeColumns as J,toTime as Y}from"./time-picker.js";const S="cursor-pointer rounded-ctl px-2 py-1 text-[12.5px] transition-colors disabled:cursor-not-allowed disabled:opacity-40",z="z-[60] rounded-dlg border border-border bg-raised p-3 shadow-elev3 outline-none";function B({id:t,icon:a,text:u,placeholder:N,open:P,disabled:h,onClear:l,clearLabel:p,className:C}){return s("div",{className:v("relative",C),children:[e(g.Trigger,{asChild:!0,disabled:h,children:s("button",{id:t,type:"button",className:v(U,"flex cursor-pointer items-center gap-2 text-left",P&&"border-primary ring-2 ring-primary/20",l&&u&&"pr-9"),children:[e(a,{className:"size-4 shrink-0 text-muted"}),e("span",{className:v("num min-w-0 flex-1 truncate",!u&&"text-placeholder"),children:u??N})]})}),l&&u&&!h?e("button",{type:"button","aria-label":p,onClick:l,className:"absolute right-2 top-1/2 grid size-6 -translate-y-1/2 cursor-pointer place-items-center rounded-full text-muted transition-colors hover:bg-hover hover:text-text",children:e(H,{className:"size-3.5"})}):null]})}const V=t=>new Intl.DateTimeFormat(t,{weekday:"short",day:"numeric",month:"short",year:"numeric"});function ne({value:t,onChange:a,id:u,placeholder:N="Pick a date",min:P,max:h,disabled:l,clearable:p=!0,className:C,locale:T="en-GB",weekStartsOn:F=1,labels:R}){const[y,O]=A.useState(!1),D=x(t),b=x(P),n=x(h),o=new Date,c=(!b||r(o)>=r(b))&&(!n||r(o)<=r(n)),w={today:"Today",clear:"Clear",...R},f=m=>{a(r(m)),O(!1)};return s(g.Root,{open:y,onOpenChange:O,children:[e(B,{id:u,icon:W,text:D?V(T).format(D):null,placeholder:N,open:y,disabled:l,onClear:p?()=>a(""):void 0,clearLabel:w.clear,className:C}),e(g.Portal,{children:s(g.Content,{"data-pop":"",align:"start",sideOffset:6,collisionPadding:12,onOpenAutoFocus:m=>m.preventDefault(),className:z,children:[e(I,{selected:D,onDayClick:f,min:b,max:n,locale:T,weekStartsOn:F,autoFocus:!0}),s("div",{className:"mt-2 flex items-center justify-between border-t border-border pt-2",children:[e("button",{type:"button",disabled:!c,onClick:()=>f(o),className:v(S,"font-medium text-primary hover:bg-primary-subtle"),children:w.today}),p&&D?e("button",{type:"button",onClick:()=>{a(""),O(!1)},className:v(S,"text-muted hover:bg-hover hover:text-text"),children:w.clear}):null]})]})})]})}function re({value:t,onChange:a,id:u,placeholder:N="Pick a date and time",min:P,max:h,step:l=5,hourCycle:p=24,defaultTime:C="09:00",disabled:T,clearable:F=!0,className:R,locale:y="en-GB",weekStartsOn:O=1,labels:D}){const[b,n]=A.useState(!1),o=x(t),c=q(t.split("T")[1]),w=x(P),f=x(h),m={now:"Now",done:"Done",clear:"Clear",time:"Time",...D},L=(d,M)=>a(`${r(d)}T${M}`),$=o&&w&&r(o)===r(w)?P.split("T")[1]:void 0,i=o&&f&&r(o)===r(f)?h.split("T")[1]:void 0,k=o&&c?`${V(y).format(o)} \xB7 ${X(Y(c),{locale:y,hourCycle:p})}`:null;return s(g.Root,{open:b,onOpenChange:n,children:[e(B,{id:u,icon:j,text:k,placeholder:N,open:b,disabled:T,onClear:F?()=>a(""):void 0,clearLabel:m.clear,className:R}),e(g.Portal,{children:s(g.Content,{"data-pop":"",align:"start",sideOffset:6,collisionPadding:12,onOpenAutoFocus:d=>d.preventDefault(),className:z,children:[s("div",{className:"flex flex-col gap-4 sm:flex-row",children:[e(I,{selected:o,onDayClick:d=>L(d,c?Y(c):C),min:w,max:f,locale:y,weekStartsOn:O,autoFocus:!0}),s("div",{className:"border-border sm:border-l sm:pl-4",children:[e("p",{className:"disp mb-2 hidden h-8 items-center text-[13.5px] font-semibold text-text sm:flex",children:m.time}),e(J,{value:c,onChange:d=>L(o??new Date,Y(d)),step:l,hourCycle:p,min:$,max:i,locale:y})]})]}),s("div",{className:"mt-3 flex items-center justify-between border-t border-border pt-2",children:[e("button",{type:"button",onClick:()=>{const d=new Date,M=Math.round(d.getMinutes()/l)*l;L(d,Y({h:(d.getHours()+Math.floor(M/60))%24,m:M%60}))},className:v(S,"font-medium text-primary hover:bg-primary-subtle"),children:m.now}),s("div",{className:"flex items-center gap-1",children:[F&&k?e("button",{type:"button",onClick:()=>a(""),className:v(S,"text-muted hover:bg-hover hover:text-text"),children:m.clear}):null,e("button",{type:"button",onClick:()=>n(!1),className:v(S,"bg-primary px-3 font-medium text-white hover:bg-primary-hover"),children:m.done})]})]})]})})]})}const K=[{label:"Today",range:()=>({from:new Date,to:new Date})},{label:"Yesterday",range:()=>({from:E(new Date,-1),to:E(new Date,-1)})},{label:"Last 7 days",range:()=>({from:E(new Date,-6),to:new Date})},{label:"Last 30 days",range:()=>({from:E(new Date,-29),to:new Date})},{label:"This month",range:()=>{const t=new Date;return{from:new Date(t.getFullYear(),t.getMonth(),1),to:t}}},{label:"Last month",range:()=>{const t=G(new Date(new Date().getFullYear(),new Date().getMonth(),1),-1);return{from:t,to:new Date(t.getFullYear(),t.getMonth()+1,0)}}}];function ae({value:t,onChange:a,id:u,placeholder:N="Pick a date range",min:P,max:h,presets:l=K,numberOfMonths:p=2,disabled:C,clearable:T=!0,className:F,locale:R="en-GB",weekStartsOn:y=1,labels:O}){const[D,b]=A.useState(!1),n=x(t.from),o=x(t.to),c={clear:"Clear",pickEnd:"Now pick the last day",...O},w=new Intl.DateTimeFormat(R,{day:"numeric",month:"short"}),f=new Intl.DateTimeFormat(R,{day:"numeric",month:"short",year:"numeric"}),m=n&&o?r(n)===r(o)?f.format(n):`${(n.getFullYear()===o.getFullYear()?w:f).format(n)} \u2013 ${f.format(o)}`:null,L=i=>{if(!n||o||i<n)return a({from:r(i),to:""});a({from:t.from,to:r(i)}),b(!1)},$=i=>{const k=i.range();return t.from===r(k.from)&&t.to===r(k.to)};return s(g.Root,{open:D,onOpenChange:b,children:[e(B,{id:u,icon:_,text:m,placeholder:N,open:D,disabled:C,onClear:T?()=>a({from:"",to:""}):void 0,clearLabel:c.clear,className:F}),e(g.Portal,{children:e(g.Content,{"data-pop":"",align:"start",sideOffset:6,collisionPadding:12,onOpenAutoFocus:i=>i.preventDefault(),className:z,children:s("div",{className:"flex flex-col gap-3 sm:flex-row",children:[l.length?e("ul",{className:"flex shrink-0 gap-1 overflow-x-auto border-border pb-2 sm:w-36 sm:flex-col sm:overflow-visible sm:border-r sm:pb-0 sm:pr-3",children:l.map(i=>e("li",{children:e("button",{type:"button",onClick:()=>{const k=i.range();a({from:r(k.from),to:r(k.to)}),b(!1)},className:v("w-full cursor-pointer whitespace-nowrap rounded-ctl px-2.5 py-1.5 text-left text-[13px] transition-colors",$(i)?"bg-primary-subtle font-medium text-primary":"text-body hover:bg-hover hover:text-text"),children:i.label})},i.label))}):null,s("div",{children:[e(I,{range:{from:n,to:o},onDayClick:L,min:x(P),max:x(h),locale:R,weekStartsOn:y,numberOfMonths:p,defaultMonth:n??(p===2?G(new Date,-1):void 0),autoFocus:!0}),s("div",{className:"mt-2 flex min-h-8 items-center justify-between border-t border-border pt-2",children:[e("p",{className:"num text-[12px] text-muted",children:n&&!o?c.pickEnd:m}),T&&(n||o)?e("button",{type:"button",onClick:()=>a({from:"",to:""}),className:v(S,"text-muted hover:bg-hover hover:text-text"),children:c.clear}):null]})]})]})})})]})}export{K as DEFAULT_RANGE_PRESETS,ne as DatePicker,ae as DateRangePicker,re as DateTimePicker};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Dialog — two shapes, one API.
|
|
5
|
+
*
|
|
6
|
+
* `drawer` (default): forms and confirmations slide in from the right, full
|
|
7
|
+
* height, like the record drawer. The page behind stays in view, nothing jumps
|
|
8
|
+
* to the middle of the screen, and a long form scrolls inside the panel while
|
|
9
|
+
* its actions stay put at the bottom.
|
|
10
|
+
*
|
|
11
|
+
* `center`: launchers that belong in the middle of the screen — the command
|
|
12
|
+
* palette and the app switcher.
|
|
13
|
+
*
|
|
14
|
+
* On a laptop the drawer floats: 8px off the screen edges, rounded, on the
|
|
15
|
+
* deepest shadow, so it reads as an object over the page rather than a strip
|
|
16
|
+
* bolted to it. On a phone it is full screen. The header can carry an icon tile
|
|
17
|
+
* and an eyebrow over a faint brand wash; the footer is frosted so a long form
|
|
18
|
+
* scrolls under it without losing its actions.
|
|
19
|
+
*
|
|
20
|
+
* Beside Esc the drawer has two size buttons: widen (one step wider, for a form
|
|
21
|
+
* that needs a second column) and full width (the whole screen, for a long
|
|
22
|
+
* record or a table). Each toggles back. `resizable={false}` hides them.
|
|
23
|
+
*/
|
|
24
|
+
declare const SIZES: {
|
|
25
|
+
readonly sm: "max-w-[420px]";
|
|
26
|
+
readonly md: "max-w-[520px]";
|
|
27
|
+
readonly lg: "max-w-[680px]";
|
|
28
|
+
readonly xl: "max-w-[880px]";
|
|
29
|
+
};
|
|
30
|
+
export declare const Dialog: React.FC<DialogPrimitive.DialogProps>;
|
|
31
|
+
export declare const DialogTrigger: React.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
32
|
+
export declare const DialogClose: React.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
|
|
33
|
+
export declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
34
|
+
export declare const DialogContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
35
|
+
/** Maximum width, e.g. "max-w-[560px]". The drawer is full width on phones. */
|
|
36
|
+
width?: string;
|
|
37
|
+
/** Width preset; `width` wins when both are given. */
|
|
38
|
+
size?: keyof typeof SIZES;
|
|
39
|
+
/** Drawer only: show the widen / full-width buttons. On by default. */
|
|
40
|
+
resizable?: boolean;
|
|
41
|
+
hideClose?: boolean;
|
|
42
|
+
variant?: "drawer" | "center";
|
|
43
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
44
|
+
export declare const DialogHeader: ({ className, icon, eyebrow, children, ...props }: React.HTMLAttributes<HTMLDivElement> & {
|
|
45
|
+
/** A lucide icon (or any node) in a tinted tile beside the title. */
|
|
46
|
+
icon?: React.ReactNode;
|
|
47
|
+
/** One short line above the title: the object or step, e.g. "Rate plan" or "Step 2 of 3". */
|
|
48
|
+
eyebrow?: React.ReactNode;
|
|
49
|
+
}) => React.JSX.Element;
|
|
50
|
+
export declare const DialogBody: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => React.JSX.Element;
|
|
51
|
+
export declare const DialogFooter: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => React.JSX.Element;
|
|
52
|
+
export declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
|
|
53
|
+
export declare const DialogDescription: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{Fragment as T,jsx as e,jsxs as s}from"react/jsx-runtime";import*as l from"@radix-ui/react-dialog";import{Maximize2 as y,Minimize2 as w,PanelRightClose as D,PanelRightOpen as R,X as N}from"lucide-react";import*as n from"react";import{cn as a}from"../../lib/utils.js";const C={sm:"max-w-[420px]",md:"max-w-[520px]",lg:"max-w-[680px]",xl:"max-w-[880px]"},E=l.Root,H=l.Trigger,W=l.Close,f=n.forwardRef(({className:r,...t},i)=>e(l.Overlay,{ref:i,"data-scrim":"",className:a("fixed inset-0 z-50 bg-[rgba(5,8,22,.42)] backdrop-blur-[3px]",r),...t}));f.displayName="DialogOverlay";const z=n.forwardRef(({className:r,children:t,width:i,size:p="md",hideClose:m,variant:d="drawer",resizable:g=!0,...u},v)=>{const[o,b]=n.useState("base"),c=d==="drawer",h=!c||o==="base"?i??C[p]:o==="wide"?"max-w-[min(1040px,calc(100vw-16px))]":"max-w-none sm:left-2",x="hidden size-8 cursor-pointer place-items-center rounded-full border border-border bg-raised/80 text-muted backdrop-blur transition-[background-color,color,transform] hover:bg-hover hover:text-text active:scale-95 sm:grid";return s(l.Portal,{children:[e(f,{}),s(l.Content,{ref:v,...d==="drawer"?{"data-sheet":"right"}:{"data-dialog":""},className:a("z-50 flex flex-col overflow-hidden bg-raised outline-none",d==="drawer"?"fixed inset-y-0 right-0 h-dvh w-full border-border max-sm:border-l sm:inset-y-2 sm:right-2 sm:h-[calc(100dvh-16px)] sm:rounded-[16px] sm:border":"fixed left-1/2 top-1/2 w-[calc(100vw-32px)] -translate-x-1/2 -translate-y-1/2 max-h-[calc(100dvh-48px)] rounded-[16px] border border-border",h,c&&"transition-[max-width,left] duration-300 ease-[cubic-bezier(.3,.7,.2,1)]",r),...u,children:[t,m?null:s("div",{className:a("absolute z-10 flex items-center gap-1.5",d==="drawer"?"right-4 top-4":"right-3 top-3"),children:[c&&g?s(T,{children:[e("button",{type:"button","aria-label":o==="wide"?"Back to normal width":"Widen",title:o==="wide"?"Back to normal width":"Widen",onClick:()=>b(o==="wide"?"base":"wide"),className:a(x,o==="wide"&&"border-primary/40 bg-primary-subtle text-primary"),children:o==="wide"?e(D,{className:"size-4"}):e(R,{className:"size-4"})}),e("button",{type:"button","aria-label":o==="full"?"Exit full width":"Full width",title:o==="full"?"Exit full width":"Full width",onClick:()=>b(o==="full"?"base":"full"),className:a(x,o==="full"&&"border-primary/40 bg-primary-subtle text-primary"),children:o==="full"?e(w,{className:"size-3.5"}):e(y,{className:"size-3.5"})})]}):null,e("kbd",{className:"hidden rounded-[5px] border border-border bg-surface px-1.5 py-0.5 font-sans text-[10.5px] text-muted sm:block",children:"esc"}),s(l.Close,{className:"grid size-8 cursor-pointer place-items-center rounded-full border border-border bg-raised/80 text-muted backdrop-blur transition-[background-color,color,transform] hover:bg-hover hover:text-text active:scale-95",children:[e(N,{className:"size-4"}),e("span",{className:"sr-only",children:"Close"})]})]})]})]})});z.displayName="DialogContent";const L=({className:r,icon:t,eyebrow:i,children:p,...m})=>s("div",{className:a("relative isolate flex shrink-0 items-start gap-3.5 border-b border-border px-6 pb-4 pt-5 pr-28 sm:pr-48","before:absolute before:inset-0 before:-z-10 before:bg-[radial-gradient(120%_100%_at_0%_0%,var(--primary-subtle),transparent_60%)] before:opacity-70",r),...m,children:[t?e("span",{className:"grid size-10 shrink-0 place-items-center rounded-[11px] border border-primary/15 bg-raised text-primary shadow-[0_1px_2px_rgba(5,8,22,.14)] [&>svg]:size-5",children:t}):null,s("div",{className:"min-w-0 flex-1",children:[i?e("p",{className:"mb-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-primary",children:i}):null,p]})]}),O=({className:r,...t})=>e("div",{className:a("min-h-0 flex-1 overflow-y-auto px-6 py-5",r),...t}),S=({className:r,...t})=>e("div",{className:a("mt-auto flex shrink-0 items-center justify-end gap-2 border-t border-border bg-raised/85 px-6 py-4 backdrop-blur-md",r),...t}),P=n.forwardRef(({className:r,...t},i)=>e(l.Title,{ref:i,className:a("disp text-[16px] font-semibold leading-6 text-text",r),...t}));P.displayName="DialogTitle";const k=n.forwardRef(({className:r,...t},i)=>e(l.Description,{ref:i,className:a("mt-1 text-[13px] leading-5 text-muted",r),...t}));k.displayName="DialogDescription";export{E as Dialog,O as DialogBody,W as DialogClose,z as DialogContent,k as DialogDescription,S as DialogFooter,L as DialogHeader,f as DialogOverlay,P as DialogTitle,H as DialogTrigger};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as Primitive from "@radix-ui/react-dropdown-menu";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export declare const DropdownMenu: React.FC<Primitive.DropdownMenuProps>;
|
|
4
|
+
export declare const DropdownMenuTrigger: React.ForwardRefExoticComponent<Primitive.DropdownMenuTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
5
|
+
export declare const DropdownMenuGroup: React.ForwardRefExoticComponent<Primitive.DropdownMenuGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
6
|
+
export declare const DropdownMenuSub: React.FC<Primitive.DropdownMenuSubProps>;
|
|
7
|
+
export declare const DropdownMenuRadioGroup: React.ForwardRefExoticComponent<Primitive.DropdownMenuRadioGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
/**
|
|
9
|
+
* Menu surfaces: `default` (raised), `glass` (frosted, over maps and media),
|
|
10
|
+
* `dark` (ink, a command-style menu that stands apart from the page). Items
|
|
11
|
+
* take an `icon`, a second-line `description`, a `shortcut` and a `badge`, so a
|
|
12
|
+
* menu can explain itself instead of listing bare verbs.
|
|
13
|
+
*/
|
|
14
|
+
export type MenuVariant = "default" | "glass" | "dark";
|
|
15
|
+
export declare const DropdownMenuContent: React.ForwardRefExoticComponent<Omit<Primitive.DropdownMenuContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
16
|
+
variant?: MenuVariant;
|
|
17
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
18
|
+
export declare const DropdownMenuItem: React.ForwardRefExoticComponent<Omit<Primitive.DropdownMenuItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
19
|
+
danger?: boolean;
|
|
20
|
+
/** Icon in a soft tile on the left. */
|
|
21
|
+
icon?: React.ReactNode;
|
|
22
|
+
/** Second line, muted: what the item does. */
|
|
23
|
+
description?: React.ReactNode;
|
|
24
|
+
shortcut?: string;
|
|
25
|
+
badge?: React.ReactNode;
|
|
26
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
27
|
+
export declare const DropdownMenuCheckboxItem: React.ForwardRefExoticComponent<Omit<Primitive.DropdownMenuCheckboxItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
28
|
+
export declare const DropdownMenuRadioItem: React.ForwardRefExoticComponent<Omit<Primitive.DropdownMenuRadioItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
29
|
+
export declare const DropdownMenuLabel: ({ className, ...props }: React.ComponentPropsWithoutRef<typeof Primitive.Label>) => React.JSX.Element;
|
|
30
|
+
export declare const DropdownMenuSeparator: ({ className, ...props }: React.ComponentPropsWithoutRef<typeof Primitive.Separator>) => React.JSX.Element;
|
|
31
|
+
export declare const DropdownMenuShortcut: ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => React.JSX.Element;
|
|
32
|
+
export declare const DropdownMenuSubTrigger: React.ForwardRefExoticComponent<Omit<Primitive.DropdownMenuSubTriggerProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
33
|
+
export declare const DropdownMenuSubContent: React.ForwardRefExoticComponent<Omit<Primitive.DropdownMenuSubContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
34
|
+
/**
|
|
35
|
+
* Identity at the top of an account menu: who is signed in, and where. Not an
|
|
36
|
+
* item (it does nothing), so it is plain content above the first separator.
|
|
37
|
+
*/
|
|
38
|
+
export declare function DropdownMenuHeader({ title, subtitle, media, className, }: {
|
|
39
|
+
title: React.ReactNode;
|
|
40
|
+
subtitle?: React.ReactNode;
|
|
41
|
+
/** An Avatar or mark. */
|
|
42
|
+
media?: React.ReactNode;
|
|
43
|
+
className?: string;
|
|
44
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{Fragment as I,jsx as t,jsxs as d}from"react/jsx-runtime";import*as a from"@radix-ui/react-dropdown-menu";import{Check as l,ChevronRight as v}from"lucide-react";import*as s from"react";import{cn as i}from"../../lib/utils.js";const S=a.Root,T=a.Trigger,W=a.Group,_=a.Sub,z=a.RadioGroup,f="z-50 min-w-48 overflow-hidden rounded-dlg border border-border bg-raised p-1 shadow-elev3",b=s.createContext("default"),x={default:"",glass:"border-white/40 bg-raised/70 backdrop-blur-xl backdrop-saturate-150 dark:border-white/10",dark:"dark border-white/10 bg-[#140d33] text-white [--hover:rgba(255,255,255,.08)] [--text:#f5f6fa] [--body:#d6d8e6] [--muted:#9aa1bd] [--border:rgba(255,255,255,.1)]"},w=s.forwardRef(({className:o,sideOffset:e=6,variant:n="default",...r},p)=>t(b.Provider,{value:n,children:t(a.Portal,{children:t(a.Content,{ref:p,"data-pop":"",sideOffset:e,className:i(f,x[n],o),...r})})}));w.displayName="DropdownMenuContent";const m="relative flex cursor-pointer select-none items-center gap-2.5 rounded-ctl px-2.5 py-2 text-[13px] text-body outline-none transition-colors data-[highlighted]:bg-hover data-[highlighted]:text-text data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted",C=s.forwardRef(({className:o,danger:e,icon:n,description:r,shortcut:p,badge:c,children:u,...g},R)=>{const h=n!==void 0||r!==void 0||p!==void 0||c!==void 0;return t(a.Item,{ref:R,className:i(m,r&&"items-start py-2",e&&"text-danger data-[highlighted]:bg-danger-subtle data-[highlighted]:text-danger [&_svg]:text-danger",o),...g,children:h?d(I,{children:[n?t("span",{className:i("grid shrink-0 place-items-center rounded-[8px] border border-border bg-surface",r?"size-8":"size-6",e&&"border-danger/20 bg-danger-subtle"),children:n}):null,d("span",{className:"min-w-0 flex-1",children:[d("span",{className:"flex items-center gap-2",children:[t("span",{className:"truncate",children:u}),c]}),r?t("span",{className:"mt-0.5 block text-[11.5px] leading-4 text-muted",children:r}):null]}),p?t("kbd",{className:"ml-auto self-center rounded-[5px] border border-border bg-surface px-1.5 py-px font-sans text-[10.5px] text-muted",children:p}):null]}):u})});C.displayName="DropdownMenuItem";const N=s.forwardRef(({className:o,children:e,...n},r)=>d(a.CheckboxItem,{ref:r,className:i(m,"pr-8",o),...n,children:[e,t(a.ItemIndicator,{className:"absolute right-2.5",children:t(l,{className:"size-3.5 !text-primary",strokeWidth:3})})]}));N.displayName="DropdownMenuCheckboxItem";const P=s.forwardRef(({className:o,children:e,...n},r)=>d(a.RadioItem,{ref:r,className:i(m,"pr-8",o),...n,children:[e,t(a.ItemIndicator,{className:"absolute right-2.5",children:t(l,{className:"size-3.5 !text-primary",strokeWidth:3})})]}));P.displayName="DropdownMenuRadioItem";const V=({className:o,...e})=>t(a.Label,{className:i("ov px-2.5 pb-1 pt-2",o),...e}),L=({className:o,...e})=>t(a.Separator,{className:i("-mx-1 my-1 h-px bg-border",o),...e}),G=({className:o,...e})=>t("span",{className:i("ml-auto text-[11px] tracking-wide text-muted",o),...e}),y=s.forwardRef(({className:o,children:e,...n},r)=>d(a.SubTrigger,{ref:r,className:i(m,"data-[state=open]:bg-hover",o),...n,children:[e,t(v,{className:"ml-auto size-3.5"})]}));y.displayName="DropdownMenuSubTrigger";const M=s.forwardRef(({className:o,...e},n)=>{const r=s.useContext(b);return t(a.Portal,{children:t(a.SubContent,{ref:n,"data-pop":"",className:i(f,x[r],o),...e})})});M.displayName="DropdownMenuSubContent";function H({title:o,subtitle:e,media:n,className:r}){return d("div",{className:i("flex items-center gap-3 rounded-[10px] bg-[radial-gradient(120%_120%_at_0%_0%,var(--primary-subtle),transparent_60%)] px-2.5 py-2.5",r),children:[n,d("div",{className:"min-w-0",children:[t("p",{className:"truncate text-[13px] font-semibold text-text",children:o}),e?t("p",{className:"truncate text-[11.5px] text-muted",children:e}):null]})]})}export{S as DropdownMenu,N as DropdownMenuCheckboxItem,w as DropdownMenuContent,W as DropdownMenuGroup,H as DropdownMenuHeader,C as DropdownMenuItem,V as DropdownMenuLabel,z as DropdownMenuRadioGroup,P as DropdownMenuRadioItem,L as DropdownMenuSeparator,G as DropdownMenuShortcut,_ as DropdownMenuSub,M as DropdownMenuSubContent,y as DropdownMenuSubTrigger,T as DropdownMenuTrigger};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A labelled field with its help and its verdict: label (with required star),
|
|
4
|
+
* the control, then one line under it — the error if there is one, else the
|
|
5
|
+
* warning, else the success, else the hint. One line, so the form never jumps
|
|
6
|
+
* by two lines when a message appears. The message is tied to the control with
|
|
7
|
+
* aria-describedby, and an error is announced as it appears.
|
|
8
|
+
*
|
|
9
|
+
* Give the control the same state: <Input state={error ? "error" : "default"} />.
|
|
10
|
+
*/
|
|
11
|
+
export declare function FormField({ label, htmlFor, required, hint, error, warning, success, count, className, children, }: {
|
|
12
|
+
label?: React.ReactNode;
|
|
13
|
+
/** The control's id, so clicking the label focuses it. */
|
|
14
|
+
htmlFor?: string;
|
|
15
|
+
required?: boolean;
|
|
16
|
+
hint?: React.ReactNode;
|
|
17
|
+
error?: React.ReactNode;
|
|
18
|
+
warning?: React.ReactNode;
|
|
19
|
+
success?: React.ReactNode;
|
|
20
|
+
/** Character counter, e.g. { value: note.length, max: 240 }. */
|
|
21
|
+
count?: {
|
|
22
|
+
value: number;
|
|
23
|
+
max: number;
|
|
24
|
+
};
|
|
25
|
+
className?: string;
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as s,jsxs as r}from"react/jsx-runtime";import{CircleAlert as v,CircleCheck as h,TriangleAlert as w}from"lucide-react";import*as l from"react";import{cn as i}from"../../lib/utils.js";import{Label as k}from"./label.js";function F({label:c,htmlFor:m,required:g,hint:R,error:d,warning:o,success:p,count:a,className:N,children:n}){const f=l.useId(),u=`${m??f}-msg`,t=d??o??p??R,e=d?"error":o?"warning":p?"success":"hint",x=e==="error"?v:e==="warning"?w:e==="success"?h:null,b=l.isValidElement(n)?l.cloneElement(n,{"aria-describedby":t?u:void 0}):n;return r("div",{className:i("space-y-1.5",N),children:[c?s(k,{htmlFor:m,required:g,children:c}):null,b,t||a?r("div",{className:"flex items-start gap-3",children:[t?r("p",{id:u,role:e==="error"?"alert":void 0,className:i("flex min-w-0 flex-1 items-start gap-1.5 text-[12px] leading-[18px]",e==="error"?"text-danger":e==="warning"?"text-warning":e==="success"?"text-success":"text-muted"),children:[x?s(x,{className:"mt-px size-3.5 shrink-0"}):null,s("span",{children:t})]}):s("span",{className:"flex-1"}),a?r("span",{className:i("num shrink-0 text-[11.5px] leading-[18px]",a.value>a.max?"font-medium text-danger":"text-muted"),children:[a.value,"/",a.max]}):null]}):null]})}export{F as FormField};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Primitives: small, unopinionated building blocks (Radix underneath where it helps). */
|
|
2
|
+
export * from "./avatar";
|
|
3
|
+
export * from "./badge";
|
|
4
|
+
export * from "./button";
|
|
5
|
+
export * from "./calendar";
|
|
6
|
+
export * from "./card";
|
|
7
|
+
export * from "./checkbox";
|
|
8
|
+
export * from "./combobox";
|
|
9
|
+
export * from "./confirm-dialog";
|
|
10
|
+
export * from "./dialog";
|
|
11
|
+
export * from "./dropdown-menu";
|
|
12
|
+
export * from "./form-field";
|
|
13
|
+
export * from "./input";
|
|
14
|
+
export * from "./label";
|
|
15
|
+
export * from "./popover";
|
|
16
|
+
export * from "./date-picker";
|
|
17
|
+
export * from "./progress";
|
|
18
|
+
export * from "./segmented";
|
|
19
|
+
export * from "./select";
|
|
20
|
+
export * from "./separator";
|
|
21
|
+
export * from "./sheet";
|
|
22
|
+
export * from "./skeleton";
|
|
23
|
+
export * from "./switch";
|
|
24
|
+
export * from "./tabs";
|
|
25
|
+
export * from "./time-picker";
|
|
26
|
+
export * from "./tooltip";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"./avatar.js";export*from"./badge.js";export*from"./button.js";export*from"./calendar.js";export*from"./card.js";export*from"./checkbox.js";export*from"./combobox.js";export*from"./confirm-dialog.js";export*from"./dialog.js";export*from"./dropdown-menu.js";export*from"./form-field.js";export*from"./input.js";export*from"./label.js";export*from"./popover.js";export*from"./date-picker.js";export*from"./progress.js";export*from"./segmented.js";export*from"./select.js";export*from"./separator.js";export*from"./sheet.js";export*from"./skeleton.js";export*from"./switch.js";export*from"./tabs.js";export*from"./time-picker.js";export*from"./tooltip.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export declare const inputClass: string;
|
|
3
|
+
/**
|
|
4
|
+
* Field states. `error` also sets aria-invalid (screen readers announce it)
|
|
5
|
+
* and gives one short shake when it appears — the eye goes to the field that
|
|
6
|
+
* needs fixing. Colour is never the only signal: pair a state with a message
|
|
7
|
+
* (FormField does that).
|
|
8
|
+
*/
|
|
9
|
+
export type InputState = "default" | "error" | "warning" | "success";
|
|
10
|
+
interface Extra {
|
|
11
|
+
state?: InputState;
|
|
12
|
+
/** Icon or text inside the box, before the value (a search icon, "৳", "+880"). */
|
|
13
|
+
leading?: React.ReactNode;
|
|
14
|
+
/** After the value: a unit, a clear button, a status icon. */
|
|
15
|
+
trailing?: React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare const Input: React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTMLInputElement> & Extra & React.RefAttributes<HTMLInputElement>>;
|
|
18
|
+
export declare const Textarea: React.ForwardRefExoticComponent<React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
|
|
19
|
+
state?: InputState;
|
|
20
|
+
} & React.RefAttributes<HTMLTextAreaElement>>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as a,jsxs as g}from"react/jsx-runtime";import*as i from"react";import{cn as d}from"../../lib/utils.js";const l="h-ctl w-full rounded-ctl border border-border2 bg-raised px-3 text-[13px] text-text placeholder:text-placeholder outline-none transition-[border-color,box-shadow] duration-150 focus:border-primary focus:ring-2 focus:ring-primary/20 disabled:cursor-not-allowed disabled:bg-hover disabled:text-muted aria-[invalid=true]:border-danger aria-[invalid=true]:ring-danger/20",u={default:"",error:"border-danger bg-danger-subtle/30 focus:border-danger focus:ring-danger/20 wm-shake",warning:"border-warning focus:border-warning focus:ring-warning/20",success:"border-success focus:border-success focus:ring-success/20"};function p({leading:r,trailing:e,children:t}){return!r&&!e?t:g("div",{className:"relative w-full",children:[r?a("span",{className:"pointer-events-none absolute left-3 top-1/2 flex -translate-y-1/2 items-center text-[13px] text-muted [&_svg]:size-4",children:r}):null,t,e?a("span",{className:"absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center text-[13px] text-muted [&_svg]:size-4",children:e}):null]})}const f=i.forwardRef(({className:r,type:e="text",state:t="default",leading:n,trailing:s,...o},c)=>a(p,{leading:n,trailing:s,children:a("input",{ref:c,type:e,"aria-invalid":t==="error"?!0:o["aria-invalid"],className:d(l,u[t],n?"pl-9":null,s?"pr-10":null,r),...o})}));f.displayName="Input";const x=i.forwardRef(({className:r,state:e="default",...t},n)=>a("textarea",{ref:n,"aria-invalid":e==="error"?!0:t["aria-invalid"],className:d(l,"h-auto min-h-20 resize-y py-2 leading-5",u[e],r),...t}));x.displayName="Textarea";export{f as Input,x as Textarea,l as inputClass};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export declare const Label: React.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & React.RefAttributes<HTMLLabelElement>, "ref"> & {
|
|
4
|
+
required?: boolean;
|
|
5
|
+
} & React.RefAttributes<HTMLLabelElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as s,jsxs as p}from"react/jsx-runtime";import*as r from"@radix-ui/react-label";import*as m from"react";import{cn as n}from"../../lib/utils.js";const l=m.forwardRef(({className:e,required:t,children:o,...a},i)=>p(r.Root,{ref:i,className:n("flex items-center gap-1 text-xs font-medium text-text select-none",e),...a,children:[o,t?s("span",{className:"text-danger","aria-hidden":!0,children:"*"}):null]}));l.displayName="Label";export{l as Label};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export declare const Popover: React.FC<PopoverPrimitive.PopoverProps>;
|
|
4
|
+
export declare const PopoverTrigger: React.ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
5
|
+
export declare const PopoverAnchor: React.ForwardRefExoticComponent<PopoverPrimitive.PopoverAnchorProps & React.RefAttributes<HTMLDivElement>>;
|
|
6
|
+
/**
|
|
7
|
+
* Popover surfaces: `default`, `glass` (frosted), `dark` (ink — tips that must
|
|
8
|
+
* stand out from the page), `brand` (the gradient — onboarding, "what's new").
|
|
9
|
+
* `arrow` points at the trigger, for tips attached to one control.
|
|
10
|
+
*/
|
|
11
|
+
export type PopoverVariant = "default" | "glass" | "dark" | "brand";
|
|
12
|
+
export declare const PopoverContent: React.ForwardRefExoticComponent<Omit<PopoverPrimitive.PopoverContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
13
|
+
variant?: PopoverVariant;
|
|
14
|
+
arrow?: boolean;
|
|
15
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
16
|
+
/** Title and one line under it, the top of a popover that explains something. */
|
|
17
|
+
export declare function PopoverHeader({ title, description, icon, className }: {
|
|
18
|
+
title: React.ReactNode;
|
|
19
|
+
description?: React.ReactNode;
|
|
20
|
+
icon?: React.ReactNode;
|
|
21
|
+
className?: string;
|
|
22
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as o,jsxs as d}from"react/jsx-runtime";import*as e from"@radix-ui/react-popover";import*as v from"react";import{cn as p}from"../../lib/utils.js";const g=e.Root,x=e.Trigger,P=e.Anchor,s={default:{box:"border-border bg-raised",arrow:"fill-[var(--raised)]"},glass:{box:"border-white/40 bg-raised/70 backdrop-blur-xl backdrop-saturate-150 dark:border-white/10",arrow:"fill-[var(--raised)] opacity-80"},dark:{box:"border-white/10 bg-[#140d33] text-[#d6d8e6] [--text:#f5f6fa] [--body:#d6d8e6] [--muted:#9aa1bd] [--border:rgba(255,255,255,.1)] [--hover:rgba(255,255,255,.08)]",arrow:"fill-[#140d33]"},brand:{box:"border-transparent bg-[linear-gradient(135deg,#1437d3,#7560fd)] text-white/90 [--text:#ffffff] [--body:rgba(255,255,255,.9)] [--muted:rgba(255,255,255,.72)] [--border:rgba(255,255,255,.2)] [--hover:rgba(255,255,255,.12)]",arrow:"fill-[#4a4ce8]"}},f=v.forwardRef(({className:i,align:t="start",sideOffset:r=6,variant:a="default",arrow:n=!1,children:l,...b},c)=>o(e.Portal,{children:d(e.Content,{ref:c,"data-pop":"",align:t,sideOffset:n?r+2:r,className:p("z-50 w-72 rounded-dlg border p-3 shadow-elev3 outline-none",s[a].box,i),...b,children:[l,n?o(e.Arrow,{width:14,height:7,className:s[a].arrow}):null]})}));f.displayName="PopoverContent";function u({title:i,description:t,icon:r,className:a}){return d("div",{className:p("mb-2.5 flex items-start gap-2.5",a),children:[r?o("span",{className:"mt-px grid size-7 shrink-0 place-items-center rounded-[8px] bg-[var(--hover)] text-[var(--text)] [&_svg]:size-4",children:r}):null,d("div",{className:"min-w-0",children:[o("p",{className:"text-[13.5px] font-semibold text-text",children:i}),t?o("p",{className:"mt-0.5 text-[12.5px] leading-[18px] text-muted",children:t}):null]})]})}export{g as Popover,P as PopoverAnchor,f as PopoverContent,u as PopoverHeader,x as PopoverTrigger};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { Tone } from "../../types";
|
|
3
|
+
declare const heights: {
|
|
4
|
+
readonly sm: "h-1.5";
|
|
5
|
+
readonly md: "h-2.5";
|
|
6
|
+
readonly lg: "h-3.5";
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Capacity / utilisation bar. Always paired with a numeric label — a bar alone
|
|
10
|
+
* is a shape, not a measurement (`showValue` prints it beside the bar).
|
|
11
|
+
*
|
|
12
|
+
* Variants: `bar` (default), `gradient` (the brand gradient with a slow sheen:
|
|
13
|
+
* onboarding, profile completion), `striped` (moving stripes: work in progress,
|
|
14
|
+
* uploads), `segmented` (n steps: a wizard, a checklist). Leave `value` out for
|
|
15
|
+
* an indeterminate bar — something is happening, nobody knows how long.
|
|
16
|
+
*/
|
|
17
|
+
export declare function Progress({ value, tone, className, label, variant, size, segments, showValue, }: {
|
|
18
|
+
/** 0–100; undefined = indeterminate. */
|
|
19
|
+
value?: number;
|
|
20
|
+
tone?: Tone;
|
|
21
|
+
className?: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
variant?: "bar" | "gradient" | "striped" | "segmented";
|
|
24
|
+
size?: keyof typeof heights;
|
|
25
|
+
segments?: number;
|
|
26
|
+
showValue?: boolean;
|
|
27
|
+
}): React.JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* Progress as a ring, with the number in the middle — a profile that is 64%
|
|
30
|
+
* complete, a quota, a timer. Pass `children` to replace the number.
|
|
31
|
+
*/
|
|
32
|
+
export declare function ProgressRing({ value, size, thickness, tone, gradient, label, children, className, }: {
|
|
33
|
+
value: number;
|
|
34
|
+
size?: number;
|
|
35
|
+
thickness?: number;
|
|
36
|
+
tone?: Tone;
|
|
37
|
+
/** Draw the arc in the brand gradient instead of the tone. */
|
|
38
|
+
gradient?: boolean;
|
|
39
|
+
label?: string;
|
|
40
|
+
children?: React.ReactNode;
|
|
41
|
+
className?: string;
|
|
42
|
+
}): React.JSX.Element;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as a,jsxs as l}from"react/jsx-runtime";import*as w from"react";import{cn as s}from"../../lib/utils.js";const v={neutral:"bg-muted",info:"bg-primary",success:"bg-success",warning:"bg-warning",danger:"bg-danger",accent:"bg-accent"},x={neutral:"var(--muted)",info:"var(--primary)",success:"var(--success)",warning:"var(--warning)",danger:"var(--danger)",accent:"var(--accent)"},p={sm:"h-1.5",md:"h-2.5",lg:"h-3.5"};function N({value:i,tone:e="info",className:o,label:m,variant:n="bar",size:d="sm",segments:c=5,showValue:g=!1}){const t=typeof i=="number",r=t?Math.max(0,Math.min(100,i)):0,u=n==="segmented"?a("div",{className:s("flex w-full gap-1",p[d]),children:Array.from({length:c},(f,h)=>{const b=Math.max(0,Math.min(1,r/100*c-h));return a("div",{className:"h-full flex-1 overflow-hidden rounded-full bg-hover",children:a("div",{className:s("h-full rounded-full transition-[width] duration-500 ease-wave",v[e]),style:{width:`${b*100}%`}})},h)})}):a("div",{className:s("relative w-full overflow-hidden rounded-full bg-hover",p[d]),children:a("div",{className:s("relative h-full overflow-hidden rounded-full transition-[width] duration-500 ease-wave",!t&&"wm-indeterminate absolute w-2/5",n==="gradient"?"bg-[linear-gradient(90deg,#1437d3,#7560fd)]":v[e],n==="striped"&&"wm-stripes"),style:t?{width:`${r}%`}:void 0,children:n==="gradient"?a("span",{className:"wm-sheen absolute inset-y-0 w-1/3 bg-[linear-gradient(90deg,transparent,rgba(255,255,255,.45),transparent)]"}):null})});return l("div",{role:"progressbar","aria-valuenow":t?r:void 0,"aria-valuemin":0,"aria-valuemax":100,"aria-label":m,className:s("flex w-full items-center gap-3",o),children:[u,g&&t?l("span",{className:"num w-10 shrink-0 text-right text-[12px] font-medium text-text",children:[Math.round(r),"%"]}):null]})}function k({value:i,size:e=64,thickness:o=6,tone:m="info",gradient:n=!1,label:d,children:c,className:g}){const t=Math.max(0,Math.min(100,i)),r=(e-o)/2,u=2*Math.PI*r,f=w.useId().replace(/:/g,"");return l("div",{role:"progressbar","aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":100,"aria-label":d,className:s("relative inline-grid shrink-0 place-items-center",g),style:{width:e,height:e},children:[l("svg",{width:e,height:e,className:"-rotate-90",children:[n?a("defs",{children:l("linearGradient",{id:`${f}-g`,x1:"0",y1:"0",x2:"1",y2:"1",children:[a("stop",{offset:"0",stopColor:"#1437d3"}),a("stop",{offset:"1",stopColor:"#7560fd"})]})}):null,a("circle",{cx:e/2,cy:e/2,r,fill:"none",stroke:"var(--hover)",strokeWidth:o}),a("circle",{cx:e/2,cy:e/2,r,fill:"none",stroke:n?`url(#${f}-g)`:x[m],strokeWidth:o,strokeLinecap:"round",strokeDasharray:u,strokeDashoffset:u*(1-t/100),style:{transition:"stroke-dashoffset 600ms var(--ease)"}})]}),a("span",{className:"num absolute text-[13px] font-semibold text-text",style:{fontSize:Math.max(11,e*.22)},children:c??`${Math.round(t)}%`})]})}export{N as Progress,k as ProgressRing};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface SegmentedOption<T extends string> {
|
|
3
|
+
value: T;
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
title?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Pill segmented control — the prototype's `.tog`.
|
|
9
|
+
*
|
|
10
|
+
* Used for theme and density in the topbar and for any 2–3 way view switch.
|
|
11
|
+
* Beyond three options this becomes a Select: a segmented control that wraps
|
|
12
|
+
* is worse than a dropdown that does not.
|
|
13
|
+
*/
|
|
14
|
+
declare const SIZES: {
|
|
15
|
+
readonly sm: "px-2.5 py-1 text-[11px]";
|
|
16
|
+
readonly md: "h-8 px-3.5 text-[12.5px]";
|
|
17
|
+
readonly lg: "h-10 px-5 text-[13.5px]";
|
|
18
|
+
};
|
|
19
|
+
declare const TRACK: {
|
|
20
|
+
readonly pill: "rounded-full border border-border bg-hover";
|
|
21
|
+
readonly solid: "rounded-full border border-border bg-hover";
|
|
22
|
+
readonly outline: "rounded-[10px] border border-border2 bg-raised";
|
|
23
|
+
readonly glass: "rounded-full bg-[rgba(10,7,32,.22)] ring-1 ring-inset ring-white/15 shadow-[inset_0_1px_3px_rgba(5,8,22,.35)] backdrop-blur-md";
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Variants: `pill` (default, the topbar look), `solid` (the chosen option in
|
|
27
|
+
* the brand gradient: view switches that matter), `outline` (squared, for
|
|
28
|
+
* forms), `glass` (on photos and gradients). The thumb slides to the chosen
|
|
29
|
+
* option instead of jumping, so the change is seen, not just noticed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function Segmented<T extends string>({ value, onChange, options, className, ariaLabel, variant, size, fullWidth, }: {
|
|
32
|
+
value: T;
|
|
33
|
+
onChange: (v: T) => void;
|
|
34
|
+
options: SegmentedOption<T>[];
|
|
35
|
+
className?: string;
|
|
36
|
+
ariaLabel?: string;
|
|
37
|
+
variant?: keyof typeof TRACK;
|
|
38
|
+
size?: keyof typeof SIZES;
|
|
39
|
+
/** Stretch to the container, options sharing the width equally. */
|
|
40
|
+
fullWidth?: boolean;
|
|
41
|
+
}): React.JSX.Element;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as b,jsxs as y}from"react/jsx-runtime";import*as i from"react";import{cn as o}from"../../lib/utils.js";const m={sm:"px-2.5 py-1 text-[11px]",md:"h-8 px-3.5 text-[12.5px]",lg:"h-10 px-5 text-[13.5px]"},v={pill:"rounded-full border border-border bg-hover",solid:"rounded-full border border-border bg-hover",outline:"rounded-[10px] border border-border2 bg-raised",glass:"rounded-full bg-[rgba(10,7,32,.22)] ring-1 ring-inset ring-white/15 shadow-[inset_0_1px_3px_rgba(5,8,22,.35)] backdrop-blur-md"},g={pill:"rounded-full bg-raised shadow-[var(--lit),0_1px_2px_rgba(5,8,22,.08),0_2px_8px_-2px_rgba(5,8,22,.16)]",solid:"rounded-full bg-[linear-gradient(135deg,#1f45ea,#5b4af5)] shadow-[inset_0_1px_0_rgba(255,255,255,.25),0_4px_12px_-4px_rgba(20,55,211,.6)]",outline:"rounded-[7px] bg-primary-subtle ring-1 ring-inset ring-primary/30",glass:"rounded-full bg-[linear-gradient(180deg,rgba(255,255,255,.34),rgba(255,255,255,.16))] ring-1 ring-inset ring-white/45 shadow-[inset_0_1px_0_rgba(255,255,255,.55),0_6px_14px_-6px_rgba(5,8,22,.45)] backdrop-blur-md"},w={pill:"text-text",solid:"text-white",outline:"text-primary",glass:"text-white [text-shadow:0_1px_1px_rgba(5,8,22,.25)]"},T={pill:"text-muted hover:text-text",solid:"text-muted hover:text-text",outline:"text-muted hover:text-text",glass:"text-white/65 hover:text-white"};function k({value:s,onChange:c,options:a,className:f,ariaLabel:_,variant:r="pill",size:d="sm",fullWidth:u=!1}){const p=i.useRef(null),[n,h]=i.useState(null);return i.useLayoutEffect(()=>{const e=p.current;if(!e)return;const t=()=>{const l=e.querySelector('[aria-checked="true"]');h(l?{left:l.offsetLeft,width:l.offsetWidth}:null)};t();const x=new ResizeObserver(t);return x.observe(e),()=>x.disconnect()},[s,a.length,d]),y("div",{ref:p,role:"radiogroup","aria-label":_,className:o("relative isolate items-center gap-0.5 p-[3px]",u?"flex w-full":"inline-flex",v[r],f),children:[n?b("span",{"aria-hidden":!0,className:o("absolute inset-y-[3px] -z-10 transition-[left,width] duration-300 ease-[cubic-bezier(.3,.7,.2,1)]",g[r]),style:{left:n.left,width:n.width}}):null,a.map(e=>{const t=e.value===s;return b("button",{type:"button",role:"radio","aria-checked":t,title:e.title,onClick:()=>c(e.value),className:o("inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-full font-medium leading-none transition-colors duration-200 [&_svg]:size-3.5",m[d],u&&"flex-1",t?w[r]:T[r],t&&!n&&g[r]),children:e.label},e.value)})]})}export{k as Segmented};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export declare const Select: React.FC<SelectPrimitive.SelectProps>;
|
|
4
|
+
export declare const SelectGroup: React.ForwardRefExoticComponent<SelectPrimitive.SelectGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
5
|
+
export declare const SelectValue: React.ForwardRefExoticComponent<SelectPrimitive.SelectValueProps & React.RefAttributes<HTMLSpanElement>>;
|
|
6
|
+
export declare const SelectTrigger: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
7
|
+
export declare const SelectContent: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
export declare const SelectItem: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
9
|
+
export declare const SelectLabel: ({ className, ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>) => React.JSX.Element;
|
|
10
|
+
export declare const SelectSeparator: ({ className, ...props }: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>) => React.JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as t,jsxs as n}from"react/jsx-runtime";import*as e from"@radix-ui/react-select";import{Check as s,ChevronDown as m}from"lucide-react";import*as l from"react";import{cn as c}from"../../lib/utils.js";const g=e.Root,b=e.Group,u=e.Value,d=l.forwardRef(({className:o,children:r,...i},a)=>n(e.Trigger,{ref:a,className:c("flex h-ctl w-full cursor-pointer items-center justify-between gap-2 rounded-ctl border border-border2 bg-raised px-3 text-[13px] text-text outline-none transition-[border-color,box-shadow] data-[placeholder]:text-placeholder focus:border-primary focus:ring-2 focus:ring-primary/20 disabled:cursor-not-allowed disabled:bg-hover disabled:text-muted",o),...i,children:[r,t(e.Icon,{asChild:!0,children:t(m,{className:"size-4 shrink-0 text-muted"})})]}));d.displayName="SelectTrigger";const f=l.forwardRef(({className:o,children:r,position:i="popper",...a},p)=>t(e.Portal,{children:t(e.Content,{ref:p,"data-pop":"",position:i,sideOffset:6,className:c("z-50 max-h-72 min-w-[var(--radix-select-trigger-width)] overflow-hidden rounded-dlg border border-border bg-raised p-1 shadow-elev3",o),...a,children:t(e.Viewport,{children:r})})}));f.displayName="SelectContent";const x=l.forwardRef(({className:o,children:r,...i},a)=>n(e.Item,{ref:a,className:c("relative flex cursor-pointer select-none items-center rounded-ctl py-2 pl-2.5 pr-8 text-[13px] text-body outline-none data-[highlighted]:bg-hover data-[highlighted]:text-text data-[state=checked]:text-primary data-[state=checked]:font-medium data-[disabled]:pointer-events-none data-[disabled]:opacity-50",o),...i,children:[t(e.ItemText,{children:r}),t(e.ItemIndicator,{className:"absolute right-2.5",children:t(s,{className:"size-3.5",strokeWidth:3})})]}));x.displayName="SelectItem";const v=({className:o,...r})=>t(e.Label,{className:c("ov px-2.5 pb-1 pt-2",o),...r}),P=({className:o,...r})=>t(e.Separator,{className:c("-mx-1 my-1 h-px bg-border",o),...r});export{g as Select,f as SelectContent,b as SelectGroup,x as SelectItem,v as SelectLabel,P as SelectSeparator,d as SelectTrigger,u as SelectValue};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export declare const Separator: React.ForwardRefExoticComponent<Omit<SeparatorPrimitive.SeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as l}from"react/jsx-runtime";import*as i from"@radix-ui/react-separator";import*as p from"react";import{cn as f}from"../../lib/utils.js";const m=p.forwardRef(({className:r,orientation:o="horizontal",decorative:t=!0,...e},a)=>l(i.Root,{ref:a,decorative:t,orientation:o,className:f("shrink-0 bg-border",o==="horizontal"?"h-px w-full":"h-full w-px",r),...e}));m.displayName="Separator";export{m as Separator};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Right-side sheet — the physical basis of the record drawer (§2.2).
|
|
5
|
+
*
|
|
6
|
+
* Modal by default: the page behind is blurred and inert until the sheet is
|
|
7
|
+
* closed (Escape, the close button or a click on the blurred page).
|
|
8
|
+
*/
|
|
9
|
+
export declare const Sheet: React.FC<DialogPrimitive.DialogProps>;
|
|
10
|
+
export declare const SheetTrigger: React.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
11
|
+
export declare const SheetClose: React.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
|
|
12
|
+
export declare const SheetContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
13
|
+
side?: "right" | "left";
|
|
14
|
+
width?: string;
|
|
15
|
+
scrim?: boolean;
|
|
16
|
+
hideClose?: boolean;
|
|
17
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
18
|
+
export declare const SheetTitle: React.ForwardRefExoticComponent<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>>;
|
|
19
|
+
export declare const SheetDescription: React.ForwardRefExoticComponent<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as t,jsxs as o}from"react/jsx-runtime";import*as e from"@radix-ui/react-dialog";import{X as c}from"lucide-react";import*as p from"react";import{cn as g}from"../../lib/utils.js";const x=e.Root,u=e.Trigger,C=e.Close,b=p.forwardRef(({className:i,children:s,side:r="right",width:l="w-full sm:w-drawer",scrim:a=!0,hideClose:n,...m},d)=>o(e.Portal,{children:[a?t(e.Overlay,{"data-scrim":"",className:"fixed inset-0 z-50 bg-[rgba(5,8,22,.42)] backdrop-blur-[3px]"}):null,o(e.Content,{ref:d,"data-sheet":r,className:g("fixed inset-y-0 z-50 flex max-w-full flex-col border-border bg-raised shadow-elev3 outline-none",r==="right"?"right-0 max-sm:border-l sm:inset-y-2 sm:right-2 sm:rounded-[16px] sm:border":"left-0 max-sm:border-r sm:inset-y-2 sm:left-2 sm:rounded-[16px] sm:border",l,i),...m,children:[s,n?null:o(e.Close,{className:"absolute right-4 top-4 z-10 grid size-8 cursor-pointer place-items-center rounded-full border border-border bg-raised/80 text-muted backdrop-blur transition-[background-color,color,transform] hover:bg-hover hover:text-text active:scale-95",children:[t(c,{className:"size-4"}),t("span",{className:"sr-only",children:"Close"})]})]})]}));b.displayName="SheetContent";const v=e.Title,P=e.Description;export{x as Sheet,C as SheetClose,b as SheetContent,P as SheetDescription,v as SheetTitle,u as SheetTrigger};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Sweeps rather than pulses — a pulse reads as an error state to most users. */
|
|
2
|
+
export declare function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
|
|
3
|
+
/** Table placeholder that keeps the real row height, so nothing jumps on load. */
|
|
4
|
+
export declare function SkeletonTable({ rows, cols }: {
|
|
5
|
+
rows?: number;
|
|
6
|
+
cols?: number;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
export declare function SkeletonKpis({ count }: {
|
|
9
|
+
count?: number;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as s}from"react/jsx-runtime";import{cn as m}from"../../lib/utils.js";function o({className:r,...a}){return e("div",{className:m("shimmer rounded-ctl",r),...a})}function i({rows:r=8,cols:a=6}){return s("div",{className:"overflow-hidden rounded-card border border-border bg-surface",children:[e("div",{className:"flex gap-4 border-b border-border px-cellx py-2",children:Array.from({length:a}).map((l,d)=>e(o,{className:"h-3 flex-1"},d))}),Array.from({length:r}).map((l,d)=>e("div",{className:"flex items-center gap-4 border-b border-border px-cellx last:border-0",style:{height:"var(--row-h)"},children:Array.from({length:a}).map((c,t)=>e(o,{className:"h-3 flex-1",style:{opacity:1-d*.07}},t))},d))]})}function b({count:r=5}){return e("div",{className:"grid grid-cols-2 gap-3 xl:grid-cols-5",children:Array.from({length:r}).map((a,l)=>s("div",{className:"rounded-card border border-border bg-surface p-[17px]",children:[e(o,{className:"h-3 w-20"}),e(o,{className:"mt-3 h-7 w-28"}),e(o,{className:"mt-2 h-3 w-24"})]},l))})}export{o as Skeleton,b as SkeletonKpis,i as SkeletonTable};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export declare const Switch: React.ForwardRefExoticComponent<Omit<SwitchPrimitive.SwitchProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as o}from"react/jsx-runtime";import*as t from"@radix-ui/react-switch";import*as n from"react";import{cn as e}from"../../lib/utils.js";const s=n.forwardRef(({className:r,...i},a)=>o(t.Root,{ref:a,className:e("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border border-transparent bg-border2 transition-colors duration-150 data-[state=checked]:bg-primary disabled:cursor-not-allowed disabled:opacity-50",r),...i,children:o(t.Thumb,{className:e("pointer-events-none block size-4 rounded-full bg-white shadow-sm ring-0 transition-transform duration-150 ease-wave translate-x-0.5 data-[state=checked]:translate-x-[18px]")})}));s.displayName="Switch";export{s as Switch};
|