@material/web 1.1.1 → 1.1.2-nightly.043bbad.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +1 -0
  2. package/button/internal/button.js +1 -1
  3. package/button/internal/button.js.map +1 -1
  4. package/checkbox/internal/checkbox.js +2 -1
  5. package/checkbox/internal/checkbox.js.map +1 -1
  6. package/chips/internal/filter-chip.js +8 -2
  7. package/chips/internal/filter-chip.js.map +1 -1
  8. package/dialog/internal/dialog.d.ts +3 -6
  9. package/dialog/internal/dialog.js +57 -6
  10. package/dialog/internal/dialog.js.map +1 -1
  11. package/field/internal/field.js +7 -2
  12. package/field/internal/field.js.map +1 -1
  13. package/internal/events/dispatch-hooks.d.ts +85 -0
  14. package/internal/events/dispatch-hooks.js +151 -0
  15. package/internal/events/dispatch-hooks.js.map +1 -0
  16. package/internal/{controller/events.d.ts → events/form-label-activation.d.ts} +0 -22
  17. package/internal/{controller/events.js → events/form-label-activation.js} +1 -35
  18. package/internal/events/form-label-activation.js.map +1 -0
  19. package/internal/events/redispatch-event.d.ts +27 -0
  20. package/internal/events/redispatch-event.js +40 -0
  21. package/internal/events/redispatch-event.js.map +1 -0
  22. package/labs/badge/internal/badge.d.ts +1 -1
  23. package/labs/badge/internal/badge.js +1 -1
  24. package/labs/badge/internal/badge.js.map +1 -1
  25. package/labs/behaviors/validators/text-field-validator.js +12 -4
  26. package/labs/behaviors/validators/text-field-validator.js.map +1 -1
  27. package/labs/card/internal/_outlined-card.scss +3 -2
  28. package/labs/card/internal/_shared.scss +18 -4
  29. package/labs/card/internal/card.js +2 -1
  30. package/labs/card/internal/card.js.map +1 -1
  31. package/labs/card/internal/outlined-styles.css.js +1 -1
  32. package/labs/card/internal/outlined-styles.css.js.map +1 -1
  33. package/labs/card/internal/shared-styles.css.js +1 -1
  34. package/labs/card/internal/shared-styles.css.js.map +1 -1
  35. package/labs/navigationbar/internal/navigation-bar.d.ts +1 -1
  36. package/labs/navigationbar/internal/navigation-bar.js +1 -1
  37. package/labs/navigationbar/internal/navigation-bar.js.map +1 -1
  38. package/labs/navigationdrawer/internal/_navigation-drawer-modal.scss +1 -1
  39. package/labs/navigationdrawer/internal/_navigation-drawer.scss +1 -1
  40. package/labs/navigationdrawer/internal/navigation-drawer-modal.d.ts +1 -1
  41. package/labs/navigationdrawer/internal/navigation-drawer-modal.js +1 -1
  42. package/labs/navigationdrawer/internal/navigation-drawer-modal.js.map +1 -1
  43. package/labs/navigationdrawer/internal/navigation-drawer.d.ts +1 -1
  44. package/labs/navigationdrawer/internal/navigation-drawer.js +1 -1
  45. package/labs/navigationdrawer/internal/navigation-drawer.js.map +1 -1
  46. package/labs/navigationtab/internal/navigation-tab.d.ts +1 -1
  47. package/labs/navigationtab/internal/navigation-tab.js +2 -2
  48. package/labs/navigationtab/internal/navigation-tab.js.map +1 -1
  49. package/labs/navigationtab/internal/state.d.ts +0 -6
  50. package/labs/navigationtab/internal/state.js.map +1 -1
  51. package/labs/segmentedbutton/internal/_outlined-segmented-button.scss +2 -2
  52. package/labs/segmentedbutton/internal/_shared.scss +1 -1
  53. package/labs/segmentedbutton/internal/outlined-segmented-button.d.ts +1 -1
  54. package/labs/segmentedbutton/internal/outlined-segmented-button.js +1 -1
  55. package/labs/segmentedbutton/internal/outlined-segmented-button.js.map +1 -1
  56. package/labs/segmentedbuttonset/internal/outlined-segmented-button-set.d.ts +1 -1
  57. package/labs/segmentedbuttonset/internal/outlined-segmented-button-set.js +1 -1
  58. package/labs/segmentedbuttonset/internal/outlined-segmented-button-set.js.map +1 -1
  59. package/menu/internal/_menu.scss +1 -0
  60. package/menu/internal/menu-styles.css.js +1 -1
  61. package/menu/internal/menu-styles.css.js.map +1 -1
  62. package/package.json +23 -9
  63. package/progress/internal/_linear-progress.scss +6 -4
  64. package/progress/internal/linear-progress-styles.css.js +1 -1
  65. package/progress/internal/linear-progress-styles.css.js.map +1 -1
  66. package/progress/internal/linear-progress.js +4 -1
  67. package/progress/internal/linear-progress.js.map +1 -1
  68. package/radio/internal/radio.js +1 -1
  69. package/radio/internal/radio.js.map +1 -1
  70. package/ripple/internal/ripple.js +11 -0
  71. package/ripple/internal/ripple.js.map +1 -1
  72. package/select/harness.d.ts +1 -0
  73. package/select/harness.js +7 -0
  74. package/select/harness.js.map +1 -1
  75. package/select/internal/_shared.scss +10 -1
  76. package/select/internal/select.d.ts +7 -1
  77. package/select/internal/select.js +71 -28
  78. package/select/internal/select.js.map +1 -1
  79. package/select/internal/selectoption/select-option.d.ts +26 -1
  80. package/select/internal/selectoption/select-option.js.map +1 -1
  81. package/select/internal/selectoption/selectOptionController.d.ts +2 -26
  82. package/select/internal/selectoption/selectOptionController.js.map +1 -1
  83. package/select/internal/shared-styles.css.js +1 -1
  84. package/select/internal/shared-styles.css.js.map +1 -1
  85. package/select/internal/shared.d.ts +1 -1
  86. package/select/internal/shared.js.map +1 -1
  87. package/select/select-option.d.ts +1 -0
  88. package/select/select-option.js.map +1 -1
  89. package/slider/internal/_slider.scss +31 -33
  90. package/slider/internal/slider-styles.css.js +1 -1
  91. package/slider/internal/slider-styles.css.js.map +1 -1
  92. package/slider/internal/slider.js +4 -3
  93. package/slider/internal/slider.js.map +1 -1
  94. package/switch/internal/switch.js +2 -1
  95. package/switch/internal/switch.js.map +1 -1
  96. package/tabs/internal/_tab.scss +7 -5
  97. package/tabs/internal/tab-styles.css.js +1 -1
  98. package/tabs/internal/tab-styles.css.js.map +1 -1
  99. package/textfield/internal/_input.scss +1 -1
  100. package/textfield/internal/shared-styles.css.js +1 -1
  101. package/textfield/internal/shared-styles.css.js.map +1 -1
  102. package/textfield/internal/text-field.d.ts +26 -0
  103. package/textfield/internal/text-field.js +35 -5
  104. package/textfield/internal/text-field.js.map +1 -1
  105. package/tokens/_md-comp-elevated-button.scss +1 -1
  106. package/tokens/_md-comp-filled-button.scss +1 -1
  107. package/tokens/_md-comp-filled-tonal-button.scss +1 -1
  108. package/tokens/_md-comp-outlined-button.scss +1 -1
  109. package/tokens/_md-comp-text-button.scss +1 -1
  110. package/internal/controller/events.js.map +0 -1
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Add a hook for an event that is called after the event is dispatched and
8
+ * propagates to other event listeners.
9
+ *
10
+ * This is useful for behaviors that need to check if an event is canceled.
11
+ *
12
+ * The callback is invoked synchronously, which allows for better integration
13
+ * with synchronous platform APIs (like `<form>` or `<label>` clicking).
14
+ *
15
+ * Note: `setupDispatchHooks()` must be called on the element before adding any
16
+ * other event listeners. Call it in the constructor of an element or
17
+ * controller.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * class MyControl extends LitElement {
22
+ * constructor() {
23
+ * super();
24
+ * setupDispatchHooks(this, 'click');
25
+ * this.addEventListener('click', event => {
26
+ * afterDispatch(event, () => {
27
+ * if (event.defaultPrevented) {
28
+ * return
29
+ * }
30
+ *
31
+ * // ... perform logic
32
+ * });
33
+ * });
34
+ * }
35
+ * }
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * class MyController implements ReactiveController {
41
+ * constructor(host: ReactiveElement) {
42
+ * // setupDispatchHooks() may be called multiple times for the same
43
+ * // element and events, making it safe for multiple controllers to use it.
44
+ * setupDispatchHooks(host, 'click');
45
+ * host.addEventListener('click', event => {
46
+ * afterDispatch(event, () => {
47
+ * if (event.defaultPrevented) {
48
+ * return;
49
+ * }
50
+ *
51
+ * // ... perform logic
52
+ * });
53
+ * });
54
+ * }
55
+ * }
56
+ * ```
57
+ *
58
+ * @param event The event to add a hook to.
59
+ * @param callback A hook that is called after the event finishes dispatching.
60
+ */
61
+ export declare function afterDispatch(event: Event, callback: () => void): void;
62
+ /**
63
+ * Sets up an element to add dispatch hooks to given event types. This must be
64
+ * called before adding any event listeners that need to use dispatch hooks
65
+ * like `afterDispatch()`.
66
+ *
67
+ * This function is safe to call multiple times with the same element or event
68
+ * types. Call it in the constructor of elements, mixins, and controllers to
69
+ * ensure it is set up before external listeners.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * class MyControl extends LitElement {
74
+ * constructor() {
75
+ * super();
76
+ * setupDispatchHooks(this, 'click');
77
+ * this.addEventListener('click', this.listenerUsingAfterDispatch);
78
+ * }
79
+ * }
80
+ * ```
81
+ *
82
+ * @param element The element to set up event dispatch hooks for.
83
+ * @param eventTypes The event types to add dispatch hooks to.
84
+ */
85
+ export declare function setupDispatchHooks(element: Element, ...eventTypes: [string, ...string[]]): void;
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * A symbol used to access dispatch hooks on an event.
8
+ */
9
+ const dispatchHooks = Symbol('dispatchHooks');
10
+ /**
11
+ * Add a hook for an event that is called after the event is dispatched and
12
+ * propagates to other event listeners.
13
+ *
14
+ * This is useful for behaviors that need to check if an event is canceled.
15
+ *
16
+ * The callback is invoked synchronously, which allows for better integration
17
+ * with synchronous platform APIs (like `<form>` or `<label>` clicking).
18
+ *
19
+ * Note: `setupDispatchHooks()` must be called on the element before adding any
20
+ * other event listeners. Call it in the constructor of an element or
21
+ * controller.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * class MyControl extends LitElement {
26
+ * constructor() {
27
+ * super();
28
+ * setupDispatchHooks(this, 'click');
29
+ * this.addEventListener('click', event => {
30
+ * afterDispatch(event, () => {
31
+ * if (event.defaultPrevented) {
32
+ * return
33
+ * }
34
+ *
35
+ * // ... perform logic
36
+ * });
37
+ * });
38
+ * }
39
+ * }
40
+ * ```
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * class MyController implements ReactiveController {
45
+ * constructor(host: ReactiveElement) {
46
+ * // setupDispatchHooks() may be called multiple times for the same
47
+ * // element and events, making it safe for multiple controllers to use it.
48
+ * setupDispatchHooks(host, 'click');
49
+ * host.addEventListener('click', event => {
50
+ * afterDispatch(event, () => {
51
+ * if (event.defaultPrevented) {
52
+ * return;
53
+ * }
54
+ *
55
+ * // ... perform logic
56
+ * });
57
+ * });
58
+ * }
59
+ * }
60
+ * ```
61
+ *
62
+ * @param event The event to add a hook to.
63
+ * @param callback A hook that is called after the event finishes dispatching.
64
+ */
65
+ export function afterDispatch(event, callback) {
66
+ const hooks = event[dispatchHooks];
67
+ if (!hooks) {
68
+ throw new Error(`'${event.type}' event needs setupDispatchHooks().`);
69
+ }
70
+ hooks.addEventListener('after', callback);
71
+ }
72
+ /**
73
+ * A lookup map of elements and event types that have a dispatch hook listener
74
+ * set up. Used to ensure we don't set up multiple hook listeners on the same
75
+ * element for the same event.
76
+ */
77
+ const ELEMENT_DISPATCH_HOOK_TYPES = new WeakMap();
78
+ /**
79
+ * Sets up an element to add dispatch hooks to given event types. This must be
80
+ * called before adding any event listeners that need to use dispatch hooks
81
+ * like `afterDispatch()`.
82
+ *
83
+ * This function is safe to call multiple times with the same element or event
84
+ * types. Call it in the constructor of elements, mixins, and controllers to
85
+ * ensure it is set up before external listeners.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * class MyControl extends LitElement {
90
+ * constructor() {
91
+ * super();
92
+ * setupDispatchHooks(this, 'click');
93
+ * this.addEventListener('click', this.listenerUsingAfterDispatch);
94
+ * }
95
+ * }
96
+ * ```
97
+ *
98
+ * @param element The element to set up event dispatch hooks for.
99
+ * @param eventTypes The event types to add dispatch hooks to.
100
+ */
101
+ export function setupDispatchHooks(element, ...eventTypes) {
102
+ let typesAlreadySetUp = ELEMENT_DISPATCH_HOOK_TYPES.get(element);
103
+ if (!typesAlreadySetUp) {
104
+ typesAlreadySetUp = new Set();
105
+ ELEMENT_DISPATCH_HOOK_TYPES.set(element, typesAlreadySetUp);
106
+ }
107
+ for (const eventType of eventTypes) {
108
+ // Don't register multiple dispatch hook listeners. A second registration
109
+ // would lead to the second listener re-dispatching a re-dispatched event,
110
+ // which can cause an infinite loop inside the other one.
111
+ if (typesAlreadySetUp.has(eventType)) {
112
+ continue;
113
+ }
114
+ // When we re-dispatch the event, it's going to immediately trigger this
115
+ // listener again. Use a flag to ignore it.
116
+ let isRedispatching = false;
117
+ element.addEventListener(eventType, (event) => {
118
+ if (isRedispatching) {
119
+ return;
120
+ }
121
+ // Do not let the event propagate to any other listener (not just
122
+ // bubbling listeners with `stopPropagation()`).
123
+ event.stopImmediatePropagation();
124
+ // Make a copy.
125
+ const eventCopy = Reflect.construct(event.constructor, [
126
+ event.type,
127
+ event,
128
+ ]);
129
+ // Add hooks onto the event.
130
+ const hooks = new EventTarget();
131
+ eventCopy[dispatchHooks] = hooks;
132
+ // Re-dispatch the event. We can't reuse `redispatchEvent()` since we
133
+ // need to add the hooks to the copy before it's dispatched.
134
+ isRedispatching = true;
135
+ const dispatched = element.dispatchEvent(eventCopy);
136
+ isRedispatching = false;
137
+ if (!dispatched) {
138
+ event.preventDefault();
139
+ }
140
+ // Synchronously call afterDispatch() hooks.
141
+ hooks.dispatchEvent(new Event('after'));
142
+ }, {
143
+ // Ensure this listener runs before other listeners.
144
+ // `setupDispatchHooks()` should be called in constructors to also
145
+ // ensure they run before any other externally-added capture listeners.
146
+ capture: true,
147
+ });
148
+ typesAlreadySetUp.add(eventType);
149
+ }
150
+ }
151
+ //# sourceMappingURL=dispatch-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch-hooks.js","sourceRoot":"","sources":["dispatch-hooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AAS9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,QAAoB;IAC9D,MAAM,KAAK,GAAI,KAAgC,CAAC,aAAa,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,qCAAqC,CAAC,CAAC;KACtE;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,2BAA2B,GAAG,IAAI,OAAO,EAAwB,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAgB,EAChB,GAAG,UAAiC;IAEpC,IAAI,iBAAiB,GAAG,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACjE,IAAI,CAAC,iBAAiB,EAAE;QACtB,iBAAiB,GAAG,IAAI,GAAG,EAAE,CAAC;QAC9B,2BAA2B,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;KAC7D;IAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;QAClC,yEAAyE;QACzE,0EAA0E;QAC1E,yDAAyD;QACzD,IAAI,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;YACpC,SAAS;SACV;QAED,wEAAwE;QACxE,2CAA2C;QAC3C,IAAI,eAAe,GAAG,KAAK,CAAC;QAC5B,OAAO,CAAC,gBAAgB,CACtB,SAAS,EACT,CAAC,KAAY,EAAE,EAAE;YACf,IAAI,eAAe,EAAE;gBACnB,OAAO;aACR;YAED,iEAAiE;YACjE,gDAAgD;YAChD,KAAK,CAAC,wBAAwB,EAAE,CAAC;YACjC,eAAe;YACf,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE;gBACrD,KAAK,CAAC,IAAI;gBACV,KAAK;aACN,CAAC,CAAC;YAEH,4BAA4B;YAC5B,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;YAC/B,SAAoC,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC;YAE7D,qEAAqE;YACrE,4DAA4D;YAC5D,eAAe,GAAG,IAAI,CAAC;YACvB,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YACpD,eAAe,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,UAAU,EAAE;gBACf,KAAK,CAAC,cAAc,EAAE,CAAC;aACxB;YAED,4CAA4C;YAC5C,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1C,CAAC,EACD;YACE,oDAAoD;YACpD,kEAAkE;YAClE,uEAAuE;YACvE,OAAO,EAAE,IAAI;SACd,CACF,CAAC;QAEF,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;KAClC;AACH,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * A symbol used to access dispatch hooks on an event.\n */\nconst dispatchHooks = Symbol('dispatchHooks');\n\n/**\n * An `Event` with additional symbols for dispatch hooks.\n */\ninterface EventWithDispatchHooks extends Event {\n [dispatchHooks]: EventTarget;\n}\n\n/**\n * Add a hook for an event that is called after the event is dispatched and\n * propagates to other event listeners.\n *\n * This is useful for behaviors that need to check if an event is canceled.\n *\n * The callback is invoked synchronously, which allows for better integration\n * with synchronous platform APIs (like `<form>` or `<label>` clicking).\n *\n * Note: `setupDispatchHooks()` must be called on the element before adding any\n * other event listeners. Call it in the constructor of an element or\n * controller.\n *\n * @example\n * ```ts\n * class MyControl extends LitElement {\n * constructor() {\n * super();\n * setupDispatchHooks(this, 'click');\n * this.addEventListener('click', event => {\n * afterDispatch(event, () => {\n * if (event.defaultPrevented) {\n * return\n * }\n *\n * // ... perform logic\n * });\n * });\n * }\n * }\n * ```\n *\n * @example\n * ```ts\n * class MyController implements ReactiveController {\n * constructor(host: ReactiveElement) {\n * // setupDispatchHooks() may be called multiple times for the same\n * // element and events, making it safe for multiple controllers to use it.\n * setupDispatchHooks(host, 'click');\n * host.addEventListener('click', event => {\n * afterDispatch(event, () => {\n * if (event.defaultPrevented) {\n * return;\n * }\n *\n * // ... perform logic\n * });\n * });\n * }\n * }\n * ```\n *\n * @param event The event to add a hook to.\n * @param callback A hook that is called after the event finishes dispatching.\n */\nexport function afterDispatch(event: Event, callback: () => void) {\n const hooks = (event as EventWithDispatchHooks)[dispatchHooks];\n if (!hooks) {\n throw new Error(`'${event.type}' event needs setupDispatchHooks().`);\n }\n\n hooks.addEventListener('after', callback);\n}\n\n/**\n * A lookup map of elements and event types that have a dispatch hook listener\n * set up. Used to ensure we don't set up multiple hook listeners on the same\n * element for the same event.\n */\nconst ELEMENT_DISPATCH_HOOK_TYPES = new WeakMap<Element, Set<string>>();\n\n/**\n * Sets up an element to add dispatch hooks to given event types. This must be\n * called before adding any event listeners that need to use dispatch hooks\n * like `afterDispatch()`.\n *\n * This function is safe to call multiple times with the same element or event\n * types. Call it in the constructor of elements, mixins, and controllers to\n * ensure it is set up before external listeners.\n *\n * @example\n * ```ts\n * class MyControl extends LitElement {\n * constructor() {\n * super();\n * setupDispatchHooks(this, 'click');\n * this.addEventListener('click', this.listenerUsingAfterDispatch);\n * }\n * }\n * ```\n *\n * @param element The element to set up event dispatch hooks for.\n * @param eventTypes The event types to add dispatch hooks to.\n */\nexport function setupDispatchHooks(\n element: Element,\n ...eventTypes: [string, ...string[]]\n) {\n let typesAlreadySetUp = ELEMENT_DISPATCH_HOOK_TYPES.get(element);\n if (!typesAlreadySetUp) {\n typesAlreadySetUp = new Set();\n ELEMENT_DISPATCH_HOOK_TYPES.set(element, typesAlreadySetUp);\n }\n\n for (const eventType of eventTypes) {\n // Don't register multiple dispatch hook listeners. A second registration\n // would lead to the second listener re-dispatching a re-dispatched event,\n // which can cause an infinite loop inside the other one.\n if (typesAlreadySetUp.has(eventType)) {\n continue;\n }\n\n // When we re-dispatch the event, it's going to immediately trigger this\n // listener again. Use a flag to ignore it.\n let isRedispatching = false;\n element.addEventListener(\n eventType,\n (event: Event) => {\n if (isRedispatching) {\n return;\n }\n\n // Do not let the event propagate to any other listener (not just\n // bubbling listeners with `stopPropagation()`).\n event.stopImmediatePropagation();\n // Make a copy.\n const eventCopy = Reflect.construct(event.constructor, [\n event.type,\n event,\n ]);\n\n // Add hooks onto the event.\n const hooks = new EventTarget();\n (eventCopy as EventWithDispatchHooks)[dispatchHooks] = hooks;\n\n // Re-dispatch the event. We can't reuse `redispatchEvent()` since we\n // need to add the hooks to the copy before it's dispatched.\n isRedispatching = true;\n const dispatched = element.dispatchEvent(eventCopy);\n isRedispatching = false;\n if (!dispatched) {\n event.preventDefault();\n }\n\n // Synchronously call afterDispatch() hooks.\n hooks.dispatchEvent(new Event('after'));\n },\n {\n // Ensure this listener runs before other listeners.\n // `setupDispatchHooks()` should be called in constructors to also\n // ensure they run before any other externally-added capture listeners.\n capture: true,\n },\n );\n\n typesAlreadySetUp.add(eventType);\n }\n}\n"]}
@@ -3,28 +3,6 @@
3
3
  * Copyright 2021 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- /**
7
- * Re-dispatches an event from the provided element.
8
- *
9
- * This function is useful for forwarding non-composed events, such as `change`
10
- * events.
11
- *
12
- * @example
13
- * class MyInput extends LitElement {
14
- * render() {
15
- * return html`<input @change=${this.redispatchEvent}>`;
16
- * }
17
- *
18
- * protected redispatchEvent(event: Event) {
19
- * redispatchEvent(this, event);
20
- * }
21
- * }
22
- *
23
- * @param element The element to dispatch the event from.
24
- * @param event The event to re-dispatch.
25
- * @return Whether or not the event was dispatched (if cancelable).
26
- */
27
- export declare function redispatchEvent(element: Element, event: Event): boolean;
28
6
  /**
29
7
  * Dispatches a click event to the given element that triggers a native action,
30
8
  * but is not composed and therefore is not seen outside the element.
@@ -3,40 +3,6 @@
3
3
  * Copyright 2021 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- /**
7
- * Re-dispatches an event from the provided element.
8
- *
9
- * This function is useful for forwarding non-composed events, such as `change`
10
- * events.
11
- *
12
- * @example
13
- * class MyInput extends LitElement {
14
- * render() {
15
- * return html`<input @change=${this.redispatchEvent}>`;
16
- * }
17
- *
18
- * protected redispatchEvent(event: Event) {
19
- * redispatchEvent(this, event);
20
- * }
21
- * }
22
- *
23
- * @param element The element to dispatch the event from.
24
- * @param event The event to re-dispatch.
25
- * @return Whether or not the event was dispatched (if cancelable).
26
- */
27
- export function redispatchEvent(element, event) {
28
- // For bubbling events in SSR light DOM (or composed), stop their propagation
29
- // and dispatch the copy.
30
- if (event.bubbles && (!element.shadowRoot || event.composed)) {
31
- event.stopPropagation();
32
- }
33
- const copy = Reflect.construct(event.constructor, [event.type, event]);
34
- const dispatched = element.dispatchEvent(copy);
35
- if (!dispatched) {
36
- event.preventDefault();
37
- }
38
- return dispatched;
39
- }
40
6
  /**
41
7
  * Dispatches a click event to the given element that triggers a native action,
42
8
  * but is not composed and therefore is not seen outside the element.
@@ -127,4 +93,4 @@ async function squelchEventsForMicrotask() {
127
93
  await null;
128
94
  isSquelchingEvents = false;
129
95
  }
130
- //# sourceMappingURL=events.js.map
96
+ //# sourceMappingURL=form-label-activation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-label-activation.js","sourceRoot":"","sources":["form-label-activation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAoB;IAC1D,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC;IACvD,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAY;IAC5C,wCAAwC;IACxC,IAAI,KAAK,CAAC,aAAa,KAAK,KAAK,CAAC,MAAM,EAAE;QACxC,OAAO,KAAK,CAAC;KACd;IACD,gDAAgD;IAChD,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,MAAM,EAAE;QAC5C,OAAO,KAAK,CAAC;KACd;IACD,0EAA0E;IAC1E,oBAAoB;IACpB,IAAK,KAAK,CAAC,MAA4C,CAAC,QAAQ,EAAE;QAChE,OAAO,KAAK,CAAC;KACd;IACD,8DAA8D;IAC9D,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,6DAA6D;AAC7D,yCAAyC;AACzC,SAAS,YAAY,CAAC,KAAY;IAChC,MAAM,SAAS,GAAG,kBAAkB,CAAC;IACrC,IAAI,SAAS,EAAE;QACb,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,wBAAwB,EAAE,CAAC;KAClC;IACD,yBAAyB,EAAE,CAAC;IAC5B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,wCAAwC;AACxC,IAAI,kBAAkB,GAAG,KAAK,CAAC;AAC/B,KAAK,UAAU,yBAAyB;IACtC,kBAAkB,GAAG,IAAI,CAAC;IAC1B,wCAAwC;IACxC,2BAA2B;IAC3B,MAAM,IAAI,CAAC;IACX,kBAAkB,GAAG,KAAK,CAAC;AAC7B,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Dispatches a click event to the given element that triggers a native action,\n * but is not composed and therefore is not seen outside the element.\n *\n * This is useful for responding to an external click event on the host element\n * that should trigger an internal action like a button click.\n *\n * Note, a helper is provided because setting this up correctly is a bit tricky.\n * In particular, calling `click` on an element creates a composed event, which\n * is not desirable, and a manually dispatched event must specifically be a\n * `MouseEvent` to trigger a native action.\n *\n * @example\n * hostClickListener = (event: MouseEvent) {\n * if (isActivationClick(event)) {\n * this.dispatchActivationClick(this.buttonElement);\n * }\n * }\n *\n */\nexport function dispatchActivationClick(element: HTMLElement) {\n const event = new MouseEvent('click', {bubbles: true});\n element.dispatchEvent(event);\n return event;\n}\n\n/**\n * Returns true if the click event should trigger an activation behavior. The\n * behavior is defined by the element and is whatever it should do when\n * clicked.\n *\n * Typically when an element needs to handle a click, the click is generated\n * from within the element and an event listener within the element implements\n * the needed behavior; however, it's possible to fire a click directly\n * at the element that the element should handle. This method helps\n * distinguish these \"external\" clicks.\n *\n * An \"external\" click can be triggered in a number of ways: via a click\n * on an associated label for a form associated element, calling\n * `element.click()`, or calling\n * `element.dispatchEvent(new MouseEvent('click', ...))`.\n *\n * Also works around Firefox issue\n * https://bugzilla.mozilla.org/show_bug.cgi?id=1804576 by squelching\n * events for a microtask after called.\n *\n * @example\n * hostClickListener = (event: MouseEvent) {\n * if (isActivationClick(event)) {\n * this.dispatchActivationClick(this.buttonElement);\n * }\n * }\n *\n */\nexport function isActivationClick(event: Event) {\n // Event must start at the event target.\n if (event.currentTarget !== event.target) {\n return false;\n }\n // Event must not be retargeted from shadowRoot.\n if (event.composedPath()[0] !== event.target) {\n return false;\n }\n // Target must not be disabled; this should only occur for a synthetically\n // dispatched click.\n if ((event.target as EventTarget & {disabled: boolean}).disabled) {\n return false;\n }\n // This is an activation if the event should not be squelched.\n return !squelchEvent(event);\n}\n\n// TODO(https://bugzilla.mozilla.org/show_bug.cgi?id=1804576)\n// Remove when Firefox bug is addressed.\nfunction squelchEvent(event: Event) {\n const squelched = isSquelchingEvents;\n if (squelched) {\n event.preventDefault();\n event.stopImmediatePropagation();\n }\n squelchEventsForMicrotask();\n return squelched;\n}\n\n// Ignore events for one microtask only.\nlet isSquelchingEvents = false;\nasync function squelchEventsForMicrotask() {\n isSquelchingEvents = true;\n // Need to pause for just one microtask.\n // tslint:disable-next-line\n await null;\n isSquelchingEvents = false;\n}\n"]}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2021 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Re-dispatches an event from the provided element.
8
+ *
9
+ * This function is useful for forwarding non-composed events, such as `change`
10
+ * events.
11
+ *
12
+ * @example
13
+ * class MyInput extends LitElement {
14
+ * render() {
15
+ * return html`<input @change=${this.redispatchEvent}>`;
16
+ * }
17
+ *
18
+ * protected redispatchEvent(event: Event) {
19
+ * redispatchEvent(this, event);
20
+ * }
21
+ * }
22
+ *
23
+ * @param element The element to dispatch the event from.
24
+ * @param event The event to re-dispatch.
25
+ * @return Whether or not the event was dispatched (if cancelable).
26
+ */
27
+ export declare function redispatchEvent(element: Element, event: Event): boolean;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2021 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Re-dispatches an event from the provided element.
8
+ *
9
+ * This function is useful for forwarding non-composed events, such as `change`
10
+ * events.
11
+ *
12
+ * @example
13
+ * class MyInput extends LitElement {
14
+ * render() {
15
+ * return html`<input @change=${this.redispatchEvent}>`;
16
+ * }
17
+ *
18
+ * protected redispatchEvent(event: Event) {
19
+ * redispatchEvent(this, event);
20
+ * }
21
+ * }
22
+ *
23
+ * @param element The element to dispatch the event from.
24
+ * @param event The event to re-dispatch.
25
+ * @return Whether or not the event was dispatched (if cancelable).
26
+ */
27
+ export function redispatchEvent(element, event) {
28
+ // For bubbling events in SSR light DOM (or composed), stop their propagation
29
+ // and dispatch the copy.
30
+ if (event.bubbles && (!element.shadowRoot || event.composed)) {
31
+ event.stopPropagation();
32
+ }
33
+ const copy = Reflect.construct(event.constructor, [event.type, event]);
34
+ const dispatched = element.dispatchEvent(copy);
35
+ if (!dispatched) {
36
+ event.preventDefault();
37
+ }
38
+ return dispatched;
39
+ }
40
+ //# sourceMappingURL=redispatch-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redispatch-event.js","sourceRoot":"","sources":["redispatch-event.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,KAAY;IAC5D,6EAA6E;IAC7E,yBAAyB;IACzB,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE;QAC5D,KAAK,CAAC,eAAe,EAAE,CAAC;KACzB;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,EAAE;QACf,KAAK,CAAC,cAAc,EAAE,CAAC;KACxB;IAED,OAAO,UAAU,CAAC;AACpB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Re-dispatches an event from the provided element.\n *\n * This function is useful for forwarding non-composed events, such as `change`\n * events.\n *\n * @example\n * class MyInput extends LitElement {\n * render() {\n * return html`<input @change=${this.redispatchEvent}>`;\n * }\n *\n * protected redispatchEvent(event: Event) {\n * redispatchEvent(this, event);\n * }\n * }\n *\n * @param element The element to dispatch the event from.\n * @param event The event to re-dispatch.\n * @return Whether or not the event was dispatched (if cancelable).\n */\nexport function redispatchEvent(element: Element, event: Event) {\n // For bubbling events in SSR light DOM (or composed), stop their propagation\n // and dispatch the copy.\n if (event.bubbles && (!element.shadowRoot || event.composed)) {\n event.stopPropagation();\n }\n\n const copy = Reflect.construct(event.constructor, [event.type, event]);\n const dispatched = element.dispatchEvent(copy);\n if (!dispatched) {\n event.preventDefault();\n }\n\n return dispatched;\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { LitElement } from 'lit';
7
7
  /**
8
- * TODO(b/265340196): add docs
8
+ * b/265340196 - add docs
9
9
  */
10
10
  export declare class Badge extends LitElement {
11
11
  value: string;
@@ -8,7 +8,7 @@ import { html, LitElement } from 'lit';
8
8
  import { property } from 'lit/decorators.js';
9
9
  import { classMap } from 'lit/directives/class-map.js';
10
10
  /**
11
- * TODO(b/265340196): add docs
11
+ * b/265340196 - add docs
12
12
  */
13
13
  export class Badge extends LitElement {
14
14
  constructor() {
@@ -1 +1 @@
1
- {"version":3,"file":"badge.js","sourceRoot":"","sources":["badge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AAEH,OAAO,EAAC,IAAI,EAAE,UAAU,EAAC,MAAM,KAAK,CAAC;AACrC,OAAO,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAC,QAAQ,EAAC,MAAM,6BAA6B,CAAC;AAErD;;GAEG;AACH,MAAM,OAAO,KAAM,SAAQ,UAAU;IAArC;;QACc,UAAK,GAAG,EAAE,CAAC;IASzB,CAAC;IAPoB,MAAM;QACvB,MAAM,OAAO,GAAG,EAAC,kBAAkB,EAAE,IAAI,CAAC,KAAK,EAAC,CAAC;QAEjD,OAAO,IAAI,CAAA,yBAAyB,QAAQ,CAAC,OAAO,CAAC;oCACrB,IAAI,CAAC,KAAK;WACnC,CAAC;IACV,CAAC;CACF;AATa;IAAX,QAAQ,EAAE;oCAAY","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {html, LitElement} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\n/**\n * TODO(b/265340196): add docs\n */\nexport class Badge extends LitElement {\n @property() value = '';\n\n protected override render() {\n const classes = {'md3-badge--large': this.value};\n\n return html`<div class=\"md3-badge ${classMap(classes)}\">\n <p class=\"md3-badge__value\">${this.value}</p>\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"badge.js","sourceRoot":"","sources":["badge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AAEH,OAAO,EAAC,IAAI,EAAE,UAAU,EAAC,MAAM,KAAK,CAAC;AACrC,OAAO,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAC,QAAQ,EAAC,MAAM,6BAA6B,CAAC;AAErD;;GAEG;AACH,MAAM,OAAO,KAAM,SAAQ,UAAU;IAArC;;QACc,UAAK,GAAG,EAAE,CAAC;IASzB,CAAC;IAPoB,MAAM;QACvB,MAAM,OAAO,GAAG,EAAC,kBAAkB,EAAE,IAAI,CAAC,KAAK,EAAC,CAAC;QAEjD,OAAO,IAAI,CAAA,yBAAyB,QAAQ,CAAC,OAAO,CAAC;oCACrB,IAAI,CAAC,KAAK;WACnC,CAAC;IACV,CAAC;CACF;AATa;IAAX,QAAQ,EAAE;oCAAY","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {html, LitElement} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\n/**\n * b/265340196 - add docs\n */\nexport class Badge extends LitElement {\n @property() value = '';\n\n protected override render() {\n const classes = {'md3-badge--large': this.value};\n\n return html`<div class=\"md3-badge ${classMap(classes)}\">\n <p class=\"md3-badge__value\">${this.value}</p>\n </div>`;\n }\n}\n"]}
@@ -74,14 +74,22 @@ export class TextFieldValidator extends Validator {
74
74
  // Use -1 to represent no minlength and maxlength, which is what the
75
75
  // platform input returns. However, it will throw an error if you try to
76
76
  // manually set it to -1.
77
- if (state.minLength > -1) {
78
- inputOrTextArea.minLength = state.minLength;
77
+ //
78
+ // While the type is `number`, it may actually be `null` at runtime.
79
+ // `null > -1` is true since `null` coerces to `0`, so we default null and
80
+ // undefined to -1.
81
+ //
82
+ // We set attributes instead of properties since setting a property may
83
+ // throw an out of bounds error in relation to the other property.
84
+ // Attributes will not throw errors while the state is updating.
85
+ if ((state.minLength ?? -1) > -1) {
86
+ inputOrTextArea.setAttribute('minlength', String(state.minLength));
79
87
  }
80
88
  else {
81
89
  inputOrTextArea.removeAttribute('minlength');
82
90
  }
83
- if (state.maxLength > -1) {
84
- inputOrTextArea.maxLength = state.maxLength;
91
+ if ((state.maxLength ?? -1) > -1) {
92
+ inputOrTextArea.setAttribute('maxlength', String(state.maxLength));
85
93
  }
86
94
  else {
87
95
  inputOrTextArea.removeAttribute('maxlength');
@@ -1 +1 @@
1
- {"version":3,"file":"text-field-validator.js","sourceRoot":"","sources":["text-field-validator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {Validator} from './validator.js';\n\n/**\n * Constraint validation for a text field.\n */\nexport interface TextFieldState {\n /**\n * The input or textarea state to validate.\n */\n state: InputState | TextAreaState;\n\n /**\n * The `<input>` or `<textarea>` that is rendered on the page.\n *\n * `minlength` and `maxlength` validation do not apply until a user has\n * interacted with the control and the element is internally marked as dirty.\n * This is a spec quirk, the two properties behave differently from other\n * constraint validation.\n *\n * This means we need an actual rendered element instead of a virtual one,\n * since the virtual element will never be marked as dirty.\n *\n * This can be `null` if the element has not yet rendered, and the validator\n * will fall back to virtual elements for other constraint validation\n * properties, which do apply even if the control is not dirty.\n */\n renderedControl: HTMLInputElement | HTMLTextAreaElement | null;\n}\n\n/**\n * Constraint validation properties for an `<input>`.\n */\nexport interface InputState extends SharedInputAndTextAreaState {\n /**\n * The `<input>` type.\n *\n * Not all constraint validation properties apply to every type. See\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation#validation-related_attributes\n * for which properties will apply to which types.\n */\n readonly type: string;\n\n /**\n * The regex pattern a value must match.\n */\n readonly pattern: string;\n\n /**\n * The minimum value.\n */\n readonly min: string;\n\n /**\n * The maximum value.\n */\n readonly max: string;\n\n /**\n * The step interval of the value.\n */\n readonly step: string;\n}\n\n/**\n * Constraint validation properties for a `<textarea>`.\n */\nexport interface TextAreaState extends SharedInputAndTextAreaState {\n /**\n * The type, must be \"textarea\" to inform the validator to use `<textarea>`\n * instead of `<input>`.\n */\n readonly type: 'textarea';\n}\n\n/**\n * Constraint validation properties shared between an `<input>` and\n * `<textarea>`.\n */\ninterface SharedInputAndTextAreaState {\n /**\n * The current value.\n */\n readonly value: string;\n\n /**\n * Whether the textarea is required.\n */\n readonly required: boolean;\n\n /**\n * The minimum length of the value.\n */\n readonly minLength: number;\n\n /**\n * The maximum length of the value.\n */\n readonly maxLength: number;\n}\n\n/**\n * A validator that provides constraint validation that emulates `<input>` and\n * `<textarea>` validation.\n */\nexport class TextFieldValidator extends Validator<TextFieldState> {\n private inputControl?: HTMLInputElement;\n private textAreaControl?: HTMLTextAreaElement;\n\n protected override computeValidity({state, renderedControl}: TextFieldState) {\n let inputOrTextArea = renderedControl;\n if (isInputState(state) && !inputOrTextArea) {\n // Get cached <input> or create it.\n inputOrTextArea = this.inputControl || document.createElement('input');\n // Cache the <input> to re-use it next time.\n this.inputControl = inputOrTextArea;\n } else if (!inputOrTextArea) {\n // Get cached <textarea> or create it.\n inputOrTextArea =\n this.textAreaControl || document.createElement('textarea');\n // Cache the <textarea> to re-use it next time.\n this.textAreaControl = inputOrTextArea;\n }\n\n // Set this variable so we can check it for input-specific properties.\n const input = isInputState(state)\n ? (inputOrTextArea as HTMLInputElement)\n : null;\n\n // Set input's \"type\" first, since this can change the other properties\n if (input) {\n input.type = state.type;\n }\n\n if (inputOrTextArea.value !== state.value) {\n // Only programmatically set the value if there's a difference. When using\n // the rendered control, the value will always be up to date. Setting the\n // property (even if it's the same string) will reset the internal <input>\n // dirty flag, making minlength and maxlength validation reset.\n inputOrTextArea.value = state.value;\n }\n\n inputOrTextArea.required = state.required;\n\n // The following IDLAttribute properties will always hydrate an attribute,\n // even if set to a the default value ('' or -1). The presence of the\n // attribute triggers constraint validation, so we must remove the attribute\n // when empty.\n if (input) {\n const inputState = state as InputState;\n if (inputState.pattern) {\n input.pattern = inputState.pattern;\n } else {\n input.removeAttribute('pattern');\n }\n\n if (inputState.min) {\n input.min = inputState.min;\n } else {\n input.removeAttribute('min');\n }\n\n if (inputState.max) {\n input.max = inputState.max;\n } else {\n input.removeAttribute('max');\n }\n\n if (inputState.step) {\n input.step = inputState.step;\n } else {\n input.removeAttribute('step');\n }\n }\n\n // Use -1 to represent no minlength and maxlength, which is what the\n // platform input returns. However, it will throw an error if you try to\n // manually set it to -1.\n if (state.minLength > -1) {\n inputOrTextArea.minLength = state.minLength;\n } else {\n inputOrTextArea.removeAttribute('minlength');\n }\n\n if (state.maxLength > -1) {\n inputOrTextArea.maxLength = state.maxLength;\n } else {\n inputOrTextArea.removeAttribute('maxlength');\n }\n\n return {\n validity: inputOrTextArea.validity,\n validationMessage: inputOrTextArea.validationMessage,\n };\n }\n\n protected override equals(\n {state: prev}: TextFieldState,\n {state: next}: TextFieldState,\n ) {\n // Check shared input and textarea properties\n const inputOrTextAreaEqual =\n prev.type === next.type &&\n prev.value === next.value &&\n prev.required === next.required &&\n prev.minLength === next.minLength &&\n prev.maxLength === next.maxLength;\n\n if (!isInputState(prev) || !isInputState(next)) {\n // Both are textareas, all relevant properties are equal.\n return inputOrTextAreaEqual;\n }\n\n // Check additional input-specific properties.\n return (\n inputOrTextAreaEqual &&\n prev.pattern === next.pattern &&\n prev.min === next.min &&\n prev.max === next.max &&\n prev.step === next.step\n );\n }\n\n protected override copy({state}: TextFieldState): TextFieldState {\n // Don't hold a reference to the rendered control when copying since we\n // don't use it when checking if the state changed.\n return {\n state: isInputState(state)\n ? this.copyInput(state)\n : this.copyTextArea(state),\n renderedControl: null,\n };\n }\n\n private copyInput(state: InputState): InputState {\n const {type, pattern, min, max, step} = state;\n return {\n ...this.copySharedState(state),\n type,\n pattern,\n min,\n max,\n step,\n };\n }\n\n private copyTextArea(state: TextAreaState): TextAreaState {\n return {\n ...this.copySharedState(state),\n type: state.type,\n };\n }\n\n private copySharedState({\n value,\n required,\n minLength,\n maxLength,\n }: SharedInputAndTextAreaState): SharedInputAndTextAreaState {\n return {value, required, minLength, maxLength};\n }\n}\n\nfunction isInputState(state: InputState | TextAreaState): state is InputState {\n return state.type !== 'textarea';\n}\n"]}
1
+ {"version":3,"file":"text-field-validator.js","sourceRoot":"","sources":["text-field-validator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {Validator} from './validator.js';\n\n/**\n * Constraint validation for a text field.\n */\nexport interface TextFieldState {\n /**\n * The input or textarea state to validate.\n */\n state: InputState | TextAreaState;\n\n /**\n * The `<input>` or `<textarea>` that is rendered on the page.\n *\n * `minlength` and `maxlength` validation do not apply until a user has\n * interacted with the control and the element is internally marked as dirty.\n * This is a spec quirk, the two properties behave differently from other\n * constraint validation.\n *\n * This means we need an actual rendered element instead of a virtual one,\n * since the virtual element will never be marked as dirty.\n *\n * This can be `null` if the element has not yet rendered, and the validator\n * will fall back to virtual elements for other constraint validation\n * properties, which do apply even if the control is not dirty.\n */\n renderedControl: HTMLInputElement | HTMLTextAreaElement | null;\n}\n\n/**\n * Constraint validation properties for an `<input>`.\n */\nexport interface InputState extends SharedInputAndTextAreaState {\n /**\n * The `<input>` type.\n *\n * Not all constraint validation properties apply to every type. See\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation#validation-related_attributes\n * for which properties will apply to which types.\n */\n readonly type: string;\n\n /**\n * The regex pattern a value must match.\n */\n readonly pattern: string;\n\n /**\n * The minimum value.\n */\n readonly min: string;\n\n /**\n * The maximum value.\n */\n readonly max: string;\n\n /**\n * The step interval of the value.\n */\n readonly step: string;\n}\n\n/**\n * Constraint validation properties for a `<textarea>`.\n */\nexport interface TextAreaState extends SharedInputAndTextAreaState {\n /**\n * The type, must be \"textarea\" to inform the validator to use `<textarea>`\n * instead of `<input>`.\n */\n readonly type: 'textarea';\n}\n\n/**\n * Constraint validation properties shared between an `<input>` and\n * `<textarea>`.\n */\ninterface SharedInputAndTextAreaState {\n /**\n * The current value.\n */\n readonly value: string;\n\n /**\n * Whether the textarea is required.\n */\n readonly required: boolean;\n\n /**\n * The minimum length of the value.\n */\n readonly minLength: number;\n\n /**\n * The maximum length of the value.\n */\n readonly maxLength: number;\n}\n\n/**\n * A validator that provides constraint validation that emulates `<input>` and\n * `<textarea>` validation.\n */\nexport class TextFieldValidator extends Validator<TextFieldState> {\n private inputControl?: HTMLInputElement;\n private textAreaControl?: HTMLTextAreaElement;\n\n protected override computeValidity({state, renderedControl}: TextFieldState) {\n let inputOrTextArea = renderedControl;\n if (isInputState(state) && !inputOrTextArea) {\n // Get cached <input> or create it.\n inputOrTextArea = this.inputControl || document.createElement('input');\n // Cache the <input> to re-use it next time.\n this.inputControl = inputOrTextArea;\n } else if (!inputOrTextArea) {\n // Get cached <textarea> or create it.\n inputOrTextArea =\n this.textAreaControl || document.createElement('textarea');\n // Cache the <textarea> to re-use it next time.\n this.textAreaControl = inputOrTextArea;\n }\n\n // Set this variable so we can check it for input-specific properties.\n const input = isInputState(state)\n ? (inputOrTextArea as HTMLInputElement)\n : null;\n\n // Set input's \"type\" first, since this can change the other properties\n if (input) {\n input.type = state.type;\n }\n\n if (inputOrTextArea.value !== state.value) {\n // Only programmatically set the value if there's a difference. When using\n // the rendered control, the value will always be up to date. Setting the\n // property (even if it's the same string) will reset the internal <input>\n // dirty flag, making minlength and maxlength validation reset.\n inputOrTextArea.value = state.value;\n }\n\n inputOrTextArea.required = state.required;\n\n // The following IDLAttribute properties will always hydrate an attribute,\n // even if set to a the default value ('' or -1). The presence of the\n // attribute triggers constraint validation, so we must remove the attribute\n // when empty.\n if (input) {\n const inputState = state as InputState;\n if (inputState.pattern) {\n input.pattern = inputState.pattern;\n } else {\n input.removeAttribute('pattern');\n }\n\n if (inputState.min) {\n input.min = inputState.min;\n } else {\n input.removeAttribute('min');\n }\n\n if (inputState.max) {\n input.max = inputState.max;\n } else {\n input.removeAttribute('max');\n }\n\n if (inputState.step) {\n input.step = inputState.step;\n } else {\n input.removeAttribute('step');\n }\n }\n\n // Use -1 to represent no minlength and maxlength, which is what the\n // platform input returns. However, it will throw an error if you try to\n // manually set it to -1.\n //\n // While the type is `number`, it may actually be `null` at runtime.\n // `null > -1` is true since `null` coerces to `0`, so we default null and\n // undefined to -1.\n //\n // We set attributes instead of properties since setting a property may\n // throw an out of bounds error in relation to the other property.\n // Attributes will not throw errors while the state is updating.\n if ((state.minLength ?? -1) > -1) {\n inputOrTextArea.setAttribute('minlength', String(state.minLength));\n } else {\n inputOrTextArea.removeAttribute('minlength');\n }\n\n if ((state.maxLength ?? -1) > -1) {\n inputOrTextArea.setAttribute('maxlength', String(state.maxLength));\n } else {\n inputOrTextArea.removeAttribute('maxlength');\n }\n\n return {\n validity: inputOrTextArea.validity,\n validationMessage: inputOrTextArea.validationMessage,\n };\n }\n\n protected override equals(\n {state: prev}: TextFieldState,\n {state: next}: TextFieldState,\n ) {\n // Check shared input and textarea properties\n const inputOrTextAreaEqual =\n prev.type === next.type &&\n prev.value === next.value &&\n prev.required === next.required &&\n prev.minLength === next.minLength &&\n prev.maxLength === next.maxLength;\n\n if (!isInputState(prev) || !isInputState(next)) {\n // Both are textareas, all relevant properties are equal.\n return inputOrTextAreaEqual;\n }\n\n // Check additional input-specific properties.\n return (\n inputOrTextAreaEqual &&\n prev.pattern === next.pattern &&\n prev.min === next.min &&\n prev.max === next.max &&\n prev.step === next.step\n );\n }\n\n protected override copy({state}: TextFieldState): TextFieldState {\n // Don't hold a reference to the rendered control when copying since we\n // don't use it when checking if the state changed.\n return {\n state: isInputState(state)\n ? this.copyInput(state)\n : this.copyTextArea(state),\n renderedControl: null,\n };\n }\n\n private copyInput(state: InputState): InputState {\n const {type, pattern, min, max, step} = state;\n return {\n ...this.copySharedState(state),\n type,\n pattern,\n min,\n max,\n step,\n };\n }\n\n private copyTextArea(state: TextAreaState): TextAreaState {\n return {\n ...this.copySharedState(state),\n type: state.type,\n };\n }\n\n private copySharedState({\n value,\n required,\n minLength,\n maxLength,\n }: SharedInputAndTextAreaState): SharedInputAndTextAreaState {\n return {value, required, minLength, maxLength};\n }\n}\n\nfunction isInputState(state: InputState | TextAreaState): state is InputState {\n return state.type !== 'textarea';\n}\n"]}
@@ -33,7 +33,8 @@
33
33
  }
34
34
  }
35
35
 
36
- .container {
37
- border: var(--_outline-width) solid var(--_outline-color);
36
+ .outline {
37
+ border-color: var(--_outline-color);
38
+ border-width: var(--_outline-width);
38
39
  }
39
40
  }
@@ -18,18 +18,32 @@
18
18
  z-index: 0;
19
19
  }
20
20
 
21
- // Separate element will be needed for disabled opacities (b/307361748)
22
- .container {
23
- background: var(--_container-color);
21
+ md-elevation,
22
+ .background,
23
+ .outline {
24
24
  border-radius: inherit;
25
25
  inset: 0;
26
+ pointer-events: none;
26
27
  position: absolute;
28
+ }
29
+
30
+ // Separate element will be needed for disabled opacities (b/307361748)
31
+ .background {
32
+ background: var(--_container-color);
27
33
  // Place behind content.
28
34
  z-index: -1;
29
35
  }
30
36
 
37
+ // Separate element needed to overlay on top of content as opposed to
38
+ // background, which is behind content. All cards have an outline for HCM.
39
+ .outline {
40
+ // A default transparent border that is visible in HCM
41
+ border: 1px solid transparent;
42
+ // Outline should be placed on top of content, such as images.
43
+ z-index: 1;
44
+ }
45
+
31
46
  md-elevation {
32
- border-radius: inherit;
33
47
  // Place behind content.
34
48
  z-index: -1;
35
49
 
@@ -12,8 +12,9 @@ export class Card extends LitElement {
12
12
  render() {
13
13
  return html `
14
14
  <md-elevation part="elevation"></md-elevation>
15
- <div class="container"></div>
15
+ <div class="background"></div>
16
16
  <slot></slot>
17
+ <div class="outline"></div>
17
18
  `;
18
19
  }
19
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","sourceRoot":"","sources":["card.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,iCAAiC,CAAC;AAEzC,OAAO,EAAC,IAAI,EAAE,UAAU,EAAC,MAAM,KAAK,CAAC;AAErC;;GAEG;AACH,MAAM,OAAO,IAAK,SAAQ,UAAU;IACf,MAAM;QACvB,OAAO,IAAI,CAAA;;;;KAIV,CAAC;IACJ,CAAC;CACF","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport '../../../elevation/elevation.js';\n\nimport {html, LitElement} from 'lit';\n\n/**\n * A card component.\n */\nexport class Card extends LitElement {\n protected override render() {\n return html`\n <md-elevation part=\"elevation\"></md-elevation>\n <div class=\"container\"></div>\n <slot></slot>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["card.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,iCAAiC,CAAC;AAEzC,OAAO,EAAC,IAAI,EAAE,UAAU,EAAC,MAAM,KAAK,CAAC;AAErC;;GAEG;AACH,MAAM,OAAO,IAAK,SAAQ,UAAU;IACf,MAAM;QACvB,OAAO,IAAI,CAAA;;;;;KAKV,CAAC;IACJ,CAAC;CACF","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport '../../../elevation/elevation.js';\n\nimport {html, LitElement} from 'lit';\n\n/**\n * A card component.\n */\nexport class Card extends LitElement {\n protected override render() {\n return html`\n <md-elevation part=\"elevation\"></md-elevation>\n <div class=\"background\"></div>\n <slot></slot>\n <div class=\"outline\"></div>\n `;\n }\n}\n"]}
@@ -4,6 +4,6 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { css } from 'lit';
7
- export const styles = css `:host{--_container-color: var(--md-outlined-card-container-color, var(--md-sys-color-surface, #fef7ff));--_container-elevation: var(--md-outlined-card-container-elevation, 0);--_container-shadow-color: var(--md-outlined-card-container-shadow-color, var(--md-sys-color-shadow, #000));--_container-shape: var(--md-outlined-card-container-shape, 12px);--_outline-color: var(--md-outlined-card-outline-color, var(--md-sys-color-outline-variant, #cac4d0));--_outline-width: var(--md-outlined-card-outline-width, 1px)}.container{border:var(--_outline-width) solid var(--_outline-color)}/*# sourceMappingURL=outlined-styles.css.map */
7
+ export const styles = css `:host{--_container-color: var(--md-outlined-card-container-color, var(--md-sys-color-surface, #fef7ff));--_container-elevation: var(--md-outlined-card-container-elevation, 0);--_container-shadow-color: var(--md-outlined-card-container-shadow-color, var(--md-sys-color-shadow, #000));--_container-shape: var(--md-outlined-card-container-shape, 12px);--_outline-color: var(--md-outlined-card-outline-color, var(--md-sys-color-outline-variant, #cac4d0));--_outline-width: var(--md-outlined-card-outline-width, 1px)}.outline{border-color:var(--_outline-color);border-width:var(--_outline-width)}/*# sourceMappingURL=outlined-styles.css.map */
8
8
  `;
9
9
  //# sourceMappingURL=outlined-styles.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"outlined-styles.css.js","sourceRoot":"","sources":["outlined-styles.css.ts"],"names":[],"mappings":"AAAA;;;;IAII;AACH,OAAO,EAAC,GAAG,EAAC,MAAM,KAAK,CAAC;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;CACzB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n import {css} from 'lit';\n export const styles = css`:host{--_container-color: var(--md-outlined-card-container-color, var(--md-sys-color-surface, #fef7ff));--_container-elevation: var(--md-outlined-card-container-elevation, 0);--_container-shadow-color: var(--md-outlined-card-container-shadow-color, var(--md-sys-color-shadow, #000));--_container-shape: var(--md-outlined-card-container-shape, 12px);--_outline-color: var(--md-outlined-card-outline-color, var(--md-sys-color-outline-variant, #cac4d0));--_outline-width: var(--md-outlined-card-outline-width, 1px)}.container{border:var(--_outline-width) solid var(--_outline-color)}/*# sourceMappingURL=outlined-styles.css.map */\n`;\n "]}
1
+ {"version":3,"file":"outlined-styles.css.js","sourceRoot":"","sources":["outlined-styles.css.ts"],"names":[],"mappings":"AAAA;;;;IAII;AACH,OAAO,EAAC,GAAG,EAAC,MAAM,KAAK,CAAC;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;CACzB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n import {css} from 'lit';\n export const styles = css`:host{--_container-color: var(--md-outlined-card-container-color, var(--md-sys-color-surface, #fef7ff));--_container-elevation: var(--md-outlined-card-container-elevation, 0);--_container-shadow-color: var(--md-outlined-card-container-shadow-color, var(--md-sys-color-shadow, #000));--_container-shape: var(--md-outlined-card-container-shape, 12px);--_outline-color: var(--md-outlined-card-outline-color, var(--md-sys-color-outline-variant, #cac4d0));--_outline-width: var(--md-outlined-card-outline-width, 1px)}.outline{border-color:var(--_outline-color);border-width:var(--_outline-width)}/*# sourceMappingURL=outlined-styles.css.map */\n`;\n "]}
@@ -4,6 +4,6 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { css } from 'lit';
7
- export const styles = css `:host{border-radius:var(--_container-shape);box-sizing:border-box;display:flex;flex-direction:column;position:relative;z-index:0}.container{background:var(--_container-color);border-radius:inherit;inset:0;position:absolute;z-index:-1}md-elevation{border-radius:inherit;z-index:-1;--md-elevation-level: var(--_container-elevation);--md-elevation-shadow-color: var(--_container-shadow-color)}slot{border-radius:inherit}/*# sourceMappingURL=shared-styles.css.map */
7
+ export const styles = css `:host{border-radius:var(--_container-shape);box-sizing:border-box;display:flex;flex-direction:column;position:relative;z-index:0}md-elevation,.background,.outline{border-radius:inherit;inset:0;pointer-events:none;position:absolute}.background{background:var(--_container-color);z-index:-1}.outline{border:1px solid rgba(0,0,0,0);z-index:1}md-elevation{z-index:-1;--md-elevation-level: var(--_container-elevation);--md-elevation-shadow-color: var(--_container-shadow-color)}slot{border-radius:inherit}/*# sourceMappingURL=shared-styles.css.map */
8
8
  `;
9
9
  //# sourceMappingURL=shared-styles.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-styles.css.js","sourceRoot":"","sources":["shared-styles.css.ts"],"names":[],"mappings":"AAAA;;;;IAII;AACH,OAAO,EAAC,GAAG,EAAC,MAAM,KAAK,CAAC;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;CACzB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n import {css} from 'lit';\n export const styles = css`:host{border-radius:var(--_container-shape);box-sizing:border-box;display:flex;flex-direction:column;position:relative;z-index:0}.container{background:var(--_container-color);border-radius:inherit;inset:0;position:absolute;z-index:-1}md-elevation{border-radius:inherit;z-index:-1;--md-elevation-level: var(--_container-elevation);--md-elevation-shadow-color: var(--_container-shadow-color)}slot{border-radius:inherit}/*# sourceMappingURL=shared-styles.css.map */\n`;\n "]}
1
+ {"version":3,"file":"shared-styles.css.js","sourceRoot":"","sources":["shared-styles.css.ts"],"names":[],"mappings":"AAAA;;;;IAII;AACH,OAAO,EAAC,GAAG,EAAC,MAAM,KAAK,CAAC;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;CACzB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n import {css} from 'lit';\n export const styles = css`:host{border-radius:var(--_container-shape);box-sizing:border-box;display:flex;flex-direction:column;position:relative;z-index:0}md-elevation,.background,.outline{border-radius:inherit;inset:0;pointer-events:none;position:absolute}.background{background:var(--_container-color);z-index:-1}.outline{border:1px solid rgba(0,0,0,0);z-index:1}md-elevation{z-index:-1;--md-elevation-level: var(--_container-elevation);--md-elevation-shadow-color: var(--_container-shadow-color)}slot{border-radius:inherit}/*# sourceMappingURL=shared-styles.css.map */\n`;\n "]}