mtrl 0.8.0-next.37 → 0.8.0-next.38

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 (63) hide show
  1. package/dist/components/textfield/api.d.ts +1 -0
  2. package/dist/components/textfield/api.js +10 -10
  3. package/dist/components/textfield/features/density.js +1 -1
  4. package/dist/components/textfield/features/leading-icon.js +2 -1
  5. package/dist/components/textfield/features/placement.d.ts +2 -0
  6. package/dist/components/textfield/features/placement.js +25 -3
  7. package/dist/components/textfield/textfield.js +1 -1
  8. package/dist/core/compose/features/textinput.js +2 -1
  9. package/dist/index.cjs +10 -10
  10. package/dist/package.json +1 -1
  11. package/dist/styles/badge.css +1 -1
  12. package/dist/styles/base.css +1 -1
  13. package/dist/styles/bottom-app-bar.css +1 -1
  14. package/dist/styles/bottom-sheet.css +1 -1
  15. package/dist/styles/button-group.css +1 -1
  16. package/dist/styles/button.css +1 -1
  17. package/dist/styles/card.css +1 -1
  18. package/dist/styles/carousel.css +1 -1
  19. package/dist/styles/checkbox.css +1 -1
  20. package/dist/styles/chips.css +1 -1
  21. package/dist/styles/dialog.css +1 -1
  22. package/dist/styles/divider.css +1 -1
  23. package/dist/styles/drawer.css +1 -1
  24. package/dist/styles/extended-fab.css +1 -1
  25. package/dist/styles/fab.css +1 -1
  26. package/dist/styles/icon-button.css +1 -1
  27. package/dist/styles/list.css +1 -1
  28. package/dist/styles/loading-indicator.css +1 -1
  29. package/dist/styles/menu.css +1 -1
  30. package/dist/styles/navigation.css +1 -1
  31. package/dist/styles/progress.css +1 -1
  32. package/dist/styles/radios.css +1 -1
  33. package/dist/styles/search.css +1 -1
  34. package/dist/styles/segmented-button.css +1 -1
  35. package/dist/styles/select.css +1 -1
  36. package/dist/styles/side-sheet.css +1 -1
  37. package/dist/styles/slider.css +1 -1
  38. package/dist/styles/snackbar.css +1 -1
  39. package/dist/styles/split-button.css +1 -1
  40. package/dist/styles/switch.css +1 -1
  41. package/dist/styles/tabs.css +1 -1
  42. package/dist/styles/textfield.css +1 -1
  43. package/dist/styles/timepicker.css +1 -1
  44. package/dist/styles/top-app-bar.css +1 -1
  45. package/dist/styles/utilities.css +1 -1
  46. package/dist/styles.css +1 -1
  47. package/dist/themes/autumn.css +1 -1
  48. package/dist/themes/baseline.css +1 -1
  49. package/dist/themes/brownbeige.css +1 -1
  50. package/dist/themes/browngreen.css +1 -1
  51. package/dist/themes/desert.css +1 -1
  52. package/dist/themes/forest.css +1 -1
  53. package/dist/themes/highcontrast.css +1 -1
  54. package/dist/themes/legacy.css +1 -1
  55. package/dist/themes/material.css +1 -1
  56. package/dist/themes/ocean.css +1 -1
  57. package/dist/themes/sageivory.css +1 -1
  58. package/dist/themes/spring.css +1 -1
  59. package/dist/themes/summer.css +1 -1
  60. package/dist/themes/sunset.css +1 -1
  61. package/dist/themes/tealcaramel.css +1 -1
  62. package/dist/themes/winter.css +1 -1
  63. package/package.json +1 -1
@@ -8,6 +8,7 @@ type ComponentWithDensity = BaseComponent & {
8
8
  set: (density: string) => void;
9
9
  };
10
10
  updateElementPositions?: () => void;
11
+ schedulePositionUpdate?: () => void;
11
12
  setError?: (error: boolean, message?: string) => any;
12
13
  isError?: () => boolean;
13
14
  };
@@ -23,7 +23,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
23
23
  component.element.classList.remove(`${PREFIX}-${COMPONENT}--filled`, `${PREFIX}-${COMPONENT}--outlined`);
24
24
  component.element.classList.add(`${PREFIX}-${COMPONENT}--${variant}`);
25
25
  if (component.updateElementPositions) {
26
- setTimeout(() => component.updateElementPositions(), 10);
26
+ component.schedulePositionUpdate?.();
27
27
  }
28
28
  return this;
29
29
  },
@@ -38,7 +38,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
38
38
  setLabel(text) {
39
39
  component.label?.setText(text);
40
40
  if (component.updateElementPositions) {
41
- setTimeout(() => component.updateElementPositions(), 10);
41
+ component.schedulePositionUpdate?.();
42
42
  }
43
43
  return this;
44
44
  },
@@ -50,7 +50,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
50
50
  if (component.setLeadingIcon) {
51
51
  component.setLeadingIcon(html);
52
52
  if (component.updateElementPositions) {
53
- setTimeout(() => component.updateElementPositions(), 10);
53
+ component.schedulePositionUpdate?.();
54
54
  }
55
55
  }
56
56
  return this;
@@ -59,7 +59,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
59
59
  if (component.removeLeadingIcon) {
60
60
  component.removeLeadingIcon();
61
61
  if (component.updateElementPositions) {
62
- setTimeout(() => component.updateElementPositions(), 10);
62
+ component.schedulePositionUpdate?.();
63
63
  }
64
64
  }
65
65
  return this;
@@ -69,7 +69,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
69
69
  if (component.setTrailingIcon) {
70
70
  component.setTrailingIcon(html);
71
71
  if (component.updateElementPositions) {
72
- setTimeout(() => component.updateElementPositions(), 10);
72
+ component.schedulePositionUpdate?.();
73
73
  }
74
74
  }
75
75
  return this;
@@ -78,7 +78,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
78
78
  if (component.removeTrailingIcon) {
79
79
  component.removeTrailingIcon();
80
80
  if (component.updateElementPositions) {
81
- setTimeout(() => component.updateElementPositions(), 10);
81
+ component.schedulePositionUpdate?.();
82
82
  }
83
83
  }
84
84
  return this;
@@ -101,7 +101,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
101
101
  if (component.setPrefixText) {
102
102
  component.setPrefixText(text);
103
103
  if (component.updateElementPositions) {
104
- setTimeout(() => component.updateElementPositions(), 10);
104
+ component.schedulePositionUpdate?.();
105
105
  }
106
106
  }
107
107
  return this;
@@ -110,7 +110,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
110
110
  if (component.removePrefixText) {
111
111
  component.removePrefixText();
112
112
  if (component.updateElementPositions) {
113
- setTimeout(() => component.updateElementPositions(), 10);
113
+ component.schedulePositionUpdate?.();
114
114
  }
115
115
  }
116
116
  return this;
@@ -120,7 +120,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
120
120
  if (component.setSuffixText) {
121
121
  component.setSuffixText(text);
122
122
  if (component.updateElementPositions) {
123
- setTimeout(() => component.updateElementPositions(), 10);
123
+ component.schedulePositionUpdate?.();
124
124
  }
125
125
  }
126
126
  return this;
@@ -129,7 +129,7 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => ({
129
129
  if (component.removeSuffixText) {
130
130
  component.removeSuffixText();
131
131
  if (component.updateElementPositions) {
132
- setTimeout(() => component.updateElementPositions(), 10);
132
+ component.schedulePositionUpdate?.();
133
133
  }
134
134
  }
135
135
  return this;
@@ -27,7 +27,7 @@ export const withDensity = (config) => (component) => {
27
27
  component.density.current = newDensity;
28
28
  }
29
29
  if (component.updateElementPositions) {
30
- setTimeout(() => component.updateElementPositions(), 10);
30
+ component.updateElementPositions();
31
31
  }
32
32
  };
33
33
  component.density = {
@@ -14,11 +14,12 @@ export const withLeadingIcon = (config) => (component) => {
14
14
  if ('lifecycle' in component && component.lifecycle?.destroy) {
15
15
  const originalDestroy = component.lifecycle.destroy;
16
16
  component.lifecycle.destroy = () => {
17
+ clearTimeout(initialPosition);
17
18
  iconElement.remove();
18
19
  originalDestroy.call(component.lifecycle);
19
20
  };
20
21
  }
21
- setTimeout(() => {
22
+ const initialPosition = setTimeout(() => {
22
23
  const labelEl = component.element.querySelector(`.${PREFIX}-${config.componentName || 'textfield'}-label`);
23
24
  if (labelEl) {
24
25
  if (!component.element.classList.contains(`${PREFIX}-${config.componentName || 'textfield'}--with-prefix`)) {
@@ -17,6 +17,8 @@ export interface PlacementComponent extends BaseComponent {
17
17
  * @returns The component instance for chaining
18
18
  */
19
19
  updateElementPositions: () => PlacementComponent;
20
+ /** Queue a placement update owned by this component lifecycle. */
21
+ schedulePositionUpdate: () => void;
20
22
  }
21
23
  /**
22
24
  * Handles dynamic positioning of textfield elements (label, prefix, suffix)
@@ -2,12 +2,24 @@ import { getInheritedBackground } from "../../../core/utils/background.js";
2
2
  export const withPlacement = () => (component) => {
3
3
  const PREFIX = component.config.prefix || "mtrl";
4
4
  const COMPONENT = component.config.componentName || "textfield";
5
+ let destroyed = false;
6
+ let updateTimer = null;
7
+ const schedulePositionUpdate = () => {
8
+ if (destroyed)
9
+ return;
10
+ if (updateTimer !== null)
11
+ clearTimeout(updateTimer);
12
+ updateTimer = setTimeout(() => {
13
+ updateTimer = null;
14
+ updateElementPositions();
15
+ }, 10);
16
+ };
5
17
  const bgSourceObservers = new WeakMap();
6
18
  const parentObservers = new WeakMap();
7
19
  const themeChangeHandlers = new WeakMap();
8
20
  const classObservers = new WeakMap();
9
21
  const updateElementPositions = () => {
10
- if (!component.element || !component.element.isConnected)
22
+ if (destroyed || !component.element || !component.element.isConnected)
11
23
  return component;
12
24
  const labelEl = component.element.querySelector(`.${PREFIX}-${COMPONENT}-label`);
13
25
  const prefixEl = component.element.querySelector(`.${PREFIX}-${COMPONENT}-prefix`);
@@ -110,7 +122,7 @@ export const withPlacement = () => (component) => {
110
122
  mutations.forEach((mutation) => {
111
123
  if (mutation.type === "attributes" &&
112
124
  mutation.attributeName === "class") {
113
- setTimeout(updateElementPositions, 10);
125
+ schedulePositionUpdate();
114
126
  }
115
127
  });
116
128
  });
@@ -121,13 +133,22 @@ export const withPlacement = () => (component) => {
121
133
  window.addEventListener("resize", updateElementPositions);
122
134
  classObservers.set(component.element, classObserver);
123
135
  };
124
- setTimeout(() => {
136
+ const initialization = setTimeout(() => {
137
+ if (destroyed)
138
+ return;
125
139
  setupEventListeners();
126
140
  updateElementPositions();
127
141
  }, 0);
128
142
  if ("lifecycle" in component && component.lifecycle?.destroy) {
129
143
  const originalDestroy = component.lifecycle.destroy;
130
144
  component.lifecycle.destroy = () => {
145
+ if (destroyed)
146
+ return;
147
+ destroyed = true;
148
+ clearTimeout(initialization);
149
+ if (updateTimer !== null)
150
+ clearTimeout(updateTimer);
151
+ updateTimer = null;
131
152
  window.removeEventListener("resize", updateElementPositions);
132
153
  const classObserver = classObservers.get(component.element);
133
154
  if (classObserver) {
@@ -154,6 +175,7 @@ export const withPlacement = () => (component) => {
154
175
  }
155
176
  return {
156
177
  ...component,
178
+ schedulePositionUpdate,
157
179
  updateElementPositions: () => {
158
180
  updateElementPositions();
159
181
  return component;
@@ -7,7 +7,7 @@ import { createBaseConfig, getElementConfig, getApiConfig } from "./config.js";
7
7
  const createTextfield = (config = {}) => {
8
8
  const baseConfig = createBaseConfig(config);
9
9
  try {
10
- const textfield = pipe(createBase, withEvents(), withElement(getElementConfig(baseConfig)), withVariant(baseConfig), withDensity(baseConfig), withTextInput(baseConfig), withTextLabel(baseConfig), withLeadingIcon(baseConfig), withTrailingIcon(baseConfig), withPrefixText(baseConfig), withSuffixText(baseConfig), withSupportingText(baseConfig), withError(baseConfig), withDisabled(baseConfig), withLifecycle(), withPlacement(), (comp) => withAPI(getApiConfig(comp))(comp))(baseConfig);
10
+ const textfield = pipe(createBase, withEvents(), withElement(getElementConfig(baseConfig)), withLifecycle(), withVariant(baseConfig), withDensity(baseConfig), withTextInput(baseConfig), withTextLabel(baseConfig), withLeadingIcon(baseConfig), withTrailingIcon(baseConfig), withPrefixText(baseConfig), withSuffixText(baseConfig), withSupportingText(baseConfig), withError(baseConfig), withDisabled(baseConfig), withPlacement(), (comp) => withAPI(getApiConfig(comp))(comp))(baseConfig);
11
11
  return textfield;
12
12
  }
13
13
  catch (error) {
@@ -118,7 +118,7 @@ export const withTextInput = (config = {}) => (component) => {
118
118
  }
119
119
  });
120
120
  updateInputState();
121
- setTimeout(() => {
121
+ const initialAutofillCheck = setTimeout(() => {
122
122
  checkForAutofill(false);
123
123
  }, 0);
124
124
  if (isMultiline) {
@@ -128,6 +128,7 @@ export const withTextInput = (config = {}) => (component) => {
128
128
  if (hasLifecycle(component)) {
129
129
  const originalDestroy = component.lifecycle.destroy;
130
130
  component.lifecycle.destroy = () => {
131
+ clearTimeout(initialAutofillCheck);
131
132
  if (autofillObserver) {
132
133
  autofillObserver.disconnect();
133
134
  }