podo-ui 0.8.0 → 0.8.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/cdn/font/icon.woff +0 -0
- package/cdn/podo-datepicker.css +486 -0
- package/cdn/podo-datepicker.js +1134 -0
- package/cdn/podo-datepicker.min.css +2 -0
- package/cdn/podo-datepicker.min.js +2 -0
- package/cdn/podo-ui.css +19855 -0
- package/cdn/podo-ui.min.css +2 -0
- package/dist/react/molecule/datepicker.d.ts +20 -0
- package/dist/react/molecule/datepicker.d.ts.map +1 -1
- package/dist/react/molecule/datepicker.js +83 -8
- package/package.json +17 -3
- package/scss/icon/font/icon.woff +0 -0
- package/scss/icon/icon-name.scss +17 -0
- package/vanilla/datepicker.css +481 -0
- package/vanilla/datepicker.js +1129 -0
|
@@ -29,6 +29,14 @@ export interface DateTimeLimit {
|
|
|
29
29
|
}
|
|
30
30
|
/** 분 단위 선택 옵션 */
|
|
31
31
|
export type MinuteStep = 1 | 5 | 10 | 15 | 20 | 30;
|
|
32
|
+
/** 초기 달력 표시 월 설정 */
|
|
33
|
+
export type CalendarInitial = 'now' | 'prevMonth' | 'nextMonth' | Date;
|
|
34
|
+
export interface InitialCalendar {
|
|
35
|
+
/** 시작 달력 초기 월 (period 모드의 왼쪽 달력) */
|
|
36
|
+
start?: CalendarInitial;
|
|
37
|
+
/** 종료 달력 초기 월 (period 모드의 오른쪽 달력) */
|
|
38
|
+
end?: CalendarInitial;
|
|
39
|
+
}
|
|
32
40
|
export interface DatePickerProps {
|
|
33
41
|
/** 선택 모드: instant(단일) | period(기간) */
|
|
34
42
|
mode?: DatePickerMode;
|
|
@@ -58,6 +66,18 @@ export interface DatePickerProps {
|
|
|
58
66
|
maxDate?: Date | DateTimeLimit;
|
|
59
67
|
/** 분 단위 선택 간격 (1, 5, 10, 15, 30) 기본값: 1 */
|
|
60
68
|
minuteStep?: MinuteStep;
|
|
69
|
+
/**
|
|
70
|
+
* 날짜/시간 표시 포맷
|
|
71
|
+
* y: 년, m: 월, d: 일, h: 시, i: 분
|
|
72
|
+
* 예시: "y-m-d", "y.m.d h:i", "y년 m월 d일 h시 i분"
|
|
73
|
+
*/
|
|
74
|
+
format?: string;
|
|
75
|
+
/**
|
|
76
|
+
* 기간 선택 모드에서 초기 달력 표시 월 설정
|
|
77
|
+
* start: 왼쪽 달력, end: 오른쪽 달력
|
|
78
|
+
* 값: 'now' | 'prevMonth' | 'nextMonth' | Date
|
|
79
|
+
*/
|
|
80
|
+
initialCalendar?: InitialCalendar;
|
|
61
81
|
}
|
|
62
82
|
declare const DatePicker: React.FC<DatePickerProps>;
|
|
63
83
|
export default DatePicker;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datepicker.d.ts","sourceRoot":"","sources":["../../../react/molecule/datepicker.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;AAClD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAE1D,kBAAkB;AAClB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,sBAAsB;IACtB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,mBAAmB;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uCAAuC;IACvC,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,oCAAoC;IACpC,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,eAAe;AACf,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,IAAI,CAAC;CACV;AAED,wBAAwB;AACxB,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;AAEzE,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,iBAAiB;AACjB,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,mCAAmC;IACnC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,YAAY;IACZ,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,cAAc;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5C,aAAa;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,WAAW;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,iCAAiC;IACjC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,IAAI,GAAG,aAAa,CAAC;IAC/B,4CAA4C;IAC5C,OAAO,CAAC,EAAE,IAAI,GAAG,aAAa,CAAC;IAC/B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"datepicker.d.ts","sourceRoot":"","sources":["../../../react/molecule/datepicker.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;AAClD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAE1D,kBAAkB;AAClB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,sBAAsB;IACtB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,mBAAmB;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uCAAuC;IACvC,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,oCAAoC;IACpC,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,eAAe;AACf,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,IAAI,CAAC;CACV;AAED,wBAAwB;AACxB,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;AAEzE,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,iBAAiB;AACjB,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEnD,oBAAoB;AACpB,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,oCAAoC;IACpC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,qCAAqC;IACrC,GAAG,CAAC,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,mCAAmC;IACnC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,YAAY;IACZ,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,cAAc;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5C,aAAa;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,WAAW;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,iCAAiC;IACjC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,IAAI,GAAG,aAAa,CAAC;IAC/B,4CAA4C;IAC5C,OAAO,CAAC,EAAE,IAAI,GAAG,aAAa,CAAC;IAC/B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAujBD,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAklBzC,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -3,6 +3,43 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import styles from './datepicker.module.scss';
|
|
5
5
|
// Helper functions
|
|
6
|
+
/** CalendarInitial 값을 Date로 변환 */
|
|
7
|
+
const resolveCalendarInitial = (initial, fallback) => {
|
|
8
|
+
if (!initial)
|
|
9
|
+
return fallback;
|
|
10
|
+
if (initial instanceof Date)
|
|
11
|
+
return initial;
|
|
12
|
+
const now = new Date();
|
|
13
|
+
switch (initial) {
|
|
14
|
+
case 'now':
|
|
15
|
+
return new Date(now.getFullYear(), now.getMonth(), 1);
|
|
16
|
+
case 'prevMonth':
|
|
17
|
+
return new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
18
|
+
case 'nextMonth':
|
|
19
|
+
return new Date(now.getFullYear(), now.getMonth() + 1, 1);
|
|
20
|
+
default:
|
|
21
|
+
return fallback;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* 커스텀 포맷으로 날짜/시간 포맷팅
|
|
26
|
+
* y: 년(4자리), m: 월(2자리), d: 일(2자리), h: 시(2자리), i: 분(2자리)
|
|
27
|
+
*/
|
|
28
|
+
const formatWithPattern = (date, time, pattern) => {
|
|
29
|
+
if (!date && !time)
|
|
30
|
+
return '';
|
|
31
|
+
let result = pattern;
|
|
32
|
+
if (date) {
|
|
33
|
+
result = result.replace(/y/g, String(date.getFullYear()));
|
|
34
|
+
result = result.replace(/m/g, String(date.getMonth() + 1).padStart(2, '0'));
|
|
35
|
+
result = result.replace(/d/g, String(date.getDate()).padStart(2, '0'));
|
|
36
|
+
}
|
|
37
|
+
if (time) {
|
|
38
|
+
result = result.replace(/h/g, String(time.hour).padStart(2, '0'));
|
|
39
|
+
result = result.replace(/i/g, String(time.minute).padStart(2, '0'));
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
6
43
|
const formatDate = (date) => {
|
|
7
44
|
const year = date.getFullYear();
|
|
8
45
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
@@ -265,12 +302,27 @@ const PeriodCalendar = ({ value, endValue, onSelect, viewDate, endViewDate, onVi
|
|
|
265
302
|
return (_jsxs("div", { className: styles.periodCalendars, children: [_jsx("div", { className: styles.periodCalendarLeft, children: _jsx(Calendar, { value: value, endValue: endValue, mode: "period", onSelect: onSelect, viewDate: viewDate, onViewDateChange: onViewDateChange, showPrevNav: true, showNextNav: true, maxViewDate: endViewDate, disable: disable, enable: enable, minDate: minDate, maxDate: maxDate }) }), _jsx("div", { className: styles.periodCalendarRight, children: _jsx(Calendar, { value: value, endValue: endValue, mode: "period", onSelect: onSelect, viewDate: endViewDate, onViewDateChange: onEndViewDateChange, showPrevNav: true, showNextNav: true, minViewDate: viewDate, disable: disable, enable: enable, minDate: minDate, maxDate: maxDate }) })] }));
|
|
266
303
|
};
|
|
267
304
|
// Main DatePicker Component
|
|
268
|
-
const DatePicker = ({ mode = 'instant', type = 'date', value, onChange, placeholder, disabled = false, showActions, align = 'left', className, disable, enable, minDate, maxDate, minuteStep = 1, }) => {
|
|
305
|
+
const DatePicker = ({ mode = 'instant', type = 'date', value, onChange, placeholder, disabled = false, showActions, align = 'left', className, disable, enable, minDate, maxDate, minuteStep = 1, format, initialCalendar, }) => {
|
|
269
306
|
const [selectingPart, setSelectingPart] = useState(null);
|
|
270
307
|
const [tempValue, setTempValue] = useState(value || {});
|
|
271
|
-
|
|
308
|
+
// 초기 달력 표시 월 계산
|
|
309
|
+
const [viewDate, setViewDate] = useState(() => {
|
|
310
|
+
if (value?.date)
|
|
311
|
+
return value.date;
|
|
312
|
+
if (initialCalendar?.start) {
|
|
313
|
+
return resolveCalendarInitial(initialCalendar.start, new Date());
|
|
314
|
+
}
|
|
315
|
+
return new Date();
|
|
316
|
+
});
|
|
272
317
|
const [endViewDate, setEndViewDate] = useState(() => {
|
|
273
|
-
|
|
318
|
+
if (value?.endDate) {
|
|
319
|
+
return new Date(value.endDate.getFullYear(), value.endDate.getMonth() + 1, 1);
|
|
320
|
+
}
|
|
321
|
+
if (initialCalendar?.end) {
|
|
322
|
+
return resolveCalendarInitial(initialCalendar.end, new Date());
|
|
323
|
+
}
|
|
324
|
+
// 기본값: 현재 달의 다음 달
|
|
325
|
+
const d = new Date();
|
|
274
326
|
return new Date(d.getFullYear(), d.getMonth() + 1, 1);
|
|
275
327
|
});
|
|
276
328
|
const containerRef = useRef(null);
|
|
@@ -294,6 +346,16 @@ const DatePicker = ({ mode = 'instant', type = 'date', value, onChange, placehol
|
|
|
294
346
|
const formatPeriodText = () => {
|
|
295
347
|
if (!tempValue.date)
|
|
296
348
|
return '';
|
|
349
|
+
// format prop이 있으면 사용
|
|
350
|
+
if (format) {
|
|
351
|
+
const startText = formatWithPattern(tempValue.date, tempValue.time, format);
|
|
352
|
+
if (tempValue.endDate) {
|
|
353
|
+
const endText = formatWithPattern(tempValue.endDate, tempValue.endTime, format);
|
|
354
|
+
return `${startText} ~ ${endText}`;
|
|
355
|
+
}
|
|
356
|
+
return startText;
|
|
357
|
+
}
|
|
358
|
+
// 기본 포맷 (한국어)
|
|
297
359
|
const formatKoreanDateTime = (date, time) => {
|
|
298
360
|
const year = date.getFullYear();
|
|
299
361
|
const month = date.getMonth() + 1;
|
|
@@ -422,15 +484,28 @@ const DatePicker = ({ mode = 'instant', type = 'date', value, onChange, placehol
|
|
|
422
484
|
const displayValue = shouldShowActions ? tempValue : value;
|
|
423
485
|
const hasStartValue = !!displayValue?.date;
|
|
424
486
|
const hasEndValue = !!displayValue?.endDate;
|
|
487
|
+
// 날짜만 표시하는 포맷 (시간 제외)
|
|
488
|
+
const getDateOnlyFormat = () => {
|
|
489
|
+
if (!format)
|
|
490
|
+
return undefined;
|
|
491
|
+
// 시간 관련 부분 제거 (h, i 및 그 주변 문자들)
|
|
492
|
+
return format.replace(/\s*h[:\s]*i[분]?/g, '').replace(/\s*h시\s*i분/g, '').trim();
|
|
493
|
+
};
|
|
425
494
|
// Helper to render date button
|
|
426
495
|
const renderDateButton = (date, isActive, onClick, isPlaceholder) => {
|
|
496
|
+
const dateFormat = getDateOnlyFormat();
|
|
427
497
|
if (isPlaceholder || !date) {
|
|
428
|
-
|
|
498
|
+
// format이 있으면 placeholder도 포맷에 맞게 표시
|
|
499
|
+
const placeholderText = dateFormat
|
|
500
|
+
? dateFormat.replace(/y/g, 'YYYY').replace(/m/g, 'MM').replace(/d/g, 'DD')
|
|
501
|
+
: 'YYYY - MM - DD';
|
|
502
|
+
return (_jsx("button", { type: "button", className: `${styles.inputPart} ${isActive ? styles.active : ''} ${styles.placeholder}`, onClick: onClick, children: placeholderText }));
|
|
429
503
|
}
|
|
430
|
-
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
504
|
+
// format prop이 있으면 사용 (날짜만)
|
|
505
|
+
const displayText = dateFormat
|
|
506
|
+
? formatWithPattern(date, undefined, dateFormat)
|
|
507
|
+
: `${date.getFullYear()} - ${String(date.getMonth() + 1).padStart(2, '0')} - ${String(date.getDate()).padStart(2, '0')}`;
|
|
508
|
+
return (_jsx("button", { type: "button", className: `${styles.inputPart} ${isActive ? styles.active : ''}`, onClick: onClick, children: displayText }));
|
|
434
509
|
};
|
|
435
510
|
// Helper to render hour select
|
|
436
511
|
const renderHourSelect = (time, part, isPlaceholder) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "podo-ui",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "hada0127 <work@tarucy.net>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
17
|
"files": [
|
|
18
18
|
"dist",
|
|
19
|
+
"cdn",
|
|
20
|
+
"vanilla",
|
|
19
21
|
"scss",
|
|
20
22
|
"global.scss",
|
|
21
23
|
"global.d.ts",
|
|
@@ -55,13 +57,25 @@
|
|
|
55
57
|
"types": "./global.d.ts",
|
|
56
58
|
"default": "./scss/*"
|
|
57
59
|
},
|
|
58
|
-
"./package.json": "./package.json"
|
|
60
|
+
"./package.json": "./package.json",
|
|
61
|
+
"./cdn/podo-ui.css": "./cdn/podo-ui.css",
|
|
62
|
+
"./cdn/podo-ui.min.css": "./cdn/podo-ui.min.css",
|
|
63
|
+
"./cdn/podo-datepicker.js": "./cdn/podo-datepicker.js",
|
|
64
|
+
"./cdn/podo-datepicker.min.js": "./cdn/podo-datepicker.min.js",
|
|
65
|
+
"./cdn/podo-datepicker.css": "./cdn/podo-datepicker.css",
|
|
66
|
+
"./cdn/podo-datepicker.min.css": "./cdn/podo-datepicker.min.css",
|
|
67
|
+
"./cdn/font/*": "./cdn/font/*",
|
|
68
|
+
"./vanilla/datepicker": "./vanilla/datepicker.js",
|
|
69
|
+
"./vanilla/datepicker.css": "./vanilla/datepicker.css"
|
|
59
70
|
},
|
|
60
71
|
"scripts": {
|
|
61
72
|
"dev": "next dev -p 5432",
|
|
62
73
|
"build": "next build",
|
|
63
74
|
"build:lib": "node ./cli/build-lib.js",
|
|
64
|
-
"
|
|
75
|
+
"build:cdn": "node ./cli/build-cdn.js",
|
|
76
|
+
"build:cdn-js": "node ./cli/build-cdn-js.js",
|
|
77
|
+
"build:all": "npm run build:lib && npm run build:cdn && npm run build:cdn-js",
|
|
78
|
+
"prepublishOnly": "npm run build:all",
|
|
65
79
|
"start": "next start",
|
|
66
80
|
"lint": "next lint",
|
|
67
81
|
"icon": "node ./cli/icon-scss.js",
|
package/scss/icon/font/icon.woff
CHANGED
|
Binary file
|
package/scss/icon/icon-name.scss
CHANGED
|
@@ -116,4 +116,21 @@ $icon-name: (
|
|
|
116
116
|
lock: \e977,
|
|
117
117
|
unlock: \e978,
|
|
118
118
|
save: \e979,
|
|
119
|
+
database: \e980,
|
|
120
|
+
undo: \e981,
|
|
121
|
+
redo: \e982,
|
|
122
|
+
unlink-alt: \e983,
|
|
123
|
+
youtube-stroke: \e984,
|
|
124
|
+
horizontalLine: \e985,
|
|
125
|
+
gap: \e986,
|
|
126
|
+
clipboard: \e987,
|
|
127
|
+
inputForm: \e988,
|
|
128
|
+
copy: \e989,
|
|
129
|
+
text: \e990,
|
|
130
|
+
logout: \e991,
|
|
131
|
+
detailView: \e992,
|
|
132
|
+
company: \e993,
|
|
133
|
+
landing: \e994,
|
|
134
|
+
code: \e995,
|
|
135
|
+
footer: \e996,
|
|
119
136
|
);
|