@x-plat/design-system 0.4.2 → 0.4.4

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.
@@ -1410,7 +1410,7 @@ var MONTH_LABELS = {
1410
1410
  };
1411
1411
 
1412
1412
  // src/components/DatePicker/SingleDatePicker/index.tsx
1413
- import { jsx as jsx298, jsxs as jsxs191 } from "react/jsx-runtime";
1413
+ import { Fragment, jsx as jsx298, jsxs as jsxs191 } from "react/jsx-runtime";
1414
1414
  var DayCell = React5.memo(
1415
1415
  ({
1416
1416
  day,
@@ -1454,10 +1454,14 @@ var SingleDatePicker = (props) => {
1454
1454
  } = props;
1455
1455
  const initialYear = value?.getFullYear();
1456
1456
  const initialMonth = value?.getMonth();
1457
- const { year, month, days, goToPrevMonth, goToNextMonth } = useCalendar(
1457
+ const { year, month, days, goToPrevMonth, goToNextMonth, setYear, setMonth } = useCalendar(
1458
1458
  initialYear,
1459
1459
  initialMonth
1460
1460
  );
1461
+ const [pickerMode, setPickerMode] = React5.useState("days");
1462
+ const [yearRangeStart, setYearRangeStart] = React5.useState(
1463
+ Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
1464
+ );
1461
1465
  const minTime = React5.useMemo(
1462
1466
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
1463
1467
  [minDate]
@@ -1479,7 +1483,34 @@ var SingleDatePicker = (props) => {
1479
1483
  },
1480
1484
  [onChange]
1481
1485
  );
1486
+ const handlePrev = () => {
1487
+ if (pickerMode === "days") goToPrevMonth();
1488
+ else if (pickerMode === "months") setYear(year - 1);
1489
+ else setYearRangeStart((s) => s - 12);
1490
+ };
1491
+ const handleNext = () => {
1492
+ if (pickerMode === "days") goToNextMonth();
1493
+ else if (pickerMode === "months") setYear(year + 1);
1494
+ else setYearRangeStart((s) => s + 12);
1495
+ };
1496
+ const handleTitleClick = () => {
1497
+ if (pickerMode === "days") setPickerMode("months");
1498
+ else if (pickerMode === "months") {
1499
+ setYearRangeStart(Math.floor(year / 12) * 12);
1500
+ setPickerMode("years");
1501
+ }
1502
+ };
1503
+ const handleMonthSelect = (m) => {
1504
+ setMonth(m);
1505
+ setPickerMode("days");
1506
+ };
1507
+ const handleYearSelect = (y) => {
1508
+ setYear(y);
1509
+ setPickerMode("months");
1510
+ };
1482
1511
  const weekdays = WEEKDAY_LABELS[locale];
1512
+ const monthLabels = MONTH_LABELS[locale];
1513
+ const titleText = pickerMode === "days" ? locale === "ko" ? `${year}\uB144 ${monthLabels[month]}` : `${monthLabels[month]} ${year}` : pickerMode === "months" ? `${year}` : `${yearRangeStart} - ${yearRangeStart + 11}`;
1483
1514
  return /* @__PURE__ */ jsxs191(
1484
1515
  "div",
1485
1516
  {
@@ -1487,41 +1518,66 @@ var SingleDatePicker = (props) => {
1487
1518
  style: { "--datepicker-active-color": `var(--${color})` },
1488
1519
  children: [
1489
1520
  /* @__PURE__ */ jsxs191("div", { className: "datepicker-header", children: [
1490
- /* @__PURE__ */ jsx298("button", { className: "datepicker-nav", onClick: goToPrevMonth, type: "button", children: /* @__PURE__ */ jsx298(ChevronLeftIcon_default, {}) }),
1491
- /* @__PURE__ */ jsx298("span", { className: "datepicker-title", children: locale === "ko" ? `${year}\uB144 ${MONTH_LABELS.ko[month]}` : `${MONTH_LABELS.en[month]} ${year}` }),
1492
- /* @__PURE__ */ jsx298("button", { className: "datepicker-nav", onClick: goToNextMonth, type: "button", children: /* @__PURE__ */ jsx298(ChevronRightIcon_default, {}) })
1521
+ /* @__PURE__ */ jsx298("button", { className: "datepicker-nav", onClick: handlePrev, type: "button", children: /* @__PURE__ */ jsx298(ChevronLeftIcon_default, {}) }),
1522
+ /* @__PURE__ */ jsx298("button", { className: "datepicker-title", onClick: handleTitleClick, type: "button", children: titleText }),
1523
+ /* @__PURE__ */ jsx298("button", { className: "datepicker-nav", onClick: handleNext, type: "button", children: /* @__PURE__ */ jsx298(ChevronRightIcon_default, {}) })
1493
1524
  ] }),
1494
- /* @__PURE__ */ jsx298("div", { className: "datepicker-weekdays", children: weekdays.map((label, i) => /* @__PURE__ */ jsx298(
1495
- "div",
1525
+ pickerMode === "years" && /* @__PURE__ */ jsx298("div", { className: "datepicker-picker-grid", children: Array.from({ length: 12 }, (_, i) => {
1526
+ const y = yearRangeStart + i;
1527
+ return /* @__PURE__ */ jsx298(
1528
+ "button",
1529
+ {
1530
+ type: "button",
1531
+ className: clsx_default("datepicker-picker-cell", y === year && "active"),
1532
+ onClick: () => handleYearSelect(y),
1533
+ children: y
1534
+ },
1535
+ y
1536
+ );
1537
+ }) }),
1538
+ pickerMode === "months" && /* @__PURE__ */ jsx298("div", { className: "datepicker-picker-grid", children: monthLabels.map((label, i) => /* @__PURE__ */ jsx298(
1539
+ "button",
1496
1540
  {
1497
- className: clsx_default(
1498
- "datepicker-weekday",
1499
- i === 0 && "sunday",
1500
- i === 6 && "saturday"
1501
- ),
1541
+ type: "button",
1542
+ className: clsx_default("datepicker-picker-cell", i === month && "active"),
1543
+ onClick: () => handleMonthSelect(i),
1502
1544
  children: label
1503
1545
  },
1504
- label
1546
+ i
1505
1547
  )) }),
1506
- /* @__PURE__ */ jsx298("div", { className: "datepicker-grid", children: days.map((day, idx) => {
1507
- const t = day.date.getTime();
1508
- const disabled = t < minTime || t > maxTime;
1509
- const selected = value ? isSameDay(day.date, value) : false;
1510
- const highlighted = highlightSet.has(
1511
- `${day.date.getFullYear()}-${day.date.getMonth()}-${day.date.getDate()}`
1512
- );
1513
- return /* @__PURE__ */ jsx298(
1514
- DayCell,
1548
+ pickerMode === "days" && /* @__PURE__ */ jsxs191(Fragment, { children: [
1549
+ /* @__PURE__ */ jsx298("div", { className: "datepicker-weekdays", children: weekdays.map((label, i) => /* @__PURE__ */ jsx298(
1550
+ "div",
1515
1551
  {
1516
- day,
1517
- disabled,
1518
- selected,
1519
- highlighted,
1520
- onSelect: handleSelect
1552
+ className: clsx_default(
1553
+ "datepicker-weekday",
1554
+ i === 0 && "sunday",
1555
+ i === 6 && "saturday"
1556
+ ),
1557
+ children: label
1521
1558
  },
1522
- idx
1523
- );
1524
- }) })
1559
+ label
1560
+ )) }),
1561
+ /* @__PURE__ */ jsx298("div", { className: "datepicker-grid", children: days.map((day, idx) => {
1562
+ const t = day.date.getTime();
1563
+ const disabled = t < minTime || t > maxTime;
1564
+ const selected = value ? isSameDay(day.date, value) : false;
1565
+ const highlighted = highlightSet.has(
1566
+ `${day.date.getFullYear()}-${day.date.getMonth()}-${day.date.getDate()}`
1567
+ );
1568
+ return /* @__PURE__ */ jsx298(
1569
+ DayCell,
1570
+ {
1571
+ day,
1572
+ disabled,
1573
+ selected,
1574
+ highlighted,
1575
+ onSelect: handleSelect
1576
+ },
1577
+ idx
1578
+ );
1579
+ }) })
1580
+ ] })
1525
1581
  ]
1526
1582
  }
1527
1583
  );
@@ -1662,9 +1718,24 @@ var RangePicker = (props) => {
1662
1718
  } = props;
1663
1719
  const startCal = useCalendar(startDate.getFullYear(), startDate.getMonth());
1664
1720
  const endCal = useCalendar(endDate.getFullYear(), endDate.getMonth());
1665
- const isDisabled = (date) => {
1666
- if (minDate && date < new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate())) return true;
1667
- if (maxDate && date > new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate())) return true;
1721
+ const isDisabled = (date, type) => {
1722
+ const d = date.getTime();
1723
+ if (minDate) {
1724
+ const min = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime();
1725
+ if (d < min) return true;
1726
+ }
1727
+ if (maxDate) {
1728
+ const max = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime();
1729
+ if (d > max) return true;
1730
+ }
1731
+ if (type === "end") {
1732
+ const start = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()).getTime();
1733
+ if (d < start) return true;
1734
+ }
1735
+ if (type === "start") {
1736
+ const end = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()).getTime();
1737
+ if (d > end) return true;
1738
+ }
1668
1739
  return false;
1669
1740
  };
1670
1741
  const weekdays = WEEKDAY_LABELS[locale];
@@ -1673,9 +1744,25 @@ var RangePicker = (props) => {
1673
1744
  return /* @__PURE__ */ jsxs193("div", { className: "datepicker-range-panel", children: [
1674
1745
  /* @__PURE__ */ jsx302("span", { className: "datepicker-range-label", children: label }),
1675
1746
  /* @__PURE__ */ jsxs193("div", { className: "datepicker-header", children: [
1676
- /* @__PURE__ */ jsx302("button", { className: "datepicker-nav", onClick: cal.goToPrevMonth, type: "button", children: /* @__PURE__ */ jsx302(ChevronLeftIcon_default, {}) }),
1747
+ /* @__PURE__ */ jsx302(
1748
+ "button",
1749
+ {
1750
+ className: "datepicker-nav",
1751
+ onClick: cal.goToPrevMonth,
1752
+ type: "button",
1753
+ children: /* @__PURE__ */ jsx302(ChevronLeftIcon_default, {})
1754
+ }
1755
+ ),
1677
1756
  /* @__PURE__ */ jsx302("span", { className: "datepicker-title", children: locale === "ko" ? `${cal.year}\uB144 ${MONTH_LABELS.ko[cal.month]}` : `${MONTH_LABELS.en[cal.month]} ${cal.year}` }),
1678
- /* @__PURE__ */ jsx302("button", { className: "datepicker-nav", onClick: cal.goToNextMonth, type: "button", children: /* @__PURE__ */ jsx302(ChevronRightIcon_default, {}) })
1757
+ /* @__PURE__ */ jsx302(
1758
+ "button",
1759
+ {
1760
+ className: "datepicker-nav",
1761
+ onClick: cal.goToNextMonth,
1762
+ type: "button",
1763
+ children: /* @__PURE__ */ jsx302(ChevronRightIcon_default, {})
1764
+ }
1765
+ )
1679
1766
  ] }),
1680
1767
  /* @__PURE__ */ jsx302("div", { className: "datepicker-weekdays", children: weekdays.map((w, i) => /* @__PURE__ */ jsx302(
1681
1768
  "div",
@@ -1690,7 +1777,7 @@ var RangePicker = (props) => {
1690
1777
  w
1691
1778
  )) }),
1692
1779
  /* @__PURE__ */ jsx302("div", { className: "datepicker-grid", children: cal.days.map((day, idx) => {
1693
- const disabled = isDisabled(day.date);
1780
+ const disabled = isDisabled(day.date, type);
1694
1781
  const isStart = isSameDay(day.date, startDate);
1695
1782
  const isEnd = isSameDay(day.date, endDate);
1696
1783
  const inRange = isInRange(day.date, startDate, endDate);
@@ -1731,7 +1818,9 @@ var RangePicker = (props) => {
1731
1818
  "div",
1732
1819
  {
1733
1820
  className: clsx_default("lib-xplat-datepicker", "range"),
1734
- style: { "--datepicker-active-color": `var(--${color})` },
1821
+ style: {
1822
+ "--datepicker-active-color": `var(--${color})`
1823
+ },
1735
1824
  children: [
1736
1825
  renderCalendar(startCal, "start"),
1737
1826
  renderCalendar(endCal, "end")
@@ -1756,7 +1845,7 @@ var PopupPicker = (props) => {
1756
1845
  };
1757
1846
  return /* @__PURE__ */ jsxs194("div", { className: "lib-xplat-popup-datepicker", children: [
1758
1847
  React8.cloneElement(component, { onClick: handleClick }),
1759
- /* @__PURE__ */ jsx303(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs194("div", { className: "lib-xplat-popup-datepicker-card", children: [
1848
+ /* @__PURE__ */ jsx303(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs194("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
1760
1849
  /* @__PURE__ */ jsxs194("div", { className: "popup-datepicker-content", children: [
1761
1850
  type === "single" && /* @__PURE__ */ jsx303(
1762
1851
  SingleDatePicker_default,
@@ -9,6 +9,7 @@
9
9
  background-color: var(--xplat-white);
10
10
  border-radius: 0.25rem;
11
11
  overflow: hidden;
12
+ padding: 0.75rem;
12
13
  }
13
14
  .lib-xplat-imageselector > input {
14
15
  display: none;
@@ -8,7 +8,7 @@
8
8
  padding: 24px;
9
9
  max-width: calc(100vw - 2rem);
10
10
  max-height: calc(100vh - 2rem);
11
- overflow: auto;
11
+ overflow: visible;
12
12
  transform: scale(0.9);
13
13
  opacity: 0;
14
14
  transition: transform 0.2s ease, opacity 0.2s ease;
@@ -2,6 +2,7 @@
2
2
  .lib-xplat-pop-over {
3
3
  position: relative;
4
4
  z-index: 10;
5
+ width: fit-content;
5
6
  cursor: pointer;
6
7
  user-select: none;
7
8
  }