diginet-core-ui 1.4.54-beta.3 → 1.4.55

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.
@@ -29,7 +29,8 @@ const ButtonMore = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referenc
29
29
  options,
30
30
  optionType,
31
31
  popoverProp,
32
- style
32
+ style,
33
+ onClick
33
34
  } = props;
34
35
  const isOptionFull = optionType === 'full';
35
36
  let anchor = anchorProp;
@@ -38,7 +39,8 @@ const ButtonMore = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referenc
38
39
  const [iconState, setIconState] = useState(false);
39
40
  const _OptionFullCSS = OptionFullCSS(theme);
40
41
  const _PopoverCSS = PopoverCSS(isOptionFull, theme);
41
- const openPopover = () => {
42
+ const openPopover = e => {
43
+ onClick && onClick(e);
42
44
  setOpenState(true);
43
45
  };
44
46
  const closePopover = () => {
@@ -59,6 +61,8 @@ const ButtonMore = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referenc
59
61
  if (item !== null && item !== void 0 && item.hidden) return null;else if ( /*#__PURE__*/isValidElement(item)) return item;else {
60
62
  const icon = item === null || item === void 0 ? void 0 : item.icon;
61
63
  const label = item === null || item === void 0 ? void 0 : item.label;
64
+ const className = (item === null || item === void 0 ? void 0 : item.className) || '';
65
+ const style = (item === null || item === void 0 ? void 0 : item.style) || {};
62
66
  const action = () => {
63
67
  closePopover();
64
68
  if (typeof (item === null || item === void 0 ? void 0 : item.action) === 'function') item === null || item === void 0 ? void 0 : item.action();
@@ -67,7 +71,8 @@ const ButtonMore = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referenc
67
71
  return isOptionFull ? jsx("button", {
68
72
  key: idx,
69
73
  css: _OptionFullCSS,
70
- className: 'DGN-UI-ButtonMore-Option',
74
+ className: `DGN-UI-ButtonMore-Option ${className}`,
75
+ style: style,
71
76
  onClick: action
72
77
  }, icon ? jsx(Icon, {
73
78
  className: 'DGN-UI-ButtonMore-Option-Icon',
@@ -197,14 +202,18 @@ ButtonMore.propTypes = {
197
202
  label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
198
203
  icon: PropTypes.string,
199
204
  action: PropTypes.func,
200
- hidden: PropTypes.bool
205
+ hidden: PropTypes.bool,
206
+ className: PropTypes.string,
207
+ style: PropTypes.object
201
208
  })),
202
209
  /** The variant of option's type. */
203
210
  optionType: PropTypes.oneOf(['full', 'icon']),
204
211
  /** [Props](https://core.diginet.com.vn/ui/?path=/docs/components-popover) applied to the main `Popover`. */
205
212
  popoverProp: PropTypes.object,
206
213
  /** Style inline of component. */
207
- style: PropTypes.object
214
+ style: PropTypes.object,
215
+ /** Callback fired when the component is clicked. */
216
+ onClick: PropTypes.func
208
217
  };
209
218
  export { ButtonMore };
210
219
  export default OptionWrapper(ButtonMore);
@@ -652,7 +652,7 @@ const renderNavigator = (className, refs, dbLeftFn, leftFn, rightFn, dbRightFn,
652
652
  color: 'primary',
653
653
  type: 'h3',
654
654
  ref: refs.content,
655
- format: ['sentence']
655
+ format: ['lowercase']
656
656
  }))), jsx("div", {
657
657
  className: className.navigator.around
658
658
  }, jsx(ButtonIcon, {
@@ -226,7 +226,7 @@ const Calendar = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
226
226
  * START EFFECT
227
227
  */
228
228
  useEffect(() => {
229
- if (defaultValue && defaultValue !== '' && isValidDate(defaultValue) && !value) {
229
+ if (defaultValue && defaultValue !== '' && isValidDate(defaultValue)) {
230
230
  if (isBeforeLimit(min, defaultValue)) {
231
231
  onUpdate(min);
232
232
  } else if (isAfterLimit(max, defaultValue)) {
@@ -7,9 +7,10 @@ import locale from "../../../locale";
7
7
  import PropTypes from 'prop-types';
8
8
  import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
9
9
  import { render } from 'react-dom';
10
- import { bgColor, borderRadius4px, cursorPointer, displayBlock, displayFlex, displayNone, flexCol, flexRow, invisible, justifyBetween, justifyEnd, left, parseHeight, parseMaxWidth, parseMinWidth, pointerEventsNone, positionFixed, shadowLarge, textCenter, top, userSelectNone, whiteSpaceNoWrap, z } from "../../../styles/general";
10
+ import { bgColor, borderRadius4px, cursorPointer, displayBlock, displayFlex, displayNone, flexCol, flexRow, invisible, justifyBetween, justifyEnd, itemsCenter, left, parseHeight, parseMaxWidth, parseMinWidth, parseWidth, pointerEventsNone, positionFixed, shadowLarge, textCenter, top, userSelectNone, whiteSpaceNoWrap, z } from "../../../styles/general";
11
11
  import { useTheme } from "../../../theme";
12
12
  import { capitalizeSentenceCase, classNames, isEqual, date as moment, randomString, updatePosition } from "../../../utils";
13
+ import { getColor } from "../../../styles/utils";
13
14
  import { generateCalendarCSS, onUpdateNavigator, renderHeader, renderNavigator } from "../calendar/function";
14
15
  import ControlComp from "../control";
15
16
  import useThemeProps from "../../../theme/utils/useThemeProps";
@@ -66,6 +67,7 @@ const parseDate = day => {
66
67
  return Date.parse(new Date(day));
67
68
  };
68
69
  const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference) => {
70
+ var _periodOptions$dataSo;
69
71
  // props priority: `inProps` > `themeDefaultProps`
70
72
  const props = useThemeProps({
71
73
  props: inProps,
@@ -101,6 +103,7 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
101
103
  unitCount,
102
104
  value,
103
105
  viewType,
106
+ periodOptions,
104
107
  ...other
105
108
  } = props;
106
109
  const placeholder = placeholderProp !== null && placeholderProp !== void 0 ? placeholderProp : `${displayFormat} - ${displayFormat}`;
@@ -128,7 +131,9 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
128
131
  const [, setValueFr] = useState(Date.now());
129
132
  const [, setValueTo] = useState(Date.now());
130
133
  const [, setSelected] = useState(Date.now());
131
- const [focusBtn, setFocusBtn] = useState('today');
134
+ const selectedPeriodRef = useRef('');
135
+ const selectedPeriodIndex = useRef(null);
136
+ const focusBtnRef = useRef('today');
132
137
  const [valueState, setValueState] = useState();
133
138
  const navigatorFromRefs = {
134
139
  doubleLeft: useRef(null),
@@ -153,9 +158,12 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
153
158
  const yesterdayText = getGlobal(['yesterday']);
154
159
  const thisWeekText = getGlobal(['thisWeek']);
155
160
  const thisMonthText = getGlobal(['thisMonth']);
161
+ const selectPeriodText = getGlobal(['selectPeriod']);
156
162
  const _ControlContainerCSS = ControlContainerCSS(theme);
157
163
  const _FooterContainerCSS = FooterContainerCSS(theme);
158
164
  const _DateOptionsCSS = DateOptionsCSS(theme);
165
+ const _PeriodContainerCSS = PeriodContainerCSS(theme);
166
+ const _PeriodItemCSS = PeriodItemCSS(theme);
159
167
  const updateValues = useCallback(v => {
160
168
  values.current = v;
161
169
  setValues();
@@ -262,8 +270,8 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
262
270
  tableData = [],
263
271
  weekDateFirst = getDateOfWeek(firstDay),
264
272
  weekDateLast = getDateOfWeek(lastDay);
265
- /**
266
- * days of previous month
273
+ /**
274
+ * days of previous month
267
275
  */
268
276
  for (let i = weekDateFirst; i > 0; i--) {
269
277
  const day = Date.parse(new Date(time.getFullYear(), time.getMonth(), 1));
@@ -275,8 +283,8 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
275
283
  className: unique.day.day
276
284
  })));
277
285
  }
278
- /**
279
- * days of current month
286
+ /**
287
+ * days of current month
280
288
  */
281
289
  for (let i = 0; i < lastDate; i++) {
282
290
  const day = new Date(time.getFullYear(), time.getMonth(), i + 1);
@@ -302,8 +310,8 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
302
310
  type: 'h6'
303
311
  }, i + 1)));
304
312
  }
305
- /**
306
- * days of next month
313
+ /**
314
+ * days of next month
307
315
  */
308
316
  for (let i = 0; i < 13 - weekDateLast; i++) {
309
317
  const day = Date.parse(new Date(time.getFullYear(), time.getMonth() + 1, 0));
@@ -744,12 +752,13 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
744
752
  if (!ipRef.current) return;
745
753
  const el = ipRef.current;
746
754
  let enUnitText = locale.get() === 'en' && selected.current > 1 ? unitText + 's' : unitText;
755
+ const showPeriod = periodOptions === null || periodOptions === void 0 ? void 0 : periodOptions.enable;
747
756
  let tempValue;
748
757
  if (!reset) {
749
758
  if (unshift) {
750
- tempValue = formatValue(time, displayFormat) + ' - ' + el.value + (showUnitCount ? ` (${selected.current} ${enUnitText})` : '');
759
+ tempValue = `${showPeriod && selectedPeriodRef.current ? `${selectedPeriodRef.current} (` : ''}` + formatValue(time, displayFormat) + ' - ' + el.value + (showUnitCount ? ` (${selected.current} ${enUnitText})` : '') + `${showPeriod ? ')' : ''}`;
751
760
  } else {
752
- tempValue = el.value + ' - ' + formatValue(time, displayFormat) + (showUnitCount ? ` (${selected.current} ${enUnitText})` : '');
761
+ tempValue = `${showPeriod && selectedPeriodRef.current ? `${selectedPeriodRef.current} (` : ''}` + el.value + ' - ' + formatValue(time, displayFormat) + (showUnitCount ? ` (${selected.current} ${enUnitText})` : '') + `${showPeriod && selectedPeriodRef.current ? ')' : ''}`;
753
762
  }
754
763
  } else {
755
764
  tempValue = formatValue(time, displayFormat);
@@ -768,14 +777,20 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
768
777
  !!onChange && onChange(e);
769
778
  onSwap(true);
770
779
  };
771
- const onClickPresetDate = type => {
780
+ const onClickPresetDate = (type, periodData) => {
772
781
  if (!type) return;
773
- setFocusBtn(type);
774
782
  let value = [];
775
783
  const currentDay = new Date();
784
+ if (focusBtnRef.current) {
785
+ document.getElementById(focusBtnRef.current).style.color = getColor('system/dark');
786
+ }
787
+ if (selectedPeriodIndex.current) {
788
+ document.getElementById(selectedPeriodIndex.current).style.background = getColor('white');
789
+ }
776
790
  switch (type) {
777
791
  case 'today':
778
792
  value = [new Date(Date.now() - 25200000).valueOf()];
793
+ valueFr.current = new Date(Date.now() - 25200000);
779
794
  break;
780
795
  case 'yesterday':
781
796
  {
@@ -788,21 +803,48 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
788
803
  {
789
804
  const first = currentDay.getDate() - currentDay.getDay() + 1; // First day is the day of the month - the day of the week
790
805
  const last = first + 6; // last day is the first day + 6
791
- const firstday = new Date(currentDay.setDate(first)).setHours(0, 0, 0).valueOf();
792
- const lastday = new Date(currentDay.setDate(last)).setHours(0, 0, 0).valueOf();
793
- value = [firstday, lastday];
806
+ const firstday = new Date(currentDay.setDate(first)).setHours(0, 0, 0);
807
+ const lastday = new Date(currentDay.setDate(last)).setHours(0, 0, 0);
808
+ value = [firstday.valueOf(), lastday.valueOf()];
809
+ valueFr.current = firstday;
810
+ valueTo.current = lastday;
794
811
  break;
795
812
  }
796
813
  case 'thisMonth':
797
814
  {
798
- let firstday = new Date(currentDay.getFullYear(), currentDay.getMonth(), 1).valueOf();
799
- let lastday = new Date(currentDay.getFullYear(), currentDay.getMonth() + 1, 0).valueOf();
800
- value = [firstday, lastday];
815
+ let firstday = new Date(currentDay.getFullYear(), currentDay.getMonth(), 1);
816
+ let lastday = new Date(currentDay.getFullYear(), currentDay.getMonth() + 1, 0);
817
+ value = [firstday.valueOf(), lastday.valueOf()];
818
+ valueFr.current = firstday;
819
+ valueTo.current = lastday;
820
+ break;
821
+ }
822
+ case 'period':
823
+ {
824
+ let firstday = periodData === null || periodData === void 0 ? void 0 : periodData[periodOptions === null || periodOptions === void 0 ? void 0 : periodOptions.valueFromExpr];
825
+ let lastday = periodData === null || periodData === void 0 ? void 0 : periodData[periodOptions === null || periodOptions === void 0 ? void 0 : periodOptions.valueToExpr];
826
+ if ((periodOptions === null || periodOptions === void 0 ? void 0 : periodOptions.valueFormat) === 'DD/MM/YYYY') {
827
+ const firstDayArray = firstday.split('/');
828
+ const lastDayArray = lastday.split('/');
829
+ firstday = new Date(firstDayArray[2], firstDayArray[1], firstDayArray[0]);
830
+ lastday = new Date(lastDayArray[2], lastDayArray[1], lastDayArray[0]);
831
+ }
832
+ value = [firstday.valueOf(), lastday.valueOf()];
833
+ valueFr.current = firstday;
834
+ valueTo.current = lastday;
835
+ selectedPeriodIndex.current = `period${periodData === null || periodData === void 0 ? void 0 : periodData.idx}`;
836
+ selectedPeriodRef.current = periodData === null || periodData === void 0 ? void 0 : periodData[periodOptions === null || periodOptions === void 0 ? void 0 : periodOptions.displayExpr];
837
+ document.getElementById(selectedPeriodIndex.current).style.background = getColor('fill/hover');
801
838
  break;
802
839
  }
803
840
  default:
804
841
  break;
805
842
  }
843
+ if (type !== 'period') {
844
+ selectedPeriodRef.current = '';
845
+ focusBtnRef.current = type;
846
+ document.getElementById(focusBtnRef.current).style.color = getColor('primary');
847
+ }
806
848
  updateValues(value);
807
849
  updateSelected(countDay(values.current));
808
850
  renderPicker();
@@ -909,6 +951,7 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
909
951
  }, jsx("div", {
910
952
  css: _DateOptionsCSS
911
953
  }, jsx(Button, {
954
+ id: 'today',
912
955
  size: "medium",
913
956
  labelProps: {
914
957
  type: 'h4',
@@ -917,8 +960,9 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
917
960
  }
918
961
  },
919
962
  onClick: () => onClickPresetDate('today'),
920
- color: focusBtn === 'today' && 'primary'
963
+ color: focusBtnRef.current === 'today' && 'primary'
921
964
  }, todayText), jsx(Button, {
965
+ id: 'yesterday',
922
966
  size: "medium",
923
967
  labelProps: {
924
968
  type: 'h4',
@@ -927,8 +971,9 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
927
971
  }
928
972
  },
929
973
  onClick: () => onClickPresetDate('yesterday'),
930
- color: focusBtn === 'yesterday' && 'primary'
974
+ color: focusBtnRef.current === 'yesterday' && 'primary'
931
975
  }, yesterdayText), jsx(Button, {
976
+ id: 'thisWeek',
932
977
  size: "medium",
933
978
  labelProps: {
934
979
  type: 'h4',
@@ -937,8 +982,9 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
937
982
  }
938
983
  },
939
984
  onClick: () => onClickPresetDate('thisWeek'),
940
- color: focusBtn === 'thisWeek' && 'primary'
985
+ color: focusBtnRef.current === 'thisWeek' && 'primary'
941
986
  }, thisWeekText), jsx(Button, {
987
+ id: 'thisMonth',
942
988
  size: "medium",
943
989
  labelProps: {
944
990
  type: 'h4',
@@ -947,7 +993,7 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
947
993
  }
948
994
  },
949
995
  onClick: () => onClickPresetDate('thisMonth'),
950
- color: focusBtn === 'thisMonth' && 'primary'
996
+ color: focusBtnRef.current === 'thisMonth' && 'primary'
951
997
  }, thisMonthText)), jsx("div", {
952
998
  css: _ControlContainerCSS,
953
999
  className: unique.footer,
@@ -984,6 +1030,32 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
984
1030
  className: unique.table.table,
985
1031
  ref: tableToRef
986
1032
  }, renderHeader(unique), jsx("tbody", null))));
1033
+ const rightCalendarPeriodComp = jsx("div", {
1034
+ css: _PeriodContainerCSS
1035
+ }, jsx(Typography, {
1036
+ color: 'inherit',
1037
+ type: 'h3',
1038
+ style: {
1039
+ marginBottom: 8
1040
+ }
1041
+ }, selectPeriodText), periodOptions === null || periodOptions === void 0 ? void 0 : (_periodOptions$dataSo = periodOptions.dataSource) === null || _periodOptions$dataSo === void 0 ? void 0 : _periodOptions$dataSo.map((p, idx) => {
1042
+ const isSelected = (p === null || p === void 0 ? void 0 : p[periodOptions === null || periodOptions === void 0 ? void 0 : periodOptions.displayExpr]) === selectedPeriodRef.current;
1043
+ return jsx("div", {
1044
+ id: `period${idx}`,
1045
+ key: `period${idx}`,
1046
+ style: {
1047
+ background: isSelected ? getColor('fill/hover') : ''
1048
+ },
1049
+ css: _PeriodItemCSS,
1050
+ onClick: () => onClickPresetDate('period', {
1051
+ ...p,
1052
+ idx
1053
+ })
1054
+ }, jsx(Typography, {
1055
+ color: 'inherit',
1056
+ type: 'p1'
1057
+ }, p === null || p === void 0 ? void 0 : p[periodOptions === null || periodOptions === void 0 ? void 0 : periodOptions.displayExpr]));
1058
+ }));
987
1059
  const tooltipComp = jsx("div", {
988
1060
  className: unique.tooltip,
989
1061
  ref: tooltipRef
@@ -1004,7 +1076,7 @@ const DateRangePicker = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, ref
1004
1076
  height: '226px',
1005
1077
  margin: spacing([4.5, 0.5, 0])
1006
1078
  }
1007
- }), rightCalendarComp), tooltipComp, controls ? footerMemo : null);
1079
+ }), controls && periodOptions !== null && periodOptions !== void 0 && periodOptions.enable ? rightCalendarPeriodComp : rightCalendarComp), tooltipComp, controls ? footerMemo : null);
1008
1080
  return jsx(ControlComp, {
1009
1081
  ...other,
1010
1082
  disabled: disabled,
@@ -1057,6 +1129,7 @@ const unique = {
1057
1129
  }),
1058
1130
  wrapper: 'DGN-UI-DateRangePicker-Wrapper',
1059
1131
  container: 'DGN-UI-DateRangePicker',
1132
+ periodContainer: 'DGN-UI-DateRangePicker-Period',
1060
1133
  icon: 'DGN-UI-DateRangePicker-Icon',
1061
1134
  tooltip: 'DGN-UI-DateRangePicker-Tooltip',
1062
1135
  navigator: {
@@ -1132,6 +1205,29 @@ const DateOptionsCSS = ({
1132
1205
  ${displayFlex};
1133
1206
  padding-left: ${spacing(4)}px;
1134
1207
  `;
1208
+ const PeriodContainerCSS = ({
1209
+ spacing
1210
+ }) => css`
1211
+ ${displayFlex};
1212
+ ${flexCol};
1213
+ ${parseWidth('100%')};
1214
+ ${itemsCenter}
1215
+ margin: ${spacing([4, 0, 0, 0])} !important;
1216
+ `;
1217
+ const PeriodItemCSS = ({
1218
+ spacing
1219
+ }) => css`
1220
+ ${parseHeight(36)};
1221
+ ${displayFlex};
1222
+ ${itemsCenter};
1223
+ ${parseWidth('100%')};
1224
+ padding: ${spacing([2, 4])};
1225
+ box-sizing: border-box;
1226
+ &:hover {
1227
+ ${bgColor(getColor('fill/hover'))};
1228
+ ${cursorPointer};
1229
+ }
1230
+ `;
1135
1231
  const pickerCSS = {
1136
1232
  backGr: ({
1137
1233
  zIndex
@@ -1262,6 +1358,17 @@ DateRangePicker.propTypes = {
1262
1358
  placeholder: PropTypes.string,
1263
1359
  /** If `true`, hitting escape will close component. */
1264
1360
  pressESCToClose: PropTypes.bool,
1361
+ /** Options for period selector.
1362
+ * example: {
1363
+ * enable: true,
1364
+ * dataSource: [],
1365
+ * displayExpr: "DisplayName",
1366
+ * valueFromExpr: "DateFrom",
1367
+ * valueToExpr: "DateTo",
1368
+ * valueFormat: "DD/MM/YYYY"
1369
+ * }
1370
+ */
1371
+ periodOptions: PropTypes.object,
1265
1372
  /** If `true`, the component is readOnly. */
1266
1373
  readOnly: PropTypes.bool,
1267
1374
  /** If `true`, the input element is required. */
@@ -63,6 +63,7 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
63
63
  action = {},
64
64
  allowInput,
65
65
  allowSearch,
66
+ allowDuplicateValue,
66
67
  children,
67
68
  className,
68
69
  clearAble,
@@ -112,7 +113,9 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
112
113
  valueObjectDefault,
113
114
  viewType,
114
115
  defaultValue,
115
- disabled
116
+ disabled,
117
+ selectAll,
118
+ selectAllLabel
116
119
  } = props;
117
120
  const selectBox = multiple && selectBoxProp === undefined ? true : selectBoxProp;
118
121
  const searchExpr = typeof searchExprProp === 'string' ? [searchExprProp] : searchExprProp;
@@ -176,6 +179,12 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
176
179
  const _DropdownItemCSS = DropdownItemCSS(multiple, selectBox, theme);
177
180
  const _DropdownRootCSS = DropdownRootCSS(_DropdownFormCSS.name, _DropdownInputCSS.name, theme);
178
181
  const _CheckBoxCSS = CheckBoxCSS(theme);
182
+ const handleDataSource = data => {
183
+ let dataCustom = (data !== undefined ? data : dataSource) || [];
184
+ return selectAll ? [{
185
+ [valueExpr]: 'all'
186
+ }, ...dataCustom] : dataCustom;
187
+ };
179
188
 
180
189
  /* Start handler */
181
190
  const setShowDropdown = () => {
@@ -311,17 +320,21 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
311
320
  */
312
321
  const displayValue = data => {
313
322
  let text = '';
323
+ let isReplace = true;
314
324
  if (data || data === 0) {
315
325
  displayExpr = displayExpr || valueExpr;
316
326
  let mask = data === null || data === void 0 ? void 0 : data[displayExpr];
317
327
  // convert {id} - {name} to {<data[id]>} - {<data[name]>}
318
- if (!mask && regexBetween.test(displayExpr)) {
328
+ if (selectAll && (data === null || data === void 0 ? void 0 : data[valueExpr]) === 'all') {
329
+ isReplace = false;
330
+ text = selectAllLabel || getGlobal('selectAll');
331
+ } else if (!mask && regexBetween.test(displayExpr)) {
319
332
  var _displayExpr;
320
333
  mask = (_displayExpr = displayExpr) === null || _displayExpr === void 0 ? void 0 : _displayExpr.replace(regexBetween, _ => (data === null || data === void 0 ? void 0 : data[_]) || '');
321
334
  } else if (!mask) {
322
335
  mask = typeof data !== 'object' ? data : '';
323
336
  }
324
- text = mask.toString().replace(regexInclude, '');
337
+ if (isReplace) text = mask.toString().replace(regexInclude, '');
325
338
  }
326
339
  return text;
327
340
  };
@@ -389,7 +402,8 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
389
402
  type: 'p1'
390
403
  }, displayText);
391
404
  if (multiple && selectBox) {
392
- const checked = Array.isArray(valueMulti) ? valueMulti.includes(value) : valueMulti.includes(value);
405
+ let checked = valueMulti.includes(value);
406
+ if (selectAll && value === 'all') checked = selectAll && value === 'all' && valueMulti.length > 0;
393
407
  const isMaximumSelection = maximumSelectionLength === (valueMulti === null || valueMulti === void 0 ? void 0 : valueMulti.length);
394
408
  itemDisabled = itemDisabled || isMaximumSelection && !checked;
395
409
  items.push(jsx("div", {
@@ -402,6 +416,7 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
402
416
  },
403
417
  tabIndex: -1
404
418
  }, jsx(Checkbox, {
419
+ determinate: !(selectAll && (data === null || data === void 0 ? void 0 : data[valueExpr]) === 'all' && (valueMulti || []).length !== (dataSourceState || []).length - 1),
405
420
  css: _CheckBoxCSS,
406
421
  forTreeView: true,
407
422
  checked: checked,
@@ -437,7 +452,6 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
437
452
  }, items !== null && items !== void 0 && items.length ? items : EmptyDataText);
438
453
  };
439
454
  const mapTreeView = () => {
440
- console.log('here');
441
455
  return jsx("div", {
442
456
  css: _DropdownListCSS,
443
457
  ref: dropdownListRef,
@@ -639,7 +653,7 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
639
653
  const total = data && data.total ? data.total : data === null || data === void 0 ? void 0 : data.length;
640
654
  setTotalState(total);
641
655
  }
642
- setDataSourceState(isReset ? rows : dataSourceState.concat(rows));
656
+ setDataSourceState(handleDataSource(isReset ? rows : dataSourceState.concat(rows)));
643
657
  }
644
658
  };
645
659
  setLoadingState(true);
@@ -703,8 +717,10 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
703
717
  } else if (multiple) {
704
718
  if (!Array.isArray(currentValue[unique])) currentValue[unique] = [];
705
719
  // const newValueArr = [...currentValue[unique]];
706
- const newValueArrState = [...valueMulti];
707
- if (!newValueArrState.some(v => JSON.stringify(v) === JSON.stringify(value))) {
720
+ let newValueArrState = [...valueMulti];
721
+ if (selectAll && value === 'all') {
722
+ newValueArrState = e !== null && e !== void 0 && e.value ? dataSourceState.flatMap(item => (item === null || item === void 0 ? void 0 : item[valueExpr]) === 'all' ? [] : [item === null || item === void 0 ? void 0 : item[valueExpr]]) : [];
723
+ } else if (!newValueArrState.some(v => JSON.stringify(v) === JSON.stringify(value))) {
708
724
  // newValueArr.push(value);
709
725
  newValueArrState.push(value);
710
726
  } else {
@@ -717,7 +733,8 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
717
733
  data
718
734
  });
719
735
  } else {
720
- const isChanged = currentValue[unique] !== value;
736
+ // biến allowDuplicateValue chỉ dùng trong trường hợp đặc biệt ID 300034
737
+ const isChanged = allowDuplicateValue ? allowDuplicateValue : currentValue[unique] !== value;
721
738
  if (isChanged) {
722
739
  if (valueProp === undefined) {
723
740
  allValue[unique].push(value);
@@ -914,7 +931,7 @@ const Dropdown = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference)
914
931
  setTotalState(total);
915
932
  }, [total]);
916
933
  useEffect(() => {
917
- setDataSourceState(dataSource || []);
934
+ setDataSourceState(handleDataSource(dataSource || []));
918
935
  }, [dataSource]);
919
936
  useEffect(() => {
920
937
  setShowClear(clearAble && checkHasValue(valueProp !== null && valueProp !== void 0 ? valueProp : defaultValue) && !disabled && !readOnly && !loadingState);
@@ -1708,6 +1725,8 @@ Dropdown.propTypes = {
1708
1725
  }),
1709
1726
  /** If `true`, the input box for searching will be displayed. */
1710
1727
  allowSearch: PropTypes.bool,
1728
+ /** If `true`, click on same item will add its value instead of remove it (better not use this, only for specific situation). */
1729
+ allowDuplicateValue: PropTypes.bool,
1711
1730
  /** If `true`, the input value will be added when user hit Enter. */
1712
1731
  allowInput: PropTypes.bool,
1713
1732
  /** The content to be displayed inside the Dropdown box, such as TreeView. */
@@ -1811,6 +1830,10 @@ Dropdown.propTypes = {
1811
1830
  searchExpr: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
1812
1831
  /** Specifies the comparison operation used to search items. */
1813
1832
  searchMode: PropTypes.oneOf(['contains', 'startswith', 'equals']),
1833
+ /** If `true`, show select all check box. */
1834
+ selectAll: PropTypes.bool,
1835
+ /** The content display for label of checkbox select all */
1836
+ selectAllLabel: PropTypes.string,
1814
1837
  /** If `true`, checkboxes will be shown next to each dropdown item. */
1815
1838
  selectBox: PropTypes.bool,
1816
1839
  /** Inline style for the component. */
@@ -1,15 +1,13 @@
1
1
  /** @jsxRuntime classic */
2
2
  /** @jsx jsx */
3
3
  import { css, jsx } from '@emotion/core';
4
- import { ButtonIcon, InputBase, Label, Popover, PopoverBody, HelperText } from "../..";
4
+ import { ButtonIcon, InputBase, Label, Popover, PopoverBody } from "../..";
5
5
  import PropTypes from 'prop-types';
6
- import { Fragment, forwardRef, memo, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState, useMemo } from 'react';
6
+ import { Fragment, forwardRef, memo, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from 'react';
7
7
  import { animation, borderColor, displayBlock, overflowHidden, parseHeight, parseMinWidth, positionRelative, scaleX } from "../../../styles/general";
8
8
  import { useTheme } from "../../../theme";
9
9
  import useThemeProps from "../../../theme/utils/useThemeProps";
10
10
  import { classNames, getProp } from "../../../utils";
11
- const regexBetween = /[^{}]+(?=})/g;
12
- const regexInclude = /{|}/g;
13
11
  const DropdownBox = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, reference) => {
14
12
  if (!reference) reference = useRef(null);
15
13
  const theme = useTheme();
@@ -24,14 +22,10 @@ const DropdownBox = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referen
24
22
  });
25
23
  const {
26
24
  action = {},
27
- allowInput,
28
25
  bgColor: bgColorProp,
29
26
  children,
30
27
  className,
31
28
  delayOnInput,
32
- disabled,
33
- displayExpr: displayExprProp,
34
- error,
35
29
  endIcon,
36
30
  inputProps,
37
31
  inputRef,
@@ -45,19 +39,10 @@ const DropdownBox = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referen
45
39
  placeholder,
46
40
  startIcon,
47
41
  style,
48
- value: valueProps,
49
- valueExpr,
50
- viewType,
51
- helperTextProps
42
+ value,
43
+ viewType
52
44
  } = props;
53
- let displayExpr = displayExprProp;
54
45
  const bgColor = typeof bgColorProp === 'string' ? getProp(colors, bgColorProp, bgColorProp) : bgColorProp;
55
- const ErrorView = useMemo(() => {
56
- return error ? jsx(HelperText, {
57
- ...helperTextProps,
58
- disabled: disabled
59
- }, error) : null;
60
- }, [disabled, error, helperTextProps]);
61
46
  const ref = useRef(null);
62
47
  const dropdownBoxRef = useRef(null);
63
48
  const timer = useRef(null);
@@ -100,28 +85,6 @@ const DropdownBox = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referen
100
85
  onClosed === null || onClosed === void 0 ? void 0 : onClosed();
101
86
  }
102
87
  };
103
-
104
- /**
105
- * Chuyển đổi data thành giá trị cần hiện thị dựa vào displayExpr [string, string object {field} - {field}], renderSelectedItem, displayExpr, valueExpr
106
- * @param data {object} rowData of dataSource
107
- * @return {string}
108
- */
109
- const displayValue = data => {
110
- let text = '';
111
- if (data || data === 0) {
112
- displayExpr = displayExpr || valueExpr;
113
- let mask = data === null || data === void 0 ? void 0 : data[displayExpr];
114
- // convert {id} - {name} to {<data[id]>} - {<data[name]>}
115
- if (!mask && regexBetween.test(displayExpr)) {
116
- var _displayExpr;
117
- mask = (_displayExpr = displayExpr) === null || _displayExpr === void 0 ? void 0 : _displayExpr.replace(regexBetween, _ => (data === null || data === void 0 ? void 0 : data[_]) || '');
118
- } else if (!mask) {
119
- mask = typeof data !== 'object' ? data : '';
120
- }
121
- text = mask.toString().replace(regexInclude, '');
122
- }
123
- return text;
124
- };
125
88
  useLayoutEffect(() => {
126
89
  if (ref.current) {
127
90
  const {
@@ -167,17 +130,15 @@ const DropdownBox = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referen
167
130
  onClick: openOnClickAt === 'icon' ? onTriggerDropdown : null
168
131
  }) : null;
169
132
  };
170
- const value = displayValue(valueProps);
171
133
  return jsx(Fragment, null, jsx("div", {
172
134
  ref: ref,
173
135
  css: _DropdownBoxRootCSS,
174
- className: classNames('DGN-UI-Dropdown-Box', className, error && 'error'),
136
+ className: classNames('DGN-UI-Dropdown-Box', className),
175
137
  style: style
176
138
  }, label ? jsx(Label, {
177
139
  ...labelProps
178
140
  }, label) : null, jsx(InputBase, {
179
141
  ...inputProps,
180
- readOnly: !allowInput,
181
142
  style: inputStyle,
182
143
  viewType: viewType,
183
144
  inputRef: inputRef,
@@ -196,7 +157,7 @@ const DropdownBox = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((inProps, referen
196
157
  anchor: ref.current,
197
158
  width: popoverWidth,
198
159
  onClose: closeDropdownBox
199
- }, jsx(PopoverBody, null, children)), ErrorView);
160
+ }, jsx(PopoverBody, null, children)));
200
161
  }));
201
162
  const DropdownBoxRootCSS = (bgColorProp, {
202
163
  colors
@@ -205,17 +166,6 @@ const DropdownBoxRootCSS = (bgColorProp, {
205
166
  ${positionRelative};
206
167
  ${parseMinWidth(150)};
207
168
  ${parseHeight('max-content')};
208
- &.error {
209
- .DGN-UI-InputBase {
210
- ${borderColor(getProp(colors, 'semantic/danger'))};
211
- &::before {
212
- ${borderColor(getProp(colors, 'semantic/danger'))};
213
- }
214
- &::after {
215
- ${borderColor(getProp(colors, 'semantic/danger'))};
216
- }
217
- }
218
- }
219
169
  .DGN-UI-InputBase {
220
170
  background: ${bgColorProp ? bgColorProp === true ? getProp(colors, 'fill/disabled') : bgColorProp : 'inherit'} !important;
221
171
  ${openState && css`
@@ -233,6 +183,20 @@ const DropdownBoxCSS = ({
233
183
  margin-top: ${spacing([1])};
234
184
  ${overflowHidden};
235
185
  `;
186
+
187
+ // DropdownBox.defaultProps = {
188
+ // className: '',
189
+ // label: '',
190
+ // placeholder: '',
191
+ // startIcon: 'Search',
192
+ // endIcon: 'ArrowDown',
193
+ // openOnClickAt: 'icon',
194
+ // viewType: 'underlined',
195
+ // inputProps: {},
196
+ // delayOnInput: 700,
197
+ // zIndex: zIndexCORE(1),
198
+ // };
199
+
236
200
  DropdownBox.propTypes = {
237
201
  /** class for dropdown */
238
202
  className: PropTypes.string,
@@ -269,12 +233,6 @@ DropdownBox.propTypes = {
269
233
  /** the function will run after open */
270
234
  onOpened: PropTypes.func,
271
235
  /** the function will run after close */
272
- onClosed: PropTypes.func,
273
- /** Error message displayed below the input. */
274
- error: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
275
- /** If `true`, the component is disabled. */
276
- disabled: PropTypes.bool,
277
- /** If `true`, the input is enable. */
278
- allowInput: PropTypes.bool
236
+ onClosed: PropTypes.func
279
237
  };
280
238
  export default DropdownBox;
@@ -49,7 +49,7 @@ const NumberInput = /*#__PURE__*/forwardRef((inProps, reference) => {
49
49
  labelProps,
50
50
  max: maxProp,
51
51
  maxDigit,
52
- min: minProp,
52
+ min,
53
53
  nonStyle,
54
54
  onBlur,
55
55
  onChange,
@@ -69,12 +69,9 @@ const NumberInput = /*#__PURE__*/forwardRef((inProps, reference) => {
69
69
  viewType
70
70
  } = props;
71
71
  let max = maxProp;
72
- let min = minProp;
73
72
  let thousandSymbol = thousandSeparator;
74
73
  let decimalSymbol = decimalSymbolProp;
75
74
  let valueProps = valueProp;
76
- if (!min && min !== 0) min = -Infinity;
77
- if (!max && max !== 0) max = Infinity;
78
75
  const pos = useRef(null);
79
76
  const ref = useRef(null);
80
77
  const globalRef = useRef({});
package/global/index.js CHANGED
@@ -50,6 +50,7 @@ const globalObject = {
50
50
  yesterday: 'Hôm qua',
51
51
  thisWeek: 'Tuần này',
52
52
  thisMonth: 'Tháng này',
53
+ selectPeriod: 'Chọn theo kỳ',
53
54
  // Time Picker
54
55
  months: {
55
56
  full: ['tháng 01', 'tháng 02', 'tháng 03', 'tháng 04', 'tháng 05', 'tháng 06', 'tháng 07', 'tháng 08', 'tháng 09', 'tháng 10', 'tháng 11', 'tháng 12'],
@@ -130,6 +131,7 @@ const globalObject = {
130
131
  yesterday: 'Yesterday',
131
132
  thisWeek: 'This week',
132
133
  thisMonth: 'This month',
134
+ selectPeriod: 'Select period',
133
135
  // Time Picker
134
136
  months: {
135
137
  full: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
@@ -210,6 +212,7 @@ const globalObject = {
210
212
  yesterday: '昨天',
211
213
  thisWeek: '本周',
212
214
  thisMonth: '本月',
215
+ selectPeriod: '按期选择',
213
216
  // Time Picker
214
217
  months: {
215
218
  full: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
package/package.json CHANGED
@@ -1,78 +1,44 @@
1
- {
2
- "name": "diginet-core-ui",
3
- "version": "1.4.54-beta.3",
4
- "description": "",
5
- "main": "index.js",
6
- "license": "UNLICENSED",
7
- "scripts": {
8
- "start": "npm-run-all --parallel start-sb eslint-test",
9
- "start-sb": "start-storybook -p 9050",
10
- "build-storybook": "build-storybook -c .storybook -s src",
11
- "build": "run-script-os",
12
- "build:windows": "rimraf dist && mkdirp dist/components && npm run compile && sass --style=compressed src/scss:dist/css && xcopy src\\\\assets dist\\\\assets\\ /e /y",
13
- "build:darwin:linux:default": "rm -rf dist && npm run compile && sass --style=compressed src/scss:dist/css && cp -rf src/assets dist/assets",
14
- "compile": "babel src --out-dir dist --ignore **/*.stories.js",
15
- "pack": "npm run build && cp *.md dist/ && npm run version:bump --silent && npm run version:add --silent && cd dist && npm pack",
16
- "production-keep-version": "npm run build && cp *.md dist/ && cp package.json dist/ && cd dist && npm publish",
17
- "beta": "npm run build && cp *.md dist/ && cp package.json dist/ && cd dist && npm publish --tag beta",
18
- "production": "npm run build && cp *.md dist/ && npm run version:bump --silent && npm run version:add --silent && cd dist && npm publish",
19
- "version:add": "run-script-os",
20
- "version:add:windows": "cat package.json.tmp | sed \"s/0.0.0/%npm_package_version%/g\" > dist/package.json",
21
- "version:add:darwin:linux:default": "VERSION=$(npm run version:extract --silent) && cat package.json.tmp | sed \"s/0.0.0/${VERSION}/g\" > dist/package.json",
22
- "version:bump": "npm version patch --no-git-tag-version --silent",
23
- "version:extract": "cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]'",
24
- "test": "echo \"Error: no test specified\" && exit 1",
25
- "lint": "eslint --fix --config .eslintrc.js \"**/*.js\"",
26
- "eslint-test": "onchange \"src/**/*.{js,jsx,json}\" -- eslint . --fix",
27
- "freshtall": "npm cache clean --force && rm -rf node_modules && rm -f package-lock.json && npm install",
28
- "test-storybook": "test-storybook --url http://localhost:9050",
29
- "preinstall": "echo {} > package-lock.json"
30
- },
31
- "dependencies": {
32
- "@emotion/core": "^10.0.35",
33
- "@emotion/css": "^11.11.0",
34
- "@emotion/react": "^11.10.6",
35
- "babel-plugin-module-resolver": "^4.1.0",
36
- "date-fns": "^2.30.0",
37
- "prop-types": "^15.7.2"
38
- },
39
- "lint-staged": {
40
- "*/**/*.{js,jsx,json}": [
41
- "prettier --write",
42
- "git add"
43
- ]
44
- },
45
- "devDependencies": {
46
- "@babel/cli": "^7.14.3",
47
- "@babel/plugin-proposal-class-properties": "^7.13.0",
48
- "@babel/plugin-proposal-logical-assignment-operators": "^7.16.0",
49
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0",
50
- "@babel/plugin-proposal-optional-chaining": "^7.14.2",
51
- "@babel/plugin-proposal-private-methods": "^7.18.6",
52
- "@babel/plugin-proposal-private-property-in-object": "^7.18.6",
53
- "@babel/preset-react": "^7.13.13",
54
- "@storybook/addon-actions": "6.2.9",
55
- "@storybook/addon-essentials": "6.2.9",
56
- "@storybook/addon-links": "6.2.9",
57
- "@storybook/addon-postcss": "^2.0.0",
58
- "@storybook/react": "6.2.9",
59
- "@storybook/test-runner": "^0.7.1",
60
- "autoprefixer": "^10.3.1",
61
- "babel-loader": "^8.2.2",
62
- "eslint": "^8.4.1",
63
- "eslint-plugin-react": "^7.27.1",
64
- "eslint-plugin-regex": "^1.10.0",
65
- "husky": "^7.0.4",
66
- "jest": "^27.5.1",
67
- "lint-staged": "^12.1.2",
68
- "mkdirp": "^1.0.4",
69
- "npm-run-all": "^4.1.5",
70
- "onchange": "^7.1.0",
71
- "postcss-flexbugs-fixes": "^5.0.2",
72
- "react": "^17.0.1",
73
- "react-dom": "^17.0.1",
74
- "rimraf": "^3.0.2",
75
- "run-script-os": "^1.1.6",
76
- "sass": "1.58.3"
77
- }
78
- }
1
+ {
2
+ "name": "diginet-core-ui",
3
+ "version": "1.4.55",
4
+ "description": "The DigiNet core ui",
5
+ "homepage": "https://diginet.com.vn",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "start-js": "react-scripts start --max_old_space_size=4096",
9
+ "start": "npx npm-run-all -p start-js",
10
+ "build": "GENERATE_SOURCEMAP=false && react-scripts build --env=production --max_old_space_size=8192",
11
+ "eject": "react-scripts eject",
12
+ "test": "echo \"Error: no test specified\" && exit 1"
13
+ },
14
+ "dependencies": {
15
+ "@emotion/core": "^10.0.35",
16
+ "prop-types": "^15.7.2",
17
+ "@emotion/css": "^11.11.0",
18
+ "@emotion/react": "^11.10.6"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://diginetvn@bitbucket.org/diginetvn/diginet-core-ui.git"
23
+ },
24
+ "keywords": [
25
+ "core ui",
26
+ "diginet"
27
+ ],
28
+ "author": "rocachien",
29
+ "contributors": [
30
+ {
31
+ "name": "Chien Do",
32
+ "email": "rocachien@gmail.com"
33
+ },
34
+ {
35
+ "name": "Nhat Tran",
36
+ "email": "tranminhnhat1005@gmail.com"
37
+ },
38
+ {
39
+ "name": "Thuan Nguyen",
40
+ "email": "nt.thuan.hutech@gmail.com"
41
+ }
42
+ ],
43
+ "license": "MIT"
44
+ }
package/readme.md CHANGED
@@ -42,6 +42,16 @@ npm test
42
42
 
43
43
  ## Changelog
44
44
 
45
+ ## 1.4.55
46
+ - \[Added\]: Icon – Add IconMenu MHRM09N1401, MHRM09N1402
47
+ - \[Added\]: Icon – Add Icon Book
48
+ - \[Added\]: Icon – Add Icon PaperCancel, LoadingV2
49
+ - \[Added\]: Icon – Add IconMenu MHRM21N0001
50
+ - \[Added\]: Dropdown - Add 'selectAll' prop to allow multiple selection
51
+ - \[Added\]: ButtonMore – Add new property to ButtonMore
52
+ - \[Added\]: Dropdown – Add support for allowing Dropdown to reselect the same value multiple times
53
+ - \[Added\]: DateRangePicker – Add a new mode to change the UI of DateRangePicker
54
+
45
55
  ## 1.4.54
46
56
  - \[Added\]: Icon – Add Icon Camera
47
57
  - \[Fixed\]: Treeview - Fix bug Treeview keeps the search bar visible while scrolling