@waveinno/ui 0.4.0 → 0.6.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 (44) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +2 -2
  3. package/dist/components/patterns/index.d.ts +1 -0
  4. package/dist/components/patterns/index.js +1 -1
  5. package/dist/components/patterns/org-chart.d.ts +51 -0
  6. package/dist/components/patterns/org-chart.js +1 -0
  7. package/dist/components/ui/accordion.d.ts +30 -0
  8. package/dist/components/ui/accordion.js +1 -0
  9. package/dist/components/ui/avatar.js +1 -1
  10. package/dist/components/ui/calendar.js +1 -1
  11. package/dist/components/ui/carousel.d.ts +27 -0
  12. package/dist/components/ui/carousel.js +1 -0
  13. package/dist/components/ui/color-picker.d.ts +14 -0
  14. package/dist/components/ui/color-picker.js +1 -0
  15. package/dist/components/ui/confirm-dialog.d.ts +24 -11
  16. package/dist/components/ui/confirm-dialog.js +1 -1
  17. package/dist/components/ui/date-picker.d.ts +18 -1
  18. package/dist/components/ui/date-picker.js +1 -1
  19. package/dist/components/ui/file-upload.d.ts +12 -4
  20. package/dist/components/ui/file-upload.js +1 -1
  21. package/dist/components/ui/hover-card.d.ts +17 -0
  22. package/dist/components/ui/hover-card.js +1 -0
  23. package/dist/components/ui/index.d.ts +10 -0
  24. package/dist/components/ui/index.js +1 -1
  25. package/dist/components/ui/menu.d.ts +24 -0
  26. package/dist/components/ui/menu.js +1 -1
  27. package/dist/components/ui/pagination.d.ts +51 -0
  28. package/dist/components/ui/pagination.js +1 -0
  29. package/dist/components/ui/rating.d.ts +27 -0
  30. package/dist/components/ui/rating.js +1 -0
  31. package/dist/components/ui/scroll-area.d.ts +17 -0
  32. package/dist/components/ui/scroll-area.js +1 -0
  33. package/dist/components/ui/slider.d.ts +18 -6
  34. package/dist/components/ui/slider.js +1 -1
  35. package/dist/components/ui/steps.d.ts +36 -0
  36. package/dist/components/ui/steps.js +1 -0
  37. package/dist/components/ui/tag-input.d.ts +33 -0
  38. package/dist/components/ui/tag-input.js +1 -0
  39. package/dist/components/ui/toast.d.ts +12 -1
  40. package/dist/components/ui/toast.js +1 -1
  41. package/dist/components/ui/tree-view.d.ts +38 -0
  42. package/dist/components/ui/tree-view.js +1 -0
  43. package/dist/styles.css +143 -0
  44. package/package.json +4 -1
package/CHANGELOG.md CHANGED
@@ -6,6 +6,36 @@ prop, major = a renamed or removed export or prop.
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.6.0 — 2026-10-02
10
+
11
+ - **OrgChart** is smooth: opening or closing a team never moves the person clicked (the chart is re-anchored
12
+ before paint), the connector draws down and the team springs in one by one, closing lifts it away, and the view
13
+ glides to show the new team (zooming out a little when it is wide). Panning glides on after a drag; Ctrl/⌘ + wheel
14
+ zooms at the pointer; double-click zooms in. Connectors are 2px in a brand tint with a dot where a stem meets its
15
+ team; no hairline gaps. The `list` look folds with a height animation.
16
+ - **Toaster** positions: every corner and edge plus the middle of the screen (`middle-left`, `middle-center`,
17
+ `middle-right`); `ToastPosition` type. The loading spinner of a promise toast now sits in its icon tile.
18
+ - Avatar: the status dot stays on the face when the avatar sits in a stretching flex row (a hover card, a list).
19
+
20
+ ## 0.5.0 — 2026-10-02
21
+
22
+ - **New components**: Accordion (line, card, contained; chevron or plus), Pagination (outline, pill, gradient,
23
+ underline, dots, jumper, minimal; `pageRange()`), Steps (circle, glow, card, chevron, bar, dot; vertical), TreeView
24
+ (select, or tri-state checkboxes; full keyboard), HoverCard (default, glass, dark), ScrollArea (overlay scrollbar,
25
+ edge fades), TagInput (paste lists, validate, max, suggestions), Rating (half steps, labels, read-only with count),
26
+ Carousel (scroll-snap, arrows inside or outside, dots or bar, autoplay), ColorPicker and ColorPickerPopover,
27
+ OrgChart (card, gradient, avatar, compact, list; folding teams, pan, zoom, fit).
28
+ - **Menu** collapses: `collapsible`, `collapsed` / `onCollapsedChange`, `collapsedMode` `icons` (names in tooltips,
29
+ counts on the icons) or `hidden` (folds away, as the AppShell panel); `collapseShortcut` (⌘B); `MenuCollapseTrigger`.
30
+ - **DateRangePicker** redesigned: both ends and the length in the field, Start and End slots, presets showing their
31
+ dates, a band that previews the span, Cancel and Apply. **Behaviour change:** the value now changes on Apply; pass
32
+ `applyOnSelect` for the old commit-on-second-click. The calendar's range band is continuous along each week.
33
+ - **Slider** is smooth: the thumb follows the pointer and settles on the step; clicks and keys glide. New looks fat,
34
+ glow, stepped, minimal; vertical orientation.
35
+ - **FileUpload** looks: card, button, gallery (tiles with progress rings), avatar (`currentUrl`).
36
+ - **ConfirmDialog** looks: center, split, banner, sheet; `primary` tone; `hold` (press and hold to confirm).
37
+ - Docs: ⌘K search, a props table on every component page (read from the source), the new components' pages.
38
+
9
39
  ## 0.4.0 — 2026-10-02
10
40
 
11
41
  - **Works in Vite and any React 19 app.** The package no longer imports Next.js: links and navigation go through a
package/README.md CHANGED
@@ -63,8 +63,8 @@ through `labels` props, so each product passes its own language.
63
63
 
64
64
  | Group | Components |
65
65
  | --- | --- |
66
- | Primitives | Button (working + showcase variants), Badge (soft, solid, outline, dot, gradient, live), Input / Textarea (states, adornments), NumberInput, PasswordInput (strength, Caps Lock), PinInput (OTP), FileUpload, FormField, Select, Combobox (searchable), Checkbox, RadioGroup and RadioCard, Switch, Slider (range, marks), Segmented, Tabs (underline, pill, solid, enclosed), Calendar, DatePicker, DateTimePicker, DateRangePicker, TimePicker, Dialog (drawer that widens or goes full width), Sheet, ConfirmDialog, DropdownMenu (rich items, header, dark), Menu (soft, line, raised, gradient, dark, plus the shell's panel and rail; branches, sliding highlight), Popover (arrow, dark, brand), Tooltip, Alert (five tones, four looks), Toaster and toast, Spinner (ring, dots, wave), Kbd, Progress / ProgressRing, Avatar, Skeleton |
67
- | Patterns | AppLauncher (switch-app button: grid, list, spotlight, glass, dark), DataTable (advanced filters, saved views, five looks, inline and bulk edit, bulk delete, sticky actions), UserCell, RowActions, PageHero, PageHeader, StatCard, KpiCard, Money, ActivityFeed, ActivityTimeline, ChangeHistory, ChangeNotes, Note, Kanban, empty / error / loading states |
66
+ | Primitives | Button (working + showcase variants), Badge (soft, solid, outline, dot, gradient, live), Input / Textarea (states, adornments), NumberInput, PasswordInput (strength, Caps Lock), PinInput (OTP), FileUpload, FormField, Select, Combobox (searchable), Checkbox, RadioGroup and RadioCard, Switch, Slider (range, marks), Segmented, Tabs (underline, pill, solid, enclosed), Calendar, DatePicker, DateTimePicker, DateRangePicker, TimePicker, Dialog (drawer that widens or goes full width), Sheet, ConfirmDialog, DropdownMenu (rich items, header, dark), Menu (soft, line, raised, gradient, dark, plus the shell's panel and rail; branches, sliding highlight), Popover (arrow, dark, brand), HoverCard, Tooltip, Alert (five tones, four looks), Toaster and toast, Spinner (ring, dots, wave), Kbd, Accordion, Pagination (seven looks), Steps (six looks), TreeView, ScrollArea, TagInput, Rating, Carousel, ColorPicker, Progress / ProgressRing, Avatar, Skeleton |
67
+ | Patterns | AppLauncher (switch-app button: grid, list, spotlight, glass, dark), OrgChart (card, gradient, avatar, compact, list), DataTable (advanced filters, saved views, five looks, inline and bulk edit, bulk delete, sticky actions), UserCell, RowActions, PageHero, PageHeader, StatCard, KpiCard, Money, ActivityFeed, ActivityTimeline, ChangeHistory, ChangeNotes, Note, Kanban, empty / error / loading states |
68
68
  | Charts | TrendChart, BarChart, LineChart, DonutChart, GaugeChart, Heatmap, BarList, ChartCard, validated palette |
69
69
  | Brand | WaveinnoLogo, WaveinnoSymbol, WaveMark (app icon: seven tones, round, 3D, animated), PoweredBy, Watermark; `@waveinno/ui/brand/waveinno-logo.svg` |
70
70
  | Shell | AppShell (rail → panel → content → drawer, ⌘K), theme and density controls, record drawer |
@@ -9,6 +9,7 @@ export type { ColumnDef } from "@tanstack/react-table";
9
9
  export * from "./kanban";
10
10
  export * from "./kpi-card";
11
11
  export * from "./money";
12
+ export * from "./org-chart";
12
13
  export * from "./page-header";
13
14
  export * from "./page-hero";
14
15
  export * from "./page-shell";
@@ -1 +1 @@
1
- export*from"./activity-feed.js";export*from"./app-launcher.js";export*from"./data-table.js";export*from"./data-table-cells.js";export*from"./data-table-edit.js";export*from"./data-table-filters.js";export*from"./kanban.js";export*from"./kpi-card.js";export*from"./money.js";export*from"./page-header.js";export*from"./page-hero.js";export*from"./page-shell.js";export*from"./stat-card.js";export*from"./states.js";export*from"./timeline.js";
1
+ export*from"./activity-feed.js";export*from"./app-launcher.js";export*from"./data-table.js";export*from"./data-table-cells.js";export*from"./data-table-edit.js";export*from"./data-table-filters.js";export*from"./kanban.js";export*from"./kpi-card.js";export*from"./money.js";export*from"./org-chart.js";export*from"./page-header.js";export*from"./page-hero.js";export*from"./page-shell.js";export*from"./stat-card.js";export*from"./states.js";export*from"./timeline.js";
@@ -0,0 +1,51 @@
1
+ import * as React from "react";
2
+ /**
3
+ * OrgChart — who reports to whom: a company, a site's staff, a franchise.
4
+ *
5
+ * A top-down tree with rounded connectors. Each person with reports carries a
6
+ * count that folds and unfolds their team. Opening a team never moves the
7
+ * person you clicked: the chart is re-anchored under them before the frame is
8
+ * painted, the connector draws down, the team springs in one by one, and the
9
+ * view glides to show all of it. Closing plays the same in reverse. Drag the
10
+ * background to pan (it glides on when let go), Ctrl/⌘ + wheel or the toolbar
11
+ * to zoom; Fit, Expand all and Collapse all are one click. Departments get a
12
+ * colour (pass `departments`, or one is chosen from the name).
13
+ *
14
+ * Looks:
15
+ * card — the default: a card per person with photo, role and department.
16
+ * gradient — the top of the tree in the brand gradient, department-coloured cards below.
17
+ * avatar — photo-first: large round portraits with names under them.
18
+ * compact — small pills, for large organisations.
19
+ * list — an indented outline with guide lines, for phones and very wide teams.
20
+ */
21
+ export type OrgChartVariant = "card" | "gradient" | "avatar" | "compact" | "list";
22
+ export interface OrgNode {
23
+ id: string;
24
+ name: string;
25
+ title?: string;
26
+ department?: string;
27
+ /** Photo URL; without one, initials. */
28
+ avatar?: string;
29
+ /** Beside the name: "New", "On leave". */
30
+ badge?: React.ReactNode;
31
+ children?: OrgNode[];
32
+ }
33
+ export interface OrgChartProps {
34
+ data: OrgNode;
35
+ variant?: OrgChartVariant;
36
+ /** Department → colour. Departments not listed get one from a palette. */
37
+ departments?: Record<string, string>;
38
+ /** Ids folded at first. Or `collapseDepth` folds everything below a depth. */
39
+ defaultCollapsed?: string[];
40
+ collapseDepth?: number;
41
+ selected?: string;
42
+ onSelect?: (node: OrgNode) => void;
43
+ /** Height of the chart box (not used by `list`). */
44
+ height?: number;
45
+ className?: string;
46
+ }
47
+ declare const ids: (n: OrgNode) => string[];
48
+ export declare function OrgChart({ data, variant, departments, defaultCollapsed, collapseDepth, selected, onSelect, height, className, }: OrgChartProps): React.JSX.Element;
49
+ /** Every id in a tree: handy for "expand all" outside the chart. */
50
+ export declare const orgIds: typeof ids;
51
+ export {};
@@ -0,0 +1 @@
1
+ "use client";import{jsx as r,jsxs as d}from"react/jsx-runtime";import{ChevronDown as ie,ChevronRight as oe,ChevronsDownUp as le,ChevronsUpDown as ce,Maximize2 as de,Minus as ue,Plus as pe}from"lucide-react";import*as h from"react";import{cn as w}from"../../lib/utils.js";import{Avatar as I}from"../ui/avatar.js";const re=["#4f46e5","#0ea5e9","#10b981","#f59e0b","#e11d48","#7c3aed","#0d9488","#ea580c"],ge=t=>[...t].reduce((_,y)=>_*31+y.charCodeAt(0)>>>0,7),j=t=>(t.children??[]).reduce((_,y)=>_+1+j(y),0),ne=t=>[t.id,...(t.children??[]).flatMap(ne)],me=220,U=()=>typeof window<"u"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches;function we({data:t,variant:_="card",departments:y,defaultCollapsed:v,collapseDepth:C,selected:k,onSelect:$,height:R=520,className:o}){const c=h.useMemo(()=>{if(v)return new Set(v);if(C===void 0)return new Set;const s=new Set,x=(O,N)=>{N>=C&&O.children?.length&&s.add(O.id),O.children?.forEach(P=>x(P,N+1))};return x(t,0),s},[t,v,C]),[p,a]=h.useState(c),g=s=>s.department?y?.[s.department]??re[ge(s.department)%re.length]:"var(--primary)";return _==="list"?r(xe,{data:t,folded:p,toggle:x=>a(O=>{const N=new Set(O);return N.has(x)?N.delete(x):N.add(x),N}),tone:g,selected:k,onSelect:$,className:o}):r(be,{data:t,variant:_,folded:p,setFolded:a,tone:g,selected:k,onSelect:$,height:R,className:o})}function be({data:t,variant:_,folded:y,setFolded:v,tone:C,selected:k,onSelect:$,height:R,className:o}){const c=h.useRef(null),p=h.useRef(null),[a,g]=h.useState({x:0,y:28,z:1}),[s,x]=h.useState(!1),[O,N]=h.useState(new Set),[P,H]=h.useState(!1),S=h.useRef(a);S.current=a;const E=h.useRef(null),T=h.useRef(null),m=h.useRef(void 0),A=e=>p.current?.querySelector(`[data-org-card="${CSS.escape(e)}"]`)?.getBoundingClientRect(),J=(e,n)=>{x(n&&!U()),g(e)},D=h.useCallback(e=>{const n=c.current,u=p.current;if(!n||!u)return;const l=u.offsetWidth,i=u.offsetHeight,b=Math.max(.3,Math.min(1,(n.clientWidth-64)/l,(n.clientHeight-64)/i));x(e&&!U()),g({x:(n.clientWidth-l*b)/2,y:Math.max(28,(n.clientHeight-i*b)/2),z:b})},[]);h.useLayoutEffect(()=>D(!1),[D]);const se=e=>{const n=A(e);if(y.has(e)){n&&(E.current={id:e,x:n.left,y:n.top,reveal:!0}),v(l=>{const i=new Set(l);return i.delete(e),i});return}N(l=>new Set(l).add(e)),window.setTimeout(()=>{const l=A(e);l&&(E.current={id:e,x:l.left,y:l.top,reveal:!1}),v(i=>new Set(i).add(e)),N(i=>{const b=new Set(i);return b.delete(e),b})},U()?0:me)},Q=e=>{const n=A(t.id);n&&(E.current={id:t.id,x:n.left,y:n.top,reveal:!1}),v(e),requestAnimationFrame(()=>requestAnimationFrame(()=>D(!0)))};h.useLayoutEffect(()=>{const e=E.current;if(!e)return;E.current=null;const n=A(e.id);if(!n)return;const u=S.current,l={...u,x:u.x+(e.x-n.left),y:u.y+(e.y-n.top)};x(!1),g(l),e.reveal&&window.setTimeout(()=>{const i=c.current,b=p.current?.querySelector(`[data-org-li="${CSS.escape(e.id)}"]`);if(!i||!b)return;const f=i.getBoundingClientRect(),L=b.getBoundingClientRect(),M=40,z=S.current;let F=z.z;L.width>f.width-M*2&&(F=Math.max(.35,z.z*((f.width-M*2)/L.width)));const q=F/z.z,V=(L.left-f.left-z.x)*q+z.x,K=(L.top-f.top-z.y)*q+z.y,W=L.width*q,te=L.height*q;let X=z.x,Z=z.y;W>f.width-M*2?X+=f.width/2-(V+W/2):V<M?X+=M-V:V+W>f.width-M&&(X+=f.width-M-(V+W)),K+te>f.height-M&&(Z+=Math.max(M-K,f.height-M-(K+te))),(X!==z.x||Z!==z.y||F!==z.z)&&J({x:X,y:Z,z:F},!0)},60)},[y]);const B=(e,n,u)=>{const l=c.current;if(!l)return;const i=S.current,b=Math.min(1.6,Math.max(.3,e)),f=n??l.clientWidth/2,L=u??l.clientHeight/2;J({z:b,x:f-(f-i.x)/i.z*b,y:L-(L-i.y)/i.z*b},!0)},ee=()=>{m.current&&cancelAnimationFrame(m.current),m.current=void 0};h.useEffect(()=>ee,[]);const Y="grid size-8 cursor-pointer place-items-center rounded-[calc(8px*var(--radius-scale))] text-muted outline-none transition-[background-color,color,transform] hover:bg-hover hover:text-text active:scale-90 focus-visible:ring-2 focus-visible:ring-primary/40 [&_svg]:size-4",G="520ms cubic-bezier(.22,1,.36,1)";return d("div",{ref:c,className:w("relative touch-none select-none overflow-hidden rounded-[calc(16px*var(--radius-scale))] border border-border bg-surface",P?"cursor-grabbing":"cursor-grab",o),style:{height:R,backgroundImage:"radial-gradient(color-mix(in srgb, var(--border2) 60%, transparent) 1px, transparent 1px)",backgroundSize:`${20*a.z}px ${20*a.z}px`,backgroundPosition:`${a.x}px ${a.y}px`,transition:s?`background-position ${G}, background-size ${G}`:void 0},onPointerDown:e=>{e.target.closest("button, a, input")||(ee(),x(!1),H(!0),T.current={x:e.clientX,y:e.clientY,vx:a.x,vy:a.y,t:performance.now(),speedX:0,speedY:0},e.currentTarget.setPointerCapture(e.pointerId))},onPointerMove:e=>{const n=T.current;if(!n)return;const u=performance.now(),l=n.vx+e.clientX-n.x,i=n.vy+e.clientY-n.y,b=S.current,f=Math.max(1,u-n.t);n.speedX=n.speedX*.6+(l-b.x)/f*.4,n.speedY=n.speedY*.6+(i-b.y)/f*.4,n.t=u,g({...b,x:l,y:i})},onPointerUp:()=>{const e=T.current;if(T.current=null,H(!1),!e||U())return;let n=e.speedX*16,u=e.speedY*16;if(Math.hypot(n,u)<1.5||performance.now()-e.t>80)return;const l=()=>{n*=.92,u*=.92,g(i=>({...i,x:i.x+n,y:i.y+u})),m.current=Math.hypot(n,u)>.4?requestAnimationFrame(l):void 0};m.current=requestAnimationFrame(l)},onWheel:e=>{if(!(e.ctrlKey||e.metaKey))return;e.preventDefault();const n=c.current.getBoundingClientRect();B(S.current.z*(e.deltaY<0?1.12:1/1.12),e.clientX-n.left,e.clientY-n.top)},onDoubleClick:e=>{if(e.target.closest("button, a, input"))return;const n=c.current.getBoundingClientRect();B(S.current.z*1.4,e.clientX-n.left,e.clientY-n.top)},children:[r("div",{ref:p,className:"wm-org absolute left-0 top-0 w-max origin-top-left will-change-transform",style:{transform:`translate3d(${a.x}px, ${a.y}px, 0) scale(${a.z})`,transition:s?`transform ${G}`:void 0,"--org-line":_==="gradient"?"color-mix(in srgb, var(--primary) 55%, var(--border2))":void 0},onTransitionEnd:e=>{e.target===e.currentTarget&&x(!1)},children:r("ul",{children:r(ae,{node:t,index:0,depth:0,variant:_,folded:y,leaving:O,toggle:se,tone:C,selected:k,onSelect:$})})}),d("div",{className:"absolute right-3 top-3 flex items-center gap-0.5 rounded-[calc(11px*var(--radius-scale))] border border-border bg-raised/90 p-1 shadow-[var(--lit),0_4px_14px_-6px_rgba(5,8,22,.25)] backdrop-blur",children:[r("button",{type:"button","aria-label":"Zoom out",className:Y,onClick:()=>B(a.z/1.25),children:r(ue,{})}),d("span",{className:"num w-11 text-center text-[11.5px] font-medium tabular-nums text-muted",children:[Math.round(a.z*100),"%"]}),r("button",{type:"button","aria-label":"Zoom in",className:Y,onClick:()=>B(a.z*1.25),children:r(pe,{})}),r("span",{className:"mx-0.5 h-5 w-px bg-border"}),r("button",{type:"button","aria-label":"Fit to the box",className:Y,onClick:()=>D(!0),children:r(de,{})}),r("button",{type:"button","aria-label":"Expand everyone",className:Y,onClick:()=>Q(new Set),children:r(ce,{})}),r("button",{type:"button","aria-label":"Collapse to the top",className:Y,onClick:()=>Q(new Set((t.children??[]).filter(e=>e.children?.length).map(e=>e.id))),children:r(le,{})})]})]})}function ae({node:t,index:_,depth:y,variant:v,folded:C,leaving:k,toggle:$,tone:R,selected:o,onSelect:c}){const p=t.children??[],a=p.length>0&&!C.has(t.id),g=k.has(t.id),s=R(t),x=o===t.id,O=j(t),N=p.length?d("button",{type:"button",onClick:()=>$(t.id),"aria-expanded":a&&!g,"aria-label":`${a&&!g?"Hide":"Show"} ${t.name}'s team (${O})`,className:w("absolute -bottom-3 left-1/2 z-10 flex h-6 -translate-x-1/2 cursor-pointer items-center gap-0.5 rounded-full border px-2 text-[11px] font-semibold outline-none","shadow-[0_2px_6px_-2px_rgba(5,8,22,.25)] transition-[background-color,color,border-color,transform,box-shadow] duration-300 ease-[cubic-bezier(.3,1.4,.5,1)] hover:scale-110 active:scale-95 focus-visible:ring-2 focus-visible:ring-primary/40",a&&!g?"border-border bg-raised text-muted hover:text-text":"border-transparent bg-[linear-gradient(135deg,var(--brand-1),var(--brand-2))] text-white hover:shadow-[0_6px_16px_-6px_var(--brand-1)]"),children:[r("span",{className:"num",children:O}),r(ie,{className:w("size-3 transition-transform duration-300 ease-[cubic-bezier(.3,1.4,.5,1)]",a&&!g&&"rotate-180")})]}):null,P=c?()=>c(t):void 0,H=c?"button":"div",S=c?{type:"button",onClick:P}:{},E="transition-[border-color,box-shadow,transform] duration-300 ease-[cubic-bezier(.22,1,.36,1)]";let T;if(v==="avatar")T=d("div",{"data-org-card":t.id,className:"relative flex w-36 flex-col items-center pb-4 text-center",children:[r(H,{...S,className:w("relative rounded-full outline-none focus-visible:ring-2 focus-visible:ring-primary/50",E,c&&"cursor-pointer hover:-translate-y-1"),children:r("span",{className:w("block rounded-full p-[3px] transition-shadow duration-300",x&&"shadow-[0_0_0_5px_var(--primary-subtle),0_12px_28px_-12px_var(--primary)]"),style:{background:`conic-gradient(from 210deg, ${s}, color-mix(in srgb, ${s} 30%, transparent), ${s})`},children:r("span",{className:"block rounded-full bg-raised p-[3px]",children:r(I,{name:t.name,src:t.avatar,size:"xl"})})})}),r("p",{className:"mt-2 text-[13.5px] font-semibold leading-5 text-text",children:t.name}),t.title?r("p",{className:"text-[11.5px] leading-4 text-muted",children:t.title}):null,t.badge?r("div",{className:"mt-1.5",children:t.badge}):null,N]});else if(v==="compact")T=d("div",{"data-org-card":t.id,className:"relative pb-3",children:[d(H,{...S,className:w("flex h-10 max-w-[200px] items-center gap-2 rounded-full border bg-raised pl-1.5 pr-3.5 text-left shadow-[var(--lit),0_1px_2px_rgba(5,8,22,.06)] outline-none focus-visible:ring-2 focus-visible:ring-primary/40",E,x?"border-primary shadow-[0_0_0_3px_var(--primary-subtle)]":"border-border hover:border-border2",c&&"cursor-pointer hover:-translate-y-0.5 hover:shadow-[var(--lit),0_8px_18px_-10px_rgba(5,8,22,.3)]"),children:[r(I,{name:t.name,src:t.avatar,size:"md"}),d("span",{className:"min-w-0",children:[r("span",{className:"block truncate text-[12.5px] font-semibold leading-4 text-text",children:t.name}),t.title?r("span",{className:"block truncate text-[10.5px] leading-[14px] text-muted",children:t.title}):null]}),r("span",{className:"ml-1 size-2 shrink-0 rounded-full",style:{background:s}})]}),N]});else{const m=v==="gradient"&&y===0;T=d("div",{"data-org-card":t.id,className:"relative pb-3",children:[d(H,{...S,className:w("relative flex w-[212px] flex-col overflow-hidden rounded-[calc(14px*var(--radius-scale))] border text-left outline-none focus-visible:ring-2 focus-visible:ring-primary/40",E,m?"border-transparent bg-[linear-gradient(140deg,var(--brand-1),color-mix(in_srgb,var(--brand-1)_78%,#000)_45%,var(--brand-2))] text-white shadow-[inset_0_1px_0_rgba(255,255,255,.25),0_16px_34px_-16px_var(--brand-1)] [--muted:rgba(255,255,255,.75)] [--text:#fff]":"border-border bg-raised shadow-[var(--lit),0_1px_2px_rgba(5,8,22,.05),0_8px_20px_-14px_rgba(5,8,22,.25)]",x&&!m&&"border-primary shadow-[0_0_0_3px_var(--primary-subtle),0_14px_30px_-16px_color-mix(in_srgb,var(--primary)_65%,transparent)]",c&&"cursor-pointer hover:-translate-y-1 hover:shadow-[var(--lit),0_18px_36px_-18px_rgba(5,8,22,.35)]"),children:[m?null:r("span",{"aria-hidden":!0,className:"h-[3px] w-full",style:{background:v==="gradient"?`linear-gradient(90deg, ${s}, color-mix(in srgb, ${s} 40%, transparent))`:s}}),d("span",{className:"flex items-center gap-3 p-3",children:[r("span",{className:w("rounded-full",m&&"ring-2 ring-white/40"),style:m?void 0:{boxShadow:`0 0 0 2px var(--raised), 0 0 0 3.5px color-mix(in srgb, ${s} 55%, transparent)`},children:r(I,{name:t.name,src:t.avatar,size:"lg"})}),d("span",{className:"min-w-0 flex-1",children:[d("span",{className:"flex items-center gap-1.5",children:[r("span",{className:"truncate text-[13.5px] font-semibold text-text",children:t.name}),t.badge]}),t.title?r("span",{className:"block truncate text-[12px] text-muted",children:t.title}):null]})]}),t.department?d("span",{className:w("mx-3 mb-3 inline-flex w-fit items-center gap-1.5 rounded-full px-2 py-0.5 text-[10.5px] font-semibold",m&&"bg-white/15 text-white"),style:m?void 0:{background:`color-mix(in srgb, ${s} 12%, transparent)`,color:s},children:[r("span",{className:"size-1.5 rounded-full",style:{background:m?"#fff":s}}),t.department]}):null]}),N]})}return d("li",{"data-org-li":t.id,style:{"--i":_},children:[T,a?r("ul",{className:g?"wm-org-leave":"wm-org-enter",children:p.map((m,A)=>r(ae,{node:m,index:A,depth:y+1,variant:v,folded:C,leaving:k,toggle:$,tone:R,selected:o,onSelect:c},m.id))}):null]})}function xe({data:t,folded:_,toggle:y,tone:v,selected:C,onSelect:k,className:$}){const R=(o,c)=>{const p=o.children??[],a=p.length>0&&!_.has(o.id),g=C===o.id;return d("li",{children:[d("div",{className:w("group/row flex items-center gap-2.5 rounded-[calc(10px*var(--radius-scale))] py-1.5 pr-2 transition-colors duration-200",g?"bg-primary-subtle":"hover:bg-hover"),style:{paddingLeft:6+c*22},children:[p.length?r("button",{type:"button","aria-expanded":a,"aria-label":`${a?"Hide":"Show"} ${o.name}'s team`,onClick:()=>y(o.id),className:"grid size-6 shrink-0 cursor-pointer place-items-center rounded-[6px] text-muted transition-colors hover:bg-border/60 hover:text-text",children:r(oe,{className:w("size-3.5 transition-transform duration-300 ease-[cubic-bezier(.3,1.4,.5,1)]",a&&"rotate-90")})}):r("span",{className:"size-6 shrink-0"}),d("button",{type:"button",onClick:k?()=>k(o):void 0,className:w("flex min-w-0 flex-1 items-center gap-2.5 text-left outline-none",k&&"cursor-pointer"),children:[r("span",{className:"rounded-full",style:{boxShadow:`0 0 0 2px var(--canvas), 0 0 0 3.5px color-mix(in srgb, ${v(o)} 60%, transparent)`},children:r(I,{name:o.name,src:o.avatar,size:"md"})}),d("span",{className:"min-w-0 flex-1",children:[d("span",{className:"flex items-center gap-1.5",children:[r("span",{className:w("truncate text-[13px] font-semibold",g?"text-primary":"text-text"),children:o.name}),o.badge]}),r("span",{className:"block truncate text-[11.5px] text-muted",children:[o.title,o.department].filter(Boolean).join(" \xB7 ")})]})]}),p.length?r("span",{className:"num shrink-0 rounded-full bg-hover px-2 py-px text-[11px] font-medium text-muted group-hover/row:bg-raised",children:j(o)}):null]}),p.length?r("div",{className:w("grid transition-[grid-template-rows,opacity] duration-[380ms] ease-[cubic-bezier(.22,1,.36,1)]",a?"grid-rows-[1fr] opacity-100":"grid-rows-[0fr] opacity-0"),children:d("ul",{className:"relative min-h-0 overflow-hidden",inert:!a,children:[r("span",{"aria-hidden":!0,className:"absolute bottom-3 top-0 w-px bg-border",style:{left:18+c*22}}),p.map(s=>R(s,c+1))]})}):null]},o.id)};return r("ul",{className:w("space-y-px",$),children:R(t,0)})}const ye=ne;export{we as OrgChart,ye as orgIds};
@@ -0,0 +1,30 @@
1
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
2
+ import * as React from "react";
3
+ /**
4
+ * Accordion — questions and sections that fold, so a long page reads as a list
5
+ * of headings first. (One panel that hides and shows is just a button.)
6
+ *
7
+ * Looks — set `variant` on Accordion:
8
+ * line — the default: hairlines between items. FAQs, settings, help.
9
+ * card — each item its own card, the open one lifted. Onboarding, plans.
10
+ * contained — one bordered box, items divided inside. Inside forms and drawers.
11
+ * `indicator`: a chevron that turns (default) or a plus that becomes a cross.
12
+ * Items take an `icon`, a second-line `description` and a `badge`. Opening is
13
+ * animated to the content's real height; keyboard and ARIA are Radix's.
14
+ */
15
+ export type AccordionVariant = "line" | "card" | "contained";
16
+ type RootProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Root> & {
17
+ variant?: AccordionVariant;
18
+ indicator?: "chevron" | "plus";
19
+ };
20
+ export declare const Accordion: React.ForwardRefExoticComponent<RootProps & React.RefAttributes<HTMLDivElement>>;
21
+ export interface AccordionItemProps extends Omit<React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>, "title"> {
22
+ title: React.ReactNode;
23
+ /** A muted line under the title. */
24
+ description?: React.ReactNode;
25
+ icon?: React.ReactNode;
26
+ /** Beside the title: a count, "New". */
27
+ badge?: React.ReactNode;
28
+ }
29
+ export declare const AccordionItem: React.ForwardRefExoticComponent<AccordionItemProps & React.RefAttributes<HTMLDivElement>>;
30
+ export {};
@@ -0,0 +1 @@
1
+ "use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import*as o from"@radix-ui/react-accordion";import{ChevronDown as f,Plus as g}from"lucide-react";import*as n from"react";import{cn as c}from"../../lib/utils.js";const m=n.createContext({variant:"line",indicator:"chevron"}),R={line:"divide-y divide-border border-y border-border",card:"space-y-2.5",contained:"divide-y divide-border overflow-hidden rounded-card border border-border bg-raised shadow-[var(--lit)]"},y=n.forwardRef(({variant:a="line",indicator:i="chevron",className:r,...d},p)=>e(m.Provider,{value:{variant:a,indicator:i},children:e(o.Root,{ref:p,className:c(R[a],r),...d})}));y.displayName="Accordion";const h={line:"",card:"rounded-[calc(14px*var(--radius-scale))] border border-border bg-raised shadow-[var(--lit)] transition-[box-shadow,border-color] duration-200 data-[state=open]:border-primary/25 data-[state=open]:shadow-[var(--lit),0_10px_28px_-16px_color-mix(in_srgb,var(--primary)_45%,transparent)]",contained:"data-[state=open]:bg-surface/60"},A=n.forwardRef(({title:a,description:i,icon:r,badge:d,className:p,children:u,...v},x)=>{const{variant:t,indicator:b}=n.useContext(m),l=t==="line"?"px-1":"px-4";return s(o.Item,{ref:x,className:c("group/acc",h[t],p),...v,children:[e(o.Header,{asChild:!0,children:e("h3",{children:s(o.Trigger,{className:c("flex w-full cursor-pointer items-center gap-3 py-3.5 text-left outline-none transition-colors","focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary/40 disabled:cursor-not-allowed disabled:opacity-50",t==="line"&&"hover:text-primary",t!=="line"&&"rounded-[inherit]",l),children:[r?e("span",{className:"grid size-8 shrink-0 place-items-center rounded-[calc(9px*var(--radius-scale))] border border-border bg-surface text-muted transition-colors group-data-[state=open]/acc:border-primary/25 group-data-[state=open]/acc:bg-primary-subtle group-data-[state=open]/acc:text-primary [&_svg]:size-4",children:r}):null,s("span",{className:"min-w-0 flex-1",children:[s("span",{className:"flex items-center gap-2",children:[e("span",{className:"text-[14px] font-semibold text-text",children:a}),d]}),i?e("span",{className:"mt-0.5 block text-[12.5px] leading-[18px] text-muted",children:i}):null]}),b==="plus"?e("span",{className:"grid size-6 shrink-0 place-items-center rounded-full border border-border bg-raised text-muted transition-colors group-data-[state=open]/acc:border-primary/30 group-data-[state=open]/acc:text-primary",children:e(g,{className:"size-3.5 transition-transform duration-300 ease-[var(--ease)] group-data-[state=open]/acc:rotate-45"})}):e(f,{className:"size-4 shrink-0 text-muted transition-transform duration-300 ease-[var(--ease)] group-data-[state=open]/acc:rotate-180 group-data-[state=open]/acc:text-primary"})]})})}),e(o.Content,{className:"overflow-hidden data-[state=closed]:animate-[wm-acc-up_220ms_var(--ease)] data-[state=open]:animate-[wm-acc-down_260ms_var(--ease)]",children:e("div",{className:c("pb-4 text-[13.5px] leading-[1.65] text-body",l,r&&(t==="line"?"pl-[48px]":"pl-[60px]")),children:u})})]})});A.displayName="AccordionItem";export{y as Accordion,A as AccordionItem};
@@ -1 +1 @@
1
- "use client";import{jsx as t,jsxs as o}from"react/jsx-runtime";import*as m from"@radix-ui/react-avatar";import{BadgeCheck as x}from"lucide-react";import{cn as r,initials as v}from"../../lib/utils.js";const b={sm:"size-6 text-[10px]",md:"size-8 text-xs",lg:"size-10 text-[13px]",xl:"size-14 text-[17px]","2xl":"size-20 text-[24px]"},p={sm:"size-2",md:"size-2.5",lg:"size-3",xl:"size-3.5","2xl":"size-4"},u=["linear-gradient(135deg,#1f45ea,#5b4af5)","linear-gradient(135deg,#7560fd,#a78bfa)","linear-gradient(135deg,#0891b2,#22d3ee)","linear-gradient(135deg,#047857,#10b981)","linear-gradient(135deg,#d97706,#f59e0b)","linear-gradient(135deg,#db2777,#f472b6)","linear-gradient(135deg,#1a113e,#4338ca)"];function z(e){let a=0;for(const s of e)a=a*31+s.charCodeAt(0)>>>0;return u[a%u.length]}const h={online:"bg-success",away:"bg-warning",busy:"bg-danger",offline:"bg-border2"};function k({name:e,src:a,size:s="md",status:i,verified:l,ring:n,shape:c="circle",className:f}){const d=c==="circle"?"rounded-full":"rounded-[28%]",g=o(m.Root,{className:r("relative grid shrink-0 place-items-center overflow-hidden font-semibold text-white select-none shadow-[inset_0_1px_0_rgba(255,255,255,.25)]",d,b[s],!n&&f),style:{background:z(e)},children:[a?t(m.Image,{src:a,alt:e,className:"size-full object-cover"}):null,t(m.Fallback,{className:"grid size-full place-items-center",children:v(e)})]});return!n&&!i&&!l?g:o("span",{className:r("relative inline-grid shrink-0",n&&f),children:[n?t("span",{className:r("bg-[conic-gradient(from_200deg,var(--brand-1),var(--brand-2),#22d3ee,var(--brand-1))] p-[2px]",d),children:t("span",{className:r("block bg-canvas p-[2px]",d),children:g})}):g,i?t("span",{className:r("absolute bottom-0 right-0 rounded-full ring-2 ring-canvas",h[i],p[s]),"aria-label":i}):null,l?t(x,{className:r("absolute -right-1 -top-1 fill-primary text-canvas",p[s]==="size-2"?"size-3":"size-4"),"aria-label":"verified"}):null]})}function S({names:e,max:a=4,size:s="sm"}){const i=e.slice(0,a),l=e.length-i.length;return o("div",{className:"flex items-center",children:[i.map((n,c)=>t(k,{name:n,size:s,className:"-ml-1.5 ring-2 ring-surface first:ml-0"},n+c)),l>0?o("span",{className:r("num -ml-1.5 grid place-items-center rounded-full bg-hover font-semibold text-muted ring-2 ring-surface",b[s]),children:["+",l]}):null]})}export{k as Avatar,S as AvatarStack};
1
+ "use client";import{jsx as r,jsxs as o}from"react/jsx-runtime";import*as m from"@radix-ui/react-avatar";import{BadgeCheck as x}from"lucide-react";import{cn as n,initials as v}from"../../lib/utils.js";const b={sm:"size-6 text-[10px]",md:"size-8 text-xs",lg:"size-10 text-[13px]",xl:"size-14 text-[17px]","2xl":"size-20 text-[24px]"},p={sm:"size-2",md:"size-2.5",lg:"size-3",xl:"size-3.5","2xl":"size-4"},u=["linear-gradient(135deg,#1f45ea,#5b4af5)","linear-gradient(135deg,#7560fd,#a78bfa)","linear-gradient(135deg,#0891b2,#22d3ee)","linear-gradient(135deg,#047857,#10b981)","linear-gradient(135deg,#d97706,#f59e0b)","linear-gradient(135deg,#db2777,#f472b6)","linear-gradient(135deg,#1a113e,#4338ca)"];function z(e){let a=0;for(const i of e)a=a*31+i.charCodeAt(0)>>>0;return u[a%u.length]}const h={online:"bg-success",away:"bg-warning",busy:"bg-danger",offline:"bg-border2"};function k({name:e,src:a,size:i="md",status:s,verified:l,ring:t,shape:c="circle",className:f}){const d=c==="circle"?"rounded-full":"rounded-[28%]",g=o(m.Root,{className:n("relative grid shrink-0 place-items-center overflow-hidden font-semibold text-white select-none shadow-[inset_0_1px_0_rgba(255,255,255,.25)]",d,b[i],!t&&f),style:{background:z(e)},children:[a?r(m.Image,{src:a,alt:e,className:"size-full object-cover"}):null,r(m.Fallback,{className:"grid size-full place-items-center",children:v(e)})]});return!t&&!s&&!l?g:o("span",{className:n("relative inline-grid h-fit w-fit shrink-0",t&&f),children:[t?r("span",{className:n("bg-[conic-gradient(from_200deg,var(--brand-1),var(--brand-2),#22d3ee,var(--brand-1))] p-[2px]",d),children:r("span",{className:n("block bg-canvas p-[2px]",d),children:g})}):g,s?r("span",{className:n("absolute bottom-0 right-0 rounded-full ring-2 ring-canvas",h[s],p[i]),"aria-label":s}):null,l?r(x,{className:n("absolute -right-1 -top-1 fill-primary text-canvas",p[i]==="size-2"?"size-3":"size-4"),"aria-label":"verified"}):null]})}function w({names:e,max:a=4,size:i="sm"}){const s=e.slice(0,a),l=e.length-s.length;return o("div",{className:"flex items-center",children:[s.map((t,c)=>r(k,{name:t,size:i,className:"-ml-1.5 ring-2 ring-surface first:ml-0"},t+c)),l>0?o("span",{className:n("num -ml-1.5 grid place-items-center rounded-full bg-hover font-semibold text-muted ring-2 ring-surface",b[i]),children:["+",l]}):null]})}export{k as Avatar,w as AvatarStack};
@@ -1 +1 @@
1
- "use client";import{jsx as r,jsxs as k}from"react/jsx-runtime";import{ChevronLeft as W,ChevronRight as G}from"lucide-react";import*as y from"react";import{cn as D}from"../../lib/utils.js";function et(t){const e=/^(\d{4})-(\d{2})-(\d{2})/.exec(t??"");return e?new Date(Number(e[1]),Number(e[2])-1,Number(e[3])):null}function c(t){return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`}const v=(t,e)=>new Date(t.getFullYear(),t.getMonth(),t.getDate()+e),F=t=>new Date(t.getFullYear(),t.getMonth(),1),f=(t,e)=>!!t&&!!e&&c(t)===c(e);function p(t,e){const m=new Date(t.getFullYear(),t.getMonth()+e,1),x=new Date(m.getFullYear(),m.getMonth()+1,0).getDate();return new Date(m.getFullYear(),m.getMonth(),Math.min(t.getDate(),x))}function U(t,e){const m=F(t),x=(m.getDay()-e+7)%7;return Array.from({length:42},(S,I)=>v(m,I-x))}function Z(t){return y.useMemo(()=>({title:new Intl.DateTimeFormat(t,{month:"long",year:"numeric"}),month:new Intl.DateTimeFormat(t,{month:"short"}),year:new Intl.DateTimeFormat(t,{year:"numeric"}),weekday:new Intl.DateTimeFormat(t,{weekday:"short"}),day:new Intl.DateTimeFormat(t,{day:"numeric"}),full:new Intl.DateTimeFormat(t,{weekday:"long",day:"numeric",month:"long",year:"numeric"})}),[t])}const C="grid size-8 cursor-pointer place-items-center rounded-ctl text-muted transition-colors hover:bg-hover hover:text-text disabled:pointer-events-none disabled:opacity-30";function ot({selected:t=null,range:e,onDayClick:m,min:x=null,max:S=null,locale:I="en-GB",weekStartsOn:R=1,numberOfMonths:M=1,defaultMonth:j,autoFocus:q,className:E}){const d=Z(I),z=y.useMemo(()=>new Date,[]),P=t??e?.from??z,[i,w]=y.useState(()=>F(j??P)),[a,$]=y.useState(P),[u,_]=y.useState("days"),[T,K]=y.useState(null),Y=y.useRef(null),A=y.useRef(!!q),L=o=>(!x||c(o)>=c(x))&&(!S||c(o)<=c(S));y.useEffect(()=>{!A.current||u!=="days"||(A.current=!1,Y.current?.querySelector(`[data-day="${c(a)}"]`)?.focus({preventScroll:!0}))},[a,i,u]);const V=o=>{A.current=!0,$(o);const s=p(i,M-1);(o<i||o>=p(F(s),1))&&w(F(o))},J=o=>{const s=(a.getDay()-R+7)%7,b={ArrowLeft:()=>v(a,-1),ArrowRight:()=>v(a,1),ArrowUp:()=>v(a,-7),ArrowDown:()=>v(a,7),PageUp:()=>p(a,o.shiftKey?-12:-1),PageDown:()=>p(a,o.shiftKey?12:1),Home:()=>v(a,-s),End:()=>v(a,6-s)};b[o.key]?(o.preventDefault(),V(b[o.key]())):(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),L(a)&&m(a))},Q=U(new Date(2026,0,1),R).slice(0,7),h=e?e.to??(e.from&&T&&T>=e.from?T:null):null,X=o=>!!e?.from&&!!h&&o>e.from&&o<h;if(u!=="days"){const o=i.getFullYear(),s=o-o%12,b=u==="months"?Array.from({length:12},(l,g)=>new Date(o,g,1)):Array.from({length:12},(l,g)=>new Date(s+g,i.getMonth(),1)),n=l=>u==="months"?l.getMonth()===i.getMonth():l.getFullYear()===o;return k("div",{ref:Y,className:D("w-[268px]",E),children:[k("div",{className:"mb-2 flex items-center justify-between",children:[r("button",{type:"button","aria-label":"Previous",className:C,onClick:()=>w(p(i,u==="months"?-12:-144)),children:r(W,{className:"size-4"})}),r("button",{type:"button",onClick:()=>_(u==="months"?"years":"days"),className:"disp cursor-pointer rounded-ctl px-2 py-1 text-[13.5px] font-semibold text-text transition-colors hover:bg-hover",children:u==="months"?d.year.format(i):`${d.year.format(new Date(s,0))} \u2013 ${d.year.format(new Date(s+11,0))}`}),r("button",{type:"button","aria-label":"Next",className:C,onClick:()=>w(p(i,u==="months"?12:144)),children:r(G,{className:"size-4"})})]}),r("div",{className:"grid grid-cols-3 gap-1.5",children:b.map(l=>r("button",{type:"button",onClick:()=>{w(l),_(u==="years"?"months":"days")},className:D("num h-11 cursor-pointer rounded-ctl text-[13px] transition-colors",n(l)?"bg-primary font-semibold text-white shadow-[0_1px_2px_rgba(5,8,22,.14)]":"text-text hover:bg-hover"),children:u==="months"?d.month.format(l):d.year.format(l)},l.toISOString()))})]})}return r("div",{ref:Y,className:D("flex gap-5",E),onMouseLeave:()=>K(null),children:Array.from({length:M},(o,s)=>{const b=p(i,s);return k("div",{className:"w-[268px]",children:[k("div",{className:"mb-2 flex items-center justify-between",children:[r("button",{type:"button","aria-label":"Previous month",className:D(C,s>0&&"invisible"),onClick:()=>w(p(i,-1)),children:r(W,{className:"size-4"})}),r("button",{type:"button","aria-live":"polite",onClick:()=>_("months"),className:"disp cursor-pointer rounded-ctl px-2 py-1 text-[13.5px] font-semibold text-text transition-colors hover:bg-hover",children:d.title.format(b)}),r("button",{type:"button","aria-label":"Next month",className:D(C,s<M-1&&"invisible"),onClick:()=>w(p(i,1)),children:r(G,{className:"size-4"})})]}),r("div",{className:"grid grid-cols-7 pb-1",children:Q.map(n=>r("div",{className:"py-1 text-center text-[11px] font-medium text-muted",children:d.weekday.format(n)},n.getDay()))}),r("div",{role:"grid",onKeyDown:J,className:"grid grid-cols-7 gap-y-0.5",children:U(b,R).map(n=>{const l=n.getMonth()===b.getMonth();if(!l&&M>1)return r("div",{"aria-hidden":!0},c(n));const g=L(n),N=e?f(n,e.from)||f(n,h):f(n,t),H=X(n),B=f(n,z);return r("div",{className:D("relative",H&&"bg-primary-subtle",e&&f(n,e.from)&&h&&!f(e.from,h)&&"rounded-l-ctl bg-primary-subtle",e&&f(n,h)&&e.from&&!f(e.from,h)&&"rounded-r-ctl bg-primary-subtle"),children:k("button",{type:"button",role:"gridcell","data-day":c(n),tabIndex:f(n,a)?0:-1,"aria-selected":N,"aria-label":d.full.format(n),disabled:!g,onClick:()=>m(n),onFocus:()=>$(n),onMouseEnter:()=>e&&K(n),className:D("num relative grid h-9 w-full cursor-pointer place-items-center rounded-ctl text-[13px] outline-none transition-[background-color,color,box-shadow] duration-150",l?"text-text":"text-muted/55",g&&!N&&"hover:bg-hover",H&&"rounded-none text-primary hover:bg-primary/10","focus-visible:ring-2 focus-visible:ring-primary/40",N&&"bg-primary font-semibold text-white shadow-[0_1px_2px_rgba(5,8,22,.14)]",B&&!N&&"font-semibold text-primary",!g&&"cursor-not-allowed opacity-30"),children:[d.day.format(n),B&&!N?r("span",{className:"absolute bottom-1 left-1/2 size-1 -translate-x-1/2 rounded-full bg-primary"}):null]})},c(n))})})]},s)})})}export{ot as Calendar,v as addDays,p as addMonths,et as parseIsoDay,c as toIsoDay};
1
+ "use client";import{jsx as a,jsxs as N}from"react/jsx-runtime";import{ChevronLeft as X,ChevronRight as Z}from"lucide-react";import*as y from"react";import{cn as p}from"../../lib/utils.js";function ut(t){const e=/^(\d{4})-(\d{2})-(\d{2})/.exec(t??"");return e?new Date(Number(e[1]),Number(e[2])-1,Number(e[3])):null}function m(t){return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`}const h=(t,e)=>new Date(t.getFullYear(),t.getMonth(),t.getDate()+e),_=t=>new Date(t.getFullYear(),t.getMonth(),1),w=(t,e)=>!!t&&!!e&&m(t)===m(e);function f(t,e){const c=new Date(t.getFullYear(),t.getMonth()+e,1),g=new Date(c.getFullYear(),c.getMonth()+1,0).getDate();return new Date(c.getFullYear(),c.getMonth(),Math.min(t.getDate(),g))}function O(t,e){const c=_(t),g=(c.getDay()-e+7)%7;return Array.from({length:42},(S,I)=>h(c,I-g))}function st(t){return y.useMemo(()=>({title:new Intl.DateTimeFormat(t,{month:"long",year:"numeric"}),month:new Intl.DateTimeFormat(t,{month:"short"}),year:new Intl.DateTimeFormat(t,{year:"numeric"}),weekday:new Intl.DateTimeFormat(t,{weekday:"short"}),day:new Intl.DateTimeFormat(t,{day:"numeric"}),full:new Intl.DateTimeFormat(t,{weekday:"long",day:"numeric",month:"long",year:"numeric"})}),[t])}const C="grid size-8 cursor-pointer place-items-center rounded-ctl text-muted transition-colors hover:bg-hover hover:text-text disabled:pointer-events-none disabled:opacity-30";function ct({selected:t=null,range:e,onDayClick:c,min:g=null,max:S=null,locale:I="en-GB",weekStartsOn:R=1,numberOfMonths:F=1,defaultMonth:tt,autoFocus:et,className:K}){const d=st(I),L=y.useMemo(()=>new Date,[]),H=t??e?.from??L,[l,v]=y.useState(()=>_(tt??H)),[r,B]=y.useState(H),[u,T]=y.useState("days"),[E,W]=y.useState(null),Y=y.useRef(null),A=y.useRef(!!et),G=o=>(!g||m(o)>=m(g))&&(!S||m(o)<=m(S));y.useEffect(()=>{!A.current||u!=="days"||(A.current=!1,Y.current?.querySelector(`[data-day="${m(r)}"]`)?.focus({preventScroll:!0}))},[r,l,u]);const ot=o=>{A.current=!0,B(o);const s=f(l,F-1);(o<l||o>=f(_(s),1))&&v(_(o))},nt=o=>{const s=(r.getDay()-R+7)%7,b={ArrowLeft:()=>h(r,-1),ArrowRight:()=>h(r,1),ArrowUp:()=>h(r,-7),ArrowDown:()=>h(r,7),PageUp:()=>f(r,o.shiftKey?-12:-1),PageDown:()=>f(r,o.shiftKey?12:1),Home:()=>h(r,-s),End:()=>h(r,6-s)};b[o.key]?(o.preventDefault(),ot(b[o.key]())):(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),G(r)&&c(r))},at=O(new Date(2026,0,1),R).slice(0,7),k=e?e.to??(e.from&&E&&E>=e.from?E:null):null,rt=o=>!!e?.from&&!!k&&o>e.from&&o<k;if(u!=="days"){const o=l.getFullYear(),s=o-o%12,b=u==="months"?Array.from({length:12},(i,D)=>new Date(o,D,1)):Array.from({length:12},(i,D)=>new Date(s+D,l.getMonth(),1)),n=i=>u==="months"?i.getMonth()===l.getMonth():i.getFullYear()===o;return N("div",{ref:Y,className:p("w-[268px]",K),children:[N("div",{className:"mb-2 flex items-center justify-between",children:[a("button",{type:"button","aria-label":"Previous",className:C,onClick:()=>v(f(l,u==="months"?-12:-144)),children:a(X,{className:"size-4"})}),a("button",{type:"button",onClick:()=>T(u==="months"?"years":"days"),className:"disp cursor-pointer rounded-ctl px-2 py-1 text-[13.5px] font-semibold text-text transition-colors hover:bg-hover",children:u==="months"?d.year.format(l):`${d.year.format(new Date(s,0))} \u2013 ${d.year.format(new Date(s+11,0))}`}),a("button",{type:"button","aria-label":"Next",className:C,onClick:()=>v(f(l,u==="months"?12:144)),children:a(Z,{className:"size-4"})})]}),a("div",{className:"grid grid-cols-3 gap-1.5",children:b.map(i=>a("button",{type:"button",onClick:()=>{v(i),T(u==="years"?"months":"days")},className:p("num h-11 cursor-pointer rounded-ctl text-[13px] transition-colors",n(i)?"bg-primary font-semibold text-white shadow-[0_1px_2px_rgba(5,8,22,.14)]":"text-text hover:bg-hover"),children:u==="months"?d.month.format(i):d.year.format(i)},i.toISOString()))})]})}return a("div",{ref:Y,className:p("flex gap-5",K),onMouseLeave:()=>W(null),children:Array.from({length:F},(o,s)=>{const b=f(l,s);return N("div",{className:"w-[268px]",children:[N("div",{className:"mb-2 flex items-center justify-between",children:[a("button",{type:"button","aria-label":"Previous month",className:p(C,s>0&&"invisible"),onClick:()=>v(f(l,-1)),children:a(X,{className:"size-4"})}),a("button",{type:"button","aria-live":"polite",onClick:()=>T("months"),className:"disp cursor-pointer rounded-ctl px-2 py-1 text-[13.5px] font-semibold text-text transition-colors hover:bg-hover",children:d.title.format(b)}),a("button",{type:"button","aria-label":"Next month",className:p(C,s<F-1&&"invisible"),onClick:()=>v(f(l,1)),children:a(Z,{className:"size-4"})})]}),a("div",{className:"grid grid-cols-7 pb-1",children:at.map(n=>a("div",{className:"py-1 text-center text-[11px] font-medium text-muted",children:d.weekday.format(n)},n.getDay()))}),a("div",{role:"grid",onKeyDown:nt,className:"grid grid-cols-7 gap-y-1",children:O(b,R).map((n,i)=>{const D=n.getMonth()===b.getMonth();if(!D&&F>1)return a("div",{"aria-hidden":!0},m(n));const z=G(n),U=!!e&&w(n,e.from),P=!!e&&w(n,k),x=e?U||P:w(n,t),M=rt(n),j=w(n,L),q=!!e&&!e.to,$=q?"bg-primary-subtle/55":"bg-primary-subtle",V=!!e?.from&&!!k&&!w(e.from,k),J=i%7===0||n.getDate()===1,Q=i%7===6||h(n,1).getMonth()!==n.getMonth();return N("div",{className:p("relative",M&&$,M&&J&&"rounded-l-[calc(10px*var(--radius-scale))]",M&&Q&&"rounded-r-[calc(10px*var(--radius-scale))]"),children:[V&&U&&!Q?a("span",{"aria-hidden":!0,className:p("absolute inset-y-0 left-1/2 right-0",$)}):null,V&&P&&!J?a("span",{"aria-hidden":!0,className:p("absolute inset-y-0 left-0 right-1/2",$)}):null,N("button",{type:"button",role:"gridcell","data-day":m(n),tabIndex:w(n,r)?0:-1,"aria-selected":x,"aria-label":d.full.format(n),disabled:!z,onClick:()=>c(n),onFocus:()=>B(n),onMouseEnter:()=>e&&W(n),className:p("num relative grid h-9 w-full cursor-pointer place-items-center rounded-ctl text-[13px] outline-none transition-[background-color,color,box-shadow,transform] duration-150",D?"text-text":"text-muted/55",z&&!x&&!M&&"hover:bg-hover",M&&"rounded-none text-primary hover:bg-primary/10","focus-visible:ring-2 focus-visible:ring-primary/40",x&&(e?"rounded-[calc(10px*var(--radius-scale))] bg-[linear-gradient(135deg,var(--brand-1),var(--brand-2))] font-semibold text-white shadow-[inset_0_1px_0_rgba(255,255,255,.25),0_6px_14px_-6px_color-mix(in_srgb,var(--brand-1)_70%,transparent)]":"bg-primary font-semibold text-white shadow-[0_1px_2px_rgba(5,8,22,.14)]"),x&&q&&P&&"opacity-70",j&&!x&&"font-semibold text-primary",!z&&"cursor-not-allowed opacity-30"),children:[d.day.format(n),j&&!x?a("span",{className:"absolute bottom-1 left-1/2 size-1 -translate-x-1/2 rounded-full bg-primary"}):null]})]},m(n))})})]},s)})})}export{ct as Calendar,h as addDays,f as addMonths,ut as parseIsoDay,m as toIsoDay};
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ /**
3
+ * Carousel — a row of cards that scrolls sideways: site photos, plans,
4
+ * announcements. Built on the browser's own scroll-snap, so touch, trackpad
5
+ * and scrollbars behave natively and nothing is re-implemented.
6
+ *
7
+ * `slideClassName` sets how many show at once ("basis-full sm:basis-1/2
8
+ * lg:basis-1/3"). Arrows sit `inside` (over the slides) or `outside` (above,
9
+ * right); the indicator is `dots` or a `bar`. `autoplay` (ms) advances on its
10
+ * own, stops while hovered or focused, and never runs for people who ask for
11
+ * reduced motion. `loop` wraps at the ends. ← and → move when it has focus.
12
+ */
13
+ export interface CarouselProps {
14
+ children: React.ReactNode;
15
+ slideClassName?: string;
16
+ /** Space between slides, px. */
17
+ gap?: number;
18
+ arrows?: "inside" | "outside" | "none";
19
+ indicator?: "dots" | "bar" | "none";
20
+ autoplay?: number;
21
+ loop?: boolean;
22
+ /** Above the slides, left of outside arrows. */
23
+ title?: React.ReactNode;
24
+ "aria-label"?: string;
25
+ className?: string;
26
+ }
27
+ export declare function Carousel({ children, slideClassName, gap, arrows, indicator, autoplay, loop, title, "aria-label": ariaLabel, className, }: CarouselProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{Fragment as z,jsx as r,jsxs as i}from"react/jsx-runtime";import{ChevronLeft as S,ChevronRight as $}from"lucide-react";import*as n from"react";import{cn as v}from"../../lib/utils.js";function G({children:R,slideClassName:M="basis-full",gap:p=12,arrows:l="inside",indicator:g="dots",autoplay:m,loop:h=!1,title:x,"aria-label":P="Carousel",className:T}){const o=n.useRef(null),d=n.Children.toArray(R),[w,I]=n.useState(0),[c,_]=n.useState({start:!0,end:!1}),[D,W]=n.useState(0),[y,u]=n.useState(!1),a=n.useCallback(()=>{const e=o.current;if(!e)return;const t=e.scrollWidth-e.clientWidth,s=e.scrollLeft>=t-1;_({start:e.scrollLeft<=1,end:s}),W(t>0?e.scrollLeft/t:1);const L=Array.from(e.children);let k=0,C=1/0;L.forEach((A,H)=>{const E=Math.abs(A.offsetLeft-e.offsetLeft-e.scrollLeft);E<C&&(C=E,k=H)}),I(s&&t>0?L.length-1:k)},[]);n.useEffect(()=>{const e=o.current;if(!e)return;a(),e.addEventListener("scroll",a,{passive:!0});const t=new ResizeObserver(a);return t.observe(e),()=>{e.removeEventListener("scroll",a),t.disconnect()}},[a,d.length]);const N=e=>{const t=o.current,s=t?.children[e];!t||!s||t.scrollTo({left:s.offsetLeft-t.offsetLeft,behavior:"smooth"})},f=e=>{const t=o.current;if(!t)return;if(e===1&&c.end)return h?N(0):void 0;if(e===-1&&c.start)return h?t.scrollTo({left:t.scrollWidth,behavior:"smooth"}):void 0;const s=t.children[0];t.scrollBy({left:e*((s?.offsetWidth??t.clientWidth)+p),behavior:"smooth"})};n.useEffect(()=>{if(!m||y||window.matchMedia("(prefers-reduced-motion: reduce)").matches)return;const e=window.setInterval(()=>f(1),m);return()=>window.clearInterval(e)});const b=e=>{const t=!h&&(e===1?c.end:c.start),s=e===1?$:S;return r("button",{type:"button","aria-label":e===1?"Next slide":"Previous slide",disabled:t,onClick:()=>f(e),className:v("grid size-9 cursor-pointer place-items-center rounded-full outline-none transition-[opacity,background-color,transform] duration-200 focus-visible:ring-2 focus-visible:ring-primary/45 disabled:pointer-events-none disabled:opacity-0 [&_svg]:size-[18px]",l==="inside"?"border border-white/50 bg-raised/80 text-text shadow-[0_4px_14px_-4px_rgba(5,8,22,.35)] backdrop-blur-md hover:scale-105 hover:bg-raised dark:border-white/10":"border border-border bg-raised text-body shadow-[var(--lit)] hover:bg-hover hover:text-text disabled:opacity-40"),children:r(s,{})})};return i("section",{"aria-roledescription":"carousel","aria-label":P,className:v("relative",T),onPointerEnter:()=>u(!0),onPointerLeave:()=>u(!1),onFocusCapture:()=>u(!0),onBlurCapture:()=>u(!1),children:[x||l==="outside"?i("div",{className:"mb-3 flex items-center gap-3",children:[r("div",{className:"min-w-0 flex-1",children:x}),l==="outside"?i("div",{className:"flex gap-1.5",children:[b(-1),b(1)]}):null]}):null,i("div",{className:"relative",children:[r("div",{ref:o,tabIndex:0,"aria-live":m&&!y?"off":"polite",onKeyDown:e=>{e.key==="ArrowRight"?(e.preventDefault(),f(1)):e.key==="ArrowLeft"&&(e.preventDefault(),f(-1))},className:"no-bar flex snap-x snap-mandatory overflow-x-auto overscroll-x-contain rounded-[calc(14px*var(--radius-scale))] outline-none focus-visible:ring-2 focus-visible:ring-primary/40",style:{gap:p},children:d.map((e,t)=>r("div",{role:"group","aria-roledescription":"slide","aria-label":`${t+1} of ${d.length}`,className:v("min-w-0 shrink-0 grow-0 snap-start",M),children:e},t))}),l==="inside"?i(z,{children:[r("div",{className:"absolute left-3 top-1/2 -translate-y-1/2",children:b(-1)}),r("div",{className:"absolute right-3 top-1/2 -translate-y-1/2",children:b(1)})]}):null]}),g==="dots"?r("div",{className:"mt-3 flex justify-center gap-1.5",children:d.map((e,t)=>r("button",{type:"button","aria-label":`Go to slide ${t+1}`,"aria-current":t===w?"true":void 0,onClick:()=>N(t),className:v("h-1.5 cursor-pointer rounded-full transition-[width,background-color] duration-300 ease-[var(--ease)]",t===w?"w-5 bg-[linear-gradient(90deg,var(--brand-1),var(--brand-2))]":"w-1.5 bg-border2 hover:bg-muted")},t))}):g==="bar"?r("div",{className:"mx-auto mt-3 h-1 max-w-[220px] overflow-hidden rounded-full bg-hover","aria-hidden":!0,children:r("div",{className:"h-full rounded-full bg-[linear-gradient(90deg,var(--brand-1),var(--brand-2))] transition-[width] duration-150",style:{width:`${Math.max(8,D*100)}%`}})}):null]})}export{G as Carousel};
@@ -0,0 +1,14 @@
1
+ import * as React from "react";
2
+ export interface ColorPickerProps {
3
+ value?: string;
4
+ defaultValue?: string;
5
+ onValueChange?: (hex: string) => void;
6
+ /** Quick choices under the strip; `false` for none. */
7
+ swatches?: string[] | false;
8
+ className?: string;
9
+ }
10
+ export declare function ColorPicker({ value, defaultValue, onValueChange, swatches, className }: ColorPickerProps): React.JSX.Element;
11
+ /** The picker behind a field-like button showing the colour and its hex. */
12
+ export declare function ColorPickerPopover({ value, defaultValue, onValueChange, swatches, "aria-label": ariaLabel, className, }: ColorPickerProps & {
13
+ "aria-label"?: string;
14
+ }): React.JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as l,jsxs as m}from"react/jsx-runtime";import*as x from"@radix-ui/react-popover";import{Pipette as $}from"lucide-react";import*as p from"react";import{cn as P}from"../../lib/utils.js";function _(o){let t=o.trim().replace(/^#/,"");if(t.length===3&&(t=[...t].map(e=>e+e).join("")),!/^[0-9a-f]{6}$/i.test(t))return null;const a=parseInt(t,16);return[a>>16&255,a>>8&255,a&255]}const H=(o,t,a)=>`#${[o,t,a].map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`;function N(o,t,a){o/=255,t/=255,a/=255;const e=Math.max(o,t,a),i=e-Math.min(o,t,a);let d=0;return i&&(d=e===o?(t-a)/i%6:e===t?(a-o)/i+2:(o-t)/i+4),{h:(d*60+360)%360,s:e?i/e:0,v:e}}function k({h:o,s:t,v:a}){const e=i=>{const d=(i+o/60)%6;return(a-a*t*Math.max(0,Math.min(d,4-d,1)))*255};return H(e(5),e(3),e(1))}const S=["#4f46e5","#1f45ea","#7c3aed","#db2777","#e11d48","#ea580c","#d97706","#16a34a","#059669","#0d9488","#0284c7","#334155"];function T(o){const t=p.useRef(null),a=e=>{const i=t.current.getBoundingClientRect();o(Math.min(1,Math.max(0,(e.clientX-i.left)/i.width)),Math.min(1,Math.max(0,(e.clientY-i.top)/i.height)))};return{ref:t,onPointerDown:e=>{e.preventDefault(),e.currentTarget.setPointerCapture(e.pointerId),e.currentTarget.focus(),a(e)},onPointerMove:e=>{e.currentTarget.hasPointerCapture(e.pointerId)&&a(e)}}}function L({value:o,defaultValue:t="#4f46e5",onValueChange:a,swatches:e=S,className:i}){const[d,b]=p.useState(t),c=(o??d).toLowerCase(),[s,g]=p.useState(()=>N(..._(c)??[79,70,229])),[h,w]=p.useState(c);p.useEffect(()=>{if(k(s)!==c){const r=_(c);if(r){const n=N(...r);g(u=>({h:n.s===0||n.v===0?u.h:n.h,s:n.v===0?u.s:n.s,v:n.v}))}}w(c)},[c]);const v=r=>{g(r);const n=k(r);o===void 0&&b(n),a?.(n)},y=r=>{const n=_(r);if(!n)return;const u=H(...n);o===void 0&&b(u),a?.(u)},E=T((r,n)=>v({...s,s:r,v:1-n})),R=T(r=>v({...s,h:r*360})),M=(r,n)=>{const u=r.shiftKey?.1:.02,f={ArrowLeft:[-u,0],ArrowRight:[u,0],ArrowUp:[0,u],ArrowDown:[0,-u]}[r.key];f&&(r.preventDefault(),v(n==="area"?{...s,s:Math.min(1,Math.max(0,s.s+f[0])),v:Math.min(1,Math.max(0,s.v+f[1]))}:{...s,h:(s.h+(f[0]+f[1])*360+360)%360}))},D=typeof window<"u"&&"EyeDropper"in window,C=k({h:s.h,s:1,v:1});return m("div",{className:P("w-64 space-y-3",i),children:[l("div",{...E,role:"slider",tabIndex:0,"aria-label":"Saturation and brightness","aria-valuetext":`Saturation ${Math.round(s.s*100)}%, brightness ${Math.round(s.v*100)}%`,onKeyDown:r=>M(r,"area"),className:"relative h-40 cursor-crosshair touch-none rounded-[calc(10px*var(--radius-scale))] outline-none ring-offset-2 ring-offset-[var(--raised)] focus-visible:ring-2 focus-visible:ring-primary/50",style:{background:`linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, ${C})`},children:l("span",{"aria-hidden":!0,className:"pointer-events-none absolute size-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(5,8,22,.25),0_2px_6px_rgba(5,8,22,.35)]",style:{left:`${s.s*100}%`,top:`${(1-s.v)*100}%`,background:c}})}),l("div",{...R,role:"slider",tabIndex:0,"aria-label":"Hue","aria-valuemin":0,"aria-valuemax":360,"aria-valuenow":Math.round(s.h),onKeyDown:r=>M(r,"hue"),className:"relative h-3 cursor-pointer touch-none rounded-full outline-none ring-offset-2 ring-offset-[var(--raised)] focus-visible:ring-2 focus-visible:ring-primary/50",style:{background:"linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00)"},children:l("span",{"aria-hidden":!0,className:"pointer-events-none absolute top-1/2 size-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(5,8,22,.25),0_2px_6px_rgba(5,8,22,.35)]",style:{left:`${s.h/360*100}%`,background:C}})}),m("div",{className:"flex items-center gap-2",children:[l("span",{className:"size-8 shrink-0 rounded-[calc(8px*var(--radius-scale))] shadow-[inset_0_0_0_1px_rgba(5,8,22,.12)]",style:{background:c}}),m("label",{className:"flex h-8 min-w-0 flex-1 items-center gap-1 rounded-ctl border border-border2 bg-raised px-2 focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/20",children:[l("span",{className:"text-[12px] text-muted",children:"#"}),l("input",{value:h.replace(/^#/,""),"aria-label":"Hex colour",spellCheck:!1,maxLength:7,onChange:r=>{const n=`#${r.target.value.replace(/[^0-9a-f]/gi,"").slice(0,6)}`;w(n),n.length===7&&y(n)},onBlur:()=>w(c),className:"num min-w-0 flex-1 bg-transparent font-mono text-[12.5px] uppercase text-text outline-none"})]}),D?l("button",{type:"button","aria-label":"Pick a colour from the screen",onClick:async()=>{try{const r=await new window.EyeDropper().open();y(r.sRGBHex)}catch{}},className:"grid size-8 shrink-0 cursor-pointer place-items-center rounded-ctl border border-border2 bg-raised text-muted transition-colors hover:bg-hover hover:text-text",children:l($,{className:"size-4"})}):null]}),e&&e.length?l("div",{className:"grid grid-cols-6 gap-1.5",children:e.map(r=>{const n=r.toLowerCase()===c;return l("button",{type:"button","aria-label":r,"aria-pressed":n,onClick:()=>y(r),className:P("h-7 cursor-pointer rounded-[calc(7px*var(--radius-scale))] shadow-[inset_0_0_0_1px_rgba(5,8,22,.12)] transition-transform hover:scale-110",n&&"ring-2 ring-[var(--text)] ring-offset-2 ring-offset-[var(--raised)]"),style:{background:r}},r)})}):null]})}function B({value:o,defaultValue:t="#4f46e5",onValueChange:a,swatches:e,"aria-label":i="Colour",className:d}){const[b,c]=p.useState(t),s=o??b,g=h=>{o===void 0&&c(h),a?.(h)};return m(x.Root,{children:[m(x.Trigger,{"aria-label":`${i}: ${s}`,className:P("inline-flex h-ctl cursor-pointer items-center gap-2 rounded-ctl border border-border2 bg-raised pl-1.5 pr-3 text-[13px] text-text outline-none transition-[border-color,box-shadow]","hover:border-muted/50 focus-visible:border-primary focus-visible:ring-2 focus-visible:ring-primary/20 data-[state=open]:border-primary data-[state=open]:ring-2 data-[state=open]:ring-primary/20",d),children:[l("span",{className:"size-6 rounded-[calc(6px*var(--radius-scale))] shadow-[inset_0_0_0_1px_rgba(5,8,22,.12)]",style:{background:s}}),l("span",{className:"num font-mono text-[12.5px] uppercase",children:s})]}),l(x.Portal,{children:l(x.Content,{"data-pop":"",align:"start",sideOffset:6,collisionPadding:12,className:"z-50 rounded-dlg border border-border bg-raised p-3 shadow-elev3 outline-none",children:l(L,{value:s,onValueChange:g,swatches:e})})})]})}export{L as ColorPicker,B as ColorPickerPopover};
@@ -1,34 +1,47 @@
1
1
  import * as React from "react";
2
2
  /**
3
- * Confirmation for actions that cannot be taken back — delete, suspend,
4
- * void, revoke.
3
+ * Confirmation for actions that matter — delete, suspend, void, revoke, and
4
+ * the big good ones too (publish, send a payout).
5
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.
6
+ * Built to slow the hand down just enough: a clear icon in its tone, the
7
+ * consequence in one sentence, the actual things affected (first few by name,
8
+ * then "+ n more"), and for big or irreversible actions either a word to type
9
+ * (`confirmWord`) or a button to press and hold (`hold`). The confirm button
10
+ * names the action and the count ("Delete 12 rows"), never just "OK". Focus
11
+ * starts on Cancel, so Enter alone never does anything.
12
+ *
13
+ * Looks:
14
+ * center — the default: icon in a halo, centred text. Most confirmations.
15
+ * split — icon beside left-aligned text, buttons on the right. Desktop tools, dense apps.
16
+ * banner — a band of the tone across the top with a large icon. The irreversible ones.
17
+ * sheet — rises from the bottom edge, full width on phones. Touch-first screens.
18
+ * Tones: danger (default), warning, primary (a positive action worth a pause).
12
19
  */
20
+ export type ConfirmTone = "danger" | "warning" | "primary";
21
+ export type ConfirmVariant = "center" | "split" | "banner" | "sheet";
13
22
  export interface ConfirmDialogProps {
14
23
  open: boolean;
15
24
  onOpenChange: (open: boolean) => void;
16
25
  title: React.ReactNode;
17
26
  description?: React.ReactNode;
18
- /** What goes: names shown in a list (first `previewCount`, then "+ n more"). */
27
+ /** What is affected: names shown in a list (first `previewCount`, then "+ n more"). */
19
28
  items?: string[];
20
29
  previewCount?: number;
21
30
  /** Require typing this word (e.g. "DELETE") before the button unlocks. */
22
31
  confirmWord?: string;
32
+ /** Press and hold the button to confirm; a number sets the hold in ms (default 1200). */
33
+ hold?: boolean | number;
23
34
  confirmLabel: React.ReactNode;
24
35
  cancelLabel?: React.ReactNode;
25
- tone?: "danger" | "warning";
36
+ tone?: ConfirmTone;
37
+ variant?: ConfirmVariant;
26
38
  icon?: React.ReactNode;
27
39
  /** Runs on confirm; the button spins until it settles, the dialog closes on success. */
28
40
  onConfirm: () => void | Promise<void>;
29
41
  labels?: {
30
42
  typeToConfirm?: (word: string) => string;
31
43
  more?: (n: number) => string;
44
+ hold?: string;
32
45
  };
33
46
  }
34
- export declare function ConfirmDialog({ open, onOpenChange, title, description, items, previewCount, confirmWord, confirmLabel, cancelLabel, tone, icon, onConfirm, labels, }: ConfirmDialogProps): React.JSX.Element;
47
+ export declare function ConfirmDialog({ open, onOpenChange, title, description, items, previewCount, confirmWord, hold, confirmLabel, cancelLabel, tone, variant, icon, onConfirm, labels, }: ConfirmDialogProps): React.JSX.Element;
@@ -1 +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:c,onOpenChange:d,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[p,f]=s.useState(""),[m,v]=s.useState(!1),[N,g]=s.useState(null),_=s.useRef(null);s.useEffect(()=>{c&&(f(""),g(null))},[c]);const y=!!l&&p.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:c,onOpenChange:t=>!m&&d(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-[calc(18px*var(--radius-scale))] 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-[calc(12px*var(--radius-scale))] border border-border bg-surface p-2 text-left",children:[u.map((t,o)=>a("li",{className:"flex items-center gap-2 rounded-[calc(8px*var(--radius-scale))] 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:p,onChange:t=>f(t.target.value),autoComplete:"off",spellCheck:!1,className:"text-center font-medium tracking-[0.2em] uppercase",state:!y&&p?"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:()=>d(!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(),d(!1)}catch(t){g(t instanceof Error?t.message:String(t))}finally{v(!1)}},children:P})]})]})]})})}export{q as ConfirmDialog};
1
+ "use client";import{Fragment as Z,jsx as e,jsxs as r}from"react/jsx-runtime";import*as f from"@radix-ui/react-dialog";import{CircleAlert as I,CircleCheck as q,ShieldAlert as G,Trash2 as J}from"lucide-react";import*as i from"react";import{cn as d}from"../../lib/utils.js";import{Button as A}from"./button.js";import{DialogOverlay as Q}from"./dialog.js";import{Input as X}from"./input.js";const N={danger:{c:"var(--danger)",s:"var(--danger-subtle)",icon:e(J,{}),grad:"linear-gradient(180deg,#ef4444,#dc2626)",glow:"rgba(220,38,38,.7)"},warning:{c:"var(--warning)",s:"var(--warning-subtle)",icon:e(G,{}),grad:"linear-gradient(180deg,#f59e0b,#b45309)",glow:"rgba(180,83,9,.7)"},primary:{c:"var(--primary)",s:"var(--primary-subtle)",icon:e(q,{}),grad:"linear-gradient(135deg,var(--brand-1),var(--brand-2))",glow:"color-mix(in srgb,var(--brand-1) 70%,transparent)"}};function Y({ms:m,tone:c,disabled:x,busy:u,label:g,hint:v,onDone:l}){const[p,b]=i.useState(!1),h=i.useRef(void 0),s=()=>{x||u||(b(!0),h.current=window.setTimeout(()=>{b(!1),l()},m))},t=()=>{window.clearTimeout(h.current),b(!1)};return i.useEffect(()=>t,[]),r("button",{type:"button",disabled:x||u,onPointerDown:s,onPointerUp:t,onPointerLeave:t,onKeyDown:o=>{(o.key===" "||o.key==="Enter")&&!o.repeat&&s()},onKeyUp:o=>{(o.key===" "||o.key==="Enter")&&t()},"aria-label":typeof g=="string"?`${g} (${v})`:void 0,className:"relative isolate h-ctl cursor-pointer select-none overflow-hidden rounded-ctl px-4 text-[13px] font-semibold text-white outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--raised)] disabled:cursor-not-allowed disabled:opacity-50",style:{background:`color-mix(in srgb, ${N[c].c} 55%, #1a113e)`,boxShadow:`0 6px 16px -8px ${N[c].glow}`},children:[e("span",{"aria-hidden":!0,className:"absolute inset-y-0 left-0 -z-10",style:{width:p?"100%":"0%",background:N[c].grad,transition:p?`width ${m}ms linear`:"width 200ms ease-out"}}),r("span",{className:"flex items-center justify-center gap-2",children:[u?e("span",{className:"size-3.5 animate-spin rounded-full border-2 border-white/40 border-t-white"}):null,p?v:g]})]})}function ne({open:m,onOpenChange:c,title:x,description:u,items:g,previewCount:v=3,confirmWord:l,hold:p,confirmLabel:b,cancelLabel:h="Cancel",tone:s="danger",variant:t="center",icon:o,onConfirm:F,labels:H}){const[C,z]=i.useState(""),[w,$]=i.useState(!1),[S,k]=i.useState(null),B=i.useRef(null);i.useEffect(()=>{m&&(z(""),k(null))},[m]);const R=!!l&&C.trim().toUpperCase()!==l.toUpperCase(),_={typeToConfirm:a=>`Type ${a} to confirm`,more:a=>`+ ${a} more`,hold:"Keep holding\u2026",...H},n=N[s],D=g?.slice(0,v)??[],E=(g?.length??0)-D.length,L=p===!0?1200:typeof p=="number"?p:0,U=t==="center"||t==="banner",j=async()=>{$(!0),k(null);try{await F(),c(!1)}catch(a){k(a instanceof Error?a.message:String(a))}finally{$(!1)}},T=a=>e("span",{className:d("relative grid shrink-0 place-items-center rounded-full text-white shadow-[inset_0_1px_0_rgba(255,255,255,.3)]",a==="lg"?"size-14 [&_svg]:size-6":"size-9 [&_svg]:size-[18px]"),style:{background:n.grad,boxShadow:`inset 0 1px 0 rgba(255,255,255,.3), 0 6px 16px -6px ${n.glow}`},children:o??n.icon}),P=r(Z,{children:[e(f.Title,{className:d("disp text-[17px] font-semibold leading-6 text-text",t==="banner"&&"text-[19px]"),children:x}),u?e(f.Description,{className:d("mt-1.5 text-[13px] leading-5 text-muted",U&&"mx-auto max-w-[36ch]"),children:u}):null,D.length?r("ul",{className:"mt-4 space-y-1 rounded-[calc(12px*var(--radius-scale))] border border-border bg-surface p-2 text-left",children:[D.map((a,y)=>r("li",{className:"flex items-center gap-2 rounded-[calc(8px*var(--radius-scale))] px-2 py-1.5 text-[13px] text-body",children:[e("span",{className:"size-1.5 shrink-0 rounded-full",style:{background:n.c}}),e("span",{className:"truncate",children:a})]},`${a}-${y}`)),E>0?e("li",{className:"px-2 py-1 text-[12px] font-medium text-muted",children:_.more(E)}):null]}):null,l?r("div",{className:"mt-4 text-left",children:[e("label",{className:"mb-1.5 block text-[12px] font-medium text-muted",children:_.typeToConfirm(l).split(l).map((a,y,M)=>r(i.Fragment,{children:[a,y<M.length-1?e("b",{className:"font-semibold",style:{color:n.c},children:l}):null]},y))}),e(X,{value:C,onChange:a=>z(a.target.value),autoComplete:"off",spellCheck:!1,className:"text-center font-medium uppercase tracking-[0.2em]",state:!R&&C?"success":"default"})]}):null,S?r("p",{role:"alert",className:d("mt-3 flex items-center gap-1.5 text-[12.5px] text-danger",U&&"justify-center"),children:[e(I,{className:"size-3.5"})," ",S]}):null]}),K=L?e(Y,{ms:L,tone:s,disabled:R,busy:w,label:b,hint:_.hold,onDone:j}):e(A,{variant:s==="danger"?"danger":s==="primary"?"gradient":"primary",disabled:R,loading:w,style:s==="warning"?{background:n.grad}:void 0,className:d(s!=="primary"&&"shadow-[0_6px_16px_-8px_rgba(220,38,38,.8)]"),onClick:j,children:b}),O=e(A,{ref:B,disabled:w,onClick:()=>c(!1),children:h}),V={center:"left-1/2 top-1/2 w-[calc(100vw-32px)] max-w-[440px] -translate-x-1/2 -translate-y-1/2 rounded-[calc(18px*var(--radius-scale))]",banner:"left-1/2 top-1/2 w-[calc(100vw-32px)] max-w-[460px] -translate-x-1/2 -translate-y-1/2 rounded-[calc(20px*var(--radius-scale))]",split:"left-1/2 top-1/2 w-[calc(100vw-32px)] max-w-[520px] -translate-x-1/2 -translate-y-1/2 rounded-[calc(14px*var(--radius-scale))]",sheet:"inset-x-0 bottom-0 mx-auto w-full max-w-[560px] rounded-t-[calc(22px*var(--radius-scale))] sm:bottom-4 sm:w-[calc(100vw-32px)] sm:rounded-[calc(22px*var(--radius-scale))]"};return e(f.Root,{open:m,onOpenChange:a=>!w&&c(a),children:r(f.Portal,{children:[e(Q,{}),r(f.Content,{"data-dialog":t==="sheet"?void 0:"","data-confirm-sheet":t==="sheet"?"":void 0,onOpenAutoFocus:a=>{a.preventDefault(),B.current?.focus()},className:d("fixed z-50 overflow-hidden border border-border bg-raised shadow-elev3 outline-none",V[t]),style:{"--tone":n.c,"--tone-subtle":n.s},children:[t==="sheet"?e("span",{"aria-hidden":!0,className:"mx-auto mt-2.5 block h-1 w-10 rounded-full bg-border2 sm:hidden"}):null,t==="banner"?r("div",{className:"relative grid h-32 place-items-center overflow-hidden",style:{background:n.grad},children:[e("span",{"aria-hidden":!0,className:"absolute inset-0 bg-[radial-gradient(60%_80%_at_50%_120%,rgba(255,255,255,.35),transparent_70%)]"}),e("span",{"aria-hidden":!0,className:"absolute -left-10 -top-10 size-40 rounded-full border border-white/15"}),e("span",{"aria-hidden":!0,className:"absolute -bottom-16 -right-8 size-48 rounded-full border border-white/15"}),e("span",{className:"relative grid size-16 place-items-center rounded-[calc(18px*var(--radius-scale))] bg-white/15 text-white shadow-[inset_0_1px_0_rgba(255,255,255,.35),0_12px_30px_-10px_rgba(5,8,22,.5)] ring-1 ring-white/30 backdrop-blur [&_svg]:size-7",children:o??n.icon})]}):null,t==="center"?e("div",{"aria-hidden":!0,className:"pointer-events-none absolute inset-x-0 top-0 h-28",style:{background:`radial-gradient(70% 100% at 50% 0%, ${n.s}, transparent)`}}):null,t==="split"?r("div",{className:"relative flex gap-4 px-6 pb-5 pt-6",children:[T("md"),e("div",{className:"min-w-0 flex-1 pt-1",children:P})]}):t==="sheet"?e("div",{className:"relative px-6 pb-4 pt-5",children:r("div",{className:"flex items-start gap-3.5",children:[T("md"),e("div",{className:"min-w-0 flex-1 pt-1",children:P})]})}):r("div",{className:d("relative px-6 pb-5 text-center",t==="banner"?"pt-5":"pt-7"),children:[t==="center"?r("div",{className:"relative mx-auto mb-4 grid size-14 place-items-center",children:[e("span",{className:"absolute inset-0 rounded-full opacity-10",style:{background:n.c}}),e("span",{className:"absolute inset-[7px] rounded-full opacity-15",style:{background:n.c}}),T("md")]}):null,P]}),r("div",{className:d("relative gap-2 border-t border-border bg-surface/70 px-6 py-4",t==="split"?"flex justify-end":t==="sheet"?"grid grid-cols-2 sm:flex sm:justify-end":"grid grid-cols-2"),children:[O,K]})]})]})})}export{ne as ConfirmDialog};
@@ -64,7 +64,17 @@ export interface DateRangePreset {
64
64
  }
65
65
  /** The presets reports reach for most. Pass your own (translated) list to replace them. */
66
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 & {
67
+ /**
68
+ * DateRangePicker — a span of days for a report, a booking, an export.
69
+ *
70
+ * The field shows both ends and the length ("1 Oct → 7 Oct · 7 days"). In the
71
+ * panel, the Start and End slots say which end is being picked, presets show
72
+ * the dates they stand for, the band previews the span as you move toward
73
+ * the end, and nothing is committed until Apply (Escape or Cancel leaves the
74
+ * value as it was). `applyOnSelect` commits on the second click instead, for
75
+ * filters that should react at once.
76
+ */
77
+ export declare function DateRangePicker({ value, onChange, id, placeholder, min, max, presets, numberOfMonths, applyOnSelect, disabled, clearable, className, locale, weekStartsOn, labels, }: Shared & {
68
78
  value: DateRangeValue;
69
79
  onChange: (value: DateRangeValue) => void;
70
80
  min?: string;
@@ -72,9 +82,16 @@ export declare function DateRangePicker({ value, onChange, id, placeholder, min,
72
82
  /** Quick ranges on the left; [] hides the list. */
73
83
  presets?: DateRangePreset[];
74
84
  numberOfMonths?: 1 | 2;
85
+ /** Commit when the last day is picked, with no Apply button. */
86
+ applyOnSelect?: boolean;
75
87
  labels?: {
76
88
  clear?: string;
77
89
  pickEnd?: string;
90
+ start?: string;
91
+ end?: string;
92
+ apply?: string;
93
+ cancel?: string;
94
+ days?: (n: number) => string;
78
95
  };
79
96
  }): React.JSX.Element;
80
97
  export {};
@@ -1 +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};
1
+ "use client";import{Fragment as j,jsx as e,jsxs as a}from"react/jsx-runtime";import*as v from"@radix-ui/react-popover";import{CalendarClock as ie,CalendarDays as le,CalendarRange as me,X as J}from"lucide-react";import*as z from"react";import{cn as n}from"../../lib/utils.js";import{addDays as Y,addMonths as Q,Calendar as W,parseIsoDay as d,toIsoDay as s}from"./calendar.js";import{inputClass as Z}from"./input.js";import{formatTime as de,parseTime as ce,TimeColumns as pe,toTime as B}from"./time-picker.js";const O="cursor-pointer rounded-ctl px-2 py-1 text-[12.5px] transition-colors disabled:cursor-not-allowed disabled:opacity-40",ee="z-[60] rounded-dlg border border-border bg-raised p-3 shadow-elev3 outline-none";function te({id:o,icon:u,text:y,placeholder:S,open:C,disabled:w,onClear:b,clearLabel:h,className:N}){return a("div",{className:n("relative",N),children:[e(v.Trigger,{asChild:!0,disabled:w,children:a("button",{id:o,type:"button",className:n(Z,"flex cursor-pointer items-center gap-2 text-left",C&&"border-primary ring-2 ring-primary/20",b&&y&&"pr-9"),children:[e(u,{className:"size-4 shrink-0 text-muted"}),e("span",{className:n("num min-w-0 flex-1 truncate",!y&&"text-placeholder"),children:y??S})]})}),b&&y&&!w?e("button",{type:"button","aria-label":h,onClick:b,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(J,{className:"size-3.5"})}):null]})}const re=o=>new Intl.DateTimeFormat(o,{weekday:"short",day:"numeric",month:"short",year:"numeric"});function ye({value:o,onChange:u,id:y,placeholder:S="Pick a date",min:C,max:w,disabled:b,clearable:h=!0,className:N,locale:E="en-GB",weekStartsOn:T=1,labels:V}){const[g,L]=z.useState(!1),R=d(o),f=d(C),D=d(w),i=new Date,c=(!f||s(i)>=s(f))&&(!D||s(i)<=s(D)),k={today:"Today",clear:"Clear",...V},_=l=>{u(s(l)),L(!1)};return a(v.Root,{open:g,onOpenChange:L,children:[e(te,{id:y,icon:le,text:R?re(E).format(R):null,placeholder:S,open:g,disabled:b,onClear:h?()=>u(""):void 0,clearLabel:k.clear,className:N}),e(v.Portal,{children:a(v.Content,{"data-pop":"",align:"start",sideOffset:6,collisionPadding:12,onOpenAutoFocus:l=>l.preventDefault(),className:ee,children:[e(W,{selected:R,onDayClick:_,min:f,max:D,locale:E,weekStartsOn:T,autoFocus:!0}),a("div",{className:"mt-2 flex items-center justify-between border-t border-border pt-2",children:[e("button",{type:"button",disabled:!c,onClick:()=>_(i),className:n(O,"font-medium text-primary hover:bg-primary-subtle"),children:k.today}),h&&R?e("button",{type:"button",onClick:()=>{u(""),L(!1)},className:n(O,"text-muted hover:bg-hover hover:text-text"),children:k.clear}):null]})]})})]})}function he({value:o,onChange:u,id:y,placeholder:S="Pick a date and time",min:C,max:w,step:b=5,hourCycle:h=24,defaultTime:N="09:00",disabled:E,clearable:T=!0,className:V,locale:g="en-GB",weekStartsOn:L=1,labels:R}){const[f,D]=z.useState(!1),i=d(o),c=ce(o.split("T")[1]),k=d(C),_=d(w),l={now:"Now",done:"Done",clear:"Clear",time:"Time",...R},F=(m,M)=>u(`${s(m)}T${M}`),$=i&&k&&s(i)===s(k)?C.split("T")[1]:void 0,G=i&&_&&s(i)===s(_)?w.split("T")[1]:void 0,A=i&&c?`${re(g).format(i)} \xB7 ${de(B(c),{locale:g,hourCycle:h})}`:null;return a(v.Root,{open:f,onOpenChange:D,children:[e(te,{id:y,icon:ie,text:A,placeholder:S,open:f,disabled:E,onClear:T?()=>u(""):void 0,clearLabel:l.clear,className:V}),e(v.Portal,{children:a(v.Content,{"data-pop":"",align:"start",sideOffset:6,collisionPadding:12,onOpenAutoFocus:m=>m.preventDefault(),className:ee,children:[a("div",{className:"flex flex-col gap-4 sm:flex-row",children:[e(W,{selected:i,onDayClick:m=>F(m,c?B(c):N),min:k,max:_,locale:g,weekStartsOn:L,autoFocus:!0}),a("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:l.time}),e(pe,{value:c,onChange:m=>F(i??new Date,B(m)),step:b,hourCycle:h,min:$,max:G,locale:g})]})]}),a("div",{className:"mt-3 flex items-center justify-between border-t border-border pt-2",children:[e("button",{type:"button",onClick:()=>{const m=new Date,M=Math.round(m.getMinutes()/b)*b;F(m,B({h:(m.getHours()+Math.floor(M/60))%24,m:M%60}))},className:n(O,"font-medium text-primary hover:bg-primary-subtle"),children:l.now}),a("div",{className:"flex items-center gap-1",children:[T&&A?e("button",{type:"button",onClick:()=>u(""),className:n(O,"text-muted hover:bg-hover hover:text-text"),children:l.clear}):null,e("button",{type:"button",onClick:()=>D(!1),className:n(O,"bg-primary px-3 font-medium text-white hover:bg-primary-hover"),children:l.done})]})]})]})})]})}const ue=[{label:"Today",range:()=>({from:new Date,to:new Date})},{label:"Yesterday",range:()=>({from:Y(new Date,-1),to:Y(new Date,-1)})},{label:"Last 7 days",range:()=>({from:Y(new Date,-6),to:new Date})},{label:"Last 30 days",range:()=>({from:Y(new Date,-29),to:new Date})},{label:"This month",range:()=>{const o=new Date;return{from:new Date(o.getFullYear(),o.getMonth(),1),to:o}}},{label:"Last month",range:()=>{const o=Q(new Date(new Date().getFullYear(),new Date().getMonth(),1),-1);return{from:o,to:new Date(o.getFullYear(),o.getMonth()+1,0)}}}];function De({value:o,onChange:u,id:y,placeholder:S="Pick a date range",min:C,max:w,presets:b=ue,numberOfMonths:h=2,applyOnSelect:N=!1,disabled:E,clearable:T=!0,className:V,locale:g="en-GB",weekStartsOn:L=1,labels:R}){const[f,D]=z.useState(!1),[i,c]=z.useState(o),[k,_]=z.useState(0);z.useEffect(()=>{f&&c(o)},[f]);const l={clear:"Clear",pickEnd:"Now pick the last day",start:"Start",end:"End",apply:"Apply",cancel:"Cancel",days:r=>`${r} ${r===1?"day":"days"}`,...R},F=new Intl.DateTimeFormat(g,{day:"numeric",month:"short"}),$=new Intl.DateTimeFormat(g,{day:"numeric",month:"short",year:"numeric"}),G=new Intl.DateTimeFormat(g,{weekday:"short"}),A=(r,t)=>Math.round((t.getTime()-r.getTime())/864e5)+1,m=r=>{const t=d(r.from),p=d(r.to);return!t||!p?null:s(t)===s(p)?$.format(t):`${(t.getFullYear()===p.getFullYear()?F:$).format(t)} \u2192 ${$.format(p)}`},M=d(o.from),H=d(o.to),x=d(i.from),P=d(i.to),ae=x&&!P?"end":"start",K=r=>{u(r),D(!1)},oe=r=>{if(!x||P||r<x)return c({from:s(r),to:""});const t={from:i.from,to:s(r)};c(t),N&&K(t)},ne=(r,t)=>{const p=r.range();return t.from===s(p.from)&&t.to===s(p.to)},U=(r,t)=>{const p=ae===r;return a("div",{className:n("min-w-0 flex-1 rounded-[calc(10px*var(--radius-scale))] border px-3 py-2 transition-[border-color,box-shadow,background-color] duration-200",p?"border-primary bg-raised shadow-[0_0_0_3px_var(--primary-subtle)]":"border-border bg-surface"),children:[e("p",{className:n("text-[10.5px] font-semibold uppercase tracking-[0.08em]",p?"text-primary":"text-muted"),children:r==="start"?l.start:l.end}),e("p",{className:n("num truncate text-[13.5px] font-semibold",t?"text-text":"text-placeholder"),children:t?a(j,{children:[$.format(t)," ",a("span",{className:"font-normal text-muted",children:["\xB7 ",G.format(t)]})]}):"\u2014"})]})},I=m(o),X=M&&H?A(M,H):0;return a(v.Root,{open:f,onOpenChange:D,children:[a("div",{className:n("relative",V),children:[e(v.Trigger,{asChild:!0,disabled:E,children:a("button",{id:y,type:"button",className:n(Z,"flex cursor-pointer items-center gap-2 text-left",f&&"border-primary ring-2 ring-primary/20",T&&I&&"pr-9"),children:[e(me,{className:n("size-4 shrink-0",I?"text-primary":"text-muted")}),e("span",{className:n("num min-w-0 flex-1 truncate",!I&&"text-placeholder"),children:I??S}),X>1?e("span",{className:"num shrink-0 rounded-full bg-primary-subtle px-2 py-px text-[11px] font-semibold text-primary",children:l.days(X)}):null]})}),T&&I&&!E?e("button",{type:"button","aria-label":l.clear,onClick:()=>u({from:"",to:""}),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(J,{className:"size-3.5"})}):null]}),e(v.Portal,{children:e(v.Content,{"data-pop":"",align:"start",sideOffset:6,collisionPadding:12,onOpenAutoFocus:r=>r.preventDefault(),className:"z-[60] overflow-hidden rounded-dlg border border-border bg-raised shadow-elev3 outline-none",children:a("div",{className:"flex flex-col sm:flex-row",children:[b.length?e("ul",{className:"flex shrink-0 gap-1 overflow-x-auto border-b border-border bg-surface p-2 sm:w-44 sm:flex-col sm:overflow-visible sm:border-b-0 sm:border-r",children:b.map(r=>{const t=r.range(),p=ne(r,i);return e("li",{children:a("button",{type:"button",onClick:()=>{const q={from:s(t.from),to:s(t.to)};c(q),_(se=>se+1),N&&K(q)},className:n("group/p w-full cursor-pointer whitespace-nowrap rounded-[calc(9px*var(--radius-scale))] px-2.5 py-2 text-left transition-colors",p?"bg-raised shadow-[var(--lit),0_1px_2px_rgba(5,8,22,.06),0_4px_12px_-6px_rgba(5,8,22,.2)] ring-1 ring-border":"hover:bg-hover"),children:[e("span",{className:n("block text-[13px] font-medium",p?"text-primary":"text-text"),children:r.label}),e("span",{className:"num hidden text-[11px] text-muted sm:block",children:s(t.from)===s(t.to)?F.format(t.from):`${F.format(t.from)} \u2013 ${F.format(t.to)}`})]})},r.label)})}):null,a("div",{className:"p-3",children:[a("div",{className:"mb-3 flex items-center gap-2",children:[U("start",x),e("span",{className:"grid size-6 shrink-0 place-items-center text-muted",children:"\u2192"}),U("end",P)]}),e(W,{range:{from:x,to:P},onDayClick:oe,min:d(C),max:d(w),locale:g,weekStartsOn:L,numberOfMonths:h,defaultMonth:x??(h===2?Q(new Date,-1):void 0),autoFocus:!0},k),a("div",{className:"mt-3 flex min-h-9 flex-wrap items-center gap-2 border-t border-border pt-3",children:[e("p",{className:"num mr-auto text-[12.5px] text-muted",children:x&&!P?e("span",{className:"text-primary",children:l.pickEnd}):x&&P?a(j,{children:[e("span",{className:"font-semibold text-text",children:l.days(A(x,P))})," \xB7 ",m(i)]}):null}),T&&(x||P)?e("button",{type:"button",onClick:()=>c({from:"",to:""}),className:n(O,"text-muted hover:bg-hover hover:text-text"),children:l.clear}):null,N?null:a(j,{children:[e("button",{type:"button",onClick:()=>D(!1),className:n(O,"border border-border px-3 font-medium text-body hover:bg-hover"),children:l.cancel}),e("button",{type:"button",disabled:!!x&&!P,onClick:()=>K(i),className:n(O,"bg-[linear-gradient(135deg,var(--brand-1),var(--brand-2))] px-3.5 font-medium text-white shadow-[inset_0_1px_0_rgba(255,255,255,.25),0_6px_14px_-8px_var(--brand-1)] hover:brightness-110"),children:l.apply})]})]})]})]})})})]})}export{ue as DEFAULT_RANGE_PRESETS,ye as DatePicker,De as DateRangePicker,he as DateTimePicker};
@@ -8,10 +8,16 @@ import * as React from "react";
8
8
  * icon. Pass `progress` (by file name, 0–100) to show uploads moving, and
9
9
  * `failed` for the ones to retry.
10
10
  *
11
- * Looks: `dropzone` (default, a dashed area) and `compact` (one row with a
12
- * button, for a form with other fields).
11
+ * Looks:
12
+ * dropzone — the default: a dashed area. Imports, attachments.
13
+ * card — a large drop target with a moving brand border while a file is
14
+ * over it, and the accepted types as chips. The one upload a page is for.
15
+ * compact — one row with a button, inside a form with other fields.
16
+ * button — just a button, the files listed under it. Tight spaces.
17
+ * gallery — image tiles with an add tile; progress rings on the tiles. Site photos.
18
+ * avatar — one round image with change and remove. A profile photo, a logo.
13
19
  */
14
- export type FileUploadVariant = "dropzone" | "compact";
20
+ export type FileUploadVariant = "dropzone" | "card" | "compact" | "button" | "gallery" | "avatar";
15
21
  export interface FileUploadProps {
16
22
  value?: File[];
17
23
  defaultValue?: File[];
@@ -30,7 +36,9 @@ export interface FileUploadProps {
30
36
  /** Names of files whose upload failed; they get a retry button. */
31
37
  failed?: string[];
32
38
  onRetry?: (file: File) => void;
39
+ /** avatar: the current image (a URL) before a new one is picked. */
40
+ currentUrl?: string;
33
41
  disabled?: boolean;
34
42
  className?: string;
35
43
  }
36
- export declare function FileUpload({ value, defaultValue, onValueChange, accept, multiple, maxSize, maxFiles, variant, title, hint, progress, failed, onRetry, disabled, className, }: FileUploadProps): React.JSX.Element;
44
+ export declare function FileUpload({ value, defaultValue, onValueChange, accept, multiple: multipleProp, maxSize, maxFiles, variant, title, hint, progress, failed, onRetry, currentUrl, disabled, className, }: FileUploadProps): React.JSX.Element;