@shortfuse/materialdesignweb 0.8.0 → 0.9.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/README.md +50 -198
- package/bin/mdw-css.js +1 -1
- package/components/Badge.js +15 -5
- package/components/Body.js +7 -0
- package/components/BottomAppBar.js +7 -10
- package/components/BottomSheet.js +472 -0
- package/components/Box.js +11 -49
- package/components/Button.js +81 -82
- package/components/Card.js +74 -62
- package/components/Checkbox.js +15 -25
- package/components/CheckboxIcon.js +19 -31
- package/components/Chip.js +18 -13
- package/components/Dialog.js +70 -100
- package/components/DialogActions.js +4 -0
- package/components/Display.js +64 -0
- package/components/Divider.js +5 -0
- package/components/Fab.js +94 -17
- package/components/FabContainer.js +57 -0
- package/components/FilterChip.js +43 -32
- package/components/Grid.js +187 -0
- package/components/Headline.js +9 -28
- package/components/Icon.js +80 -71
- package/components/IconButton.js +77 -120
- package/components/Input.js +745 -86
- package/components/InputChip.js +193 -0
- package/components/Label.js +7 -0
- package/components/List.js +11 -5
- package/components/ListItem.js +92 -23
- package/components/ListOption.js +143 -65
- package/components/Listbox.js +57 -17
- package/components/Menu.js +39 -27
- package/components/MenuItem.js +49 -36
- package/components/NavBar.js +66 -21
- package/components/NavBarItem.js +5 -0
- package/components/NavDrawer.js +33 -16
- package/components/NavDrawerItem.js +7 -4
- package/components/NavItem.js +61 -34
- package/components/NavRail.js +32 -21
- package/components/NavRailItem.js +10 -2
- package/components/Page.js +119 -0
- package/components/Pane.js +24 -0
- package/components/Popup.js +23 -8
- package/components/Progress.js +25 -5
- package/components/Radio.js +8 -7
- package/components/RadioIcon.js +24 -15
- package/components/Ripple.js +25 -7
- package/components/Root.js +225 -0
- package/components/Scrim.js +95 -0
- package/components/Search.js +30 -25
- package/components/SegmentedButton.js +53 -40
- package/components/SegmentedButtonGroup.js +15 -12
- package/components/Select.js +19 -10
- package/components/Shape.js +10 -66
- package/components/SideSheet.js +337 -0
- package/components/Slider.js +93 -36
- package/components/Snackbar.js +52 -20
- package/components/SnackbarContainer.js +51 -0
- package/components/Surface.js +20 -10
- package/components/Switch.js +21 -18
- package/components/SwitchIcon.js +62 -33
- package/components/Tab.js +78 -38
- package/components/TabContent.js +33 -12
- package/components/TabList.js +95 -34
- package/components/TabPanel.js +10 -1
- package/components/Table.js +151 -0
- package/components/TextArea.js +48 -16
- package/components/Title.js +8 -9
- package/components/Tooltip.js +51 -22
- package/components/TopAppBar.js +71 -78
- package/constants/shapes.js +36 -0
- package/constants/typography.js +127 -0
- package/core/Composition.js +391 -201
- package/core/CompositionAdapter.js +35 -18
- package/core/CustomElement.js +634 -254
- package/core/css.js +117 -12
- package/core/customTypes.js +161 -49
- package/core/dom.js +18 -11
- package/core/jsonMergePatch.js +27 -11
- package/core/observe.js +308 -256
- package/core/optimizations.js +9 -9
- package/core/template.js +14 -57
- package/dist/CustomElement.min.js +2 -0
- package/dist/CustomElement.min.js.map +7 -0
- package/dist/core/CustomElement.min.js +2 -0
- package/dist/core/CustomElement.min.js.map +7 -0
- package/dist/index.min.js +85 -115
- package/dist/index.min.js.map +4 -4
- package/dist/meta.json +1 -1
- package/dom/HTMLOptionsCollectionProxy.js +108 -0
- package/{theming/themableMixinLoader.js → loaders/palette.js} +4 -3
- package/loaders/theme.js +12 -0
- package/mixins/AriaReflectorMixin.js +64 -15
- package/mixins/AriaToolbarMixin.js +6 -0
- package/mixins/ControlMixin.js +79 -33
- package/mixins/DelegatesFocusMixin.js +62 -0
- package/mixins/DensityMixin.js +7 -3
- package/mixins/ElevationMixin.js +61 -0
- package/mixins/FlexableMixin.js +87 -39
- package/mixins/FormAssociatedMixin.js +76 -10
- package/mixins/HyperlinkMixin.js +76 -0
- package/mixins/InputMixin.js +227 -32
- package/mixins/KeyboardNavMixin.js +11 -7
- package/mixins/NavigationListenerMixin.js +33 -0
- package/mixins/PopupMixin.js +216 -219
- package/mixins/RTLObserverMixin.js +2 -0
- package/mixins/ResizeObserverMixin.js +18 -4
- package/mixins/RippleMixin.js +11 -7
- package/mixins/ScrollListenerMixin.js +14 -2
- package/mixins/SemiStickyMixin.js +51 -98
- package/mixins/ShapeMaskedMixin.js +125 -0
- package/mixins/ShapeMixin.js +30 -203
- package/mixins/StateMixin.js +74 -34
- package/mixins/TextFieldMixin.js +128 -145
- package/mixins/ThemableMixin.js +57 -56
- package/mixins/TooltipTriggerMixin.js +305 -359
- package/mixins/TouchTargetMixin.js +5 -2
- package/mixins/TypographyMixin.js +128 -0
- package/package.json +125 -81
- package/services/rtl.js +10 -0
- package/services/svgAlias.js +17 -0
- package/{theming/index.js → services/theme.js} +25 -176
- package/types/bin/mdw-css.d.ts +3 -0
- package/types/bin/mdw-css.d.ts.map +1 -0
- package/types/components/Badge.d.ts +39 -0
- package/types/components/Badge.d.ts.map +1 -0
- package/types/components/Body.d.ts +29 -0
- package/types/components/Body.d.ts.map +1 -0
- package/types/components/BottomAppBar.d.ts +72 -0
- package/types/components/BottomAppBar.d.ts.map +1 -0
- package/types/components/BottomSheet.d.ts +135 -0
- package/types/components/BottomSheet.d.ts.map +1 -0
- package/types/components/Box.d.ts +16 -0
- package/types/components/Box.d.ts.map +1 -0
- package/types/components/Button.d.ts +245 -0
- package/types/components/Button.d.ts.map +1 -0
- package/types/components/Card.d.ts +147 -0
- package/types/components/Card.d.ts.map +1 -0
- package/types/components/Checkbox.d.ts +207 -0
- package/types/components/Checkbox.d.ts.map +1 -0
- package/types/components/CheckboxIcon.d.ts +44 -0
- package/types/components/CheckboxIcon.d.ts.map +1 -0
- package/types/components/Chip.d.ts +248 -0
- package/types/components/Chip.d.ts.map +1 -0
- package/types/components/Dialog.d.ts +103 -0
- package/types/components/Dialog.d.ts.map +1 -0
- package/types/components/DialogActions.d.ts +4 -0
- package/types/components/DialogActions.d.ts.map +1 -0
- package/types/components/Display.d.ts +46 -0
- package/types/components/Display.d.ts.map +1 -0
- package/types/components/Divider.d.ts +10 -0
- package/types/components/Divider.d.ts.map +1 -0
- package/types/components/Fab.d.ts +273 -0
- package/types/components/Fab.d.ts.map +1 -0
- package/types/components/FabContainer.d.ts +10 -0
- package/types/components/FabContainer.d.ts.map +1 -0
- package/types/components/FilterChip.d.ts +256 -0
- package/types/components/FilterChip.d.ts.map +1 -0
- package/types/components/Grid.d.ts +38 -0
- package/types/components/Grid.d.ts.map +1 -0
- package/types/components/Headline.d.ts +46 -0
- package/types/components/Headline.d.ts.map +1 -0
- package/types/components/Icon.d.ts +55 -0
- package/types/components/Icon.d.ts.map +1 -0
- package/types/components/IconButton.d.ts +284 -0
- package/types/components/IconButton.d.ts.map +1 -0
- package/types/components/Input.d.ts +2528 -0
- package/types/components/Input.d.ts.map +1 -0
- package/types/components/InputChip.d.ts +85 -0
- package/types/components/InputChip.d.ts.map +1 -0
- package/types/components/Label.d.ts +29 -0
- package/types/components/Label.d.ts.map +1 -0
- package/types/components/List.d.ts +35 -0
- package/types/components/List.d.ts.map +1 -0
- package/types/components/ListItem.d.ts +124 -0
- package/types/components/ListItem.d.ts.map +1 -0
- package/types/components/ListOption.d.ts +158 -0
- package/types/components/ListOption.d.ts.map +1 -0
- package/types/components/Listbox.d.ts +763 -0
- package/types/components/Listbox.d.ts.map +1 -0
- package/types/components/Menu.d.ts +130 -0
- package/types/components/Menu.d.ts.map +1 -0
- package/types/components/MenuItem.d.ts +232 -0
- package/types/components/MenuItem.d.ts.map +1 -0
- package/types/components/NavBar.d.ts +20 -0
- package/types/components/NavBar.d.ts.map +1 -0
- package/types/components/NavBarItem.d.ts +97 -0
- package/types/components/NavBarItem.d.ts.map +1 -0
- package/types/components/NavDrawer.d.ts +107 -0
- package/types/components/NavDrawer.d.ts.map +1 -0
- package/types/components/NavDrawerItem.d.ts +97 -0
- package/types/components/NavDrawerItem.d.ts.map +1 -0
- package/types/components/NavItem.d.ts +99 -0
- package/types/components/NavItem.d.ts.map +1 -0
- package/types/components/NavRail.d.ts +108 -0
- package/types/components/NavRail.d.ts.map +1 -0
- package/types/components/NavRailItem.d.ts +97 -0
- package/types/components/NavRailItem.d.ts.map +1 -0
- package/types/components/Page.d.ts +25 -0
- package/types/components/Page.d.ts.map +1 -0
- package/types/components/Pane.d.ts +44 -0
- package/types/components/Pane.d.ts.map +1 -0
- package/types/components/Popup.d.ts +78 -0
- package/types/components/Popup.d.ts.map +1 -0
- package/types/components/Progress.d.ts +21 -0
- package/types/components/Progress.d.ts.map +1 -0
- package/types/components/Radio.d.ts +201 -0
- package/types/components/Radio.d.ts.map +1 -0
- package/types/components/RadioIcon.d.ts +46 -0
- package/types/components/RadioIcon.d.ts.map +1 -0
- package/types/components/Ripple.d.ts +35 -0
- package/types/components/Ripple.d.ts.map +1 -0
- package/types/components/Root.d.ts +68 -0
- package/types/components/Root.d.ts.map +1 -0
- package/types/components/Scrim.d.ts +6 -0
- package/types/components/Scrim.d.ts.map +1 -0
- package/types/components/Search.d.ts +516 -0
- package/types/components/Search.d.ts.map +1 -0
- package/types/components/SegmentedButton.d.ts +252 -0
- package/types/components/SegmentedButton.d.ts.map +1 -0
- package/types/components/SegmentedButtonGroup.d.ts +43 -0
- package/types/components/SegmentedButtonGroup.d.ts.map +1 -0
- package/types/components/Select.d.ts +158 -0
- package/types/components/Select.d.ts.map +1 -0
- package/types/components/Shape.d.ts +10 -0
- package/types/components/Shape.d.ts.map +1 -0
- package/types/components/SideSheet.d.ts +111 -0
- package/types/components/SideSheet.d.ts.map +1 -0
- package/types/components/Slider.d.ts +203 -0
- package/types/components/Slider.d.ts.map +1 -0
- package/types/components/Snackbar.d.ts +73 -0
- package/types/components/Snackbar.d.ts.map +1 -0
- package/types/components/SnackbarContainer.d.ts +6 -0
- package/types/components/SnackbarContainer.d.ts.map +1 -0
- package/types/components/Surface.d.ts +45 -0
- package/types/components/Surface.d.ts.map +1 -0
- package/types/components/Switch.d.ts +187 -0
- package/types/components/Switch.d.ts.map +1 -0
- package/types/components/SwitchIcon.d.ts +61 -0
- package/types/components/SwitchIcon.d.ts.map +1 -0
- package/types/components/Tab.d.ts +139 -0
- package/types/components/Tab.d.ts.map +1 -0
- package/types/components/TabContent.d.ts +124 -0
- package/types/components/TabContent.d.ts.map +1 -0
- package/types/components/TabList.d.ts +1111 -0
- package/types/components/TabList.d.ts.map +1 -0
- package/types/components/TabPanel.d.ts +28 -0
- package/types/components/TabPanel.d.ts.map +1 -0
- package/types/components/Table.d.ts +25 -0
- package/types/components/Table.d.ts.map +1 -0
- package/types/components/TextArea.d.ts +201 -0
- package/types/components/TextArea.d.ts.map +1 -0
- package/types/components/Title.d.ts +46 -0
- package/types/components/Title.d.ts.map +1 -0
- package/types/components/Tooltip.d.ts +49 -0
- package/types/components/Tooltip.d.ts.map +1 -0
- package/types/components/TopAppBar.d.ts +129 -0
- package/types/components/TopAppBar.d.ts.map +1 -0
- package/types/constants/colorKeywords.d.ts +2 -0
- package/types/constants/colorKeywords.d.ts.map +1 -0
- package/types/constants/shapes.d.ts +38 -0
- package/types/constants/shapes.d.ts.map +1 -0
- package/types/constants/typography.d.ts +212 -0
- package/types/constants/typography.d.ts.map +1 -0
- package/types/core/Composition.d.ts +260 -0
- package/types/core/Composition.d.ts.map +1 -0
- package/types/core/CompositionAdapter.d.ts +114 -0
- package/types/core/CompositionAdapter.d.ts.map +1 -0
- package/types/core/CustomElement.d.ts +304 -0
- package/types/core/CustomElement.d.ts.map +1 -0
- package/types/core/css.d.ts +44 -0
- package/types/core/css.d.ts.map +1 -0
- package/types/core/customTypes.d.ts +22 -0
- package/types/core/customTypes.d.ts.map +1 -0
- package/types/core/dom.d.ts +32 -0
- package/types/core/dom.d.ts.map +1 -0
- package/types/core/jsonMergePatch.d.ts +31 -0
- package/types/core/jsonMergePatch.d.ts.map +1 -0
- package/types/core/observe.d.ts +114 -0
- package/types/core/observe.d.ts.map +1 -0
- package/types/core/optimizations.d.ts +7 -0
- package/types/core/optimizations.d.ts.map +1 -0
- package/types/core/template.d.ts +47 -0
- package/types/core/template.d.ts.map +1 -0
- package/types/core/uid.d.ts +6 -0
- package/types/core/uid.d.ts.map +1 -0
- package/types/dom/HTMLOptionsCollectionProxy.d.ts +18 -0
- package/types/dom/HTMLOptionsCollectionProxy.d.ts.map +1 -0
- package/types/index.d.ts +88 -0
- package/types/index.d.ts.map +1 -0
- package/types/loaders/palette.d.ts +2 -0
- package/types/loaders/palette.d.ts.map +1 -0
- package/types/loaders/theme.d.ts +2 -0
- package/types/loaders/theme.d.ts.map +1 -0
- package/types/mixins/AriaReflectorMixin.d.ts +31 -0
- package/types/mixins/AriaReflectorMixin.d.ts.map +1 -0
- package/types/mixins/AriaToolbarMixin.d.ts +34 -0
- package/types/mixins/AriaToolbarMixin.d.ts.map +1 -0
- package/types/mixins/ControlMixin.d.ts +124 -0
- package/types/mixins/ControlMixin.d.ts.map +1 -0
- package/types/mixins/DelegatesFocusMixin.d.ts +13 -0
- package/types/mixins/DelegatesFocusMixin.d.ts.map +1 -0
- package/types/mixins/DensityMixin.d.ts +8 -0
- package/types/mixins/DensityMixin.d.ts.map +1 -0
- package/types/mixins/ElevationMixin.d.ts +32 -0
- package/types/mixins/ElevationMixin.d.ts.map +1 -0
- package/types/mixins/FlexableMixin.d.ts +14 -0
- package/types/mixins/FlexableMixin.d.ts.map +1 -0
- package/types/mixins/FormAssociatedMixin.d.ts +123 -0
- package/types/mixins/FormAssociatedMixin.d.ts.map +1 -0
- package/types/mixins/HyperlinkMixin.d.ts +25 -0
- package/types/mixins/HyperlinkMixin.d.ts.map +1 -0
- package/types/mixins/InputMixin.d.ts +173 -0
- package/types/mixins/InputMixin.d.ts.map +1 -0
- package/types/mixins/KeyboardNavMixin.d.ts +46 -0
- package/types/mixins/KeyboardNavMixin.d.ts.map +1 -0
- package/types/mixins/NavigationListenerMixin.d.ts +8 -0
- package/types/mixins/NavigationListenerMixin.d.ts.map +1 -0
- package/types/mixins/PopupMixin.d.ts +98 -0
- package/types/mixins/PopupMixin.d.ts.map +1 -0
- package/types/mixins/RTLObserverMixin.d.ts +8 -0
- package/types/mixins/RTLObserverMixin.d.ts.map +1 -0
- package/types/mixins/ResizeObserverMixin.d.ts +13 -0
- package/types/mixins/ResizeObserverMixin.d.ts.map +1 -0
- package/types/mixins/RippleMixin.d.ts +94 -0
- package/types/mixins/RippleMixin.d.ts.map +1 -0
- package/types/mixins/ScrollListenerMixin.d.ts +46 -0
- package/types/mixins/ScrollListenerMixin.d.ts.map +1 -0
- package/types/mixins/SemiStickyMixin.d.ts +50 -0
- package/types/mixins/SemiStickyMixin.d.ts.map +1 -0
- package/types/mixins/ShapeMaskedMixin.d.ts +12 -0
- package/types/mixins/ShapeMaskedMixin.d.ts.map +1 -0
- package/types/mixins/ShapeMixin.d.ts +39 -0
- package/types/mixins/ShapeMixin.d.ts.map +1 -0
- package/types/mixins/StateMixin.d.ts +29 -0
- package/types/mixins/StateMixin.d.ts.map +1 -0
- package/types/mixins/TextFieldMixin.d.ts +153 -0
- package/types/mixins/TextFieldMixin.d.ts.map +1 -0
- package/types/mixins/ThemableMixin.d.ts +10 -0
- package/types/mixins/ThemableMixin.d.ts.map +1 -0
- package/types/mixins/TooltipTriggerMixin.d.ts +114 -0
- package/types/mixins/TooltipTriggerMixin.d.ts.map +1 -0
- package/types/mixins/TouchTargetMixin.d.ts +6 -0
- package/types/mixins/TouchTargetMixin.d.ts.map +1 -0
- package/types/mixins/TypographyMixin.d.ts +20 -0
- package/types/mixins/TypographyMixin.d.ts.map +1 -0
- package/types/services/rtl.d.ts +3 -0
- package/types/services/rtl.d.ts.map +1 -0
- package/types/services/svgAlias.d.ts +13 -0
- package/types/services/svgAlias.d.ts.map +1 -0
- package/types/services/theme.d.ts +45 -0
- package/types/services/theme.d.ts.map +1 -0
- package/types/utils/cli.d.ts +3 -0
- package/types/utils/cli.d.ts.map +1 -0
- package/types/utils/function.d.ts +3 -0
- package/types/utils/function.d.ts.map +1 -0
- package/types/utils/jsx-runtime.d.ts +20 -0
- package/types/utils/jsx-runtime.d.ts.map +1 -0
- package/types/utils/material-color/blend.d.ts +34 -0
- package/types/utils/material-color/blend.d.ts.map +1 -0
- package/types/utils/material-color/hct/Cam16.d.ts +142 -0
- package/types/utils/material-color/hct/Cam16.d.ts.map +1 -0
- package/types/utils/material-color/hct/Hct.d.ts +93 -0
- package/types/utils/material-color/hct/Hct.d.ts.map +1 -0
- package/types/utils/material-color/hct/ViewingConditions.d.ts +69 -0
- package/types/utils/material-color/hct/ViewingConditions.d.ts.map +1 -0
- package/types/utils/material-color/hct/hctSolver.d.ts +30 -0
- package/types/utils/material-color/hct/hctSolver.d.ts.map +1 -0
- package/types/utils/material-color/helper.d.ts +8 -0
- package/types/utils/material-color/helper.d.ts.map +1 -0
- package/types/utils/material-color/palettes/CorePalette.d.ts +75 -0
- package/types/utils/material-color/palettes/CorePalette.d.ts.map +1 -0
- package/types/utils/material-color/palettes/TonalPalette.d.ts +38 -0
- package/types/utils/material-color/palettes/TonalPalette.d.ts.map +1 -0
- package/types/utils/material-color/scheme/Scheme.d.ts +264 -0
- package/types/utils/material-color/scheme/Scheme.d.ts.map +1 -0
- package/types/utils/material-color/utils/color.d.ts +172 -0
- package/types/utils/material-color/utils/color.d.ts.map +1 -0
- package/types/utils/material-color/utils/math.d.ts +94 -0
- package/types/utils/material-color/utils/math.d.ts.map +1 -0
- package/types/utils/pixelmatch.d.ts +22 -0
- package/types/utils/pixelmatch.d.ts.map +1 -0
- package/types/utils/popup.d.ts +106 -0
- package/types/utils/popup.d.ts.map +1 -0
- package/types/utils/searchParams.d.ts +3 -0
- package/types/utils/searchParams.d.ts.map +1 -0
- package/types/utils/svg.d.ts +7 -0
- package/types/utils/svg.d.ts.map +1 -0
- package/utils/jsx-runtime.js +9 -4
- package/utils/material-color/scheme/Scheme.js +1 -1
- package/utils/pixelmatch.js +363 -0
- package/utils/popup.js +86 -10
- package/utils/searchParams.js +22 -0
- package/components/Button.md +0 -61
- package/components/ExtendedFab.js +0 -32
- package/components/Layout.js +0 -504
- package/components/Nav.js +0 -38
- package/core/DomAdapter.js +0 -586
- package/core/ICustomElement.d.ts +0 -291
- package/core/ICustomElement.js +0 -1
- package/core/test.js +0 -126
- package/core/typings.d.ts +0 -142
- package/core/typings.js +0 -1
- package/mixins/SurfaceMixin.js +0 -127
- package/theming/loader.js +0 -22
- /package/{utils/color_keywords.js → constants/colorKeywords.js} +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* https://html.spec.whatwg.org/multipage/form-control-infrastructure.html */
|
|
2
2
|
|
|
3
|
+
import { CHROME_VERSION } from '../core/dom.js';
|
|
4
|
+
|
|
3
5
|
/** @typedef {HTMLElement & {value:string}} HTMLControlElement */
|
|
4
6
|
|
|
5
7
|
/** @typedef {import('../core/CustomElement.js').default} CustomElement */
|
|
@@ -9,6 +11,7 @@ const FORM_IPC_EVENT = 'mdw-form-associated-changed';
|
|
|
9
11
|
const DOMString = { nullParser: String, value: '' };
|
|
10
12
|
|
|
11
13
|
/**
|
|
14
|
+
* Implements form-associated element behavior (internals, validity, files, value handling).
|
|
12
15
|
* @param {ReturnType<import('./StateMixin.js').default>} Base
|
|
13
16
|
*/
|
|
14
17
|
export default function FormAssociatedMixin(Base) {
|
|
@@ -21,22 +24,36 @@ export default function FormAssociatedMixin(Base) {
|
|
|
21
24
|
_ipcListener: null,
|
|
22
25
|
/** @type {EventTarget} */
|
|
23
26
|
_ipcTarget: null,
|
|
27
|
+
/** @type {FileList} */
|
|
28
|
+
_files: null,
|
|
24
29
|
})
|
|
25
30
|
.observe({
|
|
31
|
+
/** ARIA 'controls' attribute (string). */
|
|
26
32
|
ariaControls: 'string',
|
|
33
|
+
/** Autocomplete token for the associated control (string). */
|
|
27
34
|
autocomplete: DOMString,
|
|
35
|
+
/** Name attribute for the control used in forms. */
|
|
28
36
|
name: DOMString,
|
|
37
|
+
/** Read-only state reflected to control via 'readonly' attribute. */
|
|
29
38
|
readOnly: { attr: 'readonly', type: 'boolean' },
|
|
39
|
+
/** When true, form validation is skipped for this control (formnovalidate). */
|
|
40
|
+
formNoValidate: { attr: 'formnovalidate', type: 'boolean' },
|
|
41
|
+
/** Default checked state for checkable controls (checkbox/radio). */
|
|
30
42
|
defaultChecked: { attr: 'checked', type: 'boolean' },
|
|
31
43
|
_checkedDirty: 'boolean',
|
|
32
44
|
/* "Checkedness" */
|
|
33
45
|
_checked: 'boolean',
|
|
46
|
+
/** Whether the control is required for form submission. */
|
|
34
47
|
required: 'boolean',
|
|
48
|
+
/** Control type token (e.g. 'text','checkbox','radio','file'). */
|
|
35
49
|
type: DOMString,
|
|
36
50
|
// [CEReactions] attribute [LegacyNullToEmptyString] DOMString value;
|
|
51
|
+
/** Reflected default value backing field (attr: value). */
|
|
37
52
|
_defaultValue: { reflect: true, attr: 'value' },
|
|
53
|
+
/** Internal value storage. */
|
|
38
54
|
_value: { empty: '' },
|
|
39
55
|
_valueDirty: 'boolean',
|
|
56
|
+
/** Whether the user has interacted with the control (used for validation UX). */
|
|
40
57
|
_userInteracted: 'boolean',
|
|
41
58
|
_invalid: 'boolean',
|
|
42
59
|
_badInput: 'boolean',
|
|
@@ -73,14 +90,14 @@ export default function FormAssociatedMixin(Base) {
|
|
|
73
90
|
})
|
|
74
91
|
.methods({
|
|
75
92
|
/**
|
|
76
|
-
* Default behavior
|
|
93
|
+
* Default behavior should likely be overridden
|
|
77
94
|
* @param {string} value
|
|
78
95
|
*/
|
|
79
96
|
_onSetValue(value) {
|
|
80
97
|
this._value = value;
|
|
81
98
|
},
|
|
82
99
|
/**
|
|
83
|
-
* Default behavior
|
|
100
|
+
* Default behavior should likely be overridden
|
|
84
101
|
* @param {boolean} checked
|
|
85
102
|
*/
|
|
86
103
|
_onSetChecked(checked) {
|
|
@@ -92,14 +109,13 @@ export default function FormAssociatedMixin(Base) {
|
|
|
92
109
|
reflect: false,
|
|
93
110
|
get({ _valueBehavior, _defaultValue, _value }) {
|
|
94
111
|
switch (_valueBehavior) {
|
|
112
|
+
case 'filename':
|
|
95
113
|
default:
|
|
96
114
|
return _value;
|
|
97
115
|
case 'default':
|
|
98
116
|
return _defaultValue ?? '';
|
|
99
117
|
case 'default/on':
|
|
100
118
|
return _defaultValue ?? 'on';
|
|
101
|
-
case 'filename':
|
|
102
|
-
throw new Error('Not supported!');
|
|
103
119
|
}
|
|
104
120
|
},
|
|
105
121
|
/** @param {string} v */
|
|
@@ -109,6 +125,14 @@ export default function FormAssociatedMixin(Base) {
|
|
|
109
125
|
this._valueDirty = true;
|
|
110
126
|
this._onSetValue(v);
|
|
111
127
|
break;
|
|
128
|
+
case 'filename':
|
|
129
|
+
if (v == null || v === '') {
|
|
130
|
+
this._files = null;
|
|
131
|
+
// Presume overriding class will interpet null as empty
|
|
132
|
+
} else {
|
|
133
|
+
throw new DOMException('InvalidStateError');
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
112
136
|
default:
|
|
113
137
|
this.defaultValue = v;
|
|
114
138
|
}
|
|
@@ -121,8 +145,9 @@ export default function FormAssociatedMixin(Base) {
|
|
|
121
145
|
checked: {
|
|
122
146
|
reflect: false,
|
|
123
147
|
type: 'boolean',
|
|
124
|
-
get({ _checked }) {
|
|
125
|
-
return _checked;
|
|
148
|
+
get({ _checkedDirty, defaultChecked, _checked }) {
|
|
149
|
+
if (_checkedDirty) return _checked;
|
|
150
|
+
return defaultChecked;
|
|
126
151
|
},
|
|
127
152
|
/** @param {boolean} checked */
|
|
128
153
|
set(checked) {
|
|
@@ -135,7 +160,11 @@ export default function FormAssociatedMixin(Base) {
|
|
|
135
160
|
form() { return this.elementInternals.form; },
|
|
136
161
|
validity() { return this.elementInternals.validity; },
|
|
137
162
|
validationMessage() { return this.elementInternals.validationMessage; },
|
|
138
|
-
willValidate() {
|
|
163
|
+
willValidate() {
|
|
164
|
+
if (this.type === 'submit') return !this.formNoValidate;
|
|
165
|
+
if (this.type === 'button' || this.type === 'reset') return false;
|
|
166
|
+
return this.elementInternals.willValidate;
|
|
167
|
+
},
|
|
139
168
|
labels() { return this.elementInternals.labels; },
|
|
140
169
|
})
|
|
141
170
|
.observe({
|
|
@@ -195,7 +224,6 @@ export default function FormAssociatedMixin(Base) {
|
|
|
195
224
|
*/
|
|
196
225
|
formAssociatedCallback(form) {
|
|
197
226
|
this.refreshFormAssociation();
|
|
198
|
-
console.debug('FormAssociatedMixin: formAssociatedCallback', this);
|
|
199
227
|
this.checkValidity();
|
|
200
228
|
},
|
|
201
229
|
|
|
@@ -231,6 +259,7 @@ export default function FormAssociatedMixin(Base) {
|
|
|
231
259
|
this._formReset = true; // Fires Change Event
|
|
232
260
|
this._valueDirty = false;
|
|
233
261
|
this.checkValidity();
|
|
262
|
+
this._userInteracted = false; // Reset error states
|
|
234
263
|
this._formReset = false;
|
|
235
264
|
},
|
|
236
265
|
|
|
@@ -239,8 +268,7 @@ export default function FormAssociatedMixin(Base) {
|
|
|
239
268
|
* @param {'autocomplete'|'restore'} mode
|
|
240
269
|
*/
|
|
241
270
|
formStateRestoreCallback(state, mode) {
|
|
242
|
-
if (
|
|
243
|
-
// console.warn('Chromium Bug: 1429585 - Ignoring formStateRestoreCallback on Chromium', { state, mode });
|
|
271
|
+
if (CHROME_VERSION < 115) {
|
|
244
272
|
// formStateRestoreCallback is broken on Chromium
|
|
245
273
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1429585
|
|
246
274
|
return;
|
|
@@ -282,6 +310,36 @@ export default function FormAssociatedMixin(Base) {
|
|
|
282
310
|
this.elementInternals.setFormValue(null, 'unchecked');
|
|
283
311
|
}
|
|
284
312
|
break;
|
|
313
|
+
case 'button':
|
|
314
|
+
case 'reset':
|
|
315
|
+
this.elementInternals.setFormValue(null);
|
|
316
|
+
break;
|
|
317
|
+
case 'file': {
|
|
318
|
+
const { elementInternals, _files, name } = this;
|
|
319
|
+
if (!_files || _files.length) {
|
|
320
|
+
elementInternals.setFormValue(null);
|
|
321
|
+
} else {
|
|
322
|
+
const fd = new FormData();
|
|
323
|
+
for (const entry of _files) {
|
|
324
|
+
fd.append(name, entry);
|
|
325
|
+
}
|
|
326
|
+
elementInternals.setFormValue(fd);
|
|
327
|
+
}
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
case 'select-multiple': {
|
|
331
|
+
const formData = new FormData();
|
|
332
|
+
// eslint-disable-next-line unicorn/no-this-assignment, @typescript-eslint/no-this-alias
|
|
333
|
+
const selectElement = /** @type {HTMLSelectElement} */ (/** @type {unknown} */ (this));
|
|
334
|
+
if (selectElement.name) {
|
|
335
|
+
for (const option of selectElement.selectedOptions) {
|
|
336
|
+
formData.append(selectElement.name, option.value);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
this.elementInternals.setFormValue(formData);
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
// case 'select-one':
|
|
285
343
|
default:
|
|
286
344
|
// console.debug('FormAssociatedMixin: setFormValue', this.name, this.value, this);
|
|
287
345
|
this.elementInternals.setFormValue(this.value);
|
|
@@ -305,5 +363,13 @@ export default function FormAssociatedMixin(Base) {
|
|
|
305
363
|
valueChanged() {
|
|
306
364
|
this._updateFormAssociatedValue();
|
|
307
365
|
},
|
|
366
|
+
_valueBehaviorChanged(previous, current) {
|
|
367
|
+
if (previous !== 'filename' && current === 'filename') {
|
|
368
|
+
this.value = '';
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
typeChanged() {
|
|
372
|
+
this._updateFormAssociatedValue();
|
|
373
|
+
},
|
|
308
374
|
});
|
|
309
375
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import NavigationListenerMixin from './NavigationListenerMixin.js';
|
|
2
|
+
|
|
3
|
+
// https://html.spec.whatwg.org/multipage/links.html#dom-hyperlink-protocol-dev
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @template {keyof URL} T
|
|
7
|
+
* @param {T} name
|
|
8
|
+
* @return {ThisType<URL> & TypedPropertyDescriptor<URL[T]>}
|
|
9
|
+
*/
|
|
10
|
+
function buildHyperlinkDefinition(name) {
|
|
11
|
+
return {
|
|
12
|
+
get() {
|
|
13
|
+
return new URL(this.href, window.location.href)[name];
|
|
14
|
+
},
|
|
15
|
+
set(value) {
|
|
16
|
+
const { href } = this;
|
|
17
|
+
if (!href) return;
|
|
18
|
+
const url = new URL(href, window.location.href);
|
|
19
|
+
url[name] = value;
|
|
20
|
+
this.href = url.href;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Adds hyperlink-related properties and URL helpers (href, target, rel, etc.).
|
|
27
|
+
* @param {typeof import('../core/CustomElement.js').default} Base
|
|
28
|
+
*/
|
|
29
|
+
export default function HyperlinkMixin(Base) {
|
|
30
|
+
return Base
|
|
31
|
+
.mixin(NavigationListenerMixin)
|
|
32
|
+
.observe({
|
|
33
|
+
/** The URL that the hyperlink points to. */
|
|
34
|
+
href: 'string',
|
|
35
|
+
/** The browsing context in which to open the linked resource (e.g. '_blank'). */
|
|
36
|
+
target: 'string',
|
|
37
|
+
/** Suggested filename for download. */
|
|
38
|
+
download: 'string',
|
|
39
|
+
/** URLs to be pinged when the link is followed. */
|
|
40
|
+
ping: 'string',
|
|
41
|
+
/** Link relationship tokens (e.g. 'noopener', 'noreferrer'). */
|
|
42
|
+
rel: 'string',
|
|
43
|
+
/** Language of the linked resource. */
|
|
44
|
+
hreflang: 'string',
|
|
45
|
+
/** Referrer policy for the link (serialized to 'referrerpolicy' attribute). */
|
|
46
|
+
referrerPolicy: { type: 'string', attr: 'referrerpolicy' },
|
|
47
|
+
})
|
|
48
|
+
.define({
|
|
49
|
+
origin() { return new URL(this.href).origin; },
|
|
50
|
+
protocol: buildHyperlinkDefinition('protocol'),
|
|
51
|
+
username: buildHyperlinkDefinition('username'),
|
|
52
|
+
password: buildHyperlinkDefinition('password'),
|
|
53
|
+
host: buildHyperlinkDefinition('host'),
|
|
54
|
+
hostname: buildHyperlinkDefinition('hostname'),
|
|
55
|
+
port: buildHyperlinkDefinition('port'),
|
|
56
|
+
pathname: buildHyperlinkDefinition('pathname'),
|
|
57
|
+
search: buildHyperlinkDefinition('search'),
|
|
58
|
+
hash: buildHyperlinkDefinition('hash'),
|
|
59
|
+
})
|
|
60
|
+
.html`
|
|
61
|
+
<a id=anchor
|
|
62
|
+
href={href}
|
|
63
|
+
target={target}
|
|
64
|
+
download={download}
|
|
65
|
+
ping={ping}
|
|
66
|
+
rel={rel}
|
|
67
|
+
hreflang={hreflang}
|
|
68
|
+
referrerpolicy={referrerPolicy}
|
|
69
|
+
></a>
|
|
70
|
+
`
|
|
71
|
+
.methods({
|
|
72
|
+
toString() {
|
|
73
|
+
return this.href;
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|
package/mixins/InputMixin.js
CHANGED
|
@@ -23,7 +23,13 @@ const IMPLICIT_SUBMISSION_BLOCKING_TYPES = new Set([
|
|
|
23
23
|
|
|
24
24
|
const DOMString = { nullParser: String, empty: '' };
|
|
25
25
|
|
|
26
|
+
/** Flag redispatched click events to know not to block them */
|
|
27
|
+
const redispatchedClickEvents = new WeakSet();
|
|
28
|
+
/** Flag root click events to know not to block them */
|
|
29
|
+
const rootClickEvents = new WeakSet();
|
|
30
|
+
|
|
26
31
|
/**
|
|
32
|
+
* Enhances a component with input-like attributes and behaviors (value, step, min/max, etc.).
|
|
27
33
|
* @see https://html.spec.whatwg.org/multipage/input.html#htmlinputelement
|
|
28
34
|
* @param {ReturnType<import('./StateMixin.js').default>} Base
|
|
29
35
|
*/
|
|
@@ -31,49 +37,85 @@ export default function InputMixin(Base) {
|
|
|
31
37
|
return Base
|
|
32
38
|
.mixin(ControlMixin)
|
|
33
39
|
.observe({
|
|
40
|
+
/** Accepted file types for file input (e.g. '.png,.jpg'). */
|
|
34
41
|
accept: DOMString,
|
|
42
|
+
/** Alternate text for images (for `type='image'`). */
|
|
35
43
|
alt: DOMString,
|
|
44
|
+
/** Directionality for form submission name (dirname attribute). */
|
|
36
45
|
dirName: { attr: 'dirname', ...DOMString },
|
|
46
|
+
/** Form action URL when this input is used as a submit button. */
|
|
37
47
|
_formAction: { attr: 'formaction' },
|
|
48
|
+
/** Form encoding type (formenctype). */
|
|
38
49
|
formEnctype: { attr: 'formenctype', ...DOMString },
|
|
50
|
+
/** Form method when associated with a submit input (formmethod). */
|
|
39
51
|
formMethod: { attr: 'formmethod', ...DOMString },
|
|
40
|
-
|
|
52
|
+
/** Target browsing context for form submission (formtarget). */
|
|
41
53
|
formTarget: { attr: 'formtarget', ...DOMString },
|
|
54
|
+
/** Rendered height hint for certain input types (integer). */
|
|
42
55
|
_height: { attr: 'height', type: 'integer' },
|
|
43
|
-
|
|
56
|
+
_indeterminate: 'boolean',
|
|
57
|
+
/** Max value or token for the input. */
|
|
44
58
|
max: DOMString,
|
|
59
|
+
/** Maximum length for text-like inputs. */
|
|
45
60
|
maxLength: { attr: 'maxlength', type: 'integer', empty: -1 },
|
|
61
|
+
/** Min value or token for the input. */
|
|
46
62
|
min: DOMString,
|
|
63
|
+
/** Minimum length for text-like inputs. */
|
|
47
64
|
minLength: { attr: 'minlength', type: 'integer', empty: -1 },
|
|
65
|
+
/** When true, multiple values are allowed (e.g. file inputs). */
|
|
48
66
|
multiple: 'boolean',
|
|
67
|
+
/** Pattern used for validation (RegExp as string). */
|
|
49
68
|
pattern: DOMString,
|
|
69
|
+
/** Placeholder text shown when no value is present. */
|
|
50
70
|
placeholder: DOMString,
|
|
71
|
+
/** Suggested control size (number of characters). */
|
|
51
72
|
size: { type: 'integer', empty: 20 },
|
|
73
|
+
/** Source URL for image-type inputs. */
|
|
52
74
|
src: DOMString,
|
|
75
|
+
/** Step interval for numeric inputs. */
|
|
53
76
|
step: DOMString,
|
|
54
77
|
// [CEReactions] attribute [LegacyNullToEmptyString] DOMString value;
|
|
78
|
+
/** Rendered width hint for certain input types (integer). */
|
|
55
79
|
_width: { attr: 'width', type: 'integer' },
|
|
56
80
|
})
|
|
81
|
+
.set({
|
|
82
|
+
_useFormImplicitSubmission: true,
|
|
83
|
+
})
|
|
57
84
|
.define({
|
|
58
85
|
// Alias for typescript
|
|
59
86
|
_input() { return /** @type {HTMLInputElement} */ (this.refs.control); },
|
|
60
87
|
})
|
|
88
|
+
.observe({
|
|
89
|
+
indeterminate: {
|
|
90
|
+
type: 'boolean',
|
|
91
|
+
get({ _indeterminate }) {
|
|
92
|
+
return _indeterminate;
|
|
93
|
+
},
|
|
94
|
+
/** @param {boolean} value */
|
|
95
|
+
set(value) {
|
|
96
|
+
this._input.indeterminate = value;
|
|
97
|
+
this._indeterminate = this._input.indeterminate;
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
})
|
|
61
101
|
.overrides({
|
|
62
102
|
controlTagName: 'input',
|
|
63
103
|
})
|
|
104
|
+
.recompose(({ refs: { control } }) => {
|
|
105
|
+
control.setAttribute('checked', '{defaultChecked}');
|
|
106
|
+
control.setAttribute('height', '{_height}');
|
|
107
|
+
control.setAttribute('width', '{_width}');
|
|
108
|
+
control.setAttribute('value', '{_defaultValue}');
|
|
109
|
+
})
|
|
64
110
|
.on({
|
|
65
|
-
composed() {
|
|
66
|
-
const { control } = this.refs;
|
|
67
|
-
control.setAttribute('checked', '{defaultChecked}');
|
|
68
|
-
control.setAttribute('height', '{_height}');
|
|
69
|
-
control.setAttribute('width', '{_width}');
|
|
70
|
-
control.setAttribute('value', '{_defaultValue}');
|
|
71
|
-
},
|
|
72
|
-
|
|
73
111
|
// TODO: Bind multiple
|
|
74
112
|
typeChanged() { this.onValueChangingContentAttribute(); },
|
|
75
|
-
|
|
76
|
-
this.
|
|
113
|
+
checkedChanged() {
|
|
114
|
+
this._input.checked = this.checked;
|
|
115
|
+
this._input.indeterminate = this._indeterminate;
|
|
116
|
+
},
|
|
117
|
+
_indeterminateChanged(previous, current) {
|
|
118
|
+
this._input.indeterminate = current;
|
|
77
119
|
},
|
|
78
120
|
minChanged() { this.onValueChangingContentAttribute(); },
|
|
79
121
|
minLengthChanged() { this.onValueChangingContentAttribute(); },
|
|
@@ -85,11 +127,9 @@ export default function InputMixin(Base) {
|
|
|
85
127
|
defaultValueChanged() { this.onValueChangingContentAttribute(); },
|
|
86
128
|
_formResetChanged(oldValue, newValue) {
|
|
87
129
|
if (!newValue) return;
|
|
88
|
-
|
|
130
|
+
this._onSetValue(this.defaultValue);
|
|
89
131
|
const input = this._input;
|
|
90
|
-
input.value = this.defaultValue;
|
|
91
132
|
input.checked = this.defaultChecked;
|
|
92
|
-
this._value = input.value;
|
|
93
133
|
this._checked = input.checked;
|
|
94
134
|
this._checkedDirty = false;
|
|
95
135
|
},
|
|
@@ -118,6 +158,7 @@ export default function InputMixin(Base) {
|
|
|
118
158
|
// Apply user value to input and read back result to apply control to parse
|
|
119
159
|
this._input.checked = checked;
|
|
120
160
|
this._checked = this._input.checked;
|
|
161
|
+
this.indeterminate = false;
|
|
121
162
|
},
|
|
122
163
|
_onSetValue(value) {
|
|
123
164
|
// Apply user value to input and read back result to apply control to parse
|
|
@@ -132,6 +173,7 @@ export default function InputMixin(Base) {
|
|
|
132
173
|
* @return {void}
|
|
133
174
|
*/
|
|
134
175
|
performImplicitSubmission(event) {
|
|
176
|
+
if (!this._useFormImplicitSubmission) return;
|
|
135
177
|
const form = this.form;
|
|
136
178
|
if (!form) return;
|
|
137
179
|
/** @type {HTMLInputElement} */
|
|
@@ -148,13 +190,125 @@ export default function InputMixin(Base) {
|
|
|
148
190
|
}
|
|
149
191
|
}
|
|
150
192
|
if (defaultButton) {
|
|
151
|
-
defaultButton.
|
|
193
|
+
defaultButton.dispatchEvent(new PointerEvent(
|
|
194
|
+
'click',
|
|
195
|
+
{ bubbles: true, cancelable: true, composed: true },
|
|
196
|
+
));
|
|
152
197
|
return;
|
|
153
198
|
}
|
|
154
199
|
if (submissionBlockers.size > 1) return;
|
|
155
200
|
this.form.submit();
|
|
156
201
|
},
|
|
202
|
+
/** @param {Event} event */
|
|
203
|
+
_redispatchControlClickEvent(event) {
|
|
204
|
+
event.stopPropagation();
|
|
205
|
+
// Use constructor to match mouse/pointer properties
|
|
206
|
+
/** @type {Event} */
|
|
207
|
+
// @ts-ignore skip-cast
|
|
208
|
+
const newEvent = (new event.constructor(event.type, event));
|
|
209
|
+
redispatchedClickEvents.add(newEvent);
|
|
210
|
+
return this.dispatchEvent(newEvent);
|
|
211
|
+
},
|
|
212
|
+
/** @param {MouseEvent} event */
|
|
213
|
+
_handleInputClick(event) {
|
|
214
|
+
if (this.disabledState) return;
|
|
215
|
+
const input = this._input;
|
|
216
|
+
switch (input.type) {
|
|
217
|
+
case 'checkbox':
|
|
218
|
+
case 'radio': {
|
|
219
|
+
const { _checkedDirty, _checked, _indeterminate } = this;
|
|
220
|
+
this.checked = input.checked;
|
|
221
|
+
// Event needs to be rethrown and preventDefault inspected
|
|
222
|
+
if (this._redispatchControlClickEvent(event)) return;
|
|
223
|
+
event.preventDefault();
|
|
224
|
+
this._checkedDirty = _checkedDirty;
|
|
225
|
+
this._checked = _checked;
|
|
226
|
+
this._indeterminate = _indeterminate;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
case 'button':
|
|
230
|
+
case 'submit':
|
|
231
|
+
case 'reset': {
|
|
232
|
+
if (!this._redispatchControlClickEvent(event)) {
|
|
233
|
+
event.preventDefault();
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const { type } = input;
|
|
237
|
+
if (type !== 'submit' && type !== 'reset') return;
|
|
238
|
+
// If in the composed path is another submit/reset button,
|
|
239
|
+
// Let that button take preference and ignore click.
|
|
240
|
+
|
|
241
|
+
for (const target of event.composedPath()) {
|
|
242
|
+
if (target === input || target === this) break;
|
|
243
|
+
if ((target instanceof HTMLInputElement || target instanceof HTMLButtonElement)
|
|
244
|
+
&& (target.type === 'submit' || target.type === 'reset')) {
|
|
245
|
+
// Inner Native Button
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
// @ts-expect-error Verified in runtime
|
|
249
|
+
if ((target instanceof HTMLElement && target.form instanceof HTMLFormElement
|
|
250
|
+
// @ts-expect-error Verified in runtime
|
|
251
|
+
&& (target.type === 'submit' || target.type === 'reset'))) {
|
|
252
|
+
// Inner FACE Button
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if ((target instanceof HTMLAnchorElement && target.href)) {
|
|
256
|
+
// Inner Anchor Button
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
157
260
|
|
|
261
|
+
const form = this.elementInternals?.form;
|
|
262
|
+
if (!form) return;
|
|
263
|
+
|
|
264
|
+
if (type === 'submit') {
|
|
265
|
+
const duplicatedButton = /** @type {HTMLInputElement} */ (input.cloneNode());
|
|
266
|
+
duplicatedButton.hidden = true;
|
|
267
|
+
form.append(duplicatedButton);
|
|
268
|
+
if ('requestSubmit' in form) {
|
|
269
|
+
form.requestSubmit(duplicatedButton);
|
|
270
|
+
} else {
|
|
271
|
+
duplicatedButton.click();
|
|
272
|
+
}
|
|
273
|
+
duplicatedButton.remove();
|
|
274
|
+
} else if (type === 'reset') {
|
|
275
|
+
form.reset();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
break;
|
|
279
|
+
default:
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
})
|
|
283
|
+
.rootEvents({
|
|
284
|
+
click(event) {
|
|
285
|
+
rootClickEvents.add(event);
|
|
286
|
+
const { control } = this.refs;
|
|
287
|
+
if (event.target === control) return;
|
|
288
|
+
// Label-like click
|
|
289
|
+
if (!event.bubbles) return;
|
|
290
|
+
const { disabledState, type } = this;
|
|
291
|
+
if (disabledState) return;
|
|
292
|
+
if (type === 'checkbox' || type === 'radio') {
|
|
293
|
+
event.stopPropagation();
|
|
294
|
+
control.click();
|
|
295
|
+
} else {
|
|
296
|
+
this._handleInputClick(event);
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
})
|
|
300
|
+
.events({
|
|
301
|
+
click(event) {
|
|
302
|
+
// If click event came from own shadowRoot, let it through
|
|
303
|
+
if (rootClickEvents.has(event)) return;
|
|
304
|
+
// If click event is a redispatch, let it through
|
|
305
|
+
if (redispatchedClickEvents.has(event)) return;
|
|
306
|
+
if (event.target === this) {
|
|
307
|
+
// Support custom host.dispatchEvent(new Event('click'))
|
|
308
|
+
event.stopImmediatePropagation();
|
|
309
|
+
this.refs.control.click();
|
|
310
|
+
}
|
|
311
|
+
},
|
|
158
312
|
})
|
|
159
313
|
.childEvents({
|
|
160
314
|
control: {
|
|
@@ -164,6 +318,16 @@ export default function InputMixin(Base) {
|
|
|
164
318
|
if (/** @type {HTMLInputElement} */ (event.currentTarget).type === 'submit') return;
|
|
165
319
|
this.performImplicitSubmission(event);
|
|
166
320
|
},
|
|
321
|
+
click: '_handleInputClick',
|
|
322
|
+
input(event) {
|
|
323
|
+
if (this.disabledState) {
|
|
324
|
+
event.preventDefault();
|
|
325
|
+
event.stopImmediatePropagation();
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const input = /** @type {HTMLInputElement} */ (event.currentTarget);
|
|
329
|
+
this.checked = input.checked;
|
|
330
|
+
},
|
|
167
331
|
change(event) {
|
|
168
332
|
if (this.disabledState) {
|
|
169
333
|
event.preventDefault();
|
|
@@ -171,15 +335,51 @@ export default function InputMixin(Base) {
|
|
|
171
335
|
return;
|
|
172
336
|
}
|
|
173
337
|
const input = /** @type {HTMLInputElement} */ (event.currentTarget);
|
|
174
|
-
this.
|
|
175
|
-
this._checked = input.checked;
|
|
338
|
+
this.checked = input.checked;
|
|
176
339
|
},
|
|
177
340
|
},
|
|
178
341
|
})
|
|
179
|
-
.
|
|
180
|
-
|
|
342
|
+
.methods({
|
|
343
|
+
/** @type {HTMLInputElement['setRangeText']} */
|
|
344
|
+
// @ts-ignore Can't cast?
|
|
345
|
+
setRangeText(...args) { this._input.setRangeText(...args); },
|
|
346
|
+
|
|
347
|
+
/** @type {HTMLInputElement['setSelectionRange']} */
|
|
348
|
+
setSelectionRange(...args) { this._input.setSelectionRange(...args); },
|
|
349
|
+
|
|
350
|
+
/** @type {HTMLInputElement['showPicker']} */
|
|
351
|
+
showPicker(...args) { this._input.showPicker(...args); },
|
|
181
352
|
|
|
182
|
-
|
|
353
|
+
/** @type {HTMLInputElement['stepDown']} */
|
|
354
|
+
stepDown(...args) {
|
|
355
|
+
this._input.stepDown(...args);
|
|
356
|
+
this._value = this._input.value;
|
|
357
|
+
},
|
|
358
|
+
|
|
359
|
+
/** @type {HTMLInputElement['stepUp']} */
|
|
360
|
+
stepUp(...args) {
|
|
361
|
+
this._input.stepUp(...args);
|
|
362
|
+
this._value = this._input.value;
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
/** @type {HTMLInputElement['select']} */
|
|
366
|
+
select(...args) {
|
|
367
|
+
this._input.select(...args);
|
|
368
|
+
},
|
|
369
|
+
})
|
|
370
|
+
.define({
|
|
371
|
+
files: {
|
|
372
|
+
get() { return this._input.files; },
|
|
373
|
+
set(value) {
|
|
374
|
+
if (value == null && this.type === 'file') {
|
|
375
|
+
// TODO: Clean up single-loop recursion
|
|
376
|
+
this._input.value = ''; // Clears files
|
|
377
|
+
this.value = '';
|
|
378
|
+
} else {
|
|
379
|
+
this._input.files = value;
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
},
|
|
183
383
|
|
|
184
384
|
selectionDirection: {
|
|
185
385
|
get() { return this._input.selectionDirection; },
|
|
@@ -196,16 +396,6 @@ export default function InputMixin(Base) {
|
|
|
196
396
|
set(value) { this._input.selectionStart = value; },
|
|
197
397
|
},
|
|
198
398
|
|
|
199
|
-
setRangeText() { return this._input.setRangeText; },
|
|
200
|
-
|
|
201
|
-
setSelectionRange() { return this._input.setSelectionRange; },
|
|
202
|
-
|
|
203
|
-
showPicker() { return this._input.showPicker; },
|
|
204
|
-
|
|
205
|
-
stepDown() { return this._input.stepDown; },
|
|
206
|
-
|
|
207
|
-
stepUp() { return this._input.stepUp; },
|
|
208
|
-
|
|
209
399
|
valueAsDate: {
|
|
210
400
|
get() { return this._input.valueAsDate; },
|
|
211
401
|
set(value) {
|
|
@@ -245,5 +435,10 @@ export default function InputMixin(Base) {
|
|
|
245
435
|
this._width = value;
|
|
246
436
|
},
|
|
247
437
|
},
|
|
248
|
-
})
|
|
438
|
+
})
|
|
439
|
+
.css`
|
|
440
|
+
#control::-webkit-file-upload-button {
|
|
441
|
+
display: none;
|
|
442
|
+
}
|
|
443
|
+
`;
|
|
249
444
|
}
|