Skip to content

Commit

Permalink
(focus-trap) Add isBuilt to the return value
Browse files Browse the repository at this point in the history
  • Loading branch information
DaviDevMod committed May 29, 2023
1 parent 3738fc2 commit f70f79b
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 23 deletions.
5 changes: 5 additions & 0 deletions .changeset/great-flies-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@davidevmod/focus-trap': major
---

Add `isBuilt` to the return value.
32 changes: 12 additions & 20 deletions packages/focus-trap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,39 +133,31 @@ They are pretty straightforward, calling `focusTrap` with `"PAUSE"`, `"RESUME"`

## Return value

An object being a shallow copy of the `NormalisedTrapConfig` used internally by the focus trap.
That is the provided `TrapConfig` with IDs resolved to actual elements and default values set.

<details>
<summary>Here is a comparison:</summary>

<br>
An object of type `TrapState`:

```ts
type Focusable = HTMLElement | SVGElement;

type Roots = (Focusable | string)[];

// The shape of the config expected from you.
interface TrapConfig {
roots: Roots;
initialFocus?: boolean | Focusable | string;
returnFocus?: boolean | Focusable | string;
lock?: boolean | Function;
escape?: boolean;
}

// The shape of the returned config.
interface NormalisedTrapConfig {
roots: Focusable[];
initialFocus: boolean | Focusable;
returnFocus: Focusable | null;
lock: boolean | Function;
escape: boolean;
}

interface TrapState {
isBuilt: boolean;
config: NormalisedTrapConfig;
}
```

</details>
Where `isBuilt` tells whether a trap has been built and not demolished yet, while `NormalisedTrapConfig` is a shallow copy of the config used internally by the library and basically is the provided `TrapConfig` with IDs resolved to actual elements and default values set.

> **Note**
> The normalised `roots` are updated at every <kbd>Tab</kbd> key press to account for any relevant mutaion (eg: elements attached to or detached from the DOM) so they only represent a snapshot of an ever changing array of elements.
This value is rarely useful, it may be used to eg: implement a [stack](<https://en.wikipedia.org/wiki/Stack_(abstract_data_type)>) of focus traps.

## Dependencies & Browser Support

Expand Down
12 changes: 9 additions & 3 deletions packages/focus-trap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ type TrapAction = 'RESUME' | 'DEMOLISH' | 'PAUSE';

type TrapArg = Roots | TrapConfig | TrapAction;

export const focusTrap = (arg: TrapArg) => {
interface TrapState {
isBuilt: boolean;
config: NormalisedTrapConfig;
}

export const focusTrap = (arg: TrapArg): TrapState => {
const result =
typeof arg === 'string'
? arg === 'DEMOLISH'
Expand All @@ -18,7 +23,8 @@ export const focusTrap = (arg: TrapArg) => {

if (result.isErr) throw new Error(result.error);

return { ...state.normalisedConfig } as NormalisedTrapConfig;
// If !state.normalisedConfig, result.isErr === true; and this line is unreachable.
return { isBuilt: state.isBuilt, config: { ...state.normalisedConfig! } };
};

export type { TrapArg, Roots, TrapConfig, TrapAction, NormalisedTrapConfig };
export type { TrapArg, Roots, TrapConfig, TrapAction, TrapState, NormalisedTrapConfig };

0 comments on commit f70f79b

Please sign in to comment.