@structyl/core 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 your-lib contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # @structyl/core
2
+
3
+ > Headless React primitives that power the structyl component library.
4
+
5
+ ![npm](https://img.shields.io/npm/v/@structyl/core)
6
+ ![license](https://img.shields.io/npm/l/@structyl/core)
7
+
8
+ `@structyl/core` is the low-level foundation underneath every styled component in [structyl](https://structyl.dev). It provides the unstyled, accessible building blocks — polymorphic elements, the `asChild` slot pattern, scoped contexts, focus management, presence/animation handling, and Floating UI–based positioning. If you are building your own headless components (or extending structyl), this is the package you compose from; most app authors will consume `@structyl/primitives` or `@structyl/styled` instead.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ # pnpm
14
+ pnpm add @structyl/core
15
+
16
+ # npm
17
+ npm install @structyl/core
18
+
19
+ # yarn
20
+ yarn add @structyl/core
21
+ ```
22
+
23
+ `react` and `react-dom` (v18 or v19) are peer dependencies.
24
+
25
+ ## Usage
26
+
27
+ Build a polymorphic, accessible primitive using `Primitive` (with built-in `asChild`) and a typed context created with `createContext`:
28
+
29
+ ```tsx
30
+ 'use client';
31
+
32
+ import * as React from 'react';
33
+ import { Primitive, createContext } from '@structyl/core';
34
+
35
+ interface ToggleContextValue {
36
+ pressed: boolean;
37
+ onToggle: () => void;
38
+ }
39
+
40
+ const [ToggleProvider, useToggleContext] = createContext<ToggleContextValue>('Toggle');
41
+
42
+ function Toggle({ children }: { children: React.ReactNode }) {
43
+ const [pressed, setPressed] = React.useState(false);
44
+ return (
45
+ <ToggleProvider pressed={pressed} onToggle={() => setPressed((p) => !p)}>
46
+ {children}
47
+ </ToggleProvider>
48
+ );
49
+ }
50
+
51
+ const ToggleButton = React.forwardRef<
52
+ HTMLButtonElement,
53
+ React.ComponentPropsWithRef<typeof Primitive.button>
54
+ >((props, ref) => {
55
+ const { pressed, onToggle } = useToggleContext('ToggleButton');
56
+ return (
57
+ <Primitive.button
58
+ ref={ref}
59
+ type="button"
60
+ aria-pressed={pressed}
61
+ data-state={pressed ? 'on' : 'off'}
62
+ onClick={onToggle}
63
+ {...props}
64
+ />
65
+ );
66
+ });
67
+ ToggleButton.displayName = 'ToggleButton';
68
+
69
+ // `asChild` renders the behavior on your own element instead of a <button>:
70
+ // <ToggleButton asChild><MyLink href="/" /></ToggleButton>
71
+ ```
72
+
73
+ ## Features
74
+
75
+ - **Polymorphic `Primitive`** — render `Primitive.button`, `Primitive.div`, etc., with first-class ref forwarding and an `asChild` prop on every node.
76
+ - **`Slot` / `Slottable`** — merge props, class names, styles, and event handlers onto a consumer-supplied child to implement `asChild`.
77
+ - **Typed contexts** — `createContext`, `createContextScope`, and `composeContextScopes` give descriptive errors outside a provider and avoid context leakage in nested or shared component families.
78
+ - **Focus management** — `FocusScope` traps and loops focus, and `useFocusGuards` inserts sentinel guards so Tab cannot escape an open layer.
79
+ - **Layer dismissal** — `DismissableLayer` handles Escape, outside-pointer, and outside-focus interactions for popovers, dialogs, and menus.
80
+ - **Presence & animation** — `Presence` / `usePresence` keep an element mounted until its exit CSS animation or transition finishes.
81
+ - **Positioning** — the `Popper` namespace wraps `@floating-ui/react` for anchored content with flip, shift, size, and arrow support.
82
+ - **Roving focus & collections** — `RovingFocusGroup` and `createCollection` provide arrow-key navigation over DOM-ordered items.
83
+ - **Accessibility helpers** — `VisuallyHidden`, `AccessibleIcon`, and `DirectionProvider` / `useDirection` for screen-reader labels and RTL awareness.
84
+ - **SSR-safe** — all browser access is guarded; primitives are marked `'use client'` and work in the Next.js App Router.
85
+
86
+ ## API
87
+
88
+ | Export | Kind | Description |
89
+ | --- | --- | --- |
90
+ | `Primitive` | Components | Polymorphic elements (`button`, `div`, `span`, …) with `asChild` and ref forwarding. |
91
+ | `Slot`, `Slottable` | Component | Render a child with merged props; the engine behind `asChild`. |
92
+ | `createContext` | Function | Create a typed context that throws a helpful error outside its provider. |
93
+ | `createContextScope` | Function | Create a scoped context factory to prevent leakage across nested/shared families. |
94
+ | `composeContextScopes` | Function | Merge multiple scope factories into one. |
95
+ | `Portal` | Component | Render children into a container (defaults to `document.body`). |
96
+ | `Presence`, `usePresence` | Component / Hook | Defer unmount until exit animations complete. |
97
+ | `FocusScope` | Component | Trap, loop, and restore focus within a region. |
98
+ | `useFocusGuards` | Hook | Inject focus sentinel guards around the document body. |
99
+ | `DismissableLayer` | Component | Handle Escape and outside pointer/focus dismissal. |
100
+ | `RovingFocusGroup` | Component | Arrow-key roving tabindex navigation. |
101
+ | `createCollection` | Function | Track child items in DOM order. |
102
+ | `Popper` | Namespace | `Popper`, `Popper.Anchor`, `Popper.Content`, `Popper.Arrow` (Floating UI). |
103
+ | `Arrow` | Component | Standalone SVG arrow primitive. |
104
+ | `VisuallyHidden` | Component | Hide content visually while keeping it accessible. |
105
+ | `AccessibleIcon` | Component | Decorate an icon with an `aria-hidden` element and a hidden label. |
106
+ | `DirectionProvider`, `useDirection` | Component / Hook | Provide and read text direction (`ltr` / `rtl`). |
107
+ | `useScrollLock` | Hook | Lock body scroll without layout shift (reference-counted). |
108
+
109
+ Type definitions are exported alongside each component (e.g. `PrimitivePropsWithRef`, `SlotProps`, `PortalProps`, `PresenceProps`, `Direction`).
110
+
111
+ ## Part of structyl
112
+
113
+ This package is part of [structyl](https://github.com/imirfanul/structyl) — the React UI library with structure. See the full documentation at [structyl.dev](https://structyl.dev).
114
+
115
+ ## License
116
+
117
+ MIT