material 3.3.1 → 3.3.3
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/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/tooltip/api.js +53 -97
- 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/css/tooltip.css +1 -1
- package/dist/elements/css/tooltip.js +1 -1
- 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 +2 -2
- 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 +2 -2
- 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/src/styles/components/_tooltip.scss +3 -16
- package/dist/components/card/features.js +0 -217
- 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/progress/features/index.js +0 -4
- package/dist/components/progress/features/resize-observer.js +0 -40
- 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/tabs/scroll-indicators.js +0 -78
- package/dist/components/tabs/state.js +0 -44
- package/dist/core/utils/validate.js +0 -114
|
@@ -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;
|
|
@@ -40,106 +40,62 @@ export const withAPI = ({ lifecycle }) => (component) => {
|
|
|
40
40
|
if (!target)
|
|
41
41
|
return { top: 0, left: 0 };
|
|
42
42
|
component.element.style.left = "0px";
|
|
43
|
-
const
|
|
44
|
-
const
|
|
43
|
+
const styles = getComputedStyle(component.element);
|
|
44
|
+
const tooltipWidth = parseFloat(styles.width);
|
|
45
|
+
const tooltipHeight = parseFloat(styles.height);
|
|
45
46
|
const targetRect = target.getBoundingClientRect();
|
|
46
47
|
const offset = DEFAULT_OFFSET;
|
|
47
48
|
let top = 0;
|
|
48
49
|
let left = 0;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
break;
|
|
64
|
-
case TOOLTIP_POSITIONS.TOP_END:
|
|
65
|
-
top = targetRect.top - tooltipHeight - offset;
|
|
66
|
-
left =
|
|
67
|
-
targetRect.left + targetRect.width - tooltipWidth;
|
|
68
|
-
arrowPosition = "bottom-end";
|
|
69
|
-
break;
|
|
70
|
-
case TOOLTIP_POSITIONS.RIGHT:
|
|
71
|
-
top =
|
|
72
|
-
targetRect.top +
|
|
73
|
-
targetRect.height / 2 -
|
|
74
|
-
tooltipHeight / 2;
|
|
75
|
-
left = targetRect.left + targetRect.width + offset;
|
|
76
|
-
arrowPosition = "left";
|
|
77
|
-
break;
|
|
78
|
-
case TOOLTIP_POSITIONS.RIGHT_START:
|
|
79
|
-
top = targetRect.top;
|
|
80
|
-
left = targetRect.left + targetRect.width + offset;
|
|
81
|
-
arrowPosition = "left-start";
|
|
82
|
-
break;
|
|
83
|
-
case TOOLTIP_POSITIONS.RIGHT_END:
|
|
84
|
-
top =
|
|
85
|
-
targetRect.top + targetRect.height - tooltipHeight;
|
|
86
|
-
left = targetRect.left + targetRect.width + offset;
|
|
87
|
-
arrowPosition = "left-end";
|
|
88
|
-
break;
|
|
89
|
-
case TOOLTIP_POSITIONS.BOTTOM:
|
|
90
|
-
top = targetRect.top + targetRect.height + offset;
|
|
91
|
-
left =
|
|
92
|
-
targetRect.left +
|
|
93
|
-
targetRect.width / 2 -
|
|
94
|
-
tooltipWidth / 2;
|
|
95
|
-
arrowPosition = "top";
|
|
96
|
-
break;
|
|
97
|
-
case TOOLTIP_POSITIONS.BOTTOM_START:
|
|
98
|
-
top = targetRect.top + targetRect.height + offset;
|
|
99
|
-
left = targetRect.left;
|
|
100
|
-
arrowPosition = "top-start";
|
|
101
|
-
break;
|
|
102
|
-
case TOOLTIP_POSITIONS.BOTTOM_END:
|
|
103
|
-
top = targetRect.top + targetRect.height + offset;
|
|
104
|
-
left =
|
|
105
|
-
targetRect.left + targetRect.width - tooltipWidth;
|
|
106
|
-
arrowPosition = "top-end";
|
|
107
|
-
break;
|
|
108
|
-
case TOOLTIP_POSITIONS.LEFT:
|
|
109
|
-
top =
|
|
110
|
-
targetRect.top +
|
|
111
|
-
targetRect.height / 2 -
|
|
112
|
-
tooltipHeight / 2;
|
|
113
|
-
left = targetRect.left - tooltipWidth - offset;
|
|
114
|
-
arrowPosition = "right";
|
|
115
|
-
break;
|
|
116
|
-
case TOOLTIP_POSITIONS.LEFT_START:
|
|
117
|
-
top = targetRect.top;
|
|
118
|
-
left = targetRect.left - tooltipWidth - offset;
|
|
119
|
-
arrowPosition = "right-start";
|
|
120
|
-
break;
|
|
121
|
-
case TOOLTIP_POSITIONS.LEFT_END:
|
|
122
|
-
top =
|
|
123
|
-
targetRect.top + targetRect.height - tooltipHeight;
|
|
124
|
-
left = targetRect.left - tooltipWidth - offset;
|
|
125
|
-
arrowPosition = "right-end";
|
|
126
|
-
break;
|
|
127
|
-
default:
|
|
128
|
-
top = targetRect.top + targetRect.height + offset;
|
|
129
|
-
left =
|
|
130
|
-
targetRect.left +
|
|
131
|
-
targetRect.width / 2 -
|
|
132
|
-
tooltipWidth / 2;
|
|
133
|
-
arrowPosition = "top";
|
|
50
|
+
const [side, anchor] = position.split("-");
|
|
51
|
+
const vertical = side !== "left" && side !== "right";
|
|
52
|
+
const align = anchor === "start" ? 0 : anchor === "end" ? 1 : 0.5;
|
|
53
|
+
if (vertical) {
|
|
54
|
+
top = side === "top"
|
|
55
|
+
? targetRect.top - tooltipHeight - offset
|
|
56
|
+
: targetRect.bottom + offset;
|
|
57
|
+
left = targetRect.left + (targetRect.width - tooltipWidth) * align;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
left = side === "left"
|
|
61
|
+
? targetRect.left - tooltipWidth - offset
|
|
62
|
+
: targetRect.right + offset;
|
|
63
|
+
top = targetRect.top + (targetRect.height - tooltipHeight) * align;
|
|
134
64
|
}
|
|
135
65
|
const windowWidth = window.innerWidth;
|
|
136
|
-
|
|
137
|
-
|
|
66
|
+
const windowHeight = window.innerHeight;
|
|
67
|
+
let suffix = anchor ? `-${anchor}` : "";
|
|
68
|
+
if (vertical) {
|
|
69
|
+
if (top < 0)
|
|
70
|
+
top = targetRect.bottom + offset;
|
|
71
|
+
else if (top + tooltipHeight > windowHeight) {
|
|
72
|
+
top = targetRect.top - tooltipHeight - offset;
|
|
73
|
+
}
|
|
138
74
|
}
|
|
139
|
-
|
|
140
|
-
|
|
75
|
+
const clampedX = left < 0 || left + tooltipWidth > windowWidth;
|
|
76
|
+
const clampedY = top < 0 || top + tooltipHeight > windowHeight;
|
|
77
|
+
left = Math.max(0, Math.min(windowWidth - tooltipWidth, left));
|
|
78
|
+
top = Math.max(0, Math.min(windowHeight - tooltipHeight, top));
|
|
79
|
+
if (vertical ? clampedX : clampedY) {
|
|
80
|
+
const from = vertical ? left : top;
|
|
81
|
+
const size = vertical ? tooltipWidth : tooltipHeight;
|
|
82
|
+
const targetFrom = vertical ? targetRect.left : targetRect.top;
|
|
83
|
+
const targetTo = vertical ? targetRect.right : targetRect.bottom;
|
|
84
|
+
const spanAt = [from + 8, from + size / 2 - 8, from + size - 24];
|
|
85
|
+
const meet = spanAt.findIndex((x) => x + 16 > targetFrom && x < targetTo);
|
|
86
|
+
suffix = ["-start", "", "-end"][meet < 0 ? 2 : meet];
|
|
141
87
|
}
|
|
142
|
-
return {
|
|
88
|
+
return {
|
|
89
|
+
top,
|
|
90
|
+
left,
|
|
91
|
+
arrowPosition: (vertical
|
|
92
|
+
? top + tooltipHeight <= targetRect.top
|
|
93
|
+
? "bottom"
|
|
94
|
+
: "top"
|
|
95
|
+
: left + tooltipWidth <= targetRect.left
|
|
96
|
+
? "right"
|
|
97
|
+
: "left") + suffix,
|
|
98
|
+
};
|
|
143
99
|
};
|
|
144
100
|
const addTargetEvents = (targetEl) => {
|
|
145
101
|
if (showOnHover) {
|
|
@@ -264,7 +220,7 @@ export const withAPI = ({ lifecycle }) => (component) => {
|
|
|
264
220
|
isVisible = true;
|
|
265
221
|
this.updatePosition();
|
|
266
222
|
window.addEventListener("resize", handleWindowResize);
|
|
267
|
-
window.addEventListener("scroll", handleWindowScroll);
|
|
223
|
+
window.addEventListener("scroll", handleWindowScroll, true);
|
|
268
224
|
document.addEventListener("keydown", handleDocumentKeydown);
|
|
269
225
|
};
|
|
270
226
|
if (immediate) {
|
|
@@ -289,7 +245,7 @@ export const withAPI = ({ lifecycle }) => (component) => {
|
|
|
289
245
|
component.element.classList.remove(`${component.getClass("tooltip")}--visible`);
|
|
290
246
|
isVisible = false;
|
|
291
247
|
window.removeEventListener("resize", handleWindowResize);
|
|
292
|
-
window.removeEventListener("scroll", handleWindowScroll);
|
|
248
|
+
window.removeEventListener("scroll", handleWindowScroll, true);
|
|
293
249
|
document.removeEventListener("keydown", handleDocumentKeydown);
|
|
294
250
|
if (topLayer) {
|
|
295
251
|
if (layerTimer !== null)
|
|
@@ -316,8 +272,8 @@ export const withAPI = ({ lifecycle }) => (component) => {
|
|
|
316
272
|
if (!target)
|
|
317
273
|
return this;
|
|
318
274
|
const { top, left, arrowPosition } = calculatePosition();
|
|
319
|
-
component.element.style.top = `${
|
|
320
|
-
component.element.style.left = `${
|
|
275
|
+
component.element.style.top = `${top}px`;
|
|
276
|
+
component.element.style.left = `${left}px`;
|
|
321
277
|
if (arrowPosition) {
|
|
322
278
|
arrowElement.className = `${component.getClass("tooltip")}__arrow`;
|
|
323
279
|
arrowElement.classList.add(`${component.getClass("tooltip")}__arrow--${arrowPosition}`);
|
|
@@ -339,7 +295,7 @@ export const withAPI = ({ lifecycle }) => (component) => {
|
|
|
339
295
|
undescribe(target);
|
|
340
296
|
}
|
|
341
297
|
window.removeEventListener("resize", handleWindowResize);
|
|
342
|
-
window.removeEventListener("scroll", handleWindowScroll);
|
|
298
|
+
window.removeEventListener("scroll", handleWindowScroll, true);
|
|
343
299
|
document.removeEventListener("keydown", handleDocumentKeydown);
|
|
344
300
|
component.element.removeEventListener("mouseenter", handleTooltipMouseEnter);
|
|
345
301
|
component.element.removeEventListener("mouseleave", handleTooltipMouseLeave);
|
|
@@ -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
|
};
|