@material/web 1.0.2-nightly.f7a66a8.0 → 1.1.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 (118) hide show
  1. package/checkbox/internal/checkbox.d.ts +1 -0
  2. package/checkbox/internal/checkbox.js +6 -1
  3. package/checkbox/internal/checkbox.js.map +1 -1
  4. package/chips/internal/_shared.scss +16 -3
  5. package/chips/internal/_trailing-icon.scss +2 -1
  6. package/chips/internal/assist-styles.css.js +1 -1
  7. package/chips/internal/assist-styles.css.js.map +1 -1
  8. package/chips/internal/chip-set.js +2 -6
  9. package/chips/internal/chip-set.js.map +1 -1
  10. package/chips/internal/chip.d.ts +8 -0
  11. package/chips/internal/chip.js +17 -2
  12. package/chips/internal/chip.js.map +1 -1
  13. package/chips/internal/filter-chip.d.ts +8 -0
  14. package/chips/internal/filter-chip.js +17 -4
  15. package/chips/internal/filter-chip.js.map +1 -1
  16. package/chips/internal/filter-styles.css.js +1 -1
  17. package/chips/internal/filter-styles.css.js.map +1 -1
  18. package/chips/internal/input-styles.css.js +1 -1
  19. package/chips/internal/input-styles.css.js.map +1 -1
  20. package/chips/internal/shared-styles.css.js +1 -1
  21. package/chips/internal/shared-styles.css.js.map +1 -1
  22. package/chips/internal/suggestion-styles.css.js +1 -1
  23. package/chips/internal/suggestion-styles.css.js.map +1 -1
  24. package/chips/internal/trailing-icon-styles.css.js +1 -1
  25. package/chips/internal/trailing-icon-styles.css.js.map +1 -1
  26. package/chips/internal/trailing-icons.js +8 -4
  27. package/chips/internal/trailing-icons.js.map +1 -1
  28. package/fab/internal/_shared.scss +1 -0
  29. package/fab/internal/shared-styles.css.js +1 -1
  30. package/fab/internal/shared-styles.css.js.map +1 -1
  31. package/field/internal/_content.scss +3 -1
  32. package/field/internal/shared-styles.css.js +1 -1
  33. package/field/internal/shared-styles.css.js.map +1 -1
  34. package/internal/aria/aria.d.ts +0 -29
  35. package/internal/aria/aria.js +0 -141
  36. package/internal/aria/aria.js.map +1 -1
  37. package/internal/controller/form-submitter.js +2 -2
  38. package/internal/controller/form-submitter.js.map +1 -1
  39. package/labs/behaviors/constraint-validation.d.ts +2 -2
  40. package/labs/behaviors/constraint-validation.js +18 -1
  41. package/labs/behaviors/constraint-validation.js.map +1 -1
  42. package/labs/behaviors/element-internals.js +1 -5
  43. package/labs/behaviors/element-internals.js.map +1 -1
  44. package/labs/behaviors/focusable.js +20 -7
  45. package/labs/behaviors/focusable.js.map +1 -1
  46. package/labs/behaviors/on-report-validity.d.ts +70 -0
  47. package/labs/behaviors/on-report-validity.js +185 -0
  48. package/labs/behaviors/on-report-validity.js.map +1 -0
  49. package/labs/behaviors/validators/checkbox-validator.d.ts +6 -3
  50. package/labs/behaviors/validators/checkbox-validator.js.map +1 -1
  51. package/labs/behaviors/validators/radio-validator.d.ts +38 -0
  52. package/labs/behaviors/validators/radio-validator.js +65 -0
  53. package/labs/behaviors/validators/radio-validator.js.map +1 -0
  54. package/labs/behaviors/validators/select-validator.d.ts +35 -0
  55. package/labs/behaviors/validators/select-validator.js +33 -0
  56. package/labs/behaviors/validators/select-validator.js.map +1 -0
  57. package/labs/behaviors/validators/text-field-validator.d.ts +110 -0
  58. package/labs/behaviors/validators/text-field-validator.js +146 -0
  59. package/labs/behaviors/validators/text-field-validator.js.map +1 -0
  60. package/labs/behaviors/validators/validator.d.ts +4 -0
  61. package/labs/behaviors/validators/validator.js.map +1 -1
  62. package/labs/card/internal/_outlined-card.scss +1 -1
  63. package/labs/card/internal/_shared.scss +10 -2
  64. package/labs/card/internal/outlined-styles.css.js +1 -1
  65. package/labs/card/internal/outlined-styles.css.js.map +1 -1
  66. package/labs/card/internal/shared-styles.css.js +1 -1
  67. package/labs/card/internal/shared-styles.css.js.map +1 -1
  68. package/labs/segmentedbutton/internal/_shared.scss +1 -0
  69. package/labs/segmentedbutton/internal/shared-styles.css.js +1 -1
  70. package/labs/segmentedbutton/internal/shared-styles.css.js.map +1 -1
  71. package/list/internal/list.js +2 -6
  72. package/list/internal/list.js.map +1 -1
  73. package/list/internal/listitem/_list-item.scss +2 -0
  74. package/list/internal/listitem/list-item-styles.css.js +1 -1
  75. package/list/internal/listitem/list-item-styles.css.js.map +1 -1
  76. package/menu/internal/controllers/menuItemController.d.ts +13 -1
  77. package/menu/internal/controllers/menuItemController.js +32 -6
  78. package/menu/internal/controllers/menuItemController.js.map +1 -1
  79. package/menu/internal/menu.js +7 -8
  80. package/menu/internal/menu.js.map +1 -1
  81. package/menu/internal/menuitem/menu-item.d.ts +2 -0
  82. package/menu/internal/menuitem/menu-item.js +13 -1
  83. package/menu/internal/menuitem/menu-item.js.map +1 -1
  84. package/package.json +1 -1
  85. package/radio/internal/radio.d.ts +11 -1
  86. package/radio/internal/radio.js +28 -2
  87. package/radio/internal/radio.js.map +1 -1
  88. package/radio/internal/single-selection-controller.d.ts +5 -5
  89. package/radio/internal/single-selection-controller.js +16 -14
  90. package/radio/internal/single-selection-controller.js.map +1 -1
  91. package/select/internal/_shared.scss +5 -0
  92. package/select/internal/select.d.ts +21 -72
  93. package/select/internal/select.js +106 -184
  94. package/select/internal/select.js.map +1 -1
  95. package/select/internal/selectoption/select-option.d.ts +2 -0
  96. package/select/internal/selectoption/select-option.js +13 -1
  97. package/select/internal/selectoption/select-option.js.map +1 -1
  98. package/select/internal/selectoption/selectOptionController.d.ts +7 -3
  99. package/select/internal/selectoption/selectOptionController.js +8 -11
  100. package/select/internal/selectoption/selectOptionController.js.map +1 -1
  101. package/select/internal/shared-styles.css.js +1 -1
  102. package/select/internal/shared-styles.css.js.map +1 -1
  103. package/switch/internal/_icon.scss +14 -10
  104. package/switch/internal/switch-styles.css.js +1 -1
  105. package/switch/internal/switch-styles.css.js.map +1 -1
  106. package/switch/internal/switch.js +12 -8
  107. package/switch/internal/switch.js.map +1 -1
  108. package/tabs/internal/tab.js +2 -6
  109. package/tabs/internal/tab.js.map +1 -1
  110. package/tabs/internal/tabs.js +2 -6
  111. package/tabs/internal/tabs.js.map +1 -1
  112. package/textfield/internal/text-field.d.ts +9 -74
  113. package/textfield/internal/text-field.js +34 -150
  114. package/textfield/internal/text-field.js.map +1 -1
  115. package/tokens/_md-comp-assist-chip.scss +11 -0
  116. package/tokens/_md-comp-filter-chip.scss +14 -0
  117. package/tokens/_md-comp-input-chip.scss +14 -0
  118. package/tokens/_md-comp-suggestion-chip.scss +11 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-report-validity.js","sourceRoot":"","sources":["on-report-validity.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 {LitElement, isServer} from 'lit';\n\nimport {ConstraintValidation} from './constraint-validation.js';\nimport {MixinBase, MixinReturn} from './mixin.js';\n\n/**\n * A constraint validation element that has a callback for when the element\n * should report validity styles and error messages to the user.\n *\n * This is commonly used in text-field-like controls that display error styles\n * and error messages.\n */\nexport interface OnReportValidity extends ConstraintValidation {\n /**\n * A callback that is invoked when validity should be reported. Components\n * that can display their own error state can use this and update their\n * styles.\n *\n * If an invalid event is provided, the element is invalid. If `null`, the\n * element is valid.\n *\n * The invalid event's `preventDefault()` may be called to stop the platform\n * popup from displaying.\n *\n * @param invalidEvent The `invalid` event dispatched when an element is\n * invalid, or `null` if the element is valid.\n */\n [onReportValidity](invalidEvent: Event | null): void;\n\n // `mixinOnReportValidity()` implements this optional method. If overriden,\n // call `super.formAssociatedCallback(form)`.\n // (inherit jsdoc from `FormAssociated`)\n formAssociatedCallback(form: HTMLFormElement | null): void;\n}\n\n/**\n * A symbol property used for a callback when validity has been reported.\n */\nexport const onReportValidity = Symbol('onReportValidity');\n\n// Private symbol members, used to avoid name clashing.\nconst privateCleanupFormListeners = Symbol('privateCleanupFormListeners');\nconst privateDoNotReportInvalid = Symbol('privateDoNotReportInvalid');\n\n/**\n * Mixes in a callback for constraint validation when validity should be\n * styled and reported to the user.\n *\n * This is commonly used in text-field-like controls that display error styles\n * and error messages.\n *\n * @example\n * ```ts\n * const baseClass = mixinOnReportValidity(\n * mixinConstraintValidation(\n * mixinFormAssociated(mixinElementInternals(LitElement)),\n * ),\n * );\n *\n * class MyField extends baseClass {\n * \\@property({type: Boolean}) error = false;\n * \\@property() errorMessage = '';\n *\n * [onReportValidity](invalidEvent: Event | null) {\n * this.error = !!invalidEvent;\n * this.errorMessage = this.validationMessage;\n *\n * // Optionally prevent platform popup from displaying\n * invalidEvent?.preventDefault();\n * }\n * }\n * ```\n *\n * @param base The class to mix functionality into.\n * @return The provided class with `OnReportValidity` mixed in.\n */\nexport function mixinOnReportValidity<\n T extends MixinBase<LitElement & ConstraintValidation>,\n>(base: T): MixinReturn<T, OnReportValidity> {\n abstract class OnReportValidityElement\n extends base\n implements OnReportValidity\n {\n /**\n * Used to clean up event listeners when a new form is associated.\n */\n [privateCleanupFormListeners] = new AbortController();\n\n /**\n * Used to determine if an invalid event should report validity. Invalid\n * events from `checkValidity()` do not trigger reporting.\n */\n [privateDoNotReportInvalid] = false;\n\n // Mixins must have a constructor with `...args: any[]`\n // tslint:disable-next-line:no-any\n constructor(...args: any[]) {\n super(...args);\n if (isServer) {\n return;\n }\n\n this.addEventListener(\n 'invalid',\n (invalidEvent) => {\n // Listen for invalid events dispatched by a `<form>` when it tries to\n // submit and the element is invalid. We ignore events dispatched when\n // calling `checkValidity()` as well as untrusted events, since the\n // `reportValidity()` and `<form>`-dispatched events are always\n // trusted.\n if (this[privateDoNotReportInvalid] || !invalidEvent.isTrusted) {\n return;\n }\n\n this.addEventListener(\n 'invalid',\n () => {\n // A normal bubbling phase event listener. By adding it here, we\n // ensure it's the last event listener that is called during the\n // bubbling phase.\n if (!invalidEvent.defaultPrevented) {\n this[onReportValidity](invalidEvent);\n }\n },\n {once: true},\n );\n },\n {\n // Listen during the capture phase, which will happen before the\n // bubbling phase. That way, we can add a final event listener that\n // will run after other event listeners, and we can check if it was\n // default prevented. This works because invalid does not bubble.\n capture: true,\n },\n );\n }\n\n override checkValidity() {\n this[privateDoNotReportInvalid] = true;\n const valid = super.checkValidity();\n this[privateDoNotReportInvalid] = false;\n return valid;\n }\n\n override reportValidity() {\n const valid = super.reportValidity();\n // Constructor's invalid listener will handle reporting invalid events.\n if (valid) {\n this[onReportValidity](null);\n }\n\n return valid;\n }\n\n [onReportValidity](invalidEvent: Event | null) {\n throw new Error('Implement [onReportValidity]');\n }\n\n override formAssociatedCallback(form: HTMLFormElement | null) {\n // can't use super.formAssociatedCallback?.() due to closure\n if (super.formAssociatedCallback) {\n super.formAssociatedCallback(form);\n }\n\n // Clean up previous submit listener\n this[privateCleanupFormListeners].abort();\n if (!form) {\n return;\n }\n\n this[privateCleanupFormListeners] = new AbortController();\n // If the element's form submits, then all controls are valid. This lets\n // the element remove its error styles that may have been set when\n // `reportValidity()` was called.\n form.addEventListener(\n 'submit',\n () => {\n this[onReportValidity](null);\n },\n {\n signal: this[privateCleanupFormListeners].signal,\n },\n );\n\n // Inject a callback when `form.reportValidity()` is called and the form\n // is valid. There isn't an event that is dispatched to alert us (unlike\n // the 'invalid' event), and we need to remove error styles when\n // `form.reportValidity()` is called and returns true.\n let reportedInvalidEventFromForm = false;\n let formReportValidityCleanup = new AbortController();\n injectFormReportValidityHooks({\n form,\n cleanup: this[privateCleanupFormListeners].signal,\n beforeReportValidity: () => {\n reportedInvalidEventFromForm = false;\n this.addEventListener(\n 'invalid',\n (invalidEvent) => {\n reportedInvalidEventFromForm = true;\n if (!invalidEvent.defaultPrevented) {\n this[onReportValidity](invalidEvent);\n }\n },\n {signal: formReportValidityCleanup.signal},\n );\n },\n afterReportValidity: () => {\n formReportValidityCleanup.abort();\n formReportValidityCleanup = new AbortController();\n if (reportedInvalidEventFromForm) {\n reportedInvalidEventFromForm = false;\n return;\n }\n\n // Report successful form validation if an invalid event wasn't\n // fired.\n this[onReportValidity](null);\n },\n });\n }\n }\n\n return OnReportValidityElement;\n}\n\nconst FORM_REPORT_VALIDITY_HOOKS = new WeakMap<HTMLFormElement, EventTarget>();\n\nfunction injectFormReportValidityHooks({\n form,\n beforeReportValidity,\n afterReportValidity,\n cleanup,\n}: {\n form: HTMLFormElement;\n beforeReportValidity: () => void;\n afterReportValidity: () => void;\n cleanup: AbortSignal;\n}) {\n if (!FORM_REPORT_VALIDITY_HOOKS.has(form)) {\n // Patch form.reportValidity() to add an event target that can be used to\n // react when the method is called.\n // We should only patch this method once, since multiple controls and other\n // forces may want to patch this method. We cannot reliably clean it up by\n // resetting the method to \"superReportValidity\", which may be a patched\n // function.\n // Instead, we never clean up the patch but add and clean up event listener\n // hooks once it's patched.\n const hooks = new EventTarget();\n const superReportValidity = form.reportValidity;\n form.reportValidity = function (this: HTMLFormElement) {\n hooks.dispatchEvent(new Event('before'));\n const valid = superReportValidity.call(this);\n hooks.dispatchEvent(new Event('after'));\n return valid;\n };\n\n FORM_REPORT_VALIDITY_HOOKS.set(form, hooks);\n }\n\n const hooks = FORM_REPORT_VALIDITY_HOOKS.get(form)!;\n hooks.addEventListener('before', beforeReportValidity, {signal: cleanup});\n hooks.addEventListener('after', afterReportValidity, {signal: cleanup});\n}\n"]}
@@ -11,11 +11,11 @@ export interface CheckboxState {
11
11
  /**
12
12
  * Whether the checkbox is checked.
13
13
  */
14
- checked: boolean;
14
+ readonly checked: boolean;
15
15
  /**
16
16
  * Whether the checkbox is required.
17
17
  */
18
- required: boolean;
18
+ readonly required: boolean;
19
19
  }
20
20
  /**
21
21
  * A validator that provides constraint validation that emulates
@@ -28,5 +28,8 @@ export declare class CheckboxValidator extends Validator<CheckboxState> {
28
28
  validationMessage: string;
29
29
  };
30
30
  protected equals(prev: CheckboxState, next: CheckboxState): boolean;
31
- protected copy({ checked, required }: CheckboxState): CheckboxState;
31
+ protected copy({ checked, required }: CheckboxState): {
32
+ checked: boolean;
33
+ required: boolean;
34
+ };
32
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox-validator.js","sourceRoot":"","sources":["checkbox-validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAiBzC;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,SAAwB;IAG1C,eAAe,CAAC,KAAoB;QACrD,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;YACzB,mCAAmC;YACnC,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,CAAC,eAAe,CAAC,IAAI,GAAG,UAAU,CAAC;SACxC;QAED,IAAI,CAAC,eAAe,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC7C,IAAI,CAAC,eAAe,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC/C,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ;YACvC,iBAAiB,EAAE,IAAI,CAAC,eAAe,CAAC,iBAAiB;SAC1D,CAAC;IACJ,CAAC;IAEkB,MAAM,CAAC,IAAmB,EAAE,IAAmB;QAChE,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAC;IAC1E,CAAC;IAEkB,IAAI,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAgB;QACxD,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAC,CAAC;IAC7B,CAAC;CACF","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 properties for a checkbox.\n */\nexport interface CheckboxState {\n /**\n * Whether the checkbox is checked.\n */\n checked: boolean;\n\n /**\n * Whether the checkbox is required.\n */\n required: boolean;\n}\n\n/**\n * A validator that provides constraint validation that emulates\n * `<input type=\"checkbox\">` validation.\n */\nexport class CheckboxValidator extends Validator<CheckboxState> {\n private checkboxControl?: HTMLInputElement;\n\n protected override computeValidity(state: CheckboxState) {\n if (!this.checkboxControl) {\n // Lazily create the platform input\n this.checkboxControl = document.createElement('input');\n this.checkboxControl.type = 'checkbox';\n }\n\n this.checkboxControl.checked = state.checked;\n this.checkboxControl.required = state.required;\n return {\n validity: this.checkboxControl.validity,\n validationMessage: this.checkboxControl.validationMessage,\n };\n }\n\n protected override equals(prev: CheckboxState, next: CheckboxState) {\n return prev.checked === next.checked && prev.required === next.required;\n }\n\n protected override copy({checked, required}: CheckboxState): CheckboxState {\n return {checked, required};\n }\n}\n"]}
1
+ {"version":3,"file":"checkbox-validator.js","sourceRoot":"","sources":["checkbox-validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAiBzC;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,SAAwB;IAG1C,eAAe,CAAC,KAAoB;QACrD,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;YACzB,mCAAmC;YACnC,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,CAAC,eAAe,CAAC,IAAI,GAAG,UAAU,CAAC;SACxC;QAED,IAAI,CAAC,eAAe,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC7C,IAAI,CAAC,eAAe,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC/C,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ;YACvC,iBAAiB,EAAE,IAAI,CAAC,eAAe,CAAC,iBAAiB;SAC1D,CAAC;IACJ,CAAC;IAEkB,MAAM,CAAC,IAAmB,EAAE,IAAmB;QAChE,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAC;IAC1E,CAAC;IAEkB,IAAI,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAgB;QACxD,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAC,CAAC;IAC7B,CAAC;CACF","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 properties for a checkbox.\n */\nexport interface CheckboxState {\n /**\n * Whether the checkbox is checked.\n */\n readonly checked: boolean;\n\n /**\n * Whether the checkbox is required.\n */\n readonly required: boolean;\n}\n\n/**\n * A validator that provides constraint validation that emulates\n * `<input type=\"checkbox\">` validation.\n */\nexport class CheckboxValidator extends Validator<CheckboxState> {\n private checkboxControl?: HTMLInputElement;\n\n protected override computeValidity(state: CheckboxState) {\n if (!this.checkboxControl) {\n // Lazily create the platform input\n this.checkboxControl = document.createElement('input');\n this.checkboxControl.type = 'checkbox';\n }\n\n this.checkboxControl.checked = state.checked;\n this.checkboxControl.required = state.required;\n return {\n validity: this.checkboxControl.validity,\n validationMessage: this.checkboxControl.validationMessage,\n };\n }\n\n protected override equals(prev: CheckboxState, next: CheckboxState) {\n return prev.checked === next.checked && prev.required === next.required;\n }\n\n protected override copy({checked, required}: CheckboxState) {\n return {checked, required};\n }\n}\n"]}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Validator } from './validator.js';
7
+ /**
8
+ * Constraint validation properties for a radio.
9
+ */
10
+ export interface RadioState {
11
+ /**
12
+ * Whether the radio is checked.
13
+ */
14
+ readonly checked: boolean;
15
+ /**
16
+ * Whether the radio is required.
17
+ */
18
+ readonly required: boolean;
19
+ }
20
+ /**
21
+ * Radio constraint validation properties for a single radio and its siblings.
22
+ */
23
+ export type RadioGroupState = readonly [RadioState, ...RadioState[]];
24
+ /**
25
+ * A validator that provides constraint validation that emulates
26
+ * `<input type="radio">` validation.
27
+ */
28
+ export declare class RadioValidator extends Validator<RadioGroupState> {
29
+ private radioElement?;
30
+ protected computeValidity(states: RadioGroupState): {
31
+ validity: {
32
+ valueMissing: boolean;
33
+ };
34
+ validationMessage: string;
35
+ };
36
+ protected equals(prevGroup: RadioGroupState, nextGroup: RadioGroupState): boolean;
37
+ protected copy(states: RadioGroupState): RadioGroupState;
38
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Validator } from './validator.js';
7
+ /**
8
+ * A validator that provides constraint validation that emulates
9
+ * `<input type="radio">` validation.
10
+ */
11
+ export class RadioValidator extends Validator {
12
+ computeValidity(states) {
13
+ if (!this.radioElement) {
14
+ // Lazily create the radio element
15
+ this.radioElement = document.createElement('input');
16
+ this.radioElement.type = 'radio';
17
+ // A name is required for validation to run
18
+ this.radioElement.name = 'group';
19
+ }
20
+ let isRequired = false;
21
+ let isChecked = false;
22
+ for (const { checked, required } of states) {
23
+ if (required) {
24
+ isRequired = true;
25
+ }
26
+ if (checked) {
27
+ isChecked = true;
28
+ }
29
+ }
30
+ // Firefox v119 doesn't compute grouped radio validation correctly while
31
+ // they are detached from the DOM, which is why we don't render multiple
32
+ // virtual <input>s. Instead, we can check the required/checked states and
33
+ // grab the i18n'd validation message if the value is missing.
34
+ this.radioElement.checked = isChecked;
35
+ this.radioElement.required = isRequired;
36
+ return {
37
+ validity: {
38
+ valueMissing: isRequired && !isChecked,
39
+ },
40
+ validationMessage: this.radioElement.validationMessage,
41
+ };
42
+ }
43
+ equals(prevGroup, nextGroup) {
44
+ if (prevGroup.length !== nextGroup.length) {
45
+ return false;
46
+ }
47
+ for (let i = 0; i < prevGroup.length; i++) {
48
+ const prev = prevGroup[i];
49
+ const next = nextGroup[i];
50
+ if (prev.checked !== next.checked || prev.required !== next.required) {
51
+ return false;
52
+ }
53
+ }
54
+ return true;
55
+ }
56
+ copy(states) {
57
+ // Cast as unknown since typescript does not have enough information to
58
+ // infer that the array always has at least one element.
59
+ return states.map(({ checked, required }) => ({
60
+ checked,
61
+ required,
62
+ }));
63
+ }
64
+ }
65
+ //# sourceMappingURL=radio-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-validator.js","sourceRoot":"","sources":["radio-validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAsBzC;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,SAA0B;IAGzC,eAAe,CAAC,MAAuB;QACxD,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACtB,kCAAkC;YAClC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACpD,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,OAAO,CAAC;YACjC,2CAA2C;YAC3C,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,OAAO,CAAC;SAClC;QAED,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,KAAK,MAAM,EAAC,OAAO,EAAE,QAAQ,EAAC,IAAI,MAAM,EAAE;YACxC,IAAI,QAAQ,EAAE;gBACZ,UAAU,GAAG,IAAI,CAAC;aACnB;YAED,IAAI,OAAO,EAAE;gBACX,SAAS,GAAG,IAAI,CAAC;aAClB;SACF;QAED,wEAAwE;QACxE,wEAAwE;QACxE,0EAA0E;QAC1E,8DAA8D;QAC9D,IAAI,CAAC,YAAY,CAAC,OAAO,GAAG,SAAS,CAAC;QACtC,IAAI,CAAC,YAAY,CAAC,QAAQ,GAAG,UAAU,CAAC;QACxC,OAAO;YACL,QAAQ,EAAE;gBACR,YAAY,EAAE,UAAU,IAAI,CAAC,SAAS;aACvC;YACD,iBAAiB,EAAE,IAAI,CAAC,YAAY,CAAC,iBAAiB;SACvD,CAAC;IACJ,CAAC;IAEkB,MAAM,CACvB,SAA0B,EAC1B,SAA0B;QAE1B,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE;YACzC,OAAO,KAAK,CAAC;SACd;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACzC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,EAAE;gBACpE,OAAO,KAAK,CAAC;aACd;SACF;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEkB,IAAI,CAAC,MAAuB;QAC7C,uEAAuE;QACvE,wDAAwD;QACxD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAC,EAAE,EAAE,CAAC,CAAC;YAC1C,OAAO;YACP,QAAQ;SACT,CAAC,CAA+B,CAAC;IACpC,CAAC;CACF","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 properties for a radio.\n */\nexport interface RadioState {\n /**\n * Whether the radio is checked.\n */\n readonly checked: boolean;\n\n /**\n * Whether the radio is required.\n */\n readonly required: boolean;\n}\n\n/**\n * Radio constraint validation properties for a single radio and its siblings.\n */\nexport type RadioGroupState = readonly [RadioState, ...RadioState[]];\n\n/**\n * A validator that provides constraint validation that emulates\n * `<input type=\"radio\">` validation.\n */\nexport class RadioValidator extends Validator<RadioGroupState> {\n private radioElement?: HTMLInputElement;\n\n protected override computeValidity(states: RadioGroupState) {\n if (!this.radioElement) {\n // Lazily create the radio element\n this.radioElement = document.createElement('input');\n this.radioElement.type = 'radio';\n // A name is required for validation to run\n this.radioElement.name = 'group';\n }\n\n let isRequired = false;\n let isChecked = false;\n for (const {checked, required} of states) {\n if (required) {\n isRequired = true;\n }\n\n if (checked) {\n isChecked = true;\n }\n }\n\n // Firefox v119 doesn't compute grouped radio validation correctly while\n // they are detached from the DOM, which is why we don't render multiple\n // virtual <input>s. Instead, we can check the required/checked states and\n // grab the i18n'd validation message if the value is missing.\n this.radioElement.checked = isChecked;\n this.radioElement.required = isRequired;\n return {\n validity: {\n valueMissing: isRequired && !isChecked,\n },\n validationMessage: this.radioElement.validationMessage,\n };\n }\n\n protected override equals(\n prevGroup: RadioGroupState,\n nextGroup: RadioGroupState,\n ) {\n if (prevGroup.length !== nextGroup.length) {\n return false;\n }\n\n for (let i = 0; i < prevGroup.length; i++) {\n const prev = prevGroup[i];\n const next = nextGroup[i];\n if (prev.checked !== next.checked || prev.required !== next.required) {\n return false;\n }\n }\n\n return true;\n }\n\n protected override copy(states: RadioGroupState): RadioGroupState {\n // Cast as unknown since typescript does not have enough information to\n // infer that the array always has at least one element.\n return states.map(({checked, required}) => ({\n checked,\n required,\n })) as unknown as RadioGroupState;\n }\n}\n"]}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Validator } from './validator.js';
7
+ /**
8
+ * Constraint validation properties for a select dropdown.
9
+ */
10
+ export interface SelectState {
11
+ /**
12
+ * The current selected value.
13
+ */
14
+ readonly value: string;
15
+ /**
16
+ * Whether the select is required.
17
+ */
18
+ readonly required: boolean;
19
+ }
20
+ /**
21
+ * A validator that provides constraint validation that emulates `<select>`
22
+ * validation.
23
+ */
24
+ export declare class SelectValidator extends Validator<SelectState> {
25
+ private selectControl?;
26
+ protected computeValidity(state: SelectState): {
27
+ validity: ValidityState;
28
+ validationMessage: string;
29
+ };
30
+ protected equals(prev: SelectState, next: SelectState): boolean;
31
+ protected copy({ value, required }: SelectState): {
32
+ value: string;
33
+ required: boolean;
34
+ };
35
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { html, render } from 'lit';
7
+ import { Validator } from './validator.js';
8
+ /**
9
+ * A validator that provides constraint validation that emulates `<select>`
10
+ * validation.
11
+ */
12
+ export class SelectValidator extends Validator {
13
+ computeValidity(state) {
14
+ if (!this.selectControl) {
15
+ // Lazily create the platform select
16
+ this.selectControl = document.createElement('select');
17
+ }
18
+ render(html `<option value=${state.value}></option>`, this.selectControl);
19
+ this.selectControl.value = state.value;
20
+ this.selectControl.required = state.required;
21
+ return {
22
+ validity: this.selectControl.validity,
23
+ validationMessage: this.selectControl.validationMessage,
24
+ };
25
+ }
26
+ equals(prev, next) {
27
+ return prev.value === next.value && prev.required === next.required;
28
+ }
29
+ copy({ value, required }) {
30
+ return { value, required };
31
+ }
32
+ }
33
+ //# sourceMappingURL=select-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-validator.js","sourceRoot":"","sources":["select-validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,IAAI,EAAE,MAAM,EAAC,MAAM,KAAK,CAAC;AAEjC,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAiBzC;;;GAGG;AACH,MAAM,OAAO,eAAgB,SAAQ,SAAsB;IAGtC,eAAe,CAAC,KAAkB;QACnD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YACvB,oCAAoC;YACpC,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;SACvD;QAED,MAAM,CAAC,IAAI,CAAA,iBAAiB,KAAK,CAAC,KAAK,YAAY,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEzE,IAAI,CAAC,aAAa,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACvC,IAAI,CAAC,aAAa,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC7C,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ;YACrC,iBAAiB,EAAE,IAAI,CAAC,aAAa,CAAC,iBAAiB;SACxD,CAAC;IACJ,CAAC;IAEkB,MAAM,CAAC,IAAiB,EAAE,IAAiB;QAC5D,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAC;IACtE,CAAC;IAEkB,IAAI,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAc;QACpD,OAAO,EAAC,KAAK,EAAE,QAAQ,EAAC,CAAC;IAC3B,CAAC;CACF","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {html, render} from 'lit';\n\nimport {Validator} from './validator.js';\n\n/**\n * Constraint validation properties for a select dropdown.\n */\nexport interface SelectState {\n /**\n * The current selected value.\n */\n readonly value: string;\n\n /**\n * Whether the select is required.\n */\n readonly required: boolean;\n}\n\n/**\n * A validator that provides constraint validation that emulates `<select>`\n * validation.\n */\nexport class SelectValidator extends Validator<SelectState> {\n private selectControl?: HTMLSelectElement;\n\n protected override computeValidity(state: SelectState) {\n if (!this.selectControl) {\n // Lazily create the platform select\n this.selectControl = document.createElement('select');\n }\n\n render(html`<option value=${state.value}></option>`, this.selectControl);\n\n this.selectControl.value = state.value;\n this.selectControl.required = state.required;\n return {\n validity: this.selectControl.validity,\n validationMessage: this.selectControl.validationMessage,\n };\n }\n\n protected override equals(prev: SelectState, next: SelectState) {\n return prev.value === next.value && prev.required === next.required;\n }\n\n protected override copy({value, required}: SelectState) {\n return {value, required};\n }\n}\n"]}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Validator } from './validator.js';
7
+ /**
8
+ * Constraint validation for a text field.
9
+ */
10
+ export interface TextFieldState {
11
+ /**
12
+ * The input or textarea state to validate.
13
+ */
14
+ state: InputState | TextAreaState;
15
+ /**
16
+ * The `<input>` or `<textarea>` that is rendered on the page.
17
+ *
18
+ * `minlength` and `maxlength` validation do not apply until a user has
19
+ * interacted with the control and the element is internally marked as dirty.
20
+ * This is a spec quirk, the two properties behave differently from other
21
+ * constraint validation.
22
+ *
23
+ * This means we need an actual rendered element instead of a virtual one,
24
+ * since the virtual element will never be marked as dirty.
25
+ *
26
+ * This can be `null` if the element has not yet rendered, and the validator
27
+ * will fall back to virtual elements for other constraint validation
28
+ * properties, which do apply even if the control is not dirty.
29
+ */
30
+ renderedControl: HTMLInputElement | HTMLTextAreaElement | null;
31
+ }
32
+ /**
33
+ * Constraint validation properties for an `<input>`.
34
+ */
35
+ export interface InputState extends SharedInputAndTextAreaState {
36
+ /**
37
+ * The `<input>` type.
38
+ *
39
+ * Not all constraint validation properties apply to every type. See
40
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation#validation-related_attributes
41
+ * for which properties will apply to which types.
42
+ */
43
+ readonly type: string;
44
+ /**
45
+ * The regex pattern a value must match.
46
+ */
47
+ readonly pattern: string;
48
+ /**
49
+ * The minimum value.
50
+ */
51
+ readonly min: string;
52
+ /**
53
+ * The maximum value.
54
+ */
55
+ readonly max: string;
56
+ /**
57
+ * The step interval of the value.
58
+ */
59
+ readonly step: string;
60
+ }
61
+ /**
62
+ * Constraint validation properties for a `<textarea>`.
63
+ */
64
+ export interface TextAreaState extends SharedInputAndTextAreaState {
65
+ /**
66
+ * The type, must be "textarea" to inform the validator to use `<textarea>`
67
+ * instead of `<input>`.
68
+ */
69
+ readonly type: 'textarea';
70
+ }
71
+ /**
72
+ * Constraint validation properties shared between an `<input>` and
73
+ * `<textarea>`.
74
+ */
75
+ interface SharedInputAndTextAreaState {
76
+ /**
77
+ * The current value.
78
+ */
79
+ readonly value: string;
80
+ /**
81
+ * Whether the textarea is required.
82
+ */
83
+ readonly required: boolean;
84
+ /**
85
+ * The minimum length of the value.
86
+ */
87
+ readonly minLength: number;
88
+ /**
89
+ * The maximum length of the value.
90
+ */
91
+ readonly maxLength: number;
92
+ }
93
+ /**
94
+ * A validator that provides constraint validation that emulates `<input>` and
95
+ * `<textarea>` validation.
96
+ */
97
+ export declare class TextFieldValidator extends Validator<TextFieldState> {
98
+ private inputControl?;
99
+ private textAreaControl?;
100
+ protected computeValidity({ state, renderedControl }: TextFieldState): {
101
+ validity: ValidityState;
102
+ validationMessage: string;
103
+ };
104
+ protected equals({ state: prev }: TextFieldState, { state: next }: TextFieldState): boolean;
105
+ protected copy({ state }: TextFieldState): TextFieldState;
106
+ private copyInput;
107
+ private copyTextArea;
108
+ private copySharedState;
109
+ }
110
+ export {};
@@ -0,0 +1,146 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Validator } from './validator.js';
7
+ /**
8
+ * A validator that provides constraint validation that emulates `<input>` and
9
+ * `<textarea>` validation.
10
+ */
11
+ export class TextFieldValidator extends Validator {
12
+ computeValidity({ state, renderedControl }) {
13
+ let inputOrTextArea = renderedControl;
14
+ if (isInputState(state) && !inputOrTextArea) {
15
+ // Get cached <input> or create it.
16
+ inputOrTextArea = this.inputControl || document.createElement('input');
17
+ // Cache the <input> to re-use it next time.
18
+ this.inputControl = inputOrTextArea;
19
+ }
20
+ else if (!inputOrTextArea) {
21
+ // Get cached <textarea> or create it.
22
+ inputOrTextArea =
23
+ this.textAreaControl || document.createElement('textarea');
24
+ // Cache the <textarea> to re-use it next time.
25
+ this.textAreaControl = inputOrTextArea;
26
+ }
27
+ // Set this variable so we can check it for input-specific properties.
28
+ const input = isInputState(state)
29
+ ? inputOrTextArea
30
+ : null;
31
+ // Set input's "type" first, since this can change the other properties
32
+ if (input) {
33
+ input.type = state.type;
34
+ }
35
+ if (inputOrTextArea.value !== state.value) {
36
+ // Only programmatically set the value if there's a difference. When using
37
+ // the rendered control, the value will always be up to date. Setting the
38
+ // property (even if it's the same string) will reset the internal <input>
39
+ // dirty flag, making minlength and maxlength validation reset.
40
+ inputOrTextArea.value = state.value;
41
+ }
42
+ inputOrTextArea.required = state.required;
43
+ // The following IDLAttribute properties will always hydrate an attribute,
44
+ // even if set to a the default value ('' or -1). The presence of the
45
+ // attribute triggers constraint validation, so we must remove the attribute
46
+ // when empty.
47
+ if (input) {
48
+ const inputState = state;
49
+ if (inputState.pattern) {
50
+ input.pattern = inputState.pattern;
51
+ }
52
+ else {
53
+ input.removeAttribute('pattern');
54
+ }
55
+ if (inputState.min) {
56
+ input.min = inputState.min;
57
+ }
58
+ else {
59
+ input.removeAttribute('min');
60
+ }
61
+ if (inputState.max) {
62
+ input.max = inputState.max;
63
+ }
64
+ else {
65
+ input.removeAttribute('max');
66
+ }
67
+ if (inputState.step) {
68
+ input.step = inputState.step;
69
+ }
70
+ else {
71
+ input.removeAttribute('step');
72
+ }
73
+ }
74
+ // Use -1 to represent no minlength and maxlength, which is what the
75
+ // platform input returns. However, it will throw an error if you try to
76
+ // manually set it to -1.
77
+ if (state.minLength > -1) {
78
+ inputOrTextArea.minLength = state.minLength;
79
+ }
80
+ else {
81
+ inputOrTextArea.removeAttribute('minlength');
82
+ }
83
+ if (state.maxLength > -1) {
84
+ inputOrTextArea.maxLength = state.maxLength;
85
+ }
86
+ else {
87
+ inputOrTextArea.removeAttribute('maxlength');
88
+ }
89
+ return {
90
+ validity: inputOrTextArea.validity,
91
+ validationMessage: inputOrTextArea.validationMessage,
92
+ };
93
+ }
94
+ equals({ state: prev }, { state: next }) {
95
+ // Check shared input and textarea properties
96
+ const inputOrTextAreaEqual = prev.type === next.type &&
97
+ prev.value === next.value &&
98
+ prev.required === next.required &&
99
+ prev.minLength === next.minLength &&
100
+ prev.maxLength === next.maxLength;
101
+ if (!isInputState(prev) || !isInputState(next)) {
102
+ // Both are textareas, all relevant properties are equal.
103
+ return inputOrTextAreaEqual;
104
+ }
105
+ // Check additional input-specific properties.
106
+ return (inputOrTextAreaEqual &&
107
+ prev.pattern === next.pattern &&
108
+ prev.min === next.min &&
109
+ prev.max === next.max &&
110
+ prev.step === next.step);
111
+ }
112
+ copy({ state }) {
113
+ // Don't hold a reference to the rendered control when copying since we
114
+ // don't use it when checking if the state changed.
115
+ return {
116
+ state: isInputState(state)
117
+ ? this.copyInput(state)
118
+ : this.copyTextArea(state),
119
+ renderedControl: null,
120
+ };
121
+ }
122
+ copyInput(state) {
123
+ const { type, pattern, min, max, step } = state;
124
+ return {
125
+ ...this.copySharedState(state),
126
+ type,
127
+ pattern,
128
+ min,
129
+ max,
130
+ step,
131
+ };
132
+ }
133
+ copyTextArea(state) {
134
+ return {
135
+ ...this.copySharedState(state),
136
+ type: state.type,
137
+ };
138
+ }
139
+ copySharedState({ value, required, minLength, maxLength, }) {
140
+ return { value, required, minLength, maxLength };
141
+ }
142
+ }
143
+ function isInputState(state) {
144
+ return state.type !== 'textarea';
145
+ }
146
+ //# sourceMappingURL=text-field-validator.js.map
@@ -0,0 +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"]}
@@ -70,6 +70,10 @@ export declare abstract class Validator<State> {
70
70
  * Creates a copy of a state. This is used to cache state and check if it
71
71
  * changes.
72
72
  *
73
+ * Note: do NOT spread the {...state} to copy it. The actual state object is
74
+ * a web component, and trying to spread its getter/setter properties won't
75
+ * work.
76
+ *
73
77
  * @param state The state to copy.
74
78
  * @return A copy of the state.
75
79
  */
@@ -1 +1 @@
1
- {"version":3,"file":"validator.js","sourceRoot":"","sources":["validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,OAAgB,SAAS;IAgB7B;;;;;OAKG;IACH,YAA6B,eAA4B;QAA5B,oBAAe,GAAf,eAAe,CAAa;QAfzD;;;WAGG;QACK,oBAAe,GAAuB;YAC5C,QAAQ,EAAE,EAAE;YACZ,iBAAiB,EAAE,EAAE;SACtB,CAAC;IAQ0D,CAAC;IAE7D;;;;;;;;;OASG;IACH,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACrC,MAAM,eAAe,GACnB,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,eAAe,EAAE;YACpB,OAAO,IAAI,CAAC,eAAe,CAAC;SAC7B;QAED,MAAM,EAAC,QAAQ,EAAE,iBAAiB,EAAC,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAClE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,eAAe,GAAG;YACrB,iBAAiB;YACjB,QAAQ,EAAE;gBACR,uEAAuE;gBACvE,kDAAkD;gBAClD,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,eAAe,EAAE,QAAQ,CAAC,eAAe;gBACzC,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,cAAc,EAAE,QAAQ,CAAC,cAAc;gBACvC,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,YAAY,EAAE,QAAQ,CAAC,YAAY;aACpC;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;CAkCF","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * A class that computes and caches `ValidityStateFlags` for a component with\n * a given `State` interface.\n *\n * Cached performance before computing validity is important since constraint\n * validation must be checked frequently and synchronously when properties\n * change.\n *\n * @template State The expected interface of properties relevant to constraint\n * validation.\n */\nexport abstract class Validator<State> {\n /**\n * The previous state, used to determine if state changed and validation needs\n * to be re-computed.\n */\n private prevState?: State;\n\n /**\n * The current validity state and message. This is cached and returns if\n * constraint validation state does not change.\n */\n private currentValidity: ValidityAndMessage = {\n validity: {},\n validationMessage: '',\n };\n\n /**\n * Creates a new validator.\n *\n * @param getCurrentState A callback that returns the current state of\n * constraint validation-related properties.\n */\n constructor(private readonly getCurrentState: () => State) {}\n\n /**\n * Returns the current `ValidityStateFlags` and validation message for the\n * validator.\n *\n * If the constraint validation state has not changed, this will return a\n * cached result. This is important since `getValidity()` can be called\n * frequently in response to synchronous property changes.\n *\n * @return The current validity and validation message.\n */\n getValidity(): ValidityAndMessage {\n const state = this.getCurrentState();\n const hasStateChanged =\n !this.prevState || !this.equals(this.prevState, state);\n if (!hasStateChanged) {\n return this.currentValidity;\n }\n\n const {validity, validationMessage} = this.computeValidity(state);\n this.prevState = this.copy(state);\n this.currentValidity = {\n validationMessage,\n validity: {\n // Change any `ValidityState` instances into `ValidityStateFlags` since\n // `ValidityState` cannot be easily `{...spread}`.\n badInput: validity.badInput,\n customError: validity.customError,\n patternMismatch: validity.patternMismatch,\n rangeOverflow: validity.rangeOverflow,\n rangeUnderflow: validity.rangeUnderflow,\n stepMismatch: validity.stepMismatch,\n tooLong: validity.tooLong,\n tooShort: validity.tooShort,\n typeMismatch: validity.typeMismatch,\n valueMissing: validity.valueMissing,\n },\n };\n\n return this.currentValidity;\n }\n\n /**\n * Computes the `ValidityStateFlags` and validation message for a given set\n * of constraint validation properties.\n *\n * Implementations can use platform elements like `<input>` and `<select>` to\n * sync state and compute validation along with i18n'd messages. This function\n * may be expensive, and is only called when state changes.\n *\n * @param state The new state of constraint validation properties.\n * @return An object containing a `validity` property with\n * `ValidityStateFlags` and a `validationMessage` property.\n */\n protected abstract computeValidity(state: State): ValidityAndMessage;\n\n /**\n * Checks if two states are equal. This is used to check against cached state\n * to see if validity needs to be re-computed.\n *\n * @param prev The previous state.\n * @param next The next state.\n * @return True if the states are equal, or false if not.\n */\n protected abstract equals(prev: State, next: State): boolean;\n\n /**\n * Creates a copy of a state. This is used to cache state and check if it\n * changes.\n *\n * @param state The state to copy.\n * @return A copy of the state.\n */\n protected abstract copy(state: State): State;\n}\n\n/**\n * An object containing `ValidityStateFlags` and a corresponding validation\n * message.\n */\nexport interface ValidityAndMessage {\n /**\n * Validity flags.\n */\n validity: ValidityStateFlags;\n\n /**\n * The validation message for the associated flags. It may not be an empty\n * string if any of the validity flags are `true`.\n */\n validationMessage: string;\n}\n"]}
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,OAAgB,SAAS;IAgB7B;;;;;OAKG;IACH,YAA6B,eAA4B;QAA5B,oBAAe,GAAf,eAAe,CAAa;QAfzD;;;WAGG;QACK,oBAAe,GAAuB;YAC5C,QAAQ,EAAE,EAAE;YACZ,iBAAiB,EAAE,EAAE;SACtB,CAAC;IAQ0D,CAAC;IAE7D;;;;;;;;;OASG;IACH,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACrC,MAAM,eAAe,GACnB,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,eAAe,EAAE;YACpB,OAAO,IAAI,CAAC,eAAe,CAAC;SAC7B;QAED,MAAM,EAAC,QAAQ,EAAE,iBAAiB,EAAC,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAClE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,eAAe,GAAG;YACrB,iBAAiB;YACjB,QAAQ,EAAE;gBACR,uEAAuE;gBACvE,kDAAkD;gBAClD,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,eAAe,EAAE,QAAQ,CAAC,eAAe;gBACzC,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,cAAc,EAAE,QAAQ,CAAC,cAAc;gBACvC,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,YAAY,EAAE,QAAQ,CAAC,YAAY;aACpC;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;CAsCF","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * A class that computes and caches `ValidityStateFlags` for a component with\n * a given `State` interface.\n *\n * Cached performance before computing validity is important since constraint\n * validation must be checked frequently and synchronously when properties\n * change.\n *\n * @template State The expected interface of properties relevant to constraint\n * validation.\n */\nexport abstract class Validator<State> {\n /**\n * The previous state, used to determine if state changed and validation needs\n * to be re-computed.\n */\n private prevState?: State;\n\n /**\n * The current validity state and message. This is cached and returns if\n * constraint validation state does not change.\n */\n private currentValidity: ValidityAndMessage = {\n validity: {},\n validationMessage: '',\n };\n\n /**\n * Creates a new validator.\n *\n * @param getCurrentState A callback that returns the current state of\n * constraint validation-related properties.\n */\n constructor(private readonly getCurrentState: () => State) {}\n\n /**\n * Returns the current `ValidityStateFlags` and validation message for the\n * validator.\n *\n * If the constraint validation state has not changed, this will return a\n * cached result. This is important since `getValidity()` can be called\n * frequently in response to synchronous property changes.\n *\n * @return The current validity and validation message.\n */\n getValidity(): ValidityAndMessage {\n const state = this.getCurrentState();\n const hasStateChanged =\n !this.prevState || !this.equals(this.prevState, state);\n if (!hasStateChanged) {\n return this.currentValidity;\n }\n\n const {validity, validationMessage} = this.computeValidity(state);\n this.prevState = this.copy(state);\n this.currentValidity = {\n validationMessage,\n validity: {\n // Change any `ValidityState` instances into `ValidityStateFlags` since\n // `ValidityState` cannot be easily `{...spread}`.\n badInput: validity.badInput,\n customError: validity.customError,\n patternMismatch: validity.patternMismatch,\n rangeOverflow: validity.rangeOverflow,\n rangeUnderflow: validity.rangeUnderflow,\n stepMismatch: validity.stepMismatch,\n tooLong: validity.tooLong,\n tooShort: validity.tooShort,\n typeMismatch: validity.typeMismatch,\n valueMissing: validity.valueMissing,\n },\n };\n\n return this.currentValidity;\n }\n\n /**\n * Computes the `ValidityStateFlags` and validation message for a given set\n * of constraint validation properties.\n *\n * Implementations can use platform elements like `<input>` and `<select>` to\n * sync state and compute validation along with i18n'd messages. This function\n * may be expensive, and is only called when state changes.\n *\n * @param state The new state of constraint validation properties.\n * @return An object containing a `validity` property with\n * `ValidityStateFlags` and a `validationMessage` property.\n */\n protected abstract computeValidity(state: State): ValidityAndMessage;\n\n /**\n * Checks if two states are equal. This is used to check against cached state\n * to see if validity needs to be re-computed.\n *\n * @param prev The previous state.\n * @param next The next state.\n * @return True if the states are equal, or false if not.\n */\n protected abstract equals(prev: State, next: State): boolean;\n\n /**\n * Creates a copy of a state. This is used to cache state and check if it\n * changes.\n *\n * Note: do NOT spread the {...state} to copy it. The actual state object is\n * a web component, and trying to spread its getter/setter properties won't\n * work.\n *\n * @param state The state to copy.\n * @return A copy of the state.\n */\n protected abstract copy(state: State): State;\n}\n\n/**\n * An object containing `ValidityStateFlags` and a corresponding validation\n * message.\n */\nexport interface ValidityAndMessage {\n /**\n * Validity flags.\n */\n validity: ValidityStateFlags;\n\n /**\n * The validation message for the associated flags. It may not be an empty\n * string if any of the validity flags are `true`.\n */\n validationMessage: string;\n}\n"]}
@@ -34,6 +34,6 @@
34
34
  }
35
35
 
36
36
  .container {
37
- outline: var(--_outline-width) solid var(--_outline-color);
37
+ border: var(--_outline-width) solid var(--_outline-color);
38
38
  }
39
39
  }
@@ -10,9 +10,12 @@
10
10
  @mixin styles() {
11
11
  :host {
12
12
  border-radius: var(--_container-shape);
13
+ box-sizing: border-box;
13
14
  display: flex;
14
- padding: 16px;
15
+ flex-direction: column;
15
16
  position: relative;
17
+ // Reset z-index for background elements.
18
+ z-index: 0;
16
19
  }
17
20
 
18
21
  // Separate element will be needed for disabled opacities (b/307361748)
@@ -21,10 +24,14 @@
21
24
  border-radius: inherit;
22
25
  inset: 0;
23
26
  position: absolute;
27
+ // Place behind content.
28
+ z-index: -1;
24
29
  }
25
30
 
26
31
  md-elevation {
27
32
  border-radius: inherit;
33
+ // Place behind content.
34
+ z-index: -1;
28
35
 
29
36
  @include elevation.theme(
30
37
  (
@@ -35,6 +42,7 @@
35
42
  }
36
43
 
37
44
  slot {
38
- z-index: 0; // Place content above background elements
45
+ // Allow content to inherit card's border radius
46
+ border-radius: inherit;
39
47
  }
40
48
  }
@@ -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{outline: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)}.container{border:var(--_outline-width) solid var(--_outline-color)}/*# sourceMappingURL=outlined-styles.css.map */
8
8
  `;
9
9
  //# sourceMappingURL=outlined-styles.css.js.map