@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.
package/dist/index.js CHANGED
@@ -313,25 +313,26 @@ var IconButton_default = IconButton;
313
313
  import { useState, useCallback, useEffect, useRef } from "react";
314
314
  function useControlledState(controlledValue, defaultValue, onChange, options) {
315
315
  const { current: isControlled } = useRef(controlledValue !== void 0);
316
- const [displayValue, setDisplayValue] = useState(
316
+ const [internalValue, setInternalValue] = useState(
317
317
  controlledValue ?? defaultValue
318
318
  );
319
+ const displayValue = isControlled ? controlledValue : internalValue;
319
320
  useEffect(() => {
320
321
  if (isControlled) {
321
- setDisplayValue(controlledValue ?? defaultValue);
322
+ setInternalValue(controlledValue);
322
323
  }
323
- }, [controlledValue, defaultValue, isControlled]);
324
+ }, [isControlled, controlledValue]);
324
325
  const handleChange = useCallback(
325
326
  (value) => {
326
327
  const newValue = typeof value === "function" ? value(displayValue) : value;
327
- if (options?.disableStrict || !isControlled) {
328
- setDisplayValue(newValue);
328
+ if (!isControlled) {
329
+ setInternalValue(newValue);
329
330
  }
330
331
  onChange?.(newValue);
331
332
  },
332
- [isControlled, onChange, displayValue, options]
333
+ [isControlled, onChange, displayValue]
333
334
  );
334
- return [displayValue, handleChange];
335
+ return [displayValue, handleChange, isControlled];
335
336
  }
336
337
 
337
338
  // src/components/Autocomplete/Autocomplete.tsx
@@ -785,8 +786,11 @@ var getCalendarDates = (date) => {
785
786
  var getYearName = (date, locale) => {
786
787
  return date.toLocaleString(locale, { year: "numeric" });
787
788
  };
788
- var getMonthName = (date, locale) => {
789
- return date.toLocaleString(locale, { year: "numeric", month: "long" });
789
+ var getMonthName = (date, locale, options) => {
790
+ return date.toLocaleString(locale, {
791
+ month: "long",
792
+ ...options?.hideYear ? {} : { year: "numeric" }
793
+ });
790
794
  };
791
795
  var getMonthNameFromIndex = (index, locale) => {
792
796
  return new Date(0, index).toLocaleString(locale, { month: "short" });
@@ -4963,7 +4967,6 @@ import React31, {
4963
4967
  useRef as useRef7,
4964
4968
  useState as useState10
4965
4969
  } from "react";
4966
- import { IMaskInput as IMaskInput3, IMask as IMask3 } from "react-imask";
4967
4970
  import CalendarTodayIcon3 from "@mui/icons-material/CalendarToday";
4968
4971
  import { styled as styled20, useThemeProps as useThemeProps6 } from "@mui/joy";
4969
4972
  import { FocusTrap as FocusTrap3, ClickAwayListener as ClickAwayListener3, Popper as Popper4 } from "@mui/base";
@@ -4989,60 +4992,35 @@ var MonthPickerRoot = styled20("div", {
4989
4992
  })({
4990
4993
  width: "100%"
4991
4994
  });
4992
- var formatValueString3 = (date, format) => {
4993
- let month = `${date.getMonth() + 1}`;
4994
- const year = date.getFullYear();
4995
- if (Number(month) < 10) month = "0" + month;
4996
- return format.replace(/YYYY/g, year.toString()).replace(/MM/g, month);
4997
- };
4998
- var formatToPattern3 = (format) => {
4999
- return format.replace(/YYYY/g, "Y").replace(/MM/g, "M").replace(/[^YM\s]/g, (match) => `${match}\``);
4995
+ var formatValueString3 = (date, format, locale = "default") => {
4996
+ const year = date.getFullYear().toString();
4997
+ const month = (date.getMonth() + 1).toString().padStart(2, "0");
4998
+ const monthName = getMonthName(date, locale, { hideYear: true });
4999
+ const day = "01";
5000
+ return format.replace(/MMMM/g, monthName).replace(/MM/g, month).replace(/DD/g, day).replace(/YYYY/g, year);
5000
5001
  };
5001
- function parseDate3(dateString) {
5002
+ function parseDate3(dateString, format) {
5003
+ const dateParts = dateString.split(/[-./\s]/);
5004
+ const formatParts = format.split(/[-./\s]/);
5005
+ if (formatParts.length !== dateParts.length) {
5006
+ throw new Error("Invalid date string or format");
5007
+ }
5002
5008
  let month, year;
5003
- const cleanDateString = dateString.replace(/[^\d]/g, "");
5004
- if (dateString.match(/\d{1,2}.\d{4}/)) {
5005
- month = cleanDateString.slice(0, 2);
5006
- year = cleanDateString.slice(2);
5007
- } else if (dateString.match(/\d{4}.\d{1,2}/)) {
5008
- year = cleanDateString.slice(0, 4);
5009
- month = cleanDateString.slice(4);
5009
+ const day = 1;
5010
+ for (let i = 0; i < formatParts.length; i++) {
5011
+ const value = parseInt(dateParts[i], 10);
5012
+ switch (formatParts[i]) {
5013
+ case "MM":
5014
+ month = value - 1;
5015
+ break;
5016
+ case "YYYY":
5017
+ year = value;
5018
+ break;
5019
+ }
5010
5020
  }
5011
- const date = /* @__PURE__ */ new Date(`${year}/${month}`);
5012
- return date;
5021
+ const result = new Date(year, month, day);
5022
+ return result;
5013
5023
  }
5014
- var TextMaskAdapter7 = React31.forwardRef(
5015
- function TextMaskAdapter8(props, ref) {
5016
- const { onChange, format, ...other } = props;
5017
- return /* @__PURE__ */ React31.createElement(
5018
- IMaskInput3,
5019
- {
5020
- ...other,
5021
- inputRef: ref,
5022
- onAccept: (value) => onChange({ target: { name: props.name, value } }),
5023
- mask: Date,
5024
- pattern: formatToPattern3(format),
5025
- blocks: {
5026
- M: {
5027
- mask: IMask3.MaskedRange,
5028
- from: 1,
5029
- to: 12,
5030
- maxLength: 2
5031
- },
5032
- Y: {
5033
- mask: IMask3.MaskedRange,
5034
- from: 1900,
5035
- to: 9999
5036
- }
5037
- },
5038
- format: (date) => formatValueString3(date, format),
5039
- parse: parseDate3,
5040
- autofix: "pad",
5041
- overwrite: true
5042
- }
5043
- );
5044
- }
5045
- );
5046
5024
  var MonthPicker = forwardRef9(
5047
5025
  (inProps, ref) => {
5048
5026
  const props = useThemeProps6({ props: inProps, name: "MonthPicker" });
@@ -5060,12 +5038,20 @@ var MonthPicker = forwardRef9(
5060
5038
  // NOTE: 스타일 관련된 props는 최상위 엘리먼트에 적용한다.
5061
5039
  sx,
5062
5040
  className,
5063
- format = "YYYY/MM",
5041
+ /**
5042
+ * NOTE: 현재 CalendarDate는 YYYY-MM-DD로 개발하고 있어 date를 포함하여 value를 관리한다.
5043
+ * @see https://ecubelabs.atlassian.net/wiki/spaces/SW/pages/1938784349/Date#CalendarDate
5044
+ * @see https://github.com/Ecube-Labs/hds/pull/145
5045
+ */
5046
+ format = "YYYY/MM/DD",
5047
+ displayFormat = "YYYY/MM",
5064
5048
  size,
5049
+ locale,
5065
5050
  ...innerProps
5066
5051
  } = props;
5067
5052
  const innerRef = useRef7(null);
5068
- const [value, setValue] = useControlledState(
5053
+ const buttonRef = useRef7(null);
5054
+ const [value, setValue, isControlled] = useControlledState(
5069
5055
  props.value,
5070
5056
  props.defaultValue || "",
5071
5057
  useCallback12(
@@ -5074,6 +5060,24 @@ var MonthPicker = forwardRef9(
5074
5060
  ),
5075
5061
  { disableStrict: true }
5076
5062
  );
5063
+ const getFormattedDisplayValue = useCallback12(
5064
+ (inputValue) => {
5065
+ if (!inputValue) return "";
5066
+ try {
5067
+ return formatValueString3(
5068
+ parseDate3(inputValue, format),
5069
+ displayFormat,
5070
+ locale
5071
+ );
5072
+ } catch (e) {
5073
+ return inputValue;
5074
+ }
5075
+ },
5076
+ [format, displayFormat, locale]
5077
+ );
5078
+ const [displayValue, setDisplayValue] = useState10(
5079
+ () => getFormattedDisplayValue(value)
5080
+ );
5077
5081
  const [anchorEl, setAnchorEl] = useState10(null);
5078
5082
  const open = Boolean(anchorEl);
5079
5083
  useEffect9(() => {
@@ -5084,11 +5088,18 @@ var MonthPicker = forwardRef9(
5084
5088
  useImperativeHandle4(ref, () => innerRef.current, [
5085
5089
  innerRef
5086
5090
  ]);
5091
+ useEffect9(() => {
5092
+ setDisplayValue(getFormattedDisplayValue(value));
5093
+ }, [value, getFormattedDisplayValue]);
5087
5094
  const handleChange = useCallback12(
5088
5095
  (event) => {
5089
- setValue(event.target.value);
5096
+ const newValue = event.target.value;
5097
+ setValue(newValue);
5098
+ if (!isControlled) {
5099
+ setDisplayValue(getFormattedDisplayValue(newValue));
5100
+ }
5090
5101
  },
5091
- [setValue]
5102
+ [setValue, getFormattedDisplayValue, isControlled]
5092
5103
  );
5093
5104
  const handleCalendarToggle = useCallback12(
5094
5105
  (event) => {
@@ -5097,6 +5108,13 @@ var MonthPicker = forwardRef9(
5097
5108
  },
5098
5109
  [anchorEl, setAnchorEl, innerRef]
5099
5110
  );
5111
+ const handleInputMouseDown = useCallback12(
5112
+ (event) => {
5113
+ event.preventDefault();
5114
+ buttonRef.current?.focus();
5115
+ },
5116
+ [buttonRef]
5117
+ );
5100
5118
  return /* @__PURE__ */ React31.createElement(MonthPickerRoot, null, /* @__PURE__ */ React31.createElement(FocusTrap3, { open: true }, /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement(
5101
5119
  Input_default,
5102
5120
  {
@@ -5104,13 +5122,21 @@ var MonthPicker = forwardRef9(
5104
5122
  color: error ? "danger" : innerProps.color,
5105
5123
  ref: innerRef,
5106
5124
  size,
5107
- value,
5108
- onChange: handleChange,
5109
- placeholder: format,
5125
+ value: displayValue,
5126
+ placeholder: displayFormat,
5110
5127
  disabled,
5111
5128
  required,
5112
5129
  slotProps: {
5113
- input: { component: TextMaskAdapter7, ref: innerRef, format }
5130
+ input: {
5131
+ ref: innerRef,
5132
+ format: displayFormat,
5133
+ sx: {
5134
+ "&:hover": {
5135
+ cursor: "default"
5136
+ }
5137
+ },
5138
+ onMouseDown: handleInputMouseDown
5139
+ }
5114
5140
  },
5115
5141
  error,
5116
5142
  className,
@@ -5122,12 +5148,14 @@ var MonthPicker = forwardRef9(
5122
5148
  endDecorator: /* @__PURE__ */ React31.createElement(
5123
5149
  IconButton_default,
5124
5150
  {
5151
+ ref: buttonRef,
5125
5152
  variant: "plain",
5126
5153
  onClick: handleCalendarToggle,
5127
5154
  "aria-label": "Toggle Calendar",
5128
5155
  "aria-controls": "month-picker-popper",
5129
5156
  "aria-haspopup": "dialog",
5130
- "aria-expanded": open
5157
+ "aria-expanded": open,
5158
+ disabled
5131
5159
  },
5132
5160
  /* @__PURE__ */ React31.createElement(CalendarTodayIcon3, null)
5133
5161
  ),
@@ -5163,7 +5191,7 @@ var MonthPicker = forwardRef9(
5163
5191
  handleChange({
5164
5192
  target: {
5165
5193
  name: props.name,
5166
- value: formatValueString3(date, format)
5194
+ value: formatValueString3(date, format, locale)
5167
5195
  }
5168
5196
  });
5169
5197
  setAnchorEl(null);
@@ -5171,7 +5199,8 @@ var MonthPicker = forwardRef9(
5171
5199
  minDate: minDate ? new Date(minDate) : void 0,
5172
5200
  maxDate: maxDate ? new Date(maxDate) : void 0,
5173
5201
  disableFuture,
5174
- disablePast
5202
+ disablePast,
5203
+ locale
5175
5204
  }
5176
5205
  ), /* @__PURE__ */ React31.createElement(
5177
5206
  DialogActions_default,
@@ -5213,7 +5242,7 @@ import React32, {
5213
5242
  useRef as useRef8,
5214
5243
  useState as useState11
5215
5244
  } from "react";
5216
- import { IMaskInput as IMaskInput4, IMask as IMask4 } from "react-imask";
5245
+ import { IMaskInput as IMaskInput3, IMask as IMask3 } from "react-imask";
5217
5246
  import CalendarTodayIcon4 from "@mui/icons-material/CalendarToday";
5218
5247
  import { styled as styled21, useThemeProps as useThemeProps7 } from "@mui/joy";
5219
5248
  import { FocusTrap as FocusTrap4, ClickAwayListener as ClickAwayListener4, Popper as Popper5 } from "@mui/base";
@@ -5267,29 +5296,29 @@ var parseDates2 = (str) => {
5267
5296
  const date2 = str.split(" - ")[1] || "";
5268
5297
  return [parseDate4(date1), parseDate4(date2)];
5269
5298
  };
5270
- var formatToPattern4 = (format) => {
5299
+ var formatToPattern3 = (format) => {
5271
5300
  return `${format} - ${format}`.replace(/YYYY/g, "Y").replace(/MM/g, "m").replace(/[^YMm\s]/g, (match) => `${match}\``);
5272
5301
  };
5273
- var TextMaskAdapter9 = React32.forwardRef(
5274
- function TextMaskAdapter10(props, ref) {
5302
+ var TextMaskAdapter7 = React32.forwardRef(
5303
+ function TextMaskAdapter8(props, ref) {
5275
5304
  const { onChange, format, ...other } = props;
5276
5305
  return /* @__PURE__ */ React32.createElement(
5277
- IMaskInput4,
5306
+ IMaskInput3,
5278
5307
  {
5279
5308
  ...other,
5280
5309
  inputRef: ref,
5281
5310
  onAccept: (value) => onChange({ target: { name: props.name, value } }),
5282
5311
  mask: Date,
5283
- pattern: formatToPattern4(format),
5312
+ pattern: formatToPattern3(format),
5284
5313
  blocks: {
5285
5314
  m: {
5286
- mask: IMask4.MaskedRange,
5315
+ mask: IMask3.MaskedRange,
5287
5316
  from: 1,
5288
5317
  to: 12,
5289
5318
  maxLength: 2
5290
5319
  },
5291
5320
  Y: {
5292
- mask: IMask4.MaskedRange,
5321
+ mask: IMask3.MaskedRange,
5293
5322
  from: 1900,
5294
5323
  to: 9999
5295
5324
  }
@@ -5381,7 +5410,7 @@ var MonthRangePicker = forwardRef10(
5381
5410
  required,
5382
5411
  placeholder: `${format} - ${format}`,
5383
5412
  slotProps: {
5384
- input: { component: TextMaskAdapter9, ref: innerRef, format }
5413
+ input: { component: TextMaskAdapter7, ref: innerRef, format }
5385
5414
  },
5386
5415
  error,
5387
5416
  className,
@@ -5595,8 +5624,8 @@ var padDecimal = (value, decimalScale) => {
5595
5624
  const [integer, decimal = ""] = `${value}`.split(".");
5596
5625
  return Number(`${integer}${decimal.padEnd(decimalScale, "0")}`);
5597
5626
  };
5598
- var TextMaskAdapter11 = React36.forwardRef(
5599
- function TextMaskAdapter12(props, ref) {
5627
+ var TextMaskAdapter9 = React36.forwardRef(
5628
+ function TextMaskAdapter10(props, ref) {
5600
5629
  const { onChange, min, max, ...innerProps } = props;
5601
5630
  return /* @__PURE__ */ React36.createElement(
5602
5631
  NumericFormat2,
@@ -5692,7 +5721,7 @@ var PercentageInput = React36.forwardRef(function PercentageInput2(inProps, ref)
5692
5721
  helperText,
5693
5722
  slotProps: {
5694
5723
  input: {
5695
- component: TextMaskAdapter11,
5724
+ component: TextMaskAdapter9,
5696
5725
  "aria-label": innerProps["aria-label"],
5697
5726
  decimalScale: maxDecimalScale
5698
5727
  }