@ceed/ads 1.5.4 → 1.5.6-next.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.
@@ -1,6 +1,8 @@
1
1
  export declare const getCalendarDates: (date: Date) => (number | undefined)[][];
2
2
  export declare const getYearName: (date: Date, locale: string) => string;
3
- export declare const getMonthName: (date: Date, locale: string) => string;
3
+ export declare const getMonthName: (date: Date, locale: string, options?: {
4
+ hideYear?: boolean;
5
+ }) => string;
4
6
  export declare const getMonthNameFromIndex: (index: number, locale: string) => string;
5
7
  /**
6
8
  * 일~토 / Sun ~ Sat 같은 요일 이름을 가져옵니다.
@@ -20,6 +20,8 @@ interface BaseMonthPickerProps {
20
20
  disableFuture?: boolean;
21
21
  disablePast?: boolean;
22
22
  format?: string;
23
+ displayFormat?: string;
24
+ locale?: string;
23
25
  }
24
26
  export type MonthPickerProps = BaseMonthPickerProps & Omit<React.ComponentProps<typeof Input>, "onChange" | "value" | "defaultValue">;
25
27
  declare const MonthPicker: React.ForwardRefExoticComponent<Omit<MonthPickerProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
@@ -1,3 +1,3 @@
1
1
  export declare function useControlledState<T>(controlledValue: T | undefined, defaultValue: T, onChange?: (value: T) => void, options?: {
2
2
  disableStrict?: boolean;
3
- }): [T, (value: T | ((prev: T) => T)) => void];
3
+ }): [T, (value: T | ((prev: T) => T)) => void, boolean];
package/dist/index.cjs CHANGED
@@ -405,25 +405,26 @@ var IconButton_default = IconButton;
405
405
  var import_react5 = require("react");
406
406
  function useControlledState(controlledValue, defaultValue, onChange, options) {
407
407
  const { current: isControlled } = (0, import_react5.useRef)(controlledValue !== void 0);
408
- const [displayValue, setDisplayValue] = (0, import_react5.useState)(
408
+ const [internalValue, setInternalValue] = (0, import_react5.useState)(
409
409
  controlledValue ?? defaultValue
410
410
  );
411
+ const displayValue = isControlled ? controlledValue : internalValue;
411
412
  (0, import_react5.useEffect)(() => {
412
413
  if (isControlled) {
413
- setDisplayValue(controlledValue ?? defaultValue);
414
+ setInternalValue(controlledValue);
414
415
  }
415
- }, [controlledValue, defaultValue, isControlled]);
416
+ }, [isControlled, controlledValue]);
416
417
  const handleChange = (0, import_react5.useCallback)(
417
418
  (value) => {
418
419
  const newValue = typeof value === "function" ? value(displayValue) : value;
419
- if (options?.disableStrict || !isControlled) {
420
- setDisplayValue(newValue);
420
+ if (!isControlled) {
421
+ setInternalValue(newValue);
421
422
  }
422
423
  onChange?.(newValue);
423
424
  },
424
- [isControlled, onChange, displayValue, options]
425
+ [isControlled, onChange, displayValue]
425
426
  );
426
- return [displayValue, handleChange];
427
+ return [displayValue, handleChange, isControlled];
427
428
  }
428
429
 
429
430
  // src/components/Autocomplete/Autocomplete.tsx
@@ -865,8 +866,11 @@ var getCalendarDates = (date) => {
865
866
  var getYearName = (date, locale) => {
866
867
  return date.toLocaleString(locale, { year: "numeric" });
867
868
  };
868
- var getMonthName = (date, locale) => {
869
- return date.toLocaleString(locale, { year: "numeric", month: "long" });
869
+ var getMonthName = (date, locale, options) => {
870
+ return date.toLocaleString(locale, {
871
+ month: "long",
872
+ ...options?.hideYear ? {} : { year: "numeric" }
873
+ });
870
874
  };
871
875
  var getMonthNameFromIndex = (index, locale) => {
872
876
  return new Date(0, index).toLocaleString(locale, { month: "short" });
@@ -4976,7 +4980,6 @@ MenuButton.displayName = "MenuButton";
4976
4980
 
4977
4981
  // src/components/MonthPicker/MonthPicker.tsx
4978
4982
  var import_react33 = __toESM(require("react"));
4979
- var import_react_imask3 = require("react-imask");
4980
4983
  var import_CalendarToday3 = __toESM(require("@mui/icons-material/CalendarToday"));
4981
4984
  var import_joy46 = require("@mui/joy");
4982
4985
  var import_base4 = require("@mui/base");
@@ -5002,60 +5005,35 @@ var MonthPickerRoot = (0, import_joy46.styled)("div", {
5002
5005
  })({
5003
5006
  width: "100%"
5004
5007
  });
5005
- var formatValueString3 = (date, format) => {
5006
- let month = `${date.getMonth() + 1}`;
5007
- const year = date.getFullYear();
5008
- if (Number(month) < 10) month = "0" + month;
5009
- return format.replace(/YYYY/g, year.toString()).replace(/MM/g, month);
5010
- };
5011
- var formatToPattern3 = (format) => {
5012
- return format.replace(/YYYY/g, "Y").replace(/MM/g, "M").replace(/[^YM\s]/g, (match) => `${match}\``);
5008
+ var formatValueString3 = (date, format, locale = "default") => {
5009
+ const year = date.getFullYear().toString();
5010
+ const month = (date.getMonth() + 1).toString().padStart(2, "0");
5011
+ const monthName = getMonthName(date, locale, { hideYear: true });
5012
+ const day = "01";
5013
+ return format.replace(/MMMM/g, monthName).replace(/MM/g, month).replace(/DD/g, day).replace(/YYYY/g, year);
5013
5014
  };
5014
- function parseDate3(dateString) {
5015
+ function parseDate3(dateString, format) {
5016
+ const dateParts = dateString.split(/[-./\s]/);
5017
+ const formatParts = format.split(/[-./\s]/);
5018
+ if (formatParts.length !== dateParts.length) {
5019
+ throw new Error("Invalid date string or format");
5020
+ }
5015
5021
  let month, year;
5016
- const cleanDateString = dateString.replace(/[^\d]/g, "");
5017
- if (dateString.match(/\d{1,2}.\d{4}/)) {
5018
- month = cleanDateString.slice(0, 2);
5019
- year = cleanDateString.slice(2);
5020
- } else if (dateString.match(/\d{4}.\d{1,2}/)) {
5021
- year = cleanDateString.slice(0, 4);
5022
- month = cleanDateString.slice(4);
5022
+ const day = 1;
5023
+ for (let i = 0; i < formatParts.length; i++) {
5024
+ const value = parseInt(dateParts[i], 10);
5025
+ switch (formatParts[i]) {
5026
+ case "MM":
5027
+ month = value - 1;
5028
+ break;
5029
+ case "YYYY":
5030
+ year = value;
5031
+ break;
5032
+ }
5023
5033
  }
5024
- const date = /* @__PURE__ */ new Date(`${year}/${month}`);
5025
- return date;
5034
+ const result = new Date(year, month, day);
5035
+ return result;
5026
5036
  }
5027
- var TextMaskAdapter7 = import_react33.default.forwardRef(
5028
- function TextMaskAdapter8(props, ref) {
5029
- const { onChange, format, ...other } = props;
5030
- return /* @__PURE__ */ import_react33.default.createElement(
5031
- import_react_imask3.IMaskInput,
5032
- {
5033
- ...other,
5034
- inputRef: ref,
5035
- onAccept: (value) => onChange({ target: { name: props.name, value } }),
5036
- mask: Date,
5037
- pattern: formatToPattern3(format),
5038
- blocks: {
5039
- M: {
5040
- mask: import_react_imask3.IMask.MaskedRange,
5041
- from: 1,
5042
- to: 12,
5043
- maxLength: 2
5044
- },
5045
- Y: {
5046
- mask: import_react_imask3.IMask.MaskedRange,
5047
- from: 1900,
5048
- to: 9999
5049
- }
5050
- },
5051
- format: (date) => formatValueString3(date, format),
5052
- parse: parseDate3,
5053
- autofix: "pad",
5054
- overwrite: true
5055
- }
5056
- );
5057
- }
5058
- );
5059
5037
  var MonthPicker = (0, import_react33.forwardRef)(
5060
5038
  (inProps, ref) => {
5061
5039
  const props = (0, import_joy46.useThemeProps)({ props: inProps, name: "MonthPicker" });
@@ -5073,12 +5051,20 @@ var MonthPicker = (0, import_react33.forwardRef)(
5073
5051
  // NOTE: 스타일 관련된 props는 최상위 엘리먼트에 적용한다.
5074
5052
  sx,
5075
5053
  className,
5076
- format = "YYYY/MM",
5054
+ /**
5055
+ * NOTE: 현재 CalendarDate는 YYYY-MM-DD로 개발하고 있어 date를 포함하여 value를 관리한다.
5056
+ * @see https://ecubelabs.atlassian.net/wiki/spaces/SW/pages/1938784349/Date#CalendarDate
5057
+ * @see https://github.com/Ecube-Labs/hds/pull/145
5058
+ */
5059
+ format = "YYYY/MM/DD",
5060
+ displayFormat = "YYYY/MM",
5077
5061
  size,
5062
+ locale,
5078
5063
  ...innerProps
5079
5064
  } = props;
5080
5065
  const innerRef = (0, import_react33.useRef)(null);
5081
- const [value, setValue] = useControlledState(
5066
+ const buttonRef = (0, import_react33.useRef)(null);
5067
+ const [value, setValue, isControlled] = useControlledState(
5082
5068
  props.value,
5083
5069
  props.defaultValue || "",
5084
5070
  (0, import_react33.useCallback)(
@@ -5087,6 +5073,24 @@ var MonthPicker = (0, import_react33.forwardRef)(
5087
5073
  ),
5088
5074
  { disableStrict: true }
5089
5075
  );
5076
+ const getFormattedDisplayValue = (0, import_react33.useCallback)(
5077
+ (inputValue) => {
5078
+ if (!inputValue) return "";
5079
+ try {
5080
+ return formatValueString3(
5081
+ parseDate3(inputValue, format),
5082
+ displayFormat,
5083
+ locale
5084
+ );
5085
+ } catch (e) {
5086
+ return inputValue;
5087
+ }
5088
+ },
5089
+ [format, displayFormat, locale]
5090
+ );
5091
+ const [displayValue, setDisplayValue] = (0, import_react33.useState)(
5092
+ () => getFormattedDisplayValue(value)
5093
+ );
5090
5094
  const [anchorEl, setAnchorEl] = (0, import_react33.useState)(null);
5091
5095
  const open = Boolean(anchorEl);
5092
5096
  (0, import_react33.useEffect)(() => {
@@ -5097,11 +5101,18 @@ var MonthPicker = (0, import_react33.forwardRef)(
5097
5101
  (0, import_react33.useImperativeHandle)(ref, () => innerRef.current, [
5098
5102
  innerRef
5099
5103
  ]);
5104
+ (0, import_react33.useEffect)(() => {
5105
+ setDisplayValue(getFormattedDisplayValue(value));
5106
+ }, [value, getFormattedDisplayValue]);
5100
5107
  const handleChange = (0, import_react33.useCallback)(
5101
5108
  (event) => {
5102
- setValue(event.target.value);
5109
+ const newValue = event.target.value;
5110
+ setValue(newValue);
5111
+ if (!isControlled) {
5112
+ setDisplayValue(getFormattedDisplayValue(newValue));
5113
+ }
5103
5114
  },
5104
- [setValue]
5115
+ [setValue, getFormattedDisplayValue, isControlled]
5105
5116
  );
5106
5117
  const handleCalendarToggle = (0, import_react33.useCallback)(
5107
5118
  (event) => {
@@ -5110,6 +5121,13 @@ var MonthPicker = (0, import_react33.forwardRef)(
5110
5121
  },
5111
5122
  [anchorEl, setAnchorEl, innerRef]
5112
5123
  );
5124
+ const handleInputMouseDown = (0, import_react33.useCallback)(
5125
+ (event) => {
5126
+ event.preventDefault();
5127
+ buttonRef.current?.focus();
5128
+ },
5129
+ [buttonRef]
5130
+ );
5113
5131
  return /* @__PURE__ */ import_react33.default.createElement(MonthPickerRoot, null, /* @__PURE__ */ import_react33.default.createElement(import_base4.FocusTrap, { open: true }, /* @__PURE__ */ import_react33.default.createElement(import_react33.default.Fragment, null, /* @__PURE__ */ import_react33.default.createElement(
5114
5132
  Input_default,
5115
5133
  {
@@ -5117,13 +5135,21 @@ var MonthPicker = (0, import_react33.forwardRef)(
5117
5135
  color: error ? "danger" : innerProps.color,
5118
5136
  ref: innerRef,
5119
5137
  size,
5120
- value,
5121
- onChange: handleChange,
5122
- placeholder: format,
5138
+ value: displayValue,
5139
+ placeholder: displayFormat,
5123
5140
  disabled,
5124
5141
  required,
5125
5142
  slotProps: {
5126
- input: { component: TextMaskAdapter7, ref: innerRef, format }
5143
+ input: {
5144
+ ref: innerRef,
5145
+ format: displayFormat,
5146
+ sx: {
5147
+ "&:hover": {
5148
+ cursor: "default"
5149
+ }
5150
+ },
5151
+ onMouseDown: handleInputMouseDown
5152
+ }
5127
5153
  },
5128
5154
  error,
5129
5155
  className,
@@ -5135,12 +5161,14 @@ var MonthPicker = (0, import_react33.forwardRef)(
5135
5161
  endDecorator: /* @__PURE__ */ import_react33.default.createElement(
5136
5162
  IconButton_default,
5137
5163
  {
5164
+ ref: buttonRef,
5138
5165
  variant: "plain",
5139
5166
  onClick: handleCalendarToggle,
5140
5167
  "aria-label": "Toggle Calendar",
5141
5168
  "aria-controls": "month-picker-popper",
5142
5169
  "aria-haspopup": "dialog",
5143
- "aria-expanded": open
5170
+ "aria-expanded": open,
5171
+ disabled
5144
5172
  },
5145
5173
  /* @__PURE__ */ import_react33.default.createElement(import_CalendarToday3.default, null)
5146
5174
  ),
@@ -5176,7 +5204,7 @@ var MonthPicker = (0, import_react33.forwardRef)(
5176
5204
  handleChange({
5177
5205
  target: {
5178
5206
  name: props.name,
5179
- value: formatValueString3(date, format)
5207
+ value: formatValueString3(date, format, locale)
5180
5208
  }
5181
5209
  });
5182
5210
  setAnchorEl(null);
@@ -5184,7 +5212,8 @@ var MonthPicker = (0, import_react33.forwardRef)(
5184
5212
  minDate: minDate ? new Date(minDate) : void 0,
5185
5213
  maxDate: maxDate ? new Date(maxDate) : void 0,
5186
5214
  disableFuture,
5187
- disablePast
5215
+ disablePast,
5216
+ locale
5188
5217
  }
5189
5218
  ), /* @__PURE__ */ import_react33.default.createElement(
5190
5219
  DialogActions_default,
@@ -5218,7 +5247,7 @@ var MonthPicker = (0, import_react33.forwardRef)(
5218
5247
 
5219
5248
  // src/components/MonthRangePicker/MonthRangePicker.tsx
5220
5249
  var import_react34 = __toESM(require("react"));
5221
- var import_react_imask4 = require("react-imask");
5250
+ var import_react_imask3 = require("react-imask");
5222
5251
  var import_CalendarToday4 = __toESM(require("@mui/icons-material/CalendarToday"));
5223
5252
  var import_joy47 = require("@mui/joy");
5224
5253
  var import_base5 = require("@mui/base");
@@ -5272,29 +5301,29 @@ var parseDates2 = (str) => {
5272
5301
  const date2 = str.split(" - ")[1] || "";
5273
5302
  return [parseDate4(date1), parseDate4(date2)];
5274
5303
  };
5275
- var formatToPattern4 = (format) => {
5304
+ var formatToPattern3 = (format) => {
5276
5305
  return `${format} - ${format}`.replace(/YYYY/g, "Y").replace(/MM/g, "m").replace(/[^YMm\s]/g, (match) => `${match}\``);
5277
5306
  };
5278
- var TextMaskAdapter9 = import_react34.default.forwardRef(
5279
- function TextMaskAdapter10(props, ref) {
5307
+ var TextMaskAdapter7 = import_react34.default.forwardRef(
5308
+ function TextMaskAdapter8(props, ref) {
5280
5309
  const { onChange, format, ...other } = props;
5281
5310
  return /* @__PURE__ */ import_react34.default.createElement(
5282
- import_react_imask4.IMaskInput,
5311
+ import_react_imask3.IMaskInput,
5283
5312
  {
5284
5313
  ...other,
5285
5314
  inputRef: ref,
5286
5315
  onAccept: (value) => onChange({ target: { name: props.name, value } }),
5287
5316
  mask: Date,
5288
- pattern: formatToPattern4(format),
5317
+ pattern: formatToPattern3(format),
5289
5318
  blocks: {
5290
5319
  m: {
5291
- mask: import_react_imask4.IMask.MaskedRange,
5320
+ mask: import_react_imask3.IMask.MaskedRange,
5292
5321
  from: 1,
5293
5322
  to: 12,
5294
5323
  maxLength: 2
5295
5324
  },
5296
5325
  Y: {
5297
- mask: import_react_imask4.IMask.MaskedRange,
5326
+ mask: import_react_imask3.IMask.MaskedRange,
5298
5327
  from: 1900,
5299
5328
  to: 9999
5300
5329
  }
@@ -5386,7 +5415,7 @@ var MonthRangePicker = (0, import_react34.forwardRef)(
5386
5415
  required,
5387
5416
  placeholder: `${format} - ${format}`,
5388
5417
  slotProps: {
5389
- input: { component: TextMaskAdapter9, ref: innerRef, format }
5418
+ input: { component: TextMaskAdapter7, ref: innerRef, format }
5390
5419
  },
5391
5420
  error,
5392
5421
  className,
@@ -5587,8 +5616,8 @@ var padDecimal = (value, decimalScale) => {
5587
5616
  const [integer, decimal = ""] = `${value}`.split(".");
5588
5617
  return Number(`${integer}${decimal.padEnd(decimalScale, "0")}`);
5589
5618
  };
5590
- var TextMaskAdapter11 = import_react38.default.forwardRef(
5591
- function TextMaskAdapter12(props, ref) {
5619
+ var TextMaskAdapter9 = import_react38.default.forwardRef(
5620
+ function TextMaskAdapter10(props, ref) {
5592
5621
  const { onChange, min, max, ...innerProps } = props;
5593
5622
  return /* @__PURE__ */ import_react38.default.createElement(
5594
5623
  import_react_number_format2.NumericFormat,
@@ -5684,7 +5713,7 @@ var PercentageInput = import_react38.default.forwardRef(function PercentageInput
5684
5713
  helperText,
5685
5714
  slotProps: {
5686
5715
  input: {
5687
- component: TextMaskAdapter11,
5716
+ component: TextMaskAdapter9,
5688
5717
  "aria-label": innerProps["aria-label"],
5689
5718
  decimalScale: maxDecimalScale
5690
5719
  }