universal-datetime-picker 2.0.0 → 2.0.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/dist/wc/index.js CHANGED
@@ -397,23 +397,28 @@ var PickerController = class {
397
397
  this.draft = this.draft.year(day.year()).month(day.month()).date(day.date());
398
398
  this.focusedDay = day;
399
399
  this.emit();
400
+ this.maybeCommitInline();
400
401
  }
401
402
  setHour(hourValue) {
402
403
  this.draft = this.draft.hour(hourValue);
403
404
  this.emit();
405
+ this.maybeCommitInline();
404
406
  }
405
407
  setMinute(minute) {
406
408
  this.draft = this.draft.minute(minute);
407
409
  this.emit();
410
+ this.maybeCommitInline();
408
411
  }
409
412
  setSecond(second) {
410
413
  this.draft = this.draft.second(second);
411
414
  this.emit();
415
+ this.maybeCommitInline();
412
416
  }
413
417
  setAmPm(isAm) {
414
418
  const { hour } = to12Hour(this.draft.hour());
415
419
  this.draft = this.draft.hour(to24Hour(hour, isAm));
416
420
  this.emit();
421
+ this.maybeCommitInline();
417
422
  }
418
423
  toggleHours() {
419
424
  this.showHours = !this.showHours;
@@ -459,22 +464,26 @@ var PickerController = class {
459
464
  }
460
465
  this.showHours = false;
461
466
  this.emit();
467
+ this.maybeCommitInline();
462
468
  }
463
469
  selectMinuteOption(opt) {
464
470
  this.draft = this.draft.minute(Number(opt));
465
471
  this.showMinutes = false;
466
472
  this.emit();
473
+ this.maybeCommitInline();
467
474
  }
468
475
  selectSecondOption(opt) {
469
476
  this.draft = this.draft.second(Number(opt));
470
477
  this.showSecondsOpen = false;
471
478
  this.emit();
479
+ this.maybeCommitInline();
472
480
  }
473
481
  selectAmPmOption(opt) {
474
482
  const { hour } = to12Hour(this.draft.hour());
475
483
  this.draft = this.draft.hour(to24Hour(hour, opt === "AM"));
476
484
  this.showAmPm = false;
477
485
  this.emit();
486
+ this.maybeCommitInline();
478
487
  }
479
488
  handleGridKeyDown(key) {
480
489
  const snap = this.snapshot;
@@ -524,23 +533,30 @@ var PickerController = class {
524
533
  this.emit();
525
534
  return true;
526
535
  }
527
- confirm() {
536
+ buildPayload() {
528
537
  const snap = this.snapshot;
529
- let payload;
530
538
  if (snap.asString === false) {
531
539
  if (snap.mode === "time") {
532
- payload = buildTimeValue(this.draft, snap.resolvedFormat);
533
- } else if (snap.mode === "date") {
534
- payload = this.draft.startOf("day").toDate();
535
- } else {
536
- payload = this.draft.toDate();
540
+ return buildTimeValue(this.draft, snap.resolvedFormat);
537
541
  }
538
- } else {
539
- if (snap.asString === void 0) {
540
- warnAsStringDeprecation();
542
+ if (snap.mode === "date") {
543
+ return this.draft.startOf("day").toDate();
541
544
  }
542
- payload = formatValue(this.draft, snap.resolvedFormat);
545
+ return this.draft.toDate();
543
546
  }
547
+ if (snap.asString === void 0) {
548
+ warnAsStringDeprecation();
549
+ }
550
+ return formatValue(this.draft, snap.resolvedFormat);
551
+ }
552
+ maybeCommitInline() {
553
+ if (!this.options.inline) {
554
+ return;
555
+ }
556
+ this.options.onChange?.(this.buildPayload());
557
+ }
558
+ confirm() {
559
+ const payload = this.buildPayload();
544
560
  this.options.onChange?.(payload);
545
561
  this.close();
546
562
  return payload;
@@ -1132,13 +1148,15 @@ function renderPicker(controller, snap, titleId, position, options) {
1132
1148
  })
1133
1149
  );
1134
1150
  }
1135
- footerChildren.push(
1136
- el("button", {
1137
- type: "button",
1138
- onClick: () => controller.confirm(),
1139
- textContent: snap.labels.ok
1140
- })
1141
- );
1151
+ if (!snap.inline) {
1152
+ footerChildren.push(
1153
+ el("button", {
1154
+ type: "button",
1155
+ onClick: () => controller.confirm(),
1156
+ textContent: snap.labels.ok
1157
+ })
1158
+ );
1159
+ }
1142
1160
  picker.append(el("div", { className: "ctp-footer" }, footerChildren));
1143
1161
  return picker;
1144
1162
  }
@@ -1272,6 +1290,15 @@ var RangeController = class {
1272
1290
  end: parseValue(range?.end ?? null, format)
1273
1291
  };
1274
1292
  }
1293
+ sameDay(a, b) {
1294
+ if (a === null && b === null) {
1295
+ return true;
1296
+ }
1297
+ if (a === null || b === null) {
1298
+ return false;
1299
+ }
1300
+ return a.isSame(b, "day");
1301
+ }
1275
1302
  setOptions(partial) {
1276
1303
  this.options = { ...this.options, ...partial };
1277
1304
  if (partial.open !== void 0) {
@@ -1285,11 +1312,14 @@ var RangeController = class {
1285
1312
  } else if (partial.value !== void 0) {
1286
1313
  const format = this.options.format ?? DATE_FORMAT;
1287
1314
  const parsed = this.parseRange(partial.value, format);
1288
- this.start = parsed.start;
1289
- this.end = parsed.end;
1290
- if (parsed.start) {
1291
- this.viewMonth = parsed.start.startOf("month");
1292
- this.focusedDay = parsed.start;
1315
+ const unchanged = this.sameDay(parsed.start, this.start) && this.sameDay(parsed.end, this.end);
1316
+ if (!unchanged) {
1317
+ this.start = parsed.start;
1318
+ this.end = parsed.end;
1319
+ if (parsed.start) {
1320
+ this.viewMonth = parsed.start.startOf("month");
1321
+ this.focusedDay = parsed.start;
1322
+ }
1293
1323
  }
1294
1324
  }
1295
1325
  }
@@ -1421,6 +1451,11 @@ var RangeController = class {
1421
1451
  this.focusedDay = day;
1422
1452
  }
1423
1453
  this.emit();
1454
+ if (this.options.asString === false) {
1455
+ this.emitRange(this.start, this.end);
1456
+ } else if (this.options.inline && this.start && this.end) {
1457
+ this.emitRange(this.start, this.end);
1458
+ }
1424
1459
  }
1425
1460
  setHoverEnd(day) {
1426
1461
  if (this.start && !this.end) {
@@ -1540,12 +1575,51 @@ function applyStyle2(node, style) {
1540
1575
  }
1541
1576
  Object.assign(node.style, style);
1542
1577
  }
1578
+ function sameDay(a, b) {
1579
+ if (a === null && b === null) {
1580
+ return true;
1581
+ }
1582
+ if (a === null || b === null) {
1583
+ return false;
1584
+ }
1585
+ return a.isSame(b, "day");
1586
+ }
1587
+ function dayDateClassName(dayData) {
1588
+ return cx(
1589
+ "ctp-box",
1590
+ "ctp-box-date",
1591
+ !dayData.isCurrentMonth && "not-current-month",
1592
+ dayData.isDisabled && "disabled-date",
1593
+ dayData.isWeekend && "weekend-day",
1594
+ dayData.isCurrentDate && "ctp-today",
1595
+ dayData.isInRange && "ctp-in-range",
1596
+ dayData.isRangeStart && "ctp-range-start",
1597
+ dayData.isRangeEnd && "ctp-range-end"
1598
+ );
1599
+ }
1600
+ function syncDayButton(btn, dayData, snap) {
1601
+ const focused = dayData.date.isSame(snap.focusedDay, "day");
1602
+ const disabled = !dayData.isCurrentMonth || dayData.isDisabled;
1603
+ btn.className = dayDateClassName(dayData);
1604
+ btn.tabIndex = focused ? 0 : -1;
1605
+ btn.disabled = disabled;
1606
+ btn.setAttribute(
1607
+ "aria-selected",
1608
+ String(Boolean(dayData.isRangeStart || dayData.isRangeEnd))
1609
+ );
1610
+ btn.setAttribute("aria-disabled", String(disabled));
1611
+ }
1612
+ function canPatchHoverOnly(prev, next) {
1613
+ return prev.calPanel === "day" && next.calPanel === "day" && prev.viewMonth.isSame(next.viewMonth, "month") && sameDay(prev.start, next.start) && sameDay(prev.end, next.end) && prev.focusedDay.isSame(next.focusedDay, "day") && prev.open === next.open && prev.inline === next.inline;
1614
+ }
1543
1615
  function createDateTimeRangePicker(target, options = {}) {
1544
1616
  const controller = new RangeController(options);
1545
1617
  const titleId = `ctp-range-${Math.random().toString(36).slice(2, 9)}`;
1546
1618
  let cleanups = [];
1547
1619
  let host = null;
1548
1620
  let portalRoot = null;
1621
+ let lastSnap = null;
1622
+ let dayButtons = null;
1549
1623
  const teardown = () => {
1550
1624
  cleanups.forEach((c) => c());
1551
1625
  cleanups = [];
@@ -1553,13 +1627,29 @@ function createDateTimeRangePicker(target, options = {}) {
1553
1627
  portalRoot = null;
1554
1628
  host?.remove();
1555
1629
  host = null;
1630
+ lastSnap = null;
1631
+ dayButtons = null;
1556
1632
  };
1557
1633
  const paint = () => {
1558
- teardown();
1559
1634
  const snap = controller.getSnapshot();
1560
1635
  if (!snap.open && !snap.inline) {
1636
+ teardown();
1637
+ return;
1638
+ }
1639
+ if (lastSnap && dayButtons && host && canPatchHoverOnly(lastSnap, snap)) {
1640
+ for (const week of snap.weeks) {
1641
+ for (const dayData of week) {
1642
+ const key = dayData.date.format("YYYY-MM-DD");
1643
+ const btn = dayButtons.get(key);
1644
+ if (btn) {
1645
+ syncDayButton(btn, dayData, snap);
1646
+ }
1647
+ }
1648
+ }
1649
+ lastSnap = snap;
1561
1650
  return;
1562
1651
  }
1652
+ teardown();
1563
1653
  const now = dayjs__default.default();
1564
1654
  const year = snap.viewMonth.year();
1565
1655
  const windowStart = Math.floor(year / 12) * 12;
@@ -1608,6 +1698,7 @@ function createDateTimeRangePicker(target, options = {}) {
1608
1698
  ])
1609
1699
  ]);
1610
1700
  if (snap.calPanel === "day") {
1701
+ const buttons = /* @__PURE__ */ new Map();
1611
1702
  const grid = el2("div", {
1612
1703
  className: "ctp-main-calendar",
1613
1704
  role: "grid",
@@ -1618,7 +1709,8 @@ function createDateTimeRangePicker(target, options = {}) {
1618
1709
  if (controller.handleGridKeyDown(ke.key)) {
1619
1710
  ke.preventDefault();
1620
1711
  }
1621
- }
1712
+ },
1713
+ onMouseleave: () => controller.setHoverEnd(null)
1622
1714
  });
1623
1715
  for (const label of snap.weekdayLabels) {
1624
1716
  grid.append(
@@ -1633,47 +1725,38 @@ function createDateTimeRangePicker(target, options = {}) {
1633
1725
  for (const dayData of week) {
1634
1726
  const focused = dayData.date.isSame(snap.focusedDay, "day");
1635
1727
  const disabled = !dayData.isCurrentMonth || dayData.isDisabled;
1636
- grid.append(
1637
- el2("button", {
1638
- type: "button",
1639
- role: "gridcell",
1640
- tabIndex: focused ? 0 : -1,
1641
- ariaSelected: Boolean(
1642
- dayData.isRangeStart || dayData.isRangeEnd
1643
- ),
1644
- ariaDisabled: disabled,
1645
- disabled,
1646
- ariaLabel: formatLocalized(
1647
- dayData.date,
1648
- "dddd, MMMM D, YYYY",
1649
- snap.locale
1650
- ),
1651
- className: cx(
1652
- "ctp-box",
1653
- "ctp-box-date",
1654
- !dayData.isCurrentMonth && "not-current-month",
1655
- dayData.isDisabled && "disabled-date",
1656
- dayData.isWeekend && "weekend-day",
1657
- dayData.isCurrentDate && "ctp-today",
1658
- dayData.isInRange && "ctp-in-range",
1659
- dayData.isRangeStart && "ctp-range-start",
1660
- dayData.isRangeEnd && "ctp-range-end"
1661
- ),
1662
- onClick: () => {
1663
- if (!disabled) {
1664
- controller.pickDay(dayData.date);
1665
- }
1666
- },
1667
- onMouseenter: () => {
1668
- if (!disabled && snap.start && !snap.end) {
1669
- controller.setHoverEnd(dayData.date);
1670
- }
1671
- },
1672
- textContent: dayData.date.format("D")
1673
- })
1674
- );
1728
+ const btn = el2("button", {
1729
+ type: "button",
1730
+ role: "gridcell",
1731
+ tabIndex: focused ? 0 : -1,
1732
+ ariaSelected: Boolean(
1733
+ dayData.isRangeStart || dayData.isRangeEnd
1734
+ ),
1735
+ ariaDisabled: disabled,
1736
+ disabled,
1737
+ ariaLabel: formatLocalized(
1738
+ dayData.date,
1739
+ "dddd, MMMM D, YYYY",
1740
+ snap.locale
1741
+ ),
1742
+ className: dayDateClassName(dayData),
1743
+ onClick: () => {
1744
+ if (!disabled) {
1745
+ controller.pickDay(dayData.date);
1746
+ }
1747
+ },
1748
+ onMouseenter: () => {
1749
+ if (!disabled && snap.start && !snap.end) {
1750
+ controller.setHoverEnd(dayData.date);
1751
+ }
1752
+ },
1753
+ textContent: dayData.date.format("D")
1754
+ });
1755
+ buttons.set(dayData.date.format("YYYY-MM-DD"), btn);
1756
+ grid.append(btn);
1675
1757
  }
1676
1758
  }
1759
+ dayButtons = buttons;
1677
1760
  body.append(grid);
1678
1761
  } else if (snap.calPanel === "month") {
1679
1762
  const grid = el2("div", {
@@ -1743,14 +1826,16 @@ function createDateTimeRangePicker(target, options = {}) {
1743
1826
  })
1744
1827
  );
1745
1828
  }
1746
- footerChildren.push(
1747
- el2("button", {
1748
- type: "button",
1749
- disabled: !snap.start || !snap.end,
1750
- onClick: () => controller.confirm(),
1751
- textContent: snap.labels.ok
1752
- })
1753
- );
1829
+ if (!snap.inline) {
1830
+ footerChildren.push(
1831
+ el2("button", {
1832
+ type: "button",
1833
+ disabled: !snap.start || !snap.end,
1834
+ onClick: () => controller.confirm(),
1835
+ textContent: snap.labels.ok
1836
+ })
1837
+ );
1838
+ }
1754
1839
  const picker = el2(
1755
1840
  "div",
1756
1841
  {
@@ -1775,6 +1860,7 @@ function createDateTimeRangePicker(target, options = {}) {
1775
1860
  if (snap.inline) {
1776
1861
  host = picker;
1777
1862
  target.append(picker);
1863
+ lastSnap = snap;
1778
1864
  return;
1779
1865
  }
1780
1866
  const backdrop = el2("div", {
@@ -1792,6 +1878,7 @@ function createDateTimeRangePicker(target, options = {}) {
1792
1878
  attachFocusTrap(picker),
1793
1879
  attachEscape(() => controller.close())
1794
1880
  );
1881
+ lastSnap = snap;
1795
1882
  };
1796
1883
  const unsub = controller.subscribe(paint);
1797
1884
  paint();
@@ -1849,7 +1936,7 @@ function ensureStylesheet(href) {
1849
1936
  const link = document.createElement("link");
1850
1937
  link.id = STYLE_LINK_ID;
1851
1938
  link.rel = "stylesheet";
1852
- link.href = href ?? "https://cdn.jsdelivr.net/npm/universal-datetime-picker/style.css";
1939
+ link.href = href ?? "https://cdn.jsdelivr.net/npm/universal-datetime-picker/dist/style.css";
1853
1940
  document.head.append(link);
1854
1941
  }
1855
1942
  var BaseCalendarElement = class extends HTMLElement {