diginet-core-ui 1.4.53-beta.6 → 1.4.53-beta.8

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,10 +1,10 @@
1
1
  import { useEffect } from 'react';
2
- import { addDays, addHours, addMinutes, addMonths, addSeconds, addYears, format, isLastDayOfMonth, isValid, lastDayOfMonth } from 'date-fns';
3
- import { enUS, vi } from 'date-fns/locale';
2
+ import { addDays, addHours, addMinutes, addMonths, addSeconds, addYears, isLastDayOfMonth, isValid, lastDayOfMonth } from 'date-fns';
4
3
  import { getGlobal } from "../../../global";
5
4
  import { capitalize } from "../../../utils";
6
5
  import { patternMap, useDateField } from "./DateField";
7
6
  import { lowerCaseDayYear } from "./utils";
7
+ import { parseDateString } from "../../../utils/getLang";
8
8
  export const useDateInputState = ({
9
9
  formatStr,
10
10
  locale,
@@ -95,9 +95,7 @@ export const useDateInputState = ({
95
95
  };
96
96
  const toControlledDateString = () => {
97
97
  if (date && isValid(date)) {
98
- return format(date, lowerCaseDayYear(formatStr), {
99
- locale: locale === 'vi' ? vi : enUS
100
- });
98
+ return parseDateString(date, lowerCaseDayYear(formatStr), locale);
101
99
  }
102
100
  // if date is not valid, return uncontrolled date string
103
101
  return toDateString();
@@ -2,8 +2,7 @@
2
2
  /** @jsx jsx */
3
3
  import { css, jsx } from '@emotion/core';
4
4
  import { Button, ButtonIcon, DateInput, HelperText, InputBase, Label, Popover, Tooltip } from "../..";
5
- import { format, isValid, parse } from 'date-fns';
6
- import { enUS, vi } from 'date-fns/locale';
5
+ import { isValid, parse } from 'date-fns';
7
6
  import { getGlobal } from "../../../global";
8
7
  import locale from "../../../locale";
9
8
  import PropTypes from 'prop-types';
@@ -14,6 +13,7 @@ import useThemeProps from "../../../theme/utils/useThemeProps";
14
13
  import { capitalizeSentenceCase, classNames, isValidDate, useControlled } from "../../../utils";
15
14
  import Calendar from "../calendar";
16
15
  import { lowerCaseDayYear } from "../date-input/utils";
16
+ import { parseDateString } from "../../../utils/getLang";
17
17
  const unique = {
18
18
  footer: 'DGN-UI-DatePicker-Footer',
19
19
  cancel: 'DGN-UI-DatePicker-cancel',
@@ -23,6 +23,10 @@ const unique = {
23
23
  const confirmText = getGlobal(['confirm']);
24
24
  const cancelText = getGlobal(['cancel']);
25
25
  const viDisplayFormat = new Map([['year', 'YYYY'], ['quarter', 'Q-YYYY'], ['month', 'MM-YYYY']]);
26
+ const zhDisplayFormat = new Map([['year', 'YYYY年'], ['quarter', 'YYYY年第Q季度'], ['month', 'YYYY年MM月']]);
27
+ const enDisplayFormat = new Map([['year', 'YYYY'], ['quarter', 'YYYY [Q]Q'],
28
+ // Exp: 2025 Q1
29
+ ['month', 'MM/YYYY']]);
26
30
  const pickerReturnFormat = new Map([['year', 'YYYY'], ['quarter', 'YYYY-Q'], ['month', 'YYYY-MM']]);
27
31
  const parseValueToDate = valueProp => {
28
32
  if (!valueProp) return null;else if (isValidDate(valueProp)) {
@@ -42,8 +46,26 @@ const parseValueToDate = valueProp => {
42
46
  return valueProp;
43
47
  }
44
48
  };
49
+ const getDateFormats = (locale, minZoom) => {
50
+ let formatMap;
51
+ switch (locale) {
52
+ case 'vi':
53
+ formatMap = viDisplayFormat;
54
+ break;
55
+ case 'zh':
56
+ formatMap = zhDisplayFormat;
57
+ break;
58
+ case 'en':
59
+ formatMap = enDisplayFormat;
60
+ break;
61
+ default:
62
+ formatMap = pickerReturnFormat; // fallback
63
+ break;
64
+ }
65
+ return formatMap.get(minZoom) || '';
66
+ };
45
67
  const DatePicker = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference) => {
46
- var _ref, _pickerReturnFormat$g, _ipRef$current, _ipRef$current2;
68
+ var _getDateFormats, _pickerReturnFormat$g, _ipRef$current, _ipRef$current2;
47
69
  if (!reference) reference = useRef(null);
48
70
  const theme = useTheme();
49
71
 
@@ -87,7 +109,7 @@ const DatePicker = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference
87
109
  ...other
88
110
  } = props;
89
111
  const dateLocale = locale.get();
90
- const displayFormat = (_ref = dateLocale === 'vi' ? viDisplayFormat.get(minZoom) : pickerReturnFormat.get(minZoom)) !== null && _ref !== void 0 ? _ref : displayFormatProp;
112
+ const displayFormat = (_getDateFormats = getDateFormats(dateLocale, minZoom)) !== null && _getDateFormats !== void 0 ? _getDateFormats : displayFormatProp;
91
113
  const returnFormat = (_pickerReturnFormat$g = pickerReturnFormat.get(minZoom)) !== null && _pickerReturnFormat$g !== void 0 ? _pickerReturnFormat$g : returnFormatProp;
92
114
  const placeholder = placeholderProp !== null && placeholderProp !== void 0 ? placeholderProp : displayFormat;
93
115
  const [value, setValue] = useControlled(parseValueToDate(valueProp), parseValueToDate(defaultValue));
@@ -112,9 +134,7 @@ const DatePicker = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference
112
134
  };
113
135
  const formatValue = (value, formatStr) => {
114
136
  // return moment(value).format(format, utc = false);
115
- return format(value, lowerCaseDayYear(formatStr), {
116
- locale: dateLocale === 'vi' ? vi : enUS
117
- });
137
+ return parseDateString(value, lowerCaseDayYear(formatStr), dateLocale);
118
138
  };
119
139
  const onChangeValue = e => {
120
140
  const vl = (e === null || e === void 0 ? void 0 : e.value) || e;
@@ -294,6 +294,7 @@ const Dropdown = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference)
294
294
  * @return {boolean}
295
295
  */
296
296
  const handleRenderBySearch = (text = '') => {
297
+ if (text === null || text === undefined) text = '';
297
298
  if (typeof text !== 'string') text = text.toString();
298
299
  if (!txtSearch) return true;
299
300
  if (searchMode === 'startswith') {
@@ -10,6 +10,7 @@ import { forwardRef, memo, useEffect, useImperativeHandle, useRef } from 'react'
10
10
  import { displayBlock, positionRelative } from "../../../styles/general";
11
11
  import useThemeProps from "../../../theme/utils/useThemeProps";
12
12
  import { onValidate } from "../../../utils";
13
+ import { getThousandSeparatorByCountry } from "../../../utils/getLang";
13
14
  const num2WordsVi = function () {
14
15
  let t = ['không', 'một', 'hai', 'ba', 'bốn', 'năm', 'sáu', 'bảy', 'tám', 'chín'],
15
16
  r = function (r, n) {
@@ -72,6 +73,61 @@ const num2WordsEn = n => {
72
73
  if (n === '0') return 'zero';
73
74
  return comp(chunk(3))(reverse)(arr(n)).map(makeGroup).map(thousand).filter(comp(not)(isEmpty)).reverse().join(' ');
74
75
  };
76
+ const num2WordsZh = (() => {
77
+ const t = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
78
+ const units = ['', '十', '百', '千'];
79
+ const bigUnits = ['', '万', '亿', '兆'];
80
+ const readSection = num => {
81
+ let str = '';
82
+ let zero = true;
83
+ for (let i = 0; i < 4 && num > 0; i++) {
84
+ const digit = num % 10;
85
+ if (digit === 0) {
86
+ if (!zero) {
87
+ zero = true;
88
+ str = t[0] + str;
89
+ }
90
+ } else {
91
+ zero = false;
92
+ str = t[digit] + units[i] + str;
93
+ }
94
+ num = Math.floor(num / 10);
95
+ }
96
+ return str;
97
+ };
98
+ return {
99
+ convert: num => {
100
+ if (num === 0) return t[0];
101
+ let str = '';
102
+ let unitPos = 0;
103
+ let needZero = false;
104
+ while (num > 0) {
105
+ const section = num % 10000;
106
+ if (section === 0) {
107
+ if (needZero) {
108
+ str = t[0] + str;
109
+ needZero = false;
110
+ }
111
+ } else {
112
+ const sectionStr = readSection(section) + bigUnits[unitPos];
113
+ str = sectionStr + str;
114
+ needZero = true;
115
+ }
116
+ num = Math.floor(num / 10000);
117
+ unitPos++;
118
+ }
119
+
120
+ // Special cases
121
+ str = str.replace(/^一十/, '十'); // "一十X" => "十X"
122
+ return str;
123
+ }
124
+ };
125
+ })();
126
+ const converters = {
127
+ vi: num2WordsVi,
128
+ en: num2WordsEn,
129
+ zh: num2WordsZh
130
+ };
75
131
  const MoneyInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference) => {
76
132
  if (!reference) reference = useRef(null);
77
133
 
@@ -126,7 +182,7 @@ const MoneyInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference
126
182
  isPaste: false,
127
183
  clipboardText: ''
128
184
  });
129
- const separatorSymbol = typeof thousandSeparator === 'string' ? thousandSeparator : locale.get() === 'vi' ? '.' : ',';
185
+ const separatorSymbol = typeof thousandSeparator === 'string' ? thousandSeparator : getThousandSeparatorByCountry(locale.get());
130
186
  const decimalSymbol = separatorSymbol === '.' ? ',' : '.';
131
187
  const thousandSeparatorPattern = new RegExp(`[0-9]|Backspace|Delete|Arrow|Home|End|Tab${decimalDigit === 0 ? '' : '|\\' + decimalSymbol}${disabledNegative ? '' : '|-'}`);
132
188
  const isError = !!error && !value && value !== 0;
@@ -350,7 +406,9 @@ const MoneyInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference
350
406
  if (convertToWords && !decimalDigit && (disabled || readOnly)) {
351
407
  let valueConverted = getGlobal('helperInvalid');
352
408
  if (Number.isInteger(number)) {
353
- valueConverted = locale.get() === 'vi' ? num2WordsVi.convert(number) : num2WordsEn(number);
409
+ const currentLocale = locale.get();
410
+ const converter = converters[currentLocale] || num2WordsVi; // fallback VN
411
+ valueConverted = converter.convert(number);
354
412
  }
355
413
  inputRef.current.value = parseValueWithFix(valueConverted);
356
414
  } else {
@@ -239,8 +239,10 @@ const TreeView = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference)
239
239
  // // Trường hợp phải set về false để xét các input đã check không bao gồm node này
240
240
  checkbox.firstChild.checked = isChecked;
241
241
  determinateCheckbox(checkbox.firstChild, !mustDisabled);
242
- // Nếu có ít nhất một input con được check thì phải checked cho input này
243
- checkbox.firstChild.checked = mustDisabled;
242
+ setTimeout(() => {
243
+ // Nếu có ít nhất một input con được check thì phải checked cho input này
244
+ checkbox.firstChild.checked = mustDisabled;
245
+ }, 200);
244
246
  node.classList[mustDisabled || isChecked ? 'add' : 'remove']('disabled');
245
247
  checkbox.classList[mustDisabled || isChecked ? 'add' : 'remove']('disabled');
246
248
  Array.from(node.childNodes).forEach(e => {
@@ -691,16 +693,16 @@ const TreeView = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((inProps, reference)
691
693
  }
692
694
  };
693
695
  } else if (disabledRelevantValue) {
694
- Array.from(ref.current.querySelectorAll('.TreeView-Item.non-child, .DGN-UI-Accordion')).forEach(el => {
695
- if (el.firstChild.querySelector('input').checked) {
696
- if (!el.classList.contains('non-child')) {
697
- setTimeout(() => {
696
+ setTimeout(() => {
697
+ Array.from(ref.current.querySelectorAll('.TreeView-Item.non-child, .DGN-UI-Accordion')).forEach(el => {
698
+ if (el.firstChild.querySelector('input').checked) {
699
+ if (!el.classList.contains('non-child')) {
698
700
  handleDisabledChildren(el, true);
699
- }, 200);
701
+ }
702
+ handleDisabledParent(el.parentNode, true);
700
703
  }
701
- handleDisabledParent(el.parentNode, true);
702
- }
703
- });
704
+ });
705
+ }, 200);
704
706
  }
705
707
  }
706
708
  }, []);
package/locale/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import GlobalObject from "../global";
2
2
  const locale = {
3
3
  get: () => {
4
- const language = GlobalObject.language === 'en' ? 'en' : 'vi';
4
+ const language = GlobalObject.language || 'vi';
5
5
  return language;
6
6
  },
7
7
  set: language => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diginet-core-ui",
3
- "version": "1.4.53-beta.6",
3
+ "version": "1.4.53-beta.8",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "license": "UNLICENSED",
package/theme/settings.js CHANGED
@@ -3,6 +3,7 @@ import { font } from "../styles/font";
3
3
  import { typography as typographies } from "../styles/typography";
4
4
  import createTheme from "./createTheme";
5
5
  import locale from "../locale";
6
+ import { getFormatDateByCountry, getDecimalSymbolByCountry } from "../utils/getLang";
6
7
  // import { getGlobal } from 'global';
7
8
  const {
8
9
  fontSize,
@@ -345,7 +346,7 @@ const settings = {
345
346
  className: '',
346
347
  disabled: false,
347
348
  error: '',
348
- format: locale.get() === 'vi' ? 'DD/MM/YYYY' : 'DD/MM/YYYY',
349
+ format: getFormatDateByCountry(locale.get()),
349
350
  label: '',
350
351
  readOnly: false,
351
352
  required: false,
@@ -360,7 +361,7 @@ const settings = {
360
361
  controls: false,
361
362
  disabled: false,
362
363
  displayAnotherMonth: true,
363
- displayFormat: locale.get() === 'vi' ? 'DD/MM/YYYY' : 'MM/DD/YYYY',
364
+ displayFormat: getFormatDateByCountry(locale.get()),
364
365
  pressESCToClose: true,
365
366
  readOnly: false,
366
367
  required: false,
@@ -596,7 +597,7 @@ const settings = {
596
597
  autoFocus: false,
597
598
  className: '',
598
599
  decimalDigit: Infinity,
599
- decimalSymbol: locale.get() === 'vi' ? ',' : '.',
600
+ decimalSymbol: getDecimalSymbolByCountry(locale.get()),
600
601
  disabled: false,
601
602
  disabledNegative: false,
602
603
  endIcon: '',
@@ -0,0 +1,69 @@
1
+ import { format } from 'date-fns';
2
+ import { lowerCaseDayYear } from "../components/form-control/date-input/utils";
3
+ import { enUS, zhCN, vi, ja } from 'date-fns/locale';
4
+ const getFormatDateByCountry = (lang, isDateFns = false) => {
5
+ let result = '';
6
+ switch (lang) {
7
+ case 'en':
8
+ result = isDateFns ? enUS : 'MM/DD/YYYY';
9
+ break;
10
+ case 'zh':
11
+ result = isDateFns ? zhCN : 'YYYY/MM/DD';
12
+ break;
13
+ case 'ja':
14
+ result = isDateFns ? ja : 'YYYY/MM/DD';
15
+ break;
16
+ case 'vi':
17
+ result = isDateFns ? vi : 'DD/MM/YYYY';
18
+ break;
19
+ default:
20
+ result = 'DD/MM/YYYY';
21
+ break;
22
+ }
23
+ return result;
24
+ };
25
+ const parseDateString = (date, formatStr, locale) => {
26
+ return format(date, lowerCaseDayYear(formatStr), {
27
+ locale: getFormatDateByCountry(locale, true)
28
+ });
29
+ };
30
+ const getDecimalSymbolByCountry = lang => {
31
+ let result = '';
32
+ switch (lang) {
33
+ case 'vi': // Việt Nam
34
+ case 'de': // Đức
35
+ case 'fr': // Pháp
36
+ case 'it': // Ý
37
+ case 'es': // Tây Ban Nha
38
+ case 'ru':
39
+ // Nga
40
+ result = ','; // Dấu phẩy làm thập phân
41
+ break;
42
+ case 'en': // Anh, Mỹ
43
+ case 'zh': // Trung Quốc
44
+ case 'ja': // Nhật Bản
45
+ default:
46
+ result = '.'; // Dấu chấm làm thập phân
47
+ break;
48
+ }
49
+ return result;
50
+ };
51
+ const getThousandSeparatorByCountry = lang => {
52
+ switch (lang) {
53
+ case 'vi': // Việt Nam
54
+ case 'de': // Đức
55
+ case 'es':
56
+ // Tây Ban Nha
57
+ return '.';
58
+ case 'fr':
59
+ // Pháp
60
+ return '\u00A0';
61
+ // space không ngắt
62
+ case 'en': // Anh, Mỹ
63
+ case 'zh': // Trung Quốc
64
+ case 'ja': // Nhật
65
+ default:
66
+ return ',';
67
+ }
68
+ };
69
+ export { getFormatDateByCountry, parseDateString, getDecimalSymbolByCountry, getThousandSeparatorByCountry };
package/utils/index.js CHANGED
@@ -35,4 +35,5 @@ export * from "./sb-template";
35
35
  export * from "./string/string";
36
36
  export * from "./validate";
37
37
  export * from "./object/object";
38
+ export * from "./getLang";
38
39
  export default utils;