@flipdish/ui-library 0.28.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/templates/AppShell/index.cjs +28 -0
- package/dist/components/templates/AppShell/index.cjs.map +1 -0
- package/dist/components/templates/AppShell/index.d.ts +40 -0
- package/dist/components/templates/AppShell/index.d.ts.map +1 -0
- package/dist/components/templates/AppShell/index.js +26 -0
- package/dist/components/templates/AppShell/index.js.map +1 -0
- package/dist/native/components/templates/AppShell/index.d.ts +12 -0
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var cx = require('@flipdish/ui-library/utilities/cx');
|
|
5
|
+
var testIdUtils = require('@flipdish/ui-library/utilities/testIdUtils');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Layout-only template for an app shell: navigation beside a content column that stacks the
|
|
9
|
+
* header above the page, with an optional side panel that pushes the page instead of covering it.
|
|
10
|
+
* The shell is exactly the height of the window and the document never scrolls: the page content
|
|
11
|
+
* scrolls in its own area under the header, so the header, navigation and side panel stay in place
|
|
12
|
+
* with no sticky positioning. It holds no state and renders whatever is passed to its slots, so the
|
|
13
|
+
* app keeps ownership of navigation, search and panel state.
|
|
14
|
+
*
|
|
15
|
+
* @summary window-height layout template placing navigation, header, a scrolling page area and a side panel
|
|
16
|
+
*/
|
|
17
|
+
const AppShell = ({ sidebar, header, panel, children, scrollAreaProps, className, 'data-testid': dataTestId }) => {
|
|
18
|
+
const appShellTestId = testIdUtils.useResolvedTestId({ testId: dataTestId, segment: 'app-shell', rootName: 'app-shell' });
|
|
19
|
+
return (
|
|
20
|
+
// A column below `lg`, so a navigation that renders its own mobile top bar stacks above the content.
|
|
21
|
+
jsxRuntime.jsxs("div", { "data-testid": appShellTestId, className: cx.cx('flex h-dvh w-full flex-col overflow-hidden bg-primary lg:flex-row', className), children: [sidebar, jsxRuntime.jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [header, jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1", children: [jsxRuntime.jsx("div", { id: scrollAreaProps?.id, ref: scrollAreaProps?.ref, "data-testid": scrollAreaProps?.['data-testid'] ?? testIdUtils.joinTestId(appShellTestId, 'scroll-area'),
|
|
22
|
+
// Focusable so keyboard users can scroll a page that has no focusable content of its own (axe: scrollable-region-focusable).
|
|
23
|
+
// biome-ignore lint/a11y/noNoninteractiveTabindex: a scrollable region must be reachable by keyboard
|
|
24
|
+
tabIndex: 0, className: "flex min-w-0 flex-1 flex-col overflow-y-auto outline-focus-ring focus-visible:outline-2 focus-visible:-outline-offset-2", children: children }), panel] })] })] }));
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
exports.AppShell = AppShell;
|
|
28
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/templates/AppShell/index.tsx"],"sourcesContent":[null],"names":["useResolvedTestId","_jsxs","cx","_jsx","joinTestId"],"mappings":";;;;;;AAmCA;;;;;;;;;AASG;MACU,QAAQ,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAiB,KAAe;AAChJ,IAAA,MAAM,cAAc,GAAGA,6BAAiB,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAE7G;;IAEEC,eAAA,CAAA,KAAA,EAAA,EAAA,aAAA,EAAkB,cAAc,EAAE,SAAS,EAAEC,KAAE,CAAC,mEAAmE,EAAE,SAAS,CAAC,EAAA,QAAA,EAAA,CAC5H,OAAO,EAGRD,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,sCAAsC,aAClD,MAAM,EAEPA,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,qBAAqB,aAClCE,cAAA,CAAA,KAAA,EAAA,EACE,EAAE,EAAE,eAAe,EAAE,EAAE,EACvB,GAAG,EAAE,eAAe,EAAE,GAAG,iBACZ,eAAe,GAAG,aAAa,CAAC,IAAIC,sBAAU,CAAC,cAAc,EAAE,aAAa,CAAC;;;AAG1F,gCAAA,QAAQ,EAAE,CAAC,EACX,SAAS,EAAC,yHAAyH,EAAA,QAAA,EAElI,QAAQ,EAAA,CACL,EAEL,KAAK,CAAA,EAAA,CACF,CAAA,EAAA,CACF,CAAA,EAAA,CACF;AAEV;;;;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ReactNode, Ref } from 'react';
|
|
2
|
+
export interface AppShellScrollAreaProps {
|
|
3
|
+
/** `id` for the scrolling element, e.g. for a scroll-to-top helper that looks it up. */
|
|
4
|
+
id?: string;
|
|
5
|
+
/** Ref to the scrolling element, e.g. to reset `scrollTop` on navigation or attach a scroll listener. */
|
|
6
|
+
ref?: Ref<HTMLDivElement>;
|
|
7
|
+
/** Overrides the scrolling element's `data-testid` (defaults to `<root>--scroll-area`). */
|
|
8
|
+
'data-testid'?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AppShellProps {
|
|
11
|
+
/** Primary navigation, rendered first beside the content column. Compose `<SidebarNavigation>` here. */
|
|
12
|
+
sidebar?: ReactNode;
|
|
13
|
+
/** Top bar, rendered at the top of the content column. It stays in place while the page area scrolls. Compose `<ApplicationHeader>` here. */
|
|
14
|
+
header?: ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* Side panel rendered under the header, beside the page area, which narrows to make room. It fills
|
|
17
|
+
* the height under the header and stays in view while the page area scrolls.
|
|
18
|
+
*/
|
|
19
|
+
panel?: ReactNode;
|
|
20
|
+
/** Page content, normally a `<PageLayout>`. Rendered inside the shell's scroll area. */
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
/** Hooks for the element that scrolls the page content, since the document itself does not scroll. */
|
|
23
|
+
scrollAreaProps?: AppShellScrollAreaProps;
|
|
24
|
+
/** Extra classes merged onto the root element. */
|
|
25
|
+
className?: string;
|
|
26
|
+
/** Overrides the `data-testid` (defaults to `fd-app-shell`). */
|
|
27
|
+
'data-testid'?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Layout-only template for an app shell: navigation beside a content column that stacks the
|
|
31
|
+
* header above the page, with an optional side panel that pushes the page instead of covering it.
|
|
32
|
+
* The shell is exactly the height of the window and the document never scrolls: the page content
|
|
33
|
+
* scrolls in its own area under the header, so the header, navigation and side panel stay in place
|
|
34
|
+
* with no sticky positioning. It holds no state and renders whatever is passed to its slots, so the
|
|
35
|
+
* app keeps ownership of navigation, search and panel state.
|
|
36
|
+
*
|
|
37
|
+
* @summary window-height layout template placing navigation, header, a scrolling page area and a side panel
|
|
38
|
+
*/
|
|
39
|
+
export declare const AppShell: ({ sidebar, header, panel, children, scrollAreaProps, className, "data-testid": dataTestId }: AppShellProps) => ReactNode;
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/templates/AppShell/index.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,WAAW,uBAAuB;IACtC,wFAAwF;IACxF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yGAAyG;IACzG,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1B,2FAA2F;IAC3F,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,wGAAwG;IACxG,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,6IAA6I;IAC7I,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wFAAwF;IACxF,QAAQ,EAAE,SAAS,CAAC;IACpB,sGAAsG;IACtG,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,GAAI,6FAA6F,aAAa,KAAG,SA8BrI,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { cx } from '@flipdish/ui-library/utilities/cx';
|
|
3
|
+
import { useResolvedTestId, joinTestId } from '@flipdish/ui-library/utilities/testIdUtils';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Layout-only template for an app shell: navigation beside a content column that stacks the
|
|
7
|
+
* header above the page, with an optional side panel that pushes the page instead of covering it.
|
|
8
|
+
* The shell is exactly the height of the window and the document never scrolls: the page content
|
|
9
|
+
* scrolls in its own area under the header, so the header, navigation and side panel stay in place
|
|
10
|
+
* with no sticky positioning. It holds no state and renders whatever is passed to its slots, so the
|
|
11
|
+
* app keeps ownership of navigation, search and panel state.
|
|
12
|
+
*
|
|
13
|
+
* @summary window-height layout template placing navigation, header, a scrolling page area and a side panel
|
|
14
|
+
*/
|
|
15
|
+
const AppShell = ({ sidebar, header, panel, children, scrollAreaProps, className, 'data-testid': dataTestId }) => {
|
|
16
|
+
const appShellTestId = useResolvedTestId({ testId: dataTestId, segment: 'app-shell', rootName: 'app-shell' });
|
|
17
|
+
return (
|
|
18
|
+
// A column below `lg`, so a navigation that renders its own mobile top bar stacks above the content.
|
|
19
|
+
jsxs("div", { "data-testid": appShellTestId, className: cx('flex h-dvh w-full flex-col overflow-hidden bg-primary lg:flex-row', className), children: [sidebar, jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [header, jsxs("div", { className: "flex min-h-0 flex-1", children: [jsx("div", { id: scrollAreaProps?.id, ref: scrollAreaProps?.ref, "data-testid": scrollAreaProps?.['data-testid'] ?? joinTestId(appShellTestId, 'scroll-area'),
|
|
20
|
+
// Focusable so keyboard users can scroll a page that has no focusable content of its own (axe: scrollable-region-focusable).
|
|
21
|
+
// biome-ignore lint/a11y/noNoninteractiveTabindex: a scrollable region must be reachable by keyboard
|
|
22
|
+
tabIndex: 0, className: "flex min-w-0 flex-1 flex-col overflow-y-auto outline-focus-ring focus-visible:outline-2 focus-visible:-outline-offset-2", children: children }), panel] })] })] }));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { AppShell };
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/templates/AppShell/index.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":";;;;AAmCA;;;;;;;;;AASG;MACU,QAAQ,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAiB,KAAe;AAChJ,IAAA,MAAM,cAAc,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAE7G;;IAEEA,IAAA,CAAA,KAAA,EAAA,EAAA,aAAA,EAAkB,cAAc,EAAE,SAAS,EAAE,EAAE,CAAC,mEAAmE,EAAE,SAAS,CAAC,EAAA,QAAA,EAAA,CAC5H,OAAO,EAGRA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,sCAAsC,aAClD,MAAM,EAEPA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,qBAAqB,aAClCC,GAAA,CAAA,KAAA,EAAA,EACE,EAAE,EAAE,eAAe,EAAE,EAAE,EACvB,GAAG,EAAE,eAAe,EAAE,GAAG,iBACZ,eAAe,GAAG,aAAa,CAAC,IAAI,UAAU,CAAC,cAAc,EAAE,aAAa,CAAC;;;AAG1F,gCAAA,QAAQ,EAAE,CAAC,EACX,SAAS,EAAC,yHAAyH,EAAA,QAAA,EAElI,QAAQ,EAAA,CACL,EAEL,KAAK,CAAA,EAAA,CACF,CAAA,EAAA,CACF,CAAA,EAAA,CACF;AAEV;;;;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `AppShell` has no React Native implementation.
|
|
3
|
+
*
|
|
4
|
+
* This is a generated types-only stub (scripts/emit-native-stubs.mjs). It exists so
|
|
5
|
+
* that importing `@flipdish/ui-library/components/templates/AppShell` from React Native fails at
|
|
6
|
+
* compile time rather than resolving to the web build's types. There is no
|
|
7
|
+
* matching `index.js`, so Metro cannot bundle this module either.
|
|
8
|
+
*
|
|
9
|
+
* To make `AppShell` available on React Native, add an `index.native.tsx` beside
|
|
10
|
+
* its `index.tsx` — the build picks it up automatically and this stub disappears.
|
|
11
|
+
*/
|
|
12
|
+
export declare const __NO_REACT_NATIVE_IMPLEMENTATION__: never;
|