@openbunny/react 0.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 +21 -0
- package/README.md +184 -0
- package/dist/components/chevron-icon.d.ts +4 -0
- package/dist/components/chevron-icon.js +6 -0
- package/dist/components/chevron-icon.js.map +1 -0
- package/dist/components/command-block.d.ts +18 -0
- package/dist/components/command-block.js +9 -0
- package/dist/components/command-block.js.map +1 -0
- package/dist/components/command-line.d.ts +7 -0
- package/dist/components/command-line.js +7 -0
- package/dist/components/command-line.js.map +1 -0
- package/dist/components/copy-button.d.ts +13 -0
- package/dist/components/copy-button.js +54 -0
- package/dist/components/copy-button.js.map +1 -0
- package/dist/components/page-section.d.ts +6 -0
- package/dist/components/page-section.js +6 -0
- package/dist/components/page-section.js.map +1 -0
- package/dist/components/page-shell.d.ts +4 -0
- package/dist/components/page-shell.js +5 -0
- package/dist/components/page-shell.js.map +1 -0
- package/dist/components/page-title.d.ts +7 -0
- package/dist/components/page-title.js +6 -0
- package/dist/components/page-title.js.map +1 -0
- package/dist/components/plate-header.d.ts +6 -0
- package/dist/components/plate-header.js +6 -0
- package/dist/components/plate-header.js.map +1 -0
- package/dist/components/plate.d.ts +6 -0
- package/dist/components/plate.js +6 -0
- package/dist/components/plate.js.map +1 -0
- package/dist/components/section-heading.d.ts +5 -0
- package/dist/components/section-heading.js +5 -0
- package/dist/components/section-heading.js.map +1 -0
- package/dist/components/shell-command.d.ts +4 -0
- package/dist/components/shell-command.js +13 -0
- package/dist/components/shell-command.js.map +1 -0
- package/dist/components/skip-link.d.ts +4 -0
- package/dist/components/skip-link.js +5 -0
- package/dist/components/skip-link.js.map +1 -0
- package/dist/components/status-page.d.ts +9 -0
- package/dist/components/status-page.js +6 -0
- package/dist/components/status-page.js.map +1 -0
- package/dist/components/ui/button.d.ts +9 -0
- package/dist/components/ui/button.js +23 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/command-step.d.ts +4 -0
- package/dist/lib/command-step.js +2 -0
- package/dist/lib/command-step.js.map +1 -0
- package/dist/lib/iso-date.d.ts +2 -0
- package/dist/lib/iso-date.js +20 -0
- package/dist/lib/iso-date.js.map +1 -0
- package/dist/lib/plate-asset.d.ts +6 -0
- package/dist/lib/plate-asset.js +2 -0
- package/dist/lib/plate-asset.js.map +1 -0
- package/dist/lib/shell-tokens.d.ts +5 -0
- package/dist/lib/shell-tokens.js +23 -0
- package/dist/lib/shell-tokens.js.map +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/styles.css +22 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenBunny
|
|
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,184 @@
|
|
|
1
|
+
# @openbunny/react
|
|
2
|
+
|
|
3
|
+
> **Work in progress.** Names, identifiers and interfaces can change without
|
|
4
|
+
> notice.
|
|
5
|
+
|
|
6
|
+
Generic React components for OpenBunny sites. The package ships components and
|
|
7
|
+
helpers with no site content.
|
|
8
|
+
|
|
9
|
+
## Components
|
|
10
|
+
|
|
11
|
+
| Component | Purpose |
|
|
12
|
+
| --------------------------------------------- | ----------------------------------------------------- |
|
|
13
|
+
| `PageShell`, `PageSection` | Centred column and bordered section |
|
|
14
|
+
| `PageTitle`, `SectionHeading` | Page `h1` with optional date, numbered section `h2` |
|
|
15
|
+
| `Plate`, `PlateHeader`, `StatusPage` | Animated and static image pair, header, status layout |
|
|
16
|
+
| `CommandBlock`, `CommandLine`, `ShellCommand` | Numbered command steps, one command row, token spans |
|
|
17
|
+
| `CopyButton`, `Button` | Clipboard button, base button |
|
|
18
|
+
| `SkipLink`, `ChevronIcon` | Skip-to-content link, chevron icon |
|
|
19
|
+
|
|
20
|
+
The package renders no site identity. Each component takes its text, artwork
|
|
21
|
+
and behaviour through props. Where a prop has a default, the default is neutral
|
|
22
|
+
English. No component imports `next`, an analytics client or a router, and none
|
|
23
|
+
renders a link. A caller that needs a link passes its own element as a child or
|
|
24
|
+
as a prop of type `ReactNode`.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm install @openbunny/react @base-ui/react react react-dom
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`react`, `react-dom` and `@base-ui/react` are peer dependencies. Each stays a
|
|
33
|
+
single copy in the consumer's tree.
|
|
34
|
+
|
|
35
|
+
For a Git install, use `bun add github:openbunny/react`. `dist` is not committed;
|
|
36
|
+
the Git install builds it through the `prepare` script.
|
|
37
|
+
`bun` runs the lifecycle scripts of dependencies only for packages listed in
|
|
38
|
+
`trustedDependencies`, and not at all when `install.ignoreScripts` is `true`.
|
|
39
|
+
When the package is not listed or `install.ignoreScripts` is `true`, the install
|
|
40
|
+
succeeds and `dist` is missing. Add the listing to the consumer `package.json`:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{ "trustedDependencies": ["@openbunny/react"] }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { CommandBlock, PageShell } from "@openbunny/react"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The consumer's Tailwind build must scan the package, or the utilities are not
|
|
53
|
+
generated, and the consumer imports the theme and the package stylesheet:
|
|
54
|
+
|
|
55
|
+
```css
|
|
56
|
+
@import "tailwindcss";
|
|
57
|
+
@import "@openbunny/theme/css/tokens.css";
|
|
58
|
+
@import "@openbunny/theme/css/tailwind.css";
|
|
59
|
+
@import "@openbunny/theme/css/extension-base.css";
|
|
60
|
+
@import "@openbunny/react/styles.css";
|
|
61
|
+
@source "../node_modules/@openbunny/react/dist";
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Styling contract
|
|
65
|
+
|
|
66
|
+
The components style against the OpenBunny theme (`@openbunny/theme`). The
|
|
67
|
+
theme defines the items below; a consumer that does not use the theme defines
|
|
68
|
+
them itself. A missing item raises no error; the component renders unstyled in
|
|
69
|
+
that respect.
|
|
70
|
+
|
|
71
|
+
### Theme custom properties and Tailwind tokens
|
|
72
|
+
|
|
73
|
+
`tailwind.css` from the theme maps each colour to a Tailwind utility. The
|
|
74
|
+
components use these utilities: `border-line`, `bg-paper`, `bg-paper-inset`,
|
|
75
|
+
`bg-foreground`, `text-background`, `text-foreground`, `text-ink`, `text-muted`,
|
|
76
|
+
`border-foreground`, `ring` and the `font-display`, `font-sc` and `font-mono`
|
|
77
|
+
families. `styles.css` reads `--ink-deep`, `--ink-mid`, `--sprout` and
|
|
78
|
+
`--font-weight-bold`. Components assume square corners (`--radius-*` is `0`).
|
|
79
|
+
|
|
80
|
+
### Component classes
|
|
81
|
+
|
|
82
|
+
| Class | Defined by | Used by | Rule |
|
|
83
|
+
| ----------------------------------- | ----------------------------- | -------------- | ------------------------------------------------------------------- |
|
|
84
|
+
| `.tok-cmd`, `.tok-flag`, `.tok-str` | `@openbunny/react/styles.css` | `ShellCommand` | colours from `--ink-deep`, `--ink-mid`, `--sprout`; `.tok-cmd` bold |
|
|
85
|
+
| `.plate` | `@openbunny/react/styles.css` | `Plate` | `image-rendering: pixelated` |
|
|
86
|
+
| `.js-only` | `@openbunny/react/styles.css` | `CopyButton` | hidden under `@media (scripting: none)` |
|
|
87
|
+
|
|
88
|
+
`src/styles.test.ts` fails when a component uses a custom class that neither
|
|
89
|
+
this table nor the theme defines. The theme defines `.link` and `.chip`; no
|
|
90
|
+
component uses them.
|
|
91
|
+
|
|
92
|
+
### Document contract
|
|
93
|
+
|
|
94
|
+
- The page has one element with `id="main"`. `SkipLink` and `StatusPage` target
|
|
95
|
+
it.
|
|
96
|
+
- `:focus-visible` has a visible outline. The theme's `extension-base.css`
|
|
97
|
+
provides one.
|
|
98
|
+
|
|
99
|
+
## Props reference
|
|
100
|
+
|
|
101
|
+
Every prop is required unless its row shows a default or `?`.
|
|
102
|
+
|
|
103
|
+
| Component | Props |
|
|
104
|
+
| ---------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
105
|
+
| `Button` | `variant` (`"outline"`), `size` (`"xs"`), and every prop of `@base-ui/react` `Button` |
|
|
106
|
+
| `ChevronIcon` | `direction`: `"left"` or `"right"` |
|
|
107
|
+
| `CommandBlock` | `id`, `number`, `title`, `steps`: `CommandStep[]`, `note?`, `copyAll?` (`false`), `copy?`, `copyLabel?`, `lead?` |
|
|
108
|
+
| `CommandLine` | `command`, `copy?`, `copyLabel?` |
|
|
109
|
+
| `CopyButton` | `text`, `label`, `caption?`, `copiedCaption?`, `failureHint?`, `onCopy?` |
|
|
110
|
+
| `PageSection` | `id`, `className?`, `children` |
|
|
111
|
+
| `PageShell` | `children` |
|
|
112
|
+
| `PageTitle` | `title`, `lastChangedAt?`, `changedLabel?`, `formatDate?` |
|
|
113
|
+
| `Plate` | `asset`: `PlateAsset`, `className?` |
|
|
114
|
+
| `PlateHeader` | `asset`: `PlateAsset`, `plateClassName` |
|
|
115
|
+
| `SectionHeading` | `number`, `children` |
|
|
116
|
+
| `ShellCommand` | `command` |
|
|
117
|
+
| `SkipLink` | `label?` |
|
|
118
|
+
| `StatusPage` | `asset`: `PlateAsset`, `plateClassName`, `heading`, `children`, `actions` |
|
|
119
|
+
|
|
120
|
+
Types and helpers:
|
|
121
|
+
|
|
122
|
+
- `PlateAsset`: `gifSrc`, `staticSrc` (strings), `width`, `height` (numbers).
|
|
123
|
+
- `CommandStep`: `command` and `comment` (strings).
|
|
124
|
+
- `CopyText`: `caption?`, `copiedCaption?`, `failureHint?`.
|
|
125
|
+
- `shellTokens(command)` returns `ShellToken[]`; it throws on unbalanced quotes.
|
|
126
|
+
- `formatLongDate(isoDate)` formats an ISO date for `PageTitle`.
|
|
127
|
+
- `cn(...classes)` merges class names.
|
|
128
|
+
|
|
129
|
+
`bun run build` also emits declarations in `dist/index.d.ts`.
|
|
130
|
+
|
|
131
|
+
## Props that carry text
|
|
132
|
+
|
|
133
|
+
Copy, captions and labels are props with neutral English defaults.
|
|
134
|
+
|
|
135
|
+
| Component | Props |
|
|
136
|
+
| -------------- | ------------------------------------------------------------------------ |
|
|
137
|
+
| `CopyButton` | `label` (required), `caption`, `copiedCaption`, `failureHint`, `onCopy` |
|
|
138
|
+
| `CommandLine` | `copy` (`caption`, `copiedCaption`, `failureHint`), `copyLabel(command)` |
|
|
139
|
+
| `CommandBlock` | `copy`, `copyLabel`, `copyAllCaption`, `copyAllLabel`, `note`, `lead` |
|
|
140
|
+
| `PageTitle` | `changedLabel`, `formatDate(isoDate)` |
|
|
141
|
+
| `SkipLink` | `label` |
|
|
142
|
+
|
|
143
|
+
`CopyButton` reports a successful copy through `onCopy`. The consumer attaches
|
|
144
|
+
analytics there; the package contains none.
|
|
145
|
+
|
|
146
|
+
## Parity
|
|
147
|
+
|
|
148
|
+
Each component is compared with markup captured once from the component it was
|
|
149
|
+
extracted from. The captured files are `parity/fixtures/<component>.json`. The
|
|
150
|
+
package imports nothing from the original and needs no checkout of it.
|
|
151
|
+
`parity/fixtures/README.md` states that the fixtures are frozen and when they
|
|
152
|
+
change.
|
|
153
|
+
|
|
154
|
+
Package defaults differ from the original defaults in capitalisation. A case with
|
|
155
|
+
an `adoption` entry in `parity/definitions.tsx` lists the props that reproduce
|
|
156
|
+
the original markup, and the parity run also asserts that the default render
|
|
157
|
+
differs from the fixture. `just parity` fails when `parity/fixtures` holds no
|
|
158
|
+
fixture, because a gate with no cases checks nothing.
|
|
159
|
+
|
|
160
|
+
## Development
|
|
161
|
+
|
|
162
|
+
Requires `bun` and `just`. `package.json` pins the `bun` version.
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
just install
|
|
166
|
+
just check
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`just check` runs `format-check`, `lint`, `typecheck`, `test`, `build` and
|
|
170
|
+
`parity`, reports every failure, then exits non-zero if any failed.
|
|
171
|
+
|
|
172
|
+
The build is `tsc`, not a bundler. A bundler would collapse the module graph and
|
|
173
|
+
drop the `"use client"` directives that mark client components. `tsc` emits one
|
|
174
|
+
module per source file with those directives intact, plus declarations. The
|
|
175
|
+
consumer's bundler tree-shakes.
|
|
176
|
+
|
|
177
|
+
`next` is a development dependency, present only because the lint configuration extends `eslint-config-next`. The built package does not import it.
|
|
178
|
+
|
|
179
|
+
Source imports use explicit `.ts` and `.tsx` extensions. The compiler rewrites
|
|
180
|
+
them to `.js` in `dist`.
|
|
181
|
+
|
|
182
|
+
## Licence
|
|
183
|
+
|
|
184
|
+
MIT. See `LICENSE`. Copyright (c) 2026 OpenBunny.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export function ChevronIcon({ direction, }) {
|
|
3
|
+
const d = direction === "left" ? "M10 3 5 8l5 5" : "M6 3l5 5-5 5";
|
|
4
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: d }) }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=chevron-icon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chevron-icon.js","sourceRoot":"","sources":["../../src/components/chevron-icon.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,WAAW,CAAC,EAC1B,SAAS,GAGV;IACC,MAAM,CAAC,GAAG,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,cAAc,CAAA;IAEjE,OAAO,CACL,cACE,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,iBACV,MAAM,EAClB,SAAS,EAAC,OAAO,YAEjB,eAAM,CAAC,EAAE,CAAC,GAAI,GACV,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { CommandStep } from "../lib/command-step.ts";
|
|
3
|
+
import { type CopyText } from "./copy-button.tsx";
|
|
4
|
+
type CommandBlockProps = {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly number: string;
|
|
7
|
+
readonly title: string;
|
|
8
|
+
readonly steps: ReadonlyArray<CommandStep>;
|
|
9
|
+
readonly note?: string;
|
|
10
|
+
readonly copyAll?: boolean;
|
|
11
|
+
readonly copyAllCaption?: string;
|
|
12
|
+
readonly copyAllLabel?: string;
|
|
13
|
+
readonly copy?: CopyText;
|
|
14
|
+
readonly copyLabel?: (command: string) => string;
|
|
15
|
+
readonly lead?: ReactNode;
|
|
16
|
+
};
|
|
17
|
+
export declare function CommandBlock({ id, number, title, steps, note, copyAll, copyAllCaption, copyAllLabel, copy, copyLabel, lead, }: CommandBlockProps): ReactElement;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CommandLine } from "./command-line.js";
|
|
3
|
+
import { CopyButton } from "./copy-button.js";
|
|
4
|
+
import { PageSection } from "./page-section.js";
|
|
5
|
+
import { SectionHeading } from "./section-heading.js";
|
|
6
|
+
export function CommandBlock({ id, number, title, steps, note, copyAll = false, copyAllCaption = "Copy all", copyAllLabel = `Copy all ${title} commands`, copy, copyLabel, lead, }) {
|
|
7
|
+
return (_jsxs(PageSection, { id: id, children: [_jsxs("div", { className: "flex items-baseline justify-between gap-4", children: [_jsx(SectionHeading, { number: number, children: title }), copyAll ? (_jsx(CopyButton, { ...copy, text: steps.map((step) => step.command).join(" &&\n"), label: copyAllLabel, caption: copyAllCaption })) : null] }), lead, _jsx("ol", { className: "flex flex-col gap-4", children: steps.map((step, index) => (_jsxs("li", { className: "flex flex-col gap-1", children: [_jsxs("p", { className: "flex items-baseline gap-3 font-display text-[0.92rem] leading-[1.6]", children: [_jsxs("span", { "aria-hidden": "true", className: "font-mono text-[0.62rem] text-muted", children: [number, ".", index + 1] }), step.comment] }), _jsx(CommandLine, { command: step.command, ...(copy === undefined ? {} : { copy }), ...(copyLabel === undefined ? {} : { copyLabel }) })] }, step.command))) }), note === undefined ? null : (_jsx("p", { className: "mt-1 font-display text-[0.92rem] leading-[1.7] text-pretty text-muted", children: note }))] }));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=command-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-block.js","sourceRoot":"","sources":["../../src/components/command-block.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAoB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAiB,MAAM,kBAAmB,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAoB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAuB,CAAA;AAgBtD,MAAM,UAAU,YAAY,CAAC,EAC3B,EAAE,EACF,MAAM,EACN,KAAK,EACL,KAAK,EACL,IAAI,EACJ,OAAO,GAAG,KAAK,EACf,cAAc,GAAG,UAAU,EAC3B,YAAY,GAAG,YAAY,KAAK,WAAW,EAC3C,IAAI,EACJ,SAAS,EACT,IAAI,GACc;IAClB,OAAO,CACL,MAAC,WAAW,IAAC,EAAE,EAAE,EAAE,aACjB,eAAK,SAAS,EAAC,2CAA2C,aACxD,KAAC,cAAc,IAAC,MAAM,EAAE,MAAM,YAAG,KAAK,GAAkB,EACvD,OAAO,CAAC,CAAC,CAAC,CACT,KAAC,UAAU,OACL,IAAI,EACR,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EACrD,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,cAAc,GACvB,CACH,CAAC,CAAC,CAAC,IAAI,IACJ,EACL,IAAI,EACL,aAAI,SAAS,EAAC,qBAAqB,YAChC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,cAAuB,SAAS,EAAC,qBAAqB,aACpD,aAAG,SAAS,EAAC,qEAAqE,aAChF,+BACc,MAAM,EAClB,SAAS,EAAC,qCAAqC,aAE9C,MAAM,OAAG,KAAK,GAAG,CAAC,IACd,EACN,IAAI,CAAC,OAAO,IACX,EACJ,KAAC,WAAW,IACV,OAAO,EAAE,IAAI,CAAC,OAAO,KACjB,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,KACpC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,GAClD,KAdK,IAAI,CAAC,OAAO,CAehB,CACN,CAAC,GACC,EACJ,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC3B,YAAG,SAAS,EAAC,uEAAuE,YACjF,IAAI,GACH,CACL,IACW,CACf,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
import { type CopyText } from "./copy-button.tsx";
|
|
3
|
+
export declare function CommandLine({ command, copy, copyLabel, }: {
|
|
4
|
+
readonly command: string;
|
|
5
|
+
readonly copy?: CopyText;
|
|
6
|
+
readonly copyLabel?: (command: string) => string;
|
|
7
|
+
}): ReactElement;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CopyButton } from "./copy-button.js";
|
|
3
|
+
import { ShellCommand } from "./shell-command.js";
|
|
4
|
+
export function CommandLine({ command, copy, copyLabel = (text) => `Copy command: ${text}`, }) {
|
|
5
|
+
return (_jsxs("div", { className: "flex items-center gap-3 border border-line bg-paper-inset px-4 py-2", children: [_jsxs("code", { className: "flex min-w-0 flex-1 items-baseline gap-2 font-mono text-[0.68rem] leading-[1.65] [overflow-wrap:anywhere] whitespace-break-spaces", children: [_jsx("span", { "aria-hidden": "true", className: "text-muted select-none", children: "$" }), _jsx("span", { className: "min-w-0", children: _jsx(ShellCommand, { command: command }) })] }), _jsx(CopyButton, { ...copy, text: command, label: copyLabel(command) })] }));
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=command-line.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-line.js","sourceRoot":"","sources":["../../src/components/command-line.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAiB,MAAM,kBAAmB,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAqB,CAAA;AAElD,MAAM,UAAU,WAAW,CAAC,EAC1B,OAAO,EACP,IAAI,EACJ,SAAS,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,IAAI,EAAE,GAK9C;IACC,OAAO,CACL,eAAK,SAAS,EAAC,qEAAqE,aAClF,gBAAM,SAAS,EAAC,mIAAmI,aACjJ,8BAAkB,MAAM,EAAC,SAAS,EAAC,wBAAwB,kBAEpD,EACP,eAAM,SAAS,EAAC,SAAS,YACvB,KAAC,YAAY,IAAC,OAAO,EAAE,OAAO,GAAI,GAC7B,IACF,EACP,KAAC,UAAU,OAAK,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,GAAI,IAC9D,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
export type CopyText = {
|
|
3
|
+
readonly failureHint?: string;
|
|
4
|
+
readonly caption?: string;
|
|
5
|
+
readonly copiedCaption?: string;
|
|
6
|
+
};
|
|
7
|
+
type CopyButtonProps = CopyText & {
|
|
8
|
+
readonly text: string;
|
|
9
|
+
readonly label: string;
|
|
10
|
+
readonly onCopy?: () => void;
|
|
11
|
+
};
|
|
12
|
+
export declare function CopyButton({ text, label, failureHint, caption, copiedCaption, onCopy, }: CopyButtonProps): ReactElement;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import { Button } from "./ui/button.js";
|
|
5
|
+
const DIM_MS = 450;
|
|
6
|
+
const ANNOUNCE_MS = 1600;
|
|
7
|
+
export function CopyButton({ text, label, failureHint = "Select the text and copy it by hand.", caption = "Copy", copiedCaption = "Copied", onCopy, }) {
|
|
8
|
+
const [state, setState] = useState("idle");
|
|
9
|
+
const [dimmed, setDimmed] = useState(false);
|
|
10
|
+
const resetRef = useRef(undefined);
|
|
11
|
+
const dimRef = useRef(undefined);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
return () => {
|
|
14
|
+
window.clearTimeout(resetRef.current);
|
|
15
|
+
window.clearTimeout(dimRef.current);
|
|
16
|
+
};
|
|
17
|
+
}, []);
|
|
18
|
+
async function copy() {
|
|
19
|
+
window.clearTimeout(resetRef.current);
|
|
20
|
+
window.clearTimeout(dimRef.current);
|
|
21
|
+
try {
|
|
22
|
+
await navigator.clipboard.writeText(text);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
26
|
+
console.error("Copy failed:", message);
|
|
27
|
+
setDimmed(false);
|
|
28
|
+
setState("failed");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
setState("copied");
|
|
32
|
+
setDimmed(true);
|
|
33
|
+
dimRef.current = window.setTimeout(() => {
|
|
34
|
+
setDimmed(false);
|
|
35
|
+
}, DIM_MS);
|
|
36
|
+
resetRef.current = window.setTimeout(() => {
|
|
37
|
+
setState("idle");
|
|
38
|
+
}, ANNOUNCE_MS);
|
|
39
|
+
try {
|
|
40
|
+
onCopy?.();
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
44
|
+
console.error("Copy callback failed:", message);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const status = state === "failed" ? `${label} failed. ${failureHint}` : "";
|
|
48
|
+
return (_jsxs("span", { className: "js-only inline-flex flex-col items-end gap-1", children: [_jsx(Button, { type: "button", onClick: () => {
|
|
49
|
+
void copy();
|
|
50
|
+
}, "aria-label": label, "data-copied": dimmed ? "" : undefined, className: "border-foreground/45 bg-paper font-sc text-[0.65rem] hover:border-ink hover:bg-paper hover:text-ink", children: _jsx("span", { "aria-hidden": "true", children: dimmed ? copiedCaption : caption }) }), _jsx("span", { role: "status", className: state === "failed"
|
|
51
|
+
? "max-w-64 text-right font-display text-xs leading-relaxed text-foreground/70"
|
|
52
|
+
: "sr-only", children: status })] }));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=copy-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-button.js","sourceRoot":"","sources":["../../src/components/copy-button.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
export function PageSection({ id, className, children, }) {
|
|
4
|
+
return (_jsx("section", { id: id, className: cn("mt-14 flex flex-col gap-3 border-t border-line pt-6", className), children: children }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=page-section.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-section.js","sourceRoot":"","sources":["../../src/components/page-section.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC,MAAM,UAAU,WAAW,CAAC,EAC1B,EAAE,EACF,SAAS,EACT,QAAQ,GAKT;IACC,OAAO,CACL,kBACE,EAAE,EAAE,EAAE,EACN,SAAS,EAAE,EAAE,CACX,qDAAqD,EACrD,SAAS,CACV,YAEA,QAAQ,GACD,CACX,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export function PageShell({ children, }) {
|
|
3
|
+
return (_jsx("div", { className: "flex min-h-svh justify-center px-6 py-8 md:px-8 md:py-10", children: _jsx("div", { className: "flex w-full max-w-[65ch] min-w-0 flex-col", children: children }) }));
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=page-shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-shell.js","sourceRoot":"","sources":["../../src/components/page-shell.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,SAAS,CAAC,EACxB,QAAQ,GAGT;IACC,OAAO,CACL,cAAK,SAAS,EAAC,0DAA0D,YACvE,cAAK,SAAS,EAAC,2CAA2C,YACvD,QAAQ,GACL,GACF,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
export declare function PageTitle({ title, lastChangedAt, changedLabel, formatDate, }: {
|
|
3
|
+
readonly title: string;
|
|
4
|
+
readonly lastChangedAt?: string;
|
|
5
|
+
readonly changedLabel?: string;
|
|
6
|
+
readonly formatDate?: (isoDate: string) => string;
|
|
7
|
+
}): ReactElement;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { formatLongDate } from "../lib/iso-date.js";
|
|
3
|
+
export function PageTitle({ title, lastChangedAt, changedLabel = "Last changed", formatDate = formatLongDate, }) {
|
|
4
|
+
return (_jsxs("div", { children: [_jsx("h1", { className: "font-display text-[1.4rem] leading-none", children: title }), lastChangedAt === undefined ? null : (_jsx("time", { dateTime: lastChangedAt, className: "mt-3 block font-mono text-[0.75rem] text-muted", children: `${changedLabel} ${formatDate(lastChangedAt.slice(0, 10))}` }))] }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=page-title.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-title.js","sourceRoot":"","sources":["../../src/components/page-title.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,aAAa,EACb,YAAY,GAAG,cAAc,EAC7B,UAAU,GAAG,cAAc,GAM5B;IACC,OAAO,CACL,0BACE,aAAI,SAAS,EAAC,yCAAyC,YAAE,KAAK,GAAM,EACnE,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACpC,eACE,QAAQ,EAAE,aAAa,EACvB,SAAS,EAAC,gDAAgD,YAEzD,GAAG,YAAY,IAAI,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GACvD,CACR,IACG,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Plate } from "./plate.js";
|
|
3
|
+
export function PlateHeader({ asset, plateClassName, }) {
|
|
4
|
+
return (_jsx("header", { className: "mt-6 border-b border-line", children: _jsx(Plate, { asset: asset, className: plateClassName }) }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=plate-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plate-header.js","sourceRoot":"","sources":["../../src/components/plate-header.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAa,CAAA;AAEnC,MAAM,UAAU,WAAW,CAAC,EAC1B,KAAK,EACL,cAAc,GAIf;IACC,OAAO,CACL,iBAAQ,SAAS,EAAC,2BAA2B,YAC3C,KAAC,KAAK,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,GAAI,GAC3C,CACV,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
export function Plate({ asset, className, }) {
|
|
4
|
+
return (_jsxs("span", { "aria-hidden": "true", className: cn("inline-block", className), children: [_jsx("img", { src: asset.gifSrc, alt: "", width: asset.width, height: asset.height, className: "plate h-auto w-full motion-reduce:hidden" }), _jsx("img", { src: asset.staticSrc, alt: "", width: asset.width, height: asset.height, className: "plate hidden h-auto w-full motion-reduce:block" })] }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=plate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plate.js","sourceRoot":"","sources":["../../src/components/plate.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC,MAAM,UAAU,KAAK,CAAC,EACpB,KAAK,EACL,SAAS,GAIV;IACC,OAAO,CACL,+BAAkB,MAAM,EAAC,SAAS,EAAE,EAAE,CAAC,cAAc,EAAE,SAAS,CAAC,aAC/D,cACE,GAAG,EAAE,KAAK,CAAC,MAAM,EACjB,GAAG,EAAC,EAAE,EACN,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,SAAS,EAAC,0CAA0C,GACpD,EACF,cACE,GAAG,EAAE,KAAK,CAAC,SAAS,EACpB,GAAG,EAAC,EAAE,EACN,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,SAAS,EAAC,gDAAgD,GAC1D,IACG,CACR,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function SectionHeading({ number, children, }) {
|
|
3
|
+
return (_jsxs("h2", { className: "flex items-baseline gap-3 font-sc text-[1.05rem]", children: [_jsx("span", { "aria-hidden": "true", className: "font-mono text-[0.7rem] text-muted", children: number }), children] }));
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=section-heading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-heading.js","sourceRoot":"","sources":["../../src/components/section-heading.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,cAAc,CAAC,EAC7B,MAAM,EACN,QAAQ,GAIT;IACC,OAAO,CACL,cAAI,SAAS,EAAC,kDAAkD,aAC9D,8BAAkB,MAAM,EAAC,SAAS,EAAC,oCAAoC,YACpE,MAAM,GACF,EACN,QAAQ,IACN,CACN,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { shellTokens } from "../lib/shell-tokens.js";
|
|
3
|
+
const tokenClass = {
|
|
4
|
+
cmd: "tok-cmd",
|
|
5
|
+
flag: "tok-flag",
|
|
6
|
+
str: "tok-str",
|
|
7
|
+
text: undefined,
|
|
8
|
+
space: undefined,
|
|
9
|
+
};
|
|
10
|
+
export function ShellCommand({ command, }) {
|
|
11
|
+
return (_jsx(_Fragment, { children: shellTokens(command).map((token, index) => (_jsx("span", { className: tokenClass[token.kind], children: token.text }, index))) }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=shell-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-command.js","sourceRoot":"","sources":["../../src/components/shell-command.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEpD,MAAM,UAAU,GAAG;IACjB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,UAAU;IAChB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;CACR,CAAA;AAEV,MAAM,UAAU,YAAY,CAAC,EAC3B,OAAO,GAGR;IACC,OAAO,CACL,4BACG,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1C,eAAkB,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,YAChD,KAAK,CAAC,IAAI,IADF,KAAK,CAET,CACR,CAAC,GACD,CACJ,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export function SkipLink({ label = "Skip to content", }) {
|
|
3
|
+
return (_jsx("a", { href: "#main", className: "sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-50 focus:bg-foreground focus:px-3 focus:py-2 focus:text-background", children: label }));
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=skip-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skip-link.js","sourceRoot":"","sources":["../../src/components/skip-link.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,QAAQ,CAAC,EACvB,KAAK,GAAG,iBAAiB,GAG1B;IACC,OAAO,CACL,YACE,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,2IAA2I,YAEpJ,KAAK,GACJ,CACL,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { PlateAsset } from "../lib/plate-asset.ts";
|
|
3
|
+
export declare function StatusPage({ asset, plateClassName, heading, children, actions, }: {
|
|
4
|
+
readonly asset: PlateAsset;
|
|
5
|
+
readonly plateClassName: string;
|
|
6
|
+
readonly heading: ReactNode;
|
|
7
|
+
readonly children: ReactNode;
|
|
8
|
+
readonly actions: ReactNode;
|
|
9
|
+
}): ReactElement;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Plate } from "./plate.js";
|
|
3
|
+
export function StatusPage({ asset, plateClassName, heading, children, actions, }) {
|
|
4
|
+
return (_jsx("div", { className: "flex min-h-svh items-center justify-center px-6", children: _jsxs("main", { id: "main", className: "flex max-w-[38rem] flex-col gap-6", children: [_jsx(Plate, { asset: asset, className: plateClassName }), _jsx("h1", { className: "font-display text-[1.4rem]", children: heading }), _jsx("p", { className: "font-display text-[0.92rem] leading-[1.7]", children: children }), actions] }) }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=status-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-page.js","sourceRoot":"","sources":["../../src/components/status-page.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAa,CAAA;AAEnC,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,cAAc,EACd,OAAO,EACP,QAAQ,EACR,OAAO,GAOR;IACC,OAAO,CACL,cAAK,SAAS,EAAC,iDAAiD,YAC9D,gBAAM,EAAE,EAAC,MAAM,EAAC,SAAS,EAAC,mCAAmC,aAC3D,KAAC,KAAK,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,GAAI,EAClD,aAAI,SAAS,EAAC,4BAA4B,YAAE,OAAO,GAAM,EACzD,YAAG,SAAS,EAAC,2CAA2C,YAAE,QAAQ,GAAK,EACtE,OAAO,IACH,GACH,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Button as ButtonPrimitive } from "@base-ui/react/button";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
import type { ReactElement } from "react";
|
|
4
|
+
declare const buttonVariants: (props?: ({
|
|
5
|
+
variant?: "outline" | null | undefined;
|
|
6
|
+
size?: "xs" | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
|
+
declare function Button({ className, variant, size, ...props }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>): ReactElement;
|
|
9
|
+
export { Button };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button as ButtonPrimitive } from "@base-ui/react/button";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { cn } from "../../lib/utils.js";
|
|
5
|
+
const buttonVariants = cva("inline-flex shrink-0 items-center justify-center border border-transparent bg-clip-padding text-sm leading-none font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-foreground aria-invalid:ring-3 aria-invalid:ring-foreground/20", {
|
|
6
|
+
variants: {
|
|
7
|
+
variant: {
|
|
8
|
+
outline: "border-border bg-background hover:bg-foreground/5 hover:text-foreground aria-expanded:bg-foreground/5 aria-expanded:text-foreground",
|
|
9
|
+
},
|
|
10
|
+
size: {
|
|
11
|
+
xs: "h-6 gap-1 px-2.5 text-xs",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
variant: "outline",
|
|
16
|
+
size: "xs",
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
function Button({ className, variant = "outline", size = "xs", ...props }) {
|
|
20
|
+
return (_jsx(ButtonPrimitive, { "data-slot": "button", className: cn(buttonVariants({ variant, size, className })), ...props }));
|
|
21
|
+
}
|
|
22
|
+
export { Button };
|
|
23
|
+
//# sourceMappingURL=button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../../src/components/ui/button.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAGjE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,MAAM,cAAc,GAAG,GAAG,CACxB,qYAAqY,EACrY;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EACL,qIAAqI;SACxI;QACD,IAAI,EAAE;YACJ,EAAE,EAAE,0BAA0B;SAC/B;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,IAAI;KACX;CACF,CACF,CAAA;AAED,SAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,IAAI,EACX,GAAG,KAAK,EACoD;IAC5D,OAAO,CACL,KAAC,eAAe,iBACJ,QAAQ,EAClB,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,KACvD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { cn } from "./lib/utils.ts";
|
|
2
|
+
export { shellTokens, type ShellToken } from "./lib/shell-tokens.ts";
|
|
3
|
+
export { formatLongDate } from "./lib/iso-date.ts";
|
|
4
|
+
export type { PlateAsset } from "./lib/plate-asset.ts";
|
|
5
|
+
export type { CommandStep } from "./lib/command-step.ts";
|
|
6
|
+
export { ChevronIcon } from "./components/chevron-icon.tsx";
|
|
7
|
+
export { PageSection } from "./components/page-section.tsx";
|
|
8
|
+
export { PageShell } from "./components/page-shell.tsx";
|
|
9
|
+
export { PageTitle } from "./components/page-title.tsx";
|
|
10
|
+
export { SectionHeading } from "./components/section-heading.tsx";
|
|
11
|
+
export { ShellCommand } from "./components/shell-command.tsx";
|
|
12
|
+
export { CommandLine } from "./components/command-line.tsx";
|
|
13
|
+
export { CommandBlock } from "./components/command-block.tsx";
|
|
14
|
+
export { SkipLink } from "./components/skip-link.tsx";
|
|
15
|
+
export { Plate } from "./components/plate.tsx";
|
|
16
|
+
export { PlateHeader } from "./components/plate-header.tsx";
|
|
17
|
+
export { StatusPage } from "./components/status-page.tsx";
|
|
18
|
+
export { Button } from "./components/ui/button.tsx";
|
|
19
|
+
export { CopyButton, type CopyText } from "./components/copy-button.tsx";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { cn } from "./lib/utils.js";
|
|
2
|
+
export { shellTokens } from "./lib/shell-tokens.js";
|
|
3
|
+
export { formatLongDate } from "./lib/iso-date.js";
|
|
4
|
+
export { ChevronIcon } from "./components/chevron-icon.js";
|
|
5
|
+
export { PageSection } from "./components/page-section.js";
|
|
6
|
+
export { PageShell } from "./components/page-shell.js";
|
|
7
|
+
export { PageTitle } from "./components/page-title.js";
|
|
8
|
+
export { SectionHeading } from "./components/section-heading.js";
|
|
9
|
+
export { ShellCommand } from "./components/shell-command.js";
|
|
10
|
+
export { CommandLine } from "./components/command-line.js";
|
|
11
|
+
export { CommandBlock } from "./components/command-block.js";
|
|
12
|
+
export { SkipLink } from "./components/skip-link.js";
|
|
13
|
+
export { Plate } from "./components/plate.js";
|
|
14
|
+
export { PlateHeader } from "./components/plate-header.js";
|
|
15
|
+
export { StatusPage } from "./components/status-page.js";
|
|
16
|
+
export { Button } from "./components/ui/button.js";
|
|
17
|
+
export { CopyButton } from "./components/copy-button.js";
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAA;AACnC,OAAO,EAAE,WAAW,EAAmB,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA6B,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA6B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAkC,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAAgC,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAAgC,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA4B,CAAA;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAwB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA8B,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA4B,CAAA;AACnD,OAAO,EAAE,UAAU,EAAiB,MAAM,6BAA8B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-step.js","sourceRoot":"","sources":["../../src/lib/command-step.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function parseIsoDate(isoDate) {
|
|
2
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(isoDate)) {
|
|
3
|
+
throw new Error(`Invalid ISO date: ${isoDate}`);
|
|
4
|
+
}
|
|
5
|
+
const date = new Date(`${isoDate}T00:00:00Z`);
|
|
6
|
+
if (Number.isNaN(date.getTime()) ||
|
|
7
|
+
date.toISOString().slice(0, 10) !== isoDate) {
|
|
8
|
+
throw new Error(`Invalid ISO date: ${isoDate}`);
|
|
9
|
+
}
|
|
10
|
+
return date;
|
|
11
|
+
}
|
|
12
|
+
export function formatLongDate(isoDate) {
|
|
13
|
+
return new Intl.DateTimeFormat("en-GB", {
|
|
14
|
+
day: "numeric",
|
|
15
|
+
month: "long",
|
|
16
|
+
year: "numeric",
|
|
17
|
+
timeZone: "UTC",
|
|
18
|
+
}).format(parseIsoDate(isoDate));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=iso-date.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iso-date.js","sourceRoot":"","sources":["../../src/lib/iso-date.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAA;IACjD,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,OAAO,YAAY,CAAC,CAAA;IAC7C,IACE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,EAC3C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAA;IACjD,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QACtC,GAAG,EAAE,SAAS;QACd,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;AAClC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plate-asset.js","sourceRoot":"","sources":["../../src/lib/plate-asset.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const pieces = /\s+|'[^']*'|"[^"]*"|[^\s'"]+/g;
|
|
2
|
+
export function shellTokens(command) {
|
|
3
|
+
const texts = command.match(pieces) ?? [];
|
|
4
|
+
if (texts.join("") !== command) {
|
|
5
|
+
throw new Error(`Unbalanced quotes in command: ${command}`);
|
|
6
|
+
}
|
|
7
|
+
let atCommand = true;
|
|
8
|
+
return texts.map((text) => {
|
|
9
|
+
if (/^\s+$/.test(text)) {
|
|
10
|
+
return { kind: "space", text };
|
|
11
|
+
}
|
|
12
|
+
const kind = atCommand
|
|
13
|
+
? "cmd"
|
|
14
|
+
: text.startsWith("'") || text.startsWith('"')
|
|
15
|
+
? "str"
|
|
16
|
+
: /^--?[a-z]/i.test(text)
|
|
17
|
+
? "flag"
|
|
18
|
+
: "text";
|
|
19
|
+
atCommand = ["|", "||", "&&", ";"].includes(text);
|
|
20
|
+
return { kind, text };
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=shell-tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-tokens.js","sourceRoot":"","sources":["../../src/lib/shell-tokens.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,GAAG,+BAA+B,CAAA;AAE9C,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;IACzC,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAA;IAC7D,CAAC;IAED,IAAI,SAAS,GAAG,IAAI,CAAA;IACpB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAc,EAAE;QACpC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QAChC,CAAC;QAED,MAAM,IAAI,GAAG,SAAS;YACpB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAC5C,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;oBACvB,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,MAAM,CAAA;QACd,SAAS,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACjD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACvB,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,MAAM,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAExC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;AAC9B,CAAC"}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.tok-cmd {
|
|
2
|
+
color: var(--ink-deep);
|
|
3
|
+
font-weight: var(--font-weight-bold);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.tok-flag {
|
|
7
|
+
color: var(--ink-mid);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.tok-str {
|
|
11
|
+
color: var(--sprout);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.plate {
|
|
15
|
+
image-rendering: pixelated;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (scripting: none) {
|
|
19
|
+
.js-only {
|
|
20
|
+
display: none;
|
|
21
|
+
}
|
|
22
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openbunny/react",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "Generic React components for OpenBunny sites.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/openbunny/react.git"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"packageManager": "bun@1.4.2",
|
|
15
|
+
"engines": {
|
|
16
|
+
"bun": "1.4.2"
|
|
17
|
+
},
|
|
18
|
+
"browserslist": [
|
|
19
|
+
"chrome 111",
|
|
20
|
+
"edge 111",
|
|
21
|
+
"firefox 111",
|
|
22
|
+
"safari 16.4"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": [
|
|
25
|
+
"./dist/styles.css"
|
|
26
|
+
],
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./package.json": "./package.json",
|
|
36
|
+
"./styles.css": "./dist/styles.css"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"prepare": "bun run build",
|
|
40
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && cp src/styles.css dist/styles.css",
|
|
41
|
+
"format": "prettier --write .",
|
|
42
|
+
"format:check": "prettier --check .",
|
|
43
|
+
"lint": "eslint --max-warnings 0 .",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run --project unit --coverage",
|
|
46
|
+
"test:parity": "vitest run --project parity"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@base-ui/react": "^1.7.0",
|
|
50
|
+
"react": "^19.3.0",
|
|
51
|
+
"react-dom": "^19.3.0"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@types/react": "19.3.0",
|
|
55
|
+
"class-variance-authority": "0.7.1",
|
|
56
|
+
"clsx": "2.1.1",
|
|
57
|
+
"tailwind-merge": "3.7.0",
|
|
58
|
+
"typescript": "6.0.3"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@base-ui/react": "1.7.0",
|
|
62
|
+
"@testing-library/jest-dom": "7.0.1",
|
|
63
|
+
"@testing-library/react": "16.3.3",
|
|
64
|
+
"@types/node": "26.4.0",
|
|
65
|
+
"@types/react-dom": "19.3.0",
|
|
66
|
+
"@vitest/coverage-v8": "5.0.2",
|
|
67
|
+
"@vitest/eslint-plugin": "1.6.27",
|
|
68
|
+
"eslint": "9.39.5",
|
|
69
|
+
"eslint-config-next": "16.3.6",
|
|
70
|
+
"eslint-plugin-check-file": "3.3.2",
|
|
71
|
+
"eslint-plugin-compat": "7.0.2",
|
|
72
|
+
"eslint-plugin-promise": "7.3.0",
|
|
73
|
+
"eslint-plugin-regexp": "3.3.1",
|
|
74
|
+
"eslint-plugin-security": "4.1.0",
|
|
75
|
+
"eslint-plugin-unicorn": "65.0.0",
|
|
76
|
+
"eslint-plugin-unused-imports": "4.4.1",
|
|
77
|
+
"globals": "17.12.0",
|
|
78
|
+
"jsdom": "30.1.1",
|
|
79
|
+
"next": "16.3.6",
|
|
80
|
+
"prettier": "3.9.9",
|
|
81
|
+
"prettier-plugin-tailwindcss": "0.8.1",
|
|
82
|
+
"react": "19.3.0",
|
|
83
|
+
"react-dom": "19.3.0",
|
|
84
|
+
"tailwindcss": "4.3.3",
|
|
85
|
+
"typescript-eslint": "8.70.1",
|
|
86
|
+
"vitest": "5.0.2"
|
|
87
|
+
}
|
|
88
|
+
}
|