npm package: @slithy/layers
Description: Layer and z-index management for React UIs.
Author: Matthew Campagna
Latest version: 0.4.0

# @slithy/layers

Layer and z-index management for React UIs. Tracks a stack of mounted layers and determines which is "active" (highest priority). Useful for managing focus, keyboard interactions, and visual stacking of overlaid components like modals and drawers.

## Installation

```bash
npm install @slithy/layers
```

**Peer dependencies:** `react@^17 || ^18 || ^19`

---

## `LayerProvider`

Wraps a component to register it in the global layer stack. On mount, the layer is added to the stack; on unmount, it is removed.

```tsx
import { LayerProvider, LayerStackPriority } from "@slithy/layers";

<LayerProvider id="my-modal" zIndex={LayerStackPriority.Modal}>
  <MyModal />
</LayerProvider>;
```

**Props:**

| Prop       | Type        | Default        | Description                                      |
| ---------- | ----------- | -------------- | ------------------------------------------------ |
| `id`       | `string`    | auto-generated | Unique identifier for this layer                 |
| `zIndex`   | `number`    | `0`            | Priority in the stack — higher wins              |
| `isActive` | `boolean`   | `true`         | If `false`, layer is not registered in the stack |
| `children` | `ReactNode` | —              |                                                  |

---

## `useLayerState`

Hook to read state from the nearest `LayerProvider`. Must be called within a `LayerProvider`.

```tsx
// Selector form — returns selected value, re-renders only on change
const layerIsActive = useLayerState((s) => s.layerIsActive);

// No-arg form — returns full store object
const { getState, setState } = useLayerState();
```

**Store shape (`LayerStore`):**

```ts
type LayerStore = {
  layerId: string;
  layerIsActive: boolean; // true when this layer has the highest priority
  zIndex: number;
};
```

---

## `useLayer`

Convenience hook to read the current layer's ID and zIndex from the nearest `LayerProvider`. Must be called within a `LayerProvider`.

```tsx
import { useLayer } from "@slithy/layers";

const { layerId, layerZIndex } = useLayer();
```

Returns:

```ts
{
  layerId: string;      // ID of the current layer
  layerZIndex: number;  // zIndex of the current layer
}
```

---

## `useLayerStackStore`

Reactive hook for reading the global layer stack store. Call with a selector to get reactive updates whenever the layer stack changes.

```ts
import { useLayerStackStore } from "@slithy/layers";

// Selector form — re-renders only when the selected value changes
const activeLayerId = useLayerStackStore((state) => state.activeLayerId);

// Full store object — returns current state
const { activeLayerId, layers } = useLayerStackStore((state) => state);
```

For imperative access (outside React components or in effects):

```ts
// Read current state
const { activeLayerId, layers } = useLayerStackStore.getState();

// Subscribe to changes
const unsubscribe = useLayerStackStore.subscribe(() => {
  const { activeLayerId } = useLayerStackStore.getState();
});
```

---

## `useActiveLayer`

Convenience hook to read the active (topmost) layer's ID and zIndex from the global layer stack.

```tsx
import { useActiveLayer } from "@slithy/layers";

const { activeLayerId, activeZIndex } = useActiveLayer();
```

Returns:

```ts
{
  activeLayerId: string;  // ID of the layer with highest priority
  activeZIndex: number;   // zIndex of the active layer
}
```

---

## `createLayerPriorities`

Factory for defining a custom set of layer priorities. Returns a frozen readonly object.

```ts
import { createLayerPriorities } from '@slithy/layers'

const MyPriorities = createLayerPriorities({
  App: 0,
  Overlay: 5,
  Toast: 10,
})

<LayerProvider zIndex={MyPriorities.Toast}>
  <ToastStack />
</LayerProvider>
```

---

## `LayerStackPriority`

The built-in default priority set, defined with `createLayerPriorities`:

```ts
const LayerStackPriority = createLayerPriorities({
  App: 0,
  Modal: 1,
  Toasts: 2,
});
```

---

## `MockLayerProvider`

A test utility that provides a mock layer context with hardcoded values. Use this to render components that depend on `LayerProvider` without needing a real stack.

```tsx
import { MockLayerProvider } from "@slithy/layers";

render(
  <MockLayerProvider>
    <ComponentUnderTest />
  </MockLayerProvider>,
);
```