@kalyx/react 0.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.
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/README.md +88 -0
- package/dist/components/DatePicker/Calendar.d.ts +23 -0
- package/dist/components/DatePicker/Calendar.d.ts.map +1 -0
- package/dist/components/DatePicker/Calendar.js +127 -0
- package/dist/components/DatePicker/Calendar.js.map +1 -0
- package/dist/components/DatePicker/Input.d.ts +7 -0
- package/dist/components/DatePicker/Input.d.ts.map +1 -0
- package/dist/components/DatePicker/Input.js +73 -0
- package/dist/components/DatePicker/Input.js.map +1 -0
- package/dist/components/DatePicker/MonthGrid.d.ts +34 -0
- package/dist/components/DatePicker/MonthGrid.d.ts.map +1 -0
- package/dist/components/DatePicker/MonthGrid.js +54 -0
- package/dist/components/DatePicker/MonthGrid.js.map +1 -0
- package/dist/components/DatePicker/Popover.d.ts +6 -0
- package/dist/components/DatePicker/Popover.d.ts.map +1 -0
- package/dist/components/DatePicker/Popover.js +72 -0
- package/dist/components/DatePicker/Popover.js.map +1 -0
- package/dist/components/DatePicker/Root.d.ts +46 -0
- package/dist/components/DatePicker/Root.d.ts.map +1 -0
- package/dist/components/DatePicker/Root.js +90 -0
- package/dist/components/DatePicker/Root.js.map +1 -0
- package/dist/components/DatePicker/Trigger.d.ts +6 -0
- package/dist/components/DatePicker/Trigger.d.ts.map +1 -0
- package/dist/components/DatePicker/Trigger.js +21 -0
- package/dist/components/DatePicker/Trigger.js.map +1 -0
- package/dist/components/DatePicker/YearGrid.d.ts +29 -0
- package/dist/components/DatePicker/YearGrid.d.ts.map +1 -0
- package/dist/components/DatePicker/YearGrid.js +53 -0
- package/dist/components/DatePicker/YearGrid.js.map +1 -0
- package/dist/components/DatePicker/index.d.ts +48 -0
- package/dist/components/DatePicker/index.d.ts.map +1 -0
- package/dist/components/DatePicker/index.js +42 -0
- package/dist/components/DatePicker/index.js.map +1 -0
- package/dist/components/DateTimePicker/Input.d.ts +12 -0
- package/dist/components/DateTimePicker/Input.d.ts.map +1 -0
- package/dist/components/DateTimePicker/Input.js +41 -0
- package/dist/components/DateTimePicker/Input.js.map +1 -0
- package/dist/components/DateTimePicker/Root.d.ts +60 -0
- package/dist/components/DateTimePicker/Root.d.ts.map +1 -0
- package/dist/components/DateTimePicker/Root.js +140 -0
- package/dist/components/DateTimePicker/Root.js.map +1 -0
- package/dist/components/DateTimePicker/index.d.ts +55 -0
- package/dist/components/DateTimePicker/index.d.ts.map +1 -0
- package/dist/components/DateTimePicker/index.js +55 -0
- package/dist/components/DateTimePicker/index.js.map +1 -0
- package/dist/components/RangePicker/Calendar.d.ts +24 -0
- package/dist/components/RangePicker/Calendar.d.ts.map +1 -0
- package/dist/components/RangePicker/Calendar.js +134 -0
- package/dist/components/RangePicker/Calendar.js.map +1 -0
- package/dist/components/RangePicker/Input.d.ts +14 -0
- package/dist/components/RangePicker/Input.d.ts.map +1 -0
- package/dist/components/RangePicker/Input.js +38 -0
- package/dist/components/RangePicker/Input.js.map +1 -0
- package/dist/components/RangePicker/Popover.d.ts +6 -0
- package/dist/components/RangePicker/Popover.d.ts.map +1 -0
- package/dist/components/RangePicker/Popover.js +71 -0
- package/dist/components/RangePicker/Popover.js.map +1 -0
- package/dist/components/RangePicker/Presets.d.ts +49 -0
- package/dist/components/RangePicker/Presets.d.ts.map +1 -0
- package/dist/components/RangePicker/Presets.js +117 -0
- package/dist/components/RangePicker/Presets.js.map +1 -0
- package/dist/components/RangePicker/Root.d.ts +40 -0
- package/dist/components/RangePicker/Root.d.ts.map +1 -0
- package/dist/components/RangePicker/Root.js +138 -0
- package/dist/components/RangePicker/Root.js.map +1 -0
- package/dist/components/RangePicker/index.d.ts +48 -0
- package/dist/components/RangePicker/index.d.ts.map +1 -0
- package/dist/components/RangePicker/index.js +43 -0
- package/dist/components/RangePicker/index.js.map +1 -0
- package/dist/components/TimePicker/AmPmToggle.d.ts +15 -0
- package/dist/components/TimePicker/AmPmToggle.d.ts.map +1 -0
- package/dist/components/TimePicker/AmPmToggle.js +29 -0
- package/dist/components/TimePicker/AmPmToggle.js.map +1 -0
- package/dist/components/TimePicker/HourList.d.ts +18 -0
- package/dist/components/TimePicker/HourList.d.ts.map +1 -0
- package/dist/components/TimePicker/HourList.js +71 -0
- package/dist/components/TimePicker/HourList.js.map +1 -0
- package/dist/components/TimePicker/Input.d.ts +9 -0
- package/dist/components/TimePicker/Input.d.ts.map +1 -0
- package/dist/components/TimePicker/Input.js +37 -0
- package/dist/components/TimePicker/Input.js.map +1 -0
- package/dist/components/TimePicker/MinuteList.d.ts +15 -0
- package/dist/components/TimePicker/MinuteList.d.ts.map +1 -0
- package/dist/components/TimePicker/MinuteList.js +62 -0
- package/dist/components/TimePicker/MinuteList.js.map +1 -0
- package/dist/components/TimePicker/Root.d.ts +38 -0
- package/dist/components/TimePicker/Root.d.ts.map +1 -0
- package/dist/components/TimePicker/Root.js +40 -0
- package/dist/components/TimePicker/Root.js.map +1 -0
- package/dist/components/TimePicker/index.d.ts +32 -0
- package/dist/components/TimePicker/index.d.ts.map +1 -0
- package/dist/components/TimePicker/index.js +27 -0
- package/dist/components/TimePicker/index.js.map +1 -0
- package/dist/context/DatePickerContext.d.ts +49 -0
- package/dist/context/DatePickerContext.d.ts.map +1 -0
- package/dist/context/DatePickerContext.js +18 -0
- package/dist/context/DatePickerContext.js.map +1 -0
- package/dist/context/RangePickerContext.d.ts +53 -0
- package/dist/context/RangePickerContext.d.ts.map +1 -0
- package/dist/context/RangePickerContext.js +18 -0
- package/dist/context/RangePickerContext.js.map +1 -0
- package/dist/context/TimePickerContext.d.ts +29 -0
- package/dist/context/TimePickerContext.d.ts.map +1 -0
- package/dist/context/TimePickerContext.js +18 -0
- package/dist/context/TimePickerContext.js.map +1 -0
- package/dist/hooks/useDatePicker.d.ts +63 -0
- package/dist/hooks/useDatePicker.d.ts.map +1 -0
- package/dist/hooks/useDatePicker.js +82 -0
- package/dist/hooks/useDatePicker.js.map +1 -0
- package/dist/hooks/useRangePicker.d.ts +67 -0
- package/dist/hooks/useRangePicker.d.ts.map +1 -0
- package/dist/hooks/useRangePicker.js +116 -0
- package/dist/hooks/useRangePicker.js.map +1 -0
- package/dist/hooks/useTimePicker.d.ts +63 -0
- package/dist/hooks/useTimePicker.d.ts.map +1 -0
- package/dist/hooks/useTimePicker.js +69 -0
- package/dist/hooks/useTimePicker.js.map +1 -0
- package/dist/index.cjs +2150 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +744 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @kalyx/react
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e9bb9e8: Initial release of Kalyx — headless, SSR-safe React DatePicker library.
|
|
8
|
+
|
|
9
|
+
Features:
|
|
10
|
+
|
|
11
|
+
- DatePicker: single date selection with Calendar, Input, Trigger, Popover
|
|
12
|
+
- RangePicker: date range selection with auto-swap and hover preview
|
|
13
|
+
- TimePicker: 12h/24h mode, minute step, HourList/MinuteList/AmPmToggle
|
|
14
|
+
- DateTimePicker: combined date+time via context bridging (reuses existing components)
|
|
15
|
+
- useDatePicker, useRangePicker, useTimePicker hooks for custom UIs
|
|
16
|
+
- WAI-ARIA compliant: grid, dialog, combobox, listbox, radiogroup patterns
|
|
17
|
+
- SSR safe: verified with Next.js 15 App Router
|
|
18
|
+
- Zero CSS: style with classNames prop and data-\* attributes
|
|
19
|
+
- ISO 8601 UTC strings only (no native Date objects)
|
|
20
|
+
- Bundle: 7.71KB gzip (target ≤12KB)
|
|
21
|
+
- 185 unit/integration tests passing
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [e9bb9e8]
|
|
26
|
+
- @kalyx/core@0.2.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jihoon Lee (jiji-hoon96)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# @kalyx/react
|
|
2
|
+
|
|
3
|
+
> Headless, SSR-safe React DatePicker. Zero CSS. Composition API. < 8KB gzip.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @kalyx/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Peer dependencies:** `react >= 19.0.0`, `react-dom >= 19.0.0`
|
|
12
|
+
|
|
13
|
+
## Components
|
|
14
|
+
|
|
15
|
+
### DatePicker
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { DatePicker } from '@kalyx/react';
|
|
19
|
+
|
|
20
|
+
<DatePicker value={date} onChange={setDate}>
|
|
21
|
+
<DatePicker.Input placeholder="Select date" />
|
|
22
|
+
<DatePicker.Popover>
|
|
23
|
+
<DatePicker.Calendar />
|
|
24
|
+
</DatePicker.Popover>
|
|
25
|
+
</DatePicker>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### RangePicker
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { RangePicker } from '@kalyx/react';
|
|
32
|
+
|
|
33
|
+
<RangePicker value={range} onChange={setRange}>
|
|
34
|
+
<RangePicker.Input part="start" />
|
|
35
|
+
<RangePicker.Input part="end" />
|
|
36
|
+
<RangePicker.Popover>
|
|
37
|
+
<RangePicker.Calendar />
|
|
38
|
+
</RangePicker.Popover>
|
|
39
|
+
</RangePicker>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### TimePicker
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { TimePicker } from '@kalyx/react';
|
|
46
|
+
|
|
47
|
+
<TimePicker value={time} onChange={setTime} format="24h" step={15}>
|
|
48
|
+
<TimePicker.Input />
|
|
49
|
+
<TimePicker.HourList />
|
|
50
|
+
<TimePicker.MinuteList />
|
|
51
|
+
<TimePicker.AmPmToggle />
|
|
52
|
+
</TimePicker>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### DateTimePicker
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { DateTimePicker } from '@kalyx/react';
|
|
59
|
+
|
|
60
|
+
<DateTimePicker value={dt} onChange={setDt} format="24h" step={15}>
|
|
61
|
+
<DateTimePicker.Input />
|
|
62
|
+
<DateTimePicker.Popover>
|
|
63
|
+
<DateTimePicker.Calendar />
|
|
64
|
+
<DateTimePicker.HourList />
|
|
65
|
+
<DateTimePicker.MinuteList />
|
|
66
|
+
</DateTimePicker.Popover>
|
|
67
|
+
</DateTimePicker>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Hooks
|
|
71
|
+
|
|
72
|
+
For fully custom UIs, use the equivalent hooks:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { useDatePicker, useRangePicker, useTimePicker } from '@kalyx/react';
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Key Features
|
|
79
|
+
|
|
80
|
+
- **Zero CSS** — Style with `classNames` prop or `data-*` attributes
|
|
81
|
+
- **ISO 8601 UTC** — All values are UTC strings, no native Date objects
|
|
82
|
+
- **SSR Safe** — Verified with Next.js 15 App Router
|
|
83
|
+
- **Accessible** — WAI-ARIA patterns, keyboard navigation, axe tested
|
|
84
|
+
- **7.71KB gzip** — DatePicker + RangePicker + TimePicker + DateTimePicker
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
export interface DatePickerCalendarClassNames {
|
|
3
|
+
root?: string;
|
|
4
|
+
header?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
navButton?: string;
|
|
7
|
+
grid?: string;
|
|
8
|
+
gridRow?: string;
|
|
9
|
+
gridCell?: string;
|
|
10
|
+
day?: string;
|
|
11
|
+
daySelected?: string;
|
|
12
|
+
dayToday?: string;
|
|
13
|
+
dayDisabled?: string;
|
|
14
|
+
dayOutsideMonth?: string;
|
|
15
|
+
weekdayHeader?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface DatePickerCalendarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'role'> {
|
|
18
|
+
classNames?: DatePickerCalendarClassNames;
|
|
19
|
+
/** 타이틀("January 2026") 클릭 시 콜백. Month/Year 뷰 전환에 사용. */
|
|
20
|
+
onTitleClick?: () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare function DatePickerCalendar({ classNames, onTitleClick, ...props }: DatePickerCalendarProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=Calendar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Calendar.d.ts","sourceRoot":"","sources":["../../../src/components/DatePicker/Calendar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAK5C,MAAM,WAAW,4BAA4B;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAC3F,UAAU,CAAC,EAAE,4BAA4B,CAAC;IAC1C,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAeD,wBAAgB,kBAAkB,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,KAAK,EAAE,EAAE,uBAAuB,2CAiOjG"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { getCalendarDays, isDateDisabled, getWeekdayNames, formatMonthYear, formatFullDate } from '@kalyx/core';
|
|
4
|
+
import { useDatePickerContext } from '../../context/DatePickerContext.js';
|
|
5
|
+
/** 스크린리더 전용 숨김 스타일 */
|
|
6
|
+
const srOnly = {
|
|
7
|
+
position: 'absolute',
|
|
8
|
+
width: '1px',
|
|
9
|
+
height: '1px',
|
|
10
|
+
padding: 0,
|
|
11
|
+
margin: '-1px',
|
|
12
|
+
overflow: 'hidden',
|
|
13
|
+
clip: 'rect(0, 0, 0, 0)',
|
|
14
|
+
whiteSpace: 'nowrap',
|
|
15
|
+
border: 0,
|
|
16
|
+
};
|
|
17
|
+
export function DatePickerCalendar({ classNames, onTitleClick, ...props }) {
|
|
18
|
+
const ctx = useDatePickerContext('DatePicker.Calendar');
|
|
19
|
+
const gridRef = useRef(null);
|
|
20
|
+
const [announcement, setAnnouncement] = useState('');
|
|
21
|
+
const { adapter, viewMonth, focusedDate, weekStartsOn, disabled, locale } = ctx;
|
|
22
|
+
const weekdays = getWeekdayNames(locale, weekStartsOn);
|
|
23
|
+
const weeks = getCalendarDays(viewMonth, adapter, {
|
|
24
|
+
weekStartsOn,
|
|
25
|
+
selected: ctx.value,
|
|
26
|
+
focusedDate,
|
|
27
|
+
disabled,
|
|
28
|
+
});
|
|
29
|
+
const year = adapter.getYear(viewMonth);
|
|
30
|
+
const month = adapter.getMonth(viewMonth);
|
|
31
|
+
const title = formatMonthYear(year, month, locale);
|
|
32
|
+
// 포커스된 날짜 셀에 포커스 이동
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!ctx.isOpen || !gridRef.current)
|
|
35
|
+
return;
|
|
36
|
+
const focusedButton = gridRef.current.querySelector('[data-focused="true"]');
|
|
37
|
+
focusedButton?.focus();
|
|
38
|
+
}, [focusedDate, ctx.isOpen]);
|
|
39
|
+
const navigateMonth = useCallback((direction) => {
|
|
40
|
+
const newMonth = adapter.addMonths(viewMonth, direction);
|
|
41
|
+
ctx.setViewMonth(newMonth);
|
|
42
|
+
ctx.setFocusedDate(adapter.startOfMonth(newMonth));
|
|
43
|
+
const y = adapter.getYear(newMonth);
|
|
44
|
+
const m = adapter.getMonth(newMonth);
|
|
45
|
+
setAnnouncement(formatMonthYear(y, m, locale));
|
|
46
|
+
}, [adapter, viewMonth, ctx, locale]);
|
|
47
|
+
const handleDayClick = useCallback((day) => {
|
|
48
|
+
if (day.isDisabled)
|
|
49
|
+
return;
|
|
50
|
+
ctx.selectDate(day.isoString);
|
|
51
|
+
setAnnouncement(formatFullDate(day.isoString, locale));
|
|
52
|
+
}, [ctx, locale]);
|
|
53
|
+
const handleKeyDown = useCallback((e) => {
|
|
54
|
+
let newFocused = null;
|
|
55
|
+
switch (e.key) {
|
|
56
|
+
case 'ArrowLeft':
|
|
57
|
+
newFocused = adapter.addDays(focusedDate, -1);
|
|
58
|
+
break;
|
|
59
|
+
case 'ArrowRight':
|
|
60
|
+
newFocused = adapter.addDays(focusedDate, 1);
|
|
61
|
+
break;
|
|
62
|
+
case 'ArrowUp':
|
|
63
|
+
newFocused = adapter.addDays(focusedDate, -7);
|
|
64
|
+
break;
|
|
65
|
+
case 'ArrowDown':
|
|
66
|
+
newFocused = adapter.addDays(focusedDate, 7);
|
|
67
|
+
break;
|
|
68
|
+
case 'PageUp':
|
|
69
|
+
if (e.shiftKey) {
|
|
70
|
+
newFocused = adapter.addYears(focusedDate, -1);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
newFocused = adapter.addMonths(focusedDate, -1);
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
case 'PageDown':
|
|
77
|
+
if (e.shiftKey) {
|
|
78
|
+
newFocused = adapter.addYears(focusedDate, 1);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
newFocused = adapter.addMonths(focusedDate, 1);
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
case 'Home':
|
|
85
|
+
newFocused = adapter.startOfWeek(focusedDate, weekStartsOn);
|
|
86
|
+
break;
|
|
87
|
+
case 'End':
|
|
88
|
+
newFocused = adapter.endOfWeek(focusedDate, weekStartsOn);
|
|
89
|
+
// endOfWeek는 23:59:59 반환하므로 startOfDay로 정규화
|
|
90
|
+
newFocused = adapter.startOfDay(newFocused);
|
|
91
|
+
break;
|
|
92
|
+
case 'Enter':
|
|
93
|
+
case ' ':
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
if (!isDateDisabled(focusedDate, disabled, adapter)) {
|
|
96
|
+
ctx.selectDate(focusedDate);
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
case 'Escape':
|
|
100
|
+
ctx.close();
|
|
101
|
+
return;
|
|
102
|
+
default:
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (newFocused) {
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
ctx.setFocusedDate(newFocused);
|
|
108
|
+
// 포커스가 현재 뷰 월을 벗어나면 뷰도 업데이트
|
|
109
|
+
if (!adapter.isSameMonth(newFocused, viewMonth)) {
|
|
110
|
+
ctx.setViewMonth(newFocused);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}, [adapter, focusedDate, viewMonth, weekStartsOn, disabled, ctx]);
|
|
114
|
+
return (_jsxs("div", { className: classNames?.root, ...props, children: [_jsxs("div", { className: classNames?.header, children: [_jsx("button", { type: "button", className: classNames?.navButton, onClick: () => navigateMonth(-1), "aria-label": "\uC774\uC804 \uB2EC", children: "<" }), onTitleClick ? (_jsx("button", { type: "button", className: classNames?.title, onClick: onTitleClick, "aria-live": "polite", children: title })) : (_jsx("span", { className: classNames?.title, "aria-live": "polite", children: title })), _jsx("button", { type: "button", className: classNames?.navButton, onClick: () => navigateMonth(1), "aria-label": "\uB2E4\uC74C \uB2EC", children: ">" })] }), _jsxs("table", { ref: gridRef, role: "grid", "aria-label": title, className: classNames?.grid, onKeyDown: handleKeyDown, children: [_jsx("thead", { children: _jsx("tr", { role: "row", children: weekdays.map((day) => (_jsx("th", { role: "columnheader", abbr: day.full, scope: "col", className: classNames?.weekdayHeader, children: day.short }, day.short))) }) }), _jsx("tbody", { children: weeks.map((week, weekIndex) => (_jsx("tr", { role: "row", className: classNames?.gridRow, children: week.map((day) => {
|
|
115
|
+
const dayClasses = [
|
|
116
|
+
classNames?.day,
|
|
117
|
+
day.isSelected && classNames?.daySelected,
|
|
118
|
+
day.isToday && classNames?.dayToday,
|
|
119
|
+
day.isDisabled && classNames?.dayDisabled,
|
|
120
|
+
!day.isCurrentMonth && classNames?.dayOutsideMonth,
|
|
121
|
+
]
|
|
122
|
+
.filter(Boolean)
|
|
123
|
+
.join(' ') || undefined;
|
|
124
|
+
return (_jsx("td", { role: "gridcell", "aria-selected": day.isSelected || undefined, "aria-disabled": day.isDisabled || undefined, "aria-current": day.isToday ? 'date' : undefined, className: classNames?.gridCell, children: _jsx("button", { type: "button", tabIndex: day.isFocused ? 0 : -1, disabled: day.isDisabled, "data-focused": day.isFocused || undefined, "data-selected": day.isSelected || undefined, "data-today": day.isToday || undefined, "data-outside-month": !day.isCurrentMonth || undefined, className: dayClasses, onClick: () => handleDayClick(day), "aria-label": formatFullDate(day.isoString, locale), children: day.dayNumber }) }, day.isoString));
|
|
125
|
+
}) }, weekIndex))) })] }), _jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", style: srOnly, children: announcement })] }));
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=Calendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Calendar.js","sourceRoot":"","sources":["../../../src/components/DatePicker/Calendar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InputHTMLAttributes } from 'react';
|
|
2
|
+
export interface DatePickerInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
|
|
3
|
+
/** 날짜 표시 포맷 (기본: 부모의 displayFormat) */
|
|
4
|
+
format?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const DatePickerInput: import("react").ForwardRefExoticComponent<DatePickerInputProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
7
|
+
//# sourceMappingURL=Input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/DatePicker/Input.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAIjD,MAAM,WAAW,oBACf,SAAQ,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IAClF,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,eAAe,mHA2G3B,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useCallback, useState } from 'react';
|
|
3
|
+
import { parseInputValue } from '@kalyx/core';
|
|
4
|
+
import { useDatePickerContext } from '../../context/DatePickerContext.js';
|
|
5
|
+
export const DatePickerInput = forwardRef(function DatePickerInput({ format: formatProp, onFocus, onBlur, onKeyDown, ...props }, ref) {
|
|
6
|
+
const ctx = useDatePickerContext('DatePicker.Input');
|
|
7
|
+
const displayFormat = formatProp ?? ctx.displayFormat;
|
|
8
|
+
// 입력 중인 텍스트 (편집 모드)
|
|
9
|
+
const [inputText, setInputText] = useState(null);
|
|
10
|
+
const displayValue = inputText !== null
|
|
11
|
+
? inputText
|
|
12
|
+
: ctx.value
|
|
13
|
+
? ctx.adapter.format(ctx.value, displayFormat)
|
|
14
|
+
: '';
|
|
15
|
+
const handleFocus = useCallback((e) => {
|
|
16
|
+
ctx.open();
|
|
17
|
+
onFocus?.(e);
|
|
18
|
+
}, [ctx, onFocus]);
|
|
19
|
+
const handleBlur = useCallback((e) => {
|
|
20
|
+
if (inputText !== null) {
|
|
21
|
+
const parsed = parseInputValue(inputText, displayFormat, ctx.adapter);
|
|
22
|
+
if (parsed) {
|
|
23
|
+
ctx.selectDate(parsed);
|
|
24
|
+
}
|
|
25
|
+
setInputText(null);
|
|
26
|
+
}
|
|
27
|
+
onBlur?.(e);
|
|
28
|
+
}, [inputText, displayFormat, ctx, onBlur]);
|
|
29
|
+
const handleChange = useCallback((e) => {
|
|
30
|
+
const text = e.target.value;
|
|
31
|
+
setInputText(text);
|
|
32
|
+
if (!text) {
|
|
33
|
+
ctx.selectDate(null);
|
|
34
|
+
setInputText(null);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const parsed = parseInputValue(text, displayFormat, ctx.adapter);
|
|
38
|
+
if (parsed) {
|
|
39
|
+
ctx.selectDate(parsed);
|
|
40
|
+
setInputText(null);
|
|
41
|
+
}
|
|
42
|
+
}, [displayFormat, ctx]);
|
|
43
|
+
const handleKeyDown = useCallback((e) => {
|
|
44
|
+
if (e.key === 'Escape') {
|
|
45
|
+
ctx.close();
|
|
46
|
+
}
|
|
47
|
+
else if (e.key === 'Enter') {
|
|
48
|
+
if (inputText !== null) {
|
|
49
|
+
const parsed = parseInputValue(inputText, displayFormat, ctx.adapter);
|
|
50
|
+
if (parsed) {
|
|
51
|
+
ctx.selectDate(parsed);
|
|
52
|
+
setInputText(null);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if (e.key === 'ArrowDown' && !ctx.isOpen) {
|
|
57
|
+
e.preventDefault();
|
|
58
|
+
ctx.open();
|
|
59
|
+
}
|
|
60
|
+
onKeyDown?.(e);
|
|
61
|
+
}, [ctx, inputText, displayFormat, onKeyDown]);
|
|
62
|
+
const calendarId = `${ctx.pickerId}-calendar`;
|
|
63
|
+
return (_jsx("input", { ref: (node) => {
|
|
64
|
+
// Floating UI reference 등록
|
|
65
|
+
ctx.referenceRef.current = node;
|
|
66
|
+
// forwardRef 전달
|
|
67
|
+
if (typeof ref === 'function')
|
|
68
|
+
ref(node);
|
|
69
|
+
else if (ref)
|
|
70
|
+
ref.current = node;
|
|
71
|
+
}, type: "text", role: "combobox", "aria-expanded": ctx.isOpen, "aria-haspopup": "dialog", "aria-controls": ctx.isOpen ? calendarId : undefined, "aria-autocomplete": "none", autoComplete: "off", value: displayValue, disabled: ctx.isDisabled || props.disabled, readOnly: ctx.isReadOnly, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, ...props }));
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=Input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Input.js","sourceRoot":"","sources":["../../../src/components/DatePicker/Input.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
export interface DatePickerMonthGridClassNames {
|
|
3
|
+
root?: string;
|
|
4
|
+
header?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
navButton?: string;
|
|
7
|
+
grid?: string;
|
|
8
|
+
month?: string;
|
|
9
|
+
monthSelected?: string;
|
|
10
|
+
monthCurrent?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DatePickerMonthGridProps extends Omit<HTMLAttributes<HTMLDivElement>, 'role'> {
|
|
13
|
+
classNames?: DatePickerMonthGridClassNames;
|
|
14
|
+
/** 월 선택 시 콜백. 일반적으로 day 뷰로 전환한다. */
|
|
15
|
+
onSelect?: () => void;
|
|
16
|
+
/** 타이틀(년도) 클릭 시 콜백. Year 뷰로 전환할 때 사용. */
|
|
17
|
+
onTitleClick?: () => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* DatePicker.MonthGrid — 12개월 그리드에서 월을 빠르게 선택.
|
|
21
|
+
* Calendar 타이틀 클릭 → MonthGrid 표시 → 월 클릭 → Calendar로 복귀.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* {view === 'months' && (
|
|
26
|
+
* <DatePicker.MonthGrid
|
|
27
|
+
* onSelect={() => setView('days')}
|
|
28
|
+
* onTitleClick={() => setView('years')}
|
|
29
|
+
* />
|
|
30
|
+
* )}
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function DatePickerMonthGrid({ classNames, onSelect, onTitleClick, ...props }: DatePickerMonthGridProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
//# sourceMappingURL=MonthGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonthGrid.d.ts","sourceRoot":"","sources":["../../../src/components/DatePicker/MonthGrid.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAI5C,MAAM,WAAW,6BAA6B;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAC5F,UAAU,CAAC,EAAE,6BAA6B,CAAC;IAC3C,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,wBAAwB,2CAqG1B"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { getMonthName } from '@kalyx/core';
|
|
4
|
+
import { useDatePickerContext } from '../../context/DatePickerContext.js';
|
|
5
|
+
/**
|
|
6
|
+
* DatePicker.MonthGrid — 12개월 그리드에서 월을 빠르게 선택.
|
|
7
|
+
* Calendar 타이틀 클릭 → MonthGrid 표시 → 월 클릭 → Calendar로 복귀.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* {view === 'months' && (
|
|
12
|
+
* <DatePicker.MonthGrid
|
|
13
|
+
* onSelect={() => setView('days')}
|
|
14
|
+
* onTitleClick={() => setView('years')}
|
|
15
|
+
* />
|
|
16
|
+
* )}
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function DatePickerMonthGrid({ classNames, onSelect, onTitleClick, ...props }) {
|
|
20
|
+
const ctx = useDatePickerContext('DatePicker.MonthGrid');
|
|
21
|
+
const { adapter, viewMonth, locale } = ctx;
|
|
22
|
+
const currentYear = adapter.getYear(viewMonth);
|
|
23
|
+
const currentMonth = adapter.getMonth(viewMonth);
|
|
24
|
+
const todayMonth = adapter.getMonth(adapter.today());
|
|
25
|
+
const todayYear = adapter.getYear(adapter.today());
|
|
26
|
+
const navigateYear = useCallback((direction) => {
|
|
27
|
+
const newDate = adapter.addYears(viewMonth, direction);
|
|
28
|
+
ctx.setViewMonth(newDate);
|
|
29
|
+
}, [adapter, viewMonth, ctx]);
|
|
30
|
+
const handleMonthSelect = useCallback((monthIndex) => {
|
|
31
|
+
// 현재 년도 + 선택된 월의 1일로 viewMonth 설정
|
|
32
|
+
const target = new Date(Date.UTC(currentYear, monthIndex, 1)).toISOString();
|
|
33
|
+
ctx.setViewMonth(target);
|
|
34
|
+
ctx.setFocusedDate(target);
|
|
35
|
+
onSelect?.();
|
|
36
|
+
}, [currentYear, ctx, onSelect]);
|
|
37
|
+
const months = Array.from({ length: 12 }, (_, i) => ({
|
|
38
|
+
index: i,
|
|
39
|
+
name: getMonthName(i, locale),
|
|
40
|
+
isSelected: i === currentMonth,
|
|
41
|
+
isCurrent: i === todayMonth && currentYear === todayYear,
|
|
42
|
+
}));
|
|
43
|
+
return (_jsxs("div", { className: classNames?.root, ...props, children: [_jsxs("div", { className: classNames?.header, children: [_jsx("button", { type: "button", className: classNames?.navButton, onClick: () => navigateYear(-1), "aria-label": "\uC774\uC804 \uB144", children: "<" }), onTitleClick ? (_jsx("button", { type: "button", className: classNames?.title, onClick: onTitleClick, children: currentYear })) : (_jsx("span", { className: classNames?.title, children: currentYear })), _jsx("button", { type: "button", className: classNames?.navButton, onClick: () => navigateYear(1), "aria-label": "\uB2E4\uC74C \uB144", children: ">" })] }), _jsx("div", { role: "grid", "aria-label": `${currentYear} months`, className: classNames?.grid, style: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }, children: months.map((m) => {
|
|
44
|
+
const monthClass = [
|
|
45
|
+
classNames?.month,
|
|
46
|
+
m.isSelected && classNames?.monthSelected,
|
|
47
|
+
m.isCurrent && classNames?.monthCurrent,
|
|
48
|
+
]
|
|
49
|
+
.filter(Boolean)
|
|
50
|
+
.join(' ') || undefined;
|
|
51
|
+
return (_jsx("button", { type: "button", role: "gridcell", "aria-selected": m.isSelected || undefined, "aria-current": m.isCurrent ? 'date' : undefined, "data-selected": m.isSelected || undefined, "data-current": m.isCurrent || undefined, className: monthClass, onClick: () => handleMonthSelect(m.index), children: m.name }, m.index));
|
|
52
|
+
}) })] }));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=MonthGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonthGrid.js","sourceRoot":"","sources":["../../../src/components/DatePicker/MonthGrid.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface DatePickerPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'role'> {
|
|
3
|
+
children?: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
export declare function DatePickerPopover({ children, ...props }: DatePickerPopoverProps): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
//# sourceMappingURL=Popover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../../src/components/DatePicker/Popover.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUvD,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAC1F,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,sBAAsB,kDAuF/E"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { useFloating, autoUpdate, offset, flip, shift, } from '@floating-ui/react';
|
|
4
|
+
import { useDatePickerContext } from '../../context/DatePickerContext.js';
|
|
5
|
+
export function DatePickerPopover({ children, ...props }) {
|
|
6
|
+
const ctx = useDatePickerContext('DatePicker.Popover');
|
|
7
|
+
const calendarId = `${ctx.pickerId}-calendar`;
|
|
8
|
+
const floatingRef = useRef(null);
|
|
9
|
+
const { refs, floatingStyles } = useFloating({
|
|
10
|
+
open: ctx.isOpen,
|
|
11
|
+
placement: 'bottom-start',
|
|
12
|
+
middleware: [offset(4), flip(), shift({ padding: 8 })],
|
|
13
|
+
whileElementsMounted: autoUpdate,
|
|
14
|
+
});
|
|
15
|
+
// Context의 referenceRef를 Floating UI에 연결
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (ctx.referenceRef.current) {
|
|
18
|
+
refs.setReference(ctx.referenceRef.current);
|
|
19
|
+
}
|
|
20
|
+
}, [ctx.referenceRef, refs, ctx.isOpen]);
|
|
21
|
+
// 포커스 복원: 닫힐 때 이전 포커스 요소로 복원
|
|
22
|
+
const previousFocusRef = useRef(null);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (ctx.isOpen) {
|
|
25
|
+
previousFocusRef.current = document.activeElement;
|
|
26
|
+
}
|
|
27
|
+
else if (previousFocusRef.current) {
|
|
28
|
+
previousFocusRef.current.focus();
|
|
29
|
+
previousFocusRef.current = null;
|
|
30
|
+
}
|
|
31
|
+
}, [ctx.isOpen]);
|
|
32
|
+
// 바깥 클릭 감지
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!ctx.isOpen)
|
|
35
|
+
return;
|
|
36
|
+
function handleClickOutside(e) {
|
|
37
|
+
const floating = floatingRef.current;
|
|
38
|
+
const reference = ctx.referenceRef.current;
|
|
39
|
+
const target = e.target;
|
|
40
|
+
if (floating && !floating.contains(target) && (!reference || !reference.contains(target))) {
|
|
41
|
+
ctx.close();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// 다음 틱에 등록해서 현재 클릭 이벤트는 무시
|
|
45
|
+
const timer = setTimeout(() => {
|
|
46
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
47
|
+
}, 0);
|
|
48
|
+
return () => {
|
|
49
|
+
clearTimeout(timer);
|
|
50
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
51
|
+
};
|
|
52
|
+
}, [ctx.isOpen, ctx]);
|
|
53
|
+
// Escape 키 처리
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (!ctx.isOpen)
|
|
56
|
+
return;
|
|
57
|
+
function handleKeyDown(e) {
|
|
58
|
+
if (e.key === 'Escape') {
|
|
59
|
+
ctx.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
63
|
+
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
64
|
+
}, [ctx.isOpen, ctx]);
|
|
65
|
+
if (!ctx.isOpen)
|
|
66
|
+
return null;
|
|
67
|
+
return (_jsx("div", { ref: (node) => {
|
|
68
|
+
floatingRef.current = node;
|
|
69
|
+
refs.setFloating(node);
|
|
70
|
+
}, id: calendarId, role: "dialog", "aria-label": "\uB0A0\uC9DC \uC120\uD0DD", "aria-modal": "false", style: floatingStyles, ...props, children: children }));
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=Popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Popover.js","sourceRoot":"","sources":["../../../src/components/DatePicker/Popover.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EACL,WAAW,EACX,UAAU,EACV,MAAM,EACN,IAAI,EACJ,KAAK,GACN,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAM1E,MAAM,UAAU,iBAAiB,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAA0B;IAC9E,MAAM,GAAG,GAAG,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,GAAG,GAAG,CAAC,QAAQ,WAAW,CAAC;IAC9C,MAAM,WAAW,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IAExD,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC;QAC3C,IAAI,EAAE,GAAG,CAAC,MAAM;QAChB,SAAS,EAAE,cAAc;QACzB,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QACtD,oBAAoB,EAAE,UAAU;KACjC,CAAC,CAAC;IAEH,yCAAyC;IACzC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAEzC,6BAA6B;IAC7B,MAAM,gBAAgB,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IAE1D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,gBAAgB,CAAC,OAAO,GAAG,QAAQ,CAAC,aAA4B,CAAC;QACnE,CAAC;aAAM,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;YACpC,gBAAgB,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC;QAClC,CAAC;IACH,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAEjB,WAAW;IACX,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,OAAO;QAExB,SAAS,kBAAkB,CAAC,CAAa;YACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC;YACrC,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC;YAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,MAAc,CAAC;YAChC,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC1F,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QAC7D,CAAC,EAAE,CAAC,CAAC,CAAC;QAEN,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QAChE,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAEtB,cAAc;IACd,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,OAAO;QAExB,SAAS,aAAa,CAAC,CAAgB;YACrC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACvB,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACpD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACtE,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAEtB,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE7B,OAAO,CACL,cACE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;YACZ,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC,EACD,EAAE,EAAE,UAAU,EACd,IAAI,EAAC,QAAQ,gBACF,2BAAO,gBACP,OAAO,EAClB,KAAK,EAAE,cAAc,KACjB,KAAK,YAER,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { DateAdapter, DisabledRule, ISODateString, WeekStartsOn } from '@kalyx/core';
|
|
3
|
+
/**
|
|
4
|
+
* DatePicker의 Root 컴포넌트 props.
|
|
5
|
+
*
|
|
6
|
+
* @example 제어 모드
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <DatePicker value={date} onChange={setDate}>
|
|
9
|
+
* <DatePicker.Input />
|
|
10
|
+
* <DatePicker.Popover>
|
|
11
|
+
* <DatePicker.Calendar />
|
|
12
|
+
* </DatePicker.Popover>
|
|
13
|
+
* </DatePicker>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @example 비제어 모드
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <DatePicker defaultValue="2026-01-15T00:00:00.000Z">
|
|
19
|
+
* <DatePicker.Input />
|
|
20
|
+
* </DatePicker>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export interface DatePickerRootProps {
|
|
24
|
+
/** 선택된 날짜 (제어 모드, ISO 8601 UTC). `null`이면 빈 상태. */
|
|
25
|
+
value?: ISODateString | null;
|
|
26
|
+
/** 초기 날짜 (비제어 모드) */
|
|
27
|
+
defaultValue?: ISODateString;
|
|
28
|
+
/** 날짜 변경 콜백 */
|
|
29
|
+
onChange?: (value: ISODateString | null) => void;
|
|
30
|
+
/** 비활성화 규칙 */
|
|
31
|
+
disabled?: DisabledRule[] | boolean;
|
|
32
|
+
/** 읽기 전용 */
|
|
33
|
+
readOnly?: boolean;
|
|
34
|
+
/** 주 시작 요일 */
|
|
35
|
+
weekStartsOn?: WeekStartsOn;
|
|
36
|
+
/** 날짜 표시 포맷 */
|
|
37
|
+
displayFormat?: string;
|
|
38
|
+
/** BCP 47 locale (예: "en-US", "ko-KR", "ja-JP") */
|
|
39
|
+
locale?: string;
|
|
40
|
+
/** 날짜 어댑터 */
|
|
41
|
+
adapter?: DateAdapter;
|
|
42
|
+
/** 자식 컴포넌트 */
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
}
|
|
45
|
+
export declare function DatePickerRoot({ value: controlledValue, defaultValue, onChange, disabled, readOnly, weekStartsOn, displayFormat, locale, adapter, children, }: DatePickerRootProps): import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
//# sourceMappingURL=Root.d.ts.map
|