@statistikzh/leu 0.19.1 → 0.20.0
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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/Accordion.js +1 -1
- package/dist/Button.js +1 -1
- package/dist/ButtonGroup.js +1 -1
- package/dist/ChartWrapper.js +1 -1
- package/dist/Checkbox.js +1 -1
- package/dist/CheckboxGroup.js +1 -1
- package/dist/Chip.js +1 -1
- package/dist/ChipGroup.js +1 -1
- package/dist/ChipLink.js +1 -1
- package/dist/ChipRemovable.js +1 -1
- package/dist/ChipSelectable.js +1 -1
- package/dist/Dialog.js +1 -1
- package/dist/Dropdown.d.ts +1 -0
- package/dist/Dropdown.js +1 -1
- package/dist/FileInput.d.ts +7 -1
- package/dist/FileInput.js +18 -1
- package/dist/Icon.js +1 -1
- package/dist/Input.js +1 -1
- package/dist/{LeuElement-CRdVLttR.js → LeuElement-C1c3TgrG.js} +1 -1
- package/dist/Menu.d.ts +2 -1
- package/dist/Menu.js +1 -1
- package/dist/MenuItem.js +1 -1
- package/dist/Message.js +1 -1
- package/dist/Pagination.js +1 -1
- package/dist/Placeholder.js +1 -1
- package/dist/Popup.d.ts +22 -46
- package/dist/Popup.js +40 -31
- package/dist/ProgressBar.js +1 -1
- package/dist/Radio.js +1 -1
- package/dist/RadioGroup.js +1 -1
- package/dist/Range.js +1 -1
- package/dist/ScrollTop.js +1 -1
- package/dist/Select.d.ts +3 -2
- package/dist/Select.js +1 -1
- package/dist/Spinner.js +1 -1
- package/dist/Table.js +1 -1
- package/dist/Tag.js +1 -1
- package/dist/VisuallyHidden.js +1 -1
- package/dist/components/file-input/FileInput.d.ts +7 -1
- package/dist/components/file-input/FileInput.d.ts.map +1 -1
- package/dist/components/menu/Menu.d.ts +2 -1
- package/dist/components/menu/Menu.d.ts.map +1 -1
- package/dist/components/popup/Popup.d.ts +21 -46
- package/dist/components/popup/Popup.d.ts.map +1 -1
- package/dist/components/popup/stories/popup.stories.d.ts +9 -0
- package/dist/components/popup/stories/popup.stories.d.ts.map +1 -1
- package/dist/components/select/Select.d.ts +2 -2
- package/dist/components/select/Select.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/leu-accordion.js +1 -1
- package/dist/leu-button-group.js +1 -1
- package/dist/leu-button.js +1 -1
- package/dist/leu-chart-wrapper.js +1 -1
- package/dist/leu-checkbox-group.js +1 -1
- package/dist/leu-checkbox.js +1 -1
- package/dist/leu-chip-group.js +1 -1
- package/dist/leu-chip-link.js +1 -1
- package/dist/leu-chip-removable.js +1 -1
- package/dist/leu-chip-selectable.js +1 -1
- package/dist/leu-dialog.js +1 -1
- package/dist/leu-dropdown.d.ts +1 -0
- package/dist/leu-dropdown.js +1 -1
- package/dist/leu-file-input.js +1 -1
- package/dist/leu-icon.js +1 -1
- package/dist/leu-input.js +1 -1
- package/dist/leu-menu-item.js +1 -1
- package/dist/leu-menu.js +1 -1
- package/dist/leu-message.js +1 -1
- package/dist/leu-pagination.js +1 -1
- package/dist/leu-placeholder.js +1 -1
- package/dist/leu-popup.d.ts +1 -0
- package/dist/leu-popup.js +3 -1
- package/dist/leu-progress-bar.js +1 -1
- package/dist/leu-radio-group.js +1 -1
- package/dist/leu-radio.js +1 -1
- package/dist/leu-range.js +1 -1
- package/dist/leu-scroll-top.js +1 -1
- package/dist/leu-select.d.ts +1 -0
- package/dist/leu-select.js +1 -1
- package/dist/leu-spinner.js +1 -1
- package/dist/leu-table.js +1 -1
- package/dist/leu-tag.js +1 -1
- package/dist/leu-visually-hidden.js +1 -1
- package/dist/vscode.html-custom-data.json +17 -13
- package/dist/vue/index.d.ts +29 -27
- package/dist/web-types.json +48 -50
- package/package.json +1 -1
- package/src/components/file-input/FileInput.ts +25 -2
- package/src/components/menu/Menu.ts +2 -2
- package/src/components/popup/Popup.ts +49 -44
- package/src/components/popup/stories/popup.stories.ts +49 -0
- package/src/components/popup/test/popup.test.ts +39 -3
- package/src/components/select/Select.ts +2 -2
package/dist/vue/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { DefineComponent } from "vue";
|
|
2
2
|
|
|
3
3
|
import type { LeuAccordion } from "../Accordion.js";
|
|
4
|
-
import type { LeuButton } from "../Button.js";
|
|
5
4
|
import type { LeuButtonGroup } from "../ButtonGroup.js";
|
|
5
|
+
import type { LeuButton } from "../Button.js";
|
|
6
6
|
import type { LeuChartWrapper } from "../ChartWrapper.js";
|
|
7
7
|
import type { LeuCheckbox } from "../Checkbox.js";
|
|
8
8
|
import type { LeuCheckboxGroup } from "../CheckboxGroup.js";
|
|
@@ -12,7 +12,7 @@ import type { LeuChipRemovable } from "../ChipRemovable.js";
|
|
|
12
12
|
import type { LeuChipSelectable, CustomEvent } from "../ChipSelectable.js";
|
|
13
13
|
import type { LeuDialog } from "../Dialog.js";
|
|
14
14
|
import type { LeuDropdown } from "../Dropdown.js";
|
|
15
|
-
import type { LeuFileInput } from "../FileInput.js";
|
|
15
|
+
import type { LeuFileInput, CustomEvent } from "../FileInput.js";
|
|
16
16
|
import type { LeuIcon } from "../Icon.js";
|
|
17
17
|
import type { LeuInput, CustomEvent } from "../Input.js";
|
|
18
18
|
import type { LeuMenu } from "../Menu.js";
|
|
@@ -43,6 +43,13 @@ type LeuAccordionProps = {
|
|
|
43
43
|
label?: LeuAccordion["label"];
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
type LeuButtonGroupProps = {
|
|
47
|
+
/** The value of the currently selected (active) button */
|
|
48
|
+
value?: LeuButtonGroup["value"];
|
|
49
|
+
/** When the value of the group changes by clicking a button */
|
|
50
|
+
oninput?: (e: CustomEvent<never>) => void;
|
|
51
|
+
};
|
|
52
|
+
|
|
46
53
|
type LeuButtonProps = {
|
|
47
54
|
/** `aria-label` of the underlying button elements.
|
|
48
55
|
Use it to provide a label when only an icon is visible. */
|
|
@@ -74,13 +81,6 @@ If it is set, the icon will either show an expanded or collapsed state. */
|
|
|
74
81
|
fluid?: LeuButton["fluid"];
|
|
75
82
|
};
|
|
76
83
|
|
|
77
|
-
type LeuButtonGroupProps = {
|
|
78
|
-
/** The value of the currently selected (active) button */
|
|
79
|
-
value?: LeuButtonGroup["value"];
|
|
80
|
-
/** When the value of the group changes by clicking a button */
|
|
81
|
-
oninput?: (e: CustomEvent<never>) => void;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
84
|
type LeuChartWrapperProps = {
|
|
85
85
|
/** Whether the chart is currently loading or not.
|
|
86
86
|
When set to `true`, a spinner will be shown in the chart container. */
|
|
@@ -208,6 +208,10 @@ type LeuFileInputProps = {
|
|
|
208
208
|
form?: LeuFileInput["form"];
|
|
209
209
|
/** */
|
|
210
210
|
name?: LeuFileInput["name"];
|
|
211
|
+
/** */
|
|
212
|
+
oninput?: (e: CustomEvent<CustomEvent>) => void;
|
|
213
|
+
/** */
|
|
214
|
+
onchange?: (e: CustomEvent<CustomEvent>) => void;
|
|
211
215
|
};
|
|
212
216
|
|
|
213
217
|
type LeuIconProps = {
|
|
@@ -347,12 +351,6 @@ type LeuPopupProps = {
|
|
|
347
351
|
autoSize?: LeuPopup["autoSize"];
|
|
348
352
|
/** */
|
|
349
353
|
autoSizePadding?: LeuPopup["autoSizePadding"];
|
|
350
|
-
/** */
|
|
351
|
-
popupEl?: LeuPopup["popupEl"];
|
|
352
|
-
/** */
|
|
353
|
-
anchorEl?: LeuPopup["anchorEl"];
|
|
354
|
-
/** */
|
|
355
|
-
cleanup?: LeuPopup["cleanup"];
|
|
356
354
|
};
|
|
357
355
|
|
|
358
356
|
type LeuProgressBarProps = {
|
|
@@ -502,18 +500,6 @@ export type CustomElements = {
|
|
|
502
500
|
*/
|
|
503
501
|
"leu-accordion": DefineComponent<LeuAccordionProps>;
|
|
504
502
|
|
|
505
|
-
/**
|
|
506
|
-
*
|
|
507
|
-
* ---
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
* ### **Slots:**
|
|
511
|
-
* - **before** - The icon to display before the label
|
|
512
|
-
* - **after** - The icon to display after the label
|
|
513
|
-
* - _default_ - The label of the button or the icon if no label is set
|
|
514
|
-
*/
|
|
515
|
-
"leu-button": DefineComponent<LeuButtonProps>;
|
|
516
|
-
|
|
517
503
|
/**
|
|
518
504
|
* A radio input-like button group component.
|
|
519
505
|
* It allows only one button to be active at a time.
|
|
@@ -528,6 +514,18 @@ export type CustomElements = {
|
|
|
528
514
|
*/
|
|
529
515
|
"leu-button-group": DefineComponent<LeuButtonGroupProps>;
|
|
530
516
|
|
|
517
|
+
/**
|
|
518
|
+
*
|
|
519
|
+
* ---
|
|
520
|
+
*
|
|
521
|
+
*
|
|
522
|
+
* ### **Slots:**
|
|
523
|
+
* - **before** - The icon to display before the label
|
|
524
|
+
* - **after** - The icon to display after the label
|
|
525
|
+
* - _default_ - The label of the button or the icon if no label is set
|
|
526
|
+
*/
|
|
527
|
+
"leu-button": DefineComponent<LeuButtonProps>;
|
|
528
|
+
|
|
531
529
|
/**
|
|
532
530
|
* A wrapper element for charts.
|
|
533
531
|
* ---
|
|
@@ -632,6 +630,10 @@ export type CustomElements = {
|
|
|
632
630
|
*
|
|
633
631
|
* ---
|
|
634
632
|
*
|
|
633
|
+
*
|
|
634
|
+
* ### **Events:**
|
|
635
|
+
* - **input**
|
|
636
|
+
* - **change**
|
|
635
637
|
*/
|
|
636
638
|
"leu-file-input": DefineComponent<LeuFileInputProps>;
|
|
637
639
|
|
package/dist/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
|
|
3
3
|
"name": "@statistikzh/leu",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.20.0",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
@@ -65,6 +65,33 @@
|
|
|
65
65
|
"events": []
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
|
+
{
|
|
69
|
+
"name": "leu-button-group",
|
|
70
|
+
"description": "A radio input-like button group component.\nIt allows only one button to be active at a time.\n---\n\n\n### **Events:**\n - **input** - When the value of the group changes by clicking a button\n\n### **Slots:**\n - _default_ - Slot for the buttons",
|
|
71
|
+
"doc-url": "",
|
|
72
|
+
"attributes": [],
|
|
73
|
+
"slots": [{ "name": "", "description": "Slot for the buttons" }],
|
|
74
|
+
"events": [
|
|
75
|
+
{
|
|
76
|
+
"name": "input",
|
|
77
|
+
"description": "When the value of the group changes by clicking a button"
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"js": {
|
|
81
|
+
"properties": [
|
|
82
|
+
{
|
|
83
|
+
"name": "value",
|
|
84
|
+
"description": "The value of the currently selected (active) button"
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"events": [
|
|
88
|
+
{
|
|
89
|
+
"name": "input",
|
|
90
|
+
"description": "When the value of the group changes by clicking a button"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
},
|
|
68
95
|
{
|
|
69
96
|
"name": "leu-button",
|
|
70
97
|
"description": "\n---\n\n\n### **Slots:**\n - **before** - The icon to display before the label\n- **after** - The icon to display after the label\n- _default_ - The label of the button or the icon if no label is set",
|
|
@@ -211,33 +238,6 @@
|
|
|
211
238
|
"events": []
|
|
212
239
|
}
|
|
213
240
|
},
|
|
214
|
-
{
|
|
215
|
-
"name": "leu-button-group",
|
|
216
|
-
"description": "A radio input-like button group component.\nIt allows only one button to be active at a time.\n---\n\n\n### **Events:**\n - **input** - When the value of the group changes by clicking a button\n\n### **Slots:**\n - _default_ - Slot for the buttons",
|
|
217
|
-
"doc-url": "",
|
|
218
|
-
"attributes": [],
|
|
219
|
-
"slots": [{ "name": "", "description": "Slot for the buttons" }],
|
|
220
|
-
"events": [
|
|
221
|
-
{
|
|
222
|
-
"name": "input",
|
|
223
|
-
"description": "When the value of the group changes by clicking a button"
|
|
224
|
-
}
|
|
225
|
-
],
|
|
226
|
-
"js": {
|
|
227
|
-
"properties": [
|
|
228
|
-
{
|
|
229
|
-
"name": "value",
|
|
230
|
-
"description": "The value of the currently selected (active) button"
|
|
231
|
-
}
|
|
232
|
-
],
|
|
233
|
-
"events": [
|
|
234
|
-
{
|
|
235
|
-
"name": "input",
|
|
236
|
-
"description": "When the value of the group changes by clicking a button"
|
|
237
|
-
}
|
|
238
|
-
]
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
241
|
{
|
|
242
242
|
"name": "leu-chart-wrapper",
|
|
243
243
|
"description": "A wrapper element for charts.\n---\n\n\n### **Slots:**\n - **title** - The title of the chart. Use a heading tag (h2-4) depending on your context.\n- **description** - A description of the chart. Content is wrapped in a `<p>` tag by the component.\n- **chart** - The actual chart\n- **caption** - A caption for the chart, e.g. a source or explanation of the data.\n- **download** - A download button or dropdown to export the chart in different formats.",
|
|
@@ -597,7 +597,7 @@
|
|
|
597
597
|
},
|
|
598
598
|
{
|
|
599
599
|
"name": "leu-file-input",
|
|
600
|
-
"description": "\n---\n",
|
|
600
|
+
"description": "\n---\n\n\n### **Events:**\n - **input**\n- **change**",
|
|
601
601
|
"doc-url": "",
|
|
602
602
|
"attributes": [
|
|
603
603
|
{
|
|
@@ -633,7 +633,10 @@
|
|
|
633
633
|
}
|
|
634
634
|
}
|
|
635
635
|
],
|
|
636
|
-
"events": [
|
|
636
|
+
"events": [
|
|
637
|
+
{ "name": "input", "type": "CustomEvent" },
|
|
638
|
+
{ "name": "change", "type": "CustomEvent" }
|
|
639
|
+
],
|
|
637
640
|
"js": {
|
|
638
641
|
"properties": [
|
|
639
642
|
{ "name": "label", "type": "string" },
|
|
@@ -667,7 +670,10 @@
|
|
|
667
670
|
{ "name": "form" },
|
|
668
671
|
{ "name": "name" }
|
|
669
672
|
],
|
|
670
|
-
"events": [
|
|
673
|
+
"events": [
|
|
674
|
+
{ "name": "input", "type": "CustomEvent" },
|
|
675
|
+
{ "name": "change", "type": "CustomEvent" }
|
|
676
|
+
]
|
|
671
677
|
}
|
|
672
678
|
},
|
|
673
679
|
{
|
|
@@ -1205,10 +1211,7 @@
|
|
|
1205
1211
|
"attributes": [
|
|
1206
1212
|
{
|
|
1207
1213
|
"name": "anchor",
|
|
1208
|
-
"value": {
|
|
1209
|
-
"type": "string | HTMLElement",
|
|
1210
|
-
"default": "undefined"
|
|
1211
|
-
}
|
|
1214
|
+
"value": { "type": "Element | string | VirtualElement" }
|
|
1212
1215
|
},
|
|
1213
1216
|
{
|
|
1214
1217
|
"name": "active",
|
|
@@ -1216,7 +1219,7 @@
|
|
|
1216
1219
|
},
|
|
1217
1220
|
{
|
|
1218
1221
|
"name": "placement",
|
|
1219
|
-
"value": { "type": "Placement
|
|
1222
|
+
"value": { "type": "Placement | undefined" }
|
|
1220
1223
|
},
|
|
1221
1224
|
{
|
|
1222
1225
|
"name": "flip",
|
|
@@ -1233,15 +1236,13 @@
|
|
|
1233
1236
|
{
|
|
1234
1237
|
"name": "matchSize",
|
|
1235
1238
|
"value": {
|
|
1236
|
-
"type": "\"width\" | \"height\" | \"both\""
|
|
1237
|
-
"default": "undefined"
|
|
1239
|
+
"type": "\"width\" | \"height\" | \"both\" | undefined"
|
|
1238
1240
|
}
|
|
1239
1241
|
},
|
|
1240
1242
|
{
|
|
1241
1243
|
"name": "autoSize",
|
|
1242
1244
|
"value": {
|
|
1243
|
-
"type": "\"width\"
|
|
1244
|
-
"default": "undefined"
|
|
1245
|
+
"type": "| \"width\"\n | \"height\"\n | \"both\" | undefined"
|
|
1245
1246
|
}
|
|
1246
1247
|
},
|
|
1247
1248
|
{
|
|
@@ -1252,24 +1253,21 @@
|
|
|
1252
1253
|
"events": [],
|
|
1253
1254
|
"js": {
|
|
1254
1255
|
"properties": [
|
|
1255
|
-
{ "name": "
|
|
1256
|
-
{ "name": "
|
|
1257
|
-
{ "name": "
|
|
1256
|
+
{ "name": "anchor", "type": "Element | string | VirtualElement" },
|
|
1257
|
+
{ "name": "active", "type": "boolean" },
|
|
1258
|
+
{ "name": "placement", "type": "Placement | undefined" },
|
|
1258
1259
|
{ "name": "flip", "type": "boolean" },
|
|
1259
1260
|
{ "name": "shift", "type": "boolean" },
|
|
1260
|
-
{ "name": "
|
|
1261
|
-
{ "name": "placement", "type": "Placement" },
|
|
1261
|
+
{ "name": "shiftPadding", "type": "number" },
|
|
1262
1262
|
{
|
|
1263
1263
|
"name": "matchSize",
|
|
1264
|
-
"type": "\"width\" | \"height\" | \"both\""
|
|
1264
|
+
"type": "\"width\" | \"height\" | \"both\" | undefined"
|
|
1265
1265
|
},
|
|
1266
1266
|
{
|
|
1267
1267
|
"name": "autoSize",
|
|
1268
|
-
"type": "\"width\"
|
|
1268
|
+
"type": "| \"width\"\n | \"height\"\n | \"both\" | undefined"
|
|
1269
1269
|
},
|
|
1270
|
-
{ "name": "
|
|
1271
|
-
{ "name": "autoSizePadding", "type": "number" },
|
|
1272
|
-
{ "name": "anchor", "type": "string | HTMLElement" }
|
|
1270
|
+
{ "name": "autoSizePadding", "type": "number" }
|
|
1273
1271
|
],
|
|
1274
1272
|
"events": []
|
|
1275
1273
|
}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { html, nothing } from "lit"
|
|
1
|
+
import { html, nothing, PropertyValues } from "lit"
|
|
2
2
|
import { property, query, state } from "lit/decorators.js"
|
|
3
3
|
import { ifDefined } from "lit/directives/if-defined.js"
|
|
4
4
|
import { classMap } from "lit/directives/class-map.js"
|
|
@@ -10,6 +10,11 @@ import { LeuButton } from "../../index.js"
|
|
|
10
10
|
import { LeuIcon } from "../icon/leu-icon.js"
|
|
11
11
|
import { LeuVisuallyHidden } from "../visually-hidden/VisuallyHidden.js"
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @todo Pluralize text when multiple files are allowed
|
|
15
|
+
* @todo Hide dropzone when not multiple and already filled
|
|
16
|
+
*/
|
|
17
|
+
|
|
13
18
|
/**
|
|
14
19
|
* @tagname leu-file-input
|
|
15
20
|
*/
|
|
@@ -77,7 +82,7 @@ export class LeuFileInput extends LeuElement {
|
|
|
77
82
|
return this.getAttribute("name")
|
|
78
83
|
}
|
|
79
84
|
|
|
80
|
-
updated(changedProperties) {
|
|
85
|
+
updated(changedProperties: PropertyValues<this>) {
|
|
81
86
|
if (
|
|
82
87
|
changedProperties.has("files") ||
|
|
83
88
|
changedProperties.has("disabled") ||
|
|
@@ -100,6 +105,11 @@ export class LeuFileInput extends LeuElement {
|
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
|
|
108
|
+
private handleChange(event: Event & { target: HTMLInputElement }) {
|
|
109
|
+
const customEvent = new CustomEvent(event.type, event)
|
|
110
|
+
this.dispatchEvent(customEvent)
|
|
111
|
+
}
|
|
112
|
+
|
|
103
113
|
public formResetCallback() {
|
|
104
114
|
this.files = []
|
|
105
115
|
this.input.value = ""
|
|
@@ -119,6 +129,18 @@ export class LeuFileInput extends LeuElement {
|
|
|
119
129
|
|
|
120
130
|
protected removeFile(fileToRemove: File) {
|
|
121
131
|
this.files = this.files.filter((file) => file !== fileToRemove)
|
|
132
|
+
this.dispatchEvent(
|
|
133
|
+
new CustomEvent("input", {
|
|
134
|
+
composed: true,
|
|
135
|
+
bubbles: true,
|
|
136
|
+
}),
|
|
137
|
+
)
|
|
138
|
+
this.dispatchEvent(
|
|
139
|
+
new CustomEvent("change", {
|
|
140
|
+
composed: true,
|
|
141
|
+
bubbles: true,
|
|
142
|
+
}),
|
|
143
|
+
)
|
|
122
144
|
}
|
|
123
145
|
|
|
124
146
|
protected static formatFileSize(size: number) {
|
|
@@ -220,6 +242,7 @@ export class LeuFileInput extends LeuElement {
|
|
|
220
242
|
accept=${ifDefined(this.accept)}
|
|
221
243
|
?disabled=${this.disabled}
|
|
222
244
|
@input=${this.handleInput}
|
|
245
|
+
@change=${this.handleChange}
|
|
223
246
|
/>
|
|
224
247
|
</leu-visually-hidden>
|
|
225
248
|
<div
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { html } from "lit"
|
|
1
|
+
import { html, PropertyValues } from "lit"
|
|
2
2
|
|
|
3
3
|
import { LeuElement } from "../../lib/LeuElement.js"
|
|
4
4
|
|
|
@@ -142,7 +142,7 @@ export class LeuMenu extends LeuElement {
|
|
|
142
142
|
this.setCurrentItem(0)
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
updated(changedProperties) {
|
|
145
|
+
updated(changedProperties: PropertyValues<this>) {
|
|
146
146
|
if (changedProperties.has("selects")) {
|
|
147
147
|
this._setMenuItemRoles()
|
|
148
148
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { html } from "lit"
|
|
1
|
+
import { html, PropertyValues } from "lit"
|
|
2
|
+
import { property } from "lit/decorators.js"
|
|
2
3
|
import {
|
|
3
4
|
autoUpdate,
|
|
4
5
|
computePosition,
|
|
5
6
|
flip,
|
|
7
|
+
Placement,
|
|
6
8
|
shift,
|
|
7
9
|
size,
|
|
8
10
|
} from "@floating-ui/dom"
|
|
@@ -11,9 +13,19 @@ import { LeuElement } from "../../lib/LeuElement.js"
|
|
|
11
13
|
|
|
12
14
|
import styles from "./popup.css"
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export interface VirtualElement {
|
|
17
|
+
getBoundingClientRect: () => DOMRect
|
|
18
|
+
contextElement?: Element
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isVirtualElement(el: unknown): el is VirtualElement {
|
|
22
|
+
return (
|
|
23
|
+
el !== null &&
|
|
24
|
+
typeof el === "object" &&
|
|
25
|
+
"getBoundingClientRect" in el &&
|
|
26
|
+
("contextElement" in el ? el instanceof Element : true)
|
|
27
|
+
)
|
|
28
|
+
}
|
|
17
29
|
|
|
18
30
|
/**
|
|
19
31
|
* @tagname leu-popup
|
|
@@ -26,50 +38,43 @@ export class LeuPopup extends LeuElement {
|
|
|
26
38
|
delegatesFocus: true,
|
|
27
39
|
}
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
anchor: {},
|
|
31
|
-
active: { type: Boolean, reflect: true },
|
|
32
|
-
placement: { type: String, reflect: true },
|
|
33
|
-
flip: { type: Boolean, reflect: true },
|
|
34
|
-
shift: { type: Boolean, reflect: true },
|
|
35
|
-
shiftPadding: { type: Number, reflect: true },
|
|
36
|
-
matchSize: { type: String, reflect: true },
|
|
37
|
-
autoSize: { type: String, reflect: true },
|
|
38
|
-
autoSizePadding: { type: Number, reflect: true },
|
|
39
|
-
}
|
|
41
|
+
@property() anchor: Element | string | VirtualElement
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
@property({ type: Boolean, reflect: true })
|
|
44
|
+
active: boolean = false
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.flip = false
|
|
47
|
-
this.shift = false
|
|
46
|
+
@property({ type: String, reflect: true })
|
|
47
|
+
placement?: Placement
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
@property({ type: Boolean, reflect: true })
|
|
50
|
+
flip: boolean = false
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
@property({ type: Boolean, reflect: true })
|
|
53
|
+
shift: boolean = false
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
@property({ type: Number, reflect: true })
|
|
56
|
+
shiftPadding: number = 0
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
@property({ type: String, reflect: true })
|
|
59
|
+
matchSize?: "width" | "height" | "both"
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
@property({ type: String, reflect: true }) autoSize?:
|
|
62
|
+
| "width"
|
|
63
|
+
| "height"
|
|
64
|
+
| "both"
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
@property({ type: Number, reflect: true }) autoSizePadding: number = 0
|
|
67
|
+
|
|
68
|
+
private anchorEl: Element | null
|
|
69
|
+
|
|
70
|
+
private cleanup: ReturnType<typeof autoUpdate> | undefined
|
|
66
71
|
|
|
67
72
|
disconnectedCallback() {
|
|
68
73
|
super.disconnectedCallback()
|
|
69
74
|
this.stop()
|
|
70
75
|
}
|
|
71
76
|
|
|
72
|
-
updated(changedProperties) {
|
|
77
|
+
updated(changedProperties: PropertyValues<this>) {
|
|
73
78
|
if (changedProperties.has("active")) {
|
|
74
79
|
if (this.active) {
|
|
75
80
|
this.start()
|
|
@@ -87,14 +92,11 @@ export class LeuPopup extends LeuElement {
|
|
|
87
92
|
}
|
|
88
93
|
}
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
*/
|
|
93
|
-
get popupEl() {
|
|
94
|
-
return this.renderRoot?.querySelector(".popup") ?? null
|
|
95
|
+
protected get popupEl() {
|
|
96
|
+
return this.renderRoot?.querySelector<HTMLDivElement>(".popup") ?? null
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
start() {
|
|
99
|
+
protected start() {
|
|
98
100
|
if (!this.anchorEl || !this.active) return
|
|
99
101
|
|
|
100
102
|
this.cleanup = autoUpdate(this.anchorEl, this.popupEl, () => {
|
|
@@ -102,14 +104,14 @@ export class LeuPopup extends LeuElement {
|
|
|
102
104
|
})
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
stop() {
|
|
107
|
+
protected stop() {
|
|
106
108
|
this.cleanup?.()
|
|
107
109
|
|
|
108
110
|
this.style.removeProperty("--auto-size-available-width")
|
|
109
111
|
this.style.removeProperty("--auto-size-available-height")
|
|
110
112
|
}
|
|
111
113
|
|
|
112
|
-
reposition() {
|
|
114
|
+
public reposition() {
|
|
113
115
|
if (!this.anchorEl || !this.popupEl || !this.active) return
|
|
114
116
|
|
|
115
117
|
const middleware = []
|
|
@@ -194,9 +196,12 @@ export class LeuPopup extends LeuElement {
|
|
|
194
196
|
|
|
195
197
|
handleAnchorChange() {
|
|
196
198
|
if (this.anchor && typeof this.anchor === "string") {
|
|
197
|
-
const root = this.getRootNode()
|
|
199
|
+
const root = this.getRootNode() as Document | ShadowRoot
|
|
198
200
|
this.anchorEl = root.getElementById(this.anchor)
|
|
199
|
-
} else if (
|
|
201
|
+
} else if (
|
|
202
|
+
this.anchor instanceof HTMLElement ||
|
|
203
|
+
isVirtualElement(this.anchor)
|
|
204
|
+
) {
|
|
200
205
|
this.anchorEl = this.anchor
|
|
201
206
|
} else {
|
|
202
207
|
this.anchorEl = this.querySelector("[slot=anchor]")
|
|
@@ -56,3 +56,52 @@ Regular.args = {
|
|
|
56
56
|
flip: true,
|
|
57
57
|
shift: true,
|
|
58
58
|
}
|
|
59
|
+
|
|
60
|
+
export const VirtualElement = {
|
|
61
|
+
render: (args = {}) => html`
|
|
62
|
+
<leu-popup
|
|
63
|
+
?active=${args.active}
|
|
64
|
+
?flip=${args.flip}
|
|
65
|
+
?shift=${args.shift}
|
|
66
|
+
placement=${ifDefined(args.placement)}
|
|
67
|
+
>
|
|
68
|
+
<div style=${styleMap(popupStyles)}>Popup content</div>
|
|
69
|
+
</leu-popup>
|
|
70
|
+
<script>
|
|
71
|
+
const body = document.body
|
|
72
|
+
const popup = document.querySelector("leu-popup")
|
|
73
|
+
let clientX = 0
|
|
74
|
+
let clientY = 0
|
|
75
|
+
|
|
76
|
+
body.style.height = "100vh"
|
|
77
|
+
|
|
78
|
+
popup.anchor = {
|
|
79
|
+
getBoundingClientRect() {
|
|
80
|
+
return {
|
|
81
|
+
width: 0,
|
|
82
|
+
height: 0,
|
|
83
|
+
x: clientX,
|
|
84
|
+
y: clientY,
|
|
85
|
+
top: clientY,
|
|
86
|
+
left: clientX,
|
|
87
|
+
right: clientX,
|
|
88
|
+
bottom: clientY,
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
body.addEventListener("mousemove", (event) => {
|
|
94
|
+
clientX = event.clientX
|
|
95
|
+
clientY = event.clientY
|
|
96
|
+
|
|
97
|
+
popup.reposition()
|
|
98
|
+
})
|
|
99
|
+
</script>
|
|
100
|
+
`,
|
|
101
|
+
args: {
|
|
102
|
+
active: true,
|
|
103
|
+
placement: "bottom-start",
|
|
104
|
+
flip: true,
|
|
105
|
+
shift: true,
|
|
106
|
+
},
|
|
107
|
+
}
|
|
@@ -2,9 +2,10 @@ import { html } from "lit"
|
|
|
2
2
|
import { fixture, expect } from "@open-wc/testing"
|
|
3
3
|
|
|
4
4
|
import "../leu-popup.js"
|
|
5
|
+
import { LeuPopup } from "../Popup.js"
|
|
5
6
|
|
|
6
7
|
async function defaultFixture() {
|
|
7
|
-
return fixture(html`
|
|
8
|
+
return fixture<LeuPopup>(html`
|
|
8
9
|
<leu-popup
|
|
9
10
|
><div slot="anchor"></div>
|
|
10
11
|
<p>Popup content</p></leu-popup
|
|
@@ -14,9 +15,9 @@ async function defaultFixture() {
|
|
|
14
15
|
|
|
15
16
|
describe("LeuPopup", () => {
|
|
16
17
|
it("is a defined element", async () => {
|
|
17
|
-
const el =
|
|
18
|
+
const el = customElements.get("leu-popup")
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
expect(el).not.to.be.undefined
|
|
20
21
|
})
|
|
21
22
|
|
|
22
23
|
it("passes the a11y audit", async () => {
|
|
@@ -24,4 +25,39 @@ describe("LeuPopup", () => {
|
|
|
24
25
|
|
|
25
26
|
await expect(el).shadowDom.to.be.accessible()
|
|
26
27
|
})
|
|
28
|
+
|
|
29
|
+
it("moves content to the position of a virtual element", async () => {
|
|
30
|
+
const popup = await fixture<LeuPopup>(
|
|
31
|
+
html`<leu-popup ?active=${true} placement="bottom-start"
|
|
32
|
+
><div slot="anchor"></div>
|
|
33
|
+
<div
|
|
34
|
+
style="background: white; border: 1px solid black; padding: 0.5rem"
|
|
35
|
+
>
|
|
36
|
+
Popup content
|
|
37
|
+
</div></leu-popup
|
|
38
|
+
>
|
|
39
|
+
<style>
|
|
40
|
+
* {
|
|
41
|
+
margin: 0;
|
|
42
|
+
padding: 0;
|
|
43
|
+
}
|
|
44
|
+
</style> `,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
popup.anchor = {
|
|
48
|
+
getBoundingClientRect: () => new DOMRect(32, 125, 0, 0),
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
popup.reposition()
|
|
52
|
+
|
|
53
|
+
await new Promise<void>((resolve) => {
|
|
54
|
+
requestAnimationFrame(() => resolve())
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const popupContent =
|
|
58
|
+
popup.shadowRoot!.querySelector<HTMLDivElement>(".popup")
|
|
59
|
+
|
|
60
|
+
expect(popupContent.style.left).to.equal("32px")
|
|
61
|
+
expect(popupContent.style.top).to.equal("125px")
|
|
62
|
+
})
|
|
27
63
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { html, nothing } from "lit"
|
|
1
|
+
import { html, nothing, PropertyValues } from "lit"
|
|
2
2
|
import { classMap } from "lit/directives/class-map.js"
|
|
3
3
|
import { createRef, ref } from "lit/directives/ref.js"
|
|
4
4
|
|
|
@@ -128,7 +128,7 @@ export class LeuSelect extends LeuElement {
|
|
|
128
128
|
document.removeEventListener("click", this._handleDocumentClick)
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
updated(changedProperties) {
|
|
131
|
+
updated(changedProperties: PropertyValues<this>) {
|
|
132
132
|
if (changedProperties.has("open") && this.open) {
|
|
133
133
|
if (this.filterable) {
|
|
134
134
|
this._optionFilterRef.value.focus()
|