@salesforcedevs/dx-components 0.8.0 → 0.8.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/package.json +2 -2
- package/src/modules/dx/dropdown/__tests__/dropdown.test.ts +53 -12
- package/src/modules/dx/dropdown/dropdown.html +0 -1
- package/src/modules/dx/dropdown/dropdown.ts +19 -30
- package/src/modules/dx/headerSearch/__tests__/headerSearch.test.ts +1 -1
- package/src/modules/dx/headerSearch/headerSearch.ts +1 -1
- package/src/modules/dx/popover/__tests__/mockProps.ts +0 -1
- package/src/modules/dx/popover/popover.ts +19 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"@types/debounce": "^1.2.0",
|
|
30
30
|
"@types/lodash.get": "^4.4.6"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "9c9dc1dbb7ff863bfa26b863daac98f638b7c299"
|
|
33
33
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Dropdown from "dx/dropdown";
|
|
2
2
|
import DropdownOption from "dx/dropdownOption";
|
|
3
|
+
import Popover from "dx/popover";
|
|
3
4
|
import { getOptionsCount } from "utils/options";
|
|
4
5
|
import { createRenderComponent } from "utils/tests";
|
|
5
6
|
import mockNestedOptions from "./mockNestedOptions";
|
|
@@ -12,6 +13,13 @@ describe(TAG, () => {
|
|
|
12
13
|
describe("render", () => {
|
|
13
14
|
it("renders all options when open", () => {
|
|
14
15
|
const component = render({ ...mockProps, open: true });
|
|
16
|
+
|
|
17
|
+
const menuDiv: HTMLElement = component.shadowRoot.querySelector(
|
|
18
|
+
".menu_list"
|
|
19
|
+
);
|
|
20
|
+
expect(menuDiv).not.toBeNull();
|
|
21
|
+
expect(menuDiv.getAttribute("role")).toBe("menu");
|
|
22
|
+
|
|
15
23
|
const options = component.shadowRoot.querySelectorAll(
|
|
16
24
|
"dx-dropdown-option"
|
|
17
25
|
);
|
|
@@ -55,6 +63,24 @@ describe(TAG, () => {
|
|
|
55
63
|
expect(id).toEqual(mockProps.value);
|
|
56
64
|
return expect(component).toBeAccessible();
|
|
57
65
|
});
|
|
66
|
+
|
|
67
|
+
it("renders with menu-offset-small and menu-hidden", () => {
|
|
68
|
+
const component = render({ offset: "small", options: [] });
|
|
69
|
+
const popover: Popover = component.shadowRoot.querySelector(
|
|
70
|
+
"dx-popover"
|
|
71
|
+
);
|
|
72
|
+
expect(popover).not.toBeNull();
|
|
73
|
+
|
|
74
|
+
expect(popover.classList).toContain("menu-offset-small");
|
|
75
|
+
expect(popover.classList).toContain("menu-hidden");
|
|
76
|
+
|
|
77
|
+
const options = component.shadowRoot.querySelectorAll(
|
|
78
|
+
"dx-dropdown-option"
|
|
79
|
+
);
|
|
80
|
+
expect(options).toHaveLength(0);
|
|
81
|
+
|
|
82
|
+
return expect(component).toBeAccessible();
|
|
83
|
+
});
|
|
58
84
|
});
|
|
59
85
|
|
|
60
86
|
describe("interactions", () => {
|
|
@@ -98,34 +124,49 @@ describe(TAG, () => {
|
|
|
98
124
|
option.dispatchEvent(new CustomEvent("select", { detail: id }));
|
|
99
125
|
|
|
100
126
|
expect(mockClose).toHaveBeenCalledTimes(1);
|
|
101
|
-
expect(component.open).toEqual(false);
|
|
102
127
|
return expect(component).toBeAccessible();
|
|
103
128
|
});
|
|
104
129
|
|
|
105
|
-
it("handles
|
|
106
|
-
const
|
|
107
|
-
|
|
130
|
+
it("handles keydown event with ArrowDown key", () => {
|
|
131
|
+
const [firstOption] = mockProps.options;
|
|
132
|
+
const component = render({ ...mockProps, value: null, open: true });
|
|
133
|
+
expect(component.focusedValue).toBeNull();
|
|
108
134
|
|
|
109
|
-
|
|
110
|
-
"
|
|
135
|
+
component.dispatchEvent(
|
|
136
|
+
new KeyboardEvent("keydown", { key: "ArrowDown" })
|
|
111
137
|
);
|
|
112
|
-
expect(
|
|
113
|
-
|
|
138
|
+
expect(component.focusedValue).toBe(firstOption.id);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("ignores other click keys", () => {
|
|
142
|
+
const component = render({ ...mockProps, open: true });
|
|
114
143
|
|
|
115
|
-
|
|
144
|
+
component.dispatchEvent(
|
|
145
|
+
new KeyboardEvent("keydown", { key: "ArrowDown" })
|
|
146
|
+
);
|
|
147
|
+
expect(component.focusedValue).toBe(mockProps.value);
|
|
148
|
+
|
|
149
|
+
component.dispatchEvent(
|
|
150
|
+
new KeyboardEvent("keydown", { key: "ArrowLeft" })
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
expect(component.focusedValue).toBe(mockProps.value);
|
|
116
154
|
});
|
|
117
155
|
|
|
118
156
|
it("handles close event from popover", () => {
|
|
119
157
|
const component = render({ ...mockProps, open: true });
|
|
120
|
-
|
|
158
|
+
|
|
159
|
+
component.dispatchEvent(
|
|
160
|
+
new KeyboardEvent("keydown", { key: "ArrowDown" })
|
|
161
|
+
);
|
|
162
|
+
expect(component.focusedValue).toBe(mockProps.value);
|
|
121
163
|
|
|
122
164
|
const popover: HTMLElement = component.shadowRoot.querySelector(
|
|
123
165
|
"dx-popover"
|
|
124
166
|
);
|
|
125
167
|
expect(popover).not.toBeNull();
|
|
126
168
|
popover.dispatchEvent(new CustomEvent("close"));
|
|
127
|
-
|
|
128
|
-
expect(component.open).toBe(false);
|
|
169
|
+
expect(component.focusedValue).toBeNull();
|
|
129
170
|
});
|
|
130
171
|
});
|
|
131
172
|
});
|
|
@@ -23,6 +23,7 @@ export default class Dropdown extends LightningElement {
|
|
|
23
23
|
@api ariaLabel: string | null = null;
|
|
24
24
|
@api tempId: string | null = null;
|
|
25
25
|
@api offset?: "small" | "medium";
|
|
26
|
+
@api open: boolean | null = null;
|
|
26
27
|
@api pagePadding?: number = 16; // padding between dropdown and the edge of the page
|
|
27
28
|
@api placement?: PopperPlacement = "bottom-start";
|
|
28
29
|
@api small?: boolean = false;
|
|
@@ -44,12 +45,8 @@ export default class Dropdown extends LightningElement {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
@api
|
|
47
|
-
get
|
|
48
|
-
return this.
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
set open(value) {
|
|
52
|
-
this._open = value;
|
|
48
|
+
get focusedValue() {
|
|
49
|
+
return this._focusedValue;
|
|
53
50
|
}
|
|
54
51
|
|
|
55
52
|
@track
|
|
@@ -57,8 +54,7 @@ export default class Dropdown extends LightningElement {
|
|
|
57
54
|
|
|
58
55
|
// PRIVATE VARS
|
|
59
56
|
|
|
60
|
-
private
|
|
61
|
-
private _open = false;
|
|
57
|
+
private _focusedValue: string | null = null;
|
|
62
58
|
private popoverEl: HTMLElement | null = null;
|
|
63
59
|
|
|
64
60
|
constructor() {
|
|
@@ -98,18 +94,16 @@ export default class Dropdown extends LightningElement {
|
|
|
98
94
|
// CLASS FNS
|
|
99
95
|
|
|
100
96
|
private onKeyDown = (e: KeyboardEvent) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
default:
|
|
112
|
-
}
|
|
97
|
+
switch (e.key) {
|
|
98
|
+
case "ArrowDown":
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
this.incrementOptionFocus(1);
|
|
101
|
+
break;
|
|
102
|
+
case "ArrowUp":
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
this.incrementOptionFocus(-1);
|
|
105
|
+
break;
|
|
106
|
+
default:
|
|
113
107
|
}
|
|
114
108
|
};
|
|
115
109
|
|
|
@@ -125,7 +119,7 @@ export default class Dropdown extends LightningElement {
|
|
|
125
119
|
private onOptionFocus(e: PointerEvent) {
|
|
126
120
|
if (e.target) {
|
|
127
121
|
// @ts-ignore
|
|
128
|
-
this.
|
|
122
|
+
this._focusedValue = e.target.option.id;
|
|
129
123
|
}
|
|
130
124
|
}
|
|
131
125
|
|
|
@@ -137,13 +131,13 @@ export default class Dropdown extends LightningElement {
|
|
|
137
131
|
}
|
|
138
132
|
|
|
139
133
|
private incrementOptionFocus(indexChange: number) {
|
|
140
|
-
if (!this.
|
|
134
|
+
if (!this._focusedValue) {
|
|
141
135
|
this.focusDefaultOption();
|
|
142
136
|
return;
|
|
143
137
|
}
|
|
144
138
|
|
|
145
139
|
const focusedOptionIndex = this.findOptionElementIndex(
|
|
146
|
-
this.
|
|
140
|
+
this._focusedValue
|
|
147
141
|
);
|
|
148
142
|
|
|
149
143
|
let nextIndex = focusedOptionIndex + indexChange;
|
|
@@ -160,13 +154,8 @@ export default class Dropdown extends LightningElement {
|
|
|
160
154
|
}
|
|
161
155
|
}
|
|
162
156
|
|
|
163
|
-
private onOpen(): void {
|
|
164
|
-
this._open = true;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
157
|
private onClose(): void {
|
|
168
|
-
this.
|
|
169
|
-
this._open = false;
|
|
158
|
+
this._focusedValue = null;
|
|
170
159
|
}
|
|
171
160
|
|
|
172
161
|
private focusDefaultOption() {
|
|
@@ -179,7 +168,7 @@ export default class Dropdown extends LightningElement {
|
|
|
179
168
|
];
|
|
180
169
|
if (optionToFocus) {
|
|
181
170
|
optionToFocus.focus();
|
|
182
|
-
this.
|
|
171
|
+
this._focusedValue = optionToFocus.option.id;
|
|
183
172
|
}
|
|
184
173
|
}
|
|
185
174
|
|
|
@@ -24,7 +24,7 @@ const COVEO_CONFIG = {
|
|
|
24
24
|
reducers: searchAppReducers
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
const REDIRECT_URL = "https://
|
|
27
|
+
const REDIRECT_URL = "https://developer.salesforce.com";
|
|
28
28
|
|
|
29
29
|
const TAG = "dx-header-search";
|
|
30
30
|
const render = createRenderComponent(TAG, HeaderSearch);
|
|
@@ -80,7 +80,7 @@ export default class HeaderSearch extends LightningElement {
|
|
|
80
80
|
private instantiateSearchbox() {
|
|
81
81
|
const options: StandaloneSearchBoxOptions = {
|
|
82
82
|
numberOfSuggestions: 3,
|
|
83
|
-
redirectionUrl: "https://
|
|
83
|
+
redirectionUrl: "https://developer.salesforce.com"
|
|
84
84
|
};
|
|
85
85
|
|
|
86
86
|
const engine = new HeadlessEngine({
|
|
@@ -37,6 +37,7 @@ export default class Popover extends LightningElement {
|
|
|
37
37
|
return this._open;
|
|
38
38
|
}
|
|
39
39
|
set open(value: boolean | null) {
|
|
40
|
+
this.controlled = typeof value === "boolean";
|
|
40
41
|
if (value !== this._open) {
|
|
41
42
|
if (value) {
|
|
42
43
|
this.openPopover();
|
|
@@ -101,6 +102,7 @@ export default class Popover extends LightningElement {
|
|
|
101
102
|
|
|
102
103
|
// PRIVATE VARS
|
|
103
104
|
|
|
105
|
+
private controlled: boolean = false;
|
|
104
106
|
private _open: boolean = false;
|
|
105
107
|
private _rendered: boolean = isPrerender();
|
|
106
108
|
private _role: string | null = null;
|
|
@@ -152,19 +154,26 @@ export default class Popover extends LightningElement {
|
|
|
152
154
|
|
|
153
155
|
private addControlListeners() {
|
|
154
156
|
if (this.control) {
|
|
155
|
-
this.control.addEventListener("click", this.onControlClick);
|
|
156
157
|
this.control.addEventListener("keydown", this.onControlKeydown);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.
|
|
160
|
-
|
|
158
|
+
|
|
159
|
+
if (!this.openOnHover) {
|
|
160
|
+
this.control.addEventListener("click", this.onControlClick);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (this.openOnHover) {
|
|
164
|
+
this.control.addEventListener(
|
|
165
|
+
"mouseenter",
|
|
166
|
+
this.onControlMouseEnter
|
|
167
|
+
);
|
|
168
|
+
}
|
|
161
169
|
}
|
|
162
170
|
}
|
|
163
171
|
|
|
164
172
|
private removeControlListeners() {
|
|
165
173
|
if (this.control) {
|
|
166
|
-
this.control.removeEventListener("click", this.onControlClick);
|
|
167
174
|
this.control.removeEventListener("keydown", this.onControlKeydown);
|
|
175
|
+
|
|
176
|
+
this.control.removeEventListener("click", this.onControlClick);
|
|
168
177
|
this.control.removeEventListener(
|
|
169
178
|
"mouseenter",
|
|
170
179
|
this.onControlMouseEnter
|
|
@@ -186,11 +195,7 @@ export default class Popover extends LightningElement {
|
|
|
186
195
|
// @ts-ignore something weird happening here with debounce types
|
|
187
196
|
debounce(this._interactOutsideListener(e), 100);
|
|
188
197
|
|
|
189
|
-
private onControlMouseEnter = () =>
|
|
190
|
-
if (this.openOnHover) {
|
|
191
|
-
this.openPopover();
|
|
192
|
-
}
|
|
193
|
-
};
|
|
198
|
+
private onControlMouseEnter = () => this.openPopover();
|
|
194
199
|
|
|
195
200
|
private onControlKeydown = (e: KeyboardEvent) => {
|
|
196
201
|
switch (e.key) {
|
|
@@ -207,13 +212,13 @@ export default class Popover extends LightningElement {
|
|
|
207
212
|
};
|
|
208
213
|
|
|
209
214
|
private onControlClick = () => {
|
|
210
|
-
if (this.
|
|
211
|
-
this.
|
|
215
|
+
if (this.controlled) {
|
|
216
|
+
this.dispatchRequestCloseEvent("click-control");
|
|
212
217
|
return;
|
|
213
218
|
}
|
|
214
219
|
|
|
215
220
|
if (this.open) {
|
|
216
|
-
this.
|
|
221
|
+
this.closePopover();
|
|
217
222
|
return;
|
|
218
223
|
}
|
|
219
224
|
|