@aquera/nile-elements 2.0.10 → 2.0.11
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 +852 -0
- package/demo/nxtgen-classes.css +2 -2
- package/demo/nxtgen-properties.css +2 -2
- package/demo/nxtgen-utilities.css +2 -2
- package/demo/nxtgen.css +2 -2
- package/demo/utilities.css +2 -2
- package/demo/variables.css +2 -2
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +579 -296
- package/dist/internal/app-shell-utility-control-styles.cjs.js +2 -0
- package/dist/internal/app-shell-utility-control-styles.cjs.js.map +1 -0
- package/dist/internal/app-shell-utility-control-styles.esm.js +16 -0
- package/dist/nile-app-shell/index.cjs.js +1 -1
- package/dist/nile-app-shell/index.esm.js +1 -1
- 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 +270 -92
- package/dist/nile-app-shell/nile-app-shell.esm.js +61 -10
- package/dist/nile-app-shell/shell-controller.cjs.js.map +1 -1
- package/dist/nile-app-shell-main/nile-app-shell-main.cjs.js.map +1 -1
- package/dist/nile-app-shell-nav-toggle/index.cjs.js +1 -1
- package/dist/nile-app-shell-nav-toggle/index.esm.js +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.cjs.js +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.cjs.js.map +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.cjs.js +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.cjs.js.map +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.esm.js +7 -3
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.esm.js +3 -3
- package/dist/nile-app-shell-panel/index.cjs.js +1 -1
- package/dist/nile-app-shell-panel/index.esm.js +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.cjs.js +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.cjs.js.map +1 -1
- 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 +29 -7
- package/dist/nile-app-shell-panel/nile-app-shell-panel.esm.js +18 -5
- package/dist/nile-app-shell-side-nav/nile-app-shell-side-nav.cjs.js.map +1 -1
- package/dist/nile-app-shell-side-nav/nile-app-shell-side-nav.css.cjs.js.map +1 -1
- package/dist/src/internal/app-shell-utility-control-styles.d.ts +12 -0
- package/dist/src/internal/app-shell-utility-control-styles.js +29 -0
- package/dist/src/internal/app-shell-utility-control-styles.js.map +1 -0
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.d.ts +3 -0
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.js +206 -0
- 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.d.ts +1 -9
- package/dist/src/nile-app-shell/nile-app-shell.css.js +270 -99
- 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 +90 -122
- package/dist/src/nile-app-shell/nile-app-shell.js +224 -143
- 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 +3 -0
- package/dist/src/nile-app-shell/nile-app-shell.test.js +898 -29
- package/dist/src/nile-app-shell/nile-app-shell.test.js.map +1 -1
- package/dist/src/nile-app-shell/shell-controller.d.ts +1 -8
- package/dist/src/nile-app-shell/shell-controller.js +2 -14
- package/dist/src/nile-app-shell/shell-controller.js.map +1 -1
- package/dist/src/nile-app-shell-main/nile-app-shell-main.d.ts +2 -6
- package/dist/src/nile-app-shell-main/nile-app-shell-main.js +2 -6
- package/dist/src/nile-app-shell-main/nile-app-shell-main.js.map +1 -1
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.d.ts +1 -4
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.js +7 -5
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.js.map +1 -1
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.d.ts +4 -8
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.js +5 -6
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.js.map +1 -1
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js +28 -5
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js.map +1 -1
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.d.ts +18 -13
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.js +45 -16
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.js.map +1 -1
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.d.ts +1 -4
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.js +1 -4
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.js.map +1 -1
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.d.ts +4 -12
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.js +4 -12
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.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/dist/version.cjs.js +1 -1
- package/dist/version.cjs.js.map +1 -1
- package/dist/version.esm.js +1 -1
- package/package.json +1 -1
- package/plop-templates/lit/lit.test.ts.hbs +22 -0
- package/plop-templates/lit/lit.ts.hbs +10 -5
- package/plopfile.js +12 -0
- package/src/internal/app-shell-utility-control-styles.ts +30 -0
- package/src/nile-app-shell/nile-app-shell-regions.test.ts +248 -0
- package/src/nile-app-shell/nile-app-shell.css.ts +270 -99
- package/src/nile-app-shell/nile-app-shell.test.ts +1120 -29
- package/src/nile-app-shell/nile-app-shell.ts +241 -148
- package/src/nile-app-shell/shell-controller.ts +2 -14
- package/src/nile-app-shell-main/nile-app-shell-main.ts +2 -6
- package/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.ts +7 -5
- package/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.ts +7 -11
- package/src/nile-app-shell-panel/nile-app-shell-panel.css.ts +28 -5
- package/src/nile-app-shell-panel/nile-app-shell-panel.ts +44 -16
- package/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.ts +1 -4
- package/src/nile-app-shell-side-nav/nile-app-shell-side-nav.ts +4 -12
- package/vscode-html-custom-data.json +114 -37
package/dist/version.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
System.register([],function(_export,_context){"use strict";var e;function n(){var _ref;return(_ref=function(){if("undefined"==typeof window||"function"!=typeof getComputedStyle)return null;try{return getComputedStyle(document.documentElement).getPropertyValue("--nile-version").trim().replace(/^["']|["']$/g,"")||null;}catch(_unused){return null;}}())!==null&&_ref!==void 0?_ref:"1.3.
|
|
1
|
+
System.register([],function(_export,_context){"use strict";var e;function n(){var _ref;return(_ref=function(){if("undefined"==typeof window||"function"!=typeof getComputedStyle)return null;try{return getComputedStyle(document.documentElement).getPropertyValue("--nile-version").trim().replace(/^["']|["']$/g,"")||null;}catch(_unused){return null;}}())!==null&&_ref!==void 0?_ref:"1.3.4";}return{setters:[],execute:function execute(){if("undefined"!=typeof window){window.nileElementsVersion="__NILE_ELEMENTS_VERSION__";e=null;Object.defineProperty(window,"nileVersion",{configurable:!0,get:function get(){return e!==null&&e!==void 0?e:n();},set:function set(n){e=n;}}),window.process=window.process||{env:{NODE_ENV:"production"}};}}};});
|
|
2
2
|
//# sourceMappingURL=version.cjs.js.map
|
package/dist/version.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.cjs.js","sources":["../../src/version.ts","../../nile/lib/version.js"],"sourcesContent":["// Version utility.\n//\n// NILE_ELEMENTS_VERSION is this package's own version and is still substituted\n// at build time by scripts/replace-version.cjs.\n//\n// The tokens version is read from the loaded Nile stylesheet's --nile-version\n// custom property (stamped by @aquera/nile's scripts/stamp-css-version.mjs),\n// falling back to the @aquera/nile installed alongside this package.\n//\n// Reading the stylesheet is what makes a tokens-only release visible. The\n// imported constant alone is not enough: rollup.config.js bundles\n// @aquera/nile/lib/version.js into dist/index.js, so on the CDN build it is\n// frozen at this package's build time. The stylesheet is the live source.\nimport { NILE_VERSION as BUILT_IN_NILE_VERSION } from '@aquera/nile/lib/version.js';\n\nexport const NILE_ELEMENTS_VERSION = '__NILE_ELEMENTS_VERSION__';\n\nfunction readStylesheetNileVersion(): string | null {\n if (typeof window === 'undefined' || typeof getComputedStyle !== 'function') {\n return null;\n }\n\n try {\n const value = getComputedStyle(document.documentElement)\n .getPropertyValue('--nile-version')\n .trim()\n .replace(/^[\"']|[\"']$/g, '');\n\n return value || null;\n } catch {\n return null;\n }\n}\n\n/**\n * The version of @aquera/nile (tokens/stylesheets) whose CSS is loaded in the\n * page, falling back to the @aquera/nile bundled into this package when no\n * stamped stylesheet is present.\n *\n * This is the canonical runtime API. It resolves on every call rather than\n * caching, so it is correct even when the Nile stylesheet is added to the page\n * after this module evaluates - which is the common case, and why no\n * module-evaluation-time snapshot of it is exported.\n */\nexport function getNileVersion(): string {\n return readStylesheetNileVersion() ?? BUILT_IN_NILE_VERSION;\n}\n\n// Set global versions for runtime access\nif (typeof window !== 'undefined') {\n (window as any).nileElementsVersion = NILE_ELEMENTS_VERSION;\n\n // A getter rather than a value, so window.nileVersion reflects whichever\n // stylesheet is loaded at read time regardless of script/style ordering.\n let override: string | null = null;\n Object.defineProperty(window, 'nileVersion', {\n configurable: true,\n get: () => override ?? getNileVersion(),\n set: (value: string) => {\n override = value;\n },\n });\n\n (window as any).process = (window as any).process || {\n env: { NODE_ENV: 'production' },\n };\n}\n","// Generated by scripts/build-version.mjs - do not edit by hand.\nexport const NILE_VERSION = '1.3.
|
|
1
|
+
{"version":3,"file":"version.cjs.js","sources":["../../src/version.ts","../../nile/lib/version.js"],"sourcesContent":["// Version utility.\n//\n// NILE_ELEMENTS_VERSION is this package's own version and is still substituted\n// at build time by scripts/replace-version.cjs.\n//\n// The tokens version is read from the loaded Nile stylesheet's --nile-version\n// custom property (stamped by @aquera/nile's scripts/stamp-css-version.mjs),\n// falling back to the @aquera/nile installed alongside this package.\n//\n// Reading the stylesheet is what makes a tokens-only release visible. The\n// imported constant alone is not enough: rollup.config.js bundles\n// @aquera/nile/lib/version.js into dist/index.js, so on the CDN build it is\n// frozen at this package's build time. The stylesheet is the live source.\nimport { NILE_VERSION as BUILT_IN_NILE_VERSION } from '@aquera/nile/lib/version.js';\n\nexport const NILE_ELEMENTS_VERSION = '__NILE_ELEMENTS_VERSION__';\n\nfunction readStylesheetNileVersion(): string | null {\n if (typeof window === 'undefined' || typeof getComputedStyle !== 'function') {\n return null;\n }\n\n try {\n const value = getComputedStyle(document.documentElement)\n .getPropertyValue('--nile-version')\n .trim()\n .replace(/^[\"']|[\"']$/g, '');\n\n return value || null;\n } catch {\n return null;\n }\n}\n\n/**\n * The version of @aquera/nile (tokens/stylesheets) whose CSS is loaded in the\n * page, falling back to the @aquera/nile bundled into this package when no\n * stamped stylesheet is present.\n *\n * This is the canonical runtime API. It resolves on every call rather than\n * caching, so it is correct even when the Nile stylesheet is added to the page\n * after this module evaluates - which is the common case, and why no\n * module-evaluation-time snapshot of it is exported.\n */\nexport function getNileVersion(): string {\n return readStylesheetNileVersion() ?? BUILT_IN_NILE_VERSION;\n}\n\n// Set global versions for runtime access\nif (typeof window !== 'undefined') {\n (window as any).nileElementsVersion = NILE_ELEMENTS_VERSION;\n\n // A getter rather than a value, so window.nileVersion reflects whichever\n // stylesheet is loaded at read time regardless of script/style ordering.\n let override: string | null = null;\n Object.defineProperty(window, 'nileVersion', {\n configurable: true,\n get: () => override ?? getNileVersion(),\n set: (value: string) => {\n override = value;\n },\n });\n\n (window as any).process = (window as any).process || {\n env: { NODE_ENV: 'production' },\n };\n}\n","// Generated by scripts/build-version.mjs - do not edit by hand.\nexport const NILE_VERSION = '1.3.4';\n"],"names":["getNileVersion","n","_ref","window","getComputedStyle","document","documentElement","getPropertyValue","trim","replace","_unused","readStylesheetNileVersion","setters","execute","nileElementsVersion","override","Object","defineProperty","configurable","get","set","value","process","env","NODE_ENV"],"mappings":"yEA4CgBA,CAAAA,CACdC,CAAA,CAAA,KAAAC,IAAA,CAAA,OAAAA,IAAA,CA5BF,UACE,CAAA,GAAsB,WAAXC,EAAAA,MAAAA,CAAAA,MAAAA,EAAsD,UAArBC,EAAAA,MAAAA,CAAAA,gBAAAA,CAC1C,MAAO,KAAA,CAGT,GAME,CAAA,MALcA,CAAAA,iBAAiBC,QAASC,CAAAA,eAAAA,CAAAA,CACrCC,gBAAiB,CAAA,gBAAA,CAAA,CACjBC,IACAC,CAAAA,CAAAA,CAAAA,OAAAA,CAAQ,cAAgB,CAAA,EAAA,CAAA,EAEX,IACjB,EAAC,MAAAC,OAAA,CACA,CAAA,MAAO,KACR,EACH,CAaSC,CAAAA,CAAAA,UAAAA,IAAAA,UAAAA,IAAAA,CC5CmB,OD6C5B,EAGA,OAAAC,OAAA,IAAAC,OAAA,UAAAA,QAAA,KAAsB,WAAXV,EAAAA,MAAAA,CAAAA,MAAAA,CAAwB,CAChCA,MAAAA,CAAeW,mBAnCmB,CAAA,2BAAA,CAuC/BC,CAAAA,CAA0B,IAC9BC,CAAAA,MAAAA,CAAOC,cAAed,CAAAA,MAAAA,CAAQ,aAAe,CAAA,CAC3Ce,cAAc,CACdC,CAAAA,GAAAA,CAAK,QAALA,CAAAA,GAAAA,CAAAA,QAAWJ,CAAAA,CAAAA,SAAAA,CAAAA,UAAAA,CAAAA,CAAYf,CACvBoB,CAAAA,CAAAA,GAAAA,GAAAA,CAAMC,QAAND,CAAAA,GAAAA,CAAMC,CACJN,CAAAA,CAAAA,CAAAA,CAAWM,CAAK,EAInBlB,CAAAA,CAAAA,CAAAA,MAAAA,CAAemB,OAAWnB,CAAAA,MAAAA,CAAemB,OAAW,EAAA,CACnDC,GAAK,CAAA,CAAEC,SAAU,YAErB,CAAA,CAAA,EAAA"}
|
package/dist/version.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function n(){return function(){if("undefined"==typeof window||"function"!=typeof getComputedStyle)return null;try{return getComputedStyle(document.documentElement).getPropertyValue("--nile-version").trim().replace(/^["']|["']$/g,"")||null}catch{return null}}()??"1.3.
|
|
1
|
+
function n(){return function(){if("undefined"==typeof window||"function"!=typeof getComputedStyle)return null;try{return getComputedStyle(document.documentElement).getPropertyValue("--nile-version").trim().replace(/^["']|["']$/g,"")||null}catch{return null}}()??"1.3.4"}if("undefined"!=typeof window){window.nileElementsVersion="__NILE_ELEMENTS_VERSION__";let e=null;Object.defineProperty(window,"nileVersion",{configurable:!0,get:()=>e??n(),set:n=>{e=n}}),window.process=window.process||{env:{NODE_ENV:"production"}}}
|
package/package.json
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
|
2
|
+
import './nile-{{name}}';
|
|
3
|
+
import type { Nile{{pascalCase name}} } from './nile-{{name}}';
|
|
4
|
+
|
|
5
|
+
// One test per acceptance criterion in kb/specs/nile-{{name}}.md (nile-component skill).
|
|
6
|
+
describe('Nile{{pascalCase name}}', () => {
|
|
7
|
+
it('renders', async () => {
|
|
8
|
+
const el = await fixture<Nile{{pascalCase name}}>(html`<nile-{{name}}></nile-{{name}}>`);
|
|
9
|
+
expect(el).to.exist;
|
|
10
|
+
expect(el.shadowRoot).to.not.be.null;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('exposes the base part', async () => {
|
|
14
|
+
const el = await fixture<Nile{{pascalCase name}}>(html`<nile-{{name}}></nile-{{name}}>`);
|
|
15
|
+
expect(el.shadowRoot!.querySelector('[part="base"]')).to.exist;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('renders slotted content', async () => {
|
|
19
|
+
const el = await fixture<Nile{{pascalCase name}}>(html`<nile-{{name}}><span>content</span></nile-{{name}}>`);
|
|
20
|
+
expect(el.querySelector('span')).to.exist;
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import { customElement
|
|
8
|
+
import { html, CSSResultArray, TemplateResult } from 'lit';
|
|
9
|
+
import { customElement } from 'lit/decorators.js';
|
|
10
10
|
import {styles} from './nile-{{name}}.css';
|
|
11
11
|
import NileElement from '../internal/nile-element';
|
|
12
12
|
|
|
@@ -15,7 +15,11 @@ import NileElement from '../internal/nile-element';
|
|
|
15
15
|
* Nile {{name}} component.
|
|
16
16
|
*
|
|
17
17
|
* @tag nile-{{name}}
|
|
18
|
+
* @summary TODO: one sentence on what nile-{{name}} is for.
|
|
18
19
|
*
|
|
20
|
+
* @slot - The default slot.
|
|
21
|
+
*
|
|
22
|
+
* @csspart base - The component's base wrapper.
|
|
19
23
|
*/
|
|
20
24
|
@customElement('nile-{{name}}')
|
|
21
25
|
export class Nile{{pascalCase name}} extends NileElement {
|
|
@@ -34,12 +38,13 @@ export class Nile{{pascalCase name}} extends NileElement {
|
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
40
|
* Render method
|
|
37
|
-
* @slot This is a slot test
|
|
38
41
|
*/
|
|
39
42
|
public render(): TemplateResult {
|
|
40
43
|
return html`
|
|
41
|
-
<
|
|
42
|
-
|
|
44
|
+
<div part="base">
|
|
45
|
+
<slot></slot>
|
|
46
|
+
</div>
|
|
47
|
+
`;
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
/* #endregion */
|
package/plopfile.js
CHANGED
|
@@ -41,6 +41,18 @@ export default function (plop) {
|
|
|
41
41
|
return JSON.stringify(packageJson, null, 2);
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
|
+
{
|
|
45
|
+
type: 'add',
|
|
46
|
+
path: 'src/nile-{{name}}/nile-{{name}}.test.ts',
|
|
47
|
+
templateFile: 'plop-templates/lit/lit.test.ts.hbs',
|
|
48
|
+
},
|
|
49
|
+
// nile-component skill: print the definition of done for the new component
|
|
50
|
+
(data) =>
|
|
51
|
+
[
|
|
52
|
+
`nile-${data.name} scaffolded. Definition of done: .claude/skills/nile-component/references/checklist.md`,
|
|
53
|
+
` spec: kb/specs/nile-${data.name}.md (from kb/specs/COMPONENT-SPEC-TEMPLATE.md)`,
|
|
54
|
+
` audit: python3 .claude/skills/nile-component/scripts/check-component.py nile-${data.name} --diff master --change-type new`,
|
|
55
|
+
].join('\n'),
|
|
44
56
|
],
|
|
45
57
|
});
|
|
46
58
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Aquera Inc 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the BSD-3-Clause license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { css } from 'lit';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The app shell's utility-control recipe, shared by the shell, the panel and the nav toggle.
|
|
12
|
+
* Restyles a `.utility-control` nile-button from its 38px ghost chip to a bare glyph via ::part,
|
|
13
|
+
* sized to --nile-app-shell-utility-size with a 32px fallback for mounting outside a shell.
|
|
14
|
+
*/
|
|
15
|
+
export const utilityControlStyles = css`
|
|
16
|
+
.utility-control::part(base) {
|
|
17
|
+
width: var(--nile-app-shell-utility-size, 32px);
|
|
18
|
+
height: var(--nile-app-shell-utility-size, 32px);
|
|
19
|
+
min-width: var(--nile-app-shell-utility-size, 32px);
|
|
20
|
+
min-height: var(--nile-app-shell-utility-size, 32px);
|
|
21
|
+
padding: 0;
|
|
22
|
+
background: transparent;
|
|
23
|
+
border-color: transparent;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Restate the hover surface: the button's own hover rule loses to the resting ::part rule above. */
|
|
27
|
+
.utility-control:hover:not([disabled])::part(base) {
|
|
28
|
+
background: var(--nile-colors-dark-200, var(--ng-colors-bg-primary-hover));
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
@@ -3,6 +3,9 @@ import './nile-app-shell';
|
|
|
3
3
|
import '../nile-app-shell-side-nav/nile-app-shell-side-nav';
|
|
4
4
|
import '../nile-app-shell-main/nile-app-shell-main';
|
|
5
5
|
import '../nile-app-shell-panel/nile-app-shell-panel';
|
|
6
|
+
import '../nile-side-bar/nile-side-bar';
|
|
7
|
+
import '../nile-nav-tab-group/nile-nav-tab-group';
|
|
8
|
+
import '../nile-nav-tab/nile-nav-tab';
|
|
6
9
|
import type { NileAppShell } from './nile-app-shell';
|
|
7
10
|
import type { NileAppShellSideNav } from '../nile-app-shell-side-nav/nile-app-shell-side-nav';
|
|
8
11
|
import type { NileAppShellMain } from '../nile-app-shell-main/nile-app-shell-main';
|
|
@@ -212,4 +215,249 @@ describe('nile-app-shell-panel', () => {
|
|
|
212
215
|
await panel.updateComplete;
|
|
213
216
|
expect(panel.getAttribute('aria-label')).to.equal('Ask Nile');
|
|
214
217
|
});
|
|
218
|
+
|
|
219
|
+
it('16. holds the back control until back asks for it', async () => {
|
|
220
|
+
const el = await composed();
|
|
221
|
+
const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');
|
|
222
|
+
const back = () => panel.shadowRoot!.querySelector('[part~="back"]');
|
|
223
|
+
const mark = panel.shadowRoot!.querySelector('.mark')!;
|
|
224
|
+
// Not rendered at all in the root view, so no stylesheet override can surface it.
|
|
225
|
+
expect(back()).to.not.exist;
|
|
226
|
+
expect(getComputedStyle(mark).display).to.not.equal('none');
|
|
227
|
+
|
|
228
|
+
panel.back = true;
|
|
229
|
+
await panel.updateComplete;
|
|
230
|
+
expect(back()).to.exist;
|
|
231
|
+
expect(getComputedStyle(back()!).display).to.not.equal('none');
|
|
232
|
+
// The back control stands where the brand mark stands in the root view.
|
|
233
|
+
expect(getComputedStyle(mark).display).to.equal('none');
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('17. its back control emits nile-back and leaves the panel open', async () => {
|
|
237
|
+
const el = await composed();
|
|
238
|
+
el.openPanel();
|
|
239
|
+
await el.updateComplete;
|
|
240
|
+
|
|
241
|
+
const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');
|
|
242
|
+
panel.back = true;
|
|
243
|
+
panel.backLabel = 'Back to chats';
|
|
244
|
+
await panel.updateComplete;
|
|
245
|
+
|
|
246
|
+
const back =
|
|
247
|
+
panel.shadowRoot!.querySelector<HTMLButtonElement>('[part~="back"]')!;
|
|
248
|
+
expect(back.getAttribute('aria-label')).to.equal('Back to chats');
|
|
249
|
+
|
|
250
|
+
const went = oneEvent(panel, 'nile-back');
|
|
251
|
+
back.click();
|
|
252
|
+
expect(await went).to.exist;
|
|
253
|
+
await el.updateComplete;
|
|
254
|
+
// The panel keeps no view stack, so going back is not closing.
|
|
255
|
+
expect(el.panelOpen).to.be.true;
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Birat's review: a page listening on the shell for nile-panel-back must not go deaf when it slots this panel.
|
|
259
|
+
it('82. its back control also emits nile-panel-back, once, and it reaches the shell', async () => {
|
|
260
|
+
const el = await composed();
|
|
261
|
+
el.openPanel();
|
|
262
|
+
await el.updateComplete;
|
|
263
|
+
|
|
264
|
+
const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');
|
|
265
|
+
panel.back = true;
|
|
266
|
+
await panel.updateComplete;
|
|
267
|
+
|
|
268
|
+
const order: string[] = [];
|
|
269
|
+
const log = (e: Event) => order.push(e.type);
|
|
270
|
+
el.addEventListener('nile-back', log);
|
|
271
|
+
el.addEventListener('nile-panel-back', log);
|
|
272
|
+
|
|
273
|
+
const reached = oneEvent(el, 'nile-panel-back');
|
|
274
|
+
panel.shadowRoot!.querySelector<HTMLButtonElement>('[part~="back"]')!.click();
|
|
275
|
+
const event = await reached;
|
|
276
|
+
|
|
277
|
+
// Bubbles and composed, so a listener outside the shadow roots hears it.
|
|
278
|
+
expect(event.bubbles).to.be.true;
|
|
279
|
+
expect(event.composed).to.be.true;
|
|
280
|
+
// One press: nile-back then nile-panel-back, each exactly once.
|
|
281
|
+
expect(order).to.deep.equal(['nile-back', 'nile-panel-back']);
|
|
282
|
+
|
|
283
|
+
order.length = 0;
|
|
284
|
+
panel.goBack();
|
|
285
|
+
expect(order).to.deep.equal(['nile-back', 'nile-panel-back']);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// The panel draws its header controls as bare glyphs via ::part(base), overriding nile-button's circle and ghost surface.
|
|
289
|
+
it('18. draws its header controls bare, in the utility box', async () => {
|
|
290
|
+
const el = await composed();
|
|
291
|
+
// A closed panel is display:none, and a hidden box measures zero.
|
|
292
|
+
el.openPanel();
|
|
293
|
+
await el.updateComplete;
|
|
294
|
+
|
|
295
|
+
const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');
|
|
296
|
+
panel.back = true;
|
|
297
|
+
await panel.updateComplete;
|
|
298
|
+
|
|
299
|
+
/*
|
|
300
|
+
* The contract is "the control fills the utility box", not "the control is
|
|
301
|
+
* 32px": --nile-app-shell-utility-size is a token chain
|
|
302
|
+
* (--nile-spacing-4xl, else --ng-spacing-4xl -> --ng-spacing-8), and both
|
|
303
|
+
* sheets happen to land on 32 today. Reading the resolved value keeps this
|
|
304
|
+
* honest if either sheet moves. The || 32 is the stylesheet's own literal
|
|
305
|
+
* floor, for this unthemed fixture where neither token is defined.
|
|
306
|
+
*/
|
|
307
|
+
const utility =
|
|
308
|
+
parseFloat(
|
|
309
|
+
getComputedStyle(panel).getPropertyValue('--nile-app-shell-utility-size')
|
|
310
|
+
) || 32;
|
|
311
|
+
expect(utility, 'the utility box resolves to a real size').to.be.above(0);
|
|
312
|
+
|
|
313
|
+
for (const name of ['back', 'close']) {
|
|
314
|
+
const control = panel.shadowRoot!.querySelector(`[part~="${name}"]`)!;
|
|
315
|
+
const base = control.shadowRoot!.querySelector('[part~="base"]')!;
|
|
316
|
+
expect(getComputedStyle(base).backgroundColor).to.equal(
|
|
317
|
+
'rgba(0, 0, 0, 0)'
|
|
318
|
+
);
|
|
319
|
+
const box = base.getBoundingClientRect();
|
|
320
|
+
expect(box.width, `${name} width`).to.equal(utility);
|
|
321
|
+
expect(box.height, `${name} height`).to.equal(utility);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// The panel mounts in the shell's light DOM but sizes its header as its own box, independent of the page header.
|
|
326
|
+
it('19. sizes its header independently of the page header', async () => {
|
|
327
|
+
const el = await composed();
|
|
328
|
+
el.openPanel();
|
|
329
|
+
await el.updateComplete;
|
|
330
|
+
|
|
331
|
+
const panel = region<NileAppShellPanel>(el, 'nile-app-shell-panel');
|
|
332
|
+
const header = () =>
|
|
333
|
+
panel.shadowRoot!.querySelector('.header') as HTMLElement;
|
|
334
|
+
|
|
335
|
+
expect(header().getBoundingClientRect().height).to.equal(56);
|
|
336
|
+
|
|
337
|
+
// The Description axis moves the page header to 76px, but the panel's header must not follow it.
|
|
338
|
+
el.pageTitle = 'Connected applications';
|
|
339
|
+
el.description = 'Everything connected to Aquera';
|
|
340
|
+
await el.updateComplete;
|
|
341
|
+
await panel.updateComplete;
|
|
342
|
+
|
|
343
|
+
expect(el.hasAttribute('has-description')).to.be.true;
|
|
344
|
+
expect(header().getBoundingClientRect().height).to.equal(56);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('20. keeps its 56px header when mounted outside a shell', async () => {
|
|
348
|
+
// No shell, so the literal fallback is the floor; the stray top-bar height stands in for a page that sets it globally.
|
|
349
|
+
const panel = await fixture<NileAppShellPanel>(html`
|
|
350
|
+
<nile-app-shell-panel
|
|
351
|
+
label="Ask Aquera"
|
|
352
|
+
style="--nile-app-shell-top-bar-height: 76px;"
|
|
353
|
+
>
|
|
354
|
+
<div>answer</div>
|
|
355
|
+
</nile-app-shell-panel>
|
|
356
|
+
`);
|
|
357
|
+
|
|
358
|
+
const header = panel.shadowRoot!.querySelector('.header') as HTMLElement;
|
|
359
|
+
expect(header.getBoundingClientRect().height).to.equal(56);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// 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.
|
|
364
|
+
describe('nile-side-bar in the shell track', () => {
|
|
365
|
+
const ENTERPRISE = '--nile-width-240px: 240px; --nile-width-70px: 70px;';
|
|
366
|
+
const NXTGEN = '--ng-spacing-296: 296px; --ng-spacing-68: 68px;';
|
|
367
|
+
|
|
368
|
+
const railedTo = async (tokens: string, expanded: number, rail: number) => {
|
|
369
|
+
const el = await fixture<NileAppShell>(html`
|
|
370
|
+
<nile-app-shell style="width: 1440px; height: 600px; ${tokens}">
|
|
371
|
+
<nile-side-bar slot="side-nav" position="left"></nile-side-bar>
|
|
372
|
+
<p>page</p>
|
|
373
|
+
</nile-app-shell>
|
|
374
|
+
`);
|
|
375
|
+
await waitUntil(() => el.hasAttribute('has-side-nav'));
|
|
376
|
+
const bar = el.querySelector('nile-side-bar')!;
|
|
377
|
+
const width = () => Math.round(bar.getBoundingClientRect().width);
|
|
378
|
+
|
|
379
|
+
expect(width(), 'expanded').to.equal(expanded);
|
|
380
|
+
|
|
381
|
+
el.collapseNav();
|
|
382
|
+
await el.updateComplete;
|
|
383
|
+
await waitUntil(() => width() === rail, 'the rail never settled', {
|
|
384
|
+
timeout: 2000,
|
|
385
|
+
interval: 50,
|
|
386
|
+
});
|
|
387
|
+
expect(width(), 'railed').to.equal(rail);
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
it('21. matches the deployed enterprise side bar: 240 / 70', async () => {
|
|
391
|
+
await railedTo(ENTERPRISE, 240, 70);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('22. matches the deployed nxtgen side bar: 296 / 68', async () => {
|
|
395
|
+
await railedTo(NXTGEN, 296, 68);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// 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.
|
|
399
|
+
it('83. follows an overridden track width: 200 / 50', async () => {
|
|
400
|
+
const overrides =
|
|
401
|
+
'--nile-app-shell-side-nav-width: 200px; --nile-app-shell-side-nav-rail-width: 50px;';
|
|
402
|
+
await railedTo(`${ENTERPRISE} ${overrides}`, 200, 50);
|
|
403
|
+
await railedTo(`${NXTGEN} ${overrides}`, 200, 50);
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
/*
|
|
408
|
+
* The HTML API, driven from markup. pageTitle, backLabel, noTabs, panelBack
|
|
409
|
+
* and panelBackLabel deliberately declare no `attribute:` option, so Lit
|
|
410
|
+
* observes the lowercased property name (pagetitle, notabs, ...) and markup
|
|
411
|
+
* writes them camelCase — HTML lowercases `pageTitle=` to match.
|
|
412
|
+
*
|
|
413
|
+
* Every other test in this suite sets these as JS properties, which works no
|
|
414
|
+
* matter what the attribute is called — so if a kebab `attribute:` option is
|
|
415
|
+
* added back, nothing else fails and `<nile-app-shell pageTitle="...">`
|
|
416
|
+
* silently does nothing. This fixture is markup-only on purpose: it is the
|
|
417
|
+
* one that breaks if that happens.
|
|
418
|
+
*/
|
|
419
|
+
describe('nile-app-shell — the attributes the docs advertise', () => {
|
|
420
|
+
it('23. reads its title block and switches from camelCase markup', async () => {
|
|
421
|
+
const el = await fixture<NileAppShell>(html`
|
|
422
|
+
<nile-app-shell
|
|
423
|
+
style="width: 1440px; height: 600px;"
|
|
424
|
+
pageTitle="Applications"
|
|
425
|
+
backLabel="Integrations"
|
|
426
|
+
leading="back"
|
|
427
|
+
noTabs
|
|
428
|
+
panelBack
|
|
429
|
+
panelBackLabel="Chat history"
|
|
430
|
+
>
|
|
431
|
+
<nav slot="side-nav">nav</nav>
|
|
432
|
+
<nile-nav-tab-group slot="tabs">
|
|
433
|
+
<nile-nav-tab slot="nav" panel="apps" active>Connected</nile-nav-tab>
|
|
434
|
+
</nile-nav-tab-group>
|
|
435
|
+
<p>page</p>
|
|
436
|
+
<div slot="panel">assistant</div>
|
|
437
|
+
</nile-app-shell>
|
|
438
|
+
`);
|
|
439
|
+
await el.updateComplete;
|
|
440
|
+
|
|
441
|
+
// Each attribute reached its property.
|
|
442
|
+
expect(el.pageTitle, 'pageTitle').to.equal('Applications');
|
|
443
|
+
expect(el.backLabel, 'backLabel').to.equal('Integrations');
|
|
444
|
+
expect(el.noTabs, 'noTabs').to.be.true;
|
|
445
|
+
expect(el.panelBack, 'panelBack').to.be.true;
|
|
446
|
+
expect(el.panelBackLabel, 'panelBackLabel').to.equal('Chat history');
|
|
447
|
+
|
|
448
|
+
// And had the effect the attribute promises, not just the assignment.
|
|
449
|
+
const title = el.shadowRoot!.querySelector('[part~="page-title"]');
|
|
450
|
+
expect(title!.textContent!.trim()).to.equal('Applications');
|
|
451
|
+
expect(el.tabsVisible, 'noTabs hides the strip').to.be.false;
|
|
452
|
+
|
|
453
|
+
// The reflecting pair round-trip to the lowercased name, not to kebab.
|
|
454
|
+
expect(el.hasAttribute('notabs')).to.be.true;
|
|
455
|
+
expect(el.hasAttribute('panelback')).to.be.true;
|
|
456
|
+
expect(el.hasAttribute('no-tabs')).to.be.false;
|
|
457
|
+
el.noTabs = false;
|
|
458
|
+
el.panelBack = false;
|
|
459
|
+
await el.updateComplete;
|
|
460
|
+
expect(el.hasAttribute('notabs'), 'notabs is removed again').to.be.false;
|
|
461
|
+
expect(el.hasAttribute('panelback')).to.be.false;
|
|
462
|
+
});
|
|
215
463
|
});
|