@ringcentral/spring-base 1.12.0 → 1.13.0
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/config.js +32 -12
- package/contexts.js +42 -24
- package/hooks.js +1630 -613
- package/index.js +15 -17
- package/liveAnnouncer.js +303 -1
- package/package.json +2 -2
- package/src/hooks/useButton/useButton.d.ts +1 -1
- package/typings.js +7 -0
- package/utils.js +835 -81
- package/chunks/index.js +0 -234
- package/chunks/twMerge.js +0 -503
package/chunks/index.js
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
const LIVE_ANNOUNCER_ATTR = 'data-live-announcer';
|
|
2
|
-
const visuallyHiddenStyleProperties = {
|
|
3
|
-
border: '0',
|
|
4
|
-
clip: 'rect(0 0 0 0)',
|
|
5
|
-
clipPath: 'inset(50%)',
|
|
6
|
-
height: '1px',
|
|
7
|
-
margin: '-1px',
|
|
8
|
-
overflow: 'hidden',
|
|
9
|
-
padding: '0',
|
|
10
|
-
position: 'absolute',
|
|
11
|
-
width: '1px',
|
|
12
|
-
whiteSpace: 'nowrap',
|
|
13
|
-
};
|
|
14
|
-
const applyVisuallyHiddenStyles = (el) => {
|
|
15
|
-
Object.assign(el.style, visuallyHiddenStyleProperties);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
class RepeatStringText {
|
|
19
|
-
last = {};
|
|
20
|
-
usedZwsp = {
|
|
21
|
-
assertive: false,
|
|
22
|
-
polite: false,
|
|
23
|
-
};
|
|
24
|
-
next(politeness, message) {
|
|
25
|
-
const useZwsp = this.last[politeness] === message ? !this.usedZwsp[politeness] : false;
|
|
26
|
-
this.last[politeness] = message;
|
|
27
|
-
this.usedZwsp[politeness] = useZwsp;
|
|
28
|
-
return useZwsp ? `\u200B${message}` : message;
|
|
29
|
-
}
|
|
30
|
-
reset(politeness) {
|
|
31
|
-
const channels = politeness
|
|
32
|
-
? [politeness]
|
|
33
|
-
: ['assertive', 'polite'];
|
|
34
|
-
for (const channel of channels) {
|
|
35
|
-
this.last[channel] = undefined;
|
|
36
|
-
this.usedZwsp[channel] = false;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
class LiveAnnouncer {
|
|
41
|
-
node = null;
|
|
42
|
-
assertiveLog = null;
|
|
43
|
-
politeLog = null;
|
|
44
|
-
doc;
|
|
45
|
-
repeatText = new RepeatStringText();
|
|
46
|
-
ready = false;
|
|
47
|
-
pending = [];
|
|
48
|
-
firstDelayTimerId = null;
|
|
49
|
-
constructor(doc) {
|
|
50
|
-
this.doc = doc;
|
|
51
|
-
if (typeof doc === 'undefined' || !doc.body) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
this.node = doc.createElement('div');
|
|
55
|
-
this.node.setAttribute(LIVE_ANNOUNCER_ATTR, 'true');
|
|
56
|
-
applyVisuallyHiddenStyles(this.node);
|
|
57
|
-
this.assertiveLog = this.createLog('assertive');
|
|
58
|
-
this.node.appendChild(this.assertiveLog);
|
|
59
|
-
this.politeLog = this.createLog('polite');
|
|
60
|
-
this.node.appendChild(this.politeLog);
|
|
61
|
-
doc.body.prepend(this.node);
|
|
62
|
-
}
|
|
63
|
-
isAttached() {
|
|
64
|
-
return Boolean(this.node?.isConnected);
|
|
65
|
-
}
|
|
66
|
-
createLog(ariaLive) {
|
|
67
|
-
const node = this.doc.createElement('div');
|
|
68
|
-
node.setAttribute('role', 'log');
|
|
69
|
-
node.setAttribute('aria-live', ariaLive);
|
|
70
|
-
node.setAttribute('aria-relevant', 'additions');
|
|
71
|
-
return node;
|
|
72
|
-
}
|
|
73
|
-
destroy() {
|
|
74
|
-
this.cancelFirstDelay();
|
|
75
|
-
if (!this.node) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const parent = this.node.parentNode;
|
|
79
|
-
if (parent) {
|
|
80
|
-
parent.removeChild(this.node);
|
|
81
|
-
}
|
|
82
|
-
this.node = null;
|
|
83
|
-
this.assertiveLog = null;
|
|
84
|
-
this.politeLog = null;
|
|
85
|
-
this.repeatText.reset();
|
|
86
|
-
}
|
|
87
|
-
schedule(message, politeness = 'assertive', timeout = LIVEREGION_TIMEOUT_DELAY) {
|
|
88
|
-
if (this.ready || isTestAnnounceEnvironment()) {
|
|
89
|
-
this.announce(message, politeness, timeout);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
this.pending.push({ message, politeness, timeout });
|
|
93
|
-
if (this.firstDelayTimerId != null) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const win = this.doc.defaultView ?? globalThis;
|
|
97
|
-
this.firstDelayTimerId = win.setTimeout(() => {
|
|
98
|
-
this.firstDelayTimerId = null;
|
|
99
|
-
this.ready = true;
|
|
100
|
-
const queued = this.pending;
|
|
101
|
-
this.pending = [];
|
|
102
|
-
for (const item of queued) {
|
|
103
|
-
this.announce(item.message, item.politeness, item.timeout);
|
|
104
|
-
}
|
|
105
|
-
}, FIRST_ANNOUNCE_DELAY_MS);
|
|
106
|
-
}
|
|
107
|
-
announce(message, politeness = 'assertive', timeout = LIVEREGION_TIMEOUT_DELAY) {
|
|
108
|
-
if (!this.node) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
const node = this.doc.createElement('div');
|
|
112
|
-
if (typeof message === 'object') {
|
|
113
|
-
node.setAttribute('role', 'img');
|
|
114
|
-
node.setAttribute('aria-labelledby', message['aria-labelledby']);
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
node.textContent = this.repeatText.next(politeness, message);
|
|
118
|
-
}
|
|
119
|
-
if (politeness === 'assertive') {
|
|
120
|
-
this.assertiveLog?.appendChild(node);
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
this.politeLog?.appendChild(node);
|
|
124
|
-
}
|
|
125
|
-
if (message !== '') {
|
|
126
|
-
const win = this.doc.defaultView ?? globalThis;
|
|
127
|
-
win.setTimeout(() => {
|
|
128
|
-
node.remove();
|
|
129
|
-
}, timeout);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
clear(politeness) {
|
|
133
|
-
this.pending = politeness
|
|
134
|
-
? this.pending.filter((item) => item.politeness !== politeness)
|
|
135
|
-
: [];
|
|
136
|
-
if (!this.node) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if ((!politeness || politeness === 'assertive') && this.assertiveLog) {
|
|
140
|
-
this.assertiveLog.innerHTML = '';
|
|
141
|
-
this.repeatText.reset('assertive');
|
|
142
|
-
}
|
|
143
|
-
if ((!politeness || politeness === 'polite') && this.politeLog) {
|
|
144
|
-
this.politeLog.innerHTML = '';
|
|
145
|
-
this.repeatText.reset('polite');
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
cancelFirstDelay() {
|
|
149
|
-
if (this.firstDelayTimerId != null) {
|
|
150
|
-
const win = this.doc.defaultView ?? globalThis;
|
|
151
|
-
win.clearTimeout(this.firstDelayTimerId);
|
|
152
|
-
this.firstDelayTimerId = null;
|
|
153
|
-
}
|
|
154
|
-
this.pending = [];
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
const LIVEREGION_TIMEOUT_DELAY = 7000;
|
|
158
|
-
const FIRST_ANNOUNCE_DELAY_MS = 100;
|
|
159
|
-
const announcersByDocument = new WeakMap();
|
|
160
|
-
const getLiveAnnouncer = (doc) => {
|
|
161
|
-
return announcersByDocument.get(doc) ?? null;
|
|
162
|
-
};
|
|
163
|
-
const ensureLiveAnnouncer = (doc) => {
|
|
164
|
-
const existing = announcersByDocument.get(doc);
|
|
165
|
-
if (existing?.isAttached()) {
|
|
166
|
-
return existing;
|
|
167
|
-
}
|
|
168
|
-
existing?.destroy();
|
|
169
|
-
const announcer = new LiveAnnouncer(doc);
|
|
170
|
-
announcersByDocument.set(doc, announcer);
|
|
171
|
-
return announcer;
|
|
172
|
-
};
|
|
173
|
-
const clearLiveAnnouncerRegistry = (doc) => {
|
|
174
|
-
if (doc) {
|
|
175
|
-
const announcer = announcersByDocument.get(doc);
|
|
176
|
-
announcer?.destroy();
|
|
177
|
-
announcersByDocument.delete(doc);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
const isTestAnnounceEnvironment = () => {
|
|
182
|
-
const globalObj = globalThis;
|
|
183
|
-
if (typeof globalObj.IS_REACT_ACT_ENVIRONMENT === 'boolean') {
|
|
184
|
-
return globalObj.IS_REACT_ACT_ENVIRONMENT;
|
|
185
|
-
}
|
|
186
|
-
return typeof jest !== 'undefined';
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
const resolveDocument = (doc) => {
|
|
190
|
-
if (doc) {
|
|
191
|
-
return doc;
|
|
192
|
-
}
|
|
193
|
-
if (typeof document !== 'undefined') {
|
|
194
|
-
return document;
|
|
195
|
-
}
|
|
196
|
-
return undefined;
|
|
197
|
-
};
|
|
198
|
-
const resolveTimeoutAndDocument = (timeoutOrOptions) => {
|
|
199
|
-
if (typeof timeoutOrOptions === 'number') {
|
|
200
|
-
return { timeout: timeoutOrOptions };
|
|
201
|
-
}
|
|
202
|
-
if (timeoutOrOptions && typeof timeoutOrOptions === 'object') {
|
|
203
|
-
return {
|
|
204
|
-
timeout: timeoutOrOptions.timeout ?? LIVEREGION_TIMEOUT_DELAY,
|
|
205
|
-
document: timeoutOrOptions.document,
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
return { timeout: LIVEREGION_TIMEOUT_DELAY };
|
|
209
|
-
};
|
|
210
|
-
function announce(message, politeness = 'assertive', timeoutOrOptions) {
|
|
211
|
-
const { timeout, document: optionDocument } = resolveTimeoutAndDocument(timeoutOrOptions);
|
|
212
|
-
const doc = resolveDocument(optionDocument);
|
|
213
|
-
if (!doc?.body) {
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
const liveAnnouncer = ensureLiveAnnouncer(doc);
|
|
217
|
-
liveAnnouncer.schedule(message, politeness, timeout);
|
|
218
|
-
}
|
|
219
|
-
function clearAnnouncer(politeness, doc) {
|
|
220
|
-
const target = resolveDocument(doc);
|
|
221
|
-
if (!target) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
getLiveAnnouncer(target)?.clear(politeness);
|
|
225
|
-
}
|
|
226
|
-
function destroyAnnouncer(doc) {
|
|
227
|
-
const target = resolveDocument(doc);
|
|
228
|
-
if (!target) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
clearLiveAnnouncerRegistry(target);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
export { LIVEREGION_TIMEOUT_DELAY as L, announce as a, LIVE_ANNOUNCER_ATTR as b, clearAnnouncer as c, destroyAnnouncer as d, applyVisuallyHiddenStyles as e };
|