@abuzareal/contour-ui 0.6.3 → 0.6.4

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 CHANGED
@@ -8,7 +8,7 @@ Use it when you want this visual style with typed controls, feedback, navigation
8
8
 
9
9
  [Complete core component guides](COMPONENT-GUIDES.md) are maintained in a public authored dataset with runnable [family examples](examples/catalogue); they cover actual behavior as well as emitted props.
10
10
 
11
- This source checkout targets **0.6.3**. Package publication and application upgrades are separate; check the npm registry for release availability and each application's manifest for its installed version. Catalogue examples include application patterns as well as package components. Check the exports below before treating an example as an importable component.
11
+ This source checkout targets **0.6.4**. Package publication and application upgrades are separate; check the npm registry for release availability and each application's manifest for its installed version. Catalogue examples include application patterns as well as package components. Check the exports below before treating an example as an importable component.
12
12
 
13
13
  [Public API and maturity register](PUBLIC-API.md) · [Architecture, scope and compatibility](CONTRACTS.md)
14
14
 
@@ -25,7 +25,7 @@ Version 0.6 adds a single-select [Combobox](COMBOBOX.md) backed by pinned Base U
25
25
  Use an existing React application with a bundler that resolves package CSS imports. Contour ships ESM and TypeScript declarations. The package declares Node.js 22 or newer; repository tooling uses Vite 8, which needs Node.js 22.12+ or 24+.
26
26
 
27
27
  ```sh
28
- npm install @abuzareal/contour-ui@0.6.3 --save-exact
28
+ npm install @abuzareal/contour-ui@0.6.4 --save-exact
29
29
  ```
30
30
 
31
31
  Your app must provide matching `react` and `react-dom` versions: **18.3.1 or React 19**. The compatibility script covers 18.3.1, 19.0.0, and 19.3.0; it doesn't establish support for every framework or React Server Component setup. Put interactive components inside a client boundary when your framework requires one.
@@ -182,7 +182,7 @@ Give scenes a sized container and a usable static fallback. `SceneBoundary` hide
182
182
  **0.2.0** adds native field refs, controlled tabs and popover/menu open state, menu keyboard improvements, native reset synchronization, Three.js lifecycle fixes and a tested Next.js App Router integration. Existing uncontrolled defaults and React 18/19 support remain. `fonts-latin.css`, introduced in 0.1.2, now uses packaged relative font URLs for webpack resolution. `CHANGELOG.md` is included in the package archive and [npm's Code view](https://www.npmjs.com/package/@abuzareal/contour-ui?activeTab=code); it contains the upgrade details for each version.
183
183
 
184
184
  ```sh
185
- npm install @abuzareal/contour-ui@0.6.3 --save-exact
185
+ npm install @abuzareal/contour-ui@0.6.4 --save-exact
186
186
  ```
187
187
 
188
188
  Commit your manifest and lockfile, run your application's checks, and review both themes, dialogs, forms, and motion before deploying. Version 0.1.1 includes a document scroll lock for dialogs and drawers. Review any app-level lock before removing it, including nested dialogs and short screens. Package publication doesn't update deployed consumers automatically.
@@ -250,7 +250,7 @@ export function AccountControls() {
250
250
  }
251
251
  ```
252
252
 
253
- Interactive module boundaries retain `use client` in the built package. The pinned Next.js App Router consumer checks the packed candidate archive. Follow [Next.js setup](NEXTJS.md) for the pinned Next.js 16.4.0 / React 19.3.0 pair. Pure URL/theme-bootstrap helpers remain usable from the server. A separate fixture mode checks lazy optional Three.js loading and navigation cleanup. Lenis integration, other Next versions and alternate bundlers remain separate compatibility questions.
253
+ Interactive module boundaries retain `use client` in the built package. The pinned Next.js App Router consumer checks the packed candidate archive. Follow [Next.js setup](NEXTJS.md) for the pinned Next.js 16.4.3 / React 19.3.0 pair. Pure URL/theme-bootstrap helpers remain usable from the server. A separate fixture mode checks lazy optional Three.js loading and navigation cleanup. Lenis integration, other Next versions and alternate bundlers remain separate compatibility questions.
254
254
 
255
255
  Custom `useThreeStage` setup can register disposal through `context.onDispose?.(cleanup)` immediately after acquiring each resource, including resources allocated before setup returns. Registered resources are released on failed initialization and unmount; avoid also disposing the same resource in `StageScene.dispose`. A stage may implement `resize()` to reflow after aspect changes while motion is paused.
256
256
 
package/RECIPES.md CHANGED
@@ -40,4 +40,4 @@ The optional **password visibility recipe** keeps the same input mounted, name a
40
40
 
41
41
  Use native p/span and h1–h6 with [typography tokens](STYLING.md). Heading level follows the document outline; size/weight are CSS choices. No Text/Heading wrappers are added without an independent semantic/variant contract. These explicit scope decisions do not complete deferred NumberField, full grid, calendar or other optional features.
42
42
 
43
- [Report Table/recipes 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&title=Table%20recipes%200.6.3%3A%20&component=Table%20recipes&version=0.6.3); [standalone reproduction](examples/reproduction). See [public API](PUBLIC-API.md) for exact types, [styling](STYLING.md) and [onboarding](GETTING-STARTED.md). Release source links become available with the published tag.
43
+ [Report Table/recipes 0.6.4](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&title=Table%20recipes%200.6.4%3A%20&component=Table%20recipes&version=0.6.4); [standalone reproduction](examples/reproduction). See [public API](PUBLIC-API.md) for exact types, [styling](STYLING.md) and [onboarding](GETTING-STARTED.md). Release source links become available with the published tag.
package/REFERENCE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Export reference register
2
2
 
3
- Generated for 0.6.3 from actual source/runtime declarations and the manifest. This register maps all symbols and CSS/data entry points; it does not promote every component page. Human behavior guidance lives in the linked references. Source and exact types remain in [PUBLIC-API.md](PUBLIC-API.md). Run npm run check:reference; newly added hook/helper sources need an authored mapping before this register can update.
3
+ Generated for 0.6.4 from actual source/runtime declarations and the manifest. This register maps all symbols and CSS/data entry points; it does not promote every component page. Human behavior guidance lives in the linked references. Source and exact types remain in [PUBLIC-API.md](PUBLIC-API.md). Run npm run check:reference; newly added hook/helper sources need an authored mapping before this register can update.
4
4
 
5
5
  | Entry | Symbol | Kind | Reference |
6
6
  | --- | --- | --- | --- |
package/SIZE.md CHANGED
@@ -8,7 +8,7 @@ CONTOUR_SIZE_OUTPUT=/absolute/path/sizes.json npm run measure:size
8
8
  CONTOUR_SIZE_OUTPUT=/absolute/path/check.json npm run check:size
9
9
  ```
10
10
 
11
- Set `CONTOUR_ARCHIVE` to the already packed candidate to reuse it. Fixtures install React/React DOM 19.3.0; Next uses 16.4.0, and Vite/Chromium/Node versions are recorded from the running tools. The report names package/source commit/dirty state, archive checksum/files/compressed/unpacked bytes, the fresh dependency lock hash, resolved dependency versions, fixtures, exclusions, raw/gzip file sizes and actual Resource Timing transfers. These are reproducible fixtures, not latency or production-site benchmarks. No React/framework externals are removed from the application totals. Next shared JS is the intersection of actually fetched URLs across the measured fresh routes; route-specific JS is listed separately. Server build output is excluded from client bytes.
11
+ Set `CONTOUR_ARCHIVE` to the already packed candidate to reuse it. Fixtures install React/React DOM 19.3.0; Next uses 16.4.3, and Vite/Chromium/Node versions are recorded from the running tools. The report names package/source commit/dirty state, archive checksum/files/compressed/unpacked bytes, the fresh dependency lock hash, resolved dependency versions, fixtures, exclusions, raw/gzip file sizes and actual Resource Timing transfers. These are reproducible fixtures, not latency or production-site benchmarks. No React/framework externals are removed from the application totals. Next shared JS is the intersection of actually fetched URLs across the measured fresh routes; route-specific JS is listed separately. Server build output is excluded from client bytes.
12
12
 
13
13
  Raw minified JS/CSS is reported per actual fetched file and by fixture. Gzip level 9 is reported **per file**, never summed and advertised as an application gzip total. Network transfer, encoded body and decoded body measurements are kept separately, including document/RSC resources. CSS/font requests, archive size and library dependency-closure installed file bytes are separate categories. Install counts exclude Next/Vite/development tooling and record React peers separately. Optional Three.js, Lenis and RHF are absent from core fixtures.
14
14
 
@@ -46,6 +46,6 @@ Three.js/Lenis stay optional peers behind their entries. Core imports do not ins
46
46
 
47
47
  ## 0.6 Combobox measurement
48
48
 
49
- On 14 October 2026, an initial 0.6.0 candidate used the same production fixtures to measure the new Combobox journey with React 19.3.0, Vite 8.3.2, Next 16.4.0/webpack, Node 26.10.0 and Chromium 153. A fresh Vite page fetched 365,549 raw JS bytes; selective forms/actions CSS fetched 24,729 bytes (aggregate 47,625). The Next Combobox route fetched 593,605 raw client JS bytes and 46,807 CSS bytes, including framework/shared assets. These are dated candidate measurements, not immutable final-archive byte counts. The release gate remeasures its exact archive. These whole-application fixtures are not an isolated component size or an upstream bundle-size badge. Per-file gzip and actual Resource Timing are retained in the report; independent gzip files are not advertised as an additive component total.
49
+ On 14 October 2026, an initial 0.6.0 candidate used the same production fixtures to measure the new Combobox journey with React 19.3.0, Vite 8.3.2, Next 16.4.3/webpack, Node 26.10.0 and Chromium 153. A fresh Vite page fetched 365,549 raw JS bytes; selective forms/actions CSS fetched 24,729 bytes (aggregate 47,625). The Next Combobox route fetched 593,605 raw client JS bytes and 46,807 CSS bytes, including framework/shared assets. These are dated candidate measurements, not immutable final-archive byte counts. The release gate remeasures its exact archive. These whole-application fixtures are not an isolated component size or an upstream bundle-size badge. Per-file gzip and actual Resource Timing are retained in the report; independent gzip files are not advertised as an additive component total.
50
50
 
51
51
  Every previous journey stays within its existing budget. Initial Combobox budgets are added separately under the same 10% plus 1,024-byte policy; old budgets are not reset to the new measurements. The root Button fixture remains 227,291 raw Vite JS bytes with zero font requests; importing one component does not require downloading the Combobox route's full client code. All runtime dependencies still install with the package. Base UI adds installed files and an unstyled interaction dependency; see FOUNDATION.md for the identical-host comparison and its limitations. Its optional date/time peers are absent from core consumers. TanStack Table/Store and RHF are recipe dependencies only.
package/STYLING.md CHANGED
@@ -69,4 +69,4 @@ Forced-color rules preserve focus, selected control outlines, radio marks, inval
69
69
 
70
70
  ## Version and reproduction
71
71
 
72
- Reference version **0.6.3**. A source version does not establish publication; check the npm registry for availability. [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.3/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Styles 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Styles&version=0.6.3), using the [public minimal reproduction](examples/reproduction) and synthetic data.
72
+ Reference version **0.6.4**. A source version does not establish publication; check the npm registry for availability. [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.4/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Styles 0.6.4](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Styles&version=0.6.4), using the [public minimal reproduction](examples/reproduction) and synthetic data.
package/SUPPORT.md CHANGED
@@ -33,4 +33,4 @@ Every result should name package/commit/archive, date, OS/browser/tool versions,
33
33
 
34
34
  ## Version and reproduction
35
35
 
36
- Reference version **0.6.3**. A source version does not establish publication; check the npm registry for availability. [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.3/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Support matrix 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Support%20matrix&version=0.6.3), using the [public minimal reproduction](examples/reproduction) and synthetic data.
36
+ Reference version **0.6.4**. A source version does not establish publication; check the npm registry for availability. [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.4/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Support matrix 0.6.4](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Support%20matrix&version=0.6.4), using the [public minimal reproduction](examples/reproduction) and synthetic data.
package/THREE.md CHANGED
@@ -37,4 +37,4 @@ Use one stage owner per host, stable setup and deliberate size. Product controls
37
37
 
38
38
  ## Version and reproduction
39
39
 
40
- Reference version **0.6.3**. A source version does not establish publication; check the npm registry for availability. [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.3/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Three 0.6.3](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Three&version=0.6.3), using the [public minimal reproduction](examples/reproduction) and synthetic data.
40
+ Reference version **0.6.4**. A source version does not establish publication; check the npm registry for availability. [Versioned source](https://github.com/abuzareal/contour-ui/tree/v0.6.4/src) and [emitted type inventory](PUBLIC-API.md) describe this contract; tag links resolve after release. [Report Three 0.6.4](https://github.com/abuzareal/contour-ui/issues/new?template=bug_report.yml&component=Three&version=0.6.4), using the [public minimal reproduction](examples/reproduction) and synthetic data.
@@ -1,12 +1,16 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  /** Round avatar showing a photo or Space Grotesk initials, with an optional presence dot. */
4
+ import { useState } from "react";
3
5
  import { ccx } from "../../lib/classNames.js";
4
6
  const initialsOf = (name) => name
5
- .split(" ")
7
+ .trim()
8
+ .split(/\s+/)
6
9
  .map((part) => part[0])
7
10
  .slice(0, 2)
8
11
  .join("")
9
12
  .toUpperCase();
10
13
  export default function Avatar({ name, initials, src, size = "md", status, statusLabel, }) {
11
- return (_jsxs("span", { className: ccx("avatar", `avatar-${size}`), children: [src ? (_jsx("img", { src: src, alt: name, loading: "lazy", decoding: "async" })) : (_jsx("span", { role: "img", "aria-label": name, className: ccx("avatar-initials"), children: initials ?? initialsOf(name) })), status && (_jsx("span", { className: ccx("avatar-status", `avatar-status-${status}`), role: "img", "aria-label": statusLabel ?? (status === "online" ? "Online" : "Away") }))] }));
14
+ const [failedSource, setFailedSource] = useState();
15
+ return (_jsxs("span", { className: ccx("avatar", `avatar-${size}`), children: [src && src !== failedSource ? (_jsx("img", { src: src, alt: name, loading: "lazy", decoding: "async", onError: () => setFailedSource(src) }, src)) : (_jsx("span", { role: "img", "aria-label": name, className: ccx("avatar-initials"), children: initials ?? initialsOf(name) })), status && (_jsx("span", { className: ccx("avatar-status", `avatar-status-${status}`), role: "img", "aria-label": statusLabel ?? (status === "online" ? "Online" : "Away") }))] }));
12
16
  }
@@ -6,11 +6,12 @@ import { useRef } from "react";
6
6
  import { nextIndexForKey } from "../../lib/keyboard.js";
7
7
  export default function SegmentedControl({ label, options, value, onChange, }) {
8
8
  const buttons = useRef([]);
9
+ const focusIndex = Math.max(0, options.findIndex((option) => option.value === value));
9
10
  return (_jsx("div", { className: ccx("segmented"), role: "radiogroup", "aria-label": label, children: options.map((option, index) => {
10
11
  const selected = option.value === value;
11
12
  return (_jsx("button", { ref: (element) => {
12
13
  buttons.current[index] = element;
13
- }, type: "button", role: "radio", "aria-checked": selected, tabIndex: selected ? 0 : -1, className: ccx("segmented-option"), onClick: () => onChange(option.value), onKeyDown: (event) => {
14
+ }, type: "button", role: "radio", "aria-checked": selected, tabIndex: index === focusIndex ? 0 : -1, className: ccx("segmented-option"), onClick: () => onChange(option.value), onKeyDown: (event) => {
14
15
  const next = nextIndexForKey(event.key, index, options.length, "horizontal", event.currentTarget.ownerDocument.defaultView?.getComputedStyle(event.currentTarget).direction === "rtl"
15
16
  ? "rtl"
16
17
  : "ltr");
@@ -7,14 +7,26 @@ import { ToastContext, } from "../../hooks/useToast.js";
7
7
  import { ccx } from "../../lib/classNames.js";
8
8
  const autoDismissAfter = 5000;
9
9
  function Toast({ toast, onDismiss, dismissLabel, }) {
10
- const [paused, setPaused] = useState(false);
10
+ const [hovered, setHovered] = useState(false);
11
+ const [focused, setFocused] = useState(false);
12
+ const [hidden, setHidden] = useState(false);
13
+ const paused = hovered || focused || hidden;
14
+ useEffect(() => {
15
+ const update = () => setHidden(document.visibilityState === "hidden");
16
+ update();
17
+ document.addEventListener("visibilitychange", update);
18
+ return () => document.removeEventListener("visibilitychange", update);
19
+ }, []);
11
20
  useEffect(() => {
12
21
  if (paused)
13
22
  return;
14
23
  const timer = window.setTimeout(() => onDismiss(toast.id), autoDismissAfter);
15
24
  return () => window.clearTimeout(timer);
16
25
  }, [paused, toast.id, onDismiss]);
17
- return (_jsxs("li", { className: ccx("toast", `toast-${toast.tone ?? "neutral"}`), onPointerEnter: () => setPaused(true), onPointerLeave: () => setPaused(false), onFocus: () => setPaused(true), onBlur: () => setPaused(false), children: [_jsx("span", { className: ccx("toast-bar"), "aria-hidden": "true" }), _jsxs("div", { className: ccx("toast-content"), children: [_jsx("strong", { children: toast.title }), toast.message && _jsx("p", { children: toast.message })] }), _jsx("button", { type: "button", className: ccx("toast-close"), "aria-label": dismissLabel, onClick: () => onDismiss(toast.id), children: _jsx(X, { size: 15 }) })] }));
26
+ return (_jsxs("li", { className: ccx("toast", `toast-${toast.tone ?? "neutral"}`), onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), onFocus: () => setFocused(true), onBlur: (event) => {
27
+ if (!event.currentTarget.contains(event.relatedTarget))
28
+ setFocused(false);
29
+ }, children: [_jsx("span", { className: ccx("toast-bar"), "aria-hidden": "true" }), _jsxs("div", { className: ccx("toast-content"), children: [_jsx("strong", { children: toast.title }), toast.message && _jsx("p", { children: toast.message })] }), _jsx("button", { type: "button", className: ccx("toast-close"), "aria-label": dismissLabel, onClick: () => onDismiss(toast.id), children: _jsx(X, { size: 15 }) })] }));
18
30
  }
19
31
  export default function ToastProvider({ children, label = "Notifications", dismissLabel = "Dismiss notification", }) {
20
32
  const [toasts, setToasts] = useState([]);
@@ -64,7 +64,7 @@
64
64
  "initials / src",
65
65
  "string",
66
66
  "Derived initials / omitted",
67
- "No automatic failed-image-to-initials switch."
67
+ "Failed images fall back to initials. Changing src attempts the new image."
68
68
  ],
69
69
  ["size", "sm | md | lg | xl", "md", "Visual size only."],
70
70
  [
@@ -80,10 +80,10 @@
80
80
  "detail": {
81
81
  "use": "Use for identity context. Do not use initials or a presence color as the sole explanation of a person/action; put actionable behavior on a separate native control.",
82
82
  "anatomy": "Wrapper holds an img with alt=name or a role=img initials span; optional presence dot has its own accessible label.",
83
- "state": "src chooses image versus initials. initials overrides a basic first-two-space-separated-name-parts derivation. size defaults md; status is caller-supplied online/away.",
83
+ "state": "src chooses image versus initials. initials overrides a first-two-whitespace-separated-name-parts derivation. size defaults md; status is caller-supplied online/away.",
84
84
  "forms": "Not a successful form control: no name, required constraint or native reset behavior. Reset any application-owned content/request state separately.",
85
85
  "ref": "No public native-element ref is forwarded. Keep focus on actual native interactive children rather than making the presentation wrapper focusable.",
86
- "edgeCases": "If an image fails, native alt text remains; the app must remove/change src to select initials. Test empty/long names and unavailable status without inventing live presence.",
86
+ "edgeCases": "A failed image falls back to explicit initials or initials derived from the name. A new src attempts a new image. Supply a new URL to retry a previously failed source.",
87
87
  "localization": "Supply explicit initials for scripts/emoji/name order that basic splitting cannot handle. Translate statusLabel and keep full accessible names meaningful.",
88
88
  "reference": "props",
89
89
  "styling": "Use .contour-avatar, size and presence hooks with released semantic color/line/spacing tokens. Preserve native structure, visible labels and owned state/ARIA; visual customization does not change the interaction contract."
@@ -1344,8 +1344,8 @@
1344
1344
  "Update the selected value; no default/uncontrolled API."
1345
1345
  ]
1346
1346
  ],
1347
- "keyboard": "Tab enters the selected button. Arrows/Home/End move and select with RTL-aware horizontal navigation; Enter/Space uses native button activation.",
1348
- "limits": "No name/form/required serialization, disabled-option support, async state or forwarded aggregate ref. An absent selected value leaves no selected tab stop; validate it in the parent.",
1347
+ "keyboard": "Tab enters the selected button. Arrows/Home/End move and select with RTL-aware horizontal navigation; Enter/Space uses native button activation. If value is absent from the options, the first option remains reachable with Tab without silently changing the controlled value.",
1348
+ "limits": "No name/form/required serialization, disabled-option support, async state or forwarded aggregate ref. An absent value remains unselected; the first option stays keyboard reachable. Reconcile application state in the parent.",
1349
1349
  "tasks": "A controlled single-choice button group with radio semantics and roving focus. Use for a small mutually exclusive view/filter choice. Use native RadioGroup for successful form inputs and required validation; this does not create a global density/theme API.",
1350
1350
  "detail": {
1351
1351
  "use": "Use for a small mutually exclusive view/filter choice. Use native RadioGroup for successful form inputs and required validation; this does not create a global density/theme API.",
@@ -2088,10 +2088,10 @@
2088
2088
  "detail": {
2089
2089
  "use": "Use for brief established outcomes. Keep actionable errors beside the task; use an in-page alert for a failure that needs sustained attention.",
2090
2090
  "anatomy": "Provider owns a polite notification region with up to the latest three messages and dismiss buttons. Descendants call useToast().show({title,message?,tone?}).",
2091
- "state": "The queue auto-dismisses after five seconds and pauses while hovered/focused. show reports an outcome; it does not run an operation. There are no IDs, update commands, undo or durable inbox.",
2091
+ "state": "The queue auto-dismisses after five seconds and pauses while hovered, focused or in a hidden document. show reports an outcome; it does not run an operation. There are no IDs, update commands, undo or durable inbox.",
2092
2092
  "forms": "No native form value or reset contract. Notify only after a real save result, and preserve field validation in the form.",
2093
2093
  "ref": "No native provider ref. Calling useToast outside the provider throws; mount a provider around actual consumers.",
2094
- "edgeCases": "Rapid messages displace older entries. Do not put the only record of a failure in a temporary toast. Respect focus/motion and test translated long messages.",
2094
+ "edgeCases": "Dismissal pauses while the toast is hovered, contains keyboard focus, or the document is hidden. Once all pause conditions clear, a fresh five-second reading period begins. The queue retains up to three notifications.",
2095
2095
  "localization": "Set label and dismissLabel on the provider and translate each title/message. Manual screen-reader announcement review remains pending; polite markup is not proof of every announcement.",
2096
2096
  "reference": "hooks",
2097
2097
  "styling": "Use the released scoped CSS and semantic tokens inside contour-root/ThemeScope. Preserve native semantics, public part/state hooks and geometry ownership; see the component-specific anatomy and STYLING.md."
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.3",
2
+ "version": "0.6.4",
3
3
  "compiler": "5.9.3",
4
4
  "scope": "All exported component contracts from emitted declarations, including call/construct signatures and authored/inherited prop names. Selected prop types include authored guide fields, owned fields and native integration attributes. Only explicit source parameter initializers are defaults; absence is not a browser default inference.",
5
5
  "components": {
@@ -7,7 +7,7 @@ import {
7
7
 
8
8
  export default function PreferencesAndCopy({
9
9
  animate = true,
10
- command = "npm install @abuzareal/contour-ui@0.6.3 --save-exact",
10
+ command = "npm install @abuzareal/contour-ui@0.6.4 --save-exact",
11
11
  }: {
12
12
  animate?: boolean;
13
13
  command?: string;
@@ -13,7 +13,7 @@
13
13
  "preview": "vite preview"
14
14
  },
15
15
  "dependencies": {
16
- "@abuzareal/contour-ui": "0.6.3",
16
+ "@abuzareal/contour-ui": "0.6.4",
17
17
  "react": "18.3.1",
18
18
  "react-dom": "18.3.1"
19
19
  },
@@ -22,6 +22,6 @@
22
22
  "@types/react-dom": "18.3.7",
23
23
  "@types/node": "26.6.5",
24
24
  "typescript": "5.9.3",
25
- "vite": "8.3.2"
25
+ "vite": "8.3.5"
26
26
  }
27
27
  }
@@ -9,7 +9,7 @@ npm run build
9
9
  npm start
10
10
  ```
11
11
 
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.
12
+ Direct versions: Contour 0.6.4, Next 16.4.3, 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
 
@@ -13,10 +13,10 @@
13
13
  "start": "next start"
14
14
  },
15
15
  "dependencies": {
16
- "@abuzareal/contour-ui": "0.6.3",
16
+ "@abuzareal/contour-ui": "0.6.4",
17
17
  "react": "19.3.0",
18
18
  "react-dom": "19.3.0",
19
- "next": "16.4.0"
19
+ "next": "16.4.3"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/react": "19.3.0",
@@ -9,7 +9,7 @@ npm run build
9
9
  npm run preview
10
10
  ```
11
11
 
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.
12
+ Uses Contour 0.6.4, React/React DOM 18.3.1, TypeScript 5.9.3 and Vite 8.3.5. 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
 
@@ -13,7 +13,7 @@
13
13
  "preview": "vite preview"
14
14
  },
15
15
  "dependencies": {
16
- "@abuzareal/contour-ui": "0.6.3",
16
+ "@abuzareal/contour-ui": "0.6.4",
17
17
  "react": "18.3.1",
18
18
  "react-dom": "18.3.1"
19
19
  },
@@ -22,6 +22,6 @@
22
22
  "@types/react-dom": "18.3.7",
23
23
  "@types/node": "26.6.5",
24
24
  "typescript": "5.9.3",
25
- "vite": "8.3.2"
25
+ "vite": "8.3.5"
26
26
  }
27
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abuzareal/contour-ui",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "private": false,
5
5
  "description": "Editorial React components, themes, restrained motion, and optional Three.js objects.",
6
6
  "type": "module",
@@ -156,7 +156,7 @@
156
156
  "react-dom": "18.3.1",
157
157
  "three": "^0.186.1",
158
158
  "typescript": "^5.5.3",
159
- "vite": "^8.3.2"
159
+ "vite": "^8.3.5"
160
160
  },
161
161
  "engines": {
162
162
  "node": ">=22"