chore: removed accidentally committed directory
This commit is contained in:
parent
a1f1270671
commit
886151ba85
8 changed files with 0 additions and 455 deletions
|
|
@ -1,3 +0,0 @@
|
|||
# Lion Drawer Overview
|
||||
|
||||
[=> See Source <=](../../../docs/components/drawer/overview.md)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# Lion Drawer Use Cases
|
||||
|
||||
[=> See Source <=](../../../docs/components/drawer/use-cases.md)
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { LionDrawer } from './src/LionDrawer.js';
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { LionDrawer } from './src/LionDrawer.js';
|
||||
|
||||
customElements.define('lion-drawer', LionDrawer);
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
{
|
||||
"name": "@lion/drawer",
|
||||
"version": "0.0.0",
|
||||
"description": "Drawer that can be expanded to reveal it contents",
|
||||
"license": "MIT",
|
||||
"author": "ing-bank",
|
||||
"homepage": "https://github.com/ing-bank/lion/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ing-bank/lion.git",
|
||||
"directory": "packages/drawer"
|
||||
},
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./define": "./lion-drawer.js",
|
||||
"./docs/*": "./docs/*"
|
||||
},
|
||||
"main": "index.js",
|
||||
"module": "index.js",
|
||||
"files": [
|
||||
"*.d.ts",
|
||||
"*.js",
|
||||
"custom-elements.json",
|
||||
"docs",
|
||||
"src",
|
||||
"test",
|
||||
"test-helpers",
|
||||
"translations",
|
||||
"types"
|
||||
],
|
||||
"scripts": {
|
||||
"custom-elements-manifest": "custom-elements-manifest analyze --litelement --exclude \"docs/**/*\" \"test-helpers/**/*\"",
|
||||
"debug": "cd ../../ && npm run debug -- --group drawer",
|
||||
"debug:firefox": "cd ../../ && npm run debug:firefox -- --group drawer",
|
||||
"debug:webkit": "cd ../../ && npm run debug:webkit -- --group drawer",
|
||||
"publish-docs": "node ../../packages-node/publish-docs/src/cli.js --github-url https://github.com/ing-bank/lion/ --git-root-dir ../../",
|
||||
"prepublishOnly": "npm run publish-docs && npm run custom-elements-manifest",
|
||||
"test": "cd ../../ && npm run test:browser -- --group drawer"
|
||||
},
|
||||
"sideEffects": [
|
||||
"lion-drawer.js",
|
||||
"./docs/styled-drawer-content.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@lion/collapsible": "^0.9.1",
|
||||
"@lion/core": "^0.24.0"
|
||||
},
|
||||
"keywords": [
|
||||
"drawer",
|
||||
"lion",
|
||||
"web-components"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"customElements": "custom-elements.json"
|
||||
}
|
||||
|
|
@ -1,217 +0,0 @@
|
|||
import { html } from '@lion/core';
|
||||
import { LionCollapsible } from '@lion/collapsible';
|
||||
import { drawerStyle } from './drawerStyle.js';
|
||||
|
||||
const EVENT = {
|
||||
TRANSITION_END: 'transitionend',
|
||||
TRANSITION_START: 'transitionstart',
|
||||
};
|
||||
|
||||
export class LionDrawer extends LionCollapsible {
|
||||
static get properties() {
|
||||
return {
|
||||
transitioning: {
|
||||
type: Boolean,
|
||||
reflect: true,
|
||||
},
|
||||
opened: {
|
||||
type: Boolean,
|
||||
reflect: true,
|
||||
},
|
||||
position: {
|
||||
type: String,
|
||||
reflect: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
/** @private */
|
||||
this.__toggle = () => {
|
||||
this.opened = !this.opened;
|
||||
};
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
if (!this.hasAttribute('position')) {
|
||||
this.position = 'left';
|
||||
}
|
||||
|
||||
if (this._contentNode) {
|
||||
this._contentNode.style.setProperty('display', '');
|
||||
}
|
||||
|
||||
this.__setBoundaries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update aria labels on state change.
|
||||
* @param {import('@lion/core').PropertyValues } changedProperties
|
||||
*/
|
||||
updated(changedProperties) {
|
||||
if (changedProperties.has('opened')) {
|
||||
this._openedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [drawerStyle];
|
||||
}
|
||||
|
||||
__setBoundaries() {
|
||||
const host = this.shadowRoot?.host;
|
||||
|
||||
if (this.position === 'top') {
|
||||
this.minHeight = host ? getComputedStyle(host).getPropertyValue('--min-height') : '0px';
|
||||
this.maxHeight = host ? getComputedStyle(host).getPropertyValue('--max-height') : '0px';
|
||||
this.minWidth = '0px';
|
||||
this.maxWidth = 'none';
|
||||
} else {
|
||||
this.minWidth = host ? getComputedStyle(host).getPropertyValue('--min-width') : '0px';
|
||||
this.maxWidth = host ? getComputedStyle(host).getPropertyValue('--max-width') : '0px';
|
||||
this.minHeight = 'auto';
|
||||
this.maxHeight = 'fit-content';
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const prop = this.position === 'top' ? 'width' : 'height';
|
||||
|
||||
if (this.__contentNode) {
|
||||
this.__contentNode.style.setProperty(prop, '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for position property, available values are 'top', 'left' and 'right'
|
||||
* @param {String} position
|
||||
*/
|
||||
set position(position) {
|
||||
const stale = this.position;
|
||||
this._position = position;
|
||||
this.setAttribute('position', position);
|
||||
|
||||
this.__setBoundaries();
|
||||
this.requestUpdate('position', stale);
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position ?? 'left';
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger show animation and wait for transition to be finished.
|
||||
* @param {Object} options - element node and its options
|
||||
* @param {HTMLElement} options.contentNode
|
||||
* @override
|
||||
*/
|
||||
async _showAnimation({ contentNode }) {
|
||||
const min = this.position === 'top' ? this.minHeight : this.minWidth;
|
||||
const max = this.position === 'top' ? this.maxHeight : this.maxWidth;
|
||||
const prop = this.position === 'top' ? 'height' : 'width';
|
||||
|
||||
contentNode.style.setProperty(prop, /** @type {string} */ (min));
|
||||
await new Promise(resolve => requestAnimationFrame(() => resolve(true)));
|
||||
contentNode.style.setProperty(prop, /** @type {string} */ (max));
|
||||
await this._waitForTransition({ contentNode });
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger hide animation and wait for transition to be finished.
|
||||
* @param {Object} options - element node and its options
|
||||
* @param {HTMLElement} options.contentNode
|
||||
* @override
|
||||
*/
|
||||
async _hideAnimation({ contentNode }) {
|
||||
if (
|
||||
((this.position === 'left' || this.position === 'right') &&
|
||||
this._contentWidth === this.minWidth) ||
|
||||
(this.position === 'top' && this._contentHeight === this.minHeight)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const min = this.position === 'top' ? this.minHeight : this.minWidth;
|
||||
const prop = this.position === 'top' ? 'height' : 'width';
|
||||
|
||||
contentNode.style.setProperty(prop, /** @type {string} */ (min));
|
||||
await this._waitForTransition({ contentNode });
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the transition event is finished.
|
||||
* @param {Object} options - element node and its options
|
||||
* @param {HTMLElement} options.contentNode
|
||||
* @returns {Promise<void>} transition event
|
||||
*/
|
||||
_waitForTransition({ contentNode }) {
|
||||
return new Promise(resolve => {
|
||||
const transitionStarted = () => {
|
||||
contentNode.removeEventListener(EVENT.TRANSITION_START, transitionStarted);
|
||||
this.transitioning = true;
|
||||
};
|
||||
contentNode.addEventListener(EVENT.TRANSITION_START, transitionStarted);
|
||||
|
||||
const transitionEnded = () => {
|
||||
contentNode.removeEventListener(EVENT.TRANSITION_END, transitionEnded);
|
||||
this.transitioning = false;
|
||||
resolve();
|
||||
};
|
||||
contentNode.addEventListener(EVENT.TRANSITION_END, transitionEnded);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
get __contentNode() {
|
||||
return /** @type {HTMLElement} */ (this.shadowRoot?.querySelector('.container'));
|
||||
}
|
||||
|
||||
get _contentWidth() {
|
||||
const size = this.__contentNode?.getBoundingClientRect().width || 0;
|
||||
return `${size}px`;
|
||||
}
|
||||
|
||||
get _contentHeight() {
|
||||
const size = this.__contentNode?.getBoundingClientRect().height || 0;
|
||||
return `${size}px`;
|
||||
}
|
||||
|
||||
_openedChanged() {
|
||||
this._updateContentSize();
|
||||
if (this._invokerNode) {
|
||||
this._invokerNode.setAttribute('aria-expanded', `${this.opened}`);
|
||||
}
|
||||
|
||||
this.dispatchEvent(new CustomEvent('opened-changed'));
|
||||
}
|
||||
|
||||
async _updateContentSize() {
|
||||
if (this.__contentNode) {
|
||||
if (this.opened) {
|
||||
await this._showAnimation({ contentNode: this.__contentNode });
|
||||
} else {
|
||||
await this._hideAnimation({ contentNode: this.__contentNode });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="container">
|
||||
<div class="headline-container">
|
||||
<slot name="invoker"></slot>
|
||||
<slot name="headline"></slot>
|
||||
</div>
|
||||
<div class="content-container">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
import { css } from '@lion/core';
|
||||
|
||||
export const drawerStyle = css`
|
||||
:host {
|
||||
display: block;
|
||||
height: 100%;
|
||||
--min-width: 72px;
|
||||
--max-width: 320px;
|
||||
--min-height: auto;
|
||||
--max-height: fit-content;
|
||||
--start-width: var(--min-width);
|
||||
--start-height: 100%;
|
||||
--transition-property: width;
|
||||
}
|
||||
|
||||
:host([position='top']) {
|
||||
width: 100%;
|
||||
--min-width: 0px;
|
||||
--max-width: none;
|
||||
--min-height: 50px;
|
||||
--max-height: 200px;
|
||||
--start-width: 100%;
|
||||
--start-height: var(--min-height);
|
||||
--transition-property: height;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: var(--start-width);
|
||||
height: var(--start-height);
|
||||
min-width: var(--min-width);
|
||||
max-width: var(--max-width);
|
||||
min-height: var(--min-height);
|
||||
max-height: var(--max-height);
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
transition: var(--transition-property) 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
|
||||
}
|
||||
|
||||
.headline-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
:host([position='right']) .headline-container {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
overflow: hidden;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
::slotted([slot='content']) {
|
||||
width: var(--max-width);
|
||||
}
|
||||
`;
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
import { expect, fixture as _fixture } from '@open-wc/testing';
|
||||
import { html } from 'lit/static-html.js';
|
||||
|
||||
import '@lion/drawer/define';
|
||||
|
||||
/**
|
||||
* @typedef {import('../src/LionDrawer').LionDrawer} LionDrawer
|
||||
* @typedef {import('@lion/core').TemplateResult} TemplateResult
|
||||
*/
|
||||
const fixture = /** @type {(arg: TemplateResult) => Promise<LionDrawer>} */ (_fixture);
|
||||
|
||||
const template = html`
|
||||
<lion-drawer>
|
||||
<button slot="invoker">Open</button>
|
||||
<p slot="headline">Headline</p>
|
||||
<div slot="content" class="drawer">This is the content of the drawer</div>
|
||||
</lion-drawer>
|
||||
`;
|
||||
|
||||
describe('<lion-drawer>', () => {
|
||||
describe('Drawer', () => {
|
||||
it('sets position to "left" by default', async () => {
|
||||
const drawer = await fixture(template);
|
||||
expect(drawer.position).to.equal('left');
|
||||
});
|
||||
|
||||
it('has [position] attribute which serves as styling hook', async () => {
|
||||
const drawer = await fixture(template);
|
||||
expect(drawer).to.have.attribute('position').equal('left');
|
||||
});
|
||||
|
||||
it('sets the minimum and maximum width when position=left', async () => {
|
||||
const drawer = await fixture(template);
|
||||
const minWidth = getComputedStyle(drawer).getPropertyValue('--min-width');
|
||||
const maxWidth = getComputedStyle(drawer).getPropertyValue('--max-width');
|
||||
|
||||
expect(drawer.minWidth).to.equal(minWidth);
|
||||
expect(drawer.maxWidth).to.equal(maxWidth);
|
||||
});
|
||||
|
||||
it('sets the minimum and maximum width when position=right', async () => {
|
||||
const drawer = await fixture(template);
|
||||
drawer.position = 'right';
|
||||
await drawer.updateComplete;
|
||||
|
||||
const minWidth = getComputedStyle(drawer).getPropertyValue('--min-width');
|
||||
const maxWidth = getComputedStyle(drawer).getPropertyValue('--max-width');
|
||||
|
||||
expect(drawer.minWidth).to.equal(minWidth);
|
||||
expect(drawer.maxWidth).to.equal(maxWidth);
|
||||
});
|
||||
|
||||
it('sets the minimum and maximum height when position=top', async () => {
|
||||
const drawer = await fixture(template);
|
||||
drawer.position = 'top';
|
||||
await drawer.updateComplete;
|
||||
|
||||
const minHeight = getComputedStyle(drawer).getPropertyValue('--min-height');
|
||||
const maxHeight = getComputedStyle(drawer).getPropertyValue('--max-height');
|
||||
|
||||
expect(drawer.minHeight).to.equal(minHeight);
|
||||
expect(drawer.maxHeight).to.equal(maxHeight);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Accessibility', () => {
|
||||
it('[collapsed] is a11y AXE accessible', async () => {
|
||||
const drawer = await fixture(template);
|
||||
await expect(drawer).to.be.accessible();
|
||||
});
|
||||
|
||||
it('[opened] is a11y AXE accessible', async () => {
|
||||
const drawer = await fixture(template);
|
||||
drawer.opened = true;
|
||||
await expect(drawer).to.be.accessible();
|
||||
});
|
||||
|
||||
describe('Invoker', () => {
|
||||
it('links id of content items to invoker via [aria-controls]', async () => {
|
||||
const drawerElement = await fixture(template);
|
||||
const invoker = drawerElement.querySelector('[slot=invoker]');
|
||||
const content = drawerElement.querySelector('[slot=content]');
|
||||
expect(invoker?.getAttribute('aria-controls')).to.equal(content?.id);
|
||||
});
|
||||
|
||||
it('adds aria-expanded="false" to invoker when its content is not expanded', async () => {
|
||||
const drawerElement = await fixture(template);
|
||||
const invoker = drawerElement.querySelector('[slot=invoker]');
|
||||
expect(invoker).to.have.attribute('aria-expanded', 'false');
|
||||
});
|
||||
|
||||
it('adds aria-expanded="true" to invoker when its content is expanded', async () => {
|
||||
const drawerElement = await fixture(template);
|
||||
const invoker = drawerElement.querySelector('[slot=invoker]');
|
||||
drawerElement.opened = true;
|
||||
await drawerElement.updateComplete;
|
||||
expect(invoker).to.have.attribute('aria-expanded', 'true');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Contents', () => {
|
||||
it('adds aria-labelledby referring to invoker id', async () => {
|
||||
const drawerElement = await fixture(template);
|
||||
const invoker = drawerElement.querySelector('[slot=invoker]');
|
||||
const content = drawerElement.querySelector('[slot=content]');
|
||||
expect(content).to.have.attribute('aria-labelledby', invoker?.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue