@shortfuse/materialdesignweb 0.7.6 → 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 +87 -90
- package/bin/mdw-css.js +1 -1
- package/components/Badge.js +14 -7
- package/components/Body.js +3 -0
- package/components/BottomAppBar.js +4 -13
- package/components/BottomSheet.js +424 -0
- package/components/Box.js +20 -28
- package/components/Button.js +85 -79
- package/components/Button.md +9 -9
- package/components/Card.js +60 -72
- package/components/Checkbox.js +33 -42
- package/components/CheckboxIcon.js +11 -29
- package/components/Chip.js +13 -11
- package/components/Dialog.js +214 -394
- package/components/DialogActions.js +2 -2
- package/components/Display.js +55 -0
- package/components/Divider.js +3 -3
- package/components/Fab.js +83 -18
- package/components/FabContainer.js +48 -0
- package/components/FilterChip.js +35 -33
- package/components/Grid.js +176 -0
- package/components/Headline.js +5 -28
- package/components/Icon.js +61 -76
- package/components/IconButton.js +72 -126
- package/components/Input.js +859 -1
- package/components/InputChip.js +161 -0
- package/components/Label.js +3 -0
- package/components/List.js +4 -6
- package/components/ListItem.js +46 -30
- package/components/ListOption.js +86 -53
- package/components/Listbox.js +248 -0
- package/components/Menu.js +69 -528
- package/components/MenuItem.js +33 -36
- package/components/NavBar.js +49 -86
- package/components/NavDrawer.js +16 -15
- package/components/NavDrawerItem.js +4 -5
- package/components/NavItem.js +58 -41
- package/components/NavRail.js +30 -20
- package/components/NavRailItem.js +8 -3
- package/components/Page.js +105 -0
- package/components/Pane.js +11 -274
- package/components/Popup.js +29 -0
- package/components/Progress.js +24 -23
- package/components/Radio.js +40 -36
- package/components/RadioIcon.js +12 -16
- package/components/Ripple.js +13 -10
- package/components/Root.js +209 -0
- package/components/Scrim.js +87 -0
- package/components/Search.js +77 -0
- package/components/SegmentedButton.js +33 -45
- package/components/SegmentedButtonGroup.js +25 -13
- package/components/Select.js +10 -11
- package/components/Shape.js +5 -65
- package/components/SideSheet.js +308 -0
- package/components/Slider.js +108 -78
- package/components/Snackbar.js +26 -21
- package/components/SnackbarContainer.js +42 -0
- package/components/Surface.js +17 -12
- package/components/Switch.js +45 -24
- package/components/SwitchIcon.js +49 -39
- package/components/Tab.js +64 -43
- package/components/TabContent.js +5 -3
- package/components/TabList.js +62 -34
- package/components/TabPanel.js +11 -8
- package/components/Table.js +116 -0
- package/components/TextArea.js +54 -50
- package/components/Title.js +4 -9
- package/components/Tooltip.js +44 -22
- package/components/TopAppBar.js +68 -172
- package/constants/shapes.js +36 -0
- package/constants/typography.js +127 -0
- package/core/Composition.js +1164 -645
- package/core/CompositionAdapter.js +314 -0
- package/core/CustomElement.js +701 -286
- package/core/css.js +121 -15
- package/core/customTypes.js +157 -40
- package/core/dom.js +17 -11
- package/{utils → core}/jsonMergePatch.js +42 -18
- package/core/observe.js +343 -244
- package/core/optimizations.js +23 -0
- package/core/template.js +19 -56
- package/core/uid.js +13 -0
- package/dist/index.min.js +85 -184
- package/dist/index.min.js.map +4 -4
- package/dist/meta.json +1 -1
- package/dom/HTMLOptionsCollectionProxy.js +106 -0
- package/loaders/palette.js +13 -0
- package/loaders/theme.js +12 -0
- package/mixins/AriaReflectorMixin.js +53 -14
- package/mixins/AriaToolbarMixin.js +5 -3
- package/mixins/ControlMixin.js +92 -41
- package/mixins/DelegatesFocusMixin.js +54 -0
- package/mixins/DensityMixin.js +2 -3
- package/mixins/ElevationMixin.js +62 -0
- package/mixins/FlexableMixin.js +67 -39
- package/mixins/FormAssociatedMixin.js +71 -16
- package/mixins/HyperlinkMixin.js +66 -0
- package/mixins/InputMixin.js +205 -39
- package/mixins/KeyboardNavMixin.js +22 -7
- package/mixins/NavigationListenerMixin.js +33 -0
- package/mixins/PopupMixin.js +725 -0
- package/mixins/RTLObserverMixin.js +0 -1
- package/mixins/ResizeObserverMixin.js +16 -5
- package/mixins/RippleMixin.js +11 -10
- package/mixins/ScrollListenerMixin.js +42 -33
- package/mixins/SemiStickyMixin.js +97 -0
- package/mixins/ShapeMaskedMixin.js +117 -0
- package/mixins/ShapeMixin.js +17 -194
- package/mixins/StateMixin.js +80 -39
- package/mixins/TextFieldMixin.js +139 -183
- package/mixins/ThemableMixin.js +71 -161
- package/mixins/TooltipTriggerMixin.js +292 -366
- package/mixins/TouchTargetMixin.js +5 -4
- package/mixins/TypographyMixin.js +121 -0
- package/package.json +111 -71
- package/services/rtl.js +10 -0
- package/services/svgAlias.js +17 -0
- package/{theming/index.js → services/theme.js} +25 -175
- 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/{hct → material-color}/blend.js +8 -10
- package/utils/{hct → material-color/hct}/Cam16.js +196 -69
- package/utils/{hct → material-color/hct}/Hct.js +61 -19
- package/utils/{hct → material-color/hct}/ViewingConditions.js +3 -3
- package/utils/{hct → material-color/hct}/hctSolver.js +9 -16
- package/utils/{hct → material-color}/helper.js +11 -18
- package/utils/{hct → material-color/palettes}/CorePalette.js +79 -19
- package/utils/{hct → material-color/palettes}/TonalPalette.js +12 -4
- package/utils/material-color/scheme/Scheme.js +376 -0
- package/utils/{hct/colorUtils.js → material-color/utils/color.js} +61 -1
- package/utils/pixelmatch.js +360 -0
- package/utils/popup.js +127 -30
- package/utils/searchParams.js +19 -0
- package/components/ExtendedFab.js +0 -36
- package/components/Layout.js +0 -35
- package/components/ListSelect.js +0 -220
- package/components/Nav.js +0 -40
- package/components/Option.js +0 -91
- package/core/ICustomElement.d.ts +0 -291
- package/core/ICustomElement.js +0 -1
- package/core/identify.js +0 -40
- package/core/typings.d.ts +0 -136
- package/core/typings.js +0 -1
- package/mixins/SurfaceMixin.js +0 -181
- package/theming/loader.js +0 -22
- package/utils/hct/Scheme.js +0 -587
- /package/{utils/color_keywords.js → constants/colorKeywords.js} +0 -0
- /package/utils/{hct/mathUtils.js → material-color/utils/math.js} +0 -0
package/core/css.js
CHANGED
|
@@ -1,19 +1,84 @@
|
|
|
1
|
+
/** @type {Map<string, CSSStyleSheet>} */
|
|
2
|
+
const cssStyleSheetsCache = new Map();
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {string} content
|
|
6
|
+
* @param {boolean} [useCache=true]
|
|
7
|
+
* @return {CSSStyleSheet}
|
|
8
|
+
*/
|
|
9
|
+
export function createCSSStyleSheet(content, useCache = true) {
|
|
10
|
+
if (useCache && cssStyleSheetsCache.has(content)) {
|
|
11
|
+
return cssStyleSheetsCache.get(content);
|
|
12
|
+
}
|
|
13
|
+
const sheet = new CSSStyleSheet();
|
|
14
|
+
sheet.replaceSync(content);
|
|
15
|
+
if (useCache) {
|
|
16
|
+
cssStyleSheetsCache.set(content, sheet);
|
|
17
|
+
}
|
|
18
|
+
return sheet;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** @type {Map<string, HTMLStyleElement>} */
|
|
22
|
+
const styleElementCache = new Map();
|
|
23
|
+
|
|
24
|
+
/** @type {Document} */
|
|
25
|
+
let _inactiveDocument;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} content
|
|
29
|
+
* @param {boolean} [useCache=true]
|
|
30
|
+
* @return {HTMLStyleElement}
|
|
31
|
+
*/
|
|
32
|
+
export function createHTMLStyleElement(content, useCache = true) {
|
|
33
|
+
let style;
|
|
34
|
+
if (useCache && styleElementCache.has(content)) {
|
|
35
|
+
style = styleElementCache.get(content);
|
|
36
|
+
} else {
|
|
37
|
+
_inactiveDocument ??= document.implementation.createHTMLDocument();
|
|
38
|
+
style = _inactiveDocument.createElement('style');
|
|
39
|
+
style.textContent = content;
|
|
40
|
+
if (useCache) {
|
|
41
|
+
styleElementCache.set(content, style);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return /** @type {HTMLStyleElement} */ (style.cloneNode(true));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** @type {boolean} */
|
|
48
|
+
let _cssStyleSheetConstructable;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {string} content
|
|
52
|
+
* @param {boolean} [useCache=true]
|
|
53
|
+
*/
|
|
54
|
+
export function createCSS(content, useCache = true) {
|
|
55
|
+
if (_cssStyleSheetConstructable == null) {
|
|
56
|
+
try {
|
|
57
|
+
const sheet = createCSSStyleSheet(content, useCache);
|
|
58
|
+
_cssStyleSheetConstructable = true;
|
|
59
|
+
return sheet;
|
|
60
|
+
} catch {
|
|
61
|
+
_cssStyleSheetConstructable = false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return _cssStyleSheetConstructable
|
|
65
|
+
? createCSSStyleSheet(content, useCache)
|
|
66
|
+
: createHTMLStyleElement(content, useCache);
|
|
67
|
+
}
|
|
68
|
+
|
|
1
69
|
/**
|
|
2
70
|
* @param {Iterable<HTMLStyleElement|CSSStyleSheet>} styles
|
|
71
|
+
* @param {boolean} [useCache=true]
|
|
3
72
|
* @yields composed CSSStyleSheet
|
|
4
73
|
* @return {Generator<CSSStyleSheet>} composed CSSStyleSheet
|
|
5
74
|
*/
|
|
6
|
-
export function* generateCSSStyleSheets(styles) {
|
|
75
|
+
export function* generateCSSStyleSheets(styles, useCache = true) {
|
|
7
76
|
for (const style of styles) {
|
|
8
77
|
if (style instanceof HTMLStyleElement) {
|
|
9
|
-
|
|
10
|
-
sheet.replaceSync(style.textContent);
|
|
11
|
-
yield sheet;
|
|
78
|
+
yield createCSSStyleSheet(style.textContent, useCache);
|
|
12
79
|
} else if (style.ownerNode) {
|
|
13
80
|
console.warn('Stylesheet is part of style');
|
|
14
|
-
|
|
15
|
-
sheet.replaceSync([...style.cssRules].map((r) => r.cssText).join(''));
|
|
16
|
-
yield sheet;
|
|
81
|
+
yield createCSSStyleSheet([...style.cssRules].map((r) => r.cssText).join(''), useCache);
|
|
17
82
|
} else {
|
|
18
83
|
yield style;
|
|
19
84
|
}
|
|
@@ -21,14 +86,15 @@ export function* generateCSSStyleSheets(styles) {
|
|
|
21
86
|
}
|
|
22
87
|
|
|
23
88
|
/** @type {WeakMap<CSSStyleSheet, HTMLStyleElement>} */
|
|
24
|
-
const
|
|
89
|
+
const styleElementFromStyleSheetCache = new WeakMap();
|
|
25
90
|
|
|
26
91
|
/**
|
|
27
92
|
* @param {Iterable<HTMLStyleElement|CSSStyleSheet>} styles
|
|
93
|
+
* @param {boolean} [useCache=true]
|
|
28
94
|
* @yields composed HTMLStyleElement
|
|
29
95
|
* @return {Generator<HTMLStyleElement>} composed CSSStyleSheet
|
|
30
96
|
*/
|
|
31
|
-
export function* generateHTMLStyleElements(styles) {
|
|
97
|
+
export function* generateHTMLStyleElements(styles, useCache = true) {
|
|
32
98
|
for (const style of styles) {
|
|
33
99
|
if (style instanceof HTMLStyleElement) {
|
|
34
100
|
yield style;
|
|
@@ -36,16 +102,56 @@ export function* generateHTMLStyleElements(styles) {
|
|
|
36
102
|
// console.log('Cloning parent HTMLStyleElement instead');
|
|
37
103
|
// @ts-ignore Skip cast
|
|
38
104
|
yield style.ownerNode.cloneNode(true);
|
|
105
|
+
} else if (useCache && styleElementFromStyleSheetCache.has(style)) {
|
|
106
|
+
// @ts-ignore Skip cast
|
|
107
|
+
yield styleElementFromStyleSheetCache.get(style).cloneNode(true);
|
|
39
108
|
} else {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
styleElementWrappers.set(style, styleElement);
|
|
109
|
+
console.warn('Manually constructing HTMLStyleElement', [...style.cssRules].map((r) => r.cssText).join('\n'));
|
|
110
|
+
const styleElement = document.createElement('style');
|
|
111
|
+
styleElement.textContent = [...style.cssRules].map((r) => r.cssText).join('');
|
|
112
|
+
if (useCache) {
|
|
113
|
+
styleElementFromStyleSheetCache.set(style, styleElement);
|
|
46
114
|
}
|
|
115
|
+
|
|
47
116
|
// @ts-ignore Skip cast
|
|
48
117
|
yield styleElement.cloneNode(true);
|
|
49
118
|
}
|
|
50
119
|
}
|
|
51
120
|
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {TemplateStringsArray|string} array
|
|
124
|
+
* @param {...any} substitutions
|
|
125
|
+
* @return {HTMLStyleElement|CSSStyleSheet}
|
|
126
|
+
*/
|
|
127
|
+
export function css(array, ...substitutions) {
|
|
128
|
+
if (typeof array === 'string') return createCSS(array);
|
|
129
|
+
return createCSS(String.raw({ raw: array }, ...substitutions));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {TemplateStringsArray|string|HTMLStyleElement|CSSStyleSheet} styles
|
|
134
|
+
* @param {...any} substitutions
|
|
135
|
+
* @return {HTMLStyleElement|CSSStyleSheet}
|
|
136
|
+
*/
|
|
137
|
+
export function addGlobalCss(styles, ...substitutions) {
|
|
138
|
+
/** @type {HTMLStyleElement|CSSStyleSheet} */
|
|
139
|
+
let compiled;
|
|
140
|
+
if (typeof styles === 'string') {
|
|
141
|
+
compiled = css(styles);
|
|
142
|
+
} else if (Array.isArray(styles)) {
|
|
143
|
+
compiled = css(/** @type {TemplateStringsArray} */ (styles), ...substitutions);
|
|
144
|
+
} else {
|
|
145
|
+
compiled = /** @type {HTMLStyleElement|CSSStyleSheet} */ (styles);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (compiled instanceof HTMLStyleElement) {
|
|
149
|
+
document.head.append(compiled);
|
|
150
|
+
} else {
|
|
151
|
+
document.adoptedStyleSheets = [
|
|
152
|
+
...document.adoptedStyleSheets,
|
|
153
|
+
compiled,
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
return compiled;
|
|
157
|
+
}
|
package/core/customTypes.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
/** @typedef {import('./CustomElement').default} CustomElement */
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const eventHandlerValues = new Map();
|
|
3
|
+
import { attrNameFromPropName } from './dom.js';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* @see https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-attributes
|
|
8
|
-
* @type {import('./
|
|
7
|
+
* @type {import('./observe.js').ObserverOptions<'function',EventListener, unknown>}
|
|
9
8
|
*/
|
|
10
9
|
export const EVENT_HANDLER_TYPE = {
|
|
11
10
|
type: 'function',
|
|
12
11
|
reflect: 'read',
|
|
13
12
|
value: null,
|
|
14
|
-
values: eventHandlerValues,
|
|
15
13
|
parser(v) { return v; },
|
|
16
14
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
17
15
|
if (oldValue == null && newValue == null) return;
|
|
18
|
-
// Must continue if oldValue === newValue;
|
|
16
|
+
// Must continue even if oldValue === newValue;
|
|
19
17
|
if (newValue == null) {
|
|
20
18
|
this[name] = null;
|
|
21
19
|
return;
|
|
@@ -43,45 +41,66 @@ export const EVENT_HANDLER_TYPE = {
|
|
|
43
41
|
const weakRefValues = new WeakMap();
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
|
-
* @type {import('./
|
|
44
|
+
* @type {import('./observe.js').ObserverOptions<'object',HTMLElement>}
|
|
47
45
|
*/
|
|
48
46
|
export const WEAKREF_TYPE = {
|
|
49
47
|
type: 'object',
|
|
50
48
|
reflect: false,
|
|
51
49
|
value: null,
|
|
52
|
-
values: weakRefValues,
|
|
53
50
|
parser(v) { return new WeakRef(v); },
|
|
54
51
|
get() {
|
|
55
|
-
|
|
52
|
+
if (weakRefValues.has(this)) {
|
|
53
|
+
return weakRefValues.get(this).deref();
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
56
|
},
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
-
/** @type {WeakMap<any, Animation>} */
|
|
60
|
-
const elementStylerLastAnimation = new WeakMap();
|
|
61
|
-
/** @type {WeakMap<CustomElement, ElementStylerOptions>} */
|
|
62
|
-
const elementStylerValues = new WeakMap();
|
|
63
|
-
/** @type {WeakSet<any>} */
|
|
64
|
-
const elementStylerHasQueue = new WeakSet();
|
|
65
|
-
|
|
66
59
|
/**
|
|
67
60
|
* @typedef {Object} ElementStylerOptions
|
|
68
|
-
* @prop {string} target
|
|
61
|
+
* @prop {string|HTMLElement|null} target tag, element or null (host)
|
|
69
62
|
* @prop {Keyframe} styles
|
|
70
63
|
* @prop {EffectTiming} [timing]
|
|
71
64
|
*/
|
|
72
65
|
|
|
73
|
-
/**
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
66
|
+
/**
|
|
67
|
+
* @typedef {Object} QueuedPropsMetadata
|
|
68
|
+
* @prop {boolean} initial
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/** @type {WeakMap<CustomElement, Map<string, QueuedPropsMetadata>>} */
|
|
72
|
+
const queuedPropsByElement = new WeakMap();
|
|
73
|
+
|
|
74
|
+
/** @type {WeakMap<CustomElement, Map<string, Animation>>} */
|
|
75
|
+
const previousAnimationsByElement = new WeakMap();
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {string} name
|
|
79
|
+
* @this {CustomElement}
|
|
80
|
+
*/
|
|
81
|
+
function elementStylerMicrotaskCallback(name) {
|
|
82
|
+
const previousAnimations = previousAnimationsByElement.get(this);
|
|
83
|
+
/** @type {Animation} */
|
|
84
|
+
let previousAnimation;
|
|
85
|
+
if (previousAnimations?.has(name)) {
|
|
86
|
+
previousAnimation = previousAnimations.get(name);
|
|
87
|
+
}
|
|
88
|
+
const queuedProps = queuedPropsByElement.get(this);
|
|
89
|
+
const { initial } = queuedProps.get(name);
|
|
90
|
+
queuedProps.delete(name);
|
|
91
|
+
const value = this[name];
|
|
77
92
|
if (!value) {
|
|
78
93
|
previousAnimation?.cancel();
|
|
79
94
|
return;
|
|
80
95
|
}
|
|
96
|
+
const { target, styles, timing } = value;
|
|
81
97
|
/** @type {HTMLElement} */
|
|
82
|
-
const el =
|
|
83
|
-
|
|
84
|
-
|
|
98
|
+
const el = target
|
|
99
|
+
? (typeof target === 'string' ? this.refs[target] : target)
|
|
100
|
+
: this;
|
|
101
|
+
const currentAnimation = el.animate(styles, {
|
|
102
|
+
...timing,
|
|
103
|
+
...(initial ? { duration: 0 } : null),
|
|
85
104
|
fill: 'forwards',
|
|
86
105
|
});
|
|
87
106
|
currentAnimation.onremove = () => {
|
|
@@ -93,33 +112,131 @@ function elementStylerRAFCallback() {
|
|
|
93
112
|
previousAnimation?.cancel();
|
|
94
113
|
previousAnimation = null;
|
|
95
114
|
};
|
|
96
|
-
|
|
97
|
-
|
|
115
|
+
if (previousAnimations) {
|
|
116
|
+
previousAnimations.set(name, currentAnimation);
|
|
117
|
+
} else {
|
|
118
|
+
previousAnimationsByElement.set(this, new Map([[name, currentAnimation]]));
|
|
119
|
+
}
|
|
98
120
|
}
|
|
99
121
|
|
|
100
|
-
/** @type {
|
|
101
|
-
|
|
122
|
+
/** @type {WeakMap<Element, Function[]>} */
|
|
123
|
+
const pendingResizeCallbacks = new WeakMap();
|
|
124
|
+
const pendingConnections = new ResizeObserver((entries) => {
|
|
125
|
+
for (const { target } of entries) {
|
|
126
|
+
if (pendingResizeCallbacks.has(target)) {
|
|
127
|
+
const callbacks = pendingResizeCallbacks.get(target);
|
|
128
|
+
pendingResizeCallbacks.delete(target);
|
|
129
|
+
pendingConnections.unobserve(target);
|
|
130
|
+
for (const callback of callbacks) {
|
|
131
|
+
callback();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
/** @type {import('./observe.js').ObserverOptions<'object',ElementStylerOptions, CustomElement>} */
|
|
138
|
+
export const ELEMENT_ANIMATION_TYPE = {
|
|
102
139
|
type: 'object',
|
|
103
140
|
reflect: false,
|
|
104
|
-
values: elementStylerValues,
|
|
105
141
|
diff: null, // Skip computing entire change
|
|
106
|
-
|
|
107
|
-
const hasQueue = elementStylerHasQueue.has(this);
|
|
142
|
+
propChangedCallback(name, oldValue, newValue) {
|
|
108
143
|
if (!newValue) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
144
|
+
const previousAnimations = previousAnimationsByElement.get(this);
|
|
145
|
+
if (!previousAnimations?.has(name)) {
|
|
146
|
+
// Fast abort
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
113
149
|
}
|
|
150
|
+
const queuedProps = queuedPropsByElement.get(this);
|
|
114
151
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return;
|
|
152
|
+
const initial = !this.isConnected;
|
|
153
|
+
if (queuedProps) {
|
|
154
|
+
if (queuedProps.has(name)) return;
|
|
155
|
+
queuedProps.set(name, { initial });
|
|
156
|
+
} else {
|
|
157
|
+
queuedPropsByElement.set(this, new Map([[name, { initial }]]));
|
|
118
158
|
}
|
|
119
|
-
|
|
159
|
+
// TODO: Reuse callback instead constructing each tick
|
|
120
160
|
// Animation styles may trickle in steps, so queue a microtask before doing any work.
|
|
121
161
|
// Using requestAnimationFrame would fire one frame too late for CSS animations already scheduled
|
|
122
|
-
|
|
123
|
-
|
|
162
|
+
const callback = elementStylerMicrotaskCallback.bind(this, name);
|
|
163
|
+
if (this.isConnected) {
|
|
164
|
+
queueMicrotask(callback);
|
|
165
|
+
} else if (pendingResizeCallbacks.has(this)) {
|
|
166
|
+
pendingResizeCallbacks.get(this).push(callback);
|
|
167
|
+
} else {
|
|
168
|
+
pendingResizeCallbacks.set(this, [callback]);
|
|
169
|
+
pendingConnections.observe(this);
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @type {WeakMap<CustomElement, Map<string, HTMLStyleElement|CSSStyleSheet>>}
|
|
176
|
+
*/
|
|
177
|
+
const styleReferences = new WeakMap();
|
|
178
|
+
|
|
179
|
+
/** @type {boolean} */
|
|
180
|
+
let useAdoptedStyleSheets = null;
|
|
181
|
+
|
|
182
|
+
/** @type {import('./observe.js').ObserverOptions<'string',string, CustomElement>} */
|
|
183
|
+
export const ELEMENT_STYLE_TYPE = {
|
|
184
|
+
type: 'string',
|
|
185
|
+
reflect: false,
|
|
186
|
+
/**
|
|
187
|
+
* @param {string|Record<keyof CSSStyleDeclaration & string, string|number>} value
|
|
188
|
+
* @return {string}
|
|
189
|
+
*/
|
|
190
|
+
parser(value) {
|
|
191
|
+
if (!value || typeof value === 'string') {
|
|
192
|
+
return /** @type {string} */ (value);
|
|
193
|
+
}
|
|
194
|
+
return `:host{${
|
|
195
|
+
Object.entries(value).map(([key, rule]) => `${attrNameFromPropName(key)}:${rule}`)
|
|
196
|
+
.join(';')
|
|
197
|
+
}}`;
|
|
198
|
+
},
|
|
199
|
+
propChangedCallback(name, oldValue, newValue) {
|
|
200
|
+
let mapOfStyles;
|
|
201
|
+
|
|
202
|
+
/** @type {HTMLStyleElement|CSSStyleSheet} */
|
|
203
|
+
let styles;
|
|
204
|
+
if (styleReferences.has(this)) {
|
|
205
|
+
mapOfStyles = styleReferences.get(this);
|
|
206
|
+
if (mapOfStyles.has(name)) {
|
|
207
|
+
styles = mapOfStyles.get(name);
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
// Skip build if blank
|
|
211
|
+
if (!newValue) return;
|
|
212
|
+
mapOfStyles = new Map();
|
|
213
|
+
styleReferences.set(this, mapOfStyles);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
useAdoptedStyleSheets ??= 'adoptedStyleSheets' in ShadowRoot.prototype;
|
|
217
|
+
if (!styles) {
|
|
218
|
+
if (useAdoptedStyleSheets) {
|
|
219
|
+
styles = new CSSStyleSheet();
|
|
220
|
+
this.shadowRoot.adoptedStyleSheets = [
|
|
221
|
+
...this.shadowRoot.adoptedStyleSheets,
|
|
222
|
+
styles,
|
|
223
|
+
];
|
|
224
|
+
} else {
|
|
225
|
+
const styleElement = this.ownerDocument.createElement('style');
|
|
226
|
+
this.shadowRoot.prepend(styleElement);
|
|
227
|
+
styles = styleElement;
|
|
228
|
+
}
|
|
229
|
+
mapOfStyles.set(name, styles);
|
|
230
|
+
}
|
|
231
|
+
if (newValue) {
|
|
232
|
+
if (useAdoptedStyleSheets) {
|
|
233
|
+
/** @type {CSSStyleSheet} */(styles).replaceSync(newValue);
|
|
234
|
+
} else if (newValue) {
|
|
235
|
+
/** @type {HTMLStyleElement} */(styles).textContent = newValue;
|
|
236
|
+
}
|
|
237
|
+
styles.disabled = false;
|
|
238
|
+
} else {
|
|
239
|
+
styles.disabled = true;
|
|
240
|
+
}
|
|
124
241
|
},
|
|
125
242
|
};
|
package/core/dom.js
CHANGED
|
@@ -17,6 +17,9 @@ export function attrValueFromDataValue(value) {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/** @type {Map<string, string>} */
|
|
21
|
+
let attrNameFromPropNameCache;
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* Converts property name to attribute name
|
|
22
25
|
* (Similar to DOMStringMap)
|
|
@@ -24,18 +27,21 @@ export function attrValueFromDataValue(value) {
|
|
|
24
27
|
* @return {string}
|
|
25
28
|
*/
|
|
26
29
|
export function attrNameFromPropName(name) {
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
});
|
|
30
|
+
attrNameFromPropNameCache ??= new Map();
|
|
31
|
+
if (attrNameFromPropNameCache.has(name)) {
|
|
32
|
+
return attrNameFromPropNameCache.get(name);
|
|
33
|
+
}
|
|
34
|
+
// eslint-disable-next-line unicorn/prefer-string-replace-all
|
|
35
|
+
const value = name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
36
|
+
attrNameFromPropNameCache.set(name, value);
|
|
37
|
+
return value;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
const
|
|
40
|
+
export const CHROME_VERSION = Number.parseFloat(navigator.userAgent.match(/Chrome\/([\d.]+)/)?.[1]);
|
|
41
|
+
export const FIREFOX_VERSION = Number.parseFloat(navigator.userAgent.match(/Firefox\/([\d.]+)/)?.[1]);
|
|
42
|
+
export const SAFARI_VERSION = CHROME_VERSION || !navigator.userAgent.includes('AppleWebKit')
|
|
43
|
+
? Number.NaN
|
|
44
|
+
: Number.parseFloat(navigator.userAgent.match(/Version\/([\d.]+)/)?.[1]);
|
|
39
45
|
|
|
40
46
|
/**
|
|
41
47
|
* @param {Element} element
|
|
@@ -43,7 +49,7 @@ const IS_FIREFOX = globalThis?.navigator?.userAgent.includes('Firefox');
|
|
|
43
49
|
*/
|
|
44
50
|
export function isFocused(element) {
|
|
45
51
|
if (!element) return false;
|
|
46
|
-
if (
|
|
52
|
+
if (FIREFOX_VERSION < 113 && element.constructor.formAssociated && element.hasAttribute('disabled')) {
|
|
47
53
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1818287
|
|
48
54
|
console.warn('Firefox bug 1818287: Disabled form associated custom element cannot receive focus.');
|
|
49
55
|
return false;
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export function applyMergePatch(target, patch) {
|
|
11
11
|
if (target === patch) return target;
|
|
12
|
-
if (patch == null || typeof patch !== 'object') return patch;
|
|
13
|
-
if (
|
|
12
|
+
if (target == null || patch == null || typeof patch !== 'object') return patch;
|
|
13
|
+
if (typeof target !== 'object') {
|
|
14
14
|
target = {};
|
|
15
15
|
}
|
|
16
16
|
for (const [key, value] of Object.entries(patch)) {
|
|
@@ -28,37 +28,65 @@ export function applyMergePatch(target, patch) {
|
|
|
28
28
|
/**
|
|
29
29
|
* Creates a JSON Merge patch based
|
|
30
30
|
* Allows different strategies for arrays
|
|
31
|
-
* - `
|
|
31
|
+
* - `reference`: Per spec, returns array as is
|
|
32
|
+
* - `clone`: Clones all entries with no inspection.
|
|
32
33
|
* - `object`: Convert to flattened, array-like objects. Requires
|
|
33
34
|
* consumer of patch to be aware of the schema beforehand.
|
|
34
35
|
* @param {object|number|string|boolean} previous
|
|
35
36
|
* @param {object|number|string|boolean} current
|
|
36
|
-
* @param {'clone'|'object'} [arrayStrategy='
|
|
37
|
+
* @param {'clone'|'object'|'reference'} [arrayStrategy='reference']
|
|
37
38
|
* @return {any} Patch
|
|
38
39
|
*/
|
|
39
|
-
export function buildMergePatch(previous, current, arrayStrategy = '
|
|
40
|
+
export function buildMergePatch(previous, current, arrayStrategy = 'reference') {
|
|
40
41
|
if (previous === current) return null;
|
|
41
42
|
if (current == null || typeof current !== 'object') return current;
|
|
42
43
|
if (previous == null || typeof previous !== 'object') {
|
|
43
44
|
return structuredClone(current);
|
|
44
45
|
}
|
|
45
|
-
const isArray = Array.isArray(current);
|
|
46
|
-
if (isArray && arrayStrategy === 'clone') {
|
|
47
|
-
return structuredClone(current);
|
|
48
|
-
}
|
|
49
46
|
|
|
50
47
|
const patch = {};
|
|
48
|
+
if (Array.isArray(current)) {
|
|
49
|
+
if (arrayStrategy === 'reference') {
|
|
50
|
+
return current;
|
|
51
|
+
}
|
|
52
|
+
// Assume previous is array
|
|
53
|
+
if (arrayStrategy === 'clone') {
|
|
54
|
+
return structuredClone(current);
|
|
55
|
+
}
|
|
56
|
+
for (const [index, value] of current.entries()) {
|
|
57
|
+
if (value === null) {
|
|
58
|
+
patch[index] = null;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (value == null) {
|
|
62
|
+
continue; // Skip undefined
|
|
63
|
+
}
|
|
64
|
+
const changes = buildMergePatch(previous[index], value, arrayStrategy);
|
|
65
|
+
if (changes !== null) {
|
|
66
|
+
patch[index] = changes;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// for (let i = current.length; i < previous.length; i++) {
|
|
70
|
+
// patch[i] = null;
|
|
71
|
+
// }
|
|
72
|
+
if (current.length !== previous.length) {
|
|
73
|
+
patch.length = current.length;
|
|
74
|
+
}
|
|
75
|
+
return patch;
|
|
76
|
+
}
|
|
77
|
+
|
|
51
78
|
const previousKeys = new Set(Object.keys(previous));
|
|
52
79
|
for (const [key, value] of Object.entries(current)) {
|
|
53
80
|
previousKeys.delete(key);
|
|
54
|
-
if (value
|
|
55
|
-
|
|
81
|
+
if (value === null) {
|
|
82
|
+
patch[key] = null;
|
|
56
83
|
continue;
|
|
57
84
|
}
|
|
85
|
+
if (value == null) {
|
|
86
|
+
continue; // Skip undefined
|
|
87
|
+
}
|
|
58
88
|
const changes = buildMergePatch(previous[key], value, arrayStrategy);
|
|
59
|
-
if (changes
|
|
60
|
-
console.log('keeping', key);
|
|
61
|
-
} else {
|
|
89
|
+
if (changes !== null) {
|
|
62
90
|
patch[key] = changes;
|
|
63
91
|
}
|
|
64
92
|
}
|
|
@@ -67,10 +95,6 @@ export function buildMergePatch(previous, current, arrayStrategy = 'clone') {
|
|
|
67
95
|
console.log('removing', key);
|
|
68
96
|
}
|
|
69
97
|
|
|
70
|
-
if (isArray && arrayStrategy === 'object' && current.length !== previous.length) {
|
|
71
|
-
patch.length = current.length;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
98
|
return patch;
|
|
75
99
|
}
|
|
76
100
|
|