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.
Files changed (189) hide show
  1. package/README.md +2 -2
  2. package/dist/components/menu/features/controller.js +23 -75
  3. package/dist/components/menu/features/opener.js +3 -15
  4. package/dist/components/menu/types.d.ts +1 -0
  5. package/dist/components/slider/config.js +0 -46
  6. package/dist/components/slider/features/controller.js +805 -171
  7. package/dist/components/slider/features/dom.js +29 -62
  8. package/dist/components/slider/features/index.js +1 -3
  9. package/dist/components/slider/features/states.js +2 -30
  10. package/dist/components/slider/slider.js +3 -6
  11. package/dist/components/slider/types.d.ts +0 -26
  12. package/dist/components/split-button/features/menu-on-demand.js +141 -0
  13. package/dist/components/split-button/features/menu.js +3 -4
  14. package/dist/core/canvas/resize.d.ts +1 -1
  15. package/dist/core/canvas/resize.js +24 -11
  16. package/dist/core/dom/classes.js +17 -118
  17. package/dist/core/dom/create.d.ts +0 -2
  18. package/dist/core/dom/create.js +0 -72
  19. package/dist/core/utils/mobile.js +9 -29
  20. package/dist/elements/preupgrade/badge.css +1 -1
  21. package/dist/elements/preupgrade/bottom-app-bar.css +1 -1
  22. package/dist/elements/preupgrade/bottom-sheet.css +1 -1
  23. package/dist/elements/preupgrade/button-group.css +1 -1
  24. package/dist/elements/preupgrade/button.css +1 -1
  25. package/dist/elements/preupgrade/card.css +1 -1
  26. package/dist/elements/preupgrade/carousel.css +1 -1
  27. package/dist/elements/preupgrade/checkbox.css +1 -1
  28. package/dist/elements/preupgrade/chips.css +1 -1
  29. package/dist/elements/preupgrade/datepicker.css +1 -1
  30. package/dist/elements/preupgrade/dialog.css +1 -1
  31. package/dist/elements/preupgrade/divider.css +1 -1
  32. package/dist/elements/preupgrade/drawer.css +1 -1
  33. package/dist/elements/preupgrade/extended-fab.css +1 -1
  34. package/dist/elements/preupgrade/fab-menu.css +1 -1
  35. package/dist/elements/preupgrade/fab.css +1 -1
  36. package/dist/elements/preupgrade/icon-button.css +1 -1
  37. package/dist/elements/preupgrade/list.css +1 -1
  38. package/dist/elements/preupgrade/loading-indicator.css +1 -1
  39. package/dist/elements/preupgrade/menu.css +1 -1
  40. package/dist/elements/preupgrade/navigation-bar.css +1 -1
  41. package/dist/elements/preupgrade/navigation-rail.css +1 -1
  42. package/dist/elements/preupgrade/progress.css +1 -1
  43. package/dist/elements/preupgrade/radios.css +1 -1
  44. package/dist/elements/preupgrade/search.css +1 -1
  45. package/dist/elements/preupgrade/select.css +1 -1
  46. package/dist/elements/preupgrade/side-sheet.css +1 -1
  47. package/dist/elements/preupgrade/slider.css +1 -1
  48. package/dist/elements/preupgrade/snackbar.css +1 -1
  49. package/dist/elements/preupgrade/split-button.css +1 -1
  50. package/dist/elements/preupgrade/switch.css +1 -1
  51. package/dist/elements/preupgrade/tabs.css +1 -1
  52. package/dist/elements/preupgrade/text-field.css +1 -1
  53. package/dist/elements/preupgrade/timepicker.css +1 -1
  54. package/dist/elements/preupgrade/toolbar.css +1 -1
  55. package/dist/elements/preupgrade/tooltip.css +1 -1
  56. package/dist/elements/preupgrade/top-app-bar.css +1 -1
  57. package/dist/elements/preupgrade.css +1 -1
  58. package/dist/package.json +1 -1
  59. package/dist/styles/badge.css +1 -1
  60. package/dist/styles/base.css +1 -1
  61. package/dist/styles/bottom-app-bar.css +1 -1
  62. package/dist/styles/bottom-sheet.css +1 -1
  63. package/dist/styles/button-group.css +1 -1
  64. package/dist/styles/button.css +1 -1
  65. package/dist/styles/card.css +1 -1
  66. package/dist/styles/carousel.css +1 -1
  67. package/dist/styles/checkbox.css +1 -1
  68. package/dist/styles/chips.css +1 -1
  69. package/dist/styles/contrast.css +1 -1
  70. package/dist/styles/datepicker.css +1 -1
  71. package/dist/styles/dialog.css +1 -1
  72. package/dist/styles/divider.css +1 -1
  73. package/dist/styles/drawer.css +1 -1
  74. package/dist/styles/extended-fab.css +1 -1
  75. package/dist/styles/fab-menu.css +1 -1
  76. package/dist/styles/fab.css +1 -1
  77. package/dist/styles/icon-button.css +1 -1
  78. package/dist/styles/list.css +1 -1
  79. package/dist/styles/loading-indicator.css +1 -1
  80. package/dist/styles/menu.css +1 -1
  81. package/dist/styles/navigation-bar.css +1 -1
  82. package/dist/styles/navigation-rail.css +1 -1
  83. package/dist/styles/progress.css +1 -1
  84. package/dist/styles/radios.css +1 -1
  85. package/dist/styles/search.css +1 -1
  86. package/dist/styles/select.css +1 -1
  87. package/dist/styles/side-sheet.css +1 -1
  88. package/dist/styles/slider.css +1 -1
  89. package/dist/styles/snackbar.css +1 -1
  90. package/dist/styles/split-button.css +1 -1
  91. package/dist/styles/switch.css +1 -1
  92. package/dist/styles/tabs.css +1 -1
  93. package/dist/styles/text-field.css +1 -1
  94. package/dist/styles/timepicker.css +1 -1
  95. package/dist/styles/toolbar.css +1 -1
  96. package/dist/styles/tooltip.css +1 -1
  97. package/dist/styles/top-app-bar.css +1 -1
  98. package/dist/styles/typography.css +1 -1
  99. package/dist/styles/utilities.css +1 -1
  100. package/dist/styles.css +1 -1
  101. package/dist/themes/autumn-contrast.css +1 -1
  102. package/dist/themes/autumn.css +1 -1
  103. package/dist/themes/baseline-contrast.css +1 -1
  104. package/dist/themes/baseline.css +1 -1
  105. package/dist/themes/brownbeige-contrast.css +1 -1
  106. package/dist/themes/brownbeige.css +1 -1
  107. package/dist/themes/content-contrast.css +1 -1
  108. package/dist/themes/content.css +1 -1
  109. package/dist/themes/desert-contrast.css +1 -1
  110. package/dist/themes/desert.css +1 -1
  111. package/dist/themes/expressive-contrast.css +1 -1
  112. package/dist/themes/expressive.css +1 -1
  113. package/dist/themes/fidelity-contrast.css +1 -1
  114. package/dist/themes/fidelity.css +1 -1
  115. package/dist/themes/forest-contrast.css +1 -1
  116. package/dist/themes/forest.css +1 -1
  117. package/dist/themes/fruit-salad-contrast.css +1 -1
  118. package/dist/themes/fruit-salad.css +1 -1
  119. package/dist/themes/highcontrast-contrast.css +1 -1
  120. package/dist/themes/highcontrast.css +1 -1
  121. package/dist/themes/monochrome-contrast.css +1 -1
  122. package/dist/themes/monochrome.css +1 -1
  123. package/dist/themes/neutral-contrast.css +1 -1
  124. package/dist/themes/neutral.css +1 -1
  125. package/dist/themes/ocean-contrast.css +1 -1
  126. package/dist/themes/ocean.css +1 -1
  127. package/dist/themes/rainbow-contrast.css +1 -1
  128. package/dist/themes/rainbow.css +1 -1
  129. package/dist/themes/sageivory-contrast.css +1 -1
  130. package/dist/themes/sageivory.css +1 -1
  131. package/dist/themes/spring-contrast.css +1 -1
  132. package/dist/themes/spring.css +1 -1
  133. package/dist/themes/summer-contrast.css +1 -1
  134. package/dist/themes/summer.css +1 -1
  135. package/dist/themes/sunset-contrast.css +1 -1
  136. package/dist/themes/sunset.css +1 -1
  137. package/dist/themes/tealcaramel-contrast.css +1 -1
  138. package/dist/themes/tealcaramel.css +1 -1
  139. package/dist/themes/vibrant-contrast.css +1 -1
  140. package/dist/themes/vibrant.css +1 -1
  141. package/package.json +1 -1
  142. package/dist/components/badge/types.js +0 -1
  143. package/dist/components/bottom-app-bar/types.js +0 -1
  144. package/dist/components/bottom-sheet/types.js +0 -1
  145. package/dist/components/button/types.js +0 -1
  146. package/dist/components/button-group/types.js +0 -1
  147. package/dist/components/card/features.js +0 -217
  148. package/dist/components/card/types.js +0 -1
  149. package/dist/components/carousel/types.js +0 -1
  150. package/dist/components/checkbox/types.js +0 -1
  151. package/dist/components/chips/chip/constants.js +0 -18
  152. package/dist/components/chips/chip/index.js +0 -1
  153. package/dist/components/chips/schema.js +0 -46
  154. package/dist/components/chips/types.js +0 -1
  155. package/dist/components/dialog/types.js +0 -1
  156. package/dist/components/divider/types.js +0 -1
  157. package/dist/components/drawer/types.js +0 -1
  158. package/dist/components/extended-fab/types.js +0 -1
  159. package/dist/components/fab/types.js +0 -1
  160. package/dist/components/fab-menu/types.js +0 -1
  161. package/dist/components/icon-button/types.js +0 -1
  162. package/dist/components/list/types.js +0 -1
  163. package/dist/components/loading-indicator/types.js +0 -1
  164. package/dist/components/menu/types.js +0 -14
  165. package/dist/components/navigation-bar/types.js +0 -1
  166. package/dist/components/navigation-rail/types.js +0 -1
  167. package/dist/components/progress/features/index.js +0 -4
  168. package/dist/components/progress/features/resize-observer.js +0 -40
  169. package/dist/components/progress/types.js +0 -1
  170. package/dist/components/radios/types.js +0 -1
  171. package/dist/components/search/types.js +0 -1
  172. package/dist/components/select/types.js +0 -4
  173. package/dist/components/side-sheet/types.js +0 -1
  174. package/dist/components/slider/api.js +0 -108
  175. package/dist/components/slider/features/handlers.js +0 -379
  176. package/dist/components/slider/features/range.js +0 -70
  177. package/dist/components/slider/features/tracks.js +0 -287
  178. package/dist/components/snackbar/types.js +0 -1
  179. package/dist/components/split-button/types.js +0 -1
  180. package/dist/components/switch/types.js +0 -1
  181. package/dist/components/tabs/scroll-indicators.js +0 -78
  182. package/dist/components/tabs/state.js +0 -44
  183. package/dist/components/tabs/types.js +0 -1
  184. package/dist/components/text-field/types.js +0 -18
  185. package/dist/components/toolbar/types.js +0 -1
  186. package/dist/components/top-app-bar/types.js +0 -1
  187. package/dist/core/utils/validate.js +0 -114
  188. package/dist/react/jsx.js +0 -2
  189. 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 handleAttributes = {
24
- role: "slider",
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(secondValue),
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(secondValue),
73
- "data-handle-index": "1",
31
+ "data-value": String(handleValue),
32
+ "data-handle-index": String(index),
74
33
  };
75
- if (secondHandleLabel) {
76
- secondHandleAttributes["aria-label"] = secondHandleLabel;
34
+ if (name) {
35
+ attributes["aria-label"] = name;
77
36
  }
78
- secondHandle = createElement({
37
+ const element = createElement({
79
38
  tag: "div",
80
39
  className: getClass("slider__handle"),
81
- attributes: secondHandleAttributes,
40
+ attributes,
82
41
  container: container,
83
42
  });
84
- setStyles(secondHandle, {
85
- left: `${secondValuePercent}%`,
43
+ setStyles(element, {
44
+ left: `${((handleValue - min) / (max - min)) * 100}%`,
86
45
  });
87
- secondValueBubble = createElement({
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": "1",
54
+ "data-handle-index": String(index),
93
55
  },
94
- text: formatter(secondValue),
56
+ text: formatter(bubbleValue),
95
57
  container: container,
96
58
  });
97
- setStyles(secondValueBubble, {
98
- left: `${secondValuePercent}%`,
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 ?? component.structure?.handle;
5
- const secondHandle = component.secondHandle ?? component.structure?.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 { withRange, withStates, withController, withTracks, withDom, } from "./features/index.js";
5
- import { withAPI } from "./api.js";
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 component = pipe(createBase, withEvents(), withElement(getElementConfig(baseConfig)), withRange(baseConfig), withDom(baseConfig), withTextLabel(baseConfig), withIcon(baseConfig), withLifecycle(), withStates(baseConfig), withTracks(baseConfig), withController(baseConfig, () => slider))(baseConfig);
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
- export const makeMenu = (config, trailing, items) => createMenu({
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, _canvas: HTMLCanvasElement, onResize: () => void) => (() => void);
1
+ export declare const observeCanvasResize: (element: HTMLElement, canvas: HTMLCanvasElement | null | undefined, onResize: () => void) => (() => void);
@@ -1,4 +1,4 @@
1
- export const observeCanvasResize = (element, _canvas, onResize) => {
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
- return () => {
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
- return () => {
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
  };
@@ -56,134 +56,33 @@ export const normalizeClasses = (...classes) => {
56
56
  }
57
57
  return result;
58
58
  };
59
- export const addClass = (element, ...classes) => {
60
- if (classes.length === 0)
61
- return element;
62
- if (classes.length === 1 && Array.isArray(classes[0])) {
63
- return addClass(element, ...classes[0]);
64
- }
65
- if (classes.length === 1 && typeof classes[0] === "string") {
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
- if (classes.length === 0)
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
- if (classes.length === 1 && Array.isArray(classes[0])) {
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
- if (classes.length === 0)
155
- return true;
156
- if (classes.length === 1 && Array.isArray(classes[0])) {
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 {