sherick-ui 2.0.0 → 2.1.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/README.md +55 -199
- package/dist/cjs/components/Breadcrumb.cjs +47 -0
- package/dist/cjs/components/Breadcrumb.cjs.map +1 -0
- package/dist/cjs/components/Calendar.cjs +298 -0
- package/dist/cjs/components/Calendar.cjs.map +1 -0
- package/dist/cjs/components/Combobox.cjs +1 -1
- package/dist/cjs/components/Combobox.cjs.map +1 -1
- package/dist/cjs/components/Command.cjs +81 -0
- package/dist/cjs/components/Command.cjs.map +1 -0
- package/dist/cjs/components/CommandPalette.cjs +52 -0
- package/dist/cjs/components/CommandPalette.cjs.map +1 -0
- package/dist/cjs/components/DatePicker.cjs +107 -0
- package/dist/cjs/components/DatePicker.cjs.map +1 -0
- package/dist/cjs/components/DateRangePicker.cjs +165 -0
- package/dist/cjs/components/DateRangePicker.cjs.map +1 -0
- package/dist/cjs/components/FileUpload.cjs +203 -0
- package/dist/cjs/components/FileUpload.cjs.map +1 -0
- package/dist/cjs/components/Media.cjs +27 -0
- package/dist/cjs/components/Media.cjs.map +1 -0
- package/dist/cjs/components/Pagination.cjs +115 -0
- package/dist/cjs/components/Pagination.cjs.map +1 -0
- package/dist/cjs/components/Select.cjs +1 -1
- package/dist/cjs/components/Select.cjs.map +1 -1
- package/dist/cjs/components/Stepper.cjs +40 -0
- package/dist/cjs/components/Stepper.cjs.map +1 -0
- package/dist/cjs/components/Tabs.cjs +1 -1
- package/dist/cjs/components/Tabs.cjs.map +1 -1
- package/dist/cjs/components/TreeView.cjs +247 -0
- package/dist/cjs/components/TreeView.cjs.map +1 -0
- package/dist/cjs/components/date-family.cjs +191 -0
- package/dist/cjs/components/date-family.cjs.map +1 -0
- package/dist/cjs/components/date-field.cjs +90 -0
- package/dist/cjs/components/date-field.cjs.map +1 -0
- package/dist/cjs/components/fileUpload.rules.cjs +121 -0
- package/dist/cjs/components/fileUpload.rules.cjs.map +1 -0
- package/dist/cjs/components/tree.cjs +95 -0
- package/dist/cjs/components/tree.cjs.map +1 -0
- package/dist/cjs/components/ui.common.cjs +27 -7
- package/dist/cjs/components/ui.common.cjs.map +1 -1
- package/dist/cjs/components/ui.motion.cjs +3 -3
- package/dist/cjs/components/ui.motion.cjs.map +1 -1
- package/dist/cjs/dev.cjs +5 -0
- package/dist/cjs/dev.cjs.map +1 -1
- package/dist/cjs/index.cjs +22 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/components/Breadcrumb.js +43 -0
- package/dist/esm/components/Breadcrumb.js.map +1 -0
- package/dist/esm/components/Calendar.js +294 -0
- package/dist/esm/components/Calendar.js.map +1 -0
- package/dist/esm/components/Combobox.js +2 -2
- package/dist/esm/components/Combobox.js.map +1 -1
- package/dist/esm/components/Command.js +77 -0
- package/dist/esm/components/Command.js.map +1 -0
- package/dist/esm/components/CommandPalette.js +48 -0
- package/dist/esm/components/CommandPalette.js.map +1 -0
- package/dist/esm/components/DatePicker.js +103 -0
- package/dist/esm/components/DatePicker.js.map +1 -0
- package/dist/esm/components/DateRangePicker.js +161 -0
- package/dist/esm/components/DateRangePicker.js.map +1 -0
- package/dist/esm/components/FileUpload.js +199 -0
- package/dist/esm/components/FileUpload.js.map +1 -0
- package/dist/esm/components/Media.js +25 -0
- package/dist/esm/components/Media.js.map +1 -0
- package/dist/esm/components/Pagination.js +111 -0
- package/dist/esm/components/Pagination.js.map +1 -0
- package/dist/esm/components/Select.js +2 -2
- package/dist/esm/components/Select.js.map +1 -1
- package/dist/esm/components/Stepper.js +36 -0
- package/dist/esm/components/Stepper.js.map +1 -0
- package/dist/esm/components/Tabs.js +2 -2
- package/dist/esm/components/Tabs.js.map +1 -1
- package/dist/esm/components/TreeView.js +243 -0
- package/dist/esm/components/TreeView.js.map +1 -0
- package/dist/esm/components/date-family.js +173 -0
- package/dist/esm/components/date-family.js.map +1 -0
- package/dist/esm/components/date-field.js +84 -0
- package/dist/esm/components/date-field.js.map +1 -0
- package/dist/esm/components/fileUpload.rules.js +114 -0
- package/dist/esm/components/fileUpload.rules.js.map +1 -0
- package/dist/esm/components/tree.js +88 -0
- package/dist/esm/components/tree.js.map +1 -0
- package/dist/esm/components/ui.common.js +23 -8
- package/dist/esm/components/ui.common.js.map +1 -1
- package/dist/esm/components/ui.motion.js +3 -3
- package/dist/esm/components/ui.motion.js.map +1 -1
- package/dist/esm/dev.js +1 -1
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/styles.css +362 -20
- package/dist/theme.css +15 -9
- package/dist/types/dev.d.cts +8 -3
- package/dist/types/dev.d.ts +8 -3
- package/dist/types/index.d.cts +600 -66
- package/dist/types/index.d.ts +600 -66
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,228 +1,84 @@
|
|
|
1
1
|
# Sherick UI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A React 18/19 component library with soft tonal surfaces, deliberate shape contrast
|
|
4
|
+
and restrained motion. `2.0.0` established the stable line; `1.x` is frozen.
|
|
5
|
+
This package source is `2.1.0`; verified `main` stages new versions via npm trusted
|
|
6
|
+
publishing for maintainer approval. Check the installed version for availability.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
+
## Install and style
|
|
8
9
|
|
|
9
10
|
```bash
|
|
10
11
|
npm install sherick-ui
|
|
11
12
|
```
|
|
12
13
|
|
|
13
|
-
Import the complete stylesheet once near your application root. Load framework/Tailwind/reset CSS first, then Sherick UI:
|
|
14
|
-
|
|
15
14
|
```tsx
|
|
16
|
-
import "./app.css";
|
|
15
|
+
import "./app.css"; // framework, reset or Tailwind CSS first
|
|
17
16
|
import "sherick-ui/styles.css";
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
The
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
No host reset is required: native controls and border-box geometry are normalized only on Sherick-owned nodes. Keyframes and math font families are namespaced; unrelated host elements and consumer children remain untouched.
|
|
27
|
-
|
|
28
|
-
## Writing direction
|
|
29
|
-
|
|
30
|
-
For an RTL application, set `<html dir="rtl">` and wrap the React tree with
|
|
31
|
-
`<DirectionProvider direction="rtl">` imported from `sherick-ui`. Keep both values in
|
|
32
|
-
sync when changing locale. The provider adds no DOM; it gives keyboard navigation and
|
|
33
|
-
portaled positioning the same direction as CSS. Consumers never import Base UI.
|
|
34
|
-
`Drawer` sides remain physical; `CodeBlock` source remains left-to-right.
|
|
35
|
-
|
|
36
|
-
## Themes
|
|
37
|
-
|
|
38
|
-
Theme selection is CSS-only:
|
|
39
|
-
|
|
40
|
-
```ts
|
|
41
|
-
// Force light
|
|
42
|
-
document.documentElement.dataset.sherickTheme = "light";
|
|
43
|
-
|
|
44
|
-
// Force dark
|
|
45
|
-
document.documentElement.dataset.sherickTheme = "dark";
|
|
46
|
-
|
|
47
|
-
// Follow prefers-color-scheme
|
|
48
|
-
document.documentElement.removeAttribute("data-sherick-theme");
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Custom themes override the documented `--sui-*` CSS variables at document/root level:
|
|
52
|
-
|
|
53
|
-
```css
|
|
54
|
-
:root {
|
|
55
|
-
--sui-primary: 0.50 0.17 255;
|
|
56
|
-
--sui-primary-strong: 0.47 0.19 257;
|
|
57
|
-
--sui-on-primary: 0.985 0.005 255;
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
`styles.css` includes both component styling and the generated light/dark/system token defaults. `theme.css` is also exported separately for token-only consumers.
|
|
62
|
-
|
|
63
|
-
## Runtime and browser support
|
|
64
|
-
|
|
65
|
-
Sherick UI supports React and React DOM 18 or 19. Its automated browser baseline is the Chromium,
|
|
66
|
-
Firefox and WebKit versions shipped by the repository's pinned Playwright release. Chrome, Edge and
|
|
67
|
-
Safari distribution builds and previous browser majors are not separately certified. The core package
|
|
68
|
-
has ESM and CommonJS entries; the rich-content subpath is ESM-only.
|
|
19
|
+
The complete stylesheet is precompiled, scoped and reset-free. No consumer Tailwind
|
|
20
|
+
configuration or package-content scan is needed. Load a dedicated selector-level
|
|
21
|
+
app override stylesheet **after** Sherick if required; `className` utility overrides
|
|
22
|
+
are merged by the components. `sherick-ui/theme.css` is also available for token-only
|
|
23
|
+
applications. See the [styling contract](https://github.com/Sherick16/sherick-ui/blob/main/docs/RELEASE.md#styling-import-contract).
|
|
69
24
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
The editable `Combobox` blocker is resolved by a version-specific patch to Base UI's own isolation
|
|
73
|
-
utility. The patch uses Base's focusability model to suppress every radio in a native group, observes
|
|
74
|
-
hidden subtrees for the full open lifetime, restores prior values on close and preserves non-modal
|
|
75
|
-
outside pointer interaction. The audited Base UI package is bundled so installed npm consumers receive
|
|
76
|
-
the same fix. It may be retired only after a released Base UI version passes the same axe,
|
|
77
|
-
live-mutation, restoration and pointer-interaction gates.
|
|
78
|
-
The repository's `docs/RELEASE.md` records the complete evidence and release condition.
|
|
79
|
-
|
|
80
|
-
## Usage
|
|
25
|
+
## Use
|
|
81
26
|
|
|
82
27
|
```tsx
|
|
83
|
-
import { Button,
|
|
84
|
-
import "sherick-ui/styles.css";
|
|
28
|
+
import { Button, Field, Input, Select } from "sherick-ui";
|
|
85
29
|
|
|
86
30
|
export function Example() {
|
|
87
31
|
return (
|
|
88
32
|
<>
|
|
89
33
|
<Input label="Email" name="email" type="email" required />
|
|
90
|
-
<
|
|
91
|
-
options={[
|
|
34
|
+
<Field label="Project">
|
|
35
|
+
<Select options={[
|
|
92
36
|
{ label: "Design system", value: "design" },
|
|
93
37
|
{ label: "Dashboard", value: "dashboard" },
|
|
94
|
-
]}
|
|
95
|
-
defaultValue="design"
|
|
96
|
-
/>
|
|
97
|
-
<Field label="Project">
|
|
98
|
-
<Combobox
|
|
99
|
-
options={[
|
|
100
|
-
{ label: "Design system", value: "design" },
|
|
101
|
-
{ label: "Dashboard", value: "dashboard" },
|
|
102
|
-
]}
|
|
103
|
-
defaultValue="design"
|
|
104
|
-
/>
|
|
38
|
+
]} defaultValue="design" />
|
|
105
39
|
</Field>
|
|
106
|
-
<Menu>
|
|
107
|
-
<Menu.Trigger render={<Button appearance="tonal">Actions</Button>} />
|
|
108
|
-
<Menu.Content>
|
|
109
|
-
<Menu.Item>Rename</Menu.Item>
|
|
110
|
-
<Menu.Item variant="danger">Delete</Menu.Item>
|
|
111
|
-
</Menu.Content>
|
|
112
|
-
</Menu>
|
|
113
40
|
<Button appearance="filled">Save</Button>
|
|
114
|
-
<Dialog defaultOpen>
|
|
115
|
-
<Dialog.Header>Example dialog</Dialog.Header>
|
|
116
|
-
<Dialog.Description>Base UI owns the dialog mechanics.</Dialog.Description>
|
|
117
|
-
<Dialog.Content>Styled by Sherick UI.</Dialog.Content>
|
|
118
|
-
</Dialog>
|
|
119
41
|
</>
|
|
120
42
|
);
|
|
121
43
|
}
|
|
122
44
|
```
|
|
123
45
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
The
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
with its own content;
|
|
164
|
-
- **the sheet** — `Drawer` is a `Dialog` with an edge rather than a second kind of modal, so it
|
|
165
|
-
traps focus, restores it, locks the page and dismisses exactly as a dialog does. Compose a
|
|
166
|
-
`Drawer.Trigger` and a `Drawer.Content`, with `Drawer.Header`/`Drawer.Description`/
|
|
167
|
-
`Drawer.Footer`/`Drawer.Close`. `side` is physical — `"right"` is the right edge of the screen
|
|
168
|
-
in every writing direction — and it is also the edge the surface slides out of;
|
|
169
|
-
- **toasts** — `ToastProvider` wraps the application, `ToastViewport` renders the stack, and
|
|
170
|
-
`useToast()` raises one from inside the tree. The queue, the auto-dismiss timer, the limit, the
|
|
171
|
-
live region, swipe dismissal and the stack's own state all stay with the primitive, and
|
|
172
|
-
`createToastManager()` builds a manager that lives outside React for code that has no component
|
|
173
|
-
to raise one from. What a toast is raised with is this package's own contract — `add`, `update`,
|
|
174
|
-
`close` and `promise`, with `title`, `description`, `type`, `timeout`, `priority`, `actionProps`
|
|
175
|
-
and the two lifecycle callbacks — rather than the primitive's whole option set; `promise()`
|
|
176
|
-
reports one promise through one toast, and its loading, success and error states each carry a
|
|
177
|
-
mark and a tone. **F6** enters the notification stack, including while a Dialog or Drawer is
|
|
178
|
-
open; **Tab** reaches each toast's action and dismissal. **Shift+Tab** from the viewport, or
|
|
179
|
-
Tab past the final control, returns to the previous control. Ordinary modal Tab navigation
|
|
180
|
-
remains inside the modal; notification access uses the primitive's dedicated shortcut;
|
|
181
|
-
- **navigation** — `NavGroup` is a titled group of `NavGroupItem`s that brings no surface of its
|
|
182
|
-
own, so a navigation column reads as one region rather than a card holding cards. `NavItem` is a
|
|
183
|
-
row the densest density step sizes, whose current destination takes the lightest accent tint and
|
|
184
|
-
publishes `aria-current`;
|
|
185
|
-
- **the toggle family** — a `Chip` is a tag until it is given a selection, and a toggle chip inside a
|
|
186
|
-
`ChipGroup` is a button that holds the group's value; a `ToggleGroup` and its `ToggleGroup.Item`
|
|
187
|
-
segments are the same object inside a recessed track, and `SegmentedControl` is that group's
|
|
188
|
-
single-choice form over an `options` array. Selection lives in Base UI's own pressed marker, so an
|
|
189
|
-
uncontrolled toggle is styled from the same source of truth as a controlled one, and a
|
|
190
|
-
`SegmentedControl` never empties itself;
|
|
191
|
-
- **`Progress`** — a determinate bar announces its value through Base UI's `progressbar` role, and omitting
|
|
192
|
-
`value`, or passing `null`, sweeps the fill instead of reporting a position;
|
|
193
|
-
- **removable tags** — only a chip that holds no selection can be dismissed, because a control that
|
|
194
|
-
both holds a value and deletes itself is one target with two meanings.
|
|
195
|
-
|
|
196
|
-
## Rich content
|
|
197
|
-
|
|
198
|
-
`Markdown` and `CodeBlock` are not on the root export — they live on a separate subpath:
|
|
199
|
-
|
|
200
|
-
```tsx
|
|
201
|
-
import { Markdown, CodeBlock } from "sherick-ui/content";
|
|
202
|
-
|
|
203
|
-
export function Docs() {
|
|
204
|
-
return <Markdown>{"# Heading"}</Markdown>;
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
The rich-content stack (Prism, remark/rehype, KaTeX) is deliberately separate, so a build that only uses core components never bundles a syntax highlighter or a Markdown pipeline. Importing `Button` from `sherick-ui` does not reach `sherick-ui/content`; that boundary is enforced by the package's bundle budget gate.
|
|
209
|
-
|
|
210
|
-
It is a bundle boundary, not an install boundary: the rich stack stays an ordinary dependency, so installing `sherick-ui` installs it whether or not the subpath is imported.
|
|
211
|
-
|
|
212
|
-
The subpath is **ESM only**, because `react-markdown` and remark/rehype have no CommonJS build. It therefore declares no `require` entry, and `require("sherick-ui/content")` fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`. From CommonJS, use `await import("sherick-ui/content")`. The root barrel and `sherick-ui/dev` keep their CommonJS entries.
|
|
213
|
-
|
|
214
|
-
## Architecture
|
|
215
|
-
|
|
216
|
-
Base UI owns generic interaction and accessibility mechanics when it provides the primitive: keyboard navigation, focus management, semantic relationships, form participation, portals, dismissal and popup positioning. Sherick UI owns anatomy, its public design API and the visual language.
|
|
217
|
-
|
|
218
|
-
Base UI is internal infrastructure. Consumers never import `@base-ui/react` to use Sherick UI, and Base UI's own props, DOM structure and generated IDs are not part of this package's compatibility promise.
|
|
219
|
-
|
|
220
|
-
The package tarball includes the exact audited Base UI implementation. This carries the temporary
|
|
221
|
-
editable-Combobox isolation patch into installed npm consumers while leaving Base UI — not a Sherick
|
|
222
|
-
wrapper — responsible for focus, ARIA isolation, dismissal and popup lifecycle.
|
|
223
|
-
|
|
224
|
-
Tailwind is not a runtime integration surface. It is internal authoring/build infrastructure: the package ships no Tailwind preset, declares no Tailwind peer dependency and requires no package-content scanning. Component CSS is generated inside this package and scoped internally; `.sui-scope` is private implementation detail, not a consumer class or theming hook.
|
|
225
|
-
|
|
226
|
-
Themes are document-level. Overlays portal to `document.body`, so root-level `--sui-*` variables apply to Dialog, Select and Tooltip surfaces; nested theme islands are not a supported contract.
|
|
227
|
-
|
|
228
|
-
The design language remains canonical in the repository-level `docs/DESIGN_LANGUAGE.md`. Reusable recipes live in `src/components/ui.common.ts`; authored theme values live in `src/styles/tokens.ts` and compile to the published CSS artifacts.
|
|
46
|
+
The root barrel contains actions, forms, selection, navigation, feedback and overlays.
|
|
47
|
+
`Markdown` and `CodeBlock` are imported from **ESM-only** `sherick-ui/content`;
|
|
48
|
+
CommonJS consumers use dynamic `import()`. The rich stack is installed with the
|
|
49
|
+
package but never bundled by a core-only import. `sherick-ui/dev` is unsupported
|
|
50
|
+
workbench infrastructure, not consumer API. For the current export list and semver
|
|
51
|
+
boundaries see the [release contract](https://github.com/Sherick16/sherick-ui/blob/main/docs/RELEASE.md#public-export-contract).
|
|
52
|
+
|
|
53
|
+
Use `Media.Image` and `Media.Video` for Sherick's rounded, clipped media frame.
|
|
54
|
+
[Examples and accessibility guidance](https://github.com/Sherick16/sherick-ui/blob/main/docs/MEDIA.md)
|
|
55
|
+
cover content, decorative media and native video captions.
|
|
56
|
+
|
|
57
|
+
The v2.1 wave adds Calendar/DatePicker/DateRangePicker,
|
|
58
|
+
Command/CommandPalette, Pagination/Breadcrumb, FileUpload, Stepper and TreeView to
|
|
59
|
+
the same root barrel. Its [component contracts](https://github.com/Sherick16/sherick-ui/blob/main/docs/V2_1_COMPONENTS.md)
|
|
60
|
+
use civil `YYYY-MM-DD` dates and `File[]` selections; FileUpload does not upload files.
|
|
61
|
+
|
|
62
|
+
## Themes and direction
|
|
63
|
+
|
|
64
|
+
With no root `data-sherick-theme`, the library follows `prefers-color-scheme`. Set
|
|
65
|
+
`"light"` or `"dark"` to override it. Retune `--sui-*` variables at the document
|
|
66
|
+
root; nested theme islands are not supported because overlays portal to the body.
|
|
67
|
+
The [token source](https://github.com/Sherick16/sherick-ui/blob/main/packages/ui/src/styles/tokens.ts)
|
|
68
|
+
contains the defaults; custom accent values should pass the
|
|
69
|
+
[contrast contract](https://github.com/Sherick16/sherick-ui/blob/main/docs/VERIFICATION.md#fast-package-smoke-checks)
|
|
70
|
+
in both themes and interaction states.
|
|
71
|
+
|
|
72
|
+
For RTL, set both `<html dir="rtl">` and `<DirectionProvider direction="rtl">`.
|
|
73
|
+
Drawer sides stay physical and CodeBlock source stays LTR.
|
|
74
|
+
|
|
75
|
+
## Support
|
|
76
|
+
|
|
77
|
+
The core ships ESM and CommonJS and supports React/React DOM 18 or 19. The automated
|
|
78
|
+
browser baseline is the pinned Playwright Chromium, Firefox and WebKit engines;
|
|
79
|
+
shipping browser builds and older majors are not separately certified. Base UI owns
|
|
80
|
+
generic widget behavior and accessibility; Tailwind is private styling infrastructure.
|
|
81
|
+
Neither is a consumer API. The audited patched Base UI copy is bundled for editable
|
|
82
|
+
Combobox focus isolation. See the [release contract](https://github.com/Sherick16/sherick-ui/blob/main/docs/RELEASE.md)
|
|
83
|
+
and [design language](https://github.com/Sherick16/sherick-ui/blob/main/docs/DESIGN_LANGUAGE.md)
|
|
84
|
+
for details.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var lucideReact = require('lucide-react');
|
|
7
|
+
var React = require('react');
|
|
8
|
+
var utils = require('../libs/utils.cjs');
|
|
9
|
+
var ui_common = require('./ui.common.cjs');
|
|
10
|
+
|
|
11
|
+
/* The trail of places a reader came through. It is **passive**: links and text, no state, no effect
|
|
12
|
+
and no client directive, so a server component renders it and a page that only reads it ships no
|
|
13
|
+
behaviour.
|
|
14
|
+
|
|
15
|
+
The last item is the page the reader is on, and it is text even when the caller supplies an href
|
|
16
|
+
for it — a link to where you already are is a control with nothing left to do, and `aria-current`
|
|
17
|
+
is what says which one it is. Every intermediate destination is a real anchor, so an ordinary
|
|
18
|
+
click, a modified click and every browser affordance work the way they do everywhere else on the
|
|
19
|
+
web: no router is required and none is assumed. `renderLink` is the caller's way to substitute its
|
|
20
|
+
own link component, and it receives the href, the accessible relationship and the shared classes
|
|
21
|
+
the plain anchor would have been given.
|
|
22
|
+
|
|
23
|
+
Separators are decorative chevrons: they mirror with the writing direction and are hidden from
|
|
24
|
+
assistive technology. Long labels wrap and the trail yields to a narrow parent instead of
|
|
25
|
+
collapsing, truncating or hiding a place — which places are behind the reader is information, and a
|
|
26
|
+
breadcrumb that hides one is a breadcrumb that lies. */
|
|
27
|
+
const Breadcrumb = React.forwardRef(({ items, renderLink, className, "aria-label": ariaLabel, ...props }, ref) => {
|
|
28
|
+
/* The props an intermediate destination is rendered from, composed once so the caller's own link
|
|
29
|
+
and the default anchor are the same object: the same destination, the same content and the same
|
|
30
|
+
shared classes — including the focus ring the keyboard needs to see. */
|
|
31
|
+
const linkProps = (item) => ({
|
|
32
|
+
href: item.href,
|
|
33
|
+
className: utils.cn("min-w-0 no-underline [overflow-wrap:anywhere]", ui_common.focusRing, ui_common.text.medium, "hover:text-sherick-ink"),
|
|
34
|
+
children: item.label,
|
|
35
|
+
});
|
|
36
|
+
return (jsxRuntime.jsx("nav", { ...props, ref: ref, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : "Breadcrumb", className: utils.cn("min-w-0 text-sm leading-6", className), children: jsxRuntime.jsx("ol", { role: "list", className: utils.cn("m-0 flex min-w-0 list-none flex-wrap items-start gap-x-2 gap-y-1 p-0", ui_common.text.medium), children: items.map((item, index) => {
|
|
37
|
+
const isCurrent = index === items.length - 1;
|
|
38
|
+
return (jsxRuntime.jsxs("li", { className: utils.cn("flex min-w-0 items-start gap-x-2"), children: [index > 0 && (
|
|
39
|
+
/* One inherited line box centers the glyph on the label's first line, even when
|
|
40
|
+
the label wraps or a consumer changes the trail's line-height. */
|
|
41
|
+
jsxRuntime.jsx("span", { "aria-hidden": "true", className: utils.cn("inline-flex h-[1lh] w-4 shrink-0 items-center"), children: jsxRuntime.jsx(lucideReact.ChevronRight, { className: utils.cn("size-4 rtl:-scale-x-100") }) })), isCurrent ? (jsxRuntime.jsx("span", { "aria-current": "page", className: utils.cn("min-w-0 font-medium [overflow-wrap:anywhere]", ui_common.text.high), children: item.label })) : item.href !== undefined ? (renderLink ? (renderLink(item, linkProps(item))) : (jsxRuntime.jsx("a", { ...linkProps(item) }))) : (jsxRuntime.jsx("span", { className: utils.cn("min-w-0 [overflow-wrap:anywhere]"), children: item.label }))] }, index));
|
|
42
|
+
}) }) }));
|
|
43
|
+
});
|
|
44
|
+
Breadcrumb.displayName = "Breadcrumb";
|
|
45
|
+
|
|
46
|
+
exports.default = Breadcrumb;
|
|
47
|
+
//# sourceMappingURL=Breadcrumb.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumb.cjs","sources":["../../../src/components/Breadcrumb.tsx"],"sourcesContent":["import { ChevronRight } from \"lucide-react\";\nimport {\n forwardRef,\n type AnchorHTMLAttributes,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"@/libs/utils\";\nimport { focusRing, text } from \"./ui.common\";\n\nexport interface BreadcrumbItem {\n label: ReactNode;\n href?: string;\n}\n\nexport interface BreadcrumbProps extends Omit<ComponentPropsWithoutRef<\"nav\">, \"children\"> {\n items: BreadcrumbItem[];\n /**\n * How an intermediate destination is rendered — the escape hatch for a router link. The supplied\n * props carry the destination, the shared classes and the item's own content, and the renderer\n * spreads them onto its element.\n */\n renderLink?: (item: BreadcrumbItem, props: AnchorHTMLAttributes<HTMLAnchorElement>) => ReactNode;\n}\n\n/* The trail of places a reader came through. It is **passive**: links and text, no state, no effect\n and no client directive, so a server component renders it and a page that only reads it ships no\n behaviour.\n\n The last item is the page the reader is on, and it is text even when the caller supplies an href\n for it — a link to where you already are is a control with nothing left to do, and `aria-current`\n is what says which one it is. Every intermediate destination is a real anchor, so an ordinary\n click, a modified click and every browser affordance work the way they do everywhere else on the\n web: no router is required and none is assumed. `renderLink` is the caller's way to substitute its\n own link component, and it receives the href, the accessible relationship and the shared classes\n the plain anchor would have been given.\n\n Separators are decorative chevrons: they mirror with the writing direction and are hidden from\n assistive technology. Long labels wrap and the trail yields to a narrow parent instead of\n collapsing, truncating or hiding a place — which places are behind the reader is information, and a\n breadcrumb that hides one is a breadcrumb that lies. */\nconst Breadcrumb = forwardRef<HTMLElement, BreadcrumbProps>(\n ({ items, renderLink, className, \"aria-label\": ariaLabel, ...props }, ref) => {\n /* The props an intermediate destination is rendered from, composed once so the caller's own link\n and the default anchor are the same object: the same destination, the same content and the same\n shared classes — including the focus ring the keyboard needs to see. */\n const linkProps = (item: BreadcrumbItem): AnchorHTMLAttributes<HTMLAnchorElement> => ({\n href: item.href,\n className: cn(\"min-w-0 no-underline [overflow-wrap:anywhere]\", focusRing, text.medium, \"hover:text-sherick-ink\"),\n children: item.label,\n });\n\n return (\n <nav\n {...props}\n ref={ref}\n aria-label={ariaLabel ?? \"Breadcrumb\"}\n className={cn(\"min-w-0 text-sm leading-6\", className)}\n >\n {/* A native ordered list: the trail has an order, and the order is the information. The row\n wraps rather than overflowing, so a long trail stays inside its column. `role=\"list\"`\n restates the element's own role rather than adding one, because `list-none` — which removes\n the marker a breadcrumb does not want — is also what makes Safari drop the semantics. */}\n <ol\n role=\"list\"\n className={cn(\n \"m-0 flex min-w-0 list-none flex-wrap items-start gap-x-2 gap-y-1 p-0\",\n text.medium\n )}\n >\n {items.map((item, index) => {\n const isCurrent = index === items.length - 1;\n\n return (\n <li key={index} className={cn(\"flex min-w-0 items-start gap-x-2\")}>\n {index > 0 && (\n /* One inherited line box centers the glyph on the label's first line, even when\n the label wraps or a consumer changes the trail's line-height. */\n <span aria-hidden=\"true\" className={cn(\"inline-flex h-[1lh] w-4 shrink-0 items-center\")}>\n <ChevronRight className={cn(\"size-4 rtl:-scale-x-100\")} />\n </span>\n )}\n {isCurrent ? (\n <span\n aria-current=\"page\"\n className={cn(\"min-w-0 font-medium [overflow-wrap:anywhere]\", text.high)}\n >\n {item.label}\n </span>\n ) : item.href !== undefined ? (\n renderLink ? (\n renderLink(item, linkProps(item))\n ) : (\n <a {...linkProps(item)} />\n )\n ) : (\n <span className={cn(\"min-w-0 [overflow-wrap:anywhere]\")}>{item.label}</span>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n }\n);\n\nBreadcrumb.displayName = \"Breadcrumb\";\n\nexport default Breadcrumb;\n"],"names":["forwardRef","cn","focusRing","text","_jsx","_jsxs","ChevronRight"],"mappings":";;;;;;;;;;AAyBA;;;;;;;;;;;;;;;AAe0D;AAC1D,MAAM,UAAU,GAAGA,gBAAU,CAC3B,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAI;AAC3E;;AAE0E;AAC1E,IAAA,MAAM,SAAS,GAAG,CAAC,IAAoB,MAA+C;QACpF,IAAI,EAAE,IAAI,CAAC,IAAI;AACf,QAAA,SAAS,EAAEC,QAAE,CAAC,+CAA+C,EAAEC,mBAAS,EAAEC,cAAI,CAAC,MAAM,EAAE,wBAAwB,CAAC;QAChH,QAAQ,EAAE,IAAI,CAAC,KAAK;AACrB,KAAA,CAAC;IAEF,QACEC,2BACM,KAAK,EACT,GAAG,EAAE,GAAG,EAAA,YAAA,EACI,SAAS,KAAA,IAAA,IAAT,SAAS,cAAT,SAAS,GAAI,YAAY,EACrC,SAAS,EAAEH,QAAE,CAAC,2BAA2B,EAAE,SAAS,CAAC,EAAA,QAAA,EAMrDG,uBACE,IAAI,EAAC,MAAM,EACX,SAAS,EAAEH,QAAE,CACX,sEAAsE,EACtEE,cAAI,CAAC,MAAM,CACZ,EAAA,QAAA,EAEA,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,KAAI;gBACzB,MAAM,SAAS,GAAG,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;AAE5C,gBAAA,QACEE,eAAA,CAAA,IAAA,EAAA,EAAgB,SAAS,EAAEJ,QAAE,CAAC,kCAAkC,CAAC,EAAA,QAAA,EAAA,CAC9D,KAAK,GAAG,CAAC;AACR;AACoE;wBACpEG,cAAA,CAAA,MAAA,EAAA,EAAA,aAAA,EAAkB,MAAM,EAAC,SAAS,EAAEH,QAAE,CAAC,+CAA+C,CAAC,EAAA,QAAA,EACrFG,cAAA,CAACE,wBAAY,IAAC,SAAS,EAAEL,QAAE,CAAC,yBAAyB,CAAC,GAAI,EAAA,CACrD,CACR,EACA,SAAS,IACRG,cAAA,CAAA,MAAA,EAAA,EAAA,cAAA,EACe,MAAM,EACnB,SAAS,EAAEH,QAAE,CAAC,8CAA8C,EAAEE,cAAI,CAAC,IAAI,CAAC,EAAA,QAAA,EAEvE,IAAI,CAAC,KAAK,EAAA,CACN,IACL,IAAI,CAAC,IAAI,KAAK,SAAS,IACzB,UAAU,IACR,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,KAEjCC,cAAA,CAAA,GAAA,EAAA,EAAA,GAAO,SAAS,CAAC,IAAI,CAAC,EAAA,CAAI,CAC3B,KAEDA,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAEH,QAAE,CAAC,kCAAkC,CAAC,EAAA,QAAA,EAAG,IAAI,CAAC,KAAK,EAAA,CAAQ,CAC7E,CAAA,EAAA,EAvBM,KAAK,CAwBT;AAET,YAAA,CAAC,CAAC,EAAA,CACC,EAAA,CACD;AAEV,CAAC;AAGH,UAAU,CAAC,WAAW,GAAG,YAAY;;"}
|