@mt-gloss/utils 0.1.148 → 0.1.150

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
@@ -2,6 +2,10 @@ export { isStatusModeEnabled, v1_1_status_mode, V1_1_STATUS_MODE_ENV, isEdgeHove
2
2
  export type { PresetDefinition, MarketPreset, DateRange, MarketEvent } from './lib/types';
3
3
  export { formatValue, getValueFontSize, pickMetricTier } from './lib/formatValue';
4
4
  export type { FormatValueOptions, FormattedValue, MetricTier, PickMetricTierResult } from './lib/formatValue';
5
+ export { formatCurrency } from './lib/formatCurrency';
6
+ export type { FormatCurrencyOptions } from './lib/formatCurrency';
7
+ export { daysBetween } from './lib/daysBetween';
8
+ export type { DaysBetweenOptions, DaysBetweenRounding } from './lib/daysBetween';
5
9
  export { formatTrend } from './lib/formatTrend';
6
10
  export type { TrendDirection, FormattedTrend } from './lib/formatTrend';
7
11
  export { formatDateRange, formatMarketDates, isMarketActive, isSameDay, isInRange, generateMarketId } from './lib/dateHelpers';
package/index.js CHANGED
@@ -1,38 +1,38 @@
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";
1
+ import { D as A, y as O, P as V, n as x, o as Y, R as w, T as G, d as z, t as k, f as B, b as C, k as H, l as Z, c as K, h as X, x as j, g as q, q as W, j as J, m as Q, u as tt, i as et, v as nt, p as rt, a as at, r as ot, s as st, e as it, w as ut } from "./formatting-dHqp6ksD.js";
2
2
  const g = "NEXT_PUBLIC_V1_1_STATUS_MODE";
3
- function _() {
3
+ function d() {
4
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
7
  env: g,
8
- check: _
8
+ check: d
9
9
  }, m = "NEXT_PUBLIC_V1_1_EDGE_HOVER_RESIZE";
10
10
  function D() {
11
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
- const S = {
13
+ const p = {
14
14
  env: m,
15
15
  check: D
16
16
  };
17
- function d(t, { prefix: e = "", suffix: n = "", abbreviated: a = !0, kThreshold: s = 1e3 } = {}) {
17
+ function _(t, { prefix: e = "", suffix: n = "", abbreviated: o = !0, kThreshold: a = 1e3 } = {}) {
18
18
  if (t == null) {
19
- const l = e ? `${e} —${n}` : `—${n}`;
20
- return { display: l.trim(), full: l.trim(), length: l.trim().length };
19
+ const c = e ? `${e} —${n}` : `—${n}`;
20
+ return { display: c.trim(), full: c.trim(), length: c.trim().length };
21
21
  }
22
22
  const r = typeof t == "number" ? t : parseFloat(String(t).replace(/,/g, ""));
23
23
  if (isNaN(r)) {
24
24
  const u = `${e}${t}${n}`;
25
25
  return { display: u, full: u, length: u.length };
26
26
  }
27
- let o;
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 = `${e}${o}${n}`, c = `${e}${r.toLocaleString("en-US")}${n}`;
30
- return { display: i, full: c, length: i.length };
27
+ let s;
28
+ o !== !1 && Math.abs(r) >= 1e6 ? s = (r / 1e6).toFixed(1).replace(/\.0$/, "") + "M" : o !== !1 && Math.abs(r) >= a ? s = (r / 1e3).toFixed(1).replace(/\.0$/, "") + "K" : s = r.toLocaleString("en-US");
29
+ const i = `${e}${s}${n}`, f = `${e}${r.toLocaleString("en-US")}${n}`;
30
+ return { display: i, full: f, length: i.length };
31
31
  }
32
32
  function E(t, e) {
33
33
  return (e ?? 1) >= 2 ? t <= 4 || t <= 6 ? 30 : t <= 8 ? 24 : 20 : t <= 5 ? 28 : t <= 8 ? 20 : 17;
34
34
  }
35
- const f = {
35
+ const l = {
36
36
  1: 5,
37
37
  // "$2.7K", "12K", "$5", "100%"
38
38
  2: 8,
@@ -41,92 +41,110 @@ const f = {
41
41
  // "$1,234,567"
42
42
  };
43
43
  function h(t) {
44
- return t <= 1 ? f[1] : t >= 3 ? f[3] : f[t] ?? f[1];
44
+ return t <= 1 ? l[1] : t >= 3 ? l[3] : l[t] ?? l[1];
45
45
  }
46
- function p(t, e = {}, n = 1) {
47
- const a = h(n), s = e.prefix ?? "", r = e.suffix ?? "", o = typeof t == "number" ? t : parseFloat(String(t ?? "").replace(/,/g, ""));
48
- if (t != null && !Number.isNaN(o)) {
49
- const c = `${s}${o.toLocaleString("en-US", { minimumFractionDigits: Number.isInteger(o) ? 0 : 2, maximumFractionDigits: 2 })}${r}`;
50
- if (c.length <= a) return { formatted: c, tier: "wide", length: c.length };
51
- const u = `${s}${Math.round(o).toLocaleString("en-US")}${r}`;
52
- if (u.length <= a) return { formatted: u, tier: "medium", length: u.length };
46
+ function M(t, e = {}, n = 1) {
47
+ const o = h(n), a = e.prefix ?? "", r = e.suffix ?? "", s = typeof t == "number" ? t : parseFloat(String(t ?? "").replace(/,/g, ""));
48
+ if (t != null && !Number.isNaN(s)) {
49
+ const f = `${a}${s.toLocaleString("en-US", { minimumFractionDigits: Number.isInteger(s) ? 0 : 2, maximumFractionDigits: 2 })}${r}`;
50
+ if (f.length <= o) return { formatted: f, tier: "wide", length: f.length };
51
+ const u = `${a}${Math.round(s).toLocaleString("en-US")}${r}`;
52
+ if (u.length <= o) return { formatted: u, tier: "medium", length: u.length };
53
53
  }
54
- const i = d(t, { ...e, abbreviated: !0 });
55
- return i.display.length <= a ? { formatted: i.display, tier: "narrow", length: i.display.length } : { formatted: i.display, tier: "very-narrow", length: i.display.length };
54
+ const i = _(t, { ...e, abbreviated: !0 });
55
+ return i.display.length <= o ? { formatted: i.display, tier: "narrow", length: i.display.length } : { formatted: i.display, tier: "very-narrow", length: i.display.length };
56
56
  }
57
- function T(t) {
57
+ function y(t, { notation: e = "standard", fractionDigits: n, currency: o = "USD" } = {}) {
58
+ const a = { style: "currency", currency: o };
59
+ if (e === "compact")
60
+ a.notation = "compact", a.compactDisplay = "short", n !== void 0 && (a.minimumFractionDigits = n, a.maximumFractionDigits = n);
61
+ else {
62
+ const r = n ?? 2;
63
+ a.minimumFractionDigits = r, a.maximumFractionDigits = r;
64
+ }
65
+ return new Intl.NumberFormat("en-US", a).format(t);
66
+ }
67
+ const S = 1e3 * 60 * 60 * 24;
68
+ function T(t, e, n = {}) {
69
+ const { rounding: o = "round", inclusive: a = !1, min: r, absolute: s = !0 } = n, i = e.getTime() - t.getTime(), u = (s ? Math.abs(i) : i) / S;
70
+ let c = o === "ceil" ? Math.ceil(u) : o === "floor" ? Math.floor(u) : o === "round" ? Math.round(u) : u;
71
+ return a && (c += 1), r !== void 0 && (c = Math.max(c, r)), c;
72
+ }
73
+ function R(t) {
58
74
  if (t == null || t === 0)
59
75
  return { text: "0%", direction: "flat" };
60
76
  const e = t > 0 ? "up" : t < 0 ? "down" : "flat", n = Math.abs(t);
61
77
  return { text: n >= 3 ? `${Math.round(n)}%` : `${n.toFixed(1)}%`, direction: e };
62
78
  }
63
- function y(t, e) {
79
+ function F(t, e) {
64
80
  if (!t || !e) return "";
65
- 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();
66
- 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}`;
81
+ const n = t.toLocaleDateString("en-US", { month: "short" }), o = e.toLocaleDateString("en-US", { month: "short" }), a = t.getDate(), r = e.getDate(), s = t.getFullYear(), i = e.getFullYear();
82
+ return t.getTime() === e.getTime() || n === o && a === r && s === i ? `${n} ${a}, ${s}` : n === o && s === i ? `${n} ${a}–${r}` : s === i ? `${n} ${a} – ${o} ${r}` : `${n} ${a}, ${s} – ${o} ${r}, ${i}`;
67
83
  }
68
- function M(t, e) {
69
- const n = t.toLocaleDateString("en-US", { month: "short" }), a = e.toLocaleDateString("en-US", { month: "short" }), s = t.getDate(), r = e.getDate();
70
- return n === a ? `${n} ${s}–${r}` : `${n} ${s} – ${a} ${r}`;
84
+ function P(t, e) {
85
+ const n = t.toLocaleDateString("en-US", { month: "short" }), o = e.toLocaleDateString("en-US", { month: "short" }), a = t.getDate(), r = e.getDate();
86
+ return n === o ? `${n} ${a}–${r}` : `${n} ${a} – ${o} ${r}`;
71
87
  }
72
- function R(t, e = /* @__PURE__ */ new Date()) {
88
+ function b(t, e = /* @__PURE__ */ new Date()) {
73
89
  return !t?.startDate || !t?.endDate ? !1 : e >= t.startDate && e <= t.endDate;
74
90
  }
75
- function P(t, e) {
91
+ function L(t, e) {
76
92
  return !t || !e ? !1 : t.getFullYear() === e.getFullYear() && t.getMonth() === e.getMonth() && t.getDate() === e.getDate();
77
93
  }
78
- function F(t, e, n) {
94
+ function I(t, e, n) {
79
95
  if (!t || !e || !n) return !1;
80
- const a = t.getTime(), s = e.getTime(), r = n.getTime();
81
- return a >= Math.min(s, r) && a <= Math.max(s, r);
96
+ const o = t.getTime(), a = e.getTime(), r = n.getTime();
97
+ return o >= Math.min(a, r) && o <= Math.max(a, r);
82
98
  }
83
- function L() {
99
+ function U() {
84
100
  return `custom-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
85
101
  }
86
102
  export {
87
- U as DEFAULT_MARKET_PRESETS,
88
- N as DEFAULT_PINNED,
89
- v as PERIOD_OPTIONS,
90
- A as PRESET_ID_MAP,
91
- O as PRESET_ID_REVERSE_MAP,
92
- V as ROLLING_OPTIONS,
103
+ A as DEFAULT_MARKET_PRESETS,
104
+ O as DEFAULT_PINNED,
105
+ V as PERIOD_OPTIONS,
106
+ x as PRESET_ID_MAP,
107
+ Y as PRESET_ID_REVERSE_MAP,
108
+ w as ROLLING_OPTIONS,
93
109
  G as TODAY_PRESET,
94
110
  m as V1_1_EDGE_HOVER_RESIZE_ENV,
95
111
  g as V1_1_STATUS_MODE_ENV,
96
- Y as detectPreset,
97
- x as findPreset,
98
- y as formatDateRange,
99
- z as formatDateRangeSmart,
100
- k as formatDateRangeWithPreset,
101
- w as formatDuration,
102
- M as formatMarketDates,
103
- H as formatPreset,
104
- B as formatShortYear,
105
- C as formatSingleDate,
106
- T as formatTrend,
107
- d as formatValue,
108
- L as generateMarketId,
109
- Z as getAllPresets,
110
- K as getDateRangeDisplayInfo,
111
- X as getDateRangeForPreset,
112
- j as getDurationDays,
113
- q as getPresetDateRange,
114
- W as getPresetLabel,
112
+ T as daysBetween,
113
+ z as detectPreset,
114
+ k as findPreset,
115
+ y as formatCurrency,
116
+ F as formatDateRange,
117
+ B as formatDateRangeSmart,
118
+ C as formatDateRangeWithPreset,
119
+ H as formatDuration,
120
+ P as formatMarketDates,
121
+ Z as formatPreset,
122
+ K as formatShortYear,
123
+ X as formatSingleDate,
124
+ R as formatTrend,
125
+ _ as formatValue,
126
+ U as generateMarketId,
127
+ j as getAllPresets,
128
+ q as getDateRangeDisplayInfo,
129
+ W as getDateRangeForPreset,
130
+ J as getDurationDays,
131
+ Q as getPresetDateRange,
132
+ tt as getPresetLabel,
115
133
  E as getValueFontSize,
116
134
  D as isEdgeHoverResizeEnabled,
117
- F as isInRange,
118
- R as isMarketActive,
119
- P as isSameDay,
120
- _ as isStatusModeEnabled,
121
- J as isValidDateRangeFormat,
122
- Q as normalizePresetId,
123
- tt as parseDateRange,
124
- p as pickMetricTier,
125
- et as resolveEvent,
126
- nt as resolvePreset,
127
- rt as smartDateFormat,
128
- at as stripLeadingZeros,
129
- st as toUppercasePresetId,
130
- S as v1_1_edge_hover_resize,
135
+ I as isInRange,
136
+ b as isMarketActive,
137
+ L as isSameDay,
138
+ d as isStatusModeEnabled,
139
+ et as isValidDateRangeFormat,
140
+ nt as normalizePresetId,
141
+ rt as parseDateRange,
142
+ M as pickMetricTier,
143
+ at as resolveEvent,
144
+ ot as resolvePreset,
145
+ st as smartDateFormat,
146
+ it as stripLeadingZeros,
147
+ ut as toUppercasePresetId,
148
+ p as v1_1_edge_hover_resize,
131
149
  $ as v1_1_status_mode
132
150
  };
@@ -0,0 +1,36 @@
1
+ export type DaysBetweenRounding = 'ceil' | 'floor' | 'round' | 'none';
2
+ export interface DaysBetweenOptions {
3
+ /** Rounding applied to the raw day fraction. `'none'` returns the fraction. Default `'round'`. */
4
+ rounding?: DaysBetweenRounding;
5
+ /** Add `+1` AFTER rounding to count both endpoints (e.g. `floor(x) + 1`). Default `false`. */
6
+ inclusive?: boolean;
7
+ /** Clamp the final result up to this floor (e.g. `1` to reproduce `… || 1`). Default none. */
8
+ min?: number;
9
+ /** `Math.abs` the millisecond diff so argument order is irrelevant. Default `true`. */
10
+ absolute?: boolean;
11
+ }
12
+ /**
13
+ * Day span between two dates, with explicit rounding/inclusivity/clamping.
14
+ *
15
+ * One configurable helper for the dashboard's several day-span computations,
16
+ * each of which carries a distinct mode. Order of operations is load-bearing:
17
+ * round → `+1` (inclusive) → `Math.max(min)`.
18
+ *
19
+ * Rules:
20
+ * - `rounding: 'none'` returns the raw fractional day count (callers that threshold on a non-integer).
21
+ * - `inclusive: true` adds `1` after rounding (counts both endpoints).
22
+ * - `min` clamps the final value up (e.g. `min: 1` turns a `0`-day span into `1`).
23
+ * - `absolute: true` (default) uses `|end − start|`; pass `false` for a signed difference.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { daysBetween } from '@mt-gloss/utils';
28
+ *
29
+ * const a = new Date('2026-01-01'), b = new Date('2026-01-04');
30
+ * daysBetween(a, b); // 3
31
+ * daysBetween(a, b, { rounding: 'floor', inclusive: true }); // 4 (both endpoints)
32
+ * daysBetween(a, a, { rounding: 'ceil', min: 1 }); // 1
33
+ * ```
34
+ */
35
+ export declare function daysBetween(start: Date, end: Date, opts?: DaysBetweenOptions): number;
36
+ //# sourceMappingURL=daysBetween.d.ts.map
@@ -0,0 +1,35 @@
1
+ export interface FormatCurrencyOptions {
2
+ /** `'standard'` (default) → grouped full amount; `'compact'` → `$22K` / `$1.2M`. */
3
+ notation?: 'standard' | 'compact';
4
+ /**
5
+ * Sets BOTH the minimum and maximum fraction digits.
6
+ * - standard: defaults to `2` (`$1,234.56`); pass `0` for whole dollars (`$18,000`).
7
+ * - compact: when omitted, uses Intl's compact default (`$1.2M`, never `$1.20M`).
8
+ */
9
+ fractionDigits?: number;
10
+ /** ISO 4217 currency code. Default `'USD'`. */
11
+ currency?: string;
12
+ }
13
+ /**
14
+ * Format a number as a localized currency string (pure, `en-US`).
15
+ *
16
+ * Subsumes the dashboard's three string currency formatters: the default
17
+ * 2-decimal grouped form, the compact `$K`/`$M` form, and the whole-dollar
18
+ * pace form — each selected via options, behavior-preserving.
19
+ *
20
+ * Rules:
21
+ * - `notation: 'standard'` (default): `minimumFractionDigits === maximumFractionDigits === fractionDigits` (default `2`).
22
+ * - `notation: 'compact'`: `compactDisplay: 'short'`; fraction digits left to Intl unless `fractionDigits` is passed.
23
+ * - Locale is fixed to `en-US`; `currency` defaults to `USD`.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { formatCurrency } from '@mt-gloss/utils';
28
+ *
29
+ * formatCurrency(1234.5); // '$1,234.50'
30
+ * formatCurrency(1200000, { notation: 'compact' }); // '$1.2M'
31
+ * formatCurrency(18000, { fractionDigits: 0 }); // '$18,000'
32
+ * ```
33
+ */
34
+ export declare function formatCurrency(value: number, { notation, fractionDigits, currency }?: FormatCurrencyOptions): string;
35
+ //# sourceMappingURL=formatCurrency.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mt-gloss/utils",
3
- "version": "0.1.148",
3
+ "version": "0.1.150",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"