@aquera/nile-elements 2.0.11 → 2.0.12
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/README.md +3 -0
- package/demo/app-shell.html +21 -21
- package/dist/index.js +76 -66
- package/dist/nile-app-shell/nile-app-shell.cjs.js +1 -1
- package/dist/nile-app-shell/nile-app-shell.cjs.js.map +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.cjs.js +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.cjs.js.map +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.esm.js +35 -32
- package/dist/nile-app-shell/nile-app-shell.esm.js +39 -34
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.cjs.js +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.cjs.js.map +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.esm.js +3 -1
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.js +9 -5
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.css.js +33 -30
- package/dist/src/nile-app-shell/nile-app-shell.css.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.d.ts +22 -22
- package/dist/src/nile-app-shell/nile-app-shell.js +86 -76
- package/dist/src/nile-app-shell/nile-app-shell.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.test.d.ts +1 -0
- package/dist/src/nile-app-shell/nile-app-shell.test.js +307 -89
- package/dist/src/nile-app-shell/nile-app-shell.test.js.map +1 -1
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js +3 -1
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/nile-app-shell/nile-app-shell-regions.test.ts +9 -5
- package/src/nile-app-shell/nile-app-shell.css.ts +33 -30
- package/src/nile-app-shell/nile-app-shell.test.ts +348 -105
- package/src/nile-app-shell/nile-app-shell.ts +89 -82
- package/src/nile-app-shell-panel/nile-app-shell-panel.css.ts +3 -1
- package/vscode-html-custom-data.json +27 -37
|
@@ -327,8 +327,8 @@ describe('nile-side-bar in the shell track', () => {
|
|
|
327
327
|
});
|
|
328
328
|
});
|
|
329
329
|
/*
|
|
330
|
-
* The HTML API, driven from markup. pageTitle,
|
|
331
|
-
* and panelBackLabel
|
|
330
|
+
* The HTML API, driven from markup. pageTitle, headerBack, headerBackLabel,
|
|
331
|
+
* noTabs, panelBack and panelBackLabel declare no kebab `attribute:` option, so Lit
|
|
332
332
|
* observes the lowercased property name (pagetitle, notabs, ...) and markup
|
|
333
333
|
* writes them camelCase — HTML lowercases `pageTitle=` to match.
|
|
334
334
|
*
|
|
@@ -344,8 +344,8 @@ describe('nile-app-shell — the attributes the docs advertise', () => {
|
|
|
344
344
|
<nile-app-shell
|
|
345
345
|
style="width: 1440px; height: 600px;"
|
|
346
346
|
pageTitle="Applications"
|
|
347
|
-
|
|
348
|
-
|
|
347
|
+
headerBack
|
|
348
|
+
headerBackLabel="Integrations"
|
|
349
349
|
noTabs
|
|
350
350
|
panelBack
|
|
351
351
|
panelBackLabel="Chat history"
|
|
@@ -361,7 +361,8 @@ describe('nile-app-shell — the attributes the docs advertise', () => {
|
|
|
361
361
|
await el.updateComplete;
|
|
362
362
|
// Each attribute reached its property.
|
|
363
363
|
expect(el.pageTitle, 'pageTitle').to.equal('Applications');
|
|
364
|
-
expect(el.
|
|
364
|
+
expect(el.headerBack, 'headerBack').to.be.true;
|
|
365
|
+
expect(el.headerBackLabel, 'headerBackLabel').to.equal('Integrations');
|
|
365
366
|
expect(el.noTabs, 'noTabs').to.be.true;
|
|
366
367
|
expect(el.panelBack, 'panelBack').to.be.true;
|
|
367
368
|
expect(el.panelBackLabel, 'panelBackLabel').to.equal('Chat history');
|
|
@@ -372,7 +373,10 @@ describe('nile-app-shell — the attributes the docs advertise', () => {
|
|
|
372
373
|
// The reflecting pair round-trip to the lowercased name, not to kebab.
|
|
373
374
|
expect(el.hasAttribute('notabs')).to.be.true;
|
|
374
375
|
expect(el.hasAttribute('panelback')).to.be.true;
|
|
376
|
+
expect(el.hasAttribute('headerback')).to.be.true;
|
|
377
|
+
expect(el.getAttribute('headerbacklabel')).to.equal('Integrations');
|
|
375
378
|
expect(el.hasAttribute('no-tabs')).to.be.false;
|
|
379
|
+
expect(el.hasAttribute('header-back')).to.be.false;
|
|
376
380
|
el.noTabs = false;
|
|
377
381
|
el.panelBack = false;
|
|
378
382
|
await el.updateComplete;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nile-app-shell-regions.test.js","sourceRoot":"","sources":["../../../src/nile-app-shell/nile-app-shell-regions.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture, html, oneEvent, waitUntil } from '@open-wc/testing';\nimport './nile-app-shell';\nimport '../nile-app-shell-side-nav/nile-app-shell-side-nav';\nimport '../nile-app-shell-main/nile-app-shell-main';\nimport '../nile-app-shell-panel/nile-app-shell-panel';\nimport '../nile-side-bar/nile-side-bar';\nimport '../nile-nav-tab-group/nile-nav-tab-group';\nimport '../nile-nav-tab/nile-nav-tab';\nimport type { NileAppShell } from './nile-app-shell';\nimport type { NileAppShellSideNav } from '../nile-app-shell-side-nav/nile-app-shell-side-nav';\nimport type { NileAppShellMain } from '../nile-app-shell-main/nile-app-shell-main';\nimport type { NileAppShellPanel } from '../nile-app-shell-panel/nile-app-shell-panel';\n\n/** The compositional form: one child element per region, no slot names. */\nconst composed = async (width = 1440, overlayBreakpoint = 0) => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell\n style=\"width: ${width}px; height: 600px;\"\n overlay-breakpoint=${overlayBreakpoint}\n >\n <nile-app-shell-side-nav>\n <span slot=\"header\">Aquera</span>\n <nav>nav</nav>\n <span slot=\"footer\">account</span>\n </nile-app-shell-side-nav>\n\n <span slot=\"top-bar\">Title</span>\n\n <nile-app-shell-main>\n <div class=\"page\">page</div>\n </nile-app-shell-main>\n\n <nile-app-shell-panel label=\"Ask Aquera\">\n <div>answer</div>\n <div slot=\"footer\">composer</div>\n </nile-app-shell-panel>\n </nile-app-shell>\n `);\n await waitUntil(() => el.hasAttribute('has-panel'));\n return el;\n};\n\nconst region = <T extends Element>(el: NileAppShell, tag: string) =>\n el.querySelector<T>(tag)!;\n\ndescribe('Region components — slot assignment', () => {\n it('1. each region claims the shell slot it belongs to', async () => {\n const el = await composed();\n expect(region(el, 'nile-app-shell-side-nav').getAttribute('slot')).to.equal(\n 'side-nav'\n );\n expect(region(el, 'nile-app-shell-panel').getAttribute('slot')).to.equal(\n 'panel'\n );\n // Main belongs to the default slot, so it must claim no slot at all.\n expect(region(el, 'nile-app-shell-main').hasAttribute('slot')).to.be.false;\n });\n\n it('2. the shell sees all three regions as filled', async () => {\n const el = await composed();\n expect(el.hasAttribute('has-side-nav')).to.be.true;\n expect(el.hasAttribute('has-panel')).to.be.true;\n expect(el.panelAvailable).to.be.true;\n });\n\n it('3. an explicit slot placement is respected, not overwritten', async () => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell style=\"width: 1440px; height: 600px;\">\n <nile-app-shell-panel slot=\"aside\">detail</nile-app-shell-panel>\n <nile-app-shell-main>page</nile-app-shell-main>\n </nile-app-shell>\n `);\n await el.updateComplete;\n expect(\n el.querySelector('nile-app-shell-panel')!.getAttribute('slot')\n ).to.equal('aside');\n await waitUntil(() => el.hasAttribute('has-aside'));\n expect(el.hasAttribute('has-panel')).to.be.false;\n });\n});\n\ndescribe('nile-app-shell-side-nav', () => {\n it('4. mirrors the shell rail state onto its own collapsed attribute', async () => {\n const el = await composed();\n const nav = region<NileAppShellSideNav>(el, 'nile-app-shell-side-nav');\n expect(nav.collapsed).to.be.false;\n\n el.collapseNav();\n await el.updateComplete;\n await nav.updateComplete;\n expect(nav.hasAttribute('collapsed')).to.be.true;\n\n el.expandNav();\n await el.updateComplete;\n await nav.updateComplete;\n expect(nav.hasAttribute('collapsed')).to.be.false;\n });\n\n it('5. follows a rail the shell forces at narrow widths', async () => {\n const el = await composed(1000);\n const nav = region<NileAppShellSideNav>(el, 'nile-app-shell-side-nav');\n el.openPanel();\n await waitUntil(() => el.navLocked);\n await nav.updateComplete;\n expect(nav.hasAttribute('collapsed')).to.be.true;\n expect(el.navCollapsed).to.be.false; // the lock, not a preference\n });\n\n it('6. renders header, body and footer regions', async () => {\n const el = await composed();\n const nav = region<NileAppShellSideNav>(el, 'nile-app-shell-side-nav');\n ['header', 'body', 'footer'].forEach(part => {\n expect(nav.shadowRoot!.querySelector(`[part~=\"${part}\"]`)).to.exist;\n });\n });\n});\n\ndescribe('nile-app-shell-main', () => {\n it('7. is the size query container page CSS sizes against', async () => {\n const el = await composed();\n const main = region<NileAppShellMain>(el, 'nile-app-shell-main');\n expect(getComputedStyle(main).containerType).to.equal('inline-size');\n });\n\n it('8. no-container drops the containment', async () => {\n const el = await composed();\n const main = region<NileAppShellMain>(el, 'nile-app-shell-main');\n main.noContainer = true;\n await main.updateComplete;\n expect(getComputedStyle(main).containerType).to.equal('normal');\n });\n});\n\ndescribe('nile-app-shell-panel', () => {\n it('9. takes over the panel chrome from the shell', async () => {\n const el = await composed();\n expect(el.getAttribute('panel-chrome')).to.equal('external');\n // The shell's own header must not also render.\n expect(el.shadowRoot!.querySelector('[part~=\"panel-header\"]')).to.not.exist;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n expect(panel.shadowRoot!.querySelector('[part~=\"header\"]')).to.exist;\n expect(\n panel.shadowRoot!.querySelector('[part~=\"title\"]')!.textContent!.trim()\n ).to.equal('Ask Aquera');\n });\n\n it('10. the shell keeps its own chrome for plain slotted content', async () => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell style=\"width: 1440px; height: 600px;\">\n <div slot=\"panel\">answer</div>\n </nile-app-shell>\n `);\n await waitUntil(() => el.hasAttribute('has-panel'));\n expect(el.getAttribute('panel-chrome')).to.equal('internal');\n expect(el.shadowRoot!.querySelector('[part~=\"panel-header\"]')).to.exist;\n });\n\n it('11. mirrors the shell panel mode', async () => {\n const el = await composed(1000, 1280);\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n await waitUntil(() => el.panelMode === 'overlay');\n await panel.updateComplete;\n expect(panel.getAttribute('mode')).to.equal('overlay');\n });\n\n it('12. its close button closes the panel through the shell', async () => {\n const el = await composed();\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n const close =\n panel.shadowRoot!.querySelector<HTMLButtonElement>('[part~=\"close\"]')!;\n const closed = oneEvent(panel, 'nile-close');\n close.click();\n const event = await closed;\n expect(event).to.exist;\n await el.updateComplete;\n expect(el.panelOpen).to.be.false;\n });\n\n it('13. no-close and no-header drop those controls', async () => {\n const el = await composed();\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n panel.noClose = true;\n panel.noHeader = true;\n await panel.updateComplete;\n const close = panel.shadowRoot!.querySelector('[part~=\"close\"]')!;\n const header = panel.shadowRoot!.querySelector('[part~=\"header\"]')!;\n expect(getComputedStyle(close).display).to.equal('none');\n expect(getComputedStyle(header).display).to.equal('none');\n });\n\n it('14. shows the footer only when something is slotted into it', async () => {\n const el = await composed();\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n expect(panel.hasAttribute('has-footer')).to.be.true;\n\n panel.querySelector('[slot=\"footer\"]')!.remove();\n await waitUntil(() => !panel.hasAttribute('has-footer'));\n expect(\n getComputedStyle(panel.shadowRoot!.querySelector('[part~=\"footer\"]')!)\n .display\n ).to.equal('none');\n });\n\n it('15. names the region for assistive tech from its label', async () => {\n const el = await composed();\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n expect(panel.getAttribute('role')).to.equal('complementary');\n expect(panel.getAttribute('aria-label')).to.equal('Ask Aquera');\n\n panel.label = 'Ask Nile';\n await panel.updateComplete;\n expect(panel.getAttribute('aria-label')).to.equal('Ask Nile');\n });\n\n it('16. holds the back control until back asks for it', async () => {\n const el = await composed();\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n const back = () => panel.shadowRoot!.querySelector('[part~=\"back\"]');\n const mark = panel.shadowRoot!.querySelector('.mark')!;\n // Not rendered at all in the root view, so no stylesheet override can surface it.\n expect(back()).to.not.exist;\n expect(getComputedStyle(mark).display).to.not.equal('none');\n\n panel.back = true;\n await panel.updateComplete;\n expect(back()).to.exist;\n expect(getComputedStyle(back()!).display).to.not.equal('none');\n // The back control stands where the brand mark stands in the root view.\n expect(getComputedStyle(mark).display).to.equal('none');\n });\n\n it('17. its back control emits nile-back and leaves the panel open', async () => {\n const el = await composed();\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n panel.back = true;\n panel.backLabel = 'Back to chats';\n await panel.updateComplete;\n\n const back =\n panel.shadowRoot!.querySelector<HTMLButtonElement>('[part~=\"back\"]')!;\n expect(back.getAttribute('aria-label')).to.equal('Back to chats');\n\n const went = oneEvent(panel, 'nile-back');\n back.click();\n expect(await went).to.exist;\n await el.updateComplete;\n // The panel keeps no view stack, so going back is not closing.\n expect(el.panelOpen).to.be.true;\n });\n\n // Birat's review: a page listening on the shell for nile-panel-back must not go deaf when it slots this panel.\n it('82. its back control also emits nile-panel-back, once, and it reaches the shell', async () => {\n const el = await composed();\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n panel.back = true;\n await panel.updateComplete;\n\n const order: string[] = [];\n const log = (e: Event) => order.push(e.type);\n el.addEventListener('nile-back', log);\n el.addEventListener('nile-panel-back', log);\n\n const reached = oneEvent(el, 'nile-panel-back');\n panel.shadowRoot!.querySelector<HTMLButtonElement>('[part~=\"back\"]')!.click();\n const event = await reached;\n\n // Bubbles and composed, so a listener outside the shadow roots hears it.\n expect(event.bubbles).to.be.true;\n expect(event.composed).to.be.true;\n // One press: nile-back then nile-panel-back, each exactly once.\n expect(order).to.deep.equal(['nile-back', 'nile-panel-back']);\n\n order.length = 0;\n panel.goBack();\n expect(order).to.deep.equal(['nile-back', 'nile-panel-back']);\n });\n\n // The panel draws its header controls as bare glyphs via ::part(base), overriding nile-button's circle and ghost surface.\n it('18. draws its header controls bare, in the utility box', async () => {\n const el = await composed();\n // A closed panel is display:none, and a hidden box measures zero.\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n panel.back = true;\n await panel.updateComplete;\n\n /*\n * The contract is \"the control fills the utility box\", not \"the control is\n * 32px\": --nile-app-shell-utility-size is a token chain\n * (--nile-spacing-4xl, else --ng-spacing-4xl -> --ng-spacing-8), and both\n * sheets happen to land on 32 today. Reading the resolved value keeps this\n * honest if either sheet moves. The || 32 is the stylesheet's own literal\n * floor, for this unthemed fixture where neither token is defined.\n */\n const utility =\n parseFloat(\n getComputedStyle(panel).getPropertyValue('--nile-app-shell-utility-size')\n ) || 32;\n expect(utility, 'the utility box resolves to a real size').to.be.above(0);\n\n for (const name of ['back', 'close']) {\n const control = panel.shadowRoot!.querySelector(`[part~=\"${name}\"]`)!;\n const base = control.shadowRoot!.querySelector('[part~=\"base\"]')!;\n expect(getComputedStyle(base).backgroundColor).to.equal(\n 'rgba(0, 0, 0, 0)'\n );\n const box = base.getBoundingClientRect();\n expect(box.width, `${name} width`).to.equal(utility);\n expect(box.height, `${name} height`).to.equal(utility);\n }\n });\n\n // The panel mounts in the shell's light DOM but sizes its header as its own box, independent of the page header.\n it('19. sizes its header independently of the page header', async () => {\n const el = await composed();\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n const header = () =>\n panel.shadowRoot!.querySelector('.header') as HTMLElement;\n\n expect(header().getBoundingClientRect().height).to.equal(56);\n\n // The Description axis moves the page header to 76px, but the panel's header must not follow it.\n el.pageTitle = 'Connected applications';\n el.description = 'Everything connected to Aquera';\n await el.updateComplete;\n await panel.updateComplete;\n\n expect(el.hasAttribute('has-description')).to.be.true;\n expect(header().getBoundingClientRect().height).to.equal(56);\n });\n\n it('20. keeps its 56px header when mounted outside a shell', async () => {\n // No shell, so the literal fallback is the floor; the stray top-bar height stands in for a page that sets it globally.\n const panel = await fixture<NileAppShellPanel>(html`\n <nile-app-shell-panel\n label=\"Ask Aquera\"\n style=\"--nile-app-shell-top-bar-height: 76px;\"\n >\n <div>answer</div>\n </nile-app-shell-panel>\n `);\n\n const header = panel.shadowRoot!.querySelector('.header') as HTMLElement;\n expect(header.getBoundingClientRect().height).to.equal(56);\n });\n});\n\n// The shell's nav track mirrors nile-side-bar's per-theme width, so ::slotted width:100% remains only so a raw nav still fills the track.\ndescribe('nile-side-bar in the shell track', () => {\n const ENTERPRISE = '--nile-width-240px: 240px; --nile-width-70px: 70px;';\n const NXTGEN = '--ng-spacing-296: 296px; --ng-spacing-68: 68px;';\n\n const railedTo = async (tokens: string, expanded: number, rail: number) => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell style=\"width: 1440px; height: 600px; ${tokens}\">\n <nile-side-bar slot=\"side-nav\" position=\"left\"></nile-side-bar>\n <p>page</p>\n </nile-app-shell>\n `);\n await waitUntil(() => el.hasAttribute('has-side-nav'));\n const bar = el.querySelector('nile-side-bar')!;\n const width = () => Math.round(bar.getBoundingClientRect().width);\n\n expect(width(), 'expanded').to.equal(expanded);\n\n el.collapseNav();\n await el.updateComplete;\n await waitUntil(() => width() === rail, 'the rail never settled', {\n timeout: 2000,\n interval: 50,\n });\n expect(width(), 'railed').to.equal(rail);\n };\n\n it('21. matches the deployed enterprise side bar: 240 / 70', async () => {\n await railedTo(ENTERPRISE, 240, 70);\n });\n\n it('22. matches the deployed nxtgen side bar: 296 / 68', async () => {\n await railedTo(NXTGEN, 296, 68);\n });\n\n // The slotted width is not !important, yet the shell's ::slotted rule still beats the side bar's own :host width, so overriding the documented track properties resizes the bar with the track.\n it('83. follows an overridden track width: 200 / 50', async () => {\n const overrides =\n '--nile-app-shell-side-nav-width: 200px; --nile-app-shell-side-nav-rail-width: 50px;';\n await railedTo(`${ENTERPRISE} ${overrides}`, 200, 50);\n await railedTo(`${NXTGEN} ${overrides}`, 200, 50);\n });\n});\n\n/*\n * The HTML API, driven from markup. pageTitle, backLabel, noTabs, panelBack\n * and panelBackLabel deliberately declare no `attribute:` option, so Lit\n * observes the lowercased property name (pagetitle, notabs, ...) and markup\n * writes them camelCase — HTML lowercases `pageTitle=` to match.\n *\n * Every other test in this suite sets these as JS properties, which works no\n * matter what the attribute is called — so if a kebab `attribute:` option is\n * added back, nothing else fails and `<nile-app-shell pageTitle=\"...\">`\n * silently does nothing. This fixture is markup-only on purpose: it is the\n * one that breaks if that happens.\n */\ndescribe('nile-app-shell — the attributes the docs advertise', () => {\n it('23. reads its title block and switches from camelCase markup', async () => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell\n style=\"width: 1440px; height: 600px;\"\n pageTitle=\"Applications\"\n backLabel=\"Integrations\"\n leading=\"back\"\n noTabs\n panelBack\n panelBackLabel=\"Chat history\"\n >\n <nav slot=\"side-nav\">nav</nav>\n <nile-nav-tab-group slot=\"tabs\">\n <nile-nav-tab slot=\"nav\" panel=\"apps\" active>Connected</nile-nav-tab>\n </nile-nav-tab-group>\n <p>page</p>\n <div slot=\"panel\">assistant</div>\n </nile-app-shell>\n `);\n await el.updateComplete;\n\n // Each attribute reached its property.\n expect(el.pageTitle, 'pageTitle').to.equal('Applications');\n expect(el.backLabel, 'backLabel').to.equal('Integrations');\n expect(el.noTabs, 'noTabs').to.be.true;\n expect(el.panelBack, 'panelBack').to.be.true;\n expect(el.panelBackLabel, 'panelBackLabel').to.equal('Chat history');\n\n // And had the effect the attribute promises, not just the assignment.\n const title = el.shadowRoot!.querySelector('[part~=\"page-title\"]');\n expect(title!.textContent!.trim()).to.equal('Applications');\n expect(el.tabsVisible, 'noTabs hides the strip').to.be.false;\n\n // The reflecting pair round-trip to the lowercased name, not to kebab.\n expect(el.hasAttribute('notabs')).to.be.true;\n expect(el.hasAttribute('panelback')).to.be.true;\n expect(el.hasAttribute('no-tabs')).to.be.false;\n el.noTabs = false;\n el.panelBack = false;\n await el.updateComplete;\n expect(el.hasAttribute('notabs'), 'notabs is removed again').to.be.false;\n expect(el.hasAttribute('panelback')).to.be.false;\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"nile-app-shell-regions.test.js","sourceRoot":"","sources":["../../../src/nile-app-shell/nile-app-shell-regions.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,kBAAkB,CAAC;AAC1B,OAAO,oDAAoD,CAAC;AAC5D,OAAO,4CAA4C,CAAC;AACpD,OAAO,8CAA8C,CAAC;AACtD,OAAO,gCAAgC,CAAC;AACxC,OAAO,0CAA0C,CAAC;AAClD,OAAO,8BAA8B,CAAC;AAMtC,2EAA2E;AAC3E,MAAM,QAAQ,GAAG,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,iBAAiB,GAAG,CAAC,EAAE,EAAE;IAC7D,MAAM,EAAE,GAAG,MAAM,OAAO,CAAe,IAAI,CAAA;;sBAEvB,KAAK;2BACA,iBAAiB;;;;;;;;;;;;;;;;;;;GAmBzC,CAAC,CAAC;IACH,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;IACpD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,CAAoB,EAAgB,EAAE,GAAW,EAAE,EAAE,CAClE,EAAE,CAAC,aAAa,CAAI,GAAG,CAAE,CAAC;AAE5B,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,yBAAyB,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CACzE,UAAU,CACX,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CACtE,OAAO,CACR,CAAC;QACF,qEAAqE;QACrE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QACnD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAChD,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,EAAE,GAAG,MAAM,OAAO,CAAe,IAAI,CAAA;;;;;KAK1C,CAAC,CAAC;QACH,MAAM,EAAE,CAAC,cAAc,CAAC;QACxB,MAAM,CACJ,EAAE,CAAC,aAAa,CAAC,sBAAsB,CAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAC/D,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAsB,EAAE,EAAE,yBAAyB,CAAC,CAAC;QACvE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QAElC,EAAE,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,EAAE,CAAC,cAAc,CAAC;QACxB,MAAM,GAAG,CAAC,cAAc,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAEjD,EAAE,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,cAAc,CAAC;QACxB,MAAM,GAAG,CAAC,cAAc,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,MAAM,CAAsB,EAAE,EAAE,yBAAyB,CAAC,CAAC;QACvE,EAAE,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,GAAG,CAAC,cAAc,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QACjD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,6BAA6B;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAsB,EAAE,EAAE,yBAAyB,CAAC,CAAC;QACvE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAC1C,MAAM,CAAC,GAAG,CAAC,UAAW,CAAC,aAAa,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAmB,EAAE,EAAE,qBAAqB,CAAC,CAAC;QACjE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAmB,EAAE,EAAE,qBAAqB,CAAC,CAAC;QACjE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,MAAM,IAAI,CAAC,cAAc,CAAC;QAC1B,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC7D,+CAA+C;QAC/C,MAAM,CAAC,EAAE,CAAC,UAAW,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;QAE5E,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;QACrE,MAAM,CACJ,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,iBAAiB,CAAE,CAAC,WAAY,CAAC,IAAI,EAAE,CACxE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,EAAE,GAAG,MAAM,OAAO,CAAe,IAAI,CAAA;;;;KAI1C,CAAC,CAAC;QACH,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC7D,MAAM,CAAC,EAAE,CAAC,UAAW,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;QAClD,MAAM,KAAK,CAAC,cAAc,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,EAAE,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,cAAc,CAAC;QAExB,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,MAAM,KAAK,GACT,KAAK,CAAC,UAAW,CAAC,aAAa,CAAoB,iBAAiB,CAAE,CAAC;QACzE,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QAC7C,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;QACvB,MAAM,EAAE,CAAC,cAAc,CAAC;QACxB,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QACrB,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QACtB,MAAM,KAAK,CAAC,cAAc,CAAC;QAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,iBAAiB,CAAE,CAAC;QAClE,MAAM,MAAM,GAAG,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,kBAAkB,CAAE,CAAC;QACpE,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAEpD,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAE,CAAC,MAAM,EAAE,CAAC;QACjD,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;QACzD,MAAM,CACJ,gBAAgB,CAAC,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,kBAAkB,CAAE,CAAC;aACnE,OAAO,CACX,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAEhE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC;QACzB,MAAM,KAAK,CAAC,cAAc,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,OAAO,CAAE,CAAC;QACvD,kFAAkF;QAClF,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;QAC5B,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE5D,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAClB,MAAM,KAAK,CAAC,cAAc,CAAC;QAC3B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;QACxB,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAG,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/D,wEAAwE;QACxE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,EAAE,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,cAAc,CAAC;QAExB,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAClB,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC;QAClC,MAAM,KAAK,CAAC,cAAc,CAAC;QAE3B,MAAM,IAAI,GACR,KAAK,CAAC,UAAW,CAAC,aAAa,CAAoB,gBAAgB,CAAE,CAAC;QACxE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAElE,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;QAC5B,MAAM,EAAE,CAAC,cAAc,CAAC;QACxB,+DAA+D;QAC/D,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,+GAA+G;IAC/G,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,EAAE,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,cAAc,CAAC;QAExB,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAClB,MAAM,KAAK,CAAC,cAAc,CAAC;QAE3B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,CAAC,CAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7C,EAAE,CAAC,gBAAgB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACtC,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QAE5C,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC;QAChD,KAAK,CAAC,UAAW,CAAC,aAAa,CAAoB,gBAAgB,CAAE,CAAC,KAAK,EAAE,CAAC;QAC9E,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC;QAE5B,yEAAyE;QACzE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAClC,gEAAgE;QAChE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAE9D,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACjB,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,0HAA0H;IAC1H,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,kEAAkE;QAClE,EAAE,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,cAAc,CAAC;QAExB,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAClB,MAAM,KAAK,CAAC,cAAc,CAAC;QAE3B;;;;;;;WAOG;QACH,MAAM,OAAO,GACX,UAAU,CACR,gBAAgB,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,+BAA+B,CAAC,CAC1E,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,OAAO,EAAE,yCAAyC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAE1E,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,WAAW,IAAI,IAAI,CAAE,CAAC;YACtE,MAAM,IAAI,GAAG,OAAO,CAAC,UAAW,CAAC,aAAa,CAAC,gBAAgB,CAAE,CAAC;YAClE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,KAAK,CACrD,kBAAkB,CACnB,CAAC;YACF,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,IAAI,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACrD,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,iHAAiH;IACjH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC5B,EAAE,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,cAAc,CAAC;QAExB,MAAM,KAAK,GAAG,MAAM,CAAoB,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,SAAS,CAAgB,CAAC;QAE5D,MAAM,CAAC,MAAM,EAAE,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAE7D,iGAAiG;QACjG,EAAE,CAAC,SAAS,GAAG,wBAAwB,CAAC;QACxC,EAAE,CAAC,WAAW,GAAG,gCAAgC,CAAC;QAClD,MAAM,EAAE,CAAC,cAAc,CAAC;QACxB,MAAM,KAAK,CAAC,cAAc,CAAC;QAE3B,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QACtD,MAAM,CAAC,MAAM,EAAE,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,uHAAuH;QACvH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAoB,IAAI,CAAA;;;;;;;KAOlD,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,KAAK,CAAC,UAAW,CAAC,aAAa,CAAC,SAAS,CAAgB,CAAC;QACzE,MAAM,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0IAA0I;AAC1I,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,MAAM,UAAU,GAAG,qDAAqD,CAAC;IACzE,MAAM,MAAM,GAAG,iDAAiD,CAAC;IAEjE,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,QAAgB,EAAE,IAAY,EAAE,EAAE;QACxE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAe,IAAI,CAAA;6DACc,MAAM;;;;KAI9D,CAAC,CAAC;QACH,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,eAAe,CAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,CAAC;QAElE,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAE/C,EAAE,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,EAAE,CAAC,cAAc,CAAC;QACxB,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,wBAAwB,EAAE;YAChE,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC;IAEF,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,gMAAgM;IAChM,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,SAAS,GACb,qFAAqF,CAAC;QACxF,MAAM,QAAQ,CAAC,GAAG,UAAU,IAAI,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACtD,MAAM,QAAQ,CAAC,GAAG,MAAM,IAAI,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAClE,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,EAAE,GAAG,MAAM,OAAO,CAAe,IAAI,CAAA;;;;;;;;;;;;;;;;;KAiB1C,CAAC,CAAC;QACH,MAAM,EAAE,CAAC,cAAc,CAAC;QAExB,uCAAuC;QACvC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC3D,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACvE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QACvC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAC7C,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAErE,sEAAsE;QACtE,MAAM,KAAK,GAAG,EAAE,CAAC,UAAW,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;QACnE,MAAM,CAAC,KAAM,CAAC,WAAY,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC5D,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QAE7D,uEAAuE;QACvE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAC7C,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAChD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QACjD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACpE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QACnD,EAAE,CAAC,MAAM,GAAG,KAAK,CAAC;QAClB,EAAE,CAAC,SAAS,GAAG,KAAK,CAAC;QACrB,MAAM,EAAE,CAAC,cAAc,CAAC;QACxB,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,yBAAyB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;QACzE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect, fixture, html, oneEvent, waitUntil } from '@open-wc/testing';\nimport './nile-app-shell';\nimport '../nile-app-shell-side-nav/nile-app-shell-side-nav';\nimport '../nile-app-shell-main/nile-app-shell-main';\nimport '../nile-app-shell-panel/nile-app-shell-panel';\nimport '../nile-side-bar/nile-side-bar';\nimport '../nile-nav-tab-group/nile-nav-tab-group';\nimport '../nile-nav-tab/nile-nav-tab';\nimport type { NileAppShell } from './nile-app-shell';\nimport type { NileAppShellSideNav } from '../nile-app-shell-side-nav/nile-app-shell-side-nav';\nimport type { NileAppShellMain } from '../nile-app-shell-main/nile-app-shell-main';\nimport type { NileAppShellPanel } from '../nile-app-shell-panel/nile-app-shell-panel';\n\n/** The compositional form: one child element per region, no slot names. */\nconst composed = async (width = 1440, overlayBreakpoint = 0) => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell\n style=\"width: ${width}px; height: 600px;\"\n overlay-breakpoint=${overlayBreakpoint}\n >\n <nile-app-shell-side-nav>\n <span slot=\"header\">Aquera</span>\n <nav>nav</nav>\n <span slot=\"footer\">account</span>\n </nile-app-shell-side-nav>\n\n <span slot=\"top-bar\">Title</span>\n\n <nile-app-shell-main>\n <div class=\"page\">page</div>\n </nile-app-shell-main>\n\n <nile-app-shell-panel label=\"Ask Aquera\">\n <div>answer</div>\n <div slot=\"footer\">composer</div>\n </nile-app-shell-panel>\n </nile-app-shell>\n `);\n await waitUntil(() => el.hasAttribute('has-panel'));\n return el;\n};\n\nconst region = <T extends Element>(el: NileAppShell, tag: string) =>\n el.querySelector<T>(tag)!;\n\ndescribe('Region components — slot assignment', () => {\n it('1. each region claims the shell slot it belongs to', async () => {\n const el = await composed();\n expect(region(el, 'nile-app-shell-side-nav').getAttribute('slot')).to.equal(\n 'side-nav'\n );\n expect(region(el, 'nile-app-shell-panel').getAttribute('slot')).to.equal(\n 'panel'\n );\n // Main belongs to the default slot, so it must claim no slot at all.\n expect(region(el, 'nile-app-shell-main').hasAttribute('slot')).to.be.false;\n });\n\n it('2. the shell sees all three regions as filled', async () => {\n const el = await composed();\n expect(el.hasAttribute('has-side-nav')).to.be.true;\n expect(el.hasAttribute('has-panel')).to.be.true;\n expect(el.panelAvailable).to.be.true;\n });\n\n it('3. an explicit slot placement is respected, not overwritten', async () => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell style=\"width: 1440px; height: 600px;\">\n <nile-app-shell-panel slot=\"aside\">detail</nile-app-shell-panel>\n <nile-app-shell-main>page</nile-app-shell-main>\n </nile-app-shell>\n `);\n await el.updateComplete;\n expect(\n el.querySelector('nile-app-shell-panel')!.getAttribute('slot')\n ).to.equal('aside');\n await waitUntil(() => el.hasAttribute('has-aside'));\n expect(el.hasAttribute('has-panel')).to.be.false;\n });\n});\n\ndescribe('nile-app-shell-side-nav', () => {\n it('4. mirrors the shell rail state onto its own collapsed attribute', async () => {\n const el = await composed();\n const nav = region<NileAppShellSideNav>(el, 'nile-app-shell-side-nav');\n expect(nav.collapsed).to.be.false;\n\n el.collapseNav();\n await el.updateComplete;\n await nav.updateComplete;\n expect(nav.hasAttribute('collapsed')).to.be.true;\n\n el.expandNav();\n await el.updateComplete;\n await nav.updateComplete;\n expect(nav.hasAttribute('collapsed')).to.be.false;\n });\n\n it('5. follows a rail the shell forces at narrow widths', async () => {\n const el = await composed(1000);\n const nav = region<NileAppShellSideNav>(el, 'nile-app-shell-side-nav');\n el.openPanel();\n await waitUntil(() => el.navLocked);\n await nav.updateComplete;\n expect(nav.hasAttribute('collapsed')).to.be.true;\n expect(el.navCollapsed).to.be.false; // the lock, not a preference\n });\n\n it('6. renders header, body and footer regions', async () => {\n const el = await composed();\n const nav = region<NileAppShellSideNav>(el, 'nile-app-shell-side-nav');\n ['header', 'body', 'footer'].forEach(part => {\n expect(nav.shadowRoot!.querySelector(`[part~=\"${part}\"]`)).to.exist;\n });\n });\n});\n\ndescribe('nile-app-shell-main', () => {\n it('7. is the size query container page CSS sizes against', async () => {\n const el = await composed();\n const main = region<NileAppShellMain>(el, 'nile-app-shell-main');\n expect(getComputedStyle(main).containerType).to.equal('inline-size');\n });\n\n it('8. no-container drops the containment', async () => {\n const el = await composed();\n const main = region<NileAppShellMain>(el, 'nile-app-shell-main');\n main.noContainer = true;\n await main.updateComplete;\n expect(getComputedStyle(main).containerType).to.equal('normal');\n });\n});\n\ndescribe('nile-app-shell-panel', () => {\n it('9. takes over the panel chrome from the shell', async () => {\n const el = await composed();\n expect(el.getAttribute('panel-chrome')).to.equal('external');\n // The shell's own header must not also render.\n expect(el.shadowRoot!.querySelector('[part~=\"panel-header\"]')).to.not.exist;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n expect(panel.shadowRoot!.querySelector('[part~=\"header\"]')).to.exist;\n expect(\n panel.shadowRoot!.querySelector('[part~=\"title\"]')!.textContent!.trim()\n ).to.equal('Ask Aquera');\n });\n\n it('10. the shell keeps its own chrome for plain slotted content', async () => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell style=\"width: 1440px; height: 600px;\">\n <div slot=\"panel\">answer</div>\n </nile-app-shell>\n `);\n await waitUntil(() => el.hasAttribute('has-panel'));\n expect(el.getAttribute('panel-chrome')).to.equal('internal');\n expect(el.shadowRoot!.querySelector('[part~=\"panel-header\"]')).to.exist;\n });\n\n it('11. mirrors the shell panel mode', async () => {\n const el = await composed(1000, 1280);\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n await waitUntil(() => el.panelMode === 'overlay');\n await panel.updateComplete;\n expect(panel.getAttribute('mode')).to.equal('overlay');\n });\n\n it('12. its close button closes the panel through the shell', async () => {\n const el = await composed();\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n const close =\n panel.shadowRoot!.querySelector<HTMLButtonElement>('[part~=\"close\"]')!;\n const closed = oneEvent(panel, 'nile-close');\n close.click();\n const event = await closed;\n expect(event).to.exist;\n await el.updateComplete;\n expect(el.panelOpen).to.be.false;\n });\n\n it('13. no-close and no-header drop those controls', async () => {\n const el = await composed();\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n panel.noClose = true;\n panel.noHeader = true;\n await panel.updateComplete;\n const close = panel.shadowRoot!.querySelector('[part~=\"close\"]')!;\n const header = panel.shadowRoot!.querySelector('[part~=\"header\"]')!;\n expect(getComputedStyle(close).display).to.equal('none');\n expect(getComputedStyle(header).display).to.equal('none');\n });\n\n it('14. shows the footer only when something is slotted into it', async () => {\n const el = await composed();\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n expect(panel.hasAttribute('has-footer')).to.be.true;\n\n panel.querySelector('[slot=\"footer\"]')!.remove();\n await waitUntil(() => !panel.hasAttribute('has-footer'));\n expect(\n getComputedStyle(panel.shadowRoot!.querySelector('[part~=\"footer\"]')!)\n .display\n ).to.equal('none');\n });\n\n it('15. names the region for assistive tech from its label', async () => {\n const el = await composed();\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n expect(panel.getAttribute('role')).to.equal('complementary');\n expect(panel.getAttribute('aria-label')).to.equal('Ask Aquera');\n\n panel.label = 'Ask Nile';\n await panel.updateComplete;\n expect(panel.getAttribute('aria-label')).to.equal('Ask Nile');\n });\n\n it('16. holds the back control until back asks for it', async () => {\n const el = await composed();\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n const back = () => panel.shadowRoot!.querySelector('[part~=\"back\"]');\n const mark = panel.shadowRoot!.querySelector('.mark')!;\n // Not rendered at all in the root view, so no stylesheet override can surface it.\n expect(back()).to.not.exist;\n expect(getComputedStyle(mark).display).to.not.equal('none');\n\n panel.back = true;\n await panel.updateComplete;\n expect(back()).to.exist;\n expect(getComputedStyle(back()!).display).to.not.equal('none');\n // The back control stands where the brand mark stands in the root view.\n expect(getComputedStyle(mark).display).to.equal('none');\n });\n\n it('17. its back control emits nile-back and leaves the panel open', async () => {\n const el = await composed();\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n panel.back = true;\n panel.backLabel = 'Back to chats';\n await panel.updateComplete;\n\n const back =\n panel.shadowRoot!.querySelector<HTMLButtonElement>('[part~=\"back\"]')!;\n expect(back.getAttribute('aria-label')).to.equal('Back to chats');\n\n const went = oneEvent(panel, 'nile-back');\n back.click();\n expect(await went).to.exist;\n await el.updateComplete;\n // The panel keeps no view stack, so going back is not closing.\n expect(el.panelOpen).to.be.true;\n });\n\n // Birat's review: a page listening on the shell for nile-panel-back must not go deaf when it slots this panel.\n it('82. its back control also emits nile-panel-back, once, and it reaches the shell', async () => {\n const el = await composed();\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n panel.back = true;\n await panel.updateComplete;\n\n const order: string[] = [];\n const log = (e: Event) => order.push(e.type);\n el.addEventListener('nile-back', log);\n el.addEventListener('nile-panel-back', log);\n\n const reached = oneEvent(el, 'nile-panel-back');\n panel.shadowRoot!.querySelector<HTMLButtonElement>('[part~=\"back\"]')!.click();\n const event = await reached;\n\n // Bubbles and composed, so a listener outside the shadow roots hears it.\n expect(event.bubbles).to.be.true;\n expect(event.composed).to.be.true;\n // One press: nile-back then nile-panel-back, each exactly once.\n expect(order).to.deep.equal(['nile-back', 'nile-panel-back']);\n\n order.length = 0;\n panel.goBack();\n expect(order).to.deep.equal(['nile-back', 'nile-panel-back']);\n });\n\n // The panel draws its header controls as bare glyphs via ::part(base), overriding nile-button's circle and ghost surface.\n it('18. draws its header controls bare, in the utility box', async () => {\n const el = await composed();\n // A closed panel is display:none, and a hidden box measures zero.\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n panel.back = true;\n await panel.updateComplete;\n\n /*\n * The contract is \"the control fills the utility box\", not \"the control is\n * 32px\": --nile-app-shell-utility-size is a token chain\n * (--nile-spacing-4xl, else --ng-spacing-4xl -> --ng-spacing-8), and both\n * sheets happen to land on 32 today. Reading the resolved value keeps this\n * honest if either sheet moves. The || 32 is the stylesheet's own literal\n * floor, for this unthemed fixture where neither token is defined.\n */\n const utility =\n parseFloat(\n getComputedStyle(panel).getPropertyValue('--nile-app-shell-utility-size')\n ) || 32;\n expect(utility, 'the utility box resolves to a real size').to.be.above(0);\n\n for (const name of ['back', 'close']) {\n const control = panel.shadowRoot!.querySelector(`[part~=\"${name}\"]`)!;\n const base = control.shadowRoot!.querySelector('[part~=\"base\"]')!;\n expect(getComputedStyle(base).backgroundColor).to.equal(\n 'rgba(0, 0, 0, 0)'\n );\n const box = base.getBoundingClientRect();\n expect(box.width, `${name} width`).to.equal(utility);\n expect(box.height, `${name} height`).to.equal(utility);\n }\n });\n\n // The panel mounts in the shell's light DOM but sizes its header as its own box, independent of the page header.\n it('19. sizes its header independently of the page header', async () => {\n const el = await composed();\n el.openPanel();\n await el.updateComplete;\n\n const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');\n const header = () =>\n panel.shadowRoot!.querySelector('.header') as HTMLElement;\n\n expect(header().getBoundingClientRect().height).to.equal(56);\n\n // The Description axis moves the page header to 76px, but the panel's header must not follow it.\n el.pageTitle = 'Connected applications';\n el.description = 'Everything connected to Aquera';\n await el.updateComplete;\n await panel.updateComplete;\n\n expect(el.hasAttribute('has-description')).to.be.true;\n expect(header().getBoundingClientRect().height).to.equal(56);\n });\n\n it('20. keeps its 56px header when mounted outside a shell', async () => {\n // No shell, so the literal fallback is the floor; the stray top-bar height stands in for a page that sets it globally.\n const panel = await fixture<NileAppShellPanel>(html`\n <nile-app-shell-panel\n label=\"Ask Aquera\"\n style=\"--nile-app-shell-top-bar-height: 76px;\"\n >\n <div>answer</div>\n </nile-app-shell-panel>\n `);\n\n const header = panel.shadowRoot!.querySelector('.header') as HTMLElement;\n expect(header.getBoundingClientRect().height).to.equal(56);\n });\n});\n\n// The shell's nav track mirrors nile-side-bar's per-theme width, so ::slotted width:100% remains only so a raw nav still fills the track.\ndescribe('nile-side-bar in the shell track', () => {\n const ENTERPRISE = '--nile-width-240px: 240px; --nile-width-70px: 70px;';\n const NXTGEN = '--ng-spacing-296: 296px; --ng-spacing-68: 68px;';\n\n const railedTo = async (tokens: string, expanded: number, rail: number) => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell style=\"width: 1440px; height: 600px; ${tokens}\">\n <nile-side-bar slot=\"side-nav\" position=\"left\"></nile-side-bar>\n <p>page</p>\n </nile-app-shell>\n `);\n await waitUntil(() => el.hasAttribute('has-side-nav'));\n const bar = el.querySelector('nile-side-bar')!;\n const width = () => Math.round(bar.getBoundingClientRect().width);\n\n expect(width(), 'expanded').to.equal(expanded);\n\n el.collapseNav();\n await el.updateComplete;\n await waitUntil(() => width() === rail, 'the rail never settled', {\n timeout: 2000,\n interval: 50,\n });\n expect(width(), 'railed').to.equal(rail);\n };\n\n it('21. matches the deployed enterprise side bar: 240 / 70', async () => {\n await railedTo(ENTERPRISE, 240, 70);\n });\n\n it('22. matches the deployed nxtgen side bar: 296 / 68', async () => {\n await railedTo(NXTGEN, 296, 68);\n });\n\n // The slotted width is not !important, yet the shell's ::slotted rule still beats the side bar's own :host width, so overriding the documented track properties resizes the bar with the track.\n it('83. follows an overridden track width: 200 / 50', async () => {\n const overrides =\n '--nile-app-shell-side-nav-width: 200px; --nile-app-shell-side-nav-rail-width: 50px;';\n await railedTo(`${ENTERPRISE} ${overrides}`, 200, 50);\n await railedTo(`${NXTGEN} ${overrides}`, 200, 50);\n });\n});\n\n/*\n * The HTML API, driven from markup. pageTitle, headerBack, headerBackLabel,\n * noTabs, panelBack and panelBackLabel declare no kebab `attribute:` option, so Lit\n * observes the lowercased property name (pagetitle, notabs, ...) and markup\n * writes them camelCase — HTML lowercases `pageTitle=` to match.\n *\n * Every other test in this suite sets these as JS properties, which works no\n * matter what the attribute is called — so if a kebab `attribute:` option is\n * added back, nothing else fails and `<nile-app-shell pageTitle=\"...\">`\n * silently does nothing. This fixture is markup-only on purpose: it is the\n * one that breaks if that happens.\n */\ndescribe('nile-app-shell — the attributes the docs advertise', () => {\n it('23. reads its title block and switches from camelCase markup', async () => {\n const el = await fixture<NileAppShell>(html`\n <nile-app-shell\n style=\"width: 1440px; height: 600px;\"\n pageTitle=\"Applications\"\n headerBack\n headerBackLabel=\"Integrations\"\n noTabs\n panelBack\n panelBackLabel=\"Chat history\"\n >\n <nav slot=\"side-nav\">nav</nav>\n <nile-nav-tab-group slot=\"tabs\">\n <nile-nav-tab slot=\"nav\" panel=\"apps\" active>Connected</nile-nav-tab>\n </nile-nav-tab-group>\n <p>page</p>\n <div slot=\"panel\">assistant</div>\n </nile-app-shell>\n `);\n await el.updateComplete;\n\n // Each attribute reached its property.\n expect(el.pageTitle, 'pageTitle').to.equal('Applications');\n expect(el.headerBack, 'headerBack').to.be.true;\n expect(el.headerBackLabel, 'headerBackLabel').to.equal('Integrations');\n expect(el.noTabs, 'noTabs').to.be.true;\n expect(el.panelBack, 'panelBack').to.be.true;\n expect(el.panelBackLabel, 'panelBackLabel').to.equal('Chat history');\n\n // And had the effect the attribute promises, not just the assignment.\n const title = el.shadowRoot!.querySelector('[part~=\"page-title\"]');\n expect(title!.textContent!.trim()).to.equal('Applications');\n expect(el.tabsVisible, 'noTabs hides the strip').to.be.false;\n\n // The reflecting pair round-trip to the lowercased name, not to kebab.\n expect(el.hasAttribute('notabs')).to.be.true;\n expect(el.hasAttribute('panelback')).to.be.true;\n expect(el.hasAttribute('headerback')).to.be.true;\n expect(el.getAttribute('headerbacklabel')).to.equal('Integrations');\n expect(el.hasAttribute('no-tabs')).to.be.false;\n expect(el.hasAttribute('header-back')).to.be.false;\n el.noTabs = false;\n el.panelBack = false;\n await el.updateComplete;\n expect(el.hasAttribute('notabs'), 'notabs is removed again').to.be.false;\n expect(el.hasAttribute('panelback')).to.be.false;\n });\n});\n"]}
|
|
@@ -225,21 +225,21 @@ export const styles = css `
|
|
|
225
225
|
flex: 1 1 auto;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
/* The title block: the
|
|
228
|
+
/* The title block: the back arrow, then the stack (app icon, heading and badge, with the description under them); renders before the top-bar slot. */
|
|
229
229
|
.title-area {
|
|
230
230
|
display: flex;
|
|
231
|
-
/* Top-aligned, not centred: the
|
|
231
|
+
/* Top-aligned, not centred: the back arrow belongs to the title's row, not the title-plus-description stack. */
|
|
232
232
|
align-items: flex-start;
|
|
233
|
-
gap:
|
|
233
|
+
/* Figma's Title Area gap: 16px from the arrow to the stack. */
|
|
234
|
+
gap: var(--nile-spacing-xl, var(--ng-spacing-xl));
|
|
234
235
|
min-width: 0;
|
|
235
236
|
}
|
|
236
237
|
|
|
237
|
-
/* The
|
|
238
|
-
.
|
|
238
|
+
/* The back arrow's line box: exactly the page title's line height, centring the arrow on the title row. */
|
|
239
|
+
.back-line {
|
|
239
240
|
flex: 0 0 auto;
|
|
240
241
|
display: inline-flex;
|
|
241
242
|
align-items: center;
|
|
242
|
-
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
243
243
|
min-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));
|
|
244
244
|
}
|
|
245
245
|
|
|
@@ -278,7 +278,7 @@ export const styles = css `
|
|
|
278
278
|
font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));
|
|
279
279
|
line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));
|
|
280
280
|
font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));
|
|
281
|
-
color: var(--nile-colors-dark-500, var(--ng-colors-text-
|
|
281
|
+
color: var(--nile-colors-dark-500, var(--ng-colors-text-quaternary-500));
|
|
282
282
|
white-space: nowrap;
|
|
283
283
|
overflow: hidden;
|
|
284
284
|
text-overflow: ellipsis;
|
|
@@ -312,36 +312,24 @@ export const styles = css `
|
|
|
312
312
|
white-space: nowrap;
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
-
/*
|
|
315
|
+
/* headerBack: an icon-only native button, so the aria-label names it directly; the shell owns no history, so pressing it only emits nile-click { value: 'back' }. */
|
|
316
316
|
.back {
|
|
317
317
|
flex: 0 0 auto;
|
|
318
318
|
display: inline-flex;
|
|
319
319
|
align-items: center;
|
|
320
|
-
gap: var(--nile-spacing-xs, var(--ng-spacing-xs));
|
|
321
320
|
margin: 0;
|
|
322
321
|
padding: 0;
|
|
323
322
|
border: 0;
|
|
324
323
|
background: none;
|
|
325
324
|
cursor: pointer;
|
|
326
|
-
|
|
327
|
-
font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));
|
|
328
|
-
line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));
|
|
329
|
-
font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));
|
|
330
|
-
color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));
|
|
325
|
+
color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));
|
|
331
326
|
}
|
|
332
327
|
|
|
333
328
|
.back:hover {
|
|
334
329
|
color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));
|
|
335
330
|
}
|
|
336
331
|
|
|
337
|
-
|
|
338
|
-
flex: 0 0 auto;
|
|
339
|
-
display: inline-flex;
|
|
340
|
-
align-items: center;
|
|
341
|
-
color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/* Leading=AppIcon: a 20px block before the title; the page slots the mark, the shell owns the box, surface and radius. */
|
|
332
|
+
/* App icon: a 20px block at the start of the title row, so the description lines up under it; shown whenever the app-icon slot has content. */
|
|
345
333
|
.app-icon {
|
|
346
334
|
position: relative;
|
|
347
335
|
flex: 0 0 auto;
|
|
@@ -384,16 +372,15 @@ export const styles = css `
|
|
|
384
372
|
padding: 1.4px;
|
|
385
373
|
}
|
|
386
374
|
|
|
387
|
-
:host(:not([
|
|
388
|
-
:host(:not([leading='back'])) .back,
|
|
389
|
-
:host(:not([leading='back'])) .crumb-divider {
|
|
375
|
+
:host(:not([has-app-icon])) .app-icon {
|
|
390
376
|
display: none;
|
|
391
377
|
}
|
|
392
378
|
|
|
379
|
+
/* Figma's Header Bar gap: 16px between every header action, the divider and Ask. */
|
|
393
380
|
.top-bar-actions {
|
|
394
381
|
display: flex;
|
|
395
382
|
align-items: center;
|
|
396
|
-
gap: var(--nile-spacing-
|
|
383
|
+
gap: var(--nile-spacing-xl, var(--ng-spacing-xl));
|
|
397
384
|
margin-inline-start: auto;
|
|
398
385
|
}
|
|
399
386
|
|
|
@@ -402,7 +389,7 @@ export const styles = css `
|
|
|
402
389
|
display: none;
|
|
403
390
|
}
|
|
404
391
|
|
|
405
|
-
/* The Ask button: a stock <nile-button variant="
|
|
392
|
+
/* The Ask button: a stock <nile-button variant="secondary"> the shell renders itself; the only rule here is its flex behaviour as a top-bar item. */
|
|
406
393
|
.ask {
|
|
407
394
|
flex: 0 0 auto;
|
|
408
395
|
}
|
|
@@ -419,10 +406,11 @@ export const styles = css `
|
|
|
419
406
|
height: 16px;
|
|
420
407
|
}
|
|
421
408
|
|
|
409
|
+
/* 10px after the 32px circle is 16px after the 20px glyph (6px overhang + 10), Figma's toggle-to-divider gap. */
|
|
422
410
|
.nav-toggle-group {
|
|
423
411
|
display: flex;
|
|
424
412
|
align-items: center;
|
|
425
|
-
gap: var(--nile-spacing-
|
|
413
|
+
gap: var(--nile-spacing-md-alt, var(--ng-spacing-md-alt));
|
|
426
414
|
}
|
|
427
415
|
|
|
428
416
|
/* Lands the 20px glyph box, not the 32px utility circle, on the 24px origin: (32 - 20) / 2 = 6. */
|
|
@@ -430,10 +418,12 @@ export const styles = css `
|
|
|
430
418
|
margin-inline-start: -6px;
|
|
431
419
|
}
|
|
432
420
|
|
|
421
|
+
/* Figma's Divider Line: a 16px 1px stroke that takes no layout width, so the items on both sides sit a clean 16px from it. Used after the nav toggle and, as ask-rule, before Ask. */
|
|
433
422
|
.rule {
|
|
434
423
|
flex: 0 0 auto;
|
|
435
424
|
width: var(--nile-border-width-1, var(--ng-border-width-1));
|
|
436
|
-
|
|
425
|
+
margin-inline-end: calc(-1 * var(--nile-border-width-1, var(--ng-border-width-1)));
|
|
426
|
+
height: 16px;
|
|
437
427
|
background: var(
|
|
438
428
|
--nile-colors-neutral-400,
|
|
439
429
|
var(--ng-colors-border-secondary)
|
|
@@ -486,6 +476,17 @@ export const styles = css `
|
|
|
486
476
|
/* Scoped to the group, not the slot, so bare tab controls are not stretched to an equal share of the strip. */
|
|
487
477
|
::slotted(nile-nav-tab-group[slot='tabs']) {
|
|
488
478
|
--track-width: 0px;
|
|
479
|
+
/*
|
|
480
|
+
* The active indicator (Figma: fg-brand-primary-alt) is NOT set here: the top placement hard-codes
|
|
481
|
+
* var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)) inside nile-nav-tab-group's shadow tree, and
|
|
482
|
+
* remapping either token from here would also recolour nile-nav-tab's focus ring and focus label. Known limitation (spec A-7).
|
|
483
|
+
*/
|
|
484
|
+
/*
|
|
485
|
+
* The inactive label: nile-nav-tab paints it var(--nile-colors-dark-500, var(--ng-colors-text-secondary-700)), so the strip
|
|
486
|
+
* points the NxtGen fallback at text-quaternary-500. Enterprise defines --nile-colors-dark-500 and is untouched. Inside an
|
|
487
|
+
* underline group nothing else reads text-secondary-700 (only the group's other variants and side placements do).
|
|
488
|
+
*/
|
|
489
|
+
--ng-colors-text-secondary-700: var(--ng-colors-text-quaternary-500);
|
|
489
490
|
flex: 1 1 auto;
|
|
490
491
|
min-width: 0;
|
|
491
492
|
align-self: flex-end;
|
|
@@ -652,7 +653,9 @@ export const styles = css `
|
|
|
652
653
|
|
|
653
654
|
.panel-title {
|
|
654
655
|
margin: 0;
|
|
655
|
-
|
|
656
|
+
/* Figma's Assistant Title: Text lg/Semibold, 18/28 on NxtGen. Enterprise keeps --nile-type-scale-3, and it defines no --ng-* tokens, so the line-height declaration is invalid there and the title inherits its line height exactly as before. */
|
|
657
|
+
font-size: var(--nile-type-scale-3, var(--ng-font-size-text-lg));
|
|
658
|
+
line-height: var(--ng-line-height-text-lg);
|
|
656
659
|
font-weight: var(
|
|
657
660
|
--nile-font-weight-semi-bold,
|
|
658
661
|
var(--ng-font-weight-semibold)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nile-app-shell.css.js","sourceRoot":"","sources":["../../../src/nile-app-shell/nile-app-shell.css.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AAEpF,iJAAiJ;AACjJ,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAobrB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuSvB,CAAC;AAEF,eAAe,CAAC,MAAM,CAAC,CAAC","sourcesContent":["/**\n * Copyright Aquera Inc 2023\n *\n * This source code is licensed under the BSD-3-Clause license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { css } from 'lit';\nimport { utilityControlStyles } from '../internal/app-shell-utility-control-styles';\n\n/** AppShell CSS: a grid of banner, top bar, side-nav track and content column, whose flex row holds the container, aside and docked AI panel. */\nexport const styles = css`\n :host {\n /* Geometry: design tokens where one exists, bare pixels where none does. */\n /* The nav track mirrors nile-side-bar's own width expressions (enterprise 240/70, NxtGen 296/68); keep in step with nile-side-bar.css.ts. */\n --nile-app-shell-side-nav-width: var(\n --nile-width-240px,\n var(--ng-spacing-296, 240px)\n );\n --nile-app-shell-side-nav-rail-width: var(\n --nile-width-70px,\n var(--ng-spacing-68, 70px)\n );\n --nile-app-shell-gutter: var(--nile-spacing-xs, var(--ng-spacing-xs));\n --nile-app-shell-content-padding: var(\n --nile-spacing-3xl,\n var(--ng-spacing-3xl)\n );\n --nile-app-shell-top-bar-height: 68px;\n /* The panel header keeps its own height, distinct from the page header. */\n --nile-app-shell-panel-header-height: 56px;\n --nile-app-shell-tabs-height: 33px;\n /* The leading app icon is its own 20px size, not the 32px utility box. */\n --nile-app-shell-app-icon-size: 20px;\n --nile-app-shell-panel-width: 480px;\n --nile-app-shell-panel-min-width: 360px;\n --nile-app-shell-aside-width: 320px;\n --nile-app-shell-aside-min-width: 240px;\n --nile-app-shell-content-min-width: 640px;\n --nile-app-shell-min-width: 768px;\n --nile-app-shell-centered-width: 824px;\n /* Both tokens are 32px; the literal is the floor with no theme sheet loaded. */\n --nile-app-shell-utility-size: var(\n --nile-spacing-4xl,\n var(--ng-spacing-4xl, 32px)\n );\n --nile-app-shell-radius: var(--nile-radius-xl, var(--ng-radius-2xl));\n --nile-app-shell-duration: var(\n --nile-transition-duration-default,\n var(--ng-transition-duration-default)\n );\n /* NxtGen ships no easing tokens, so the shell names its own. */\n --nile-app-shell-ease: cubic-bezier(0.2, 0, 0, 1);\n\n --_side-nav-track: var(--nile-app-shell-side-nav-width);\n\n position: relative;\n box-sizing: border-box;\n display: grid;\n grid-template-areas:\n 'banner banner'\n 'top-bar top-bar'\n 'side-nav content';\n grid-template-columns: var(--_side-nav-track) minmax(0, 1fr);\n grid-template-rows: auto auto minmax(0, 1fr);\n /* Below this the window scrolls rather than the shell compressing. */\n min-width: var(--nile-app-shell-min-width);\n height: 100%;\n overflow: hidden;\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font-family: var(--nile-font-family-sans-serif, var(--ng-font-family-body));\n transition: grid-template-columns var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host([full-height]) {\n height: 100dvh;\n }\n\n /* Effective rail state: the user's preference, or a forced rail when narrow. */\n :host([rail]) {\n --_side-nav-track: var(--nile-app-shell-side-nav-rail-width);\n }\n\n :host(:not([has-side-nav])) {\n --_side-nav-track: 0px;\n }\n\n /* The Description axis: a present description adds the 8px its second line occupies. */\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 76px;\n }\n\n /* The top bar compresses before the content does. */\n @media (max-height: 600px) {\n :host {\n --nile-app-shell-top-bar-height: 56px;\n }\n\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 64px;\n }\n }\n\n /* ---------------------------------------------------------------- banner */\n\n .banner {\n grid-area: banner;\n min-width: 0;\n }\n\n :host(:not([has-banner])) .banner {\n display: none;\n }\n\n /* ------------------------------------------------------------- side nav */\n\n .side-nav {\n grid-area: side-nav;\n display: flex;\n min-width: 0;\n overflow: hidden;\n }\n\n :host(:not([has-side-nav])) .side-nav {\n display: none;\n }\n\n /* A slotted sidebar fills the shell-owned track and drops its own surface and edge; set --nile-app-shell-side-nav-bg to restore one. */\n /* width is deliberately not !important: the 100% lets a raw <nav> or nile-app-shell-side-nav fill the track, while a slotted\n nile-side-bar sizes itself from the same tokens the track reads (see the :host geometry block). Tests 21/22 in\n nile-app-shell-regions.test.ts lock the two together; change both or neither. */\n ::slotted([slot='side-nav']) {\n width: 100%;\n height: 100%;\n background: var(--nile-app-shell-side-nav-bg, transparent) !important;\n border-right: var(--nile-app-shell-side-nav-border, 0) !important;\n }\n\n /* -------------------------------------------------------- content column */\n\n .content-section {\n grid-area: content;\n position: relative;\n display: flex;\n min-width: 0;\n gap: var(--nile-app-shell-gutter);\n padding: var(--nile-app-shell-gutter);\n /* Flush against the nav track; the gutter insets the other three sides. */\n padding-inline-start: 0;\n box-sizing: border-box;\n }\n\n /* With no nav track there is nothing to sit flush against, so the start edge takes the gutter too. */\n :host(:not([has-side-nav])) .content-section {\n padding-inline-start: var(--nile-app-shell-gutter);\n }\n\n .container {\n box-sizing: border-box;\n /* The floor is the flex basis, not a min-width, so the container yields instead of overflowing the clipped row. */\n flex: 1 1 var(--nile-app-shell-content-min-width);\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-none, var(--ng-shadow-none));\n /* The container, not the viewport, is the sizing context for page content. */\n container-type: inline-size;\n container-name: nile-content;\n }\n\n /* content-container moves the size query context onto the slotted page root so page CSS can query nile-content; opt-in as it brings containment. */\n :host([content-container]) slot:not([name])::slotted(*) {\n container-type: inline-size;\n container-name: nile-content;\n }\n\n :host([flat]) .container {\n background: transparent;\n border-color: transparent;\n border-radius: 0;\n }\n\n /* ---------------------------------------------------------------- top bar */\n\n .top-bar {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n height: var(--nile-app-shell-top-bar-height);\n padding-inline: var(--nile-app-shell-content-padding);\n }\n\n /* The header bar draws no bottom rule in any variant; the only divider comes from the tab rail (see .tabs). */\n\n .shell-top-bar {\n grid-area: top-bar;\n min-width: 0;\n padding-inline: var(--nile-spacing-xl, var(--ng-spacing-xl));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* No slotted bar content and no nav toggle means no bar at all. */\n :host(:not([has-top-bar])) .top-bar {\n display: none;\n }\n\n .top-bar-content {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n flex: 1 1 auto;\n }\n\n /* The title block: the header's own heading, the Leading axis and the badge; renders before the top-bar slot. */\n .title-area {\n display: flex;\n /* Top-aligned, not centred: the leading element belongs to the title's row, not the title-plus-description stack. */\n align-items: flex-start;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n /* The leading line box: exactly the page title's line height, centring whatever leading control sits in it. */\n .leading {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n }\n\n .title-stack {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n min-width: 0;\n }\n\n .title-row {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .page-title {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .description {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* The badge sits on the title row and never shrinks the title away; each surface token pairs a Nile name with its NxtGen equivalent. */\n .badge {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n padding-inline: var(--nile-spacing-md, var(--ng-spacing-md));\n padding-block: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(\n --nile-colors-neutral-400,\n var(--ng-componentcolors-utility-gray-200)\n );\n border-radius: var(--nile-radius-full, var(--ng-radius-full));\n background: var(\n --nile-colors-neutral-100,\n var(--ng-componentcolors-utility-gray-50)\n );\n color: var(\n --nile-colors-dark-500,\n var(--ng-componentcolors-utility-gray-700)\n );\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium));\n white-space: nowrap;\n }\n\n /* Leading=Back: drawn as a breadcrumb label; the shell owns no history, so pressing it only emits nile-header-back. */\n .back {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin: 0;\n padding: 0;\n border: 0;\n background: none;\n cursor: pointer;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));\n }\n\n .back:hover {\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n }\n\n .crumb-divider {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));\n }\n\n /* Leading=AppIcon: a 20px block before the title; the page slots the mark, the shell owns the box, surface and radius. */\n .app-icon {\n position: relative;\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nile-app-shell-app-icon-size);\n height: var(--nile-app-shell-app-icon-size);\n border-radius: var(--nile-radius-sm, var(--ng-radius-sm));\n overflow: hidden;\n }\n\n /* The slotted mark fills the wrapper edge to edge, clipped to the box. */\n .app-icon slot::slotted(*) {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n }\n\n /* The wrapper takes no fill; the rim is a white-12% gradient drawn as a masked ::before, with literal mask fallbacks for the nxtgen-only tokens. */\n .app-icon::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 1;\n background: linear-gradient(\n 180deg,\n rgb(255 255 255 / 12%) 0%,\n rgb(255 255 255 / 0%) 100%\n );\n mask: var(\n --ng-mask-rim,\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0)\n );\n mask-composite: var(--ng-mask-composite-exclude, exclude);\n padding: 1.4px;\n }\n\n :host(:not([leading='app-icon'])) .app-icon,\n :host(:not([leading='back'])) .back,\n :host(:not([leading='back'])) .crumb-divider {\n display: none;\n }\n\n .top-bar-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n margin-inline-start: auto;\n }\n\n /* Hidden when empty, so an empty group's gap does not pull the bar's content short of the padding edge. */\n :host(:not([has-top-bar-actions]):not([has-ask])) .top-bar-actions {\n display: none;\n }\n\n /* The Ask button: a stock <nile-button variant=\"primary\"> the shell renders itself; the only rule here is its flex behaviour as a top-bar item. */\n .ask {\n flex: 0 0 auto;\n }\n\n .ask-mark {\n display: inline-flex;\n align-items: center;\n }\n\n .ask-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 16px;\n height: 16px;\n }\n\n .nav-toggle-group {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-lg, var(--ng-spacing-lg));\n }\n\n /* Lands the 20px glyph box, not the 32px utility circle, on the 24px origin: (32 - 20) / 2 = 6. */\n .nav-toggle {\n margin-inline-start: -6px;\n }\n\n .rule {\n flex: 0 0 auto;\n width: var(--nile-border-width-1, var(--ng-border-width-1));\n height: 24px;\n background: var(\n --nile-colors-neutral-400,\n var(--ng-colors-border-secondary)\n );\n }\n\n /* ------------------------------------------------------- utility controls */\n\n /* The shell's own icon controls (nav toggle, panel back and close): the shared utility-control recipe. */\n ${utilityControlStyles}\n\n /* --------------------------------------------------------------- tab strip */\n\n /* Hoisted out of the scroller so it never scrolls away; sits flush under the top bar and carries the header block's single bottom rule. */\n .tabs {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: stretch;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n min-width: 0;\n /* A floor, not a fixed box: the strip is as tall as the row it holds plus its rule. */\n min-height: var(--nile-app-shell-tabs-height);\n padding-inline: var(--nile-app-shell-content-padding);\n /* The strip carries the rule for the whole header block. */\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n /* The header tab's 0/4/12/4 padding composes the 32px row; the 12px bottom gives the active indicator its band, set via the group's public padding hook. */\n ::slotted([slot='tabs']) {\n --nile-nav-tab-padding: var(--nile-spacing-none, var(--ng-spacing-none))\n var(--nile-spacing-xs, var(--ng-spacing-xs))\n var(--nile-spacing-lg, var(--ng-spacing-lg))\n var(--nile-spacing-xs, var(--ng-spacing-xs));\n }\n\n .tabs::-webkit-scrollbar {\n display: none;\n }\n\n :host(:not([has-tabs])) .tabs,\n :host([notabs]) .tabs {\n display: none;\n }\n\n /* A slotted nile-nav-tab-group drops its own track (--track-width:0 on the host) and is bottom-aligned so its indicator sits on the region's single rule. */\n /* Scoped to the group, not the slot, so bare tab controls are not stretched to an equal share of the strip. */\n ::slotted(nile-nav-tab-group[slot='tabs']) {\n --track-width: 0px;\n flex: 1 1 auto;\n min-width: 0;\n align-self: flex-end;\n }\n\n /* ------------------------------------------------------------------- main */\n\n .main {\n box-sizing: border-box;\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n /* Top and sides only: the page runs to the container's bottom edge. */\n padding: var(--nile-app-shell-content-padding);\n padding-block-end: 0;\n }\n\n .main:focus {\n outline: none;\n }\n\n :host([no-padding]) .main {\n padding: 0;\n }\n\n .main-inner {\n width: 100%;\n min-height: 0;\n }\n\n /* Centred when short, scrolls from the top when tall. */\n :host([content-align='centered']) .main-inner {\n /* width:100% + max-width leaves space for the auto margins to centre it while short, and scroll from the top when tall. */\n width: 100%;\n max-width: var(--nile-app-shell-centered-width);\n margin: auto;\n }\n\n /* ------------------------------------------------------------------ aside */\n\n .aside {\n box-sizing: border-box;\n /* Gives before the page does, down to its own floor. */\n flex: 0 1 var(--nile-app-shell-aside-width);\n min-width: var(--nile-app-shell-aside-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n padding: var(--nile-app-shell-content-padding);\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n border-radius: var(--nile-app-shell-radius);\n }\n\n :host(:not([has-aside])) .aside {\n display: none;\n }\n\n /* -------------------------------------------------------------- AI panel */\n\n .panel {\n box-sizing: border-box;\n /* The panel pushes the page rather than covering it: full width while the row affords it, shrinking to a real min-width floor. */\n flex: 0 1 var(--nile-app-shell-panel-width);\n width: var(--nile-app-shell-panel-width);\n min-width: var(--nile-app-shell-panel-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n /* The panel is elevated, so its edge sits a rung above the container's. */\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n }\n\n /* Docked: a flex sibling. It squeezes the content, it does not cover it. */\n :host(:not([panel-open])) .panel {\n display: none;\n }\n\n /* Overlay: contained to the content column, above it, and animated in. */\n :host([panel-mode='overlay']) .panel {\n position: absolute;\n z-index: 1001;\n inset-block: var(--nile-app-shell-gutter);\n inset-inline-end: var(--nile-app-shell-gutter);\n flex: none;\n display: flex;\n width: min(var(--nile-app-shell-panel-width), 92%);\n visibility: hidden;\n transform: translateX(calc(100% + var(--nile-app-shell-gutter)));\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease),\n visibility 0s linear var(--nile-app-shell-duration);\n }\n\n :host([panel-mode='overlay'][panel-open]) .panel {\n visibility: visible;\n transform: none;\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n /* An unavailable panel is unmounted in either mode. */\n :host(:not([has-panel])) .panel {\n display: none;\n }\n\n .panel-header {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n height: var(--nile-app-shell-panel-header-height);\n padding-inline: var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* The back control for a panel sub-view; stands where the brand mark does in the root view. */\n .panel-back {\n flex: 0 0 auto;\n margin-inline-start: -6px;\n }\n\n /* Mirrors the back control's offset on the end edge: the 20px glyph, not the 32px circle, lands on the padding line. */\n .panel-close {\n margin-inline-end: -6px;\n }\n\n :host([panelback]) .panel-mark {\n display: none;\n }\n\n .panel-heading {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .panel-mark {\n display: inline-flex;\n color: var(\n --nile-colors-primary-600,\n var(--ng-colors-fg-brand-primary-600)\n );\n }\n\n .panel-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 20px;\n height: 20px;\n }\n\n .panel-title {\n margin: 0;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n font-weight: var(\n --nile-font-weight-semi-bold,\n var(--ng-font-weight-semibold)\n );\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .panel-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin-inline-start: auto;\n }\n\n .panel-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n /* 16 under the header, 24 on the sides and bottom. */\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n display: flex;\n flex-direction: column;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n }\n\n .panel-footer {\n flex: 0 0 auto;\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-top: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n :host(:not([has-panel-footer])) .panel-footer {\n display: none;\n }\n\n /* ---------------------------------------------------------- skip link */\n\n .skip-link {\n position: absolute;\n z-index: 1002;\n inset-inline-start: var(--nile-spacing-md, var(--ng-spacing-md));\n inset-block-start: var(--nile-spacing-md, var(--ng-spacing-md));\n display: inline-flex;\n align-items: center;\n padding: var(--nile-spacing-md, var(--ng-spacing-md))\n var(--nile-spacing-lg, var(--ng-spacing-lg));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-radius-md, var(--ng-radius-md));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font: inherit;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n cursor: pointer;\n transform: translateY(-200%);\n transition: transform\n var(--nile-transition-duration-short, var(--ng-transition-duration-fast))\n var(--nile-app-shell-ease);\n }\n\n .skip-link:focus-visible {\n outline: none;\n transform: none;\n box-shadow: 0 0 0 2px\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary)),\n 0 0 0 4px\n var(--nile-colors-primary-600, var(--ng-colors-fg-brand-primary-600));\n }\n\n :host([no-skip-link]) .skip-link {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n .panel,\n .skip-link {\n transition: none;\n }\n }\n`;\n\nexport default [styles];\n"]}
|
|
1
|
+
{"version":3,"file":"nile-app-shell.css.js","sourceRoot":"","sources":["../../../src/nile-app-shell/nile-app-shell.css.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AAEpF,iJAAiJ;AACjJ,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA0arB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoTvB,CAAC;AAEF,eAAe,CAAC,MAAM,CAAC,CAAC","sourcesContent":["/**\n * Copyright Aquera Inc 2023\n *\n * This source code is licensed under the BSD-3-Clause license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { css } from 'lit';\nimport { utilityControlStyles } from '../internal/app-shell-utility-control-styles';\n\n/** AppShell CSS: a grid of banner, top bar, side-nav track and content column, whose flex row holds the container, aside and docked AI panel. */\nexport const styles = css`\n :host {\n /* Geometry: design tokens where one exists, bare pixels where none does. */\n /* The nav track mirrors nile-side-bar's own width expressions (enterprise 240/70, NxtGen 296/68); keep in step with nile-side-bar.css.ts. */\n --nile-app-shell-side-nav-width: var(\n --nile-width-240px,\n var(--ng-spacing-296, 240px)\n );\n --nile-app-shell-side-nav-rail-width: var(\n --nile-width-70px,\n var(--ng-spacing-68, 70px)\n );\n --nile-app-shell-gutter: var(--nile-spacing-xs, var(--ng-spacing-xs));\n --nile-app-shell-content-padding: var(\n --nile-spacing-3xl,\n var(--ng-spacing-3xl)\n );\n --nile-app-shell-top-bar-height: 68px;\n /* The panel header keeps its own height, distinct from the page header. */\n --nile-app-shell-panel-header-height: 56px;\n --nile-app-shell-tabs-height: 33px;\n /* The leading app icon is its own 20px size, not the 32px utility box. */\n --nile-app-shell-app-icon-size: 20px;\n --nile-app-shell-panel-width: 480px;\n --nile-app-shell-panel-min-width: 360px;\n --nile-app-shell-aside-width: 320px;\n --nile-app-shell-aside-min-width: 240px;\n --nile-app-shell-content-min-width: 640px;\n --nile-app-shell-min-width: 768px;\n --nile-app-shell-centered-width: 824px;\n /* Both tokens are 32px; the literal is the floor with no theme sheet loaded. */\n --nile-app-shell-utility-size: var(\n --nile-spacing-4xl,\n var(--ng-spacing-4xl, 32px)\n );\n --nile-app-shell-radius: var(--nile-radius-xl, var(--ng-radius-2xl));\n --nile-app-shell-duration: var(\n --nile-transition-duration-default,\n var(--ng-transition-duration-default)\n );\n /* NxtGen ships no easing tokens, so the shell names its own. */\n --nile-app-shell-ease: cubic-bezier(0.2, 0, 0, 1);\n\n --_side-nav-track: var(--nile-app-shell-side-nav-width);\n\n position: relative;\n box-sizing: border-box;\n display: grid;\n grid-template-areas:\n 'banner banner'\n 'top-bar top-bar'\n 'side-nav content';\n grid-template-columns: var(--_side-nav-track) minmax(0, 1fr);\n grid-template-rows: auto auto minmax(0, 1fr);\n /* Below this the window scrolls rather than the shell compressing. */\n min-width: var(--nile-app-shell-min-width);\n height: 100%;\n overflow: hidden;\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font-family: var(--nile-font-family-sans-serif, var(--ng-font-family-body));\n transition: grid-template-columns var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host([full-height]) {\n height: 100dvh;\n }\n\n /* Effective rail state: the user's preference, or a forced rail when narrow. */\n :host([rail]) {\n --_side-nav-track: var(--nile-app-shell-side-nav-rail-width);\n }\n\n :host(:not([has-side-nav])) {\n --_side-nav-track: 0px;\n }\n\n /* The Description axis: a present description adds the 8px its second line occupies. */\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 76px;\n }\n\n /* The top bar compresses before the content does. */\n @media (max-height: 600px) {\n :host {\n --nile-app-shell-top-bar-height: 56px;\n }\n\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 64px;\n }\n }\n\n /* ---------------------------------------------------------------- banner */\n\n .banner {\n grid-area: banner;\n min-width: 0;\n }\n\n :host(:not([has-banner])) .banner {\n display: none;\n }\n\n /* ------------------------------------------------------------- side nav */\n\n .side-nav {\n grid-area: side-nav;\n display: flex;\n min-width: 0;\n overflow: hidden;\n }\n\n :host(:not([has-side-nav])) .side-nav {\n display: none;\n }\n\n /* A slotted sidebar fills the shell-owned track and drops its own surface and edge; set --nile-app-shell-side-nav-bg to restore one. */\n /* width is deliberately not !important: the 100% lets a raw <nav> or nile-app-shell-side-nav fill the track, while a slotted\n nile-side-bar sizes itself from the same tokens the track reads (see the :host geometry block). Tests 21/22 in\n nile-app-shell-regions.test.ts lock the two together; change both or neither. */\n ::slotted([slot='side-nav']) {\n width: 100%;\n height: 100%;\n background: var(--nile-app-shell-side-nav-bg, transparent) !important;\n border-right: var(--nile-app-shell-side-nav-border, 0) !important;\n }\n\n /* -------------------------------------------------------- content column */\n\n .content-section {\n grid-area: content;\n position: relative;\n display: flex;\n min-width: 0;\n gap: var(--nile-app-shell-gutter);\n padding: var(--nile-app-shell-gutter);\n /* Flush against the nav track; the gutter insets the other three sides. */\n padding-inline-start: 0;\n box-sizing: border-box;\n }\n\n /* With no nav track there is nothing to sit flush against, so the start edge takes the gutter too. */\n :host(:not([has-side-nav])) .content-section {\n padding-inline-start: var(--nile-app-shell-gutter);\n }\n\n .container {\n box-sizing: border-box;\n /* The floor is the flex basis, not a min-width, so the container yields instead of overflowing the clipped row. */\n flex: 1 1 var(--nile-app-shell-content-min-width);\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-none, var(--ng-shadow-none));\n /* The container, not the viewport, is the sizing context for page content. */\n container-type: inline-size;\n container-name: nile-content;\n }\n\n /* content-container moves the size query context onto the slotted page root so page CSS can query nile-content; opt-in as it brings containment. */\n :host([content-container]) slot:not([name])::slotted(*) {\n container-type: inline-size;\n container-name: nile-content;\n }\n\n :host([flat]) .container {\n background: transparent;\n border-color: transparent;\n border-radius: 0;\n }\n\n /* ---------------------------------------------------------------- top bar */\n\n .top-bar {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n height: var(--nile-app-shell-top-bar-height);\n padding-inline: var(--nile-app-shell-content-padding);\n }\n\n /* The header bar draws no bottom rule in any variant; the only divider comes from the tab rail (see .tabs). */\n\n .shell-top-bar {\n grid-area: top-bar;\n min-width: 0;\n padding-inline: var(--nile-spacing-xl, var(--ng-spacing-xl));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* No slotted bar content and no nav toggle means no bar at all. */\n :host(:not([has-top-bar])) .top-bar {\n display: none;\n }\n\n .top-bar-content {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n flex: 1 1 auto;\n }\n\n /* The title block: the back arrow, then the stack (app icon, heading and badge, with the description under them); renders before the top-bar slot. */\n .title-area {\n display: flex;\n /* Top-aligned, not centred: the back arrow belongs to the title's row, not the title-plus-description stack. */\n align-items: flex-start;\n /* Figma's Title Area gap: 16px from the arrow to the stack. */\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n }\n\n /* The back arrow's line box: exactly the page title's line height, centring the arrow on the title row. */\n .back-line {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n min-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n }\n\n .title-stack {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n min-width: 0;\n }\n\n .title-row {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .page-title {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .description {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-quaternary-500));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* The badge sits on the title row and never shrinks the title away; each surface token pairs a Nile name with its NxtGen equivalent. */\n .badge {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n padding-inline: var(--nile-spacing-md, var(--ng-spacing-md));\n padding-block: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(\n --nile-colors-neutral-400,\n var(--ng-componentcolors-utility-gray-200)\n );\n border-radius: var(--nile-radius-full, var(--ng-radius-full));\n background: var(\n --nile-colors-neutral-100,\n var(--ng-componentcolors-utility-gray-50)\n );\n color: var(\n --nile-colors-dark-500,\n var(--ng-componentcolors-utility-gray-700)\n );\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium));\n white-space: nowrap;\n }\n\n /* headerBack: an icon-only native button, so the aria-label names it directly; the shell owns no history, so pressing it only emits nile-click { value: 'back' }. */\n .back {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n margin: 0;\n padding: 0;\n border: 0;\n background: none;\n cursor: pointer;\n color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));\n }\n\n .back:hover {\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n }\n\n /* App icon: a 20px block at the start of the title row, so the description lines up under it; shown whenever the app-icon slot has content. */\n .app-icon {\n position: relative;\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nile-app-shell-app-icon-size);\n height: var(--nile-app-shell-app-icon-size);\n border-radius: var(--nile-radius-sm, var(--ng-radius-sm));\n overflow: hidden;\n }\n\n /* The slotted mark fills the wrapper edge to edge, clipped to the box. */\n .app-icon slot::slotted(*) {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n }\n\n /* The wrapper takes no fill; the rim is a white-12% gradient drawn as a masked ::before, with literal mask fallbacks for the nxtgen-only tokens. */\n .app-icon::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 1;\n background: linear-gradient(\n 180deg,\n rgb(255 255 255 / 12%) 0%,\n rgb(255 255 255 / 0%) 100%\n );\n mask: var(\n --ng-mask-rim,\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0)\n );\n mask-composite: var(--ng-mask-composite-exclude, exclude);\n padding: 1.4px;\n }\n\n :host(:not([has-app-icon])) .app-icon {\n display: none;\n }\n\n /* Figma's Header Bar gap: 16px between every header action, the divider and Ask. */\n .top-bar-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n margin-inline-start: auto;\n }\n\n /* Hidden when empty, so an empty group's gap does not pull the bar's content short of the padding edge. */\n :host(:not([has-top-bar-actions]):not([has-ask])) .top-bar-actions {\n display: none;\n }\n\n /* The Ask button: a stock <nile-button variant=\"secondary\"> the shell renders itself; the only rule here is its flex behaviour as a top-bar item. */\n .ask {\n flex: 0 0 auto;\n }\n\n .ask-mark {\n display: inline-flex;\n align-items: center;\n }\n\n .ask-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 16px;\n height: 16px;\n }\n\n /* 10px after the 32px circle is 16px after the 20px glyph (6px overhang + 10), Figma's toggle-to-divider gap. */\n .nav-toggle-group {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md-alt, var(--ng-spacing-md-alt));\n }\n\n /* Lands the 20px glyph box, not the 32px utility circle, on the 24px origin: (32 - 20) / 2 = 6. */\n .nav-toggle {\n margin-inline-start: -6px;\n }\n\n /* Figma's Divider Line: a 16px 1px stroke that takes no layout width, so the items on both sides sit a clean 16px from it. Used after the nav toggle and, as ask-rule, before Ask. */\n .rule {\n flex: 0 0 auto;\n width: var(--nile-border-width-1, var(--ng-border-width-1));\n margin-inline-end: calc(-1 * var(--nile-border-width-1, var(--ng-border-width-1)));\n height: 16px;\n background: var(\n --nile-colors-neutral-400,\n var(--ng-colors-border-secondary)\n );\n }\n\n /* ------------------------------------------------------- utility controls */\n\n /* The shell's own icon controls (nav toggle, panel back and close): the shared utility-control recipe. */\n ${utilityControlStyles}\n\n /* --------------------------------------------------------------- tab strip */\n\n /* Hoisted out of the scroller so it never scrolls away; sits flush under the top bar and carries the header block's single bottom rule. */\n .tabs {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: stretch;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n min-width: 0;\n /* A floor, not a fixed box: the strip is as tall as the row it holds plus its rule. */\n min-height: var(--nile-app-shell-tabs-height);\n padding-inline: var(--nile-app-shell-content-padding);\n /* The strip carries the rule for the whole header block. */\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n /* The header tab's 0/4/12/4 padding composes the 32px row; the 12px bottom gives the active indicator its band, set via the group's public padding hook. */\n ::slotted([slot='tabs']) {\n --nile-nav-tab-padding: var(--nile-spacing-none, var(--ng-spacing-none))\n var(--nile-spacing-xs, var(--ng-spacing-xs))\n var(--nile-spacing-lg, var(--ng-spacing-lg))\n var(--nile-spacing-xs, var(--ng-spacing-xs));\n }\n\n .tabs::-webkit-scrollbar {\n display: none;\n }\n\n :host(:not([has-tabs])) .tabs,\n :host([notabs]) .tabs {\n display: none;\n }\n\n /* A slotted nile-nav-tab-group drops its own track (--track-width:0 on the host) and is bottom-aligned so its indicator sits on the region's single rule. */\n /* Scoped to the group, not the slot, so bare tab controls are not stretched to an equal share of the strip. */\n ::slotted(nile-nav-tab-group[slot='tabs']) {\n --track-width: 0px;\n /*\n * The active indicator (Figma: fg-brand-primary-alt) is NOT set here: the top placement hard-codes\n * var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)) inside nile-nav-tab-group's shadow tree, and\n * remapping either token from here would also recolour nile-nav-tab's focus ring and focus label. Known limitation (spec A-7).\n */\n /*\n * The inactive label: nile-nav-tab paints it var(--nile-colors-dark-500, var(--ng-colors-text-secondary-700)), so the strip\n * points the NxtGen fallback at text-quaternary-500. Enterprise defines --nile-colors-dark-500 and is untouched. Inside an\n * underline group nothing else reads text-secondary-700 (only the group's other variants and side placements do).\n */\n --ng-colors-text-secondary-700: var(--ng-colors-text-quaternary-500);\n flex: 1 1 auto;\n min-width: 0;\n align-self: flex-end;\n }\n\n /* ------------------------------------------------------------------- main */\n\n .main {\n box-sizing: border-box;\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n /* Top and sides only: the page runs to the container's bottom edge. */\n padding: var(--nile-app-shell-content-padding);\n padding-block-end: 0;\n }\n\n .main:focus {\n outline: none;\n }\n\n :host([no-padding]) .main {\n padding: 0;\n }\n\n .main-inner {\n width: 100%;\n min-height: 0;\n }\n\n /* Centred when short, scrolls from the top when tall. */\n :host([content-align='centered']) .main-inner {\n /* width:100% + max-width leaves space for the auto margins to centre it while short, and scroll from the top when tall. */\n width: 100%;\n max-width: var(--nile-app-shell-centered-width);\n margin: auto;\n }\n\n /* ------------------------------------------------------------------ aside */\n\n .aside {\n box-sizing: border-box;\n /* Gives before the page does, down to its own floor. */\n flex: 0 1 var(--nile-app-shell-aside-width);\n min-width: var(--nile-app-shell-aside-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n padding: var(--nile-app-shell-content-padding);\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n border-radius: var(--nile-app-shell-radius);\n }\n\n :host(:not([has-aside])) .aside {\n display: none;\n }\n\n /* -------------------------------------------------------------- AI panel */\n\n .panel {\n box-sizing: border-box;\n /* The panel pushes the page rather than covering it: full width while the row affords it, shrinking to a real min-width floor. */\n flex: 0 1 var(--nile-app-shell-panel-width);\n width: var(--nile-app-shell-panel-width);\n min-width: var(--nile-app-shell-panel-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n /* The panel is elevated, so its edge sits a rung above the container's. */\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n }\n\n /* Docked: a flex sibling. It squeezes the content, it does not cover it. */\n :host(:not([panel-open])) .panel {\n display: none;\n }\n\n /* Overlay: contained to the content column, above it, and animated in. */\n :host([panel-mode='overlay']) .panel {\n position: absolute;\n z-index: 1001;\n inset-block: var(--nile-app-shell-gutter);\n inset-inline-end: var(--nile-app-shell-gutter);\n flex: none;\n display: flex;\n width: min(var(--nile-app-shell-panel-width), 92%);\n visibility: hidden;\n transform: translateX(calc(100% + var(--nile-app-shell-gutter)));\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease),\n visibility 0s linear var(--nile-app-shell-duration);\n }\n\n :host([panel-mode='overlay'][panel-open]) .panel {\n visibility: visible;\n transform: none;\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n /* An unavailable panel is unmounted in either mode. */\n :host(:not([has-panel])) .panel {\n display: none;\n }\n\n .panel-header {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n height: var(--nile-app-shell-panel-header-height);\n padding-inline: var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* The back control for a panel sub-view; stands where the brand mark does in the root view. */\n .panel-back {\n flex: 0 0 auto;\n margin-inline-start: -6px;\n }\n\n /* Mirrors the back control's offset on the end edge: the 20px glyph, not the 32px circle, lands on the padding line. */\n .panel-close {\n margin-inline-end: -6px;\n }\n\n :host([panelback]) .panel-mark {\n display: none;\n }\n\n .panel-heading {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .panel-mark {\n display: inline-flex;\n color: var(\n --nile-colors-primary-600,\n var(--ng-colors-fg-brand-primary-600)\n );\n }\n\n .panel-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 20px;\n height: 20px;\n }\n\n .panel-title {\n margin: 0;\n /* Figma's Assistant Title: Text lg/Semibold, 18/28 on NxtGen. Enterprise keeps --nile-type-scale-3, and it defines no --ng-* tokens, so the line-height declaration is invalid there and the title inherits its line height exactly as before. */\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-lg));\n line-height: var(--ng-line-height-text-lg);\n font-weight: var(\n --nile-font-weight-semi-bold,\n var(--ng-font-weight-semibold)\n );\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .panel-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin-inline-start: auto;\n }\n\n .panel-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n /* 16 under the header, 24 on the sides and bottom. */\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n display: flex;\n flex-direction: column;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n }\n\n .panel-footer {\n flex: 0 0 auto;\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-top: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n :host(:not([has-panel-footer])) .panel-footer {\n display: none;\n }\n\n /* ---------------------------------------------------------- skip link */\n\n .skip-link {\n position: absolute;\n z-index: 1002;\n inset-inline-start: var(--nile-spacing-md, var(--ng-spacing-md));\n inset-block-start: var(--nile-spacing-md, var(--ng-spacing-md));\n display: inline-flex;\n align-items: center;\n padding: var(--nile-spacing-md, var(--ng-spacing-md))\n var(--nile-spacing-lg, var(--ng-spacing-lg));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-radius-md, var(--ng-radius-md));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font: inherit;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n cursor: pointer;\n transform: translateY(-200%);\n transition: transform\n var(--nile-transition-duration-short, var(--ng-transition-duration-fast))\n var(--nile-app-shell-ease);\n }\n\n .skip-link:focus-visible {\n outline: none;\n transform: none;\n box-shadow: 0 0 0 2px\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary)),\n 0 0 0 4px\n var(--nile-colors-primary-600, var(--ng-colors-fg-brand-primary-600));\n }\n\n :host([no-skip-link]) .skip-link {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n .panel,\n .skip-link {\n transition: none;\n }\n }\n`;\n\nexport default [styles];\n"]}
|