@asteby/metacore-runtime-react 46.2.0 → 46.2.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 46.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 712f605: fix(runtime-react): una columna con `display: date` que guarda un INSTANTE (timestamptz, p. ej. `invoice_date`) se pinta en la zona horaria de la organización y no en UTC (PIT-025). Con zona de la org, `formatDateCell` fijaba a UTC toda celda de día, así que una factura de la tarde del 29-sep en México (30-sep 00:41Z) aparecía como «30 de septiembre». Solo `YYYY-MM-DD` o medianoche UTC exacta (`isCalendarDayValue`) se siguen tratando como día de calendario.
8
+
3
9
  ## 46.2.0
4
10
 
5
11
  ### Minor Changes
@@ -1,4 +1,12 @@
1
1
  /** Parse a calendar day ("YYYY-MM-DD…" or any Date-parseable value) into a
2
2
  * local Date at noon, or undefined when empty/invalid. */
3
3
  export declare function parseCalendarDate(v: unknown): Date | undefined;
4
+ /**
5
+ * True when a serialized value is a pure CALENDAR DAY: `YYYY-MM-DD`, or that day at
6
+ * exactly UTC midnight (how the backend serves a `date` column). Anything with a
7
+ * real time of day is an INSTANT: a `timestamptz` shown with a day-only renderer
8
+ * must be read in the organization's zone, or an evening invoice (29 Sep 19:41 in
9
+ * Mexico City = 30 Sep 00:41Z) shows as the 30th (PIT-025).
10
+ */
11
+ export declare function isCalendarDayValue(v: unknown): boolean;
4
12
  //# sourceMappingURL=calendar-date.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"calendar-date.d.ts","sourceRoot":"","sources":["../src/calendar-date.ts"],"names":[],"mappings":"AAKA;2DAC2D;AAC3D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAQ9D"}
1
+ {"version":3,"file":"calendar-date.d.ts","sourceRoot":"","sources":["../src/calendar-date.ts"],"names":[],"mappings":"AAKA;2DAC2D;AAC3D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAQ9D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAGtD"}
@@ -16,3 +16,15 @@ export function parseCalendarDate(v) {
16
16
  const d = new Date(s);
17
17
  return isNaN(d.getTime()) ? undefined : d;
18
18
  }
19
+ /**
20
+ * True when a serialized value is a pure CALENDAR DAY: `YYYY-MM-DD`, or that day at
21
+ * exactly UTC midnight (how the backend serves a `date` column). Anything with a
22
+ * real time of day is an INSTANT: a `timestamptz` shown with a day-only renderer
23
+ * must be read in the organization's zone, or an evening invoice (29 Sep 19:41 in
24
+ * Mexico City = 30 Sep 00:41Z) shows as the 30th (PIT-025).
25
+ */
26
+ export function isCalendarDayValue(v) {
27
+ if (typeof v !== 'string')
28
+ return false;
29
+ return /^\d{4}-\d{2}-\d{2}(?:[T ]00:00:00(?:\.0+)?(?:Z|\+00:00)?)?$/.test(v.trim());
30
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  // argument so the SDK stays free of environment-bound code.
15
15
  import * as React from 'react';
16
16
  import { format } from 'date-fns';
17
- import { parseCalendarDate } from './calendar-date';
17
+ import { isCalendarDayValue, parseCalendarDate } from './calendar-date';
18
18
  import { es, enUS } from 'date-fns/locale';
19
19
  import { Calendar, Check, Copy, Mail, Minus, MoreHorizontal } from 'lucide-react';
20
20
  import { Avatar, AvatarFallback, AvatarImage, Badge, Button, Checkbox, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, InitialsAvatar, } from '@asteby/metacore-ui';
@@ -373,10 +373,13 @@ export function formatDateCell(value, renderAs, locale, timeZone) {
373
373
  }).format(date),
374
374
  };
375
375
  }
376
- // Pure calendar date: pin to UTC so it never shifts across zones.
376
+ // Pure calendar date: pin to UTC so it never shifts across zones. A value
377
+ // with a real time of day is an instant even under a day-only renderer
378
+ // (timestamptz columns like invoice_date): show ITS day in the org zone.
379
+ const calendarDay = typeof value !== 'string' || isCalendarDayValue(value);
377
380
  return {
378
381
  display: new Intl.DateTimeFormat(localeTag, {
379
- timeZone: 'UTC',
382
+ timeZone: calendarDay ? 'UTC' : timeZone,
380
383
  dateStyle: 'long',
381
384
  }).format(date),
382
385
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "46.2.0",
3
+ "version": "46.2.1",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest'
2
2
  import { es } from 'date-fns/locale'
3
- import { parseCalendarDate } from '../calendar-date'
3
+ import { isCalendarDayValue, parseCalendarDate } from '../calendar-date'
4
4
  import { formatDateCell } from '../dynamic-columns'
5
5
 
6
6
  describe('parseCalendarDate', () => {
@@ -20,3 +20,16 @@ describe('parseCalendarDate', () => {
20
20
  expect(formatDateCell('2026-09-27T00:00:00Z', 'date', es)?.display).toContain('27')
21
21
  })
22
22
  })
23
+
24
+ describe('isCalendarDayValue', () => {
25
+ it('día de calendario: YYYY-MM-DD o medianoche UTC', () => {
26
+ for (const v of ['2026-09-27', '2026-09-27T00:00:00Z', '2026-09-27T00:00:00.000Z', '2026-09-27 00:00:00', '2026-09-27T00:00:00+00:00']) {
27
+ expect(isCalendarDayValue(v)).toBe(true)
28
+ }
29
+ })
30
+ it('un instante con hora, vacío o no-string NO lo es', () => {
31
+ for (const v of ['2026-09-30T00:41:06Z', '2026-09-27T00:00:01Z', '2026-09-27T05:00:00Z', '', null, undefined, 123, new Date()]) {
32
+ expect(isCalendarDayValue(v)).toBe(false)
33
+ }
34
+ })
35
+ })
@@ -75,5 +75,20 @@ describe('formatDateCell', () => {
75
75
  expect(out!.display).not.toMatch(/\d{1,2}:\d{2}/)
76
76
  expect(out!.title).toBeUndefined()
77
77
  })
78
+
79
+ // PIT-025: invoice_date is a timestamptz shown with the day-only renderer.
80
+ // 2026-09-30T00:41:06Z is the 29th (18:41) in Mexico City: an evening
81
+ // invoice must not roll to the 30th.
82
+ it('renders a `date` column that holds an INSTANT in the org zone, not UTC', () => {
83
+ const out = formatDateCell('2026-09-30T00:41:06Z', 'date', enUS, 'America/Mexico_City')
84
+ expect(out!.display).toMatch(/September 29, 2026/)
85
+ expect(out!.title).toBeUndefined()
86
+ })
87
+
88
+ it('keeps UTC-midnight and YYYY-MM-DD as calendar days', () => {
89
+ for (const v of ['2026-09-27T00:00:00Z', '2026-09-27T00:00:00.000Z', '2026-09-27']) {
90
+ expect(formatDateCell(v, 'date', enUS, 'America/Mexico_City')!.display).toMatch(/September 27, 2026/)
91
+ }
92
+ })
78
93
  })
79
94
  })
@@ -14,3 +14,15 @@ export function parseCalendarDate(v: unknown): Date | undefined {
14
14
  const d = new Date(s)
15
15
  return isNaN(d.getTime()) ? undefined : d
16
16
  }
17
+
18
+ /**
19
+ * True when a serialized value is a pure CALENDAR DAY: `YYYY-MM-DD`, or that day at
20
+ * exactly UTC midnight (how the backend serves a `date` column). Anything with a
21
+ * real time of day is an INSTANT: a `timestamptz` shown with a day-only renderer
22
+ * must be read in the organization's zone, or an evening invoice (29 Sep 19:41 in
23
+ * Mexico City = 30 Sep 00:41Z) shows as the 30th (PIT-025).
24
+ */
25
+ export function isCalendarDayValue(v: unknown): boolean {
26
+ if (typeof v !== 'string') return false
27
+ return /^\d{4}-\d{2}-\d{2}(?:[T ]00:00:00(?:\.0+)?(?:Z|\+00:00)?)?$/.test(v.trim())
28
+ }
@@ -15,7 +15,7 @@
15
15
  import * as React from 'react'
16
16
  import { ColumnDef } from '@tanstack/react-table'
17
17
  import { format, type Locale } from 'date-fns'
18
- import { parseCalendarDate } from './calendar-date'
18
+ import { isCalendarDayValue, parseCalendarDate } from './calendar-date'
19
19
  import { es, enUS } from 'date-fns/locale'
20
20
  import { Calendar, Check, Copy, Mail, Minus, MoreHorizontal } from 'lucide-react'
21
21
  import {
@@ -525,10 +525,13 @@ export function formatDateCell(
525
525
  }).format(date),
526
526
  }
527
527
  }
528
- // Pure calendar date: pin to UTC so it never shifts across zones.
528
+ // Pure calendar date: pin to UTC so it never shifts across zones. A value
529
+ // with a real time of day is an instant even under a day-only renderer
530
+ // (timestamptz columns like invoice_date): show ITS day in the org zone.
531
+ const calendarDay = typeof value !== 'string' || isCalendarDayValue(value)
529
532
  return {
530
533
  display: new Intl.DateTimeFormat(localeTag, {
531
- timeZone: 'UTC',
534
+ timeZone: calendarDay ? 'UTC' : timeZone,
532
535
  dateStyle: 'long',
533
536
  }).format(date),
534
537
  }