@nkootstra/block-kit 0.3.1 → 0.3.2

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/dist/index.js CHANGED
@@ -6285,6 +6285,39 @@ const TIME_ZONE_LABELS = {
6285
6285
  function timeZoneLabel(timeZone) {
6286
6286
  return TIME_ZONE_LABELS[timeZone] ?? timeZone;
6287
6287
  }
6288
+ /** A timestamp's wall-clock date ("2026-01-01") and time ("11:00") in `timeZone`. */
6289
+ function wallClock(ts, timeZone) {
6290
+ const parts = new Intl.DateTimeFormat("en-US", {
6291
+ timeZone,
6292
+ year: "numeric",
6293
+ month: "2-digit",
6294
+ day: "2-digit",
6295
+ hour: "2-digit",
6296
+ minute: "2-digit",
6297
+ hourCycle: "h23"
6298
+ }).formatToParts(/* @__PURE__ */ new Date(ts * 1e3));
6299
+ const get = (type) => parts.find((p) => p.type === type)?.value ?? "00";
6300
+ return {
6301
+ date: `${get("year")}-${get("month")}-${get("day")}`,
6302
+ time: `${get("hour")}:${get("minute")}`
6303
+ };
6304
+ }
6305
+ /** The timestamp of a wall-clock date and time in `timeZone`. Around a daylight saving change it
6306
+ * resolves like JavaScript's `Date`: a time the clocks skip moves forward by the gap, and a time
6307
+ * they repeat takes its first occurrence. */
6308
+ function fromWallClock(date, time, timeZone) {
6309
+ const asUtc = Date.parse(`${date}T${time}:00Z`) / 1e3;
6310
+ const offsetAt = (ts) => {
6311
+ const wall = wallClock(ts, timeZone);
6312
+ return Date.parse(`${wall.date}T${wall.time}:00Z`) / 1e3 - ts;
6313
+ };
6314
+ const before = asUtc - offsetAt(asUtc - 86400);
6315
+ const matches = [before, asUtc - offsetAt(asUtc + 86400)].filter((ts) => {
6316
+ const wall = wallClock(ts, timeZone);
6317
+ return wall.date === date && wall.time === time;
6318
+ });
6319
+ return matches.length > 0 ? Math.min(...matches) : before;
6320
+ }
6288
6321
  //#endregion
6289
6322
  //#region src/elements/inputBlockContext.ts
6290
6323
  /** True while rendering the element of an `input` block, where Slack lays some elements out differently. */
@@ -6470,16 +6503,6 @@ function DatePicker({ element, blockId }) {
6470
6503
  }
6471
6504
  //#endregion
6472
6505
  //#region src/elements/DateTimePicker.tsx
6473
- function toISODate(ts) {
6474
- return (/* @__PURE__ */ new Date(ts * 1e3)).toISOString().slice(0, 10);
6475
- }
6476
- function toHM(ts) {
6477
- const d = /* @__PURE__ */ new Date(ts * 1e3);
6478
- return `${String(d.getUTCHours()).padStart(2, "0")}:${String(d.getUTCMinutes()).padStart(2, "0")}`;
6479
- }
6480
- function combine(date, time) {
6481
- return Math.floor((/* @__PURE__ */ new Date(`${date}T${time}:00Z`)).getTime() / 1e3);
6482
- }
6483
6506
  /** Slack's Builder splits a datetimepicker's closed control into a date box ("January 1st,
6484
6507
  * 2026") and a separate time box ("11:00 AM"), rather than one combined string. */
6485
6508
  function formatDate(ts, timeZone) {
@@ -6488,7 +6511,7 @@ function formatDate(ts, timeZone) {
6488
6511
  month: "long",
6489
6512
  day: "numeric",
6490
6513
  year: "numeric",
6491
- timeZone: timeZone ?? "UTC"
6514
+ timeZone
6492
6515
  }).formatToParts(d);
6493
6516
  const month = parts.find((p) => p.type === "month")?.value ?? "";
6494
6517
  const day = Number(parts.find((p) => p.type === "day")?.value ?? "1");
@@ -6499,7 +6522,7 @@ function formatTime$1(ts, timeZone) {
6499
6522
  return (/* @__PURE__ */ new Date(ts * 1e3)).toLocaleString("en-US", {
6500
6523
  hour: "numeric",
6501
6524
  minute: "2-digit",
6502
- timeZone: timeZone ?? "UTC"
6525
+ timeZone
6503
6526
  });
6504
6527
  }
6505
6528
  function DateTimePicker({ element, blockId }) {
@@ -6507,8 +6530,10 @@ function DateTimePicker({ element, blockId }) {
6507
6530
  const { ask, dialog } = useConfirm(element.confirm);
6508
6531
  const [value, setValueState] = useState(element.initial_date_time);
6509
6532
  const [open, setOpen] = useState(false);
6510
- const [draftDate, setDraftDate] = useState(element.initial_date_time ? toISODate(element.initial_date_time) : void 0);
6511
- const [draftTime, setDraftTime] = useState(element.initial_date_time ? toHM(element.initial_date_time) : "12:00");
6533
+ const zone = timeZone ?? "UTC";
6534
+ const initial = element.initial_date_time !== void 0 ? wallClock(element.initial_date_time, zone) : void 0;
6535
+ const [draftDate, setDraftDate] = useState(initial?.date);
6536
+ const [draftTime, setDraftTime] = useState(initial?.time ?? "12:00");
6512
6537
  const rootRef = useRef(null);
6513
6538
  const focusRef = useFocusOnLoad(element);
6514
6539
  const actionId = element.action_id ?? "";
@@ -6521,7 +6546,7 @@ function DateTimePicker({ element, blockId }) {
6521
6546
  async function apply() {
6522
6547
  if (!draftDate) return;
6523
6548
  if (!await ask()) return;
6524
- const ts = combine(draftDate, draftTime);
6549
+ const ts = fromWallClock(draftDate, draftTime, zone);
6525
6550
  setValueState(ts);
6526
6551
  setOpen(false);
6527
6552
  setValue(blockId, actionId, {
@@ -6552,7 +6577,7 @@ function DateTimePicker({ element, blockId }) {
6552
6577
  /* @__PURE__ */ jsx(CalendarIcon, { className: "sbk-datetimepicker__icon" }),
6553
6578
  /* @__PURE__ */ jsx("span", {
6554
6579
  className: value !== void 0 ? "sbk-datetimepicker__value" : "sbk-datetimepicker__placeholder",
6555
- children: value !== void 0 ? formatDate(value, timeZone) : "Select a date"
6580
+ children: value !== void 0 ? formatDate(value, zone) : "Select a date"
6556
6581
  }),
6557
6582
  /* @__PURE__ */ jsx(ChevronDownIcon, { className: "sbk-datetimepicker__chevron" })
6558
6583
  ]
@@ -6567,13 +6592,13 @@ function DateTimePicker({ element, blockId }) {
6567
6592
  /* @__PURE__ */ jsx(ClockIcon, { className: "sbk-datetimepicker__icon" }),
6568
6593
  /* @__PURE__ */ jsx("span", {
6569
6594
  className: value !== void 0 ? "sbk-datetimepicker__value" : "sbk-datetimepicker__placeholder",
6570
- children: value !== void 0 ? formatTime$1(value, timeZone) : "Select a time"
6595
+ children: value !== void 0 ? formatTime$1(value, zone) : "Select a time"
6571
6596
  }),
6572
6597
  /* @__PURE__ */ jsx(ChevronDownIcon, { className: "sbk-datetimepicker__chevron" })
6573
6598
  ]
6574
6599
  }), /* @__PURE__ */ jsxs("p", {
6575
6600
  className: "sbk-datetimepicker__timezone",
6576
- children: ["Time zone: ", timeZoneLabel(timeZone ?? "UTC")]
6601
+ children: ["Time zone: ", timeZoneLabel(zone)]
6577
6602
  })]
6578
6603
  })]
6579
6604
  }),