@daoyi/nmtl-ui 2.0.1-beta.98 → 2.0.1-beta.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/{Autocomplete-5d6f1df8.js → Autocomplete-9e392b0c.js} +5 -0
- package/lib/components/Autocomplete.js +1 -1
- package/lib/components/CollapseContent.js +2 -1
- package/lib/components/{ContactModal-c006ed2c.js → ContactModal-90b95c63.js} +57 -3
- package/lib/components/ContactModal.js +1 -1
- package/lib/components/Footer.js +40 -16
- package/lib/components/Header.js +12 -4
- package/lib/components/{KeywordSearch-33341dd3.js → KeywordSearch-d378ca7f.js} +8 -1
- package/lib/components/KeywordSearch.js +2 -2
- package/lib/components/KeywordTicker.js +38 -5
- package/lib/components/Keywords.js +29 -4
- package/lib/components/{MoreButton-44d3b4fe.js → MoreButton-692584cd.js} +55 -34
- package/lib/components/MoreButton.js +2 -1
- package/lib/components/globalConfig.js +36 -3
- package/package.json +1 -1
|
@@ -244,6 +244,7 @@ var Autocomplete = function Autocomplete(props) {
|
|
|
244
244
|
onFocus = props.onFocus,
|
|
245
245
|
onBlur = props.onBlur,
|
|
246
246
|
onEnter = props.onEnter,
|
|
247
|
+
_onKeyDown = props.onKeyDown,
|
|
247
248
|
arrowIcon = props.arrowIcon;
|
|
248
249
|
var _useState = useState(true),
|
|
249
250
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -351,6 +352,7 @@ var Autocomplete = function Autocomplete(props) {
|
|
|
351
352
|
if (result && typeof result === 'string' && reason === 'input') setCurrentResult(result);
|
|
352
353
|
},
|
|
353
354
|
onKeyDown: function onKeyDown(event) {
|
|
355
|
+
_onKeyDown(event);
|
|
354
356
|
switch (event.key) {
|
|
355
357
|
case 'ArrowDown':
|
|
356
358
|
case 'ArrowUp':
|
|
@@ -413,6 +415,7 @@ Autocomplete.defaultProps = {
|
|
|
413
415
|
onSearch: function onSearch() {},
|
|
414
416
|
onFocus: function onFocus() {},
|
|
415
417
|
onBlur: function onBlur() {},
|
|
418
|
+
onKeyDown: function onKeyDown() {},
|
|
416
419
|
onEnter: function onEnter() {},
|
|
417
420
|
arrowIcon: false,
|
|
418
421
|
ariaLabel: undefined
|
|
@@ -454,6 +457,8 @@ Autocomplete.propTypes = {
|
|
|
454
457
|
onFocus: PropTypes.func,
|
|
455
458
|
/** Input離開時的callback */
|
|
456
459
|
onBlur: PropTypes.func,
|
|
460
|
+
/** 鍵盤按下任意鍵的callback(早於內部處理) */
|
|
461
|
+
onKeyDown: PropTypes.func,
|
|
457
462
|
/** 鍵盤輸入Enter的callback */
|
|
458
463
|
onEnter: PropTypes.func,
|
|
459
464
|
/** 是否顯示arrow icon */
|
|
@@ -3,9 +3,10 @@ import React__default, { useState, useRef, useEffect } from 'react';
|
|
|
3
3
|
import { c as classNames } from './index-b76a85f4.js';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
5
|
import { Typography } from '@material-ui/core';
|
|
6
|
-
import { M as MoreButton } from './MoreButton-
|
|
6
|
+
import { M as MoreButton } from './MoreButton-692584cd.js';
|
|
7
7
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
8
8
|
import '@material-ui/icons';
|
|
9
|
+
import './globalConfig';
|
|
9
10
|
|
|
10
11
|
const HtmlToReactParser = require('html-to-react').Parser;
|
|
11
12
|
const htmlToReactParser = new HtmlToReactParser();
|
|
@@ -6,13 +6,14 @@ import axios from 'axios';
|
|
|
6
6
|
import { M as Modal } from './Modal-777fe87d.js';
|
|
7
7
|
import { c as commonjsGlobal, a as getDefaultExportFromCjs } from './_commonjsHelpers-70de2c37.js';
|
|
8
8
|
import { c as classNames } from './index-b76a85f4.js';
|
|
9
|
-
import { Input, Button, Box, Typography, FormControl, RadioGroup, FormControlLabel, Radio, TextField, TextareaAutosize } from '@material-ui/core';
|
|
9
|
+
import { Input, IconButton, Button, Box, Typography, FormControl, RadioGroup, FormControlLabel, Radio, TextField, TextareaAutosize } from '@material-ui/core';
|
|
10
10
|
import './defaultTheme-ed7746fe.js';
|
|
11
11
|
import 'react-is';
|
|
12
12
|
import '@material-ui/styles';
|
|
13
13
|
import { u as useTheme } from './useTheme-d16d02d9.js';
|
|
14
14
|
import './withTheme-2d778133.js';
|
|
15
15
|
import { S as Select } from './Select-e0790135.js';
|
|
16
|
+
import { VolumeUp } from '@material-ui/icons';
|
|
16
17
|
import { getIntl } from './globalConfig';
|
|
17
18
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
18
19
|
import { r as requireCreateSvgIcon, i as interopRequireDefault, a as interopRequireWildcard } from './createSvgIcon-e3803ee1.js';
|
|
@@ -10010,6 +10011,7 @@ const VCode = _ref => {
|
|
|
10010
10011
|
required
|
|
10011
10012
|
} = _ref;
|
|
10012
10013
|
const [codeConfig, setCodeConfig] = useState(getConfig());
|
|
10014
|
+
const [liveMessage, setLiveMessage] = useState('');
|
|
10013
10015
|
const {
|
|
10014
10016
|
data,
|
|
10015
10017
|
rotate,
|
|
@@ -10019,14 +10021,55 @@ const VCode = _ref => {
|
|
|
10019
10021
|
const refresh = () => {
|
|
10020
10022
|
canvas();
|
|
10021
10023
|
setCodeConfig(getConfig());
|
|
10024
|
+
/* WCAG 4.1.3 刷新後播報(tltc 認證模式) */
|
|
10025
|
+
setLiveMessage(getIntl().formatMessage({
|
|
10026
|
+
id: 'aria.vcode.refreshed'
|
|
10027
|
+
}));
|
|
10028
|
+
setTimeout(() => setLiveMessage(''), 3000);
|
|
10022
10029
|
};
|
|
10023
10030
|
useEffect(() => {
|
|
10024
10031
|
refresh();
|
|
10025
10032
|
}, [visible]);
|
|
10026
10033
|
const vcodeNumber = `${convert(data[0])}${convert(data[1])}${convert(data[2])}${convert(data[3])}`;
|
|
10034
|
+
|
|
10035
|
+
/* WCAG 1.1.1 驗證碼語音替代(tltc 認證模式):speechSynthesis 逐字報讀,
|
|
10036
|
+
讓無法辨識圖片的使用者取得驗證碼內容 */
|
|
10037
|
+
const speakVerificationCode = () => {
|
|
10038
|
+
if ('speechSynthesis' in window) {
|
|
10039
|
+
window.speechSynthesis.cancel();
|
|
10040
|
+
const characters = vcodeNumber.split('');
|
|
10041
|
+
let currentIndex = 0;
|
|
10042
|
+
const speakNext = () => {
|
|
10043
|
+
if (currentIndex < characters.length) {
|
|
10044
|
+
const utterance = new SpeechSynthesisUtterance(characters[currentIndex]);
|
|
10045
|
+
utterance.rate = 0.7;
|
|
10046
|
+
utterance.onend = () => {
|
|
10047
|
+
currentIndex += 1;
|
|
10048
|
+
setTimeout(speakNext, 300);
|
|
10049
|
+
};
|
|
10050
|
+
window.speechSynthesis.speak(utterance);
|
|
10051
|
+
}
|
|
10052
|
+
};
|
|
10053
|
+
const introUtterance = new SpeechSynthesisUtterance(getIntl().formatMessage({
|
|
10054
|
+
id: 'aria.vcode.audioIntro'
|
|
10055
|
+
}));
|
|
10056
|
+
introUtterance.onend = () => setTimeout(speakNext, 500);
|
|
10057
|
+
window.speechSynthesis.speak(introUtterance);
|
|
10058
|
+
} else {
|
|
10059
|
+
setLiveMessage(getIntl().formatMessage({
|
|
10060
|
+
id: 'aria.vcode.audioUnsupported'
|
|
10061
|
+
}));
|
|
10062
|
+
setTimeout(() => setLiveMessage(''), 3000);
|
|
10063
|
+
}
|
|
10064
|
+
};
|
|
10027
10065
|
return /*#__PURE__*/React__default.createElement("div", {
|
|
10028
10066
|
className: "vcode"
|
|
10029
|
-
}, /*#__PURE__*/React__default.createElement(
|
|
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, {
|
|
10030
10073
|
inputProps: {
|
|
10031
10074
|
id: inputId,
|
|
10032
10075
|
'aria-required': required || undefined
|
|
@@ -10037,7 +10080,18 @@ const VCode = _ref => {
|
|
|
10037
10080
|
onChange: e => onChange(e.target.value.toUpperCase() === vcodeNumber.toUpperCase())
|
|
10038
10081
|
}), /*#__PURE__*/React__default.createElement("div", {
|
|
10039
10082
|
className: "vcode__box"
|
|
10040
|
-
}, /*#__PURE__*/React__default.createElement(
|
|
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", {
|
|
10041
10095
|
className: "vcode__image",
|
|
10042
10096
|
role: "img",
|
|
10043
10097
|
"aria-label": getIntl().formatMessage({
|
package/lib/components/Footer.js
CHANGED
|
@@ -3,8 +3,9 @@ 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-
|
|
6
|
+
import { C as ContactModal } from './ContactModal-90b95c63.js';
|
|
7
7
|
import { S as Spin } from './Spin-8dc60bfe.js';
|
|
8
|
+
import { getIntl } from './globalConfig';
|
|
8
9
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
9
10
|
import './hoist-non-react-statics.cjs-3f408ad2.js';
|
|
10
11
|
import 'react-is';
|
|
@@ -12,7 +13,6 @@ import './Modal-777fe87d.js';
|
|
|
12
13
|
import '@material-ui/core';
|
|
13
14
|
import '@material-ui/icons';
|
|
14
15
|
import './Button-305b69a0.js';
|
|
15
|
-
import './globalConfig';
|
|
16
16
|
import './_commonjsHelpers-70de2c37.js';
|
|
17
17
|
import './defaultTheme-ed7746fe.js';
|
|
18
18
|
import '@material-ui/styles';
|
|
@@ -130,13 +130,25 @@ var Footer = function Footer(props) {
|
|
|
130
130
|
style: {
|
|
131
131
|
background: color
|
|
132
132
|
}
|
|
133
|
-
}, /*#__PURE__*/React__default.createElement(
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
}, /*#__PURE__*/React__default.createElement("span", {
|
|
134
|
+
role: "link",
|
|
135
|
+
tabIndex: 0,
|
|
136
|
+
"aria-label": getIntl().formatMessage({
|
|
137
|
+
id: 'aria.footer.nmtlLogo'
|
|
138
|
+
}),
|
|
136
139
|
onClick: function onClick() {
|
|
137
140
|
return window.open('https://www.nmtl.gov.tw/');
|
|
141
|
+
},
|
|
142
|
+
onKeyDown: function onKeyDown(event) {
|
|
143
|
+
if (event.key === 'Enter') {
|
|
144
|
+
event.preventDefault();
|
|
145
|
+
window.open('https://www.nmtl.gov.tw/');
|
|
146
|
+
}
|
|
138
147
|
}
|
|
139
|
-
}
|
|
148
|
+
}, /*#__PURE__*/React__default.createElement(NmtlLogo, {
|
|
149
|
+
className: "footer__logo",
|
|
150
|
+
color: primaryColor
|
|
151
|
+
})), /*#__PURE__*/React__default.createElement("div", {
|
|
140
152
|
className: "footer__content"
|
|
141
153
|
}, counter && /*#__PURE__*/React__default.createElement("div", {
|
|
142
154
|
className: "footer__content__item",
|
|
@@ -200,16 +212,23 @@ var Footer = function Footer(props) {
|
|
|
200
212
|
key: i.toString()
|
|
201
213
|
}, name.toUpperCase());
|
|
202
214
|
}
|
|
203
|
-
return
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
215
|
+
return (
|
|
216
|
+
/*#__PURE__*/
|
|
217
|
+
/* WCAG 3.2.2 另開新視窗需預先提示(比照 ForwardLink 模式) */
|
|
218
|
+
React__default.createElement("a", {
|
|
219
|
+
className: "footer__content__item__link",
|
|
220
|
+
style: {
|
|
221
|
+
color: primaryColor
|
|
222
|
+
},
|
|
223
|
+
href: url,
|
|
224
|
+
key: i.toString(),
|
|
225
|
+
target: "_blank",
|
|
226
|
+
rel: "noopener noreferrer",
|
|
227
|
+
"aria-label": "".concat(name.toUpperCase()).concat(getIntl().formatMessage({
|
|
228
|
+
id: 'aria.newWindow'
|
|
229
|
+
}))
|
|
230
|
+
}, name.toUpperCase())
|
|
231
|
+
);
|
|
213
232
|
}), /*#__PURE__*/React__default.createElement("div", {
|
|
214
233
|
className: "footer__content__item__link",
|
|
215
234
|
style: {
|
|
@@ -218,6 +237,11 @@ var Footer = function Footer(props) {
|
|
|
218
237
|
role: "button",
|
|
219
238
|
tabIndex: 0,
|
|
220
239
|
"aria-haspopup": "dialog",
|
|
240
|
+
"aria-label": "".concat(formatMessage({
|
|
241
|
+
id: 'common.has.problem'
|
|
242
|
+
})).concat(getIntl().formatMessage({
|
|
243
|
+
id: 'aria.opensDialog'
|
|
244
|
+
})),
|
|
221
245
|
onClick: function onClick() {
|
|
222
246
|
return setContactModalOpen(true);
|
|
223
247
|
},
|
package/lib/components/Header.js
CHANGED
|
@@ -6,7 +6,7 @@ import { d as debounce_1 } from './debounce-127da66c.js';
|
|
|
6
6
|
import { useHistory, useRouteMatch, NavLink } from 'react-router-dom';
|
|
7
7
|
import { Typography, IconButton } from '@material-ui/core';
|
|
8
8
|
import { SearchOutlined } from '@material-ui/icons';
|
|
9
|
-
import { K as KeywordSearch } from './KeywordSearch-
|
|
9
|
+
import { K as KeywordSearch } from './KeywordSearch-d378ca7f.js';
|
|
10
10
|
import { S as Select } from './Select-e0790135.js';
|
|
11
11
|
import { c as checkLanguageSupport, D as Drawer, d as defaultSupportLanguage } from './Drawer-2cbcec04.js';
|
|
12
12
|
import { getIntl } from './globalConfig';
|
|
@@ -14,7 +14,7 @@ import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
|
14
14
|
import './isObjectLike-e111475d.js';
|
|
15
15
|
import './_commonjsHelpers-70de2c37.js';
|
|
16
16
|
import 'axios';
|
|
17
|
-
import './Autocomplete-
|
|
17
|
+
import './Autocomplete-9e392b0c.js';
|
|
18
18
|
import '@material-ui/lab';
|
|
19
19
|
import './createSvgIcon-e3803ee1.js';
|
|
20
20
|
import './defaultTheme-ed7746fe.js';
|
|
@@ -124,10 +124,18 @@ var Header = function Header(props) {
|
|
|
124
124
|
className: "header__links__item",
|
|
125
125
|
color: typographyColor
|
|
126
126
|
}, name);
|
|
127
|
-
return path.indexOf('http') > -1 ?
|
|
127
|
+
return path.indexOf('http') > -1 ?
|
|
128
|
+
/*#__PURE__*/
|
|
129
|
+
/* WCAG 3.2.2 外部連結(如文學好臺誌)另開新視窗需預先提示 */
|
|
130
|
+
React__default.createElement("a", {
|
|
128
131
|
key: i.toString(),
|
|
129
132
|
href: path,
|
|
130
|
-
className: "header__links__item--active"
|
|
133
|
+
className: "header__links__item--active",
|
|
134
|
+
target: "_blank",
|
|
135
|
+
rel: "noopener noreferrer",
|
|
136
|
+
"aria-label": "".concat(name).concat(getIntl().formatMessage({
|
|
137
|
+
id: 'aria.newWindow'
|
|
138
|
+
}))
|
|
131
139
|
}, label) : /*#__PURE__*/React__default.createElement(NavLink, {
|
|
132
140
|
key: i.toString(),
|
|
133
141
|
to: "".concat(url).concat(path),
|
|
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
|
|
4
4
|
import { c as classNames } from './index-b76a85f4.js';
|
|
5
5
|
import axios from 'axios';
|
|
6
6
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
7
|
-
import { A as Autocomplete } from './Autocomplete-
|
|
7
|
+
import { A as Autocomplete } from './Autocomplete-9e392b0c.js';
|
|
8
8
|
|
|
9
9
|
var css_248z = ".keywordSearch {\n border-radius: 4px;\n width: 100%;\n margin-right: 14px;\n}\n.keywordSearch--animation .autocomplete {\n transition: max-width 0.3s ease-out;\n max-width: 240px;\n}\n.keywordSearch--focus {\n flex: 1;\n}\n.keywordSearch--focus .autocomplete {\n max-width: 100%;\n}\n.keywordSearch .MuiAutocomplete-hasPopupIcon.MuiAutocomplete-hasClearIcon .MuiAutocomplete-inputRoot[class*=MuiOutlinedInput-root] {\n border-radius: 10px;\n background-color: #ffffff66;\n}";
|
|
10
10
|
styleInject(css_248z);
|
|
@@ -106,6 +106,13 @@ var KeywordSearch = function KeywordSearch(_ref) {
|
|
|
106
106
|
},
|
|
107
107
|
onBlur: function onBlur() {
|
|
108
108
|
return setMenuOpen(false);
|
|
109
|
+
},
|
|
110
|
+
onKeyDown: function onKeyDown(event) {
|
|
111
|
+
/* WCAG 2.1.1:搜尋框聚焦時 header--focus 會 display:none 隱藏導覽連結,
|
|
112
|
+
瀏覽器在 keydown 當下就決定 Tab 的下一個焦點目標——若等 blur 才收合,
|
|
113
|
+
導覽連結永遠不在焦點順序中。改在 Tab 按下時同步收合(React 事件結尾
|
|
114
|
+
同步 re-render,早於瀏覽器預設移焦),讓導覽連結恢復可聚焦。 */
|
|
115
|
+
if (event.key === 'Tab') setMenuOpen(false);
|
|
109
116
|
}
|
|
110
117
|
}));
|
|
111
118
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { K as default } from './KeywordSearch-
|
|
1
|
+
export { K as default } from './KeywordSearch-d378ca7f.js';
|
|
2
2
|
import './_rollupPluginBabelHelpers-a52356f6.js';
|
|
3
3
|
import 'react';
|
|
4
4
|
import 'prop-types';
|
|
5
5
|
import './index-b76a85f4.js';
|
|
6
6
|
import 'axios';
|
|
7
7
|
import './style-inject.es-1f59c1d0.js';
|
|
8
|
-
import './Autocomplete-
|
|
8
|
+
import './Autocomplete-9e392b0c.js';
|
|
9
9
|
import './debounce-127da66c.js';
|
|
10
10
|
import './isObjectLike-e111475d.js';
|
|
11
11
|
import './_commonjsHelpers-70de2c37.js';
|
|
@@ -3,13 +3,13 @@ import React__default, { useState, useRef, useEffect } from 'react';
|
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { c as classNames } from './index-b76a85f4.js';
|
|
5
5
|
import { F as ForwardLink } from './ForwardLink-83a7eea9.js';
|
|
6
|
+
import { getIntl } from './globalConfig';
|
|
6
7
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
7
8
|
import './index-b47819f3.js';
|
|
8
9
|
import 'react-router-dom';
|
|
9
10
|
import '@material-ui/core';
|
|
10
|
-
import './globalConfig';
|
|
11
11
|
|
|
12
|
-
var css_248z = ".keywordTicker {\n width: 100%;\n display: flex;\n justify-content: flex-start;\n align-items: center;\n}\n.keywordTicker__track {\n display: flex;\n width: 100%;\n padding: 20px 0px;\n background-color: #ece8c0;\n overflow: hidden;\n margin-left: -80px;\n padding-left: 100px;\n z-index: 1;\n position: relative;\n}\n.keywordTicker__items {\n display: flex;\n justify-content: flex-start;\n align-items: center;\n flex-wrap: nowrap;\n position: relative;\n}\n.keywordTicker-item {\n width: auto;\n display: flex;\n justify-content: center;\n align-items: center;\n white-space: nowrap;\n cursor: pointer;\n}\n.keywordTicker-text {\n font-size: 1.5rem;\n z-index: 2;\n font-weight: bold;\n color: #825c0d;\n border-left: 2px solid #fff;\n padding: 0px 40px;\n}\n.keywordTicker__img {\n z-index: 2;\n position: relative;\n display: flex;\n}\n.keywordTicker__img img {\n height: 100%;\n max-height: 195px;\n image-rendering: -webkit-optimize-contrast;\n position: relative;\n}\n.keywordTicker--fake {\n position: absolute;\n opacity: 0;\n width: 100%;\n}\n\n@media only screen and (max-width: 768px) {\n .keywordTicker-text {\n font-size: 1.5rem;\n padding: 0px 15px;\n }\n .keywordTicker__img img {\n max-height: 104px;\n left: -60px;\n }\n .keywordTicker__track {\n padding: 10px 0px;\n margin-left: -100px;\n }\n}\n@media only screen and (max-width: 484px) {\n .keywordTicker-text {\n font-size: 14px;\n }\n}";
|
|
12
|
+
var css_248z = ".keywordTicker {\n width: 100%;\n display: flex;\n justify-content: flex-start;\n align-items: center;\n position: relative;\n}\n.keywordTicker__playToggle {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 3;\n padding: 4px 12px;\n background: rgba(0, 0, 0, 0.75);\n color: #fff;\n border: 1px solid #fff;\n border-radius: 4px;\n font-size: 1rem;\n cursor: pointer;\n}\n.keywordTicker__track {\n display: flex;\n width: 100%;\n padding: 20px 0px;\n background-color: #ece8c0;\n overflow: hidden;\n margin-left: -80px;\n padding-left: 100px;\n z-index: 1;\n position: relative;\n}\n.keywordTicker__items {\n display: flex;\n justify-content: flex-start;\n align-items: center;\n flex-wrap: nowrap;\n position: relative;\n}\n.keywordTicker-item {\n width: auto;\n display: flex;\n justify-content: center;\n align-items: center;\n white-space: nowrap;\n cursor: pointer;\n}\n.keywordTicker-text {\n font-size: 1.5rem;\n z-index: 2;\n font-weight: bold;\n color: #825c0d;\n border-left: 2px solid #fff;\n padding: 0px 40px;\n}\n.keywordTicker__img {\n z-index: 2;\n position: relative;\n display: flex;\n}\n.keywordTicker__img img {\n height: 100%;\n max-height: 195px;\n image-rendering: -webkit-optimize-contrast;\n position: relative;\n}\n.keywordTicker--fake {\n position: absolute;\n opacity: 0;\n width: 100%;\n}\n\n@media only screen and (max-width: 768px) {\n .keywordTicker-text {\n font-size: 1.5rem;\n padding: 0px 15px;\n }\n .keywordTicker__img img {\n max-height: 104px;\n left: -60px;\n }\n .keywordTicker__track {\n padding: 10px 0px;\n margin-left: -100px;\n }\n}\n@media only screen and (max-width: 484px) {\n .keywordTicker-text {\n font-size: 14px;\n }\n}";
|
|
13
13
|
styleInject(css_248z);
|
|
14
14
|
|
|
15
15
|
var KeywordTicker = function KeywordTicker(_ref) {
|
|
@@ -23,6 +23,11 @@ var KeywordTicker = function KeywordTicker(_ref) {
|
|
|
23
23
|
_useState2 = _slicedToArray(_useState, 2),
|
|
24
24
|
tracking = _useState2[0],
|
|
25
25
|
setTracking = _useState2[1];
|
|
26
|
+
/* WCAG 2.2.2 自動移動內容需提供暫停控制;並尊重「減少動態效果」偏好預設暫停(WCAG 2.3.3) */
|
|
27
|
+
var _useState3 = useState(typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches),
|
|
28
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
29
|
+
paused = _useState4[0],
|
|
30
|
+
setPaused = _useState4[1];
|
|
26
31
|
var _ref2 = tickerAttribute || {
|
|
27
32
|
result: [],
|
|
28
33
|
mounted: false,
|
|
@@ -121,24 +126,52 @@ var KeywordTicker = function KeywordTicker(_ref) {
|
|
|
121
126
|
setTracking(initTracking);
|
|
122
127
|
}
|
|
123
128
|
}, [mounted, step]);
|
|
129
|
+
|
|
130
|
+
/* 暫停狀態同步到動畫(含 prefers-reduced-motion 預設暫停) */
|
|
131
|
+
useEffect(function () {
|
|
132
|
+
if (!tracking) return;
|
|
133
|
+
if (paused) tracking.pause();else tracking.play();
|
|
134
|
+
}, [tracking, paused]);
|
|
135
|
+
|
|
136
|
+
/* WCAG 2.1.1/2.4.7 跑馬燈連結為無限輪播重複複製且持續移動,鍵盤逐一 Tab 體驗惡劣:
|
|
137
|
+
本體標記 aria-hidden 並將內部連結移出 Tab 順序(消費端另以等效清單提供鍵盤操作)。
|
|
138
|
+
跑馬燈重渲染後需重設。 */
|
|
139
|
+
useEffect(function () {
|
|
140
|
+
if (track.current) {
|
|
141
|
+
track.current.querySelectorAll('a').forEach(function (a) {
|
|
142
|
+
return a.setAttribute('tabindex', '-1');
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}, [result]);
|
|
124
146
|
return /*#__PURE__*/React__default.createElement("div", {
|
|
125
147
|
className: classNames('keywordTicker', className)
|
|
126
|
-
},
|
|
148
|
+
}, /*#__PURE__*/React__default.createElement("button", {
|
|
149
|
+
type: "button",
|
|
150
|
+
className: "keywordTicker__playToggle",
|
|
151
|
+
"aria-pressed": paused,
|
|
152
|
+
onClick: function onClick() {
|
|
153
|
+
return setPaused(!paused);
|
|
154
|
+
}
|
|
155
|
+
}, getIntl().formatMessage({
|
|
156
|
+
id: paused ? 'aria.ticker.play' : 'aria.ticker.pause'
|
|
157
|
+
})), leftImg && /*#__PURE__*/React__default.createElement("div", {
|
|
127
158
|
className: "keywordTicker__img"
|
|
128
159
|
}, /*#__PURE__*/React__default.createElement("img", {
|
|
129
160
|
src: leftImg,
|
|
130
|
-
alt: "
|
|
161
|
+
alt: "",
|
|
162
|
+
"aria-hidden": "true"
|
|
131
163
|
})), /*#__PURE__*/React__default.createElement("div", {
|
|
132
164
|
className: "keywordTicker__track",
|
|
133
165
|
ref: track,
|
|
134
166
|
style: {
|
|
135
167
|
backgroundColor: backgroundColor
|
|
136
168
|
},
|
|
169
|
+
"aria-hidden": "true",
|
|
137
170
|
onMouseEnter: function onMouseEnter() {
|
|
138
171
|
return tracking === null || tracking === void 0 ? void 0 : tracking.pause();
|
|
139
172
|
},
|
|
140
173
|
onMouseLeave: function onMouseLeave() {
|
|
141
|
-
|
|
174
|
+
if (!paused && tracking) tracking.play();
|
|
142
175
|
}
|
|
143
176
|
}, /*#__PURE__*/React__default.createElement("div", {
|
|
144
177
|
className: "keywordTicker__items",
|
|
@@ -5,11 +5,11 @@ import { c as classNames } from './index-b76a85f4.js';
|
|
|
5
5
|
import { M as Modal } from './Modal-777fe87d.js';
|
|
6
6
|
import { Typography } from '@material-ui/core';
|
|
7
7
|
import { r as requireCreateSvgIcon, i as interopRequireDefault, a as interopRequireWildcard } from './createSvgIcon-e3803ee1.js';
|
|
8
|
+
import { getIntl } from './globalConfig';
|
|
8
9
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
9
10
|
import '@material-ui/icons';
|
|
10
11
|
import './Button-305b69a0.js';
|
|
11
12
|
import './Spin-8dc60bfe.js';
|
|
12
|
-
import './globalConfig';
|
|
13
13
|
import './_commonjsHelpers-70de2c37.js';
|
|
14
14
|
import './defaultTheme-ed7746fe.js';
|
|
15
15
|
import 'react-is';
|
|
@@ -71,7 +71,18 @@ const KeywordList = _ref => {
|
|
|
71
71
|
color: "textSecondary",
|
|
72
72
|
className: "keywordList__item",
|
|
73
73
|
key: i.toString(),
|
|
74
|
-
|
|
74
|
+
role: "button",
|
|
75
|
+
tabIndex: 0,
|
|
76
|
+
"aria-label": `${keyword}${getIntl().formatMessage({
|
|
77
|
+
id: 'aria.keyword.searchHint'
|
|
78
|
+
})}`,
|
|
79
|
+
onClick: () => onKeywordClick(keyword),
|
|
80
|
+
onKeyDown: event => {
|
|
81
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
onKeywordClick(keyword);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
75
86
|
}, /*#__PURE__*/React__default.createElement("div", {
|
|
76
87
|
style: {
|
|
77
88
|
color: textColor,
|
|
@@ -83,13 +94,27 @@ const KeywordList = _ref => {
|
|
|
83
94
|
style: {
|
|
84
95
|
backgroundColor
|
|
85
96
|
},
|
|
86
|
-
|
|
97
|
+
role: "button",
|
|
98
|
+
tabIndex: 0,
|
|
99
|
+
"aria-haspopup": "dialog",
|
|
100
|
+
"aria-label": getIntl().formatMessage({
|
|
101
|
+
id: 'aria.keyword.more'
|
|
102
|
+
}),
|
|
103
|
+
onClick: onMoreClick,
|
|
104
|
+
onKeyDown: event => {
|
|
105
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
onMoreClick();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
87
110
|
}, /*#__PURE__*/React__default.createElement("div", {
|
|
88
111
|
className: "keywordList__item__hover",
|
|
89
112
|
style: {
|
|
90
113
|
color: textColor
|
|
91
114
|
}
|
|
92
|
-
}, /*#__PURE__*/React__default.createElement(default_1,
|
|
115
|
+
}, /*#__PURE__*/React__default.createElement(default_1, {
|
|
116
|
+
"aria-hidden": "true"
|
|
117
|
+
}))));
|
|
93
118
|
};
|
|
94
119
|
KeywordList.defaultProps = {
|
|
95
120
|
className: undefined,
|
|
@@ -2,6 +2,7 @@ import React__default from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { c as classNames } from './index-b76a85f4.js';
|
|
4
4
|
import { ExpandLess, ExpandMore } from '@material-ui/icons';
|
|
5
|
+
import { getIntl } from './globalConfig';
|
|
5
6
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
6
7
|
|
|
7
8
|
var css_248z = ".moreButton {\n width: -moz-fit-content;\n width: fit-content;\n display: flex;\n align-items: center;\n position: relative;\n margin: 1rem 0rem;\n border-radius: 8px;\n padding: 1rem 2.5rem;\n -webkit-user-select: none;\n user-select: none;\n cursor: pointer;\n}\n.moreButton__mask {\n transition: all 0.3s ease-in-out;\n position: absolute;\n left: 0;\n top: 0;\n border-radius: 8px;\n width: 100%;\n height: 100%;\n opacity: 0;\n}\n.moreButton:hover .moreButton__mask {\n opacity: 1;\n}\n.moreButton--shadow {\n transition: all 0.3s ease-in-out;\n border: 3px solid #ffffff;\n position: relative;\n left: 0px;\n top: 0px;\n}\n.moreButton--shadow:hover {\n box-shadow: initial !important;\n left: 3px;\n top: 3px;\n}\n.moreButton--small {\n border: 0;\n padding: 0;\n left: 0px !important;\n top: 0px !important;\n background: transparent !important;\n box-shadow: initial !important;\n}\n.moreButton--small .moreButton__mask {\n opacity: 0 !important;\n}\n.moreButton__icon {\n display: flex;\n z-index: 1;\n}\n.moreButton__icon--small {\n font-size: 1.5rem;\n border-radius: 45px;\n color: white !important;\n}\n.moreButton__text {\n z-index: 1;\n font-size: 1.5rem;\n line-height: 1.5rem;\n transition: color 0.3s ease-in-out;\n}\n.moreButton__text--small {\n margin-left: 0.75rem;\n font-size: 1.5rem;\n color: #0c2a4d;\n}\n.moreButton__text--small:hover {\n text-decoration: underline;\n}";
|
|
@@ -16,7 +17,7 @@ var MoreButton = function MoreButton(props) {
|
|
|
16
17
|
customExpandIcon = props.customExpandIcon;
|
|
17
18
|
var expand = props.expand,
|
|
18
19
|
setExpand = props.setExpand,
|
|
19
|
-
|
|
20
|
+
onClick = props.onClick,
|
|
20
21
|
formatMessage = props.formatMessage;
|
|
21
22
|
var smallIcon = expand ? /*#__PURE__*/React__default.createElement(ExpandLess, {
|
|
22
23
|
className: "moreButton__icon--small",
|
|
@@ -33,42 +34,62 @@ var MoreButton = function MoreButton(props) {
|
|
|
33
34
|
var message = small ? smallMessage : 'common.watch.more';
|
|
34
35
|
var largeIcon = customExpandIcon && /*#__PURE__*/React__default.createElement("img", {
|
|
35
36
|
src: customExpandIcon,
|
|
36
|
-
alt: "
|
|
37
|
+
alt: "",
|
|
38
|
+
"aria-hidden": "true"
|
|
37
39
|
});
|
|
38
40
|
var icon = small ? smallIcon : largeIcon;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}),
|
|
45
|
-
style: {
|
|
46
|
-
color: shadowColor || 'white',
|
|
47
|
-
background: primaryColor,
|
|
48
|
-
boxShadow: enableShadow ? "3px 3px 0 0 ".concat(shadowColor) : undefined
|
|
49
|
-
},
|
|
50
|
-
onClick: function onClick() {
|
|
51
|
-
setExpand(!expand);
|
|
52
|
-
_onClick();
|
|
53
|
-
}
|
|
54
|
-
}, !enableShadow && /*#__PURE__*/React__default.createElement("div", {
|
|
55
|
-
className: "moreButton__mask",
|
|
56
|
-
style: {
|
|
57
|
-
background: secondaryColor
|
|
58
|
-
}
|
|
59
|
-
}), /*#__PURE__*/React__default.createElement("div", {
|
|
60
|
-
className: "moreButton__icon"
|
|
61
|
-
}, icon), /*#__PURE__*/React__default.createElement("div", {
|
|
62
|
-
className: classNames('moreButton__text', {
|
|
63
|
-
'moreButton__text--small': small
|
|
64
|
-
}),
|
|
65
|
-
style: {
|
|
66
|
-
color: small ? shadowColor || primaryColor : undefined,
|
|
67
|
-
marginLeft: icon ? '0.5rem' : undefined
|
|
68
|
-
}
|
|
69
|
-
}, formatMessage ? formatMessage({
|
|
41
|
+
var handleAction = function handleAction() {
|
|
42
|
+
setExpand(!expand);
|
|
43
|
+
onClick();
|
|
44
|
+
};
|
|
45
|
+
var messageText = formatMessage ? formatMessage({
|
|
70
46
|
id: message
|
|
71
|
-
}) : message
|
|
47
|
+
}) : message;
|
|
48
|
+
return (
|
|
49
|
+
/*#__PURE__*/
|
|
50
|
+
/* WCAG 2.1.1/4.1.2 看更多為互動元件:role="button" + tabIndex + 鍵盤操作,
|
|
51
|
+
報讀補「點選後載入更多結果」預先提示、aria-expanded 表達展開狀態 */
|
|
52
|
+
React__default.createElement("div", {
|
|
53
|
+
className: classNames('moreButton', {
|
|
54
|
+
'moreButton--shadow': enableShadow
|
|
55
|
+
}, {
|
|
56
|
+
'moreButton--small': small
|
|
57
|
+
}),
|
|
58
|
+
role: "button",
|
|
59
|
+
tabIndex: 0,
|
|
60
|
+
"aria-expanded": expand,
|
|
61
|
+
"aria-label": "".concat(messageText).concat(getIntl().formatMessage({
|
|
62
|
+
id: 'aria.moreButton.hint'
|
|
63
|
+
})),
|
|
64
|
+
style: {
|
|
65
|
+
color: shadowColor || 'white',
|
|
66
|
+
background: primaryColor,
|
|
67
|
+
boxShadow: enableShadow ? "3px 3px 0 0 ".concat(shadowColor) : undefined
|
|
68
|
+
},
|
|
69
|
+
onClick: handleAction,
|
|
70
|
+
onKeyDown: function onKeyDown(event) {
|
|
71
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
handleAction();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}, !enableShadow && /*#__PURE__*/React__default.createElement("div", {
|
|
77
|
+
className: "moreButton__mask",
|
|
78
|
+
style: {
|
|
79
|
+
background: secondaryColor
|
|
80
|
+
}
|
|
81
|
+
}), /*#__PURE__*/React__default.createElement("div", {
|
|
82
|
+
className: "moreButton__icon"
|
|
83
|
+
}, icon), /*#__PURE__*/React__default.createElement("div", {
|
|
84
|
+
className: classNames('moreButton__text', {
|
|
85
|
+
'moreButton__text--small': small
|
|
86
|
+
}),
|
|
87
|
+
style: {
|
|
88
|
+
color: small ? shadowColor || primaryColor : undefined,
|
|
89
|
+
marginLeft: icon ? '0.5rem' : undefined
|
|
90
|
+
}
|
|
91
|
+
}, messageText))
|
|
92
|
+
);
|
|
72
93
|
};
|
|
73
94
|
MoreButton.defaultProps = {
|
|
74
95
|
primaryColor: '#271702',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { M as default } from './MoreButton-
|
|
1
|
+
export { M as default } from './MoreButton-692584cd.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
import 'prop-types';
|
|
4
4
|
import './index-b76a85f4.js';
|
|
5
5
|
import '@material-ui/icons';
|
|
6
|
+
import './globalConfig';
|
|
6
7
|
import './style-inject.es-1f59c1d0.js';
|
|
@@ -63,7 +63,18 @@ var zhtw = {
|
|
|
63
63
|
"aria.modal.close": "關閉視窗",
|
|
64
64
|
"aria.newWindow": "(另開新視窗)",
|
|
65
65
|
"aria.vcode.image": "驗證碼圖片,如無法辨識可刷新驗證碼",
|
|
66
|
-
"aria.vcode.refresh": "刷新驗證碼"
|
|
66
|
+
"aria.vcode.refresh": "刷新驗證碼",
|
|
67
|
+
"aria.footer.nmtlLogo": "國立臺灣文學館(另開新視窗)",
|
|
68
|
+
"aria.opensDialog": "(開啟對話框)",
|
|
69
|
+
"aria.ticker.pause": "暫停關鍵字跑馬燈",
|
|
70
|
+
"aria.ticker.play": "播放關鍵字跑馬燈",
|
|
71
|
+
"aria.moreButton.hint": "(點選後載入更多結果)",
|
|
72
|
+
"aria.keyword.searchHint": "(關鍵字,點選後顯示相關作品)",
|
|
73
|
+
"aria.keyword.more": "顯示更多關鍵字(開啟對話框)",
|
|
74
|
+
"aria.vcode.audioPlay": "播放驗證碼語音",
|
|
75
|
+
"aria.vcode.audioIntro": "驗證碼為:",
|
|
76
|
+
"aria.vcode.audioUnsupported": "瀏覽器不支援語音合成,請刷新驗證碼或改用圖片辨識",
|
|
77
|
+
"aria.vcode.refreshed": "驗證碼已更新"
|
|
67
78
|
};
|
|
68
79
|
|
|
69
80
|
var zhcn = {
|
|
@@ -115,7 +126,18 @@ var zhcn = {
|
|
|
115
126
|
"aria.modal.close": "关闭视窗",
|
|
116
127
|
"aria.newWindow": "(另开新视窗)",
|
|
117
128
|
"aria.vcode.image": "验证码图片,如无法辨识可刷新验证码",
|
|
118
|
-
"aria.vcode.refresh": "刷新验证码"
|
|
129
|
+
"aria.vcode.refresh": "刷新验证码",
|
|
130
|
+
"aria.footer.nmtlLogo": "国立台湾文学馆(另开新窗口)",
|
|
131
|
+
"aria.opensDialog": "(开启对话框)",
|
|
132
|
+
"aria.ticker.pause": "暂停关键字跑马灯",
|
|
133
|
+
"aria.ticker.play": "播放关键字跑马灯",
|
|
134
|
+
"aria.moreButton.hint": "(点选后载入更多结果)",
|
|
135
|
+
"aria.keyword.searchHint": "(关键字,点选后显示相关作品)",
|
|
136
|
+
"aria.keyword.more": "显示更多关键字(开启对话框)",
|
|
137
|
+
"aria.vcode.audioPlay": "播放验证码语音",
|
|
138
|
+
"aria.vcode.audioIntro": "验证码为:",
|
|
139
|
+
"aria.vcode.audioUnsupported": "浏览器不支持语音合成,请刷新验证码或改用图片辨识",
|
|
140
|
+
"aria.vcode.refreshed": "验证码已更新"
|
|
119
141
|
};
|
|
120
142
|
|
|
121
143
|
var enus = {
|
|
@@ -167,7 +189,18 @@ var enus = {
|
|
|
167
189
|
"aria.modal.close": "Close dialog",
|
|
168
190
|
"aria.newWindow": " (opens in new window)",
|
|
169
191
|
"aria.vcode.image": "CAPTCHA image, refresh if unreadable",
|
|
170
|
-
"aria.vcode.refresh": "Refresh CAPTCHA"
|
|
192
|
+
"aria.vcode.refresh": "Refresh CAPTCHA",
|
|
193
|
+
"aria.footer.nmtlLogo": "National Museum of Taiwan Literature (opens in new window)",
|
|
194
|
+
"aria.opensDialog": " (opens a dialog)",
|
|
195
|
+
"aria.ticker.pause": "Pause keyword ticker",
|
|
196
|
+
"aria.ticker.play": "Play keyword ticker",
|
|
197
|
+
"aria.moreButton.hint": " (click to load more results)",
|
|
198
|
+
"aria.keyword.searchHint": " (keyword, click to show related works)",
|
|
199
|
+
"aria.keyword.more": "Show more keywords (opens a dialog)",
|
|
200
|
+
"aria.vcode.audioPlay": "Play verification code audio",
|
|
201
|
+
"aria.vcode.audioIntro": "The verification code is:",
|
|
202
|
+
"aria.vcode.audioUnsupported": "Speech synthesis not supported; please refresh the code",
|
|
203
|
+
"aria.vcode.refreshed": "Verification code refreshed"
|
|
171
204
|
};
|
|
172
205
|
|
|
173
206
|
var _languages;
|
package/package.json
CHANGED