hs-uix 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/utils.mjs ADDED
@@ -0,0 +1,230 @@
1
+ // src/utils/collections.js
2
+ var sumBy = (items, keyOrFn) => (items || []).reduce((total, item) => {
3
+ const value = typeof keyOrFn === "function" ? keyOrFn(item) : item == null ? void 0 : item[keyOrFn];
4
+ return total + Number(value || 0);
5
+ }, 0);
6
+
7
+ // src/utils/formatters.js
8
+ var DEFAULT_LOCALE = "en-US";
9
+ var formatCurrency = (value, { locale = DEFAULT_LOCALE, currency = "USD", maximumFractionDigits = 0, ...options } = {}) => new Intl.NumberFormat(locale, {
10
+ style: "currency",
11
+ currency,
12
+ maximumFractionDigits,
13
+ ...options
14
+ }).format(Number(value || 0));
15
+ var formatDate = (value, { locale = DEFAULT_LOCALE, month = "short", day = "numeric", year = "numeric", ...options } = {}) => {
16
+ if (value == null || value === "") return "";
17
+ const date = value instanceof Date ? value : new Date(value);
18
+ if (Number.isNaN(date.getTime())) return "";
19
+ return date.toLocaleDateString(locale, {
20
+ month,
21
+ day,
22
+ year,
23
+ ...options
24
+ });
25
+ };
26
+ var formatDateTime = (value, {
27
+ locale = DEFAULT_LOCALE,
28
+ month = "short",
29
+ day = "numeric",
30
+ year = "numeric",
31
+ hour = "numeric",
32
+ minute = "2-digit",
33
+ ...options
34
+ } = {}) => {
35
+ if (value == null || value === "") return "";
36
+ const date = value instanceof Date ? value : new Date(value);
37
+ if (Number.isNaN(date.getTime())) return "";
38
+ return date.toLocaleString(locale, {
39
+ month,
40
+ day,
41
+ year,
42
+ hour,
43
+ minute,
44
+ ...options
45
+ });
46
+ };
47
+ var formatPercentage = (value, { locale = DEFAULT_LOCALE, minimumFractionDigits = 0, maximumFractionDigits = 0, ...options } = {}) => new Intl.NumberFormat(locale, {
48
+ style: "percent",
49
+ minimumFractionDigits,
50
+ maximumFractionDigits,
51
+ ...options
52
+ }).format(Number(value || 0));
53
+
54
+ // src/utils/hubspotValues.js
55
+ var isDateValueObject = (value) => Boolean(
56
+ value && typeof value === "object" && typeof value.year === "number" && typeof value.month === "number" && typeof value.date === "number"
57
+ );
58
+ var isTimeValueObject = (value) => Boolean(
59
+ value && typeof value === "object" && typeof value.hours === "number" && typeof value.minutes === "number"
60
+ );
61
+ var isDateTimeValueObject = (value) => Boolean(
62
+ value && typeof value === "object" && (value.date == null || isDateValueObject(value.date)) && (value.time == null || isTimeValueObject(value.time))
63
+ );
64
+
65
+ // src/utils/options.js
66
+ var buildOptions = (items, { labelKey = "label", valueKey = "value", descriptionKey, mapLabel, mapValue, mapDescription } = {}) => (items || []).map((item) => {
67
+ const label = mapLabel ? mapLabel(item) : (item == null ? void 0 : item[labelKey]) ?? item;
68
+ const value = mapValue ? mapValue(item) : (item == null ? void 0 : item[valueKey]) ?? item;
69
+ const description = descriptionKey ? item == null ? void 0 : item[descriptionKey] : void 0;
70
+ const mappedDescription = mapDescription ? mapDescription(item) : description;
71
+ return mappedDescription == null ? { label, value } : { label, value, description: mappedDescription };
72
+ });
73
+ var findOptionLabel = (options, value, fallback = "") => {
74
+ const match = (options || []).find((option) => (option == null ? void 0 : option.value) === value);
75
+ return (match == null ? void 0 : match.label) ?? fallback;
76
+ };
77
+
78
+ // src/utils/tagVariants.js
79
+ var DEFAULT_VARIANT = "default";
80
+ var DANGER_VARIANT = "danger";
81
+ var ERROR_VARIANT = "error";
82
+ var SUCCESS_MATCHERS = [
83
+ "active",
84
+ "success",
85
+ "succeeded",
86
+ "complete",
87
+ "completed",
88
+ "approved",
89
+ "won",
90
+ "healthy",
91
+ "enabled",
92
+ "connected",
93
+ "paid",
94
+ "live",
95
+ "published",
96
+ "available",
97
+ "synced",
98
+ "resolved"
99
+ ];
100
+ var WARNING_MATCHERS = [
101
+ "warning",
102
+ "at risk",
103
+ "risky",
104
+ "pending",
105
+ "paused",
106
+ "pause",
107
+ "on hold",
108
+ "hold",
109
+ "review",
110
+ "expiring",
111
+ "trial",
112
+ "in progress",
113
+ "awaiting",
114
+ "scheduled"
115
+ ];
116
+ var DANGER_MATCHERS = [
117
+ "danger",
118
+ "error",
119
+ "failed",
120
+ "failure",
121
+ "inactive",
122
+ "disabled",
123
+ "blocked",
124
+ "cancelled",
125
+ "canceled",
126
+ "rejected",
127
+ "denied",
128
+ "churned",
129
+ "lost",
130
+ "overdue",
131
+ "expired",
132
+ "offline",
133
+ "deleted",
134
+ "archived",
135
+ "unpaid"
136
+ ];
137
+ var INFO_MATCHERS = [
138
+ "info",
139
+ "new",
140
+ "queued",
141
+ "processing",
142
+ "progress",
143
+ "upcoming",
144
+ "draft",
145
+ "open"
146
+ ];
147
+ var normalizeTagValue = (value) => {
148
+ if (value == null) return "";
149
+ if (typeof value === "boolean") return value ? "true" : "false";
150
+ return String(value).trim().toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ");
151
+ };
152
+ var matchesAny = (value, matchers) => matchers.some((matcher) => {
153
+ if (value === matcher) return true;
154
+ return ` ${value} `.includes(` ${matcher} `);
155
+ });
156
+ var getSemanticVariant = (value, options = {}) => {
157
+ const normalized = normalizeTagValue(value);
158
+ const fallback = options.fallback || DEFAULT_VARIANT;
159
+ if (!normalized) return fallback;
160
+ if (options.overrides) {
161
+ const overrideKey = Object.keys(options.overrides).find(
162
+ (key) => normalizeTagValue(key) === normalized
163
+ );
164
+ if (overrideKey) return options.overrides[overrideKey];
165
+ }
166
+ if (normalized === "true") return "success";
167
+ if (normalized === "false") return fallback;
168
+ if (matchesAny(normalized, SUCCESS_MATCHERS)) return "success";
169
+ if (matchesAny(normalized, DANGER_MATCHERS)) return DANGER_VARIANT;
170
+ if (matchesAny(normalized, WARNING_MATCHERS)) return "warning";
171
+ if (matchesAny(normalized, INFO_MATCHERS)) return "info";
172
+ return fallback;
173
+ };
174
+ var getAutoTagVariant = (value, options = {}) => {
175
+ const semanticVariant = getSemanticVariant(value, options);
176
+ return semanticVariant === DANGER_VARIANT ? ERROR_VARIANT : semanticVariant;
177
+ };
178
+ var getAutoStatusTagVariant = (value, options = {}) => getSemanticVariant(value, options);
179
+ var getAutoTagDisplayValue = (value) => {
180
+ if (typeof value === "boolean") return value ? "True" : "False";
181
+ return value;
182
+ };
183
+ var DEFAULT_STATUS_TAG_COLOR_ORDER = [
184
+ "success",
185
+ "warning",
186
+ "danger",
187
+ "error",
188
+ "info",
189
+ "default"
190
+ ];
191
+ var createStatusTagSortComparator = (options = {}) => {
192
+ const {
193
+ variantOrder = DEFAULT_STATUS_TAG_COLOR_ORDER,
194
+ overrides,
195
+ fallback,
196
+ getLabel
197
+ } = options;
198
+ const variantIndex = (variant) => {
199
+ const idx = variantOrder.indexOf(variant);
200
+ return idx === -1 ? variantOrder.length : idx;
201
+ };
202
+ const labelOf = (value) => {
203
+ if (getLabel) return String(getLabel(value) ?? "");
204
+ if (value == null) return "";
205
+ return String(getAutoTagDisplayValue(value) ?? "");
206
+ };
207
+ return (aVal, bVal) => {
208
+ const aVariant = getSemanticVariant(aVal, { overrides, fallback });
209
+ const bVariant = getSemanticVariant(bVal, { overrides, fallback });
210
+ const diff = variantIndex(aVariant) - variantIndex(bVariant);
211
+ if (diff !== 0) return diff;
212
+ return labelOf(aVal).localeCompare(labelOf(bVal));
213
+ };
214
+ };
215
+ export {
216
+ buildOptions,
217
+ createStatusTagSortComparator,
218
+ findOptionLabel,
219
+ formatCurrency,
220
+ formatDate,
221
+ formatDateTime,
222
+ formatPercentage,
223
+ getAutoStatusTagVariant,
224
+ getAutoTagDisplayValue,
225
+ getAutoTagVariant,
226
+ isDateTimeValueObject,
227
+ isDateValueObject,
228
+ isTimeValueObject,
229
+ sumBy
230
+ };
package/index.d.ts CHANGED
@@ -51,3 +51,24 @@ export type {
51
51
  FormBuilderRef,
52
52
  FieldTypePlugin,
53
53
  } from "./packages/form/index";
54
+
55
+ export { AutoTag, AutoStatusTag, KeyValueList, SectionHeader } from "./common-components";
56
+ export {
57
+ getAutoTagVariant,
58
+ getAutoStatusTagVariant,
59
+ createStatusTagSortComparator,
60
+ } from "./utils";
61
+ export type {
62
+ AutoTagOptions,
63
+ AutoTagVariant,
64
+ AutoStatusTagOptions,
65
+ AutoStatusTagVariant,
66
+ StatusTagSortComparatorOptions,
67
+ } from "./utils";
68
+ export type {
69
+ AutoTagProps,
70
+ AutoStatusTagProps,
71
+ KeyValueListItem,
72
+ KeyValueListProps,
73
+ SectionHeaderProps,
74
+ } from "./common-components";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hs-uix",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Production-ready UI components for HubSpot UI Extensions — DataTable, FormBuilder, and more",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
@@ -21,6 +21,16 @@
21
21
  "types": "./form.d.ts",
22
22
  "import": "./dist/form.mjs",
23
23
  "require": "./dist/form.js"
24
+ },
25
+ "./common-components": {
26
+ "types": "./common-components.d.ts",
27
+ "import": "./dist/common-components.mjs",
28
+ "require": "./dist/common-components.js"
29
+ },
30
+ "./utils": {
31
+ "types": "./utils.d.ts",
32
+ "import": "./dist/utils.mjs",
33
+ "require": "./dist/utils.js"
24
34
  }
25
35
  },
26
36
  "files": [
@@ -28,6 +38,8 @@
28
38
  "index.d.ts",
29
39
  "datatable.d.ts",
30
40
  "form.d.ts",
41
+ "common-components.d.ts",
42
+ "utils.d.ts",
31
43
  "README.md"
32
44
  ],
33
45
  "workspaces": [
@@ -46,7 +58,7 @@
46
58
  "react": ">=18.0.0"
47
59
  },
48
60
  "devDependencies": {
49
- "@hubspot/ui-extensions": "latest",
61
+ "@hubspot/ui-extensions": "^0.12.3",
50
62
  "react": "^18.0.0",
51
63
  "tsup": "^8.0.0"
52
64
  },
package/utils.d.ts ADDED
@@ -0,0 +1,59 @@
1
+ export type AutoStatusTagVariant = "default" | "success" | "warning" | "danger" | "info";
2
+ export type AutoTagVariant = "default" | "success" | "warning" | "error" | "info";
3
+
4
+ export interface AutoTagSharedOptions<TVariant extends string> {
5
+ overrides?: Record<string, TVariant>;
6
+ fallback?: TVariant;
7
+ }
8
+
9
+ export interface AutoStatusTagOptions extends AutoTagSharedOptions<AutoStatusTagVariant> {}
10
+
11
+ export interface AutoTagOptions extends AutoTagSharedOptions<AutoTagVariant> {}
12
+
13
+ export interface FormatCurrencyOptions extends Intl.NumberFormatOptions {
14
+ locale?: string;
15
+ currency?: string;
16
+ maximumFractionDigits?: number;
17
+ }
18
+
19
+ export interface FormatDateOptions extends Intl.DateTimeFormatOptions {
20
+ locale?: string;
21
+ }
22
+
23
+ export interface BuildOptionsConfig<Item> {
24
+ labelKey?: keyof Item | string;
25
+ valueKey?: keyof Item | string;
26
+ descriptionKey?: keyof Item | string;
27
+ mapLabel?: (item: Item) => unknown;
28
+ mapValue?: (item: Item) => unknown;
29
+ mapDescription?: (item: Item) => unknown;
30
+ }
31
+
32
+ export interface BuiltOption {
33
+ label: unknown;
34
+ value: unknown;
35
+ description?: unknown;
36
+ }
37
+
38
+ export declare function getAutoTagVariant(value: unknown, options?: AutoTagOptions): AutoTagVariant;
39
+ export declare function getAutoStatusTagVariant(value: unknown, options?: AutoStatusTagOptions): AutoStatusTagVariant;
40
+ export declare function getAutoTagDisplayValue(value: unknown): unknown;
41
+
42
+ export interface StatusTagSortComparatorOptions extends AutoStatusTagOptions {
43
+ variantOrder?: readonly string[];
44
+ getLabel?: (value: unknown) => unknown;
45
+ }
46
+
47
+ export declare function createStatusTagSortComparator(
48
+ options?: StatusTagSortComparatorOptions
49
+ ): (aValue: unknown, bValue: unknown) => number;
50
+ export declare function formatCurrency(value: unknown, options?: FormatCurrencyOptions): string;
51
+ export declare function formatDate(value: unknown, options?: FormatDateOptions): string;
52
+ export declare function formatDateTime(value: unknown, options?: FormatDateOptions): string;
53
+ export declare function formatPercentage(value: unknown, options?: Intl.NumberFormatOptions & { locale?: string }): string;
54
+ export declare function buildOptions<Item = Record<string, unknown>>(items: Item[] | null | undefined, config?: BuildOptionsConfig<Item>): BuiltOption[];
55
+ export declare function findOptionLabel(options: Array<{ label?: unknown; value?: unknown }> | null | undefined, value: unknown, fallback?: string): unknown;
56
+ export declare function isDateValueObject(value: unknown): boolean;
57
+ export declare function isTimeValueObject(value: unknown): boolean;
58
+ export declare function isDateTimeValueObject(value: unknown): boolean;
59
+ export declare function sumBy<Item = Record<string, unknown>>(items: Item[] | null | undefined, keyOrFn: keyof Item | ((item: Item) => unknown)): number;