@primer/behaviors 1.10.2 → 1.10.3
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/cjs/focus-trap.js +11 -5
- package/dist/cjs/stories/anchored-position.stories.d.ts +20 -0
- package/dist/cjs/stories/focus-trap.stories.d.ts +11 -0
- package/dist/cjs/stories/focus-zone.stories.d.ts +18 -0
- package/dist/cjs/stories/scroll-into-view.stories.d.ts +9 -0
- package/dist/esm/focus-trap.mjs +11 -5
- package/dist/esm/stories/anchored-position.stories.d.ts +20 -0
- package/dist/esm/stories/focus-trap.stories.d.ts +11 -0
- package/dist/esm/stories/focus-zone.stories.d.ts +18 -0
- package/dist/esm/stories/scroll-into-view.stories.d.ts +9 -0
- package/package.json +7 -7
package/dist/cjs/focus-trap.js
CHANGED
|
@@ -7,6 +7,12 @@ eventListenerSignal.polyfill();
|
|
|
7
7
|
const suspendedTrapStack = [];
|
|
8
8
|
let activeTrap = undefined;
|
|
9
9
|
const SR_ONLY_STYLES = 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0';
|
|
10
|
+
function focusWithDataOpt(el) {
|
|
11
|
+
if (!el)
|
|
12
|
+
return;
|
|
13
|
+
const preventScroll = el.hasAttribute('data-prevent-scroll-on-focus');
|
|
14
|
+
el.focus({ preventScroll });
|
|
15
|
+
}
|
|
10
16
|
function createSentinel({ onFocus }) {
|
|
11
17
|
const sentinel = document.createElement('span');
|
|
12
18
|
sentinel.setAttribute('class', 'sentinel');
|
|
@@ -60,13 +66,13 @@ function focusTrap(container, initialFocus, abortSignal) {
|
|
|
60
66
|
const sentinelStart = createSentinel({
|
|
61
67
|
onFocus: () => {
|
|
62
68
|
const lastFocusableChild = iterateFocusableElements.getFocusableChild(container, true);
|
|
63
|
-
lastFocusableChild
|
|
69
|
+
focusWithDataOpt(lastFocusableChild);
|
|
64
70
|
},
|
|
65
71
|
});
|
|
66
72
|
const sentinelEnd = createSentinel({
|
|
67
73
|
onFocus: () => {
|
|
68
74
|
const firstFocusableChild = iterateFocusableElements.getFocusableChild(container);
|
|
69
|
-
firstFocusableChild
|
|
75
|
+
focusWithDataOpt(firstFocusableChild);
|
|
70
76
|
},
|
|
71
77
|
});
|
|
72
78
|
const hasExistingSentinels = container.querySelector(':scope > span.sentinel') !== null;
|
|
@@ -84,16 +90,16 @@ function focusTrap(container, initialFocus, abortSignal) {
|
|
|
84
90
|
}
|
|
85
91
|
else {
|
|
86
92
|
if (lastFocusedChild && iterateFocusableElements.isTabbable(lastFocusedChild) && container.contains(lastFocusedChild)) {
|
|
87
|
-
lastFocusedChild
|
|
93
|
+
focusWithDataOpt(lastFocusedChild);
|
|
88
94
|
return;
|
|
89
95
|
}
|
|
90
96
|
else if (initialFocus && container.contains(initialFocus)) {
|
|
91
|
-
initialFocus
|
|
97
|
+
focusWithDataOpt(initialFocus);
|
|
92
98
|
return;
|
|
93
99
|
}
|
|
94
100
|
else {
|
|
95
101
|
const firstFocusableChild = iterateFocusableElements.getFocusableChild(container);
|
|
96
|
-
firstFocusableChild
|
|
102
|
+
focusWithDataOpt(firstFocusableChild);
|
|
97
103
|
return;
|
|
98
104
|
}
|
|
99
105
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { type PositionSettings } from '../anchored-position';
|
|
3
|
+
type AnchoredPositionArgs = Partial<PositionSettings> & {
|
|
4
|
+
floatingWidth: number;
|
|
5
|
+
floatingHeight: number;
|
|
6
|
+
anchorWidth: number;
|
|
7
|
+
anchorHeight: number;
|
|
8
|
+
};
|
|
9
|
+
declare const meta: Meta<AnchoredPositionArgs>;
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<AnchoredPositionArgs>;
|
|
12
|
+
export declare const OutsideBottom: Story;
|
|
13
|
+
export declare const OutsideTop: Story;
|
|
14
|
+
export declare const OutsideRight: Story;
|
|
15
|
+
export declare const OutsideLeft: Story;
|
|
16
|
+
export declare const CenterAlignment: Story;
|
|
17
|
+
export declare const EndAlignment: Story;
|
|
18
|
+
export declare const InsideCenter: Story;
|
|
19
|
+
export declare const WithOffsets: Story;
|
|
20
|
+
export declare const InsideDialog: Story;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
type FocusTrapArgs = {
|
|
3
|
+
initialFocusIndex: number;
|
|
4
|
+
autoCloseSeconds?: number;
|
|
5
|
+
};
|
|
6
|
+
declare const meta: Meta<FocusTrapArgs>;
|
|
7
|
+
export default meta;
|
|
8
|
+
type Story = StoryObj<FocusTrapArgs>;
|
|
9
|
+
export declare const BasicTrap: Story;
|
|
10
|
+
export declare const CustomInitialFocus: Story;
|
|
11
|
+
export declare const ExternalAbortSignal: Story;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
type BindKeysOption = 'Arrow Horizontal' | 'Arrow Vertical' | 'J and K' | 'H and L' | 'Home and End' | 'Page Up and Down' | 'W and S' | 'A and D' | 'Tab' | 'Backspace';
|
|
3
|
+
type FocusZoneArgs = {
|
|
4
|
+
bindKeys: BindKeysOption[];
|
|
5
|
+
focusOutBehavior: 'stop' | 'wrap';
|
|
6
|
+
focusInStrategy: 'first' | 'previous' | 'closest' | 'initial';
|
|
7
|
+
};
|
|
8
|
+
declare const meta: Meta<FocusZoneArgs>;
|
|
9
|
+
export default meta;
|
|
10
|
+
type Story = StoryObj<FocusZoneArgs>;
|
|
11
|
+
export declare const VerticalList: Story;
|
|
12
|
+
export declare const HorizontalList: Story;
|
|
13
|
+
export declare const ClosestStrategy: Story;
|
|
14
|
+
export declare const GridNavigation: Story;
|
|
15
|
+
export declare const FilteredElements: Story;
|
|
16
|
+
export declare const ActiveDescendant: Story;
|
|
17
|
+
export declare const ActiveDescendantWithInput: Story;
|
|
18
|
+
export declare const PrependedElementsActiveDescendant: Story;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { type ScrollIntoViewOptions } from '../scroll-into-view';
|
|
3
|
+
declare const meta: Meta<ScrollIntoViewOptions>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<ScrollIntoViewOptions>;
|
|
6
|
+
export declare const Vertical: Story;
|
|
7
|
+
export declare const Horizontal: Story;
|
|
8
|
+
export declare const WithMargins: Story;
|
|
9
|
+
export declare const InstantScroll: Story;
|
package/dist/esm/focus-trap.mjs
CHANGED
|
@@ -5,6 +5,12 @@ polyfill();
|
|
|
5
5
|
const suspendedTrapStack = [];
|
|
6
6
|
let activeTrap = undefined;
|
|
7
7
|
const SR_ONLY_STYLES = 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0';
|
|
8
|
+
function focusWithDataOpt(el) {
|
|
9
|
+
if (!el)
|
|
10
|
+
return;
|
|
11
|
+
const preventScroll = el.hasAttribute('data-prevent-scroll-on-focus');
|
|
12
|
+
el.focus({ preventScroll });
|
|
13
|
+
}
|
|
8
14
|
function createSentinel({ onFocus }) {
|
|
9
15
|
const sentinel = document.createElement('span');
|
|
10
16
|
sentinel.setAttribute('class', 'sentinel');
|
|
@@ -58,13 +64,13 @@ function focusTrap(container, initialFocus, abortSignal) {
|
|
|
58
64
|
const sentinelStart = createSentinel({
|
|
59
65
|
onFocus: () => {
|
|
60
66
|
const lastFocusableChild = getFocusableChild(container, true);
|
|
61
|
-
lastFocusableChild
|
|
67
|
+
focusWithDataOpt(lastFocusableChild);
|
|
62
68
|
},
|
|
63
69
|
});
|
|
64
70
|
const sentinelEnd = createSentinel({
|
|
65
71
|
onFocus: () => {
|
|
66
72
|
const firstFocusableChild = getFocusableChild(container);
|
|
67
|
-
firstFocusableChild
|
|
73
|
+
focusWithDataOpt(firstFocusableChild);
|
|
68
74
|
},
|
|
69
75
|
});
|
|
70
76
|
const hasExistingSentinels = container.querySelector(':scope > span.sentinel') !== null;
|
|
@@ -82,16 +88,16 @@ function focusTrap(container, initialFocus, abortSignal) {
|
|
|
82
88
|
}
|
|
83
89
|
else {
|
|
84
90
|
if (lastFocusedChild && isTabbable(lastFocusedChild) && container.contains(lastFocusedChild)) {
|
|
85
|
-
lastFocusedChild
|
|
91
|
+
focusWithDataOpt(lastFocusedChild);
|
|
86
92
|
return;
|
|
87
93
|
}
|
|
88
94
|
else if (initialFocus && container.contains(initialFocus)) {
|
|
89
|
-
initialFocus
|
|
95
|
+
focusWithDataOpt(initialFocus);
|
|
90
96
|
return;
|
|
91
97
|
}
|
|
92
98
|
else {
|
|
93
99
|
const firstFocusableChild = getFocusableChild(container);
|
|
94
|
-
firstFocusableChild
|
|
100
|
+
focusWithDataOpt(firstFocusableChild);
|
|
95
101
|
return;
|
|
96
102
|
}
|
|
97
103
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { type PositionSettings } from '../anchored-position';
|
|
3
|
+
type AnchoredPositionArgs = Partial<PositionSettings> & {
|
|
4
|
+
floatingWidth: number;
|
|
5
|
+
floatingHeight: number;
|
|
6
|
+
anchorWidth: number;
|
|
7
|
+
anchorHeight: number;
|
|
8
|
+
};
|
|
9
|
+
declare const meta: Meta<AnchoredPositionArgs>;
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<AnchoredPositionArgs>;
|
|
12
|
+
export declare const OutsideBottom: Story;
|
|
13
|
+
export declare const OutsideTop: Story;
|
|
14
|
+
export declare const OutsideRight: Story;
|
|
15
|
+
export declare const OutsideLeft: Story;
|
|
16
|
+
export declare const CenterAlignment: Story;
|
|
17
|
+
export declare const EndAlignment: Story;
|
|
18
|
+
export declare const InsideCenter: Story;
|
|
19
|
+
export declare const WithOffsets: Story;
|
|
20
|
+
export declare const InsideDialog: Story;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
type FocusTrapArgs = {
|
|
3
|
+
initialFocusIndex: number;
|
|
4
|
+
autoCloseSeconds?: number;
|
|
5
|
+
};
|
|
6
|
+
declare const meta: Meta<FocusTrapArgs>;
|
|
7
|
+
export default meta;
|
|
8
|
+
type Story = StoryObj<FocusTrapArgs>;
|
|
9
|
+
export declare const BasicTrap: Story;
|
|
10
|
+
export declare const CustomInitialFocus: Story;
|
|
11
|
+
export declare const ExternalAbortSignal: Story;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
type BindKeysOption = 'Arrow Horizontal' | 'Arrow Vertical' | 'J and K' | 'H and L' | 'Home and End' | 'Page Up and Down' | 'W and S' | 'A and D' | 'Tab' | 'Backspace';
|
|
3
|
+
type FocusZoneArgs = {
|
|
4
|
+
bindKeys: BindKeysOption[];
|
|
5
|
+
focusOutBehavior: 'stop' | 'wrap';
|
|
6
|
+
focusInStrategy: 'first' | 'previous' | 'closest' | 'initial';
|
|
7
|
+
};
|
|
8
|
+
declare const meta: Meta<FocusZoneArgs>;
|
|
9
|
+
export default meta;
|
|
10
|
+
type Story = StoryObj<FocusZoneArgs>;
|
|
11
|
+
export declare const VerticalList: Story;
|
|
12
|
+
export declare const HorizontalList: Story;
|
|
13
|
+
export declare const ClosestStrategy: Story;
|
|
14
|
+
export declare const GridNavigation: Story;
|
|
15
|
+
export declare const FilteredElements: Story;
|
|
16
|
+
export declare const ActiveDescendant: Story;
|
|
17
|
+
export declare const ActiveDescendantWithInput: Story;
|
|
18
|
+
export declare const PrependedElementsActiveDescendant: Story;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { type ScrollIntoViewOptions } from '../scroll-into-view';
|
|
3
|
+
declare const meta: Meta<ScrollIntoViewOptions>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<ScrollIntoViewOptions>;
|
|
6
|
+
export declare const Vertical: Story;
|
|
7
|
+
export declare const Horizontal: Story;
|
|
8
|
+
export declare const WithMargins: Story;
|
|
9
|
+
export declare const InstantScroll: Story;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primer/behaviors",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.3",
|
|
4
4
|
"description": "Shared behaviors for JavaScript components",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
@@ -72,13 +72,13 @@
|
|
|
72
72
|
],
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@arethetypeswrong/cli": "^0.18.0",
|
|
75
|
-
"@changesets/changelog-github": "^0.
|
|
75
|
+
"@changesets/changelog-github": "^0.7.0",
|
|
76
76
|
"@changesets/cli": "^2.18.1",
|
|
77
77
|
"@github/prettier-config": "^0.0.6",
|
|
78
78
|
"@rollup/plugin-typescript": "^12.1.0",
|
|
79
79
|
"@rollup/wasm-node": "^4.19.1",
|
|
80
80
|
"@size-limit/preset-small-lib": "^12.0.0",
|
|
81
|
-
"@storybook/react-vite": "
|
|
81
|
+
"@storybook/react-vite": "10.3.6",
|
|
82
82
|
"@testing-library/react": "^16.0.0",
|
|
83
83
|
"@testing-library/user-event": "^14.5.1",
|
|
84
84
|
"@types/jest": "^30.0.0",
|
|
@@ -86,12 +86,12 @@
|
|
|
86
86
|
"@types/react": "^19.0.1",
|
|
87
87
|
"@types/react-dom": "^19.2.3",
|
|
88
88
|
"clsx": "^2.1.1",
|
|
89
|
-
"esbuild": "^0.
|
|
89
|
+
"esbuild": "^0.28.0",
|
|
90
90
|
"esbuild-jest": "^0.5.0",
|
|
91
91
|
"eslint": "^8.50.0",
|
|
92
92
|
"eslint-plugin-github": "^5.0.0",
|
|
93
93
|
"eslint-plugin-prettier": "^5.0.0",
|
|
94
|
-
"eslint-plugin-storybook": "
|
|
94
|
+
"eslint-plugin-storybook": "10.3.6",
|
|
95
95
|
"jest": "^30.0.4",
|
|
96
96
|
"jest-environment-jsdom": "^30.0.4",
|
|
97
97
|
"prettier": "^3.0.3",
|
|
@@ -100,8 +100,8 @@
|
|
|
100
100
|
"rimraf": "^6.0.1",
|
|
101
101
|
"rollup": "^4.18.0",
|
|
102
102
|
"size-limit": "^12.0.0",
|
|
103
|
-
"storybook": "
|
|
103
|
+
"storybook": "10.3.6",
|
|
104
104
|
"tslib": "^2.8.1",
|
|
105
|
-
"typescript": "^
|
|
105
|
+
"typescript": "^6.0.2"
|
|
106
106
|
}
|
|
107
107
|
}
|