@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
package/core/Composition.js
CHANGED
|
@@ -22,12 +22,99 @@ import { generateUID } from './uid.js';
|
|
|
22
22
|
/**
|
|
23
23
|
* @template T
|
|
24
24
|
* @typedef {Object} RenderOptions
|
|
25
|
+
* @prop {T} [defaults] what
|
|
25
26
|
* @prop {T} [store] what
|
|
26
|
-
* @prop {DocumentFragment|
|
|
27
|
+
* @prop {DocumentFragment|HTMLElement|Element} [target] where
|
|
28
|
+
* @prop {ShadowRoot} [shadowRoot] where
|
|
27
29
|
* @prop {any} [context] `this` on callbacks/events
|
|
28
30
|
* @prop {any} [injections]
|
|
29
31
|
*/
|
|
30
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @template T
|
|
35
|
+
* @typedef {{
|
|
36
|
+
* target: Element|DocumentFragment,
|
|
37
|
+
* byProp: (prop: keyof T & string, value:any, data?:Partial<T>) => void,
|
|
38
|
+
* state: InitializationState,
|
|
39
|
+
* } & ((changes:Partial<T>, data:T) => void)} RenderDraw
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/** @typedef {HTMLElementEventMap & { input: InputEvent; } } HTMLElementEventMapFixed */
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {(
|
|
46
|
+
* Pick<HTMLElementEventMapFixed,
|
|
47
|
+
* 'auxclick' |
|
|
48
|
+
* 'beforeinput' |
|
|
49
|
+
* 'click' |
|
|
50
|
+
* 'compositionstart' |
|
|
51
|
+
* 'contextmenu' |
|
|
52
|
+
* 'drag' |
|
|
53
|
+
* 'dragenter' |
|
|
54
|
+
* 'dragover' |
|
|
55
|
+
* 'dragstart' |
|
|
56
|
+
* 'drop' |
|
|
57
|
+
* 'invalid' |
|
|
58
|
+
* 'keydown' |
|
|
59
|
+
* 'keypress' |
|
|
60
|
+
* 'keyup' |
|
|
61
|
+
* 'mousedown' |
|
|
62
|
+
* 'mousemove' |
|
|
63
|
+
* 'mouseout' |
|
|
64
|
+
* 'mouseover' |
|
|
65
|
+
* 'mouseup' |
|
|
66
|
+
* 'pointerdown' |
|
|
67
|
+
* 'pointermove' |
|
|
68
|
+
* 'pointerout' |
|
|
69
|
+
* 'pointerover' |
|
|
70
|
+
* 'pointerup' |
|
|
71
|
+
* 'reset' |
|
|
72
|
+
* 'selectstart' |
|
|
73
|
+
* 'submit' |
|
|
74
|
+
* 'touchend' |
|
|
75
|
+
* 'touchmove' |
|
|
76
|
+
* 'touchstart' |
|
|
77
|
+
* 'wheel'
|
|
78
|
+
* >
|
|
79
|
+
* )} HTMLElementCancellableEventMap
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @typedef {(
|
|
84
|
+
* HTMLElementEventMapFixed
|
|
85
|
+
* & {[P in keyof HTMLElementCancellableEventMap as `~${P}`]: HTMLElementCancellableEventMap[P]}
|
|
86
|
+
* & Record<string, Event|CustomEvent<any>>
|
|
87
|
+
* )} CompositionEventMap
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @template {any} T
|
|
92
|
+
* @template {keyof CompositionEventMap} [K = keyof CompositionEventMap]
|
|
93
|
+
* @typedef {{
|
|
94
|
+
* type?: K
|
|
95
|
+
* tag?: string|symbol,
|
|
96
|
+
* capture?: boolean;
|
|
97
|
+
* once?: boolean;
|
|
98
|
+
* passive?: boolean;
|
|
99
|
+
* signal?: AbortSignal;
|
|
100
|
+
* handleEvent?: (
|
|
101
|
+
* this: T,
|
|
102
|
+
* event: (K extends keyof CompositionEventMap ? CompositionEventMap[K] : Event) & {currentTarget:HTMLElement}
|
|
103
|
+
* ) => any;
|
|
104
|
+
* prop?: string;
|
|
105
|
+
* deepProp?: string[],
|
|
106
|
+
* }} CompositionEventListener
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @template T
|
|
111
|
+
* @typedef {{
|
|
112
|
+
* [P in keyof CompositionEventMap]?: (keyof T & string)
|
|
113
|
+
* | ((this: T, event: CompositionEventMap[P] & {currentTarget:HTMLElement}) => any)
|
|
114
|
+
* | CompositionEventListener<T, P>
|
|
115
|
+
* }} CompositionEventListenerObject
|
|
116
|
+
*/
|
|
117
|
+
|
|
31
118
|
/**
|
|
32
119
|
* @template {any} T
|
|
33
120
|
* @typedef {Object} NodeBindEntry
|
|
@@ -41,7 +128,7 @@ import { generateUID } from './uid.js';
|
|
|
41
128
|
* @prop {boolean} [doubleNegate]
|
|
42
129
|
* @prop {Function} [expression]
|
|
43
130
|
* @prop {(options: RenderOptions<?>, element: Element, changes:any, data:any) => any} [render] custom render function
|
|
44
|
-
* @prop {
|
|
131
|
+
* @prop {CompositionEventListener<T>[]} [listeners]
|
|
45
132
|
* @prop {Composition<any>} [composition] // Sub composition templating (eg: array)
|
|
46
133
|
* @prop {T} defaultValue
|
|
47
134
|
*/
|
|
@@ -52,9 +139,10 @@ import { generateUID } from './uid.js';
|
|
|
52
139
|
* @typedef RenderGraphSearch
|
|
53
140
|
* @prop {(state:InitializationState, changes:any, data:any) => any} invocation
|
|
54
141
|
* @prop {number} cacheIndex
|
|
55
|
-
* @prop {number}
|
|
56
|
-
* @prop {number} dirtyIndex
|
|
142
|
+
* @prop {number} searchIndex
|
|
57
143
|
* @prop {string | Function | string[]} query
|
|
144
|
+
* @prop {boolean} [negate]
|
|
145
|
+
* @prop {boolean} [doubleNegate]
|
|
58
146
|
* @prop {Function} [expression]
|
|
59
147
|
* @prop {string} prop
|
|
60
148
|
* @prop {string[]} deepProp
|
|
@@ -73,16 +161,16 @@ import { generateUID } from './uid.js';
|
|
|
73
161
|
* @prop {string} [attrName]
|
|
74
162
|
* @prop {any} [defaultValue]
|
|
75
163
|
* @prop {RenderGraphSearch} search
|
|
164
|
+
* @prop {InterpolateOptions['injections']} [injections]
|
|
76
165
|
*/
|
|
77
166
|
|
|
78
167
|
/**
|
|
79
168
|
* @type {RenderGraphAction['invocation']}
|
|
80
169
|
* @this {RenderGraphAction}
|
|
81
170
|
*/
|
|
82
|
-
function writeDOMAttribute(
|
|
171
|
+
function writeDOMAttribute({ nodes }, value) {
|
|
83
172
|
const { nodeIndex, attrName } = this;
|
|
84
|
-
/** @type {Element} */
|
|
85
|
-
const element = state.nodes[nodeIndex];
|
|
173
|
+
const element = /** @type {Element} */ (nodes[nodeIndex]);
|
|
86
174
|
switch (value) {
|
|
87
175
|
case undefined:
|
|
88
176
|
case null:
|
|
@@ -102,43 +190,97 @@ function writeDOMAttribute(state, value) {
|
|
|
102
190
|
* @type {RenderGraphAction['invocation']}
|
|
103
191
|
* @this {RenderGraphAction}
|
|
104
192
|
*/
|
|
105
|
-
function
|
|
106
|
-
|
|
107
|
-
|
|
193
|
+
function writeDynamicNode({ nodeStates, comments, nodes }, value) {
|
|
194
|
+
const { commentIndex, nodeIndex } = this;
|
|
195
|
+
const nodeState = nodeStates[nodeIndex];
|
|
196
|
+
// eslint-disable-next-line no-bitwise
|
|
197
|
+
const hidden = nodeState & 0b0001;
|
|
198
|
+
const show = value != null && value !== false;
|
|
199
|
+
if (!show) {
|
|
200
|
+
// Should be hidden
|
|
201
|
+
if (hidden) return;
|
|
202
|
+
// Replace whatever node is there with the comment
|
|
203
|
+
let comment = comments[commentIndex];
|
|
204
|
+
if (!comment) {
|
|
205
|
+
comment = createEmptyComment();
|
|
206
|
+
comments[commentIndex] = comment;
|
|
207
|
+
}
|
|
208
|
+
nodes[nodeIndex].replaceWith(comment);
|
|
209
|
+
// eslint-disable-next-line no-bitwise
|
|
210
|
+
nodeStates[nodeIndex] |= 0b0001;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// Must be shown
|
|
214
|
+
// Update node first (offscreen rendering)
|
|
215
|
+
const node = nodes[nodeIndex];
|
|
216
|
+
// eslint-disable-next-line no-bitwise
|
|
217
|
+
const isDynamicNode = nodeState & 0b0010;
|
|
218
|
+
|
|
219
|
+
if (typeof value === 'object') {
|
|
220
|
+
// Not string data, need to replace
|
|
221
|
+
console.warn('Dynamic nodes not supported yet');
|
|
222
|
+
} else if (isDynamicNode) {
|
|
223
|
+
const textNode = new Text(value);
|
|
224
|
+
node.replaceWith(textNode);
|
|
225
|
+
nodes[nodeIndex] = textNode;
|
|
226
|
+
// eslint-disable-next-line no-bitwise
|
|
227
|
+
nodeStates[nodeIndex] &= ~0b0010;
|
|
228
|
+
} else {
|
|
229
|
+
/** @type {Text} */ (node).data = value;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Updated, now set hidden state
|
|
233
|
+
|
|
234
|
+
if (hidden) {
|
|
235
|
+
const comment = comments[commentIndex];
|
|
236
|
+
comment.replaceWith(node);
|
|
237
|
+
// eslint-disable-next-line no-bitwise
|
|
238
|
+
nodeStates[nodeIndex] &= ~0b0001;
|
|
239
|
+
}
|
|
240
|
+
// Done
|
|
108
241
|
}
|
|
109
242
|
|
|
110
243
|
/**
|
|
111
244
|
* @type {RenderGraphAction['invocation']}
|
|
112
245
|
* @this {RenderGraphAction}
|
|
113
246
|
*/
|
|
114
|
-
function writeDOMElementAttachedState(
|
|
247
|
+
function writeDOMElementAttachedState({ nodeStates, nodes, comments }, value) {
|
|
115
248
|
const { commentIndex, nodeIndex } = this;
|
|
116
|
-
|
|
249
|
+
// eslint-disable-next-line no-bitwise
|
|
250
|
+
const hidden = nodeStates[nodeIndex] & 1;
|
|
251
|
+
const show = value != null && value !== false;
|
|
252
|
+
if (show === !hidden) return;
|
|
253
|
+
|
|
254
|
+
const element = nodes[nodeIndex];
|
|
255
|
+
let comment = comments[commentIndex];
|
|
117
256
|
if (!comment) {
|
|
118
257
|
comment = createEmptyComment();
|
|
119
|
-
|
|
258
|
+
comments[commentIndex] = comment;
|
|
120
259
|
}
|
|
121
|
-
const element = state.nodes[nodeIndex];
|
|
122
|
-
const show = value != null && value !== false;
|
|
123
260
|
if (show) {
|
|
124
261
|
comment.replaceWith(element);
|
|
262
|
+
// eslint-disable-next-line no-bitwise
|
|
263
|
+
nodeStates[nodeIndex] &= ~0b0001;
|
|
125
264
|
} else {
|
|
126
265
|
element.replaceWith(comment);
|
|
266
|
+
// eslint-disable-next-line no-bitwise
|
|
267
|
+
nodeStates[nodeIndex] |= 0b0001;
|
|
127
268
|
}
|
|
128
|
-
return show;
|
|
129
269
|
}
|
|
130
270
|
|
|
131
271
|
/**
|
|
132
272
|
* @type {RenderGraphAction['invocation']}
|
|
133
273
|
* @this {RenderGraphAction}
|
|
134
274
|
*/
|
|
135
|
-
function
|
|
275
|
+
function writeDOMHideNodeOnInit({ comments, nodeStates, nodes }) {
|
|
136
276
|
const { commentIndex, nodeIndex } = this;
|
|
137
277
|
|
|
138
278
|
const comment = createEmptyComment();
|
|
139
|
-
|
|
279
|
+
comments[commentIndex] = comment;
|
|
280
|
+
// eslint-disable-next-line no-bitwise
|
|
281
|
+
nodeStates[nodeIndex] |= 1;
|
|
140
282
|
|
|
141
|
-
|
|
283
|
+
nodes[nodeIndex].replaceWith(comment);
|
|
142
284
|
}
|
|
143
285
|
|
|
144
286
|
/**
|
|
@@ -146,37 +288,50 @@ function writeDOMHideElementOnInit(state) {
|
|
|
146
288
|
* @param {Parameters<RenderGraphSearch['invocation']>} args
|
|
147
289
|
*/
|
|
148
290
|
function executeSearch(search, ...args) {
|
|
149
|
-
const [
|
|
150
|
-
const
|
|
151
|
-
|
|
291
|
+
const [{ caches, searchStates }] = args;
|
|
292
|
+
const { cacheIndex, searchIndex, subSearch, invocation } = search;
|
|
293
|
+
const cachedValue = caches[cacheIndex];
|
|
294
|
+
const searchState = searchStates[searchIndex];
|
|
295
|
+
|
|
296
|
+
// Ran = 0b0001
|
|
297
|
+
// Dirty = 0b0010
|
|
298
|
+
// eslint-disable-next-line no-bitwise
|
|
299
|
+
if (searchState & 0b0001) {
|
|
152
300
|
// Return last result
|
|
153
301
|
return {
|
|
154
302
|
value: cachedValue,
|
|
155
|
-
|
|
303
|
+
// eslint-disable-next-line no-bitwise
|
|
304
|
+
dirty: ((searchState & 0b0010) === 0b0010),
|
|
156
305
|
};
|
|
157
306
|
}
|
|
158
|
-
|
|
307
|
+
|
|
308
|
+
// eslint-disable-next-line no-bitwise
|
|
309
|
+
searchStates[searchIndex] |= 0b0001;
|
|
159
310
|
let result;
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
311
|
+
if (invocation) {
|
|
312
|
+
if (subSearch) {
|
|
313
|
+
const subResult = executeSearch(subSearch, ...args);
|
|
314
|
+
// Use last cached value (if any)
|
|
315
|
+
if (!subResult.dirty && cachedValue !== undefined) {
|
|
316
|
+
// eslint-disable-next-line no-bitwise
|
|
317
|
+
searchStates[searchIndex] &= ~0b0010;
|
|
318
|
+
return { value: cachedValue, dirty: false };
|
|
319
|
+
}
|
|
320
|
+
// Pass from subquery
|
|
321
|
+
result = search.invocation(subResult.value);
|
|
322
|
+
} else {
|
|
323
|
+
result = search.invocation(...args);
|
|
324
|
+
}
|
|
325
|
+
if ((result === undefined) || (cachedValue === result)) {
|
|
326
|
+
// Return from cache
|
|
327
|
+
return { value: result, dirty: false };
|
|
166
328
|
}
|
|
167
|
-
// Pass from subquery
|
|
168
|
-
result = search.invocation(subResult.value);
|
|
169
|
-
} else {
|
|
170
|
-
result = search.invocation(...args);
|
|
171
|
-
}
|
|
172
|
-
if ((result === undefined) || (cachedValue === result)) {
|
|
173
|
-
// Returnf rom cache
|
|
174
|
-
return { value: result, dirty: false };
|
|
175
329
|
}
|
|
176
330
|
|
|
177
331
|
// Overwrite cache and flag as dirty
|
|
178
|
-
|
|
179
|
-
|
|
332
|
+
caches[cacheIndex] = result;
|
|
333
|
+
// eslint-disable-next-line no-bitwise
|
|
334
|
+
searchStates[searchIndex] |= 0b0010;
|
|
180
335
|
return { value: result, dirty: true };
|
|
181
336
|
}
|
|
182
337
|
|
|
@@ -184,11 +339,11 @@ function executeSearch(search, ...args) {
|
|
|
184
339
|
* @type {RenderGraphSearch['invocation']}
|
|
185
340
|
* @this {RenderGraphSearch}
|
|
186
341
|
*/
|
|
187
|
-
function searchWithExpression(
|
|
342
|
+
function searchWithExpression({ options: { context, store, injections } }, changes, data) {
|
|
188
343
|
return this.expression.call(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
344
|
+
context,
|
|
345
|
+
store ?? data,
|
|
346
|
+
injections,
|
|
192
347
|
);
|
|
193
348
|
}
|
|
194
349
|
|
|
@@ -196,7 +351,7 @@ function searchWithExpression(state, changes, data) {
|
|
|
196
351
|
* @type {RenderGraphSearch['invocation']}
|
|
197
352
|
* @this {RenderGraphSearch}
|
|
198
353
|
*/
|
|
199
|
-
function searchWithProp(state, changes
|
|
354
|
+
function searchWithProp(state, changes) {
|
|
200
355
|
return changes[this.prop];
|
|
201
356
|
}
|
|
202
357
|
|
|
@@ -216,23 +371,21 @@ function searchWithDeepProp(state, changes, data) {
|
|
|
216
371
|
|
|
217
372
|
/**
|
|
218
373
|
* @typedef InterpolateOptions
|
|
219
|
-
* @prop {
|
|
220
|
-
* @prop {{iterable:string} & Record<string,any>} [injections] Context-specific injected properties. (Experimental)
|
|
374
|
+
* @prop {Record<string,any>} [defaults] Default values to use for interpolation
|
|
375
|
+
* @prop {{iterable:string} & Record<string,any> & {index:number}} [injections] Context-specific injected properties. (Experimental)
|
|
221
376
|
*/
|
|
222
377
|
|
|
223
378
|
/**
|
|
224
379
|
* @typedef InitializationState
|
|
225
380
|
* @prop {Element} lastElement
|
|
226
|
-
* @prop {boolean} isShadowRoot
|
|
227
381
|
* @prop {ChildNode} lastChildNode
|
|
228
382
|
* @prop {(Element|Text)[]} nodes
|
|
229
383
|
* @prop {any[]} caches
|
|
230
384
|
* @prop {Comment[]} comments
|
|
231
|
-
* @prop {
|
|
232
|
-
* @prop {
|
|
233
|
-
* @prop {
|
|
385
|
+
* @prop {Uint8Array} nodeStates
|
|
386
|
+
* @prop {Uint8Array} searchStates
|
|
387
|
+
* @prop {HTMLElement[]} refs
|
|
234
388
|
* @prop {number} lastChildNodeIndex
|
|
235
|
-
* @prop {DocumentFragment} instanceFragment
|
|
236
389
|
* @prop {RenderOptions<?>} options
|
|
237
390
|
*/
|
|
238
391
|
|
|
@@ -242,7 +395,6 @@ const STRING_INTERPOLATION_REGEX = /{([^}]*)}/g;
|
|
|
242
395
|
/**
|
|
243
396
|
* Returns event listener bound to shadow root host.
|
|
244
397
|
* Use this function to avoid generating extra closures
|
|
245
|
-
*
|
|
246
398
|
* @this {HTMLElement}
|
|
247
399
|
* @param {Function} fn
|
|
248
400
|
*/
|
|
@@ -317,13 +469,16 @@ function valueFromPropName(prop, source) {
|
|
|
317
469
|
return value;
|
|
318
470
|
}
|
|
319
471
|
|
|
472
|
+
const compositionCache = new Map();
|
|
473
|
+
|
|
320
474
|
/** @template T */
|
|
321
475
|
export default class Composition {
|
|
322
|
-
|
|
476
|
+
static EVENT_PREFIX_REGEX = /^([*1~]+)?(.*)$/;
|
|
477
|
+
|
|
478
|
+
_interpolationState = {
|
|
323
479
|
nodeIndex: -1,
|
|
324
|
-
|
|
480
|
+
searchIndex: 0,
|
|
325
481
|
cacheIndex: 0,
|
|
326
|
-
dirtyIndex: 0,
|
|
327
482
|
commentIndex: 0,
|
|
328
483
|
/** @type {this['nodesToBind'][0]} */
|
|
329
484
|
nodeEntry: null,
|
|
@@ -346,65 +501,49 @@ export default class Composition {
|
|
|
346
501
|
|
|
347
502
|
/**
|
|
348
503
|
* Index of searches by query (dotted notation for deep props)
|
|
349
|
-
*
|
|
350
504
|
* @type {Map<Function|string, RenderGraphSearch>}
|
|
351
505
|
*/
|
|
352
|
-
searchByQuery
|
|
506
|
+
searchByQuery;
|
|
353
507
|
|
|
354
508
|
/**
|
|
355
509
|
* Index of searches by query (dotted notation for deep props)
|
|
356
|
-
*
|
|
357
510
|
* @type {Map<string, RenderGraphAction[]>}
|
|
358
511
|
*/
|
|
359
|
-
actionsByPropsUsed
|
|
360
|
-
|
|
361
|
-
/** @type {RenderGraphAction[]} */
|
|
362
|
-
actions = [];
|
|
512
|
+
actionsByPropsUsed;
|
|
363
513
|
|
|
364
514
|
/** @type {RenderGraphAction[]} */
|
|
365
515
|
postInitActions = [];
|
|
366
516
|
|
|
367
517
|
/** @type {Set<string>} */
|
|
368
|
-
tagsWithBindings
|
|
518
|
+
tagsWithBindings;
|
|
369
519
|
|
|
370
520
|
/**
|
|
371
521
|
* Array of element tags
|
|
372
|
-
*
|
|
373
522
|
* @type {string[]}
|
|
374
523
|
*/
|
|
375
524
|
tags = [];
|
|
376
525
|
|
|
377
|
-
/**
|
|
378
|
-
* Array of property bindings sorted by tag/subnode
|
|
379
|
-
*
|
|
380
|
-
* @type {Set<string>}
|
|
381
|
-
*/
|
|
382
|
-
watchedProps = new Set();
|
|
383
|
-
|
|
384
526
|
/**
|
|
385
527
|
* Data of arrays used in templates
|
|
386
528
|
* Usage of a [mdw-for] will create an ArrayLike expectation based on key
|
|
387
529
|
* Only store metadata, not actual data. Currently only needs length.
|
|
388
530
|
* TBD if more is needed later
|
|
389
531
|
* Referenced by property key (string)
|
|
390
|
-
*
|
|
391
|
-
* @type {CompositionAdapter}
|
|
532
|
+
* @type {CompositionAdapter<T>}
|
|
392
533
|
*/
|
|
393
534
|
adapter;
|
|
394
535
|
|
|
395
536
|
/**
|
|
396
537
|
* Collection of events to bind.
|
|
397
538
|
* Indexed by ID
|
|
398
|
-
*
|
|
399
|
-
* @type {Map<string|symbol, import('./typings.js').CompositionEventListener<any>[]>}
|
|
539
|
+
* @type {Map<string|symbol, CompositionEventListener<any>[]>}
|
|
400
540
|
*/
|
|
401
|
-
events
|
|
541
|
+
events;
|
|
402
542
|
|
|
403
543
|
/**
|
|
404
544
|
* Snapshot of composition at initial state.
|
|
405
545
|
* This fragment can be cloned for first rendering, instead of calling
|
|
406
546
|
* of using `render()` to construct the initial DOM tree.
|
|
407
|
-
*
|
|
408
547
|
* @type {DocumentFragment}
|
|
409
548
|
*/
|
|
410
549
|
cloneable;
|
|
@@ -421,7 +560,6 @@ export default class Composition {
|
|
|
421
560
|
/**
|
|
422
561
|
* List of IDs used by template elements
|
|
423
562
|
* May be needed to be removed when adding to non-DocumentFragment
|
|
424
|
-
*
|
|
425
563
|
* @type {string[]}
|
|
426
564
|
*/
|
|
427
565
|
allIds = [];
|
|
@@ -430,7 +568,8 @@ export default class Composition {
|
|
|
430
568
|
* Collection of IDs used for referencing elements
|
|
431
569
|
* Not meant for live DOM. Removed before attaching to document
|
|
432
570
|
*/
|
|
433
|
-
|
|
571
|
+
/** @type {Set<string>} */
|
|
572
|
+
temporaryIds;
|
|
434
573
|
|
|
435
574
|
/** Flag set when template and styles have been interpolated */
|
|
436
575
|
interpolated = false;
|
|
@@ -453,6 +592,24 @@ export default class Composition {
|
|
|
453
592
|
yield this.template;
|
|
454
593
|
}
|
|
455
594
|
|
|
595
|
+
/**
|
|
596
|
+
* @template T
|
|
597
|
+
* @param {ConstructorParameters<typeof Composition<T>>} parts
|
|
598
|
+
* @return {Composition<T>}
|
|
599
|
+
*/
|
|
600
|
+
static compose(...parts) {
|
|
601
|
+
for (const [cache, comp] of compositionCache) {
|
|
602
|
+
if (cache.length !== parts.length) continue;
|
|
603
|
+
if (parts.every((part, index) => part === cache[index])) {
|
|
604
|
+
return comp;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const composition = new Composition(...parts);
|
|
609
|
+
compositionCache.set(parts, composition);
|
|
610
|
+
return composition;
|
|
611
|
+
}
|
|
612
|
+
|
|
456
613
|
/**
|
|
457
614
|
* @param {CompositionPart<T>[]} parts
|
|
458
615
|
*/
|
|
@@ -472,13 +629,15 @@ export default class Composition {
|
|
|
472
629
|
return this;
|
|
473
630
|
}
|
|
474
631
|
|
|
475
|
-
/** @param {
|
|
632
|
+
/** @param {CompositionEventListener<T>} listener */
|
|
476
633
|
addCompositionEventListener(listener) {
|
|
477
634
|
const key = listener.tag ?? '';
|
|
478
|
-
|
|
479
|
-
|
|
635
|
+
// eslint-disable-next-line no-multi-assign
|
|
636
|
+
const events = (this.events ??= new Map());
|
|
637
|
+
if (events.has(key)) {
|
|
638
|
+
events.get(key).push(listener);
|
|
480
639
|
} else {
|
|
481
|
-
|
|
640
|
+
events.set(key, [listener]);
|
|
482
641
|
}
|
|
483
642
|
return this;
|
|
484
643
|
}
|
|
@@ -490,7 +649,7 @@ export default class Composition {
|
|
|
490
649
|
* @return {void}
|
|
491
650
|
*/
|
|
492
651
|
#bindCompositionEventListeners(tag, target, context) {
|
|
493
|
-
if (!this.events
|
|
652
|
+
if (!this.events?.has(tag)) return;
|
|
494
653
|
for (const event of this.events.get(tag)) {
|
|
495
654
|
let listener;
|
|
496
655
|
if (event.handleEvent) {
|
|
@@ -508,56 +667,66 @@ export default class Composition {
|
|
|
508
667
|
* TODO: Add types and clean up closure leak
|
|
509
668
|
* Updates component nodes based on data.
|
|
510
669
|
* Expects data in JSON Merge Patch format
|
|
511
|
-
*
|
|
512
670
|
* @see https://www.rfc-editor.org/rfc/rfc7386
|
|
513
671
|
* @template {Object} T
|
|
514
672
|
* @param {Partial<T>} changes what specifically
|
|
515
673
|
* @param {T} [data]
|
|
516
674
|
* @param {RenderOptions<T>} [options]
|
|
517
|
-
* @return {
|
|
675
|
+
* @return {RenderDraw<T>} anchor
|
|
518
676
|
*/
|
|
519
677
|
render(changes, data, options = {}) {
|
|
520
|
-
// console.log('render', changes, options);
|
|
521
678
|
if (!this.interpolated) {
|
|
522
|
-
this.interpolate({
|
|
679
|
+
this.interpolate({
|
|
680
|
+
defaults: data ?? changes,
|
|
681
|
+
...options,
|
|
682
|
+
});
|
|
523
683
|
}
|
|
524
684
|
|
|
525
685
|
const instanceFragment = /** @type {DocumentFragment} */ (this.cloneable.cloneNode(true));
|
|
526
686
|
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
const isShadowRoot = target instanceof ShadowRoot;
|
|
687
|
+
const shadowRoot = options.shadowRoot;
|
|
688
|
+
const target = shadowRoot ?? options.target ?? instanceFragment.firstElementChild;
|
|
530
689
|
|
|
531
690
|
/** @type {InitializationState} */
|
|
532
691
|
const initState = {
|
|
533
|
-
instanceFragment,
|
|
534
692
|
lastChildNode: null,
|
|
535
693
|
lastChildNodeIndex: 0,
|
|
536
694
|
lastElement: null,
|
|
537
|
-
|
|
538
|
-
|
|
695
|
+
nodeStates: new Uint8Array(this._interpolationState.nodeIndex + 1),
|
|
696
|
+
searchStates: new Uint8Array(this._interpolationState.searchIndex),
|
|
539
697
|
comments: [],
|
|
540
698
|
nodes: [],
|
|
541
699
|
caches: this.initCache.slice(),
|
|
542
|
-
dirtyFlags: [],
|
|
543
700
|
refs: [],
|
|
544
701
|
options,
|
|
545
702
|
};
|
|
546
703
|
|
|
547
|
-
const nodes = initState
|
|
704
|
+
const { nodes, refs, searchStates, caches } = initState;
|
|
548
705
|
for (const { tag, textNodes } of this.nodesToBind) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
706
|
+
/** @type {Text} */
|
|
707
|
+
let textNode;
|
|
708
|
+
if (tag === '') {
|
|
709
|
+
if (!textNodes.length) {
|
|
710
|
+
console.warn('why was root tagged?');
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
console.warn('found empty tag??');
|
|
714
|
+
refs.push(null);
|
|
715
|
+
nodes.push(null);
|
|
716
|
+
textNode = /** @type {Text} */ (instanceFragment.firstChild);
|
|
717
|
+
} else {
|
|
718
|
+
const element = instanceFragment.getElementById(tag);
|
|
719
|
+
refs.push(element);
|
|
720
|
+
nodes.push(element);
|
|
721
|
+
this.#bindCompositionEventListeners(tag, element, options.context);
|
|
722
|
+
if (!textNodes.length) continue;
|
|
723
|
+
textNode = /** @type {Text} */ (element.firstChild);
|
|
724
|
+
}
|
|
555
725
|
|
|
556
|
-
let textNode = element.firstChild;
|
|
557
726
|
let currentIndex = 0;
|
|
558
727
|
for (const index of textNodes) {
|
|
559
728
|
while (index !== currentIndex) {
|
|
560
|
-
textNode = textNode.nextSibling;
|
|
729
|
+
textNode = /** @type {Text} */ (textNode.nextSibling);
|
|
561
730
|
currentIndex++;
|
|
562
731
|
}
|
|
563
732
|
nodes.push(textNode);
|
|
@@ -570,32 +739,35 @@ export default class Composition {
|
|
|
570
739
|
action.invocation(initState);
|
|
571
740
|
}
|
|
572
741
|
|
|
742
|
+
/**
|
|
743
|
+
* @param {Partial<T>} changes
|
|
744
|
+
* @param {T} data
|
|
745
|
+
*/
|
|
573
746
|
const draw = (changes, data) => {
|
|
574
747
|
let ranSearch = false;
|
|
575
748
|
for (const prop of this.props) {
|
|
576
|
-
if (!this.actionsByPropsUsed
|
|
749
|
+
if (!this.actionsByPropsUsed?.has(prop)) continue;
|
|
577
750
|
if (!(prop in changes)) continue;
|
|
578
751
|
const actions = this.actionsByPropsUsed.get(prop);
|
|
579
752
|
for (const action of actions) {
|
|
580
753
|
ranSearch = true;
|
|
581
|
-
const
|
|
582
|
-
if (
|
|
583
|
-
// console.log('dirty, updating from batch', initState.nodes[action.nodeIndex], 'with',
|
|
584
|
-
action.invocation(initState,
|
|
754
|
+
const { dirty, value } = executeSearch(action.search, initState, changes, data);
|
|
755
|
+
if (dirty) {
|
|
756
|
+
// console.log('dirty, updating from batch', initState.nodes[action.nodeIndex], 'with', value);
|
|
757
|
+
action.invocation(initState, value, changes, data);
|
|
585
758
|
}
|
|
586
759
|
}
|
|
587
760
|
}
|
|
588
761
|
if (!ranSearch) return;
|
|
589
|
-
|
|
590
|
-
initState.dirtyFlags.fill(false);
|
|
762
|
+
searchStates.fill(0);
|
|
591
763
|
};
|
|
592
764
|
|
|
593
|
-
if (
|
|
594
|
-
options.context ??=
|
|
595
|
-
if ('adoptedStyleSheets' in
|
|
765
|
+
if (shadowRoot) {
|
|
766
|
+
options.context ??= shadowRoot.host;
|
|
767
|
+
if ('adoptedStyleSheets' in shadowRoot) {
|
|
596
768
|
if (this.adoptedStyleSheets.length) {
|
|
597
|
-
|
|
598
|
-
...
|
|
769
|
+
shadowRoot.adoptedStyleSheets = [
|
|
770
|
+
...shadowRoot.adoptedStyleSheets,
|
|
599
771
|
...this.adoptedStyleSheets,
|
|
600
772
|
];
|
|
601
773
|
}
|
|
@@ -611,34 +783,42 @@ export default class Composition {
|
|
|
611
783
|
draw(changes, data);
|
|
612
784
|
}
|
|
613
785
|
|
|
614
|
-
if (
|
|
615
|
-
|
|
786
|
+
if (shadowRoot) {
|
|
787
|
+
shadowRoot.append(instanceFragment);
|
|
788
|
+
customElements.upgrade(shadowRoot);
|
|
616
789
|
}
|
|
617
790
|
|
|
618
791
|
draw.target = target;
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* @param {keyof T & string} prop
|
|
795
|
+
* @param {any} value
|
|
796
|
+
* @param {Partial<T>} [data]
|
|
797
|
+
*/
|
|
619
798
|
draw.byProp = (prop, value, data) => {
|
|
620
|
-
if (!this.actionsByPropsUsed
|
|
799
|
+
if (!this.actionsByPropsUsed?.has(prop)) return;
|
|
621
800
|
let ranSearch = false;
|
|
622
801
|
|
|
623
802
|
// Update search
|
|
624
|
-
if (this.searchByQuery
|
|
803
|
+
if (this.searchByQuery?.has(prop)) {
|
|
625
804
|
ranSearch = true;
|
|
626
805
|
const search = this.searchByQuery.get(prop);
|
|
627
|
-
const cachedValue =
|
|
806
|
+
const cachedValue = caches[search.cacheIndex];
|
|
628
807
|
if (cachedValue === value) {
|
|
629
808
|
return;
|
|
630
809
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
initState.dirtyFlags[search.dirtyIndex] = true;
|
|
810
|
+
caches[search.cacheIndex] = value;
|
|
811
|
+
searchStates[search.searchIndex] = 0b0011;
|
|
634
812
|
}
|
|
635
813
|
|
|
814
|
+
/** @type {Partial<T>} */
|
|
636
815
|
let changes;
|
|
637
816
|
const actions = this.actionsByPropsUsed.get(prop);
|
|
638
817
|
for (const action of actions) {
|
|
639
818
|
if (action.search.query === prop) {
|
|
640
819
|
action.invocation(initState, value);
|
|
641
820
|
} else {
|
|
821
|
+
// @ts-expect-error Skip cast
|
|
642
822
|
changes ??= { [prop]: value };
|
|
643
823
|
data ??= changes;
|
|
644
824
|
ranSearch = true;
|
|
@@ -651,8 +831,7 @@ export default class Composition {
|
|
|
651
831
|
}
|
|
652
832
|
|
|
653
833
|
if (!ranSearch) return;
|
|
654
|
-
|
|
655
|
-
initState.dirtyFlags.fill(false);
|
|
834
|
+
searchStates.fill(0);
|
|
656
835
|
};
|
|
657
836
|
draw.state = initState;
|
|
658
837
|
return draw;
|
|
@@ -660,7 +839,7 @@ export default class Composition {
|
|
|
660
839
|
|
|
661
840
|
/**
|
|
662
841
|
* @param {Attr|Text} node
|
|
663
|
-
* @param {Element} element
|
|
842
|
+
* @param {Element|null} [element]
|
|
664
843
|
* @param {InterpolateOptions} [options]
|
|
665
844
|
* @param {string} [parsedValue]
|
|
666
845
|
* @return {true|undefined} remove node
|
|
@@ -683,7 +862,7 @@ export default class Composition {
|
|
|
683
862
|
if (!nodeValue) return;
|
|
684
863
|
const trimmed = nodeValue.trim();
|
|
685
864
|
if (!trimmed) return;
|
|
686
|
-
if (attr) {
|
|
865
|
+
if (attr || element?.tagName === 'STYLE') {
|
|
687
866
|
if (trimmed[0] !== '{') return;
|
|
688
867
|
const { length } = trimmed;
|
|
689
868
|
if (trimmed[length - 1] !== '}') return;
|
|
@@ -798,7 +977,7 @@ export default class Composition {
|
|
|
798
977
|
/** @type {RenderGraphSearch} */
|
|
799
978
|
let search;
|
|
800
979
|
|
|
801
|
-
if (this.searchByQuery
|
|
980
|
+
if (this.searchByQuery?.has(query)) {
|
|
802
981
|
search = this.searchByQuery.get(query);
|
|
803
982
|
} else {
|
|
804
983
|
// Has subquery?
|
|
@@ -806,7 +985,7 @@ export default class Composition {
|
|
|
806
985
|
const isSubquery = subquery !== query;
|
|
807
986
|
/** @type {RenderGraphSearch} */
|
|
808
987
|
let subSearch;
|
|
809
|
-
if (isSubquery && this.searchByQuery
|
|
988
|
+
if (isSubquery && this.searchByQuery?.has(subquery)) {
|
|
810
989
|
subSearch = this.searchByQuery.get(subquery);
|
|
811
990
|
} else {
|
|
812
991
|
// Construct subsearch, even is not subquery.
|
|
@@ -846,7 +1025,7 @@ export default class Composition {
|
|
|
846
1025
|
}
|
|
847
1026
|
if (defaultValue == null && options?.injections) {
|
|
848
1027
|
defaultValue = valueFromPropName(parsedValue, options.injections);
|
|
849
|
-
console.log('default value from injection', parsedValue, { defaultValue });
|
|
1028
|
+
// console.log('default value from injection', parsedValue, { defaultValue });
|
|
850
1029
|
}
|
|
851
1030
|
}
|
|
852
1031
|
|
|
@@ -893,9 +1072,8 @@ export default class Composition {
|
|
|
893
1072
|
inlineFunctionOptions.deepProps = deepPropsUsed;
|
|
894
1073
|
}
|
|
895
1074
|
subSearch = {
|
|
896
|
-
cacheIndex: this
|
|
897
|
-
|
|
898
|
-
ranFlagIndex: this.#interpolationState.ranFlagIndex++,
|
|
1075
|
+
cacheIndex: this._interpolationState.cacheIndex++,
|
|
1076
|
+
searchIndex: this._interpolationState.searchIndex++,
|
|
899
1077
|
query: subquery,
|
|
900
1078
|
defaultValue,
|
|
901
1079
|
subSearch: null,
|
|
@@ -910,9 +1088,8 @@ export default class Composition {
|
|
|
910
1088
|
}
|
|
911
1089
|
if (isSubquery) {
|
|
912
1090
|
search = {
|
|
913
|
-
cacheIndex: this
|
|
914
|
-
|
|
915
|
-
ranFlagIndex: this.#interpolationState.ranFlagIndex++,
|
|
1091
|
+
cacheIndex: this._interpolationState.cacheIndex++,
|
|
1092
|
+
searchIndex: this._interpolationState.searchIndex++,
|
|
916
1093
|
query,
|
|
917
1094
|
subSearch,
|
|
918
1095
|
negate,
|
|
@@ -942,7 +1119,6 @@ export default class Composition {
|
|
|
942
1119
|
let subnode = null;
|
|
943
1120
|
let defaultValue = search.defaultValue;
|
|
944
1121
|
if (text) {
|
|
945
|
-
text.data = defaultValue;
|
|
946
1122
|
subnode = textNodeIndex;
|
|
947
1123
|
} else if (nodeName === 'mdw-if') {
|
|
948
1124
|
tag = this.#tagElement(element);
|
|
@@ -960,15 +1136,15 @@ export default class Composition {
|
|
|
960
1136
|
tag ??= this.#tagElement(element);
|
|
961
1137
|
|
|
962
1138
|
// Node entry
|
|
963
|
-
let nodeEntry = this
|
|
1139
|
+
let nodeEntry = this._interpolationState.nodeEntry;
|
|
964
1140
|
if (!nodeEntry || nodeEntry.tag !== tag) {
|
|
965
1141
|
nodeEntry = {
|
|
966
1142
|
tag,
|
|
967
1143
|
textNodes: [],
|
|
968
1144
|
};
|
|
969
|
-
this
|
|
1145
|
+
this._interpolationState.nodeEntry = nodeEntry;
|
|
970
1146
|
this.nodesToBind.push(nodeEntry);
|
|
971
|
-
this
|
|
1147
|
+
this._interpolationState.nodeIndex++;
|
|
972
1148
|
}
|
|
973
1149
|
|
|
974
1150
|
/** @type {RenderGraphAction} */
|
|
@@ -978,25 +1154,38 @@ export default class Composition {
|
|
|
978
1154
|
if (text) {
|
|
979
1155
|
nodeEntry.textNodes.push(textNodeIndex);
|
|
980
1156
|
|
|
981
|
-
this
|
|
1157
|
+
this._interpolationState.nodeIndex++;
|
|
982
1158
|
action = {
|
|
983
|
-
nodeIndex: this
|
|
984
|
-
|
|
1159
|
+
nodeIndex: this._interpolationState.nodeIndex,
|
|
1160
|
+
commentIndex: this._interpolationState.commentIndex++,
|
|
1161
|
+
invocation: writeDynamicNode,
|
|
985
1162
|
defaultValue,
|
|
986
1163
|
search,
|
|
987
1164
|
};
|
|
1165
|
+
switch (typeof defaultValue) {
|
|
1166
|
+
case 'string':
|
|
1167
|
+
text.data = defaultValue;
|
|
1168
|
+
break;
|
|
1169
|
+
case 'number':
|
|
1170
|
+
// Manually coerce to string (0 will be empty otherwise)
|
|
1171
|
+
text.data = `${defaultValue}`;
|
|
1172
|
+
break;
|
|
1173
|
+
default:
|
|
1174
|
+
text.data = '';
|
|
1175
|
+
break;
|
|
1176
|
+
}
|
|
988
1177
|
} else if (subnode) {
|
|
989
1178
|
action = {
|
|
990
|
-
nodeIndex: this
|
|
991
|
-
attrName: subnode,
|
|
1179
|
+
nodeIndex: this._interpolationState.nodeIndex,
|
|
1180
|
+
attrName: /** @type {string} */ (subnode),
|
|
992
1181
|
defaultValue,
|
|
993
1182
|
invocation: writeDOMAttribute,
|
|
994
1183
|
search,
|
|
995
1184
|
};
|
|
996
1185
|
} else {
|
|
997
1186
|
action = {
|
|
998
|
-
nodeIndex: this
|
|
999
|
-
commentIndex: this
|
|
1187
|
+
nodeIndex: this._interpolationState.nodeIndex,
|
|
1188
|
+
commentIndex: this._interpolationState.commentIndex++,
|
|
1000
1189
|
defaultValue,
|
|
1001
1190
|
invocation: writeDOMElementAttachedState,
|
|
1002
1191
|
search,
|
|
@@ -1004,13 +1193,15 @@ export default class Composition {
|
|
|
1004
1193
|
if (!defaultValue) {
|
|
1005
1194
|
this.postInitActions.push({
|
|
1006
1195
|
...action,
|
|
1007
|
-
invocation:
|
|
1196
|
+
invocation: writeDOMHideNodeOnInit,
|
|
1008
1197
|
});
|
|
1009
1198
|
}
|
|
1010
1199
|
}
|
|
1011
1200
|
|
|
1012
1201
|
this.addAction(action);
|
|
1013
|
-
|
|
1202
|
+
// eslint-disable-next-line no-multi-assign
|
|
1203
|
+
const tagsWithBindings = (this.tagsWithBindings ??= new Set());
|
|
1204
|
+
tagsWithBindings.add(tag);
|
|
1014
1205
|
}
|
|
1015
1206
|
|
|
1016
1207
|
/**
|
|
@@ -1018,6 +1209,7 @@ export default class Composition {
|
|
|
1018
1209
|
* @return {string}
|
|
1019
1210
|
*/
|
|
1020
1211
|
#tagElement(element) {
|
|
1212
|
+
if (!element) return '';
|
|
1021
1213
|
let id = element.id;
|
|
1022
1214
|
if (id) {
|
|
1023
1215
|
if (!this.allIds.includes(id)) {
|
|
@@ -1025,7 +1217,9 @@ export default class Composition {
|
|
|
1025
1217
|
}
|
|
1026
1218
|
} else {
|
|
1027
1219
|
id = generateUID();
|
|
1028
|
-
|
|
1220
|
+
// eslint-disable-next-line no-multi-assign
|
|
1221
|
+
const temporaryIds = (this.temporaryIds ??= new Set());
|
|
1222
|
+
temporaryIds.add(id);
|
|
1029
1223
|
this.allIds.push(id);
|
|
1030
1224
|
element.id = id;
|
|
1031
1225
|
}
|
|
@@ -1034,11 +1228,10 @@ export default class Composition {
|
|
|
1034
1228
|
|
|
1035
1229
|
/**
|
|
1036
1230
|
* TODO: Subtemplating lacks optimization, though functional.
|
|
1037
|
-
*
|
|
1231
|
+
* - Would benefit from custom type handler for arrays
|
|
1038
1232
|
* to avoid multi-iteration change-detection.
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
1233
|
+
* - Could benefit from debounced/throttled render
|
|
1234
|
+
* - Consider remap of {item.prop} as {array[index].prop}
|
|
1042
1235
|
* @param {Element} element
|
|
1043
1236
|
* @param {InterpolateOptions} options
|
|
1044
1237
|
* @return {?Composition<?>}
|
|
@@ -1066,26 +1259,26 @@ export default class Composition {
|
|
|
1066
1259
|
element.removeAttribute('mdw-for');
|
|
1067
1260
|
// Create a new composition targetting element as root
|
|
1068
1261
|
|
|
1069
|
-
const elementAnchor =
|
|
1262
|
+
const elementAnchor = element.ownerDocument.createElement('template');
|
|
1070
1263
|
element.replaceWith(elementAnchor);
|
|
1071
1264
|
const tag = this.#tagElement(elementAnchor);
|
|
1072
1265
|
// console.log('tagging placeholder element with', elementAnchor, tag);
|
|
1073
1266
|
|
|
1074
|
-
let nodeEntry = this
|
|
1267
|
+
let nodeEntry = this._interpolationState.nodeEntry;
|
|
1075
1268
|
if (!nodeEntry || nodeEntry.tag !== tag) {
|
|
1076
1269
|
nodeEntry = {
|
|
1077
1270
|
tag,
|
|
1078
1271
|
textNodes: [],
|
|
1079
1272
|
};
|
|
1080
|
-
this
|
|
1273
|
+
this._interpolationState.nodeEntry = nodeEntry;
|
|
1081
1274
|
this.nodesToBind.push(nodeEntry);
|
|
1082
|
-
this
|
|
1083
|
-
console.log('adding node entry', tag, this.#interpolationState.nodeIndex);
|
|
1275
|
+
this._interpolationState.nodeIndex++;
|
|
1084
1276
|
}
|
|
1085
1277
|
|
|
1086
1278
|
const newComposition = new Composition();
|
|
1087
1279
|
newComposition.template.append(element);
|
|
1088
1280
|
// Move uninterpolated element to new composition template.
|
|
1281
|
+
/** @type {InterpolateOptions['injections']} */
|
|
1089
1282
|
const injections = {
|
|
1090
1283
|
...options.injections,
|
|
1091
1284
|
[valueName]: null,
|
|
@@ -1095,24 +1288,23 @@ export default class Composition {
|
|
|
1095
1288
|
const propsUsed = [iterableName];
|
|
1096
1289
|
/** @type {RenderGraphSearch} */
|
|
1097
1290
|
const search = {
|
|
1098
|
-
cacheIndex: this
|
|
1099
|
-
|
|
1100
|
-
|
|
1291
|
+
cacheIndex: this._interpolationState.cacheIndex++,
|
|
1292
|
+
searchIndex: this._interpolationState.searchIndex++,
|
|
1293
|
+
query: null,
|
|
1294
|
+
prop: null,
|
|
1295
|
+
deepProp: null,
|
|
1101
1296
|
propsUsed,
|
|
1102
1297
|
deepPropsUsed: [[iterableName]],
|
|
1103
1298
|
defaultValue: {},
|
|
1104
|
-
invocation
|
|
1105
|
-
// Return unique to always specify dirty
|
|
1106
|
-
return {};
|
|
1107
|
-
},
|
|
1299
|
+
invocation: null,
|
|
1108
1300
|
};
|
|
1109
1301
|
|
|
1110
1302
|
/** @type {RenderGraphAction} */
|
|
1111
1303
|
const action = {
|
|
1112
1304
|
defaultValue: null,
|
|
1113
|
-
nodeIndex: this
|
|
1305
|
+
nodeIndex: this._interpolationState.nodeIndex,
|
|
1114
1306
|
search,
|
|
1115
|
-
commentIndex: this
|
|
1307
|
+
commentIndex: this._interpolationState.commentIndex++,
|
|
1116
1308
|
injections,
|
|
1117
1309
|
invocation(state, value, changes, data) {
|
|
1118
1310
|
if (!newComposition.adapter) {
|
|
@@ -1120,7 +1312,7 @@ export default class Composition {
|
|
|
1120
1312
|
const instanceAnchorElement = state.nodes[this.nodeIndex];
|
|
1121
1313
|
const anchorNode = createEmptyComment();
|
|
1122
1314
|
// Avoid leak
|
|
1123
|
-
state.
|
|
1315
|
+
state.comments[this.commentIndex] = anchorNode;
|
|
1124
1316
|
instanceAnchorElement.replaceWith(anchorNode);
|
|
1125
1317
|
newComposition.adapter = new CompositionAdapter({
|
|
1126
1318
|
anchorNode,
|
|
@@ -1145,8 +1337,9 @@ export default class Composition {
|
|
|
1145
1337
|
const needTargetAll = newComposition.props.some((prop) => prop !== iterableName && prop in changes);
|
|
1146
1338
|
|
|
1147
1339
|
adapter.startBatch();
|
|
1148
|
-
|
|
1149
|
-
|
|
1340
|
+
let isArray;
|
|
1341
|
+
if (!needTargetAll && !(isArray = Array.isArray(changeList))) {
|
|
1342
|
+
const iterator = isArray ? changeList.entries() : Object.entries(changeList);
|
|
1150
1343
|
// console.log('changeList render', iterator);
|
|
1151
1344
|
for (const [key, change] of iterator) {
|
|
1152
1345
|
if (key === 'length') continue;
|
|
@@ -1204,7 +1397,9 @@ export default class Composition {
|
|
|
1204
1397
|
propsUsed.push(...newComposition.props);
|
|
1205
1398
|
this.addSearch(search);
|
|
1206
1399
|
this.addAction(action);
|
|
1207
|
-
|
|
1400
|
+
// eslint-disable-next-line no-multi-assign
|
|
1401
|
+
const tagsWithBindings = (this.tagsWithBindings ??= new Set());
|
|
1402
|
+
tagsWithBindings.add(tag);
|
|
1208
1403
|
// console.log('adding', iterable, 'bind to', this);
|
|
1209
1404
|
// this.addBinding(iterable, entry);
|
|
1210
1405
|
return newComposition;
|
|
@@ -1232,31 +1427,23 @@ export default class Composition {
|
|
|
1232
1427
|
switch (node.nodeType) {
|
|
1233
1428
|
case Node.ELEMENT_NODE:
|
|
1234
1429
|
element = /** @type {Element} */ (node);
|
|
1235
|
-
if (element
|
|
1236
|
-
node = treeWalker.
|
|
1430
|
+
if (element.tagName === 'TEMPLATE') {
|
|
1431
|
+
while (element.contains(node = treeWalker.nextNode()));
|
|
1237
1432
|
continue;
|
|
1238
1433
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
if (node.parentNode === this.cloneable) {
|
|
1242
|
-
this.styles.push(node);
|
|
1243
|
-
node.remove();
|
|
1244
|
-
node = treeWalker.nextSibling();
|
|
1245
|
-
continue;
|
|
1246
|
-
}
|
|
1247
|
-
console.warn('<style> element not moved');
|
|
1248
|
-
}
|
|
1249
|
-
if (node instanceof HTMLScriptElement) {
|
|
1434
|
+
|
|
1435
|
+
if (element.tagName === 'SCRIPT') {
|
|
1250
1436
|
console.warn('<script> element found.');
|
|
1251
|
-
node.
|
|
1252
|
-
node = treeWalker.nextSibling();
|
|
1437
|
+
while (element.contains(node = treeWalker.nextNode()));
|
|
1253
1438
|
continue;
|
|
1254
1439
|
}
|
|
1255
1440
|
|
|
1256
1441
|
if (element.hasAttribute('mdw-for')) {
|
|
1257
|
-
node = treeWalker.
|
|
1442
|
+
while (element.contains(node = treeWalker.nextNode()));
|
|
1258
1443
|
this.#interpolateIterable(element, options);
|
|
1444
|
+
continue;
|
|
1259
1445
|
} else {
|
|
1446
|
+
// @ts-expect-error Bad typings
|
|
1260
1447
|
const idAttr = element.attributes.id;
|
|
1261
1448
|
if (idAttr) {
|
|
1262
1449
|
this.#interpolateNode(idAttr, element, options);
|
|
@@ -1270,14 +1457,13 @@ export default class Composition {
|
|
|
1270
1457
|
|
|
1271
1458
|
break;
|
|
1272
1459
|
case Node.TEXT_NODE:
|
|
1273
|
-
element = node.
|
|
1460
|
+
element = node.parentElement;
|
|
1274
1461
|
if (this.#interpolateNode(/** @type {Text} */ (node), element, options)) {
|
|
1275
1462
|
const nextNode = treeWalker.nextNode();
|
|
1276
|
-
node.remove();
|
|
1463
|
+
/** @type {Text} */ (node).remove();
|
|
1277
1464
|
node = nextNode;
|
|
1278
1465
|
continue;
|
|
1279
1466
|
}
|
|
1280
|
-
|
|
1281
1467
|
break;
|
|
1282
1468
|
default:
|
|
1283
1469
|
throw new Error(`Unexpected node type: ${node.nodeType}`);
|
|
@@ -1296,10 +1482,12 @@ export default class Composition {
|
|
|
1296
1482
|
);
|
|
1297
1483
|
}
|
|
1298
1484
|
|
|
1299
|
-
this.props =
|
|
1485
|
+
this.props = this.actionsByPropsUsed
|
|
1486
|
+
? [...this.actionsByPropsUsed.keys()]
|
|
1487
|
+
: [];
|
|
1300
1488
|
|
|
1301
1489
|
for (const id of this.allIds) {
|
|
1302
|
-
if (!this.tagsWithBindings
|
|
1490
|
+
if (!this.tagsWithBindings?.has(id)) {
|
|
1303
1491
|
this.nodesToBind.push({
|
|
1304
1492
|
tag: id,
|
|
1305
1493
|
textNodes: [],
|
|
@@ -1308,7 +1496,6 @@ export default class Composition {
|
|
|
1308
1496
|
}
|
|
1309
1497
|
|
|
1310
1498
|
this.tags = this.nodesToBind.map((n) => n.tag);
|
|
1311
|
-
|
|
1312
1499
|
this.interpolated = true;
|
|
1313
1500
|
|
|
1314
1501
|
// console.log('Cloneable', [...this.cloneable.children].map((child) => child.outerHTML).join('\n'));
|
|
@@ -1321,7 +1508,9 @@ export default class Composition {
|
|
|
1321
1508
|
addSearch(search) {
|
|
1322
1509
|
this.searches.push(search);
|
|
1323
1510
|
if (search.query) {
|
|
1324
|
-
|
|
1511
|
+
// eslint-disable-next-line no-multi-assign
|
|
1512
|
+
const searchByQuery = (this.searchByQuery ??= new Map());
|
|
1513
|
+
searchByQuery.set(search.query, search);
|
|
1325
1514
|
this.initCache[search.cacheIndex] = search.defaultValue;
|
|
1326
1515
|
}
|
|
1327
1516
|
return search;
|
|
@@ -1332,12 +1521,13 @@ export default class Composition {
|
|
|
1332
1521
|
* @return {RenderGraphAction}
|
|
1333
1522
|
*/
|
|
1334
1523
|
addAction(action) {
|
|
1335
|
-
|
|
1524
|
+
// eslint-disable-next-line no-multi-assign
|
|
1525
|
+
const actionsByPropsUsed = (this.actionsByPropsUsed ??= new Map());
|
|
1336
1526
|
for (const prop of action.search.propsUsed) {
|
|
1337
|
-
if (
|
|
1338
|
-
|
|
1527
|
+
if (actionsByPropsUsed.has(prop)) {
|
|
1528
|
+
actionsByPropsUsed.get(prop).push(action);
|
|
1339
1529
|
} else {
|
|
1340
|
-
|
|
1530
|
+
actionsByPropsUsed.set(prop, [action]);
|
|
1341
1531
|
}
|
|
1342
1532
|
}
|
|
1343
1533
|
return action;
|