@daoyi/nmtl-ui 2.0.1-beta.130 → 2.0.1-beta.131

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,17 +1,17 @@
1
1
  import { _ as _extends$1, a as _slicedToArray$2, b as _objectSpread2, e as _defineProperty$1 } from './_rollupPluginBabelHelpers-a52356f6.js';
2
- import React__default, { createContext, forwardRef, createElement, useContext, useRef, useEffect, useReducer, useCallback, useMemo, useLayoutEffect, Component, useState, useImperativeHandle, Fragment } from 'react';
2
+ import React__default, { createContext, forwardRef, createElement, useContext, useRef, useEffect, useReducer, useCallback, useMemo, useLayoutEffect, useState, useImperativeHandle, Fragment } from 'react';
3
3
  import PropTypes from 'prop-types';
4
- import { h as hoistNonReactStatics_cjs } from './hoist-non-react-statics.cjs-3f408ad2.js';
5
- import axios from 'axios';
6
- import { M as Modal } from './Modal-e04532fa.js';
7
- import { c as commonjsGlobal, a as getDefaultExportFromCjs } from './_commonjsHelpers-70de2c37.js';
8
- import { c as classNames } from './index-b76a85f4.js';
9
- import { Input, IconButton, Button, Box, Typography, FormControl, RadioGroup, FormControlLabel, Radio, TextField, TextareaAutosize } from '@material-ui/core';
4
+ import './hoist-non-react-statics.cjs-3f408ad2.js';
10
5
  import './defaultTheme-ed7746fe.js';
11
6
  import 'react-is';
12
7
  import '@material-ui/styles';
13
8
  import { u as useTheme } from './useTheme-d16d02d9.js';
14
9
  import './withTheme-2d778133.js';
10
+ import axios from 'axios';
11
+ import { M as Modal } from './Modal-e04532fa.js';
12
+ import { c as commonjsGlobal, a as getDefaultExportFromCjs } from './_commonjsHelpers-70de2c37.js';
13
+ import { c as classNames } from './index-b76a85f4.js';
14
+ import { Input, IconButton, Button, Box, Typography, FormControl, RadioGroup, FormControlLabel, Radio, TextField, TextareaAutosize } from '@material-ui/core';
15
15
  import { S as Select } from './Select-cb3e1ba1.js';
16
16
  import { VolumeUp } from '@material-ui/icons';
17
17
  import { getIntl } from './globalConfig';
@@ -2803,12 +2803,6 @@ function _extends() {
2803
2803
  return _extends.apply(this, arguments);
2804
2804
  }
2805
2805
 
2806
- function _inheritsLoose(subClass, superClass) {
2807
- subClass.prototype = Object.create(superClass.prototype);
2808
- subClass.prototype.constructor = subClass;
2809
- subClass.__proto__ = superClass;
2810
- }
2811
-
2812
2806
  function _objectWithoutPropertiesLoose$1(source, excluded) {
2813
2807
  if (source == null) return {};
2814
2808
  var target = {};
@@ -2969,7 +2963,7 @@ function setNestedObjectValues(object, value, visited, response) {
2969
2963
  var FormikContext = /*#__PURE__*/createContext(undefined);
2970
2964
  FormikContext.displayName = 'FormikContext';
2971
2965
  var FormikProvider = FormikContext.Provider;
2972
- var FormikConsumer = FormikContext.Consumer;
2966
+ FormikContext.Consumer;
2973
2967
  function useFormikContext() {
2974
2968
  var formik = useContext(FormikContext);
2975
2969
  return formik;
@@ -4025,65 +4019,6 @@ var Form = /*#__PURE__*/forwardRef(function (props, ref) {
4025
4019
  });
4026
4020
  Form.displayName = 'Form';
4027
4021
 
4028
- /**
4029
- * Connect any component to Formik context, and inject as a prop called `formik`;
4030
- * @param Comp React Component
4031
- */
4032
-
4033
- function connect(Comp) {
4034
- var C = function C(props) {
4035
- return createElement(FormikConsumer, null, function (formik) {
4036
- return createElement(Comp, Object.assign({}, props, {
4037
- formik: formik
4038
- }));
4039
- });
4040
- };
4041
-
4042
- var componentDisplayName = Comp.displayName || Comp.name || Comp.constructor && Comp.constructor.name || 'Component'; // Assign Comp to C.WrappedComponent so we can access the inner component in tests
4043
- // For example, <Field.WrappedComponent /> gets us <FieldInner/>
4044
-
4045
- C.WrappedComponent = Comp;
4046
- C.displayName = "FormikConnect(" + componentDisplayName + ")";
4047
- return hoistNonReactStatics_cjs(C, Comp // cast type to ComponentClass (even if SFC)
4048
- );
4049
- }
4050
-
4051
- var ErrorMessageImpl = /*#__PURE__*/function (_React$Component) {
4052
- _inheritsLoose(ErrorMessageImpl, _React$Component);
4053
-
4054
- function ErrorMessageImpl() {
4055
- return _React$Component.apply(this, arguments) || this;
4056
- }
4057
-
4058
- var _proto = ErrorMessageImpl.prototype;
4059
-
4060
- _proto.shouldComponentUpdate = function shouldComponentUpdate(props) {
4061
- if (getIn(this.props.formik.errors, this.props.name) !== getIn(props.formik.errors, this.props.name) || getIn(this.props.formik.touched, this.props.name) !== getIn(props.formik.touched, this.props.name) || Object.keys(this.props).length !== Object.keys(props).length) {
4062
- return true;
4063
- } else {
4064
- return false;
4065
- }
4066
- };
4067
-
4068
- _proto.render = function render() {
4069
- var _this$props = this.props,
4070
- component = _this$props.component,
4071
- formik = _this$props.formik,
4072
- render = _this$props.render,
4073
- children = _this$props.children,
4074
- name = _this$props.name,
4075
- rest = _objectWithoutPropertiesLoose$1(_this$props, ["component", "formik", "render", "children", "name"]);
4076
-
4077
- var touch = getIn(formik.touched, name);
4078
- var error = getIn(formik.errors, name);
4079
- return !!touch && !!error ? render ? isFunction(render) ? render(error) : null : children ? isFunction(children) ? children(error) : null : component ? createElement(component, rest, error) : error : null;
4080
- };
4081
-
4082
- return ErrorMessageImpl;
4083
- }(Component);
4084
-
4085
- var ErrorMessage = /*#__PURE__*/connect(ErrorMessageImpl);
4086
-
4087
4022
  // const sendMail = {
4088
4023
  // from: "orient.cc.noreply@gmail.com",
4089
4024
  // to: email,
@@ -9998,16 +9933,27 @@ const getConfig = () => ({
9998
9933
  color: [getRandom(100, 255, 3), getRandom(100, 255, 4), getRandom(100, 255, 3), getRandom(100, 255, 3)]
9999
9934
  });
10000
9935
 
10001
- var css_248z$2 = ".vcode {\n display: block;\n align-items: center;\n}\n.vcode__image {\n margin-top: 10px;\n background: rgba(0, 0, 0, 0.8);\n width: 160px;\n overflow: hidden;\n height: 50px;\n text-align: center;\n position: relative;\n}\n.vcode__image:hover .vcode__mask {\n opacity: 0.8;\n}\n.vcode__image__mask {\n position: absolute;\n width: 100%;\n top: 0;\n line-height: 50px;\n background-color: rgba(0, 0, 0, 0.95);\n opacity: 0;\n z-index: 1;\n transition: opacity 0.3s ease-in-out;\n cursor: pointer;\n}\n.vcode__image__itemStr {\n float: left;\n margin-left: 20px;\n}\n.vcode__box {\n display: flex;\n align-items: center;\n}\n.vcode__error {\n color: #d93333;\n font-weight: bold;\n margin-left: 1rem;\n}\n\n#bgi {\n top: 0;\n left: 0;\n position: absolute;\n width: 100%;\n height: 100%;\n}";
10002
- styleInject(css_248z$2);
10003
-
9936
+ var css_248z$3 = ".vcode {\n display: block;\n align-items: center;\n}\n.vcode__image {\n margin-top: 10px;\n background: rgba(0, 0, 0, 0.8);\n width: 160px;\n overflow: hidden;\n height: 50px;\n text-align: center;\n position: relative;\n}\n.vcode__image:hover .vcode__mask {\n opacity: 0.8;\n}\n.vcode__image__mask {\n position: absolute;\n width: 100%;\n top: 0;\n line-height: 50px;\n background-color: rgba(0, 0, 0, 0.95);\n opacity: 0;\n z-index: 1;\n transition: opacity 0.3s ease-in-out;\n cursor: pointer;\n}\n.vcode__image__itemStr {\n float: left;\n margin-left: 20px;\n}\n.vcode__box {\n display: flex;\n align-items: center;\n}\n.vcode__error {\n color: #b91c1c;\n font-weight: bold;\n margin-left: 1rem;\n}\n\n#bgi {\n top: 0;\n left: 0;\n position: absolute;\n width: 100%;\n height: 100%;\n}";
9937
+ styleInject(css_248z$3);
9938
+
9939
+ /* 視覺隱藏的輸入說明(不依賴各站的 .visually-hidden,同 Select) */
9940
+ const hiddenStyle = {
9941
+ position: 'absolute',
9942
+ width: 1,
9943
+ height: 1,
9944
+ overflow: 'hidden',
9945
+ clip: 'rect(1px, 1px, 1px, 1px)',
9946
+ whiteSpace: 'nowrap'
9947
+ };
10004
9948
  const VCode = _ref => {
10005
9949
  let {
10006
9950
  visible,
10007
9951
  onChange,
10008
9952
  formatMessage,
10009
- name,
10010
9953
  inputId,
9954
+ labelId,
9955
+ errorId,
9956
+ errorMessage,
10011
9957
  required
10012
9958
  } = _ref;
10013
9959
  const [codeConfig, setCodeConfig] = useState(getConfig());
@@ -10018,6 +9964,12 @@ const VCode = _ref => {
10018
9964
  fz,
10019
9965
  color
10020
9966
  } = codeConfig;
9967
+ const hintId = `${inputId}-hint`;
9968
+ /* WCAG 1.4.3 錯誤文字深色主題改亮色(同 FormItem 必填星號) */
9969
+ const theme = useTheme();
9970
+ const errorStyle = theme && theme.palette && theme.palette.type === 'dark' ? {
9971
+ color: '#ff8a80'
9972
+ } : undefined;
10021
9973
  const refresh = () => {
10022
9974
  canvas();
10023
9975
  setCodeConfig(getConfig());
@@ -10032,7 +9984,7 @@ const VCode = _ref => {
10032
9984
  }, [visible]);
10033
9985
  const vcodeNumber = `${convert(data[0])}${convert(data[1])}${convert(data[2])}${convert(data[3])}`;
10034
9986
 
10035
- /* WCAG 1.1.1 驗證碼語音替代(tltc 認證模式):speechSynthesis 逐字報讀,
9987
+ /* WCAG 1.1.1 驗證碼語音替代(tltc 認證模式):speechSynthesis 逐字報讀,
10036
9988
  讓無法辨識圖片的使用者取得驗證碼內容 */
10037
9989
  const speakVerificationCode = () => {
10038
9990
  if ('speechSynthesis' in window) {
@@ -10062,84 +10014,99 @@ const VCode = _ref => {
10062
10014
  setTimeout(() => setLiveMessage(''), 3000);
10063
10015
  }
10064
10016
  };
10065
- return /*#__PURE__*/React__default.createElement("div", {
10066
- className: "vcode"
10067
- }, /*#__PURE__*/React__default.createElement("div", {
10068
- "aria-live": "polite",
10069
- "aria-atomic": "true",
10070
- role: "status",
10071
- className: "visually-hidden"
10072
- }, liveMessage), /*#__PURE__*/React__default.createElement(Input, {
10073
- inputProps: {
10074
- id: inputId,
10075
- 'aria-required': required || undefined
10076
- },
10077
- placeholder: formatMessage({
10078
- id: 'common.form.code.check'
10079
- }),
10080
- onChange: e => onChange(e.target.value.toUpperCase() === vcodeNumber.toUpperCase())
10081
- }), /*#__PURE__*/React__default.createElement("div", {
10082
- className: "vcode__box"
10083
- }, /*#__PURE__*/React__default.createElement(IconButton, {
10084
- className: "vcode__audio",
10085
- "aria-label": getIntl().formatMessage({
10086
- id: 'aria.vcode.audioPlay'
10087
- }),
10088
- title: getIntl().formatMessage({
10089
- id: 'aria.vcode.audioPlay'
10090
- }),
10091
- onClick: speakVerificationCode
10092
- }, /*#__PURE__*/React__default.createElement(VolumeUp, {
10093
- "aria-hidden": "true"
10094
- })), /*#__PURE__*/React__default.createElement("div", {
10095
- className: "vcode__image",
10096
- role: "img",
10097
- "aria-label": getIntl().formatMessage({
10098
- id: 'aria.vcode.image'
10099
- })
10100
- }, /*#__PURE__*/React__default.createElement("canvas", {
10101
- id: "bgi",
10102
- width: "200",
10103
- height: "200",
10104
- "aria-hidden": "true"
10105
- }), data.map((v, i) => /*#__PURE__*/React__default.createElement("div", {
10106
- key: i.toString(),
10107
- className: "vcode__image__itemStr",
10108
- "aria-hidden": "true",
10109
- style: {
10110
- transform: `rotate(${rotate[i]}deg)`,
10111
- fontSize: `${fz[i]}px`,
10112
- color: `rgb(${color[i].toString()})`
10113
- }
10114
- }, convert(v))), /*#__PURE__*/React__default.createElement("div", {
10115
- className: "vcode__image__mask",
10116
- role: "button",
10117
- tabIndex: 0,
10118
- "aria-label": getIntl().formatMessage({
10119
- id: 'aria.vcode.refresh'
10120
- }),
10121
- onClick: refresh,
10122
- onKeyDown: e => {
10123
- if (e.key === 'Enter' || e.key === ' ') {
10124
- e.preventDefault();
10125
- refresh();
10017
+ return (
10018
+ /*#__PURE__*/
10019
+ /* WCAG 1.3.1 驗證碼由輸入框、語音、圖片、刷新組成,以 group 包起來並沿用欄位標題命名(規範 04 §3) */
10020
+ React__default.createElement("div", {
10021
+ className: "vcode",
10022
+ role: "group",
10023
+ "aria-labelledby": labelId
10024
+ }, /*#__PURE__*/React__default.createElement("div", {
10025
+ "aria-live": "polite",
10026
+ "aria-atomic": "true",
10027
+ role: "status",
10028
+ className: "visually-hidden"
10029
+ }, liveMessage), /*#__PURE__*/React__default.createElement("span", {
10030
+ id: hintId,
10031
+ style: hiddenStyle
10032
+ }, getIntl().formatMessage({
10033
+ id: 'aria.vcode.hint'
10034
+ })), /*#__PURE__*/React__default.createElement(Input, {
10035
+ inputProps: {
10036
+ id: inputId,
10037
+ 'aria-required': required || undefined,
10038
+ 'aria-invalid': errorMessage ? true : undefined,
10039
+ 'aria-describedby': errorMessage ? `${hintId} ${errorId}` : hintId
10040
+ },
10041
+ placeholder: formatMessage({
10042
+ id: 'common.form.code.check'
10043
+ }),
10044
+ onChange: e => onChange(e.target.value.toUpperCase() === vcodeNumber.toUpperCase())
10045
+ }), /*#__PURE__*/React__default.createElement("div", {
10046
+ className: "vcode__box"
10047
+ }, /*#__PURE__*/React__default.createElement(IconButton, {
10048
+ className: "vcode__audio",
10049
+ "aria-label": getIntl().formatMessage({
10050
+ id: 'aria.vcode.audioPlay'
10051
+ }),
10052
+ title: getIntl().formatMessage({
10053
+ id: 'aria.vcode.audioPlay'
10054
+ }),
10055
+ onClick: speakVerificationCode
10056
+ }, /*#__PURE__*/React__default.createElement(VolumeUp, {
10057
+ "aria-hidden": "true"
10058
+ })), /*#__PURE__*/React__default.createElement("div", {
10059
+ className: "vcode__image",
10060
+ role: "img",
10061
+ "aria-label": getIntl().formatMessage({
10062
+ id: 'aria.vcode.image'
10063
+ })
10064
+ }, /*#__PURE__*/React__default.createElement("canvas", {
10065
+ id: "bgi",
10066
+ width: "200",
10067
+ height: "200",
10068
+ "aria-hidden": "true"
10069
+ }), data.map((v, i) => /*#__PURE__*/React__default.createElement("div", {
10070
+ key: i.toString(),
10071
+ className: "vcode__image__itemStr",
10072
+ "aria-hidden": "true",
10073
+ style: {
10074
+ transform: `rotate(${rotate[i]}deg)`,
10075
+ fontSize: `${fz[i]}px`,
10076
+ color: `rgb(${color[i].toString()})`
10126
10077
  }
10127
- }
10128
- }, formatMessage({
10129
- id: 'common.click.refresh'
10130
- }))), /*#__PURE__*/React__default.createElement(ErrorMessage, {
10131
- className: "vcode__error",
10132
- name: name,
10133
- component: "div"
10134
- })));
10078
+ }, convert(v))), /*#__PURE__*/React__default.createElement("div", {
10079
+ className: "vcode__image__mask",
10080
+ role: "button",
10081
+ tabIndex: 0,
10082
+ "aria-label": getIntl().formatMessage({
10083
+ id: 'aria.vcode.refresh'
10084
+ }),
10085
+ onClick: refresh,
10086
+ onKeyDown: e => {
10087
+ if (e.key === 'Enter' || e.key === ' ') {
10088
+ e.preventDefault();
10089
+ refresh();
10090
+ }
10091
+ }
10092
+ }, formatMessage({
10093
+ id: 'common.click.refresh'
10094
+ }))), errorMessage && /*#__PURE__*/React__default.createElement("div", {
10095
+ id: errorId,
10096
+ className: "vcode__error",
10097
+ style: errorStyle
10098
+ }, errorMessage)))
10099
+ );
10135
10100
  };
10136
10101
  VCode.defaultProps = {
10137
10102
  visible: false,
10138
10103
  // placeholder: undefined,
10139
10104
  onChange: () => {},
10140
10105
  formatMessage: () => {},
10141
- name: undefined,
10142
10106
  inputId: undefined,
10107
+ labelId: undefined,
10108
+ errorId: undefined,
10109
+ errorMessage: undefined,
10143
10110
  required: false
10144
10111
  };
10145
10112
  VCode.propTypes = {
@@ -10147,9 +10114,14 @@ VCode.propTypes = {
10147
10114
  // placeholder: PropTypes.string,
10148
10115
  onChange: PropTypes.func,
10149
10116
  formatMessage: PropTypes.func,
10150
- name: PropTypes.string,
10151
10117
  /** 與外部 label 關聯用的 input id(WCAG 3.3.2) */
10152
10118
  inputId: PropTypes.string,
10119
+ /** 欄位標題元素 id,作為驗證碼群組的名稱(WCAG 1.3.1) */
10120
+ labelId: PropTypes.string,
10121
+ /** 錯誤訊息元素 id(aria-describedby 關聯用) */
10122
+ errorId: PropTypes.string,
10123
+ /** 目前要顯示的錯誤訊息;沒有錯誤時不給 */
10124
+ errorMessage: PropTypes.string,
10153
10125
  /** 是否必填(aria-required) */
10154
10126
  required: PropTypes.bool
10155
10127
  };
@@ -10170,8 +10142,8 @@ var googleLogin = {exports: {}};
10170
10142
 
10171
10143
  var GoogleLogin = /*@__PURE__*/getDefaultExportFromCjs(googleLogin.exports);
10172
10144
 
10173
- var css_248z$1 = ".emailInput__loginSDK {\n display: flex;\n align-items: center;\n}\n.emailInput__loginSDK__google {\n padding: 6px 10px 4px !important;\n border: 1px solid black !important;\n}\n.emailInput__loginSDK__google div {\n padding: 0 !important;\n}\n.emailInput__loginSDK__google span {\n padding: 0 !important;\n}\n.emailInput__loginSDK__fb {\n padding: 9px 10px !important;\n border-radius: 3px;\n margin-left: 10px;\n background-color: #4c69ba;\n border: 1px solid black;\n color: white;\n}\n.emailInput__loginSDK__fb i {\n margin-right: 10px;\n}\n.emailInput__operator {\n margin-top: 10px;\n}";
10174
- styleInject(css_248z$1);
10145
+ var css_248z$2 = ".emailInput__loginSDK {\n display: flex;\n align-items: center;\n}\n.emailInput__loginSDK__google {\n padding: 6px 10px 4px !important;\n border: 1px solid black !important;\n}\n.emailInput__loginSDK__google div {\n padding: 0 !important;\n}\n.emailInput__loginSDK__google span {\n padding: 0 !important;\n}\n.emailInput__loginSDK__fb {\n padding: 9px 10px !important;\n border-radius: 3px;\n margin-left: 10px;\n background-color: #4c69ba;\n border: 1px solid black;\n color: white;\n}\n.emailInput__loginSDK__fb i {\n margin-right: 10px;\n}\n.emailInput__operator {\n margin-top: 10px;\n}";
10146
+ styleInject(css_248z$2);
10175
10147
 
10176
10148
  const EmailInput = _ref => {
10177
10149
  let {
@@ -10180,7 +10152,9 @@ const EmailInput = _ref => {
10180
10152
  onChange,
10181
10153
  onNotify,
10182
10154
  inputId,
10183
- required
10155
+ required,
10156
+ ariaInvalid,
10157
+ ariaDescribedby
10184
10158
  } = _ref;
10185
10159
  const [init, setInit] = useState(false); // google login 在init時會先failed
10186
10160
  useMemo(() => () => setTimeout(() => setInit(true), 1000), []); // 故延遲一秒後再給google call(最非最佳解 可優化)
@@ -10231,7 +10205,9 @@ const EmailInput = _ref => {
10231
10205
  value: value,
10232
10206
  inputProps: {
10233
10207
  id: inputId,
10234
- 'aria-required': required || undefined
10208
+ 'aria-required': required || undefined,
10209
+ 'aria-invalid': ariaInvalid,
10210
+ 'aria-describedby': ariaDescribedby
10235
10211
  },
10236
10212
  placeholder: placeholder,
10237
10213
  onChange: e => onChange(e.target.value)
@@ -10243,7 +10219,9 @@ EmailInput.defaultProps = {
10243
10219
  onChange: () => {},
10244
10220
  onNotify: () => {},
10245
10221
  inputId: undefined,
10246
- required: false
10222
+ required: false,
10223
+ ariaInvalid: undefined,
10224
+ ariaDescribedby: undefined
10247
10225
  };
10248
10226
  EmailInput.propTypes = {
10249
10227
  value: PropTypes.string,
@@ -10253,7 +10231,11 @@ EmailInput.propTypes = {
10253
10231
  /** 與外部 label 關聯用的 input id(WCAG 3.3.2) */
10254
10232
  inputId: PropTypes.string,
10255
10233
  /** 是否必填(aria-required) */
10256
- required: PropTypes.bool
10234
+ required: PropTypes.bool,
10235
+ /** 欄位驗證未通過(aria-invalid,WCAG 3.3.1) */
10236
+ ariaInvalid: PropTypes.bool,
10237
+ /** 錯誤訊息元素 id(aria-describedby) */
10238
+ ariaDescribedby: PropTypes.string
10257
10239
  };
10258
10240
 
10259
10241
  var CloudUpload = {};
@@ -11600,6 +11582,7 @@ function reducer(state, action) {
11600
11582
  const Upload = _ref => {
11601
11583
  let {
11602
11584
  ariaLabelledby,
11585
+ ariaDescribedby,
11603
11586
  buttonText,
11604
11587
  onChange
11605
11588
  } = _ref;
@@ -11634,6 +11617,7 @@ const Upload = _ref => {
11634
11617
  startIcon: /*#__PURE__*/React__default.createElement(default_1, {
11635
11618
  "aria-hidden": "true"
11636
11619
  }),
11620
+ "aria-describedby": ariaDescribedby,
11637
11621
  onClick: openDialog
11638
11622
  }, buttonText || 'Upload')), /*#__PURE__*/React__default.createElement("aside", null, /*#__PURE__*/React__default.createElement("ul", {
11639
11623
  "aria-live": "polite"
@@ -11644,19 +11628,29 @@ const Upload = _ref => {
11644
11628
  };
11645
11629
  Upload.defaultProps = {
11646
11630
  ariaLabelledby: undefined,
11631
+ ariaDescribedby: undefined,
11647
11632
  buttonText: undefined
11648
11633
  };
11649
11634
  Upload.propTypes = {
11650
11635
  /** 欄位標題元素 id(aria-labelledby 關聯用) */
11651
11636
  ariaLabelledby: PropTypes.string,
11637
+ /** 錯誤訊息元素 id(aria-describedby 關聯用) */
11638
+ ariaDescribedby: PropTypes.string,
11652
11639
  /** 觸發按鈕的可見文字(建議傳欄位標題,如「附件上傳」) */
11653
11640
  buttonText: PropTypes.string,
11654
11641
  onChange: PropTypes.func.isRequired
11655
11642
  };
11656
11643
 
11657
- var css_248z = ".formItem {\n width: 100%;\n margin-bottom: 16px;\n}\n.formItem:last-child {\n margin-bottom: initial;\n}\n.formItem__title {\n display: flex;\n font-size: 1rem;\n font-weight: bold;\n}\n.formItem__title__star {\n margin-left: 3px;\n color: #b91c1c;\n}\n.formItem__operator {\n margin: 2px 0;\n font-size: 0.875rem;\n}\n.formItem__operator__radio__desc {\n margin-left: 35px !important;\n}\n.formItem__operator--unsupport {\n border: 1px solid #d93333;\n background: pink;\n color: black;\n padding: 5px 10px;\n}\n.formItem__error {\n color: #b91c1c;\n font-weight: bold;\n}\n.formItem textarea {\n border: 1px solid #d9d9d9;\n border-radius: 3px;\n width: 100%;\n background: transparent;\n padding: 6px 10px;\n}\n.formItem ::-webkit-calendar-picker-indicator {\n filter: invert(1);\n}";
11658
- styleInject(css_248z);
11644
+ var css_248z$1 = ".formItem {\n width: 100%;\n margin-bottom: 16px;\n}\n.formItem:last-child {\n margin-bottom: initial;\n}\n.formItem__title {\n display: flex;\n font-size: 1rem;\n font-weight: bold;\n}\n.formItem__title__star {\n margin-left: 3px;\n color: #b91c1c;\n}\n.formItem__operator {\n margin: 2px 0;\n font-size: 0.875rem;\n}\n.formItem__operator__radio__desc {\n margin-left: 35px !important;\n}\n.formItem__operator--unsupport {\n border: 1px solid #d93333;\n background: pink;\n color: black;\n padding: 5px 10px;\n}\n.formItem__error {\n color: #b91c1c;\n font-weight: bold;\n}\n.formItem textarea {\n border: 1px solid #d9d9d9;\n border-radius: 3px;\n width: 100%;\n background: transparent;\n padding: 6px 10px;\n}\n.formItem ::-webkit-calendar-picker-indicator {\n filter: invert(1);\n}";
11645
+ styleInject(css_248z$1);
11659
11646
 
11647
+ /* 欄位相關元素的 id 命名集中在這裡:ContactModal 的錯誤摘要靠同一組 id 找到欄位 */
11648
+ const getFormItemIds = name => ({
11649
+ containerId: `form-${name}`,
11650
+ inputId: `form-input-${name}`,
11651
+ labelId: `form-label-${name}`,
11652
+ errorId: `form-error-${name}`
11653
+ });
11660
11654
  const FormItem = _ref => {
11661
11655
  let {
11662
11656
  name,
@@ -11675,21 +11669,36 @@ const FormItem = _ref => {
11675
11669
  id: 'common.enter'
11676
11670
  })} ${label}`;
11677
11671
  /* WCAG 1.3.1/3.3.2 欄位與標題的程式化關聯(WAVE: Missing form label) */
11678
- const inputId = `form-input-${name}`;
11679
- const labelId = `form-label-${name}`;
11680
- const a11yInputProps = {
11681
- id: inputId,
11682
- 'aria-required': required || undefined
11683
- };
11672
+ const {
11673
+ containerId,
11674
+ inputId,
11675
+ labelId,
11676
+ errorId
11677
+ } = getFormItemIds(name);
11684
11678
  /* 這些欄位型別會渲染帶 inputId 的 input,標題才能用 label htmlFor;其餘型別改以 aria-labelledby 關聯 */
11685
11679
  const hasInputId = ['input', 'textarea', 'datePicker', 'email', 'vcode'].includes(type);
11686
11680
  /* WCAG 1.4.3 必填星號依主題深淺自動選色:formItem.scss 的 #b91c1c 只適用淺底 Modal,
11687
- 深色主題(如 ocean Paper #30353d)對比僅約 1.5:1(WAVE 實測被抓)→ 深色用 #ff8a80(約 5.4:1) */
11681
+ 深色主題(如 ocean Paper #30353d)對比僅約 1.5:1(WAVE 實測被抓)→ 深色用 #ff8a80(約 5.4:1)。
11682
+ 錯誤訊息同色,一併套用 */
11688
11683
  const theme = useTheme();
11689
11684
  const starStyle = theme && theme.palette && theme.palette.type === 'dark' ? {
11690
11685
  color: '#ff8a80'
11691
11686
  } : undefined;
11692
- const render = field => {
11687
+
11688
+ /* WCAG 3.3.1 欄位出錯時:aria-invalid,並以 aria-describedby 指向下方的錯誤訊息,
11689
+ 讀屏聚焦欄位就會唸出錯在哪裡(規範 04 §2)。沒有錯誤時兩者都不輸出 */
11690
+ const render = (field, _ref2) => {
11691
+ let {
11692
+ invalid,
11693
+ describedBy,
11694
+ errorMessage
11695
+ } = _ref2;
11696
+ const a11yInputProps = {
11697
+ id: inputId,
11698
+ 'aria-required': required || undefined,
11699
+ 'aria-invalid': invalid,
11700
+ 'aria-describedby': describedBy
11701
+ };
11693
11702
  let component;
11694
11703
  switch (type) {
11695
11704
  case 'input':
@@ -11699,9 +11708,7 @@ const FormItem = _ref => {
11699
11708
  }));
11700
11709
  break;
11701
11710
  case 'textarea':
11702
- component = /*#__PURE__*/React__default.createElement(TextareaAutosize, _extends$1({}, field, {
11703
- id: inputId,
11704
- "aria-required": required || undefined,
11711
+ component = /*#__PURE__*/React__default.createElement(TextareaAutosize, _extends$1({}, field, a11yInputProps, {
11705
11712
  minRows: 3,
11706
11713
  placeholder: currentPlaceholder
11707
11714
  }));
@@ -11725,6 +11732,8 @@ const FormItem = _ref => {
11725
11732
  component = /*#__PURE__*/React__default.createElement(EmailInput, _extends$1({}, field, {
11726
11733
  inputId: inputId,
11727
11734
  required: required,
11735
+ ariaInvalid: invalid,
11736
+ ariaDescribedby: describedBy,
11728
11737
  placeholder: currentPlaceholder,
11729
11738
  onChange: email => setFieldValue(field.name, email),
11730
11739
  onNotify: onNotify
@@ -11734,8 +11743,12 @@ const FormItem = _ref => {
11734
11743
  component = /*#__PURE__*/React__default.createElement(FormControl, {
11735
11744
  component: "fieldset",
11736
11745
  "aria-labelledby": labelId
11737
- }, /*#__PURE__*/React__default.createElement(RadioGroup, field, options.map(option => /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(FormControlLabel, {
11738
- key: option.value,
11746
+ }, /*#__PURE__*/React__default.createElement(RadioGroup, _extends$1({}, field, {
11747
+ "aria-invalid": invalid,
11748
+ "aria-describedby": describedBy
11749
+ }), options.map(option => /*#__PURE__*/React__default.createElement(React__default.Fragment, {
11750
+ key: option.value
11751
+ }, /*#__PURE__*/React__default.createElement(FormControlLabel, {
11739
11752
  value: option.value,
11740
11753
  control: /*#__PURE__*/React__default.createElement(Radio, null),
11741
11754
  label: option.label
@@ -11748,6 +11761,7 @@ const FormItem = _ref => {
11748
11761
  /* WCAG 1.3.1/3.3.2 附件上傳:標題 id 關聯內部 file input;按鈕以欄位標題為可見文字(WAVE: Missing form label) */
11749
11762
  component = /*#__PURE__*/React__default.createElement(Upload, _extends$1({}, field, {
11750
11763
  ariaLabelledby: labelId,
11764
+ ariaDescribedby: describedBy,
11751
11765
  buttonText: label,
11752
11766
  onChange: files => setFieldValue(field.name, files)
11753
11767
  }));
@@ -11755,11 +11769,13 @@ const FormItem = _ref => {
11755
11769
  case 'vcode':
11756
11770
  component = /*#__PURE__*/React__default.createElement(VCode, {
11757
11771
  inputId: inputId,
11772
+ labelId: labelId,
11773
+ errorId: errorId,
11774
+ errorMessage: errorMessage,
11758
11775
  required: required,
11759
11776
  placeholder: currentPlaceholder,
11760
11777
  onChange: pass => setFieldValue(field.name, pass),
11761
- formatMessage: formatMessage,
11762
- name: name
11778
+ formatMessage: formatMessage
11763
11779
  });
11764
11780
  break;
11765
11781
  default:
@@ -11769,13 +11785,20 @@ const FormItem = _ref => {
11769
11785
  };
11770
11786
  return /*#__PURE__*/React__default.createElement(Field, {
11771
11787
  name: name,
11772
- render: _ref2 => {
11788
+ render: _ref3 => {
11773
11789
  let {
11774
- field
11775
- } = _ref2;
11776
- const component = render(field);
11790
+ field,
11791
+ meta
11792
+ } = _ref3;
11793
+ /* 與 formik ErrorMessage 相同的顯示條件:碰過(或按過送出)且有錯誤 */
11794
+ const hasError = Boolean(meta.touched && meta.error);
11795
+ const component = render(field, {
11796
+ invalid: hasError || undefined,
11797
+ describedBy: hasError ? errorId : undefined,
11798
+ errorMessage: hasError ? meta.error : undefined
11799
+ });
11777
11800
  return /*#__PURE__*/React__default.createElement("div", {
11778
- id: `form-${name}`,
11801
+ id: containerId,
11779
11802
  className: "formItem"
11780
11803
  }, label && (hasInputId ?
11781
11804
  /*#__PURE__*/
@@ -11807,11 +11830,11 @@ const FormItem = _ref => {
11807
11830
  className: classNames('formItem__operator', {
11808
11831
  'formItem__operator--unsupport': !component
11809
11832
  })
11810
- }, component || 'Check component type is support on FormItem'), field.name === 'vcode' ? null : /*#__PURE__*/React__default.createElement(ErrorMessage, {
11833
+ }, component || 'Check component type is support on FormItem'), hasError && type !== 'vcode' && /*#__PURE__*/React__default.createElement("div", {
11834
+ id: errorId,
11811
11835
  className: "formItem__error",
11812
- name: name,
11813
- component: "div"
11814
- }));
11836
+ style: starStyle
11837
+ }, meta.error));
11815
11838
  }
11816
11839
  });
11817
11840
  };
@@ -11964,7 +11987,27 @@ const problemMail = _ref2 => {
11964
11987
  return body.join('<br />');
11965
11988
  };
11966
11989
 
11967
- var errorId;
11990
+ var css_248z = "@charset \"UTF-8\";\n/* 送出失敗的錯誤摘要(WCAG 3.3.1,規範 04 §2);深色主題由 ContactModal 以 inline color 覆寫 */\n.contactModal__errorSummary {\n color: #b91c1c;\n border-left: 4px solid currentColor;\n padding: 0.5rem 0.75rem;\n margin-bottom: 1rem;\n /* 容器常駐 DOM(role=\"alert\" 才能可靠播報),沒有錯誤時不佔版面 */\n}\n.contactModal__errorSummary:empty {\n padding: 0;\n margin: 0;\n border: 0;\n}\n.contactModal__errorSummary__title {\n margin: 0 0 0.25rem;\n font-weight: bold;\n}\n.contactModal__errorSummary__list {\n margin: 0;\n padding-left: 1.25rem;\n}\n.contactModal__errorSummary__link {\n padding: 0;\n border: 0;\n background: none;\n color: inherit;\n font: inherit;\n text-align: left;\n text-decoration: underline;\n cursor: pointer;\n}";
11991
+ styleInject(css_248z);
11992
+
11993
+ /* 錯誤摘要的「前往該欄位」:優先聚焦帶 inputId 的欄位;
11994
+ 單選、下拉、上傳沒有該 id,改找欄位容器內第一個看得到、可聚焦的元素 */
11995
+ var focusFormItem = function focusFormItem(name) {
11996
+ var _getFormItemIds = getFormItemIds(name),
11997
+ containerId = _getFormItemIds.containerId,
11998
+ inputId = _getFormItemIds.inputId;
11999
+ var input = document.getElementById(inputId);
12000
+ if (input) {
12001
+ input.focus();
12002
+ return;
12003
+ }
12004
+ var container = document.getElementById(containerId);
12005
+ if (!container) return;
12006
+ var target = Array.from(container.querySelectorAll('input, textarea, button, [role="button"]')).find(function (el) {
12007
+ return !el.disabled && el.tabIndex >= 0 && el.getClientRects().length > 0;
12008
+ });
12009
+ if (target) target.focus();
12010
+ };
11968
12011
  var ContactModal = function ContactModal(_ref) {
11969
12012
  var type = _ref.type,
11970
12013
  mailto = _ref.mailto,
@@ -11982,6 +12025,21 @@ var ContactModal = function ContactModal(_ref) {
11982
12025
  _useState4 = _slicedToArray$2(_useState3, 2),
11983
12026
  formType = _useState4[0],
11984
12027
  setFormType = _useState4[1];
12028
+ /* WCAG 3.3.1 錯誤摘要(規範 04 §2):只在按下送出時更新,使用者逐欄修正時不跟著變動 */
12029
+ var _useState5 = useState([]),
12030
+ _useState6 = _slicedToArray$2(_useState5, 2),
12031
+ errorSummary = _useState6[0],
12032
+ setErrorSummary = _useState6[1];
12033
+ var _useState7 = useState(0),
12034
+ _useState8 = _slicedToArray$2(_useState7, 2),
12035
+ summaryVersion = _useState8[0],
12036
+ setSummaryVersion = _useState8[1];
12037
+ var summaryRef = useRef(null);
12038
+ /* WCAG 1.4.3 錯誤文字與必填星號同色:深色主題(如 ocean Paper #30353d)改亮色 */
12039
+ var theme = useTheme();
12040
+ var errorStyle = theme && theme.palette && theme.palette.type === 'dark' ? {
12041
+ color: '#ff8a80'
12042
+ } : undefined;
11985
12043
 
11986
12044
  /* 建立表單設定檔 */
11987
12045
  var template = contactTemplate({
@@ -11989,6 +12047,11 @@ var ContactModal = function ContactModal(_ref) {
11989
12047
  formType: formType
11990
12048
  });
11991
12049
 
12050
+ /* 送出失敗後把焦點移到錯誤摘要:摘要內容在這一輪才渲染,要等 commit 之後再聚焦 */
12051
+ useEffect(function () {
12052
+ if (summaryVersion > 0 && summaryRef.current) summaryRef.current.focus();
12053
+ }, [summaryVersion]);
12054
+
11992
12055
  /* 表單控制元件 */
11993
12056
  var formik = useFormik({
11994
12057
  initialValues: template.reduce(function (obj, item) {
@@ -12030,9 +12093,6 @@ var ContactModal = function ContactModal(_ref) {
12030
12093
  id: 'common.form.attachment.valid.error'
12031
12094
  });
12032
12095
  }
12033
-
12034
- /* 取得第一個錯誤的id */
12035
- errorId = Object.keys(errors).length > 0 ? Object.keys(errors).shift() : null;
12036
12096
  return errors;
12037
12097
  },
12038
12098
  onSubmit: function onSubmit(values) {
@@ -12111,28 +12171,36 @@ var ContactModal = function ContactModal(_ref) {
12111
12171
  /* 關閉表單 */
12112
12172
  var handleClose = function handleClose() {
12113
12173
  formik.resetForm();
12174
+ setErrorSummary([]);
12114
12175
  setOpen(false);
12115
12176
  };
12116
12177
 
12117
- /* 送出郵件 */
12178
+ /* 送出:先取得驗證結果決定摘要內容,再交給 formik 送出。
12179
+ formik 送出時會把所有欄位標為 touched,欄位下方的錯誤訊息才會出現;驗證通過才會真的寄信。
12180
+ (原本在 handleSubmit 之後同步讀取驗證結果,但 formik 2 的驗證是非同步的,第一次按送出時讀不到) */
12118
12181
  var handleSubmit = function handleSubmit() {
12119
- formik.handleSubmit();
12120
- /* 滾動過去錯誤的地方 */
12121
- var errorElement = document.getElementById("form-".concat(errorId));
12122
- if (errorElement) {
12123
- var offsetY = errorElement.offsetTop - 65;
12124
- if (errorElement.parentElement.scrollTo) {
12125
- errorElement.parentElement.scrollTo({
12126
- top: offsetY,
12127
- behavior: 'smooth'
12182
+ formik.validateForm().then(function (errors) {
12183
+ var invalidItems = template.filter(function (_ref6) {
12184
+ var name = _ref6.name;
12185
+ return errors[name];
12186
+ }).map(function (_ref7) {
12187
+ var name = _ref7.name;
12188
+ return {
12189
+ name: name,
12190
+ message: errors[name]
12191
+ };
12192
+ });
12193
+ setErrorSummary(invalidItems);
12194
+ formik.handleSubmit();
12195
+ if (invalidItems.length > 0) {
12196
+ setSummaryVersion(function (version) {
12197
+ return version + 1;
12198
+ });
12199
+ onNotify({
12200
+ type: 'error',
12201
+ message: 'common.form.error'
12128
12202
  });
12129
- } else {
12130
- errorElement.parentElement.scrollTop = offsetY;
12131
12203
  }
12132
- }
12133
- if (errorId) onNotify({
12134
- type: 'error',
12135
- message: 'common.form.error'
12136
12204
  });
12137
12205
  };
12138
12206
  return /*#__PURE__*/React__default.createElement(Modal, {
@@ -12150,7 +12218,33 @@ var ContactModal = function ContactModal(_ref) {
12150
12218
  okText: formatMessage({
12151
12219
  id: 'common.submit'
12152
12220
  })
12153
- }, /*#__PURE__*/React__default.createElement(FormikProvider, {
12221
+ }, /*#__PURE__*/React__default.createElement("div", {
12222
+ ref: summaryRef,
12223
+ className: "contactModal__errorSummary",
12224
+ role: "alert",
12225
+ tabIndex: -1,
12226
+ style: errorStyle
12227
+ }, errorSummary.length > 0 && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("p", {
12228
+ className: "contactModal__errorSummary__title"
12229
+ }, formatMessage({
12230
+ id: 'common.form.errorSummary'
12231
+ }, {
12232
+ count: errorSummary.length
12233
+ })), /*#__PURE__*/React__default.createElement("ul", {
12234
+ className: "contactModal__errorSummary__list"
12235
+ }, errorSummary.map(function (_ref8) {
12236
+ var name = _ref8.name,
12237
+ message = _ref8.message;
12238
+ return /*#__PURE__*/React__default.createElement("li", {
12239
+ key: name
12240
+ }, /*#__PURE__*/React__default.createElement("button", {
12241
+ type: "button",
12242
+ className: "contactModal__errorSummary__link",
12243
+ onClick: function onClick() {
12244
+ return focusFormItem(name);
12245
+ }
12246
+ }, message));
12247
+ })))), /*#__PURE__*/React__default.createElement(FormikProvider, {
12154
12248
  value: formik
12155
12249
  }, template.map(function (schema) {
12156
12250
  return /*#__PURE__*/React__default.createElement(FormItem, _extends$1({
@@ -1,9 +1,13 @@
1
- export { C as default } from './ContactModal-7e5b14e8.js';
1
+ export { C as default } from './ContactModal-eaed02b8.js';
2
2
  import './_rollupPluginBabelHelpers-a52356f6.js';
3
3
  import 'react';
4
4
  import 'prop-types';
5
5
  import './hoist-non-react-statics.cjs-3f408ad2.js';
6
6
  import 'react-is';
7
+ import './defaultTheme-ed7746fe.js';
8
+ import '@material-ui/styles';
9
+ import './useTheme-d16d02d9.js';
10
+ import './withTheme-2d778133.js';
7
11
  import 'axios';
8
12
  import './Modal-e04532fa.js';
9
13
  import './index-b76a85f4.js';
@@ -14,10 +18,6 @@ import './style-inject.es-1f59c1d0.js';
14
18
  import './Spin-8f87eadc.js';
15
19
  import './globalConfig';
16
20
  import './_commonjsHelpers-70de2c37.js';
17
- import './defaultTheme-ed7746fe.js';
18
- import '@material-ui/styles';
19
- import './useTheme-d16d02d9.js';
20
- import './withTheme-2d778133.js';
21
21
  import './Select-cb3e1ba1.js';
22
22
  import './Empty-c6a44967.js';
23
23
  import './createSvgIcon-e3803ee1.js';
@@ -3,21 +3,21 @@ import React__default, { useState, useEffect } from 'react';
3
3
  import { c as classNames } from './index-b76a85f4.js';
4
4
  import PropTypes from 'prop-types';
5
5
  import axios from 'axios';
6
- import { C as ContactModal } from './ContactModal-7e5b14e8.js';
6
+ import { C as ContactModal } from './ContactModal-eaed02b8.js';
7
7
  import { S as Spin } from './Spin-8f87eadc.js';
8
8
  import { getIntl } from './globalConfig';
9
9
  import { s as styleInject } from './style-inject.es-1f59c1d0.js';
10
10
  import './hoist-non-react-statics.cjs-3f408ad2.js';
11
11
  import 'react-is';
12
+ import './defaultTheme-ed7746fe.js';
13
+ import '@material-ui/styles';
14
+ import './useTheme-d16d02d9.js';
15
+ import './withTheme-2d778133.js';
12
16
  import './Modal-e04532fa.js';
13
17
  import '@material-ui/core';
14
18
  import '@material-ui/icons';
15
19
  import './Button-7bd5aa09.js';
16
20
  import './_commonjsHelpers-70de2c37.js';
17
- import './defaultTheme-ed7746fe.js';
18
- import '@material-ui/styles';
19
- import './useTheme-d16d02d9.js';
20
- import './withTheme-2d778133.js';
21
21
  import './Select-cb3e1ba1.js';
22
22
  import './Empty-c6a44967.js';
23
23
  import './createSvgIcon-e3803ee1.js';
@@ -55,6 +55,7 @@ var zhtw = {
55
55
  "common.form.attachment.hint2": "2.若有多個檔案請先集中至同一資料夾並以壓縮檔上傳",
56
56
  "common.form.contactUs": "聯繫我們",
57
57
  "common.form.error": "表單尚未完成 請檢察必填項目",
58
+ "common.form.errorSummary": "表單有 {count} 個欄位需要修正,點選下列項目可前往該欄位:",
58
59
  "common.sna.reset": "回到原來位置與大小",
59
60
  "aria.header.searchOpen": "開啟搜尋",
60
61
  "aria.header.menuOpen": "開啟主選單",
@@ -79,6 +80,7 @@ var zhtw = {
79
80
  "aria.vcode.audioIntro": "驗證碼為:",
80
81
  "aria.vcode.audioUnsupported": "瀏覽器不支援語音合成,請刷新驗證碼或改用圖片辨識",
81
82
  "aria.vcode.refreshed": "驗證碼已更新",
83
+ "aria.vcode.hint": "請輸入圖片中的 4 個字元,英文不分大小寫;看不清楚可播放語音或刷新驗證碼",
82
84
  "aria.moreButton.loaded": "已載入更多結果",
83
85
  "aria.moreButton.collapsed": "已收合結果",
84
86
  "aria.filter.hint": "(篩選條件,選取後過濾下方結果)",
@@ -179,6 +181,7 @@ var zhcn = {
179
181
  "common.form.attachment.hint2": "2.若有多个档案请先集中至同一资料夹并以压缩档上传",
180
182
  "common.form.contactUs": "联系我们",
181
183
  "common.form.error": "表单尚未完成 请检察必填项目",
184
+ "common.form.errorSummary": "表单有 {count} 个字段需要修正,点击下列项目可前往该字段:",
182
185
  "aria.header.searchOpen": "开启搜寻",
183
186
  "aria.header.menuOpen": "开启主选单",
184
187
  "aria.header.logoHome": "回首页",
@@ -202,6 +205,7 @@ var zhcn = {
202
205
  "aria.vcode.audioIntro": "验证码为:",
203
206
  "aria.vcode.audioUnsupported": "浏览器不支持语音合成,请刷新验证码或改用图片辨识",
204
207
  "aria.vcode.refreshed": "验证码已更新",
208
+ "aria.vcode.hint": "请输入图片中的 4 个字符,英文不区分大小写;看不清楚可播放语音或刷新验证码",
205
209
  "aria.moreButton.loaded": "已载入更多结果",
206
210
  "aria.moreButton.collapsed": "已收合结果",
207
211
  "aria.filter.hint": "(筛选条件,选取后过滤下方结果)",
@@ -304,6 +308,7 @@ var enus = {
304
308
  "common.form.attachment.hint2": "2. If there are multiple files, please gather them in the same folder and upload them as compressed files",
305
309
  "common.form.contactUs": "Contact Us",
306
310
  "common.form.error": "The form has not been completed, please check the required items",
311
+ "common.form.errorSummary": "{count} field(s) need to be corrected. Select an item below to go to that field:",
307
312
  "aria.header.searchOpen": "Open search",
308
313
  "aria.header.menuOpen": "Open main menu",
309
314
  "aria.header.logoHome": "Back to home",
@@ -327,6 +332,7 @@ var enus = {
327
332
  "aria.vcode.audioIntro": "The verification code is:",
328
333
  "aria.vcode.audioUnsupported": "Speech synthesis not supported; please refresh the code",
329
334
  "aria.vcode.refreshed": "Verification code refreshed",
335
+ "aria.vcode.hint": "Enter the 4 characters shown in the image (not case-sensitive). If you cannot read them, play the audio or refresh the code.",
330
336
  "aria.moreButton.loaded": "More results loaded",
331
337
  "aria.moreButton.collapsed": "Results collapsed",
332
338
  "aria.filter.hint": " (filter, updates the results below)",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@daoyi/nmtl-ui",
3
3
  "packageManager": "pnpm@10.34.5",
4
- "version": "2.0.1-beta.130",
4
+ "version": "2.0.1-beta.131",
5
5
  "description": "This project is to be used as a starter kit for building React component using Storybook and Rollup",
6
6
  "author": "daoyi",
7
7
  "main": "lib/index.js",