@fayz-ai/ui 0.22.0 → 0.23.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 (71) hide show
  1. package/dist/analytics/AnalyticsCard.d.ts.map +1 -1
  2. package/dist/analytics/AnalyticsControls.d.ts.map +1 -1
  3. package/dist/analytics/DateRangeControl.d.ts +14 -0
  4. package/dist/analytics/DateRangeControl.d.ts.map +1 -0
  5. package/dist/analytics/StatementTable.d.ts +22 -0
  6. package/dist/analytics/StatementTable.d.ts.map +1 -0
  7. package/dist/analytics/context.d.ts +8 -0
  8. package/dist/analytics/context.d.ts.map +1 -1
  9. package/dist/analytics/derive.d.ts +13 -0
  10. package/dist/analytics/derive.d.ts.map +1 -1
  11. package/dist/analytics/index.d.ts +7 -1
  12. package/dist/analytics/index.d.ts.map +1 -1
  13. package/dist/analytics/statement.d.ts +58 -0
  14. package/dist/analytics/statement.d.ts.map +1 -0
  15. package/dist/{chunk-E44WOPCR.js → chunk-HO2P2XB4.js} +428 -58
  16. package/dist/chunk-HO2P2XB4.js.map +1 -0
  17. package/dist/{chunk-7G3O54CC.js → chunk-L4TXDKMN.js} +5 -5
  18. package/dist/chunk-L4TXDKMN.js.map +1 -0
  19. package/dist/{chunk-DHNUZF2X.js → chunk-OWN3GFDG.js} +4 -3
  20. package/dist/chunk-OWN3GFDG.js.map +1 -0
  21. package/dist/{chunk-PQUS22JE.js → chunk-RRNMNFLF.js} +483 -794
  22. package/dist/chunk-RRNMNFLF.js.map +1 -0
  23. package/dist/chunk-UP7WVKSU.js +631 -0
  24. package/dist/chunk-UP7WVKSU.js.map +1 -0
  25. package/dist/{chunk-ZSOT7KTE.js → chunk-XEUIYSW2.js} +321 -361
  26. package/dist/chunk-XEUIYSW2.js.map +1 -0
  27. package/dist/{chunk-SUSW4LSW.js → chunk-XKFYX3DG.js} +5 -5
  28. package/dist/{chunk-SUSW4LSW.js.map → chunk-XKFYX3DG.js.map} +1 -1
  29. package/dist/dashboard/index.js +4 -4
  30. package/dist/icons.js +1 -1
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +672 -87
  34. package/dist/index.js.map +1 -1
  35. package/dist/layout/AppShell.d.ts +7 -1
  36. package/dist/layout/AppShell.d.ts.map +1 -1
  37. package/dist/layout/ShellSearch.d.ts +53 -0
  38. package/dist/layout/ShellSearch.d.ts.map +1 -0
  39. package/dist/layout/Sidebar.d.ts +10 -6
  40. package/dist/layout/Sidebar.d.ts.map +1 -1
  41. package/dist/layout/Takeover.d.ts.map +1 -1
  42. package/dist/layout/index.d.ts +1 -0
  43. package/dist/layout/index.d.ts.map +1 -1
  44. package/dist/layout/index.js +4 -4
  45. package/dist/primitives/data-table.d.ts.map +1 -1
  46. package/dist/primitives/date-range-chip.d.ts +32 -0
  47. package/dist/primitives/date-range-chip.d.ts.map +1 -0
  48. package/dist/primitives/header-tabs.d.ts.map +1 -1
  49. package/dist/primitives/index.d.ts +2 -1
  50. package/dist/primitives/index.d.ts.map +1 -1
  51. package/dist/primitives/index.js +5 -5
  52. package/dist/primitives/list-view.d.ts +43 -1
  53. package/dist/primitives/list-view.d.ts.map +1 -1
  54. package/dist/primitives/modal.d.ts +2 -0
  55. package/dist/primitives/modal.d.ts.map +1 -1
  56. package/dist/primitives/page-actions.d.ts +14 -0
  57. package/dist/primitives/page-actions.d.ts.map +1 -1
  58. package/dist/primitives/page-toolbar.d.ts +16 -1
  59. package/dist/primitives/page-toolbar.d.ts.map +1 -1
  60. package/dist/primitives/segmented-control.d.ts.map +1 -1
  61. package/dist/stores/layout.store.d.ts +20 -1
  62. package/dist/stores/layout.store.d.ts.map +1 -1
  63. package/dist/styles.css +58 -0
  64. package/package.json +2 -2
  65. package/dist/chunk-7G3O54CC.js.map +0 -1
  66. package/dist/chunk-DHNUZF2X.js.map +0 -1
  67. package/dist/chunk-E44WOPCR.js.map +0 -1
  68. package/dist/chunk-HKGTF2YA.js +0 -117
  69. package/dist/chunk-HKGTF2YA.js.map +0 -1
  70. package/dist/chunk-PQUS22JE.js.map +0 -1
  71. package/dist/chunk-ZSOT7KTE.js.map +0 -1
@@ -1,25 +1,24 @@
1
- import { useSaveBarVisible, useCrossModuleBack, useBackHandler, PageHeaderActions, SegmentedControl } from './chunk-PQUS22JE.js';
2
- import { useIsWide, Dropdown, DropdownTrigger, DropdownContent, DropdownSeparator, DropdownItem, Card, DataTable, Checkbox } from './chunk-E44WOPCR.js';
1
+ import { PageHeaderActions, SegmentedControl } from './chunk-UP7WVKSU.js';
2
+ import { Hint, Dropdown, DropdownTrigger, DropdownContent, DropdownSeparator, DropdownItem, Card, PageActionBar, DataTable, Popover, PopoverTrigger, PopoverContent, Checkbox, useIsWide } from './chunk-HO2P2XB4.js';
3
+ import { useSaveBarVisible, useCrossModuleBack, useBackHandler } from './chunk-RRNMNFLF.js';
3
4
  import { cn, Button } from './chunk-OKZ6WQB3.js';
4
- import * as React18 from 'react';
5
- import React18__default, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
5
+ import * as React15 from 'react';
6
+ import React15__default, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
6
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
8
  import { cva } from 'class-variance-authority';
8
9
  import * as DialogPrimitive from '@radix-ui/react-dialog';
9
- import { X, ChevronDown, ChevronUp, Check, ArrowLeft, MoreHorizontal, Plus, MoreVertical, Search, ChevronLeft, ChevronRight, ImageIcon, RefreshCw, Clock, Download, Calendar, Loader2 } from 'lucide-react';
10
+ import { X, ChevronDown, ChevronUp, Check, ArrowLeft, MoreHorizontal, Search, ChevronLeft, ChevronRight, ImageIcon, RefreshCw, Clock, Plus, Download, Calendar, Loader2, CalendarDays, SlidersHorizontal } from 'lucide-react';
10
11
  import * as SelectPrimitive from '@radix-ui/react-select';
11
12
  import { Toaster } from 'sonner';
12
13
  export { toast } from 'sonner';
13
14
  import * as TabsPrimitive from '@radix-ui/react-tabs';
14
15
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
15
- import * as TooltipPrimitive from '@radix-ui/react-tooltip';
16
- import { createPortal } from 'react-dom';
17
16
  import { useTranslation, getCountry, unmaskPhone, maskPhone, getCurrentLocale } from '@fayz-ai/core';
18
- import * as PopoverPrimitive from '@radix-ui/react-popover';
17
+ import { createPortal } from 'react-dom';
19
18
 
20
- var Input = React18.forwardRef(
19
+ var Input = React15.forwardRef(
21
20
  ({ className, type, error, description, id, ...props }, ref) => {
22
- const inputId = id ?? React18.useId();
21
+ const inputId = id ?? React15.useId();
23
22
  const descriptionId = description ? `${inputId}-description` : void 0;
24
23
  const errorId = error ? `${inputId}-error` : void 0;
25
24
  return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
@@ -101,13 +100,18 @@ var SIZE_MAP = {
101
100
  xl: "sm:max-w-xl",
102
101
  "2xl": "sm:max-w-2xl",
103
102
  "3xl": "sm:max-w-3xl",
103
+ // Duas colunas de trabalho lado a lado (ficha + linha do tempo) não cabem em
104
+ // 3xl: a coluna da direita fica com 20rem e o texto de cada anotação quebra
105
+ // a cada quatro palavras.
106
+ "4xl": "sm:max-w-4xl",
107
+ "5xl": "sm:max-w-5xl",
104
108
  full: "sm:max-w-[calc(100vw-4rem)]"
105
109
  };
106
110
  var Modal = DialogPrimitive.Root;
107
111
  var ModalTrigger = DialogPrimitive.Trigger;
108
112
  var ModalClose = DialogPrimitive.Close;
109
113
  var ModalPortal = DialogPrimitive.Portal;
110
- var ModalOverlay = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
114
+ var ModalOverlay = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
111
115
  DialogPrimitive.Overlay,
112
116
  {
113
117
  ref,
@@ -120,7 +124,7 @@ var ModalOverlay = React18.forwardRef(({ className, ...props }, ref) => /* @__PU
120
124
  }
121
125
  ));
122
126
  ModalOverlay.displayName = "ModalOverlay";
123
- var ModalContent = React18.forwardRef(({ className, children, size = "lg", hideClose, noPadding, onPointerDownOutside, onInteractOutside, onCloseAutoFocus, ...props }, ref) => /* @__PURE__ */ jsx(ModalPortal, { children: /* @__PURE__ */ jsx(ModalOverlay, { children: /* @__PURE__ */ jsxs(
127
+ var ModalContent = React15.forwardRef(({ className, children, size = "lg", hideClose, noPadding, onPointerDownOutside, onInteractOutside, onCloseAutoFocus, ...props }, ref) => /* @__PURE__ */ jsx(ModalPortal, { children: /* @__PURE__ */ jsx(ModalOverlay, { children: /* @__PURE__ */ jsxs(
124
128
  DialogPrimitive.Content,
125
129
  {
126
130
  ref,
@@ -175,14 +179,14 @@ function ModalBody({ className, ...props }) {
175
179
  function ModalFooter({ className, ...props }) {
176
180
  return /* @__PURE__ */ jsx("div", { className: cn("mt-auto flex flex-col-reverse gap-2 sm:mt-0 sm:flex-row sm:justify-end sm:gap-0 sm:space-x-2 shrink-0", className), ...props });
177
181
  }
178
- var ModalTitle = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props }));
182
+ var ModalTitle = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props }));
179
183
  ModalTitle.displayName = "ModalTitle";
180
- var ModalDescription = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
184
+ var ModalDescription = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
181
185
  ModalDescription.displayName = "ModalDescription";
182
186
  var Select = SelectPrimitive.Root;
183
187
  var SelectGroup = SelectPrimitive.Group;
184
188
  var SelectValue = SelectPrimitive.Value;
185
- var SelectTrigger = React18.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
189
+ var SelectTrigger = React15.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
186
190
  SelectPrimitive.Trigger,
187
191
  {
188
192
  ref,
@@ -198,7 +202,7 @@ var SelectTrigger = React18.forwardRef(({ className, children, ...props }, ref)
198
202
  }
199
203
  ));
200
204
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
201
- var SelectScrollUpButton = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
205
+ var SelectScrollUpButton = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
202
206
  SelectPrimitive.ScrollUpButton,
203
207
  {
204
208
  ref,
@@ -211,7 +215,7 @@ var SelectScrollUpButton = React18.forwardRef(({ className, ...props }, ref) =>
211
215
  }
212
216
  ));
213
217
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
214
- var SelectScrollDownButton = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
218
+ var SelectScrollDownButton = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
215
219
  SelectPrimitive.ScrollDownButton,
216
220
  {
217
221
  ref,
@@ -224,7 +228,7 @@ var SelectScrollDownButton = React18.forwardRef(({ className, ...props }, ref) =
224
228
  }
225
229
  ));
226
230
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
227
- var SelectContent = React18.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
231
+ var SelectContent = React15.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
228
232
  SelectPrimitive.Content,
229
233
  {
230
234
  ref,
@@ -252,7 +256,7 @@ var SelectContent = React18.forwardRef(({ className, children, position = "poppe
252
256
  }
253
257
  ) }));
254
258
  SelectContent.displayName = SelectPrimitive.Content.displayName;
255
- var SelectLabel = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
259
+ var SelectLabel = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
256
260
  SelectPrimitive.Label,
257
261
  {
258
262
  ref,
@@ -264,7 +268,7 @@ var SelectLabel = React18.forwardRef(({ className, ...props }, ref) => /* @__PUR
264
268
  }
265
269
  ));
266
270
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
267
- var SelectItem = React18.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
271
+ var SelectItem = React15.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
268
272
  SelectPrimitive.Item,
269
273
  {
270
274
  ref,
@@ -280,7 +284,7 @@ var SelectItem = React18.forwardRef(({ className, children, ...props }, ref) =>
280
284
  }
281
285
  ));
282
286
  SelectItem.displayName = SelectPrimitive.Item.displayName;
283
- var SelectSeparator = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
287
+ var SelectSeparator = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
284
288
  SelectPrimitive.Separator,
285
289
  {
286
290
  ref,
@@ -318,7 +322,7 @@ function ToastProvider({
318
322
  );
319
323
  }
320
324
  var Tabs = TabsPrimitive.Root;
321
- var TabsList = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
325
+ var TabsList = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
322
326
  TabsPrimitive.List,
323
327
  {
324
328
  ref,
@@ -332,7 +336,7 @@ var TabsList = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__
332
336
  }
333
337
  ));
334
338
  TabsList.displayName = TabsPrimitive.List.displayName;
335
- var TabsTrigger = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
339
+ var TabsTrigger = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
336
340
  TabsPrimitive.Trigger,
337
341
  {
338
342
  ref,
@@ -344,7 +348,7 @@ var TabsTrigger = React18.forwardRef(({ className, ...props }, ref) => /* @__PUR
344
348
  }
345
349
  ));
346
350
  TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
347
- var TabsContent = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
351
+ var TabsContent = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
348
352
  TabsPrimitive.Content,
349
353
  {
350
354
  ref,
@@ -356,7 +360,7 @@ var TabsContent = React18.forwardRef(({ className, ...props }, ref) => /* @__PUR
356
360
  }
357
361
  ));
358
362
  TabsContent.displayName = TabsPrimitive.Content.displayName;
359
- var Separator2 = React18.forwardRef(
363
+ var Separator2 = React15.forwardRef(
360
364
  ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
361
365
  SeparatorPrimitive.Root,
362
366
  {
@@ -407,7 +411,7 @@ function formatPhone(digits, fallback, countryCode) {
407
411
  const tail = rest.length === 9 ? rest.slice(5) : rest.slice(4);
408
412
  return `+55 (${ddd}) ${head}-${tail}`;
409
413
  }
410
- var PhoneLink = React18.forwardRef(
414
+ var PhoneLink = React15.forwardRef(
411
415
  ({ phone, message, countryCode, raw, className, children, ...props }, ref) => {
412
416
  const { e164, display } = normalizePhone(phone, countryCode);
413
417
  const label = children ?? (raw ? phone ?? "" : display);
@@ -467,235 +471,6 @@ function Breadcrumb({ parent, current, onBack }) {
467
471
  ] })
468
472
  ] });
469
473
  }
470
- var TooltipProvider = TooltipPrimitive.Provider;
471
- var Tooltip = TooltipPrimitive.Root;
472
- var TooltipTrigger = TooltipPrimitive.Trigger;
473
- var TooltipContent = React18.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
474
- TooltipPrimitive.Content,
475
- {
476
- ref,
477
- sideOffset,
478
- className: cn(
479
- "fayz-glass-surface z-[120] overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
480
- className
481
- ),
482
- ...props
483
- }
484
- ));
485
- TooltipContent.displayName = TooltipPrimitive.Content.displayName;
486
- var Hint = React18.forwardRef(function Hint2({ label, children, side = "top", delayDuration = 0, ...rest }, ref) {
487
- if (!label) return React18.cloneElement(children, { ...rest, ref });
488
- return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, { delayDuration, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
489
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, ...rest, ref, children }),
490
- /* @__PURE__ */ jsx(TooltipContent, { side, className: "px-2 py-1 text-xs font-medium", children: label })
491
- ] }) });
492
- });
493
- function iconOf(action, className) {
494
- const Icon2 = action.icon;
495
- return Icon2 ? /* @__PURE__ */ jsx(Icon2, { className }) : null;
496
- }
497
- function PageActionBar({ actions, className }) {
498
- const wide = useIsWide();
499
- const visible = actions.filter((a) => !a.hidden);
500
- if (visible.length === 0) return null;
501
- if (!wide) {
502
- const usable = visible.filter((a) => !a.desktopOnly);
503
- return usable.length > 0 ? /* @__PURE__ */ jsx(PageActionFab, { actions: usable }) : null;
504
- }
505
- let seenPrimary = false;
506
- const primary = [];
507
- const secondary = [];
508
- const utility = [];
509
- const danger = [];
510
- for (const a of visible) {
511
- const intent = a.intent ?? "secondary";
512
- if (intent === "primary" && !seenPrimary) {
513
- seenPrimary = true;
514
- primary.push(a);
515
- continue;
516
- }
517
- if (intent === "danger") {
518
- danger.push(a);
519
- continue;
520
- }
521
- if (intent === "utility") {
522
- utility.push(a);
523
- continue;
524
- }
525
- secondary.push(a);
526
- }
527
- const head = primary[0];
528
- const menu = [...secondary, ...danger];
529
- return /* @__PURE__ */ jsxs("div", { className: cn("flex shrink-0 items-center gap-2", className), children: [
530
- utility.map((a) => (
531
- // Um botão só de ícone não diz o que faz. `title=` parecia resolver e
532
- // não resolve: espera ~1s que ninguém controla, sai na pintura do
533
- // sistema operacional, nunca aparece no toque e vários leitores de tela
534
- // pulam. Hint é o tooltip do design system, e o texto é ANUNCIADO.
535
- /* @__PURE__ */ jsx(Hint, { label: a.label, children: /* @__PURE__ */ jsx(
536
- Button,
537
- {
538
- variant: "outline",
539
- size: "icon",
540
- onClick: () => void a.onSelect(),
541
- disabled: a.disabled,
542
- "aria-label": a.label,
543
- "data-testid": a.testId,
544
- "data-tour": `action.${a.id}`,
545
- children: iconOf(a, "h-4 w-4")
546
- }
547
- ) }, a.id)
548
- )),
549
- head && menu.length === 0 && /* @__PURE__ */ jsxs(Button, { onClick: () => void head.onSelect(), disabled: head.disabled, "data-testid": head.testId, "data-tour": `action.${head.id}`, children: [
550
- iconOf(head, "mr-1.5 h-4 w-4"),
551
- head.label
552
- ] }),
553
- head && menu.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
554
- /* @__PURE__ */ jsxs(Button, { className: "rounded-r-none", onClick: () => void head.onSelect(), disabled: head.disabled, "data-testid": head.testId, "data-tour": `action.${head.id}`, children: [
555
- iconOf(head, "mr-1.5 h-4 w-4"),
556
- head.label
557
- ] }),
558
- /* @__PURE__ */ jsxs(Dropdown, { children: [
559
- /* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Hint, { label: `${head.label}\u2026`, children: /* @__PURE__ */ jsx(
560
- Button,
561
- {
562
- className: "-ml-px rounded-l-none px-2",
563
- "aria-label": `${head.label}\u2026`,
564
- "data-tour": menu.map((a) => `action.${a.id}`).join(" "),
565
- children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
566
- }
567
- ) }) }),
568
- /* @__PURE__ */ jsx(DropdownContent, { align: "end", className: "w-56", children: /* @__PURE__ */ jsx(ActionItems, { actions: menu }) })
569
- ] })
570
- ] }),
571
- !head && menu.length > 0 && /* @__PURE__ */ jsxs(Dropdown, { children: [
572
- /* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Hint, { label: "A\xE7\xF5es", children: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "icon", "aria-label": "A\xE7\xF5es", children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-4 w-4" }) }) }) }),
573
- /* @__PURE__ */ jsx(DropdownContent, { align: "end", className: "w-56", children: /* @__PURE__ */ jsx(ActionItems, { actions: menu }) })
574
- ] })
575
- ] });
576
- }
577
- function ActionItems({ actions, stagger }) {
578
- const out = [];
579
- actions.forEach((a, i) => {
580
- const isDanger = a.intent === "danger";
581
- const prevSafe = i > 0 && actions[i - 1].intent !== "danger";
582
- if (isDanger && prevSafe) out.push(/* @__PURE__ */ jsx(DropdownSeparator, {}, `${a.id}-sep`));
583
- out.push(
584
- /* @__PURE__ */ jsxs(
585
- DropdownItem,
586
- {
587
- disabled: a.disabled,
588
- onSelect: () => void a.onSelect(),
589
- "data-testid": a.testId,
590
- style: stagger ? { ["--i"]: i } : void 0,
591
- className: cn("gap-2", stagger && "fz-fab-item", isDanger && "text-destructive focus:text-destructive"),
592
- children: [
593
- iconOf(a, "h-4 w-4 shrink-0"),
594
- /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
595
- /* @__PURE__ */ jsx("span", { className: "block truncate", children: a.label }),
596
- a.description && /* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-muted-foreground", children: a.description })
597
- ] })
598
- ]
599
- },
600
- a.id
601
- )
602
- );
603
- });
604
- return /* @__PURE__ */ jsx(Fragment, { children: out });
605
- }
606
- function PageActionFab({ actions }) {
607
- const byIntent = (i) => actions.filter((a) => (a.intent ?? "secondary") === i);
608
- const utility = byIntent("utility");
609
- const main = [...byIntent("primary"), ...byIntent("secondary"), ...byIntent("danger")];
610
- if (main.length === 0) return /* @__PURE__ */ jsx(FabButton, { actions: utility, tone: "neutral" });
611
- const isCreate = main.every((a) => a.creates ?? a.icon === Plus);
612
- return /* @__PURE__ */ jsxs(Fragment, { children: [
613
- utility.length > 0 && /* @__PURE__ */ jsx(FabButton, { actions: utility, tone: "neutral", mini: true }),
614
- /* @__PURE__ */ jsx(FabButton, { actions: main, tone: isCreate ? "primary" : "neutral" })
615
- ] });
616
- }
617
- function useScrim(open) {
618
- const [mounted, setMounted] = React18.useState(open);
619
- const [visible, setVisible] = React18.useState(open);
620
- React18.useEffect(() => {
621
- if (open) {
622
- setMounted(true);
623
- const frame = requestAnimationFrame(() => setVisible(true));
624
- return () => cancelAnimationFrame(frame);
625
- }
626
- setVisible(false);
627
- const timer = window.setTimeout(() => setMounted(false), SCRIM_MS);
628
- return () => window.clearTimeout(timer);
629
- }, [open]);
630
- return { mounted, visible };
631
- }
632
- var SCRIM_MS = 200;
633
- function FabButton({ actions, tone, mini }) {
634
- const [open, setOpen] = React18.useState(false);
635
- const scrim = useScrim(open);
636
- if (actions.length === 0) return null;
637
- const isCreate = tone === "primary";
638
- const FabIcon = isCreate ? Plus : MoreVertical;
639
- const style = {
640
- bottom: mini ? "calc(var(--fz-bottom-bar, 0px) + 4.75rem)" : "calc(var(--fz-bottom-bar, 0px) + 1rem)"
641
- };
642
- const shell = cn(
643
- "fz-tap fixed z-40 flex items-center justify-center rounded-full",
644
- "transition-transform active:scale-95 md:hidden",
645
- // Centred on the main circle's column, so the two read as one stack.
646
- mini ? "right-5 h-12 w-12" : "right-4 h-14 w-14",
647
- isCreate ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30 ring-4 ring-background" : "bg-card text-foreground shadow-lg ring-1 ring-border"
648
- );
649
- if (actions.length === 1) {
650
- const only = actions[0];
651
- const Icon2 = only.icon ?? FabIcon;
652
- return /* @__PURE__ */ jsx(
653
- "button",
654
- {
655
- type: "button",
656
- style,
657
- className: shell,
658
- onClick: () => void only.onSelect(),
659
- disabled: only.disabled,
660
- "aria-label": only.label,
661
- "data-testid": only.testId,
662
- children: /* @__PURE__ */ jsx(Icon2, { className: mini ? "h-5 w-5" : "h-6 w-6" })
663
- }
664
- );
665
- }
666
- return /* @__PURE__ */ jsxs(Dropdown, { open, onOpenChange: setOpen, children: [
667
- scrim.mounted && typeof document !== "undefined" && createPortal(
668
- /* @__PURE__ */ jsx(
669
- "div",
670
- {
671
- "aria-hidden": true,
672
- onClick: () => setOpen(false),
673
- className: cn(
674
- "fixed inset-0 z-[100] bg-foreground/40 transition-opacity duration-200 md:hidden",
675
- "motion-reduce:transition-none",
676
- scrim.visible ? "opacity-100" : "opacity-0"
677
- )
678
- }
679
- ),
680
- document.body
681
- ),
682
- /* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
683
- "button",
684
- {
685
- type: "button",
686
- style,
687
- className: cn(shell, open && "z-[105]", isCreate && "fz-fab-trigger"),
688
- "aria-label": actionsMenuLabel,
689
- children: /* @__PURE__ */ jsx(FabIcon, { className: mini ? "h-5 w-5" : "h-6 w-6" })
690
- }
691
- ) }),
692
- /* @__PURE__ */ jsx(DropdownContent, { side: "top", align: "end", sideOffset: 12, className: "fz-fab-menu w-60 md:hidden", children: /* @__PURE__ */ jsx(ActionItems, { actions, stagger: true }) })
693
- ] });
694
- }
695
- var actionsMenuLabel = "A\xE7\xF5es";
696
- function setActionsMenuLabel(label) {
697
- actionsMenuLabel = label;
698
- }
699
474
  var INLINE_LIMIT = 2;
700
475
  function RowActions({
701
476
  actions,
@@ -744,7 +519,7 @@ function RowActions({
744
519
  const Icon2 = a.icon;
745
520
  const isDanger = a.intent === "danger";
746
521
  const prevSafe = i > 0 && overflow[i - 1].intent !== "danger";
747
- return /* @__PURE__ */ jsxs(React18.Fragment, { children: [
522
+ return /* @__PURE__ */ jsxs(React15.Fragment, { children: [
748
523
  isDanger && prevSafe && /* @__PURE__ */ jsx(DropdownSeparator, {}),
749
524
  /* @__PURE__ */ jsxs(
750
525
  DropdownItem,
@@ -963,8 +738,8 @@ var ICON_CLASSES = {
963
738
  lg: "h-5 w-5"
964
739
  };
965
740
  function Thumbnail({ src, alt = "", size = "md", icon: Icon2 = ImageIcon, className }) {
966
- const [failed, setFailed] = React18.useState(false);
967
- React18.useEffect(() => {
741
+ const [failed, setFailed] = React15.useState(false);
742
+ React15.useEffect(() => {
968
743
  setFailed(false);
969
744
  }, [src]);
970
745
  const base = cn("shrink-0 overflow-hidden", SIZE_CLASSES[size], className);
@@ -991,9 +766,9 @@ function Thumbnail({ src, alt = "", size = "md", icon: Icon2 = ImageIcon, classN
991
766
  }
992
767
  Thumbnail.displayName = "Thumbnail";
993
768
  function RefreshButton({ onRefresh, fromCache, label, labelCached, className, ...rest }) {
994
- const [phase, setPhase] = React18.useState("idle");
995
- const alive = React18.useRef(true);
996
- React18.useEffect(() => () => {
769
+ const [phase, setPhase] = React15.useState("idle");
770
+ const alive = React15.useRef(true);
771
+ React15.useEffect(() => () => {
997
772
  alive.current = false;
998
773
  }, []);
999
774
  const title = fromCache ? labelCached ?? label : label;
@@ -1211,27 +986,27 @@ function useRowSelection({
1211
986
  getRowId,
1212
987
  enabled = true
1213
988
  }) {
1214
- const identify = React18.useCallback(
989
+ const identify = React15.useCallback(
1215
990
  (row) => getRowId ? getRowId(row) : String(row?.id ?? ""),
1216
991
  [getRowId]
1217
992
  );
1218
- const visible = React18.useMemo(() => rows ?? [], [rows]);
1219
- const [rawSelection, setRawSelection] = React18.useState([]);
1220
- const visibleIds = React18.useMemo(() => new Set(visible.map(identify)), [visible, identify]);
1221
- const selectedIds = React18.useMemo(
993
+ const visible = React15.useMemo(() => rows ?? [], [rows]);
994
+ const [rawSelection, setRawSelection] = React15.useState([]);
995
+ const visibleIds = React15.useMemo(() => new Set(visible.map(identify)), [visible, identify]);
996
+ const selectedIds = React15.useMemo(
1222
997
  () => rawSelection.filter((id) => visibleIds.has(id)),
1223
998
  [rawSelection, visibleIds]
1224
999
  );
1225
- const selectedRows = React18.useMemo(() => {
1000
+ const selectedRows = React15.useMemo(() => {
1226
1001
  const picked = new Set(selectedIds);
1227
1002
  return visible.filter((row) => picked.has(identify(row)));
1228
1003
  }, [visible, selectedIds, identify]);
1229
- const clear = React18.useCallback(() => setRawSelection([]), []);
1230
- const selectAll = React18.useCallback(
1004
+ const clear = React15.useCallback(() => setRawSelection([]), []);
1005
+ const selectAll = React15.useCallback(
1231
1006
  () => setRawSelection(visible.map(identify)),
1232
1007
  [visible, identify]
1233
1008
  );
1234
- const barActions = React18.useMemo(
1009
+ const barActions = React15.useMemo(
1235
1010
  () => (actions ?? []).map((action) => ({
1236
1011
  id: action.id,
1237
1012
  label: action.label,
@@ -1291,11 +1066,61 @@ function FilterChip({ allLabel, options, value, onChange, label, icon: Icon2, cl
1291
1066
  ] });
1292
1067
  }
1293
1068
  var ICON_BTN = "fz-tap text-muted-foreground";
1069
+ function ListFilters({ tagFilter, filters, advanced, label, count, wideCount }) {
1070
+ const wide = useIsWide();
1071
+ const [open, setOpen] = useState(false);
1072
+ if (!tagFilter && !filters && !advanced) return null;
1073
+ const inPanel = wide ? advanced : /* @__PURE__ */ jsxs(Fragment, { children: [
1074
+ tagFilter,
1075
+ filters,
1076
+ advanced
1077
+ ] });
1078
+ const badge = wide ? wideCount : count;
1079
+ const trigger = wide && !advanced ? null : /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
1080
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
1081
+ "button",
1082
+ {
1083
+ type: "button",
1084
+ "aria-label": label,
1085
+ className: cn(
1086
+ "inline-flex shrink-0 items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-medium transition-colors",
1087
+ badge > 0 ? "border-primary/30 bg-primary/10 text-primary hover:bg-primary/15" : "border-transparent bg-muted/70 text-muted-foreground hover:bg-muted hover:text-foreground"
1088
+ ),
1089
+ children: [
1090
+ /* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-3 w-3 shrink-0 opacity-70" }),
1091
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: label }),
1092
+ badge > 0 && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-primary/20 px-1.5 text-[10px] font-semibold tabular-nums", children: badge })
1093
+ ]
1094
+ }
1095
+ ) }),
1096
+ /* @__PURE__ */ jsx(
1097
+ PopoverContent,
1098
+ {
1099
+ align: "end",
1100
+ sideOffset: 8,
1101
+ className: "flex max-h-[70vh] w-[min(18rem,calc(100vw-1.5rem))] flex-col gap-3 overflow-y-auto p-3 [&_button]:w-full [&_button]:justify-between",
1102
+ children: inPanel
1103
+ }
1104
+ )
1105
+ ] });
1106
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1107
+ wide && tagFilter,
1108
+ wide && filters,
1109
+ trigger
1110
+ ] });
1111
+ }
1112
+ var PAGER_BTN = "flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-40";
1294
1113
  function ListView({
1295
1114
  columns,
1296
1115
  data,
1297
1116
  loading = false,
1298
1117
  searchPlaceholder = "Search...",
1118
+ filtersLabel = "Filtros",
1119
+ advancedFilters,
1120
+ activeFilterCount = 0,
1121
+ advancedFilterCount,
1122
+ onClearFilters,
1123
+ clearFiltersLabel = "Clear",
1299
1124
  search: controlledSearch,
1300
1125
  onSearchChange,
1301
1126
  searchDebounce = 300,
@@ -1316,6 +1141,9 @@ function ListView({
1316
1141
  total,
1317
1142
  page = 1,
1318
1143
  pageSize = 25,
1144
+ rangeOfLabel = "of",
1145
+ prevPageLabel = "Previous page",
1146
+ nextPageLabel = "Next page",
1319
1147
  onPageChange,
1320
1148
  toolbar,
1321
1149
  filters,
@@ -1404,9 +1232,34 @@ function ListView({
1404
1232
  }
1405
1233
  )
1406
1234
  ] }),
1407
- (tagFilter || filters || onRefresh || onExport) && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex flex-wrap items-center justify-end gap-2", children: [
1408
- tagFilter,
1409
- filters,
1235
+ (tagFilter || filters || advancedFilters || onRefresh || onExport) && // `flex-nowrap`: envolvendo, cada filtro a mais abria uma
1236
+ // linha nova sob a busca, e quatro deles gastavam três linhas
1237
+ // antes da primeira linha da tabela. No celular eles se
1238
+ // recolhem num gatilho (abaixo) e a linha volta a ser uma.
1239
+ /* @__PURE__ */ jsxs("div", { className: "ml-auto flex flex-nowrap items-center justify-end gap-2 md:flex-wrap", children: [
1240
+ /* @__PURE__ */ jsx(
1241
+ ListFilters,
1242
+ {
1243
+ tagFilter,
1244
+ filters,
1245
+ advanced: advancedFilters,
1246
+ label: filtersLabel,
1247
+ count: activeFilterCount,
1248
+ wideCount: advancedFilterCount ?? activeFilterCount
1249
+ }
1250
+ ),
1251
+ onClearFilters && activeFilterCount > 0 && /* @__PURE__ */ jsxs(
1252
+ "button",
1253
+ {
1254
+ type: "button",
1255
+ onClick: onClearFilters,
1256
+ className: "inline-flex shrink-0 items-center gap-1 rounded-full px-2 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
1257
+ children: [
1258
+ /* @__PURE__ */ jsx(X, { className: "h-3 w-3 shrink-0" }),
1259
+ clearFiltersLabel
1260
+ ]
1261
+ }
1262
+ ),
1410
1263
  onRefresh && /* @__PURE__ */ jsx(Hint, { label: refreshLabel, children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": refreshLabel, onClick: onRefresh, className: ICON_BTN, children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }) }) }),
1411
1264
  onExport && /* @__PURE__ */ jsx(Hint, { label: exportLabel, children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": exportLabel, onClick: onExport, className: ICON_BTN, children: /* @__PURE__ */ jsx(Download, { className: "h-4 w-4" }) }) })
1412
1265
  ] })
@@ -1426,40 +1279,46 @@ function ListView({
1426
1279
  onSelectedIdsChange: selection.setSelectedIds,
1427
1280
  getRowId
1428
1281
  }
1429
- )
1430
- ] }),
1431
- showPagination && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-1", children: [
1432
- /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
1433
- (page - 1) * pageSize + 1,
1434
- "\u2013",
1435
- Math.min(page * pageSize, totalItems),
1436
- " of ",
1437
- totalItems
1438
- ] }),
1439
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1440
- /* @__PURE__ */ jsx(
1441
- "button",
1442
- {
1443
- onClick: () => onPageChange(page - 1),
1444
- disabled: page <= 1,
1445
- className: "flex h-7 w-7 items-center justify-center rounded-md border hover:bg-muted bg-card shadow-button active:shadow-button-inset transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
1446
- children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-3.5 w-3.5" })
1447
- }
1448
- ),
1449
- /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground px-2", children: [
1450
- page,
1451
- " / ",
1452
- totalPages
1282
+ ),
1283
+ showPagination && /* @__PURE__ */ jsxs("div", { className: "-mt-px flex flex-wrap items-center justify-between gap-2 rounded-b-card border-t border-border px-3 py-2", children: [
1284
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
1285
+ (page - 1) * pageSize + 1,
1286
+ "\u2013",
1287
+ Math.min(page * pageSize, totalItems),
1288
+ " ",
1289
+ rangeOfLabel,
1290
+ " ",
1291
+ totalItems.toLocaleString()
1453
1292
  ] }),
1454
- /* @__PURE__ */ jsx(
1455
- "button",
1456
- {
1457
- onClick: () => onPageChange(page + 1),
1458
- disabled: page >= totalPages,
1459
- className: "flex h-7 w-7 items-center justify-center rounded-md border hover:bg-muted bg-card shadow-button active:shadow-button-inset transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
1460
- children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5" })
1461
- }
1462
- )
1293
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1294
+ /* @__PURE__ */ jsx(
1295
+ "button",
1296
+ {
1297
+ type: "button",
1298
+ onClick: () => onPageChange(page - 1),
1299
+ disabled: page <= 1,
1300
+ "aria-label": prevPageLabel,
1301
+ className: PAGER_BTN,
1302
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
1303
+ }
1304
+ ),
1305
+ /* @__PURE__ */ jsxs("span", { className: "px-1 text-xs tabular-nums text-muted-foreground", children: [
1306
+ page,
1307
+ " / ",
1308
+ totalPages
1309
+ ] }),
1310
+ /* @__PURE__ */ jsx(
1311
+ "button",
1312
+ {
1313
+ type: "button",
1314
+ onClick: () => onPageChange(page + 1),
1315
+ disabled: page >= totalPages,
1316
+ "aria-label": nextPageLabel,
1317
+ className: PAGER_BTN,
1318
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
1319
+ }
1320
+ )
1321
+ ] })
1463
1322
  ] })
1464
1323
  ] })
1465
1324
  ] });
@@ -1667,7 +1526,7 @@ function toLocalISODate(d) {
1667
1526
  }
1668
1527
  function MiniCalendar({ selectedDate, onDateSelect, onMonthChange, markers }) {
1669
1528
  const locale = getCurrentLocale();
1670
- const [viewMonth, setViewMonth] = React18__default.useState(() => new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1));
1529
+ const [viewMonth, setViewMonth] = React15__default.useState(() => new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1));
1671
1530
  const monthLabel = viewMonth.toLocaleDateString(toDateLocale2(locale), { month: "long", year: "numeric" });
1672
1531
  const dayLabels = DAY_LABELS2[locale] ?? DAY_LABELS2.en;
1673
1532
  const weeks = useMemo(() => {
@@ -1746,7 +1605,7 @@ function FilterSection({
1746
1605
  defaultOpen = true,
1747
1606
  children
1748
1607
  }) {
1749
- const [open, setOpen] = React18__default.useState(defaultOpen);
1608
+ const [open, setOpen] = React15__default.useState(defaultOpen);
1750
1609
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1751
1610
  /* @__PURE__ */ jsxs(
1752
1611
  "button",
@@ -1819,7 +1678,7 @@ function FilterCheckList({
1819
1678
  }
1820
1679
  return /* @__PURE__ */ jsx("div", { className: className ? `${className} space-y-0.5` : "space-y-0.5", children: rows });
1821
1680
  }
1822
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React18.useLayoutEffect : React18.useEffect;
1681
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React15.useLayoutEffect : React15.useEffect;
1823
1682
  function SearchSelect({
1824
1683
  value,
1825
1684
  displayValue,
@@ -1843,18 +1702,18 @@ function SearchSelect({
1843
1702
  "data-tour": dataTour
1844
1703
  }) {
1845
1704
  const canCreate = !!onCreate && allowCreate !== false;
1846
- const [open, setOpen] = React18.useState(false);
1847
- const [query, setQuery] = React18.useState("");
1848
- const [results, setResults] = React18.useState([]);
1849
- const [loading, setLoading] = React18.useState(false);
1850
- const [creating, setCreating] = React18.useState(false);
1851
- const [selectedLabel, setSelectedLabel] = React18.useState(displayValue ?? "");
1852
- const containerRef = React18.useRef(null);
1853
- const inputRef = React18.useRef(null);
1854
- const timerRef = React18.useRef();
1855
- const [rect, setRect] = React18.useState(null);
1856
- const dropdownRef = React18.useRef(null);
1857
- React18.useEffect(() => {
1705
+ const [open, setOpen] = React15.useState(false);
1706
+ const [query, setQuery] = React15.useState("");
1707
+ const [results, setResults] = React15.useState([]);
1708
+ const [loading, setLoading] = React15.useState(false);
1709
+ const [creating, setCreating] = React15.useState(false);
1710
+ const [selectedLabel, setSelectedLabel] = React15.useState(displayValue ?? "");
1711
+ const containerRef = React15.useRef(null);
1712
+ const inputRef = React15.useRef(null);
1713
+ const timerRef = React15.useRef();
1714
+ const [rect, setRect] = React15.useState(null);
1715
+ const dropdownRef = React15.useRef(null);
1716
+ React15.useEffect(() => {
1858
1717
  function handler(e) {
1859
1718
  const target = e.target;
1860
1719
  if (containerRef.current?.contains(target)) return;
@@ -1864,10 +1723,10 @@ function SearchSelect({
1864
1723
  document.addEventListener("mousedown", handler);
1865
1724
  return () => document.removeEventListener("mousedown", handler);
1866
1725
  }, []);
1867
- React18.useEffect(() => {
1726
+ React15.useEffect(() => {
1868
1727
  if (displayValue !== void 0) setSelectedLabel(displayValue);
1869
1728
  }, [displayValue]);
1870
- React18.useEffect(() => {
1729
+ React15.useEffect(() => {
1871
1730
  if (open && loadOnOpen && query.length === 0 && results.length === 0 && !loading) {
1872
1731
  setLoading(true);
1873
1732
  Promise.resolve(onSearch("")).then(setResults).catch(() => setResults([])).finally(() => setLoading(false));
@@ -1925,7 +1784,7 @@ function SearchSelect({
1925
1784
  setResults([]);
1926
1785
  setTimeout(() => inputRef.current?.focus(), 0);
1927
1786
  }
1928
- const groups = React18.useMemo(() => {
1787
+ const groups = React15.useMemo(() => {
1929
1788
  const map = /* @__PURE__ */ new Map();
1930
1789
  for (const opt of results) {
1931
1790
  const group = opt.group ?? "";
@@ -2020,7 +1879,7 @@ function SearchSelect({
2020
1879
  /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
2021
1880
  " ",
2022
1881
  searchingLabel
2023
- ] }) : results.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-4 py-4 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: noResultsLabel ?? (query ? `No results for "${query}"` : "No results") }) }) : /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-auto py-1", children: [...groups.entries()].map(([group, options]) => /* @__PURE__ */ jsxs(React18.Fragment, { children: [
1882
+ ] }) : results.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-4 py-4 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: noResultsLabel ?? (query ? `No results for "${query}"` : "No results") }) }) : /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-auto py-1", children: [...groups.entries()].map(([group, options]) => /* @__PURE__ */ jsxs(React15.Fragment, { children: [
2024
1883
  group && /* @__PURE__ */ jsx("div", { className: "sticky top-0 bg-muted/50 px-3 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: group }),
2025
1884
  options.map((opt) => /* @__PURE__ */ jsx(
2026
1885
  "button",
@@ -2082,9 +1941,9 @@ function CurrencyInput({
2082
1941
  className,
2083
1942
  disabled
2084
1943
  }) {
2085
- const inputRef = React18.useRef(null);
2086
- const [focused, setFocused] = React18.useState(false);
2087
- const format = React18.useCallback((v) => {
1944
+ const inputRef = React15.useRef(null);
1945
+ const [focused, setFocused] = React15.useState(false);
1946
+ const format = React15.useCallback((v) => {
2088
1947
  return new Intl.NumberFormat(locale, {
2089
1948
  minimumFractionDigits: 2,
2090
1949
  maximumFractionDigits: 2
@@ -2154,24 +2013,125 @@ function CurrencyInput({
2154
2013
  )
2155
2014
  ] });
2156
2015
  }
2157
- var Popover = PopoverPrimitive.Root;
2158
- var PopoverTrigger = PopoverPrimitive.Trigger;
2159
- var PopoverAnchor = PopoverPrimitive.Anchor;
2160
- var PopoverContent = React18.forwardRef(({ className, align = "start", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
2161
- PopoverPrimitive.Content,
2162
- {
2163
- ref,
2164
- align,
2165
- sideOffset,
2166
- className: cn(
2167
- "fayz-glass-surface z-[110] w-72 rounded-xl border bg-popover p-0 text-popover-foreground shadow-lg outline-none",
2168
- "data-[state=open]:animate-zoom-in data-[state=closed]:animate-zoom-out",
2169
- className
2170
- ),
2171
- ...props
2016
+ function formatRange(from, to, locale) {
2017
+ const parse = (s) => {
2018
+ const [y, m, d] = s.split("-").map(Number);
2019
+ return new Date(y, (m ?? 1) - 1, d ?? 1);
2020
+ };
2021
+ const day = (d) => String(d.getDate());
2022
+ const dayMonth = (d) => d.toLocaleDateString(locale, { day: "numeric", month: "short" }).replace(/\.$/, "");
2023
+ if (from && to) {
2024
+ const a = parse(from);
2025
+ const b = parse(to);
2026
+ if (a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth()) {
2027
+ return a.getDate() === b.getDate() ? dayMonth(a) : `${day(a)}\u2013${dayMonth(b)}`;
2028
+ }
2029
+ return `${dayMonth(a)} \u2013 ${dayMonth(b)}`;
2172
2030
  }
2173
- ) }));
2174
- PopoverContent.displayName = PopoverPrimitive.Content.displayName;
2031
+ return dayMonth(parse(from || to));
2032
+ }
2033
+ function DateRangeChip({
2034
+ from,
2035
+ to,
2036
+ onChange,
2037
+ presets = [],
2038
+ preset,
2039
+ onPresetChange,
2040
+ allLabel,
2041
+ labels,
2042
+ label,
2043
+ className
2044
+ }) {
2045
+ const [open, setOpen] = React15.useState(false);
2046
+ const active = !!(from || to);
2047
+ const locale = typeof navigator !== "undefined" ? navigator.language : "en";
2048
+ const presetLabel = presets.find((p) => p.value === preset)?.label;
2049
+ const text = !active ? allLabel : presetLabel ?? formatRange(from, to, locale);
2050
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
2051
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2052
+ "button",
2053
+ {
2054
+ type: "button",
2055
+ "aria-label": label,
2056
+ className: cn(
2057
+ "inline-flex shrink-0 items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-medium transition-colors",
2058
+ active ? "border-primary/30 bg-primary/10 text-primary hover:bg-primary/15" : "border-transparent bg-muted/70 text-muted-foreground hover:bg-muted hover:text-foreground",
2059
+ className
2060
+ ),
2061
+ children: [
2062
+ /* @__PURE__ */ jsx(CalendarDays, { className: "h-3 w-3 shrink-0 opacity-70" }),
2063
+ /* @__PURE__ */ jsx("span", { className: "max-w-[12rem] truncate", children: text })
2064
+ ]
2065
+ }
2066
+ ) }),
2067
+ /* @__PURE__ */ jsxs(PopoverContent, { align: "start", sideOffset: 6, className: "w-60 p-1.5", children: [
2068
+ /* @__PURE__ */ jsxs(
2069
+ "button",
2070
+ {
2071
+ type: "button",
2072
+ onClick: () => {
2073
+ onPresetChange?.("all");
2074
+ onChange({ from: "", to: "" });
2075
+ setOpen(false);
2076
+ },
2077
+ className: "flex w-full items-center rounded-md px-2 py-1.5 text-sm transition-colors hover:bg-muted",
2078
+ children: [
2079
+ allLabel,
2080
+ !active && /* @__PURE__ */ jsx(Check, { className: "ml-auto h-3.5 w-3.5 shrink-0" })
2081
+ ]
2082
+ }
2083
+ ),
2084
+ presets.map((p) => /* @__PURE__ */ jsxs(
2085
+ "button",
2086
+ {
2087
+ type: "button",
2088
+ onClick: () => {
2089
+ onPresetChange?.(p.value);
2090
+ setOpen(false);
2091
+ },
2092
+ className: "flex w-full items-center rounded-md px-2 py-1.5 text-sm transition-colors hover:bg-muted",
2093
+ children: [
2094
+ p.label,
2095
+ active && preset === p.value && /* @__PURE__ */ jsx(Check, { className: "ml-auto h-3.5 w-3.5 shrink-0" })
2096
+ ]
2097
+ },
2098
+ p.value
2099
+ )),
2100
+ /* @__PURE__ */ jsxs("div", { className: "mt-1 space-y-1.5 border-t border-border px-2 pb-1 pt-2", children: [
2101
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2102
+ /* @__PURE__ */ jsx("span", { className: "w-8 shrink-0", children: labels?.from ?? "From" }),
2103
+ /* @__PURE__ */ jsx(
2104
+ DatePicker,
2105
+ {
2106
+ value: from,
2107
+ onChange: (next) => {
2108
+ onPresetChange?.("custom");
2109
+ onChange({ from: next, to });
2110
+ },
2111
+ variant: "toolbar",
2112
+ className: "min-w-0 flex-1"
2113
+ }
2114
+ )
2115
+ ] }),
2116
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2117
+ /* @__PURE__ */ jsx("span", { className: "w-8 shrink-0", children: labels?.to ?? "To" }),
2118
+ /* @__PURE__ */ jsx(
2119
+ DatePicker,
2120
+ {
2121
+ value: to,
2122
+ onChange: (next) => {
2123
+ onPresetChange?.("custom");
2124
+ onChange({ from, to: next });
2125
+ },
2126
+ variant: "toolbar",
2127
+ className: "min-w-0 flex-1"
2128
+ }
2129
+ )
2130
+ ] })
2131
+ ] })
2132
+ ] })
2133
+ ] });
2134
+ }
2175
2135
  function MultiSelect({
2176
2136
  options,
2177
2137
  value,
@@ -2183,9 +2143,9 @@ function MultiSelect({
2183
2143
  className,
2184
2144
  searchThreshold = 8
2185
2145
  }) {
2186
- const [query, setQuery] = React18.useState("");
2187
- const selected = React18.useMemo(() => new Set(value), [value]);
2188
- const filtered = React18.useMemo(() => {
2146
+ const [query, setQuery] = React15.useState("");
2147
+ const selected = React15.useMemo(() => new Set(value), [value]);
2148
+ const filtered = React15.useMemo(() => {
2189
2149
  const q = query.trim().toLowerCase();
2190
2150
  if (!q) return options;
2191
2151
  return options.filter((o) => o.label.toLowerCase().includes(q));
@@ -2280,7 +2240,7 @@ function renderInline(text, keyPrefix) {
2280
2240
  if (part.startsWith("`") && part.endsWith("`") && part.length > 2) {
2281
2241
  return /* @__PURE__ */ jsx("code", { className: "rounded bg-muted px-1 py-0.5 font-mono text-[0.85em]", children: part.slice(1, -1) }, key);
2282
2242
  }
2283
- return part === "" ? null : /* @__PURE__ */ jsx(React18.Fragment, { children: part }, key);
2243
+ return part === "" ? null : /* @__PURE__ */ jsx(React15.Fragment, { children: part }, key);
2284
2244
  });
2285
2245
  }
2286
2246
  function parseBlocks(source) {
@@ -2364,7 +2324,7 @@ function renderMarkdown(source) {
2364
2324
  case "ol":
2365
2325
  return /* @__PURE__ */ jsx("ol", { className: "list-decimal space-y-1 pl-5", children: block.items.map((item, li) => /* @__PURE__ */ jsx("li", { children: renderInline(item, `${key}-${li}`) }, `${key}-${li}`)) }, key);
2366
2326
  case "p":
2367
- return /* @__PURE__ */ jsx("p", { children: block.lines.map((l, li) => /* @__PURE__ */ jsxs(React18.Fragment, { children: [
2327
+ return /* @__PURE__ */ jsx("p", { children: block.lines.map((l, li) => /* @__PURE__ */ jsxs(React15.Fragment, { children: [
2368
2328
  li > 0 && /* @__PURE__ */ jsx("br", {}),
2369
2329
  renderInline(l, `${key}-${li}`)
2370
2330
  ] }, `${key}-${li}`)) }, key);
@@ -2385,7 +2345,7 @@ function MarkdownEditor({
2385
2345
  renderPreview,
2386
2346
  className
2387
2347
  }) {
2388
- const [mode, setMode] = React18.useState(
2348
+ const [mode, setMode] = React15.useState(
2389
2349
  defaultMode === "preview" && value.trim() === "" ? "edit" : defaultMode
2390
2350
  );
2391
2351
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
@@ -2679,13 +2639,13 @@ function StockEntryForm({
2679
2639
  labels: overrides
2680
2640
  }) {
2681
2641
  const labels = { ...DEFAULT_LABELS, ...overrides };
2682
- const [quantity, setQuantity] = React18.useState("");
2683
- const [reasonCode, setReasonCode] = React18.useState("");
2684
- const [occurredOn, setOccurredOn] = React18.useState(todayISO());
2685
- const [note, setNote] = React18.useState("");
2686
- const [noteOpen, setNoteOpen] = React18.useState(false);
2687
- const quantityRef = React18.useRef(null);
2688
- React18.useEffect(() => {
2642
+ const [quantity, setQuantity] = React15.useState("");
2643
+ const [reasonCode, setReasonCode] = React15.useState("");
2644
+ const [occurredOn, setOccurredOn] = React15.useState(todayISO());
2645
+ const [note, setNote] = React15.useState("");
2646
+ const [noteOpen, setNoteOpen] = React15.useState(false);
2647
+ const quantityRef = React15.useRef(null);
2648
+ React15.useEffect(() => {
2689
2649
  if (verb === null) return;
2690
2650
  setQuantity("");
2691
2651
  setReasonCode("");
@@ -2811,6 +2771,6 @@ function StockEntryForm({
2811
2771
  ] }) });
2812
2772
  }
2813
2773
 
2814
- export { Badge, Breadcrumb, BulkActionBar, ChevronPager, CurrencyInput, DatePicker, DotBadge, DraftCommitBar, FilterCheckBox, FilterCheckList, FilterCheckRow, FilterChip, FilterSection, Hint, Input, ListView, Markdown, MarkdownEditor, MiniCalendar, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, MultiSelect, PageActionBar, PhoneField, PhoneLink, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, RefreshButton, RowActions, SearchCombobox, SearchField, SearchSelect, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, StatTiles, StockEntryForm, Tabs, TabsContent, TabsList, TabsTrigger, Thumbnail, TimePicker, ToastProvider, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, WHATSAPP_BRAND_COLOR, WhatsAppIcon, badgeVariants, formatPhone2 as formatPhone, normalizePhone, renderMarkdown, setActionsMenuLabel, setRowActionsLabel, toLocalISODate, useRowSelection };
2815
- //# sourceMappingURL=chunk-ZSOT7KTE.js.map
2816
- //# sourceMappingURL=chunk-ZSOT7KTE.js.map
2774
+ export { Badge, Breadcrumb, BulkActionBar, ChevronPager, CurrencyInput, DatePicker, DateRangeChip, DotBadge, DraftCommitBar, FilterCheckBox, FilterCheckList, FilterCheckRow, FilterChip, FilterSection, Input, ListView, Markdown, MarkdownEditor, MiniCalendar, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, MultiSelect, PhoneField, PhoneLink, RefreshButton, RowActions, SearchCombobox, SearchField, SearchSelect, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, StatTiles, StockEntryForm, Tabs, TabsContent, TabsList, TabsTrigger, Thumbnail, TimePicker, ToastProvider, WHATSAPP_BRAND_COLOR, WhatsAppIcon, badgeVariants, formatPhone2 as formatPhone, normalizePhone, renderMarkdown, setRowActionsLabel, toLocalISODate, useRowSelection };
2775
+ //# sourceMappingURL=chunk-XEUIYSW2.js.map
2776
+ //# sourceMappingURL=chunk-XEUIYSW2.js.map