hs-uix 1.4.1 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -30,7 +30,8 @@ import {
30
30
  Text,
31
31
  TextArea,
32
32
  TimeInput,
33
- Toggle
33
+ Toggle,
34
+ Tooltip
34
35
  } from "@hubspot/ui-extensions";
35
36
  var formatDateChip = (dateObj) => {
36
37
  if (!dateObj) return "";
@@ -304,7 +305,9 @@ var DataTable = ({
304
305
  const initialSortState = useMemo(() => {
305
306
  return normalizeSortState(columns, defaultSort);
306
307
  }, [columns, defaultSort]);
307
- const [internalSearchTerm, setInternalSearchTerm] = useState("");
308
+ const [internalSearchTerm, setInternalSearchTerm] = useState(
309
+ () => serverSide && searchValue != null ? searchValue : ""
310
+ );
308
311
  const [internalFilterValues, setInternalFilterValues] = useState(() => {
309
312
  const init = {};
310
313
  filters.forEach((f) => {
@@ -315,7 +318,16 @@ var DataTable = ({
315
318
  const [internalSortState, setInternalSortState] = useState(initialSortState);
316
319
  const [currentPage, setCurrentPage] = useState(1);
317
320
  const [showMoreFilters, setShowMoreFilters] = useState(false);
321
+ const lastAppliedSearchRef = useRef(
322
+ serverSide && searchValue != null ? searchValue : ""
323
+ );
318
324
  const searchTerm = serverSide && searchValue != null ? searchValue : internalSearchTerm;
325
+ useEffect(() => {
326
+ if (!serverSide || searchValue == null) return;
327
+ if (searchValue === lastAppliedSearchRef.current) return;
328
+ lastAppliedSearchRef.current = searchValue;
329
+ setInternalSearchTerm(searchValue);
330
+ }, [serverSide, searchValue]);
319
331
  const filterValues = serverSide && externalFilterValues != null ? externalFilterValues : internalFilterValues;
320
332
  const externalSortState = useMemo(
321
333
  () => normalizeSortState(columns, externalSort),
@@ -349,15 +361,16 @@ var DataTable = ({
349
361
  const handleSearchChange = useCallback((term) => {
350
362
  setInternalSearchTerm(term);
351
363
  resetPage();
364
+ const dispatch = () => {
365
+ lastAppliedSearchRef.current = term;
366
+ fireSearchCallback(term);
367
+ fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
368
+ };
352
369
  if (searchDebounce > 0) {
353
370
  if (debounceRef.current) clearTimeout(debounceRef.current);
354
- debounceRef.current = setTimeout(() => {
355
- fireSearchCallback(term);
356
- fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
357
- }, searchDebounce);
371
+ debounceRef.current = setTimeout(dispatch, searchDebounce);
358
372
  } else {
359
- fireSearchCallback(term);
360
- fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
373
+ dispatch();
361
374
  }
362
375
  }, [searchDebounce, fireSearchCallback, fireParamsChange, resetPage, resetPageOnChange]);
363
376
  useEffect(() => () => {
@@ -439,10 +452,23 @@ var DataTable = ({
439
452
  if (serverSide) return filteredData;
440
453
  const activeField = Object.keys(sortState).find((k) => sortState[k] !== "none");
441
454
  if (!activeField) return filteredData;
455
+ const activeCol = columns.find((c) => c.field === activeField);
456
+ const sortOrder = Array.isArray(activeCol == null ? void 0 : activeCol.sortOrder) ? activeCol.sortOrder : null;
457
+ const sortOrderIndex = (val) => {
458
+ const idx = sortOrder.indexOf(val);
459
+ return idx === -1 ? sortOrder.length : idx;
460
+ };
442
461
  return [...filteredData].sort((a, b) => {
443
462
  const dir = sortState[activeField] === "ascending" ? 1 : -1;
444
463
  const aVal = a[activeField];
445
464
  const bVal = b[activeField];
465
+ if (typeof (activeCol == null ? void 0 : activeCol.sortComparator) === "function") {
466
+ return dir * activeCol.sortComparator(aVal, bVal, a, b);
467
+ }
468
+ if (sortOrder) {
469
+ const diff = sortOrderIndex(aVal) - sortOrderIndex(bVal);
470
+ if (diff !== 0) return dir * diff;
471
+ }
446
472
  if (aVal == null && bVal == null) return 0;
447
473
  if (aVal == null) return 1;
448
474
  if (bVal == null) return -1;
@@ -450,7 +476,7 @@ var DataTable = ({
450
476
  if (aVal > bVal) return dir;
451
477
  return 0;
452
478
  });
453
- }, [filteredData, sortState, serverSide]);
479
+ }, [filteredData, sortState, serverSide, columns]);
454
480
  const groupedData = useMemo(() => {
455
481
  if (!groupBy) return null;
456
482
  const source = serverSide ? data : sortedData;
@@ -979,7 +1005,7 @@ var DataTable = ({
979
1005
  {
980
1006
  name: "datatable-search",
981
1007
  placeholder: searchPlaceholder,
982
- value: searchTerm,
1008
+ value: internalSearchTerm,
983
1009
  onChange: handleSearchChange
984
1010
  }
985
1011
  ), filters.slice(0, filterInlineLimit).map(renderFilterControl), filters.length > filterInlineLimit && /* @__PURE__ */ React.createElement(
@@ -992,7 +1018,7 @@ var DataTable = ({
992
1018
  /* @__PURE__ */ React.createElement(Icon, { name: "filter", size: "sm" }),
993
1019
  " ",
994
1020
  resolvedFiltersButtonLabel
995
- )), showMoreFilters && filters.length > filterInlineLimit && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "end", gap: "sm", wrap: "wrap" }, filters.slice(filterInlineLimit).map(renderFilterControl)), activeChips.length > 0 && (showFilterBadges || showClearFiltersButton) && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showFilterBadges && activeChips.map((chip) => /* @__PURE__ */ React.createElement(Tag, { key: chip.key, variant: "default", onDelete: () => handleFilterRemove(chip.key) }, chip.label)), showClearFiltersButton && /* @__PURE__ */ React.createElement(
1021
+ )), showMoreFilters && filters.length > filterInlineLimit && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, filters.slice(filterInlineLimit).map(renderFilterControl)), activeChips.length > 0 && (showFilterBadges || showClearFiltersButton) && /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "sm", wrap: "wrap" }, showFilterBadges && activeChips.map((chip) => /* @__PURE__ */ React.createElement(Tag, { key: chip.key, variant: "default", onDelete: () => handleFilterRemove(chip.key) }, chip.label)), showClearFiltersButton && /* @__PURE__ */ React.createElement(
996
1022
  Button,
997
1023
  {
998
1024
  variant: "transparent",
@@ -1056,7 +1082,7 @@ var DataTable = ({
1056
1082
  sortDirection: col.sortable ? sortState[col.field] || "none" : "never",
1057
1083
  onSortChange: col.sortable ? () => handleSortChange(col.field) : void 0
1058
1084
  },
1059
- col.label
1085
+ col.description ? /* @__PURE__ */ React.createElement(React.Fragment, null, col.label, "\xA0", /* @__PURE__ */ React.createElement(Link, { inline: true, variant: "dark", overlay: /* @__PURE__ */ React.createElement(Tooltip, null, col.description) }, /* @__PURE__ */ React.createElement(Icon, { name: "info", screenReaderText: typeof col.description === "string" ? col.description : void 0 }))) : col.label
1060
1086
  );
1061
1087
  }), showRowActionsColumn && /* @__PURE__ */ React.createElement(TableHeader, { width: "min" }))),
1062
1088
  /* @__PURE__ */ React.createElement(TableBody, null, displayRows.map(
@@ -1134,7 +1160,7 @@ import {
1134
1160
  Button as Button2,
1135
1161
  LoadingButton,
1136
1162
  Alert,
1137
- Tooltip,
1163
+ Tooltip as Tooltip2,
1138
1164
  StepIndicator,
1139
1165
  Input as Input2,
1140
1166
  TextArea as TextArea2,
@@ -3144,7 +3170,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
3144
3170
  const groupLabel = getDependsOnLabel(firstWithLabel) || dependentPropertiesLabel;
3145
3171
  const rawMessage = getDependsOnMessage(firstWithMessage);
3146
3172
  const tooltipMessage = typeof rawMessage === "function" ? rawMessage(parentField.label) : rawMessage || "";
3147
- return /* @__PURE__ */ React2.createElement(Tile, { key: `dep-${parentField.name}`, compact: true }, /* @__PURE__ */ React2.createElement(Flex2, { direction: "column", gap }, /* @__PURE__ */ React2.createElement(Flex2, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ React2.createElement(Text2, { format: { fontWeight: "demibold" } }, groupLabel, " ", tooltipMessage && /* @__PURE__ */ React2.createElement(Link2, { inline: true, variant: "dark", overlay: /* @__PURE__ */ React2.createElement(Tooltip, null, tooltipMessage) }, /* @__PURE__ */ React2.createElement(Icon2, { name: "info" })))), renderFieldSubset(dependents)));
3173
+ return /* @__PURE__ */ React2.createElement(Tile, { key: `dep-${parentField.name}`, compact: true }, /* @__PURE__ */ React2.createElement(Flex2, { direction: "column", gap }, /* @__PURE__ */ React2.createElement(Flex2, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ React2.createElement(Text2, { format: { fontWeight: "demibold" } }, groupLabel, " ", tooltipMessage && /* @__PURE__ */ React2.createElement(Link2, { inline: true, variant: "dark", overlay: /* @__PURE__ */ React2.createElement(Tooltip2, null, tooltipMessage) }, /* @__PURE__ */ React2.createElement(Icon2, { name: "info" })))), renderFieldSubset(dependents)));
3148
3174
  };
3149
3175
  const renderGridLayout = (fieldSubset, effectiveCols) => {
3150
3176
  const cols = effectiveCols || columns;
@@ -3380,7 +3406,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
3380
3406
  );
3381
3407
  if (sec.info) {
3382
3408
  elements.push(
3383
- /* @__PURE__ */ React2.createElement(Flex2, { key: sec.id, direction: "row", align: "start", justify: "start", gap: "flush" }, /* @__PURE__ */ React2.createElement(Box2, { flex: 1 }, accordion), /* @__PURE__ */ React2.createElement(Link2, { variant: "dark", overlay: /* @__PURE__ */ React2.createElement(Tooltip, null, sec.info) }, /* @__PURE__ */ React2.createElement(Icon2, { name: "info", size: "sm", screenReaderText: sec.info })))
3409
+ /* @__PURE__ */ React2.createElement(Flex2, { key: sec.id, direction: "row", align: "start", justify: "start", gap: "flush" }, /* @__PURE__ */ React2.createElement(Box2, { flex: 1 }, accordion), /* @__PURE__ */ React2.createElement(Link2, { variant: "dark", overlay: /* @__PURE__ */ React2.createElement(Tooltip2, null, sec.info) }, /* @__PURE__ */ React2.createElement(Icon2, { name: "info", size: "sm", screenReaderText: sec.info })))
3384
3410
  );
3385
3411
  } else {
3386
3412
  elements.push(accordion);
@@ -3482,8 +3508,211 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
3482
3508
  formContent
3483
3509
  );
3484
3510
  });
3511
+
3512
+ // src/common-components/AutoTag.js
3513
+ import React3 from "react";
3514
+ import { Tag as Tag2 } from "@hubspot/ui-extensions";
3515
+
3516
+ // src/utils/tagVariants.js
3517
+ var DEFAULT_VARIANT = "default";
3518
+ var DANGER_VARIANT = "danger";
3519
+ var ERROR_VARIANT = "error";
3520
+ var SUCCESS_MATCHERS = [
3521
+ "active",
3522
+ "success",
3523
+ "succeeded",
3524
+ "complete",
3525
+ "completed",
3526
+ "approved",
3527
+ "won",
3528
+ "healthy",
3529
+ "enabled",
3530
+ "connected",
3531
+ "paid",
3532
+ "live",
3533
+ "published",
3534
+ "available",
3535
+ "synced",
3536
+ "resolved"
3537
+ ];
3538
+ var WARNING_MATCHERS = [
3539
+ "warning",
3540
+ "at risk",
3541
+ "risky",
3542
+ "pending",
3543
+ "paused",
3544
+ "pause",
3545
+ "on hold",
3546
+ "hold",
3547
+ "review",
3548
+ "expiring",
3549
+ "trial",
3550
+ "in progress",
3551
+ "awaiting",
3552
+ "scheduled"
3553
+ ];
3554
+ var DANGER_MATCHERS = [
3555
+ "danger",
3556
+ "error",
3557
+ "failed",
3558
+ "failure",
3559
+ "inactive",
3560
+ "disabled",
3561
+ "blocked",
3562
+ "cancelled",
3563
+ "canceled",
3564
+ "rejected",
3565
+ "denied",
3566
+ "churned",
3567
+ "lost",
3568
+ "overdue",
3569
+ "expired",
3570
+ "offline",
3571
+ "deleted",
3572
+ "archived",
3573
+ "unpaid"
3574
+ ];
3575
+ var INFO_MATCHERS = [
3576
+ "info",
3577
+ "new",
3578
+ "queued",
3579
+ "processing",
3580
+ "progress",
3581
+ "upcoming",
3582
+ "draft",
3583
+ "open"
3584
+ ];
3585
+ var normalizeTagValue = (value) => {
3586
+ if (value == null) return "";
3587
+ if (typeof value === "boolean") return value ? "true" : "false";
3588
+ return String(value).trim().toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ");
3589
+ };
3590
+ var matchesAny = (value, matchers) => matchers.some((matcher) => {
3591
+ if (value === matcher) return true;
3592
+ return ` ${value} `.includes(` ${matcher} `);
3593
+ });
3594
+ var getSemanticVariant = (value, options = {}) => {
3595
+ const normalized = normalizeTagValue(value);
3596
+ const fallback = options.fallback || DEFAULT_VARIANT;
3597
+ if (!normalized) return fallback;
3598
+ if (options.overrides) {
3599
+ const overrideKey = Object.keys(options.overrides).find(
3600
+ (key) => normalizeTagValue(key) === normalized
3601
+ );
3602
+ if (overrideKey) return options.overrides[overrideKey];
3603
+ }
3604
+ if (normalized === "true") return "success";
3605
+ if (normalized === "false") return fallback;
3606
+ if (matchesAny(normalized, SUCCESS_MATCHERS)) return "success";
3607
+ if (matchesAny(normalized, DANGER_MATCHERS)) return DANGER_VARIANT;
3608
+ if (matchesAny(normalized, WARNING_MATCHERS)) return "warning";
3609
+ if (matchesAny(normalized, INFO_MATCHERS)) return "info";
3610
+ return fallback;
3611
+ };
3612
+ var getAutoTagVariant = (value, options = {}) => {
3613
+ const semanticVariant = getSemanticVariant(value, options);
3614
+ return semanticVariant === DANGER_VARIANT ? ERROR_VARIANT : semanticVariant;
3615
+ };
3616
+ var getAutoStatusTagVariant = (value, options = {}) => getSemanticVariant(value, options);
3617
+ var getAutoTagDisplayValue = (value) => {
3618
+ if (typeof value === "boolean") return value ? "True" : "False";
3619
+ return value;
3620
+ };
3621
+ var DEFAULT_STATUS_TAG_COLOR_ORDER = [
3622
+ "success",
3623
+ "warning",
3624
+ "danger",
3625
+ "error",
3626
+ "info",
3627
+ "default"
3628
+ ];
3629
+ var createStatusTagSortComparator = (options = {}) => {
3630
+ const {
3631
+ variantOrder = DEFAULT_STATUS_TAG_COLOR_ORDER,
3632
+ overrides,
3633
+ fallback,
3634
+ getLabel
3635
+ } = options;
3636
+ const variantIndex = (variant) => {
3637
+ const idx = variantOrder.indexOf(variant);
3638
+ return idx === -1 ? variantOrder.length : idx;
3639
+ };
3640
+ const labelOf = (value) => {
3641
+ if (getLabel) return String(getLabel(value) ?? "");
3642
+ if (value == null) return "";
3643
+ return String(getAutoTagDisplayValue(value) ?? "");
3644
+ };
3645
+ return (aVal, bVal) => {
3646
+ const aVariant = getSemanticVariant(aVal, { overrides, fallback });
3647
+ const bVariant = getSemanticVariant(bVal, { overrides, fallback });
3648
+ const diff = variantIndex(aVariant) - variantIndex(bVariant);
3649
+ if (diff !== 0) return diff;
3650
+ return labelOf(aVal).localeCompare(labelOf(bVal));
3651
+ };
3652
+ };
3653
+
3654
+ // src/common-components/AutoTag.js
3655
+ var AutoTag = ({
3656
+ value,
3657
+ tag,
3658
+ children,
3659
+ variant,
3660
+ overrides,
3661
+ fallback,
3662
+ ...props
3663
+ }) => {
3664
+ const resolvedValue = value ?? tag ?? children;
3665
+ const displayValue = children ?? getAutoTagDisplayValue(resolvedValue);
3666
+ const resolvedVariant = variant || getAutoTagVariant(resolvedValue, {
3667
+ overrides,
3668
+ fallback
3669
+ });
3670
+ return React3.createElement(
3671
+ Tag2,
3672
+ { variant: resolvedVariant, ...props },
3673
+ displayValue
3674
+ );
3675
+ };
3676
+
3677
+ // src/common-components/AutoStatusTag.js
3678
+ import React4 from "react";
3679
+ import { StatusTag } from "@hubspot/ui-extensions";
3680
+ var AutoStatusTag = ({
3681
+ value,
3682
+ status,
3683
+ children,
3684
+ variant,
3685
+ overrides,
3686
+ fallback,
3687
+ ...props
3688
+ }) => {
3689
+ const resolvedValue = value ?? status ?? children;
3690
+ const displayValue = children ?? getAutoTagDisplayValue(resolvedValue);
3691
+ const resolvedVariant = variant || getAutoStatusTagVariant(resolvedValue, {
3692
+ overrides,
3693
+ fallback
3694
+ });
3695
+ return React4.createElement(
3696
+ StatusTag,
3697
+ { variant: resolvedVariant, ...props },
3698
+ displayValue
3699
+ );
3700
+ };
3701
+
3702
+ // src/common-components/KeyValueList.js
3703
+ import React5 from "react";
3704
+ import { DescriptionList, DescriptionListItem, Flex as Flex3 } from "@hubspot/ui-extensions";
3705
+
3706
+ // src/common-components/SectionHeader.js
3707
+ import React6 from "react";
3708
+ import { Flex as Flex4, Heading, Text as Text3 } from "@hubspot/ui-extensions";
3485
3709
  export {
3710
+ AutoStatusTag,
3711
+ AutoTag,
3486
3712
  DataTable,
3487
3713
  FormBuilder,
3714
+ createStatusTagSortComparator,
3715
+ getAutoStatusTagVariant,
3716
+ getAutoTagVariant,
3488
3717
  useFormPrefill
3489
3718
  };
package/dist/utils.js ADDED
@@ -0,0 +1,269 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/utils/index.js
20
+ var utils_exports = {};
21
+ __export(utils_exports, {
22
+ buildOptions: () => buildOptions,
23
+ createStatusTagSortComparator: () => createStatusTagSortComparator,
24
+ findOptionLabel: () => findOptionLabel,
25
+ formatCurrency: () => formatCurrency,
26
+ formatDate: () => formatDate,
27
+ formatDateTime: () => formatDateTime,
28
+ formatPercentage: () => formatPercentage,
29
+ getAutoStatusTagVariant: () => getAutoStatusTagVariant,
30
+ getAutoTagDisplayValue: () => getAutoTagDisplayValue,
31
+ getAutoTagVariant: () => getAutoTagVariant,
32
+ isDateTimeValueObject: () => isDateTimeValueObject,
33
+ isDateValueObject: () => isDateValueObject,
34
+ isTimeValueObject: () => isTimeValueObject,
35
+ sumBy: () => sumBy
36
+ });
37
+ module.exports = __toCommonJS(utils_exports);
38
+
39
+ // src/utils/collections.js
40
+ var sumBy = (items, keyOrFn) => (items || []).reduce((total, item) => {
41
+ const value = typeof keyOrFn === "function" ? keyOrFn(item) : item == null ? void 0 : item[keyOrFn];
42
+ return total + Number(value || 0);
43
+ }, 0);
44
+
45
+ // src/utils/formatters.js
46
+ var DEFAULT_LOCALE = "en-US";
47
+ var formatCurrency = (value, { locale = DEFAULT_LOCALE, currency = "USD", maximumFractionDigits = 0, ...options } = {}) => new Intl.NumberFormat(locale, {
48
+ style: "currency",
49
+ currency,
50
+ maximumFractionDigits,
51
+ ...options
52
+ }).format(Number(value || 0));
53
+ var formatDate = (value, { locale = DEFAULT_LOCALE, month = "short", day = "numeric", year = "numeric", ...options } = {}) => {
54
+ if (value == null || value === "") return "";
55
+ const date = value instanceof Date ? value : new Date(value);
56
+ if (Number.isNaN(date.getTime())) return "";
57
+ return date.toLocaleDateString(locale, {
58
+ month,
59
+ day,
60
+ year,
61
+ ...options
62
+ });
63
+ };
64
+ var formatDateTime = (value, {
65
+ locale = DEFAULT_LOCALE,
66
+ month = "short",
67
+ day = "numeric",
68
+ year = "numeric",
69
+ hour = "numeric",
70
+ minute = "2-digit",
71
+ ...options
72
+ } = {}) => {
73
+ if (value == null || value === "") return "";
74
+ const date = value instanceof Date ? value : new Date(value);
75
+ if (Number.isNaN(date.getTime())) return "";
76
+ return date.toLocaleString(locale, {
77
+ month,
78
+ day,
79
+ year,
80
+ hour,
81
+ minute,
82
+ ...options
83
+ });
84
+ };
85
+ var formatPercentage = (value, { locale = DEFAULT_LOCALE, minimumFractionDigits = 0, maximumFractionDigits = 0, ...options } = {}) => new Intl.NumberFormat(locale, {
86
+ style: "percent",
87
+ minimumFractionDigits,
88
+ maximumFractionDigits,
89
+ ...options
90
+ }).format(Number(value || 0));
91
+
92
+ // src/utils/hubspotValues.js
93
+ var isDateValueObject = (value) => Boolean(
94
+ value && typeof value === "object" && typeof value.year === "number" && typeof value.month === "number" && typeof value.date === "number"
95
+ );
96
+ var isTimeValueObject = (value) => Boolean(
97
+ value && typeof value === "object" && typeof value.hours === "number" && typeof value.minutes === "number"
98
+ );
99
+ var isDateTimeValueObject = (value) => Boolean(
100
+ value && typeof value === "object" && (value.date == null || isDateValueObject(value.date)) && (value.time == null || isTimeValueObject(value.time))
101
+ );
102
+
103
+ // src/utils/options.js
104
+ var buildOptions = (items, { labelKey = "label", valueKey = "value", descriptionKey, mapLabel, mapValue, mapDescription } = {}) => (items || []).map((item) => {
105
+ const label = mapLabel ? mapLabel(item) : (item == null ? void 0 : item[labelKey]) ?? item;
106
+ const value = mapValue ? mapValue(item) : (item == null ? void 0 : item[valueKey]) ?? item;
107
+ const description = descriptionKey ? item == null ? void 0 : item[descriptionKey] : void 0;
108
+ const mappedDescription = mapDescription ? mapDescription(item) : description;
109
+ return mappedDescription == null ? { label, value } : { label, value, description: mappedDescription };
110
+ });
111
+ var findOptionLabel = (options, value, fallback = "") => {
112
+ const match = (options || []).find((option) => (option == null ? void 0 : option.value) === value);
113
+ return (match == null ? void 0 : match.label) ?? fallback;
114
+ };
115
+
116
+ // src/utils/tagVariants.js
117
+ var DEFAULT_VARIANT = "default";
118
+ var DANGER_VARIANT = "danger";
119
+ var ERROR_VARIANT = "error";
120
+ var SUCCESS_MATCHERS = [
121
+ "active",
122
+ "success",
123
+ "succeeded",
124
+ "complete",
125
+ "completed",
126
+ "approved",
127
+ "won",
128
+ "healthy",
129
+ "enabled",
130
+ "connected",
131
+ "paid",
132
+ "live",
133
+ "published",
134
+ "available",
135
+ "synced",
136
+ "resolved"
137
+ ];
138
+ var WARNING_MATCHERS = [
139
+ "warning",
140
+ "at risk",
141
+ "risky",
142
+ "pending",
143
+ "paused",
144
+ "pause",
145
+ "on hold",
146
+ "hold",
147
+ "review",
148
+ "expiring",
149
+ "trial",
150
+ "in progress",
151
+ "awaiting",
152
+ "scheduled"
153
+ ];
154
+ var DANGER_MATCHERS = [
155
+ "danger",
156
+ "error",
157
+ "failed",
158
+ "failure",
159
+ "inactive",
160
+ "disabled",
161
+ "blocked",
162
+ "cancelled",
163
+ "canceled",
164
+ "rejected",
165
+ "denied",
166
+ "churned",
167
+ "lost",
168
+ "overdue",
169
+ "expired",
170
+ "offline",
171
+ "deleted",
172
+ "archived",
173
+ "unpaid"
174
+ ];
175
+ var INFO_MATCHERS = [
176
+ "info",
177
+ "new",
178
+ "queued",
179
+ "processing",
180
+ "progress",
181
+ "upcoming",
182
+ "draft",
183
+ "open"
184
+ ];
185
+ var normalizeTagValue = (value) => {
186
+ if (value == null) return "";
187
+ if (typeof value === "boolean") return value ? "true" : "false";
188
+ return String(value).trim().toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ");
189
+ };
190
+ var matchesAny = (value, matchers) => matchers.some((matcher) => {
191
+ if (value === matcher) return true;
192
+ return ` ${value} `.includes(` ${matcher} `);
193
+ });
194
+ var getSemanticVariant = (value, options = {}) => {
195
+ const normalized = normalizeTagValue(value);
196
+ const fallback = options.fallback || DEFAULT_VARIANT;
197
+ if (!normalized) return fallback;
198
+ if (options.overrides) {
199
+ const overrideKey = Object.keys(options.overrides).find(
200
+ (key) => normalizeTagValue(key) === normalized
201
+ );
202
+ if (overrideKey) return options.overrides[overrideKey];
203
+ }
204
+ if (normalized === "true") return "success";
205
+ if (normalized === "false") return fallback;
206
+ if (matchesAny(normalized, SUCCESS_MATCHERS)) return "success";
207
+ if (matchesAny(normalized, DANGER_MATCHERS)) return DANGER_VARIANT;
208
+ if (matchesAny(normalized, WARNING_MATCHERS)) return "warning";
209
+ if (matchesAny(normalized, INFO_MATCHERS)) return "info";
210
+ return fallback;
211
+ };
212
+ var getAutoTagVariant = (value, options = {}) => {
213
+ const semanticVariant = getSemanticVariant(value, options);
214
+ return semanticVariant === DANGER_VARIANT ? ERROR_VARIANT : semanticVariant;
215
+ };
216
+ var getAutoStatusTagVariant = (value, options = {}) => getSemanticVariant(value, options);
217
+ var getAutoTagDisplayValue = (value) => {
218
+ if (typeof value === "boolean") return value ? "True" : "False";
219
+ return value;
220
+ };
221
+ var DEFAULT_STATUS_TAG_COLOR_ORDER = [
222
+ "success",
223
+ "warning",
224
+ "danger",
225
+ "error",
226
+ "info",
227
+ "default"
228
+ ];
229
+ var createStatusTagSortComparator = (options = {}) => {
230
+ const {
231
+ variantOrder = DEFAULT_STATUS_TAG_COLOR_ORDER,
232
+ overrides,
233
+ fallback,
234
+ getLabel
235
+ } = options;
236
+ const variantIndex = (variant) => {
237
+ const idx = variantOrder.indexOf(variant);
238
+ return idx === -1 ? variantOrder.length : idx;
239
+ };
240
+ const labelOf = (value) => {
241
+ if (getLabel) return String(getLabel(value) ?? "");
242
+ if (value == null) return "";
243
+ return String(getAutoTagDisplayValue(value) ?? "");
244
+ };
245
+ return (aVal, bVal) => {
246
+ const aVariant = getSemanticVariant(aVal, { overrides, fallback });
247
+ const bVariant = getSemanticVariant(bVal, { overrides, fallback });
248
+ const diff = variantIndex(aVariant) - variantIndex(bVariant);
249
+ if (diff !== 0) return diff;
250
+ return labelOf(aVal).localeCompare(labelOf(bVal));
251
+ };
252
+ };
253
+ // Annotate the CommonJS export names for ESM import in node:
254
+ 0 && (module.exports = {
255
+ buildOptions,
256
+ createStatusTagSortComparator,
257
+ findOptionLabel,
258
+ formatCurrency,
259
+ formatDate,
260
+ formatDateTime,
261
+ formatPercentage,
262
+ getAutoStatusTagVariant,
263
+ getAutoTagDisplayValue,
264
+ getAutoTagVariant,
265
+ isDateTimeValueObject,
266
+ isDateValueObject,
267
+ isTimeValueObject,
268
+ sumBy
269
+ });