@cratis/scene.blueprint.default 4.28.0 → 4.30.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/cjs/shell/RegionNavigation.js +38 -0
- package/dist/cjs/shell/RegionNavigation.js.map +1 -0
- package/dist/cjs/shell/Sidebar.js +10 -1
- package/dist/cjs/shell/Sidebar.js.map +1 -1
- package/dist/cjs/shell/Topbar.js +10 -1
- package/dist/cjs/shell/Topbar.js.map +1 -1
- package/dist/esm/shell/RegionNavigation.d.ts +7 -0
- package/dist/esm/shell/RegionNavigation.d.ts.map +1 -0
- package/dist/esm/shell/RegionNavigation.js +35 -0
- package/dist/esm/shell/RegionNavigation.js.map +1 -0
- package/dist/esm/shell/RegionNavigation.stories.d.ts +16 -0
- package/dist/esm/shell/RegionNavigation.stories.d.ts.map +1 -0
- package/dist/esm/shell/RegionNavigation.stories.js +70 -0
- package/dist/esm/shell/RegionNavigation.stories.js.map +1 -0
- package/dist/esm/shell/Sidebar.d.ts.map +1 -1
- package/dist/esm/shell/Sidebar.js +11 -2
- package/dist/esm/shell/Sidebar.js.map +1 -1
- package/dist/esm/shell/ToolbarSliceDialog.stories.d.ts +16 -0
- package/dist/esm/shell/ToolbarSliceDialog.stories.d.ts.map +1 -0
- package/dist/esm/shell/ToolbarSliceDialog.stories.js +31 -0
- package/dist/esm/shell/ToolbarSliceDialog.stories.js.map +1 -0
- package/dist/esm/shell/Topbar.d.ts.map +1 -1
- package/dist/esm/shell/Topbar.js +10 -1
- package/dist/esm/shell/Topbar.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/shell/RegionNavigation.stories.tsx +99 -0
- package/shell/RegionNavigation.tsx +31 -0
- package/shell/Sidebar.tsx +8 -2
- package/shell/ToolbarSliceDialog.stories.tsx +56 -0
- package/shell/Topbar.tsx +7 -1
- package/shell/layout.css +234 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var scene_react = require('@cratis/scene.react');
|
|
5
|
+
|
|
6
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
7
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
8
|
+
/** The `layout-menu` vocabulary the shell's stylesheet already styles, so a region looks like the menu it replaces. */ const classNames = {
|
|
9
|
+
root: 'layout-region',
|
|
10
|
+
list: 'layout-menu',
|
|
11
|
+
item: 'layout-menu-item',
|
|
12
|
+
link: 'layout-menu-link',
|
|
13
|
+
icon: 'layout-menu-icon',
|
|
14
|
+
label: 'layout-menu-label',
|
|
15
|
+
toggle: 'layout-menu-toggle',
|
|
16
|
+
submenu: 'layout-submenu'
|
|
17
|
+
};
|
|
18
|
+
/** Whether a navigation model is in scope, so the topbar and sidebar have a region to show. */ function useHasRegionNavigation() {
|
|
19
|
+
return scene_react.useSceneNavigationModel() !== undefined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The navigation a shell's topbar or sidebar shows when the application supplies a navigation model: the effective items of
|
|
23
|
+
* its region - inherit/extend/override already applied - as the shell's menu, with the active item, the hierarchy and
|
|
24
|
+
* the keyboard behaviour of `NavigationRegionView`.
|
|
25
|
+
*/ function RegionNavigation({ region, label }) {
|
|
26
|
+
return /*#__PURE__*/ jsxRuntime.jsx(scene_react.NavigationRegionView, {
|
|
27
|
+
region: region,
|
|
28
|
+
label: label,
|
|
29
|
+
classNames: {
|
|
30
|
+
...classNames,
|
|
31
|
+
root: `layout-region layout-region-${region}`
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.RegionNavigation = RegionNavigation;
|
|
37
|
+
exports.useHasRegionNavigation = useHasRegionNavigation;
|
|
38
|
+
//# sourceMappingURL=RegionNavigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegionNavigation.js","sources":["../../../shell/RegionNavigation.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { NavigationRegionKind } from '@cratis/scene.model';\nimport { NavigationRegionClassNames, NavigationRegionView, useSceneNavigationModel } from '@cratis/scene.react';\n\n/** The `layout-menu` vocabulary the shell's stylesheet already styles, so a region looks like the menu it replaces. */\nconst classNames: Partial<NavigationRegionClassNames> = {\n root: 'layout-region',\n list: 'layout-menu',\n item: 'layout-menu-item',\n link: 'layout-menu-link',\n icon: 'layout-menu-icon',\n label: 'layout-menu-label',\n toggle: 'layout-menu-toggle',\n submenu: 'layout-submenu',\n};\n\n/** Whether a navigation model is in scope, so the topbar and sidebar have a region to show. */\nexport function useHasRegionNavigation(): boolean {\n return useSceneNavigationModel() !== undefined;\n}\n\n/**\n * The navigation a shell's topbar or sidebar shows when the application supplies a navigation model: the effective items of\n * its region - inherit/extend/override already applied - as the shell's menu, with the active item, the hierarchy and\n * the keyboard behaviour of `NavigationRegionView`.\n */\nexport function RegionNavigation({ region, label }: { region: NavigationRegionKind; label?: string }) {\n return <NavigationRegionView region={region} label={label} classNames={{ ...classNames, root: `layout-region layout-region-${region}` }} />;\n}\n"],"names":["classNames","root","list","item","link","icon","label","toggle","submenu","useHasRegionNavigation","useSceneNavigationModel","undefined","RegionNavigation","region","_jsx","NavigationRegionView"],"mappings":";;;;;AAAA;AACA;AAKA,wHACA,MAAMA,UAAAA,GAAkD;IACpDC,IAAAA,EAAM,eAAA;IACNC,IAAAA,EAAM,aAAA;IACNC,IAAAA,EAAM,kBAAA;IACNC,IAAAA,EAAM,kBAAA;IACNC,IAAAA,EAAM,kBAAA;IACNC,KAAAA,EAAO,mBAAA;IACPC,MAAAA,EAAQ,oBAAA;IACRC,OAAAA,EAAS;AACb,CAAA;AAEA,gGACO,SAASC,sBAAAA,GAAAA;AACZ,IAAA,OAAOC,mCAAAA,EAAAA,KAA8BC,SAAAA;AACzC;AAEA;;;;AAIC,IACM,SAASC,gBAAAA,CAAiB,EAAEC,MAAM,EAAEP,KAAK,EAAoD,EAAA;AAChG,IAAA,qBAAOQ,cAAA,CAACC,gCAAAA,EAAAA;QAAqBF,MAAAA,EAAQA,MAAAA;QAAQP,KAAAA,EAAOA,KAAAA;QAAON,UAAAA,EAAY;AAAE,YAAA,GAAGA,UAAU;YAAEC,IAAAA,EAAM,CAAC,4BAA4B,EAAEY,MAAAA,CAAAA;AAAS;;AAC1I;;;"}
|
|
@@ -4,7 +4,9 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
4
4
|
var button = require('primereact/button');
|
|
5
5
|
var layoutConfigTransitions = require('../configuration/layoutConfigTransitions.js');
|
|
6
6
|
var LayoutConfigProvider = require('../configuration/LayoutConfigProvider.js');
|
|
7
|
+
var scene_model = require('@cratis/scene.model');
|
|
7
8
|
var elementProperties = require('./elementProperties.js');
|
|
9
|
+
var RegionNavigation = require('./RegionNavigation.js');
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* The sidebar's own chrome, inside the panel {@link AppShell} positions.
|
|
@@ -14,10 +16,14 @@ var elementProperties = require('./elementProperties.js');
|
|
|
14
16
|
* the shell; everything about *what is in it* belongs to the screen. A template can replace this header
|
|
15
17
|
* wholesale without any of the mode CSS noticing.
|
|
16
18
|
*
|
|
19
|
+
* When the application supplies a navigation model and the sidebar has no `content` of its own, the content is the effective
|
|
20
|
+
* navigation of the sidebar region for the module on the page (set `regionNavigation` to false to opt out).
|
|
21
|
+
*
|
|
17
22
|
* The pin button only appears in `reveal` and `drawer`, the two modes where the sidebar answers to the
|
|
18
23
|
* pointer and therefore needs a way to be made to stay.
|
|
19
24
|
*/ function Sidebar({ element, slots }) {
|
|
20
25
|
const { effectiveMode, config, toggleSidebarAnchor } = LayoutConfigProvider.useLayoutConfig();
|
|
26
|
+
const hasRegion = RegionNavigation.useHasRegionNavigation();
|
|
21
27
|
const title = elementProperties.readString(element, 'title');
|
|
22
28
|
const isPinnable = layoutConfigTransitions.isPointerRevealMode(effectiveMode);
|
|
23
29
|
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
@@ -46,7 +52,10 @@ var elementProperties = require('./elementProperties.js');
|
|
|
46
52
|
})
|
|
47
53
|
]
|
|
48
54
|
}),
|
|
49
|
-
slots.content
|
|
55
|
+
slots.content?.length ? slots.content : hasRegion && elementProperties.readBoolean(element, 'regionNavigation', true) ? /*#__PURE__*/ jsxRuntime.jsx(RegionNavigation.RegionNavigation, {
|
|
56
|
+
region: scene_model.NavigationRegionKind.Sidebar,
|
|
57
|
+
label: "Sidebar"
|
|
58
|
+
}) : null
|
|
50
59
|
]
|
|
51
60
|
});
|
|
52
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.js","sources":["../../../shell/Sidebar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Button } from 'primereact/button';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { isPointerRevealMode, useLayoutConfig } from '../configuration';\nimport { readString } from './elementProperties';\n\n/**\n * The sidebar's own chrome, inside the panel {@link AppShell} positions.\n *\n * The panel and its contents are deliberately different components. Everything about *where* the sidebar\n * is - translated off-canvas, collapsed to a rail, growing on hover - belongs to the mode and therefore to\n * the shell; everything about *what is in it* belongs to the screen. A template can replace this header\n * wholesale without any of the mode CSS noticing.\n *\n * The pin button only appears in `reveal` and `drawer`, the two modes where the sidebar answers to the\n * pointer and therefore needs a way to be made to stay.\n */\nexport function Sidebar({ element, slots }: RegisteredComponentProps) {\n const { effectiveMode, config, toggleSidebarAnchor } = useLayoutConfig();\n const title = readString(element, 'title');\n const isPinnable = isPointerRevealMode(effectiveMode);\n\n return (\n <>\n <div className='layout-sidebar-header' data-scene-id={element.id}>\n {slots.logo}\n {title && <span className='layout-sidebar-title'>{title}</span>}\n {isPinnable && (\n <Button\n type='button'\n variant='text'\n rounded\n iconOnly\n aria-label={config.isSidebarAnchored ? 'Unpin the menu' : 'Pin the menu open'}\n aria-pressed={config.isSidebarAnchored}\n onClick={toggleSidebarAnchor}>\n <i className={config.isSidebarAnchored ? 'pi pi-lock' : 'pi pi-lock-open'} aria-hidden='true' />\n </Button>\n )}\n </div>\n {slots.content}\n </>\n );\n}\n"],"names":["Sidebar","element","slots","effectiveMode","config","toggleSidebarAnchor","useLayoutConfig","title","readString","isPinnable","isPointerRevealMode","_jsxs","_Fragment","div","className","data-scene-id","id","logo","_jsx","span","Button","type","variant","rounded","iconOnly","aria-label","isSidebarAnchored","aria-pressed","onClick","i","aria-hidden","content"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Sidebar.js","sources":["../../../shell/Sidebar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Button } from 'primereact/button';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { isPointerRevealMode, useLayoutConfig } from '../configuration';\nimport { NavigationRegionKind } from '@cratis/scene.model';\nimport { readBoolean, readString } from './elementProperties';\nimport { RegionNavigation, useHasRegionNavigation } from './RegionNavigation';\n\n/**\n * The sidebar's own chrome, inside the panel {@link AppShell} positions.\n *\n * The panel and its contents are deliberately different components. Everything about *where* the sidebar\n * is - translated off-canvas, collapsed to a rail, growing on hover - belongs to the mode and therefore to\n * the shell; everything about *what is in it* belongs to the screen. A template can replace this header\n * wholesale without any of the mode CSS noticing.\n *\n * When the application supplies a navigation model and the sidebar has no `content` of its own, the content is the effective\n * navigation of the sidebar region for the module on the page (set `regionNavigation` to false to opt out).\n *\n * The pin button only appears in `reveal` and `drawer`, the two modes where the sidebar answers to the\n * pointer and therefore needs a way to be made to stay.\n */\nexport function Sidebar({ element, slots }: RegisteredComponentProps) {\n const { effectiveMode, config, toggleSidebarAnchor } = useLayoutConfig();\n const hasRegion = useHasRegionNavigation();\n const title = readString(element, 'title');\n const isPinnable = isPointerRevealMode(effectiveMode);\n\n return (\n <>\n <div className='layout-sidebar-header' data-scene-id={element.id}>\n {slots.logo}\n {title && <span className='layout-sidebar-title'>{title}</span>}\n {isPinnable && (\n <Button\n type='button'\n variant='text'\n rounded\n iconOnly\n aria-label={config.isSidebarAnchored ? 'Unpin the menu' : 'Pin the menu open'}\n aria-pressed={config.isSidebarAnchored}\n onClick={toggleSidebarAnchor}>\n <i className={config.isSidebarAnchored ? 'pi pi-lock' : 'pi pi-lock-open'} aria-hidden='true' />\n </Button>\n )}\n </div>\n {slots.content?.length ? slots.content : hasRegion && readBoolean(element, 'regionNavigation', true) ? <RegionNavigation region={NavigationRegionKind.Sidebar} label='Sidebar' /> : null}\n </>\n );\n}\n"],"names":["Sidebar","element","slots","effectiveMode","config","toggleSidebarAnchor","useLayoutConfig","hasRegion","useHasRegionNavigation","title","readString","isPinnable","isPointerRevealMode","_jsxs","_Fragment","div","className","data-scene-id","id","logo","_jsx","span","Button","type","variant","rounded","iconOnly","aria-label","isSidebarAnchored","aria-pressed","onClick","i","aria-hidden","content","length","readBoolean","RegionNavigation","region","NavigationRegionKind","label"],"mappings":";;;;;;;;;;AAUA;;;;;;;;;;;;;AAaC,IACM,SAASA,OAAAA,CAAQ,EAAEC,OAAO,EAAEC,KAAK,EAA4B,EAAA;AAChE,IAAA,MAAM,EAAEC,aAAa,EAAEC,MAAM,EAAEC,mBAAmB,EAAE,GAAGC,oCAAAA,EAAAA;AACvD,IAAA,MAAMC,SAAAA,GAAYC,uCAAAA,EAAAA;IAClB,MAAMC,KAAAA,GAAQC,6BAAWT,OAAAA,EAAS,OAAA,CAAA;AAClC,IAAA,MAAMU,aAAaC,2CAAAA,CAAoBT,aAAAA,CAAAA;IAEvC,qBACIU,eAAA,CAAAC,mBAAA,EAAA;;0BACID,eAAA,CAACE,KAAAA,EAAAA;gBAAIC,SAAAA,EAAU,uBAAA;AAAwBC,gBAAAA,eAAAA,EAAehB,QAAQiB,EAAE;;AAC3DhB,oBAAAA,KAAAA,CAAMiB,IAAI;AACVV,oBAAAA,KAAAA,kBAASW,cAAA,CAACC,MAAAA,EAAAA;wBAAKL,SAAAA,EAAU,sBAAA;AAAwBP,wBAAAA,QAAAA,EAAAA;;AACjDE,oBAAAA,UAAAA,kBACGS,cAAA,CAACE,aAAAA,EAAAA;wBACGC,IAAAA,EAAK,QAAA;wBACLC,OAAAA,EAAQ,MAAA;wBACRC,OAAO,EAAA,IAAA;wBACPC,QAAQ,EAAA,IAAA;wBACRC,YAAAA,EAAYvB,MAAAA,CAAOwB,iBAAiB,GAAG,gBAAA,GAAmB,mBAAA;AAC1DC,wBAAAA,cAAAA,EAAczB,OAAOwB,iBAAiB;wBACtCE,OAAAA,EAASzB,mBAAAA;AACT,wBAAA,QAAA,gBAAAe,cAAA,CAACW,GAAAA,EAAAA;4BAAEf,SAAAA,EAAWZ,MAAAA,CAAOwB,iBAAiB,GAAG,YAAA,GAAe,iBAAA;4BAAmBI,aAAAA,EAAY;;;;;YAIlG9B,KAAAA,CAAM+B,OAAO,EAAEC,MAAAA,GAAShC,KAAAA,CAAM+B,OAAO,GAAG1B,SAAAA,IAAa4B,6BAAAA,CAAYlC,OAAAA,EAAS,kBAAA,EAAoB,IAAA,CAAA,iBAAQmB,cAAA,CAACgB,iCAAAA,EAAAA;AAAiBC,gBAAAA,MAAAA,EAAQC,iCAAqBtC,OAAO;gBAAEuC,KAAAA,EAAM;AAAe,aAAA,CAAA,GAAA;;;AAGhM;;"}
|
package/dist/cjs/shell/Topbar.js
CHANGED
|
@@ -4,7 +4,9 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
4
4
|
var button = require('primereact/button');
|
|
5
5
|
var LayoutMode = require('../configuration/LayoutMode.js');
|
|
6
6
|
var LayoutConfigProvider = require('../configuration/LayoutConfigProvider.js');
|
|
7
|
+
var scene_model = require('@cratis/scene.model');
|
|
7
8
|
var elementProperties = require('./elementProperties.js');
|
|
9
|
+
var RegionNavigation = require('./RegionNavigation.js');
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* The fixed strip across the top of the application shell.
|
|
@@ -13,11 +15,15 @@ var elementProperties = require('./elementProperties.js');
|
|
|
13
15
|
* menu itself, which is why the menu arrives here as a slot rather than being hard-wired into the
|
|
14
16
|
* sidebar - the same navigation markup has to be able to render in two places.
|
|
15
17
|
*
|
|
18
|
+
* When the application supplies a navigation model and the topbar has no `menu` slot of its own, the menu is the effective
|
|
19
|
+
* navigation of the topbar region for the module on the page (set `regionNavigation` to false to opt out).
|
|
20
|
+
*
|
|
16
21
|
* The toggle hides itself in the rail modes, where there is nothing to toggle: `slim`, `slim-plus` and
|
|
17
22
|
* `compact` are always showing, `reveal` and `drawer` answer to the pointer and the pin, and `horizontal`
|
|
18
23
|
* has no sidebar at all. A button that does nothing is worse than no button.
|
|
19
24
|
*/ function Topbar({ element, slots }) {
|
|
20
25
|
const { effectiveMode, config, toggleSidebar } = LayoutConfigProvider.useLayoutConfig();
|
|
26
|
+
const hasRegion = RegionNavigation.useHasRegionNavigation();
|
|
21
27
|
const showsToggle = elementProperties.readBoolean(element, 'showToggle', true) && togglesSidebar(effectiveMode);
|
|
22
28
|
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
23
29
|
children: [
|
|
@@ -42,7 +48,10 @@ var elementProperties = require('./elementProperties.js');
|
|
|
42
48
|
slots.start
|
|
43
49
|
]
|
|
44
50
|
}),
|
|
45
|
-
slots.menu,
|
|
51
|
+
slots.menu?.length ? slots.menu : hasRegion && elementProperties.readBoolean(element, 'regionNavigation', true) ? /*#__PURE__*/ jsxRuntime.jsx(RegionNavigation.RegionNavigation, {
|
|
52
|
+
region: scene_model.NavigationRegionKind.Topbar,
|
|
53
|
+
label: "Modules"
|
|
54
|
+
}) : null,
|
|
46
55
|
/*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
47
56
|
className: "layout-topbar-end",
|
|
48
57
|
children: slots.end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Topbar.js","sources":["../../../shell/Topbar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Button } from 'primereact/button';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { LayoutMode, useLayoutConfig } from '../configuration';\nimport { readBoolean } from './elementProperties';\n\n/**\n * The fixed strip across the top of the application shell.\n *\n * It owns the one control every mode needs: the sidebar toggle. In `horizontal` mode it also hosts the\n * menu itself, which is why the menu arrives here as a slot rather than being hard-wired into the\n * sidebar - the same navigation markup has to be able to render in two places.\n *\n * The toggle hides itself in the rail modes, where there is nothing to toggle: `slim`, `slim-plus` and\n * `compact` are always showing, `reveal` and `drawer` answer to the pointer and the pin, and `horizontal`\n * has no sidebar at all. A button that does nothing is worse than no button.\n */\nexport function Topbar({ element, slots }: RegisteredComponentProps) {\n const { effectiveMode, config, toggleSidebar } = useLayoutConfig();\n const showsToggle = readBoolean(element, 'showToggle', true) && togglesSidebar(effectiveMode);\n\n return (\n <>\n <div className='layout-topbar-start' data-scene-id={element.id}>\n {showsToggle && (\n <Button\n type='button'\n variant='text'\n rounded\n iconOnly\n aria-label={config.isSidebarOpen ? 'Close the menu' : 'Open the menu'}\n aria-expanded={config.isSidebarOpen}\n onClick={toggleSidebar}>\n <i className='pi pi-bars' aria-hidden='true' />\n </Button>\n )}\n {slots.logo}\n {slots.start}\n </div>\n {slots.menu}\n <div className='layout-topbar-end'>{slots.end}</div>\n </>\n );\n}\n\nfunction togglesSidebar(mode: LayoutMode): boolean {\n return mode === LayoutMode.Static || mode === LayoutMode.Overlay;\n}\n"],"names":["Topbar","element","slots","effectiveMode","config","toggleSidebar","useLayoutConfig","showsToggle","readBoolean","togglesSidebar","_jsxs","_Fragment","div","className","data-scene-id","id","_jsx","Button","type","variant","rounded","iconOnly","aria-label","isSidebarOpen","aria-expanded","onClick","i","aria-hidden","logo","start","menu","end","mode","LayoutMode","Static","Overlay"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Topbar.js","sources":["../../../shell/Topbar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Button } from 'primereact/button';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { LayoutMode, useLayoutConfig } from '../configuration';\nimport { NavigationRegionKind } from '@cratis/scene.model';\nimport { readBoolean } from './elementProperties';\nimport { RegionNavigation, useHasRegionNavigation } from './RegionNavigation';\n\n/**\n * The fixed strip across the top of the application shell.\n *\n * It owns the one control every mode needs: the sidebar toggle. In `horizontal` mode it also hosts the\n * menu itself, which is why the menu arrives here as a slot rather than being hard-wired into the\n * sidebar - the same navigation markup has to be able to render in two places.\n *\n * When the application supplies a navigation model and the topbar has no `menu` slot of its own, the menu is the effective\n * navigation of the topbar region for the module on the page (set `regionNavigation` to false to opt out).\n *\n * The toggle hides itself in the rail modes, where there is nothing to toggle: `slim`, `slim-plus` and\n * `compact` are always showing, `reveal` and `drawer` answer to the pointer and the pin, and `horizontal`\n * has no sidebar at all. A button that does nothing is worse than no button.\n */\nexport function Topbar({ element, slots }: RegisteredComponentProps) {\n const { effectiveMode, config, toggleSidebar } = useLayoutConfig();\n const hasRegion = useHasRegionNavigation();\n const showsToggle = readBoolean(element, 'showToggle', true) && togglesSidebar(effectiveMode);\n\n return (\n <>\n <div className='layout-topbar-start' data-scene-id={element.id}>\n {showsToggle && (\n <Button\n type='button'\n variant='text'\n rounded\n iconOnly\n aria-label={config.isSidebarOpen ? 'Close the menu' : 'Open the menu'}\n aria-expanded={config.isSidebarOpen}\n onClick={toggleSidebar}>\n <i className='pi pi-bars' aria-hidden='true' />\n </Button>\n )}\n {slots.logo}\n {slots.start}\n </div>\n {slots.menu?.length ? slots.menu : hasRegion && readBoolean(element, 'regionNavigation', true) ? <RegionNavigation region={NavigationRegionKind.Topbar} label='Modules' /> : null}\n <div className='layout-topbar-end'>{slots.end}</div>\n </>\n );\n}\n\nfunction togglesSidebar(mode: LayoutMode): boolean {\n return mode === LayoutMode.Static || mode === LayoutMode.Overlay;\n}\n"],"names":["Topbar","element","slots","effectiveMode","config","toggleSidebar","useLayoutConfig","hasRegion","useHasRegionNavigation","showsToggle","readBoolean","togglesSidebar","_jsxs","_Fragment","div","className","data-scene-id","id","_jsx","Button","type","variant","rounded","iconOnly","aria-label","isSidebarOpen","aria-expanded","onClick","i","aria-hidden","logo","start","menu","length","RegionNavigation","region","NavigationRegionKind","label","end","mode","LayoutMode","Static","Overlay"],"mappings":";;;;;;;;;;AAUA;;;;;;;;;;;;;AAaC,IACM,SAASA,MAAAA,CAAO,EAAEC,OAAO,EAAEC,KAAK,EAA4B,EAAA;AAC/D,IAAA,MAAM,EAAEC,aAAa,EAAEC,MAAM,EAAEC,aAAa,EAAE,GAAGC,oCAAAA,EAAAA;AACjD,IAAA,MAAMC,SAAAA,GAAYC,uCAAAA,EAAAA;AAClB,IAAA,MAAMC,WAAAA,GAAcC,6BAAAA,CAAYT,OAAAA,EAAS,YAAA,EAAc,SAASU,cAAAA,CAAeR,aAAAA,CAAAA;IAE/E,qBACIS,eAAA,CAAAC,mBAAA,EAAA;;0BACID,eAAA,CAACE,KAAAA,EAAAA;gBAAIC,SAAAA,EAAU,qBAAA;AAAsBC,gBAAAA,eAAAA,EAAef,QAAQgB,EAAE;;AACzDR,oBAAAA,WAAAA,kBACGS,cAAA,CAACC,aAAAA,EAAAA;wBACGC,IAAAA,EAAK,QAAA;wBACLC,OAAAA,EAAQ,MAAA;wBACRC,OAAO,EAAA,IAAA;wBACPC,QAAQ,EAAA,IAAA;wBACRC,YAAAA,EAAYpB,MAAAA,CAAOqB,aAAa,GAAG,gBAAA,GAAmB,eAAA;AACtDC,wBAAAA,eAAAA,EAAetB,OAAOqB,aAAa;wBACnCE,OAAAA,EAAStB,aAAAA;AACT,wBAAA,QAAA,gBAAAa,cAAA,CAACU,GAAAA,EAAAA;4BAAEb,SAAAA,EAAU,YAAA;4BAAac,aAAAA,EAAY;;;AAG7C3B,oBAAAA,KAAAA,CAAM4B,IAAI;AACV5B,oBAAAA,KAAAA,CAAM6B;;;YAEV7B,KAAAA,CAAM8B,IAAI,EAAEC,MAAAA,GAAS/B,KAAAA,CAAM8B,IAAI,GAAGzB,SAAAA,IAAaG,6BAAAA,CAAYT,OAAAA,EAAS,kBAAA,EAAoB,IAAA,CAAA,iBAAQiB,cAAA,CAACgB,iCAAAA,EAAAA;AAAiBC,gBAAAA,MAAAA,EAAQC,iCAAqBpC,MAAM;gBAAEqC,KAAAA,EAAM;AAAe,aAAA,CAAA,GAAA,IAAA;0BAC7KnB,cAAA,CAACJ,KAAAA,EAAAA;gBAAIC,SAAAA,EAAU,mBAAA;AAAqBb,gBAAAA,QAAAA,EAAAA,KAAAA,CAAMoC;;;;AAGtD;AAEA,SAAS3B,eAAe4B,IAAgB,EAAA;AACpC,IAAA,OAAOA,SAASC,qBAAAA,CAAWC,MAAM,IAAIF,IAAAA,KAASC,sBAAWE,OAAO;AACpE;;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { NavigationRegionKind } from '@cratis/scene.model';
|
|
2
|
+
export declare function useHasRegionNavigation(): boolean;
|
|
3
|
+
export declare function RegionNavigation({ region, label }: {
|
|
4
|
+
region: NavigationRegionKind;
|
|
5
|
+
label?: string;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=RegionNavigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegionNavigation.d.ts","sourceRoot":"","sources":["../../../shell/RegionNavigation.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAgB3D,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAOD,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BAEnG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useSceneNavigationModel, NavigationRegionView } from '@cratis/scene.react';
|
|
3
|
+
|
|
4
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
5
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
6
|
+
/** The `layout-menu` vocabulary the shell's stylesheet already styles, so a region looks like the menu it replaces. */ const classNames = {
|
|
7
|
+
root: 'layout-region',
|
|
8
|
+
list: 'layout-menu',
|
|
9
|
+
item: 'layout-menu-item',
|
|
10
|
+
link: 'layout-menu-link',
|
|
11
|
+
icon: 'layout-menu-icon',
|
|
12
|
+
label: 'layout-menu-label',
|
|
13
|
+
toggle: 'layout-menu-toggle',
|
|
14
|
+
submenu: 'layout-submenu'
|
|
15
|
+
};
|
|
16
|
+
/** Whether a navigation model is in scope, so the topbar and sidebar have a region to show. */ function useHasRegionNavigation() {
|
|
17
|
+
return useSceneNavigationModel() !== undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The navigation a shell's topbar or sidebar shows when the application supplies a navigation model: the effective items of
|
|
21
|
+
* its region - inherit/extend/override already applied - as the shell's menu, with the active item, the hierarchy and
|
|
22
|
+
* the keyboard behaviour of `NavigationRegionView`.
|
|
23
|
+
*/ function RegionNavigation({ region, label }) {
|
|
24
|
+
return /*#__PURE__*/ jsx(NavigationRegionView, {
|
|
25
|
+
region: region,
|
|
26
|
+
label: label,
|
|
27
|
+
classNames: {
|
|
28
|
+
...classNames,
|
|
29
|
+
root: `layout-region layout-region-${region}`
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { RegionNavigation, useHasRegionNavigation };
|
|
35
|
+
//# sourceMappingURL=RegionNavigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegionNavigation.js","sources":["../../../shell/RegionNavigation.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { NavigationRegionKind } from '@cratis/scene.model';\nimport { NavigationRegionClassNames, NavigationRegionView, useSceneNavigationModel } from '@cratis/scene.react';\n\n/** The `layout-menu` vocabulary the shell's stylesheet already styles, so a region looks like the menu it replaces. */\nconst classNames: Partial<NavigationRegionClassNames> = {\n root: 'layout-region',\n list: 'layout-menu',\n item: 'layout-menu-item',\n link: 'layout-menu-link',\n icon: 'layout-menu-icon',\n label: 'layout-menu-label',\n toggle: 'layout-menu-toggle',\n submenu: 'layout-submenu',\n};\n\n/** Whether a navigation model is in scope, so the topbar and sidebar have a region to show. */\nexport function useHasRegionNavigation(): boolean {\n return useSceneNavigationModel() !== undefined;\n}\n\n/**\n * The navigation a shell's topbar or sidebar shows when the application supplies a navigation model: the effective items of\n * its region - inherit/extend/override already applied - as the shell's menu, with the active item, the hierarchy and\n * the keyboard behaviour of `NavigationRegionView`.\n */\nexport function RegionNavigation({ region, label }: { region: NavigationRegionKind; label?: string }) {\n return <NavigationRegionView region={region} label={label} classNames={{ ...classNames, root: `layout-region layout-region-${region}` }} />;\n}\n"],"names":["classNames","root","list","item","link","icon","label","toggle","submenu","useHasRegionNavigation","useSceneNavigationModel","undefined","RegionNavigation","region","_jsx","NavigationRegionView"],"mappings":";;;AAAA;AACA;AAKA,wHACA,MAAMA,UAAAA,GAAkD;IACpDC,IAAAA,EAAM,eAAA;IACNC,IAAAA,EAAM,aAAA;IACNC,IAAAA,EAAM,kBAAA;IACNC,IAAAA,EAAM,kBAAA;IACNC,IAAAA,EAAM,kBAAA;IACNC,KAAAA,EAAO,mBAAA;IACPC,MAAAA,EAAQ,oBAAA;IACRC,OAAAA,EAAS;AACb,CAAA;AAEA,gGACO,SAASC,sBAAAA,GAAAA;AACZ,IAAA,OAAOC,uBAAAA,EAAAA,KAA8BC,SAAAA;AACzC;AAEA;;;;AAIC,IACM,SAASC,gBAAAA,CAAiB,EAAEC,MAAM,EAAEP,KAAK,EAAoD,EAAA;AAChG,IAAA,qBAAOQ,GAAA,CAACC,oBAAAA,EAAAA;QAAqBF,MAAAA,EAAQA,MAAAA;QAAQP,KAAAA,EAAOA,KAAAA;QAAON,UAAAA,EAAY;AAAE,YAAA,GAAGA,UAAU;YAAEC,IAAAA,EAAM,CAAC,4BAA4B,EAAEY,MAAAA,CAAAA;AAAS;;AAC1I;;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/react';
|
|
2
|
+
declare function Application({ initialScreen }: {
|
|
3
|
+
initialScreen: string;
|
|
4
|
+
}): import("react").JSX.Element;
|
|
5
|
+
declare const meta: {
|
|
6
|
+
title: string;
|
|
7
|
+
component: typeof Application;
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof meta>;
|
|
14
|
+
export declare const HierarchicalSidebar: Story;
|
|
15
|
+
export declare const TwoSlots: Story;
|
|
16
|
+
//# sourceMappingURL=RegionNavigation.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegionNavigation.stories.d.ts","sourceRoot":"","sources":["../../../shell/RegionNavigation.stories.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AA0DvD,iBAAS,WAAW,CAAC,EAAE,aAAa,EAAE,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,+BAUhE;AAMD,QAAA,MAAM,IAAI;;;;QAGQ,MAAM;;CACY,CAAC;eAEtB,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAGnC,eAAO,MAAM,mBAAmB,EAAE,KAAmD,CAAC;AAGtF,eAAO,MAAM,QAAQ,EAAE,KAOtB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { expect, userEvent, within } from 'storybook/test';
|
|
3
|
+
import { PrimeReactProvider } from '@primereact/core';
|
|
4
|
+
import { NavigationRegionKind, NavigationRegionMode, Visibility } from '@cratis/scene.model';
|
|
5
|
+
import { ApplicationStructureIndex } from '@cratis/scene.engine';
|
|
6
|
+
import { CoreOutlet, SceneNavigationHost } from '@cratis/scene.react';
|
|
7
|
+
import { LayoutConfigProvider } from '../configuration';
|
|
8
|
+
import { Sidebar } from './Sidebar';
|
|
9
|
+
import { Topbar } from './Topbar';
|
|
10
|
+
const structure = {
|
|
11
|
+
modules: [
|
|
12
|
+
{ id: 'dashboard', name: 'Dashboard', features: [{ id: 'overview', name: 'Overview', features: [], slices: [] }] },
|
|
13
|
+
{ id: 'sales', name: 'Sales', features: [{ id: 'orders', name: 'Orders', features: [{ id: 'returns', name: 'Returns', features: [], slices: [] }], slices: [] }, { id: 'customers', name: 'Customers', features: [], slices: [] }] },
|
|
14
|
+
{ id: 'support', name: 'Support', features: [{ id: 'tickets', name: 'Tickets', features: [], slices: [] }, { id: 'kb', name: 'Knowledge base', features: [], slices: [] }] },
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
const navigation = {
|
|
18
|
+
application: { regions: [
|
|
19
|
+
{ region: NavigationRegionKind.Topbar, items: [
|
|
20
|
+
{ id: 'dashboard', title: 'Dashboard', target: { module: 'dashboard' } },
|
|
21
|
+
{ id: 'sales', title: 'Sales', target: { module: 'sales' } },
|
|
22
|
+
{ id: 'support', title: 'Support', target: { module: 'support' } },
|
|
23
|
+
] },
|
|
24
|
+
{ region: NavigationRegionKind.Sidebar, items: [{ id: 'dashboard', title: 'Dashboard', target: { module: 'dashboard', feature: 'overview' } }] },
|
|
25
|
+
] },
|
|
26
|
+
modules: [
|
|
27
|
+
{ module: 'sales', regions: [{ region: NavigationRegionKind.Sidebar, mode: NavigationRegionMode.Override, items: [
|
|
28
|
+
{ id: 'orders', title: 'Orders', target: { module: 'sales', feature: 'orders' }, children: [{ id: 'returns', title: 'Returns', target: { module: 'sales', feature: 'orders.returns' } }] },
|
|
29
|
+
{ id: 'customers', title: 'Customers', target: { module: 'sales', feature: 'customers' } },
|
|
30
|
+
] }] },
|
|
31
|
+
{ module: 'support', regions: [
|
|
32
|
+
{ region: NavigationRegionKind.Topbar, mode: NavigationRegionMode.Extend, items: [{ id: 'help', title: 'Help center', target: { module: 'support', feature: 'kb' }, slot: 'side' }] },
|
|
33
|
+
{ region: NavigationRegionKind.Sidebar, mode: NavigationRegionMode.Override, items: [
|
|
34
|
+
{ id: 'tickets', title: 'Tickets', target: { module: 'support', feature: 'tickets' } },
|
|
35
|
+
{ id: 'kb', title: 'Knowledge base', target: { module: 'support', feature: 'kb' }, slot: 'side' },
|
|
36
|
+
] },
|
|
37
|
+
] },
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
const element = (id, componentName, properties = {}, content = []) => ({ id, componentName, properties, slots: content.length > 0 ? { content } : {}, visibility: Visibility.Visible });
|
|
41
|
+
function Page({ element: page, slots }) {
|
|
42
|
+
return _jsxs("section", { style: { padding: '1rem' }, children: [_jsx("h2", { children: page.id }), slots.content] });
|
|
43
|
+
}
|
|
44
|
+
const screens = {
|
|
45
|
+
'dashboard.overview': element('dashboard.overview', 'story:page'),
|
|
46
|
+
'sales.orders': element('sales.orders', 'story:page'),
|
|
47
|
+
'sales.orders.returns': element('sales.orders.returns', 'story:page'),
|
|
48
|
+
'sales.customers': element('sales.customers', 'story:page'),
|
|
49
|
+
'support.tickets': element('support.tickets', 'story:page', {}, [element('side', 'core:outlet', { name: 'side' })]),
|
|
50
|
+
'support.kb': element('support.kb', 'story:page'),
|
|
51
|
+
};
|
|
52
|
+
function Application({ initialScreen }) {
|
|
53
|
+
return _jsx(PrimeReactProvider, { children: _jsx(LayoutConfigProvider, { children: _jsx(SceneNavigationHost, { screens: screens, initialScreen: initialScreen, registry: { 'story:page': Page, 'core:outlet': CoreOutlet }, navigationModel: { structure: new ApplicationStructureIndex(structure), navigation }, frame: content => _jsxs("div", { className: 'layout-wrapper layout-static', children: [_jsx("div", { className: 'layout-topbar', children: _jsx(Topbar, { element: element('topbar', 'topbar'), slots: {} }) }), _jsx("div", { className: 'layout-sidebar', children: _jsx(Sidebar, { element: element('sidebar', 'sidebar'), slots: {} }) }), _jsx("div", { className: 'layout-content-wrapper', children: content })] }) }) }) });
|
|
54
|
+
}
|
|
55
|
+
const meta = {
|
|
56
|
+
title: 'Blueprint/Navigation regions',
|
|
57
|
+
component: Application,
|
|
58
|
+
parameters: { layout: 'fullscreen' },
|
|
59
|
+
};
|
|
60
|
+
export default meta;
|
|
61
|
+
export const HierarchicalSidebar = { args: { initialScreen: 'sales.orders' } };
|
|
62
|
+
export const TwoSlots = {
|
|
63
|
+
args: { initialScreen: 'support.tickets' },
|
|
64
|
+
play: async ({ canvasElement }) => {
|
|
65
|
+
const canvas = within(canvasElement);
|
|
66
|
+
await userEvent.click(canvas.getByRole('link', { name: 'Knowledge base' }));
|
|
67
|
+
await expect(canvasElement.querySelectorAll('.layout-region-sidebar [data-active="true"]').length).toBe(2);
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=RegionNavigation.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegionNavigation.stories.js","sourceRoot":"","sources":["../../../shell/RegionNavigation.stories.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../shell/Sidebar.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../shell/Sidebar.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAoB/D,wBAAgB,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,wBAAwB,+BA2BnE"}
|
|
@@ -2,7 +2,9 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { Button } from 'primereact/button';
|
|
3
3
|
import { isPointerRevealMode } from '../configuration/layoutConfigTransitions.js';
|
|
4
4
|
import { useLayoutConfig } from '../configuration/LayoutConfigProvider.js';
|
|
5
|
-
import {
|
|
5
|
+
import { NavigationRegionKind } from '@cratis/scene.model';
|
|
6
|
+
import { readString, readBoolean } from './elementProperties.js';
|
|
7
|
+
import { useHasRegionNavigation, RegionNavigation } from './RegionNavigation.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* The sidebar's own chrome, inside the panel {@link AppShell} positions.
|
|
@@ -12,10 +14,14 @@ import { readString } from './elementProperties.js';
|
|
|
12
14
|
* the shell; everything about *what is in it* belongs to the screen. A template can replace this header
|
|
13
15
|
* wholesale without any of the mode CSS noticing.
|
|
14
16
|
*
|
|
17
|
+
* When the application supplies a navigation model and the sidebar has no `content` of its own, the content is the effective
|
|
18
|
+
* navigation of the sidebar region for the module on the page (set `regionNavigation` to false to opt out).
|
|
19
|
+
*
|
|
15
20
|
* The pin button only appears in `reveal` and `drawer`, the two modes where the sidebar answers to the
|
|
16
21
|
* pointer and therefore needs a way to be made to stay.
|
|
17
22
|
*/ function Sidebar({ element, slots }) {
|
|
18
23
|
const { effectiveMode, config, toggleSidebarAnchor } = useLayoutConfig();
|
|
24
|
+
const hasRegion = useHasRegionNavigation();
|
|
19
25
|
const title = readString(element, 'title');
|
|
20
26
|
const isPinnable = isPointerRevealMode(effectiveMode);
|
|
21
27
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
@@ -44,7 +50,10 @@ import { readString } from './elementProperties.js';
|
|
|
44
50
|
})
|
|
45
51
|
]
|
|
46
52
|
}),
|
|
47
|
-
slots.content
|
|
53
|
+
slots.content?.length ? slots.content : hasRegion && readBoolean(element, 'regionNavigation', true) ? /*#__PURE__*/ jsx(RegionNavigation, {
|
|
54
|
+
region: NavigationRegionKind.Sidebar,
|
|
55
|
+
label: "Sidebar"
|
|
56
|
+
}) : null
|
|
48
57
|
]
|
|
49
58
|
});
|
|
50
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.js","sources":["../../../shell/Sidebar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Button } from 'primereact/button';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { isPointerRevealMode, useLayoutConfig } from '../configuration';\nimport { readString } from './elementProperties';\n\n/**\n * The sidebar's own chrome, inside the panel {@link AppShell} positions.\n *\n * The panel and its contents are deliberately different components. Everything about *where* the sidebar\n * is - translated off-canvas, collapsed to a rail, growing on hover - belongs to the mode and therefore to\n * the shell; everything about *what is in it* belongs to the screen. A template can replace this header\n * wholesale without any of the mode CSS noticing.\n *\n * The pin button only appears in `reveal` and `drawer`, the two modes where the sidebar answers to the\n * pointer and therefore needs a way to be made to stay.\n */\nexport function Sidebar({ element, slots }: RegisteredComponentProps) {\n const { effectiveMode, config, toggleSidebarAnchor } = useLayoutConfig();\n const title = readString(element, 'title');\n const isPinnable = isPointerRevealMode(effectiveMode);\n\n return (\n <>\n <div className='layout-sidebar-header' data-scene-id={element.id}>\n {slots.logo}\n {title && <span className='layout-sidebar-title'>{title}</span>}\n {isPinnable && (\n <Button\n type='button'\n variant='text'\n rounded\n iconOnly\n aria-label={config.isSidebarAnchored ? 'Unpin the menu' : 'Pin the menu open'}\n aria-pressed={config.isSidebarAnchored}\n onClick={toggleSidebarAnchor}>\n <i className={config.isSidebarAnchored ? 'pi pi-lock' : 'pi pi-lock-open'} aria-hidden='true' />\n </Button>\n )}\n </div>\n {slots.content}\n </>\n );\n}\n"],"names":["Sidebar","element","slots","effectiveMode","config","toggleSidebarAnchor","useLayoutConfig","title","readString","isPinnable","isPointerRevealMode","_jsxs","_Fragment","div","className","data-scene-id","id","logo","_jsx","span","Button","type","variant","rounded","iconOnly","aria-label","isSidebarAnchored","aria-pressed","onClick","i","aria-hidden","content"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Sidebar.js","sources":["../../../shell/Sidebar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Button } from 'primereact/button';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { isPointerRevealMode, useLayoutConfig } from '../configuration';\nimport { NavigationRegionKind } from '@cratis/scene.model';\nimport { readBoolean, readString } from './elementProperties';\nimport { RegionNavigation, useHasRegionNavigation } from './RegionNavigation';\n\n/**\n * The sidebar's own chrome, inside the panel {@link AppShell} positions.\n *\n * The panel and its contents are deliberately different components. Everything about *where* the sidebar\n * is - translated off-canvas, collapsed to a rail, growing on hover - belongs to the mode and therefore to\n * the shell; everything about *what is in it* belongs to the screen. A template can replace this header\n * wholesale without any of the mode CSS noticing.\n *\n * When the application supplies a navigation model and the sidebar has no `content` of its own, the content is the effective\n * navigation of the sidebar region for the module on the page (set `regionNavigation` to false to opt out).\n *\n * The pin button only appears in `reveal` and `drawer`, the two modes where the sidebar answers to the\n * pointer and therefore needs a way to be made to stay.\n */\nexport function Sidebar({ element, slots }: RegisteredComponentProps) {\n const { effectiveMode, config, toggleSidebarAnchor } = useLayoutConfig();\n const hasRegion = useHasRegionNavigation();\n const title = readString(element, 'title');\n const isPinnable = isPointerRevealMode(effectiveMode);\n\n return (\n <>\n <div className='layout-sidebar-header' data-scene-id={element.id}>\n {slots.logo}\n {title && <span className='layout-sidebar-title'>{title}</span>}\n {isPinnable && (\n <Button\n type='button'\n variant='text'\n rounded\n iconOnly\n aria-label={config.isSidebarAnchored ? 'Unpin the menu' : 'Pin the menu open'}\n aria-pressed={config.isSidebarAnchored}\n onClick={toggleSidebarAnchor}>\n <i className={config.isSidebarAnchored ? 'pi pi-lock' : 'pi pi-lock-open'} aria-hidden='true' />\n </Button>\n )}\n </div>\n {slots.content?.length ? slots.content : hasRegion && readBoolean(element, 'regionNavigation', true) ? <RegionNavigation region={NavigationRegionKind.Sidebar} label='Sidebar' /> : null}\n </>\n );\n}\n"],"names":["Sidebar","element","slots","effectiveMode","config","toggleSidebarAnchor","useLayoutConfig","hasRegion","useHasRegionNavigation","title","readString","isPinnable","isPointerRevealMode","_jsxs","_Fragment","div","className","data-scene-id","id","logo","_jsx","span","Button","type","variant","rounded","iconOnly","aria-label","isSidebarAnchored","aria-pressed","onClick","i","aria-hidden","content","length","readBoolean","RegionNavigation","region","NavigationRegionKind","label"],"mappings":";;;;;;;;AAUA;;;;;;;;;;;;;AAaC,IACM,SAASA,OAAAA,CAAQ,EAAEC,OAAO,EAAEC,KAAK,EAA4B,EAAA;AAChE,IAAA,MAAM,EAAEC,aAAa,EAAEC,MAAM,EAAEC,mBAAmB,EAAE,GAAGC,eAAAA,EAAAA;AACvD,IAAA,MAAMC,SAAAA,GAAYC,sBAAAA,EAAAA;IAClB,MAAMC,KAAAA,GAAQC,WAAWT,OAAAA,EAAS,OAAA,CAAA;AAClC,IAAA,MAAMU,aAAaC,mBAAAA,CAAoBT,aAAAA,CAAAA;IAEvC,qBACIU,IAAA,CAAAC,QAAA,EAAA;;0BACID,IAAA,CAACE,KAAAA,EAAAA;gBAAIC,SAAAA,EAAU,uBAAA;AAAwBC,gBAAAA,eAAAA,EAAehB,QAAQiB,EAAE;;AAC3DhB,oBAAAA,KAAAA,CAAMiB,IAAI;AACVV,oBAAAA,KAAAA,kBAASW,GAAA,CAACC,MAAAA,EAAAA;wBAAKL,SAAAA,EAAU,sBAAA;AAAwBP,wBAAAA,QAAAA,EAAAA;;AACjDE,oBAAAA,UAAAA,kBACGS,GAAA,CAACE,MAAAA,EAAAA;wBACGC,IAAAA,EAAK,QAAA;wBACLC,OAAAA,EAAQ,MAAA;wBACRC,OAAO,EAAA,IAAA;wBACPC,QAAQ,EAAA,IAAA;wBACRC,YAAAA,EAAYvB,MAAAA,CAAOwB,iBAAiB,GAAG,gBAAA,GAAmB,mBAAA;AAC1DC,wBAAAA,cAAAA,EAAczB,OAAOwB,iBAAiB;wBACtCE,OAAAA,EAASzB,mBAAAA;AACT,wBAAA,QAAA,gBAAAe,GAAA,CAACW,GAAAA,EAAAA;4BAAEf,SAAAA,EAAWZ,MAAAA,CAAOwB,iBAAiB,GAAG,YAAA,GAAe,iBAAA;4BAAmBI,aAAAA,EAAY;;;;;YAIlG9B,KAAAA,CAAM+B,OAAO,EAAEC,MAAAA,GAAShC,KAAAA,CAAM+B,OAAO,GAAG1B,SAAAA,IAAa4B,WAAAA,CAAYlC,OAAAA,EAAS,kBAAA,EAAoB,IAAA,CAAA,iBAAQmB,GAAA,CAACgB,gBAAAA,EAAAA;AAAiBC,gBAAAA,MAAAA,EAAQC,qBAAqBtC,OAAO;gBAAEuC,KAAAA,EAAM;AAAe,aAAA,CAAA,GAAA;;;AAGhM;;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/react';
|
|
2
|
+
declare function OrdersToolbar({ warnEmptySlices }: {
|
|
3
|
+
warnEmptySlices: boolean;
|
|
4
|
+
}): import("react").JSX.Element;
|
|
5
|
+
declare const meta: {
|
|
6
|
+
title: string;
|
|
7
|
+
component: typeof OrdersToolbar;
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof meta>;
|
|
14
|
+
export declare const Running: Story;
|
|
15
|
+
export declare const Designing: Story;
|
|
16
|
+
//# sourceMappingURL=ToolbarSliceDialog.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolbarSliceDialog.stories.d.ts","sourceRoot":"","sources":["../../../shell/ToolbarSliceDialog.stories.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAmBvD,iBAAS,aAAa,CAAC,EAAE,eAAe,EAAE,EAAE;IAAE,eAAe,EAAE,OAAO,CAAA;CAAE,+BAOvE;AAMD,QAAA,MAAM,IAAI;;;;QAGQ,MAAM;;CACc,CAAC;eAExB,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAGnC,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAGF,eAAO,MAAM,SAAS,EAAE,KAA2C,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { expect, userEvent, within } from 'storybook/test';
|
|
3
|
+
import { ApplicationStructureIndex } from '@cratis/scene.engine';
|
|
4
|
+
import { SceneNavigationHost, SliceCommandFieldsProvider, SliceInvokerProvider, coreComponents, createDryRunInvoker } from '@cratis/scene.react';
|
|
5
|
+
const structure = {
|
|
6
|
+
modules: [{ id: 'sales', name: 'Sales', features: [{ id: 'orders', name: 'Orders', features: [], slices: [{ id: 'PlaceOrder', name: 'Place order', kind: 'StateChange', command: 'PlaceOrder' }] }] }],
|
|
7
|
+
};
|
|
8
|
+
const element = (id, componentName, properties = {}, slots = {}) => ({ id, componentName, properties, slots });
|
|
9
|
+
const toolbar = element('toolbar', 'core:toolbar', { name: 'orders' }, { items: [
|
|
10
|
+
element('new', 'core:toolbarItem', { name: 'new', kind: 'Action', label: 'New order', slice: 'sales.orders.PlaceOrder', emphasis: 'primary' }),
|
|
11
|
+
element('cancel', 'core:toolbarItem', { name: 'cancel', kind: 'Action', label: 'Cancel order', slice: 'sales.orders.PlaceOrder', emphasis: 'secondary' }),
|
|
12
|
+
element('more', 'core:toolbarItem', { name: 'more', kind: 'Action', label: 'More', emphasis: 'quiet' }),
|
|
13
|
+
] });
|
|
14
|
+
function OrdersToolbar({ warnEmptySlices }) {
|
|
15
|
+
return _jsx(SliceInvokerProvider, { invoker: createDryRunInvoker({ onInvoked: invocation => console.info('Dry run', invocation) }), warnEmptySlices: warnEmptySlices, children: _jsx(SliceCommandFieldsProvider, { fieldsFor: () => [{ name: 'customer', type: 'string', required: true }, { name: 'product', type: 'string' }, { name: 'quantity', type: 'number' }], children: _jsx(SceneNavigationHost, { screens: { Orders: toolbar }, initialScreen: 'Orders', registry: coreComponents, navigationModel: { structure: new ApplicationStructureIndex(structure), navigation: { application: { regions: [] }, modules: [] } } }) }) });
|
|
16
|
+
}
|
|
17
|
+
const meta = {
|
|
18
|
+
title: 'Blueprint/Toolbar slice dialogs',
|
|
19
|
+
component: OrdersToolbar,
|
|
20
|
+
parameters: { layout: 'padded' },
|
|
21
|
+
};
|
|
22
|
+
export default meta;
|
|
23
|
+
export const Running = {
|
|
24
|
+
args: { warnEmptySlices: false },
|
|
25
|
+
play: async ({ canvasElement }) => {
|
|
26
|
+
await userEvent.click(within(canvasElement).getByRole('button', { name: 'New order' }));
|
|
27
|
+
await expect(await within(document.body).findByRole('dialog', { name: 'New order' })).toBeTruthy();
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
export const Designing = { args: { warnEmptySlices: true } };
|
|
31
|
+
//# sourceMappingURL=ToolbarSliceDialog.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolbarSliceDialog.stories.js","sourceRoot":"","sources":["../../../shell/ToolbarSliceDialog.stories.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Topbar.d.ts","sourceRoot":"","sources":["../../../shell/Topbar.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"Topbar.d.ts","sourceRoot":"","sources":["../../../shell/Topbar.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAoB/D,wBAAgB,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,wBAAwB,+BA2BlE"}
|
package/dist/esm/shell/Topbar.js
CHANGED
|
@@ -2,7 +2,9 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { Button } from 'primereact/button';
|
|
3
3
|
import { LayoutMode } from '../configuration/LayoutMode.js';
|
|
4
4
|
import { useLayoutConfig } from '../configuration/LayoutConfigProvider.js';
|
|
5
|
+
import { NavigationRegionKind } from '@cratis/scene.model';
|
|
5
6
|
import { readBoolean } from './elementProperties.js';
|
|
7
|
+
import { useHasRegionNavigation, RegionNavigation } from './RegionNavigation.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* The fixed strip across the top of the application shell.
|
|
@@ -11,11 +13,15 @@ import { readBoolean } from './elementProperties.js';
|
|
|
11
13
|
* menu itself, which is why the menu arrives here as a slot rather than being hard-wired into the
|
|
12
14
|
* sidebar - the same navigation markup has to be able to render in two places.
|
|
13
15
|
*
|
|
16
|
+
* When the application supplies a navigation model and the topbar has no `menu` slot of its own, the menu is the effective
|
|
17
|
+
* navigation of the topbar region for the module on the page (set `regionNavigation` to false to opt out).
|
|
18
|
+
*
|
|
14
19
|
* The toggle hides itself in the rail modes, where there is nothing to toggle: `slim`, `slim-plus` and
|
|
15
20
|
* `compact` are always showing, `reveal` and `drawer` answer to the pointer and the pin, and `horizontal`
|
|
16
21
|
* has no sidebar at all. A button that does nothing is worse than no button.
|
|
17
22
|
*/ function Topbar({ element, slots }) {
|
|
18
23
|
const { effectiveMode, config, toggleSidebar } = useLayoutConfig();
|
|
24
|
+
const hasRegion = useHasRegionNavigation();
|
|
19
25
|
const showsToggle = readBoolean(element, 'showToggle', true) && togglesSidebar(effectiveMode);
|
|
20
26
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
21
27
|
children: [
|
|
@@ -40,7 +46,10 @@ import { readBoolean } from './elementProperties.js';
|
|
|
40
46
|
slots.start
|
|
41
47
|
]
|
|
42
48
|
}),
|
|
43
|
-
slots.menu,
|
|
49
|
+
slots.menu?.length ? slots.menu : hasRegion && readBoolean(element, 'regionNavigation', true) ? /*#__PURE__*/ jsx(RegionNavigation, {
|
|
50
|
+
region: NavigationRegionKind.Topbar,
|
|
51
|
+
label: "Modules"
|
|
52
|
+
}) : null,
|
|
44
53
|
/*#__PURE__*/ jsx("div", {
|
|
45
54
|
className: "layout-topbar-end",
|
|
46
55
|
children: slots.end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Topbar.js","sources":["../../../shell/Topbar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Button } from 'primereact/button';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { LayoutMode, useLayoutConfig } from '../configuration';\nimport { readBoolean } from './elementProperties';\n\n/**\n * The fixed strip across the top of the application shell.\n *\n * It owns the one control every mode needs: the sidebar toggle. In `horizontal` mode it also hosts the\n * menu itself, which is why the menu arrives here as a slot rather than being hard-wired into the\n * sidebar - the same navigation markup has to be able to render in two places.\n *\n * The toggle hides itself in the rail modes, where there is nothing to toggle: `slim`, `slim-plus` and\n * `compact` are always showing, `reveal` and `drawer` answer to the pointer and the pin, and `horizontal`\n * has no sidebar at all. A button that does nothing is worse than no button.\n */\nexport function Topbar({ element, slots }: RegisteredComponentProps) {\n const { effectiveMode, config, toggleSidebar } = useLayoutConfig();\n const showsToggle = readBoolean(element, 'showToggle', true) && togglesSidebar(effectiveMode);\n\n return (\n <>\n <div className='layout-topbar-start' data-scene-id={element.id}>\n {showsToggle && (\n <Button\n type='button'\n variant='text'\n rounded\n iconOnly\n aria-label={config.isSidebarOpen ? 'Close the menu' : 'Open the menu'}\n aria-expanded={config.isSidebarOpen}\n onClick={toggleSidebar}>\n <i className='pi pi-bars' aria-hidden='true' />\n </Button>\n )}\n {slots.logo}\n {slots.start}\n </div>\n {slots.menu}\n <div className='layout-topbar-end'>{slots.end}</div>\n </>\n );\n}\n\nfunction togglesSidebar(mode: LayoutMode): boolean {\n return mode === LayoutMode.Static || mode === LayoutMode.Overlay;\n}\n"],"names":["Topbar","element","slots","effectiveMode","config","toggleSidebar","useLayoutConfig","showsToggle","readBoolean","togglesSidebar","_jsxs","_Fragment","div","className","data-scene-id","id","_jsx","Button","type","variant","rounded","iconOnly","aria-label","isSidebarOpen","aria-expanded","onClick","i","aria-hidden","logo","start","menu","end","mode","LayoutMode","Static","Overlay"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Topbar.js","sources":["../../../shell/Topbar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Button } from 'primereact/button';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { LayoutMode, useLayoutConfig } from '../configuration';\nimport { NavigationRegionKind } from '@cratis/scene.model';\nimport { readBoolean } from './elementProperties';\nimport { RegionNavigation, useHasRegionNavigation } from './RegionNavigation';\n\n/**\n * The fixed strip across the top of the application shell.\n *\n * It owns the one control every mode needs: the sidebar toggle. In `horizontal` mode it also hosts the\n * menu itself, which is why the menu arrives here as a slot rather than being hard-wired into the\n * sidebar - the same navigation markup has to be able to render in two places.\n *\n * When the application supplies a navigation model and the topbar has no `menu` slot of its own, the menu is the effective\n * navigation of the topbar region for the module on the page (set `regionNavigation` to false to opt out).\n *\n * The toggle hides itself in the rail modes, where there is nothing to toggle: `slim`, `slim-plus` and\n * `compact` are always showing, `reveal` and `drawer` answer to the pointer and the pin, and `horizontal`\n * has no sidebar at all. A button that does nothing is worse than no button.\n */\nexport function Topbar({ element, slots }: RegisteredComponentProps) {\n const { effectiveMode, config, toggleSidebar } = useLayoutConfig();\n const hasRegion = useHasRegionNavigation();\n const showsToggle = readBoolean(element, 'showToggle', true) && togglesSidebar(effectiveMode);\n\n return (\n <>\n <div className='layout-topbar-start' data-scene-id={element.id}>\n {showsToggle && (\n <Button\n type='button'\n variant='text'\n rounded\n iconOnly\n aria-label={config.isSidebarOpen ? 'Close the menu' : 'Open the menu'}\n aria-expanded={config.isSidebarOpen}\n onClick={toggleSidebar}>\n <i className='pi pi-bars' aria-hidden='true' />\n </Button>\n )}\n {slots.logo}\n {slots.start}\n </div>\n {slots.menu?.length ? slots.menu : hasRegion && readBoolean(element, 'regionNavigation', true) ? <RegionNavigation region={NavigationRegionKind.Topbar} label='Modules' /> : null}\n <div className='layout-topbar-end'>{slots.end}</div>\n </>\n );\n}\n\nfunction togglesSidebar(mode: LayoutMode): boolean {\n return mode === LayoutMode.Static || mode === LayoutMode.Overlay;\n}\n"],"names":["Topbar","element","slots","effectiveMode","config","toggleSidebar","useLayoutConfig","hasRegion","useHasRegionNavigation","showsToggle","readBoolean","togglesSidebar","_jsxs","_Fragment","div","className","data-scene-id","id","_jsx","Button","type","variant","rounded","iconOnly","aria-label","isSidebarOpen","aria-expanded","onClick","i","aria-hidden","logo","start","menu","length","RegionNavigation","region","NavigationRegionKind","label","end","mode","LayoutMode","Static","Overlay"],"mappings":";;;;;;;;AAUA;;;;;;;;;;;;;AAaC,IACM,SAASA,MAAAA,CAAO,EAAEC,OAAO,EAAEC,KAAK,EAA4B,EAAA;AAC/D,IAAA,MAAM,EAAEC,aAAa,EAAEC,MAAM,EAAEC,aAAa,EAAE,GAAGC,eAAAA,EAAAA;AACjD,IAAA,MAAMC,SAAAA,GAAYC,sBAAAA,EAAAA;AAClB,IAAA,MAAMC,WAAAA,GAAcC,WAAAA,CAAYT,OAAAA,EAAS,YAAA,EAAc,SAASU,cAAAA,CAAeR,aAAAA,CAAAA;IAE/E,qBACIS,IAAA,CAAAC,QAAA,EAAA;;0BACID,IAAA,CAACE,KAAAA,EAAAA;gBAAIC,SAAAA,EAAU,qBAAA;AAAsBC,gBAAAA,eAAAA,EAAef,QAAQgB,EAAE;;AACzDR,oBAAAA,WAAAA,kBACGS,GAAA,CAACC,MAAAA,EAAAA;wBACGC,IAAAA,EAAK,QAAA;wBACLC,OAAAA,EAAQ,MAAA;wBACRC,OAAO,EAAA,IAAA;wBACPC,QAAQ,EAAA,IAAA;wBACRC,YAAAA,EAAYpB,MAAAA,CAAOqB,aAAa,GAAG,gBAAA,GAAmB,eAAA;AACtDC,wBAAAA,eAAAA,EAAetB,OAAOqB,aAAa;wBACnCE,OAAAA,EAAStB,aAAAA;AACT,wBAAA,QAAA,gBAAAa,GAAA,CAACU,GAAAA,EAAAA;4BAAEb,SAAAA,EAAU,YAAA;4BAAac,aAAAA,EAAY;;;AAG7C3B,oBAAAA,KAAAA,CAAM4B,IAAI;AACV5B,oBAAAA,KAAAA,CAAM6B;;;YAEV7B,KAAAA,CAAM8B,IAAI,EAAEC,MAAAA,GAAS/B,KAAAA,CAAM8B,IAAI,GAAGzB,SAAAA,IAAaG,WAAAA,CAAYT,OAAAA,EAAS,kBAAA,EAAoB,IAAA,CAAA,iBAAQiB,GAAA,CAACgB,gBAAAA,EAAAA;AAAiBC,gBAAAA,MAAAA,EAAQC,qBAAqBpC,MAAM;gBAAEqC,KAAAA,EAAM;AAAe,aAAA,CAAA,GAAA,IAAA;0BAC7KnB,GAAA,CAACJ,KAAAA,EAAAA;gBAAIC,SAAAA,EAAU,mBAAA;AAAqBb,gBAAAA,QAAAA,EAAAA,KAAAA,CAAMoC;;;;AAGtD;AAEA,SAAS3B,eAAe4B,IAAgB,EAAA;AACpC,IAAA,OAAOA,SAASC,UAAAA,CAAWC,MAAM,IAAIF,IAAAA,KAASC,WAAWE,OAAO;AACpE;;"}
|