@mt-gloss/utils 0.1.149 → 0.1.151

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
@@ -4,6 +4,10 @@ export { formatValue, getValueFontSize, pickMetricTier } from './lib/formatValue
4
4
  export type { FormatValueOptions, FormattedValue, MetricTier, PickMetricTierResult } from './lib/formatValue';
5
5
  export { formatCurrency } from './lib/formatCurrency';
6
6
  export type { FormatCurrencyOptions } from './lib/formatCurrency';
7
+ export { hexToRgba, lerpHex } from './lib/color';
8
+ export { getTransitionStyle, interpolate, parseNumericValue } from './lib/cssAnimation';
9
+ export { daysBetween } from './lib/daysBetween';
10
+ export type { DaysBetweenOptions, DaysBetweenRounding } from './lib/daysBetween';
7
11
  export { formatTrend } from './lib/formatTrend';
8
12
  export type { TrendDirection, FormattedTrend } from './lib/formatTrend';
9
13
  export { formatDateRange, formatMarketDates, isMarketActive, isSameDay, isInRange, generateMarketId } from './lib/dateHelpers';
package/index.js CHANGED
@@ -1,20 +1,20 @@
1
- import { D as N, y as v, P as A, n as O, o as V, R as x, T as G, d as Y, t as w, f as z, b as k, k as C, l as H, c as B, h as Z, x as K, g as X, q as j, j as q, m as W, u as J, i as Q, v as tt, p as et, a as nt, r as rt, s as at, e as st, w as ot } from "./formatting-dHqp6ksD.js";
2
- const g = "NEXT_PUBLIC_V1_1_STATUS_MODE";
3
- function d() {
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
- }
6
- const $ = {
7
- env: g,
8
- check: d
9
- }, m = "NEXT_PUBLIC_V1_1_EDGE_HOVER_RESIZE";
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[m] === "true" : !1;
12
- }
13
- const S = {
1
+ import { D as G, y as z, P as H, n as k, o as B, R as C, T as Z, d as j, t as K, f as X, b as q, k as W, l as J, c as Q, h as tt, x as et, g as nt, q as rt, j as at, m as ot, u as st, i as it, v as ut, p as ct, a as lt, r as ft, s as gt, e as mt, w as dt } from "./formatting-dHqp6ksD.js";
2
+ const m = "NEXT_PUBLIC_V1_1_STATUS_MODE";
3
+ function $() {
4
+ return typeof globalThis < "u" && globalThis.__GLOSS_FLAGS__?.v1_1_status_mode === !0 ? !0 : typeof process < "u" && process.env ? process.env[m] === "true" : !1;
5
+ }
6
+ const p = {
14
7
  env: m,
15
- check: D
8
+ check: $
9
+ }, d = "NEXT_PUBLIC_V1_1_EDGE_HOVER_RESIZE";
10
+ function h() {
11
+ return typeof globalThis < "u" && globalThis.__GLOSS_FLAGS__?.v1_1_edge_hover_resize === !0 ? !0 : typeof process < "u" && process.env ? process.env[d] === "true" : !1;
12
+ }
13
+ const M = {
14
+ env: d,
15
+ check: h
16
16
  };
17
- function _(t, { prefix: e = "", suffix: n = "", abbreviated: s = !0, kThreshold: r = 1e3 } = {}) {
17
+ function D(t, { prefix: e = "", suffix: n = "", abbreviated: r = !0, kThreshold: o = 1e3 } = {}) {
18
18
  if (t == null) {
19
19
  const l = e ? `${e} —${n}` : `—${n}`;
20
20
  return { display: l.trim(), full: l.trim(), length: l.trim().length };
@@ -24,12 +24,12 @@ function _(t, { prefix: e = "", suffix: n = "", abbreviated: s = !0, kThreshold:
24
24
  const u = `${e}${t}${n}`;
25
25
  return { display: u, full: u, length: u.length };
26
26
  }
27
- let o;
28
- s !== !1 && Math.abs(a) >= 1e6 ? o = (a / 1e6).toFixed(1).replace(/\.0$/, "") + "M" : s !== !1 && Math.abs(a) >= r ? o = (a / 1e3).toFixed(1).replace(/\.0$/, "") + "K" : o = a.toLocaleString("en-US");
29
- const i = `${e}${o}${n}`, c = `${e}${a.toLocaleString("en-US")}${n}`;
27
+ let s;
28
+ r !== !1 && Math.abs(a) >= 1e6 ? s = (a / 1e6).toFixed(1).replace(/\.0$/, "") + "M" : r !== !1 && Math.abs(a) >= o ? s = (a / 1e3).toFixed(1).replace(/\.0$/, "") + "K" : s = a.toLocaleString("en-US");
29
+ const i = `${e}${s}${n}`, c = `${e}${a.toLocaleString("en-US")}${n}`;
30
30
  return { display: i, full: c, length: i.length };
31
31
  }
32
- function p(t, e) {
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
35
  const f = {
@@ -40,104 +40,147 @@ const f = {
40
40
  3: 12
41
41
  // "$1,234,567"
42
42
  };
43
- function h(t) {
43
+ function _(t) {
44
44
  return t <= 1 ? f[1] : t >= 3 ? f[3] : f[t] ?? f[1];
45
45
  }
46
- function E(t, e = {}, n = 1) {
47
- const s = h(n), r = e.prefix ?? "", a = e.suffix ?? "", o = typeof t == "number" ? t : parseFloat(String(t ?? "").replace(/,/g, ""));
48
- if (t != null && !Number.isNaN(o)) {
49
- const c = `${r}${o.toLocaleString("en-US", { minimumFractionDigits: Number.isInteger(o) ? 0 : 2, maximumFractionDigits: 2 })}${a}`;
50
- if (c.length <= s) return { formatted: c, tier: "wide", length: c.length };
51
- const u = `${r}${Math.round(o).toLocaleString("en-US")}${a}`;
52
- if (u.length <= s) return { formatted: u, tier: "medium", length: u.length };
46
+ function y(t, e = {}, n = 1) {
47
+ const r = _(n), o = e.prefix ?? "", a = e.suffix ?? "", s = typeof t == "number" ? t : parseFloat(String(t ?? "").replace(/,/g, ""));
48
+ if (t != null && !Number.isNaN(s)) {
49
+ const c = `${o}${s.toLocaleString("en-US", { minimumFractionDigits: Number.isInteger(s) ? 0 : 2, maximumFractionDigits: 2 })}${a}`;
50
+ if (c.length <= r) return { formatted: c, tier: "wide", length: c.length };
51
+ const u = `${o}${Math.round(s).toLocaleString("en-US")}${a}`;
52
+ if (u.length <= r) return { formatted: u, tier: "medium", length: u.length };
53
53
  }
54
- const i = _(t, { ...e, abbreviated: !0 });
55
- return i.display.length <= s ? { formatted: i.display, tier: "narrow", length: i.display.length } : { formatted: i.display, tier: "very-narrow", length: i.display.length };
54
+ const i = D(t, { ...e, abbreviated: !0 });
55
+ return i.display.length <= r ? { formatted: i.display, tier: "narrow", length: i.display.length } : { formatted: i.display, tier: "very-narrow", length: i.display.length };
56
56
  }
57
- function y(t, { notation: e = "standard", fractionDigits: n, currency: s = "USD" } = {}) {
58
- const r = { style: "currency", currency: s };
57
+ function T(t, { notation: e = "standard", fractionDigits: n, currency: r = "USD" } = {}) {
58
+ const o = { style: "currency", currency: r };
59
59
  if (e === "compact")
60
- r.notation = "compact", r.compactDisplay = "short", n !== void 0 && (r.minimumFractionDigits = n, r.maximumFractionDigits = n);
60
+ o.notation = "compact", o.compactDisplay = "short", n !== void 0 && (o.minimumFractionDigits = n, o.maximumFractionDigits = n);
61
61
  else {
62
62
  const a = n ?? 2;
63
- r.minimumFractionDigits = a, r.maximumFractionDigits = a;
63
+ o.minimumFractionDigits = a, o.maximumFractionDigits = a;
64
64
  }
65
- return new Intl.NumberFormat("en-US", r).format(t);
65
+ return new Intl.NumberFormat("en-US", o).format(t);
66
+ }
67
+ function g(t) {
68
+ const e = t.replace("#", "");
69
+ return [
70
+ parseInt(e.slice(0, 2), 16),
71
+ parseInt(e.slice(2, 4), 16),
72
+ parseInt(e.slice(4, 6), 16)
73
+ ];
74
+ }
75
+ function b(t, e) {
76
+ const n = t.replace("#", "");
77
+ if (!/^[0-9a-fA-F]{6}$/.test(n))
78
+ return `rgba(0,0,0,${e})`;
79
+ const [r, o, a] = g(t);
80
+ return `rgba(${r},${o},${a},${e})`;
81
+ }
82
+ function F(t, e, n) {
83
+ const r = Math.max(0, Math.min(1, n)), [o, a, s] = g(t), [i, c, u] = g(e);
84
+ return `rgb(${Math.round(o + (i - o) * r)}, ${Math.round(a + (c - a) * r)}, ${Math.round(
85
+ s + (u - s) * r
86
+ )})`;
87
+ }
88
+ function R(t, e = 200, n = "cubic-bezier(0, 0, 0.2, 1)") {
89
+ return t.map((r) => `${r} ${e}ms ${n}`).join(", ");
90
+ }
91
+ function P(t, e, n) {
92
+ return t + (e - t) * n;
93
+ }
94
+ function I(t) {
95
+ const e = t.match(/^([-\d.]+)(.*)$/);
96
+ return e ? { value: parseFloat(e[1]), unit: e[2] || "" } : { value: 0, unit: "" };
97
+ }
98
+ const S = 1e3 * 60 * 60 * 24;
99
+ function L(t, e, n = {}) {
100
+ const { rounding: r = "round", inclusive: o = !1, min: a, absolute: s = !0 } = n, i = e.getTime() - t.getTime(), u = (s ? Math.abs(i) : i) / S;
101
+ let l = r === "ceil" ? Math.ceil(u) : r === "floor" ? Math.floor(u) : r === "round" ? Math.round(u) : u;
102
+ return o && (l += 1), a !== void 0 && (l = Math.max(l, a)), l;
66
103
  }
67
- function T(t) {
104
+ function v(t) {
68
105
  if (t == null || t === 0)
69
106
  return { text: "0%", direction: "flat" };
70
107
  const e = t > 0 ? "up" : t < 0 ? "down" : "flat", n = Math.abs(t);
71
108
  return { text: n >= 3 ? `${Math.round(n)}%` : `${n.toFixed(1)}%`, direction: e };
72
109
  }
73
- function F(t, e) {
110
+ function U(t, e) {
74
111
  if (!t || !e) return "";
75
- const n = t.toLocaleDateString("en-US", { month: "short" }), s = e.toLocaleDateString("en-US", { month: "short" }), r = t.getDate(), a = e.getDate(), o = t.getFullYear(), i = e.getFullYear();
76
- return t.getTime() === e.getTime() || n === s && r === a && o === i ? `${n} ${r}, ${o}` : n === s && o === i ? `${n} ${r}–${a}` : o === i ? `${n} ${r} – ${s} ${a}` : `${n} ${r}, ${o} – ${s} ${a}, ${i}`;
112
+ const n = t.toLocaleDateString("en-US", { month: "short" }), r = e.toLocaleDateString("en-US", { month: "short" }), o = t.getDate(), a = e.getDate(), s = t.getFullYear(), i = e.getFullYear();
113
+ return t.getTime() === e.getTime() || n === r && o === a && s === i ? `${n} ${o}, ${s}` : n === r && s === i ? `${n} ${o}–${a}` : s === i ? `${n} ${o} – ${r} ${a}` : `${n} ${o}, ${s} – ${r} ${a}, ${i}`;
77
114
  }
78
- function M(t, e) {
79
- const n = t.toLocaleDateString("en-US", { month: "short" }), s = e.toLocaleDateString("en-US", { month: "short" }), r = t.getDate(), a = e.getDate();
80
- return n === s ? `${n} ${r}–${a}` : `${n} ${r} – ${s} ${a}`;
115
+ function N(t, e) {
116
+ const n = t.toLocaleDateString("en-US", { month: "short" }), r = e.toLocaleDateString("en-US", { month: "short" }), o = t.getDate(), a = e.getDate();
117
+ return n === r ? `${n} ${o}–${a}` : `${n} ${o} – ${r} ${a}`;
81
118
  }
82
- function R(t, e = /* @__PURE__ */ new Date()) {
119
+ function A(t, e = /* @__PURE__ */ new Date()) {
83
120
  return !t?.startDate || !t?.endDate ? !1 : e >= t.startDate && e <= t.endDate;
84
121
  }
85
- function P(t, e) {
122
+ function V(t, e) {
86
123
  return !t || !e ? !1 : t.getFullYear() === e.getFullYear() && t.getMonth() === e.getMonth() && t.getDate() === e.getDate();
87
124
  }
88
- function b(t, e, n) {
125
+ function x(t, e, n) {
89
126
  if (!t || !e || !n) return !1;
90
- const s = t.getTime(), r = e.getTime(), a = n.getTime();
91
- return s >= Math.min(r, a) && s <= Math.max(r, a);
127
+ const r = t.getTime(), o = e.getTime(), a = n.getTime();
128
+ return r >= Math.min(o, a) && r <= Math.max(o, a);
92
129
  }
93
- function L() {
130
+ function O() {
94
131
  return `custom-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
95
132
  }
96
133
  export {
97
- N as DEFAULT_MARKET_PRESETS,
98
- v as DEFAULT_PINNED,
99
- A as PERIOD_OPTIONS,
100
- O as PRESET_ID_MAP,
101
- V as PRESET_ID_REVERSE_MAP,
102
- x as ROLLING_OPTIONS,
103
- G as TODAY_PRESET,
104
- m as V1_1_EDGE_HOVER_RESIZE_ENV,
105
- g as V1_1_STATUS_MODE_ENV,
106
- Y as detectPreset,
107
- w as findPreset,
108
- y as formatCurrency,
109
- F as formatDateRange,
110
- z as formatDateRangeSmart,
111
- k as formatDateRangeWithPreset,
112
- C as formatDuration,
113
- M as formatMarketDates,
114
- H as formatPreset,
115
- B as formatShortYear,
116
- Z as formatSingleDate,
117
- T as formatTrend,
118
- _ as formatValue,
119
- L as generateMarketId,
120
- K as getAllPresets,
121
- X as getDateRangeDisplayInfo,
122
- j as getDateRangeForPreset,
123
- q as getDurationDays,
124
- W as getPresetDateRange,
125
- J as getPresetLabel,
126
- p as getValueFontSize,
127
- D as isEdgeHoverResizeEnabled,
128
- b as isInRange,
129
- R as isMarketActive,
130
- P as isSameDay,
131
- d as isStatusModeEnabled,
132
- Q as isValidDateRangeFormat,
133
- tt as normalizePresetId,
134
- et as parseDateRange,
135
- E as pickMetricTier,
136
- nt as resolveEvent,
137
- rt as resolvePreset,
138
- at as smartDateFormat,
139
- st as stripLeadingZeros,
140
- ot as toUppercasePresetId,
141
- S as v1_1_edge_hover_resize,
142
- $ as v1_1_status_mode
134
+ G as DEFAULT_MARKET_PRESETS,
135
+ z as DEFAULT_PINNED,
136
+ H as PERIOD_OPTIONS,
137
+ k as PRESET_ID_MAP,
138
+ B as PRESET_ID_REVERSE_MAP,
139
+ C as ROLLING_OPTIONS,
140
+ Z as TODAY_PRESET,
141
+ d as V1_1_EDGE_HOVER_RESIZE_ENV,
142
+ m as V1_1_STATUS_MODE_ENV,
143
+ L as daysBetween,
144
+ j as detectPreset,
145
+ K as findPreset,
146
+ T as formatCurrency,
147
+ U as formatDateRange,
148
+ X as formatDateRangeSmart,
149
+ q as formatDateRangeWithPreset,
150
+ W as formatDuration,
151
+ N as formatMarketDates,
152
+ J as formatPreset,
153
+ Q as formatShortYear,
154
+ tt as formatSingleDate,
155
+ v as formatTrend,
156
+ D as formatValue,
157
+ O as generateMarketId,
158
+ et as getAllPresets,
159
+ nt as getDateRangeDisplayInfo,
160
+ rt as getDateRangeForPreset,
161
+ at as getDurationDays,
162
+ ot as getPresetDateRange,
163
+ st as getPresetLabel,
164
+ R as getTransitionStyle,
165
+ E as getValueFontSize,
166
+ b as hexToRgba,
167
+ P as interpolate,
168
+ h as isEdgeHoverResizeEnabled,
169
+ x as isInRange,
170
+ A as isMarketActive,
171
+ V as isSameDay,
172
+ $ as isStatusModeEnabled,
173
+ it as isValidDateRangeFormat,
174
+ F as lerpHex,
175
+ ut as normalizePresetId,
176
+ ct as parseDateRange,
177
+ I as parseNumericValue,
178
+ y as pickMetricTier,
179
+ lt as resolveEvent,
180
+ ft as resolvePreset,
181
+ gt as smartDateFormat,
182
+ mt as stripLeadingZeros,
183
+ dt as toUppercasePresetId,
184
+ M as v1_1_edge_hover_resize,
185
+ p as v1_1_status_mode
143
186
  };
package/lib/color.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Convert a 6-digit hex color to an `rgba(r,g,b,a)` string.
3
+ *
4
+ * Guards against malformed input: a value that is not exactly 6 hex digits
5
+ * (after stripping a leading `#`) returns a safe transparent fallback
6
+ * `rgba(0,0,0,${alpha})` rather than throwing. Callers should pre-resolve
7
+ * semantic color names to hex before calling.
8
+ *
9
+ * @example
10
+ * import { hexToRgba } from '@mt-gloss/utils';
11
+ * hexToRgba('#10b981', 0.2) // 'rgba(16,185,129,0.2)'
12
+ * hexToRgba('nope', 0.5) // 'rgba(0,0,0,0.5)'
13
+ */
14
+ export declare function hexToRgba(hex: string, alpha: number): string;
15
+ /**
16
+ * Linearly interpolate between two `#rrggbb` hex colors, returning `rgb(r, g, b)`.
17
+ *
18
+ * `t` is clamped to `[0, 1]`; `t = 0` yields `from`, `t = 1` yields `to`.
19
+ * Channels are rounded to the nearest integer.
20
+ *
21
+ * @example
22
+ * import { lerpHex } from '@mt-gloss/utils';
23
+ * lerpHex('#000000', '#ffffff', 0.5) // 'rgb(128, 128, 128)'
24
+ */
25
+ export declare function lerpHex(from: string, to: string, t: number): string;
26
+ //# sourceMappingURL=color.d.ts.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Build a CSS `transition` shorthand from a list of properties.
3
+ *
4
+ * Defaults (`200ms`, `cubic-bezier(0, 0, 0.2, 1)`) are inlined literals rather
5
+ * than `@mt-gloss/tokens` reads: `utils` is a leaf package and must not depend
6
+ * on `tokens`. The values mirror the `durations.normal` / `easings.easeOut`
7
+ * design tokens; callers that need a tokenized curve pass it explicitly.
8
+ *
9
+ * @example
10
+ * import { getTransitionStyle } from '@mt-gloss/utils';
11
+ * getTransitionStyle(['opacity', 'transform']) // 'opacity 200ms cubic-bezier(0, 0, 0.2, 1), transform 200ms cubic-bezier(0, 0, 0.2, 1)'
12
+ * getTransitionStyle(['width'], 300, 'linear') // 'width 300ms linear'
13
+ */
14
+ export declare function getTransitionStyle(properties: string[], duration?: number, easing?: string): string;
15
+ /**
16
+ * Linearly interpolate between two numbers by `progress` (0–1, unclamped).
17
+ *
18
+ * @example
19
+ * import { interpolate } from '@mt-gloss/utils';
20
+ * interpolate(0, 100, 0.25) // 25
21
+ */
22
+ export declare function interpolate(from: number, to: number, progress: number): number;
23
+ /**
24
+ * Parse a CSS dimension string (e.g. `"8px"`) into its numeric value and unit.
25
+ * Unparseable input yields `{ value: 0, unit: '' }`.
26
+ *
27
+ * @example
28
+ * import { parseNumericValue } from '@mt-gloss/utils';
29
+ * parseNumericValue('8px') // { value: 8, unit: 'px' }
30
+ * parseNumericValue('1.5e') // { value: 1.5, unit: 'e' }
31
+ */
32
+ export declare function parseNumericValue(value: string): {
33
+ value: number;
34
+ unit: string;
35
+ };
36
+ //# sourceMappingURL=cssAnimation.d.ts.map
@@ -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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mt-gloss/utils",
3
- "version": "0.1.149",
3
+ "version": "0.1.151",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"