@pathscale/ui 3.0.0 → 3.2.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/README.md +13 -2
- package/dist/components/accordion/Accordion.css +24 -1
- package/dist/components/alert/Alert.css +11 -1
- package/dist/components/auth-field-group/AuthFieldGroup.css +11 -3
- package/dist/components/button/Button.css +37 -10
- package/dist/components/calendar/Calendar.generated.d.ts +19 -2
- package/dist/components/calendar/Calendar.generated.js +30 -23
- package/dist/components/calendar/index.d.ts +1 -1
- package/dist/components/card/Card.generated.d.ts +38 -2
- package/dist/components/card/Card.generated.js +99 -45
- package/dist/components/card/Card.interactions.d.ts +70 -0
- package/dist/components/card/Card.interactions.js +19 -0
- package/dist/components/card/index.d.ts +1 -1
- package/dist/components/checkbox/Checkbox.generated.d.ts +23 -2
- package/dist/components/checkbox/Checkbox.generated.js +14 -6
- package/dist/components/collapsible/Collapsible.css +17 -1
- package/dist/components/color-wheel-flower/ColorWheelFlower.generated.d.ts +8 -0
- package/dist/components/color-wheel-flower/ColorWheelFlower.generated.js +14 -1
- package/dist/components/color-wheel-flower/colorWheelFlowerContext.d.ts +9 -2
- package/dist/components/color-wheel-flower/colorWheelFlowerContext.js +2 -4
- package/dist/components/connection-settings/ConnectionSettings.css +76 -0
- package/dist/components/connection-settings/ConnectionSettings.generated.d.ts +45 -0
- package/dist/components/connection-settings/ConnectionSettings.generated.js +300 -0
- package/dist/components/connection-settings/ConnectionSettings.recipe.d.ts +54 -0
- package/dist/components/connection-settings/ConnectionSettings.recipe.js +111 -0
- package/dist/components/connection-settings/index.d.ts +2 -0
- package/dist/components/connection-settings/index.js +1 -0
- package/dist/components/date-picker/DatePicker.generated.d.ts +3 -1
- package/dist/components/date-picker/DatePicker.generated.js +8 -5
- package/dist/components/date-range-picker/DateRangePicker.generated.d.ts +3 -1
- package/dist/components/date-range-picker/DateRangePicker.generated.js +9 -6
- package/dist/components/dialog/Dialog.generated.js +17 -79
- package/dist/components/drawer/Drawer.a11y.d.ts +1 -3
- package/dist/components/drawer/Drawer.a11y.js +2 -30
- package/dist/components/drawer/Drawer.generated.d.ts +24 -0
- package/dist/components/drawer/Drawer.generated.js +65 -58
- package/dist/components/grid/Grid.generated.js +3 -3
- package/dist/components/icon/Icon.generated.d.ts +15 -0
- package/dist/components/icon/Icon.generated.js +11 -2
- package/dist/components/immersive-landing/ImmersiveLanding.css +1 -1
- package/dist/components/immersive-landing/components/CookieConsent.interactions.d.ts +24 -0
- package/dist/components/immersive-landing/components/CookieConsent.interactions.js +2 -0
- package/dist/components/immersive-landing/components/CookieConsent.js +52 -47
- package/dist/components/immersive-landing/components/FirefoxPWABanner.js +10 -10
- package/dist/components/immersive-landing/types.d.ts +15 -0
- package/dist/components/input/Input.css +5 -3
- package/dist/components/input/Input.generated.js +6 -3
- package/dist/components/language-switcher/LanguageSwitcher.generated.js +1 -1
- package/dist/components/live-chat/LiveChatPanel.generated.js +2 -6
- package/dist/components/live-chat/LiveChatPanel.interactions.d.ts +21 -0
- package/dist/components/live-chat/LiveChatPanel.interactions.js +10 -0
- package/dist/components/password-field/PasswordField.generated.d.ts +9 -1
- package/dist/components/password-field/PasswordField.generated.js +2 -2
- package/dist/components/password-field/PasswordField.interactions.d.ts +2 -2
- package/dist/components/password-field/PasswordField.interactions.js +2 -2
- package/dist/components/popover/Popover.a11y.d.ts +47 -0
- package/dist/components/popover/Popover.a11y.js +19 -0
- package/dist/components/popover/Popover.generated.d.ts +26 -0
- package/dist/components/popover/Popover.generated.js +119 -46
- package/dist/components/radio/Radio.generated.d.ts +26 -2
- package/dist/components/radio/Radio.generated.js +9 -5
- package/dist/components/range-calendar/RangeCalendar.generated.d.ts +3 -1
- package/dist/components/range-calendar/RangeCalendar.generated.js +4 -1
- package/dist/components/select/Select.generated.js +5 -0
- package/dist/components/slider/Slider.generated.d.ts +14 -1
- package/dist/components/slider/Slider.generated.js +3 -2
- package/dist/components/switch/Switch.css +0 -3
- package/dist/components/switch/Switch.generated.d.ts +23 -2
- package/dist/components/switch/Switch.generated.js +21 -44
- package/dist/components/switch/Switch.recipe.d.ts +61 -38
- package/dist/components/switch/Switch.recipe.js +88 -68
- package/dist/components/table/MobileListView.generated.js +1 -1
- package/dist/components/text/Text.generated.d.ts +26 -1
- package/dist/components/text/Text.generated.js +14 -13
- package/dist/components/text/Text.recipe.d.ts +17 -5
- package/dist/components/text/Text.recipe.js +7 -13
- package/dist/components/text/index.d.ts +1 -1
- package/dist/components/theme-color-picker/ThemeColorPicker.generated.js +1 -1
- package/dist/hooks/connection/createConnectionSettings.d.ts +128 -0
- package/dist/hooks/connection/createConnectionSettings.js +211 -0
- package/dist/hooks/connection/index.d.ts +2 -0
- package/dist/hooks/connection/index.js +1 -0
- package/dist/hooks/date/date.names.d.ts +107 -0
- package/dist/hooks/date/date.names.js +74 -0
- package/dist/hooks/date/date.utils.d.ts +11 -1
- package/dist/hooks/date/date.utils.js +3 -6
- package/dist/hooks/date/index.d.ts +1 -0
- package/dist/hooks/date/index.js +1 -0
- package/dist/hooks/date/useCalendarState.d.ts +12 -5
- package/dist/hooks/date/useCalendarState.js +7 -19
- package/dist/hooks/form/createForm.d.ts +4 -4
- package/dist/hooks/form/createForm.js +7 -9
- package/dist/index.d.ts +8 -4
- package/dist/index.js +3 -1
- package/dist/layouts.manifest.json +4 -1
- package/dist/lib/focus.d.ts +31 -0
- package/dist/lib/focus.js +39 -0
- package/dist/lib/overlay.d.ts +94 -0
- package/dist/lib/overlay.js +72 -0
- package/dist/purge-manifest.json +14427 -15269
- package/dist/responsive-classes.txt +450 -0
- package/dist/styles/base/index.css +42 -0
- package/package.json +11 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"format": "solid-layouts-library-v2",
|
|
3
3
|
"package": "@pathscale/ui",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.2.0",
|
|
5
5
|
"components": {
|
|
6
6
|
"Accordion": {
|
|
7
7
|
"kind": "embedded"
|
|
@@ -153,6 +153,9 @@
|
|
|
153
153
|
"Composer": {
|
|
154
154
|
"kind": "embedded"
|
|
155
155
|
},
|
|
156
|
+
"ConnectionSettings": {
|
|
157
|
+
"kind": "embedded"
|
|
158
|
+
},
|
|
156
159
|
"CookieConsent": {
|
|
157
160
|
"kind": "embedded"
|
|
158
161
|
},
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyboard focus, for the overlays that have to contain it.
|
|
3
|
+
*
|
|
4
|
+
* Here rather than in a component's own module because two components had
|
|
5
|
+
* their own copy of the same twenty lines -- Drawer's in `Drawer.a11y.ts` and
|
|
6
|
+
* Dialog's written out inline -- and the overlay manager now needs it too. A
|
|
7
|
+
* `lib` importing from a `components` directory to reach one of those copies
|
|
8
|
+
* would be the layering inverted to avoid moving a helper.
|
|
9
|
+
*/
|
|
10
|
+
/** Everything inside `container` a person can Tab to, in document order. */
|
|
11
|
+
export declare const getFocusable: (container: HTMLElement) => HTMLElement[];
|
|
12
|
+
/** Move focus to the first thing inside `container` that will take it. */
|
|
13
|
+
export declare const focusFirst: (container: HTMLElement) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Keep Tab inside a scope, wrapping at both ends.
|
|
16
|
+
*
|
|
17
|
+
* The scope is a list, not one element, because a modal's content is not
|
|
18
|
+
* always one subtree: a Popover opened from inside a Dialog portals its
|
|
19
|
+
* content elsewhere in the document, and it is still part of what the person
|
|
20
|
+
* is looking at. Trapping in the Dialog's element alone would make the popover
|
|
21
|
+
* unreachable by keyboard; treating the popover as the scope would let Tab
|
|
22
|
+
* leave the modal behind it. Both belong.
|
|
23
|
+
*
|
|
24
|
+
* Order matters: the containers are given innermost-last, and the focusables
|
|
25
|
+
* are concatenated in that order, so tabbing off the end of the newest overlay
|
|
26
|
+
* wraps to the start of the modal that owns the scope.
|
|
27
|
+
*
|
|
28
|
+
* A scope with nothing focusable in it takes focus itself, so Tab cannot
|
|
29
|
+
* escape a modal that is still loading its content.
|
|
30
|
+
*/
|
|
31
|
+
export declare const trapFocus: (event: KeyboardEvent, scope: HTMLElement | HTMLElement[]) => void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const FOCUSABLE_SELECTOR = "a[href],area[href],button:not([disabled]),input:not([disabled]):not([type='hidden']),select:not([disabled]),textarea:not([disabled]),[contenteditable='true'],[tabindex]:not([tabindex='-1'])";
|
|
2
|
+
const getFocusable = (container)=>Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter((el)=>!el.hidden && el.tabIndex >= 0 && "true" !== el.getAttribute("aria-hidden"));
|
|
3
|
+
const focusFirst = (container)=>{
|
|
4
|
+
const autofocus = container.querySelector("[autofocus]");
|
|
5
|
+
if (autofocus) return void autofocus.focus();
|
|
6
|
+
const nodes = getFocusable(container);
|
|
7
|
+
if (nodes.length > 0) return void nodes[0].focus();
|
|
8
|
+
container.focus();
|
|
9
|
+
};
|
|
10
|
+
const trapFocus = (event, scope)=>{
|
|
11
|
+
const containers = Array.isArray(scope) ? scope : [
|
|
12
|
+
scope
|
|
13
|
+
];
|
|
14
|
+
const container = containers[0];
|
|
15
|
+
if (!container) return;
|
|
16
|
+
const nodes = containers.flatMap((element)=>getFocusable(element));
|
|
17
|
+
if (0 === nodes.length) {
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
container.focus();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const first = nodes[0];
|
|
23
|
+
const last = nodes[nodes.length - 1];
|
|
24
|
+
const active = document.activeElement;
|
|
25
|
+
if (!event.shiftKey && active === last) {
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
first.focus();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (event.shiftKey && (active === first || containers.some((element)=>active === element))) {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
last.focus();
|
|
33
|
+
}
|
|
34
|
+
if (active && !containers.some((element)=>element.contains(active))) {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
(event.shiftKey ? last : first).focus();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
export { focusFirst, getFocusable, trapFocus };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One owner for the things overlapping overlays have to agree about.
|
|
3
|
+
*
|
|
4
|
+
* Dialog, Drawer and Popover each had their own copy of this, which is fine
|
|
5
|
+
* until two of them are open at once, and then it is not:
|
|
6
|
+
*
|
|
7
|
+
* - **Escape closed every layer.** Each component bound its own `keydown` on
|
|
8
|
+
* `document`, and every listener that saw the key acted on it. Opening a
|
|
9
|
+
* Popover from inside a Dialog and pressing Escape dismissed both, because
|
|
10
|
+
* nothing established which overlay owned the event.
|
|
11
|
+
*
|
|
12
|
+
* - **The body could be left unscrollable for good.** Dialog and Drawer had
|
|
13
|
+
* *separate* module-scope lock counters, each saving `document.body.style
|
|
14
|
+
* .overflow` the first time it locked. Dialog opens and saves `""`. Drawer
|
|
15
|
+
* opens and saves `"hidden"` -- Dialog's value, not the page's. Dialog closes
|
|
16
|
+
* and restores `""`. Drawer closes and restores `"hidden"`. The page is now
|
|
17
|
+
* stuck, and nothing on screen says why.
|
|
18
|
+
*
|
|
19
|
+
* Components supply policy -- whether they are dismissable, what closing means
|
|
20
|
+
* -- and this owns the mechanism.
|
|
21
|
+
*/
|
|
22
|
+
type DismissReason = "escape";
|
|
23
|
+
interface OverlayEntry {
|
|
24
|
+
dismiss: (reason: DismissReason) => void;
|
|
25
|
+
/** Asked at dismiss time, not at registration: `closeOnEscape` can change. */
|
|
26
|
+
dismissable: () => boolean;
|
|
27
|
+
/**
|
|
28
|
+
* This overlay's own content, asked at key time because it is portalled and
|
|
29
|
+
* mounts after registration.
|
|
30
|
+
*
|
|
31
|
+
* Declared by modal and non-modal overlays alike. A Popover is not modal and
|
|
32
|
+
* still has to be part of the focus scope of whatever it was opened from, or
|
|
33
|
+
* Tab cannot reach it.
|
|
34
|
+
*/
|
|
35
|
+
element?: () => HTMLElement | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Whether this overlay contains focus while it is open.
|
|
38
|
+
*
|
|
39
|
+
* True for Dialog and Drawer, false for Popover. It decides who *owns* the
|
|
40
|
+
* scope; `element` decides what is *in* it.
|
|
41
|
+
*
|
|
42
|
+
* Here rather than on each component for the same reason `dismiss` is.
|
|
43
|
+
* Dialog and Drawer each bound their own document-level Tab listener and
|
|
44
|
+
* each gated it on "am I visible", so with both open both traps ran and the
|
|
45
|
+
* one behind could pull focus out of the one in front. Which overlay owns
|
|
46
|
+
* the keyboard is a question about all of them.
|
|
47
|
+
*/
|
|
48
|
+
modal?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The elements Tab may move within, given what is open.
|
|
52
|
+
*
|
|
53
|
+
* The innermost *modal* owns the scope, and everything opened above it is
|
|
54
|
+
* inside that scope. Empty when nothing open contains focus, which is Tab
|
|
55
|
+
* belonging to the page.
|
|
56
|
+
*
|
|
57
|
+
* Asking only the top entry was wrong in the one arrangement this manager
|
|
58
|
+
* exists for: a Popover opened from inside a Dialog is the top entry and is
|
|
59
|
+
* not modal, so Tab did nothing at all and focus walked out to the page behind
|
|
60
|
+
* a dialog that was still open -- worse than before the manager, where the
|
|
61
|
+
* Dialog's own listener at least still ran. Trapping in the modal's element
|
|
62
|
+
* alone is the opposite failure: the popover's portalled content sits outside
|
|
63
|
+
* that element and Tab could never reach it.
|
|
64
|
+
*
|
|
65
|
+
* Exported for tests. This repository has no DOM in its unit tests -- the
|
|
66
|
+
* harness is the DOM-level instrument -- and the bugs here are arrangements
|
|
67
|
+
* rather than components, which is exactly what a one-component-per-page sweep
|
|
68
|
+
* cannot set up. Keeping the decision pure is what makes it assertable at all.
|
|
69
|
+
*/
|
|
70
|
+
export declare const focusScope: (entries: readonly OverlayEntry[]) => HTMLElement[];
|
|
71
|
+
/**
|
|
72
|
+
* Claim the keyboard while an overlay is open.
|
|
73
|
+
*
|
|
74
|
+
* Call this **when the overlay becomes visible**, not when the component
|
|
75
|
+
* mounts, and call the returned function when it closes. The stack is the
|
|
76
|
+
* order overlays opened in, and it can only be that if registration is.
|
|
77
|
+
*
|
|
78
|
+
* The most recently registered overlay owns Escape, and — when it declares
|
|
79
|
+
* `trapFocusIn` — Tab.
|
|
80
|
+
*/
|
|
81
|
+
export declare const registerOverlay: (entry: OverlayEntry) => (() => void);
|
|
82
|
+
/** How many overlays currently own dismissal. Exposed for tests. */
|
|
83
|
+
export declare const overlayDepth: () => number;
|
|
84
|
+
/**
|
|
85
|
+
* Hold the body still while an overlay is open.
|
|
86
|
+
*
|
|
87
|
+
* One counter for the whole library. The saved values are captured on the
|
|
88
|
+
* first lock and restored on the last release, so overlapping overlays cannot
|
|
89
|
+
* save each other's `hidden` and restore it afterwards.
|
|
90
|
+
*/
|
|
91
|
+
export declare const lockBodyScroll: () => (() => void);
|
|
92
|
+
/** Outstanding scroll locks. Exposed for tests. */
|
|
93
|
+
export declare const bodyScrollLockDepth: () => number;
|
|
94
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { trapFocus } from "./focus.js";
|
|
2
|
+
const stack = [];
|
|
3
|
+
let keydownBound = false;
|
|
4
|
+
const overlay_top = ()=>stack[stack.length - 1];
|
|
5
|
+
const focusScope = (entries)=>{
|
|
6
|
+
for(let i = entries.length - 1; i >= 0; i -= 1)if (entries[i]?.modal) return entries.slice(i).map((entry)=>entry.element?.()).filter((element)=>Boolean(element));
|
|
7
|
+
return [];
|
|
8
|
+
};
|
|
9
|
+
const handleKeyDown = (event)=>{
|
|
10
|
+
if (event.defaultPrevented) return;
|
|
11
|
+
const entry = overlay_top();
|
|
12
|
+
if (!entry) return;
|
|
13
|
+
if ("Tab" === event.key) {
|
|
14
|
+
const scope = focusScope(stack);
|
|
15
|
+
if (scope.length > 0) trapFocus(event, scope);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if ("Escape" !== event.key) return;
|
|
19
|
+
if (!entry.dismissable()) return;
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
entry.dismiss("escape");
|
|
22
|
+
};
|
|
23
|
+
const bindKeyDown = ()=>{
|
|
24
|
+
if (keydownBound || "u" < typeof document) return;
|
|
25
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
26
|
+
keydownBound = true;
|
|
27
|
+
};
|
|
28
|
+
const unbindKeyDown = ()=>{
|
|
29
|
+
if (!keydownBound || stack.length > 0 || "u" < typeof document) return;
|
|
30
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
31
|
+
keydownBound = false;
|
|
32
|
+
};
|
|
33
|
+
const registerOverlay = (entry)=>{
|
|
34
|
+
stack.push(entry);
|
|
35
|
+
bindKeyDown();
|
|
36
|
+
let released = false;
|
|
37
|
+
return ()=>{
|
|
38
|
+
if (released) return;
|
|
39
|
+
released = true;
|
|
40
|
+
const index = stack.lastIndexOf(entry);
|
|
41
|
+
if (-1 !== index) stack.splice(index, 1);
|
|
42
|
+
unbindKeyDown();
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
const overlayDepth = ()=>stack.length;
|
|
46
|
+
let lockCount = 0;
|
|
47
|
+
let restoreOverflow = "";
|
|
48
|
+
let restorePaddingRight = "";
|
|
49
|
+
const lockBodyScroll = ()=>{
|
|
50
|
+
if ("u" < typeof document) return ()=>{};
|
|
51
|
+
if (0 === lockCount) {
|
|
52
|
+
restoreOverflow = document.body.style.overflow;
|
|
53
|
+
restorePaddingRight = document.body.style.paddingRight;
|
|
54
|
+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
55
|
+
if (scrollbarWidth > 0) document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
56
|
+
document.body.style.overflow = "hidden";
|
|
57
|
+
}
|
|
58
|
+
lockCount += 1;
|
|
59
|
+
let released = false;
|
|
60
|
+
return ()=>{
|
|
61
|
+
if (released) return;
|
|
62
|
+
released = true;
|
|
63
|
+
if (lockCount <= 0) return;
|
|
64
|
+
lockCount -= 1;
|
|
65
|
+
if (0 === lockCount) {
|
|
66
|
+
document.body.style.overflow = restoreOverflow;
|
|
67
|
+
document.body.style.paddingRight = restorePaddingRight;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const bodyScrollLockDepth = ()=>lockCount;
|
|
72
|
+
export { bodyScrollLockDepth, focusScope, lockBodyScroll, overlayDepth, registerOverlay };
|