@caratlogic/design-system 0.1.25 → 0.1.27

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 (34) hide show
  1. package/dist/components/molecules/CompanyCard/CompanyCard.d.ts +9 -0
  2. package/dist/components/molecules/CompanyCard/CompanyCard.d.ts.map +1 -0
  3. package/dist/components/molecules/CompanyCard/CompanyCard.parts.d.ts +4 -0
  4. package/dist/components/molecules/CompanyCard/CompanyCard.parts.d.ts.map +1 -0
  5. package/dist/components/molecules/CompanyCard/CompanyCard.types.d.ts +32 -0
  6. package/dist/components/molecules/CompanyCard/CompanyCard.types.d.ts.map +1 -0
  7. package/dist/components/molecules/CompanyCard/CompanyCard.utils.d.ts +4 -0
  8. package/dist/components/molecules/CompanyCard/CompanyCard.utils.d.ts.map +1 -0
  9. package/dist/components/molecules/CompanyCard/index.d.ts +3 -0
  10. package/dist/components/molecules/CompanyCard/index.d.ts.map +1 -0
  11. package/dist/components/molecules/DateInput/DateInput.d.ts +1 -1
  12. package/dist/components/molecules/DateInput/DateInput.d.ts.map +1 -1
  13. package/dist/components/molecules/DateInput/DateInput.types.d.ts +7 -0
  14. package/dist/components/molecules/DateInput/DateInput.types.d.ts.map +1 -1
  15. package/dist/components/molecules/FilterSelect/FilterMultiSelect.d.ts +8 -0
  16. package/dist/components/molecules/FilterSelect/FilterMultiSelect.d.ts.map +1 -1
  17. package/dist/components/molecules/InvoiceComboBox/InvoiceComboBox.d.ts.map +1 -1
  18. package/dist/components/molecules/InvoiceComboBox/InvoiceComboBox.utils.d.ts +4 -0
  19. package/dist/components/molecules/InvoiceComboBox/InvoiceComboBox.utils.d.ts.map +1 -1
  20. package/dist/components/molecules/SegmentedControl/SegmentedControl.d.ts +7 -5
  21. package/dist/components/molecules/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  22. package/dist/components/molecules/SegmentedControl/SegmentedControl.types.d.ts +11 -4
  23. package/dist/components/molecules/SegmentedControl/SegmentedControl.types.d.ts.map +1 -1
  24. package/dist/components/molecules/SegmentedControl/SegmentedControl.utils.d.ts +9 -0
  25. package/dist/components/molecules/SegmentedControl/SegmentedControl.utils.d.ts.map +1 -0
  26. package/dist/components/molecules/SegmentedControl/index.d.ts +1 -1
  27. package/dist/components/molecules/SegmentedControl/index.d.ts.map +1 -1
  28. package/dist/index.cjs.js +141 -59
  29. package/dist/index.cjs.js.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.esm.js +141 -60
  33. package/dist/index.esm.js.map +1 -1
  34. package/package.json +1 -1
package/dist/index.cjs.js CHANGED
@@ -2698,12 +2698,12 @@ const createLucideIcon = (iconName, iconNode) => {
2698
2698
  */
2699
2699
 
2700
2700
 
2701
- const __iconNode$1o = [
2701
+ const __iconNode$1p = [
2702
2702
  ["path", { d: "M15 12H3", key: "6jk70r" }],
2703
2703
  ["path", { d: "M17 18H3", key: "1amg6g" }],
2704
2704
  ["path", { d: "M21 6H3", key: "1jwq7v" }]
2705
2705
  ];
2706
- const AlignLeft = createLucideIcon("align-left", __iconNode$1o);
2706
+ const AlignLeft = createLucideIcon("align-left", __iconNode$1p);
2707
2707
 
2708
2708
  /**
2709
2709
  * @license lucide-react v0.539.0 - ISC
@@ -2713,12 +2713,12 @@ const AlignLeft = createLucideIcon("align-left", __iconNode$1o);
2713
2713
  */
2714
2714
 
2715
2715
 
2716
- const __iconNode$1n = [
2716
+ const __iconNode$1o = [
2717
2717
  ["rect", { width: "20", height: "5", x: "2", y: "3", rx: "1", key: "1wp1u1" }],
2718
2718
  ["path", { d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8", key: "1s80jp" }],
2719
2719
  ["path", { d: "M10 12h4", key: "a56b0p" }]
2720
2720
  ];
2721
- const Archive = createLucideIcon("archive", __iconNode$1n);
2721
+ const Archive = createLucideIcon("archive", __iconNode$1o);
2722
2722
 
2723
2723
  /**
2724
2724
  * @license lucide-react v0.539.0 - ISC
@@ -2728,11 +2728,11 @@ const Archive = createLucideIcon("archive", __iconNode$1n);
2728
2728
  */
2729
2729
 
2730
2730
 
2731
- const __iconNode$1m = [
2731
+ const __iconNode$1n = [
2732
2732
  ["path", { d: "m12 19-7-7 7-7", key: "1l729n" }],
2733
2733
  ["path", { d: "M19 12H5", key: "x3x0zl" }]
2734
2734
  ];
2735
- const ArrowLeft = createLucideIcon("arrow-left", __iconNode$1m);
2735
+ const ArrowLeft = createLucideIcon("arrow-left", __iconNode$1n);
2736
2736
 
2737
2737
  /**
2738
2738
  * @license lucide-react v0.539.0 - ISC
@@ -2742,11 +2742,11 @@ const ArrowLeft = createLucideIcon("arrow-left", __iconNode$1m);
2742
2742
  */
2743
2743
 
2744
2744
 
2745
- const __iconNode$1l = [
2745
+ const __iconNode$1m = [
2746
2746
  ["path", { d: "M5 12h14", key: "1ays0h" }],
2747
2747
  ["path", { d: "m12 5 7 7-7 7", key: "xquz4c" }]
2748
2748
  ];
2749
- const ArrowRight = createLucideIcon("arrow-right", __iconNode$1l);
2749
+ const ArrowRight = createLucideIcon("arrow-right", __iconNode$1m);
2750
2750
 
2751
2751
  /**
2752
2752
  * @license lucide-react v0.539.0 - ISC
@@ -2756,11 +2756,11 @@ const ArrowRight = createLucideIcon("arrow-right", __iconNode$1l);
2756
2756
  */
2757
2757
 
2758
2758
 
2759
- const __iconNode$1k = [
2759
+ const __iconNode$1l = [
2760
2760
  ["path", { d: "M4.929 4.929 19.07 19.071", key: "196cmz" }],
2761
2761
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]
2762
2762
  ];
2763
- const Ban = createLucideIcon("ban", __iconNode$1k);
2763
+ const Ban = createLucideIcon("ban", __iconNode$1l);
2764
2764
 
2765
2765
  /**
2766
2766
  * @license lucide-react v0.539.0 - ISC
@@ -2770,7 +2770,7 @@ const Ban = createLucideIcon("ban", __iconNode$1k);
2770
2770
  */
2771
2771
 
2772
2772
 
2773
- const __iconNode$1j = [
2773
+ const __iconNode$1k = [
2774
2774
  ["path", { d: "M10.268 21a2 2 0 0 0 3.464 0", key: "vwvbt9" }],
2775
2775
  [
2776
2776
  "path",
@@ -2781,7 +2781,7 @@ const __iconNode$1j = [
2781
2781
  ],
2782
2782
  ["circle", { cx: "18", cy: "8", r: "3", key: "1g0gzu" }]
2783
2783
  ];
2784
- const BellDot = createLucideIcon("bell-dot", __iconNode$1j);
2784
+ const BellDot = createLucideIcon("bell-dot", __iconNode$1k);
2785
2785
 
2786
2786
  /**
2787
2787
  * @license lucide-react v0.539.0 - ISC
@@ -2791,7 +2791,7 @@ const BellDot = createLucideIcon("bell-dot", __iconNode$1j);
2791
2791
  */
2792
2792
 
2793
2793
 
2794
- const __iconNode$1i = [
2794
+ const __iconNode$1j = [
2795
2795
  ["path", { d: "M10.268 21a2 2 0 0 0 3.464 0", key: "vwvbt9" }],
2796
2796
  ["path", { d: "M22 8c0-2.3-.8-4.3-2-6", key: "5bb3ad" }],
2797
2797
  [
@@ -2803,7 +2803,7 @@ const __iconNode$1i = [
2803
2803
  ],
2804
2804
  ["path", { d: "M4 2C2.8 3.7 2 5.7 2 8", key: "tap9e0" }]
2805
2805
  ];
2806
- const BellRing = createLucideIcon("bell-ring", __iconNode$1i);
2806
+ const BellRing = createLucideIcon("bell-ring", __iconNode$1j);
2807
2807
 
2808
2808
  /**
2809
2809
  * @license lucide-react v0.539.0 - ISC
@@ -2813,7 +2813,7 @@ const BellRing = createLucideIcon("bell-ring", __iconNode$1i);
2813
2813
  */
2814
2814
 
2815
2815
 
2816
- const __iconNode$1h = [
2816
+ const __iconNode$1i = [
2817
2817
  ["path", { d: "M10.268 21a2 2 0 0 0 3.464 0", key: "vwvbt9" }],
2818
2818
  [
2819
2819
  "path",
@@ -2823,7 +2823,7 @@ const __iconNode$1h = [
2823
2823
  }
2824
2824
  ]
2825
2825
  ];
2826
- const Bell = createLucideIcon("bell", __iconNode$1h);
2826
+ const Bell = createLucideIcon("bell", __iconNode$1i);
2827
2827
 
2828
2828
  /**
2829
2829
  * @license lucide-react v0.539.0 - ISC
@@ -2833,13 +2833,32 @@ const Bell = createLucideIcon("bell", __iconNode$1h);
2833
2833
  */
2834
2834
 
2835
2835
 
2836
- const __iconNode$1g = [
2836
+ const __iconNode$1h = [
2837
2837
  [
2838
2838
  "path",
2839
2839
  { d: "M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8", key: "mg9rjx" }
2840
2840
  ]
2841
2841
  ];
2842
- const Bold$1 = createLucideIcon("bold", __iconNode$1g);
2842
+ const Bold$1 = createLucideIcon("bold", __iconNode$1h);
2843
+
2844
+ /**
2845
+ * @license lucide-react v0.539.0 - ISC
2846
+ *
2847
+ * This source code is licensed under the ISC license.
2848
+ * See the LICENSE file in the root directory of this source tree.
2849
+ */
2850
+
2851
+
2852
+ const __iconNode$1g = [
2853
+ ["path", { d: "M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z", key: "1b4qmf" }],
2854
+ ["path", { d: "M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2", key: "i71pzd" }],
2855
+ ["path", { d: "M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2", key: "10jefs" }],
2856
+ ["path", { d: "M10 6h4", key: "1itunk" }],
2857
+ ["path", { d: "M10 10h4", key: "tcdvrf" }],
2858
+ ["path", { d: "M10 14h4", key: "kelpxr" }],
2859
+ ["path", { d: "M10 18h4", key: "1ulq68" }]
2860
+ ];
2861
+ const Building2 = createLucideIcon("building-2", __iconNode$1g);
2843
2862
 
2844
2863
  /**
2845
2864
  * @license lucide-react v0.539.0 - ISC
@@ -15280,7 +15299,7 @@ const isFilterActive = (value, resetValue) => !!value && value !== resetValue;
15280
15299
  * `FilterSelect` trigger look (filter icon + count badge when active).
15281
15300
  * Selecting items keeps the popover open; the trigger shows the count.
15282
15301
  */
15283
- const FilterMultiSelect = ({ label, value, onChange, options, triggerClassName, contentClassName, }) => {
15302
+ const FilterMultiSelect = ({ label, value, onChange, options, triggerClassName, contentClassName, listClassName, modal = false, }) => {
15284
15303
  const active = value.length > 0;
15285
15304
  const toggle = (optValue) => {
15286
15305
  if (value.includes(optValue)) {
@@ -15290,7 +15309,7 @@ const FilterMultiSelect = ({ label, value, onChange, options, triggerClassName,
15290
15309
  onChange([...value, optValue]);
15291
15310
  }
15292
15311
  };
15293
- return (jsxRuntime.jsxs(Popover, { children: [jsxRuntime.jsx(PopoverTrigger, { className: cn(TRIGGER_BASE, 'inline-flex items-center justify-between', active && TRIGGER_ACTIVE, triggerClassName), children: jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(Funnel, { className: cn('h-4 w-4 shrink-0', active ? 'text-primary' : 'text-muted-foreground'), "aria-hidden": "true" }), label, active && (jsxRuntime.jsx("span", { className: "ml-1 inline-flex h-4 min-w-4 items-center justify-center rounded bg-primary/10 px-1 text-[10px] font-semibold leading-none text-primary", children: value.length }))] }) }), jsxRuntime.jsx(PopoverContent, { align: "start", className: cn('w-56 p-1', contentClassName), children: jsxRuntime.jsx("div", { className: "max-h-[18rem] overflow-y-auto", children: options.map((opt) => {
15312
+ return (jsxRuntime.jsxs(Popover, { modal: modal, children: [jsxRuntime.jsx(PopoverTrigger, { className: cn(TRIGGER_BASE, 'inline-flex items-center justify-between', active && TRIGGER_ACTIVE, triggerClassName), children: jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(Funnel, { className: cn('h-4 w-4 shrink-0', active ? 'text-primary' : 'text-muted-foreground'), "aria-hidden": "true" }), label, active && (jsxRuntime.jsx("span", { className: "ml-1 inline-flex h-4 min-w-4 items-center justify-center rounded bg-primary/10 px-1 text-[10px] font-semibold leading-none text-primary", children: value.length }))] }) }), jsxRuntime.jsx(PopoverContent, { align: "start", className: cn('w-56 p-1', contentClassName), children: jsxRuntime.jsx("div", { className: cn('max-h-[18rem] overflow-y-auto', listClassName), children: options.map((opt) => {
15294
15313
  const checked = value.includes(opt.value);
15295
15314
  return (jsxRuntime.jsxs("button", { type: "button", onClick: () => toggle(opt.value), className: "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-foreground hover:bg-muted/60", children: [jsxRuntime.jsx(Checkbox, { checked: checked, onCheckedChange: () => toggle(opt.value),
15296
15315
  // Stop the inner checkbox click from double-toggling via the button.
@@ -15396,6 +15415,48 @@ const CollapsibleCard = ({ title, subtitle, icon, headerActions, defaultOpen = t
15396
15415
  return (jsxRuntime.jsxs("section", { className: cn('overflow-hidden rounded-xl border border-border bg-card shadow-card', className), children: [jsxRuntime.jsxs("header", { className: cn('flex items-center gap-3 bg-muted/30 px-4 py-3', isOpen && 'border-b border-border', headerClassName), children: [icon && jsxRuntime.jsx(SectionIcon, { children: icon }), jsxRuntime.jsxs("div", { className: "flex min-w-0 shrink flex-col gap-0.5", children: [jsxRuntime.jsx("h3", { className: "truncate text-sm font-medium text-foreground", children: title }), subtitle && (jsxRuntime.jsx("div", { className: "truncate text-xs text-muted-foreground", children: subtitle }))] }), headerActions && (jsxRuntime.jsx("div", { className: "ml-auto flex min-w-0 flex-1 items-center justify-end gap-2", children: headerActions })), !headerActions && jsxRuntime.jsx("div", { className: "flex-1" }), !nonCollapsible && (jsxRuntime.jsx("button", { type: "button", onClick: toggle, "aria-expanded": isOpen, "aria-label": isOpen ? 'Collapse section' : 'Expand section', className: "inline-flex h-7 w-7 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30", children: jsxRuntime.jsx(ChevronDown, { className: cn('h-4 w-4 transition-transform duration-200', isOpen && 'rotate-180'), "aria-hidden": "true" }) }))] }), isOpen && jsxRuntime.jsx("div", { className: cn('p-4', bodyClassName), children: children })] }));
15397
15416
  };
15398
15417
 
15418
+ const HEADER_TONE_CLASSES = {
15419
+ neutral: 'bg-[var(--section-header)]',
15420
+ gem: 'bg-primary/5 dark:bg-[#173626]',
15421
+ diamond: 'bg-blue-50 dark:bg-[#0284C7]/20',
15422
+ };
15423
+ const ICON_TONE_CLASSES$1 = {
15424
+ neutral: 'bg-primary/10 text-primary',
15425
+ gem: 'bg-primary/10 text-primary',
15426
+ diamond: 'bg-blue-100 text-blue-500',
15427
+ };
15428
+ /**
15429
+ * Section panel used across the redesigned create/edit forms: a rounded card
15430
+ * with a tinted header band (icon square + title + description) above a
15431
+ * divider, then the form body. The icon-square + title + description header
15432
+ * is the recurring pattern in the new designs.
15433
+ * divider, then the form body.
15434
+ */
15435
+ const FormSectionCard = ({ icon, title, description, headerAction, children, className, bodyClassName, tone = 'neutral', headerClassName, }) => {
15436
+ return (jsxRuntime.jsxs("section", { className: cn('overflow-hidden rounded-xl border border-border bg-card shadow-card', className), children: [jsxRuntime.jsxs("header", { className: cn('flex items-center justify-between gap-4 border-b border-border px-5 py-4', HEADER_TONE_CLASSES[tone], headerClassName), children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [jsxRuntime.jsx("span", { className: cn('inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-md', ICON_TONE_CLASSES$1[tone]), children: icon }), jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [jsxRuntime.jsx("p", { className: "text-base font-medium text-foreground", children: title }), description && (jsxRuntime.jsx("p", { className: "text-[13px] font-normal text-label", children: description }))] })] }), headerAction] }), jsxRuntime.jsx("div", { className: cn('p-5', bodyClassName), children: children })] }));
15437
+ };
15438
+
15439
+ function CompanyCardField({ label, children, emptyLabel, className, }) {
15440
+ return (jsxRuntime.jsxs("div", { className: cn('flex min-w-0 flex-col gap-1', className), children: [jsxRuntime.jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: label }), children ? (jsxRuntime.jsx("div", { className: "truncate text-sm font-medium leading-5 text-foreground", children: children })) : (jsxRuntime.jsx("p", { className: "text-sm font-medium italic leading-5 text-muted-foreground", children: emptyLabel }))] }));
15441
+ }
15442
+
15443
+ /** `—` is the placeholder the apps' display helpers return for a missing value. */
15444
+ function hasValue(value) {
15445
+ const trimmed = value?.trim();
15446
+ return !!trimmed && trimmed !== '—';
15447
+ }
15448
+ function getInitial(name) {
15449
+ return (name.trim()[0] ?? '?').toUpperCase();
15450
+ }
15451
+
15452
+ /**
15453
+ * A business contact at a glance: avatar + name, email / phone / tax number,
15454
+ * then the address. Data-only — the app formats each value before passing it.
15455
+ */
15456
+ function CompanyCard({ name, subtitle, email, phone, taxNumber, address, viewHref, viewLabel = 'View company', title = 'Company', icon = jsxRuntime.jsx(Building2, { className: "size-5", "aria-hidden": true }), emptyLabel = 'Not provided', className, }) {
15457
+ return (jsxRuntime.jsxs(FormSectionCard, { icon: icon, title: title, className: className, headerClassName: "px-4 py-3", bodyClassName: "flex flex-col gap-4 p-4", headerAction: viewHref ? (jsxRuntime.jsx(TextHyperlink, { href: viewHref, showIcon: false, className: "shrink-0 text-sm font-medium", children: viewLabel })) : undefined, children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [jsxRuntime.jsx("span", { "aria-hidden": true, className: "flex size-10 shrink-0 items-center justify-center rounded-full bg-primary text-sm font-semibold text-primary-foreground", children: getInitial(name) }), jsxRuntime.jsxs("div", { className: "min-w-0", children: [jsxRuntime.jsx("p", { className: "break-words text-base font-semibold leading-6 text-foreground", children: name }), hasValue(subtitle) ? (jsxRuntime.jsx("p", { className: "break-words text-xs leading-4 text-muted-foreground", children: subtitle })) : null] })] }), jsxRuntime.jsxs("div", { className: cn('grid grid-cols-1 gap-4', taxNumber ? 'sm:grid-cols-3' : 'sm:grid-cols-2'), children: [jsxRuntime.jsx(CompanyCardField, { label: "Email", emptyLabel: emptyLabel, children: hasValue(email) ? (jsxRuntime.jsx("a", { href: `mailto:${email}`, className: "text-primary underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: email })) : null }), jsxRuntime.jsx(CompanyCardField, { label: "Phone", emptyLabel: emptyLabel, children: hasValue(phone) ? phone : null }), taxNumber ? (jsxRuntime.jsx(CompanyCardField, { label: taxNumber.label, emptyLabel: emptyLabel, children: hasValue(taxNumber.value) ? taxNumber.value : null })) : null] }), jsxRuntime.jsx(CompanyCardField, { label: "Address", emptyLabel: emptyLabel, className: "border-t border-border pt-4", children: hasValue(address) ? jsxRuntime.jsx("span", { className: "whitespace-normal break-words", children: address }) : null })] }));
15458
+ }
15459
+
15399
15460
  function commonjsRequire(path) {
15400
15461
  throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
15401
15462
  }
@@ -37088,7 +37149,7 @@ styleInject(css_248z$1);
37088
37149
  * Date field that can be typed or picked. The text box takes a masked
37089
37150
  * `DD/MM/YYYY` entry; the trailing button opens the same calendar as before.
37090
37151
  */
37091
- function DateInput({ value, onChange, onBlur, name, id, className, min, max, disabled, placeholder = DATE_FORMAT, ariaLabel, }) {
37152
+ function DateInput({ value, onChange, onBlur, name, id, className, min, max, disabled, placeholder = DATE_FORMAT, ariaLabel, align = 'start', }) {
37092
37153
  const { open, text, invalid, bounds, inputRef, handleOpenChange, handleTextChange, handleKeyDown, handleTextBlur, toggleOpen, selectDate, clearDate, selectToday, } = useDateInput({ value, onChange, onBlur, min, max, disabled });
37093
37154
  // NOTE: We drive `open` ourselves from the button's onClick instead of using
37094
37155
  // Radix's <PopoverTrigger> toggle. When this Popover is nested inside the
@@ -37098,7 +37159,7 @@ function DateInput({ value, onChange, onBlur, name, id, className, min, max, dis
37098
37159
  // source of truth — no double-fire, and it works across browsers. `modal`
37099
37160
  // lets the open popover own pointer events above the dialog so the calendar
37100
37161
  // (portalled to <body>) stays clickable.
37101
- return (jsxRuntime.jsxs(Popover, { open: open, onOpenChange: handleOpenChange, modal: true, children: [jsxRuntime.jsx(PopoverAnchor, { asChild: true, children: jsxRuntime.jsxs("div", { "data-slot": "input", "data-empty": !value || undefined, "data-invalid": invalid || undefined, className: cn('border-input-border flex h-9 w-full min-w-0 items-center gap-2 rounded-md border bg-transparent px-3 py-1 shadow-[0_1px_2px_0_#0000000d] transition-[color,box-shadow] outline-none', 'focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]', 'data-[invalid]:border-destructive data-[invalid]:ring-destructive/20 data-[invalid]:ring-[3px]', disabled && 'cursor-not-allowed bg-muted/50 text-label', className), children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", inputMode: "numeric", autoComplete: "off", spellCheck: false, id: id, name: name, value: text, placeholder: placeholder, disabled: disabled, maxLength: DATE_FORMAT.length, "aria-label": ariaLabel, "aria-invalid": invalid || undefined, title: DATE_FORMAT_HINT, onChange: handleTextChange, onKeyDown: handleKeyDown, onBlur: handleTextBlur, className: "placeholder:text-placeholder selection:bg-primary selection:text-primary-foreground h-full min-w-0 flex-1 bg-transparent text-base text-foreground outline-none placeholder:text-sm disabled:cursor-not-allowed disabled:text-label md:text-sm" }), jsxRuntime.jsx("button", { type: "button", disabled: disabled, "aria-label": CALENDAR_BUTTON_LABEL, "aria-haspopup": "dialog", "aria-expanded": open, onClick: toggleOpen, className: "-mr-1 inline-flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-sm text-muted-foreground outline-none hover:text-foreground focus-visible:ring-ring/50 focus-visible:ring-[2px] disabled:cursor-not-allowed", children: jsxRuntime.jsx(CalendarDays, { className: "h-4 w-4 stroke-[1.75]" }) })] }) }), jsxRuntime.jsx(PopoverContent, { align: "start", className: "date-range-picker-popover w-auto p-4", children: jsxRuntime.jsx(DatePicker, { inline: true, selected: value ?? null, minDate: toBoundDate(bounds.minDate), maxDate: toBoundDate(bounds.maxDate), onChange: selectDate, calendarClassName: "date-range-picker-calendar", formatWeekDay: (weekday) => weekday.slice(0, 2), renderCustomHeader: ({ monthDate, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled, }) => (jsxRuntime.jsx(DatePickerHeader, { monthDate: monthDate, changeYear: changeYear, changeMonth: changeMonth, decreaseMonth: decreaseMonth, increaseMonth: increaseMonth, prevMonthButtonDisabled: prevMonthButtonDisabled, nextMonthButtonDisabled: nextMonthButtonDisabled, minYear: bounds.minYear, maxYear: bounds.maxYear })), children: jsxRuntime.jsxs("div", { className: "date-range-picker-footer", children: [jsxRuntime.jsx("button", { type: "button", onClick: clearDate, className: "date-range-picker-action", children: "Clear" }), jsxRuntime.jsx("button", { type: "button", onClick: selectToday, className: "date-range-picker-action", children: "Today" })] }) }) })] }));
37162
+ return (jsxRuntime.jsxs(Popover, { open: open, onOpenChange: handleOpenChange, modal: true, children: [jsxRuntime.jsx(PopoverAnchor, { asChild: true, children: jsxRuntime.jsxs("div", { "data-slot": "input", "data-empty": !value || undefined, "data-invalid": invalid || undefined, className: cn('border-input-border flex h-9 w-full min-w-0 items-center gap-2 rounded-md border bg-transparent px-3 py-1 shadow-[0_1px_2px_0_#0000000d] transition-[color,box-shadow] outline-none', 'focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]', 'data-[invalid]:border-destructive data-[invalid]:ring-destructive/20 data-[invalid]:ring-[3px]', disabled && 'cursor-not-allowed bg-muted/50 text-label', className), children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", inputMode: "numeric", autoComplete: "off", spellCheck: false, id: id, name: name, value: text, placeholder: placeholder, disabled: disabled, maxLength: DATE_FORMAT.length, "aria-label": ariaLabel, "aria-invalid": invalid || undefined, title: DATE_FORMAT_HINT, onChange: handleTextChange, onKeyDown: handleKeyDown, onBlur: handleTextBlur, className: "placeholder:text-placeholder selection:bg-primary selection:text-primary-foreground h-full min-w-0 flex-1 bg-transparent text-base text-foreground outline-none placeholder:text-sm disabled:cursor-not-allowed disabled:text-label md:text-sm" }), jsxRuntime.jsx("button", { type: "button", disabled: disabled, "aria-label": CALENDAR_BUTTON_LABEL, "aria-haspopup": "dialog", "aria-expanded": open, onClick: toggleOpen, className: "-mr-1 inline-flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-sm text-muted-foreground outline-none hover:text-foreground focus-visible:ring-ring/50 focus-visible:ring-[2px] disabled:cursor-not-allowed", children: jsxRuntime.jsx(CalendarDays, { className: "h-4 w-4 stroke-[1.75]" }) })] }) }), jsxRuntime.jsx(PopoverContent, { align: align, className: "date-range-picker-popover w-auto p-4", children: jsxRuntime.jsx(DatePicker, { inline: true, selected: value ?? null, minDate: toBoundDate(bounds.minDate), maxDate: toBoundDate(bounds.maxDate), onChange: selectDate, calendarClassName: "date-range-picker-calendar", formatWeekDay: (weekday) => weekday.slice(0, 2), renderCustomHeader: ({ monthDate, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled, }) => (jsxRuntime.jsx(DatePickerHeader, { monthDate: monthDate, changeYear: changeYear, changeMonth: changeMonth, decreaseMonth: decreaseMonth, increaseMonth: increaseMonth, prevMonthButtonDisabled: prevMonthButtonDisabled, nextMonthButtonDisabled: nextMonthButtonDisabled, minYear: bounds.minYear, maxYear: bounds.maxYear })), children: jsxRuntime.jsxs("div", { className: "date-range-picker-footer", children: [jsxRuntime.jsx("button", { type: "button", onClick: clearDate, className: "date-range-picker-action", children: "Clear" }), jsxRuntime.jsx("button", { type: "button", onClick: selectToday, className: "date-range-picker-action", children: "Today" })] }) }) })] }));
37102
37163
  }
37103
37164
 
37104
37165
  const DropdownMenu = DropdownMenuPrimitive__namespace.Root;
@@ -37633,27 +37694,6 @@ const InAppNotificationCard = ({ notification, onSelect, defaultIcon, className,
37633
37694
  return (jsxRuntime.jsxs("button", { type: "button", onClick: () => onSelect(notification), className: getInAppNotificationCardClasses(isRead, className), children: [jsxRuntime.jsx("span", { className: getInAppNotificationIconClasses(isRead), children: icon ?? defaultIcon ?? (jsxRuntime.jsx(BellDot, { className: "size-4", "aria-hidden": "true" })) }), jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [jsxRuntime.jsxs("span", { className: "flex items-baseline gap-2", children: [!isRead && (jsxRuntime.jsx("span", { role: "img", "aria-label": inAppNotificationCardA11y.unreadLabel, className: "size-1.5 shrink-0 rounded-full bg-primary" })), jsxRuntime.jsx("span", { className: cn('min-w-0 flex-1 truncate text-sm text-foreground', isRead ? 'font-medium' : 'font-semibold'), children: title }), jsxRuntime.jsx("time", { className: "shrink-0 text-[0.6875rem] text-muted-foreground tabular-nums", children: formatRelativeTime(createdAt) })] }), jsxRuntime.jsx("span", { className: "mt-1 line-clamp-1 text-xs text-secondary-foreground", children: message }), subject && (jsxRuntime.jsx("span", { className: "mt-0.5 block truncate text-[0.6875rem] font-medium text-muted-foreground", children: subject }))] })] }));
37634
37695
  };
37635
37696
 
37636
- const HEADER_TONE_CLASSES = {
37637
- neutral: 'bg-[var(--section-header)]',
37638
- gem: 'bg-primary/5 dark:bg-[#173626]',
37639
- diamond: 'bg-blue-50 dark:bg-[#0284C7]/20',
37640
- };
37641
- const ICON_TONE_CLASSES$1 = {
37642
- neutral: 'bg-primary/10 text-primary',
37643
- gem: 'bg-primary/10 text-primary',
37644
- diamond: 'bg-blue-100 text-blue-500',
37645
- };
37646
- /**
37647
- * Section panel used across the redesigned create/edit forms: a rounded card
37648
- * with a tinted header band (icon square + title + description) above a
37649
- * divider, then the form body. The icon-square + title + description header
37650
- * is the recurring pattern in the new designs.
37651
- * divider, then the form body.
37652
- */
37653
- const FormSectionCard = ({ icon, title, description, headerAction, children, className, bodyClassName, tone = 'neutral', headerClassName, }) => {
37654
- return (jsxRuntime.jsxs("section", { className: cn('overflow-hidden rounded-xl border border-border bg-card shadow-card', className), children: [jsxRuntime.jsxs("header", { className: cn('flex items-center justify-between gap-4 border-b border-border px-5 py-4', HEADER_TONE_CLASSES[tone], headerClassName), children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [jsxRuntime.jsx("span", { className: cn('inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-md', ICON_TONE_CLASSES$1[tone]), children: icon }), jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [jsxRuntime.jsx("p", { className: "text-base font-medium text-foreground", children: title }), description && (jsxRuntime.jsx("p", { className: "text-[13px] font-normal text-label", children: description }))] })] }), headerAction] }), jsxRuntime.jsx("div", { className: cn('p-5', bodyClassName), children: children })] }));
37655
- };
37656
-
37657
37697
  const TONE_STYLES = {
37658
37698
  info: {
37659
37699
  container: 'border-border bg-section-header',
@@ -38003,6 +38043,21 @@ function formatCurrency(amount, currency) {
38003
38043
  currency: currency || 'USD',
38004
38044
  }).format(amount);
38005
38045
  }
38046
+ /** The currency the invoice was issued in; `baseCurrency` is only its ledger currency. */
38047
+ function getInvoiceCurrency(invoice) {
38048
+ const target = invoice.target?.currency?.trim().toUpperCase();
38049
+ return target && invoice.target?.rate ? target : invoice.baseCurrency || 'USD';
38050
+ }
38051
+ function getInvoiceCompany(invoice) {
38052
+ return invoice.customer?.companyName || invoice.customer?.contactName || 'N/A';
38053
+ }
38054
+ function getInvoiceLocation(invoice) {
38055
+ const address = invoice.customer?.address ?? invoice.address;
38056
+ return [address?.city, address?.state, address?.country]
38057
+ .map((part) => part?.trim())
38058
+ .filter(Boolean)
38059
+ .join(', ');
38060
+ }
38006
38061
 
38007
38062
  function useInvoiceComboBox(fetchInvoices, statusFilter) {
38008
38063
  const fetchPage = React.useCallback(async ({ page, limit, search }) => {
@@ -38067,7 +38122,8 @@ function InvoiceComboBox({ selectedItem, onSelect, fetchInvoices, searchPlacehol
38067
38122
  const invoice = item.data;
38068
38123
  const invoiceDate = new Date(invoice.invoiceDate).toLocaleDateString();
38069
38124
  const dueDate = new Date(invoice.paymentDueDate).toLocaleDateString();
38070
- return (jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [jsxRuntime.jsx("span", { className: "font-semibold text-sm text-foreground", children: invoice.invoiceNumber }), jsxRuntime.jsx(StatusBadge, { status: invoice.status })] }), jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground mb-1", children: ["Customer: ", invoice.customer?.contactName || 'N/A'] }), jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2 mt-1", children: [jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: ["Date: ", invoiceDate] }), jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "\u2022" }), jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: ["Due: ", dueDate] })] }), jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2 mt-1", children: [jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground", children: ["Total:", ' ', formatCurrency(invoice.totalAmount, invoice.baseCurrency)] }), invoice.outstandingAmount > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "\u2022" }), jsxRuntime.jsxs("span", { className: "text-xs text-destructive", children: ["Outstanding:", ' ', formatCurrency(invoice.outstandingAmount, invoice.baseCurrency)] })] }))] })] }));
38125
+ const location = getInvoiceLocation(invoice);
38126
+ return (jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 mb-1", children: [jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [jsxRuntime.jsx("span", { className: "font-semibold text-sm text-foreground", children: invoice.invoiceNumber }), jsxRuntime.jsx(StatusBadge, { status: invoice.status })] }), jsxRuntime.jsx("span", { className: "shrink-0 text-xs font-semibold text-foreground", children: getInvoiceCurrency(invoice) })] }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 mb-1 text-xs text-muted-foreground", children: [jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: getInvoiceCompany(invoice) }), location ? jsxRuntime.jsx("span", { className: "shrink-0", children: location }) : null] }), jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2 mt-1", children: [jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: ["Date: ", invoiceDate] }), jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "\u2022" }), jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: ["Due: ", dueDate] })] }), jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2 mt-1", children: [jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground", children: ["Total:", ' ', formatCurrency(invoice.totalAmount, invoice.baseCurrency)] }), invoice.outstandingAmount > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "\u2022" }), jsxRuntime.jsxs("span", { className: "text-xs text-destructive", children: ["Outstanding:", ' ', formatCurrency(invoice.outstandingAmount, invoice.baseCurrency)] })] }))] })] }));
38071
38127
  }, fetchPage: fetchPage, resolveById: resolveById, preSelectedId: preSelectedId ?? null, searchPlaceholder: searchPlaceholder, emptyMessage: "No invoices found.", disabled: disabled, className: className, align: align, debounceMs: 300 }));
38072
38128
  }
38073
38129
 
@@ -38244,27 +38300,52 @@ const NumberedStepCard = ({ step, title, description, className, }) => {
38244
38300
  return (jsxRuntime.jsxs("div", { className: cn('flex flex-col gap-3 rounded-xl border border-border bg-card p-4', className), children: [jsxRuntime.jsx("span", { className: "inline-flex h-6 w-6 items-center justify-center rounded-full bg-primary text-xs font-medium text-primary-foreground", children: step }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: title }), jsxRuntime.jsx("p", { className: "text-xs leading-snug text-label", children: description })] })] }));
38245
38301
  };
38246
38302
 
38303
+ /** Options with a description get the taller layout with an icon badge (default variant only). */
38304
+ function hasDetails(variant, hasDescription) {
38305
+ return variant === 'default' && hasDescription;
38306
+ }
38307
+ function getListClassName(variant, detailed) {
38308
+ return cn('inline-flex w-full items-center gap-1 bg-muted p-1', detailed ? 'rounded-xl' : variant === 'bordered' ? 'rounded-lg' : 'rounded-md');
38309
+ }
38310
+ function getSegmentClassName(variant, isActive, isDisabled, detailed = false) {
38311
+ return cn('inline-flex cursor-pointer items-center justify-center gap-2 border px-3 text-sm font-medium transition-colors disabled:cursor-not-allowed', 'outline-none focus-visible:ring-2 focus-visible:ring-primary/30', detailed ? 'min-h-11 rounded-lg py-2 font-semibold' : 'h-7 rounded-md',
38312
+ // Bordered tabs size to their content (Figma "Advance Tabs"); the others stretch to equal width.
38313
+ variant === 'bordered' ? 'shrink-0' : 'flex-1',
38314
+ // Every segment carries a border so the active one's primary border doesn't shift the layout.
38315
+ isActive
38316
+ ? cn('border-primary bg-card shadow-xs', detailed ? 'text-primary dark:text-foreground' : 'text-primary')
38317
+ : cn('border-transparent', variant === 'bordered' ? 'text-foreground' : 'text-muted-foreground', 'hover:text-foreground'), isDisabled && 'cursor-not-allowed opacity-50');
38318
+ }
38319
+ function getIconClassName(detailed, isActive) {
38320
+ if (!detailed) {
38321
+ return 'inline-flex shrink-0 items-center [&_svg]:h-4 [&_svg]:w-4';
38322
+ }
38323
+ return cn('inline-flex size-7 shrink-0 items-center justify-center rounded-full text-sm font-semibold [&_svg]:size-4', isActive ? 'bg-primary/10 text-primary' : 'bg-foreground/5 text-muted-foreground');
38324
+ }
38325
+ function getContentClassName(layout) {
38326
+ return layout === 'inline'
38327
+ ? 'flex min-w-0 items-baseline gap-2'
38328
+ : 'flex min-w-0 flex-col items-center gap-0.5';
38329
+ }
38330
+ function getDescriptionClassName(isActive) {
38331
+ return cn('truncate text-xs font-normal', isActive ? 'text-primary' : 'text-muted-foreground');
38332
+ }
38333
+
38247
38334
  /**
38248
- * Pill-shaped segmented control with N equally-sized buttons. The active
38249
- * segment lifts forward with a white bg + subtle shadow; inactive segments
38250
- * blend into the muted container background.
38335
+ * Pill-shaped segmented control. The active segment lifts forward with a card
38336
+ * bg, primary border and subtle shadow; inactive segments blend into the muted
38337
+ * container background. Giving options a `description` makes the default
38338
+ * segments taller, with the icon in a badge.
38251
38339
  *
38252
38340
  * Single source of truth for "two-or-more mutually exclusive views" toggles
38253
38341
  * (e.g. Owned / Memo on the ownership form).
38254
38342
  */
38255
- function SegmentedControl({ value, onChange, options, ariaLabel, className, disabled, variant = 'default', }) {
38256
- const isBordered = variant === 'bordered';
38257
- return (jsxRuntime.jsx("div", { role: "tablist", "aria-label": ariaLabel, className: cn('inline-flex w-full items-center gap-1 bg-muted p-1', isBordered ? 'rounded-lg' : 'rounded-md', className), children: options.map((opt) => {
38343
+ function SegmentedControl({ value, onChange, options, ariaLabel, className, disabled, variant = 'default', optionLayout = 'stacked', }) {
38344
+ const detailed = options.some((opt) => hasDetails(variant, opt.description != null));
38345
+ return (jsxRuntime.jsx("div", { role: "tablist", "aria-label": ariaLabel, className: cn(getListClassName(variant, detailed), className), children: options.map((opt) => {
38258
38346
  const isActive = value === opt.value;
38259
- const isDisabled = disabled || opt.disabled;
38260
- return (jsxRuntime.jsxs("button", { type: "button", role: "tab", "aria-selected": isActive, disabled: isDisabled, onClick: () => !isDisabled && onChange(opt.value), className: cn('inline-flex h-7 cursor-pointer items-center justify-center gap-2 rounded-md px-3 text-sm font-medium transition-colors disabled:cursor-not-allowed', 'outline-none focus-visible:ring-2 focus-visible:ring-primary/30',
38261
- // Bordered tabs size to their content (Figma "Advance Tabs"); the
38262
- // default variant stretches every segment to equal width.
38263
- isBordered ? 'shrink-0' : 'flex-1', isActive
38264
- ? cn('bg-card text-primary shadow-xs', isBordered && 'border border-primary')
38265
- : isBordered
38266
- ? 'text-foreground hover:text-foreground'
38267
- : 'text-muted-foreground hover:text-foreground', isDisabled && 'cursor-not-allowed opacity-50'), children: [opt.icon && (jsxRuntime.jsx("span", { "aria-hidden": "true", className: "inline-flex shrink-0 items-center [&_svg]:h-4 [&_svg]:w-4", children: opt.icon })), jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: opt.label })] }, opt.value));
38347
+ const isDisabled = !!(disabled || opt.disabled);
38348
+ return (jsxRuntime.jsxs("button", { type: "button", role: "tab", "aria-selected": isActive, disabled: isDisabled, onClick: () => !isDisabled && onChange(opt.value), className: getSegmentClassName(variant, isActive, isDisabled, detailed), children: [opt.icon && (jsxRuntime.jsx("span", { "aria-hidden": "true", className: getIconClassName(detailed, isActive), children: opt.icon })), detailed && opt.description != null ? (jsxRuntime.jsxs("span", { className: getContentClassName(optionLayout), children: [jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: opt.label }), jsxRuntime.jsx("span", { className: getDescriptionClassName(isActive), children: opt.description })] })) : (jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: opt.label }))] }, opt.value));
38268
38349
  }) }));
38269
38350
  }
38270
38351
 
@@ -77709,6 +77790,7 @@ exports.Collapsible = Collapsible;
77709
77790
  exports.CollapsibleCard = CollapsibleCard;
77710
77791
  exports.CollapsibleContent = CollapsibleContent;
77711
77792
  exports.CollapsibleTrigger = CollapsibleTrigger;
77793
+ exports.CompanyCard = CompanyCard;
77712
77794
  exports.ConfirmDialog = ConfirmDialog;
77713
77795
  exports.ContactTypeFilter = ContactTypeFilter;
77714
77796
  exports.CopyButton = CopyButton;