@gravitee/graphene-core 2.51.0 → 2.52.0-feat-layout-content-width-tiers.35c2ff9
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/USAGE_GUIDE.md +145 -11
- package/dist/composed/AppLayout/AppLayout.d.ts +17 -4
- package/dist/composed/AppLayout/AppLayout.d.ts.map +1 -1
- package/dist/composed/LayoutSlots/LayoutSlotsContext.d.ts +11 -1
- package/dist/composed/LayoutSlots/LayoutSlotsContext.d.ts.map +1 -1
- package/dist/composed/LayoutSlots/use-layout-config.d.ts +3 -0
- package/dist/composed/LayoutSlots/use-layout-config.d.ts.map +1 -1
- package/dist/composed/PageContent/PageContent.d.ts +60 -0
- package/dist/composed/PageContent/PageContent.d.ts.map +1 -0
- package/dist/composed/PageContent/index.d.ts +3 -0
- package/dist/composed/PageContent/index.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7250 -7216
- package/dist/lib/view-transitions.d.ts +14 -0
- package/dist/lib/view-transitions.d.ts.map +1 -0
- package/dist/styles/globals.css +1 -1
- package/dist/styles/tailwind-theme.css +3 -0
- package/dist/tokens/component.css +3 -1
- package/package.json +2 -1
- package/snippets/context-sidebar-detail-page.tsx +10 -1
- package/snippets/creation-wizard-page.tsx +121 -0
- package/snippets/data-table-list-page.tsx +5 -0
- package/snippets/form-settings-page.tsx +112 -0
package/USAGE_GUIDE.md
CHANGED
|
@@ -141,9 +141,62 @@ Scale: `0`, `0.5`, `1`, `1.5`, `2`, `2.5`, `3`, `3.5`, `4`, `5`, `6`, `7`, `8`,
|
|
|
141
141
|
|
|
142
142
|
`rounded-sm`, `rounded-md`, `rounded-lg`, `rounded-xl` (mapped to semantic `--radius`).
|
|
143
143
|
|
|
144
|
-
### Layout
|
|
144
|
+
### Layout — content width system
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
The layout uses a single default container (100rem / 1600px, left-aligned) with two content wrappers for narrower pages:
|
|
147
|
+
|
|
148
|
+
| Layer | Token | Rem | Tailwind class | When to use |
|
|
149
|
+
|-------|-------|-----|----------------|-------------|
|
|
150
|
+
| Container (default) | `--content-max-width` | `100rem` | `max-w-content` | The shell container. Applied automatically by `AppLayout`. |
|
|
151
|
+
| Full-bleed | N/A | none | N/A | Tool layouts (Policy Studio), observability pages. Set via `useLayoutConfig({ contentVariant: 'full-bleed' })`. |
|
|
152
|
+
| `<PageSection>` | `--content-form-width` | `80rem` | `max-w-form` | Form pages, settings, config views. Wrap page content in this component. |
|
|
153
|
+
| `<PageFocused>` | `--content-focused-width` | `56rem` | `max-w-focused` | Creation wizards, steppers, onboarding flows. Wrap page content in this component. |
|
|
154
|
+
|
|
155
|
+
**Decision flowchart:**
|
|
156
|
+
|
|
157
|
+
1. Is this a tool/workspace layout (Policy Studio, LLM Studio, observability)? → `useLayoutConfig({ contentVariant: 'full-bleed' })`
|
|
158
|
+
2. Is this a creation wizard or stepper? → Wrap content in `<PageFocused>`
|
|
159
|
+
3. Is the page primarily forms, settings, or card-based config? → Wrap content in `<PageSection>`
|
|
160
|
+
4. Is the page primarily a DataTable, entity list, or dashboard? → No wrapper needed (fills the 100rem container)
|
|
161
|
+
5. Not sure? → No wrapper. The default container handles most content well.
|
|
162
|
+
|
|
163
|
+
Content is **left-aligned** (not centered). Width changes between pages only affect the right edge, keeping the left anchor stable during navigation.
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
import { PageSection, PageFocused } from '@gravitee/graphene-core';
|
|
167
|
+
|
|
168
|
+
// Form/settings page
|
|
169
|
+
function GeneralSettingsPage() {
|
|
170
|
+
return (
|
|
171
|
+
<PageSection>
|
|
172
|
+
<h2>General</h2>
|
|
173
|
+
<form>...</form>
|
|
174
|
+
</PageSection>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Wizard/creation page
|
|
179
|
+
function CreateApiPage() {
|
|
180
|
+
return (
|
|
181
|
+
<PageFocused>
|
|
182
|
+
<StepProgress steps={steps} activeStep={step} />
|
|
183
|
+
<StepContent />
|
|
184
|
+
</PageFocused>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Table page — no wrapper needed
|
|
189
|
+
function ApisPage() {
|
|
190
|
+
return (
|
|
191
|
+
<div className="space-y-4">
|
|
192
|
+
<h2>APIs</h2>
|
|
193
|
+
<DataTable ... />
|
|
194
|
+
</div>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
All width values are defined in `rem` so they scale with user font-size preferences and browser zoom. Consumers do not set `max-w-*` classes directly on page wrappers — use the provided components instead.
|
|
147
200
|
|
|
148
201
|
## Styling
|
|
149
202
|
|
|
@@ -293,27 +346,108 @@ If you have not migrated to `AppContextBar` yet, keeping the app name as the fir
|
|
|
293
346
|
|
|
294
347
|
**Linear breadcrumbs:** When each step maps to a **path string** and React Router’s `navigate`, use **`buildLinearBreadcrumbs(navigate, segments)`** so `ContentHeader` / `useLayoutConfig` get consistent `BreadcrumbEntry[]` without copying the same `onClick` wiring. If the first crumb is a **custom action** (e.g. “back” that is not `navigate('/path')`), build that entry by hand or mix with `buildLinearBreadcrumbs`—see Storybook **Composed/ContentHeader → Linear breadcrumbs from builder** for the canonical route-based pattern. API edge cases are covered in `packages/core/src/lib/breadcrumbs/buildLinearBreadcrumbs.test.ts`.
|
|
295
348
|
|
|
296
|
-
### `contentVariant` —
|
|
349
|
+
### `contentVariant` — content width tiers
|
|
350
|
+
|
|
351
|
+
`AppLayout` accepts `contentVariant` to control content area width and padding:
|
|
352
|
+
|
|
353
|
+
- `"default"` (default) — `max-w-content` (80rem) with standard padding. Most pages.
|
|
354
|
+
- `"wide"` — `max-w-wide` (100rem) with standard padding. DataTable list pages.
|
|
355
|
+
- `"full-bleed"` — no max-width, no padding; content spans edge-to-edge. Tool layouts and observability pages.
|
|
356
|
+
|
|
357
|
+
```tsx
|
|
358
|
+
// Default (80rem) — no change needed, AppLayout applies it automatically
|
|
359
|
+
<AppLayout>
|
|
360
|
+
<DetailPage />
|
|
361
|
+
</AppLayout>
|
|
362
|
+
|
|
363
|
+
// Wide (100rem) — for DataTable list pages, add one line
|
|
364
|
+
useLayoutConfig({ contentVariant: 'wide' }, []);
|
|
365
|
+
|
|
366
|
+
// Full-bleed — for tool layouts and observability pages
|
|
367
|
+
useLayoutConfig({ contentVariant: 'full-bleed' }, []);
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
With `useLayoutConfig` (module federation), a nested page can set `contentVariant` without affecting other layout slots owned by parent components. Each hook only resets the keys it owns on unmount.
|
|
371
|
+
|
|
372
|
+
#### Artifact-free page transitions
|
|
373
|
+
|
|
374
|
+
When navigating between pages with different `contentVariant` values, wrap the navigation action in `startLayoutTransition` to eliminate visual overlap artifacts during DOM reconciliation:
|
|
375
|
+
|
|
376
|
+
```tsx
|
|
377
|
+
import { startLayoutTransition } from '@gravitee/graphene-core';
|
|
378
|
+
|
|
379
|
+
// In your router or navigation handler (called once, not per-page):
|
|
380
|
+
function useAppNavigate() {
|
|
381
|
+
const navigate = useNavigate();
|
|
382
|
+
return useCallback((to: string) => {
|
|
383
|
+
startLayoutTransition(() => navigate(to));
|
|
384
|
+
}, [navigate]);
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
This uses the View Transitions API to capture the old visual state before applying DOM changes, preventing any intermediate "two pages visible" flash. No visible animation is produced; the swap is perceptually instant. Falls back to direct execution in browsers without View Transitions API support.
|
|
297
389
|
|
|
298
|
-
`
|
|
390
|
+
When the user has **Reduce motion** enabled at the OS level (`prefers-reduced-motion: reduce`), view-transition animation duration is `0ms` and navigation is fully instant.
|
|
299
391
|
|
|
300
|
-
|
|
301
|
-
- `"full-bleed"` — no padding; content spans edge-to-edge.
|
|
392
|
+
### `banner` — full-width status slot
|
|
302
393
|
|
|
303
|
-
|
|
394
|
+
`AppLayout` accepts a `banner` prop that renders a full-width region above the padded content wrapper but inside the scroll container. Use it for persistent status indicators with an action (deploy status, environment warnings).
|
|
304
395
|
|
|
305
396
|
```tsx
|
|
306
|
-
|
|
307
|
-
|
|
397
|
+
// Direct prop usage
|
|
398
|
+
<AppLayout banner={<DeployStrip />} bannerSticky>
|
|
399
|
+
<PageContent />
|
|
308
400
|
</AppLayout>
|
|
401
|
+
|
|
402
|
+
// Module federation via useLayoutConfig
|
|
403
|
+
useLayoutConfig({
|
|
404
|
+
banner: deployState === 'NEED_REDEPLOY' ? (
|
|
405
|
+
<DeployStrip onDeploy={handleDeploy} isPending={isPending} />
|
|
406
|
+
) : null,
|
|
407
|
+
bannerSticky: true,
|
|
408
|
+
}, [deployState, handleDeploy, isPending]);
|
|
309
409
|
```
|
|
310
410
|
|
|
311
|
-
|
|
411
|
+
The banner spans full width regardless of `contentVariant`. When `bannerSticky` is true, it sticks to the top of the scroll area so the action remains reachable while scrolling.
|
|
412
|
+
|
|
413
|
+
**Button hierarchy:** When a banner contains an action button alongside page content that has its own primary buttons, use an outline treatment on the banner button to avoid competing with the page's primary CTA:
|
|
312
414
|
|
|
313
415
|
```tsx
|
|
314
|
-
|
|
416
|
+
function DeployStrip({ onDeploy, isPending }) {
|
|
417
|
+
return (
|
|
418
|
+
<div className="flex items-center gap-2 border-b border-border px-5 py-1.5">
|
|
419
|
+
<span className="size-1.5 shrink-0 rounded-full bg-warning" />
|
|
420
|
+
<span className="text-sm text-muted-foreground">Undeployed changes</span>
|
|
421
|
+
<div className="flex-1" />
|
|
422
|
+
<button
|
|
423
|
+
type="button"
|
|
424
|
+
className="rounded-md border border-warning/25 bg-warning/5 px-2.5 py-0.5 text-sm font-semibold text-warning-foreground transition-colors hover:bg-warning/10 disabled:opacity-50"
|
|
425
|
+
onClick={onDeploy}
|
|
426
|
+
disabled={isPending}
|
|
427
|
+
>
|
|
428
|
+
{isPending ? 'Deploying…' : 'Deploy API'}
|
|
429
|
+
</button>
|
|
430
|
+
</div>
|
|
431
|
+
);
|
|
432
|
+
}
|
|
315
433
|
```
|
|
316
434
|
|
|
435
|
+
See Storybook **Composed/AppLayout → BannerSlot** for the full interactive example.
|
|
436
|
+
|
|
437
|
+
### Adopting content width tiers in consumer modules
|
|
438
|
+
|
|
439
|
+
Follow these steps to apply the layout tier system to an existing consumer module:
|
|
440
|
+
|
|
441
|
+
1. **Identify all pages** in your module that render inside `AppLayout`.
|
|
442
|
+
2. **Categorize each page:**
|
|
443
|
+
- **Default** — detail views, edit forms, overviews, settings, creation wizards. No change needed; `AppLayout` applies `max-w-content` (80rem) automatically.
|
|
444
|
+
- **Wide** — any page whose primary content is a `DataTable`. Add `useLayoutConfig({ contentVariant: 'wide' }, [])` at the top of the component.
|
|
445
|
+
- **Full-bleed** — tool layouts (Policy Studio) or observability pages (dashboards, explorers). Add `useLayoutConfig({ contentVariant: 'full-bleed' }, [])` if not already set.
|
|
446
|
+
3. **Remove ad-hoc width constraints** — delete any `max-w-*` classes on page-level wrapper divs. The design system owns content width.
|
|
447
|
+
4. **Verify** — resize the browser to confirm content centers correctly on wide viewports and doesn't clip on narrow ones.
|
|
448
|
+
|
|
449
|
+
See `packages/core/snippets/data-table-list-page.tsx` for a complete list-page example with `useLayoutConfig`.
|
|
450
|
+
|
|
317
451
|
### Data table (entity list pages)
|
|
318
452
|
|
|
319
453
|
Use `DataTable` for any entity list — whether the data is fetched page-by-page from an API or loaded in full on the client. The component provides sorting, filtering, pagination, column visibility, row selection, and bulk actions through a composable slot API.
|
|
@@ -18,11 +18,24 @@ interface AppLayoutProps {
|
|
|
18
18
|
/** Optional callback when context expansion state changes. */
|
|
19
19
|
readonly onContextExpandedChange?: (expanded: boolean) => void;
|
|
20
20
|
/**
|
|
21
|
-
* Controls content area padding.
|
|
22
|
-
* - `"default"` —
|
|
23
|
-
* - `"full-bleed"` — no padding; content spans edge-to-edge.
|
|
21
|
+
* Controls content area width and padding.
|
|
22
|
+
* - `"default"` — `max-w-content` (100rem) left-aligned with standard padding.
|
|
23
|
+
* - `"full-bleed"` — no max-width, no padding; content spans edge-to-edge.
|
|
24
|
+
*
|
|
25
|
+
* Pages that need narrower content (forms, wizards) use `<PageSection>` or
|
|
26
|
+
* `<PageFocused>` wrappers inside the default container.
|
|
27
|
+
*
|
|
28
|
+
* @deprecated `"wide"` is accepted for backward compatibility but is equivalent to `"default"`.
|
|
24
29
|
*/
|
|
25
|
-
readonly contentVariant?: 'default' | 'full-bleed';
|
|
30
|
+
readonly contentVariant?: 'default' | 'wide' | 'full-bleed';
|
|
31
|
+
/**
|
|
32
|
+
* Full-width banner rendered above the padded content area.
|
|
33
|
+
* Sits inside the scroll container but outside the content padding wrapper,
|
|
34
|
+
* so it spans edge-to-edge regardless of `contentVariant`.
|
|
35
|
+
*/
|
|
36
|
+
readonly banner?: ReactNode;
|
|
37
|
+
/** When true the banner sticks to the top of the scroll container. Defaults to `false`. */
|
|
38
|
+
readonly bannerSticky?: boolean;
|
|
26
39
|
/**
|
|
27
40
|
* When true the layout spans the full viewport height.
|
|
28
41
|
* Defaults to `true` (sidebar-dominant shell).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppLayout.d.ts","sourceRoot":"","sources":["../../../src/composed/AppLayout/AppLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,SAAS,EAA6B,MAAM,OAAO,CAAC;AAGtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8CAA8C,CAAC;AAEhF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gDAAgD,CAAC;AAGhF,UAAU,cAAc;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IACpC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,yBAAyB;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACzC,iEAAiE;IACjE,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,8DAA8D;IAC9D,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/D
|
|
1
|
+
{"version":3,"file":"AppLayout.d.ts","sourceRoot":"","sources":["../../../src/composed/AppLayout/AppLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,SAAS,EAA6B,MAAM,OAAO,CAAC;AAGtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8CAA8C,CAAC;AAEhF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gDAAgD,CAAC;AAGhF,UAAU,cAAc;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IACpC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,yBAAyB;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACzC,iEAAiE;IACjE,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,8DAA8D;IAC9D,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/D;;;;;;;;;OASG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,YAAY,CAAC;IAC5D;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;IAC5B,2FAA2F;IAC3F,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,WAAW,CAAC;IAC1C,kDAAkD;IAClD,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;CACnC;AAmGD,iBAAS,SAAS,CAAC,EAAE,kBAAmC,EAAE,YAAuB,EAAE,GAAG,IAAI,EAAE,EAAE,cAAc,+BAQ3G;kBARQ,SAAS;;;AAYlB,OAAO,EAAE,SAAS,EAAE,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -8,7 +8,17 @@ interface LayoutSlots {
|
|
|
8
8
|
readonly leading: ReactNode;
|
|
9
9
|
readonly viewMode: 'global' | 'context';
|
|
10
10
|
readonly contextExpanded: boolean;
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* `"default"` — 100rem left-aligned with padding (use for all standard pages).
|
|
13
|
+
* `"full-bleed"` — no max-width, no padding (tool layouts like Policy Studio).
|
|
14
|
+
*
|
|
15
|
+
* @deprecated `"wide"` is accepted for backward compatibility but equivalent to `"default"`.
|
|
16
|
+
*/
|
|
17
|
+
readonly contentVariant: 'default' | 'wide' | 'full-bleed';
|
|
18
|
+
/** Full-width banner rendered above the padded content area (e.g. deploy status, environment warnings). */
|
|
19
|
+
readonly banner: ReactNode;
|
|
20
|
+
/** When true the banner sticks to the top of the scroll container. */
|
|
21
|
+
readonly bannerSticky: boolean;
|
|
12
22
|
}
|
|
13
23
|
interface LayoutSlotsContextValue {
|
|
14
24
|
readonly slots: LayoutSlots;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayoutSlotsContext.d.ts","sourceRoot":"","sources":["../../../src/composed/LayoutSlots/LayoutSlotsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAA8C,MAAM,OAAO,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAEtF,UAAU,WAAW;IACnB,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,eAAe,EAAE,CAAC;IACxC,sFAAsF;IACtF,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,SAAS,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"LayoutSlotsContext.d.ts","sourceRoot":"","sources":["../../../src/composed/LayoutSlots/LayoutSlotsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAA8C,MAAM,OAAO,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAEtF,UAAU,WAAW;IACnB,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,eAAe,EAAE,CAAC;IACxC,sFAAsF;IACtF,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,GAAG,MAAM,GAAG,YAAY,CAAC;IAC3D,2GAA2G;IAC3G,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC;AAED,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,MAAM,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACvF,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAC3D,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,WAAW,CAAC,KAAK,IAAI,CAAC;CACvE;AAED,QAAA,MAAM,aAAa,EAAE,WAUpB,CAAC;AAIF,iBAAS,mBAAmB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAwB1E;AAED,iBAAS,cAAc,IAAI,uBAAuB,CAMjD;AAED,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,cAAc,EAAE,CAAC;AAC9D,YAAY,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC"}
|
|
@@ -7,6 +7,9 @@ import { LayoutSlots } from './LayoutSlotsContext';
|
|
|
7
7
|
* **Resets all slots to defaults on unmount** so stale module content
|
|
8
8
|
* never lingers after navigation.
|
|
9
9
|
*
|
|
10
|
+
* Uses `useLayoutEffect` to apply config synchronously before paint,
|
|
11
|
+
* preventing visible layout shifts during navigation.
|
|
12
|
+
*
|
|
10
13
|
* @param config - Slot values the module wants to own.
|
|
11
14
|
* @param deps - Dependency array that triggers a config re-push
|
|
12
15
|
* (same semantics as `useEffect` deps).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-layout-config.d.ts","sourceRoot":"","sources":["../../../src/composed/LayoutSlots/use-layout-config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AAExE
|
|
1
|
+
{"version":3,"file":"use-layout-config.d.ts","sourceRoot":"","sources":["../../../src/composed/LayoutSlots/use-layout-config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,iBAAS,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,GAAE,KAAK,CAAC,cAAmB,QAYrF;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface PageSectionProps {
|
|
3
|
+
/** Page content (forms, settings panels, card layouts). */
|
|
4
|
+
readonly children: ReactNode;
|
|
5
|
+
readonly className?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Constrains page content to a comfortable form width (80rem / 1280px),
|
|
9
|
+
* left-aligned within the default 100rem container.
|
|
10
|
+
*
|
|
11
|
+
* Use for settings pages, configuration forms, detail overviews, and
|
|
12
|
+
* any page where the primary content is NOT a full-width DataTable.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* export function GeneralSettingsPage() {
|
|
17
|
+
* return (
|
|
18
|
+
* <PageSection>
|
|
19
|
+
* <h2>General</h2>
|
|
20
|
+
* <form>...</form>
|
|
21
|
+
* </PageSection>
|
|
22
|
+
* );
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare function PageSection({ children, className }: PageSectionProps): import("react").JSX.Element;
|
|
27
|
+
declare namespace PageSection {
|
|
28
|
+
var displayName: string;
|
|
29
|
+
}
|
|
30
|
+
interface PageFocusedProps {
|
|
31
|
+
/** Focused content (stepper, creation wizard, onboarding flow). */
|
|
32
|
+
readonly children: ReactNode;
|
|
33
|
+
readonly className?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Constrains and centers page content for focused flows (56rem / 896px).
|
|
37
|
+
*
|
|
38
|
+
* Use for creation wizards, multi-step forms, onboarding sequences, and
|
|
39
|
+
* any task where the user is working through a focused linear flow.
|
|
40
|
+
* The centering signals "you are in a sub-task" and draws the eye inward.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* export function CreateApiWizardPage() {
|
|
45
|
+
* return (
|
|
46
|
+
* <PageFocused>
|
|
47
|
+
* <StepProgress steps={steps} activeStep={step} />
|
|
48
|
+
* <StepContent />
|
|
49
|
+
* </PageFocused>
|
|
50
|
+
* );
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare function PageFocused({ children, className }: PageFocusedProps): import("react").JSX.Element;
|
|
55
|
+
declare namespace PageFocused {
|
|
56
|
+
var displayName: string;
|
|
57
|
+
}
|
|
58
|
+
export { PageFocused, PageSection };
|
|
59
|
+
export type { PageFocusedProps, PageSectionProps };
|
|
60
|
+
//# sourceMappingURL=PageContent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageContent.d.ts","sourceRoot":"","sources":["../../../src/composed/PageContent/PageContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,UAAU,gBAAgB;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,+BAE7D;kBAFQ,WAAW;;;AAMpB,UAAU,gBAAgB;IACxB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,+BAE7D;kBAFQ,WAAW;;;AAMpB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AACpC,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/composed/PageContent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACzD,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { cn } from './lib/utils';
|
|
2
2
|
export { PortalContainerProvider, usePortalContainer } from './lib/PortalContainerContext';
|
|
3
|
+
export { startLayoutTransition } from './lib/view-transitions';
|
|
3
4
|
export * from './base/Accordion';
|
|
4
5
|
export * from './base/Alert';
|
|
5
6
|
export * from './base/Avatar';
|
|
@@ -62,6 +63,7 @@ export * from './composed/FacetedFilter';
|
|
|
62
63
|
export * from './composed/FileUpload';
|
|
63
64
|
export * from './composed/JsonSchemaForm';
|
|
64
65
|
export * from './composed/LayoutSlots';
|
|
66
|
+
export * from './composed/PageContent';
|
|
65
67
|
export * from './composed/PasswordInput';
|
|
66
68
|
export * from './composed/SelectorDropdown';
|
|
67
69
|
export * from './composed/SidebarMode';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAC3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AAMvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EACL,sBAAsB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,0CAA0C,CAAC;AAClD,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
|