@material/web 1.0.2-nightly.f7a66a8.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/checkbox/internal/checkbox.d.ts +1 -0
- package/checkbox/internal/checkbox.js +6 -1
- package/checkbox/internal/checkbox.js.map +1 -1
- package/chips/internal/_shared.scss +16 -3
- package/chips/internal/_trailing-icon.scss +2 -1
- package/chips/internal/assist-styles.css.js +1 -1
- package/chips/internal/assist-styles.css.js.map +1 -1
- package/chips/internal/chip-set.js +2 -6
- package/chips/internal/chip-set.js.map +1 -1
- package/chips/internal/chip.d.ts +8 -0
- package/chips/internal/chip.js +17 -2
- package/chips/internal/chip.js.map +1 -1
- package/chips/internal/filter-chip.d.ts +8 -0
- package/chips/internal/filter-chip.js +17 -4
- package/chips/internal/filter-chip.js.map +1 -1
- package/chips/internal/filter-styles.css.js +1 -1
- package/chips/internal/filter-styles.css.js.map +1 -1
- package/chips/internal/input-styles.css.js +1 -1
- package/chips/internal/input-styles.css.js.map +1 -1
- package/chips/internal/shared-styles.css.js +1 -1
- package/chips/internal/shared-styles.css.js.map +1 -1
- package/chips/internal/suggestion-styles.css.js +1 -1
- package/chips/internal/suggestion-styles.css.js.map +1 -1
- package/chips/internal/trailing-icon-styles.css.js +1 -1
- package/chips/internal/trailing-icon-styles.css.js.map +1 -1
- package/chips/internal/trailing-icons.js +8 -4
- package/chips/internal/trailing-icons.js.map +1 -1
- package/fab/internal/_shared.scss +1 -0
- package/fab/internal/shared-styles.css.js +1 -1
- package/fab/internal/shared-styles.css.js.map +1 -1
- package/field/internal/_content.scss +3 -1
- package/field/internal/shared-styles.css.js +1 -1
- package/field/internal/shared-styles.css.js.map +1 -1
- package/internal/aria/aria.d.ts +0 -29
- package/internal/aria/aria.js +0 -141
- package/internal/aria/aria.js.map +1 -1
- package/internal/controller/form-submitter.js +2 -2
- package/internal/controller/form-submitter.js.map +1 -1
- package/labs/behaviors/constraint-validation.d.ts +2 -2
- package/labs/behaviors/constraint-validation.js +18 -1
- package/labs/behaviors/constraint-validation.js.map +1 -1
- package/labs/behaviors/element-internals.js +1 -5
- package/labs/behaviors/element-internals.js.map +1 -1
- package/labs/behaviors/focusable.js +20 -7
- package/labs/behaviors/focusable.js.map +1 -1
- package/labs/behaviors/form-associated.js +31 -11
- package/labs/behaviors/form-associated.js.map +1 -1
- package/labs/behaviors/on-report-validity.d.ts +70 -0
- package/labs/behaviors/on-report-validity.js +185 -0
- package/labs/behaviors/on-report-validity.js.map +1 -0
- package/labs/behaviors/validators/checkbox-validator.d.ts +6 -3
- package/labs/behaviors/validators/checkbox-validator.js.map +1 -1
- package/labs/behaviors/validators/radio-validator.d.ts +38 -0
- package/labs/behaviors/validators/radio-validator.js +65 -0
- package/labs/behaviors/validators/radio-validator.js.map +1 -0
- package/labs/behaviors/validators/select-validator.d.ts +35 -0
- package/labs/behaviors/validators/select-validator.js +33 -0
- package/labs/behaviors/validators/select-validator.js.map +1 -0
- package/labs/behaviors/validators/text-field-validator.d.ts +110 -0
- package/labs/behaviors/validators/text-field-validator.js +146 -0
- package/labs/behaviors/validators/text-field-validator.js.map +1 -0
- package/labs/behaviors/validators/validator.d.ts +4 -0
- package/labs/behaviors/validators/validator.js.map +1 -1
- package/labs/card/internal/_outlined-card.scss +1 -1
- package/labs/card/internal/_shared.scss +10 -2
- package/labs/card/internal/outlined-styles.css.js +1 -1
- package/labs/card/internal/outlined-styles.css.js.map +1 -1
- package/labs/card/internal/shared-styles.css.js +1 -1
- package/labs/card/internal/shared-styles.css.js.map +1 -1
- package/labs/segmentedbutton/internal/_shared.scss +1 -0
- package/labs/segmentedbutton/internal/shared-styles.css.js +1 -1
- package/labs/segmentedbutton/internal/shared-styles.css.js.map +1 -1
- package/list/internal/list.js +2 -6
- package/list/internal/list.js.map +1 -1
- package/list/internal/listitem/_list-item.scss +2 -0
- package/list/internal/listitem/list-item-styles.css.js +1 -1
- package/list/internal/listitem/list-item-styles.css.js.map +1 -1
- package/menu/internal/controllers/menuItemController.d.ts +13 -1
- package/menu/internal/controllers/menuItemController.js +32 -6
- package/menu/internal/controllers/menuItemController.js.map +1 -1
- package/menu/internal/menu.js +7 -8
- package/menu/internal/menu.js.map +1 -1
- package/menu/internal/menuitem/menu-item.d.ts +2 -0
- package/menu/internal/menuitem/menu-item.js +13 -1
- package/menu/internal/menuitem/menu-item.js.map +1 -1
- package/package.json +1 -1
- package/radio/internal/radio.d.ts +11 -1
- package/radio/internal/radio.js +28 -2
- package/radio/internal/radio.js.map +1 -1
- package/radio/internal/single-selection-controller.d.ts +5 -5
- package/radio/internal/single-selection-controller.js +16 -14
- package/radio/internal/single-selection-controller.js.map +1 -1
- package/select/internal/_shared.scss +5 -0
- package/select/internal/select.d.ts +21 -72
- package/select/internal/select.js +106 -184
- package/select/internal/select.js.map +1 -1
- package/select/internal/selectoption/select-option.d.ts +2 -0
- package/select/internal/selectoption/select-option.js +13 -1
- package/select/internal/selectoption/select-option.js.map +1 -1
- package/select/internal/selectoption/selectOptionController.d.ts +7 -3
- package/select/internal/selectoption/selectOptionController.js +8 -11
- package/select/internal/selectoption/selectOptionController.js.map +1 -1
- package/select/internal/shared-styles.css.js +1 -1
- package/select/internal/shared-styles.css.js.map +1 -1
- package/switch/internal/_icon.scss +14 -10
- package/switch/internal/switch-styles.css.js +1 -1
- package/switch/internal/switch-styles.css.js.map +1 -1
- package/switch/internal/switch.js +12 -8
- package/switch/internal/switch.js.map +1 -1
- package/tabs/internal/tab.js +2 -6
- package/tabs/internal/tab.js.map +1 -1
- package/tabs/internal/tabs.js +2 -6
- package/tabs/internal/tabs.js.map +1 -1
- package/textfield/internal/text-field.d.ts +9 -74
- package/textfield/internal/text-field.js +34 -150
- package/textfield/internal/text-field.js.map +1 -1
- package/tokens/_md-comp-assist-chip.scss +11 -0
- package/tokens/_md-comp-filter-chip.scss +14 -0
- package/tokens/_md-comp-input-chip.scss +14 -0
- package/tokens/_md-comp-suggestion-chip.scss +11 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aria.js","sourceRoot":"","sources":["aria.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 {isServer, ReactiveElement} from 'lit';\n\n/**\n * Accessibility Object Model reflective aria property name types.\n */\nexport type ARIAProperty = Exclude<keyof ARIAMixin, 'role'>;\n\n/**\n * Accessibility Object Model reflective aria properties.\n */\nexport const ARIA_PROPERTIES: ARIAProperty[] = [\n 'ariaAtomic',\n 'ariaAutoComplete',\n 'ariaBusy',\n 'ariaChecked',\n 'ariaColCount',\n 'ariaColIndex',\n 'ariaColSpan',\n 'ariaCurrent',\n 'ariaDisabled',\n 'ariaExpanded',\n 'ariaHasPopup',\n 'ariaHidden',\n 'ariaInvalid',\n 'ariaKeyShortcuts',\n 'ariaLabel',\n 'ariaLevel',\n 'ariaLive',\n 'ariaModal',\n 'ariaMultiLine',\n 'ariaMultiSelectable',\n 'ariaOrientation',\n 'ariaPlaceholder',\n 'ariaPosInSet',\n 'ariaPressed',\n 'ariaReadOnly',\n 'ariaRequired',\n 'ariaRoleDescription',\n 'ariaRowCount',\n 'ariaRowIndex',\n 'ariaRowSpan',\n 'ariaSelected',\n 'ariaSetSize',\n 'ariaSort',\n 'ariaValueMax',\n 'ariaValueMin',\n 'ariaValueNow',\n 'ariaValueText',\n];\n\n/**\n * Accessibility Object Model aria attribute name types.\n */\nexport type ARIAAttribute = ARIAPropertyToAttribute<ARIAProperty>;\n\n/**\n * Accessibility Object Model aria attributes.\n */\nexport const ARIA_ATTRIBUTES = ARIA_PROPERTIES.map(ariaPropertyToAttribute);\n\n/**\n * Checks if an attribute is one of the AOM aria attributes.\n *\n * @example\n * isAriaAttribute('aria-label'); // true\n *\n * @param attribute The attribute to check.\n * @return True if the attribute is an aria attribute, or false if not.\n */\nexport function isAriaAttribute(attribute: string): attribute is ARIAAttribute {\n return attribute.startsWith('aria-');\n}\n\n/**\n * Converts an AOM aria property into its corresponding attribute.\n *\n * @example\n * ariaPropertyToAttribute('ariaLabel'); // 'aria-label'\n *\n * @param property The aria property.\n * @return The aria attribute.\n */\nexport function ariaPropertyToAttribute<K extends ARIAProperty | 'role'>(\n property: K,\n) {\n return (\n property\n .replace('aria', 'aria-')\n // IDREF attributes also include an \"Element\" or \"Elements\" suffix\n .replace(/Elements?/g, '')\n .toLowerCase() as ARIAPropertyToAttribute<K>\n );\n}\n\n// Converts an `ariaFoo` string type to an `aria-foo` string type.\ntype ARIAPropertyToAttribute<K extends string> =\n K extends `aria${infer Suffix}Element${infer OptS}`\n ? `aria-${Lowercase<Suffix>}`\n : K extends `aria${infer Suffix}`\n ? `aria-${Lowercase<Suffix>}`\n : K;\n\n/**\n * An extension of `ARIAMixin` that enforces strict value types for aria\n * properties.\n *\n * This is needed for correct typing in render functions with lit analyzer.\n *\n * @example\n * render() {\n * const {ariaLabel} = this as ARIAMixinStrict;\n * return html`\n * <button aria-label=${ariaLabel || nothing}>\n * <slot></slot>\n * </button>\n * `;\n * }\n */\nexport interface ARIAMixinStrict extends ARIAMixin {\n ariaAtomic: 'true' | 'false' | null;\n ariaAutoComplete: 'none' | 'inline' | 'list' | 'both' | null;\n ariaBusy: 'true' | 'false' | null;\n ariaChecked: 'true' | 'false' | null;\n ariaColCount: `${number}` | null;\n ariaColIndex: `${number}` | null;\n ariaColSpan: `${number}` | null;\n ariaCurrent:\n | 'page'\n | 'step'\n | 'location'\n | 'date'\n | 'time'\n | 'true'\n | 'false'\n | null;\n ariaDisabled: 'true' | 'false' | null;\n ariaExpanded: 'true' | 'false' | null;\n ariaHasPopup:\n | 'false'\n | 'true'\n | 'menu'\n | 'listbox'\n | 'tree'\n | 'grid'\n | 'dialog'\n | null;\n ariaHidden: 'true' | 'false' | null;\n ariaInvalid: 'true' | 'false' | null;\n ariaKeyShortcuts: string | null;\n ariaLabel: string | null;\n ariaLevel: `${number}` | null;\n ariaLive: 'assertive' | 'off' | 'polite' | null;\n ariaModal: 'true' | 'false' | null;\n ariaMultiLine: 'true' | 'false' | null;\n ariaMultiSelectable: 'true' | 'false' | null;\n ariaOrientation: 'horizontal' | 'vertical' | 'undefined' | null;\n ariaPlaceholder: string | null;\n ariaPosInSet: `${number}` | null;\n ariaPressed: 'true' | 'false' | null;\n ariaReadOnly: 'true' | 'false' | null;\n ariaRequired: 'true' | 'false' | null;\n ariaRoleDescription: string | null;\n ariaRowCount: `${number}` | null;\n ariaRowIndex: `${number}` | null;\n ariaRowSpan: `${number}` | null;\n ariaSelected: 'true' | 'false' | null;\n ariaSetSize: `${number}` | null;\n ariaSort: 'ascending' | 'descending' | 'none' | 'other' | null;\n ariaValueMax: `${number}` | null;\n ariaValueMin: `${number}` | null;\n ariaValueNow: `${number}` | null;\n ariaValueText: string | null;\n role: ARIARole | null;\n}\n\n/**\n * Valid values for `role`.\n */\nexport type ARIARole =\n | 'alert'\n | 'alertdialog'\n | 'button'\n | 'checkbox'\n | 'dialog'\n | 'gridcell'\n | 'link'\n | 'log'\n | 'marquee'\n | 'menuitem'\n | 'menuitemcheckbox'\n | 'menuitemradio'\n | 'option'\n | 'progressbar'\n | 'radio'\n | 'scrollbar'\n | 'searchbox'\n | 'slider'\n | 'spinbutton'\n | 'status'\n | 'switch'\n | 'tab'\n | 'tabpanel'\n | 'textbox'\n | 'timer'\n | 'tooltip'\n | 'treeitem'\n | 'combobox'\n | 'grid'\n | 'listbox'\n | 'menu'\n | 'menubar'\n | 'radiogroup'\n | 'tablist'\n | 'tree'\n | 'treegrid'\n | 'application'\n | 'article'\n | 'cell'\n | 'columnheader'\n | 'definition'\n | 'directory'\n | 'document'\n | 'feed'\n | 'figure'\n | 'group'\n | 'heading'\n | 'img'\n | 'list'\n | 'listitem'\n | 'math'\n | 'none'\n | 'note'\n | 'presentation'\n | 'region'\n | 'row'\n | 'rowgroup'\n | 'rowheader'\n | 'separator'\n | 'table'\n | 'term'\n | 'text'\n | 'toolbar'\n | 'banner'\n | 'complementary'\n | 'contentinfo'\n | 'form'\n | 'main'\n | 'navigation'\n | 'region'\n | 'search'\n | 'doc-abstract'\n | 'doc-acknowledgments'\n | 'doc-afterword'\n | 'doc-appendix'\n | 'doc-backlink'\n | 'doc-biblioentry'\n | 'doc-bibliography'\n | 'doc-biblioref'\n | 'doc-chapter'\n | 'doc-colophon'\n | 'doc-conclusion'\n | 'doc-cover'\n | 'doc-credit'\n | 'doc-credits'\n | 'doc-dedication'\n | 'doc-endnote'\n | 'doc-endnotes'\n | 'doc-epigraph'\n | 'doc-epilogue'\n | 'doc-errata'\n | 'doc-example'\n | 'doc-footnote'\n | 'doc-foreword'\n | 'doc-glossary'\n | 'doc-glossref'\n | 'doc-index'\n | 'doc-introduction'\n | 'doc-noteref'\n | 'doc-notice'\n | 'doc-pagebreak'\n | 'doc-pagelist'\n | 'doc-part'\n | 'doc-preface'\n | 'doc-prologue'\n | 'doc-pullquote'\n | 'doc-qna'\n | 'doc-subtitle'\n | 'doc-tip'\n | 'doc-toc';\n\n/**\n * This function will polyfill `ARIAMixin` properties for Firefox.\n *\n * @param ctor The `ReactiveElement` constructor to set up.\n */\nexport function polyfillARIAMixin(ctor: typeof ReactiveElement) {\n if (isServer || 'role' in Element.prototype) {\n return;\n }\n\n // Polyfill reflective aria properties for Firefox\n for (const ariaProperty of ARIA_PROPERTIES) {\n ctor.createProperty(ariaProperty, {\n attribute: ariaPropertyToAttribute(ariaProperty),\n reflect: true,\n });\n }\n\n ctor.createProperty('role', {reflect: true});\n}\n\n/**\n * Polyfills an element and its `ElementInternals` to support `ARIAMixin`\n * properties on internals. This is needed for Firefox.\n *\n * `polyfillARIAMixin()` must be called for the element class.\n *\n * @example\n * class XButton extends LitElement {\n * static {\n * polyfillARIAMixin(XButton);\n * }\n *\n * private internals =\n * polyfillElementInternalsAria(this, this.attachInternals());\n *\n * constructor() {\n * super();\n * this.internals.role = 'button';\n * }\n * }\n */\nexport function polyfillElementInternalsAria(\n host: ReactiveElement,\n internals: ElementInternals,\n) {\n if (checkIfElementInternalsSupportsAria(internals)) {\n return internals;\n }\n\n if (!('role' in host)) {\n throw new Error('Missing polyfillARIAMixin()');\n }\n\n let firstConnectedCallbacks: Array<{\n property: ARIAProperty | 'role';\n callback: () => void;\n }> = [];\n let hasBeenConnected = false;\n\n // Add support for Firefox, which has not yet implement ElementInternals aria\n for (const ariaProperty of ARIA_PROPERTIES) {\n let internalAriaValue: string | null = null;\n Object.defineProperty(internals, ariaProperty, {\n enumerable: true,\n configurable: true,\n get() {\n return internalAriaValue;\n },\n set(value: string | null) {\n const setValue = () => {\n internalAriaValue = value;\n if (!hasBeenConnected) {\n firstConnectedCallbacks.push({\n property: ariaProperty,\n callback: setValue,\n });\n return;\n }\n\n // Dynamic lookup rather than hardcoding all properties.\n // tslint:disable-next-line:no-dict-access-on-struct-type\n host[ariaProperty] = value;\n };\n\n setValue();\n },\n });\n }\n\n let internalRoleValue: string | null = null;\n Object.defineProperty(internals, 'role', {\n enumerable: true,\n configurable: true,\n get() {\n return internalRoleValue;\n },\n set(value: string | null) {\n const setRole = () => {\n internalRoleValue = value;\n\n if (!hasBeenConnected) {\n firstConnectedCallbacks.push({\n property: 'role',\n callback: setRole,\n });\n return;\n }\n\n if (value === null) {\n host.removeAttribute('role');\n } else {\n host.setAttribute('role', value);\n }\n };\n\n setRole();\n },\n });\n\n host.addController({\n hostConnected() {\n if (hasBeenConnected) {\n return;\n }\n\n hasBeenConnected = true;\n\n const propertiesSetByUser = new Set<ARIAProperty | 'role'>();\n\n // See which properties were set by the user on host before we apply\n // internals values as attributes to host. Needs to be done in another\n // for loop because the callbacks set these attributes on host.\n for (const {property} of firstConnectedCallbacks) {\n const wasSetByUser =\n host.getAttribute(ariaPropertyToAttribute(property)) !== null ||\n // Dynamic lookup rather than hardcoding all properties.\n // tslint:disable-next-line:no-dict-access-on-struct-type\n host[property] !== undefined;\n\n if (wasSetByUser) {\n propertiesSetByUser.add(property);\n }\n }\n\n for (const {property, callback} of firstConnectedCallbacks) {\n // If the user has set the attribute or property, do not override the\n // user's value\n if (propertiesSetByUser.has(property)) {\n continue;\n }\n\n callback();\n }\n\n // Remove strong callback references\n firstConnectedCallbacks = [];\n },\n });\n\n return internals;\n}\n\n// Separate function so that typescript doesn't complain about internals being\n// \"never\".\nfunction checkIfElementInternalsSupportsAria(internals: ElementInternals) {\n return 'role' in internals;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"aria.js","sourceRoot":"","sources":["aria.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAmB;IAC7C,YAAY;IACZ,kBAAkB;IAClB,UAAU;IACV,aAAa;IACb,cAAc;IACd,cAAc;IACd,aAAa;IACb,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,YAAY;IACZ,aAAa;IACb,kBAAkB;IAClB,WAAW;IACX,WAAW;IACX,UAAU;IACV,WAAW;IACX,eAAe;IACf,qBAAqB;IACrB,iBAAiB;IACjB,iBAAiB;IACjB,cAAc;IACd,aAAa;IACb,cAAc;IACd,cAAc;IACd,qBAAqB;IACrB,cAAc;IACd,cAAc;IACd,aAAa;IACb,cAAc;IACd,aAAa;IACb,UAAU;IACV,cAAc;IACd,cAAc;IACd,cAAc;IACd,eAAe;CAChB,CAAC;AAOF;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAE5E;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,OAAO,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAAW;IAEX,OACE,QAAQ;SACL,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;QACzB,kEAAkE;SACjE,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,WAAW,EACf,CAAC;AACJ,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Accessibility Object Model reflective aria property name types.\n */\nexport type ARIAProperty = Exclude<keyof ARIAMixin, 'role'>;\n\n/**\n * Accessibility Object Model reflective aria properties.\n */\nexport const ARIA_PROPERTIES: ARIAProperty[] = [\n 'ariaAtomic',\n 'ariaAutoComplete',\n 'ariaBusy',\n 'ariaChecked',\n 'ariaColCount',\n 'ariaColIndex',\n 'ariaColSpan',\n 'ariaCurrent',\n 'ariaDisabled',\n 'ariaExpanded',\n 'ariaHasPopup',\n 'ariaHidden',\n 'ariaInvalid',\n 'ariaKeyShortcuts',\n 'ariaLabel',\n 'ariaLevel',\n 'ariaLive',\n 'ariaModal',\n 'ariaMultiLine',\n 'ariaMultiSelectable',\n 'ariaOrientation',\n 'ariaPlaceholder',\n 'ariaPosInSet',\n 'ariaPressed',\n 'ariaReadOnly',\n 'ariaRequired',\n 'ariaRoleDescription',\n 'ariaRowCount',\n 'ariaRowIndex',\n 'ariaRowSpan',\n 'ariaSelected',\n 'ariaSetSize',\n 'ariaSort',\n 'ariaValueMax',\n 'ariaValueMin',\n 'ariaValueNow',\n 'ariaValueText',\n];\n\n/**\n * Accessibility Object Model aria attribute name types.\n */\nexport type ARIAAttribute = ARIAPropertyToAttribute<ARIAProperty>;\n\n/**\n * Accessibility Object Model aria attributes.\n */\nexport const ARIA_ATTRIBUTES = ARIA_PROPERTIES.map(ariaPropertyToAttribute);\n\n/**\n * Checks if an attribute is one of the AOM aria attributes.\n *\n * @example\n * isAriaAttribute('aria-label'); // true\n *\n * @param attribute The attribute to check.\n * @return True if the attribute is an aria attribute, or false if not.\n */\nexport function isAriaAttribute(attribute: string): attribute is ARIAAttribute {\n return attribute.startsWith('aria-');\n}\n\n/**\n * Converts an AOM aria property into its corresponding attribute.\n *\n * @example\n * ariaPropertyToAttribute('ariaLabel'); // 'aria-label'\n *\n * @param property The aria property.\n * @return The aria attribute.\n */\nexport function ariaPropertyToAttribute<K extends ARIAProperty | 'role'>(\n property: K,\n) {\n return (\n property\n .replace('aria', 'aria-')\n // IDREF attributes also include an \"Element\" or \"Elements\" suffix\n .replace(/Elements?/g, '')\n .toLowerCase() as ARIAPropertyToAttribute<K>\n );\n}\n\n// Converts an `ariaFoo` string type to an `aria-foo` string type.\ntype ARIAPropertyToAttribute<K extends string> =\n K extends `aria${infer Suffix}Element${infer OptS}`\n ? `aria-${Lowercase<Suffix>}`\n : K extends `aria${infer Suffix}`\n ? `aria-${Lowercase<Suffix>}`\n : K;\n\n/**\n * An extension of `ARIAMixin` that enforces strict value types for aria\n * properties.\n *\n * This is needed for correct typing in render functions with lit analyzer.\n *\n * @example\n * render() {\n * const {ariaLabel} = this as ARIAMixinStrict;\n * return html`\n * <button aria-label=${ariaLabel || nothing}>\n * <slot></slot>\n * </button>\n * `;\n * }\n */\nexport interface ARIAMixinStrict extends ARIAMixin {\n ariaAtomic: 'true' | 'false' | null;\n ariaAutoComplete: 'none' | 'inline' | 'list' | 'both' | null;\n ariaBusy: 'true' | 'false' | null;\n ariaChecked: 'true' | 'false' | null;\n ariaColCount: `${number}` | null;\n ariaColIndex: `${number}` | null;\n ariaColSpan: `${number}` | null;\n ariaCurrent:\n | 'page'\n | 'step'\n | 'location'\n | 'date'\n | 'time'\n | 'true'\n | 'false'\n | null;\n ariaDisabled: 'true' | 'false' | null;\n ariaExpanded: 'true' | 'false' | null;\n ariaHasPopup:\n | 'false'\n | 'true'\n | 'menu'\n | 'listbox'\n | 'tree'\n | 'grid'\n | 'dialog'\n | null;\n ariaHidden: 'true' | 'false' | null;\n ariaInvalid: 'true' | 'false' | null;\n ariaKeyShortcuts: string | null;\n ariaLabel: string | null;\n ariaLevel: `${number}` | null;\n ariaLive: 'assertive' | 'off' | 'polite' | null;\n ariaModal: 'true' | 'false' | null;\n ariaMultiLine: 'true' | 'false' | null;\n ariaMultiSelectable: 'true' | 'false' | null;\n ariaOrientation: 'horizontal' | 'vertical' | 'undefined' | null;\n ariaPlaceholder: string | null;\n ariaPosInSet: `${number}` | null;\n ariaPressed: 'true' | 'false' | null;\n ariaReadOnly: 'true' | 'false' | null;\n ariaRequired: 'true' | 'false' | null;\n ariaRoleDescription: string | null;\n ariaRowCount: `${number}` | null;\n ariaRowIndex: `${number}` | null;\n ariaRowSpan: `${number}` | null;\n ariaSelected: 'true' | 'false' | null;\n ariaSetSize: `${number}` | null;\n ariaSort: 'ascending' | 'descending' | 'none' | 'other' | null;\n ariaValueMax: `${number}` | null;\n ariaValueMin: `${number}` | null;\n ariaValueNow: `${number}` | null;\n ariaValueText: string | null;\n role: ARIARole | null;\n}\n\n/**\n * Valid values for `role`.\n */\nexport type ARIARole =\n | 'alert'\n | 'alertdialog'\n | 'button'\n | 'checkbox'\n | 'dialog'\n | 'gridcell'\n | 'link'\n | 'log'\n | 'marquee'\n | 'menuitem'\n | 'menuitemcheckbox'\n | 'menuitemradio'\n | 'option'\n | 'progressbar'\n | 'radio'\n | 'scrollbar'\n | 'searchbox'\n | 'slider'\n | 'spinbutton'\n | 'status'\n | 'switch'\n | 'tab'\n | 'tabpanel'\n | 'textbox'\n | 'timer'\n | 'tooltip'\n | 'treeitem'\n | 'combobox'\n | 'grid'\n | 'listbox'\n | 'menu'\n | 'menubar'\n | 'radiogroup'\n | 'tablist'\n | 'tree'\n | 'treegrid'\n | 'application'\n | 'article'\n | 'cell'\n | 'columnheader'\n | 'definition'\n | 'directory'\n | 'document'\n | 'feed'\n | 'figure'\n | 'group'\n | 'heading'\n | 'img'\n | 'list'\n | 'listitem'\n | 'math'\n | 'none'\n | 'note'\n | 'presentation'\n | 'region'\n | 'row'\n | 'rowgroup'\n | 'rowheader'\n | 'separator'\n | 'table'\n | 'term'\n | 'text'\n | 'toolbar'\n | 'banner'\n | 'complementary'\n | 'contentinfo'\n | 'form'\n | 'main'\n | 'navigation'\n | 'region'\n | 'search'\n | 'doc-abstract'\n | 'doc-acknowledgments'\n | 'doc-afterword'\n | 'doc-appendix'\n | 'doc-backlink'\n | 'doc-biblioentry'\n | 'doc-bibliography'\n | 'doc-biblioref'\n | 'doc-chapter'\n | 'doc-colophon'\n | 'doc-conclusion'\n | 'doc-cover'\n | 'doc-credit'\n | 'doc-credits'\n | 'doc-dedication'\n | 'doc-endnote'\n | 'doc-endnotes'\n | 'doc-epigraph'\n | 'doc-epilogue'\n | 'doc-errata'\n | 'doc-example'\n | 'doc-footnote'\n | 'doc-foreword'\n | 'doc-glossary'\n | 'doc-glossref'\n | 'doc-index'\n | 'doc-introduction'\n | 'doc-noteref'\n | 'doc-notice'\n | 'doc-pagebreak'\n | 'doc-pagelist'\n | 'doc-part'\n | 'doc-preface'\n | 'doc-prologue'\n | 'doc-pullquote'\n | 'doc-qna'\n | 'doc-subtitle'\n | 'doc-tip'\n | 'doc-toc';\n"]}
|
|
@@ -39,9 +39,9 @@ export function setupFormSubmitter(ctor) {
|
|
|
39
39
|
if (!form || type === 'button') {
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
// Wait a
|
|
42
|
+
// Wait a full task for event bubbling to complete.
|
|
43
43
|
await new Promise((resolve) => {
|
|
44
|
-
resolve
|
|
44
|
+
setTimeout(resolve);
|
|
45
45
|
});
|
|
46
46
|
if (event.defaultPrevented) {
|
|
47
47
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-submitter.js","sourceRoot":"","sources":["form-submitter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,QAAQ,EAAkB,MAAM,KAAK,CAAC;AAE9C,OAAO,EACL,SAAS,GAEV,MAAM,2CAA2C,CAAC;AAgDnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAA8B;IAC/D,IAAI,QAAQ,EAAE;QACZ,OAAO;KACR;IAEA,IAA0C,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE,EAAE;QACtE,MAAM,SAAS,GAAG,QAAyB,CAAC;QAC5C,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAClD,MAAM,EAAC,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,gBAAgB,EAAC,GAAG,SAAS,CAAC;YACxD,MAAM,EAAC,IAAI,EAAC,GAAG,gBAAgB,CAAC;YAChC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,QAAQ,EAAE;gBAC9B,OAAO;aACR;YAED,mDAAmD;YACnD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAClC,OAAO,
|
|
1
|
+
{"version":3,"file":"form-submitter.js","sourceRoot":"","sources":["form-submitter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,QAAQ,EAAkB,MAAM,KAAK,CAAC;AAE9C,OAAO,EACL,SAAS,GAEV,MAAM,2CAA2C,CAAC;AAgDnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAA8B;IAC/D,IAAI,QAAQ,EAAE;QACZ,OAAO;KACR;IAEA,IAA0C,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE,EAAE;QACtE,MAAM,SAAS,GAAG,QAAyB,CAAC;QAC5C,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAClD,MAAM,EAAC,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,gBAAgB,EAAC,GAAG,SAAS,CAAC;YACxD,MAAM,EAAC,IAAI,EAAC,GAAG,gBAAgB,CAAC;YAChC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,QAAQ,EAAE;gBAC9B,OAAO;aACR;YAED,mDAAmD;YACnD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAClC,UAAU,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;YAEH,IAAI,KAAK,CAAC,gBAAgB,EAAE;gBAC1B,OAAO;aACR;YAED,IAAI,IAAI,KAAK,OAAO,EAAE;gBACpB,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,OAAO;aACR;YAED,0EAA0E;YAC1E,wEAAwE;YACxE,eAAe;YACf,uDAAuD;YACvD,IAAI,CAAC,gBAAgB,CACnB,QAAQ,EACR,CAAC,WAAW,EAAE,EAAE;gBACd,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,WAAW,EAAE;oBAC9C,YAAY,EAAE,IAAI;oBAClB,UAAU,EAAE,IAAI;oBAChB,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS;iBACrB,CAAC,CAAC;YACL,CAAC,EACD,EAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAC,CAC5B,CAAC;YAEF,gBAAgB,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC/C,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {isServer, ReactiveElement} from 'lit';\n\nimport {\n internals,\n WithElementInternals,\n} from '../../labs/behaviors/element-internals.js';\n\n/**\n * A string indicating the form submission behavior of the element.\n *\n * - submit: The element submits the form. This is the default value if the\n * attribute is not specified, or if it is dynamically changed to an empty or\n * invalid value.\n * - reset: The element resets the form.\n * - button: The element does nothing.\n */\nexport type FormSubmitterType = 'button' | 'submit' | 'reset';\n\n/**\n * An element that can submit or reset a `<form>`, similar to\n * `<button type=\"submit\">`.\n */\nexport interface FormSubmitter extends ReactiveElement, WithElementInternals {\n /**\n * A string indicating the form submission behavior of the element.\n *\n * - submit: The element submits the form. This is the default value if the\n * attribute is not specified, or if it is dynamically changed to an empty or\n * invalid value.\n * - reset: The element resets the form.\n * - button: The element does nothing.\n */\n type: FormSubmitterType;\n\n /**\n * The HTML name to use in form submission. When combined with a `value`, the\n * submitting button's name/value will be added to the form.\n *\n * Names must reflect to a `name` attribute for form integration.\n */\n name: string;\n\n /**\n * The value of the button. When combined with a `name`, the submitting\n * button's name/value will be added to the form.\n */\n value: string;\n}\n\ntype FormSubmitterConstructor =\n | (new () => FormSubmitter)\n | (abstract new () => FormSubmitter);\n\n/**\n * Sets up an element's constructor to enable form submission. The element\n * instance should be form associated and have a `type` property.\n *\n * A click listener is added to each element instance. If the click is not\n * default prevented, it will submit the element's form, if any.\n *\n * @example\n * ```ts\n * class MyElement extends mixinElementInternals(LitElement) {\n * static {\n * setupFormSubmitter(MyElement);\n * }\n *\n * static formAssociated = true;\n *\n * type: FormSubmitterType = 'submit';\n * }\n * ```\n *\n * @param ctor The form submitter element's constructor.\n */\nexport function setupFormSubmitter(ctor: FormSubmitterConstructor) {\n if (isServer) {\n return;\n }\n\n (ctor as unknown as typeof ReactiveElement).addInitializer((instance) => {\n const submitter = instance as FormSubmitter;\n submitter.addEventListener('click', async (event) => {\n const {type, [internals]: elementInternals} = submitter;\n const {form} = elementInternals;\n if (!form || type === 'button') {\n return;\n }\n\n // Wait a full task for event bubbling to complete.\n await new Promise<void>((resolve) => {\n setTimeout(resolve);\n });\n\n if (event.defaultPrevented) {\n return;\n }\n\n if (type === 'reset') {\n form.reset();\n return;\n }\n\n // form.requestSubmit(submitter) does not work with form associated custom\n // elements. This patches the dispatched submit event to add the correct\n // `submitter`.\n // See https://github.com/WICG/webcomponents/issues/814\n form.addEventListener(\n 'submit',\n (submitEvent) => {\n Object.defineProperty(submitEvent, 'submitter', {\n configurable: true,\n enumerable: true,\n get: () => submitter,\n });\n },\n {capture: true, once: true},\n );\n\n elementInternals.setFormValue(submitter.value);\n form.requestSubmit();\n });\n });\n}\n"]}
|
|
@@ -13,7 +13,7 @@ import { Validator } from './validators/validator.js';
|
|
|
13
13
|
*
|
|
14
14
|
* https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation
|
|
15
15
|
*/
|
|
16
|
-
export interface ConstraintValidation {
|
|
16
|
+
export interface ConstraintValidation extends FormAssociated {
|
|
17
17
|
/**
|
|
18
18
|
* Returns a ValidityState object that represents the validity states of the
|
|
19
19
|
* element.
|
|
@@ -99,7 +99,7 @@ export declare const createValidator: unique symbol;
|
|
|
99
99
|
*/
|
|
100
100
|
export declare const getValidityAnchor: unique symbol;
|
|
101
101
|
/**
|
|
102
|
-
*
|
|
102
|
+
* Mixes in constraint validation APIs for an element.
|
|
103
103
|
*
|
|
104
104
|
* See https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation
|
|
105
105
|
* for more details.
|
|
@@ -20,7 +20,7 @@ const privateValidator = Symbol('privateValidator');
|
|
|
20
20
|
const privateSyncValidity = Symbol('privateSyncValidity');
|
|
21
21
|
const privateCustomValidationMessage = Symbol('privateCustomValidationMessage');
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Mixes in constraint validation APIs for an element.
|
|
24
24
|
*
|
|
25
25
|
* See https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation
|
|
26
26
|
* for more details.
|
|
@@ -90,6 +90,23 @@ export function mixinConstraintValidation(base) {
|
|
|
90
90
|
super.requestUpdate(name, oldValue, options);
|
|
91
91
|
this[privateSyncValidity]();
|
|
92
92
|
}
|
|
93
|
+
firstUpdated(changed) {
|
|
94
|
+
super.firstUpdated(changed);
|
|
95
|
+
// Sync the validity again when the element first renders, since the
|
|
96
|
+
// validity anchor is now available.
|
|
97
|
+
//
|
|
98
|
+
// Elements that `delegatesFocus: true` to an `<input>` will throw an
|
|
99
|
+
// error in Chrome and Safari when a form tries to submit or call
|
|
100
|
+
// `form.reportValidity()`:
|
|
101
|
+
// "An invalid form control with name='' is not focusable"
|
|
102
|
+
//
|
|
103
|
+
// The validity anchor MUST be provided in `internals.setValidity()` and
|
|
104
|
+
// MUST be the `<input>` element rendered.
|
|
105
|
+
//
|
|
106
|
+
// See https://lit.dev/playground/#gist=6c26e418e0010f7a5aac15005cde8bde
|
|
107
|
+
// for a reproduction.
|
|
108
|
+
this[privateSyncValidity]();
|
|
109
|
+
}
|
|
93
110
|
[(_a = privateCustomValidationMessage, privateSyncValidity)]() {
|
|
94
111
|
if (isServer) {
|
|
95
112
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constraint-validation.js","sourceRoot":"","sources":["constraint-validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,QAAQ,EAAkC,MAAM,KAAK,CAAC;AAE9D,OAAO,EAAC,SAAS,EAAuB,MAAM,wBAAwB,CAAC;AA6FvE;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAEzD;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAE7D,uDAAuD;AACvD,MAAM,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AACpD,MAAM,mBAAmB,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAC1D,MAAM,8BAA8B,GAAG,MAAM,CAAC,gCAAgC,CAAC,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,yBAAyB,CAEvC,IAAO;;IACP,MAAe,2BACb,SAAQ,IAAI;QADd;;YAwBE;;;eAGG;YACH,QAAgC,GAAG,EAAE,CAAC;QAwDxC,CAAC;QAhFC,IAAI,QAAQ;YACV,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC;QAClC,CAAC;QAED,IAAI,iBAAiB;YACnB,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC;QAC3C,CAAC;QAED,IAAI,YAAY;YACd,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC;QACtC,CAAC;QAaD,aAAa;YACX,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC;QACzC,CAAC;QAED,cAAc;YACZ,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,CAAC;QAC1C,CAAC;QAED,iBAAiB,CAAC,KAAa;YAC7B,IAAI,CAAC,8BAA8B,CAAC,GAAG,KAAK,CAAC;YAC7C,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC9B,CAAC;QAEQ,aAAa,CACpB,IAAkB,EAClB,QAAkB,EAClB,OAA6B;YAE7B,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC7C,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC9B,CAAC;QAED,OA1BC,8BAA8B,EA0B9B,mBAAmB,EAAC;YACnB,IAAI,QAAQ,EAAE;gBACZ,OAAO;aACR;YAED,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE;gBAC3B,IAAI,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;aAClD;YAED,MAAM,EAAC,QAAQ,EAAE,iBAAiB,EAAE,0BAA0B,EAAC,GAC7D,IAAI,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;YAEvC,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;YAC3D,MAAM,iBAAiB,GACrB,IAAI,CAAC,8BAA8B,CAAC,IAAI,0BAA0B,CAAC;YAErE,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,CACzB,EAAC,GAAG,QAAQ,EAAE,WAAW,EAAC,EAC1B,iBAAiB,EACjB,IAAI,CAAC,iBAAiB,CAAC,EAAE,IAAI,SAAS,CACvC,CAAC;QACJ,CAAC;QAED,CAAC,eAAe,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,CAAC,iBAAiB,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;KACF;IAED,OAAO,2BAA2B,CAAC;AACrC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {isServer, LitElement, PropertyDeclaration} from 'lit';\n\nimport {internals, WithElementInternals} from './element-internals.js';\nimport {FormAssociated} from './form-associated.js';\nimport {MixinBase, MixinReturn} from './mixin.js';\nimport {Validator} from './validators/validator.js';\n\n/**\n * A form associated element that provides constraint validation APIs.\n *\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation\n */\nexport interface ConstraintValidation {\n /**\n * Returns a ValidityState object that represents the validity states of the\n * element.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ValidityState\n */\n readonly validity: ValidityState;\n\n /**\n * Returns a validation error message or an empty string if the element is\n * valid.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/validationMessage\n */\n readonly validationMessage: string;\n\n /**\n * Returns whether an element will successfully validate based on forms\n * validation rules and constraints.\n *\n * Disabled and readonly elements will not validate.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/willValidate\n */\n readonly willValidate: boolean;\n\n /**\n * Checks the element's constraint validation and returns true if the element\n * is valid or false if not.\n *\n * If invalid, this method will dispatch an `invalid` event.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/checkValidity\n *\n * @return true if the element is valid, or false if not.\n */\n checkValidity(): boolean;\n\n /**\n * Checks the element's constraint validation and returns true if the element\n * is valid or false if not.\n *\n * If invalid, this method will dispatch a cancelable `invalid` event. If not\n * canceled, a the current `validationMessage` will be reported to the user.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/reportValidity\n *\n * @return true if the element is valid, or false if not.\n */\n reportValidity(): boolean;\n\n /**\n * Sets the element's constraint validation error message. When set to a\n * non-empty string, `validity.customError` will be true and\n * `validationMessage` will display the provided error.\n *\n * Use this method to customize error messages reported.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setCustomValidity\n *\n * @param error The error message to display, or an empty string.\n */\n setCustomValidity(error: string): void;\n\n /**\n * Creates and returns a `Validator` that is used to compute and cache\n * validity for the element.\n *\n * A validator that caches validity is important since constraint validation\n * must be computed synchronously and frequently in response to constraint\n * validation property changes.\n */\n [createValidator](): Validator<unknown>;\n\n /**\n * Returns shadow DOM child that is used as the anchor for the platform\n * `reportValidity()` popup. This is often the root element or the inner\n * focus-delegated element.\n */\n [getValidityAnchor](): HTMLElement | null;\n}\n\n/**\n * A symbol property used to create a constraint validation `Validator`.\n * Required for all `mixinConstraintValidation()` elements.\n */\nexport const createValidator = Symbol('createValidator');\n\n/**\n * A symbol property used to return an anchor for constraint validation popups.\n * Required for all `mixinConstraintValidation()` elements.\n */\nexport const getValidityAnchor = Symbol('getValidityAnchor');\n\n// Private symbol members, used to avoid name clashing.\nconst privateValidator = Symbol('privateValidator');\nconst privateSyncValidity = Symbol('privateSyncValidity');\nconst privateCustomValidationMessage = Symbol('privateCustomValidationMessage');\n\n/**\n * Mixins in constraint validation APIs for an element.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation\n * for more details.\n *\n * Implementations must provide a validator to cache and compute its validity,\n * along with a shadow root element to anchor validation popups to.\n *\n * @example\n * ```ts\n * const baseClass = mixinConstraintValidation(\n * mixinFormAssociated(mixinElementInternals(LitElement))\n * );\n *\n * class MyCheckbox extends baseClass {\n * \\@property({type: Boolean}) checked = false;\n * \\@property({type: Boolean}) required = false;\n *\n * [createValidator]() {\n * return new CheckboxValidator(() => this);\n * }\n *\n * [getValidityAnchor]() {\n * return this.renderRoot.querySelector('.root');\n * }\n * }\n * ```\n *\n * @param base The class to mix functionality into.\n * @return The provided class with `ConstraintValidation` mixed in.\n */\nexport function mixinConstraintValidation<\n T extends MixinBase<LitElement & FormAssociated & WithElementInternals>,\n>(base: T): MixinReturn<T, ConstraintValidation> {\n abstract class ConstraintValidationElement\n extends base\n implements ConstraintValidation\n {\n get validity() {\n this[privateSyncValidity]();\n return this[internals].validity;\n }\n\n get validationMessage() {\n this[privateSyncValidity]();\n return this[internals].validationMessage;\n }\n\n get willValidate() {\n this[privateSyncValidity]();\n return this[internals].willValidate;\n }\n\n /**\n * A validator instance created from `[createValidator]()`.\n */\n [privateValidator]?: Validator<unknown>;\n\n /**\n * Needed for Safari, see https://bugs.webkit.org/show_bug.cgi?id=261432\n * Replace with this[internals].validity.customError when resolved.\n */\n [privateCustomValidationMessage] = '';\n\n checkValidity() {\n this[privateSyncValidity]();\n return this[internals].checkValidity();\n }\n\n reportValidity() {\n this[privateSyncValidity]();\n return this[internals].reportValidity();\n }\n\n setCustomValidity(error: string) {\n this[privateCustomValidationMessage] = error;\n this[privateSyncValidity]();\n }\n\n override requestUpdate(\n name?: PropertyKey,\n oldValue?: unknown,\n options?: PropertyDeclaration,\n ) {\n super.requestUpdate(name, oldValue, options);\n this[privateSyncValidity]();\n }\n\n [privateSyncValidity]() {\n if (isServer) {\n return;\n }\n\n if (!this[privateValidator]) {\n this[privateValidator] = this[createValidator]();\n }\n\n const {validity, validationMessage: nonCustomValidationMessage} =\n this[privateValidator].getValidity();\n\n const customError = !!this[privateCustomValidationMessage];\n const validationMessage =\n this[privateCustomValidationMessage] || nonCustomValidationMessage;\n\n this[internals].setValidity(\n {...validity, customError},\n validationMessage,\n this[getValidityAnchor]() ?? undefined,\n );\n }\n\n [createValidator](): Validator<unknown> {\n throw new Error('Implement [createValidator]');\n }\n\n [getValidityAnchor](): HTMLElement | null {\n throw new Error('Implement [getValidityAnchor]');\n }\n }\n\n return ConstraintValidationElement;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"constraint-validation.js","sourceRoot":"","sources":["constraint-validation.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 {isServer, LitElement, PropertyDeclaration, PropertyValues} from 'lit';\n\nimport {internals, WithElementInternals} from './element-internals.js';\nimport {FormAssociated} from './form-associated.js';\nimport {MixinBase, MixinReturn} from './mixin.js';\nimport {Validator} from './validators/validator.js';\n\n/**\n * A form associated element that provides constraint validation APIs.\n *\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation\n */\nexport interface ConstraintValidation extends FormAssociated {\n /**\n * Returns a ValidityState object that represents the validity states of the\n * element.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ValidityState\n */\n readonly validity: ValidityState;\n\n /**\n * Returns a validation error message or an empty string if the element is\n * valid.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/validationMessage\n */\n readonly validationMessage: string;\n\n /**\n * Returns whether an element will successfully validate based on forms\n * validation rules and constraints.\n *\n * Disabled and readonly elements will not validate.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/willValidate\n */\n readonly willValidate: boolean;\n\n /**\n * Checks the element's constraint validation and returns true if the element\n * is valid or false if not.\n *\n * If invalid, this method will dispatch an `invalid` event.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/checkValidity\n *\n * @return true if the element is valid, or false if not.\n */\n checkValidity(): boolean;\n\n /**\n * Checks the element's constraint validation and returns true if the element\n * is valid or false if not.\n *\n * If invalid, this method will dispatch a cancelable `invalid` event. If not\n * canceled, a the current `validationMessage` will be reported to the user.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/reportValidity\n *\n * @return true if the element is valid, or false if not.\n */\n reportValidity(): boolean;\n\n /**\n * Sets the element's constraint validation error message. When set to a\n * non-empty string, `validity.customError` will be true and\n * `validationMessage` will display the provided error.\n *\n * Use this method to customize error messages reported.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setCustomValidity\n *\n * @param error The error message to display, or an empty string.\n */\n setCustomValidity(error: string): void;\n\n /**\n * Creates and returns a `Validator` that is used to compute and cache\n * validity for the element.\n *\n * A validator that caches validity is important since constraint validation\n * must be computed synchronously and frequently in response to constraint\n * validation property changes.\n */\n [createValidator](): Validator<unknown>;\n\n /**\n * Returns shadow DOM child that is used as the anchor for the platform\n * `reportValidity()` popup. This is often the root element or the inner\n * focus-delegated element.\n */\n [getValidityAnchor](): HTMLElement | null;\n}\n\n/**\n * A symbol property used to create a constraint validation `Validator`.\n * Required for all `mixinConstraintValidation()` elements.\n */\nexport const createValidator = Symbol('createValidator');\n\n/**\n * A symbol property used to return an anchor for constraint validation popups.\n * Required for all `mixinConstraintValidation()` elements.\n */\nexport const getValidityAnchor = Symbol('getValidityAnchor');\n\n// Private symbol members, used to avoid name clashing.\nconst privateValidator = Symbol('privateValidator');\nconst privateSyncValidity = Symbol('privateSyncValidity');\nconst privateCustomValidationMessage = Symbol('privateCustomValidationMessage');\n\n/**\n * Mixes in constraint validation APIs for an element.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation\n * for more details.\n *\n * Implementations must provide a validator to cache and compute its validity,\n * along with a shadow root element to anchor validation popups to.\n *\n * @example\n * ```ts\n * const baseClass = mixinConstraintValidation(\n * mixinFormAssociated(mixinElementInternals(LitElement))\n * );\n *\n * class MyCheckbox extends baseClass {\n * \\@property({type: Boolean}) checked = false;\n * \\@property({type: Boolean}) required = false;\n *\n * [createValidator]() {\n * return new CheckboxValidator(() => this);\n * }\n *\n * [getValidityAnchor]() {\n * return this.renderRoot.querySelector('.root');\n * }\n * }\n * ```\n *\n * @param base The class to mix functionality into.\n * @return The provided class with `ConstraintValidation` mixed in.\n */\nexport function mixinConstraintValidation<\n T extends MixinBase<LitElement & FormAssociated & WithElementInternals>,\n>(base: T): MixinReturn<T, ConstraintValidation> {\n abstract class ConstraintValidationElement\n extends base\n implements ConstraintValidation\n {\n get validity() {\n this[privateSyncValidity]();\n return this[internals].validity;\n }\n\n get validationMessage() {\n this[privateSyncValidity]();\n return this[internals].validationMessage;\n }\n\n get willValidate() {\n this[privateSyncValidity]();\n return this[internals].willValidate;\n }\n\n /**\n * A validator instance created from `[createValidator]()`.\n */\n [privateValidator]?: Validator<unknown>;\n\n /**\n * Needed for Safari, see https://bugs.webkit.org/show_bug.cgi?id=261432\n * Replace with this[internals].validity.customError when resolved.\n */\n [privateCustomValidationMessage] = '';\n\n checkValidity() {\n this[privateSyncValidity]();\n return this[internals].checkValidity();\n }\n\n reportValidity() {\n this[privateSyncValidity]();\n return this[internals].reportValidity();\n }\n\n setCustomValidity(error: string) {\n this[privateCustomValidationMessage] = error;\n this[privateSyncValidity]();\n }\n\n override requestUpdate(\n name?: PropertyKey,\n oldValue?: unknown,\n options?: PropertyDeclaration,\n ) {\n super.requestUpdate(name, oldValue, options);\n this[privateSyncValidity]();\n }\n\n override firstUpdated(changed: PropertyValues) {\n super.firstUpdated(changed);\n // Sync the validity again when the element first renders, since the\n // validity anchor is now available.\n //\n // Elements that `delegatesFocus: true` to an `<input>` will throw an\n // error in Chrome and Safari when a form tries to submit or call\n // `form.reportValidity()`:\n // \"An invalid form control with name='' is not focusable\"\n //\n // The validity anchor MUST be provided in `internals.setValidity()` and\n // MUST be the `<input>` element rendered.\n //\n // See https://lit.dev/playground/#gist=6c26e418e0010f7a5aac15005cde8bde\n // for a reproduction.\n this[privateSyncValidity]();\n }\n\n [privateSyncValidity]() {\n if (isServer) {\n return;\n }\n\n if (!this[privateValidator]) {\n this[privateValidator] = this[createValidator]();\n }\n\n const {validity, validationMessage: nonCustomValidationMessage} =\n this[privateValidator].getValidity();\n\n const customError = !!this[privateCustomValidationMessage];\n const validationMessage =\n this[privateCustomValidationMessage] || nonCustomValidationMessage;\n\n this[internals].setValidity(\n {...validity, customError},\n validationMessage,\n this[getValidityAnchor]() ?? undefined,\n );\n }\n\n [createValidator](): Validator<unknown> {\n throw new Error('Implement [createValidator]');\n }\n\n [getValidityAnchor](): HTMLElement | null {\n throw new Error('Implement [getValidityAnchor]');\n }\n }\n\n return ConstraintValidationElement;\n}\n"]}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Copyright 2023 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { polyfillARIAMixin, polyfillElementInternalsAria, } from '../../internal/aria/aria.js';
|
|
7
6
|
/**
|
|
8
7
|
* A unique symbol used for protected access to an instance's
|
|
9
8
|
* `ElementInternals`.
|
|
@@ -37,14 +36,11 @@ export function mixinElementInternals(base) {
|
|
|
37
36
|
// construction in `ReactiveElement`, such as `requestUpdate()`.
|
|
38
37
|
if (!this[privateInternals]) {
|
|
39
38
|
// Cast needed for closure
|
|
40
|
-
this[privateInternals] =
|
|
39
|
+
this[privateInternals] = this.attachInternals();
|
|
41
40
|
}
|
|
42
41
|
return this[privateInternals];
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
|
-
(() => {
|
|
46
|
-
polyfillARIAMixin(WithElementInternalsElement);
|
|
47
|
-
})();
|
|
48
44
|
return WithElementInternalsElement;
|
|
49
45
|
}
|
|
50
46
|
//# sourceMappingURL=element-internals.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-internals.js","sourceRoot":"","sources":["element-internals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"element-internals.js","sourceRoot":"","sources":["element-internals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAgB7C,kBAAkB;AAClB,MAAM,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAO;IAEP,MAAe,2BACb,SAAQ,IAAI;QAGZ,IAAI,CAAC,SAAS,CAAC;YACb,yEAAyE;YACzE,gEAAgE;YAChE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE;gBAC3B,0BAA0B;gBAC1B,IAAI,CAAC,gBAAgB,CAAC,GAAI,IAAoB,CAAC,eAAe,EAAE,CAAC;aAClE;YAED,OAAO,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAChC,CAAC;KAGF;IAED,OAAO,2BAA2B,CAAC;AACrC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {LitElement} from 'lit';\n\nimport {MixinBase, MixinReturn} from './mixin.js';\n\n/**\n * A unique symbol used for protected access to an instance's\n * `ElementInternals`.\n *\n * @example\n * ```ts\n * class MyElement extends mixinElementInternals(LitElement) {\n * constructor() {\n * super();\n * this[internals].role = 'button';\n * }\n * }\n * ```\n */\nexport const internals = Symbol('internals');\n\n/**\n * An instance with an `internals` symbol property for the component's\n * `ElementInternals`.\n *\n * Use this when protected access is needed for an instance's `ElementInternals`\n * from other files. A unique symbol is used to access the internals.\n */\nexport interface WithElementInternals {\n /**\n * An instance's `ElementInternals`.\n */\n [internals]: ElementInternals;\n}\n\n// Private symbols\nconst privateInternals = Symbol('privateInternals');\n\n/**\n * Mixes in an attached `ElementInternals` instance.\n *\n * This mixin is only needed when other shared code needs access to a\n * component's `ElementInternals`, such as form-associated mixins.\n *\n * @param base The class to mix functionality into.\n * @return The provided class with `WithElementInternals` mixed in.\n */\nexport function mixinElementInternals<T extends MixinBase<LitElement>>(\n base: T,\n): MixinReturn<T, WithElementInternals> {\n abstract class WithElementInternalsElement\n extends base\n implements WithElementInternals\n {\n get [internals]() {\n // Create internals in getter so that it can be used in methods called on\n // construction in `ReactiveElement`, such as `requestUpdate()`.\n if (!this[privateInternals]) {\n // Cast needed for closure\n this[privateInternals] = (this as HTMLElement).attachInternals();\n }\n\n return this[privateInternals];\n }\n\n [privateInternals]?: ElementInternals;\n }\n\n return WithElementInternalsElement;\n}\n"]}
|
|
@@ -14,6 +14,7 @@ const privateIsFocusable = Symbol('privateIsFocusable');
|
|
|
14
14
|
const externalTabIndex = Symbol('externalTabIndex');
|
|
15
15
|
const isUpdatingTabIndex = Symbol('isUpdatingTabIndex');
|
|
16
16
|
const updateTabIndex = Symbol('updateTabIndex');
|
|
17
|
+
const hasConstructed = Symbol('hasConstructed');
|
|
17
18
|
/**
|
|
18
19
|
* Mixes in focusable functionality for a class.
|
|
19
20
|
*
|
|
@@ -31,7 +32,7 @@ const updateTabIndex = Symbol('updateTabIndex');
|
|
|
31
32
|
* @return The provided class with `Focusable` mixed in.
|
|
32
33
|
*/
|
|
33
34
|
export function mixinFocusable(base) {
|
|
34
|
-
var _a, _b, _c;
|
|
35
|
+
var _a, _b, _c, _d;
|
|
35
36
|
class FocusableElement extends base {
|
|
36
37
|
get [isFocusable]() {
|
|
37
38
|
return this[privateIsFocusable];
|
|
@@ -49,11 +50,21 @@ export function mixinFocusable(base) {
|
|
|
49
50
|
this[_a] = false;
|
|
50
51
|
this[_b] = null;
|
|
51
52
|
this[_c] = false;
|
|
53
|
+
this[_d] = false;
|
|
52
54
|
this[isFocusable] = true;
|
|
55
|
+
queueMicrotask(() => {
|
|
56
|
+
this[hasConstructed] = true;
|
|
57
|
+
this[updateTabIndex]();
|
|
58
|
+
});
|
|
53
59
|
}
|
|
54
60
|
attributeChangedCallback(name, old, value) {
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
if (name !== 'tabindex') {
|
|
62
|
+
super.attributeChangedCallback(name, old, value);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
this.requestUpdate('tabIndex', Number(old ?? -1));
|
|
66
|
+
if (this[isUpdatingTabIndex]) {
|
|
67
|
+
// Not an externally-initiated update.
|
|
57
68
|
return;
|
|
58
69
|
}
|
|
59
70
|
if (!this.hasAttribute('tabindex')) {
|
|
@@ -64,18 +75,20 @@ export function mixinFocusable(base) {
|
|
|
64
75
|
}
|
|
65
76
|
this[externalTabIndex] = this.tabIndex;
|
|
66
77
|
}
|
|
67
|
-
|
|
78
|
+
[(_a = privateIsFocusable, _b = externalTabIndex, _c = isUpdatingTabIndex, _d = hasConstructed, updateTabIndex)]() {
|
|
79
|
+
if (!this[hasConstructed]) {
|
|
80
|
+
// Custom elements may not hydrate attributes during construction.
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
68
83
|
const internalTabIndex = this[isFocusable] ? 0 : -1;
|
|
69
84
|
const computedTabIndex = this[externalTabIndex] ?? internalTabIndex;
|
|
70
85
|
this[isUpdatingTabIndex] = true;
|
|
71
86
|
this.tabIndex = computedTabIndex;
|
|
72
|
-
this.requestUpdate();
|
|
73
|
-
await this.updateComplete;
|
|
74
87
|
this[isUpdatingTabIndex] = false;
|
|
75
88
|
}
|
|
76
89
|
}
|
|
77
90
|
__decorate([
|
|
78
|
-
property({
|
|
91
|
+
property({ noAccessor: true })
|
|
79
92
|
], FocusableElement.prototype, "tabIndex", void 0);
|
|
80
93
|
return FocusableElement;
|
|
81
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focusable.js","sourceRoot":"","sources":["focusable.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AAGH,OAAO,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAe3C;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AAEjD,MAAM,kBAAkB,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AACxD,MAAM,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AACpD,MAAM,kBAAkB,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AACxD,MAAM,cAAc,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAO;;IAEP,MAAe,gBAAiB,SAAQ,IAAI;
|
|
1
|
+
{"version":3,"file":"focusable.js","sourceRoot":"","sources":["focusable.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} from 'lit';\nimport {property} from 'lit/decorators.js';\n\nimport {MixinBase, MixinReturn} from './mixin.js';\n\n/**\n * An element that can enable and disable `tabindex` focusability.\n */\nexport interface Focusable {\n /**\n * Whether or not the element can be focused. Defaults to true. Set to false\n * to disable focusing (unless a user has set a `tabindex`).\n */\n [isFocusable]: boolean;\n}\n\n/**\n * A property symbol that indicates whether or not a `Focusable` element can be\n * focused.\n */\nexport const isFocusable = Symbol('isFocusable');\n\nconst privateIsFocusable = Symbol('privateIsFocusable');\nconst externalTabIndex = Symbol('externalTabIndex');\nconst isUpdatingTabIndex = Symbol('isUpdatingTabIndex');\nconst updateTabIndex = Symbol('updateTabIndex');\nconst hasConstructed = Symbol('hasConstructed');\n\n/**\n * Mixes in focusable functionality for a class.\n *\n * Elements can enable and disable their focusability with the `isFocusable`\n * symbol property. Changing `tabIndex` will trigger a lit render, meaning\n * `this.tabIndex` can be used in template expressions.\n *\n * This mixin will preserve externally-set tabindices. If an element turns off\n * focusability, but a user sets `tabindex=\"0\"`, it will still be focusable.\n *\n * To remove user overrides and restore focusability control to the element,\n * remove the `tabindex` attribute.\n *\n * @param base The class to mix functionality into.\n * @return The provided class with `Focusable` mixed in.\n */\nexport function mixinFocusable<T extends MixinBase<LitElement>>(\n base: T,\n): MixinReturn<T, Focusable> {\n abstract class FocusableElement extends base implements Focusable {\n @property({noAccessor: true})\n declare tabIndex: number;\n\n get [isFocusable]() {\n return this[privateIsFocusable];\n }\n\n set [isFocusable](value: boolean) {\n if (this[isFocusable] === value) {\n return;\n }\n\n this[privateIsFocusable] = value;\n this[updateTabIndex]();\n }\n\n [privateIsFocusable] = false;\n [externalTabIndex]: number | null = null;\n [isUpdatingTabIndex] = false;\n [hasConstructed] = false;\n\n // tslint:disable-next-line:no-any\n constructor(...args: any[]) {\n super(...args);\n this[isFocusable] = true;\n queueMicrotask(() => {\n this[hasConstructed] = true;\n this[updateTabIndex]();\n });\n }\n\n override attributeChangedCallback(\n name: string,\n old: string | null,\n value: string | null,\n ) {\n if (name !== 'tabindex') {\n super.attributeChangedCallback(name, old, value);\n return;\n }\n\n this.requestUpdate('tabIndex', Number(old ?? -1));\n if (this[isUpdatingTabIndex]) {\n // Not an externally-initiated update.\n return;\n }\n\n if (!this.hasAttribute('tabindex')) {\n // User removed the attribute, can now use internal tabIndex\n this[externalTabIndex] = null;\n this[updateTabIndex]();\n return;\n }\n\n this[externalTabIndex] = this.tabIndex;\n }\n\n [updateTabIndex]() {\n if (!this[hasConstructed]) {\n // Custom elements may not hydrate attributes during construction.\n return;\n }\n\n const internalTabIndex = this[isFocusable] ? 0 : -1;\n const computedTabIndex = this[externalTabIndex] ?? internalTabIndex;\n\n this[isUpdatingTabIndex] = true;\n this.tabIndex = computedTabIndex;\n this[isUpdatingTabIndex] = false;\n }\n }\n\n return FocusableElement;\n}\n"]}
|
|
@@ -100,26 +100,46 @@ export function mixinFormAssociated(base) {
|
|
|
100
100
|
get labels() {
|
|
101
101
|
return this[internals].labels;
|
|
102
102
|
}
|
|
103
|
-
// name
|
|
103
|
+
// Use @property for the `name` and `disabled` properties to add them to the
|
|
104
|
+
// `observedAttributes` array and trigger `attributeChangedCallback()`.
|
|
105
|
+
//
|
|
106
|
+
// We don't use Lit's default getter/setter (`noAccessor: true`) because
|
|
107
|
+
// the attributes need to be updated synchronously to work with synchronous
|
|
108
|
+
// form APIs, and Lit updates attributes async by default.
|
|
104
109
|
get name() {
|
|
105
110
|
return this.getAttribute('name') ?? '';
|
|
106
111
|
}
|
|
107
112
|
set name(name) {
|
|
108
|
-
|
|
109
|
-
// Setting name to null or empty string does not remove the attribute.
|
|
113
|
+
// Note: setting name to null or empty does not remove the attribute.
|
|
110
114
|
this.setAttribute('name', name);
|
|
111
|
-
//
|
|
112
|
-
|
|
115
|
+
// We don't need to call `requestUpdate()` since it's called synchronously
|
|
116
|
+
// in `attributeChangedCallback()`.
|
|
113
117
|
}
|
|
114
|
-
// disabled attribute must be set synchronously
|
|
115
118
|
get disabled() {
|
|
116
119
|
return this.hasAttribute('disabled');
|
|
117
120
|
}
|
|
118
121
|
set disabled(disabled) {
|
|
119
|
-
const prev = this.disabled;
|
|
120
122
|
this.toggleAttribute('disabled', disabled);
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
+
// We don't need to call `requestUpdate()` since it's called synchronously
|
|
124
|
+
// in `attributeChangedCallback()`.
|
|
125
|
+
}
|
|
126
|
+
attributeChangedCallback(name, old, value) {
|
|
127
|
+
// Manually `requestUpdate()` for `name` and `disabled` when their
|
|
128
|
+
// attribute or property changes.
|
|
129
|
+
// The properties update their attributes, so this callback is invoked
|
|
130
|
+
// immediately when the properties are set. We call `requestUpdate()` here
|
|
131
|
+
// instead of letting Lit set the properties from the attribute change.
|
|
132
|
+
// That would cause the properties to re-set the attribute and invoke this
|
|
133
|
+
// callback again in a loop. This leads to stale state when Lit tries to
|
|
134
|
+
// determine if a property changed or not.
|
|
135
|
+
if (name === 'name' || name === 'disabled') {
|
|
136
|
+
// Disabled's value is only false if the attribute is missing and null.
|
|
137
|
+
const oldValue = name === 'disabled' ? old !== null : old;
|
|
138
|
+
// Trigger a lit update when the attribute changes.
|
|
139
|
+
this.requestUpdate(name, oldValue);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
super.attributeChangedCallback(name, old, value);
|
|
123
143
|
}
|
|
124
144
|
requestUpdate(name, oldValue, options) {
|
|
125
145
|
super.requestUpdate(name, oldValue, options);
|
|
@@ -145,10 +165,10 @@ export function mixinFormAssociated(base) {
|
|
|
145
165
|
/** @nocollapse */
|
|
146
166
|
FormAssociatedElement.formAssociated = true;
|
|
147
167
|
__decorate([
|
|
148
|
-
property({
|
|
168
|
+
property({ noAccessor: true })
|
|
149
169
|
], FormAssociatedElement.prototype, "name", null);
|
|
150
170
|
__decorate([
|
|
151
|
-
property({ type: Boolean,
|
|
171
|
+
property({ type: Boolean, noAccessor: true })
|
|
152
172
|
], FormAssociatedElement.prototype, "disabled", null);
|
|
153
173
|
return FormAssociatedElement;
|
|
154
174
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-associated.js","sourceRoot":"","sources":["form-associated.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AAGH,OAAO,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAC,SAAS,EAAuB,MAAM,wBAAwB,CAAC;AA0GvE;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,MAAM,UAAU,mBAAmB,CAEjC,IAAO;IACP,MAAe,qBAAsB,SAAQ,IAAI;QAI/C,IAAI,IAAI;YACN,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC;QAC9B,CAAC;QAED,IAAI,MAAM;YACR,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;QAChC,CAAC;QAED,2CAA2C;QAE3C,IAAI,IAAI;YACN,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC;QACD,IAAI,IAAI,CAAC,IAAY;YACnB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACvB,sEAAsE;YACtE,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAChC,4CAA4C;YAC5C,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACnC,CAAC;QAED,+CAA+C;QAE/C,IAAI,QAAQ;YACV,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,QAAQ,CAAC,QAAiB;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC3B,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC3C,4CAA4C;YAC5C,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;QAEQ,aAAa,CACpB,IAAkB,EAClB,QAAkB,EAClB,OAA6B;YAE7B,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC7C,0EAA0E;YAC1E,WAAW;YACX,uEAAuE;YACvE,0EAA0E;YAC1E,qEAAqE;YACrE,IAAI,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,CAAC,YAAY,CAAC;YACZ,+DAA+D;YAC/D,4BAA4B;YAC5B,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QAED,CAAC,YAAY,CAAC;YACZ,OAAO,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,CAAC;QAED,oBAAoB,CAAC,QAAiB;YACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC3B,CAAC;;IA9DD,kBAAkB;IACF,oCAAc,GAAG,IAAI,CAAC;IAYtC;QADC,QAAQ,CAAC,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC;qDAGzB;IAWD;QADC,QAAQ,CAAC,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC;yDAGxC;IA4CH,OAAO,qBAAqB,CAAC;AAC/B,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {LitElement, PropertyDeclaration} from 'lit';\nimport {property} from 'lit/decorators.js';\n\nimport {internals, WithElementInternals} from './element-internals.js';\nimport {MixinBase, MixinReturn} from './mixin.js';\n\n/**\n * A form-associated element.\n *\n * IMPORTANT: Requires declares for lit-analyzer\n * @example\n * ```ts\n * const base = mixinFormAssociated(mixinElementInternals(LitElement));\n * class MyControl extends base {\n * // Writable mixin properties for lit-html binding, needed for lit-analyzer\n * declare disabled: boolean;\n * declare name: string;\n * }\n * ```\n */\nexport interface FormAssociated {\n /**\n * The associated form element with which this element's value will submit.\n */\n readonly form: HTMLFormElement | null;\n\n /**\n * The labels this element is associated with.\n */\n readonly labels: NodeList;\n\n /**\n * The HTML name to use in form submission.\n */\n name: string;\n\n /**\n * Whether or not the element is disabled.\n */\n disabled: boolean;\n\n /**\n * Gets the current form value of a component.\n *\n * @return The current form value.\n */\n [getFormValue](): FormValue | null;\n\n /**\n * Gets the current form state of a component. Defaults to the component's\n * `[formValue]`.\n *\n * Use this when the state of an element is different from its value, such as\n * checkboxes (internal boolean state and a user string value).\n *\n * @return The current form state, defaults to the form value.\n */\n [getFormState](): FormValue | null;\n\n /**\n * A callback for when a form component should be disabled or enabled. This\n * can be called in a variety of situations, such as disabled `<fieldset>`s.\n *\n * @param disabled Whether or not the form control should be disabled.\n */\n formDisabledCallback(disabled: boolean): void;\n\n /**\n * A callback for when the form requests to reset its value. Typically, the\n * default value that is reset is represented in the attribute of an element.\n *\n * This means the attribute used for the value should not update as the value\n * changes. For example, a checkbox should not change its default `checked`\n * attribute when selected. Ensure form values do not reflect.\n */\n formResetCallback(): void;\n\n /**\n * A callback for when the form restores the state of a component. For\n * example, when a page is reloaded or forms are autofilled.\n *\n * @param state The state to restore, or null to reset the form control's\n * value.\n * @param reason The reason state was restored, either `'restore'` or\n * `'autocomplete'`.\n */\n formStateRestoreCallback(\n state: FormRestoreState | null,\n reason: FormRestoreReason,\n ): void;\n\n /**\n * An optional callback for when the associated form changes.\n *\n * @param form The new associated form, or `null` if there is none.\n */\n formAssociatedCallback?(form: HTMLFormElement | null): void;\n}\n\n/**\n * The constructor of a `FormAssociated` element.\n */\nexport interface FormAssociatedConstructor {\n /**\n * Indicates that an element is participating in form association.\n */\n readonly formAssociated: true;\n}\n\n/**\n * A symbol property to retrieve the form value for an element.\n */\nexport const getFormValue = Symbol('getFormValue');\n\n/**\n * A symbol property to retrieve the form state for an element.\n */\nexport const getFormState = Symbol('getFormState');\n\n/**\n * Mixes in form-associated behavior for a class. This allows an element to add\n * values to `<form>` elements.\n *\n * Implementing classes should provide a `[formValue]` to return the current\n * value of the element, as well as reset and restore callbacks.\n *\n * @example\n * ```ts\n * const base = mixinFormAssociated(mixinElementInternals(LitElement));\n *\n * class MyControl extends base {\n * \\@property()\n * value = '';\n *\n * override [getFormValue]() {\n * return this.value;\n * }\n *\n * override formResetCallback() {\n * const defaultValue = this.getAttribute('value');\n * this.value = defaultValue;\n * }\n *\n * override formStateRestoreCallback(state: string) {\n * this.value = state;\n * }\n * }\n * ```\n *\n * Elements may optionally provide a `[formState]` if their values do not\n * represent the state of the component.\n *\n * @example\n * ```ts\n * const base = mixinFormAssociated(mixinElementInternals(LitElement));\n *\n * class MyCheckbox extends base {\n * \\@property()\n * value = 'on';\n *\n * \\@property({type: Boolean})\n * checked = false;\n *\n * override [getFormValue]() {\n * return this.checked ? this.value : null;\n * }\n *\n * override [getFormState]() {\n * return String(this.checked);\n * }\n *\n * override formResetCallback() {\n * const defaultValue = this.hasAttribute('checked');\n * this.checked = defaultValue;\n * }\n *\n * override formStateRestoreCallback(state: string) {\n * this.checked = Boolean(state);\n * }\n * }\n * ```\n *\n * IMPORTANT: Requires declares for lit-analyzer\n * @example\n * ```ts\n * const base = mixinFormAssociated(mixinElementInternals(LitElement));\n * class MyControl extends base {\n * // Writable mixin properties for lit-html binding, needed for lit-analyzer\n * declare disabled: boolean;\n * declare name: string;\n * }\n * ```\n *\n * @param base The class to mix functionality into. The base class must use\n * `mixinElementInternals()`.\n * @return The provided class with `FormAssociated` mixed in.\n */\nexport function mixinFormAssociated<\n T extends MixinBase<LitElement & WithElementInternals>,\n>(base: T): MixinReturn<T & FormAssociatedConstructor, FormAssociated> {\n abstract class FormAssociatedElement extends base implements FormAssociated {\n /** @nocollapse */\n static readonly formAssociated = true;\n\n get form() {\n return this[internals].form;\n }\n\n get labels() {\n return this[internals].labels;\n }\n\n // name attribute must be set synchronously\n @property({reflect: true})\n get name() {\n return this.getAttribute('name') ?? '';\n }\n set name(name: string) {\n const prev = this.name;\n // Setting name to null or empty string does not remove the attribute.\n this.setAttribute('name', name);\n // Explicit requestUpdate needed for Lit 2.0\n this.requestUpdate('name', prev);\n }\n\n // disabled attribute must be set synchronously\n @property({type: Boolean, reflect: true})\n get disabled() {\n return this.hasAttribute('disabled');\n }\n set disabled(disabled: boolean) {\n const prev = this.disabled;\n this.toggleAttribute('disabled', disabled);\n // Explicit requestUpdate needed for Lit 2.0\n this.requestUpdate('disabled', prev);\n }\n\n override requestUpdate(\n name?: PropertyKey,\n oldValue?: unknown,\n options?: PropertyDeclaration,\n ) {\n super.requestUpdate(name, oldValue, options);\n // If any properties change, update the form value, which may have changed\n // as well.\n // Update the form value synchronously in `requestUpdate()` rather than\n // `update()` or `updated()`, which are async. This is necessary to ensure\n // that form data is updated in time for synchronous event listeners.\n this[internals].setFormValue(this[getFormValue](), this[getFormState]());\n }\n\n [getFormValue](): FormValue | null {\n // Closure does not allow abstract symbol members, so a default\n // implementation is needed.\n throw new Error('Implement [getFormValue]');\n }\n\n [getFormState](): FormValue | null {\n return this[getFormValue]();\n }\n\n formDisabledCallback(disabled: boolean) {\n this.disabled = disabled;\n }\n\n abstract formResetCallback(): void;\n\n abstract formStateRestoreCallback(\n state: FormRestoreState | null,\n reason: FormRestoreReason,\n ): void;\n }\n\n return FormAssociatedElement;\n}\n\n/**\n * A value that can be provided for form submission and state.\n */\nexport type FormValue = File | string | FormData;\n\n/**\n * A value to be restored for a component's form value. If a component's form\n * state is a `FormData` object, its entry list of name and values will be\n * provided.\n */\nexport type FormRestoreState =\n | File\n | string\n | Array<[string, FormDataEntryValue]>;\n\n/**\n * The reason a form component is being restored for, either `'restore'` for\n * browser restoration or `'autocomplete'` for restoring user values.\n */\nexport type FormRestoreReason = 'restore' | 'autocomplete';\n"]}
|
|
1
|
+
{"version":3,"file":"form-associated.js","sourceRoot":"","sources":["form-associated.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, PropertyDeclaration} from 'lit';\nimport {property} from 'lit/decorators.js';\n\nimport {internals, WithElementInternals} from './element-internals.js';\nimport {MixinBase, MixinReturn} from './mixin.js';\n\n/**\n * A form-associated element.\n *\n * IMPORTANT: Requires declares for lit-analyzer\n * @example\n * ```ts\n * const base = mixinFormAssociated(mixinElementInternals(LitElement));\n * class MyControl extends base {\n * // Writable mixin properties for lit-html binding, needed for lit-analyzer\n * declare disabled: boolean;\n * declare name: string;\n * }\n * ```\n */\nexport interface FormAssociated {\n /**\n * The associated form element with which this element's value will submit.\n */\n readonly form: HTMLFormElement | null;\n\n /**\n * The labels this element is associated with.\n */\n readonly labels: NodeList;\n\n /**\n * The HTML name to use in form submission.\n */\n name: string;\n\n /**\n * Whether or not the element is disabled.\n */\n disabled: boolean;\n\n /**\n * Gets the current form value of a component.\n *\n * @return The current form value.\n */\n [getFormValue](): FormValue | null;\n\n /**\n * Gets the current form state of a component. Defaults to the component's\n * `[formValue]`.\n *\n * Use this when the state of an element is different from its value, such as\n * checkboxes (internal boolean state and a user string value).\n *\n * @return The current form state, defaults to the form value.\n */\n [getFormState](): FormValue | null;\n\n /**\n * A callback for when a form component should be disabled or enabled. This\n * can be called in a variety of situations, such as disabled `<fieldset>`s.\n *\n * @param disabled Whether or not the form control should be disabled.\n */\n formDisabledCallback(disabled: boolean): void;\n\n /**\n * A callback for when the form requests to reset its value. Typically, the\n * default value that is reset is represented in the attribute of an element.\n *\n * This means the attribute used for the value should not update as the value\n * changes. For example, a checkbox should not change its default `checked`\n * attribute when selected. Ensure form values do not reflect.\n */\n formResetCallback(): void;\n\n /**\n * A callback for when the form restores the state of a component. For\n * example, when a page is reloaded or forms are autofilled.\n *\n * @param state The state to restore, or null to reset the form control's\n * value.\n * @param reason The reason state was restored, either `'restore'` or\n * `'autocomplete'`.\n */\n formStateRestoreCallback(\n state: FormRestoreState | null,\n reason: FormRestoreReason,\n ): void;\n\n /**\n * An optional callback for when the associated form changes.\n *\n * @param form The new associated form, or `null` if there is none.\n */\n formAssociatedCallback?(form: HTMLFormElement | null): void;\n}\n\n/**\n * The constructor of a `FormAssociated` element.\n */\nexport interface FormAssociatedConstructor {\n /**\n * Indicates that an element is participating in form association.\n */\n readonly formAssociated: true;\n}\n\n/**\n * A symbol property to retrieve the form value for an element.\n */\nexport const getFormValue = Symbol('getFormValue');\n\n/**\n * A symbol property to retrieve the form state for an element.\n */\nexport const getFormState = Symbol('getFormState');\n\n/**\n * Mixes in form-associated behavior for a class. This allows an element to add\n * values to `<form>` elements.\n *\n * Implementing classes should provide a `[formValue]` to return the current\n * value of the element, as well as reset and restore callbacks.\n *\n * @example\n * ```ts\n * const base = mixinFormAssociated(mixinElementInternals(LitElement));\n *\n * class MyControl extends base {\n * \\@property()\n * value = '';\n *\n * override [getFormValue]() {\n * return this.value;\n * }\n *\n * override formResetCallback() {\n * const defaultValue = this.getAttribute('value');\n * this.value = defaultValue;\n * }\n *\n * override formStateRestoreCallback(state: string) {\n * this.value = state;\n * }\n * }\n * ```\n *\n * Elements may optionally provide a `[formState]` if their values do not\n * represent the state of the component.\n *\n * @example\n * ```ts\n * const base = mixinFormAssociated(mixinElementInternals(LitElement));\n *\n * class MyCheckbox extends base {\n * \\@property()\n * value = 'on';\n *\n * \\@property({type: Boolean})\n * checked = false;\n *\n * override [getFormValue]() {\n * return this.checked ? this.value : null;\n * }\n *\n * override [getFormState]() {\n * return String(this.checked);\n * }\n *\n * override formResetCallback() {\n * const defaultValue = this.hasAttribute('checked');\n * this.checked = defaultValue;\n * }\n *\n * override formStateRestoreCallback(state: string) {\n * this.checked = Boolean(state);\n * }\n * }\n * ```\n *\n * IMPORTANT: Requires declares for lit-analyzer\n * @example\n * ```ts\n * const base = mixinFormAssociated(mixinElementInternals(LitElement));\n * class MyControl extends base {\n * // Writable mixin properties for lit-html binding, needed for lit-analyzer\n * declare disabled: boolean;\n * declare name: string;\n * }\n * ```\n *\n * @param base The class to mix functionality into. The base class must use\n * `mixinElementInternals()`.\n * @return The provided class with `FormAssociated` mixed in.\n */\nexport function mixinFormAssociated<\n T extends MixinBase<LitElement & WithElementInternals>,\n>(base: T): MixinReturn<T & FormAssociatedConstructor, FormAssociated> {\n abstract class FormAssociatedElement extends base implements FormAssociated {\n /** @nocollapse */\n static readonly formAssociated = true;\n\n get form() {\n return this[internals].form;\n }\n\n get labels() {\n return this[internals].labels;\n }\n\n // Use @property for the `name` and `disabled` properties to add them to the\n // `observedAttributes` array and trigger `attributeChangedCallback()`.\n //\n // We don't use Lit's default getter/setter (`noAccessor: true`) because\n // the attributes need to be updated synchronously to work with synchronous\n // form APIs, and Lit updates attributes async by default.\n @property({noAccessor: true})\n get name() {\n return this.getAttribute('name') ?? '';\n }\n set name(name: string) {\n // Note: setting name to null or empty does not remove the attribute.\n this.setAttribute('name', name);\n // We don't need to call `requestUpdate()` since it's called synchronously\n // in `attributeChangedCallback()`.\n }\n\n @property({type: Boolean, noAccessor: true})\n get disabled() {\n return this.hasAttribute('disabled');\n }\n set disabled(disabled: boolean) {\n this.toggleAttribute('disabled', disabled);\n // We don't need to call `requestUpdate()` since it's called synchronously\n // in `attributeChangedCallback()`.\n }\n\n override attributeChangedCallback(\n name: string,\n old: string | null,\n value: string | null,\n ) {\n // Manually `requestUpdate()` for `name` and `disabled` when their\n // attribute or property changes.\n // The properties update their attributes, so this callback is invoked\n // immediately when the properties are set. We call `requestUpdate()` here\n // instead of letting Lit set the properties from the attribute change.\n // That would cause the properties to re-set the attribute and invoke this\n // callback again in a loop. This leads to stale state when Lit tries to\n // determine if a property changed or not.\n if (name === 'name' || name === 'disabled') {\n // Disabled's value is only false if the attribute is missing and null.\n const oldValue = name === 'disabled' ? old !== null : old;\n // Trigger a lit update when the attribute changes.\n this.requestUpdate(name, oldValue);\n return;\n }\n\n super.attributeChangedCallback(name, old, value);\n }\n\n override requestUpdate(\n name?: PropertyKey,\n oldValue?: unknown,\n options?: PropertyDeclaration,\n ) {\n super.requestUpdate(name, oldValue, options);\n // If any properties change, update the form value, which may have changed\n // as well.\n // Update the form value synchronously in `requestUpdate()` rather than\n // `update()` or `updated()`, which are async. This is necessary to ensure\n // that form data is updated in time for synchronous event listeners.\n this[internals].setFormValue(this[getFormValue](), this[getFormState]());\n }\n\n [getFormValue](): FormValue | null {\n // Closure does not allow abstract symbol members, so a default\n // implementation is needed.\n throw new Error('Implement [getFormValue]');\n }\n\n [getFormState](): FormValue | null {\n return this[getFormValue]();\n }\n\n formDisabledCallback(disabled: boolean) {\n this.disabled = disabled;\n }\n\n abstract formResetCallback(): void;\n\n abstract formStateRestoreCallback(\n state: FormRestoreState | null,\n reason: FormRestoreReason,\n ): void;\n }\n\n return FormAssociatedElement;\n}\n\n/**\n * A value that can be provided for form submission and state.\n */\nexport type FormValue = File | string | FormData;\n\n/**\n * A value to be restored for a component's form value. If a component's form\n * state is a `FormData` object, its entry list of name and values will be\n * provided.\n */\nexport type FormRestoreState =\n | File\n | string\n | Array<[string, FormDataEntryValue]>;\n\n/**\n * The reason a form component is being restored for, either `'restore'` for\n * browser restoration or `'autocomplete'` for restoring user values.\n */\nexport type FormRestoreReason = 'restore' | 'autocomplete';\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { LitElement } from 'lit';
|
|
7
|
+
import { ConstraintValidation } from './constraint-validation.js';
|
|
8
|
+
import { MixinBase, MixinReturn } from './mixin.js';
|
|
9
|
+
/**
|
|
10
|
+
* A constraint validation element that has a callback for when the element
|
|
11
|
+
* should report validity styles and error messages to the user.
|
|
12
|
+
*
|
|
13
|
+
* This is commonly used in text-field-like controls that display error styles
|
|
14
|
+
* and error messages.
|
|
15
|
+
*/
|
|
16
|
+
export interface OnReportValidity extends ConstraintValidation {
|
|
17
|
+
/**
|
|
18
|
+
* A callback that is invoked when validity should be reported. Components
|
|
19
|
+
* that can display their own error state can use this and update their
|
|
20
|
+
* styles.
|
|
21
|
+
*
|
|
22
|
+
* If an invalid event is provided, the element is invalid. If `null`, the
|
|
23
|
+
* element is valid.
|
|
24
|
+
*
|
|
25
|
+
* The invalid event's `preventDefault()` may be called to stop the platform
|
|
26
|
+
* popup from displaying.
|
|
27
|
+
*
|
|
28
|
+
* @param invalidEvent The `invalid` event dispatched when an element is
|
|
29
|
+
* invalid, or `null` if the element is valid.
|
|
30
|
+
*/
|
|
31
|
+
[onReportValidity](invalidEvent: Event | null): void;
|
|
32
|
+
formAssociatedCallback(form: HTMLFormElement | null): void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A symbol property used for a callback when validity has been reported.
|
|
36
|
+
*/
|
|
37
|
+
export declare const onReportValidity: unique symbol;
|
|
38
|
+
/**
|
|
39
|
+
* Mixes in a callback for constraint validation when validity should be
|
|
40
|
+
* styled and reported to the user.
|
|
41
|
+
*
|
|
42
|
+
* This is commonly used in text-field-like controls that display error styles
|
|
43
|
+
* and error messages.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const baseClass = mixinOnReportValidity(
|
|
48
|
+
* mixinConstraintValidation(
|
|
49
|
+
* mixinFormAssociated(mixinElementInternals(LitElement)),
|
|
50
|
+
* ),
|
|
51
|
+
* );
|
|
52
|
+
*
|
|
53
|
+
* class MyField extends baseClass {
|
|
54
|
+
* \@property({type: Boolean}) error = false;
|
|
55
|
+
* \@property() errorMessage = '';
|
|
56
|
+
*
|
|
57
|
+
* [onReportValidity](invalidEvent: Event | null) {
|
|
58
|
+
* this.error = !!invalidEvent;
|
|
59
|
+
* this.errorMessage = this.validationMessage;
|
|
60
|
+
*
|
|
61
|
+
* // Optionally prevent platform popup from displaying
|
|
62
|
+
* invalidEvent?.preventDefault();
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @param base The class to mix functionality into.
|
|
68
|
+
* @return The provided class with `OnReportValidity` mixed in.
|
|
69
|
+
*/
|
|
70
|
+
export declare function mixinOnReportValidity<T extends MixinBase<LitElement & ConstraintValidation>>(base: T): MixinReturn<T, OnReportValidity>;
|