@pushwoosh/dumb-components 2.1.1 → 2.2.0

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.
@@ -1,4 +1,4 @@
1
- import { canonicalizeTimezone, findTimezoneOption, formatTimezoneLabel, formatTimezoneOffset, formatTimezoneShort, getTimezoneOffsetSafe, listTimezones, resolveTimezoneOption } from '../timezones';
1
+ import { canonicalizeTimezone, findTimezoneOption, formatTimezoneLabel, formatTimezoneOffset, formatTimezoneAbbreviation, formatTimezoneBadge, formatTimezoneShort, getTimezoneOffsetSafe, listTimezones, resolveTimezoneOption } from '../timezones';
2
2
  const winter = new Date('2026-01-15T12:00:00Z');
3
3
  const melbourneDst = new Date('2026-10-10T12:00:00Z');
4
4
  const melbourneStandard = new Date('2026-06-15T12:00:00Z');
@@ -24,6 +24,41 @@ describe('formatTimezoneShort', () => {
24
24
  expect(formatTimezoneShort('Not/AZone', winter)).toBe('Not/AZone');
25
25
  });
26
26
  });
27
+ describe('formatTimezoneAbbreviation', () => {
28
+ it('returns the letter abbreviation where the engine has one', () => {
29
+ expect(formatTimezoneAbbreviation('America/New_York', winter)).toBe('EST');
30
+ expect(formatTimezoneAbbreviation('America/Los_Angeles', winter)).toBe('PST');
31
+ });
32
+ it('returns null where the engine only offers a GMT-style name', () => {
33
+ expect(formatTimezoneAbbreviation('Asia/Karachi', winter)).toBeNull();
34
+ expect(formatTimezoneAbbreviation('Asia/Kolkata', winter)).toBeNull();
35
+ expect(formatTimezoneAbbreviation('Europe/Moscow', winter)).toBeNull();
36
+ });
37
+ it('returns null for UTC and for a zone it does not know', () => {
38
+ expect(formatTimezoneAbbreviation('UTC', winter)).toBeNull();
39
+ expect(formatTimezoneAbbreviation('Not/AZone', winter)).toBeNull();
40
+ });
41
+ it('follows DST at the given instant', () => {
42
+ expect(formatTimezoneAbbreviation('America/New_York', new Date('2026-07-01T12:00:00Z'))).toBe('EDT');
43
+ });
44
+ });
45
+ describe('formatTimezoneBadge', () => {
46
+ it('pairs the abbreviation with the offset', () => {
47
+ expect(formatTimezoneBadge('America/New_York', winter)).toBe('EST (UTC-05:00)');
48
+ });
49
+ it('falls back to the bare offset for a zone without an abbreviation', () => {
50
+ expect(formatTimezoneBadge('Asia/Karachi', winter)).toBe('UTC+05:00');
51
+ expect(formatTimezoneBadge('Asia/Kolkata', winter)).toBe('UTC+05:30');
52
+ expect(formatTimezoneBadge('UTC', winter)).toBe('UTC+00:00');
53
+ });
54
+ it('follows DST at the given instant', () => {
55
+ expect(formatTimezoneBadge('Australia/Melbourne', melbourneStandard)).toBe('UTC+10:00');
56
+ expect(formatTimezoneBadge('Australia/Melbourne', melbourneDst)).toBe('UTC+11:00');
57
+ });
58
+ it('keeps an unknown zone readable', () => {
59
+ expect(formatTimezoneBadge('Not/AZone', winter)).toBe('Not/AZone');
60
+ });
61
+ });
27
62
  describe('formatTimezoneLabel', () => {
28
63
  it('uses the current tzdata: Kazakhstan is UTC+5 since 2024', () => {
29
64
  expect(formatTimezoneLabel('Asia/Almaty', winter)).toBe('(UTC+05:00) Asia/Almaty');
@@ -15,6 +15,10 @@ export declare function formatTimezoneOffset(minutes: number): string;
15
15
  export declare function formatTimezoneLabel(timezone: string, at?: Date): string;
16
16
  /** Compact badge for a zone, `UTC+05:00`; a zone the engine doesn't know is shown by its bare name. */
17
17
  export declare function formatTimezoneShort(timezone: string, at?: Date): string;
18
+ /** Letter abbreviation of the zone at `at` (`EST`, `PKT`), or `null` when the engine only offers a `GMT+5`-style name or does not know the zone. */
19
+ export declare function formatTimezoneAbbreviation(timezone: string, at?: Date): string | null;
20
+ /** Badge naming the zone a time is shown in: `PKT (UTC+05:00)`, or the bare offset when the zone has no letter abbreviation. */
21
+ export declare function formatTimezoneBadge(timezone: string, at?: Date): string;
18
22
  /** Option for any stored zone name — aliases, `Etc/GMT±N`, POSIX abbreviations — kept verbatim as the value. */
19
23
  export declare function resolveTimezoneOption(timezone: string, at?: Date): TimezoneOption;
20
24
  /** Zones the browser knows plus `UTC` and every non-empty `include` value, sorted by offset at `at` then by name. Pass the stored value as `include` so an old alias stays selectable and is re-saved unchanged. */
@@ -40,6 +40,25 @@ export function formatTimezoneShort(timezone, at = new Date()) {
40
40
  const offset = getTimezoneOffsetSafe(timezone, at);
41
41
  return offset === null ? timezone : formatTimezoneOffset(offset);
42
42
  }
43
+ /** Letter abbreviation of the zone at `at` (`EST`, `PKT`), or `null` when the engine only offers a `GMT+5`-style name or does not know the zone. */
44
+ export function formatTimezoneAbbreviation(timezone, at = new Date()) {
45
+ try {
46
+ const parts = new Intl.DateTimeFormat('en-US', {
47
+ timeZone: timezone,
48
+ timeZoneName: 'short'
49
+ }).formatToParts(at);
50
+ const name = parts.find(part => part.type === 'timeZoneName')?.value ?? '';
51
+ return /^[A-Z]{2,5}$/.test(name) && name !== 'UTC' ? name : null;
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+ /** Badge naming the zone a time is shown in: `PKT (UTC+05:00)`, or the bare offset when the zone has no letter abbreviation. */
57
+ export function formatTimezoneBadge(timezone, at = new Date()) {
58
+ const short = formatTimezoneShort(timezone, at);
59
+ const abbreviation = formatTimezoneAbbreviation(timezone, at);
60
+ return abbreviation ? `${abbreviation} (${short})` : short;
61
+ }
43
62
  /** Option for any stored zone name — aliases, `Etc/GMT±N`, POSIX abbreviations — kept verbatim as the value. */
44
63
  export function resolveTimezoneOption(timezone, at = new Date()) {
45
64
  return {
package/index.d.ts CHANGED
@@ -59,4 +59,4 @@ export { ApplicationPreloader, type ApplicationPreloaderProps, } from './Applica
59
59
  export { NotificationInbox, NotificationBar, NotificationBell, type Notification, type NotificationInboxProps, type NotificationSeverity, type NotificationBarType, type NotificationBarProps, type NotificationBellProps, } from './NotificationInbox';
60
60
  export { LeafletTheme } from './LeafletTheme';
61
61
  export { buildBarcodeUrl, barcodePlaceholderSafeEscape, isBarcodePlaceholder, type BarcodeSymbology, type BarcodeUrlParams, } from './helpers/barcodeUrl';
62
- export { canonicalizeTimezone, findTimezoneOption, formatTimezoneLabel, formatTimezoneOffset, formatTimezoneShort, getBrowserTimezone, getTimezoneOffsetSafe, listTimezones, resolveTimezoneOption, type TimezoneOption, } from './helpers/timezones';
62
+ export { canonicalizeTimezone, findTimezoneOption, formatTimezoneAbbreviation, formatTimezoneBadge, formatTimezoneLabel, formatTimezoneOffset, formatTimezoneShort, getBrowserTimezone, getTimezoneOffsetSafe, listTimezones, resolveTimezoneOption, type TimezoneOption, } from './helpers/timezones';
package/index.js CHANGED
@@ -57,4 +57,4 @@ export { ApplicationPreloader } from './ApplicationPreloader';
57
57
  export { NotificationInbox, NotificationBar, NotificationBell } from './NotificationInbox';
58
58
  export { LeafletTheme } from './LeafletTheme';
59
59
  export { buildBarcodeUrl, barcodePlaceholderSafeEscape, isBarcodePlaceholder } from './helpers/barcodeUrl';
60
- export { canonicalizeTimezone, findTimezoneOption, formatTimezoneLabel, formatTimezoneOffset, formatTimezoneShort, getBrowserTimezone, getTimezoneOffsetSafe, listTimezones, resolveTimezoneOption } from './helpers/timezones';
60
+ export { canonicalizeTimezone, findTimezoneOption, formatTimezoneAbbreviation, formatTimezoneBadge, formatTimezoneLabel, formatTimezoneOffset, formatTimezoneShort, getBrowserTimezone, getTimezoneOffsetSafe, listTimezones, resolveTimezoneOption } from './helpers/timezones';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/dumb-components",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "description": "React components to build Pushwoosh products",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -42,7 +42,7 @@
42
42
  "@lezer/highlight": "^1.2.1",
43
43
  "@pushwoosh/kit-constants": "^2.0.0",
44
44
  "@pushwoosh/kit-helpers": "^4.12.5",
45
- "@pushwoosh/kit-icons": "^2.1.16",
45
+ "@pushwoosh/kit-icons": "^2.3.3",
46
46
  "@pushwoosh/kit-typography": "^1.8.5",
47
47
  "@tippyjs/react": "^4.2.6",
48
48
  "@uiw/codemirror-themes": "^4.23.8",