@fayz-ai/ui 0.10.2 → 0.12.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 (75) 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/batch.d.ts +19 -0
  4. package/dist/analytics/batch.d.ts.map +1 -0
  5. package/dist/analytics/context.d.ts.map +1 -1
  6. package/dist/analytics/derive.d.ts.map +1 -1
  7. package/dist/analytics/index.d.ts +2 -0
  8. package/dist/analytics/index.d.ts.map +1 -1
  9. package/dist/{chunk-SEIY2F5F.js → chunk-7BHG3XGJ.js} +317 -86
  10. package/dist/chunk-7BHG3XGJ.js.map +1 -0
  11. package/dist/{chunk-I6CPKAOD.js → chunk-7BMXN7MP.js} +215 -99
  12. package/dist/chunk-7BMXN7MP.js.map +1 -0
  13. package/dist/{chunk-6V5MGYXH.js → chunk-JGJNRNQW.js} +142 -31
  14. package/dist/chunk-JGJNRNQW.js.map +1 -0
  15. package/dist/chunk-ZBQ772DU.js +17 -0
  16. package/dist/chunk-ZBQ772DU.js.map +1 -0
  17. package/dist/{chunk-H63TOSQ7.js → chunk-ZDRHCKRK.js} +499 -142
  18. package/dist/chunk-ZDRHCKRK.js.map +1 -0
  19. package/dist/dashboard/ChartWidget.d.ts.map +1 -1
  20. package/dist/dashboard/KpiCard.d.ts.map +1 -1
  21. package/dist/dashboard/SidebarOnboarding.d.ts +16 -11
  22. package/dist/dashboard/SidebarOnboarding.d.ts.map +1 -1
  23. package/dist/dashboard/Sparkline.d.ts +13 -0
  24. package/dist/dashboard/Sparkline.d.ts.map +1 -0
  25. package/dist/dashboard/index.d.ts +1 -0
  26. package/dist/dashboard/index.d.ts.map +1 -1
  27. package/dist/dashboard/index.js +3 -2
  28. package/dist/index.d.ts +2 -2
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +237 -117
  31. package/dist/index.js.map +1 -1
  32. package/dist/layout/AppShell.d.ts +4 -1
  33. package/dist/layout/AppShell.d.ts.map +1 -1
  34. package/dist/layout/AppShellSkeleton.d.ts +23 -0
  35. package/dist/layout/AppShellSkeleton.d.ts.map +1 -0
  36. package/dist/layout/ModulePage.d.ts +5 -1
  37. package/dist/layout/ModulePage.d.ts.map +1 -1
  38. package/dist/layout/Sidebar.d.ts +19 -1
  39. package/dist/layout/Sidebar.d.ts.map +1 -1
  40. package/dist/layout/Topbar.d.ts +4 -1
  41. package/dist/layout/Topbar.d.ts.map +1 -1
  42. package/dist/layout/index.d.ts +2 -0
  43. package/dist/layout/index.d.ts.map +1 -1
  44. package/dist/layout/index.js +2 -1
  45. package/dist/layout/page-trail.d.ts +23 -0
  46. package/dist/layout/page-trail.d.ts.map +1 -0
  47. package/dist/layout/rail-flyout.d.ts +39 -0
  48. package/dist/layout/rail-flyout.d.ts.map +1 -0
  49. package/dist/primitives/bulk-action-bar.d.ts +30 -0
  50. package/dist/primitives/bulk-action-bar.d.ts.map +1 -0
  51. package/dist/primitives/checkbox.d.ts +5 -0
  52. package/dist/primitives/checkbox.d.ts.map +1 -1
  53. package/dist/primitives/data-table.d.ts +11 -1
  54. package/dist/primitives/data-table.d.ts.map +1 -1
  55. package/dist/primitives/dropdown.d.ts.map +1 -1
  56. package/dist/primitives/index.d.ts +5 -0
  57. package/dist/primitives/index.d.ts.map +1 -1
  58. package/dist/primitives/index.js +2 -2
  59. package/dist/primitives/list-chrome.d.ts +20 -0
  60. package/dist/primitives/list-chrome.d.ts.map +1 -0
  61. package/dist/primitives/modal.d.ts.map +1 -1
  62. package/dist/primitives/phone-field.d.ts +19 -0
  63. package/dist/primitives/phone-field.d.ts.map +1 -0
  64. package/dist/primitives/refresh-button.d.ts +18 -0
  65. package/dist/primitives/refresh-button.d.ts.map +1 -0
  66. package/dist/primitives/search-select.d.ts +6 -1
  67. package/dist/primitives/search-select.d.ts.map +1 -1
  68. package/dist/primitives/thumbnail.d.ts +19 -0
  69. package/dist/primitives/thumbnail.d.ts.map +1 -0
  70. package/dist/styles.css +298 -1
  71. package/package.json +2 -2
  72. package/dist/chunk-6V5MGYXH.js.map +0 -1
  73. package/dist/chunk-H63TOSQ7.js.map +0 -1
  74. package/dist/chunk-I6CPKAOD.js.map +0 -1
  75. package/dist/chunk-SEIY2F5F.js.map +0 -1
@@ -1,25 +1,25 @@
1
1
  import { useSaveBarVisible, useCrossModuleBack, useBackHandler, HeaderTabs } from './chunk-VAKWUUVC.js';
2
- import { Card, DataTable, Dropdown, DropdownTrigger, DropdownContent, DropdownItem, SegmentedControl } from './chunk-6V5MGYXH.js';
2
+ import { Dropdown, DropdownTrigger, DropdownContent, DropdownItem, Card, DataTable, SegmentedControl } from './chunk-JGJNRNQW.js';
3
3
  import { cn, Button } from './chunk-OKZ6WQB3.js';
4
- import * as React13 from 'react';
4
+ import * as React14 from 'react';
5
5
  import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
7
  import { cva } from 'class-variance-authority';
8
8
  import * as DialogPrimitive from '@radix-ui/react-dialog';
9
- import { X, Check, ChevronDown, ChevronUp, ArrowLeft, Clock, Plus, Search, RefreshCw, Download, ChevronLeft, ChevronRight, Calendar, Loader2, CheckCircle2, AlertTriangle, XCircle, Info } from 'lucide-react';
9
+ import { X, ChevronDown, ChevronUp, Check, ArrowLeft, Search, ChevronLeft, ChevronRight, MoreHorizontal, ImageIcon, RefreshCw, Clock, Plus, Download, Calendar, Loader2, CheckCircle2, AlertTriangle, XCircle, Info } from 'lucide-react';
10
10
  import * as SelectPrimitive from '@radix-ui/react-select';
11
11
  import { Toaster } from 'sonner';
12
12
  export { toast } from 'sonner';
13
13
  import * as TabsPrimitive from '@radix-ui/react-tabs';
14
14
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
15
15
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
16
+ import { useTranslation, getCountry, unmaskPhone, maskPhone, getCurrentLocale } from '@fayz-ai/core';
16
17
  import { createPortal } from 'react-dom';
17
- import { useTranslation, getCurrentLocale } from '@fayz-ai/core';
18
18
  import * as PopoverPrimitive from '@radix-ui/react-popover';
19
19
 
20
- var Input = React13.forwardRef(
20
+ var Input = React14.forwardRef(
21
21
  ({ className, type, error, description, id, ...props }, ref) => {
22
- const inputId = id ?? React13.useId();
22
+ const inputId = id ?? React14.useId();
23
23
  const descriptionId = description ? `${inputId}-description` : void 0;
24
24
  const errorId = error ? `${inputId}-error` : void 0;
25
25
  return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
@@ -107,7 +107,7 @@ var Modal = DialogPrimitive.Root;
107
107
  var ModalTrigger = DialogPrimitive.Trigger;
108
108
  var ModalClose = DialogPrimitive.Close;
109
109
  var ModalPortal = DialogPrimitive.Portal;
110
- var ModalOverlay = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
110
+ var ModalOverlay = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
111
111
  DialogPrimitive.Overlay,
112
112
  {
113
113
  ref,
@@ -120,7 +120,7 @@ var ModalOverlay = React13.forwardRef(({ className, ...props }, ref) => /* @__PU
120
120
  }
121
121
  ));
122
122
  ModalOverlay.displayName = "ModalOverlay";
123
- var ModalContent = React13.forwardRef(({ className, children, size = "lg", hideClose, noPadding, onPointerDownOutside, onInteractOutside, onCloseAutoFocus, ...props }, ref) => /* @__PURE__ */ jsx(ModalPortal, { children: /* @__PURE__ */ jsx(ModalOverlay, { children: /* @__PURE__ */ jsxs(
123
+ var ModalContent = React14.forwardRef(({ className, children, size = "lg", hideClose, noPadding, onPointerDownOutside, onInteractOutside, onCloseAutoFocus, ...props }, ref) => /* @__PURE__ */ jsx(ModalPortal, { children: /* @__PURE__ */ jsx(ModalOverlay, { children: /* @__PURE__ */ jsxs(
124
124
  DialogPrimitive.Content,
125
125
  {
126
126
  ref,
@@ -143,7 +143,10 @@ var ModalContent = React13.forwardRef(({ className, children, size = "lg", hideC
143
143
  onInteractOutside?.(e);
144
144
  },
145
145
  className: cn(
146
- "fayz-glass-surface fayz-modal-content saas-mdl-ct relative z-50 flex flex-col w-full outline-none",
146
+ // fz-container: a form inside a dialog measures the DIALOG. Without
147
+ // it a two-column field grid in an `sm` modal read the window's width
148
+ // and kept both columns in 380px.
149
+ "fayz-glass-surface fayz-modal-content saas-mdl-ct fz-container relative z-50 flex flex-col w-full outline-none",
147
150
  // Mobile fullscreen
148
151
  "h-full rounded-none border-0",
149
152
  // Desktop centered card
@@ -172,46 +175,14 @@ function ModalBody({ className, ...props }) {
172
175
  function ModalFooter({ className, ...props }) {
173
176
  return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 shrink-0", className), ...props });
174
177
  }
175
- var ModalTitle = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props }));
178
+ var ModalTitle = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props }));
176
179
  ModalTitle.displayName = "ModalTitle";
177
- var ModalDescription = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
180
+ var ModalDescription = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
178
181
  ModalDescription.displayName = "ModalDescription";
179
- var COLOR_CLASSES = {
180
- primary: "border-primary bg-primary text-primary-foreground",
181
- success: "border-success bg-success text-white dark:border-success dark:bg-success",
182
- warning: "border-warning bg-warning text-white",
183
- destructive: "border-destructive bg-destructive text-destructive-foreground"
184
- };
185
- var Checkbox = React13.forwardRef(
186
- ({ checked = false, onChange, disabled, className, color = "primary", id, ...props }, ref) => {
187
- return /* @__PURE__ */ jsx(
188
- "button",
189
- {
190
- ref,
191
- id,
192
- type: "button",
193
- role: "checkbox",
194
- "aria-checked": checked,
195
- disabled,
196
- onClick: () => onChange?.(!checked),
197
- className: cn(
198
- "peer inline-flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-[5px] border-2 transition-all duration-150",
199
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
200
- "disabled:cursor-not-allowed disabled:opacity-50",
201
- checked ? `${COLOR_CLASSES[color]} shadow-sm` : "border-muted-foreground/40 bg-background hover:border-muted-foreground/60",
202
- className
203
- ),
204
- ...props,
205
- children: checked && /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5", strokeWidth: 3 })
206
- }
207
- );
208
- }
209
- );
210
- Checkbox.displayName = "Checkbox";
211
182
  var Select = SelectPrimitive.Root;
212
183
  var SelectGroup = SelectPrimitive.Group;
213
184
  var SelectValue = SelectPrimitive.Value;
214
- var SelectTrigger = React13.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
185
+ var SelectTrigger = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
215
186
  SelectPrimitive.Trigger,
216
187
  {
217
188
  ref,
@@ -227,7 +198,7 @@ var SelectTrigger = React13.forwardRef(({ className, children, ...props }, ref)
227
198
  }
228
199
  ));
229
200
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
230
- var SelectScrollUpButton = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
201
+ var SelectScrollUpButton = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
231
202
  SelectPrimitive.ScrollUpButton,
232
203
  {
233
204
  ref,
@@ -240,7 +211,7 @@ var SelectScrollUpButton = React13.forwardRef(({ className, ...props }, ref) =>
240
211
  }
241
212
  ));
242
213
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
243
- var SelectScrollDownButton = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
214
+ var SelectScrollDownButton = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
244
215
  SelectPrimitive.ScrollDownButton,
245
216
  {
246
217
  ref,
@@ -253,7 +224,7 @@ var SelectScrollDownButton = React13.forwardRef(({ className, ...props }, ref) =
253
224
  }
254
225
  ));
255
226
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
256
- var SelectContent = React13.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
227
+ var SelectContent = React14.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
257
228
  SelectPrimitive.Content,
258
229
  {
259
230
  ref,
@@ -281,7 +252,7 @@ var SelectContent = React13.forwardRef(({ className, children, position = "poppe
281
252
  }
282
253
  ) }));
283
254
  SelectContent.displayName = SelectPrimitive.Content.displayName;
284
- var SelectLabel = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
255
+ var SelectLabel = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
285
256
  SelectPrimitive.Label,
286
257
  {
287
258
  ref,
@@ -290,7 +261,7 @@ var SelectLabel = React13.forwardRef(({ className, ...props }, ref) => /* @__PUR
290
261
  }
291
262
  ));
292
263
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
293
- var SelectItem = React13.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
264
+ var SelectItem = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
294
265
  SelectPrimitive.Item,
295
266
  {
296
267
  ref,
@@ -306,7 +277,7 @@ var SelectItem = React13.forwardRef(({ className, children, ...props }, ref) =>
306
277
  }
307
278
  ));
308
279
  SelectItem.displayName = SelectPrimitive.Item.displayName;
309
- var SelectSeparator = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
280
+ var SelectSeparator = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
310
281
  SelectPrimitive.Separator,
311
282
  {
312
283
  ref,
@@ -344,7 +315,7 @@ function ToastProvider({
344
315
  );
345
316
  }
346
317
  var Tabs = TabsPrimitive.Root;
347
- var TabsList = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
318
+ var TabsList = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
348
319
  TabsPrimitive.List,
349
320
  {
350
321
  ref,
@@ -356,7 +327,7 @@ var TabsList = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__
356
327
  }
357
328
  ));
358
329
  TabsList.displayName = TabsPrimitive.List.displayName;
359
- var TabsTrigger = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
330
+ var TabsTrigger = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
360
331
  TabsPrimitive.Trigger,
361
332
  {
362
333
  ref,
@@ -368,7 +339,7 @@ var TabsTrigger = React13.forwardRef(({ className, ...props }, ref) => /* @__PUR
368
339
  }
369
340
  ));
370
341
  TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
371
- var TabsContent = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
342
+ var TabsContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
372
343
  TabsPrimitive.Content,
373
344
  {
374
345
  ref,
@@ -380,7 +351,7 @@ var TabsContent = React13.forwardRef(({ className, ...props }, ref) => /* @__PUR
380
351
  }
381
352
  ));
382
353
  TabsContent.displayName = TabsPrimitive.Content.displayName;
383
- var Separator2 = React13.forwardRef(
354
+ var Separator2 = React14.forwardRef(
384
355
  ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
385
356
  SeparatorPrimitive.Root,
386
357
  {
@@ -431,7 +402,7 @@ function formatPhone(digits, fallback, countryCode) {
431
402
  const tail = rest.length === 9 ? rest.slice(5) : rest.slice(4);
432
403
  return `+55 (${ddd}) ${head}-${tail}`;
433
404
  }
434
- var PhoneLink = React13.forwardRef(
405
+ var PhoneLink = React14.forwardRef(
435
406
  ({ phone, message, countryCode, raw, className, children, ...props }, ref) => {
436
407
  const { e164, display } = normalizePhone(phone, countryCode);
437
408
  const label = children ?? (raw ? phone ?? "" : display);
@@ -480,7 +451,7 @@ function Breadcrumb({ parent, current, onBack }) {
480
451
  var TooltipProvider = TooltipPrimitive.Provider;
481
452
  var Tooltip = TooltipPrimitive.Root;
482
453
  var TooltipTrigger = TooltipPrimitive.Trigger;
483
- var TooltipContent = React13.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
454
+ var TooltipContent = React14.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
484
455
  TooltipPrimitive.Content,
485
456
  {
486
457
  ref,
@@ -493,6 +464,263 @@ var TooltipContent = React13.forwardRef(({ className, sideOffset = 4, ...props }
493
464
  }
494
465
  ));
495
466
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
467
+ function SearchField({ value, onChange, placeholder, ...rest }) {
468
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
469
+ /* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }),
470
+ /* @__PURE__ */ jsx(
471
+ "input",
472
+ {
473
+ type: "text",
474
+ value,
475
+ onChange: (event) => onChange(event.target.value),
476
+ placeholder,
477
+ "data-testid": rest["data-testid"],
478
+ className: "w-full bg-transparent py-1.5 pl-8 pr-3 text-sm placeholder:text-muted-foreground focus:outline-none"
479
+ }
480
+ )
481
+ ] });
482
+ }
483
+ function ChevronPager({ page, pageSize, total, onPageChange, noun }) {
484
+ const pages = Math.max(1, Math.ceil(total / pageSize));
485
+ const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
486
+ const to = Math.min(page * pageSize, total);
487
+ const button = "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";
488
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 border-t border-border px-3 py-2", children: [
489
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
490
+ from.toLocaleString(),
491
+ "\u2013",
492
+ to.toLocaleString(),
493
+ " de ",
494
+ total.toLocaleString(),
495
+ noun ? ` ${noun}` : ""
496
+ ] }),
497
+ pages > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
498
+ /* @__PURE__ */ jsx(
499
+ "button",
500
+ {
501
+ type: "button",
502
+ "aria-label": "P\xE1gina anterior",
503
+ className: button,
504
+ disabled: page <= 1,
505
+ onClick: () => onPageChange(page - 1),
506
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsxs("span", { className: "px-1 text-xs tabular-nums text-muted-foreground", children: [
510
+ page.toLocaleString(),
511
+ " / ",
512
+ pages.toLocaleString()
513
+ ] }),
514
+ /* @__PURE__ */ jsx(
515
+ "button",
516
+ {
517
+ type: "button",
518
+ "aria-label": "Pr\xF3xima p\xE1gina",
519
+ className: button,
520
+ disabled: page >= pages,
521
+ onClick: () => onPageChange(page + 1),
522
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
523
+ }
524
+ )
525
+ ] })
526
+ ] });
527
+ }
528
+ function BulkActionBar({
529
+ count,
530
+ total,
531
+ onSelectAll,
532
+ onClear,
533
+ actions = [],
534
+ className
535
+ }) {
536
+ const t = useTranslation();
537
+ if (count === 0) return null;
538
+ const inline = actions.filter((a) => !a.overflow);
539
+ const overflow = actions.filter((a) => a.overflow);
540
+ return /* @__PURE__ */ jsxs(
541
+ "div",
542
+ {
543
+ className: cn(
544
+ "flex flex-wrap items-center justify-between gap-2 rounded-lg border border-border bg-muted/30 px-3 py-2",
545
+ className
546
+ ),
547
+ role: "region",
548
+ "aria-label": t("crud.list.bulkActions"),
549
+ children: [
550
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 text-sm", children: [
551
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: count === 1 ? t("crud.list.selectedOne") : t("crud.list.selectedMany", { count: count.toLocaleString() }) }),
552
+ onSelectAll && count < total && /* @__PURE__ */ jsx(
553
+ "button",
554
+ {
555
+ type: "button",
556
+ onClick: onSelectAll,
557
+ className: "text-muted-foreground underline-offset-2 transition-colors hover:text-foreground hover:underline",
558
+ children: t("crud.list.selectAllCount", { total: total.toLocaleString() })
559
+ }
560
+ ),
561
+ /* @__PURE__ */ jsx(
562
+ "button",
563
+ {
564
+ type: "button",
565
+ onClick: onClear,
566
+ className: "text-muted-foreground underline-offset-2 transition-colors hover:text-foreground hover:underline",
567
+ children: t("crud.list.deselectAll")
568
+ }
569
+ )
570
+ ] }),
571
+ (inline.length > 0 || overflow.length > 0) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
572
+ inline.map((action) => /* @__PURE__ */ jsxs(
573
+ Button,
574
+ {
575
+ variant: "outline",
576
+ size: "sm",
577
+ disabled: action.disabled,
578
+ onClick: () => void action.onSelect(),
579
+ className: action.destructive ? "text-destructive hover:text-destructive" : void 0,
580
+ children: [
581
+ action.icon && /* @__PURE__ */ jsx(action.icon, { className: "mr-1.5 h-3.5 w-3.5" }),
582
+ action.label
583
+ ]
584
+ },
585
+ action.id
586
+ )),
587
+ overflow.length > 0 && /* @__PURE__ */ jsxs(Dropdown, { children: [
588
+ /* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", "aria-label": t("crud.list.moreActions"), children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-3.5 w-3.5" }) }) }),
589
+ /* @__PURE__ */ jsx(DropdownContent, { align: "end", children: overflow.map((action) => /* @__PURE__ */ jsxs(
590
+ DropdownItem,
591
+ {
592
+ disabled: action.disabled,
593
+ onClick: () => void action.onSelect(),
594
+ className: action.destructive ? "text-destructive focus:text-destructive" : void 0,
595
+ children: [
596
+ action.icon && /* @__PURE__ */ jsx(action.icon, { className: "mr-2 h-3.5 w-3.5 shrink-0" }),
597
+ action.label
598
+ ]
599
+ },
600
+ action.id
601
+ )) })
602
+ ] })
603
+ ] })
604
+ ]
605
+ }
606
+ );
607
+ }
608
+ BulkActionBar.displayName = "BulkActionBar";
609
+ var SIZE_CLASSES = {
610
+ sm: "h-8 w-8 rounded",
611
+ md: "h-9 w-9 rounded",
612
+ lg: "h-12 w-12 rounded-md"
613
+ };
614
+ var ICON_CLASSES = {
615
+ sm: "h-3.5 w-3.5",
616
+ md: "h-4 w-4",
617
+ lg: "h-5 w-5"
618
+ };
619
+ function Thumbnail({ src, alt = "", size = "md", icon: Icon2 = ImageIcon, className }) {
620
+ const [failed, setFailed] = React14.useState(false);
621
+ React14.useEffect(() => {
622
+ setFailed(false);
623
+ }, [src]);
624
+ const base = cn("shrink-0 overflow-hidden", SIZE_CLASSES[size], className);
625
+ if (!src || failed) {
626
+ return /* @__PURE__ */ jsx(
627
+ "div",
628
+ {
629
+ className: cn(base, "flex items-center justify-center border border-border/60 bg-muted/50 text-muted-foreground/60"),
630
+ "aria-hidden": true,
631
+ children: /* @__PURE__ */ jsx(Icon2, { className: ICON_CLASSES[size], strokeWidth: 1.75 })
632
+ }
633
+ );
634
+ }
635
+ return /* @__PURE__ */ jsx(
636
+ "img",
637
+ {
638
+ src,
639
+ alt,
640
+ loading: "lazy",
641
+ onError: () => setFailed(true),
642
+ className: cn(base, "border border-border/60 object-cover")
643
+ }
644
+ );
645
+ }
646
+ Thumbnail.displayName = "Thumbnail";
647
+ function RefreshButton({ onRefresh, fromCache, label, labelCached, className, ...rest }) {
648
+ const [phase, setPhase] = React14.useState("idle");
649
+ const alive = React14.useRef(true);
650
+ React14.useEffect(() => () => {
651
+ alive.current = false;
652
+ }, []);
653
+ const title = fromCache ? labelCached ?? label : label;
654
+ async function run() {
655
+ if (phase === "busy") return;
656
+ setPhase("busy");
657
+ try {
658
+ await onRefresh();
659
+ } catch {
660
+ }
661
+ if (!alive.current) return;
662
+ setPhase("done");
663
+ setTimeout(() => {
664
+ if (alive.current) setPhase((p) => p === "done" ? "idle" : p);
665
+ }, 1400);
666
+ }
667
+ return /* @__PURE__ */ jsx(
668
+ "button",
669
+ {
670
+ type: "button",
671
+ title,
672
+ "aria-label": title,
673
+ onClick: () => {
674
+ void run();
675
+ },
676
+ className: cn(
677
+ "inline-flex items-center justify-center transition",
678
+ fromCache && phase !== "done" && "text-amber-600 hover:text-amber-700 dark:text-amber-500 dark:hover:text-amber-400",
679
+ phase === "done" && "text-emerald-600 dark:text-emerald-500",
680
+ className
681
+ ),
682
+ ...rest,
683
+ children: phase === "done" ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(RefreshCw, { className: cn("h-4 w-4", phase === "busy" && "animate-spin") })
684
+ }
685
+ );
686
+ }
687
+ RefreshButton.displayName = "RefreshButton";
688
+ function PhoneField({
689
+ value,
690
+ onChange,
691
+ country,
692
+ placeholder,
693
+ disabled,
694
+ autoFocus,
695
+ className,
696
+ ...rest
697
+ }) {
698
+ const mask = getCountry(country).mask;
699
+ return /* @__PURE__ */ jsx(
700
+ "input",
701
+ {
702
+ type: "tel",
703
+ inputMode: "tel",
704
+ autoComplete: "tel",
705
+ value: maskPhone(value, mask),
706
+ onChange: (event) => onChange(unmaskPhone(event.target.value)),
707
+ placeholder: placeholder ?? mask.replace(/#/gu, "0"),
708
+ disabled,
709
+ autoFocus,
710
+ "aria-label": rest["aria-label"],
711
+ "data-testid": rest["data-testid"],
712
+ className: cn(
713
+ "w-full rounded-md border bg-background px-2.5 py-1.5 text-sm outline-none focus:border-primary",
714
+ className
715
+ )
716
+ }
717
+ );
718
+ }
719
+ function formatPhone2(value, country) {
720
+ const digits = unmaskPhone(String(value ?? ""));
721
+ if (!digits) return "";
722
+ return maskPhone(digits, getCountry(country).mask) || digits;
723
+ }
496
724
  function StatTiles({ tiles, loading, className }) {
497
725
  if (tiles.length === 0) return null;
498
726
  return /* @__PURE__ */ jsx("div", { className: cn("grid gap-4 sm:grid-cols-2 lg:grid-cols-4", className), children: tiles.map((tile) => {
@@ -517,7 +745,7 @@ var THUMB = {
517
745
  sm: "h-3 w-3 data-[on=true]:translate-x-3",
518
746
  md: "h-4 w-4 data-[on=true]:translate-x-4"
519
747
  };
520
- var Switch = React13.forwardRef(function Switch2({ checked, onCheckedChange, size = "sm", label, className, disabled, ...rest }, ref) {
748
+ var Switch = React14.forwardRef(function Switch2({ checked, onCheckedChange, size = "sm", label, className, disabled, ...rest }, ref) {
521
749
  const control = /* @__PURE__ */ jsx(
522
750
  "button",
523
751
  {
@@ -568,8 +796,8 @@ var Switch = React13.forwardRef(function Switch2({ checked, onCheckedChange, siz
568
796
  }
569
797
  );
570
798
  });
571
- var Hint = React13.forwardRef(function Hint2({ label, children, side = "top", delayDuration = 0, ...rest }, ref) {
572
- if (!label) return React13.cloneElement(children, { ...rest, ref });
799
+ var Hint = React14.forwardRef(function Hint2({ label, children, side = "top", delayDuration = 0, ...rest }, ref) {
800
+ if (!label) return React14.cloneElement(children, { ...rest, ref });
573
801
  return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, { delayDuration, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
574
802
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, ...rest, ref, children }),
575
803
  /* @__PURE__ */ jsx(TooltipContent, { side, className: "px-2 py-1 text-xs font-medium", children: label })
@@ -1034,6 +1262,8 @@ function SearchSelect({
1034
1262
  required,
1035
1263
  debounce = 250,
1036
1264
  minChars = 1,
1265
+ noResultsLabel,
1266
+ searchingLabel = "Searching...",
1037
1267
  allowCreate,
1038
1268
  createLabel = "Add",
1039
1269
  onCreate,
@@ -1042,16 +1272,16 @@ function SearchSelect({
1042
1272
  className,
1043
1273
  disabled
1044
1274
  }) {
1045
- const [open, setOpen] = React13.useState(false);
1046
- const [query, setQuery] = React13.useState("");
1047
- const [results, setResults] = React13.useState([]);
1048
- const [loading, setLoading] = React13.useState(false);
1049
- const [creating, setCreating] = React13.useState(false);
1050
- const [selectedLabel, setSelectedLabel] = React13.useState(displayValue ?? "");
1051
- const containerRef = React13.useRef(null);
1052
- const inputRef = React13.useRef(null);
1053
- const timerRef = React13.useRef();
1054
- React13.useEffect(() => {
1275
+ const [open, setOpen] = React14.useState(false);
1276
+ const [query, setQuery] = React14.useState("");
1277
+ const [results, setResults] = React14.useState([]);
1278
+ const [loading, setLoading] = React14.useState(false);
1279
+ const [creating, setCreating] = React14.useState(false);
1280
+ const [selectedLabel, setSelectedLabel] = React14.useState(displayValue ?? "");
1281
+ const containerRef = React14.useRef(null);
1282
+ const inputRef = React14.useRef(null);
1283
+ const timerRef = React14.useRef();
1284
+ React14.useEffect(() => {
1055
1285
  function handler(e) {
1056
1286
  if (containerRef.current && !containerRef.current.contains(e.target)) {
1057
1287
  setOpen(false);
@@ -1060,10 +1290,10 @@ function SearchSelect({
1060
1290
  document.addEventListener("mousedown", handler);
1061
1291
  return () => document.removeEventListener("mousedown", handler);
1062
1292
  }, []);
1063
- React13.useEffect(() => {
1293
+ React14.useEffect(() => {
1064
1294
  if (displayValue !== void 0) setSelectedLabel(displayValue);
1065
1295
  }, [displayValue]);
1066
- React13.useEffect(() => {
1296
+ React14.useEffect(() => {
1067
1297
  if (open && loadOnOpen && query.length === 0 && results.length === 0 && !loading) {
1068
1298
  setLoading(true);
1069
1299
  Promise.resolve(onSearch("")).then(setResults).catch(() => setResults([])).finally(() => setLoading(false));
@@ -1121,7 +1351,7 @@ function SearchSelect({
1121
1351
  setResults([]);
1122
1352
  setTimeout(() => inputRef.current?.focus(), 0);
1123
1353
  }
1124
- const groups = React13.useMemo(() => {
1354
+ const groups = React14.useMemo(() => {
1125
1355
  const map = /* @__PURE__ */ new Map();
1126
1356
  for (const opt of results) {
1127
1357
  const group = opt.group ?? "";
@@ -1180,9 +1410,10 @@ function SearchSelect({
1180
1410
  ),
1181
1411
  showDropdown && /* @__PURE__ */ jsx("div", { className: "fayz-glass-surface absolute top-full left-0 right-0 z-50 mt-1 rounded-lg border bg-popover shadow-lg overflow-hidden", children: loading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-6 text-xs text-muted-foreground", children: [
1182
1412
  /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
1183
- " Searching..."
1413
+ " ",
1414
+ searchingLabel
1184
1415
  ] }) : results.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "px-4 py-4 text-center", children: [
1185
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: query ? `No results for "${query}"` : "No results" }),
1416
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: noResultsLabel ?? (query ? `No results for "${query}"` : "No results") }),
1186
1417
  allowCreate && onCreate && /* @__PURE__ */ jsxs(
1187
1418
  "button",
1188
1419
  {
@@ -1198,7 +1429,7 @@ function SearchSelect({
1198
1429
  }
1199
1430
  )
1200
1431
  ] }) : /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-auto py-1", children: [
1201
- [...groups.entries()].map(([group, options]) => /* @__PURE__ */ jsxs(React13.Fragment, { children: [
1432
+ [...groups.entries()].map(([group, options]) => /* @__PURE__ */ jsxs(React14.Fragment, { children: [
1202
1433
  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 }),
1203
1434
  options.map((opt) => /* @__PURE__ */ jsx(
1204
1435
  "button",
@@ -1249,9 +1480,9 @@ function CurrencyInput({
1249
1480
  className,
1250
1481
  disabled
1251
1482
  }) {
1252
- const inputRef = React13.useRef(null);
1253
- const [focused, setFocused] = React13.useState(false);
1254
- const format = React13.useCallback((v) => {
1483
+ const inputRef = React14.useRef(null);
1484
+ const [focused, setFocused] = React14.useState(false);
1485
+ const format = React14.useCallback((v) => {
1255
1486
  return new Intl.NumberFormat(locale, {
1256
1487
  minimumFractionDigits: 2,
1257
1488
  maximumFractionDigits: 2
@@ -1360,7 +1591,7 @@ function ConfirmDialog({
1360
1591
  }) {
1361
1592
  const config = VARIANT_CONFIG[variant];
1362
1593
  const Icon2 = config.icon;
1363
- React13.useEffect(() => {
1594
+ React14.useEffect(() => {
1364
1595
  if (!open) return;
1365
1596
  function handleKey(e) {
1366
1597
  if (e.key === "Escape") onCancel();
@@ -1407,7 +1638,7 @@ function ConfirmDialog({
1407
1638
  }
1408
1639
  var Popover = PopoverPrimitive.Root;
1409
1640
  var PopoverTrigger = PopoverPrimitive.Trigger;
1410
- var PopoverContent = React13.forwardRef(({ className, align = "start", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1641
+ var PopoverContent = React14.forwardRef(({ className, align = "start", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1411
1642
  PopoverPrimitive.Content,
1412
1643
  {
1413
1644
  ref,
@@ -1468,7 +1699,7 @@ function renderInline(text, keyPrefix) {
1468
1699
  if (part.startsWith("`") && part.endsWith("`") && part.length > 2) {
1469
1700
  return /* @__PURE__ */ jsx("code", { className: "rounded bg-muted px-1 py-0.5 font-mono text-[0.85em]", children: part.slice(1, -1) }, key);
1470
1701
  }
1471
- return part === "" ? null : /* @__PURE__ */ jsx(React13.Fragment, { children: part }, key);
1702
+ return part === "" ? null : /* @__PURE__ */ jsx(React14.Fragment, { children: part }, key);
1472
1703
  });
1473
1704
  }
1474
1705
  function parseBlocks(source) {
@@ -1552,7 +1783,7 @@ function renderMarkdown(source) {
1552
1783
  case "ol":
1553
1784
  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);
1554
1785
  case "p":
1555
- return /* @__PURE__ */ jsx("p", { children: block.lines.map((l, li) => /* @__PURE__ */ jsxs(React13.Fragment, { children: [
1786
+ return /* @__PURE__ */ jsx("p", { children: block.lines.map((l, li) => /* @__PURE__ */ jsxs(React14.Fragment, { children: [
1556
1787
  li > 0 && /* @__PURE__ */ jsx("br", {}),
1557
1788
  renderInline(l, `${key}-${li}`)
1558
1789
  ] }, `${key}-${li}`)) }, key);
@@ -1573,7 +1804,7 @@ function MarkdownEditor({
1573
1804
  renderPreview,
1574
1805
  className
1575
1806
  }) {
1576
- const [mode, setMode] = React13.useState(
1807
+ const [mode, setMode] = React14.useState(
1577
1808
  defaultMode === "preview" && value.trim() === "" ? "edit" : defaultMode
1578
1809
  );
1579
1810
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
@@ -1816,6 +2047,6 @@ function SearchCombobox({
1816
2047
  ] });
1817
2048
  }
1818
2049
 
1819
- export { Badge, Breadcrumb, Checkbox, ConfirmDialog, CurrencyInput, DatePicker, FilterChip, Hint, Input, ListView, Markdown, MarkdownEditor, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, PhoneLink, Popover, PopoverContent, PopoverTrigger, SearchCombobox, SearchSelect, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, StatTiles, Switch, Tabs, TabsContent, TabsList, TabsTrigger, TimePicker, ToastProvider, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, normalizePhone, renderMarkdown };
1820
- //# sourceMappingURL=chunk-SEIY2F5F.js.map
1821
- //# sourceMappingURL=chunk-SEIY2F5F.js.map
2050
+ export { Badge, Breadcrumb, BulkActionBar, ChevronPager, ConfirmDialog, CurrencyInput, DatePicker, FilterChip, Hint, Input, ListView, Markdown, MarkdownEditor, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, PhoneField, PhoneLink, Popover, PopoverContent, PopoverTrigger, RefreshButton, SearchCombobox, SearchField, SearchSelect, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, StatTiles, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Thumbnail, TimePicker, ToastProvider, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, formatPhone2 as formatPhone, normalizePhone, renderMarkdown };
2051
+ //# sourceMappingURL=chunk-7BHG3XGJ.js.map
2052
+ //# sourceMappingURL=chunk-7BHG3XGJ.js.map