@shortfuse/materialdesignweb 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -24
- package/bin/mdw-css.js +1 -1
- package/components/Badge.js +12 -5
- package/components/Body.js +3 -0
- package/components/BottomAppBar.js +1 -8
- package/components/BottomSheet.js +424 -0
- package/components/Box.js +11 -49
- package/components/Button.js +61 -82
- package/components/Card.js +56 -61
- package/components/Checkbox.js +7 -25
- package/components/CheckboxIcon.js +10 -28
- package/components/Chip.js +13 -11
- package/components/Dialog.js +49 -98
- package/components/Display.js +55 -0
- package/components/Fab.js +83 -17
- package/components/FabContainer.js +48 -0
- package/components/FilterChip.js +34 -32
- package/components/Grid.js +176 -0
- package/components/Headline.js +5 -28
- package/components/Icon.js +54 -69
- package/components/IconButton.js +71 -120
- package/components/Input.js +669 -83
- package/components/InputChip.js +161 -0
- package/components/Label.js +3 -0
- package/components/List.js +1 -5
- package/components/ListItem.js +39 -23
- package/components/ListOption.js +79 -62
- package/components/Listbox.js +19 -10
- package/components/Menu.js +8 -18
- package/components/MenuItem.js +25 -26
- package/components/NavBar.js +53 -19
- package/components/NavDrawer.js +15 -15
- package/components/NavDrawerItem.js +2 -4
- package/components/NavItem.js +40 -33
- package/components/NavRail.js +23 -21
- package/components/NavRailItem.js +5 -2
- package/components/Page.js +105 -0
- package/components/Pane.js +18 -0
- package/components/Popup.js +17 -8
- package/components/Radio.js +2 -5
- package/components/RadioIcon.js +10 -14
- package/components/Ripple.js +11 -7
- package/components/Root.js +209 -0
- package/components/Scrim.js +87 -0
- package/components/Search.js +12 -20
- package/components/SegmentedButton.js +33 -36
- package/components/SegmentedButtonGroup.js +9 -3
- package/components/Select.js +6 -7
- package/components/Shape.js +5 -65
- package/components/SideSheet.js +308 -0
- package/components/Slider.js +71 -34
- package/components/Snackbar.js +22 -16
- package/components/SnackbarContainer.js +42 -0
- package/components/Surface.js +15 -10
- package/components/Switch.js +3 -16
- package/components/SwitchIcon.js +40 -32
- package/components/Tab.js +57 -38
- package/components/TabContent.js +1 -0
- package/components/TabList.js +60 -32
- package/components/TabPanel.js +1 -1
- package/components/Table.js +116 -0
- package/components/TextArea.js +16 -15
- package/components/Title.js +4 -9
- package/components/Tooltip.js +43 -21
- package/components/TopAppBar.js +56 -78
- package/constants/shapes.js +36 -0
- package/constants/typography.js +127 -0
- package/core/Composition.js +354 -192
- package/core/CompositionAdapter.js +11 -12
- package/core/CustomElement.js +588 -236
- package/core/css.js +117 -12
- package/core/customTypes.js +120 -25
- package/core/dom.js +17 -11
- package/core/jsonMergePatch.js +12 -10
- package/core/observe.js +298 -253
- package/core/optimizations.js +9 -9
- package/core/template.js +14 -57
- 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 +106 -0
- package/{theming/themableMixinLoader.js → loaders/palette.js} +4 -3
- package/loaders/theme.js +12 -0
- package/mixins/AriaReflectorMixin.js +53 -13
- package/mixins/AriaToolbarMixin.js +3 -0
- package/mixins/ControlMixin.js +76 -33
- package/mixins/DelegatesFocusMixin.js +54 -0
- package/mixins/DensityMixin.js +2 -2
- package/mixins/ElevationMixin.js +62 -0
- package/mixins/FlexableMixin.js +66 -37
- package/mixins/FormAssociatedMixin.js +60 -8
- package/mixins/HyperlinkMixin.js +66 -0
- package/mixins/InputMixin.js +205 -32
- package/mixins/KeyboardNavMixin.js +8 -6
- package/mixins/NavigationListenerMixin.js +33 -0
- package/mixins/PopupMixin.js +176 -208
- package/mixins/ResizeObserverMixin.js +16 -4
- package/mixins/RippleMixin.js +8 -6
- package/mixins/ScrollListenerMixin.js +1 -1
- package/mixins/SemiStickyMixin.js +44 -98
- package/mixins/ShapeMaskedMixin.js +117 -0
- package/mixins/ShapeMixin.js +22 -204
- package/mixins/StateMixin.js +70 -34
- package/mixins/TextFieldMixin.js +107 -143
- package/mixins/ThemableMixin.js +44 -56
- package/mixins/TooltipTriggerMixin.js +291 -359
- package/mixins/TouchTargetMixin.js +1 -1
- package/mixins/TypographyMixin.js +121 -0
- package/package.json +110 -74
- package/services/rtl.js +10 -0
- package/services/svgAlias.js +17 -0
- package/{theming/index.js → services/theme.js} +24 -174
- 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 +73 -0
- package/types/components/BottomAppBar.d.ts.map +1 -0
- package/types/components/BottomSheet.d.ts +109 -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 +714 -0
- package/types/components/Button.d.ts.map +1 -0
- package/types/components/Card.d.ts +412 -0
- package/types/components/Card.d.ts.map +1 -0
- package/types/components/Checkbox.d.ts +205 -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 +1425 -0
- package/types/components/Chip.d.ts.map +1 -0
- package/types/components/Dialog.d.ts +286 -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 +45 -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 +741 -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 +4283 -0
- package/types/components/FilterChip.d.ts.map +1 -0
- package/types/components/Grid.d.ts +37 -0
- package/types/components/Grid.d.ts.map +1 -0
- package/types/components/Headline.d.ts +47 -0
- package/types/components/Headline.d.ts.map +1 -0
- package/types/components/Icon.d.ts +103 -0
- package/types/components/Icon.d.ts.map +1 -0
- package/types/components/IconButton.d.ts +1486 -0
- package/types/components/IconButton.d.ts.map +1 -0
- package/types/components/Input.d.ts +51288 -0
- package/types/components/Input.d.ts.map +1 -0
- package/types/components/InputChip.d.ts +243 -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 +31 -0
- package/types/components/List.d.ts.map +1 -0
- package/types/components/ListItem.d.ts +349 -0
- package/types/components/ListItem.d.ts.map +1 -0
- package/types/components/ListOption.d.ts +1493 -0
- package/types/components/ListOption.d.ts.map +1 -0
- package/types/components/Listbox.d.ts +12012 -0
- package/types/components/Listbox.d.ts.map +1 -0
- package/types/components/Menu.d.ts +119 -0
- package/types/components/Menu.d.ts.map +1 -0
- package/types/components/MenuItem.d.ts +3109 -0
- package/types/components/MenuItem.d.ts.map +1 -0
- package/types/components/NavBar.d.ts +18 -0
- package/types/components/NavBar.d.ts.map +1 -0
- package/types/components/NavBarItem.d.ts +186 -0
- package/types/components/NavBarItem.d.ts.map +1 -0
- package/types/components/NavDrawer.d.ts +108 -0
- package/types/components/NavDrawer.d.ts.map +1 -0
- package/types/components/NavDrawerItem.d.ts +186 -0
- package/types/components/NavDrawerItem.d.ts.map +1 -0
- package/types/components/NavItem.d.ts +190 -0
- package/types/components/NavItem.d.ts.map +1 -0
- package/types/components/NavRail.d.ts +109 -0
- package/types/components/NavRail.d.ts.map +1 -0
- package/types/components/NavRailItem.d.ts +186 -0
- package/types/components/NavRailItem.d.ts.map +1 -0
- package/types/components/Page.d.ts +24 -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 +76 -0
- package/types/components/Popup.d.ts.map +1 -0
- package/types/components/Progress.d.ts +19 -0
- package/types/components/Progress.d.ts.map +1 -0
- package/types/components/Radio.d.ts +199 -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 +34 -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 +16 -0
- package/types/components/Search.d.ts.map +1 -0
- package/types/components/SegmentedButton.d.ts +718 -0
- package/types/components/SegmentedButton.d.ts.map +1 -0
- package/types/components/SegmentedButtonGroup.d.ts +44 -0
- package/types/components/SegmentedButtonGroup.d.ts.map +1 -0
- package/types/components/Select.d.ts +1361 -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 +106 -0
- package/types/components/SideSheet.d.ts.map +1 -0
- package/types/components/Slider.d.ts +382 -0
- package/types/components/Slider.d.ts.map +1 -0
- package/types/components/Snackbar.d.ts +65 -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 +183 -0
- package/types/components/Switch.d.ts.map +1 -0
- package/types/components/SwitchIcon.d.ts +169 -0
- package/types/components/SwitchIcon.d.ts.map +1 -0
- package/types/components/Tab.d.ts +879 -0
- package/types/components/Tab.d.ts.map +1 -0
- package/types/components/TabContent.d.ts +122 -0
- package/types/components/TabContent.d.ts.map +1 -0
- package/types/components/TabList.d.ts +6266 -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 +2 -0
- package/types/components/Table.d.ts.map +1 -0
- package/types/components/TextArea.d.ts +1394 -0
- package/types/components/TextArea.d.ts.map +1 -0
- package/types/components/Title.d.ts +47 -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 +130 -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 +252 -0
- package/types/core/Composition.d.ts.map +1 -0
- package/types/core/CompositionAdapter.d.ts +92 -0
- package/types/core/CompositionAdapter.d.ts.map +1 -0
- package/types/core/CustomElement.d.ts +302 -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 +26 -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 +113 -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 +23 -0
- package/types/mixins/AriaReflectorMixin.d.ts.map +1 -0
- package/types/mixins/AriaToolbarMixin.d.ts +32 -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 +5 -0
- package/types/mixins/DelegatesFocusMixin.d.ts.map +1 -0
- package/types/mixins/DensityMixin.d.ts +5 -0
- package/types/mixins/DensityMixin.d.ts.map +1 -0
- package/types/mixins/ElevationMixin.d.ts +33 -0
- package/types/mixins/ElevationMixin.d.ts.map +1 -0
- package/types/mixins/FlexableMixin.d.ts +13 -0
- package/types/mixins/FlexableMixin.d.ts.map +1 -0
- package/types/mixins/FormAssociatedMixin.d.ts +122 -0
- package/types/mixins/FormAssociatedMixin.d.ts.map +1 -0
- package/types/mixins/HyperlinkMixin.d.ts +22 -0
- package/types/mixins/HyperlinkMixin.d.ts.map +1 -0
- package/types/mixins/InputMixin.d.ts +179 -0
- package/types/mixins/InputMixin.d.ts.map +1 -0
- package/types/mixins/KeyboardNavMixin.d.ts +47 -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 +82 -0
- package/types/mixins/PopupMixin.d.ts.map +1 -0
- package/types/mixins/RTLObserverMixin.d.ts +7 -0
- package/types/mixins/RTLObserverMixin.d.ts.map +1 -0
- package/types/mixins/ResizeObserverMixin.d.ts +12 -0
- package/types/mixins/ResizeObserverMixin.d.ts.map +1 -0
- package/types/mixins/RippleMixin.d.ts +92 -0
- package/types/mixins/RippleMixin.d.ts.map +1 -0
- package/types/mixins/ScrollListenerMixin.d.ts +41 -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 +9 -0
- package/types/mixins/ShapeMaskedMixin.d.ts.map +1 -0
- package/types/mixins/ShapeMixin.d.ts +38 -0
- package/types/mixins/ShapeMixin.d.ts.map +1 -0
- package/types/mixins/StateMixin.d.ts +27 -0
- package/types/mixins/StateMixin.d.ts.map +1 -0
- package/types/mixins/TextFieldMixin.d.ts +1354 -0
- package/types/mixins/TextFieldMixin.d.ts.map +1 -0
- package/types/mixins/ThemableMixin.d.ts +9 -0
- package/types/mixins/ThemableMixin.d.ts.map +1 -0
- package/types/mixins/TooltipTriggerMixin.d.ts +106 -0
- package/types/mixins/TooltipTriggerMixin.d.ts.map +1 -0
- package/types/mixins/TouchTargetMixin.d.ts +3 -0
- package/types/mixins/TouchTargetMixin.d.ts.map +1 -0
- package/types/mixins/TypographyMixin.d.ts +17 -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/material-color/scheme/Scheme.js +1 -1
- package/utils/pixelmatch.js +360 -0
- package/utils/popup.js +86 -10
- package/utils/searchParams.js +19 -0
- 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
package/core/CustomElement.js
CHANGED
|
@@ -1,11 +1,117 @@
|
|
|
1
1
|
/* eslint-disable max-classes-per-file */
|
|
2
2
|
|
|
3
3
|
import Composition from './Composition.js';
|
|
4
|
-
import {
|
|
4
|
+
import { css } from './css.js';
|
|
5
5
|
import { attrNameFromPropName, attrValueFromDataValue } from './dom.js';
|
|
6
6
|
import { applyMergePatch } from './jsonMergePatch.js';
|
|
7
7
|
import { defineObservableProperty } from './observe.js';
|
|
8
|
-
import { addInlineFunction,
|
|
8
|
+
import { addInlineFunction, html } from './template.js';
|
|
9
|
+
|
|
10
|
+
/** @typedef {import('./observe.js').ObserverPropertyType} ObserverPropertyType */
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @template {any} T
|
|
14
|
+
* @typedef {{
|
|
15
|
+
* [P in keyof T]:
|
|
16
|
+
* T[P] extends (...args:any[]) => infer T2 ? T2
|
|
17
|
+
* : T[P] extends ObserverPropertyType
|
|
18
|
+
* ? import('./observe.js').ParsedObserverPropertyType<T[P]>
|
|
19
|
+
* : T[P] extends {type: ObserverPropertyType}
|
|
20
|
+
* ? import('./observe.js').ParsedObserverPropertyType<T[P]['type']>
|
|
21
|
+
* : T[P] extends ObserverOptions<null, infer T2>
|
|
22
|
+
* ? unknown extends T2 ? string : T2
|
|
23
|
+
* : never
|
|
24
|
+
* }} ParsedProps
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @template {ObserverPropertyType} T1
|
|
29
|
+
* @template {any} T2
|
|
30
|
+
* @template {Object} [C=any]
|
|
31
|
+
* @typedef {import('./observe.js').ObserverOptions<T1,T2,C>} ObserverOptions
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @template {{ prototype: unknown; }} T
|
|
36
|
+
* @typedef {T} ClassOf<T>
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @template {any} [T=any]
|
|
41
|
+
* @template {any[]} [A=any[]]
|
|
42
|
+
* @typedef {abstract new (...args: A) => T} Class
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @template {any} T1
|
|
47
|
+
* @template {any} [T2=T1]
|
|
48
|
+
* @callback HTMLTemplater
|
|
49
|
+
* @param {TemplateStringsArray} string
|
|
50
|
+
* @param {...(string|DocumentFragment|Element|((this:T1, data:T2) => any))} substitutions
|
|
51
|
+
* @return {DocumentFragment}
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @template {any} [T1=any]
|
|
56
|
+
* @template {any} [T2=T1]
|
|
57
|
+
* @typedef {Object} CallbackArguments
|
|
58
|
+
* @prop {Composition<T1>} composition
|
|
59
|
+
* @prop {Record<string, HTMLElement>} refs
|
|
60
|
+
* @prop {HTMLTemplater<T1, Partial<T2>>} html
|
|
61
|
+
* @prop {(fn: (this:T1, data: T2) => any) => string} inline
|
|
62
|
+
* @prop {DocumentFragment} template
|
|
63
|
+
* @prop {T1} element
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @template {any} T1
|
|
68
|
+
* @template {any} [T2=T1]
|
|
69
|
+
* @typedef {{
|
|
70
|
+
* composed?: (this: T1, options: CallbackArguments<T1, T2>) => any,
|
|
71
|
+
* constructed?: (this: T1, options: CallbackArguments<T1, T2>) => any,
|
|
72
|
+
* connected?: (this: T1, options: CallbackArguments<T1, T2>) => any,
|
|
73
|
+
* disconnected?: (this: T1, options: CallbackArguments<T1, T2>) => any,
|
|
74
|
+
* props?: {
|
|
75
|
+
* [P in keyof T1] : (
|
|
76
|
+
* this: T1,
|
|
77
|
+
* oldValue: T1[P],
|
|
78
|
+
* newValue: T1[P],
|
|
79
|
+
* changes:any,
|
|
80
|
+
* element: T1
|
|
81
|
+
* ) => any
|
|
82
|
+
* },
|
|
83
|
+
* attrs?: {[K in keyof any]: (
|
|
84
|
+
* this: T1,
|
|
85
|
+
* oldValue: string,
|
|
86
|
+
* newValue: string,
|
|
87
|
+
* element: T1
|
|
88
|
+
* ) => unknown
|
|
89
|
+
* },
|
|
90
|
+
* } & {
|
|
91
|
+
* [P in keyof T1 & string as `${P}Changed`]?: (
|
|
92
|
+
* this: T1,
|
|
93
|
+
* oldValue: T1[P],
|
|
94
|
+
* newValue: T1[P],
|
|
95
|
+
* changes:any,
|
|
96
|
+
* element: T1
|
|
97
|
+
* ) => any
|
|
98
|
+
* }} CompositionCallback
|
|
99
|
+
*/
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @template {Object} C
|
|
103
|
+
* @typedef {{
|
|
104
|
+
* [P in string] :
|
|
105
|
+
* ObserverPropertyType
|
|
106
|
+
* | ObserverOptions<ObserverPropertyType, unknown, C>
|
|
107
|
+
* | ((this:C, data:Partial<C>, fn?: () => any) => any)
|
|
108
|
+
* }} IDLParameter
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @template T
|
|
113
|
+
* @typedef {(T | Array<[keyof T & string, T[keyof T]]>)} ObjectOrObjectEntries
|
|
114
|
+
*/
|
|
9
115
|
|
|
10
116
|
/**
|
|
11
117
|
* @template {abstract new (...args: any) => unknown} T
|
|
@@ -33,57 +139,49 @@ export function cloneAttributeCallback(name, target) {
|
|
|
33
139
|
};
|
|
34
140
|
}
|
|
35
141
|
|
|
36
|
-
const EVENT_PREFIX_REGEX = /^([*1~]+)?(.*)$/;
|
|
37
|
-
|
|
38
142
|
/**
|
|
39
143
|
* Web Component that can cache templates for minification or performance
|
|
40
144
|
*/
|
|
41
|
-
export default class CustomElement extends
|
|
145
|
+
export default class CustomElement extends HTMLElement {
|
|
42
146
|
/** @type {string} */
|
|
43
147
|
static elementName;
|
|
44
148
|
|
|
45
149
|
/** @return {Iterable<string>} */
|
|
46
150
|
static get observedAttributes() {
|
|
47
|
-
|
|
48
|
-
for (const config of this.propList.values()) {
|
|
49
|
-
if (config.reflect === true || config.reflect === 'read') {
|
|
50
|
-
s.add(config.attr);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return s;
|
|
151
|
+
return this.attrList.keys();
|
|
54
152
|
}
|
|
55
153
|
|
|
56
154
|
/** @type {import('./Composition.js').Compositor<?>} */
|
|
57
155
|
compose() {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
this.#composition = new Composition();
|
|
62
|
-
return this.#composition;
|
|
156
|
+
// eslint-disable-next-line no-return-assign
|
|
157
|
+
return (this.#composition ??= new Composition());
|
|
63
158
|
}
|
|
64
159
|
|
|
65
160
|
/** @type {Composition<?>} */
|
|
66
161
|
static _composition = null;
|
|
67
162
|
|
|
68
|
-
/** @type {Map<string, import('./
|
|
163
|
+
/** @type {Map<string, import('./observe.js').ObserverConfiguration<?,?,?>>} */
|
|
69
164
|
static _props = new Map();
|
|
70
165
|
|
|
166
|
+
/** @type {Map<string, import('./observe.js').ObserverConfiguration<?,?,?>>} */
|
|
167
|
+
static _attrs = new Map();
|
|
168
|
+
|
|
71
169
|
/** @type {Map<string, Function[]>} */
|
|
72
170
|
static _propChangedCallbacks = new Map();
|
|
73
171
|
|
|
74
172
|
/** @type {Map<string, Function[]>} */
|
|
75
173
|
static _attributeChangedCallbacks = new Map();
|
|
76
174
|
|
|
77
|
-
/** @type {
|
|
175
|
+
/** @type {((callback: CallbackArguments) => any)[]} */
|
|
78
176
|
static _onComposeCallbacks = [];
|
|
79
177
|
|
|
80
|
-
/** @type {
|
|
178
|
+
/** @type {((callback: CallbackArguments) => any)[]} */
|
|
81
179
|
static _onConnectedCallbacks = [];
|
|
82
180
|
|
|
83
|
-
/** @type {
|
|
181
|
+
/** @type {((callback: CallbackArguments) => any)[]} */
|
|
84
182
|
static _onDisconnectedCallbacks = [];
|
|
85
183
|
|
|
86
|
-
/** @type {
|
|
184
|
+
/** @type {((callback: CallbackArguments) => any)[]} */
|
|
87
185
|
static _onConstructedCallbacks = [];
|
|
88
186
|
|
|
89
187
|
static interpolatesTemplate = true;
|
|
@@ -103,68 +201,189 @@ export default class CustomElement extends ICustomElement {
|
|
|
103
201
|
/** @type {Map<string, typeof CustomElement>} */
|
|
104
202
|
static registrations = new Map();
|
|
105
203
|
|
|
106
|
-
/**
|
|
107
|
-
|
|
204
|
+
/**
|
|
205
|
+
* Expressions are idempotent functions that are selectively called whenever
|
|
206
|
+
* a render is requested.
|
|
207
|
+
* Expressions are constructed exactly as methods though differ in expected
|
|
208
|
+
* arguments. The first argument should be destructured to ensure each used
|
|
209
|
+
* property is accessed at least once in order to inspect used properties.
|
|
210
|
+
*
|
|
211
|
+
* The Composition API will inspect this function with a proxy for `this` to
|
|
212
|
+
* catalog what observables are used by the expression. This allows the
|
|
213
|
+
* Composition API to build a cache as well as selective invoke the expression
|
|
214
|
+
* only when needed.
|
|
215
|
+
*
|
|
216
|
+
* When used with in element templates, the element itself will be passed as
|
|
217
|
+
* its first argument.
|
|
218
|
+
* ````js
|
|
219
|
+
* Button
|
|
220
|
+
* .prop('filled', 'boolean')
|
|
221
|
+
* .prop('outlined', 'boolean')
|
|
222
|
+
* .expresssions({
|
|
223
|
+
* _isFilledOrOutlined({filled, outlined}) {
|
|
224
|
+
* return (filled || outlined)
|
|
225
|
+
* },
|
|
226
|
+
* })
|
|
227
|
+
* .html`<div custom={_isFilledOrOutlined}></div>`;
|
|
228
|
+
* ````
|
|
229
|
+
*
|
|
230
|
+
* When used with external data source, that data source
|
|
231
|
+
* will be passed to the expression with all properties being `null` at first
|
|
232
|
+
* inspection.
|
|
233
|
+
* ````js
|
|
234
|
+
* const externalData = {first: 'John', last: 'Doe'};
|
|
235
|
+
* ContactCard
|
|
236
|
+
* .expresssions({
|
|
237
|
+
* _fullName({first, last}) {
|
|
238
|
+
* return [first, last].filter(Boolean).join(' ');
|
|
239
|
+
* },
|
|
240
|
+
* })
|
|
241
|
+
* myButton.render(externalData);
|
|
242
|
+
* ````
|
|
243
|
+
*
|
|
244
|
+
* Expressions may be support argumentless calls by using default
|
|
245
|
+
* parameters with `this`.
|
|
246
|
+
* ````js
|
|
247
|
+
* Button
|
|
248
|
+
* .expresssions({
|
|
249
|
+
* isFilledOrOutlined({filled, outlined} = this) {
|
|
250
|
+
* return (filled || outlined)
|
|
251
|
+
* },
|
|
252
|
+
* });
|
|
253
|
+
* myButton.isFilledorOutlined();
|
|
254
|
+
* ````
|
|
255
|
+
* @type {{
|
|
256
|
+
* <
|
|
257
|
+
* CLASS extends typeof CustomElement,
|
|
258
|
+
* ARGS extends ConstructorParameters<CLASS>,
|
|
259
|
+
* INSTANCE extends InstanceType<CLASS>,
|
|
260
|
+
* PROPS extends {
|
|
261
|
+
* [K in keyof any]: K extends `_${any}` ? ((data: INSTANCE, state?: Record<string, any>) => string|boolean|null)
|
|
262
|
+
* : ((data?: INSTANCE, state?: Record<string, any>) => string|boolean|null)
|
|
263
|
+
* } & ThisType<INSTANCE>
|
|
264
|
+
* >(this: CLASS, expressions: PROPS & ThisType<INSTANCE & PROPS>):
|
|
265
|
+
* CLASS & Class<{
|
|
266
|
+
* [K in keyof PROPS]: K extends `_${any}` ? never : () => ReturnType<PROPS[K]> }
|
|
267
|
+
* ,ARGS>
|
|
268
|
+
* }}
|
|
269
|
+
*/
|
|
270
|
+
static expressions = /** @type {any} */ (this.set);
|
|
108
271
|
|
|
109
|
-
/** @type {typeof ICustomElement.methods} */
|
|
110
272
|
static methods = this.set;
|
|
111
273
|
|
|
112
|
-
/**
|
|
113
|
-
|
|
274
|
+
/**
|
|
275
|
+
* @type {{
|
|
276
|
+
* <
|
|
277
|
+
* CLASS extends typeof CustomElement,
|
|
278
|
+
* ARGS extends ConstructorParameters<CLASS>,
|
|
279
|
+
* INSTANCE extends InstanceType<CLASS>,
|
|
280
|
+
* PROPS extends Partial<INSTANCE>>
|
|
281
|
+
* (this: CLASS, source: PROPS & ThisType<PROPS & INSTANCE>, options?: Partial<PropertyDescriptor>)
|
|
282
|
+
* : CLASS & Class<PROPS,ARGS>
|
|
283
|
+
* }}
|
|
284
|
+
*/
|
|
285
|
+
static overrides = /** @type {any} */ (this.set);
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* @type {{
|
|
289
|
+
* <
|
|
290
|
+
* CLASS extends typeof CustomElement,
|
|
291
|
+
* ARGS extends ConstructorParameters<CLASS>,
|
|
292
|
+
* INSTANCE extends InstanceType<CLASS>,
|
|
293
|
+
* KEY extends string,
|
|
294
|
+
* OPTIONS extends ObserverPropertyType
|
|
295
|
+
* | ObserverOptions<ObserverPropertyType, unknown, INSTANCE>
|
|
296
|
+
* | ((this:INSTANCE, data:Partial<INSTANCE>, fn?: () => any) => any),
|
|
297
|
+
* VALUE extends Record<KEY, OPTIONS extends (...args2:any[]) => infer R ? R
|
|
298
|
+
* : OPTIONS extends ObserverPropertyType ? import('./observe.js').ParsedObserverPropertyType<OPTIONS>
|
|
299
|
+
* : OPTIONS extends {type: 'object'} & ObserverOptions<any, infer R> ? (unknown extends R ? object : R)
|
|
300
|
+
* : OPTIONS extends {type: ObserverPropertyType} ? import('./observe.js').ParsedObserverPropertyType<OPTIONS['type']>
|
|
301
|
+
* : OPTIONS extends ObserverOptions<any, infer R> ? (unknown extends R ? string : R)
|
|
302
|
+
* : never
|
|
303
|
+
* >
|
|
304
|
+
* > (this: CLASS, name: KEY, options: OPTIONS)
|
|
305
|
+
* : CLASS & Class<VALUE,ARGS>;
|
|
306
|
+
* }}
|
|
307
|
+
*/
|
|
308
|
+
static props = /** @type {any} */ (this.observe);
|
|
114
309
|
|
|
115
|
-
|
|
116
|
-
static props = this.observe;
|
|
310
|
+
static idl = this.prop;
|
|
117
311
|
|
|
118
312
|
/**
|
|
119
|
-
* @template {typeof CustomElement} T
|
|
120
313
|
* @this T
|
|
314
|
+
* @template {typeof CustomElement} T
|
|
121
315
|
* @template {keyof T} K
|
|
122
316
|
* @param {K} collection
|
|
123
317
|
* @param {T[K] extends (infer R)[] ? R : never} callback
|
|
124
318
|
*/
|
|
125
319
|
static _addCallback(collection, callback) {
|
|
126
320
|
if (!this.hasOwnProperty(collection)) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
321
|
+
// @ts-expect-error not typed
|
|
322
|
+
this[collection] = [...this[collection], callback];
|
|
323
|
+
return;
|
|
130
324
|
}
|
|
325
|
+
// @ts-expect-error any
|
|
131
326
|
this[collection].push(callback);
|
|
132
327
|
}
|
|
133
328
|
|
|
134
329
|
/**
|
|
135
330
|
* Append parts to composition
|
|
136
|
-
* @type {
|
|
331
|
+
* @type {{
|
|
332
|
+
* <
|
|
333
|
+
* T extends typeof CustomElement,
|
|
334
|
+
* >
|
|
335
|
+
* (this: T, ...parts: ConstructorParameters<typeof Composition<InstanceType<T>>>): T;
|
|
336
|
+
* }}
|
|
137
337
|
*/
|
|
138
338
|
static append(...parts) {
|
|
139
|
-
this.
|
|
140
|
-
|
|
141
|
-
// console.debug('onComposed:append', ...parts);
|
|
142
|
-
composition.append(...parts);
|
|
143
|
-
},
|
|
339
|
+
this._addCallback('_onComposeCallbacks', ({ composition }) => {
|
|
340
|
+
composition.append(...parts);
|
|
144
341
|
});
|
|
145
342
|
// @ts-expect-error Can't cast T
|
|
146
343
|
return this;
|
|
147
344
|
}
|
|
148
345
|
|
|
149
346
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
347
|
+
* After composition, invokes callback.
|
|
348
|
+
* May be called multiple times.
|
|
349
|
+
* @type {{
|
|
350
|
+
* <
|
|
351
|
+
* T1 extends typeof CustomElement,
|
|
352
|
+
* T2 extends InstanceType<T1>,
|
|
353
|
+
* T3 extends CompositionCallback<T2, T2>['composed'],
|
|
354
|
+
* >
|
|
355
|
+
* (this: T1, callback: T3): T1
|
|
356
|
+
* }}
|
|
152
357
|
*/
|
|
153
|
-
static
|
|
154
|
-
|
|
155
|
-
// @ts-expect-error Complex cast
|
|
156
|
-
this.append(css(array, ...substitutions));
|
|
157
|
-
} else {
|
|
158
|
-
// @ts-expect-error Complex cast
|
|
159
|
-
this.append(array, ...substitutions);
|
|
160
|
-
}
|
|
358
|
+
static recompose(callback) {
|
|
359
|
+
this._addCallback('_onComposeCallbacks', callback);
|
|
161
360
|
// @ts-expect-error Can't cast T
|
|
162
361
|
return this;
|
|
163
362
|
}
|
|
164
363
|
|
|
165
|
-
/**
|
|
166
|
-
|
|
167
|
-
|
|
364
|
+
/**
|
|
365
|
+
* Appends styles to composition
|
|
366
|
+
* @type {{
|
|
367
|
+
* <
|
|
368
|
+
* T1 extends typeof CustomElement,
|
|
369
|
+
* T2 extends TemplateStringsArray|HTMLStyleElement|CSSStyleSheet|string>(
|
|
370
|
+
* this: T1,
|
|
371
|
+
* array: T2,
|
|
372
|
+
* ...rest: T2 extends string ? any : T2 extends TemplateStringsArray ? any[] : (HTMLStyleElement|CSSStyleSheet)[]
|
|
373
|
+
* ): T1
|
|
374
|
+
* }}
|
|
375
|
+
*/
|
|
376
|
+
static css(array, ...substitutions) {
|
|
377
|
+
this._addCallback('_onComposeCallbacks', ({ composition }) => {
|
|
378
|
+
if (typeof array === 'string' || Array.isArray(array)) {
|
|
379
|
+
// @ts-expect-error Complex cast
|
|
380
|
+
composition.append(css(array, ...substitutions));
|
|
381
|
+
} else {
|
|
382
|
+
// @ts-expect-error Complex cast
|
|
383
|
+
composition.append(array, ...substitutions);
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
|
|
168
387
|
// @ts-expect-error Can't cast T
|
|
169
388
|
return this;
|
|
170
389
|
}
|
|
@@ -173,7 +392,9 @@ export default class CustomElement extends ICustomElement {
|
|
|
173
392
|
* Registers class asynchronously at end of current event loop cycle
|
|
174
393
|
* via `queueMicrotask`. If class is registered before then,
|
|
175
394
|
* does nothing.
|
|
176
|
-
* @type {
|
|
395
|
+
* @type {{
|
|
396
|
+
* <T extends typeof CustomElement>(this: T, elementName: string): T;
|
|
397
|
+
* }}
|
|
177
398
|
*/
|
|
178
399
|
static autoRegister(elementName) {
|
|
179
400
|
if (this.hasOwnProperty('defined') && this.defined) {
|
|
@@ -188,14 +409,18 @@ export default class CustomElement extends ICustomElement {
|
|
|
188
409
|
|
|
189
410
|
/**
|
|
190
411
|
* Appends DocumentFragment to composition
|
|
191
|
-
* @type {
|
|
412
|
+
* @type {{
|
|
413
|
+
* <T extends typeof CustomElement>(
|
|
414
|
+
* this: T,
|
|
415
|
+
* string: TemplateStringsArray,
|
|
416
|
+
* ...substitutions: (string|Element|((this:InstanceType<T>, data:InstanceType<T>, injections?:any) => any))[]
|
|
417
|
+
* ): T
|
|
418
|
+
* }}
|
|
192
419
|
*/
|
|
193
420
|
static html(strings, ...substitutions) {
|
|
194
|
-
this.
|
|
195
|
-
composed({ composition }) {
|
|
421
|
+
this._addCallback('_onComposeCallbacks', ({ composition }) => {
|
|
196
422
|
// console.log('onComposed:html', strings);
|
|
197
|
-
|
|
198
|
-
},
|
|
423
|
+
composition.append(html(strings, ...substitutions));
|
|
199
424
|
});
|
|
200
425
|
// @ts-expect-error Can't cast T
|
|
201
426
|
return this;
|
|
@@ -204,26 +429,28 @@ export default class CustomElement extends ICustomElement {
|
|
|
204
429
|
/**
|
|
205
430
|
* Extends base class into a new class.
|
|
206
431
|
* Use to avoid mutating base class.
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
// @ts-expect-error Can't cast T
|
|
212
|
-
return class extends this {};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Fix for Typescript not parsing constructor params
|
|
217
|
-
* @type {typeof ICustomElement.tsClassFix}
|
|
432
|
+
* @type {{
|
|
433
|
+
* <T1 extends typeof CustomElement, T2 extends T1, T3 extends (Base:T1) => T2>
|
|
434
|
+
* (this: T1,customExtender?: T3|null): T3 extends null ? T1 : T2;
|
|
435
|
+
* }}
|
|
218
436
|
*/
|
|
219
|
-
static
|
|
437
|
+
static extend(customExtender) {
|
|
220
438
|
// @ts-expect-error Can't cast T
|
|
221
|
-
return this;
|
|
439
|
+
return customExtender ? customExtender(this) : class extends this {};
|
|
222
440
|
}
|
|
223
441
|
|
|
224
442
|
/**
|
|
225
443
|
* Assigns static values to class
|
|
226
|
-
* @type {
|
|
444
|
+
* @type {{
|
|
445
|
+
* <
|
|
446
|
+
* T1 extends typeof CustomElement,
|
|
447
|
+
* T2 extends {
|
|
448
|
+
* [K in keyof any]: (
|
|
449
|
+
* ((this:T1, ...args:any[]) => any)
|
|
450
|
+
* |string|number|boolean|any[]|object)}
|
|
451
|
+
* >
|
|
452
|
+
* (this: T1, source: T2 & ThisType<T1 & T2>):T1 & T2;
|
|
453
|
+
* }}
|
|
227
454
|
*/
|
|
228
455
|
static setStatic(source) {
|
|
229
456
|
Object.assign(this, source);
|
|
@@ -233,7 +460,15 @@ export default class CustomElement extends ICustomElement {
|
|
|
233
460
|
|
|
234
461
|
/**
|
|
235
462
|
* Assigns values directly to all instances (via prototype)
|
|
236
|
-
* @type {
|
|
463
|
+
* @type {{
|
|
464
|
+
* <
|
|
465
|
+
* CLASS extends typeof CustomElement,
|
|
466
|
+
* ARGS extends ConstructorParameters<CLASS>,
|
|
467
|
+
* INSTANCE extends InstanceType<CLASS>,
|
|
468
|
+
* PROPS extends object>
|
|
469
|
+
* (this: CLASS, source: PROPS & ThisType<PROPS & INSTANCE>, options?: Partial<PropertyDescriptor>)
|
|
470
|
+
* : CLASS & Class<PROPS,ARGS>
|
|
471
|
+
* }}
|
|
237
472
|
*/
|
|
238
473
|
static readonly(source, options) {
|
|
239
474
|
// @ts-expect-error Can't cast T
|
|
@@ -242,7 +477,15 @@ export default class CustomElement extends ICustomElement {
|
|
|
242
477
|
|
|
243
478
|
/**
|
|
244
479
|
* Assigns values directly to all instances (via prototype)
|
|
245
|
-
* @type {
|
|
480
|
+
* @type {{
|
|
481
|
+
* <
|
|
482
|
+
* CLASS extends typeof CustomElement,
|
|
483
|
+
* ARGS extends ConstructorParameters<CLASS>,
|
|
484
|
+
* INSTANCE extends InstanceType<CLASS>,
|
|
485
|
+
* PROPS extends object>
|
|
486
|
+
* (this: CLASS, source: PROPS & ThisType<PROPS & INSTANCE>, options?: Partial<PropertyDescriptor>)
|
|
487
|
+
* : CLASS & Class<PROPS,ARGS>
|
|
488
|
+
* }}
|
|
246
489
|
*/
|
|
247
490
|
static set(source, options) {
|
|
248
491
|
Object.defineProperties(
|
|
@@ -281,7 +524,14 @@ export default class CustomElement extends ICustomElement {
|
|
|
281
524
|
|
|
282
525
|
/**
|
|
283
526
|
* Returns result of calling mixin with current class
|
|
284
|
-
* @type {
|
|
527
|
+
* @type {{
|
|
528
|
+
* <
|
|
529
|
+
* BASE extends typeof CustomElement,
|
|
530
|
+
* FN extends (...args:any[]) => any,
|
|
531
|
+
* RETURN extends ReturnType<FN>,
|
|
532
|
+
* SUBCLASS extends ClassOf<RETURN>,
|
|
533
|
+
* (this: BASE, mixin: FN): SUBCLASS & BASE
|
|
534
|
+
* }}
|
|
285
535
|
*/
|
|
286
536
|
static mixin(mixin) {
|
|
287
537
|
return mixin(this);
|
|
@@ -289,7 +539,9 @@ export default class CustomElement extends ICustomElement {
|
|
|
289
539
|
|
|
290
540
|
/**
|
|
291
541
|
* Registers class with window.customElements synchronously
|
|
292
|
-
* @type {
|
|
542
|
+
* @type {{
|
|
543
|
+
* <T extends typeof CustomElement>(this: T, elementName?: string, force?: boolean): T;
|
|
544
|
+
* }}
|
|
293
545
|
*/
|
|
294
546
|
static register(elementName) {
|
|
295
547
|
if (elementName) {
|
|
@@ -310,6 +562,13 @@ export default class CustomElement extends ICustomElement {
|
|
|
310
562
|
return this._props;
|
|
311
563
|
}
|
|
312
564
|
|
|
565
|
+
static get attrList() {
|
|
566
|
+
if (!this.hasOwnProperty('_attrs')) {
|
|
567
|
+
this._attrs = new Map(this._attrs);
|
|
568
|
+
}
|
|
569
|
+
return this._attrs;
|
|
570
|
+
}
|
|
571
|
+
|
|
313
572
|
static get propChangedCallbacks() {
|
|
314
573
|
if (!this.hasOwnProperty('_propChangedCallbacks')) {
|
|
315
574
|
// structuredClone()
|
|
@@ -335,55 +594,82 @@ export default class CustomElement extends ICustomElement {
|
|
|
335
594
|
|
|
336
595
|
/**
|
|
337
596
|
* Creates observable property on instances (via prototype)
|
|
338
|
-
* @
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
* )
|
|
597
|
+
* @type {{
|
|
598
|
+
* <
|
|
599
|
+
* CLASS extends typeof CustomElement,
|
|
600
|
+
* ARGS extends ConstructorParameters<CLASS>,
|
|
601
|
+
* INSTANCE extends InstanceType<CLASS>,
|
|
602
|
+
* KEY extends string,
|
|
603
|
+
* OPTIONS extends ObserverPropertyType
|
|
604
|
+
* | ObserverOptions<ObserverPropertyType, unknown, INSTANCE>
|
|
605
|
+
* | ((this:INSTANCE, data:Partial<INSTANCE>, fn?: () => any) => any),
|
|
606
|
+
* VALUE extends Record<KEY, OPTIONS extends (...args2:any[]) => infer R ? R
|
|
607
|
+
* : OPTIONS extends ObserverPropertyType ? import('./observe').ParsedObserverPropertyType<OPTIONS>
|
|
608
|
+
* : OPTIONS extends {type: 'object'} & ObserverOptions<any, infer R> ? (unknown extends R ? object : R)
|
|
609
|
+
* : OPTIONS extends {type: ObserverPropertyType} ? import('./observe').ParsedObserverPropertyType<OPTIONS['type']>
|
|
610
|
+
* : OPTIONS extends ObserverOptions<any, infer R> ? (unknown extends R ? string : R)
|
|
611
|
+
* : never
|
|
612
|
+
* >
|
|
613
|
+
* > (this: CLASS, name: KEY, options: OPTIONS)
|
|
614
|
+
* : CLASS & Class<VALUE,ARGS>
|
|
615
|
+
* }}
|
|
352
616
|
*/
|
|
353
617
|
static prop(name, typeOrOptions) {
|
|
354
618
|
// TODO: Cache and save configuration for reuse (mixins)
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const customCallback = options.changedCallback;
|
|
619
|
+
const config = defineObservableProperty(
|
|
620
|
+
/** @type {any} */ (this.prototype),
|
|
621
|
+
name,
|
|
622
|
+
/** @type {any} */ (typeOrOptions),
|
|
623
|
+
);
|
|
361
624
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
625
|
+
const { changedCallback, attr, reflect, watchers } = config;
|
|
626
|
+
if (changedCallback) {
|
|
627
|
+
watchers.push([name, changedCallback]);
|
|
365
628
|
}
|
|
366
|
-
|
|
367
629
|
// TODO: Inspect possible closure bloat
|
|
368
|
-
|
|
630
|
+
config.changedCallback = function wrappedChangedCallback(oldValue, newValue, changes) {
|
|
369
631
|
this._onObserverPropertyChanged.call(this, name, oldValue, newValue, changes);
|
|
370
632
|
};
|
|
371
633
|
|
|
372
|
-
const config = defineObservableProperty(this.prototype, name, options);
|
|
373
|
-
|
|
374
634
|
this.propList.set(name, config);
|
|
375
|
-
|
|
376
|
-
|
|
635
|
+
|
|
636
|
+
if (attr && (reflect === true || reflect === 'read')) {
|
|
637
|
+
this.attrList.set(attr, config);
|
|
377
638
|
}
|
|
378
639
|
|
|
379
|
-
|
|
640
|
+
this.onPropChanged(watchers);
|
|
641
|
+
|
|
642
|
+
// @ts-expect-error Can't cast T
|
|
643
|
+
return this;
|
|
380
644
|
}
|
|
381
645
|
|
|
382
646
|
/**
|
|
383
647
|
* Define properties on instances via Object.defineProperties().
|
|
384
648
|
* Automatically sets property non-enumerable if name begins with `_`.
|
|
385
649
|
* Functions will be remapped as getters
|
|
386
|
-
* @type {
|
|
650
|
+
* @type {{
|
|
651
|
+
* <
|
|
652
|
+
* CLASS extends typeof CustomElement,
|
|
653
|
+
* ARGS extends ConstructorParameters<CLASS>,
|
|
654
|
+
* INSTANCE extends InstanceType<CLASS>,
|
|
655
|
+
* PROPS extends {
|
|
656
|
+
* [P in keyof any] :
|
|
657
|
+
* {
|
|
658
|
+
* enumerable?: boolean;
|
|
659
|
+
* configurable?: boolean;
|
|
660
|
+
* writable?: boolean;
|
|
661
|
+
* value?: any;
|
|
662
|
+
* get?: ((this: INSTANCE) => any);
|
|
663
|
+
* set?: (this: INSTANCE, value: any) => void;
|
|
664
|
+
* } | ((this: INSTANCE, ...args:any[]) => any)
|
|
665
|
+
* },
|
|
666
|
+
* VALUE extends {
|
|
667
|
+
* [KEY in keyof PROPS]: PROPS[KEY] extends (...args2:any[]) => infer R ? R
|
|
668
|
+
* : PROPS[KEY] extends TypedPropertyDescriptor<infer R> ? R : never
|
|
669
|
+
* }>
|
|
670
|
+
* (this: CLASS, props: PROPS & ThisType<PROPS & INSTANCE>): CLASS
|
|
671
|
+
* & Class<VALUE,ARGS>
|
|
672
|
+
* }}
|
|
387
673
|
*/
|
|
388
674
|
static define(props) {
|
|
389
675
|
Object.defineProperties(
|
|
@@ -415,43 +701,68 @@ export default class CustomElement extends ICustomElement {
|
|
|
415
701
|
|
|
416
702
|
static undefine(name) {
|
|
417
703
|
Reflect.deleteProperty(this.prototype, name);
|
|
418
|
-
if (this.propList.has(name))
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}
|
|
704
|
+
if (!this.propList.has(name)) return this;
|
|
705
|
+
const { watchers, attr, reflect } = this.propList.get(name);
|
|
706
|
+
if (watchers.length && this.propChangedCallbacks.has(name)) {
|
|
707
|
+
const propWatchers = this.propChangedCallbacks.get(name);
|
|
708
|
+
for (const watcher of watchers) {
|
|
709
|
+
const index = propWatchers.indexOf(watcher);
|
|
710
|
+
if (index !== -1) {
|
|
711
|
+
console.warn('Unwatching', name);
|
|
712
|
+
propWatchers.splice(index, 1);
|
|
428
713
|
}
|
|
429
714
|
}
|
|
430
715
|
}
|
|
716
|
+
if (attr && (reflect === true || reflect === 'read')) {
|
|
717
|
+
this.attrList.delete(attr);
|
|
718
|
+
}
|
|
431
719
|
this.propList.delete(name);
|
|
720
|
+
|
|
432
721
|
return this;
|
|
433
722
|
}
|
|
434
723
|
|
|
435
724
|
/**
|
|
436
725
|
* Creates observable properties on instances
|
|
437
|
-
* @type {
|
|
726
|
+
* @type {{
|
|
727
|
+
* <
|
|
728
|
+
* CLASS extends typeof CustomElement,
|
|
729
|
+
* ARGS extends ConstructorParameters<CLASS>,
|
|
730
|
+
* INSTANCE extends InstanceType<CLASS>,
|
|
731
|
+
* PROPS extends IDLParameter<INSTANCE & VALUE>,
|
|
732
|
+
* VALUE extends {
|
|
733
|
+
* [KEY in keyof PROPS]:
|
|
734
|
+
* PROPS[KEY] extends (...args2:any[]) => infer R ? R
|
|
735
|
+
* : PROPS[KEY] extends ObserverPropertyType ? import('./observe').ParsedObserverPropertyType<PROPS[KEY]>
|
|
736
|
+
* : PROPS[KEY] extends {type: 'object'} & ObserverOptions<any, infer R> ? (unknown extends R ? object : R)
|
|
737
|
+
* : PROPS[KEY] extends {type: ObserverPropertyType} ? import('./observe').ParsedObserverPropertyType<PROPS[KEY]['type']>
|
|
738
|
+
* : PROPS[KEY] extends ObserverOptions<any, infer R> ? (unknown extends R ? string : R)
|
|
739
|
+
* : never
|
|
740
|
+
* },
|
|
741
|
+
* > (this: CLASS, props: PROPS)
|
|
742
|
+
* : CLASS & Class<VALUE,ARGS>
|
|
743
|
+
* }}
|
|
438
744
|
*/
|
|
439
745
|
static observe(props) {
|
|
440
746
|
for (const [name, typeOrOptions] of Object.entries(props ?? {})) {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
this.prop(name, typeOrOptions);
|
|
448
|
-
}
|
|
747
|
+
/** @type {any} */
|
|
748
|
+
const options = (typeof typeOrOptions === 'function')
|
|
749
|
+
? { reflect: false, get: typeOrOptions }
|
|
750
|
+
: typeOrOptions;
|
|
751
|
+
|
|
752
|
+
this.prop(name, options);
|
|
449
753
|
}
|
|
450
754
|
// @ts-expect-error Can't cast T
|
|
451
755
|
return this;
|
|
452
756
|
}
|
|
453
757
|
|
|
454
|
-
/**
|
|
758
|
+
/**
|
|
759
|
+
* @type {{
|
|
760
|
+
* <
|
|
761
|
+
* T1 extends typeof CustomElement,
|
|
762
|
+
* T2 extends IDLParameter<T1>>
|
|
763
|
+
* (this: T1, props: T2):T1 & ParsedProps<T2>
|
|
764
|
+
* }}
|
|
765
|
+
*/
|
|
455
766
|
static defineStatic(props) {
|
|
456
767
|
for (const [name, typeOrOptions] of Object.entries(props ?? {})) {
|
|
457
768
|
const options = (typeof typeOrOptions === 'function')
|
|
@@ -468,12 +779,21 @@ export default class CustomElement extends ICustomElement {
|
|
|
468
779
|
return this;
|
|
469
780
|
}
|
|
470
781
|
|
|
471
|
-
/**
|
|
782
|
+
/**
|
|
783
|
+
* @type {{
|
|
784
|
+
* <T extends typeof CustomElement>
|
|
785
|
+
* (
|
|
786
|
+
* this: T,
|
|
787
|
+
* listeners?: import('./Composition').CompositionEventListenerObject<InstanceType<T>>,
|
|
788
|
+
* options?: Partial<import('./Composition').CompositionEventListener<InstanceType<T>>>,
|
|
789
|
+
* ): T;
|
|
790
|
+
* }}
|
|
791
|
+
*/
|
|
472
792
|
static events(listeners, options) {
|
|
473
793
|
this.on({
|
|
474
794
|
composed({ composition }) {
|
|
475
795
|
for (const [key, listenerOptions] of Object.entries(listeners)) {
|
|
476
|
-
const [, flags, type] = key.match(
|
|
796
|
+
const [, flags, type] = key.match(/^([*1~]+)?(.*)$/);
|
|
477
797
|
// TODO: Make abstract
|
|
478
798
|
let prop;
|
|
479
799
|
/** @type {string[]} */
|
|
@@ -513,7 +833,18 @@ export default class CustomElement extends ICustomElement {
|
|
|
513
833
|
return this;
|
|
514
834
|
}
|
|
515
835
|
|
|
516
|
-
/**
|
|
836
|
+
/**
|
|
837
|
+
* @type {{
|
|
838
|
+
* <T extends typeof CustomElement>
|
|
839
|
+
* (
|
|
840
|
+
* this: T,
|
|
841
|
+
* listenerMap: {
|
|
842
|
+
* [P in keyof any]: import('./Composition').CompositionEventListenerObject<InstanceType<T>>
|
|
843
|
+
* },
|
|
844
|
+
* options?: Partial<import('./Composition').CompositionEventListener<InstanceType<T>>>,
|
|
845
|
+
* ): T;
|
|
846
|
+
* }}
|
|
847
|
+
*/
|
|
517
848
|
static childEvents(listenerMap, options) {
|
|
518
849
|
for (const [tag, listeners] of Object.entries(listenerMap)) {
|
|
519
850
|
// @ts-expect-error Can't cast T
|
|
@@ -527,7 +858,7 @@ export default class CustomElement extends ICustomElement {
|
|
|
527
858
|
return this;
|
|
528
859
|
}
|
|
529
860
|
|
|
530
|
-
/** @type {typeof
|
|
861
|
+
/** @type {typeof CustomElement['events']} */
|
|
531
862
|
static rootEvents(listeners, options) {
|
|
532
863
|
// @ts-expect-error Can't cast T
|
|
533
864
|
return this.events(listeners, {
|
|
@@ -536,7 +867,17 @@ export default class CustomElement extends ICustomElement {
|
|
|
536
867
|
});
|
|
537
868
|
}
|
|
538
869
|
|
|
539
|
-
/**
|
|
870
|
+
/**
|
|
871
|
+
* @type {{
|
|
872
|
+
* <
|
|
873
|
+
* T1 extends typeof CustomElement,
|
|
874
|
+
* T2 extends InstanceType<T1>,
|
|
875
|
+
* T3 extends CompositionCallback<T2, T2>,
|
|
876
|
+
* T4 extends keyof T3,
|
|
877
|
+
* >
|
|
878
|
+
* (this: T1, name: T3|T4, callbacks?: T3[T4] & ThisType<T2>): T1
|
|
879
|
+
* }}
|
|
880
|
+
*/
|
|
540
881
|
static on(nameOrCallbacks, callback) {
|
|
541
882
|
const callbacks = typeof nameOrCallbacks === 'string'
|
|
542
883
|
? { [nameOrCallbacks]: callback }
|
|
@@ -570,13 +911,34 @@ export default class CustomElement extends ICustomElement {
|
|
|
570
911
|
return this;
|
|
571
912
|
}
|
|
572
913
|
|
|
573
|
-
/**
|
|
914
|
+
/**
|
|
915
|
+
* @type {{
|
|
916
|
+
* <
|
|
917
|
+
* T1 extends typeof CustomElement,
|
|
918
|
+
* T2 extends InstanceType<T1>
|
|
919
|
+
* >
|
|
920
|
+
* (
|
|
921
|
+
* this: T1,
|
|
922
|
+
* options: ObjectOrObjectEntries<{
|
|
923
|
+
* [P in keyof T2]? : (
|
|
924
|
+
* this: T2,
|
|
925
|
+
* oldValue: T2[P],
|
|
926
|
+
* newValue: T2[P],
|
|
927
|
+
* changes:any,
|
|
928
|
+
* element: T2
|
|
929
|
+
* ) => void
|
|
930
|
+
* }>,
|
|
931
|
+
* ): T1;
|
|
932
|
+
* }}
|
|
933
|
+
*/
|
|
574
934
|
static onPropChanged(options) {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
935
|
+
const entries = Array.isArray(options) ? options : Object.entries(options);
|
|
936
|
+
const { propChangedCallbacks } = this;
|
|
937
|
+
for (const [prop, callback] of entries) {
|
|
938
|
+
if (propChangedCallbacks.has(prop)) {
|
|
939
|
+
propChangedCallbacks.get(prop).push(callback);
|
|
578
940
|
} else {
|
|
579
|
-
|
|
941
|
+
propChangedCallbacks.set(prop, [callback]);
|
|
580
942
|
}
|
|
581
943
|
}
|
|
582
944
|
|
|
@@ -584,14 +946,33 @@ export default class CustomElement extends ICustomElement {
|
|
|
584
946
|
return this;
|
|
585
947
|
}
|
|
586
948
|
|
|
587
|
-
/**
|
|
949
|
+
/**
|
|
950
|
+
* @type {{
|
|
951
|
+
* <
|
|
952
|
+
* T1 extends typeof CustomElement,
|
|
953
|
+
* T2 extends InstanceType<T1>
|
|
954
|
+
* >
|
|
955
|
+
* (
|
|
956
|
+
* this: T1,
|
|
957
|
+
* options: {
|
|
958
|
+
* [x:string]: (
|
|
959
|
+
* this: T2,
|
|
960
|
+
* oldValue: string,
|
|
961
|
+
* newValue: string,
|
|
962
|
+
* element: T2
|
|
963
|
+
* ) => void
|
|
964
|
+
* },
|
|
965
|
+
* ): T1;
|
|
966
|
+
* }}
|
|
967
|
+
*/
|
|
588
968
|
static onAttributeChanged(options) {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
969
|
+
const entries = Array.isArray(options) ? options : Object.entries(options);
|
|
970
|
+
const { attributeChangedCallbacks } = this;
|
|
971
|
+
for (const [name, callback] of entries) {
|
|
972
|
+
if (attributeChangedCallbacks.has(name)) {
|
|
973
|
+
attributeChangedCallbacks.get(name).push(callback);
|
|
593
974
|
} else {
|
|
594
|
-
|
|
975
|
+
attributeChangedCallbacks.set(name, [callback]);
|
|
595
976
|
}
|
|
596
977
|
}
|
|
597
978
|
|
|
@@ -614,7 +995,7 @@ export default class CustomElement extends ICustomElement {
|
|
|
614
995
|
/** @type {Map<string,{stringValue:string, parsedValue:any}>} */
|
|
615
996
|
_propAttributeCache;
|
|
616
997
|
|
|
617
|
-
/** @type {
|
|
998
|
+
/** @type {CallbackArguments} */
|
|
618
999
|
_callbackArguments = null;
|
|
619
1000
|
|
|
620
1001
|
/** @param {any[]} args */
|
|
@@ -636,11 +1017,12 @@ export default class CustomElement extends ICustomElement {
|
|
|
636
1017
|
* @return {void}
|
|
637
1018
|
*/
|
|
638
1019
|
this.render = this.composition.render(
|
|
639
|
-
this,
|
|
1020
|
+
this.constructor.prototype,
|
|
640
1021
|
this,
|
|
641
1022
|
{
|
|
1023
|
+
defaults: this.constructor.prototype,
|
|
642
1024
|
store: this,
|
|
643
|
-
|
|
1025
|
+
shadowRoot: this.shadowRoot,
|
|
644
1026
|
context: this,
|
|
645
1027
|
},
|
|
646
1028
|
);
|
|
@@ -650,15 +1032,27 @@ export default class CustomElement extends ICustomElement {
|
|
|
650
1032
|
}
|
|
651
1033
|
}
|
|
652
1034
|
|
|
653
|
-
/**
|
|
1035
|
+
/**
|
|
1036
|
+
* @type {{
|
|
1037
|
+
* <
|
|
1038
|
+
* T extends CustomElement,
|
|
1039
|
+
* K extends string = string,
|
|
1040
|
+
* >(this:T,
|
|
1041
|
+
* name: K,
|
|
1042
|
+
* oldValue: K extends keyof T ? T[K] : unknown,
|
|
1043
|
+
* newValue: K extends keyof T ? T[K] : unknown,
|
|
1044
|
+
* changes?: K extends keyof T ? T[K] extends object ? Partial<T[K]> : T[K] : unknown): void;
|
|
1045
|
+
* }}
|
|
1046
|
+
*/
|
|
654
1047
|
propChangedCallback(name, oldValue, newValue, changes = newValue) {
|
|
655
1048
|
if (!this.patching) {
|
|
656
1049
|
this.render.byProp(name, changes, this);
|
|
657
1050
|
// this.render({ [name]: changes });
|
|
658
1051
|
}
|
|
659
1052
|
|
|
660
|
-
|
|
661
|
-
|
|
1053
|
+
const { _propChangedCallbacks } = this.static;
|
|
1054
|
+
if (_propChangedCallbacks.has(name)) {
|
|
1055
|
+
for (const callback of _propChangedCallbacks.get(name)) {
|
|
662
1056
|
callback.call(this, oldValue, newValue, changes, this);
|
|
663
1057
|
}
|
|
664
1058
|
}
|
|
@@ -670,55 +1064,53 @@ export default class CustomElement extends ICustomElement {
|
|
|
670
1064
|
* @param {string|null} newValue
|
|
671
1065
|
*/
|
|
672
1066
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
673
|
-
const
|
|
674
|
-
if (
|
|
675
|
-
for (const callback of
|
|
1067
|
+
const { attributeChangedCallbacks } = this.static;
|
|
1068
|
+
if (attributeChangedCallbacks.has(name)) {
|
|
1069
|
+
for (const callback of attributeChangedCallbacks.get(name)) {
|
|
676
1070
|
callback.call(this, oldValue, newValue, this);
|
|
677
1071
|
}
|
|
678
1072
|
}
|
|
679
1073
|
|
|
680
1074
|
// Array.find
|
|
681
|
-
|
|
682
|
-
|
|
1075
|
+
const { attrList } = this.static;
|
|
1076
|
+
if (!attrList.has(name)) return;
|
|
683
1077
|
|
|
684
|
-
|
|
1078
|
+
const config = attrList.get(name);
|
|
685
1079
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
1080
|
+
if (config.attributeChangedCallback) {
|
|
1081
|
+
config.attributeChangedCallback.call(this, name, oldValue, newValue);
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
690
1084
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
1085
|
+
let cacheEntry;
|
|
1086
|
+
if (this.attributeCache.has(name)) {
|
|
1087
|
+
cacheEntry = this.attributeCache.get(name);
|
|
1088
|
+
if (cacheEntry.stringValue === newValue) return;
|
|
1089
|
+
}
|
|
696
1090
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
1091
|
+
// @ts-expect-error any
|
|
1092
|
+
const previousDataValue = this[config.key];
|
|
1093
|
+
const parsedValue = newValue === null
|
|
1094
|
+
? config.nullParser(/** @type {null} */ (newValue))
|
|
1095
|
+
// Avoid Boolean('') === false
|
|
1096
|
+
: (config.type === 'boolean' ? true : config.parser(newValue));
|
|
703
1097
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
return;
|
|
707
|
-
}
|
|
708
|
-
// "Remember" that this attrValue equates to this data value
|
|
709
|
-
// Avoids rewriting attribute later on data change event
|
|
710
|
-
if (cacheEntry) {
|
|
711
|
-
cacheEntry.stringValue = newValue;
|
|
712
|
-
cacheEntry.parsedValue = parsedValue;
|
|
713
|
-
} else {
|
|
714
|
-
this.attributeCache.set(lcName, {
|
|
715
|
-
stringValue: newValue, parsedValue,
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
// @ts-expect-error any
|
|
719
|
-
this[config.key] = parsedValue;
|
|
1098
|
+
if (parsedValue === previousDataValue) {
|
|
1099
|
+
// No internal value change
|
|
720
1100
|
return;
|
|
721
1101
|
}
|
|
1102
|
+
// "Remember" that this attrValue equates to this data value
|
|
1103
|
+
// Avoids rewriting attribute later on data change event
|
|
1104
|
+
if (cacheEntry) {
|
|
1105
|
+
cacheEntry.stringValue = newValue;
|
|
1106
|
+
cacheEntry.parsedValue = parsedValue;
|
|
1107
|
+
} else {
|
|
1108
|
+
this.attributeCache.set(name, {
|
|
1109
|
+
stringValue: newValue, parsedValue,
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
// @ts-expect-error any
|
|
1113
|
+
this[config.key] = parsedValue;
|
|
722
1114
|
}
|
|
723
1115
|
|
|
724
1116
|
get #template() {
|
|
@@ -732,20 +1124,21 @@ export default class CustomElement extends ICustomElement {
|
|
|
732
1124
|
* @param {any} changes
|
|
733
1125
|
*/
|
|
734
1126
|
_onObserverPropertyChanged(name, oldValue, newValue, changes) {
|
|
735
|
-
|
|
736
|
-
|
|
1127
|
+
const { propList } = this.static;
|
|
1128
|
+
if (propList.has(name)) {
|
|
1129
|
+
const { reflect, attr } = propList.get(name);
|
|
737
1130
|
if (attr && (reflect === true || reflect === 'write')) {
|
|
738
|
-
const lcName = attr.toLowerCase();
|
|
739
1131
|
/** @type {{stringValue:string, parsedValue:any}} */
|
|
740
1132
|
let cacheEntry;
|
|
741
1133
|
let needsWrite = false;
|
|
742
|
-
|
|
743
|
-
|
|
1134
|
+
const { attributeCache } = this;
|
|
1135
|
+
if (attributeCache.has(attr)) {
|
|
1136
|
+
cacheEntry = attributeCache.get(attr);
|
|
744
1137
|
needsWrite = (cacheEntry.parsedValue !== newValue);
|
|
745
1138
|
} else {
|
|
746
1139
|
// @ts-ignore skip cast
|
|
747
1140
|
cacheEntry = {};
|
|
748
|
-
|
|
1141
|
+
attributeCache.set(attr, cacheEntry);
|
|
749
1142
|
needsWrite = true;
|
|
750
1143
|
}
|
|
751
1144
|
if (needsWrite) {
|
|
@@ -823,50 +1216,8 @@ export default class CustomElement extends ICustomElement {
|
|
|
823
1216
|
}
|
|
824
1217
|
|
|
825
1218
|
get attributeCache() {
|
|
826
|
-
|
|
827
|
-
return this._propAttributeCache;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
get tabIndex() {
|
|
831
|
-
return super.tabIndex;
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
set tabIndex(value) {
|
|
835
|
-
if (value === super.tabIndex && value !== -1) {
|
|
836
|
-
// Non -1 value already set
|
|
837
|
-
return;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
if (this.delegatesFocus && document.activeElement === this) {
|
|
841
|
-
if (this.getAttribute('tabindex') === value.toString()) {
|
|
842
|
-
// Skip if possible
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
// Chrome blurs on tabindex changes with delegatesFocus
|
|
847
|
-
// Fixed in Chrome 111
|
|
848
|
-
// Remove this code ~June 2023
|
|
849
|
-
// https://bugs.chromium.org/p/chromium/issues/detail?id=1346606
|
|
850
|
-
/** @type {EventListener} */
|
|
851
|
-
const listener = (e) => {
|
|
852
|
-
e.stopImmediatePropagation();
|
|
853
|
-
e.stopPropagation();
|
|
854
|
-
if (e.type === 'blur') {
|
|
855
|
-
console.warn('Chromium bug 1346606: Tabindex change caused blur. Giving focusing back.', this);
|
|
856
|
-
this.focus();
|
|
857
|
-
} else {
|
|
858
|
-
console.warn('Chromium bug 1346606: Blocking focus event.', this);
|
|
859
|
-
}
|
|
860
|
-
};
|
|
861
|
-
this.addEventListener('blur', listener, { capture: true, once: true });
|
|
862
|
-
this.addEventListener('focus', listener, { capture: true, once: true });
|
|
863
|
-
super.tabIndex = value;
|
|
864
|
-
this.removeEventListener('blur', listener, { capture: true });
|
|
865
|
-
this.removeEventListener('focus', listener, { capture: true });
|
|
866
|
-
return;
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
super.tabIndex = value;
|
|
1219
|
+
// eslint-disable-next-line no-return-assign
|
|
1220
|
+
return (this._propAttributeCache ??= new Map());
|
|
870
1221
|
}
|
|
871
1222
|
|
|
872
1223
|
get static() { return /** @type {typeof CustomElement} */ (/** @type {unknown} */ (this.constructor)); }
|
|
@@ -877,6 +1228,7 @@ export default class CustomElement extends ICustomElement {
|
|
|
877
1228
|
// eslint-disable-next-line no-return-assign
|
|
878
1229
|
return this._callbackArguments ??= {
|
|
879
1230
|
composition: this.#composition,
|
|
1231
|
+
refs: this.refs,
|
|
880
1232
|
html: html.bind(this),
|
|
881
1233
|
inline: addInlineFunction,
|
|
882
1234
|
template: this.#template,
|