@ncds/ui-admin 1.5.1 → 1.5.3

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.
@@ -31,6 +31,9 @@ var __rest = void 0 && (void 0).__rest || function (s, e) {
31
31
  }
32
32
  return t;
33
33
  };
34
+
35
+ /** biome-ignore-all lint/correctness/noUnusedVariables: <explanation> */
36
+
34
37
  var isValidDate = function (dateString) {
35
38
  var date = new Date(dateString);
36
39
  return date instanceof Date && !isNaN(date.getTime());
@@ -45,17 +48,117 @@ var DatePicker = exports.DatePicker = /*#__PURE__*/(0, _react.forwardRef)(functi
45
48
  datePickerOptions = _a.datePickerOptions,
46
49
  _d = _a.isEndDate,
47
50
  isEndDate = _d === void 0 ? false : _d,
48
- attrs = __rest(_a, ["shouldFocus", "currentDate", "size", "onChangeDate", "datePickerOptions", "isEndDate"]);
49
- var onChangeDateHandler = function (dateTimeStamp, dateStr) {
51
+ onValidationError = _a.onValidationError,
52
+ attrs = __rest(_a, ["shouldFocus", "currentDate", "size", "onChangeDate", "datePickerOptions", "isEndDate", "onValidationError"]);
53
+ var flatpickrInstanceRef = (0, _react.useRef)(null);
54
+ var dateFormatRef = (0, _react.useRef)('Y-m-d');
55
+ var minMaxDateRef = (0, _react.useRef)({});
56
+ var checkDateViolations = function (date, minDate, maxDate) {
57
+ var violations = [];
58
+ var inputDate = (0, _moment.default)(date);
59
+ if (!inputDate.isValid()) return violations;
60
+ if (minDate) {
61
+ var min = (0, _moment.default)(minDate);
62
+ if (min.isValid() && inputDate.isBefore(min, 'day')) {
63
+ violations.push('minDate');
64
+ }
65
+ }
66
+ if (maxDate) {
67
+ var max = (0, _moment.default)(maxDate);
68
+ if (max.isValid() && inputDate.isAfter(max, 'day')) {
69
+ violations.push('maxDate');
70
+ }
71
+ }
72
+ return violations;
73
+ };
74
+ var onChangeDateHandler = function (dateTimeStamp, dateStr, instance) {
75
+ var _a;
76
+ if (!dateTimeStamp || dateTimeStamp.length === 0) {
77
+ restorePreviousDate(instance.input, instance);
78
+ return;
79
+ }
80
+ var selectedDate = dateTimeStamp[0];
81
+ if (!selectedDate || !(selectedDate instanceof Date) || isNaN(selectedDate.getTime())) {
82
+ // 유효하지 않은 날짜 - 이전 값으로 복원하거나 빈 값으로 처리
83
+ var previousDate = instance === null || instance === void 0 ? void 0 : instance._previousDateBeforeInput;
84
+ if (previousDate && previousDate instanceof Date && !isNaN(previousDate.getTime())) {
85
+ // 이전 값이 있으면 이전 값으로 복원
86
+ instance.selectedDates = [previousDate];
87
+ instance.setDate(previousDate, false);
88
+ } else {
89
+ // 이전 값이 없으면 빈 값으로 처리
90
+ restorePreviousDate(instance.input, instance);
91
+ }
92
+ return;
93
+ }
94
+ var minDate = options.minDate,
95
+ maxDate = options.maxDate;
96
+ var violations = checkDateViolations(selectedDate, minDate, maxDate);
97
+ if (violations.length > 0) {
98
+ var prevDate = (_a = instance === null || instance === void 0 ? void 0 : instance.selectedDates) === null || _a === void 0 ? void 0 : _a[0];
99
+ if (onValidationError) {
100
+ onValidationError({
101
+ date: selectedDate,
102
+ minDate: minDate,
103
+ maxDate: maxDate,
104
+ violations: violations,
105
+ previousDate: prevDate instanceof Date && !isNaN(prevDate.getTime()) ? prevDate : undefined
106
+ });
107
+ return; // onValidationError가 있으면 날짜 변경 안 함
108
+ }
109
+ // onValidationError가 없으면 범위를 벗어난 날짜도 허용 (계속 진행)
110
+ }
111
+ // 유효한 날짜인 경우 이전 날짜로 저장
112
+ instance._previousDateBeforeInput = selectedDate;
50
113
  var formattedDate = (0, _datePicker.formatDateInput)(dateStr);
51
114
  isValidDate(formattedDate) ? onChangeDate(formattedDate) : onChangeDate(dateStr);
52
115
  };
116
+ var restorePreviousDate = function (target, instance) {
117
+ if (instance.selectedDates.length > 0) {
118
+ var prevDate = instance.selectedDates[0];
119
+ if (prevDate instanceof Date && !isNaN(prevDate.getTime())) {
120
+ var momentFormat = dateFormatRef.current.replace(/Y/g, 'YYYY').replace(/m/g, 'MM').replace(/d/g, 'DD');
121
+ target.value = (0, _moment.default)(prevDate).format(momentFormat);
122
+ instance.setDate(prevDate, false);
123
+ return;
124
+ }
125
+ }
126
+ target.value = '';
127
+ instance.setDate('', false);
128
+ };
53
129
  var onInputHandler = function (e) {
54
130
  var target = e.target;
55
131
  var input = target.value;
132
+ var instance = flatpickrInstanceRef.current;
133
+ if (!instance) return;
134
+ if (!input || input.trim() === '') {
135
+ return;
136
+ }
137
+ // 숫자가 최소 하나는 포함되어야 함 (하이픈만 있는 경우 방지)
138
+ if (!/[0-9]/.test(input)) {
139
+ restorePreviousDate(target, instance);
140
+ return;
141
+ }
56
142
  var formattedInput = (0, _datePicker.formatDateInput)(input);
57
- if (formattedInput === input) return;
58
- target.value = formattedInput;
143
+ if (formattedInput !== input) {
144
+ target.value = formattedInput;
145
+ return;
146
+ }
147
+ if (formattedInput && formattedInput.length >= 10) {
148
+ var parsedDate = (0, _moment.default)(formattedInput);
149
+ if (!parsedDate.isValid()) {
150
+ restorePreviousDate(target, instance);
151
+ return;
152
+ }
153
+ var parsedDateObj = parsedDate.toDate();
154
+ var violations = checkDateViolations(parsedDateObj, minMaxDateRef.current.minDate, minMaxDateRef.current.maxDate);
155
+ if (violations.length > 0) {
156
+ // onInputHandler에서는 onValidationError를 호출하지 않음
157
+ // validation은 onChangeDateHandler에서만 처리
158
+ // onValidationError가 없으면 아무것도 하지 않음 (범위를 벗어난 날짜도 허용)
159
+ return;
160
+ }
161
+ }
59
162
  };
60
163
  var onHourInputHandler = function (e) {
61
164
  var target = e.target;
@@ -79,13 +182,50 @@ var DatePicker = exports.DatePicker = /*#__PURE__*/(0, _react.forwardRef)(functi
79
182
  dateFormat: 'Y-m-d',
80
183
  clickOpens: true,
81
184
  time_24hr: true,
185
+ formatDate: function (date, format, locale) {
186
+ try {
187
+ // 유효한 날짜인지 확인
188
+ if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
189
+ return '';
190
+ }
191
+ // moment로 포맷팅
192
+ var momentDate = (0, _moment.default)(date);
193
+ if (!momentDate.isValid()) {
194
+ return '';
195
+ }
196
+ // format을 moment 형식으로 변환
197
+ var momentFormat = format.replace(/Y/g, 'YYYY').replace(/y/g, 'YY').replace(/m/g, 'MM').replace(/d/g, 'DD').replace(/H/g, 'HH').replace(/i/g, 'mm').replace(/S/g, 'ss');
198
+ return momentDate.format(momentFormat);
199
+ } catch (error) {
200
+ // 오류 발생 시 빈 문자열 반환 (232-23 같은 잘못된 날짜 처리)
201
+ return '';
202
+ }
203
+ },
82
204
  onChange: onChangeDateHandler,
83
205
  allowInvalidPreload: true,
84
206
  onReady: function (selectedDates, dateStr, instance) {
85
207
  var _a;
86
208
  var input = instance.input;
87
209
  if (!input) return;
210
+ flatpickrInstanceRef.current = instance;
211
+ dateFormatRef.current = (datePickerOptions === null || datePickerOptions === void 0 ? void 0 : datePickerOptions.dateFormat) || options.dateFormat || 'Y-m-d';
212
+ minMaxDateRef.current = {
213
+ minDate: (datePickerOptions === null || datePickerOptions === void 0 ? void 0 : datePickerOptions.minDate) || options.minDate,
214
+ maxDate: (datePickerOptions === null || datePickerOptions === void 0 ? void 0 : datePickerOptions.maxDate) || options.maxDate
215
+ };
216
+ // blur 시점에 현재 selectedDates를 저장 (입력 전 상태)
217
+ var onBlurHandler = function (e) {
218
+ if (instance && instance.selectedDates.length > 0) {
219
+ // 이전 날짜를 별도로 저장 (onChange에서 사용)
220
+ instance._previousDateBeforeInput = instance.selectedDates[0];
221
+ }
222
+ };
88
223
  input.addEventListener('input', onInputHandler);
224
+ input.addEventListener('blur', onBlurHandler);
225
+ // 초기 날짜가 있으면 저장
226
+ if (instance.selectedDates.length > 0) {
227
+ instance._previousDateBeforeInput = instance.selectedDates[0];
228
+ }
89
229
  var timeInputWrapper = (_a = input.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('.flatpickr-time');
90
230
  if (!timeInputWrapper) return;
91
231
  var hourInput = timeInputWrapper.querySelector('.flatpickr-hour');
@@ -107,13 +247,20 @@ var DatePicker = exports.DatePicker = /*#__PURE__*/(0, _react.forwardRef)(functi
107
247
  };
108
248
  document.addEventListener('mousedown', handleMouseDown, true);
109
249
  instance._handleMouseDown = handleMouseDown;
250
+ instance._onBlurHandler = onBlurHandler;
110
251
  },
111
252
  onDestroy: function (selectedDates, dateStr, instance) {
112
253
  var _a;
113
254
  var input = instance.input;
114
255
  if (!input) return;
256
+ flatpickrInstanceRef.current = null;
115
257
  // 메인 input 이벤트 리스너 제거
116
258
  input.removeEventListener('input', onInputHandler);
259
+ // blur 이벤트 리스너 제거
260
+ var onBlurHandler = instance === null || instance === void 0 ? void 0 : instance._onBlurHandler;
261
+ if (onBlurHandler) {
262
+ input.removeEventListener('blur', onBlurHandler);
263
+ }
117
264
  var timeInputWrapper = (_a = input.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('.flatpickr-time');
118
265
  if (!timeInputWrapper) return;
119
266
  // 시간 input 이벤트 리스너 제거
@@ -166,7 +313,17 @@ var DatePicker = exports.DatePicker = /*#__PURE__*/(0, _react.forwardRef)(functi
166
313
  var defaultValue = _a.defaultValue,
167
314
  value = _a.value,
168
315
  props = __rest(_a, ["defaultValue", "value"]);
169
- return (0, _jsxRuntime.jsx)(_CustomInput.CustomInput, __assign({}, props, {
316
+ // input에 반영 되면 안되는 attribute 제외
317
+ var _b = props,
318
+ allowInput = _b.allowInput,
319
+ dateFormat = _b.dateFormat,
320
+ minDate = _b.minDate,
321
+ maxDate = _b.maxDate,
322
+ enableTime = _b.enableTime,
323
+ enableSeconds = _b.enableSeconds,
324
+ noCalendar = _b.noCalendar,
325
+ inputProps = __rest(_b, ["allowInput", "dateFormat", "minDate", "maxDate", "enableTime", "enableSeconds", "noCalendar"]);
326
+ return (0, _jsxRuntime.jsx)(_CustomInput.CustomInput, __assign({}, inputProps, {
170
327
  id: inputId,
171
328
  iconSize: size,
172
329
  disabled: !!attrs.disabled,
@@ -31,9 +31,11 @@ var RangeDatePickerWithButtons = function (_a) {
31
31
  endDateOptions = _a.endDateOptions,
32
32
  validationOption = _a.validationOption,
33
33
  periodKeys = _a.periodKeys,
34
+ periodItems = _a.periodItems,
34
35
  onDateValidation = _a.onDateValidation;
36
+ var items = periodItems !== null && periodItems !== void 0 ? periodItems : _datePicker.PERIOD_ITEM;
35
37
  var setCalculatedDate = function () {
36
- var currentPeriodItem = _datePicker.PERIOD_ITEM[currentButtonId];
38
+ var currentPeriodItem = items[currentButtonId];
37
39
  if (!currentPeriodItem) {
38
40
  return;
39
41
  }
@@ -71,7 +73,7 @@ var RangeDatePickerWithButtons = function (_a) {
71
73
  children: periodKeys.map(function (key) {
72
74
  return (0, _jsxRuntime.jsx)(_button.ButtonGroup.Item, {
73
75
  isCurrent: currentButtonId === key,
74
- label: _datePicker.PERIOD_ITEM[key].text,
76
+ label: items[key].text,
75
77
  onClick: function () {
76
78
  return setCurrentButtonId(key);
77
79
  }
@@ -5,13 +5,13 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.ImageFileInputErrorType = exports.ImageFileInput = void 0;
7
7
  var _jsxRuntime = require("react/jsx-runtime");
8
- var _react = require("react");
9
- var _classnames = _interopRequireDefault(require("classnames"));
10
8
  var _dynamic = _interopRequireDefault(require("@ncds/ui-admin-icon/dynamic"));
9
+ var _classnames = _interopRequireDefault(require("classnames"));
10
+ var _react = require("react");
11
11
  var _button = require("../button");
12
12
  var _shared = require("../shared");
13
- var _ImagePreview = require("./components/ImagePreview");
14
13
  var _tooltip = require("../tooltip");
14
+ var _ImagePreview = require("./components/ImagePreview");
15
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
16
  var __assign = void 0 && (void 0).__assign || function () {
17
17
  __assign = Object.assign || function (t) {
@@ -189,7 +189,9 @@ var ImageFileInput = exports.ImageFileInput = /*#__PURE__*/(0, _react.forwardRef
189
189
  children: [(0, _jsxRuntime.jsx)(_button.Button, {
190
190
  onlyIcon: true,
191
191
  size: size,
192
- className: "ncua-image-file-input__preview-container",
192
+ className: (0, _classnames.default)('ncua-image-file-input__preview-container', {
193
+ destructive: destructive
194
+ }),
193
195
  onClick: handleBrowseClick,
194
196
  disabled: disabled,
195
197
  label: imagePreviewTooltipLabel
@@ -8,7 +8,6 @@ var _jsxRuntime = require("react/jsx-runtime");
8
8
  var _uiAdminIcon = require("@ncds/ui-admin-icon");
9
9
  var _classnames = _interopRequireDefault(require("classnames"));
10
10
  var _react = require("react");
11
- var _hooks = require("../../hooks");
12
11
  var _InputBase = require("./InputBase");
13
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
13
  var __assign = void 0 && (void 0).__assign || function () {
@@ -40,37 +39,23 @@ var PasswordInput = exports.PasswordInput = /*#__PURE__*/(0, _react.forwardRef)(
40
39
  var _c = (0, _react.useState)(false),
41
40
  isVisible = _c[0],
42
41
  setIsVisible = _c[1];
43
- var _d = (0, _react.useState)(false),
44
- hasContent = _d[0],
45
- setHasContent = _d[1];
46
- var callbackRef = (0, _hooks.useCallbackRef)(function (node) {
47
- if (node) {
48
- setHasContent(!!node.value);
49
- var handleInput_1 = function () {
50
- setHasContent(!!node.value);
51
- };
52
- node.addEventListener('input', handleInput_1);
53
- return function () {
54
- node.removeEventListener('input', handleInput_1);
55
- };
56
- }
57
- });
58
- var mergedRef = (0, _hooks.useMergeRefs)([ref, callbackRef]);
59
42
  var svgProps = {
60
43
  width: svgSize[size],
61
44
  height: svgSize[size]
62
45
  };
63
46
  var handleVisibilityChange = function () {
64
- setIsVisible(!isVisible);
47
+ setIsVisible(function (prev) {
48
+ return !prev;
49
+ });
65
50
  };
66
51
  return (0, _jsxRuntime.jsx)(_InputBase.InputBase, __assign({
67
- ref: mergedRef,
52
+ ref: ref,
68
53
  size: size,
69
54
  type: isVisible ? 'text' : 'password',
70
55
  leadingElement: {
71
56
  type: 'icon',
72
57
  icon: 'lock-01',
73
- color: hasContent ? 'gray600' : 'gray300'
58
+ color: props.value ? 'gray600' : 'gray300'
74
59
  },
75
60
  trailingElement: {
76
61
  type: 'custom',
@@ -46,8 +46,8 @@ var Pagination = function (_a) {
46
46
  var _f = (0, _react.useState)(1),
47
47
  start = _f[0],
48
48
  setStart = _f[1];
49
- var noPrev = start === 1;
50
- var noNext = start + pageCount - 1 >= totalPage;
49
+ var noPrev = breakPoint === 'mo' ? currentPage === 1 : start === 1;
50
+ var noNext = breakPoint === 'mo' ? currentPage >= totalPage : start + pageCount - 1 >= totalPage;
51
51
  var showJumpPageButton = totalPage > pageCount;
52
52
  var handleClickButton = function (pageNum) {
53
53
  if ((0, _lodashEs.isFunction)(onPageChange)) {
@@ -69,7 +69,7 @@ var Pagination = function (_a) {
69
69
  setStart(1);
70
70
  }
71
71
  if (currentPage === totalPage) {
72
- var lastGroupStart = Math.max(1, totalPage - pageCount + 1);
72
+ var lastGroupStart = Math.floor((totalPage - 1) / pageCount) * pageCount + 1;
73
73
  setStart(lastGroupStart);
74
74
  }
75
75
  }, [currentPage]);
@@ -92,7 +92,7 @@ var Pagination = function (_a) {
92
92
  noPrev: noPrev,
93
93
  noNext: noNext,
94
94
  onClick: function () {
95
- return handleClickButton(Math.max(start - pageCount, 1));
95
+ return breakPoint === 'mo' ? handleClickButton(Math.max(currentPage - 1, 1)) : handleClickButton(Math.max(start - pageCount, 1));
96
96
  }
97
97
  })]
98
98
  }), (0, _jsxRuntime.jsx)("ul", __assign({
@@ -129,7 +129,7 @@ var Pagination = function (_a) {
129
129
  noPrev: noPrev,
130
130
  noNext: noNext,
131
131
  onClick: function () {
132
- return handleClickButton(Math.min(start + pageCount, totalPage));
132
+ return breakPoint === 'mo' ? handleClickButton(Math.min(currentPage + 1, totalPage)) : handleClickButton(Math.min(start + pageCount, totalPage));
133
133
  }
134
134
  }), (0, _NavButton.NavButton)({
135
135
  type: 'last',
@@ -39,7 +39,7 @@ var HorizontalTab = function (_a) {
39
39
  };
40
40
  if (!menus.length) return (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {});
41
41
  return (0, _jsxRuntime.jsx)("div", __assign({
42
- className: (0, _classnames.default)('ncua-horizontal-tab', "ncua-horizontal-tab--".concat(type), {
42
+ className: (0, _classnames.default)('ncua-horizontal-tab', "ncua-horizontal-tab--".concat(type), "ncua-horizontal-tab--".concat(size), {
43
43
  'ncua-horizontal-tab--fullWidth': fullWidth
44
44
  })
45
45
  }, {