material 3.3.2 → 3.3.4
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 +2 -2
- package/dist/components/menu/features/controller.js +23 -75
- package/dist/components/menu/features/opener.js +3 -15
- package/dist/components/menu/types.d.ts +1 -0
- package/dist/components/slider/config.js +0 -46
- package/dist/components/slider/features/controller.js +805 -171
- package/dist/components/slider/features/dom.js +29 -62
- package/dist/components/slider/features/index.js +1 -3
- package/dist/components/slider/features/states.js +2 -30
- package/dist/components/slider/slider.js +3 -6
- package/dist/components/slider/types.d.ts +0 -26
- package/dist/components/split-button/features/menu-on-demand.js +141 -0
- package/dist/components/split-button/features/menu.js +3 -4
- package/dist/core/canvas/resize.d.ts +1 -1
- package/dist/core/canvas/resize.js +24 -11
- package/dist/core/dom/classes.js +17 -118
- package/dist/core/dom/create.d.ts +0 -2
- package/dist/core/dom/create.js +0 -72
- package/dist/core/utils/mobile.js +9 -29
- package/dist/elements/preupgrade/badge.css +1 -1
- package/dist/elements/preupgrade/bottom-app-bar.css +1 -1
- package/dist/elements/preupgrade/bottom-sheet.css +1 -1
- package/dist/elements/preupgrade/button-group.css +1 -1
- package/dist/elements/preupgrade/button.css +1 -1
- package/dist/elements/preupgrade/card.css +1 -1
- package/dist/elements/preupgrade/carousel.css +1 -1
- package/dist/elements/preupgrade/checkbox.css +1 -1
- package/dist/elements/preupgrade/chips.css +1 -1
- package/dist/elements/preupgrade/datepicker.css +1 -1
- package/dist/elements/preupgrade/dialog.css +1 -1
- package/dist/elements/preupgrade/divider.css +1 -1
- package/dist/elements/preupgrade/drawer.css +1 -1
- package/dist/elements/preupgrade/extended-fab.css +1 -1
- package/dist/elements/preupgrade/fab-menu.css +1 -1
- package/dist/elements/preupgrade/fab.css +1 -1
- package/dist/elements/preupgrade/icon-button.css +1 -1
- package/dist/elements/preupgrade/list.css +1 -1
- package/dist/elements/preupgrade/loading-indicator.css +1 -1
- package/dist/elements/preupgrade/menu.css +1 -1
- package/dist/elements/preupgrade/navigation-bar.css +1 -1
- package/dist/elements/preupgrade/navigation-rail.css +1 -1
- package/dist/elements/preupgrade/progress.css +1 -1
- package/dist/elements/preupgrade/radios.css +1 -1
- package/dist/elements/preupgrade/search.css +1 -1
- package/dist/elements/preupgrade/select.css +1 -1
- package/dist/elements/preupgrade/side-sheet.css +1 -1
- package/dist/elements/preupgrade/slider.css +1 -1
- package/dist/elements/preupgrade/snackbar.css +1 -1
- package/dist/elements/preupgrade/split-button.css +1 -1
- package/dist/elements/preupgrade/switch.css +1 -1
- package/dist/elements/preupgrade/tabs.css +1 -1
- package/dist/elements/preupgrade/text-field.css +1 -1
- package/dist/elements/preupgrade/timepicker.css +1 -1
- package/dist/elements/preupgrade/toolbar.css +1 -1
- package/dist/elements/preupgrade/tooltip.css +1 -1
- package/dist/elements/preupgrade/top-app-bar.css +1 -1
- package/dist/elements/preupgrade.css +1 -1
- package/dist/package.json +1 -1
- package/dist/styles/badge.css +1 -1
- package/dist/styles/base.css +1 -1
- package/dist/styles/bottom-app-bar.css +1 -1
- package/dist/styles/bottom-sheet.css +1 -1
- package/dist/styles/button-group.css +1 -1
- package/dist/styles/button.css +1 -1
- package/dist/styles/card.css +1 -1
- package/dist/styles/carousel.css +1 -1
- package/dist/styles/checkbox.css +1 -1
- package/dist/styles/chips.css +1 -1
- package/dist/styles/contrast.css +1 -1
- package/dist/styles/datepicker.css +1 -1
- package/dist/styles/dialog.css +1 -1
- package/dist/styles/divider.css +1 -1
- package/dist/styles/drawer.css +1 -1
- package/dist/styles/extended-fab.css +1 -1
- package/dist/styles/fab-menu.css +1 -1
- package/dist/styles/fab.css +1 -1
- package/dist/styles/icon-button.css +1 -1
- package/dist/styles/list.css +1 -1
- package/dist/styles/loading-indicator.css +1 -1
- package/dist/styles/menu.css +1 -1
- package/dist/styles/navigation-bar.css +1 -1
- package/dist/styles/navigation-rail.css +1 -1
- package/dist/styles/progress.css +1 -1
- package/dist/styles/radios.css +1 -1
- package/dist/styles/search.css +1 -1
- package/dist/styles/select.css +1 -1
- package/dist/styles/side-sheet.css +1 -1
- package/dist/styles/slider.css +1 -1
- package/dist/styles/snackbar.css +1 -1
- package/dist/styles/split-button.css +1 -1
- package/dist/styles/switch.css +1 -1
- package/dist/styles/tabs.css +1 -1
- package/dist/styles/text-field.css +1 -1
- package/dist/styles/timepicker.css +1 -1
- package/dist/styles/toolbar.css +1 -1
- package/dist/styles/tooltip.css +1 -1
- package/dist/styles/top-app-bar.css +1 -1
- package/dist/styles/typography.css +1 -1
- package/dist/styles/utilities.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/themes/autumn-contrast.css +1 -1
- package/dist/themes/autumn.css +1 -1
- package/dist/themes/baseline-contrast.css +1 -1
- package/dist/themes/baseline.css +1 -1
- package/dist/themes/brownbeige-contrast.css +1 -1
- package/dist/themes/brownbeige.css +1 -1
- package/dist/themes/content-contrast.css +1 -1
- package/dist/themes/content.css +1 -1
- package/dist/themes/desert-contrast.css +1 -1
- package/dist/themes/desert.css +1 -1
- package/dist/themes/expressive-contrast.css +1 -1
- package/dist/themes/expressive.css +1 -1
- package/dist/themes/fidelity-contrast.css +1 -1
- package/dist/themes/fidelity.css +1 -1
- package/dist/themes/forest-contrast.css +1 -1
- package/dist/themes/forest.css +1 -1
- package/dist/themes/fruit-salad-contrast.css +1 -1
- package/dist/themes/fruit-salad.css +1 -1
- package/dist/themes/highcontrast-contrast.css +1 -1
- package/dist/themes/highcontrast.css +1 -1
- package/dist/themes/monochrome-contrast.css +1 -1
- package/dist/themes/monochrome.css +1 -1
- package/dist/themes/neutral-contrast.css +1 -1
- package/dist/themes/neutral.css +1 -1
- package/dist/themes/ocean-contrast.css +1 -1
- package/dist/themes/ocean.css +1 -1
- package/dist/themes/rainbow-contrast.css +1 -1
- package/dist/themes/rainbow.css +1 -1
- package/dist/themes/sageivory-contrast.css +1 -1
- package/dist/themes/sageivory.css +1 -1
- package/dist/themes/spring-contrast.css +1 -1
- package/dist/themes/spring.css +1 -1
- package/dist/themes/summer-contrast.css +1 -1
- package/dist/themes/summer.css +1 -1
- package/dist/themes/sunset-contrast.css +1 -1
- package/dist/themes/sunset.css +1 -1
- package/dist/themes/tealcaramel-contrast.css +1 -1
- package/dist/themes/tealcaramel.css +1 -1
- package/dist/themes/vibrant-contrast.css +1 -1
- package/dist/themes/vibrant.css +1 -1
- package/package.json +1 -1
- package/dist/components/badge/types.js +0 -1
- package/dist/components/bottom-app-bar/types.js +0 -1
- package/dist/components/bottom-sheet/types.js +0 -1
- package/dist/components/button/types.js +0 -1
- package/dist/components/button-group/types.js +0 -1
- package/dist/components/card/features.js +0 -217
- package/dist/components/card/types.js +0 -1
- package/dist/components/carousel/types.js +0 -1
- package/dist/components/checkbox/types.js +0 -1
- package/dist/components/chips/chip/constants.js +0 -18
- package/dist/components/chips/chip/index.js +0 -1
- package/dist/components/chips/schema.js +0 -46
- package/dist/components/chips/types.js +0 -1
- package/dist/components/dialog/types.js +0 -1
- package/dist/components/divider/types.js +0 -1
- package/dist/components/drawer/types.js +0 -1
- package/dist/components/extended-fab/types.js +0 -1
- package/dist/components/fab/types.js +0 -1
- package/dist/components/fab-menu/types.js +0 -1
- package/dist/components/icon-button/types.js +0 -1
- package/dist/components/list/types.js +0 -1
- package/dist/components/loading-indicator/types.js +0 -1
- package/dist/components/menu/types.js +0 -14
- package/dist/components/navigation-bar/types.js +0 -1
- package/dist/components/navigation-rail/types.js +0 -1
- package/dist/components/progress/features/index.js +0 -4
- package/dist/components/progress/features/resize-observer.js +0 -40
- package/dist/components/progress/types.js +0 -1
- package/dist/components/radios/types.js +0 -1
- package/dist/components/search/types.js +0 -1
- package/dist/components/select/types.js +0 -4
- package/dist/components/side-sheet/types.js +0 -1
- package/dist/components/slider/api.js +0 -108
- package/dist/components/slider/features/handlers.js +0 -379
- package/dist/components/slider/features/range.js +0 -70
- package/dist/components/slider/features/tracks.js +0 -287
- package/dist/components/snackbar/types.js +0 -1
- package/dist/components/split-button/types.js +0 -1
- package/dist/components/switch/types.js +0 -1
- package/dist/components/tabs/scroll-indicators.js +0 -78
- package/dist/components/tabs/state.js +0 -44
- package/dist/components/tabs/types.js +0 -1
- package/dist/components/text-field/types.js +0 -18
- package/dist/components/toolbar/types.js +0 -1
- package/dist/components/top-app-bar/types.js +0 -1
- package/dist/core/utils/validate.js +0 -114
- package/dist/react/jsx.js +0 -2
- package/dist/solid/jsx.js +0 -1
|
@@ -8,7 +8,6 @@ export const withDom = (config) => (component) => {
|
|
|
8
8
|
const value = config.value !== undefined ? config.value : min;
|
|
9
9
|
const isDisabled = config.disabled === true;
|
|
10
10
|
const formatter = config.valueFormatter || ((val) => val.toString());
|
|
11
|
-
const valuePercent = ((value - min) / (max - min)) * 100;
|
|
12
11
|
const container = createElement({
|
|
13
12
|
tag: "div",
|
|
14
13
|
className: getClass("slider__container"),
|
|
@@ -20,83 +19,56 @@ export const withDom = (config) => (component) => {
|
|
|
20
19
|
const label = config.label || "";
|
|
21
20
|
const handleLabel = config.range && label ? `${label} minimum` : label;
|
|
22
21
|
const secondHandleLabel = label ? `${label} maximum` : "";
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
"aria-valuemin": String(min),
|
|
26
|
-
"aria-valuemax": String(max),
|
|
27
|
-
"aria-valuenow": String(value),
|
|
28
|
-
"aria-orientation": config.orientation === "vertical" ? "vertical" : "horizontal",
|
|
29
|
-
tabindex: isDisabled ? "-1" : "0",
|
|
30
|
-
"aria-disabled": isDisabled ? "true" : "false",
|
|
31
|
-
"data-value": String(value),
|
|
32
|
-
"data-handle-index": "0",
|
|
33
|
-
};
|
|
34
|
-
if (handleLabel) {
|
|
35
|
-
handleAttributes["aria-label"] = handleLabel;
|
|
36
|
-
}
|
|
37
|
-
const handle = createElement({
|
|
38
|
-
tag: "div",
|
|
39
|
-
className: getClass("slider__handle"),
|
|
40
|
-
attributes: handleAttributes,
|
|
41
|
-
container: container,
|
|
42
|
-
});
|
|
43
|
-
setStyles(handle, {
|
|
44
|
-
left: `${valuePercent}%`,
|
|
45
|
-
});
|
|
46
|
-
const valueBubble = createElement({
|
|
47
|
-
tag: "div",
|
|
48
|
-
className: getClass("slider__value"),
|
|
49
|
-
attributes: {
|
|
50
|
-
"aria-hidden": "true",
|
|
51
|
-
"data-handle-index": "0",
|
|
52
|
-
},
|
|
53
|
-
text: formatter(value),
|
|
54
|
-
container: container,
|
|
55
|
-
});
|
|
56
|
-
setStyles(valueBubble, {
|
|
57
|
-
left: `${valuePercent}%`,
|
|
58
|
-
});
|
|
59
|
-
let secondHandle;
|
|
60
|
-
let secondValueBubble;
|
|
61
|
-
if (config.range) {
|
|
62
|
-
const secondValue = config.secondValue !== undefined ? config.secondValue : max;
|
|
63
|
-
const secondValuePercent = ((secondValue - min) / (max - min)) * 100;
|
|
64
|
-
const secondHandleAttributes = {
|
|
22
|
+
const handleElement = (index, handleValue, name) => {
|
|
23
|
+
const attributes = {
|
|
65
24
|
role: "slider",
|
|
66
25
|
"aria-valuemin": String(min),
|
|
67
26
|
"aria-valuemax": String(max),
|
|
68
|
-
"aria-valuenow": String(
|
|
27
|
+
"aria-valuenow": String(handleValue),
|
|
69
28
|
"aria-orientation": config.orientation === "vertical" ? "vertical" : "horizontal",
|
|
70
29
|
tabindex: isDisabled ? "-1" : "0",
|
|
71
30
|
"aria-disabled": isDisabled ? "true" : "false",
|
|
72
|
-
"data-value": String(
|
|
73
|
-
"data-handle-index":
|
|
31
|
+
"data-value": String(handleValue),
|
|
32
|
+
"data-handle-index": String(index),
|
|
74
33
|
};
|
|
75
|
-
if (
|
|
76
|
-
|
|
34
|
+
if (name) {
|
|
35
|
+
attributes["aria-label"] = name;
|
|
77
36
|
}
|
|
78
|
-
|
|
37
|
+
const element = createElement({
|
|
79
38
|
tag: "div",
|
|
80
39
|
className: getClass("slider__handle"),
|
|
81
|
-
attributes
|
|
40
|
+
attributes,
|
|
82
41
|
container: container,
|
|
83
42
|
});
|
|
84
|
-
setStyles(
|
|
85
|
-
left: `${
|
|
43
|
+
setStyles(element, {
|
|
44
|
+
left: `${((handleValue - min) / (max - min)) * 100}%`,
|
|
86
45
|
});
|
|
87
|
-
|
|
46
|
+
return element;
|
|
47
|
+
};
|
|
48
|
+
const bubbleElement = (index, bubbleValue) => {
|
|
49
|
+
const element = createElement({
|
|
88
50
|
tag: "div",
|
|
89
51
|
className: getClass("slider__value"),
|
|
90
52
|
attributes: {
|
|
91
53
|
"aria-hidden": "true",
|
|
92
|
-
"data-handle-index":
|
|
54
|
+
"data-handle-index": String(index),
|
|
93
55
|
},
|
|
94
|
-
text: formatter(
|
|
56
|
+
text: formatter(bubbleValue),
|
|
95
57
|
container: container,
|
|
96
58
|
});
|
|
97
|
-
setStyles(
|
|
98
|
-
left: `${
|
|
59
|
+
setStyles(element, {
|
|
60
|
+
left: `${((bubbleValue - min) / (max - min)) * 100}%`,
|
|
99
61
|
});
|
|
62
|
+
return element;
|
|
63
|
+
};
|
|
64
|
+
const handle = handleElement(0, value, handleLabel);
|
|
65
|
+
const valueBubble = bubbleElement(0, value);
|
|
66
|
+
let secondHandle;
|
|
67
|
+
let secondValueBubble;
|
|
68
|
+
if (config.range) {
|
|
69
|
+
const secondValue = config.secondValue !== undefined ? config.secondValue : max;
|
|
70
|
+
secondHandle = handleElement(1, secondValue, secondHandleLabel);
|
|
71
|
+
secondValueBubble = bubbleElement(1, secondValue);
|
|
100
72
|
}
|
|
101
73
|
const name = config.name;
|
|
102
74
|
const formFields = name
|
|
@@ -115,10 +87,5 @@ export const withDom = (config) => (component) => {
|
|
|
115
87
|
secondHandle,
|
|
116
88
|
secondValueBubble,
|
|
117
89
|
formFields,
|
|
118
|
-
getContainer: () => container,
|
|
119
|
-
getHandle: () => handle,
|
|
120
|
-
getValueBubble: () => valueBubble,
|
|
121
|
-
getSecondHandle: () => secondHandle || null,
|
|
122
|
-
getSecondValueBubble: () => secondValueBubble || null,
|
|
123
90
|
};
|
|
124
91
|
};
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export { withRange } from "./range.js";
|
|
2
1
|
export { withStates } from "./states.js";
|
|
3
|
-
export { withController } from "./controller.js";
|
|
4
|
-
export { withTracks } from "./tracks.js";
|
|
2
|
+
export { withController, withTracks } from "./controller.js";
|
|
5
3
|
export { withDom } from "./dom.js";
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { SLIDER_COLORS } from "../types.js";
|
|
2
|
-
import { SLIDER_SIZES } from "../constants.js";
|
|
3
2
|
export const withStates = (config) => (component) => {
|
|
4
|
-
const handle = component.handle
|
|
5
|
-
const secondHandle = component.secondHandle
|
|
3
|
+
const handle = component.handle;
|
|
4
|
+
const secondHandle = component.secondHandle;
|
|
6
5
|
const setFieldsDisabled = (disabled) => {
|
|
7
6
|
for (const field of component.formFields ?? []) {
|
|
8
7
|
if (field)
|
|
@@ -44,11 +43,6 @@ export const withStates = (config) => (component) => {
|
|
|
44
43
|
function getActiveColor() {
|
|
45
44
|
return (Object.values(SLIDER_COLORS).find((colorName) => component.element.classList.contains(`${component.getClass("slider")}--${colorName}`)) || SLIDER_COLORS.PRIMARY);
|
|
46
45
|
}
|
|
47
|
-
function getActiveSize() {
|
|
48
|
-
const sizeKeys = Object.keys(SLIDER_SIZES);
|
|
49
|
-
const foundKey = sizeKeys.find((sizeKey) => component.element.classList.contains(`${component.getClass("slider")}--${sizeKey.toLowerCase()}`));
|
|
50
|
-
return foundKey || "XS";
|
|
51
|
-
}
|
|
52
46
|
if (config.disabled === true)
|
|
53
47
|
disableComponent();
|
|
54
48
|
return Object.assign(component, {
|
|
@@ -78,28 +72,6 @@ export const withStates = (config) => (component) => {
|
|
|
78
72
|
getColor() {
|
|
79
73
|
return getActiveColor();
|
|
80
74
|
},
|
|
81
|
-
setSize(size) {
|
|
82
|
-
const sizeKeys = Object.keys(SLIDER_SIZES);
|
|
83
|
-
sizeKeys.forEach((sizeKey) => {
|
|
84
|
-
component.element.classList.remove(`${component.getClass("slider")}--${sizeKey.toLowerCase()}`);
|
|
85
|
-
});
|
|
86
|
-
let sizeKey;
|
|
87
|
-
if (typeof size === "string" && size in SLIDER_SIZES) {
|
|
88
|
-
sizeKey = size;
|
|
89
|
-
}
|
|
90
|
-
else if (typeof size === "number") {
|
|
91
|
-
const entry = Object.entries(SLIDER_SIZES).find(([, value]) => value === size);
|
|
92
|
-
sizeKey = entry ? entry[0] : "XS";
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
sizeKey = "XS";
|
|
96
|
-
}
|
|
97
|
-
component.element.classList.add(`${component.getClass("slider")}--${sizeKey.toLowerCase()}`);
|
|
98
|
-
return this;
|
|
99
|
-
},
|
|
100
|
-
getSize() {
|
|
101
|
-
return getActiveSize();
|
|
102
|
-
},
|
|
103
75
|
showTicks(show) {
|
|
104
76
|
config.ticks = show;
|
|
105
77
|
component.renderTracks?.();
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { pipe } from "../../core/compose/pipe.js";
|
|
2
2
|
import { createBase, withElement } from "../../core/compose/component.js";
|
|
3
3
|
import { withEvents, withLifecycle, withIcon, withTextLabel, } from "../../core/compose/features/index.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { createBaseConfig, getElementConfig, getApiConfig } from "./config.js";
|
|
4
|
+
import { withStates, withController, withTracks, withDom, } from "./features/index.js";
|
|
5
|
+
import { createBaseConfig, getElementConfig } from "./config.js";
|
|
7
6
|
const createSlider = (config = {}) => {
|
|
8
7
|
const baseConfig = createBaseConfig(config);
|
|
9
8
|
try {
|
|
10
|
-
const
|
|
11
|
-
const apiOptions = getApiConfig(component);
|
|
12
|
-
const slider = withAPI(apiOptions)(component);
|
|
9
|
+
const slider = pipe(createBase, withEvents(), withElement(getElementConfig(baseConfig)), withDom(baseConfig), withTextLabel(baseConfig), withIcon(baseConfig), withLifecycle(), withStates(baseConfig), withTracks(baseConfig), withController(baseConfig, () => slider))(baseConfig);
|
|
13
10
|
if (baseConfig.on && typeof slider.on === "function") {
|
|
14
11
|
Object.entries(baseConfig.on).forEach(([event, handler]) => {
|
|
15
12
|
if (typeof handler === "function") {
|
|
@@ -47,10 +47,8 @@ export interface SliderEvent {
|
|
|
47
47
|
}
|
|
48
48
|
export type SliderActiveHandle = "first" | "second" | null;
|
|
49
49
|
export interface SliderState {
|
|
50
|
-
component: SliderStateComponent;
|
|
51
50
|
value: number;
|
|
52
51
|
secondValue: number | null;
|
|
53
|
-
previousValue?: number;
|
|
54
52
|
min: number;
|
|
55
53
|
max: number;
|
|
56
54
|
step: number;
|
|
@@ -67,7 +65,6 @@ export interface SliderStateComponent {
|
|
|
67
65
|
valueBubble?: HTMLElement | null;
|
|
68
66
|
secondHandle?: HTMLElement | null;
|
|
69
67
|
secondValueBubble?: HTMLElement | null;
|
|
70
|
-
components?: Record<string, HTMLElement | null | undefined>;
|
|
71
68
|
getClass: (name: string) => string;
|
|
72
69
|
emit: (event: string, data: unknown) => unknown;
|
|
73
70
|
disabled?: {
|
|
@@ -80,31 +77,8 @@ export interface SliderStateComponent {
|
|
|
80
77
|
destroy?: () => void;
|
|
81
78
|
mount?: () => void;
|
|
82
79
|
};
|
|
83
|
-
slider?: {
|
|
84
|
-
setValue?: (value: number, triggerEvent?: boolean) => unknown;
|
|
85
|
-
};
|
|
86
80
|
}
|
|
87
81
|
export type SliderPointerEvent = MouseEvent | TouchEvent;
|
|
88
|
-
export interface SliderElements {
|
|
89
|
-
container?: HTMLElement | null;
|
|
90
|
-
handle?: HTMLElement | null;
|
|
91
|
-
valueBubble?: HTMLElement | null;
|
|
92
|
-
secondHandle?: HTMLElement | null;
|
|
93
|
-
secondValueBubble?: HTMLElement | null;
|
|
94
|
-
[key: string]: HTMLElement | null | undefined;
|
|
95
|
-
}
|
|
96
|
-
export interface SliderUiRenderer {
|
|
97
|
-
getPercentage: (value: number) => number;
|
|
98
|
-
getValueFromPosition: (position: number) => number;
|
|
99
|
-
roundToStep: (value: number) => number;
|
|
100
|
-
clamp: (value: number, min?: number, max?: number) => number;
|
|
101
|
-
showValueBubble: (bubbleElement: HTMLElement | null, show: boolean) => void;
|
|
102
|
-
updateUi: () => void;
|
|
103
|
-
render: () => void;
|
|
104
|
-
}
|
|
105
|
-
export interface SliderEventHelpers {
|
|
106
|
-
triggerEvent: (eventName: string, originalEvent?: Event | null) => void;
|
|
107
|
-
}
|
|
108
82
|
export interface SliderEvents extends TouchEvents {
|
|
109
83
|
change: (payload: SliderEvent) => void;
|
|
110
84
|
input: (payload: SliderEvent) => void;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export const createOnDemandMenu = (settings, items) => {
|
|
2
|
+
let menu = null;
|
|
3
|
+
let loading = false;
|
|
4
|
+
let destroyed = false;
|
|
5
|
+
let opened = false;
|
|
6
|
+
let asked = [undefined, undefined];
|
|
7
|
+
let current = items;
|
|
8
|
+
let selected;
|
|
9
|
+
let position = settings.position ?? "bottom-end";
|
|
10
|
+
let opener = settings.opener;
|
|
11
|
+
const openerElement = typeof settings.opener === "string"
|
|
12
|
+
? null
|
|
13
|
+
: settings.opener.element ?? settings.opener;
|
|
14
|
+
const placeholder = document.createElement("div");
|
|
15
|
+
placeholder.id = `menu-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
|
|
16
|
+
openerElement?.setAttribute("aria-controls", placeholder.id);
|
|
17
|
+
const listeners = new Map();
|
|
18
|
+
const notify = (event, payload) => {
|
|
19
|
+
for (const listener of listeners.get(event) ?? [])
|
|
20
|
+
listener(payload);
|
|
21
|
+
};
|
|
22
|
+
const attach = (created) => {
|
|
23
|
+
menu = created;
|
|
24
|
+
if (selected !== undefined)
|
|
25
|
+
created.setSelected(selected);
|
|
26
|
+
if (position !== settings.position)
|
|
27
|
+
created.setPosition(position);
|
|
28
|
+
if (opener !== settings.opener)
|
|
29
|
+
created.setOpener(opener);
|
|
30
|
+
if (opened)
|
|
31
|
+
created.open(asked[0], asked[1]);
|
|
32
|
+
for (const [event, set] of listeners)
|
|
33
|
+
for (const listener of set)
|
|
34
|
+
created.on(event, listener);
|
|
35
|
+
listeners.clear();
|
|
36
|
+
};
|
|
37
|
+
const load = () => {
|
|
38
|
+
if (menu || loading || destroyed)
|
|
39
|
+
return;
|
|
40
|
+
loading = true;
|
|
41
|
+
import("../../menu/index.js").then(({ default: createMenu }) => {
|
|
42
|
+
loading = false;
|
|
43
|
+
if (destroyed)
|
|
44
|
+
return;
|
|
45
|
+
attach(createMenu({ ...settings, items: current }));
|
|
46
|
+
}, (error) => {
|
|
47
|
+
loading = false;
|
|
48
|
+
console.error("Split button menu failed to load:", error);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const api = {
|
|
52
|
+
get element() {
|
|
53
|
+
return menu?.element ?? placeholder;
|
|
54
|
+
},
|
|
55
|
+
open(event, interactionType) {
|
|
56
|
+
if (menu) {
|
|
57
|
+
menu.open(event, interactionType);
|
|
58
|
+
return api;
|
|
59
|
+
}
|
|
60
|
+
if (!opened) {
|
|
61
|
+
opened = true;
|
|
62
|
+
notify("open", { menu: api, originalEvent: event });
|
|
63
|
+
}
|
|
64
|
+
asked = [event, interactionType];
|
|
65
|
+
load();
|
|
66
|
+
return api;
|
|
67
|
+
},
|
|
68
|
+
close(event, restoreFocus = true, skipAnimation = false) {
|
|
69
|
+
if (menu) {
|
|
70
|
+
menu.close(event, restoreFocus, skipAnimation);
|
|
71
|
+
return api;
|
|
72
|
+
}
|
|
73
|
+
if (opened) {
|
|
74
|
+
opened = false;
|
|
75
|
+
notify("close", { menu: api, originalEvent: event });
|
|
76
|
+
}
|
|
77
|
+
return api;
|
|
78
|
+
},
|
|
79
|
+
toggle(event) {
|
|
80
|
+
if (api.isOpen())
|
|
81
|
+
api.close(event);
|
|
82
|
+
else
|
|
83
|
+
api.open(event);
|
|
84
|
+
return api;
|
|
85
|
+
},
|
|
86
|
+
isOpen: () => (menu ? menu.isOpen() : opened),
|
|
87
|
+
setItems(items) {
|
|
88
|
+
current = items;
|
|
89
|
+
menu?.setItems(items);
|
|
90
|
+
return api;
|
|
91
|
+
},
|
|
92
|
+
getItems: () => (menu ? menu.getItems() : current),
|
|
93
|
+
setOpener(value) {
|
|
94
|
+
if (menu)
|
|
95
|
+
menu.setOpener(value);
|
|
96
|
+
else
|
|
97
|
+
opener = value;
|
|
98
|
+
return api;
|
|
99
|
+
},
|
|
100
|
+
getOpener: () => (menu ? menu.getOpener() : opener),
|
|
101
|
+
setPosition(value) {
|
|
102
|
+
if (menu)
|
|
103
|
+
menu.setPosition(value);
|
|
104
|
+
else
|
|
105
|
+
position = value;
|
|
106
|
+
return api;
|
|
107
|
+
},
|
|
108
|
+
getPosition: () => (menu ? menu.getPosition() : position),
|
|
109
|
+
setSelected(value) {
|
|
110
|
+
if (menu)
|
|
111
|
+
menu.setSelected(value);
|
|
112
|
+
else
|
|
113
|
+
selected = value;
|
|
114
|
+
return api;
|
|
115
|
+
},
|
|
116
|
+
getSelected: () => (menu ? menu.getSelected() : (selected ?? null)),
|
|
117
|
+
on(event, handler) {
|
|
118
|
+
if (menu)
|
|
119
|
+
menu.on(event, handler);
|
|
120
|
+
else {
|
|
121
|
+
const set = listeners.get(event) ?? new Set();
|
|
122
|
+
set.add(handler);
|
|
123
|
+
listeners.set(event, set);
|
|
124
|
+
}
|
|
125
|
+
return api;
|
|
126
|
+
},
|
|
127
|
+
off(event, handler) {
|
|
128
|
+
if (menu)
|
|
129
|
+
menu.off(event, handler);
|
|
130
|
+
else
|
|
131
|
+
listeners.get(event)?.delete(handler);
|
|
132
|
+
return api;
|
|
133
|
+
},
|
|
134
|
+
destroy() {
|
|
135
|
+
destroyed = true;
|
|
136
|
+
listeners.clear();
|
|
137
|
+
menu?.destroy();
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
return api;
|
|
141
|
+
};
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import createMenu from "../../menu/index.js";
|
|
2
1
|
import { MENU } from "../../menu/inner.js";
|
|
3
2
|
import { SPLIT_BUTTON_DEFAULTS } from "../constants.js";
|
|
4
|
-
|
|
3
|
+
import { createOnDemandMenu } from "./menu-on-demand.js";
|
|
4
|
+
export const makeMenu = (config, trailing, items) => createOnDemandMenu({
|
|
5
5
|
opener: trailing,
|
|
6
|
-
items,
|
|
7
6
|
position: "bottom-end",
|
|
8
7
|
offset: SPLIT_BUTTON_DEFAULTS.MENU_OFFSET,
|
|
9
8
|
manualOpen: true,
|
|
10
9
|
...(config.layer ? { layer: config.layer } : {}),
|
|
11
10
|
prefix: config.prefix,
|
|
12
|
-
});
|
|
11
|
+
}, items);
|
|
13
12
|
export const withMenu = (config) => (component) => {
|
|
14
13
|
if (!config.items || config.items.length === 0)
|
|
15
14
|
return component;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const observeCanvasResize: (element: HTMLElement,
|
|
1
|
+
export declare const observeCanvasResize: (element: HTMLElement, canvas: HTMLCanvasElement | null | undefined, onResize: () => void) => (() => void);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const observeCanvasResize = (element,
|
|
1
|
+
export const observeCanvasResize = (element, canvas, onResize) => {
|
|
2
2
|
let timeoutId = null;
|
|
3
3
|
const debouncedResize = () => {
|
|
4
4
|
if (timeoutId)
|
|
@@ -7,6 +7,21 @@ export const observeCanvasResize = (element, _canvas, onResize) => {
|
|
|
7
7
|
onResize();
|
|
8
8
|
}, 100);
|
|
9
9
|
};
|
|
10
|
+
const view = canvas ? element.ownerDocument?.defaultView ?? null : null;
|
|
11
|
+
let resolution = null;
|
|
12
|
+
function onResolutionChange() {
|
|
13
|
+
resolution?.removeEventListener("change", onResolutionChange);
|
|
14
|
+
armResolution();
|
|
15
|
+
debouncedResize();
|
|
16
|
+
}
|
|
17
|
+
function armResolution() {
|
|
18
|
+
if (!view?.matchMedia)
|
|
19
|
+
return;
|
|
20
|
+
resolution = view.matchMedia(`(resolution: ${view.devicePixelRatio || 1}dppx)`);
|
|
21
|
+
resolution.addEventListener("change", onResolutionChange);
|
|
22
|
+
}
|
|
23
|
+
armResolution();
|
|
24
|
+
let stopWidth;
|
|
10
25
|
if (typeof ResizeObserver !== 'undefined') {
|
|
11
26
|
let seen = -1;
|
|
12
27
|
const observer = new ResizeObserver((entries) => {
|
|
@@ -19,18 +34,16 @@ export const observeCanvasResize = (element, _canvas, onResize) => {
|
|
|
19
34
|
}
|
|
20
35
|
});
|
|
21
36
|
observer.observe(element);
|
|
22
|
-
|
|
23
|
-
if (timeoutId)
|
|
24
|
-
clearTimeout(timeoutId);
|
|
25
|
-
observer.disconnect();
|
|
26
|
-
};
|
|
37
|
+
stopWidth = () => observer.disconnect();
|
|
27
38
|
}
|
|
28
39
|
else {
|
|
29
40
|
window.addEventListener('resize', debouncedResize);
|
|
30
|
-
|
|
31
|
-
if (timeoutId)
|
|
32
|
-
clearTimeout(timeoutId);
|
|
33
|
-
window.removeEventListener('resize', debouncedResize);
|
|
34
|
-
};
|
|
41
|
+
stopWidth = () => window.removeEventListener('resize', debouncedResize);
|
|
35
42
|
}
|
|
43
|
+
return () => {
|
|
44
|
+
if (timeoutId)
|
|
45
|
+
clearTimeout(timeoutId);
|
|
46
|
+
resolution?.removeEventListener("change", onResolutionChange);
|
|
47
|
+
stopWidth();
|
|
48
|
+
};
|
|
36
49
|
};
|
package/dist/core/dom/classes.js
CHANGED
|
@@ -56,134 +56,33 @@ export const normalizeClasses = (...classes) => {
|
|
|
56
56
|
}
|
|
57
57
|
return result;
|
|
58
58
|
};
|
|
59
|
-
|
|
60
|
-
if (classes.length ===
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const cls = classes[0];
|
|
67
|
-
if (cls && !cls.includes(" ")) {
|
|
68
|
-
const prefixed = cls;
|
|
69
|
-
if (!prefixed.includes(" ")) {
|
|
70
|
-
element.classList.add(prefixed);
|
|
71
|
-
return element;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const normalized = normalizeClasses(...classes);
|
|
76
|
-
for (const cls of normalized) {
|
|
77
|
-
const prefixed = cls;
|
|
78
|
-
if (prefixed.includes(" ")) {
|
|
79
|
-
prefixed.split(" ").forEach((c) => {
|
|
80
|
-
const trimmed = c.trim();
|
|
81
|
-
if (trimmed)
|
|
82
|
-
element.classList.add(trimmed);
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
element.classList.add(prefixed);
|
|
87
|
-
}
|
|
59
|
+
const forEachClass = (classes, apply) => {
|
|
60
|
+
if (classes.length === 1 &&
|
|
61
|
+
typeof classes[0] === "string" &&
|
|
62
|
+
classes[0] &&
|
|
63
|
+
!classes[0].includes(" ")) {
|
|
64
|
+
apply(classes[0]);
|
|
65
|
+
return;
|
|
88
66
|
}
|
|
67
|
+
for (const name of normalizeClasses(...classes))
|
|
68
|
+
apply(name);
|
|
69
|
+
};
|
|
70
|
+
export const addClass = (element, ...classes) => {
|
|
71
|
+
forEachClass(classes, (name) => element.classList.add(name));
|
|
89
72
|
return element;
|
|
90
73
|
};
|
|
91
74
|
export const removeClass = (element, ...classes) => {
|
|
92
|
-
|
|
93
|
-
return element;
|
|
94
|
-
if (classes.length === 1 && Array.isArray(classes[0])) {
|
|
95
|
-
return removeClass(element, ...classes[0]);
|
|
96
|
-
}
|
|
97
|
-
if (classes.length === 1 && typeof classes[0] === "string") {
|
|
98
|
-
const cls = classes[0];
|
|
99
|
-
if (cls && !cls.includes(" ")) {
|
|
100
|
-
const prefixed = cls;
|
|
101
|
-
if (!prefixed.includes(" ")) {
|
|
102
|
-
element.classList.remove(prefixed);
|
|
103
|
-
return element;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
const normalized = normalizeClasses(...classes);
|
|
108
|
-
for (const cls of normalized) {
|
|
109
|
-
const prefixed = cls;
|
|
110
|
-
if (prefixed.includes(" ")) {
|
|
111
|
-
prefixed.split(" ").forEach((c) => {
|
|
112
|
-
const trimmed = c.trim();
|
|
113
|
-
if (trimmed)
|
|
114
|
-
element.classList.remove(trimmed);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
element.classList.remove(prefixed);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
75
|
+
forEachClass(classes, (name) => element.classList.remove(name));
|
|
121
76
|
return element;
|
|
122
77
|
};
|
|
123
78
|
export const toggleClass = (element, ...classes) => {
|
|
124
|
-
|
|
125
|
-
return toggleClass(element, ...classes[0]);
|
|
126
|
-
}
|
|
127
|
-
if (classes.length === 1 && typeof classes[0] === "string") {
|
|
128
|
-
const cls = classes[0];
|
|
129
|
-
if (cls && !cls.includes(" ")) {
|
|
130
|
-
const prefixed = cls;
|
|
131
|
-
if (!prefixed.includes(" ")) {
|
|
132
|
-
element.classList.toggle(prefixed);
|
|
133
|
-
return element;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
const normalized = normalizeClasses(...classes);
|
|
138
|
-
for (const cls of normalized) {
|
|
139
|
-
const prefixed = cls;
|
|
140
|
-
if (prefixed.includes(" ")) {
|
|
141
|
-
prefixed.split(" ").forEach((c) => {
|
|
142
|
-
const trimmed = c.trim();
|
|
143
|
-
if (trimmed)
|
|
144
|
-
element.classList.toggle(trimmed);
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
element.classList.toggle(prefixed);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
79
|
+
forEachClass(classes, (name) => element.classList.toggle(name));
|
|
151
80
|
return element;
|
|
152
81
|
};
|
|
153
82
|
export const hasClass = (element, ...classes) => {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return hasClass(element, ...classes[0]);
|
|
158
|
-
}
|
|
159
|
-
if (classes.length === 1 && typeof classes[0] === "string") {
|
|
160
|
-
const cls = classes[0];
|
|
161
|
-
if (cls && !cls.includes(" ")) {
|
|
162
|
-
const prefixed = cls;
|
|
163
|
-
if (!prefixed.includes(" ")) {
|
|
164
|
-
return element.classList.contains(prefixed);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
const normalized = normalizeClasses(...classes);
|
|
169
|
-
for (const cls of normalized) {
|
|
170
|
-
const prefixed = cls;
|
|
171
|
-
if (prefixed.includes(" ")) {
|
|
172
|
-
const tokens = prefixed
|
|
173
|
-
.split(" ")
|
|
174
|
-
.map((c) => c.trim())
|
|
175
|
-
.filter(Boolean);
|
|
176
|
-
for (const token of tokens) {
|
|
177
|
-
if (!element.classList.contains(token)) {
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
if (!element.classList.contains(prefixed)) {
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
83
|
+
for (const name of normalizeClasses(...classes)) {
|
|
84
|
+
if (!element.classList.contains(name))
|
|
85
|
+
return false;
|
|
187
86
|
}
|
|
188
87
|
return true;
|
|
189
88
|
};
|
|
@@ -45,8 +45,6 @@ export interface ForwardedEventPayload<E extends Event = Event, TElement extends
|
|
|
45
45
|
originalEvent: E;
|
|
46
46
|
}
|
|
47
47
|
export declare const createElement: (options?: CreateElementOptions) => HTMLElement;
|
|
48
|
-
export declare const createElementPooled: (options?: CreateElementOptions) => HTMLElement;
|
|
49
|
-
export declare const releaseElement: (element: HTMLElement) => void;
|
|
50
48
|
export declare const createSVGElement: (options?: CreateSVGElementOptions) => SVGElement;
|
|
51
49
|
export declare const removeEventHandlers: (element: HTMLElement | SVGElement) => void;
|
|
52
50
|
declare global {
|