@planningcenter/topbar 12.5.0-rc.3 → 12.5.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/dist/topbar.js +69 -18
- package/dist/topbar.js.map +1 -1
- package/dist/topbar.modern.js +69 -18
- package/dist/topbar.modern.js.map +1 -1
- package/dist/topbar.module.js +69 -18
- package/dist/topbar.module.js.map +1 -1
- package/dist/topbar.umd.js +69 -18
- package/dist/topbar.umd.js.map +1 -1
- package/package.json +3 -4
package/dist/topbar.umd.js
CHANGED
|
@@ -3346,6 +3346,25 @@ true;
|
|
|
3346
3346
|
}));
|
|
3347
3347
|
}
|
|
3348
3348
|
|
|
3349
|
+
// With the search's own debounce, about 1.4 seconds after the last keystroke,
|
|
3350
|
+
// as in GOV.UK's accessible-autocomplete.
|
|
3351
|
+
const ANNOUNCEMENT_DELAY_MS = 1100;
|
|
3352
|
+
// Screen readers echo typing themselves, as each person has set them to, so
|
|
3353
|
+
// the message waits until typing settles instead of talking over it. Waiting
|
|
3354
|
+
// also lets VoiceOver finish what focus had to say, since it often skips a
|
|
3355
|
+
// change made as focus moves, as when a tab with cached results is selected,
|
|
3356
|
+
// and only the tab someone stops on when arrowing through them is announced.
|
|
3357
|
+
// The region empties at once, so a message that comes back is read again.
|
|
3358
|
+
function useAnnouncement(message) {
|
|
3359
|
+
const [announcement, setAnnouncement] = React.useState(null);
|
|
3360
|
+
React.useEffect(() => {
|
|
3361
|
+
setAnnouncement(null);
|
|
3362
|
+
const timeout = setTimeout(() => setAnnouncement(message), ANNOUNCEMENT_DELAY_MS);
|
|
3363
|
+
return () => clearTimeout(timeout);
|
|
3364
|
+
}, [message]);
|
|
3365
|
+
return announcement;
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3349
3368
|
// useId isn't available on React 17, which our peer range still supports.
|
|
3350
3369
|
let instanceCount$1 = 0;
|
|
3351
3370
|
function useInstanceId(prefix) {
|
|
@@ -4095,7 +4114,18 @@ true;
|
|
|
4095
4114
|
return undefined;
|
|
4096
4115
|
}
|
|
4097
4116
|
}
|
|
4098
|
-
|
|
4117
|
+
const minting = new Map();
|
|
4118
|
+
function mintToken(personId) {
|
|
4119
|
+
const running = minting.get(personId);
|
|
4120
|
+
if (running) {
|
|
4121
|
+
return running;
|
|
4122
|
+
} else {
|
|
4123
|
+
const run = mint(personId).finally(() => minting.delete(personId));
|
|
4124
|
+
minting.set(personId, run);
|
|
4125
|
+
return run;
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
async function mint(personId) {
|
|
4099
4129
|
const {
|
|
4100
4130
|
json,
|
|
4101
4131
|
ok,
|
|
@@ -4119,6 +4149,10 @@ true;
|
|
|
4119
4149
|
}
|
|
4120
4150
|
return token;
|
|
4121
4151
|
}
|
|
4152
|
+
function currentToken(personId) {
|
|
4153
|
+
var _a;
|
|
4154
|
+
return (_a = cachedToken(personId)) !== null && _a !== void 0 ? _a : mintToken(personId).catch(() => null);
|
|
4155
|
+
}
|
|
4122
4156
|
async function request(personId, key, init = {}, isRetry = false) {
|
|
4123
4157
|
var _a;
|
|
4124
4158
|
const token = isRetry ? await mintToken(personId) : (_a = cachedToken(personId)) !== null && _a !== void 0 ? _a : await mintToken(personId);
|
|
@@ -4154,8 +4188,8 @@ true;
|
|
|
4154
4188
|
// retrying when another tab or device wrote in between. `change` returns null
|
|
4155
4189
|
// when there's nothing to write. A read-only token (staff impersonating
|
|
4156
4190
|
// someone) only reads, so nothing is written into the person's history.
|
|
4157
|
-
// Resolves to the value now stored,
|
|
4158
|
-
// reached.
|
|
4191
|
+
// Resolves to the value now stored, with whether the token was read-only, or
|
|
4192
|
+
// null when the service couldn't be reached.
|
|
4159
4193
|
async function updateStoredValue(personId, key, change, attemptsLeft = MAX_ATTEMPTS) {
|
|
4160
4194
|
const read = await request(personId, key);
|
|
4161
4195
|
if (read === null || read === void 0 ? void 0 : read.response.ok) {
|
|
@@ -4163,9 +4197,15 @@ true;
|
|
|
4163
4197
|
value,
|
|
4164
4198
|
version
|
|
4165
4199
|
} = await read.response.json();
|
|
4166
|
-
const
|
|
4200
|
+
const {
|
|
4201
|
+
readOnly
|
|
4202
|
+
} = read.token;
|
|
4203
|
+
const next = readOnly ? null : change(value);
|
|
4167
4204
|
if (next === null) {
|
|
4168
|
-
return
|
|
4205
|
+
return {
|
|
4206
|
+
readOnly,
|
|
4207
|
+
value: Array.isArray(value) ? value : []
|
|
4208
|
+
};
|
|
4169
4209
|
} else {
|
|
4170
4210
|
const write = await request(personId, key, {
|
|
4171
4211
|
body: JSON.stringify({
|
|
@@ -4178,7 +4218,10 @@ true;
|
|
|
4178
4218
|
method: "PUT"
|
|
4179
4219
|
});
|
|
4180
4220
|
if (write === null || write === void 0 ? void 0 : write.response.ok) {
|
|
4181
|
-
return
|
|
4221
|
+
return {
|
|
4222
|
+
readOnly,
|
|
4223
|
+
value: next
|
|
4224
|
+
};
|
|
4182
4225
|
} else if ((write === null || write === void 0 ? void 0 : write.response.status) === 409 && attemptsLeft > 1) {
|
|
4183
4226
|
return updateStoredValue(personId, key, change, attemptsLeft - 1);
|
|
4184
4227
|
} else {
|
|
@@ -4230,7 +4273,8 @@ true;
|
|
|
4230
4273
|
return isSameList(mergeEntries(shared, local), shared) ? null : mergeStored(stored, local);
|
|
4231
4274
|
});
|
|
4232
4275
|
if (synced) {
|
|
4233
|
-
|
|
4276
|
+
const shared = entriesFrom(synced.value);
|
|
4277
|
+
writeRecentlyVisited(scope, synced.readOnly ? shared : mergeEntries(shared, readRecentlyVisited(scope)));
|
|
4234
4278
|
}
|
|
4235
4279
|
} catch {
|
|
4236
4280
|
// The service is best-effort; the local copy stands on its own.
|
|
@@ -4261,11 +4305,23 @@ true;
|
|
|
4261
4305
|
function syncRecentlyVisited(scope) {
|
|
4262
4306
|
return sync(scope, false);
|
|
4263
4307
|
}
|
|
4308
|
+
function record(entry, scope, token) {
|
|
4309
|
+
if (!(token === null || token === void 0 ? void 0 : token.readOnly)) {
|
|
4310
|
+
writeRecentlyVisited(scope, addVisit(readRecentlyVisited(scope), entry));
|
|
4311
|
+
if (token) sync(scope, true);
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4264
4314
|
function recordVisit(visit, scope) {
|
|
4265
4315
|
const entry = toEntry(visit, new Date());
|
|
4266
|
-
if (isEntry(entry)) {
|
|
4267
|
-
|
|
4268
|
-
|
|
4316
|
+
if (!isEntry(entry)) {
|
|
4317
|
+
return Promise.resolve();
|
|
4318
|
+
}
|
|
4319
|
+
const token = isUserStoreSyncUnavailable() ? null : currentToken(scope.personId);
|
|
4320
|
+
if (token instanceof Promise) {
|
|
4321
|
+
return token.then(minted => record(entry, scope, minted));
|
|
4322
|
+
} else {
|
|
4323
|
+
record(entry, scope, token);
|
|
4324
|
+
return Promise.resolve();
|
|
4269
4325
|
}
|
|
4270
4326
|
}
|
|
4271
4327
|
function useRecentlyVisited({
|
|
@@ -4946,7 +5002,6 @@ true;
|
|
|
4946
5002
|
role: "tablist"
|
|
4947
5003
|
}, products.map(product => (/*#__PURE__*/React.createElement(Tab, {
|
|
4948
5004
|
"aria-controls": `${id}-panel`,
|
|
4949
|
-
"aria-describedby": `${tabId(product.slug)}-description`,
|
|
4950
5005
|
"aria-selected": product === selected,
|
|
4951
5006
|
id: tabId(product.slug),
|
|
4952
5007
|
key: product.slug,
|
|
@@ -4964,11 +5019,6 @@ true;
|
|
|
4964
5019
|
}), showAllNames || product === selected ? product.appName : (/*#__PURE__*/React.createElement("span", {
|
|
4965
5020
|
className: styles$k.visuallyHidden
|
|
4966
5021
|
}, product.appName)))))), /*#__PURE__*/React.createElement("div", {
|
|
4967
|
-
className: styles$k.visuallyHidden
|
|
4968
|
-
}, products.map(product => (/*#__PURE__*/React.createElement("span", {
|
|
4969
|
-
id: `${tabId(product.slug)}-description`,
|
|
4970
|
-
key: product.slug
|
|
4971
|
-
}, "Planning Center ", product.appName)))), /*#__PURE__*/React.createElement("div", {
|
|
4972
5022
|
"aria-labelledby": tabId(selected.slug),
|
|
4973
5023
|
className: styles$k.panel,
|
|
4974
5024
|
id: `${id}-panel`,
|
|
@@ -6063,9 +6113,9 @@ true;
|
|
|
6063
6113
|
});
|
|
6064
6114
|
case "done":
|
|
6065
6115
|
if (sections.length === 0) {
|
|
6116
|
+
// The panel's result count announces this, so it isn't read twice.
|
|
6066
6117
|
return /*#__PURE__*/React.createElement(BlankState$1, {
|
|
6067
6118
|
image: /*#__PURE__*/React.createElement(BlankStateNoResults, null),
|
|
6068
|
-
role: "status",
|
|
6069
6119
|
subtitle: "Clear search and try again.",
|
|
6070
6120
|
title: `No results for “${term.trim()}”`
|
|
6071
6121
|
});
|
|
@@ -6119,6 +6169,7 @@ true;
|
|
|
6119
6169
|
highlightedIndex
|
|
6120
6170
|
} = navigation;
|
|
6121
6171
|
const inputRef = React.useRef(null);
|
|
6172
|
+
const resultCount = useAnnouncement(hasTerm && search.status === "done" ? `${items.length === 0 ? "No results" : `${items.length} ${items.length === 1 ? "result" : "results"}`} for “${term.trim()}” in ${product.appName}` : null);
|
|
6122
6173
|
const [announceHighlight, setAnnounceHighlight] = React.useState(false);
|
|
6123
6174
|
// The tabs keep focus while arrowing through results, but only the focused
|
|
6124
6175
|
// input can point screen readers at the highlight, so from the tabs it's
|
|
@@ -6177,7 +6228,7 @@ true;
|
|
|
6177
6228
|
"aria-live": "polite",
|
|
6178
6229
|
className: styles$k.visuallyHidden,
|
|
6179
6230
|
"data-testid": "result-count"
|
|
6180
|
-
},
|
|
6231
|
+
}, resultCount), mobile ? null : /*#__PURE__*/React.createElement(KeyboardHints, {
|
|
6181
6232
|
copied: navigation.copied
|
|
6182
6233
|
}));
|
|
6183
6234
|
}
|