@mt-gloss/utils 0.1.64 → 0.1.66

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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { isStatusModeEnabled, v1_1_status_mode, V1_1_STATUS_MODE_ENV, isEdgeHoverResizeEnabled, v1_1_edge_hover_resize, V1_1_EDGE_HOVER_RESIZE_ENV } from './lib/featureFlags';
2
2
  export type { PresetDefinition, MarketPreset, DateRange, MarketEvent } from './lib/types';
3
- export { formatValue, getValueFontSize } from './lib/formatValue';
4
- export type { FormatValueOptions, FormattedValue } from './lib/formatValue';
3
+ export { formatValue, getValueFontSize, pickMetricTier } from './lib/formatValue';
4
+ export type { FormatValueOptions, FormattedValue, MetricTier, PickMetricTierResult } from './lib/formatValue';
5
5
  export { formatTrend } from './lib/formatTrend';
6
6
  export type { TrendDirection, FormattedTrend } from './lib/formatTrend';
7
7
  export { formatDateRange, formatMarketDates, isMarketActive, isSameDay, isInRange, generateMarketId } from './lib/dateHelpers';
package/index.js CHANGED
@@ -1,109 +1,134 @@
1
- import { D as v, y as F, P as I, n as O, o as U, R as V, T as b, d as A, t as N, f as Y, b as G, k as z, l as k, c as H, h as Z, x, g as B, q as C, j as K, m as X, u as j, i as q, v as W, p as J, a as Q, r as w, s as ee, e as te, w as ne } from "./formatting-dHqp6ksD.js";
2
- const l = "NEXT_PUBLIC_V1_1_STATUS_MODE";
1
+ import { D as U, y as N, P as v, n as A, o as O, R as V, T as G, d as Y, t as x, f as z, b as k, k as w, l as H, c as B, h as C, x as Z, g as K, q as X, j, m as q, u as W, i as J, v as Q, p as tt, a as et, r as nt, s as rt, e as at, w as st } from "./formatting-dHqp6ksD.js";
2
+ const g = "NEXT_PUBLIC_V1_1_STATUS_MODE";
3
3
  function _() {
4
- return typeof globalThis < "u" && globalThis.__GLOSS_FLAGS__?.v1_1_status_mode === !0 ? !0 : typeof process < "u" && process.env ? process.env[l] === "true" : !1;
4
+ return typeof globalThis < "u" && globalThis.__GLOSS_FLAGS__?.v1_1_status_mode === !0 ? !0 : typeof process < "u" && process.env ? process.env[g] === "true" : !1;
5
5
  }
6
6
  const $ = {
7
- env: l,
7
+ env: g,
8
8
  check: _
9
- }, f = "NEXT_PUBLIC_V1_1_EDGE_HOVER_RESIZE";
9
+ }, m = "NEXT_PUBLIC_V1_1_EDGE_HOVER_RESIZE";
10
10
  function D() {
11
- return typeof globalThis < "u" && globalThis.__GLOSS_FLAGS__?.v1_1_edge_hover_resize === !0 ? !0 : typeof process < "u" && process.env ? process.env[f] === "true" : !1;
11
+ return typeof globalThis < "u" && globalThis.__GLOSS_FLAGS__?.v1_1_edge_hover_resize === !0 ? !0 : typeof process < "u" && process.env ? process.env[m] === "true" : !1;
12
12
  }
13
13
  const S = {
14
- env: f,
14
+ env: m,
15
15
  check: D
16
16
  };
17
- function m(e, { prefix: t = "", suffix: n = "", abbreviated: a = !0, kThreshold: s = 1e3 } = {}) {
18
- if (e == null) {
19
- const c = t ? `${t} —${n}` : `—${n}`;
20
- return { display: c.trim(), full: c.trim(), length: c.trim().length };
17
+ function d(t, { prefix: e = "", suffix: n = "", abbreviated: a = !0, kThreshold: s = 1e3 } = {}) {
18
+ if (t == null) {
19
+ const l = e ? `${e} —${n}` : `—${n}`;
20
+ return { display: l.trim(), full: l.trim(), length: l.trim().length };
21
21
  }
22
- const r = typeof e == "number" ? e : parseFloat(String(e).replace(/,/g, ""));
22
+ const r = typeof t == "number" ? t : parseFloat(String(t).replace(/,/g, ""));
23
23
  if (isNaN(r)) {
24
- const u = `${t}${e}${n}`;
24
+ const u = `${e}${t}${n}`;
25
25
  return { display: u, full: u, length: u.length };
26
26
  }
27
27
  let o;
28
28
  a !== !1 && Math.abs(r) >= 1e6 ? o = (r / 1e6).toFixed(1).replace(/\.0$/, "") + "M" : a !== !1 && Math.abs(r) >= s ? o = (r / 1e3).toFixed(1).replace(/\.0$/, "") + "K" : o = r.toLocaleString("en-US");
29
- const i = `${t}${o}${n}`, g = `${t}${r.toLocaleString("en-US")}${n}`;
30
- return { display: i, full: g, length: i.length };
29
+ const i = `${e}${o}${n}`, c = `${e}${r.toLocaleString("en-US")}${n}`;
30
+ return { display: i, full: c, length: i.length };
31
31
  }
32
- function h(e, t) {
33
- return (t ?? 1) >= 2 ? e <= 4 || e <= 6 ? 30 : e <= 8 ? 24 : 20 : e <= 5 ? 28 : e <= 8 ? 20 : 17;
32
+ function E(t, e) {
33
+ return (e ?? 1) >= 2 ? t <= 4 || t <= 6 ? 30 : t <= 8 ? 24 : 20 : t <= 5 ? 28 : t <= 8 ? 20 : 17;
34
34
  }
35
- function E(e) {
36
- if (e == null || e === 0)
35
+ const f = {
36
+ 1: 5,
37
+ // "$2.7K", "12K", "$5", "100%"
38
+ 2: 8,
39
+ // "$2,720", "$12.5K"
40
+ 3: 12,
41
+ // "$1,234,567"
42
+ 4: 16
43
+ // "$1,234,567.89"
44
+ };
45
+ function h(t) {
46
+ return t <= 1 ? f[1] : t >= 4 ? f[4] : f[t] ?? f[1];
47
+ }
48
+ function p(t, e = {}, n = 1) {
49
+ const a = h(n), s = e.prefix ?? "", r = e.suffix ?? "", o = typeof t == "number" ? t : parseFloat(String(t ?? "").replace(/,/g, ""));
50
+ if (t != null && !Number.isNaN(o)) {
51
+ const c = `${s}${o.toLocaleString("en-US", { minimumFractionDigits: Number.isInteger(o) ? 0 : 2, maximumFractionDigits: 2 })}${r}`;
52
+ if (c.length <= a) return { formatted: c, tier: "wide", length: c.length };
53
+ const u = `${s}${Math.round(o).toLocaleString("en-US")}${r}`;
54
+ if (u.length <= a) return { formatted: u, tier: "medium", length: u.length };
55
+ }
56
+ const i = d(t, { ...e, abbreviated: !0 });
57
+ return i.display.length <= a ? { formatted: i.display, tier: "narrow", length: i.display.length } : { formatted: i.display, tier: "very-narrow", length: i.display.length };
58
+ }
59
+ function T(t) {
60
+ if (t == null || t === 0)
37
61
  return { text: "0%", direction: "flat" };
38
- const t = e > 0 ? "up" : e < 0 ? "down" : "flat", n = Math.abs(e);
39
- return { text: n >= 3 ? `${Math.round(n)}%` : `${n.toFixed(1)}%`, direction: t };
62
+ const e = t > 0 ? "up" : t < 0 ? "down" : "flat", n = Math.abs(t);
63
+ return { text: n >= 3 ? `${Math.round(n)}%` : `${n.toFixed(1)}%`, direction: e };
40
64
  }
41
- function d(e, t) {
42
- if (!e || !t) return "";
43
- const n = e.toLocaleDateString("en-US", { month: "short" }), a = t.toLocaleDateString("en-US", { month: "short" }), s = e.getDate(), r = t.getDate(), o = e.getFullYear(), i = t.getFullYear();
44
- return e.getTime() === t.getTime() || n === a && s === r && o === i ? `${n} ${s}, ${o}` : n === a && o === i ? `${n} ${s}–${r}` : o === i ? `${n} ${s} – ${a} ${r}` : `${n} ${s}, ${o} – ${a} ${r}, ${i}`;
65
+ function y(t, e) {
66
+ if (!t || !e) return "";
67
+ const n = t.toLocaleDateString("en-US", { month: "short" }), a = e.toLocaleDateString("en-US", { month: "short" }), s = t.getDate(), r = e.getDate(), o = t.getFullYear(), i = e.getFullYear();
68
+ return t.getTime() === e.getTime() || n === a && s === r && o === i ? `${n} ${s}, ${o}` : n === a && o === i ? `${n} ${s}–${r}` : o === i ? `${n} ${s} – ${a} ${r}` : `${n} ${s}, ${o} – ${a} ${r}, ${i}`;
45
69
  }
46
- function p(e, t) {
47
- const n = e.toLocaleDateString("en-US", { month: "short" }), a = t.toLocaleDateString("en-US", { month: "short" }), s = e.getDate(), r = t.getDate();
70
+ function M(t, e) {
71
+ const n = t.toLocaleDateString("en-US", { month: "short" }), a = e.toLocaleDateString("en-US", { month: "short" }), s = t.getDate(), r = e.getDate();
48
72
  return n === a ? `${n} ${s}–${r}` : `${n} ${s} – ${a} ${r}`;
49
73
  }
50
- function T(e, t = /* @__PURE__ */ new Date()) {
51
- return !e?.startDate || !e?.endDate ? !1 : t >= e.startDate && t <= e.endDate;
74
+ function R(t, e = /* @__PURE__ */ new Date()) {
75
+ return !t?.startDate || !t?.endDate ? !1 : e >= t.startDate && e <= t.endDate;
52
76
  }
53
- function P(e, t) {
54
- return !e || !t ? !1 : e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth() && e.getDate() === t.getDate();
77
+ function P(t, e) {
78
+ return !t || !e ? !1 : t.getFullYear() === e.getFullYear() && t.getMonth() === e.getMonth() && t.getDate() === e.getDate();
55
79
  }
56
- function R(e, t, n) {
57
- if (!e || !t || !n) return !1;
58
- const a = e.getTime(), s = t.getTime(), r = n.getTime();
80
+ function F(t, e, n) {
81
+ if (!t || !e || !n) return !1;
82
+ const a = t.getTime(), s = e.getTime(), r = n.getTime();
59
83
  return a >= Math.min(s, r) && a <= Math.max(s, r);
60
84
  }
61
- function M() {
85
+ function L() {
62
86
  return `custom-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
63
87
  }
64
88
  export {
65
- v as DEFAULT_MARKET_PRESETS,
66
- F as DEFAULT_PINNED,
67
- I as PERIOD_OPTIONS,
68
- O as PRESET_ID_MAP,
69
- U as PRESET_ID_REVERSE_MAP,
89
+ U as DEFAULT_MARKET_PRESETS,
90
+ N as DEFAULT_PINNED,
91
+ v as PERIOD_OPTIONS,
92
+ A as PRESET_ID_MAP,
93
+ O as PRESET_ID_REVERSE_MAP,
70
94
  V as ROLLING_OPTIONS,
71
- b as TODAY_PRESET,
72
- f as V1_1_EDGE_HOVER_RESIZE_ENV,
73
- l as V1_1_STATUS_MODE_ENV,
74
- A as detectPreset,
75
- N as findPreset,
76
- d as formatDateRange,
77
- Y as formatDateRangeSmart,
78
- G as formatDateRangeWithPreset,
79
- z as formatDuration,
80
- p as formatMarketDates,
81
- k as formatPreset,
82
- H as formatShortYear,
83
- Z as formatSingleDate,
84
- E as formatTrend,
85
- m as formatValue,
86
- M as generateMarketId,
87
- x as getAllPresets,
88
- B as getDateRangeDisplayInfo,
89
- C as getDateRangeForPreset,
90
- K as getDurationDays,
91
- X as getPresetDateRange,
92
- j as getPresetLabel,
93
- h as getValueFontSize,
95
+ G as TODAY_PRESET,
96
+ m as V1_1_EDGE_HOVER_RESIZE_ENV,
97
+ g as V1_1_STATUS_MODE_ENV,
98
+ Y as detectPreset,
99
+ x as findPreset,
100
+ y as formatDateRange,
101
+ z as formatDateRangeSmart,
102
+ k as formatDateRangeWithPreset,
103
+ w as formatDuration,
104
+ M as formatMarketDates,
105
+ H as formatPreset,
106
+ B as formatShortYear,
107
+ C as formatSingleDate,
108
+ T as formatTrend,
109
+ d as formatValue,
110
+ L as generateMarketId,
111
+ Z as getAllPresets,
112
+ K as getDateRangeDisplayInfo,
113
+ X as getDateRangeForPreset,
114
+ j as getDurationDays,
115
+ q as getPresetDateRange,
116
+ W as getPresetLabel,
117
+ E as getValueFontSize,
94
118
  D as isEdgeHoverResizeEnabled,
95
- R as isInRange,
96
- T as isMarketActive,
119
+ F as isInRange,
120
+ R as isMarketActive,
97
121
  P as isSameDay,
98
122
  _ as isStatusModeEnabled,
99
- q as isValidDateRangeFormat,
100
- W as normalizePresetId,
101
- J as parseDateRange,
102
- Q as resolveEvent,
103
- w as resolvePreset,
104
- ee as smartDateFormat,
105
- te as stripLeadingZeros,
106
- ne as toUppercasePresetId,
123
+ J as isValidDateRangeFormat,
124
+ Q as normalizePresetId,
125
+ tt as parseDateRange,
126
+ p as pickMetricTier,
127
+ et as resolveEvent,
128
+ nt as resolvePreset,
129
+ rt as smartDateFormat,
130
+ at as stripLeadingZeros,
131
+ st as toUppercasePresetId,
107
132
  S as v1_1_edge_hover_resize,
108
133
  $ as v1_1_status_mode
109
134
  };
@@ -37,4 +37,34 @@ export declare function formatValue(raw: number | string | null | undefined, { p
37
37
  * ```
38
38
  */
39
39
  export declare function getValueFontSize(length: number, colSpan?: number | null): number;
40
+ export type MetricTier = 'wide' | 'medium' | 'narrow' | 'very-narrow';
41
+ export interface PickMetricTierResult {
42
+ /** The display string at the chosen tier (e.g. `$2.7K`). */
43
+ formatted: string;
44
+ /** Which tier of the ladder produced `formatted`. Drives data-tier in MetricCard. */
45
+ tier: MetricTier;
46
+ /** `formatted.length`, for downstream `getValueFontSize`. */
47
+ length: number;
48
+ }
49
+ /**
50
+ * Walk Wide → Medium → Narrow → VeryNarrow and return the first format whose
51
+ * length fits CHAR_BUDGETS[colSpan]. Synchronous, prop-driven, content-aware.
52
+ *
53
+ * - Wide: full locale string with decimals (e.g. `$2,720.00`)
54
+ * - Medium: full locale string, no decimals (e.g. `$2,720`)
55
+ * - Narrow: alpha-suffix abbreviated (e.g. `$2.7K`)
56
+ * - VeryNarrow: alpha-suffix abbreviated; the SCSS title-clamp toggle
57
+ * fires on this tier even if VeryNarrow's string === Narrow's
58
+ *
59
+ * NOT a measurement loop. NO ResizeObserver. NO getBoundingClientRect.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * import { pickMetricTier } from '@mt-gloss/utils';
64
+ *
65
+ * const r = pickMetricTier(2720, { prefix: '$' }, 1);
66
+ * // r.tier === 'narrow', r.formatted === '$2.7K'
67
+ * ```
68
+ */
69
+ export declare function pickMetricTier(value: number | string | null | undefined, options?: FormatValueOptions, colSpan?: number): PickMetricTierResult;
40
70
  //# sourceMappingURL=formatValue.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mt-gloss/utils",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "restricted"