reshaped 3.4.7 → 3.5.0-rc.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.
@@ -18,7 +18,6 @@ declare const _default: {
18
18
  };
19
19
  };
20
20
  export default _default;
21
- export declare const foo: () => React.JSX.Element;
22
21
  export declare const active: StoryObj<{
23
22
  handleOpen: Mock;
24
23
  handleClose: Mock;
@@ -16,18 +16,6 @@ export default {
16
16
  },
17
17
  },
18
18
  };
19
- export const foo = () => {
20
- const [value, setValue] = React.useState("");
21
- const options = ["Pizza", "Pie", "Ice-cream"];
22
- return (<FormControl>
23
- <FormControl.Label>Favorite food</FormControl.Label>
24
- <Autocomplete name="fruit" placeholder="Pick your option" value={value} onChange={(args) => setValue(args.value)}>
25
- {options.map((option) => (<Autocomplete.Item key={option} value={option}>
26
- {option}
27
- </Autocomplete.Item>))}
28
- </Autocomplete>
29
- </FormControl>);
30
- };
31
19
  export const active = {
32
20
  name: "active, onOpen, onClose",
33
21
  args: {
@@ -60,7 +48,7 @@ export const active = {
60
48
  play: async ({ canvasElement, args }) => {
61
49
  const canvas = within(canvasElement.ownerDocument.body);
62
50
  const input = canvas.getByRole("combobox");
63
- const list = canvas.getByRole("listbox");
51
+ const list = await canvas.findByRole("listbox");
64
52
  expect(list).toBeInTheDocument();
65
53
  expect(args.handleOpen).not.toHaveBeenCalled();
66
54
  await userEvent.click(document.body);
@@ -167,7 +155,7 @@ export const itemData = {
167
155
  },
168
156
  play: async ({ canvasElement, args }) => {
169
157
  const canvas = within(canvasElement.ownerDocument.body);
170
- const options = canvas.getAllByRole("option");
158
+ const options = await canvas.findAllByRole("option");
171
159
  await userEvent.click(options[0]);
172
160
  expect(args.handleItemSelect).toHaveBeenLastCalledWith({ value: "Pizza" });
173
161
  await userEvent.click(options[1]);
@@ -195,7 +183,7 @@ export const itemDisabled = {
195
183
  play: async ({ canvasElement }) => {
196
184
  const canvas = within(canvasElement.ownerDocument.body);
197
185
  const input = canvas.getByRole("combobox");
198
- const options = canvas.getAllByRole("option");
186
+ const options = await canvas.findAllByRole("option");
199
187
  await fireEvent.click(options[1]);
200
188
  expect(options[1]).toBeDisabled();
201
189
  // Check that focus stays on input when clicking on disabled elements
@@ -1,5 +1,5 @@
1
1
  import type React from "react";
2
- import type { ActionableProps } from "../Actionable";
2
+ import type { ActionableProps, ActionableRef } from "../Actionable";
3
3
  import type { IconProps } from "../Icon";
4
4
  import type * as G from "../../types/global";
5
5
  type BaseProps = {
@@ -36,7 +36,9 @@ export type ContainerProps = {
36
36
  className?: G.ClassName;
37
37
  attributes?: G.Attributes<"div">;
38
38
  };
39
- export type Export = React.ForwardRefExoticComponent<Props> & {
39
+ export type Export = React.ForwardRefExoticComponent<Props & {
40
+ ref?: ActionableRef;
41
+ }> & {
40
42
  Container: React.ComponentType<ContainerProps>;
41
43
  };
42
44
  export {};
@@ -1,6 +1,6 @@
1
1
  import type React from "react";
2
2
  import type { IconProps } from "../Icon";
3
- import type { ActionableProps } from "../Actionable";
3
+ import type { ActionableProps, ActionableRef } from "../Actionable";
4
4
  import type { AlignerProps as BaseAlignerProps } from "../_private/Aligner";
5
5
  import type * as G from "../../types/global";
6
6
  export type Size = "xlarge" | "large" | "medium" | "small";
@@ -28,7 +28,9 @@ export type AlignerProps = BaseAlignerProps & {
28
28
  */
29
29
  position?: BaseAlignerProps["side"];
30
30
  };
31
- export type Export = React.ForwardRefExoticComponent<Props> & {
31
+ export type Export = React.ForwardRefExoticComponent<Props & {
32
+ ref?: ActionableRef;
33
+ }> & {
32
34
  Aligner: React.ComponentType<AlignerProps>;
33
35
  Group: React.ComponentType<GroupProps>;
34
36
  };
@@ -1,6 +1,6 @@
1
1
  import type React from "react";
2
2
  import type { IconProps } from "../Icon";
3
- import type { ActionableProps } from "../Actionable";
3
+ import type { ActionableProps, ActionableRef } from "../Actionable";
4
4
  import type * as G from "../../types/global";
5
5
  export type Size = "small" | "medium" | "large";
6
6
  export type Props = Pick<ActionableProps, "attributes" | "className" | "disabled" | "children" | "href" | "onClick" | "as" | "stopPropagation"> & {
@@ -18,6 +18,8 @@ export type AlignerProps = {
18
18
  className?: G.ClassName;
19
19
  attributes?: G.Attributes<"div">;
20
20
  };
21
- export type Export = React.ForwardRefExoticComponent<Props> & {
21
+ export type Export = React.ForwardRefExoticComponent<Props & {
22
+ ref?: ActionableRef;
23
+ }> & {
22
24
  Aligner: React.ComponentType<AlignerProps>;
23
25
  };
@@ -1 +1 @@
1
- .field{font-variant-numeric:tabular-nums}.controls{--rs-number-field-control-border-color:var(--rs-color-border-neutral);border-inline-start:1px solid var(--rs-number-field-control-border-color);display:flex;flex-direction:column;inset-block:calc(var(--rs-text-field-p-v) * -1 + var(--rs-unit-x1));inset-inline-end:1px;position:absolute;transition:border-color var(--rs-duration-fast) var(--rs-easing-standard)}.controls:has([aria-disabled]+[aria-disabled]){--rs-number-field-control-border-color:var(--rs-color-border-disabled)}.control{align-items:center;aspect-ratio:5/4;display:flex;flex-grow:1;height:50%;justify-content:center;touch-action:manipulation;transition:color var(--rs-duration-fast) var(--rs-easing-standard)}.control:first-child{box-shadow:0 1px var(--rs-number-field-control-border-color)}.control[aria-disabled]{color:var(--rs-color-foreground-disabled)}.control:not([aria-disabled]):hover{background:rgba(var(--rs-color-rgb-background-neutral),32%)}.icon--touch{display:none}@media (pointer:coarse) and (hover:none){.controls{flex-direction:row-reverse}.control{aspect-ratio:1;box-sizing:content-box;height:100%}.control:first-child{border-inline-start:1px solid var(--rs-color-border-neutral);box-shadow:none}.icon--touch{display:block}.icon--mouse{display:none}}
1
+ .field{font-variant-numeric:tabular-nums}.controls-wrapper{display:block}.controls{--rs-number-field-control-border-color:var(--rs-color-border-neutral);display:flex;flex-direction:column;inset-block:calc(var(--rs-text-field-p-v) * -1 + var(--rs-unit-x1));inset-inline-end:0;position:absolute;transition:border-color var(--rs-duration-fast) var(--rs-easing-standard)}.controls:has([aria-disabled]+[aria-disabled]){--rs-number-field-control-border-color:var(--rs-color-border-disabled)}.controls--size-small .control,.controls--size-small .controls-wrapper{width:var(--rs-unit-x4)}@media (pointer:coarse) and (hover:none){.controls--size-small .controls-wrapper{width:54px}}.controls--size-medium .control,.controls--size-medium .controls-wrapper{width:var(--rs-unit-x5)}@media (pointer:coarse) and (hover:none){.controls--size-medium .controls-wrapper{width:70px}}.controls--size-large .control{width:var(--rs-unit-x6)}.controls--size-large .controls-wrapper{width:var(--rs-unit-x5)}@media (pointer:coarse) and (hover:none){.controls--size-large .controls-wrapper{width:94px}}.controls--size-xlarge .control{width:var(--rs-unit-x7)}.controls--size-xlarge .controls-wrapper{width:var(--rs-unit-x6)}@media (pointer:coarse) and (hover:none){.controls--size-xlarge .controls-wrapper{width:110px}}.control{align-items:center;display:flex;flex-grow:1;height:50%;justify-content:center;touch-action:manipulation;transition:color var(--rs-duration-fast) var(--rs-easing-standard)}.control[aria-disabled]{color:var(--rs-color-foreground-disabled)}.control:not([aria-disabled]):hover{background:rgba(var(--rs-color-rgb-background-neutral),32%)}.icon--touch{display:none!important}.--outline .controls{border-inline-start:1px solid var(--rs-number-field-control-border-color);inset-inline-end:1px}.--outline .control:first-child{box-shadow:0 1px var(--rs-number-field-control-border-color)}@media (pointer:coarse) and (hover:none){.controls{flex-direction:row-reverse}.control{aspect-ratio:1;box-sizing:content-box;height:100%;touch-action:manipulation;width:auto!important}.icon--touch{display:block!important}.icon--mouse{display:none!important}.--outline .control:first-child{border-inline-start:1px solid var(--rs-color-border-neutral);box-shadow:none}}@media (--rs-viewport-m ){.controls--size-small--m .control,.controls--size-small--m .controls-wrapper{width:var(--rs-unit-x4)}@media (pointer:coarse) and (hover:none){.controls--size-small--m .controls-wrapper{width:54px}}.controls--size-medium--m .control,.controls--size-medium--m .controls-wrapper{width:var(--rs-unit-x5)}@media (pointer:coarse) and (hover:none){.controls--size-medium--m .controls-wrapper{width:70px}}.controls--size-large--m .control{width:var(--rs-unit-x6)}.controls--size-large--m .controls-wrapper{width:var(--rs-unit-x5)}@media (pointer:coarse) and (hover:none){.controls--size-large--m .controls-wrapper{width:94px}}.controls--size-xlarge--m .control{width:var(--rs-unit-x7)}.controls--size-xlarge--m .controls-wrapper{width:var(--rs-unit-x6)}@media (pointer:coarse) and (hover:none){.controls--size-xlarge--m .controls-wrapper{width:110px}}}@media (--rs-viewport-l ){.controls--size-small--l .control,.controls--size-small--l .controls-wrapper{width:var(--rs-unit-x4)}@media (pointer:coarse) and (hover:none){.controls--size-small--l .controls-wrapper{width:54px}}.controls--size-medium--l .control,.controls--size-medium--l .controls-wrapper{width:var(--rs-unit-x5)}@media (pointer:coarse) and (hover:none){.controls--size-medium--l .controls-wrapper{width:70px}}.controls--size-large--l .control{width:var(--rs-unit-x6)}.controls--size-large--l .controls-wrapper{width:var(--rs-unit-x5)}@media (pointer:coarse) and (hover:none){.controls--size-large--l .controls-wrapper{width:94px}}.controls--size-xlarge--l .control{width:var(--rs-unit-x7)}.controls--size-xlarge--l .controls-wrapper{width:var(--rs-unit-x6)}@media (pointer:coarse) and (hover:none){.controls--size-xlarge--l .controls-wrapper{width:110px}}}@media (--rs-viewport-xl ){.controls--size-small--xl .control,.controls--size-small--xl .controls-wrapper{width:var(--rs-unit-x4)}@media (pointer:coarse) and (hover:none){.controls--size-small--xl .controls-wrapper{width:54px}}.controls--size-medium--xl .control,.controls--size-medium--xl .controls-wrapper{width:var(--rs-unit-x5)}@media (pointer:coarse) and (hover:none){.controls--size-medium--xl .controls-wrapper{width:70px}}.controls--size-large--xl .control{width:var(--rs-unit-x6)}.controls--size-large--xl .controls-wrapper{width:var(--rs-unit-x5)}@media (pointer:coarse) and (hover:none){.controls--size-large--xl .controls-wrapper{width:94px}}.controls--size-xlarge--xl .control{width:var(--rs-unit-x7)}.controls--size-xlarge--xl .controls-wrapper{width:var(--rs-unit-x6)}@media (pointer:coarse) and (hover:none){.controls--size-xlarge--xl .controls-wrapper{width:110px}}}
@@ -1,6 +1,6 @@
1
1
  import type { TextFieldBaseProps } from "../TextField";
2
2
  import type * as G from "../../types/global";
3
- export type BaseProps = Omit<TextFieldBaseProps, "endSlot" | "onChange"> & {
3
+ export type BaseProps = Omit<TextFieldBaseProps, "endSlot" | "onChange" | "rounded" | "multiline"> & {
4
4
  onChange?: G.ChangeHandler<number>;
5
5
  increaseAriaLabel: string;
6
6
  decreaseAriaLabel: string;
@@ -4,18 +4,19 @@ import React from "react";
4
4
  import Actionable from "../Actionable/index.js";
5
5
  import Icon from "../Icon/index.js";
6
6
  import TextField from "../TextField/index.js";
7
+ import { useFormControl } from "../FormControl/index.js";
7
8
  import IconChevronUp from "../../icons/ChevronUp.js";
8
9
  import IconChevronDown from "../../icons/ChevronDown.js";
9
10
  import IconPlus from "../../icons/Plus.js";
10
11
  import IconMinus from "../../icons/Minus.js";
11
12
  import useElementId from "../../hooks/useElementId.js";
12
13
  import useHotkeys from "../../hooks/useHotkeys.js";
14
+ import useHandlerRef from "../../hooks/useHandlerRef.js";
13
15
  import * as keys from "../../constants/keys.js";
16
+ import { responsiveClassNames, responsivePropDependency } from "../../utilities/helpers.js";
14
17
  import s from "./NumberField.module.css";
15
- import useHandlerRef from "../../hooks/useHandlerRef.js";
16
- import { useFormControl } from "../FormControl/index.js";
17
18
  const NumberFieldControlled = (props) => {
18
- const { increaseAriaLabel, decreaseAriaLabel, min, max, step = 1, name, value, onChange, ...textFieldProps } = props;
19
+ const { increaseAriaLabel, decreaseAriaLabel, min, max, step = 1, name, value, onChange, size = "medium", ...textFieldProps } = props;
19
20
  const formControl = useFormControl();
20
21
  const id = useElementId(textFieldProps.id);
21
22
  const inputId = formControl?.attributes.id || props.inputAttributes?.id || id;
@@ -62,8 +63,12 @@ const NumberFieldControlled = (props) => {
62
63
  const handleChange = (args) => {
63
64
  if (!args.value.match(/^(-?)[0-9]*(\.?)[0-9]*$/))
64
65
  return;
65
- setTextValue(args.value);
66
66
  const numberValue = parseFloat(args.value);
67
+ if (numberValue > Number.MAX_SAFE_INTEGER)
68
+ return;
69
+ if (numberValue < Number.MIN_SAFE_INTEGER)
70
+ return;
71
+ setTextValue(args.value);
67
72
  if (isNaN(numberValue))
68
73
  return;
69
74
  commitValue(numberValue);
@@ -104,32 +109,43 @@ const NumberFieldControlled = (props) => {
104
109
  valueRef.current = value;
105
110
  setTextValue(value?.toString() ?? "");
106
111
  }, [value]);
107
- const controlsNode = (_jsxs("span", { className: s.controls, children: [_jsxs(Actionable, { className: s.control, disabled: increaseDisabled, disableFocusRing: true, as: "span", attributes: {
108
- "aria-label": increaseAriaLabel,
109
- "aria-controls": id,
110
- role: "button",
111
- tabIndex: increaseDisabled ? undefined : -1,
112
- onPointerDown: (e) => handleControlPointerDown(e, handleIncrease),
113
- onPointerUp: handleControlPointerUp,
114
- onPointerLeave: handleControlPointerUp,
115
- // Prevent menu from opening on long press
116
- onContextMenu: (e) => e.preventDefault(),
117
- }, children: [_jsx(Icon, { svg: IconChevronUp, size: 3, className: s["icon--mouse"] }), _jsx(Icon, { svg: IconPlus, size: 4, className: s["icon--touch"] })] }), _jsxs(Actionable, { className: s.control, disabled: decreaseDisabled, disableFocusRing: true, as: "span", attributes: {
118
- "aria-label": decreaseAriaLabel,
119
- "aria-controls": id,
120
- role: "button",
121
- tabIndex: decreaseDisabled ? undefined : -1,
122
- onPointerDown: (e) => handleControlPointerDown(e, handleDecrease),
123
- onPointerUp: handleControlPointerUp,
124
- onPointerLeave: handleControlPointerUp,
125
- // Prevent menu from opening on long press
126
- onContextMenu: (e) => e.preventDefault(),
127
- }, children: [_jsx(Icon, { svg: IconChevronDown, size: 3, className: s["icon--mouse"] }), _jsx(Icon, { svg: IconMinus, size: 4, className: s["icon--touch"] })] })] }));
128
- return (_jsx(TextField, { attributes: {
112
+ const mouseIconSize = responsivePropDependency(size, (size) => {
113
+ return size === "large" || size === "xlarge" ? 4 : 3;
114
+ });
115
+ const touchIconSize = responsivePropDependency(size, (size) => {
116
+ return size === "small" ? 3 : 4;
117
+ });
118
+ const controlsNode = (_jsx("span", { className: s["controls-wrapper"], children: _jsxs("span", { className: s.controls, children: [_jsxs(Actionable, { className: s.control, disabled: increaseDisabled, disableFocusRing: true, as: "span", attributes: {
119
+ "aria-label": increaseAriaLabel,
120
+ "aria-controls": inputId,
121
+ role: "button",
122
+ tabIndex: increaseDisabled ? undefined : -1,
123
+ onPointerDown: (e) => handleControlPointerDown(e, handleIncrease),
124
+ onPointerUp: handleControlPointerUp,
125
+ onPointerLeave: handleControlPointerUp,
126
+ // Prevent menu from opening on long press
127
+ onContextMenu: (e) => e.preventDefault(),
128
+ }, children: [_jsx(Icon, { svg: IconChevronUp, size: mouseIconSize, className: s["icon--mouse"] }), _jsx(Icon, { svg: IconPlus, size: touchIconSize, className: s["icon--touch"] })] }), _jsxs(Actionable, { className: s.control, disabled: decreaseDisabled, disableFocusRing: true, as: "span", attributes: {
129
+ "aria-label": decreaseAriaLabel,
130
+ "aria-controls": inputId,
131
+ role: "button",
132
+ tabIndex: decreaseDisabled ? undefined : -1,
133
+ onPointerDown: (e) => handleControlPointerDown(e, handleDecrease),
134
+ onPointerUp: handleControlPointerUp,
135
+ onPointerLeave: handleControlPointerUp,
136
+ // Prevent menu from opening on long press
137
+ onContextMenu: (e) => e.preventDefault(),
138
+ }, children: [_jsx(Icon, { svg: IconChevronDown, size: mouseIconSize, className: s["icon--mouse"] }), _jsx(Icon, { svg: IconMinus, size: touchIconSize, className: s["icon--touch"] })] })] }) }));
139
+ return (_jsx(TextField, { ...textFieldProps, className: [
140
+ textFieldProps.className,
141
+ responsiveClassNames(s, "controls--size", size),
142
+ !(textFieldProps.variant === "faded" || textFieldProps.variant === "headless") &&
143
+ s["--outline"],
144
+ ], attributes: {
129
145
  ...textFieldProps.attributes,
130
146
  role: "group",
131
147
  ref: rootRef,
132
- }, id: inputId, hasError: hasError, inputAttributes: {
148
+ }, inputAttributes: {
133
149
  ...textFieldProps.inputAttributes,
134
150
  ref: inputRef,
135
151
  inputMode: "numeric",
@@ -140,7 +156,7 @@ const NumberFieldControlled = (props) => {
140
156
  max,
141
157
  step,
142
158
  className: s.field,
143
- }, ...textFieldProps, disabled: disabled, value: textValue, onChange: handleChange, name: name, endSlot: controlsNode }));
159
+ }, size: size, id: inputId, hasError: hasError, disabled: disabled, value: textValue, onChange: handleChange, name: name, endSlot: controlsNode }));
144
160
  };
145
161
  NumberFieldControlled.displayName = "NumberFieldControlled";
146
162
  export default NumberFieldControlled;
@@ -13,7 +13,8 @@ declare const _default: {
13
13
  };
14
14
  };
15
15
  export default _default;
16
- export declare const base: StoryObj;
16
+ export declare const variant: StoryObj;
17
+ export declare const size: StoryObj;
17
18
  export declare const disabled: StoryObj<{
18
19
  handleChange: Mock;
19
20
  }>;
@@ -11,23 +11,48 @@ export default {
11
11
  },
12
12
  },
13
13
  };
14
- export const base = {
15
- name: "base",
14
+ export const variant = {
15
+ name: "variant",
16
16
  render: () => {
17
17
  return (<Example>
18
- <Example.Item title="base">
18
+ <Example.Item title="variant: outline">
19
19
  <NumberField name="test-name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>
20
20
  </Example.Item>
21
+ <Example.Item title="variant: faded">
22
+ <NumberField variant="faded" name="test-name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>
23
+ </Example.Item>
24
+ <Example.Item title="variant: headless">
25
+ <NumberField variant="headless" name="test-name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>
26
+ </Example.Item>
21
27
  </Example>);
22
28
  },
23
29
  play: async ({ canvas }) => {
24
- const input = canvas.getByRole("textbox");
30
+ const input = canvas.getAllByRole("textbox")[0];
25
31
  const [increaseButton, decreaseButton] = canvas.getAllByRole("button");
26
32
  expect(input).toHaveAttribute("name", "test-name");
27
33
  expect(increaseButton).toHaveAccessibleName("Increase");
28
34
  expect(decreaseButton).toHaveAccessibleName("Decrease");
29
35
  },
30
36
  };
37
+ export const size = {
38
+ name: "size",
39
+ render: () => {
40
+ return (<Example>
41
+ <Example.Item title="size: small">
42
+ <NumberField size="small" name="test-name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" suffix="m2" inputAttributes={{ "aria-label": "Label" }}/>
43
+ </Example.Item>
44
+ <Example.Item title="size: medium">
45
+ <NumberField size="medium" name="test-name" suffix="m2" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>
46
+ </Example.Item>
47
+ <Example.Item title="size: large">
48
+ <NumberField size="large" name="test-name" suffix="m2" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>
49
+ </Example.Item>
50
+ <Example.Item title="size: xlarge">
51
+ <NumberField size="xlarge" name="test-name" suffix="m2" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>
52
+ </Example.Item>
53
+ </Example>);
54
+ },
55
+ };
31
56
  export const disabled = {
32
57
  name: "disabled",
33
58
  args: {
@@ -176,7 +201,7 @@ export const valueChanges = {
176
201
  name: "test: keyboard",
177
202
  render: () => (<Example>
178
203
  <Example.Item title="keyboard">
179
- <NumberField name="name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease"/>
204
+ <NumberField name="name" increaseAriaLabel="Increase" decreaseAriaLabel="Decrease" inputAttributes={{ "aria-label": "Label" }}/>
180
205
  </Example.Item>
181
206
  </Example>),
182
207
  play: async ({ canvas }) => {
@@ -97,7 +97,7 @@ const Overlay = (props) => {
97
97
  React.useEffect(() => {
98
98
  if (!rendered || !contentRef.current)
99
99
  return;
100
- const trapFocus = new TrapFocus(contentRef.current);
100
+ const trapFocus = new TrapFocus();
101
101
  const containerEl = containerRef?.current;
102
102
  if (containerEl) {
103
103
  originalOverflowRef.current = containerEl.style.overflow;
@@ -105,7 +105,7 @@ const Overlay = (props) => {
105
105
  containerEl.style.isolation = "isolate";
106
106
  setOffset([containerEl.scrollLeft, containerEl.scrollTop]);
107
107
  }
108
- trapFocus.trap({
108
+ trapFocus.trap(contentRef.current, {
109
109
  initialFocusEl: contentRef.current.querySelector("[role=dialog][tabindex='-1']"),
110
110
  });
111
111
  onOpenRef.current?.();
@@ -1 +1 @@
1
- .root{--rs-p-h:var(--rs-text-field-gap);align-items:center;background:var(--rs-color-background-elevation-base);border:1px solid var(--rs-color-border-neutral);border-radius:var(--rs-text-field-radius);display:flex;gap:var(--rs-text-field-gap);padding:0 calc(var(--rs-text-field-gap) - 1px);position:relative;row-gap:var(--rs-unit-x1);z-index:0}.root.--focused,.root:has(label:active),.root:not(:has(button:focus,a:focus,[tabindex="0"]:focus,[role=button]:focus)):focus-within{border-color:var(--rs-color-border-primary);box-shadow:0 0 0 1px var(--rs-color-border-primary)}.root.--multiline{flex-wrap:wrap}.root.--multiline .input{width:auto}.root.--rounded{border-radius:999px}.root.--rounded .affix:first-child,.root.--rounded .icon:first-child{padding-inline-start:var(--rs-unit-x1)}.root.--rounded .input:first-child{padding-inline-start:calc(var(--rs-text-field-gap) + var(--rs-unit-x1))}.input{background:none;border:none;box-sizing:border-box;color:var(--rs-color-foreground-neutral);flex-grow:1;font-family:var(--rs-font-family-body);font-weight:var(--rs-font-weight-regular);margin:0 calc(var(--rs-text-field-gap) * -1);outline:none;padding-block:calc(var(--rs-text-field-p-v) - 1px);padding-inline:var(--rs-text-field-gap);position:relative;width:100%;z-index:1}.input:-webkit-autofill{-webkit-background-clip:text;-webkit-text-fill-color:var(--rs-color-foreground-neutral)}.affix,.input{font-size:var(--rs-text-field-font-size);letter-spacing:var(--rs-text-field-letter-spacing);line-height:var(--rs-text-field-line-height)}.affix,.icon{cursor:text}.affix,.icon,.slot{align-items:center;display:flex;flex-shrink:0;max-width:100%;min-height:calc(var(--rs-text-field-line-height) + var(--rs-unit-x2) - 2px);position:relative;z-index:5}.slot--position-end:last-child{margin-inline-end:calc(var(--rs-text-field-gap) * -1);padding-inline-end:var(--rs-text-field-action-inset)}.affix{color:var(--rs-color-foreground-neutral-faded)}.affix.affix--position-start{padding-inline-end:var(--rs-text-field-gap)}.affix.affix--position-start:after{border-inline-end:1px solid var(--rs-color-border-neutral-faded);content:"";inset-block:var(--rs-unit-x1);inset-inline-end:0;position:absolute}.affix.affix--position-end{padding-inline-start:var(--rs-text-field-gap)}.affix.affix--position-end:after{border-inline-start:1px solid var(--rs-color-border-neutral-faded);content:"";inset-block:var(--rs-unit-x1);inset-inline-start:0;position:absolute}.root.--disabled{background:var(--rs-color-background-disabled-faded);border-color:var(--rs-color-border-disabled)}.root.--disabled,.root.--disabled .input{color:var(--rs-color-foreground-disabled);cursor:not-allowed}.--size-small{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x1);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-medium{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x2);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-large{--rs-text-field-gap:var(--rs-unit-x3);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x3);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x2)}.--size-xlarge{--rs-text-field-gap:var(--rs-unit-x4);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x4);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x1)}.root.--variant-faded{background:var(--rs-color-background-neutral-faded);border-color:transparent}.root.--variant-faded.--focused,.root.--variant-faded:focus-within{border-color:var(--rs-color-border-primary)}.root.--variant-headless{background:transparent;border-color:transparent}.root.--variant-headless.--status-error,.root.--variant-headless.--status-error.--focused,.root.--variant-headless.--status-error:focus-within,.root.--variant-headless:focus-within{border-color:transparent;box-shadow:none}.root.--status-error{border-color:var(--rs-color-border-critical)}.root.--status-error.--focused,.root.--status-error:focus-within{border-color:var(--rs-color-border-primary)}@media (--rs-viewport-s ) and (hover:none){.input{font-size:var(--rs-font-size-body-2)!important}}@media (--rs-viewport-m ){.--size-small--m{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x1);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-medium--m{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x2);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-large--m{--rs-text-field-gap:var(--rs-unit-x3);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x3);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x2)}.--size-xlarge--m{--rs-text-field-gap:var(--rs-unit-x4);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x4);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x1)}}@media (--rs-viewport-l ){.--size-small--l{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x1);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-medium--l{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x2);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-large--l{--rs-text-field-gap:var(--rs-unit-x3);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x3);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x2)}.--size-xlarge--l{--rs-text-field-gap:var(--rs-unit-x4);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x4);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x1)}}@media (--rs-viewport-xl ){.--size-small--xl{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x1);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-medium--xl{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x2);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-large--xl{--rs-text-field-gap:var(--rs-unit-x3);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x3);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x2)}.--size-xlarge--xl{--rs-text-field-gap:var(--rs-unit-x4);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x4);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x1)}}
1
+ .root{--rs-p-h:var(--rs-text-field-gap);align-items:center;background:var(--rs-color-background-elevation-base);border:1px solid var(--rs-color-border-neutral);border-radius:var(--rs-text-field-radius);display:flex;gap:var(--rs-text-field-gap);padding:0 calc(var(--rs-text-field-gap) - 1px);position:relative;row-gap:var(--rs-unit-x1);z-index:0}.root.--focused,.root:has(label:active),.root:not(:has(button:focus,a:focus,[tabindex="0"]:focus,[role=button]:focus)):focus-within{border-color:var(--rs-color-border-primary);box-shadow:0 0 0 1px var(--rs-color-border-primary)}.root.--multiline{flex-wrap:wrap}.root.--multiline .input{width:auto}.root.--rounded{border-radius:999px}.root.--rounded .affix:first-child,.root.--rounded .icon:first-child{padding-inline-start:var(--rs-unit-x1)}.root.--rounded .input:first-child{padding-inline-start:calc(var(--rs-text-field-gap) + var(--rs-unit-x1))}.input{background:none;border:none;box-sizing:border-box;color:var(--rs-color-foreground-neutral);flex-grow:1;font-family:var(--rs-font-family-body);font-weight:var(--rs-font-weight-regular);margin:0 calc(var(--rs-text-field-gap) * -1);outline:none;padding-block:calc(var(--rs-text-field-p-v) - 1px);padding-inline:var(--rs-text-field-gap);position:relative;width:100%;z-index:1}.input:-webkit-autofill{-webkit-background-clip:text;-webkit-text-fill-color:var(--rs-color-foreground-neutral)}.affix,.input{font-size:var(--rs-text-field-font-size);letter-spacing:var(--rs-text-field-letter-spacing);line-height:var(--rs-text-field-line-height)}.affix,.icon{cursor:text}.affix,.icon,.slot{align-items:center;display:flex;flex-shrink:0;max-width:100%;min-height:calc(var(--rs-text-field-line-height) + var(--rs-unit-x2) - 2px);position:relative;z-index:5}.slot--position-end:last-child{margin-inline-end:calc(var(--rs-text-field-gap) * -1);padding-inline-end:var(--rs-text-field-action-inset)}.affix{color:var(--rs-color-foreground-neutral-faded)}.affix.affix--position-start{padding-inline-end:var(--rs-text-field-gap)}.affix.affix--position-start:after{border-inline-end:1px solid var(--rs-color-border-neutral-faded);content:"";inset-block:var(--rs-unit-x1);inset-inline-end:0;position:absolute}.affix.affix--position-end{padding-inline-start:var(--rs-text-field-gap)}.affix.affix--position-end:after{border-inline-start:1px solid var(--rs-color-border-neutral-faded);content:"";inset-block:var(--rs-unit-x1);inset-inline-start:0;position:absolute}.root.--disabled{background:var(--rs-color-background-disabled-faded);border-color:var(--rs-color-border-disabled)}.root.--disabled,.root.--disabled .input{color:var(--rs-color-foreground-disabled);cursor:not-allowed}.--size-small{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x1);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-medium{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x2);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-large{--rs-text-field-gap:var(--rs-unit-x3);--rs-text-field-radius:var(--rs-radius-medium);--rs-text-field-p-v:var(--rs-unit-x3);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x2)}.--size-xlarge{--rs-text-field-gap:var(--rs-unit-x4);--rs-text-field-radius:var(--rs-radius-medium);--rs-text-field-p-v:var(--rs-unit-x4);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x1)}.root.--variant-faded{background:var(--rs-color-background-neutral-faded);border-color:transparent}.root.--variant-faded.--focused,.root.--variant-faded:has(label:active),.root.--variant-faded:not(:has(button:focus,a:focus,[tabindex="0"]:focus,[role=button]:focus)):focus-within{border-color:var(--rs-color-border-primary)}.root.--variant-headless{background:transparent;border-color:transparent}.root.--variant-headless.--status-error,.root.--variant-headless.--status-error.--focused,.root.--variant-headless.--status-error:focus-within,.root.--variant-headless:focus-within{border-color:transparent;box-shadow:none}.root.--status-error{border-color:var(--rs-color-border-critical)}.root.--status-error.--focused,.root.--status-error:focus-within{border-color:var(--rs-color-border-primary)}@media (--rs-viewport-s ) and (hover:none){.input{font-size:var(--rs-font-size-body-2)!important}}@media (--rs-viewport-m ){.--size-small--m{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x1);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-medium--m{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x2);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-large--m{--rs-text-field-gap:var(--rs-unit-x3);--rs-text-field-radius:var(--rs-radius-medium);--rs-text-field-p-v:var(--rs-unit-x3);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x2)}.--size-xlarge--m{--rs-text-field-gap:var(--rs-unit-x4);--rs-text-field-radius:var(--rs-radius-medium);--rs-text-field-p-v:var(--rs-unit-x4);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x1)}}@media (--rs-viewport-l ){.--size-small--l{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x1);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-medium--l{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x2);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-large--l{--rs-text-field-gap:var(--rs-unit-x3);--rs-text-field-radius:var(--rs-radius-medium);--rs-text-field-p-v:var(--rs-unit-x3);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x2)}.--size-xlarge--l{--rs-text-field-gap:var(--rs-unit-x4);--rs-text-field-radius:var(--rs-radius-medium);--rs-text-field-p-v:var(--rs-unit-x4);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x1)}}@media (--rs-viewport-xl ){.--size-small--xl{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x1);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-medium--xl{--rs-text-field-gap:var(--rs-unit-x2);--rs-text-field-radius:var(--rs-radius-small);--rs-text-field-p-v:var(--rs-unit-x2);--rs-text-field-font-size:var(--rs-font-size-body-3);--rs-text-field-line-height:var(--rs-line-height-body-3);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-3);--rs-text-field-action-inset:var(--rs-unit-x1)}.--size-large--xl{--rs-text-field-gap:var(--rs-unit-x3);--rs-text-field-radius:var(--rs-radius-medium);--rs-text-field-p-v:var(--rs-unit-x3);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x2)}.--size-xlarge--xl{--rs-text-field-gap:var(--rs-unit-x4);--rs-text-field-radius:var(--rs-radius-medium);--rs-text-field-p-v:var(--rs-unit-x4);--rs-text-field-font-size:var(--rs-font-size-body-2);--rs-text-field-line-height:var(--rs-line-height-body-2);--rs-text-field-letter-spacing:var(--rs-letter-spacing-body-2);--rs-text-field-action-inset:var(--rs-unit-x1)}}
@@ -59,9 +59,9 @@ const ToastContainer = (props) => {
59
59
  React.useEffect(() => {
60
60
  if (!wrapperRef.current)
61
61
  return;
62
- const trapFocus = new TrapFocus(wrapperRef.current);
62
+ const trapFocus = new TrapFocus();
63
63
  if (visible) {
64
- trapFocus.trap({
64
+ trapFocus.trap(wrapperRef.current, {
65
65
  includeTrigger: true,
66
66
  mode: "content-menu",
67
67
  });
@@ -231,8 +231,8 @@ const FlyoutControlled = (props) => {
231
231
  return;
232
232
  if (trapFocusRef.current?.trapped)
233
233
  return;
234
- trapFocusRef.current = new TrapFocus(flyoutElRef.current);
235
- trapFocusRef.current.trap({
234
+ trapFocusRef.current = new TrapFocus();
235
+ trapFocusRef.current.trap(flyoutElRef.current, {
236
236
  mode: trapFocusMode,
237
237
  initialFocusEl: initialFocusRef?.current,
238
238
  includeTrigger: triggerType === "hover" && trapFocusMode !== "dialog" && !isSubmenu,
@@ -1,5 +1,4 @@
1
1
  import Chain from "../Chain";
2
- import TrapScreenReader from "./TrapScreenReader";
3
2
  import type { FocusableElement, TrapMode } from "./types";
4
3
  type ReleaseOptions = {
5
4
  withoutFocusReturn?: boolean;
@@ -11,28 +10,15 @@ type TrapOptions = {
11
10
  mode?: TrapMode;
12
11
  };
13
12
  declare class TrapFocus {
13
+ #private;
14
14
  static chain: Chain<TrapFocus>;
15
- chainId?: number;
16
- root: HTMLElement;
17
- trigger: FocusableElement | null;
18
- options: TrapOptions & {
19
- pseudoFocus?: boolean;
20
- };
21
15
  trapped?: boolean;
22
- screenReaderTrap: TrapScreenReader;
23
- mutationObserver: MutationObserver | null;
24
- constructor(root: HTMLElement);
25
- /**
26
- * Handle keyboard navigation while focus is trapped
27
- */
28
- handleKeyDown: (event: KeyboardEvent) => void;
29
- addListeners: () => void;
30
- removeListeners: () => void;
16
+ constructor();
31
17
  /**
32
18
  * Trap the focus, add observer and keyboard event listeners
33
19
  * and create a chain item
34
20
  */
35
- trap: (options?: TrapOptions) => void;
21
+ trap: (root: HTMLElement, options?: TrapOptions) => void;
36
22
  /**
37
23
  * Disabled the trap focus for the element,
38
24
  * cleanup all observers/handlers and trap for the previous element in the chain
@@ -1,3 +1,4 @@
1
+ var _a;
1
2
  import Chain from "../Chain.js";
2
3
  import * as keys from "../../constants/keys.js";
3
4
  import TrapScreenReader from "./TrapScreenReader.js";
@@ -6,26 +7,25 @@ import { getShadowRoot } from "../dom/index.js";
6
7
  import { checkKeyboardMode } from "./keyboardMode.js";
7
8
  class TrapFocus {
8
9
  static chain = new Chain();
9
- chainId;
10
- root;
11
- trigger = null;
12
- options = {};
10
+ #chainId;
11
+ #root = null;
12
+ #trigger = null;
13
+ #options = {};
13
14
  trapped;
14
- screenReaderTrap;
15
- mutationObserver = null;
16
- constructor(root) {
17
- this.root = root;
18
- this.screenReaderTrap = new TrapScreenReader(root);
19
- }
15
+ #screenReaderTrap = null;
16
+ #mutationObserver = null;
17
+ constructor() { }
20
18
  /**
21
19
  * Handle keyboard navigation while focus is trapped
22
20
  */
23
- handleKeyDown = (event) => {
21
+ #handleKeyDown = (event) => {
24
22
  if (event.defaultPrevented)
25
23
  return;
26
- if (TrapFocus.chain.tailId !== this.chainId)
24
+ if (_a.chain.tailId !== this.#chainId)
27
25
  return;
28
- const { mode, onRelease, pseudoFocus, includeTrigger } = this.options;
26
+ if (!this.#root)
27
+ return;
28
+ const { mode, onRelease, pseudoFocus, includeTrigger } = this.#options;
29
29
  let navigationMode = "tabs";
30
30
  if (mode === "action-menu" || mode === "selection-menu" || mode === "action-bar") {
31
31
  navigationMode = "arrows";
@@ -39,12 +39,12 @@ class TrapFocus {
39
39
  const isNextArrow = navigationMode === "arrows" && key === (mode === "action-bar" ? keys.RIGHT : keys.DOWN);
40
40
  const isPrev = (isPrevTab && navigationMode === "tabs") || isPrevArrow;
41
41
  const isNext = (isNextTab && navigationMode === "tabs") || isNextArrow;
42
- const isFocusedOnTrigger = getActiveElement(this.root) === this.trigger;
42
+ const isFocusedOnTrigger = getActiveElement(this.#root) === this.#trigger;
43
43
  const focusData = getFocusData({
44
- root: this.root,
44
+ root: this.#root,
45
45
  target: isPrev ? "prev" : "next",
46
46
  options: {
47
- additionalElement: includeTrigger ? this.trigger : undefined,
47
+ additionalElement: includeTrigger ? this.#trigger : undefined,
48
48
  circular: mode !== "action-menu" && mode !== "action-bar",
49
49
  },
50
50
  });
@@ -70,53 +70,57 @@ class TrapFocus {
70
70
  return;
71
71
  focusElement(focusData.el, { pseudoFocus });
72
72
  };
73
- addListeners = () => {
74
- const shadowRoot = getShadowRoot(this.root);
73
+ #addListeners = () => {
74
+ const shadowRoot = getShadowRoot(this.#root);
75
75
  const el = shadowRoot ?? document;
76
- el.addEventListener("keydown", this.handleKeyDown);
76
+ el.addEventListener("keydown", this.#handleKeyDown);
77
77
  };
78
- removeListeners = () => {
79
- const shadowRoot = getShadowRoot(this.root);
78
+ #removeListeners = () => {
79
+ const shadowRoot = getShadowRoot(this.#root);
80
80
  const el = shadowRoot ?? document;
81
- el.removeEventListener("keydown", this.handleKeyDown);
81
+ el.removeEventListener("keydown", this.#handleKeyDown);
82
82
  };
83
83
  /**
84
84
  * Trap the focus, add observer and keyboard event listeners
85
85
  * and create a chain item
86
86
  */
87
- trap = (options = {}) => {
87
+ trap = (root, options = {}) => {
88
88
  const { mode = "dialog", includeTrigger, initialFocusEl } = options;
89
- const trigger = getActiveElement(this.root);
90
- const focusable = getFocusableElements(this.root, {
89
+ this.#root = root;
90
+ this.#screenReaderTrap = new TrapScreenReader(root);
91
+ const trigger = getActiveElement(this.#root);
92
+ const focusable = getFocusableElements(this.#root, {
91
93
  additionalElement: includeTrigger ? trigger : undefined,
92
94
  });
93
95
  const pseudoFocus = mode === "selection-menu";
94
- this.options = { ...options, pseudoFocus };
95
- this.trigger = trigger;
96
- this.mutationObserver = new MutationObserver(() => {
97
- const currentActiveElement = getActiveElement(this.root);
96
+ this.#options = { ...options, pseudoFocus };
97
+ this.#trigger = trigger;
98
+ this.#mutationObserver = new MutationObserver(() => {
99
+ if (!this.#root)
100
+ return;
101
+ const currentActiveElement = getActiveElement(this.#root);
98
102
  // Focus stayed inside the wrapper, no need to refocus
99
- if (this.root.contains(currentActiveElement))
103
+ if (this.#root.contains(currentActiveElement))
100
104
  return;
101
- const focusable = getFocusableElements(this.root, {
105
+ const focusable = getFocusableElements(this.#root, {
102
106
  additionalElement: includeTrigger ? trigger : undefined,
103
107
  });
104
108
  if (!focusable.length)
105
109
  return;
106
110
  focusElement(focusable[0], { pseudoFocus });
107
111
  });
108
- this.removeListeners();
109
- this.mutationObserver.observe(this.root, { childList: true, subtree: true });
112
+ this.#removeListeners();
113
+ this.#mutationObserver.observe(this.#root, { childList: true, subtree: true });
110
114
  // Don't trap in case there is nothing to focus inside
111
115
  if (!focusable.length && !initialFocusEl)
112
116
  return;
113
- this.addListeners();
117
+ this.#addListeners();
114
118
  if (mode === "dialog")
115
- this.screenReaderTrap.trap();
119
+ this.#screenReaderTrap.trap();
116
120
  // Don't add back to the chain if we're traversing back
117
- const tailItem = TrapFocus.chain.tailId && TrapFocus.chain.get(TrapFocus.chain.tailId);
118
- if (!tailItem || this.root !== tailItem.data.root) {
119
- this.chainId = TrapFocus.chain.add(this);
121
+ const tailItem = _a.chain.tailId && _a.chain.get(_a.chain.tailId);
122
+ if (!tailItem || this.#root !== tailItem.data.#root) {
123
+ this.#chainId = _a.chain.add(this);
120
124
  focusElement(initialFocusEl || focusable[0], { pseudoFocus });
121
125
  }
122
126
  this.trapped = true;
@@ -127,21 +131,22 @@ class TrapFocus {
127
131
  */
128
132
  release = (releaseOptions = {}) => {
129
133
  const { withoutFocusReturn } = releaseOptions;
130
- if (!this.trapped || !this.chainId)
134
+ if (!this.trapped || !this.#chainId || !this.#root)
131
135
  return;
132
136
  this.trapped = false;
133
- if (this.trigger && !withoutFocusReturn) {
134
- this.trigger.focus({ preventScroll: !checkKeyboardMode() });
137
+ if (this.#trigger && !withoutFocusReturn) {
138
+ this.#trigger.focus({ preventScroll: !checkKeyboardMode() });
135
139
  }
136
- TrapFocus.chain.removePreviousTill(this.chainId, (item) => document.body.contains(item.data.trigger));
137
- this.mutationObserver?.disconnect();
138
- this.removeListeners();
139
- this.screenReaderTrap.release();
140
- const previousItem = TrapFocus.chain.tailId && TrapFocus.chain.get(TrapFocus.chain.tailId);
141
- if (previousItem) {
142
- const trapInstance = new TrapFocus(previousItem.data.root);
143
- trapInstance.trap(previousItem.data.options);
140
+ _a.chain.removePreviousTill(this.#chainId, (item) => document.body.contains(item.data.#trigger));
141
+ this.#mutationObserver?.disconnect();
142
+ this.#removeListeners();
143
+ this.#screenReaderTrap?.release();
144
+ const previousItem = _a.chain.tailId && _a.chain.get(_a.chain.tailId);
145
+ if (previousItem && previousItem.data.#root) {
146
+ const trapInstance = new _a();
147
+ trapInstance.trap(previousItem.data.#root, previousItem.data.#options);
144
148
  }
145
149
  };
146
150
  }
151
+ _a = TrapFocus;
147
152
  export default TrapFocus;