eidos-ui 3.5.1 → 3.6.1
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/{chunk-HMEREPDB.cjs → chunk-JGAL5NTA.cjs} +39 -2
- package/dist/chunk-JGAL5NTA.cjs.map +1 -0
- package/dist/chunk-ZY225TNV.js +96 -0
- package/dist/chunk-ZY225TNV.js.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.css +6 -6
- package/dist/index.js +1 -1
- package/dist/page-layout/index.cjs +2 -2
- package/dist/page-layout/index.d.cts +23 -0
- package/dist/page-layout/index.d.ts +23 -0
- package/dist/page-layout/index.js +1 -1
- package/package.json +2 -1
- package/dist/chunk-26SO4LZ5.js +0 -59
- package/dist/chunk-26SO4LZ5.js.map +0 -1
- package/dist/chunk-HMEREPDB.cjs.map +0 -1
|
@@ -11,6 +11,38 @@ var _chunkV4BZWBZTcjs = require('./chunk-V4BZWBZT.cjs');
|
|
|
11
11
|
|
|
12
12
|
var _chunkPTBBY4ZXcjs = require('./chunk-PTBBY4ZX.cjs');
|
|
13
13
|
|
|
14
|
+
// src/components/PageLayout/useScrollRestoration.ts
|
|
15
|
+
var _react = require('react');
|
|
16
|
+
var useScrollRestoration = (key, forwardTo) => {
|
|
17
|
+
const node = _react.useRef.call(void 0, null);
|
|
18
|
+
const offsets = _react.useRef.call(void 0, /* @__PURE__ */ new Map());
|
|
19
|
+
const appliedKey = _react.useRef.call(void 0, key);
|
|
20
|
+
const forwarded = _react.useRef.call(void 0, forwardTo);
|
|
21
|
+
_react.useEffect.call(void 0, () => {
|
|
22
|
+
forwarded.current = forwardTo;
|
|
23
|
+
}, [forwardTo]);
|
|
24
|
+
const setNode = _react.useCallback.call(void 0, (element) => {
|
|
25
|
+
node.current = element;
|
|
26
|
+
const ref = forwarded.current;
|
|
27
|
+
if (typeof ref === "function") ref(element);
|
|
28
|
+
else if (ref) ref.current = element;
|
|
29
|
+
}, []);
|
|
30
|
+
_react.useEffect.call(void 0, () => {
|
|
31
|
+
const element = node.current;
|
|
32
|
+
if (!element || key === void 0) return;
|
|
33
|
+
const record = () => offsets.current.set(key, element.scrollTop);
|
|
34
|
+
element.addEventListener("scroll", record, { passive: true });
|
|
35
|
+
return () => element.removeEventListener("scroll", record);
|
|
36
|
+
}, [key]);
|
|
37
|
+
_react.useLayoutEffect.call(void 0, () => {
|
|
38
|
+
const element = node.current;
|
|
39
|
+
if (!element || key === void 0 || appliedKey.current === key) return;
|
|
40
|
+
appliedKey.current = key;
|
|
41
|
+
element.scrollTop = _nullishCoalesce(offsets.current.get(key), () => ( 0));
|
|
42
|
+
}, [key]);
|
|
43
|
+
return setNode;
|
|
44
|
+
};
|
|
45
|
+
|
|
14
46
|
// src/components/PageLayout/PageLayout.component.tsx
|
|
15
47
|
var _jsxruntime = require('react/jsx-runtime');
|
|
16
48
|
var defaultFooter = { copyright: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} Eidos UI` };
|
|
@@ -21,9 +53,14 @@ var PageLayout = ({
|
|
|
21
53
|
footer,
|
|
22
54
|
children,
|
|
23
55
|
className = "",
|
|
56
|
+
// Destructured so they cannot fall into `...rest` and land on the root
|
|
57
|
+
// element, which is not the scroll container.
|
|
58
|
+
contentRef,
|
|
59
|
+
scrollRestorationKey,
|
|
24
60
|
...rest
|
|
25
61
|
}) => {
|
|
26
62
|
const classes = ["eidos-pagelayout", className].filter(Boolean).join(" ");
|
|
63
|
+
const setContentRef = useScrollRestoration(scrollRestorationKey, contentRef);
|
|
27
64
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: classes, ...rest, children: [
|
|
28
65
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
29
66
|
_chunkJCKGAAPZcjs.Toolbar,
|
|
@@ -33,7 +70,7 @@ var PageLayout = ({
|
|
|
33
70
|
}
|
|
34
71
|
),
|
|
35
72
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "eidos-pagelayout__navigation", children: navigation && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkV4BZWBZTcjs.Navigation, { ...navigation }) }),
|
|
36
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "main", { className: "eidos-pagelayout__content", children: [
|
|
73
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "main", { ref: setContentRef, tabIndex: 0, className: "eidos-pagelayout__content", children: [
|
|
37
74
|
header && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
38
75
|
_chunk3KBBJZHKcjs.Header,
|
|
39
76
|
{
|
|
@@ -56,4 +93,4 @@ var PageLayout = ({
|
|
|
56
93
|
|
|
57
94
|
|
|
58
95
|
exports.PageLayout = PageLayout;
|
|
59
|
-
//# sourceMappingURL=chunk-
|
|
96
|
+
//# sourceMappingURL=chunk-JGAL5NTA.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/eidos-ui/eidos-ui/dist/chunk-JGAL5NTA.cjs","../src/components/PageLayout/useScrollRestoration.ts","../src/components/PageLayout/PageLayout.component.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/eidos-ui/eidos-ui/dist/chunk-JGAL5NTA.cjs","sourcesContent":[null,"import { useCallback, useEffect, useLayoutEffect, useRef } from 'react';\n\n/**\n * Remembers the content region's scroll offset per key, and applies the\n * stored offset whenever the key changes.\n *\n * The key is supplied by the consumer rather than derived here, because only\n * they know what counts as a navigation - this library has no router opinion.\n * That also decides the semantics, exactly as React Router's `getKey` does:\n * a per-path key gives \"this path always reopens where you left it\", while a\n * per-history-entry key gives the browser's own behaviour, where Back\n * restores but a fresh link to the same URL starts at the top.\n *\n * Returns a ref callback for the scroll container, which also forwards the\n * node to the caller's own `contentRef`.\n */\nexport const useScrollRestoration = (\n key: string | number | undefined,\n forwardTo: React.Ref<HTMLElement> | undefined,\n): ((node: HTMLElement | null) => void) => {\n const node = useRef<HTMLElement | null>(null);\n const offsets = useRef(new Map<string | number, number>());\n const appliedKey = useRef(key);\n\n // Held in a ref so the ref callback below can keep a stable identity. A\n // callback ref that changes identity is invoked with `null` and then the\n // node again on every render that changes it, which would detach and\n // reattach the caller's ref for no reason.\n const forwarded = useRef(forwardTo);\n useEffect(() => {\n forwarded.current = forwardTo;\n }, [forwardTo]);\n\n const setNode = useCallback((element: HTMLElement | null) => {\n node.current = element;\n const ref = forwarded.current;\n if (typeof ref === 'function') ref(element);\n else if (ref) (ref as React.RefObject<HTMLElement | null>).current = element;\n }, []);\n\n // Recorded as it happens rather than when the key changes: by the time a\n // navigation commits, the new page's content is already in the DOM and the\n // browser has clamped `scrollTop` to the new, possibly shorter, height. The\n // outgoing offset is no longer readable at that point.\n useEffect(() => {\n const element = node.current;\n if (!element || key === undefined) return;\n\n const record = () => offsets.current.set(key, element.scrollTop);\n element.addEventListener('scroll', record, { passive: true });\n return () => element.removeEventListener('scroll', record);\n }, [key]);\n\n // Layout effect so the offset is applied before paint - in a passive effect\n // the new page is visible at the previous page's offset for a frame first.\n // It does not run on the server, which is correct here: there is no scroll\n // position to restore in static markup, and the client applies it on mount.\n useLayoutEffect(() => {\n const element = node.current;\n if (!element || key === undefined || appliedKey.current === key) return;\n\n appliedKey.current = key;\n element.scrollTop = offsets.current.get(key) ?? 0;\n }, [key]);\n\n return setNode;\n};\n","import React from 'react';\nimport type { PageLayoutProps } from './PageLayout.types';\nimport './PageLayout.scss';\nimport { Toolbar } from '../Toolbar';\nimport { Header } from '../Header';\nimport { Footer } from '../Footer';\nimport type { FooterProps } from '../Footer';\nimport { Navigation } from '../Navigation';\nimport { useScrollRestoration } from './useScrollRestoration';\n\nconst defaultFooter: FooterProps = { copyright: `© ${new Date().getFullYear()} Eidos UI` };\n\nexport const PageLayout: React.FC<PageLayoutProps> = ({\n toolbar,\n navigation,\n header,\n footer,\n children,\n className = '',\n // Destructured so they cannot fall into `...rest` and land on the root\n // element, which is not the scroll container.\n contentRef,\n scrollRestorationKey,\n ...rest\n}) => {\n const classes = ['eidos-pagelayout', className].filter(Boolean).join(' ');\n const setContentRef = useScrollRestoration(scrollRestorationKey, contentRef);\n\n return (\n <div className={classes} {...rest}>\n {/* Spread rather than forwarded field by field, so a prop added to\n `Toolbar` reaches `PageLayout` consumers without a second edit\n here - the previous per-field list silently dropped anything it\n didn't know about. `className` is merged last so the layout's own\n grid-area class can't be overwritten by the caller's. */}\n <Toolbar\n {...toolbar}\n className={['eidos-pagelayout__toolbar', toolbar?.className].filter(Boolean).join(' ')}\n />\n <div className=\"eidos-pagelayout__navigation\">\n {navigation && <Navigation {...navigation} />}\n </div>\n {/* A scrollable region containing nothing focusable cannot be scrolled\n by keyboard at all, and a page body is often pure content - a\n report, an article. `tabIndex={0}` makes the region itself focusable\n so arrow keys and Page Up/Down reach it (SC 2.1.1), matching\n `VirtualList` and `Chat`. */}\n <main ref={setContentRef} tabIndex={0} className=\"eidos-pagelayout__content\">\n {header && (\n <Header\n {...header}\n className={['eidos-pagelayout__header', header.className].filter(Boolean).join(' ')}\n />\n )}\n <div className=\"eidos-pagelayout__body\">{children}</div>\n <Footer\n {...(footer ?? defaultFooter)}\n className={['eidos-pagelayout__footer', footer?.className].filter(Boolean).join(' ')}\n />\n </main>\n </div>\n );\n};\n"]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Toolbar
|
|
3
|
+
} from "./chunk-SFFKQQ5Z.js";
|
|
4
|
+
import {
|
|
5
|
+
Header
|
|
6
|
+
} from "./chunk-OOCCSMWM.js";
|
|
7
|
+
import {
|
|
8
|
+
Navigation
|
|
9
|
+
} from "./chunk-HEX4IMLO.js";
|
|
10
|
+
import {
|
|
11
|
+
Footer
|
|
12
|
+
} from "./chunk-W2F6WDUX.js";
|
|
13
|
+
|
|
14
|
+
// src/components/PageLayout/useScrollRestoration.ts
|
|
15
|
+
import { useCallback, useEffect, useLayoutEffect, useRef } from "react";
|
|
16
|
+
var useScrollRestoration = (key, forwardTo) => {
|
|
17
|
+
const node = useRef(null);
|
|
18
|
+
const offsets = useRef(/* @__PURE__ */ new Map());
|
|
19
|
+
const appliedKey = useRef(key);
|
|
20
|
+
const forwarded = useRef(forwardTo);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
forwarded.current = forwardTo;
|
|
23
|
+
}, [forwardTo]);
|
|
24
|
+
const setNode = useCallback((element) => {
|
|
25
|
+
node.current = element;
|
|
26
|
+
const ref = forwarded.current;
|
|
27
|
+
if (typeof ref === "function") ref(element);
|
|
28
|
+
else if (ref) ref.current = element;
|
|
29
|
+
}, []);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const element = node.current;
|
|
32
|
+
if (!element || key === void 0) return;
|
|
33
|
+
const record = () => offsets.current.set(key, element.scrollTop);
|
|
34
|
+
element.addEventListener("scroll", record, { passive: true });
|
|
35
|
+
return () => element.removeEventListener("scroll", record);
|
|
36
|
+
}, [key]);
|
|
37
|
+
useLayoutEffect(() => {
|
|
38
|
+
const element = node.current;
|
|
39
|
+
if (!element || key === void 0 || appliedKey.current === key) return;
|
|
40
|
+
appliedKey.current = key;
|
|
41
|
+
element.scrollTop = offsets.current.get(key) ?? 0;
|
|
42
|
+
}, [key]);
|
|
43
|
+
return setNode;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// src/components/PageLayout/PageLayout.component.tsx
|
|
47
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
48
|
+
var defaultFooter = { copyright: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} Eidos UI` };
|
|
49
|
+
var PageLayout = ({
|
|
50
|
+
toolbar,
|
|
51
|
+
navigation,
|
|
52
|
+
header,
|
|
53
|
+
footer,
|
|
54
|
+
children,
|
|
55
|
+
className = "",
|
|
56
|
+
// Destructured so they cannot fall into `...rest` and land on the root
|
|
57
|
+
// element, which is not the scroll container.
|
|
58
|
+
contentRef,
|
|
59
|
+
scrollRestorationKey,
|
|
60
|
+
...rest
|
|
61
|
+
}) => {
|
|
62
|
+
const classes = ["eidos-pagelayout", className].filter(Boolean).join(" ");
|
|
63
|
+
const setContentRef = useScrollRestoration(scrollRestorationKey, contentRef);
|
|
64
|
+
return /* @__PURE__ */ jsxs("div", { className: classes, ...rest, children: [
|
|
65
|
+
/* @__PURE__ */ jsx(
|
|
66
|
+
Toolbar,
|
|
67
|
+
{
|
|
68
|
+
...toolbar,
|
|
69
|
+
className: ["eidos-pagelayout__toolbar", toolbar?.className].filter(Boolean).join(" ")
|
|
70
|
+
}
|
|
71
|
+
),
|
|
72
|
+
/* @__PURE__ */ jsx("div", { className: "eidos-pagelayout__navigation", children: navigation && /* @__PURE__ */ jsx(Navigation, { ...navigation }) }),
|
|
73
|
+
/* @__PURE__ */ jsxs("main", { ref: setContentRef, tabIndex: 0, className: "eidos-pagelayout__content", children: [
|
|
74
|
+
header && /* @__PURE__ */ jsx(
|
|
75
|
+
Header,
|
|
76
|
+
{
|
|
77
|
+
...header,
|
|
78
|
+
className: ["eidos-pagelayout__header", header.className].filter(Boolean).join(" ")
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
/* @__PURE__ */ jsx("div", { className: "eidos-pagelayout__body", children }),
|
|
82
|
+
/* @__PURE__ */ jsx(
|
|
83
|
+
Footer,
|
|
84
|
+
{
|
|
85
|
+
...footer ?? defaultFooter,
|
|
86
|
+
className: ["eidos-pagelayout__footer", footer?.className].filter(Boolean).join(" ")
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
] })
|
|
90
|
+
] });
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
PageLayout
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=chunk-ZY225TNV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/PageLayout/useScrollRestoration.ts","../src/components/PageLayout/PageLayout.component.tsx"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef } from 'react';\n\n/**\n * Remembers the content region's scroll offset per key, and applies the\n * stored offset whenever the key changes.\n *\n * The key is supplied by the consumer rather than derived here, because only\n * they know what counts as a navigation - this library has no router opinion.\n * That also decides the semantics, exactly as React Router's `getKey` does:\n * a per-path key gives \"this path always reopens where you left it\", while a\n * per-history-entry key gives the browser's own behaviour, where Back\n * restores but a fresh link to the same URL starts at the top.\n *\n * Returns a ref callback for the scroll container, which also forwards the\n * node to the caller's own `contentRef`.\n */\nexport const useScrollRestoration = (\n key: string | number | undefined,\n forwardTo: React.Ref<HTMLElement> | undefined,\n): ((node: HTMLElement | null) => void) => {\n const node = useRef<HTMLElement | null>(null);\n const offsets = useRef(new Map<string | number, number>());\n const appliedKey = useRef(key);\n\n // Held in a ref so the ref callback below can keep a stable identity. A\n // callback ref that changes identity is invoked with `null` and then the\n // node again on every render that changes it, which would detach and\n // reattach the caller's ref for no reason.\n const forwarded = useRef(forwardTo);\n useEffect(() => {\n forwarded.current = forwardTo;\n }, [forwardTo]);\n\n const setNode = useCallback((element: HTMLElement | null) => {\n node.current = element;\n const ref = forwarded.current;\n if (typeof ref === 'function') ref(element);\n else if (ref) (ref as React.RefObject<HTMLElement | null>).current = element;\n }, []);\n\n // Recorded as it happens rather than when the key changes: by the time a\n // navigation commits, the new page's content is already in the DOM and the\n // browser has clamped `scrollTop` to the new, possibly shorter, height. The\n // outgoing offset is no longer readable at that point.\n useEffect(() => {\n const element = node.current;\n if (!element || key === undefined) return;\n\n const record = () => offsets.current.set(key, element.scrollTop);\n element.addEventListener('scroll', record, { passive: true });\n return () => element.removeEventListener('scroll', record);\n }, [key]);\n\n // Layout effect so the offset is applied before paint - in a passive effect\n // the new page is visible at the previous page's offset for a frame first.\n // It does not run on the server, which is correct here: there is no scroll\n // position to restore in static markup, and the client applies it on mount.\n useLayoutEffect(() => {\n const element = node.current;\n if (!element || key === undefined || appliedKey.current === key) return;\n\n appliedKey.current = key;\n element.scrollTop = offsets.current.get(key) ?? 0;\n }, [key]);\n\n return setNode;\n};\n","import React from 'react';\nimport type { PageLayoutProps } from './PageLayout.types';\nimport './PageLayout.scss';\nimport { Toolbar } from '../Toolbar';\nimport { Header } from '../Header';\nimport { Footer } from '../Footer';\nimport type { FooterProps } from '../Footer';\nimport { Navigation } from '../Navigation';\nimport { useScrollRestoration } from './useScrollRestoration';\n\nconst defaultFooter: FooterProps = { copyright: `© ${new Date().getFullYear()} Eidos UI` };\n\nexport const PageLayout: React.FC<PageLayoutProps> = ({\n toolbar,\n navigation,\n header,\n footer,\n children,\n className = '',\n // Destructured so they cannot fall into `...rest` and land on the root\n // element, which is not the scroll container.\n contentRef,\n scrollRestorationKey,\n ...rest\n}) => {\n const classes = ['eidos-pagelayout', className].filter(Boolean).join(' ');\n const setContentRef = useScrollRestoration(scrollRestorationKey, contentRef);\n\n return (\n <div className={classes} {...rest}>\n {/* Spread rather than forwarded field by field, so a prop added to\n `Toolbar` reaches `PageLayout` consumers without a second edit\n here - the previous per-field list silently dropped anything it\n didn't know about. `className` is merged last so the layout's own\n grid-area class can't be overwritten by the caller's. */}\n <Toolbar\n {...toolbar}\n className={['eidos-pagelayout__toolbar', toolbar?.className].filter(Boolean).join(' ')}\n />\n <div className=\"eidos-pagelayout__navigation\">\n {navigation && <Navigation {...navigation} />}\n </div>\n {/* A scrollable region containing nothing focusable cannot be scrolled\n by keyboard at all, and a page body is often pure content - a\n report, an article. `tabIndex={0}` makes the region itself focusable\n so arrow keys and Page Up/Down reach it (SC 2.1.1), matching\n `VirtualList` and `Chat`. */}\n <main ref={setContentRef} tabIndex={0} className=\"eidos-pagelayout__content\">\n {header && (\n <Header\n {...header}\n className={['eidos-pagelayout__header', header.className].filter(Boolean).join(' ')}\n />\n )}\n <div className=\"eidos-pagelayout__body\">{children}</div>\n <Footer\n {...(footer ?? defaultFooter)}\n className={['eidos-pagelayout__footer', footer?.className].filter(Boolean).join(' ')}\n />\n </main>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAAA,SAAS,aAAa,WAAW,iBAAiB,cAAc;AAgBzD,IAAM,uBAAuB,CAClC,KACA,cACyC;AACzC,QAAM,OAAO,OAA2B,IAAI;AAC5C,QAAM,UAAU,OAAO,oBAAI,IAA6B,CAAC;AACzD,QAAM,aAAa,OAAO,GAAG;AAM7B,QAAM,YAAY,OAAO,SAAS;AAClC,YAAU,MAAM;AACd,cAAU,UAAU;AAAA,EACtB,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,UAAU,YAAY,CAAC,YAAgC;AAC3D,SAAK,UAAU;AACf,UAAM,MAAM,UAAU;AACtB,QAAI,OAAO,QAAQ,WAAY,KAAI,OAAO;AAAA,aACjC,IAAK,CAAC,IAA4C,UAAU;AAAA,EACvE,GAAG,CAAC,CAAC;AAML,YAAU,MAAM;AACd,UAAM,UAAU,KAAK;AACrB,QAAI,CAAC,WAAW,QAAQ,OAAW;AAEnC,UAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI,KAAK,QAAQ,SAAS;AAC/D,YAAQ,iBAAiB,UAAU,QAAQ,EAAE,SAAS,KAAK,CAAC;AAC5D,WAAO,MAAM,QAAQ,oBAAoB,UAAU,MAAM;AAAA,EAC3D,GAAG,CAAC,GAAG,CAAC;AAMR,kBAAgB,MAAM;AACpB,UAAM,UAAU,KAAK;AACrB,QAAI,CAAC,WAAW,QAAQ,UAAa,WAAW,YAAY,IAAK;AAEjE,eAAW,UAAU;AACrB,YAAQ,YAAY,QAAQ,QAAQ,IAAI,GAAG,KAAK;AAAA,EAClD,GAAG,CAAC,GAAG,CAAC;AAER,SAAO;AACT;;;AC/BM,cAYA,YAZA;AAzBN,IAAM,gBAA6B,EAAE,WAAW,SAAK,oBAAI,KAAK,GAAE,YAAY,CAAC,YAAY;AAElF,IAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA;AAAA;AAAA,EAGZ;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,UAAU,CAAC,oBAAoB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AACxE,QAAM,gBAAgB,qBAAqB,sBAAsB,UAAU;AAE3E,SACE,qBAAC,SAAI,WAAW,SAAU,GAAG,MAM3B;AAAA;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACJ,WAAW,CAAC,6BAA6B,SAAS,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA;AAAA,IACvF;AAAA,IACA,oBAAC,SAAI,WAAU,gCACZ,wBAAc,oBAAC,cAAY,GAAG,YAAY,GAC7C;AAAA,IAMA,qBAAC,UAAK,KAAK,eAAe,UAAU,GAAG,WAAU,6BAC9C;AAAA,gBACC;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,WAAW,CAAC,4BAA4B,OAAO,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA;AAAA,MACpF;AAAA,MAEF,oBAAC,SAAI,WAAU,0BAA0B,UAAS;AAAA,MAClD;AAAA,QAAC;AAAA;AAAA,UACE,GAAI,UAAU;AAAA,UACf,WAAW,CAAC,4BAA4B,QAAQ,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA;AAAA,MACrF;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -56,7 +56,7 @@ var _chunkIXZMKIV5cjs = require('./chunk-IXZMKIV5.cjs');
|
|
|
56
56
|
var _chunkVHO6JPRRcjs = require('./chunk-VHO6JPRR.cjs');
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
var
|
|
59
|
+
var _chunkJGAL5NTAcjs = require('./chunk-JGAL5NTA.cjs');
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
var _chunkJCKGAAPZcjs = require('./chunk-JCKGAAPZ.cjs');
|
|
@@ -301,5 +301,5 @@ require('./chunk-DZUJEN5N.cjs');
|
|
|
301
301
|
|
|
302
302
|
|
|
303
303
|
|
|
304
|
-
exports.Accordion = _chunkEAJGSXEWcjs.Accordion; exports.AccordionItem = _chunkEAJGSXEWcjs.AccordionItem; exports.Alert = _chunk3RWZC6OWcjs.Alert; exports.Avatar = _chunkQ3GNKF74cjs.Avatar; exports.AvatarGroup = _chunkQ3GNKF74cjs.AvatarGroup; exports.Badge = _chunk3ETWFS2Ncjs.Badge; exports.Breadcrumb = _chunk5O73AALPcjs.Breadcrumb; exports.Button = _chunkDA375AI6cjs.Button; exports.ButtonGroup = _chunk2ROKOO22cjs.ButtonGroup; exports.Calendar = _chunk6JHVXWDVcjs.Calendar; exports.Card = _chunkV5RS3JZNcjs.Card; exports.Chat = _chunkX3BVQBXDcjs.Chat; exports.Checkbox = _chunkYJNQLH2Lcjs.Checkbox; exports.Chip = _chunkTTLFY76Jcjs.Chip; exports.ColorPicker = _chunkKBQD4JLKcjs.ColorPicker; exports.Combobox = _chunk4AO5RKV5cjs.Combobox; exports.CommandPalette = _chunk2T7ZMMH5cjs.CommandPalette; exports.CommentThread = _chunkX3BVQBXDcjs.CommentThread; exports.ContextMenu = _chunkHNGFRRVZcjs.ContextMenu; exports.DataGrid = _chunk66UQTF57cjs.DataGrid; exports.DatePicker = _chunk6JHVXWDVcjs.DatePicker; exports.Divider = _chunk366R4GKRcjs.Divider; exports.Drawer = _chunkDU5JKTHKcjs.Drawer; exports.Dropdown = _chunkKIZVY57Hcjs.Dropdown; exports.DropdownProvider = _chunkKIZVY57Hcjs.DropdownProvider; exports.EmptyState = _chunkKV3V2CPHcjs.EmptyState; exports.FONT_ACCEPT = _chunkRJVHR45Icjs.FONT_ACCEPT; exports.FileUpload = _chunkXRVRGRC3cjs.FileUpload; exports.Footer = _chunkPTBBY4ZXcjs.Footer; exports.Header = _chunk3KBBJZHKcjs.Header; exports.IconButton = _chunkDA375AI6cjs.IconButton; exports.IdentityHeader = _chunk3KBBJZHKcjs.IdentityHeader; exports.InlineEdit = _chunkI6M6CVI2cjs.InlineEdit; exports.Input = _chunk7VJCGKVPcjs.Input; exports.Kbd = _chunkKVIL4EP4cjs.Kbd; exports.Menu = _chunkJ76JHN7Jcjs.Menu; exports.MenuPanel = _chunkJ76JHN7Jcjs.MenuPanel; exports.MessageComposer = _chunkX3BVQBXDcjs.MessageComposer; exports.Modal = _chunk4JSTBA4Fcjs.Modal; exports.Navigation = _chunkV4BZWBZTcjs.Navigation; exports.NumberInput = _chunkTC5IC6OPcjs.NumberInput; exports.OTPInput = _chunkVHO6JPRRcjs.OTPInput; exports.PageLayout =
|
|
304
|
+
exports.Accordion = _chunkEAJGSXEWcjs.Accordion; exports.AccordionItem = _chunkEAJGSXEWcjs.AccordionItem; exports.Alert = _chunk3RWZC6OWcjs.Alert; exports.Avatar = _chunkQ3GNKF74cjs.Avatar; exports.AvatarGroup = _chunkQ3GNKF74cjs.AvatarGroup; exports.Badge = _chunk3ETWFS2Ncjs.Badge; exports.Breadcrumb = _chunk5O73AALPcjs.Breadcrumb; exports.Button = _chunkDA375AI6cjs.Button; exports.ButtonGroup = _chunk2ROKOO22cjs.ButtonGroup; exports.Calendar = _chunk6JHVXWDVcjs.Calendar; exports.Card = _chunkV5RS3JZNcjs.Card; exports.Chat = _chunkX3BVQBXDcjs.Chat; exports.Checkbox = _chunkYJNQLH2Lcjs.Checkbox; exports.Chip = _chunkTTLFY76Jcjs.Chip; exports.ColorPicker = _chunkKBQD4JLKcjs.ColorPicker; exports.Combobox = _chunk4AO5RKV5cjs.Combobox; exports.CommandPalette = _chunk2T7ZMMH5cjs.CommandPalette; exports.CommentThread = _chunkX3BVQBXDcjs.CommentThread; exports.ContextMenu = _chunkHNGFRRVZcjs.ContextMenu; exports.DataGrid = _chunk66UQTF57cjs.DataGrid; exports.DatePicker = _chunk6JHVXWDVcjs.DatePicker; exports.Divider = _chunk366R4GKRcjs.Divider; exports.Drawer = _chunkDU5JKTHKcjs.Drawer; exports.Dropdown = _chunkKIZVY57Hcjs.Dropdown; exports.DropdownProvider = _chunkKIZVY57Hcjs.DropdownProvider; exports.EmptyState = _chunkKV3V2CPHcjs.EmptyState; exports.FONT_ACCEPT = _chunkRJVHR45Icjs.FONT_ACCEPT; exports.FileUpload = _chunkXRVRGRC3cjs.FileUpload; exports.Footer = _chunkPTBBY4ZXcjs.Footer; exports.Header = _chunk3KBBJZHKcjs.Header; exports.IconButton = _chunkDA375AI6cjs.IconButton; exports.IdentityHeader = _chunk3KBBJZHKcjs.IdentityHeader; exports.InlineEdit = _chunkI6M6CVI2cjs.InlineEdit; exports.Input = _chunk7VJCGKVPcjs.Input; exports.Kbd = _chunkKVIL4EP4cjs.Kbd; exports.Menu = _chunkJ76JHN7Jcjs.Menu; exports.MenuPanel = _chunkJ76JHN7Jcjs.MenuPanel; exports.MessageComposer = _chunkX3BVQBXDcjs.MessageComposer; exports.Modal = _chunk4JSTBA4Fcjs.Modal; exports.Navigation = _chunkV4BZWBZTcjs.Navigation; exports.NumberInput = _chunkTC5IC6OPcjs.NumberInput; exports.OTPInput = _chunkVHO6JPRRcjs.OTPInput; exports.PageLayout = _chunkJGAL5NTAcjs.PageLayout; exports.Pagination = _chunkKREHT4AQcjs.Pagination; exports.Pill = _chunkEQ6BNPTLcjs.Pill; exports.Popover = _chunkVQGLVBPLcjs.Popover; exports.Progress = _chunkV2S6XWIQcjs.Progress; exports.Radio = _chunkKPMIIGHHcjs.Radio; exports.RadioGroup = _chunkKPMIIGHHcjs.RadioGroup; exports.SegmentedControl = _chunkJPYJQ4TFcjs.SegmentedControl; exports.Select = _chunkXZLSHEHEcjs.Select; exports.Skeleton = _chunkIGFR5TEScjs.Skeleton; exports.Slider = _chunkOZZHOEN5cjs.Slider; exports.SnackbarContainer = _chunkXERBOFYZcjs.SnackbarContainer; exports.SnackbarProvider = _chunkXERBOFYZcjs.SnackbarProvider; exports.Spinner = _chunkTROYIUDHcjs.Spinner; exports.SplitButton = _chunkLQXFXXMJcjs.SplitButton; exports.Stepper = _chunkHFZ5FKRGcjs.Stepper; exports.Switch = _chunkIXZMKIV5cjs.Switch; exports.Tab = _chunkNOQF7UQ5cjs.Tab; exports.TabPanel = _chunkNOQF7UQ5cjs.TabPanel; exports.Table = _chunk3ZRFOKDMcjs.Table; exports.TableFiltersDropdown = _chunkPMSENLOAcjs.TableFiltersDropdown; exports.Tabs = _chunkNOQF7UQ5cjs.Tabs; exports.TagInput = _chunkZMRINZIOcjs.TagInput; exports.Textarea = _chunk7BFODYNLcjs.Textarea; exports.ThemeEditor = _chunk36JFXFM2cjs.ThemeEditor; exports.ThemeProvider = _chunkRJVHR45Icjs.ThemeProvider; exports.TimeInput = _chunk6JHVXWDVcjs.TimeInput; exports.Timeline = _chunkZMDZGL5Acjs.Timeline; exports.Toolbar = _chunkJCKGAAPZcjs.Toolbar; exports.Tooltip = _chunkBEOECPVJcjs.Tooltip; exports.TreeView = _chunkXKQMEVODcjs.TreeView; exports.VirtualList = _chunkRUDXHT76cjs.VirtualList; exports.defaultTheme = _chunkRJVHR45Icjs.defaultTheme; exports.familyNameFromFile = _chunkRJVHR45Icjs.familyNameFromFile; exports.isFontAvailable = _chunkRJVHR45Icjs.isFontAvailable; exports.isFontStackAvailable = _chunkRJVHR45Icjs.isFontStackAvailable; exports.registerFontFace = _chunkRJVHR45Icjs.registerFontFace; exports.registerFontFile = _chunkRJVHR45Icjs.registerFontFile; exports.renderIcon = _chunk35LGEPLPcjs.renderIcon; exports.toFontStack = _chunkRJVHR45Icjs.toFontStack; exports.useDropdownContext = _chunkKIZVY57Hcjs.useDropdownContext; exports.useSnackbar = _chunkXERBOFYZcjs.useSnackbar; exports.useSnackbarContext = _chunkXERBOFYZcjs.useSnackbarContext; exports.useTheme = _chunkRJVHR45Icjs.useTheme;
|
|
305
305
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.css
CHANGED
|
@@ -2903,9 +2903,11 @@ kbd.eidos-cmd-kbd {
|
|
|
2903
2903
|
border: 1px solid var(--gray-200);
|
|
2904
2904
|
border-radius: var(--border-radius-md);
|
|
2905
2905
|
background: var(--white);
|
|
2906
|
+
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
|
2906
2907
|
}
|
|
2907
2908
|
.eidos-message-composer:focus-within {
|
|
2908
2909
|
border-color: var(--primary-color);
|
|
2910
|
+
box-shadow: 0 0 0 2px var(--white), 0 0 0 4px var(--primary-color);
|
|
2909
2911
|
}
|
|
2910
2912
|
|
|
2911
2913
|
.eidos-composer-reply-hint {
|
|
@@ -2957,12 +2959,6 @@ kbd.eidos-cmd-kbd {
|
|
|
2957
2959
|
.eidos-composer-input {
|
|
2958
2960
|
width: 100%;
|
|
2959
2961
|
resize: none;
|
|
2960
|
-
}
|
|
2961
|
-
.eidos-composer-input:focus-visible {
|
|
2962
|
-
box-shadow: inset 0 0 0 2px var(--primary-color);
|
|
2963
|
-
border-radius: var(--border-radius-sm);
|
|
2964
|
-
}
|
|
2965
|
-
.eidos-composer-input {
|
|
2966
2962
|
font-size: var(--font-size-sm);
|
|
2967
2963
|
color: var(--dark-color);
|
|
2968
2964
|
line-height: 1.55;
|
|
@@ -9965,6 +9961,10 @@ kbd.eidos-cmd-kbd {
|
|
|
9965
9961
|
min-width: 0;
|
|
9966
9962
|
overflow: auto;
|
|
9967
9963
|
}
|
|
9964
|
+
.eidos-pagelayout__content:focus-visible {
|
|
9965
|
+
outline: none;
|
|
9966
|
+
box-shadow: inset 0 0 0 2px var(--primary-color);
|
|
9967
|
+
}
|
|
9968
9968
|
.eidos-pagelayout__header, .eidos-pagelayout__footer {
|
|
9969
9969
|
flex: 0 0 auto;
|
|
9970
9970
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkJGAL5NTAcjs = require('../chunk-JGAL5NTA.cjs');
|
|
4
4
|
require('../chunk-JCKGAAPZ.cjs');
|
|
5
5
|
require('../chunk-3KBBJZHK.cjs');
|
|
6
6
|
require('../chunk-VQGLVBPL.cjs');
|
|
@@ -21,5 +21,5 @@ require('../chunk-35LGEPLP.cjs');
|
|
|
21
21
|
require('../chunk-DZUJEN5N.cjs');
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
exports.PageLayout =
|
|
24
|
+
exports.PageLayout = _chunkJGAL5NTAcjs.PageLayout;
|
|
25
25
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -22,6 +22,29 @@ interface PageLayoutProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
22
22
|
header?: HeaderProps;
|
|
23
23
|
/** Configures the `Footer` rendered below the page content. Omit to render the default Eidos UI copyright notice. */
|
|
24
24
|
footer?: FooterProps;
|
|
25
|
+
/**
|
|
26
|
+
* Ref to the `main` content region - the layout's only scroll container.
|
|
27
|
+
*
|
|
28
|
+
* Use it to drive that region imperatively, most commonly to scroll back to
|
|
29
|
+
* the top on navigation (`contentRef.current?.scrollTo({ top: 0 })`). Any
|
|
30
|
+
* ref passed through `HTMLAttributes` reaches the outer element instead,
|
|
31
|
+
* which never scrolls.
|
|
32
|
+
*/
|
|
33
|
+
contentRef?: React.Ref<HTMLElement>;
|
|
34
|
+
/**
|
|
35
|
+
* Identifies the current page, so the content region's scroll offset is
|
|
36
|
+
* remembered per page and applied when this value changes. A page seen
|
|
37
|
+
* before reopens where it was left; a new one starts at the top.
|
|
38
|
+
*
|
|
39
|
+
* Pass the value that defines a navigation in your app - `location.pathname`
|
|
40
|
+
* for one offset per path, or a per-history-entry id to match the browser,
|
|
41
|
+
* where Back restores but a fresh link to the same URL starts at the top.
|
|
42
|
+
* Keep it unchanged across a transition that should not move the scroll
|
|
43
|
+
* position, such as a filter written to the query string.
|
|
44
|
+
*
|
|
45
|
+
* Omit it to leave the scroll position alone entirely.
|
|
46
|
+
*/
|
|
47
|
+
scrollRestorationKey?: string | number;
|
|
25
48
|
}
|
|
26
49
|
|
|
27
50
|
declare const PageLayout: React__default.FC<PageLayoutProps>;
|
|
@@ -22,6 +22,29 @@ interface PageLayoutProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
22
22
|
header?: HeaderProps;
|
|
23
23
|
/** Configures the `Footer` rendered below the page content. Omit to render the default Eidos UI copyright notice. */
|
|
24
24
|
footer?: FooterProps;
|
|
25
|
+
/**
|
|
26
|
+
* Ref to the `main` content region - the layout's only scroll container.
|
|
27
|
+
*
|
|
28
|
+
* Use it to drive that region imperatively, most commonly to scroll back to
|
|
29
|
+
* the top on navigation (`contentRef.current?.scrollTo({ top: 0 })`). Any
|
|
30
|
+
* ref passed through `HTMLAttributes` reaches the outer element instead,
|
|
31
|
+
* which never scrolls.
|
|
32
|
+
*/
|
|
33
|
+
contentRef?: React.Ref<HTMLElement>;
|
|
34
|
+
/**
|
|
35
|
+
* Identifies the current page, so the content region's scroll offset is
|
|
36
|
+
* remembered per page and applied when this value changes. A page seen
|
|
37
|
+
* before reopens where it was left; a new one starts at the top.
|
|
38
|
+
*
|
|
39
|
+
* Pass the value that defines a navigation in your app - `location.pathname`
|
|
40
|
+
* for one offset per path, or a per-history-entry id to match the browser,
|
|
41
|
+
* where Back restores but a fresh link to the same URL starts at the top.
|
|
42
|
+
* Keep it unchanged across a transition that should not move the scroll
|
|
43
|
+
* position, such as a filter written to the query string.
|
|
44
|
+
*
|
|
45
|
+
* Omit it to leave the scroll position alone entirely.
|
|
46
|
+
*/
|
|
47
|
+
scrollRestorationKey?: string | number;
|
|
25
48
|
}
|
|
26
49
|
|
|
27
50
|
declare const PageLayout: React__default.FC<PageLayoutProps>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eidos-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.1",
|
|
4
4
|
"description": "A modern React component library with TypeScript and SCSS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"postversion": "git push --follow-tags",
|
|
59
59
|
"release:needed": "node scripts/release-needed.js",
|
|
60
60
|
"check:docs": "node scripts/check-docs.js",
|
|
61
|
+
"check:story-docs": "node scripts/check-story-docs.js",
|
|
61
62
|
"release:preflight": "node scripts/preflight-release.js && npm run lint && npm run typecheck && npm run prettier:check && npm run build"
|
|
62
63
|
},
|
|
63
64
|
"keywords": [
|
package/dist/chunk-26SO4LZ5.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Toolbar
|
|
3
|
-
} from "./chunk-SFFKQQ5Z.js";
|
|
4
|
-
import {
|
|
5
|
-
Header
|
|
6
|
-
} from "./chunk-OOCCSMWM.js";
|
|
7
|
-
import {
|
|
8
|
-
Navigation
|
|
9
|
-
} from "./chunk-HEX4IMLO.js";
|
|
10
|
-
import {
|
|
11
|
-
Footer
|
|
12
|
-
} from "./chunk-W2F6WDUX.js";
|
|
13
|
-
|
|
14
|
-
// src/components/PageLayout/PageLayout.component.tsx
|
|
15
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
-
var defaultFooter = { copyright: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} Eidos UI` };
|
|
17
|
-
var PageLayout = ({
|
|
18
|
-
toolbar,
|
|
19
|
-
navigation,
|
|
20
|
-
header,
|
|
21
|
-
footer,
|
|
22
|
-
children,
|
|
23
|
-
className = "",
|
|
24
|
-
...rest
|
|
25
|
-
}) => {
|
|
26
|
-
const classes = ["eidos-pagelayout", className].filter(Boolean).join(" ");
|
|
27
|
-
return /* @__PURE__ */ jsxs("div", { className: classes, ...rest, children: [
|
|
28
|
-
/* @__PURE__ */ jsx(
|
|
29
|
-
Toolbar,
|
|
30
|
-
{
|
|
31
|
-
...toolbar,
|
|
32
|
-
className: ["eidos-pagelayout__toolbar", toolbar?.className].filter(Boolean).join(" ")
|
|
33
|
-
}
|
|
34
|
-
),
|
|
35
|
-
/* @__PURE__ */ jsx("div", { className: "eidos-pagelayout__navigation", children: navigation && /* @__PURE__ */ jsx(Navigation, { ...navigation }) }),
|
|
36
|
-
/* @__PURE__ */ jsxs("main", { className: "eidos-pagelayout__content", children: [
|
|
37
|
-
header && /* @__PURE__ */ jsx(
|
|
38
|
-
Header,
|
|
39
|
-
{
|
|
40
|
-
...header,
|
|
41
|
-
className: ["eidos-pagelayout__header", header.className].filter(Boolean).join(" ")
|
|
42
|
-
}
|
|
43
|
-
),
|
|
44
|
-
/* @__PURE__ */ jsx("div", { className: "eidos-pagelayout__body", children }),
|
|
45
|
-
/* @__PURE__ */ jsx(
|
|
46
|
-
Footer,
|
|
47
|
-
{
|
|
48
|
-
...footer ?? defaultFooter,
|
|
49
|
-
className: ["eidos-pagelayout__footer", footer?.className].filter(Boolean).join(" ")
|
|
50
|
-
}
|
|
51
|
-
)
|
|
52
|
-
] })
|
|
53
|
-
] });
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export {
|
|
57
|
-
PageLayout
|
|
58
|
-
};
|
|
59
|
-
//# sourceMappingURL=chunk-26SO4LZ5.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/PageLayout/PageLayout.component.tsx"],"sourcesContent":["import React from 'react';\nimport type { PageLayoutProps } from './PageLayout.types';\nimport './PageLayout.scss';\nimport { Toolbar } from '../Toolbar';\nimport { Header } from '../Header';\nimport { Footer } from '../Footer';\nimport type { FooterProps } from '../Footer';\nimport { Navigation } from '../Navigation';\n\nconst defaultFooter: FooterProps = { copyright: `© ${new Date().getFullYear()} Eidos UI` };\n\nexport const PageLayout: React.FC<PageLayoutProps> = ({\n toolbar,\n navigation,\n header,\n footer,\n children,\n className = '',\n ...rest\n}) => {\n const classes = ['eidos-pagelayout', className].filter(Boolean).join(' ');\n\n return (\n <div className={classes} {...rest}>\n {/* Spread rather than forwarded field by field, so a prop added to\n `Toolbar` reaches `PageLayout` consumers without a second edit\n here - the previous per-field list silently dropped anything it\n didn't know about. `className` is merged last so the layout's own\n grid-area class can't be overwritten by the caller's. */}\n <Toolbar\n {...toolbar}\n className={['eidos-pagelayout__toolbar', toolbar?.className].filter(Boolean).join(' ')}\n />\n <div className=\"eidos-pagelayout__navigation\">\n {navigation && <Navigation {...navigation} />}\n </div>\n <main className=\"eidos-pagelayout__content\">\n {header && (\n <Header\n {...header}\n className={['eidos-pagelayout__header', header.className].filter(Boolean).join(' ')}\n />\n )}\n <div className=\"eidos-pagelayout__body\">{children}</div>\n <Footer\n {...(footer ?? defaultFooter)}\n className={['eidos-pagelayout__footer', footer?.className].filter(Boolean).join(' ')}\n />\n </main>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AA6BM,cAOA,YAPA;AApBN,IAAM,gBAA6B,EAAE,WAAW,SAAK,oBAAI,KAAK,GAAE,YAAY,CAAC,YAAY;AAElF,IAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,GAAG;AACL,MAAM;AACJ,QAAM,UAAU,CAAC,oBAAoB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAExE,SACE,qBAAC,SAAI,WAAW,SAAU,GAAG,MAM3B;AAAA;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACJ,WAAW,CAAC,6BAA6B,SAAS,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA;AAAA,IACvF;AAAA,IACA,oBAAC,SAAI,WAAU,gCACZ,wBAAc,oBAAC,cAAY,GAAG,YAAY,GAC7C;AAAA,IACA,qBAAC,UAAK,WAAU,6BACb;AAAA,gBACC;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,WAAW,CAAC,4BAA4B,OAAO,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA;AAAA,MACpF;AAAA,MAEF,oBAAC,SAAI,WAAU,0BAA0B,UAAS;AAAA,MAClD;AAAA,QAAC;AAAA;AAAA,UACE,GAAI,UAAU;AAAA,UACf,WAAW,CAAC,4BAA4B,QAAQ,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA;AAAA,MACrF;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/eidos-ui/eidos-ui/dist/chunk-HMEREPDB.cjs","../src/components/PageLayout/PageLayout.component.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACgBM,+CAAA;AApBN,IAAM,cAAA,EAA6B,EAAE,SAAA,EAAW,CAAA,KAAA,EAAA,iBAAK,IAAI,IAAA,CAAK,CAAA,CAAA,CAAE,WAAA,CAAY,CAAC,CAAA,SAAA,EAAY,CAAA;AAElF,IAAM,WAAA,EAAwC,CAAC;AAAA,EACpD,OAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA,EAAY,EAAA;AAAA,EACZ,GAAG;AACL,CAAA,EAAA,GAAM;AACJ,EAAA,MAAM,QAAA,EAAU,CAAC,kBAAA,EAAoB,SAAS,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAExE,EAAA,uBACE,8BAAA,KAAC,EAAA,EAAI,SAAA,EAAW,OAAA,EAAU,GAAG,IAAA,EAM3B,QAAA,EAAA;AAAA,oBAAA,6BAAA;AAAA,MAAC,yBAAA;AAAA,MAAA;AAAA,QACE,GAAG,OAAA;AAAA,QACJ,SAAA,EAAW,CAAC,2BAAA,kBAA6B,OAAA,2BAAS,WAAS,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG;AAAA,MAAA;AAAA,IACvF,CAAA;AAAA,oBACA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,8BAAA,EACZ,QAAA,EAAA,WAAA,mBAAc,6BAAA,4BAAC,EAAA,EAAY,GAAG,WAAA,CAAY,EAAA,CAC7C,CAAA;AAAA,oBACA,8BAAA,MAAC,EAAA,EAAK,SAAA,EAAU,2BAAA,EACb,QAAA,EAAA;AAAA,MAAA,OAAA,mBACC,6BAAA;AAAA,QAAC,wBAAA;AAAA,QAAA;AAAA,UACE,GAAG,MAAA;AAAA,UACJ,SAAA,EAAW,CAAC,0BAAA,EAA4B,MAAA,CAAO,SAAS,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG;AAAA,QAAA;AAAA,MACpF,CAAA;AAAA,sBAEF,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,wBAAA,EAA0B,SAAA,CAAS,CAAA;AAAA,sBAClD,6BAAA;AAAA,QAAC,wBAAA;AAAA,QAAA;AAAA,UACE,oBAAI,MAAA,UAAU,eAAA;AAAA,UACf,SAAA,EAAW,CAAC,0BAAA,kBAA4B,MAAA,6BAAQ,WAAS,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG;AAAA,QAAA;AAAA,MACrF;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,EAAA,CACF,CAAA;AAEJ,CAAA;ADGA;AACA;AACE;AACF,gCAAC","file":"/home/runner/work/eidos-ui/eidos-ui/dist/chunk-HMEREPDB.cjs","sourcesContent":[null,"import React from 'react';\nimport type { PageLayoutProps } from './PageLayout.types';\nimport './PageLayout.scss';\nimport { Toolbar } from '../Toolbar';\nimport { Header } from '../Header';\nimport { Footer } from '../Footer';\nimport type { FooterProps } from '../Footer';\nimport { Navigation } from '../Navigation';\n\nconst defaultFooter: FooterProps = { copyright: `© ${new Date().getFullYear()} Eidos UI` };\n\nexport const PageLayout: React.FC<PageLayoutProps> = ({\n toolbar,\n navigation,\n header,\n footer,\n children,\n className = '',\n ...rest\n}) => {\n const classes = ['eidos-pagelayout', className].filter(Boolean).join(' ');\n\n return (\n <div className={classes} {...rest}>\n {/* Spread rather than forwarded field by field, so a prop added to\n `Toolbar` reaches `PageLayout` consumers without a second edit\n here - the previous per-field list silently dropped anything it\n didn't know about. `className` is merged last so the layout's own\n grid-area class can't be overwritten by the caller's. */}\n <Toolbar\n {...toolbar}\n className={['eidos-pagelayout__toolbar', toolbar?.className].filter(Boolean).join(' ')}\n />\n <div className=\"eidos-pagelayout__navigation\">\n {navigation && <Navigation {...navigation} />}\n </div>\n <main className=\"eidos-pagelayout__content\">\n {header && (\n <Header\n {...header}\n className={['eidos-pagelayout__header', header.className].filter(Boolean).join(' ')}\n />\n )}\n <div className=\"eidos-pagelayout__body\">{children}</div>\n <Footer\n {...(footer ?? defaultFooter)}\n className={['eidos-pagelayout__footer', footer?.className].filter(Boolean).join(' ')}\n />\n </main>\n </div>\n );\n};\n"]}
|