@giddaa-housing/ui 3.9.0 → 3.10.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.
package/css/theme.css CHANGED
@@ -143,6 +143,7 @@
143
143
  --animate-round-sonar-glow: round-sonar-glow 1.5s ease-out infinite;
144
144
  --animate-sonar-wave: sonar-wave 1.5s cubic-bezier(0, 0, 0.2, 1) infinite;
145
145
  --animate-spin-slow: spin 3s linear infinite;
146
+ --animate-kanban-card-flash: kanban-card-flash 0.7s ease-out;
146
147
  }
147
148
 
148
149
  :root {
@@ -303,3 +304,17 @@
303
304
  opacity: 0;
304
305
  }
305
306
  }
307
+
308
+ /* Post-move flash: a moved card holds a focus-coloured ring for a beat, then
309
+ lets it fade, so the eye can find where it landed. A colour fade rather than
310
+ motion, so it is not silenced under prefers-reduced-motion — the "where did
311
+ it go" problem is the same for everyone. */
312
+ @keyframes kanban-card-flash {
313
+ 0%,
314
+ 40% {
315
+ box-shadow: 0 0 0 2px var(--color-line-focus);
316
+ }
317
+ 100% {
318
+ box-shadow: 0 0 0 2px transparent;
319
+ }
320
+ }
package/dist/accordion.js CHANGED
@@ -25,11 +25,11 @@ function AccordionTrigger({ className, children, ...props }) {
25
25
  className: "flex",
26
26
  children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
27
27
  "data-slot": "accordion-trigger",
28
- className: cn("group/accordion-trigger flex w-full items-center gap-3 px-4 sm:px-5 py-5.5 aria-expanded:pb-2 text-left text-gdt-md font-semibold text-fg-primary outline-none transition-[padding] aria-disabled:pointer-events-none aria-disabled:opacity-50", className),
28
+ className: cn("group/accordion-trigger flex w-full items-start gap-3 px-4 sm:px-5 py-5.5 aria-expanded:pb-2 text-left text-gdt-md font-semibold text-fg-primary outline-none transition-[padding] aria-disabled:pointer-events-none aria-disabled:opacity-50", className),
29
29
  ...props,
30
30
  children: [/* @__PURE__ */ jsx(ChevronRight, {
31
31
  "data-slot": "accordion-trigger-icon",
32
- className: "pointer-events-none size-5 shrink-0 text-fg-primary transition-[rotate] duration-200 ease-out motion-reduce:transition-none group-aria-expanded/accordion-trigger:rotate-90"
32
+ className: "pointer-events-none w-5 h-(--text-gdt-md--line-height) shrink-0 text-fg-primary transition-[rotate] duration-200 ease-out motion-reduce:transition-none group-aria-expanded/accordion-trigger:rotate-90"
33
33
  }), children]
34
34
  })
35
35
  });
package/dist/calendar.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { ChevronLeft, ChevronRight } from "./icons.js";
3
3
  import { cn } from "./utils/cn.js";
4
4
  import { Button } from "./button.js";
5
- import { _ as ComboboxValue, d as ComboboxInput, f as ComboboxItem, g as ComboboxTrigger, m as ComboboxList, o as ComboboxContent, s as ComboboxEmpty, t as Combobox } from "./combobox-Jfz8hryr.js";
5
+ import { _ as ComboboxValue, d as ComboboxInput, f as ComboboxItem, g as ComboboxTrigger, m as ComboboxList, o as ComboboxContent, s as ComboboxEmpty, t as Combobox } from "./combobox-pFh77rhm.js";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import * as React from "react";
8
8
  import { DayPicker, getDefaultClassNames } from "react-day-picker";
@@ -147,8 +147,12 @@ const responsiveComboboxPopupInputSizes = {
147
147
  * trigger's open-state treatment applies: no pill, no focus ring competing
148
148
  * with the popup's own border, and a radius that belongs to the list it sits
149
149
  * above rather than to a field on the page.
150
+ *
151
+ * `shrink-0` because it shares a flex column with the list, which is the part
152
+ * meant to give way. Without it a long list squeezes the search box down to a
153
+ * sliver — the field a reader needs most is the first thing to disappear.
150
154
  */
151
- const comboboxPopupInputVariants = cva("w-auto", {
155
+ const comboboxPopupInputVariants = cva("w-auto shrink-0", {
152
156
  variants: { size: {
153
157
  sm: "rounded-md",
154
158
  md: "rounded-lg",
package/dist/combobox.js CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import { _ as ComboboxValue, a as ComboboxCollection, b as useComboboxVirtualizer, c as ComboboxFooter, d as ComboboxInput, f as ComboboxItem, g as ComboboxTrigger, h as ComboboxSeparator, i as ComboboxChipsInput, l as ComboboxGroup, m as ComboboxList, n as ComboboxChip, o as ComboboxContent, p as ComboboxLabel, r as ComboboxChips, s as ComboboxEmpty, t as Combobox, u as ComboboxHeader, v as ComboboxVirtualizedList, y as useComboboxAnchor } from "./combobox-Jfz8hryr.js";
2
+ import { _ as ComboboxValue, a as ComboboxCollection, b as useComboboxVirtualizer, c as ComboboxFooter, d as ComboboxInput, f as ComboboxItem, g as ComboboxTrigger, h as ComboboxSeparator, i as ComboboxChipsInput, l as ComboboxGroup, m as ComboboxList, n as ComboboxChip, o as ComboboxContent, p as ComboboxLabel, r as ComboboxChips, s as ComboboxEmpty, t as Combobox, u as ComboboxHeader, v as ComboboxVirtualizedList, y as useComboboxAnchor } from "./combobox-pFh77rhm.js";
3
3
  export { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxFooter, ComboboxGroup, ComboboxHeader, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSeparator, ComboboxTrigger, ComboboxValue, ComboboxVirtualizedList, useComboboxAnchor, useComboboxVirtualizer };
@@ -1,5 +1,5 @@
1
1
  import { InputSizeValue } from "./input.js";
2
- import { t as PickerPlacementProps } from "./picker-qxWi9wZ1.js";
2
+ import { t as PickerPlacementProps } from "./picker-QtFHPRqg.js";
3
3
  import * as React from "react";
4
4
  import { DateRange, Matcher } from "react-day-picker";
5
5
  //#region src/date-picker.d.ts
package/dist/dialog.js CHANGED
@@ -79,7 +79,7 @@ function DialogContent({ className, children, size, showCloseButton = true, nest
79
79
  ...props,
80
80
  children: [/* @__PURE__ */ jsx("div", {
81
81
  "data-slot": "dialog-surface",
82
- className: cn("pointer-events-auto flex max-h-[calc(100dvh-5rem)] w-full flex-col gap-4 overflow-visible rounded-2xl border border-line-subtle bg-surface-overlay bg-clip-padding p-(--dialog-padding) text-fg-primary shadow-(--elevation-e2-shadow)", className),
82
+ className: cn("pointer-events-auto flex max-h-[calc(100dvh-5rem)] w-full flex-col gap-4 overflow-y-auto overscroll-contain rounded-2xl border border-line-subtle bg-surface-overlay bg-clip-padding p-(--dialog-padding) text-fg-primary shadow-(--elevation-e2-shadow)", className),
83
83
  children
84
84
  }), showCloseButton && /* @__PURE__ */ jsx(Dialog$1.Close, {
85
85
  "data-slot": "dialog-close",
@@ -12,7 +12,7 @@ function Empty({ className, variant = "default", ...props }) {
12
12
  function EmptyHeader({ className, ...props }) {
13
13
  return /* @__PURE__ */ jsx("div", {
14
14
  "data-slot": "empty-header",
15
- className: cn("flex w-full max-w-95 flex-col items-center gap-gdt-sm", className),
15
+ className: cn("flex w-full max-w-md flex-col items-center gap-gdt-sm", className),
16
16
  ...props
17
17
  });
18
18
  }
@@ -44,7 +44,7 @@ function EmptyTitle({ className, ...props }) {
44
44
  function EmptyDescription({ className, ...props }) {
45
45
  return /* @__PURE__ */ jsx("p", {
46
46
  "data-slot": "empty-description",
47
- className: cn("max-w-95 text-gdt-md font-normal text-fg-secondary [&>a]:font-semibold [&>a]:text-fg-brand [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-fg-primary", className),
47
+ className: cn("max-w-md text-gdt-md font-normal text-fg-secondary [&>a]:font-semibold [&>a]:text-fg-brand [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-fg-primary", className),
48
48
  ...props
49
49
  });
50
50
  }
@@ -47,6 +47,7 @@ declare function FileText(props: IconProps): import("react").JSX.Element;
47
47
  */
48
48
  declare function Filter(props: IconProps): import("react").JSX.Element;
49
49
  declare function Fullscreen(props: IconProps): import("react").JSX.Element;
50
+ declare function GripVertical(props: IconProps): import("react").JSX.Element;
50
51
  declare function Image(props: IconProps): import("react").JSX.Element;
51
52
  declare function Info(props: IconProps): import("react").JSX.Element;
52
53
  declare function Italic(props: IconProps): import("react").JSX.Element;
@@ -108,4 +109,4 @@ declare function Volume2(props: IconProps): import("react").JSX.Element;
108
109
  declare function VolumeX(props: IconProps): import("react").JSX.Element;
109
110
  declare function X(props: IconProps): import("react").JSX.Element;
110
111
  //#endregion
111
- export { Phone as $, IconComponent as A, Loader2 as B, Eye as C, Video as Ct, Filter as D, X as Dt, FileText as E, VolumeX as Et, Link2 as F, MicOff as G, Maximize2 as H, List as I, Minus as J, Minimize as K, ListOrdered as L, Image as M, Info as N, Fullscreen as O, Italic as P, Pause as Q, ListVideo as R, Code2 as S, User as St, File as T, Volume2 as Tt, Menu as U, Maximize as V, Mic as W, Moon as X, Monitor as Y, MoreHorizontal as Z, ChevronLeft as _, Sun as _t, ArrowDown as a, Redo2 as at, ChevronsUpDown as b, Undo2 as bt, ArrowUpRight as c, RotateCcw as ct, Calendar as d, SearchX as dt, PictureInPicture2 as et, Captions as f, Send as ft, ChevronDown as g, Star as gt, CheckCheck as h, SlidersHorizontal as ht, AlignRight as i, Quote as it, IconProps as j, Icon as k, Baseline as l, RotateCw as lt, Check as m, Share as mt, AlignJustify as n, Play as nt, ArrowRight as o, RefreshCcw as ot, CaptionsOff as p, Settings as pt, Minimize2 as q, AlignLeft as r, Plus as rt, ArrowUp as s, Repeat2 as st, AlignCenter as t, Pin as tt, Bold as u, Search as ut, ChevronRight as v, TriangleAlert as vt, EyeOff as w, Volume1 as wt, Clock as x, UploadCloud as xt, ChevronUp as y, Underline as yt, Loader as z };
112
+ export { Pause as $, Icon as A, Loader as B, Eye as C, User as Ct, Filter as D, VolumeX as Dt, FileText as E, Volume2 as Et, Italic as F, Mic as G, Maximize as H, Link2 as I, Minimize2 as J, MicOff as K, List as L, IconProps as M, Image as N, Fullscreen as O, X as Ot, Info as P, MoreHorizontal as Q, ListOrdered as R, Code2 as S, UploadCloud as St, File as T, Volume1 as Tt, Maximize2 as U, Loader2 as V, Menu as W, Monitor as X, Minus as Y, Moon as Z, ChevronLeft as _, Star as _t, ArrowDown as a, Quote as at, ChevronsUpDown as b, Underline as bt, ArrowUpRight as c, Repeat2 as ct, Calendar as d, Search as dt, Phone as et, Captions as f, SearchX as ft, ChevronDown as g, SlidersHorizontal as gt, CheckCheck as h, Share as ht, AlignRight as i, Plus as it, IconComponent as j, GripVertical as k, Baseline as l, RotateCcw as lt, Check as m, Settings as mt, AlignJustify as n, Pin as nt, ArrowRight as o, Redo2 as ot, CaptionsOff as p, Send as pt, Minimize as q, AlignLeft as r, Play as rt, ArrowUp as s, RefreshCcw as st, AlignCenter as t, PictureInPicture2 as tt, Bold as u, RotateCw as ut, ChevronRight as v, Sun as vt, EyeOff as w, Video as wt, Clock as x, Undo2 as xt, ChevronUp as y, TriangleAlert as yt, ListVideo as z };
package/dist/icons.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as Phone, A as IconComponent, B as Loader2, C as Eye, Ct as Video, D as Filter, Dt as X, E as FileText, Et as VolumeX, F as Link2, G as MicOff, H as Maximize2, I as List, J as Minus, K as Minimize, L as ListOrdered, M as Image, N as Info, O as Fullscreen, P as Italic, Q as Pause, R as ListVideo, S as Code2, St as User, T as File, Tt as Volume2, U as Menu, V as Maximize, W as Mic, X as Moon, Y as Monitor, Z as MoreHorizontal, _ as ChevronLeft, _t as Sun, a as ArrowDown, at as Redo2, b as ChevronsUpDown, bt as Undo2, c as ArrowUpRight, ct as RotateCcw, d as Calendar, dt as SearchX, et as PictureInPicture2, f as Captions, ft as Send, g as ChevronDown, gt as Star, h as CheckCheck, ht as SlidersHorizontal, i as AlignRight, it as Quote, j as IconProps, k as Icon, l as Baseline, lt as RotateCw, m as Check, mt as Share, n as AlignJustify, nt as Play, o as ArrowRight, ot as RefreshCcw, p as CaptionsOff, pt as Settings, q as Minimize2, r as AlignLeft, rt as Plus, s as ArrowUp, st as Repeat2, t as AlignCenter, tt as Pin, u as Bold, ut as Search, v as ChevronRight, vt as TriangleAlert, w as EyeOff, wt as Volume1, x as Clock, xt as UploadCloud, y as ChevronUp, yt as Underline, z as Loader } from "./icons-C9JXR5Xv.js";
2
- export { AlignCenter, AlignJustify, AlignLeft, AlignRight, ArrowDown, ArrowRight, ArrowUp, ArrowUpRight, Baseline, Bold, Calendar, Captions, CaptionsOff, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsUpDown, Clock, Code2, Eye, EyeOff, File, FileText, Filter, Fullscreen, Icon, type IconComponent, type IconProps, Image, Info, Italic, Link2, List, ListOrdered, ListVideo, Loader, Loader2, Maximize, Maximize2, Menu, Mic, MicOff, Minimize, Minimize2, Minus, Monitor, Moon, MoreHorizontal, Pause, Phone, PictureInPicture2, Pin, Play, Plus, Quote, Redo2, RefreshCcw, Repeat2, RotateCcw, RotateCw, Search, SearchX, Send, Settings, Share, SlidersHorizontal, Star, Sun, TriangleAlert, Underline, Undo2, UploadCloud, User, Video, Volume1, Volume2, VolumeX, X };
1
+ import { $ as Pause, A as Icon, B as Loader, C as Eye, Ct as User, D as Filter, Dt as VolumeX, E as FileText, Et as Volume2, F as Italic, G as Mic, H as Maximize, I as Link2, J as Minimize2, K as MicOff, L as List, M as IconProps, N as Image, O as Fullscreen, Ot as X, P as Info, Q as MoreHorizontal, R as ListOrdered, S as Code2, St as UploadCloud, T as File, Tt as Volume1, U as Maximize2, V as Loader2, W as Menu, X as Monitor, Y as Minus, Z as Moon, _ as ChevronLeft, _t as Star, a as ArrowDown, at as Quote, b as ChevronsUpDown, bt as Underline, c as ArrowUpRight, ct as Repeat2, d as Calendar, dt as Search, et as Phone, f as Captions, ft as SearchX, g as ChevronDown, gt as SlidersHorizontal, h as CheckCheck, ht as Share, i as AlignRight, it as Plus, j as IconComponent, k as GripVertical, l as Baseline, lt as RotateCcw, m as Check, mt as Settings, n as AlignJustify, nt as Pin, o as ArrowRight, ot as Redo2, p as CaptionsOff, pt as Send, q as Minimize, r as AlignLeft, rt as Play, s as ArrowUp, st as RefreshCcw, t as AlignCenter, tt as PictureInPicture2, u as Bold, ut as RotateCw, v as ChevronRight, vt as Sun, w as EyeOff, wt as Video, x as Clock, xt as Undo2, y as ChevronUp, yt as TriangleAlert, z as ListVideo } from "./icons-e71GaFK-.js";
2
+ export { AlignCenter, AlignJustify, AlignLeft, AlignRight, ArrowDown, ArrowRight, ArrowUp, ArrowUpRight, Baseline, Bold, Calendar, Captions, CaptionsOff, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsUpDown, Clock, Code2, Eye, EyeOff, File, FileText, Filter, Fullscreen, GripVertical, Icon, type IconComponent, type IconProps, Image, Info, Italic, Link2, List, ListOrdered, ListVideo, Loader, Loader2, Maximize, Maximize2, Menu, Mic, MicOff, Minimize, Minimize2, Minus, Monitor, Moon, MoreHorizontal, Pause, Phone, PictureInPicture2, Pin, Play, Plus, Quote, Redo2, RefreshCcw, Repeat2, RotateCcw, RotateCw, Search, SearchX, Send, Settings, Share, SlidersHorizontal, Star, Sun, TriangleAlert, Underline, Undo2, UploadCloud, User, Video, Volume1, Volume2, VolumeX, X };
package/dist/icons.js CHANGED
@@ -308,6 +308,44 @@ function Fullscreen(props) {
308
308
  ]
309
309
  });
310
310
  }
311
+ function GripVertical(props) {
312
+ return /* @__PURE__ */ jsxs(Icon, {
313
+ name: "grip-vertical",
314
+ ...props,
315
+ children: [
316
+ /* @__PURE__ */ jsx("circle", {
317
+ cx: "9",
318
+ cy: "12",
319
+ r: "1"
320
+ }),
321
+ /* @__PURE__ */ jsx("circle", {
322
+ cx: "9",
323
+ cy: "5",
324
+ r: "1"
325
+ }),
326
+ /* @__PURE__ */ jsx("circle", {
327
+ cx: "9",
328
+ cy: "19",
329
+ r: "1"
330
+ }),
331
+ /* @__PURE__ */ jsx("circle", {
332
+ cx: "15",
333
+ cy: "12",
334
+ r: "1"
335
+ }),
336
+ /* @__PURE__ */ jsx("circle", {
337
+ cx: "15",
338
+ cy: "5",
339
+ r: "1"
340
+ }),
341
+ /* @__PURE__ */ jsx("circle", {
342
+ cx: "15",
343
+ cy: "19",
344
+ r: "1"
345
+ })
346
+ ]
347
+ });
348
+ }
311
349
  function Image(props) {
312
350
  return /* @__PURE__ */ jsxs(Icon, {
313
351
  name: "image",
@@ -938,4 +976,4 @@ function X(props) {
938
976
  });
939
977
  }
940
978
  //#endregion
941
- export { AlignCenter, AlignJustify, AlignLeft, AlignRight, ArrowDown, ArrowRight, ArrowUp, ArrowUpRight, Baseline, Bold, Calendar, Captions, CaptionsOff, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsUpDown, Clock, Code2, Eye, EyeOff, File, FileText, Filter, Fullscreen, Icon, Image, Info, Italic, Link2, List, ListOrdered, ListVideo, Loader, Loader2, Maximize, Maximize2, Menu, Mic, MicOff, Minimize, Minimize2, Minus, Monitor, Moon, MoreHorizontal, Pause, Phone, PictureInPicture2, Pin, Play, Plus, Quote, Redo2, RefreshCcw, Repeat2, RotateCcw, RotateCw, Search, SearchX, Send, Settings, Share, SlidersHorizontal, Star, Sun, TriangleAlert, Underline, Undo2, UploadCloud, User, Video, Volume1, Volume2, VolumeX, X };
979
+ export { AlignCenter, AlignJustify, AlignLeft, AlignRight, ArrowDown, ArrowRight, ArrowUp, ArrowUpRight, Baseline, Bold, Calendar, Captions, CaptionsOff, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsUpDown, Clock, Code2, Eye, EyeOff, File, FileText, Filter, Fullscreen, GripVertical, Icon, Image, Info, Italic, Link2, List, ListOrdered, ListVideo, Loader, Loader2, Maximize, Maximize2, Menu, Mic, MicOff, Minimize, Minimize2, Minus, Monitor, Moon, MoreHorizontal, Pause, Phone, PictureInPicture2, Pin, Play, Plus, Quote, Redo2, RefreshCcw, Repeat2, RotateCcw, RotateCw, Search, SearchX, Send, Settings, Share, SlidersHorizontal, Star, Sun, TriangleAlert, Underline, Undo2, UploadCloud, User, Video, Volume1, Volume2, VolumeX, X };
@@ -14,7 +14,7 @@ const inputGroupSizeVariants = {
14
14
  lg: "h-12",
15
15
  xl: "h-14"
16
16
  };
17
- const inputGroupVariants = cva("group/input-group relative flex w-full min-w-0 items-center overflow-hidden rounded-full has-[textarea]:rounded-xl has-data-[align=block-end]:rounded-xl has-data-[align=block-start]:rounded-xl border border-line bg-canvas transition-[background-color,border-color,box-shadow,color] outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:border-line-subtle has-disabled:bg-surface has-disabled:text-fg-caption-placeholder focus-within:border-line-focus focus-within:inset-ring-1 focus-within:inset-ring-line-focus has-[[data-slot][aria-invalid=true]]:border-line-danger has-[[data-slot][aria-invalid=true]]:inset-shadow-none has-[[data-slot][aria-invalid=true]]:focus-within:border-line-danger has-[[data-slot][aria-invalid=true]]:focus-within:inset-ring-line-danger has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:group-data-[size=sm]/input-group:pl-2 has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:group-data-[size=md]/input-group:pl-2.5 has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:group-data-[size=lg]/input-group:pl-3 has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:group-data-[size=xl]/input-group:pl-3 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:group-data-[size=sm]/input-group:pr-2 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:group-data-[size=md]/input-group:pr-2.5 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:group-data-[size=lg]/input-group:pr-3 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:group-data-[size=xl]/input-group:pr-3", {
17
+ const inputGroupVariants = cva("group/input-group relative flex w-full min-w-0 items-center overflow-hidden rounded-full has-[textarea]:rounded-xl has-data-[align=block-end]:rounded-xl has-data-[align=block-start]:rounded-xl border border-line bg-canvas transition-[background-color,border-color,box-shadow,color] outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-[[data-slot=input-group-control]:disabled]:border-line-subtle has-[[data-slot=input-group-control]:disabled]:bg-surface has-[[data-slot=input-group-control]:disabled]:text-fg-caption-placeholder focus-within:border-line-focus focus-within:inset-ring-1 focus-within:inset-ring-line-focus has-[[data-slot][aria-invalid=true]]:border-line-danger has-[[data-slot][aria-invalid=true]]:inset-shadow-none has-[[data-slot][aria-invalid=true]]:focus-within:border-line-danger has-[[data-slot][aria-invalid=true]]:focus-within:inset-ring-line-danger has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:group-data-[size=sm]/input-group:pl-2 has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:group-data-[size=md]/input-group:pl-2.5 has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:group-data-[size=lg]/input-group:pl-3 has-[>[data-align=inline-start]]:[&>[data-slot=input-group-control]]:group-data-[size=xl]/input-group:pl-3 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:group-data-[size=sm]/input-group:pr-2 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:group-data-[size=md]/input-group:pr-2.5 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:group-data-[size=lg]/input-group:pr-3 has-[>[data-align=inline-end]]:[&>[data-slot=input-group-control]]:group-data-[size=xl]/input-group:pr-3", {
18
18
  variants: { size: inputGroupSizeVariants },
19
19
  defaultVariants: { size: "md" }
20
20
  });
@@ -0,0 +1,214 @@
1
+ import { t as Button } from "./button-BS5KCibF.js";
2
+ import * as React from "react";
3
+ //#region src/kanban.d.ts
4
+ /**
5
+ * Kanban — a headless-first board built on Pragmatic drag and drop, composed
6
+ * the same way the data-table family is: a root that owns shared state,
7
+ * structural slots that own layout and tokens, and the app owning data, cards,
8
+ * and what a move means.
9
+ *
10
+ * ```tsx
11
+ * <KanbanRoot onCardMove={handleMove}>
12
+ * <KanbanBoard>
13
+ * <KanbanColumn columnId={stage.id}>
14
+ * <KanbanColumnHeader>
15
+ * <KanbanColumnTitle>
16
+ * <KanbanColumnDot className="bg-status-info" />
17
+ * <span className="flex-1 truncate">{stage.name}</span>
18
+ * <KanbanColumnCount>{count}</KanbanColumnCount>
19
+ * </KanbanColumnTitle>
20
+ * <KanbanColumnDescription>{subtitle}</KanbanColumnDescription>
21
+ * </KanbanColumnHeader>
22
+ * <KanbanColumnBody>
23
+ * <KanbanDropPlaceholder>Drop here…</KanbanDropPlaceholder>
24
+ * {cards.map((card) => (
25
+ * <KanbanCard key={card.id} cardId={card.id}>…</KanbanCard>
26
+ * ))}
27
+ * </KanbanColumnBody>
28
+ * </KanbanColumn>
29
+ * </KanbanBoard>
30
+ * </KanbanRoot>
31
+ * ```
32
+ *
33
+ * `KanbanScrollControls` (or a `KanbanScrollButton` on its own) can sit
34
+ * anywhere inside the root to step the board sideways; `useKanbanScroll` backs
35
+ * a custom control.
36
+ *
37
+ * Drops are reported through `onCardMove` as raw facts (`KanbanCardMove`);
38
+ * apply them to your lists with `applyKanbanCardMove` and persist however the
39
+ * screen needs. The component never mutates or fetches data itself. Dragging
40
+ * is a pointer affordance, so every board needs a keyboard-reachable way to
41
+ * make the same move (a status select on the card, a "move to" menu).
42
+ */
43
+ /** Which half of the target card a drop landed on. */
44
+ type KanbanEdge = "top" | "bottom";
45
+ /**
46
+ * A completed drag, as raw facts. `targetCardId`/`edge` are null when the card
47
+ * was dropped on the column itself rather than on a specific card — boards
48
+ * decide what that means (`applyKanbanCardMove` inserts at the top, where the
49
+ * drop placeholder sits).
50
+ */
51
+ type KanbanCardMove = {
52
+ cardId: string;
53
+ fromColumnId: string;
54
+ toColumnId: string;
55
+ targetCardId: string | null;
56
+ edge: KanbanEdge | null;
57
+ };
58
+ type ApplyKanbanCardMoveArgs = {
59
+ move: KanbanCardMove;
60
+ /** Card ids of the source column, in their currently rendered order. */
61
+ sourceIds: readonly string[];
62
+ /** Card ids of the target column; ignored when the move stays in-column. */
63
+ targetIds: readonly string[];
64
+ };
65
+ type ApplyKanbanCardMoveResult = {
66
+ /** Whether the move puts the card anywhere new. */
67
+ changed: boolean;
68
+ sourceIds: string[];
69
+ targetIds: string[];
70
+ };
71
+ /**
72
+ * Applies a card move to the two columns' id lists and returns the new lists.
73
+ * For an in-column move both returned lists are the same reordered list.
74
+ */
75
+ declare function applyKanbanCardMove({ move, sourceIds, targetIds }: ApplyKanbanCardMoveArgs): ApplyKanbanCardMoveResult;
76
+ /**
77
+ * Orders `ids` by a saved order: ids the saved order knows come first, in that
78
+ * order; the rest keep their given (API) order after them.
79
+ */
80
+ declare function sortIdsBySavedOrder(ids: readonly string[], savedOrder: readonly string[] | undefined): string[];
81
+ type KanbanColumnOrder = Record<string, string[]>;
82
+ /**
83
+ * Per-board card ordering, persisted to this browser's localStorage. Column
84
+ * membership belongs to the server; the only thing saved here is where inside
85
+ * a column the user dropped each card, so the board comes back arranged the
86
+ * way they left it.
87
+ *
88
+ * A column is untouched (pure API order) until its first drop; from then on
89
+ * its saved order wins, with cards the order has never seen keeping API order
90
+ * after the arranged ones.
91
+ *
92
+ * ```tsx
93
+ * const order = useKanbanCardOrder("lead-pipeline-order");
94
+ * const cards = order.sortColumn(stage.id, ids).map((id) => byId[id]);
95
+ * // …after a drop
96
+ * order.saveColumns({ [move.fromColumnId]: sourceIds, [move.toColumnId]: targetIds });
97
+ * ```
98
+ */
99
+ declare function useKanbanCardOrder(storageKey: string): {
100
+ sortColumn: (columnId: string, ids: readonly string[]) => string[];
101
+ saveColumns: (columns: KanbanColumnOrder) => void;
102
+ };
103
+ type KanbanDragState = {
104
+ cardId: string;
105
+ fromColumnId: string;
106
+ /** Column the pointer is currently over, null while outside the board. */
107
+ overColumnId: string | null;
108
+ };
109
+ type KanbanScrollDirection = "left" | "right";
110
+ type KanbanScrollState = {
111
+ canScrollLeft: boolean;
112
+ canScrollRight: boolean;
113
+ /** Columns on the board, ignoring any trailing action tile. */
114
+ columnCount: number;
115
+ /** How many of them fit in the viewport, for a "showing N of M" caption. */
116
+ visibleColumnCount: number;
117
+ };
118
+ type KanbanScrollContextValue = KanbanScrollState & {
119
+ scroll: (direction: KanbanScrollDirection) => void;
120
+ };
121
+ /**
122
+ * The in-flight drag, for app-level styling beyond what the slots do. Null
123
+ * when nothing is being dragged.
124
+ */
125
+ declare function useKanbanDrag(): KanbanDragState | null;
126
+ /**
127
+ * The board's horizontal scroll position, for controls placed anywhere inside
128
+ * `KanbanRoot`. `canScroll*` is false at the corresponding end and on a board
129
+ * that does not overflow at all, so both being false means "nothing to scroll".
130
+ */
131
+ declare function useKanbanScroll(): KanbanScrollContextValue;
132
+ /**
133
+ * The board's live region and card flash, for moves the app makes outside a
134
+ * drag — the "move to" menu that keyboard users need. Announce what changed
135
+ * and flash the card so it can be found in its new column.
136
+ *
137
+ * ```tsx
138
+ * const { announce, flashCard } = useKanbanFeedback();
139
+ *
140
+ * moveLead(lead.id, stage.id);
141
+ * flashCard(lead.id);
142
+ * announce(`${lead.name} moved to ${stage.name}.`);
143
+ * ```
144
+ */
145
+ declare function useKanbanFeedback(): {
146
+ announce: (message: string) => void;
147
+ flashCard: (cardId: string) => void;
148
+ };
149
+ type KanbanRootProps = React.ComponentProps<"div"> & {
150
+ /**
151
+ * A card finished dragging somewhere meaningful. Apply it with
152
+ * `applyKanbanCardMove` and persist as the screen requires; without a
153
+ * handler the board is drag-enabled but inert.
154
+ */
155
+ onCardMove?: (move: KanbanCardMove) => void;
156
+ /**
157
+ * What the board's live region should say once the move has been applied —
158
+ * "Amara Okoye moved to Offer Made, position 2 of 5." Only the app knows the
159
+ * names, so nothing is announced without this. Return null to stay silent.
160
+ */
161
+ announceMove?: (move: KanbanCardMove) => string | null | undefined;
162
+ };
163
+ declare function KanbanRoot({ announceMove, children, className, onCardMove, ...props }: KanbanRootProps): React.JSX.Element;
164
+ type KanbanBoardProps = React.ComponentProps<"div">;
165
+ declare function KanbanBoard({ className, ...props }: KanbanBoardProps): React.JSX.Element;
166
+ type KanbanScrollButtonProps = Omit<React.ComponentProps<typeof Button>, "children"> & {
167
+ direction: KanbanScrollDirection;
168
+ };
169
+ /**
170
+ * Steps the board one column in `direction`, and disables itself at that end.
171
+ * Keyboard users reach the same scroll through the board itself, so the
172
+ * buttons are a pointer affordance rather than the only way across.
173
+ */
174
+ declare function KanbanScrollButton({ className, direction, onClick, ...props }: KanbanScrollButtonProps): React.JSX.Element;
175
+ /**
176
+ * The pair of scroll buttons. On a board that fits its viewport both are
177
+ * disabled rather than hidden — the row holds its place (and its "showing
178
+ * N of M" caption) instead of vanishing on wide screens.
179
+ */
180
+ declare function KanbanScrollControls({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
181
+ type KanbanColumnProps = React.ComponentProps<"section"> & {
182
+ columnId: string;
183
+ /** Cards can leave this column but nothing can be dropped into it. */
184
+ dropDisabled?: boolean;
185
+ };
186
+ declare function KanbanColumn({ children, className, columnId, dropDisabled, ...props }: KanbanColumnProps): React.JSX.Element;
187
+ declare function KanbanColumnHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
188
+ declare function KanbanColumnTitle({ className, ...props }: React.ComponentProps<"h3">): React.JSX.Element;
189
+ declare function KanbanColumnDot({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
190
+ declare function KanbanColumnCount({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
191
+ declare function KanbanColumnDescription({ className, ...props }: React.ComponentProps<"p">): React.JSX.Element;
192
+ type KanbanColumnBodyProps = React.ComponentProps<"div">;
193
+ declare function KanbanColumnBody({ className, ...props }: KanbanColumnBodyProps): React.JSX.Element;
194
+ /**
195
+ * Shown only while a card from another column hovers this one — the "drop here
196
+ * to move" affordance. Dropping on the column (rather than on a card) inserts
197
+ * at the top, which is where this placeholder sits.
198
+ */
199
+ declare function KanbanDropPlaceholder({ className, children, ...props }: React.ComponentProps<"div">): React.JSX.Element | null;
200
+ type KanbanCardProps = React.ComponentProps<"div"> & {
201
+ cardId: string;
202
+ /** Turns off dragging (e.g. missing permission); drops still target it. */
203
+ dragDisabled?: boolean;
204
+ };
205
+ declare function KanbanCard({ cardId, children, className, dragDisabled, ...props }: KanbanCardProps): React.JSX.Element;
206
+ /**
207
+ * Restricts dragging to this element instead of the whole card. Worth adding
208
+ * as soon as a card holds its own controls — a menu, a link, a checkbox —
209
+ * since a drag started on one of those is a drag the user did not ask for.
210
+ * Renders a grip button; pass `children` to make it anything else.
211
+ */
212
+ declare function KanbanCardDragHandle({ children, className, ...props }: React.ComponentProps<"button">): React.JSX.Element;
213
+ //#endregion
214
+ export { KanbanBoard, KanbanCard, KanbanCardDragHandle, type KanbanCardMove, type KanbanCardProps, KanbanColumn, KanbanColumnBody, KanbanColumnCount, KanbanColumnDescription, KanbanColumnDot, KanbanColumnHeader, type KanbanColumnProps, KanbanColumnTitle, type KanbanDragState, KanbanDropPlaceholder, type KanbanEdge, KanbanRoot, type KanbanRootProps, KanbanScrollButton, KanbanScrollControls, applyKanbanCardMove, sortIdsBySavedOrder, useKanbanCardOrder, useKanbanDrag, useKanbanFeedback, useKanbanScroll };