@abuzareal/contour-ui 0.6.0 → 0.6.2
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/CHANGELOG.md +8 -0
- package/COMBOBOX.md +4 -4
- package/COMPOSITION.md +4 -0
- package/CONTRACTS.md +11 -11
- package/DOCS.md +8 -2
- package/FORMS.md +4 -0
- package/FOUNDATION.md +1 -1
- package/GETTING-STARTED.md +7 -3
- package/HELPERS.md +33 -0
- package/HOOKS.md +67 -0
- package/MANUAL-QA.md +38 -0
- package/MIGRATION.md +44 -0
- package/MODELS.md +18 -0
- package/NEXTJS.md +1 -1
- package/OVERLAYS.md +6 -0
- package/PROP-REFERENCE.md +37 -0
- package/PUBLIC-API.md +166 -166
- package/README.md +5 -3
- package/RECIPES.md +3 -3
- package/REFERENCE.md +193 -0
- package/RELEASING.md +7 -1
- package/STYLING.md +4 -0
- package/SUPPORT.md +36 -0
- package/THREE.md +40 -0
- package/dist/components/ui/Combobox.js +18 -3
- package/dist/components/ui/Tooltip.js +1 -1
- package/dist/hooks/useInitialHashScroll.js +5 -1
- package/dist/hooks/usePrintPreparation.js +12 -1
- package/dist/hooks/useScrollSpy.js +6 -3
- package/docs/prop-metadata.json +2668 -0
- package/examples/onboarding/SettingsForm.jsx +30 -0
- package/examples/onboarding/SettingsForm.tsx +50 -0
- package/examples/reference/HookExamples.tsx +146 -0
- package/examples/reproduction/README.md +1 -1
- package/examples/reproduction/package.json +1 -1
- package/examples/starters/next/README.md +1 -1
- package/examples/starters/next/package.json +1 -1
- package/examples/starters/vite/README.md +1 -1
- package/examples/starters/vite/package.json +1 -1
- package/package.json +22 -4
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Generated from SettingsForm.tsx by scripts/build-onboarding.mjs.
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
import { Button, Checkbox, Combobox, TextField } from "@abuzareal/contour-ui";
|
|
4
|
+
const options = [
|
|
5
|
+
{ value: "atlas", label: "Atlas" },
|
|
6
|
+
{ value: "field", label: "Field notes" },
|
|
7
|
+
];
|
|
8
|
+
/** Local inspection only. Validate and authorize real submissions on the server. */
|
|
9
|
+
export default function SettingsForm() {
|
|
10
|
+
const [payload, setPayload] = useState("");
|
|
11
|
+
const name = useRef(null);
|
|
12
|
+
return (<section aria-label="Settings example">
|
|
13
|
+
<h2>Project settings</h2>
|
|
14
|
+
<p>This form inspects local values; it does not save them.</p>
|
|
15
|
+
<form onSubmit={(event) => {
|
|
16
|
+
event.preventDefault();
|
|
17
|
+
setPayload(JSON.stringify(Object.fromEntries(new FormData(event.currentTarget))));
|
|
18
|
+
}} onReset={() => setPayload("")}>
|
|
19
|
+
<TextField ref={name} label="Name" name="name" defaultValue="Ada" required/>
|
|
20
|
+
<Combobox label="Project" name="project" options={options} defaultValue="atlas" required/>
|
|
21
|
+
<Checkbox label="Allow updates" name="updates" defaultChecked/>
|
|
22
|
+
<Button type="submit">Inspect values</Button>
|
|
23
|
+
<Button type="reset" variant="secondary">
|
|
24
|
+
Reset form
|
|
25
|
+
</Button>
|
|
26
|
+
</form>
|
|
27
|
+
<output aria-label="Form values">{payload}</output>
|
|
28
|
+
<Button onClick={() => name.current?.focus()}>Focus name</Button>
|
|
29
|
+
</section>);
|
|
30
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useRef, useState } from "react";
|
|
2
|
+
import { Button, Checkbox, Combobox, TextField } from "@abuzareal/contour-ui";
|
|
3
|
+
const options = [
|
|
4
|
+
{ value: "atlas", label: "Atlas" },
|
|
5
|
+
{ value: "field", label: "Field notes" },
|
|
6
|
+
];
|
|
7
|
+
/** Local inspection only. Validate and authorize real submissions on the server. */
|
|
8
|
+
export default function SettingsForm() {
|
|
9
|
+
const [payload, setPayload] = useState("");
|
|
10
|
+
const name = useRef<HTMLInputElement>(null);
|
|
11
|
+
return (
|
|
12
|
+
<section aria-label="Settings example">
|
|
13
|
+
<h2>Project settings</h2>
|
|
14
|
+
<p>This form inspects local values; it does not save them.</p>
|
|
15
|
+
<form
|
|
16
|
+
onSubmit={(event) => {
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
setPayload(
|
|
19
|
+
JSON.stringify(
|
|
20
|
+
Object.fromEntries(new FormData(event.currentTarget)),
|
|
21
|
+
),
|
|
22
|
+
);
|
|
23
|
+
}}
|
|
24
|
+
onReset={() => setPayload("")}
|
|
25
|
+
>
|
|
26
|
+
<TextField
|
|
27
|
+
ref={name}
|
|
28
|
+
label="Name"
|
|
29
|
+
name="name"
|
|
30
|
+
defaultValue="Ada"
|
|
31
|
+
required
|
|
32
|
+
/>
|
|
33
|
+
<Combobox
|
|
34
|
+
label="Project"
|
|
35
|
+
name="project"
|
|
36
|
+
options={options}
|
|
37
|
+
defaultValue="atlas"
|
|
38
|
+
required
|
|
39
|
+
/>
|
|
40
|
+
<Checkbox label="Allow updates" name="updates" defaultChecked />
|
|
41
|
+
<Button type="submit">Inspect values</Button>
|
|
42
|
+
<Button type="reset" variant="secondary">
|
|
43
|
+
Reset form
|
|
44
|
+
</Button>
|
|
45
|
+
</form>
|
|
46
|
+
<output aria-label="Form values">{payload}</output>
|
|
47
|
+
<Button onClick={() => name.current?.focus()}>Focus name</Button>
|
|
48
|
+
</section>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { useRef, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
TextField,
|
|
5
|
+
ThemeScope,
|
|
6
|
+
ToastProvider,
|
|
7
|
+
useClipboardCopy,
|
|
8
|
+
useDismiss,
|
|
9
|
+
useIdleTrigger,
|
|
10
|
+
useMotionPreference,
|
|
11
|
+
useTheme,
|
|
12
|
+
useToast,
|
|
13
|
+
type Theme,
|
|
14
|
+
} from "@abuzareal/contour-ui";
|
|
15
|
+
export function ClipboardExample() {
|
|
16
|
+
const { copy, status } = useClipboardCopy(
|
|
17
|
+
"Public synthetic project reference",
|
|
18
|
+
);
|
|
19
|
+
return (
|
|
20
|
+
<section aria-label="Clipboard example">
|
|
21
|
+
<Button onClick={() => void copy()}>Copy reference</Button>
|
|
22
|
+
<p role="status">
|
|
23
|
+
{status === "error"
|
|
24
|
+
? "Copy failed. You can try again."
|
|
25
|
+
: status === "copied"
|
|
26
|
+
? "Copied."
|
|
27
|
+
: status === "copying"
|
|
28
|
+
? "Copying…"
|
|
29
|
+
: "Ready to copy."}
|
|
30
|
+
</p>
|
|
31
|
+
</section>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
export function MotionExample() {
|
|
35
|
+
const reduced = useMotionPreference();
|
|
36
|
+
const [paused, setPaused] = useState(false);
|
|
37
|
+
return (
|
|
38
|
+
<section aria-label="Motion preference">
|
|
39
|
+
<Button
|
|
40
|
+
aria-pressed={paused}
|
|
41
|
+
onClick={() => setPaused((value) => !value)}
|
|
42
|
+
>
|
|
43
|
+
Pause optional motion
|
|
44
|
+
</Button>
|
|
45
|
+
<p>Optional animation is {!reduced && !paused ? "allowed" : "paused"}.</p>
|
|
46
|
+
<p>
|
|
47
|
+
This example owns no animation loop; a scene must consume this combined
|
|
48
|
+
policy.
|
|
49
|
+
</p>
|
|
50
|
+
</section>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
export function DismissExample() {
|
|
54
|
+
const [open, setOpen] = useState(false);
|
|
55
|
+
const panel = useRef<HTMLDivElement>(null),
|
|
56
|
+
trigger = useRef<HTMLButtonElement>(null);
|
|
57
|
+
useDismiss(
|
|
58
|
+
panel,
|
|
59
|
+
open,
|
|
60
|
+
(reason) => {
|
|
61
|
+
setOpen(false);
|
|
62
|
+
if (reason === "escape") trigger.current?.focus();
|
|
63
|
+
},
|
|
64
|
+
{ branches: [trigger] },
|
|
65
|
+
);
|
|
66
|
+
return (
|
|
67
|
+
<section aria-label="Custom nonmodal dismissal">
|
|
68
|
+
<Button
|
|
69
|
+
ref={trigger}
|
|
70
|
+
aria-expanded={open}
|
|
71
|
+
aria-controls="example-help"
|
|
72
|
+
onClick={() => setOpen((value) => !value)}
|
|
73
|
+
>
|
|
74
|
+
Toggle custom help
|
|
75
|
+
</Button>
|
|
76
|
+
{open && (
|
|
77
|
+
<div
|
|
78
|
+
id="example-help"
|
|
79
|
+
ref={panel}
|
|
80
|
+
role="region"
|
|
81
|
+
aria-label="Custom help"
|
|
82
|
+
>
|
|
83
|
+
<p>This nonmodal example does not trap or move focus.</p>
|
|
84
|
+
<TextField label="Local note" />
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
87
|
+
</section>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
export function IdleExample() {
|
|
91
|
+
const [enabled, setEnabled] = useState(false);
|
|
92
|
+
const ready = useIdleTrigger(enabled);
|
|
93
|
+
return (
|
|
94
|
+
<section aria-label="Idle signal">
|
|
95
|
+
<Button onClick={() => setEnabled(true)}>Request idle signal</Button>
|
|
96
|
+
<p role="status">
|
|
97
|
+
{ready
|
|
98
|
+
? "Idle signal received; no work was loaded."
|
|
99
|
+
: enabled
|
|
100
|
+
? "Waiting for idle signal…"
|
|
101
|
+
: "Not requested."}
|
|
102
|
+
</p>
|
|
103
|
+
</section>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
function ThemeAction() {
|
|
107
|
+
const { theme, toggle } = useTheme(false);
|
|
108
|
+
return (
|
|
109
|
+
<Button
|
|
110
|
+
aria-pressed={theme === "dark"}
|
|
111
|
+
onClick={(event) => toggle(event.currentTarget)}
|
|
112
|
+
>
|
|
113
|
+
Dark embedded theme
|
|
114
|
+
</Button>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
export function ScopedThemeExample() {
|
|
118
|
+
const [theme, setTheme] = useState<Theme>("light");
|
|
119
|
+
return (
|
|
120
|
+
<ThemeScope theme={theme} onThemeChange={setTheme}>
|
|
121
|
+
<ThemeAction />
|
|
122
|
+
</ThemeScope>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
function ToastAction() {
|
|
126
|
+
const toast = useToast();
|
|
127
|
+
return (
|
|
128
|
+
<Button
|
|
129
|
+
onClick={() =>
|
|
130
|
+
toast.show({
|
|
131
|
+
title: "Notification example",
|
|
132
|
+
message: "This local example sends and saves nothing.",
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
>
|
|
136
|
+
Show example notification
|
|
137
|
+
</Button>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
export function ToastExample() {
|
|
141
|
+
return (
|
|
142
|
+
<ToastProvider>
|
|
143
|
+
<ToastAction />
|
|
144
|
+
</ToastProvider>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
@@ -4,6 +4,6 @@ Copy this folder alone into an empty directory. Run npm install --strict-peer-de
|
|
|
4
4
|
|
|
5
5
|
Keep a failing interaction in src/main.tsx and remove unrelated UI. Include installed Contour/React/browser versions, expected/actual behavior, keyboard steps, theme, viewport and the smallest input data. Replace names and service URLs with synthetic data; never include credentials, customer records or private repository links. A public repository or sandbox can use this standalone folder.
|
|
6
6
|
|
|
7
|
-
[Report a Contour 0.6.
|
|
7
|
+
[Report a Contour 0.6.1 Combobox issue](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&title=Combobox%200.6.1%3A%20&component=Combobox&version=0.6.1)
|
|
8
8
|
|
|
9
9
|
Candidate versions need the package to be published before registry installation; the maintainer tests the same source against the packed candidate first.
|
|
@@ -9,7 +9,7 @@ npm run build
|
|
|
9
9
|
npm start
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
Direct versions: Contour 0.6.
|
|
12
|
+
Direct versions: Contour 0.6.1, Next 16.4.0, React/React DOM 19.3.0, TypeScript 7.0.2; webpack explicitly selected. Commit the generated application lockfile and use npm ci afterward. There are no workspace aliases, optional Three/Lenis peers, fonts or required providers. To opt into branded fonts, import `@abuzareal/contour-ui/fonts-latin.css` in app/layout.tsx. Root CSS and route composition belong to the application.
|
|
13
13
|
|
|
14
14
|
layout.tsx and the page are server components. Demo.tsx owns client state, refs and handlers. The pure theme-bootstrap subpath is server-safe; before-paint script changes only the root theme attribute and theme-color. The root's suppressHydrationWarning is narrowly for this attribute, not a workaround for arbitrary mismatches.
|
|
15
15
|
|
|
@@ -9,7 +9,7 @@ npm run build
|
|
|
9
9
|
npm run preview
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
Uses Contour 0.6.
|
|
12
|
+
Uses Contour 0.6.1, React/React DOM 18.3.1, TypeScript 5.9.3 and Vite 8.3.2. No aliases, workspace links, optional peers, font download, private catalogue or provider are required. Scoped CSS includes tokens and component families without the legacy global reset. The application owns the small body/layout stylesheet. Optional branded fonts: import `@abuzareal/contour-ui/fonts-latin.css` once.
|
|
13
13
|
|
|
14
14
|
The Vite config inserts the exact released theme bootstrap before the application, with a calculated CSP script hash. Keep the placeholder in index.html; recalculate through the build after upgrades. Script execution is restricted; style attributes are allowed because popup positioning and some components use inline styles. Extend connect-src intentionally for your service/development socket. An HTTP CSP header may replace this meta policy if it contains the same hash. See the package GETTING-STARTED.md for embedded themes and optional features.
|
|
15
15
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abuzareal/contour-ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Editorial React components, themes, restrained motion, and optional Three.js objects.",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,19 @@
|
|
|
30
30
|
"examples/recipes",
|
|
31
31
|
"examples/starters",
|
|
32
32
|
"examples/reproduction",
|
|
33
|
-
"examples/optional"
|
|
33
|
+
"examples/optional",
|
|
34
|
+
"HOOKS.md",
|
|
35
|
+
"HELPERS.md",
|
|
36
|
+
"THREE.md",
|
|
37
|
+
"REFERENCE.md",
|
|
38
|
+
"PROP-REFERENCE.md",
|
|
39
|
+
"MIGRATION.md",
|
|
40
|
+
"MODELS.md",
|
|
41
|
+
"SUPPORT.md",
|
|
42
|
+
"MANUAL-QA.md",
|
|
43
|
+
"docs/prop-metadata.json",
|
|
44
|
+
"examples/onboarding",
|
|
45
|
+
"examples/reference"
|
|
34
46
|
],
|
|
35
47
|
"sideEffects": [
|
|
36
48
|
"**/*.css"
|
|
@@ -80,7 +92,7 @@
|
|
|
80
92
|
"test": "node --test tests/*.test.mjs",
|
|
81
93
|
"test:browser": "node --test tests/*.browser.mjs",
|
|
82
94
|
"check:package": "node scripts/check-package.mjs",
|
|
83
|
-
"validate": "npm run check:styles && npm run typecheck && npm run lint && npm run build && npm run check:docs && npm test && npm run test:browser && npm run check:package",
|
|
95
|
+
"validate": "npm run check:styles && npm run typecheck && npm run lint && npm run build && npm run check:docs && npm run check:reference && npm run check:onboarding && npm test && npm run test:browser && npm run check:package",
|
|
84
96
|
"prepublishOnly": "node scripts/verify-release.mjs",
|
|
85
97
|
"test:consumer": "node scripts/test-consumer.mjs",
|
|
86
98
|
"test:compat": "node scripts/test-compat.mjs",
|
|
@@ -95,7 +107,12 @@
|
|
|
95
107
|
"check:styles": "node scripts/build-styles.mjs --check",
|
|
96
108
|
"test:adoption-recipes": "node scripts/test-adoption-recipes.mjs",
|
|
97
109
|
"test:starters": "node scripts/test-starters.mjs",
|
|
98
|
-
"check:docs": "node scripts/check-docs.mjs"
|
|
110
|
+
"check:docs": "node scripts/check-docs.mjs",
|
|
111
|
+
"test:qa": "playwright test --config playwright.qa.config.mjs",
|
|
112
|
+
"check:reference": "node scripts/check-reference.mjs",
|
|
113
|
+
"check:onboarding": "node scripts/build-onboarding.mjs",
|
|
114
|
+
"qa:preview": "node scripts/qa-preview.mjs",
|
|
115
|
+
"test:diagnostic:upstream": "playwright test --config playwright.upstream.config.mjs"
|
|
99
116
|
},
|
|
100
117
|
"dependencies": {
|
|
101
118
|
"@base-ui/react": "1.9.0",
|
|
@@ -120,6 +137,7 @@
|
|
|
120
137
|
}
|
|
121
138
|
},
|
|
122
139
|
"devDependencies": {
|
|
140
|
+
"@axe-core/playwright": "4.13.0",
|
|
123
141
|
"@playwright/test": "1.63.0",
|
|
124
142
|
"@tanstack/react-store": "0.11.2",
|
|
125
143
|
"@tanstack/react-table": "9.3.1",
|