@crowdstrike/glide-core 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion.d.ts +7 -3
- package/dist/button-group.button.d.ts +1 -4
- package/dist/button-group.button.styles.js +1 -0
- package/dist/button-group.d.ts +3 -0
- package/dist/button.d.ts +3 -0
- package/dist/checkbox-group.d.ts +6 -2
- package/dist/checkbox-group.stories.d.ts +1 -1
- package/dist/checkbox.d.ts +5 -4
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.stories.d.ts +1 -1
- package/dist/checkbox.test.basics.js +15 -6
- package/dist/checkbox.test.events.js +12 -4
- package/dist/checkbox.test.focus.js +1 -1
- package/dist/checkbox.test.form.js +1 -0
- package/dist/checkbox.test.interactions.js +44 -7
- package/dist/drawer.d.ts +5 -5
- package/dist/drawer.stories.d.ts +0 -1
- package/dist/dropdown.d.ts +3 -2
- package/dist/icon-button.d.ts +2 -0
- package/dist/input.d.ts +4 -3
- package/dist/input.js +1 -1
- package/dist/label.styles.js +7 -4
- package/dist/library/localize.d.ts +1 -0
- package/dist/menu.js +1 -1
- package/dist/menu.test.events.js +197 -7
- package/dist/menu.test.interactions.js +2 -2
- package/dist/modal.stories.d.ts +1 -0
- package/dist/modal.tertiary-icon.test.basics.js +2 -2
- package/dist/radio-group.d.ts +4 -3
- package/dist/radio-group.stories.d.ts +1 -1
- package/dist/radio.d.ts +1 -2
- package/dist/radio.js +1 -1
- package/dist/split-container.d.ts +1 -1
- package/dist/status-indicator.d.ts +1 -1
- package/dist/tabs.stories.d.ts +1 -0
- package/dist/tag.d.ts +3 -6
- package/dist/textarea.d.ts +4 -3
- package/dist/toggle.d.ts +3 -3
- package/dist/toggle.js +1 -1
- package/dist/toggle.stories.d.ts +1 -1
- package/dist/toggle.test.interactions.js +26 -0
- package/dist/tooltip.d.ts +2 -2
- package/dist/translations/en.js +1 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/ja.js +1 -1
- package/dist/tree.d.ts +1 -1
- package/dist/tree.item.d.ts +0 -3
- package/dist/tree.item.icon-button.d.ts +1 -0
- package/dist/tree.item.icon-button.js +1 -1
- package/dist/tree.item.icon-button.test.basics.js +9 -0
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +2 -0
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.menu.test.basics.js +15 -0
- package/dist/tree.item.styles.js +2 -0
- package/dist/tree.item.test.basics.d.ts +2 -1
- package/dist/tree.item.test.basics.js +46 -4
- package/dist/tree.js +1 -1
- package/dist/tree.test.focus.js +91 -4
- package/package.json +2 -1
package/dist/tree.item.styles.js
CHANGED
@@ -129,11 +129,13 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
129
129
|
display: flex;
|
130
130
|
flex-direction: column;
|
131
131
|
overflow: hidden;
|
132
|
+
visibility: hidden;
|
132
133
|
}
|
133
134
|
|
134
135
|
.expanded {
|
135
136
|
.child-items {
|
136
137
|
block-size: auto;
|
138
|
+
visibility: visible;
|
137
139
|
}
|
138
140
|
}
|
139
141
|
|
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
import './menu.link.js';
|
2
|
+
import './tree.item.menu.js';
|
@@ -1,7 +1,13 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
|
+
import './menu.link.js';
|
3
|
+
import './tree.item.menu.js';
|
2
4
|
import { expect, fixture, html } from '@open-wc/testing';
|
5
|
+
import Menu from './menu.js';
|
3
6
|
import TreeItem from './tree.item.js';
|
7
|
+
import TreeItemMenu from './tree.item.menu.js';
|
4
8
|
TreeItem.shadowRootOptions.mode = 'open';
|
9
|
+
TreeItemMenu.shadowRootOptions.mode = 'open';
|
10
|
+
Menu.shadowRootOptions.mode = 'open';
|
5
11
|
it('registers', () => {
|
6
12
|
expect(window.customElements.get('glide-core-tree-item')).to.equal(TreeItem);
|
7
13
|
});
|
@@ -32,13 +38,49 @@ it('renders with a prefix slot', async () => {
|
|
32
38
|
`);
|
33
39
|
expect(document.querySelector('[data-prefix]')).to.be.ok;
|
34
40
|
});
|
35
|
-
it('
|
36
|
-
await fixture(html `
|
41
|
+
it('adds label to menu target', async () => {
|
42
|
+
const treeItem = await fixture(html `
|
43
|
+
<glide-core-tree-item label="Item">
|
44
|
+
<glide-core-tree-item-menu slot="menu" data-menu>
|
45
|
+
<glide-core-menu-link label="Move" url="/move"> </glide-core-menu-link>
|
46
|
+
</glide-core-tree-item-menu>
|
47
|
+
</glide-core-tree-item>
|
48
|
+
`);
|
49
|
+
const menuTarget = treeItem
|
50
|
+
.querySelector('glide-core-tree-item-menu')
|
51
|
+
?.shadowRoot?.querySelector('glide-core-menu')
|
52
|
+
?.querySelector('glide-core-icon-button');
|
53
|
+
expect(menuTarget?.label).to.equal('Actions for Item');
|
54
|
+
});
|
55
|
+
it('adds Japanese label to menu', async () => {
|
56
|
+
document.documentElement.setAttribute('lang', 'ja');
|
57
|
+
const treeItem = await fixture(html `
|
58
|
+
<glide-core-tree-item label="Item">
|
59
|
+
<glide-core-tree-item-menu slot="menu" data-menu>
|
60
|
+
<glide-core-menu-link label="Move" url="/move"> </glide-core-menu-link>
|
61
|
+
</glide-core-tree-item-menu>
|
62
|
+
</glide-core-tree-item>
|
63
|
+
`);
|
64
|
+
const menuTarget = treeItem
|
65
|
+
.querySelector('glide-core-tree-item-menu')
|
66
|
+
?.shadowRoot?.querySelector('glide-core-menu')
|
67
|
+
?.querySelector('glide-core-icon-button');
|
68
|
+
expect(menuTarget?.label).to.equal('Actions for Item');
|
69
|
+
});
|
70
|
+
it('adds French label to menu', async () => {
|
71
|
+
document.documentElement.setAttribute('lang', 'fr');
|
72
|
+
const treeItem = await fixture(html `
|
37
73
|
<glide-core-tree-item label="Item">
|
38
|
-
<
|
74
|
+
<glide-core-tree-item-menu slot="menu" data-menu>
|
75
|
+
<glide-core-menu-link label="Move" url="/move"> </glide-core-menu-link>
|
76
|
+
</glide-core-tree-item-menu>
|
39
77
|
</glide-core-tree-item>
|
40
78
|
`);
|
41
|
-
|
79
|
+
const menuTarget = treeItem
|
80
|
+
.querySelector('glide-core-tree-item-menu')
|
81
|
+
?.shadowRoot?.querySelector('glide-core-menu')
|
82
|
+
?.querySelector('glide-core-icon-button');
|
83
|
+
expect(menuTarget?.label).to.equal('Actions for Item');
|
42
84
|
});
|
43
85
|
it('renders with a suffix slot', async () => {
|
44
86
|
await fixture(html `
|
package/dist/tree.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,t,o,s){var l
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,s){var r,l=arguments.length,i=l<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,o):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,s);else for(var n=e.length-1;n>=0;n--)(r=e[n])&&(i=(l<3?r(i):l>3?r(t,o,i):r(t,o))||i);return l>3&&i&&Object.defineProperty(t,o,i),i};import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,queryAssignedElements,state}from"lit/decorators.js";import{owSlot,owSlotType}from"./library/ow.js";import GlideCoreTreeItem from"./tree.item.js";import styles from"./tree.styles.js";let GlideCoreTree=class GlideCoreTree extends LitElement{static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("focusin",this.#e),this.removeEventListener("focusout",this.#t)}firstUpdated(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreTreeItem])}render(){return html`<div class="component" role="tree" tabindex="${this.privateTabIndex}" @click="${this.#s}" @keydown="${this.#r}"><slot @slotchange="${this.#l}" ${ref(this.#o)}></slot></div>`}selectItem(e){for(const t of this.slotElements){e===t?(t.setAttribute("selected","true"),this.selectedItem=t):t.removeAttribute("selected");const o=t.selectItem(e);o&&(this.selectedItem=o)}this.dispatchEvent(new CustomEvent("item-selected",{bubbles:!0,detail:e}))}constructor(){super(),this.privateTabIndex=0,this.#o=createRef(),this.addEventListener("focusin",this.#e),this.addEventListener("focusout",this.#t)}#o;#i(e){e?.focus(),this.focusedItem=e}#n(){return[...this.querySelectorAll("glide-core-tree-item")]}#d(){const e=this.#n(),t=new Set;return e.filter((e=>{const o=e.parentElement?.closest("glide-core-tree-item");return!o||o.expanded&&!t.has(o)||t.add(e),!t.has(e)}))}#s(e){const t=e.target;if(t.closest("glide-core-tree-item-icon-button")??t.closest("glide-core-tree-item-menu"))return;const o=t.closest("glide-core-tree-item");o&&(o.hasChildTreeItems&&!o.nonCollapsible?o.toggleExpand():this.selectItem(o))}#e(e){let t;e.target===this?t=this.selectedItem?.checkVisibility({visibilityProperty:!0})?this.selectedItem:this.slotElements[0]:e.target instanceof GlideCoreTreeItem&&(t=e.target,this.privateTabIndex=-1),this.#i(t)}#t(e){e.relatedTarget&&e.relatedTarget instanceof HTMLElement&&this.contains(e.relatedTarget)||(this.privateTabIndex=0,this.focusedItem=void 0)}#r(e){if(!["ArrowRight","ArrowLeft","ArrowDown","ArrowUp","Home","End","Enter"].includes(e.key))return;if(e.target&&e.target instanceof HTMLElement&&(e.target.closest("glide-core-tree-item-icon-button")??e.target.closest("glide-core-tree-item-menu")))return;const t=this.#d(),{focusedItem:o}=this,s=t.findIndex((e=>e.matches(":focus")));if("ArrowRight"===e.key&&o?.hasChildTreeItems&&(o.expanded?this.#i(o.slotElements[0]):o.toggleExpand()),"ArrowLeft"===e.key)if(o?.expanded&&!o.nonCollapsible)o.toggleExpand();else{const e=o?.parentElement?.closest("glide-core-tree-item");this.#i(e)}"ArrowDown"===e.key&&-1!==s&&s<t.length-1&&this.#i(t[s+1]),"ArrowUp"===e.key&&s>0&&this.#i(t[s-1]),"Home"===e.key&&this.#i(t[0]),"End"===e.key&&this.#i(t.at(-1)),"Enter"===e.key&&o&&(o.hasChildTreeItems&&!o.nonCollapsible?o.toggleExpand():this.selectItem(o))}#l(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreTreeItem])}};__decorate([state()],GlideCoreTree.prototype,"selectedItem",void 0),__decorate([state()],GlideCoreTree.prototype,"focusedItem",void 0),__decorate([state()],GlideCoreTree.prototype,"privateTabIndex",void 0),__decorate([queryAssignedElements()],GlideCoreTree.prototype,"slotElements",void 0),GlideCoreTree=__decorate([customElement("glide-core-tree")],GlideCoreTree);export default GlideCoreTree;
|
package/dist/tree.test.focus.js
CHANGED
@@ -34,6 +34,23 @@ it('focuses the selected tree item on `focus()`, if there is one', async () => {
|
|
34
34
|
assert(document.activeElement instanceof GlideCoreTreeItem);
|
35
35
|
expect(document.activeElement?.label).to.equal(childItems[1].label);
|
36
36
|
});
|
37
|
+
it('does not focus the selected tree item on `focus()` if collapsed', async () => {
|
38
|
+
const tree = await fixture(html `
|
39
|
+
<glide-core-tree>
|
40
|
+
<glide-core-tree-item label="Child Item 1"> </glide-core-tree-item>
|
41
|
+
<glide-core-tree-item label="Child Item 2">
|
42
|
+
<glide-core-tree-item
|
43
|
+
label="Grandchild Item 1"
|
44
|
+
selected
|
45
|
+
></glide-core-tree-item>
|
46
|
+
</glide-core-tree-item>
|
47
|
+
</glide-core-tree>
|
48
|
+
`);
|
49
|
+
const childItems = tree.slotElements;
|
50
|
+
tree.dispatchEvent(new Event('focusin'));
|
51
|
+
await tree.updateComplete;
|
52
|
+
expect(document.activeElement === childItems[0]).to.equal(true);
|
53
|
+
});
|
37
54
|
it('expands a tree item if right arrow is pressed', async () => {
|
38
55
|
const tree = await fixture(html `
|
39
56
|
<glide-core-tree>
|
@@ -100,8 +117,12 @@ it(`focuses on a non-collapsible tree item's parent if left arrow is pressed`, a
|
|
100
117
|
it(`focuses on a collapsed tree item's parent if left arrow is pressed`, async () => {
|
101
118
|
const tree = await fixture(html `
|
102
119
|
<glide-core-tree>
|
103
|
-
<glide-core-tree-item label="Child Item 1">
|
104
|
-
<glide-core-tree-item label="Grandchild Item 1"
|
120
|
+
<glide-core-tree-item expanded label="Child Item 1">
|
121
|
+
<glide-core-tree-item label="Grandchild Item 1">
|
122
|
+
<glide-core-tree-item
|
123
|
+
label="Great Grandchild Item 1"
|
124
|
+
></glide-core-tree-item>
|
125
|
+
</glide-core-tree-item>
|
105
126
|
</glide-core-tree-item>
|
106
127
|
<glide-core-tree-item label="Child Item 2"></glide-core-tree-item>
|
107
128
|
</glide-core-tree>
|
@@ -110,8 +131,7 @@ it(`focuses on a collapsed tree item's parent if left arrow is pressed`, async (
|
|
110
131
|
const grandchildItems = childItems[0].slotElements;
|
111
132
|
grandchildItems[0].focus();
|
112
133
|
await sendKeys({ press: 'ArrowLeft' });
|
113
|
-
|
114
|
-
expect(document.activeElement?.label).to.equal(childItems[0].label);
|
134
|
+
expect(document.activeElement === childItems[0]).to.equal(true);
|
115
135
|
});
|
116
136
|
it('moves down the non-expanded tree items with down arrow', async () => {
|
117
137
|
const tree = await fixture(html `
|
@@ -291,3 +311,70 @@ it('can use the keyboard to navigate to a tree item menu', async () => {
|
|
291
311
|
await sendKeys({ press: 'Tab' });
|
292
312
|
assert(document.activeElement instanceof GlideCoreTreeItemMenu);
|
293
313
|
});
|
314
|
+
it('does not focus on a tree item icon button unless that tree item is focused', async () => {
|
315
|
+
const tree = await fixture(html `
|
316
|
+
<glide-core-tree>
|
317
|
+
<glide-core-tree-item label="Child Item 1"> </glide-core-tree-item>
|
318
|
+
<glide-core-tree-item label="Child Item 2">
|
319
|
+
<glide-core-tree-item-icon-button slot="suffix">
|
320
|
+
<svg viewBox="0 0 24 24">
|
321
|
+
<path d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
322
|
+
</svg>
|
323
|
+
</glide-core-tree-item-icon-button>
|
324
|
+
</glide-core-tree-item>
|
325
|
+
</glide-core-tree>
|
326
|
+
`);
|
327
|
+
tree.dispatchEvent(new Event('focusin'));
|
328
|
+
const childItems = tree.slotElements;
|
329
|
+
childItems[0].focus();
|
330
|
+
await sendKeys({ press: 'Tab' });
|
331
|
+
expect(document.activeElement === document.body).to.equal(true);
|
332
|
+
childItems[1].focus();
|
333
|
+
await sendKeys({ press: 'Tab' });
|
334
|
+
expect(document.activeElement instanceof GlideCoreTreeItemIconButton).to.equal(true);
|
335
|
+
await sendKeys({ down: 'Shift' });
|
336
|
+
await sendKeys({ press: 'Tab' });
|
337
|
+
await sendKeys({ up: 'Shift' });
|
338
|
+
expect(document.activeElement === childItems[1]).to.equal(true, 'can keyboard navigate back to the parent Tree Item');
|
339
|
+
});
|
340
|
+
it('does not focus on a tree item menu unless that tree item is focused', async () => {
|
341
|
+
const tree = await fixture(html `
|
342
|
+
<glide-core-tree>
|
343
|
+
<glide-core-tree-item label="Child Item 1"> </glide-core-tree-item>
|
344
|
+
<glide-core-tree-item label="Child Item 2">
|
345
|
+
<glide-core-tree-item-menu slot="menu">
|
346
|
+
<glide-core-menu-link label="Edit" url="/edit">
|
347
|
+
</glide-core-menu-link>
|
348
|
+
</glide-core-tree-item-menu>
|
349
|
+
</glide-core-tree-item>
|
350
|
+
</glide-core-tree>
|
351
|
+
`);
|
352
|
+
tree.dispatchEvent(new Event('focusin'));
|
353
|
+
const childItems = tree.slotElements;
|
354
|
+
childItems[0].focus();
|
355
|
+
await sendKeys({ press: 'Tab' });
|
356
|
+
expect(document.activeElement === document.body).to.equal(true);
|
357
|
+
childItems[1].focus();
|
358
|
+
await sendKeys({ press: 'Tab' });
|
359
|
+
expect(document.activeElement instanceof GlideCoreTreeItemMenu).to.equal(true);
|
360
|
+
});
|
361
|
+
it('does not select a tree item if Enter is pressed while its tree item icon button is focused', async () => {
|
362
|
+
const tree = await fixture(html `
|
363
|
+
<glide-core-tree>
|
364
|
+
<glide-core-tree-item label="Child Item 1">
|
365
|
+
<glide-core-tree-item-icon-button slot="suffix">
|
366
|
+
<svg viewBox="0 0 24 24">
|
367
|
+
<path d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
368
|
+
</svg>
|
369
|
+
</glide-core-tree-item-icon-button>
|
370
|
+
</glide-core-tree-item>
|
371
|
+
</glide-core-tree>
|
372
|
+
`);
|
373
|
+
tree.dispatchEvent(new Event('focusin'));
|
374
|
+
const childItems = tree.slotElements;
|
375
|
+
childItems[0].focus();
|
376
|
+
await sendKeys({ press: 'Tab' });
|
377
|
+
expect(document.activeElement instanceof GlideCoreTreeItemIconButton).to.equal(true);
|
378
|
+
await sendKeys({ press: 'Enter' });
|
379
|
+
expect(childItems[0].hasAttribute('selected')).to.equal(false);
|
380
|
+
});
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@crowdstrike/glide-core",
|
3
|
-
"version": "0.9.
|
3
|
+
"version": "0.9.1",
|
4
4
|
"description": "CrowdStrike's Glide Design System components package for providing web components",
|
5
5
|
"author": "CrowdStrike UX Team",
|
6
6
|
"license": "Apache-2.0",
|
@@ -70,6 +70,7 @@
|
|
70
70
|
"@web/test-runner-commands": "^0.9.0",
|
71
71
|
"@web/test-runner-playwright": "^0.11.0",
|
72
72
|
"chalk": "^5.3.0",
|
73
|
+
"cheerio": "^1.0.0",
|
73
74
|
"esbuild": "^0.19.12",
|
74
75
|
"eslint": "^8.56.0",
|
75
76
|
"eslint-config-prettier": "^9.1.0",
|