@mt-gloss/utils 0.1.151 → 0.1.152

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
@@ -8,6 +8,7 @@ export { hexToRgba, lerpHex } from './lib/color';
8
8
  export { getTransitionStyle, interpolate, parseNumericValue } from './lib/cssAnimation';
9
9
  export { daysBetween } from './lib/daysBetween';
10
10
  export type { DaysBetweenOptions, DaysBetweenRounding } from './lib/daysBetween';
11
+ export { toLocalCalendarDate } from './lib/toLocalCalendarDate';
11
12
  export { formatTrend } from './lib/formatTrend';
12
13
  export type { TrendDirection, FormattedTrend } from './lib/formatTrend';
13
14
  export { formatDateRange, formatMarketDates, isMarketActive, isSameDay, isInRange, generateMarketId } from './lib/dateHelpers';
package/index.js CHANGED
@@ -1,18 +1,18 @@
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";
1
+ import { D as G, y as z, P as H, n as k, o as B, R as Z, T as j, d as K, t as X, f as q, b as W, k as J, l as Q, c as tt, h as et, x as nt, g as rt, q as at, j as ot, m as st, u as it, i as ut, v as ct, p as lt, a as ft, r as gt, s as mt, e as dt, w as ht } from "./formatting-dHqp6ksD.js";
2
2
  const m = "NEXT_PUBLIC_V1_1_STATUS_MODE";
3
- function $() {
3
+ function h() {
4
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
5
  }
6
6
  const p = {
7
7
  env: m,
8
- check: $
8
+ check: h
9
9
  }, d = "NEXT_PUBLIC_V1_1_EDGE_HOVER_RESIZE";
10
- function h() {
10
+ function $() {
11
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
12
  }
13
13
  const M = {
14
14
  env: d,
15
- check: h
15
+ check: $
16
16
  };
17
17
  function D(t, { prefix: e = "", suffix: n = "", abbreviated: r = !0, kThreshold: o = 1e3 } = {}) {
18
18
  if (t == null) {
@@ -43,7 +43,7 @@ const f = {
43
43
  function _(t) {
44
44
  return t <= 1 ? f[1] : t >= 3 ? f[3] : f[t] ?? f[1];
45
45
  }
46
- function y(t, e = {}, n = 1) {
46
+ function T(t, e = {}, n = 1) {
47
47
  const r = _(n), o = e.prefix ?? "", a = e.suffix ?? "", s = typeof t == "number" ? t : parseFloat(String(t ?? "").replace(/,/g, ""));
48
48
  if (t != null && !Number.isNaN(s)) {
49
49
  const c = `${o}${s.toLocaleString("en-US", { minimumFractionDigits: Number.isInteger(s) ? 0 : 2, maximumFractionDigits: 2 })}${a}`;
@@ -54,7 +54,7 @@ function y(t, e = {}, n = 1) {
54
54
  const i = D(t, { ...e, abbreviated: !0 });
55
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 T(t, { notation: e = "standard", fractionDigits: n, currency: r = "USD" } = {}) {
57
+ function y(t, { notation: e = "standard", fractionDigits: n, currency: r = "USD" } = {}) {
58
58
  const o = { style: "currency", currency: r };
59
59
  if (e === "compact")
60
60
  o.notation = "compact", o.compactDisplay = "short", n !== void 0 && (o.minimumFractionDigits = n, o.maximumFractionDigits = n);
@@ -101,33 +101,36 @@ function L(t, e, n = {}) {
101
101
  let l = r === "ceil" ? Math.ceil(u) : r === "floor" ? Math.floor(u) : r === "round" ? Math.round(u) : u;
102
102
  return o && (l += 1), a !== void 0 && (l = Math.max(l, a)), l;
103
103
  }
104
+ function U(t) {
105
+ return new Date(t.getUTCFullYear(), t.getUTCMonth(), t.getUTCDate());
106
+ }
104
107
  function v(t) {
105
108
  if (t == null || t === 0)
106
109
  return { text: "0%", direction: "flat" };
107
110
  const e = t > 0 ? "up" : t < 0 ? "down" : "flat", n = Math.abs(t);
108
111
  return { text: n >= 3 ? `${Math.round(n)}%` : `${n.toFixed(1)}%`, direction: e };
109
112
  }
110
- function U(t, e) {
113
+ function N(t, e) {
111
114
  if (!t || !e) return "";
112
115
  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
116
  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}`;
114
117
  }
115
- function N(t, e) {
118
+ function A(t, e) {
116
119
  const n = t.toLocaleDateString("en-US", { month: "short" }), r = e.toLocaleDateString("en-US", { month: "short" }), o = t.getDate(), a = e.getDate();
117
120
  return n === r ? `${n} ${o}–${a}` : `${n} ${o} – ${r} ${a}`;
118
121
  }
119
- function A(t, e = /* @__PURE__ */ new Date()) {
122
+ function V(t, e = /* @__PURE__ */ new Date()) {
120
123
  return !t?.startDate || !t?.endDate ? !1 : e >= t.startDate && e <= t.endDate;
121
124
  }
122
- function V(t, e) {
125
+ function x(t, e) {
123
126
  return !t || !e ? !1 : t.getFullYear() === e.getFullYear() && t.getMonth() === e.getMonth() && t.getDate() === e.getDate();
124
127
  }
125
- function x(t, e, n) {
128
+ function O(t, e, n) {
126
129
  if (!t || !e || !n) return !1;
127
130
  const r = t.getTime(), o = e.getTime(), a = n.getTime();
128
131
  return r >= Math.min(o, a) && r <= Math.max(o, a);
129
132
  }
130
- function O() {
133
+ function Y() {
131
134
  return `custom-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
132
135
  }
133
136
  export {
@@ -136,51 +139,52 @@ export {
136
139
  H as PERIOD_OPTIONS,
137
140
  k as PRESET_ID_MAP,
138
141
  B as PRESET_ID_REVERSE_MAP,
139
- C as ROLLING_OPTIONS,
140
- Z as TODAY_PRESET,
142
+ Z as ROLLING_OPTIONS,
143
+ j as TODAY_PRESET,
141
144
  d as V1_1_EDGE_HOVER_RESIZE_ENV,
142
145
  m as V1_1_STATUS_MODE_ENV,
143
146
  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,
147
+ K as detectPreset,
148
+ X as findPreset,
149
+ y as formatCurrency,
150
+ N as formatDateRange,
151
+ q as formatDateRangeSmart,
152
+ W as formatDateRangeWithPreset,
153
+ J as formatDuration,
154
+ A as formatMarketDates,
155
+ Q as formatPreset,
156
+ tt as formatShortYear,
157
+ et as formatSingleDate,
155
158
  v as formatTrend,
156
159
  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,
160
+ Y as generateMarketId,
161
+ nt as getAllPresets,
162
+ rt as getDateRangeDisplayInfo,
163
+ at as getDateRangeForPreset,
164
+ ot as getDurationDays,
165
+ st as getPresetDateRange,
166
+ it as getPresetLabel,
164
167
  R as getTransitionStyle,
165
168
  E as getValueFontSize,
166
169
  b as hexToRgba,
167
170
  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,
171
+ $ as isEdgeHoverResizeEnabled,
172
+ O as isInRange,
173
+ V as isMarketActive,
174
+ x as isSameDay,
175
+ h as isStatusModeEnabled,
176
+ ut as isValidDateRangeFormat,
174
177
  F as lerpHex,
175
- ut as normalizePresetId,
176
- ct as parseDateRange,
178
+ ct as normalizePresetId,
179
+ lt as parseDateRange,
177
180
  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,
181
+ T as pickMetricTier,
182
+ ft as resolveEvent,
183
+ gt as resolvePreset,
184
+ mt as smartDateFormat,
185
+ dt as stripLeadingZeros,
186
+ U as toLocalCalendarDate,
187
+ ht as toUppercasePresetId,
184
188
  M as v1_1_edge_hover_resize,
185
189
  p as v1_1_status_mode
186
190
  };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Re-project a date onto **local midnight of its UTC calendar date**.
3
+ *
4
+ * Order dates arrive from the BFF as date-only ISO strings (e.g. `"2026-03-09"`).
5
+ * `new Date("2026-03-09")` parses this as **UTC midnight**, which in timezones
6
+ * west of UTC falls on the *previous* local calendar day (e.g. March 8 at
7
+ * 19:00 EST). To bucket an order by its intended calendar day regardless of the
8
+ * viewer's timezone, both the dashboard's table filter and its chart grouping
9
+ * extract the date's **UTC** year/month/day and rebuild a `Date` at **local**
10
+ * midnight of those components. Doing this on both surfaces guarantees the
11
+ * table filter (which uses local-midnight boundaries) and the chart's UTC
12
+ * date-grouping agree on which day an order belongs to.
13
+ *
14
+ * Regress this and table totals silently disagree with chart bars: the only
15
+ * orders affected are those whose date sits on a UTC-vs-local day boundary, so
16
+ * nothing throws — the two surfaces just stop matching.
17
+ *
18
+ * Purity note: the input `Date` only needs to carry the right instant; this
19
+ * helper reads its UTC Y/M/D and nothing else. String parsing and null handling
20
+ * stay with the caller — one consumer coerces with `new Date(str)`, another with
21
+ * date-fns `parseISO` — and both delegate the projection here.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { toLocalCalendarDate } from '@mt-gloss/utils';
26
+ *
27
+ * // A date-only ISO string parses as UTC midnight; the helper re-keys it to
28
+ * // local midnight of the SAME calendar date — timezone-independent.
29
+ * const d = toLocalCalendarDate(new Date('2026-03-09'));
30
+ * d.getFullYear(); // 2026
31
+ * d.getMonth(); // 2 (March, 0-indexed)
32
+ * d.getDate(); // 9 — never the 8th, even west of UTC
33
+ * ```
34
+ */
35
+ export declare function toLocalCalendarDate(date: Date): Date;
36
+ //# sourceMappingURL=toLocalCalendarDate.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mt-gloss/utils",
3
- "version": "0.1.151",
3
+ "version": "0.1.152",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"