@daoyi/nmtl-ui 2.0.1-beta.122 → 2.0.1-beta.126
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,9 +1,9 @@
|
|
|
1
1
|
import { c as _objectWithoutProperties } from './_rollupPluginBabelHelpers-a52356f6.js';
|
|
2
|
-
import React__default, { useMemo } from 'react';
|
|
2
|
+
import React__default, { useMemo, useCallback } from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { c as classNames } from './index-b76a85f4.js';
|
|
5
5
|
import { q as queryString } from './index-b47819f3.js';
|
|
6
|
-
import { useHistory
|
|
6
|
+
import { useHistory } from 'react-router-dom';
|
|
7
7
|
import { Tooltip } from '@material-ui/core';
|
|
8
8
|
import { getIntl } from './globalConfig';
|
|
9
9
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
@@ -14,6 +14,21 @@ styleInject(css_248z);
|
|
|
14
14
|
var _excluded = ["className", "linkClassName", "title", "target", "disabled", "children", "tip", "onClick"];
|
|
15
15
|
var locale = '/zh-tw'; // 20230318 暫時寫死,若套件納入語系控制,可將其置換
|
|
16
16
|
|
|
17
|
+
/*
|
|
18
|
+
* ⚠️ 本元件刻意「不輸出 href 屬性」,請勿改回 <a> 或 react-router <Link>。
|
|
19
|
+
*
|
|
20
|
+
* 原因(2026-09-04 開發團隊決議,見 nmtl-web/docs/a11y/freego-scan-scope-plan-2026-09-04.md):
|
|
21
|
+
* 無障礙檢測工具 Freego 只抽取 DOM 中真實存在的 a[href]/area[href]/iframe[src]/frame[src],
|
|
22
|
+
* 且去重是完整網址字串精確比對。本元件產生的是 ?id= 明細頁連結,資料有幾筆就展開幾頁,
|
|
23
|
+
* 再乘上九個子站前綴,測試站實測達 3297 頁 / 約 24 小時。改為程式導頁後,
|
|
24
|
+
* 內容明細頁不再進入爬取佇列,只留主選單、麵包屑、網站導覽等結構性連結(仍為真 <a href>)。
|
|
25
|
+
*
|
|
26
|
+
* 可及性補償:以 role="link" 保留連結語意(非 role="button",遵循規範 03-aria-patterns §1
|
|
27
|
+
* 「導覽連結不可掛 role=button」),並自備 tabIndex 與 Enter 鍵啟動,
|
|
28
|
+
* 讀屏軟體仍會朗讀為連結、鍵盤仍可操作。焦點框由各站 a11y.scss 的
|
|
29
|
+
* [tabindex]:focus / [role='link']:focus 規則涵蓋。
|
|
30
|
+
* 已知取捨:失去中鍵/Ctrl+點擊另開分頁、右鍵複製網址等瀏覽器原生行為。
|
|
31
|
+
*/
|
|
17
32
|
var ForwardLink = function ForwardLink(_ref) {
|
|
18
33
|
var className = _ref.className,
|
|
19
34
|
linkClassName = _ref.linkClassName,
|
|
@@ -21,17 +36,17 @@ var ForwardLink = function ForwardLink(_ref) {
|
|
|
21
36
|
target = _ref.target,
|
|
22
37
|
disabled = _ref.disabled,
|
|
23
38
|
children = _ref.children,
|
|
24
|
-
tip = _ref.tip
|
|
25
|
-
_ref.onClick
|
|
26
|
-
|
|
39
|
+
tip = _ref.tip,
|
|
40
|
+
onClick = _ref.onClick,
|
|
41
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
27
42
|
var history = useHistory();
|
|
28
43
|
var _useMemo = useMemo(function () {
|
|
29
44
|
var _rest$pathname;
|
|
30
45
|
if (disabled) return {};
|
|
31
|
-
/*
|
|
32
|
-
* 若將 search 寫在 pathname 中,意即 pathname=/asd?zxc=qwe
|
|
33
|
-
* 會導致換頁時 React route dom 無法匹配 => 空白畫面
|
|
34
|
-
* 若真有此情況發生 需把 search 提領出來
|
|
46
|
+
/*
|
|
47
|
+
* 若將 search 寫在 pathname 中,意即 pathname=/asd?zxc=qwe
|
|
48
|
+
* 會導致換頁時 React route dom 無法匹配 => 空白畫面
|
|
49
|
+
* 若真有此情況發生 需把 search 提領出來
|
|
35
50
|
*/
|
|
36
51
|
var foundIndex = (_rest$pathname = rest.pathname) === null || _rest$pathname === void 0 ? void 0 : _rest$pathname.indexOf('?');
|
|
37
52
|
if (foundIndex > -1) return {
|
|
@@ -48,36 +63,65 @@ var ForwardLink = function ForwardLink(_ref) {
|
|
|
48
63
|
_useMemo$search = _useMemo.search,
|
|
49
64
|
search = _useMemo$search === void 0 ? '' : _useMemo$search;
|
|
50
65
|
|
|
66
|
+
/* 導頁:target="_blank"(預設值)沿用原本 <a target="_blank"> 的另開分頁行為,
|
|
67
|
+
其餘 target 走 SPA 換頁。history.createHref 會自動套上 Router 的 basename
|
|
68
|
+
(各站的 contextRoot),與原本 <Link> 產出的網址一致。 */
|
|
69
|
+
var go = useCallback(function () {
|
|
70
|
+
if (onClick && onClick() === false) return;
|
|
71
|
+
var to = {
|
|
72
|
+
pathname: "".concat(locale).concat(pathname),
|
|
73
|
+
search: search
|
|
74
|
+
};
|
|
75
|
+
if (target === '_blank') {
|
|
76
|
+
window.open(history.createHref(to), '_blank', 'noopener,noreferrer');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
history.push(to);
|
|
80
|
+
}, [history, onClick, target, pathname, search]);
|
|
81
|
+
|
|
82
|
+
/* role="link" 依 ARIA APG 僅以 Enter 啟動(不綁 Space,那是 role="button" 的行為) */
|
|
83
|
+
var handleKeyDown = useCallback(function (event) {
|
|
84
|
+
if (event.key === 'Enter') {
|
|
85
|
+
event.preventDefault();
|
|
86
|
+
go();
|
|
87
|
+
}
|
|
88
|
+
}, [go]);
|
|
89
|
+
|
|
51
90
|
/* WAVE: Redundant title text — title 與連結內文相同時不輸出,避免輔具重複朗讀 */
|
|
52
91
|
var domTitle = tip || typeof children === 'string' && children === title ? undefined : title;
|
|
53
92
|
/* WCAG 3.2.x 另開新視窗預告:target="_blank" 時以 aria-label 註明 */
|
|
54
93
|
var newWindowLabel = target === '_blank' && (typeof children === 'string' || title) ? "".concat(typeof children === 'string' ? children : title).concat(getIntl().formatMessage({
|
|
55
94
|
id: 'aria.newWindow'
|
|
56
95
|
})) : undefined;
|
|
57
|
-
/* R24:aria-label 已含 title 全文時不再輸出 title 屬性——NVDA 會把 title 屬性當
|
|
96
|
+
/* R24:aria-label 已含 title 全文時不再輸出 title 屬性——NVDA 會把 title 屬性當
|
|
58
97
|
description 接在 aria-label 之後再唸一次,造成「書名 ×2」(abo 首頁推薦卡實測) */
|
|
59
98
|
var linkTitle = newWindowLabel ? undefined : domTitle;
|
|
99
|
+
|
|
100
|
+
/* 沒有可及名稱的連結對所有使用者都無用,且會被判 Freego HM1240401C
|
|
101
|
+
(實測 ocean books?id=ART469770:某筆資料人名為空 → 連結內容全空)。
|
|
102
|
+
children 為空字串/空值且無 title 時,改以非互動元素呈現。 */
|
|
103
|
+
var namelessChildren = children === undefined || children === null || children === false || typeof children === 'string' && !children.trim();
|
|
104
|
+
var nameless = namelessChildren && !title;
|
|
60
105
|
var linkComponent = /*#__PURE__*/React__default.createElement("div", {
|
|
61
106
|
className: className
|
|
62
107
|
}, /*#__PURE__*/React__default.createElement("div", {
|
|
63
108
|
className: "forwardLink"
|
|
64
|
-
}, disabled ? /*#__PURE__*/React__default.createElement("div", {
|
|
109
|
+
}, disabled || nameless ? /*#__PURE__*/React__default.createElement("div", {
|
|
65
110
|
title: domTitle,
|
|
66
111
|
className: classNames('forwardLink__link--disabled', linkClassName)
|
|
67
112
|
}, children) :
|
|
68
113
|
/*#__PURE__*/
|
|
69
|
-
/* linkClassName
|
|
70
|
-
外層 className(包裹 div
|
|
114
|
+
/* linkClassName 直接掛在可聚焦元素上:消費端的 ellipsis/overflow 樣式若掛在
|
|
115
|
+
外層 className(包裹 div),會裁掉焦點框(WCAG 2.4.7 走查實測)——
|
|
71
116
|
此類樣式應改傳 linkClassName */
|
|
72
|
-
React__default.createElement(
|
|
117
|
+
React__default.createElement("span", {
|
|
118
|
+
role: "link",
|
|
119
|
+
tabIndex: 0,
|
|
73
120
|
className: classNames('forwardLink__link', linkClassName),
|
|
74
|
-
target: target,
|
|
75
121
|
title: linkTitle,
|
|
76
122
|
"aria-label": newWindowLabel,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
search: search
|
|
80
|
-
}
|
|
123
|
+
onClick: go,
|
|
124
|
+
onKeyDown: handleKeyDown
|
|
81
125
|
}, children)));
|
|
82
126
|
if (tip) {
|
|
83
127
|
return /*#__PURE__*/React__default.createElement(Tooltip, {
|
|
@@ -105,11 +149,11 @@ ForwardLink.defaultProps = {
|
|
|
105
149
|
ForwardLink.propTypes = {
|
|
106
150
|
/** Css Name(掛在外層包裹 div;帶 overflow/ellipsis 的樣式請改用 linkClassName,否則會裁掉焦點框) */
|
|
107
151
|
className: PropTypes.string,
|
|
108
|
-
/**
|
|
152
|
+
/** 直接掛在可聚焦元素上的 Css Name */
|
|
109
153
|
linkClassName: PropTypes.string,
|
|
110
154
|
/** DOM title */
|
|
111
155
|
title: PropTypes.string,
|
|
112
|
-
/**
|
|
156
|
+
/** 導頁方式:'_blank' 另開分頁(預設),其餘走 SPA 換頁 */
|
|
113
157
|
target: PropTypes.oneOf(['_self', '_blank', '_parent', '_top']),
|
|
114
158
|
/** 是否取消點擊 */
|
|
115
159
|
disabled: PropTypes.bool,
|
|
@@ -2,7 +2,7 @@ import { a as _slicedToArray } from './_rollupPluginBabelHelpers-a52356f6.js';
|
|
|
2
2
|
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
|
-
import { F as ForwardLink } from './ForwardLink-
|
|
5
|
+
import { F as ForwardLink } from './ForwardLink-fec856b3.js';
|
|
6
6
|
import { getIntl } from './globalConfig';
|
|
7
7
|
import { s as styleInject } from './style-inject.es-1f59c1d0.js';
|
|
8
8
|
import './index-b47819f3.js';
|
package/package.json
CHANGED