@consciousclouds/shell-primitive 0.1.0 → 0.1.3

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 CHANGED
@@ -1,7 +1,61 @@
1
+ # 0.1.3 (unreleased) — a tablet starts with the icon rail
2
+
3
+ Not published: it is published only under its own owner GO, then its digest is recorded (Lane 5's ruling (A); the
4
+ second frontend publish batch, after operator-shell 0.2.3's).
5
+
6
+ - **A tablet starts with the icon rail** (CCU Admin inventory R5). `sidebarDefaultOpen` is now the operator's SAVED
7
+ choice, absent when there is none (it was a boolean defaulting to `true`). With no choice the sidebar is expanded,
8
+ except at 768 to 1023px of shell, where it is the icon rail so the page keeps its width; the width keeps deciding
9
+ until the operator toggles. That automatic state is never written to the `sidebar_state` cookie: the frame now
10
+ controls the registry sidebar (`open` / `onOpenChange`), and only the operator's toggle reaches the sidebar's own
11
+ cookie write. A saved choice wins at every width. Because the shell is measured after mount, a tablet's first paint
12
+ is expanded and settles to the rail once measured (the header's post-measure reflow, too); the server cannot know
13
+ the width, and the collapsed look is the sidebar's own `data-collapsible` state, which no media query can set.
14
+ A product that passed `true` for "no cookie" should now pass nothing.
15
+
16
+ # 0.1.2 — Responsive shell local candidate
17
+
18
+ Add ShellViewportProvider/useShellViewport for container-aware composition. ShellFrame measures header height, uses available CSS layout width for sidebar/reflow and bounds portals. Default host is 100dvh; consumers can supply a sized provider. Existing slots and motion tokens remain supported.
19
+
20
+ Not published. Frozen earlier candidates remain unchanged.
21
+
1
22
  # Changelog
2
23
 
3
24
  All notable changes to `@consciousclouds/shell-primitive` are documented here.
4
25
 
26
+ ## [0.1.1] — local release candidate, 2026-11-01
27
+
28
+ - Require UI and Tokens ^0.1.1 through registry-compatible ranges; declare React DOM; respect reduced motion for workspace and inspector reflow using the existing UI hook. Public props unchanged.
29
+ - Pack lifecycle builds fresh distributable output. Historical 0.1.0 is unchanged.
30
+ - Candidate only: no registry publication or published-digest claim.
31
+
32
+ ## Unreleased
33
+
34
+ - **A skip link** (WCAG 2.4.1, bypass blocks). `ShellFrame` renders "Skip to content" as its first focusable element,
35
+ hidden until it has focus.
36
+ - It moves focus straight to the workspace scroller (`#shell-workspace`, in both chromes), so the next Tab lands in
37
+ the page.
38
+ - `skipLinkLabel` overrides its text.
39
+ - Measured in a real browser: the first Tab stop, visible with a ring. Enter puts focus in `<main>`: 2 key presses
40
+ instead of 8 with no grants, and more with a full nav.
41
+ - **The inspector region** (Frontend Platform Doctrine: the frame owns the header · nav · workspace · inspector
42
+ regions). `ShellFrame` gains the optional `inspector` slot, plus `inspectorOpen` (default `false`) and
43
+ `inspectorWidth` (default 384, surfaced as `--inspector-width`).
44
+ - Like the assistant, the slot node owns its own open/close, focus and width. The frame owns its placement,
45
+ directly beside the workspace and before the assistant, and the reflow: the workspace↔inspector gap opens while
46
+ `inspectorOpen` says the inspector takes space.
47
+ - No inspector ⇒ no region and no wrapper; the DOM is unchanged.
48
+ - In framed chrome the workspace and the inspector share their own row (`data-slot="shell-inspector-reflow"`),
49
+ so a closed zero-width inspector never adds a second gap beside the assistant.
50
+ - `ShellFrame` gains **`sidebarDefaultOpen`** (default `true`), handed to the
51
+ registry `SidebarProvider` as `defaultOpen`.
52
+ - The workspace scroll container is **keyboard-focusable** with a visible focus
53
+ ring (axe `scrollable-region-focusable`).
54
+ - **Framed chrome pads less on phones** (outer `p-2`, inner `p-3` below `sm`), so
55
+ the two layers no longer take 64px of a 390px screen.
56
+ - The reflow container carries `data-slot="shell-reflow"`. Tests select it by
57
+ that slot, not by padding classes.
58
+
5
59
  ## 0.1.0
6
60
 
7
61
  - Initial extraction of the neutral **Shell Primitive** from the live
package/README.md CHANGED
@@ -38,3 +38,26 @@ in Chief) owns its own open/close and focus lifecycle — the frame only reflows
38
38
  the main region around it.
39
39
 
40
40
  See `docs/design/frontend-platform-doctrine.md`.
41
+
42
+ ## Unit 1 compatibility candidate (0.1.1, unpublished)
43
+
44
+ Require UI and Tokens ^0.1.1 through registry-compatible ranges; declare React DOM; respect reduced motion for workspace and inspector reflow using the existing UI hook. Public props unchanged.
45
+
46
+ Use public package exports. No product checkout, application runtime or Universal source alias is required.
47
+ React 19, React Router 7/Vite 6 and Next.js 16/Tailwind 4 are the Unit 1 verification targets.
48
+ The existing React >=18 peer range is preserved; this unit does not certify every version in that range.
49
+ For CSS consumers, import Tailwind first, then `@consciousclouds/tokens/styles/house.css`,
50
+ `@consciousclouds/ui/styles/source.css`, and `@consciousclouds/shell-primitive/styles/source.css`
51
+ when using the frame. The CSS source registrations scan installed `dist` files.
52
+ Theme colors remain HSL channel triples (for example `145 65% 28%`), not full `hsl(...)` or `oklch(...)` values.
53
+ Product fonts, logos, navigation, flavors and authority remain consumer-owned.
54
+ Brand overrides target the document root; multiple independently themed embedded roots need a separately approved scoping contract.
55
+ See `scripts/frontend-foundation-unit1/README.md` in the source repository for reproducible candidate verification,
56
+ publication ordering and release limitations.
57
+
58
+
59
+ ## Responsive candidate 0.1.2
60
+
61
+ Add ShellViewportProvider/useShellViewport for container-aware composition. ShellFrame measures header height, uses available CSS layout width for sidebar/reflow and bounds portals. Default host is 100dvh; consumers can supply a sized provider. Existing slots and motion tokens remain supported.
62
+
63
+ See `scripts/operator-shell-responsive/README.md` in the source repository for artifact-only verification and compatibility limits. This is a local candidate, not a published release.
@@ -8,8 +8,18 @@
8
8
  * - a full-width header bar (the `header` slot) above
9
9
  * - an icon-collapsible sidebar (the `sidebar` slot) and
10
10
  * - a main / workspace region (`children`), with
11
+ * - an OPTIONAL inspector region beside it (the `inspector` slot), and
11
12
  * - an OPTIONAL right-side assistant panel (the `assistant` slot).
12
13
  *
14
+ * The inspector region is the frame's fourth region (Frontend Platform Doctrine:
15
+ * header · nav · workspace · inspector). Like the assistant, the slot node owns
16
+ * its own open/close, focus and width; the frame owns only its PLACEMENT,
17
+ * directly beside the workspace and before the assistant, and the reflow: the
18
+ * workspace↔inspector gap opens while `inspectorOpen` says the inspector takes
19
+ * space. The slot decides when it takes space (a shell may dock it only where
20
+ * the viewport has room and float it otherwise). No inspector ⇒ no region and
21
+ * no wrapper: the frame's DOM is exactly what it was.
22
+ *
13
23
  * The assistant-panel PLACEMENT is a frame concern; the assistant's turn flow,
14
24
  * open/close lifecycle, focus return, and its own panel-width / scrim are the
15
25
  * SLOT's concern (whatever node a shell drops in — the operator shell drops in
@@ -74,14 +84,48 @@ export interface ShellFrameProps {
74
84
  * for `push`. `rail` is always in-flow at `xl+`; `overlay` never reflows.
75
85
  */
76
86
  assistantOpen?: boolean;
87
+ /**
88
+ * OPTIONAL inspector region — the detail panel beside the workspace. The node
89
+ * owns its OWN open/close, focus and width; the frame places it between the
90
+ * workspace and the assistant and reflows the workspace around it. Absent ⇒ no
91
+ * region and no extra wrapper.
92
+ */
93
+ inspector?: React.ReactNode;
94
+ /**
95
+ * Whether the inspector currently TAKES SPACE beside the workspace (default
96
+ * `false`) — opens the workspace↔inspector gap. A slot that floats (a sheet
97
+ * over the content) leaves this false.
98
+ */
99
+ inspectorOpen?: boolean;
100
+ /**
101
+ * The inspector's width in px (default 384), surfaced to the slot as the
102
+ * `--inspector-width` CSS custom property.
103
+ */
104
+ inspectorWidth?: number;
77
105
  /** The main region's chrome (default `framed`). */
78
106
  workspaceChrome?: ShellWorkspaceChrome;
107
+ /**
108
+ * The skip link's text (default "Skip to content"). The link is the frame's first focusable element, hidden until it
109
+ * has focus, and moves focus to the workspace, so a keyboard operator does not tab through the header and every nav
110
+ * item on every page.
111
+ */
112
+ skipLinkLabel?: string;
79
113
  /**
80
114
  * OPTIONAL overlay surfaces (e.g. a command palette) mounted inside the
81
115
  * frame's provider context but out of flow — portals/dialogs that must sit
82
116
  * within the shell's React tree without disturbing the layout.
83
117
  */
84
118
  overlays?: React.ReactNode;
119
+ /**
120
+ * The operator's SAVED sidebar choice: `true` expanded, `false` collapsed, absent when they have made none. The
121
+ * registry sidebar writes its state to the `sidebar_state` cookie on every toggle; a product that reads that cookie
122
+ * on the server passes it here (absent when there is no cookie), so a choice survives a reload.
123
+ *
124
+ * With no saved choice, the sidebar is expanded, except on a tablet (768 to 1023px of shell), where it starts as the
125
+ * icon rail so the page keeps its width (CCU Admin inventory R5). That automatic state is never written to the
126
+ * cookie: only the operator's own toggle is, so a tablet never decides the desktop's sidebar.
127
+ */
128
+ sidebarDefaultOpen?: boolean;
85
129
  }
86
- export declare function ShellFrame({ header, sidebar, children, assistant, assistantBehavior, assistantWidth, assistantOpen, workspaceChrome, overlays, }: ShellFrameProps): import("react/jsx-runtime").JSX.Element;
130
+ export declare function ShellFrame(props: ShellFrameProps): import("react/jsx-runtime").JSX.Element;
87
131
  //# sourceMappingURL=ShellFrame.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ShellFrame.d.ts","sourceRoot":"","sources":["../../src/frame/ShellFrame.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,kFAAkF;AAClF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,cAAc,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,8DAA8D;IAC9D,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,yEAAyE;IACzE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mDAAmD;IACnD,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAcD,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,OAAO,EACP,QAAQ,EACR,SAAS,EACT,iBAA0B,EAC1B,cAAoB,EACpB,aAAqB,EACrB,eAA0B,EAC1B,QAAQ,GACT,EAAE,eAAe,2CA2DjB"}
1
+ {"version":3,"file":"ShellFrame.d.ts","sourceRoot":"","sources":["../../src/frame/ShellFrame.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,kFAAkF;AAClF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,cAAc,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,8DAA8D;IAC9D,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,yEAAyE;IACzE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAiBD,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAGhD"}
@@ -1,39 +1,136 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /**
4
+ * ShellFrame — the neutral shell FRAME: the one layout skeleton every
5
+ * Frontend-Platform shell (Operator / Business / Consumer) frames around.
6
+ * MECHANISM, not meaning — it knows nothing of any product, of Chief, of a
7
+ * transport, of the nav engine, or of the permission guard. It owns only the
8
+ * arrangement:
9
+ *
10
+ * - a full-width header bar (the `header` slot) above
11
+ * - an icon-collapsible sidebar (the `sidebar` slot) and
12
+ * - a main / workspace region (`children`), with
13
+ * - an OPTIONAL inspector region beside it (the `inspector` slot), and
14
+ * - an OPTIONAL right-side assistant panel (the `assistant` slot).
15
+ *
16
+ * The inspector region is the frame's fourth region (Frontend Platform Doctrine:
17
+ * header · nav · workspace · inspector). Like the assistant, the slot node owns
18
+ * its own open/close, focus and width; the frame owns only its PLACEMENT,
19
+ * directly beside the workspace and before the assistant, and the reflow: the
20
+ * workspace↔inspector gap opens while `inspectorOpen` says the inspector takes
21
+ * space. The slot decides when it takes space (a shell may dock it only where
22
+ * the viewport has room and float it otherwise). No inspector ⇒ no region and
23
+ * no wrapper: the frame's DOM is exactly what it was.
24
+ *
25
+ * The assistant-panel PLACEMENT is a frame concern; the assistant's turn flow,
26
+ * open/close lifecycle, focus return, and its own panel-width / scrim are the
27
+ * SLOT's concern (whatever node a shell drops in — the operator shell drops in
28
+ * Chief). The frame's job is the MAIN-REGION REFLOW: the gap between the
29
+ * workspace and the panel animates as the panel occupies space, given
30
+ * (assistant present + behavior + open + width).
31
+ *
32
+ * - `push` (default): the workspace visibly reflows beside an in-flow panel
33
+ * at `lg+` (the gap opens from 0 to 1rem when the panel opens).
34
+ * - `overlay`: the panel floats over the workspace — no reflow (the gap
35
+ * stays 0; the slot renders its own floating drawer).
36
+ * - `rail`: an always-present in-flow rail at `xl+` — the gap is always open
37
+ * at `xl+`.
38
+ *
39
+ * If NO assistant slot is passed, no panel and no reflow render at all: "a
40
+ * shell without an assistant" falls out for free (the gap is permanently 0 and
41
+ * the workspace fills the inset). This is exactly what the future Business /
42
+ * Consumer shells rely on when they frame around ShellFrame without Chief.
43
+ *
44
+ * The reflow motion is read from @consciousclouds/tokens (`motionTokens`) —
45
+ * the platform's single source of truth for duration/easing — never
46
+ * hand-rolled numbers. Everything else is layout composed over
47
+ * @consciousclouds/ui's `SidebarProvider` / `SidebarInset`.
48
+ */
49
+ import * as React from "react";
50
+ import { ShellViewportProvider, useShellViewport } from "./viewport.js";
3
51
  import { motionTokens } from "@consciousclouds/tokens";
4
- import { SidebarInset, SidebarProvider, cn } from "@consciousclouds/ui";
52
+ import { SidebarInset, SidebarProvider, cn, useReducedMotion } from "@consciousclouds/ui";
5
53
  /**
6
54
  * The reflow transition — motion from the token vocabulary, applied inline so
7
55
  * the timing travels with the JS values (no hand-rolled `duration-300 /
8
56
  * ease-in-out`). The gap VALUES stay Tailwind classes; only the timing is
9
57
  * tokenized here.
10
58
  */
59
+ /** The workspace scroller's id: the skip link's target, one per frame (a page renders one shell). */
60
+ const WORKSPACE_ID = "shell-workspace";
11
61
  const REFLOW_TRANSITION = {
12
62
  transitionProperty: "gap",
13
63
  transitionDuration: `${motionTokens.duration.base}s`,
14
64
  transitionTimingFunction: `cubic-bezier(${motionTokens.easing.standard.join(", ")})`,
15
65
  };
16
- export function ShellFrame({ header, sidebar, children, assistant, assistantBehavior = "push", assistantWidth = 420, assistantOpen = false, workspaceChrome = "framed", overlays, }) {
66
+ export function ShellFrame(props) {
67
+ const viewport = useShellViewport();
68
+ return viewport ? _jsx(ShellFrameBody, { ...props }) : _jsx(ShellViewportProvider, { children: _jsx(ShellFrameBody, { ...props }) });
69
+ }
70
+ function ShellFrameBody({ header, sidebar, children, assistant, assistantBehavior = "push", assistantWidth = 420, assistantOpen = false, inspector, inspectorOpen = false, inspectorWidth = 384, workspaceChrome = "framed", skipLinkLabel = "Skip to content", overlays, sidebarDefaultOpen, }) {
71
+ const viewport = useShellViewport();
72
+ // The operator's choice, once they have one (saved, or toggled here). Until then the width decides: the icon rail
73
+ // on a tablet, expanded otherwise. The shell is measured after mount, so a tablet's first paint is expanded and it
74
+ // settles to the rail once measured (the same post-measure reflow as the header's): the server cannot know the
75
+ // width, and the collapsed look is the sidebar's own data-collapsible state, not CSS a media query could reach.
76
+ const [sidebarChoice, setSidebarChoice] = React.useState(sidebarDefaultOpen);
77
+ const tablet = viewport?.width !== undefined && viewport.width >= 768 && viewport.width < 1024;
78
+ const sidebarOpen = sidebarChoice ?? !tablet;
79
+ const headerRef = React.useRef(null);
80
+ const [headerHeight, setHeaderHeight] = React.useState(56);
81
+ React.useEffect(() => {
82
+ const element = headerRef.current;
83
+ if (!element)
84
+ return;
85
+ const measure = () => { const height = element.offsetHeight; if (height > 0)
86
+ setHeaderHeight(height); };
87
+ measure();
88
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
89
+ observer?.observe(element);
90
+ return () => observer?.disconnect();
91
+ }, []);
92
+ const reducedMotion = useReducedMotion();
93
+ const reflowTransition = reducedMotion
94
+ ? { ...REFLOW_TRANSITION, transitionDuration: "0s" }
95
+ : REFLOW_TRANSITION;
17
96
  const framed = workspaceChrome === "framed";
18
97
  const hasAssistant = assistant != null;
98
+ const hasInspector = inspector != null;
99
+ const narrow = viewport?.width !== undefined && viewport.width < 768;
19
100
  // The main-region reflow gap: opens (0 → 1rem) as the panel takes space.
20
101
  // Only ever non-zero when an assistant is present — no assistant ⇒ no reflow.
21
102
  const reflowGap = !hasAssistant
22
103
  ? "gap-0"
23
104
  : assistantBehavior === "rail"
24
- ? "gap-0 xl:gap-4"
105
+ ? (viewport?.width === undefined ? "gap-0 xl:gap-4" : viewport.width >= 1280 ? "gap-4" : "gap-0")
25
106
  : assistantBehavior === "push" && assistantOpen
26
- ? "gap-0 lg:gap-4"
107
+ ? (viewport?.width === undefined ? "gap-0 lg:gap-4" : viewport.width >= 1024 ? "gap-4" : "gap-0")
27
108
  : "gap-0";
28
- return (_jsxs(SidebarProvider, { className: "h-svh flex-col overflow-hidden", style: {
29
- "--header-height": "3.5rem",
109
+ // FRAMED chrome: the workspace card and the inspector share their own flex row, so the inspector's gap is
110
+ // independent of the assistant's (a closed, zero-width region never adds a second gap beside the assistant).
111
+ const withInspector = (workspace) => hasInspector ? (_jsxs("div", { "data-slot": "shell-inspector-reflow", className: cn("flex min-h-0 min-w-0 flex-1", inspectorOpen ? "gap-4" : "gap-0"), style: reflowTransition, children: [workspace, inspector] })) : (workspace);
112
+ return (_jsxs(SidebarProvider
113
+ // Controlled: the registry sidebar writes its cookie only through its own setOpen (the operator's toggle), so
114
+ // the automatic tablet rail above is never saved as a choice.
115
+ , {
116
+ // Controlled: the registry sidebar writes its cookie only through its own setOpen (the operator's toggle), so
117
+ // the automatic tablet rail above is never saved as a choice.
118
+ open: sidebarOpen, onOpenChange: setSidebarChoice, mobile: viewport?.width === undefined ? undefined : viewport.width < 768, mobileContainer: viewport?.element, className: "h-full min-h-0 flex-col overflow-hidden", style: {
119
+ "--header-height": `${headerHeight}px`,
30
120
  "--assistant-width": `${assistantWidth}px`,
31
- }, children: [header, overlays, _jsxs("div", { className: "flex min-h-0 flex-1", children: [sidebar, _jsx(SidebarInset, { className: "min-h-0 flex-row overflow-hidden", children: framed ? (
121
+ "--inspector-width": `${inspectorWidth}px`,
122
+ }, children: [_jsx("a", { href: `#${WORKSPACE_ID}`, "data-slot": "shell-skip-link", onClick: (event) => {
123
+ const workspace = document.getElementById(WORKSPACE_ID);
124
+ if (!workspace)
125
+ return;
126
+ event.preventDefault();
127
+ workspace.focus();
128
+ }, className: "sr-only focus:not-sr-only focus:fixed focus:top-3 focus:left-3 focus:z-[100] focus:rounded-md focus:bg-background focus:px-3 focus:py-2 focus:text-sm focus:font-medium focus:text-foreground focus:shadow-overlay focus:outline-none focus:ring-2 focus:ring-ring", children: skipLinkLabel }), _jsx("div", { ref: headerRef, className: "shrink-0", children: header }), overlays, _jsxs("div", { className: "flex min-h-0 flex-1", children: [sidebar, _jsx(SidebarInset, { className: "min-h-0 flex-row overflow-hidden", children: framed ? (
32
129
  // FRAMED workspace chrome: the workspace floats as a rounded
33
130
  // container, a sibling card beside the assistant panel; the gap
34
131
  // animates alongside the panel so the reflow reads as one motion.
35
- _jsxs("div", { className: cn("flex min-h-0 min-w-0 flex-1 p-4 lg:p-6", reflowGap), style: REFLOW_TRANSITION, children: [_jsx("div", { className: "min-w-0 flex-1 overflow-y-auto rounded-xl bg-muted/50 shadow-panel p-4 lg:p-6", children: children }), assistant] })) : (
132
+ _jsxs("div", { "data-slot": "shell-reflow", className: cn("flex min-h-0 min-w-0 flex-1", narrow ? "p-2" : "p-4 lg:p-6", reflowGap), style: reflowTransition, children: [withInspector(_jsx("div", { id: WORKSPACE_ID, tabIndex: 0, className: cn("min-w-0 flex-1 overflow-x-auto overflow-y-auto rounded-xl bg-muted/50 shadow-panel outline-none focus-visible:ring-2 focus-visible:ring-ring/50", narrow ? "p-3" : "p-4 lg:p-6"), children: children })), assistant] })) : (
36
133
  // EDGE-TO-EDGE workspace chrome: the flat layout (no reflow gap).
37
- _jsxs(_Fragment, { children: [_jsx("div", { className: "min-w-0 flex-1 overflow-y-auto p-4 lg:p-6", children: children }), assistant] })) })] })] }));
134
+ _jsxs(_Fragment, { children: [_jsx("div", { id: WORKSPACE_ID, tabIndex: 0, className: "min-w-0 flex-1 overflow-y-auto p-4 outline-none focus-visible:ring-2 focus-visible:ring-ring/50 lg:p-6", children: children }), inspector, assistant] })) })] })] }));
38
135
  }
39
136
  //# sourceMappingURL=ShellFrame.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ShellFrame.js","sourceRoot":"","sources":["../../src/frame/ShellFrame.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAyCb,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAqDxE;;;;;GAKG;AACH,MAAM,iBAAiB,GAAwB;IAC7C,kBAAkB,EAAE,KAAK;IACzB,kBAAkB,EAAE,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,GAAG;IACpD,wBAAwB,EAAE,gBAAgB,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;CACrF,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,EACzB,MAAM,EACN,OAAO,EACP,QAAQ,EACR,SAAS,EACT,iBAAiB,GAAG,MAAM,EAC1B,cAAc,GAAG,GAAG,EACpB,aAAa,GAAG,KAAK,EACrB,eAAe,GAAG,QAAQ,EAC1B,QAAQ,GACQ;IAChB,MAAM,MAAM,GAAG,eAAe,KAAK,QAAQ,CAAC;IAC5C,MAAM,YAAY,GAAG,SAAS,IAAI,IAAI,CAAC;IAEvC,yEAAyE;IACzE,8EAA8E;IAC9E,MAAM,SAAS,GAAG,CAAC,YAAY;QAC7B,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,iBAAiB,KAAK,MAAM;YAC5B,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,iBAAiB,KAAK,MAAM,IAAI,aAAa;gBAC7C,CAAC,CAAC,gBAAgB;gBAClB,CAAC,CAAC,OAAO,CAAC;IAEhB,OAAO,CACL,MAAC,eAAe,IACd,SAAS,EAAC,gCAAgC,EAC1C,KAAK,EACH;YACE,iBAAiB,EAAE,QAAQ;YAC3B,mBAAmB,EAAE,GAAG,cAAc,IAAI;SACpB,aAGzB,MAAM,EACN,QAAQ,EACT,eAAK,SAAS,EAAC,qBAAqB,aACjC,OAAO,EACR,KAAC,YAAY,IAAC,SAAS,EAAC,kCAAkC,YACvD,MAAM,CAAC,CAAC,CAAC;wBACR,6DAA6D;wBAC7D,gEAAgE;wBAChE,kEAAkE;wBAClE,eACE,SAAS,EAAE,EAAE,CAAC,wCAAwC,EAAE,SAAS,CAAC,EAClE,KAAK,EAAE,iBAAiB,aAMxB,cAAK,SAAS,EAAC,+EAA+E,YAC3F,QAAQ,GACL,EAGL,SAAS,IACN,CACP,CAAC,CAAC,CAAC;wBACF,kEAAkE;wBAClE,8BACE,cAAK,SAAS,EAAC,2CAA2C,YAAE,QAAQ,GAAO,EAC1E,SAAS,IACT,CACJ,GACY,IACX,IACU,CACnB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"ShellFrame.js","sourceRoot":"","sources":["../../src/frame/ShellFrame.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ export interface ShellViewport {
3
+ /** Undefined during SSR; the initial markup stays hydration-compatible. */
4
+ width: number | undefined;
5
+ height: number | undefined;
6
+ element: HTMLDivElement | null;
7
+ }
8
+ /** Actual available layout space, not the browser's width. No routes or product state. */
9
+ export declare function useShellViewport(): ShellViewport | null;
10
+ /** Composite shells can share the frame's size and portal boundary with their slots. */
11
+ export declare function ShellViewportProvider({ children, style, className }: {
12
+ children: React.ReactNode;
13
+ style?: React.CSSProperties;
14
+ className?: string;
15
+ }): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=viewport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../../src/frame/viewport.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;CAChC;AAGD,0FAA0F;AAC1F,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CAEvD;AAED,wFAAwF;AACxF,wBAAgB,qBAAqB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;IACpE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAyBA"}
@@ -0,0 +1,35 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ const ViewportContext = React.createContext(null);
5
+ /** Actual available layout space, not the browser's width. No routes or product state. */
6
+ export function useShellViewport() {
7
+ return React.useContext(ViewportContext);
8
+ }
9
+ /** Composite shells can share the frame's size and portal boundary with their slots. */
10
+ export function ShellViewportProvider({ children, style, className }) {
11
+ const [element, setElement] = React.useState(null);
12
+ const [size, setSize] = React.useState({});
13
+ React.useEffect(() => {
14
+ if (!element)
15
+ return;
16
+ const measure = () => {
17
+ // CSS layout pixels preserve breakpoints under zoom or host transforms.
18
+ const box = { width: element.clientWidth, height: element.clientHeight };
19
+ // Hidden/unmeasured hosts retain SSR fallback until there is real geometry.
20
+ if (box.width <= 0)
21
+ return;
22
+ const width = box.width;
23
+ const height = box.height;
24
+ setSize(old => old.width === width && old.height === height ? old : { width, height });
25
+ };
26
+ measure();
27
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
28
+ observer?.observe(element);
29
+ window.addEventListener("resize", measure);
30
+ return () => { observer?.disconnect(); window.removeEventListener("resize", measure); };
31
+ }, [element]);
32
+ const value = React.useMemo(() => ({ width: size.width, height: size.height, element }), [size, element]);
33
+ return _jsx(ViewportContext.Provider, { value: value, children: _jsx("div", { ref: setElement, "data-slot": "shell-viewport", className: className, style: { position: "relative", width: "100%", height: "100dvh", minWidth: 0, contain: "layout", ...style }, children: children }) });
34
+ }
35
+ //# sourceMappingURL=viewport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewport.js","sourceRoot":"","sources":["../../src/frame/viewport.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,eAAe,GAAG,KAAK,CAAC,aAAa,CAAuB,IAAI,CAAC,CAAC;AAExE,0FAA0F;AAC1F,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AAC3C,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,qBAAqB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAIjE;IACC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAwB,IAAI,CAAC,CAAC;IAC1E,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAoC,EAAE,CAAC,CAAC;IAC9E,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,wEAAwE;YACxE,MAAM,GAAG,GAAG,EAAC,KAAK,EAAC,OAAO,CAAC,WAAW,EAAC,MAAM,EAAC,OAAO,CAAC,YAAY,EAAC,CAAC;YACpE,4EAA4E;YAC5E,IAAI,GAAG,CAAC,KAAK,IAAI,CAAC;gBAAE,OAAO;YAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YACxB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAC,KAAK,EAAE,MAAM,EAAC,CAAC,CAAC;QACvF,CAAC,CAAC;QACF,OAAO,EAAE,CAAC;QACV,MAAM,QAAQ,GAAG,OAAO,cAAc,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;QAC5F,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3B,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAO,GAAG,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1F,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACd,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAC,KAAK,EAAC,IAAI,CAAC,KAAK,EAAC,MAAM,EAAC,IAAI,CAAC,MAAM,EAAC,OAAO,EAAC,CAAC,EAAE,CAAC,IAAI,EAAC,OAAO,CAAC,CAAC,CAAC;IACnG,OAAO,KAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAE,cAAK,GAAG,EAAE,UAAU,eAAY,gBAAgB,EAC7F,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAC,QAAQ,EAAC,UAAU,EAAC,KAAK,EAAC,MAAM,EAAC,MAAM,EAAC,QAAQ,EAAC,QAAQ,EAAC,CAAC,EAAC,OAAO,EAAC,QAAQ,EAAC,GAAG,KAAK,EAAC,YACnH,QAAQ,GACL,GAA2B,CAAC;AACpC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -17,4 +17,6 @@
17
17
  */
18
18
  export { ShellFrame } from "./frame/ShellFrame.js";
19
19
  export type { AssistantBehavior, ShellFrameProps, ShellWorkspaceChrome, } from "./frame/ShellFrame.js";
20
+ export { ShellViewportProvider, useShellViewport } from "./frame/viewport.js";
21
+ export type { ShellViewport } from "./frame/viewport.js";
20
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -16,4 +16,5 @@
16
16
  * docs/design/frontend-platform-doctrine.md.
17
17
  */
18
18
  export { ShellFrame } from "./frame/ShellFrame.js";
19
+ export { ShellViewportProvider, useShellViewport } from "./frame/viewport.js";
19
20
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAOnD,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@consciousclouds/shell-primitive",
3
- "version": "0.1.0",
4
- "description": "ConsciousClouds Shell Primitive — the neutral shell FRAME (mechanism, not meaning): the header + sidebar + main-region layout skeleton over @consciousclouds/ui, the responsive assistant-panel placement mechanics (push | overlay | rail reflow), and workspace chrome (framed | edge-to-edge). No product, no Chief, no nav, no permission guard. The shared primitive the Operator / Business / Consumer shells frame around. Layer 3·5 of the Frontend Platform.",
3
+ "version": "0.1.3",
4
+ "description": "ConsciousClouds Shell Primitive \u2014 the neutral shell FRAME (mechanism, not meaning): the header + sidebar + main-region layout skeleton over @consciousclouds/ui, the responsive assistant-panel placement mechanics (push | overlay | rail reflow), and workspace chrome (framed | edge-to-edge). No product, no Chief, no nav, no permission guard. The shared primitive the Operator / Business / Consumer shells frame around. Layer 3\u00b75 of the Frontend Platform.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -25,17 +25,19 @@
25
25
  "clean": "rm -rf dist",
26
26
  "test": "bun test",
27
27
  "type-check": "tsc --noEmit",
28
- "prepublishOnly": "bun run clean && bun run build && bun run type-check"
28
+ "prepublishOnly": "bun run clean && bun run build && bun run type-check",
29
+ "prepack": "bun run clean && bun run build && bun run type-check"
29
30
  },
30
31
  "dependencies": {
31
- "@consciousclouds/ui": "0.1.0"
32
+ "@consciousclouds/ui": "^0.1.3"
32
33
  },
33
34
  "peerDependencies": {
34
- "@consciousclouds/tokens": "0.1.0",
35
- "react": ">=18.0.0"
35
+ "@consciousclouds/tokens": "^0.1.1",
36
+ "react": ">=18.0.0",
37
+ "react-dom": ">=18.0.0"
36
38
  },
37
39
  "devDependencies": {
38
- "@consciousclouds/tokens": "0.1.0",
40
+ "@consciousclouds/tokens": "^0.1.1",
39
41
  "@happy-dom/global-registrator": "^20.10.3",
40
42
  "@types/react": "^19.2.7",
41
43
  "@types/react-dom": "^19.2.1",