@remix-run/ui 0.3.0 → 0.5.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 +116 -157
- package/dist/accordion/index.d.ts +46 -0
- package/dist/accordion/index.js +142 -0
- package/dist/accordion/index.js.map +1 -0
- package/dist/accordion/primitives.d.ts +104 -0
- package/dist/accordion/primitives.js +312 -0
- package/dist/accordion/primitives.js.map +1 -0
- package/dist/{components/anchor/anchor.js → anchor/index.js} +1 -1
- package/dist/anchor/index.js.map +1 -0
- package/dist/animation/animate-layout-mixin.js +1 -1
- package/dist/animation/animate-layout-mixin.js.map +1 -1
- package/dist/animation/animate-mixins.js +2 -2
- package/dist/animation/animate-mixins.js.map +1 -1
- package/dist/animation/demos/color-interpolation.js +1 -1
- package/dist/animation/demos/color-interpolation.js.map +1 -1
- package/dist/animation/demos/drag-release.d.ts +1 -1
- package/dist/animation/demos/hold-to-confirm.d.ts +3 -3
- package/dist/animation/demos/material-ripple.js +1 -3
- package/dist/animation/demos/material-ripple.js.map +1 -1
- package/dist/animation/demos/reordering.js +9 -6
- package/dist/animation/demos/reordering.js.map +1 -1
- package/dist/animation/index.js +4 -4
- package/dist/animation/spring.js.map +1 -1
- package/dist/{components/breadcrumbs/breadcrumbs.js → breadcrumbs/index.js} +19 -19
- package/dist/breadcrumbs/index.js.map +1 -0
- package/dist/button/index.d.ts +15 -0
- package/dist/button/index.js +128 -0
- package/dist/button/index.js.map +1 -0
- package/dist/checkbox/index.d.ts +14 -0
- package/dist/checkbox/index.js +127 -0
- package/dist/checkbox/index.js.map +1 -0
- package/dist/combobox/index.d.ts +21 -0
- package/dist/combobox/index.js +58 -0
- package/dist/combobox/index.js.map +1 -0
- package/dist/{components/combobox/combobox.d.ts → combobox/primitives.d.ts} +4 -8
- package/dist/{components/combobox/combobox.js → combobox/primitives.js} +8 -61
- package/dist/combobox/primitives.js.map +1 -0
- package/dist/dev/refresh.d.ts +1 -0
- package/dist/dev/refresh.js +2 -0
- package/dist/dev/refresh.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -14
- package/dist/input/index.d.ts +13 -0
- package/dist/input/index.js +121 -0
- package/dist/input/index.js.map +1 -0
- package/dist/jsx-runtime.js +2 -2
- package/dist/listbox/flash-attribute.js.map +1 -0
- package/dist/{components/listbox/listbox.d.ts → listbox/index.d.ts} +2 -6
- package/dist/{components/listbox/listbox.js → listbox/index.js} +4 -82
- package/dist/listbox/index.js.map +1 -0
- package/dist/menu/hover-aim.js.map +1 -0
- package/dist/menu/index.d.ts +42 -0
- package/dist/menu/index.js +250 -0
- package/dist/menu/index.js.map +1 -0
- package/dist/{components/menu/menu.d.ts → menu/primitives.d.ts} +4 -33
- package/dist/{components/menu/menu.js → menu/primitives.js} +98 -315
- package/dist/menu/primitives.js.map +1 -0
- package/dist/{components/popover/popover.d.ts → popover/index.d.ts} +2 -4
- package/dist/{components/popover/popover.js → popover/index.js} +5 -48
- package/dist/popover/index.js.map +1 -0
- package/dist/{interactions/outside-click/outside-click-mixin.js → popover/outside-click.js} +1 -1
- package/dist/popover/outside-click.js.map +1 -0
- package/dist/popover/scroll-lock.d.ts +1 -0
- package/dist/{utils → popover}/scroll-lock.js +0 -18
- package/dist/popover/scroll-lock.js.map +1 -0
- package/dist/radio/index.d.ts +12 -0
- package/dist/radio/index.js +77 -0
- package/dist/radio/index.js.map +1 -0
- package/dist/runtime/client-entry-boundary.d.ts +14 -0
- package/dist/runtime/client-entry-boundary.js +29 -0
- package/dist/runtime/client-entry-boundary.js.map +1 -0
- package/dist/runtime/component.d.ts +19 -4
- package/dist/runtime/component.js +39 -9
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/core/attributes.js +36 -3
- package/dist/runtime/core/attributes.js.map +1 -1
- package/dist/runtime/core/children.d.ts +2 -0
- package/dist/runtime/core/children.js +26 -2
- package/dist/runtime/core/children.js.map +1 -1
- package/dist/runtime/core/props.js +2 -2
- package/dist/runtime/core/vnode.d.ts +3 -3
- package/dist/runtime/core/vnode.js +22 -1
- package/dist/runtime/core/vnode.js.map +1 -1
- package/dist/runtime/create-element.d.ts +2 -2
- package/dist/runtime/create-element.js +3 -2
- package/dist/runtime/create-element.js.map +1 -1
- package/dist/runtime/diff-dom.js +294 -219
- package/dist/runtime/diff-dom.js.map +1 -1
- package/dist/runtime/diff-props.js +3 -3
- package/dist/runtime/dom.d.ts +12 -0
- package/dist/runtime/element-function.d.ts +3 -0
- package/dist/runtime/element-function.js +2 -0
- package/dist/runtime/element-function.js.map +1 -0
- package/dist/runtime/form-navigation.d.ts +25 -0
- package/dist/runtime/form-navigation.js +132 -0
- package/dist/runtime/form-navigation.js.map +1 -0
- package/dist/runtime/frame-resolution.d.ts +5 -0
- package/dist/runtime/frame-resolution.js +10 -0
- package/dist/runtime/frame-resolution.js.map +1 -0
- package/dist/runtime/frame.d.ts +58 -15
- package/dist/runtime/frame.js +367 -114
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/jsx.d.ts +1 -1
- package/dist/runtime/jsx.js +1 -1
- package/dist/runtime/jsx.js.map +1 -1
- package/dist/runtime/key.d.ts +1 -0
- package/dist/runtime/key.js +2 -0
- package/dist/runtime/key.js.map +1 -0
- package/dist/runtime/mixins/attrs-mixin.js +2 -2
- package/dist/runtime/mixins/link-mixin.js +4 -3
- package/dist/runtime/mixins/link-mixin.js.map +1 -1
- package/dist/runtime/mixins/mixin.d.ts +15 -10
- package/dist/runtime/mixins/mixin.js +4 -4
- package/dist/runtime/mixins/mixin.js.map +1 -1
- package/dist/runtime/mixins/on-mixin.js +1 -1
- package/dist/runtime/mixins/ref-mixin.js +1 -1
- package/dist/runtime/navigation.d.ts +4 -1
- package/dist/runtime/navigation.js +157 -32
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/reconcile.d.ts +11 -10
- package/dist/runtime/reconcile.js +557 -423
- package/dist/runtime/reconcile.js.map +1 -1
- package/dist/runtime/refresh.d.ts +28 -0
- package/dist/runtime/refresh.js +31 -0
- package/dist/runtime/refresh.js.map +1 -0
- package/dist/runtime/render.js +1 -1
- package/dist/runtime/render.js.map +1 -1
- package/dist/runtime/run.d.ts +3 -1
- package/dist/runtime/run.js +15 -7
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/scheduler.js +8 -16
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/to-vnode.d.ts +2 -2
- package/dist/runtime/to-vnode.js +68 -20
- package/dist/runtime/to-vnode.js.map +1 -1
- package/dist/runtime/vdom.d.ts +4 -2
- package/dist/runtime/vdom.js +89 -41
- package/dist/runtime/vdom.js.map +1 -1
- package/dist/runtime/vnode.d.ts +138 -67
- package/dist/runtime/vnode.js +17 -12
- package/dist/runtime/vnode.js.map +1 -1
- package/dist/select/index.d.ts +19 -0
- package/dist/select/index.js +95 -0
- package/dist/select/index.js.map +1 -0
- package/dist/select/keydown.js.map +1 -0
- package/dist/{components/select/select.d.ts → select/primitives.d.ts} +5 -7
- package/dist/{components/select/select.js → select/primitives.js} +11 -63
- package/dist/select/primitives.js.map +1 -0
- package/dist/server/stream.js +22 -29
- package/dist/server/stream.js.map +1 -1
- package/dist/shared/focus-styles.d.ts +1 -0
- package/dist/shared/focus-styles.js +2 -0
- package/dist/shared/focus-styles.js.map +1 -0
- package/dist/shared/icons.d.ts +9 -0
- package/dist/shared/icons.js +42 -0
- package/dist/shared/icons.js.map +1 -0
- package/dist/shared/listbox-popover-styles.d.ts +6 -0
- package/dist/shared/listbox-popover-styles.js +137 -0
- package/dist/shared/listbox-popover-styles.js.map +1 -0
- package/dist/shared/style-values.d.ts +78 -0
- package/dist/shared/style-values.js +88 -0
- package/dist/shared/style-values.js.map +1 -0
- package/dist/{interactions/typeahead/typeahead-mixin.js → shared/typeahead.js} +1 -1
- package/dist/shared/typeahead.js.map +1 -0
- package/dist/shared/wait-for-css-transition.js.map +1 -0
- package/dist/shared/wait.js.map +1 -0
- package/dist/style/css-mixin.js +3 -3
- package/dist/style/index.js +2 -2
- package/dist/style/style.js +25 -6
- package/dist/style/style.js.map +1 -1
- package/dist/style/stylesheet.d.ts +0 -1
- package/dist/style/stylesheet.js +13 -54
- package/dist/style/stylesheet.js.map +1 -1
- package/dist/tabs/index.d.ts +32 -0
- package/dist/tabs/index.js +157 -0
- package/dist/tabs/index.js.map +1 -0
- package/dist/tabs/primitives.d.ts +57 -0
- package/dist/tabs/primitives.js +238 -0
- package/dist/tabs/primitives.js.map +1 -0
- package/dist/test.js +1 -1
- package/dist/toggle/index.d.ts +9 -0
- package/dist/toggle/index.js +108 -0
- package/dist/toggle/index.js.map +1 -0
- package/dist/toggle/primitives.d.ts +29 -0
- package/dist/toggle/primitives.js +127 -0
- package/dist/toggle/primitives.js.map +1 -0
- package/package.json +81 -49
- package/src/{components/accordion → accordion}/README.md +50 -14
- package/src/accordion/index.tsx +285 -0
- package/src/accordion/primitives.tsx +512 -0
- package/src/{components/anchor → anchor}/README.md +37 -2
- package/src/animation/animate-mixins.ts +3 -3
- package/src/animation/demos/color-interpolation.tsx +1 -1
- package/src/animation/demos/reordering.tsx +9 -6
- package/src/{components/breadcrumbs → breadcrumbs}/README.md +4 -4
- package/src/{components/breadcrumbs/breadcrumbs.tsx → breadcrumbs/index.tsx} +18 -18
- package/src/button/README.md +44 -0
- package/src/button/index.ts +168 -0
- package/src/checkbox/README.md +59 -0
- package/src/checkbox/index.ts +164 -0
- package/src/{components/combobox → combobox}/README.md +58 -9
- package/src/combobox/index.tsx +112 -0
- package/src/{components/combobox/combobox.tsx → combobox/primitives.tsx} +5 -91
- package/src/dev/refresh.ts +1 -0
- package/src/index.ts +1 -1
- package/src/input/README.md +52 -0
- package/src/input/index.ts +147 -0
- package/src/{components/listbox → listbox}/README.md +9 -41
- package/src/{components/listbox/listbox.ts → listbox/index.ts} +2 -87
- package/src/{components/menu → menu}/README.md +55 -14
- package/src/menu/index.tsx +354 -0
- package/src/{components/menu/menu.tsx → menu/primitives.tsx} +99 -413
- package/src/{components/popover → popover}/README.md +20 -39
- package/src/{components/popover/popover.ts → popover/index.ts} +3 -57
- package/src/{utils → popover}/scroll-lock.ts +0 -28
- package/src/radio/README.md +53 -0
- package/src/radio/index.ts +101 -0
- package/src/runtime/client-entry-boundary.ts +54 -0
- package/src/runtime/component.ts +65 -16
- package/src/runtime/core/attributes.ts +35 -1
- package/src/runtime/core/children.ts +24 -2
- package/src/runtime/core/vnode.ts +25 -4
- package/src/runtime/create-element.ts +6 -5
- package/src/runtime/demos/readme.demo.tsx +20 -18
- package/src/runtime/diff-dom.ts +358 -243
- package/src/runtime/dom.ts +331 -214
- package/src/runtime/element-function.ts +1 -0
- package/src/runtime/event-listeners.ts +1 -1
- package/src/runtime/form-navigation.ts +184 -0
- package/src/runtime/frame-resolution.ts +13 -0
- package/src/runtime/frame.ts +482 -124
- package/src/runtime/jsx.ts +3 -5
- package/src/runtime/key.ts +1 -0
- package/src/runtime/mixins/link-mixin.ts +1 -0
- package/src/runtime/mixins/mixin.ts +21 -18
- package/src/runtime/navigation.ts +204 -30
- package/src/runtime/reconcile.ts +769 -760
- package/src/runtime/refresh.ts +46 -0
- package/src/runtime/run.ts +12 -2
- package/src/runtime/scheduler.ts +9 -29
- package/src/runtime/to-vnode.ts +85 -23
- package/src/runtime/vdom.ts +91 -69
- package/src/runtime/vnode.ts +192 -88
- package/src/{components/select → select}/README.md +29 -19
- package/src/select/index.tsx +159 -0
- package/src/{components/select/select.tsx → select/primitives.tsx} +10 -98
- package/src/server/stream.ts +25 -31
- package/src/shared/focus-styles.ts +2 -0
- package/src/shared/icons.tsx +62 -0
- package/src/shared/listbox-popover-styles.ts +146 -0
- package/src/shared/style-values.ts +165 -0
- package/src/style/style.ts +25 -6
- package/src/style/stylesheet.ts +32 -57
- package/src/tabs/README.md +141 -0
- package/src/tabs/index.tsx +245 -0
- package/src/tabs/primitives.ts +365 -0
- package/src/test/README.md +151 -60
- package/src/toggle/README.md +56 -0
- package/src/toggle/index.tsx +136 -0
- package/src/toggle/primitives.ts +192 -0
- package/dist/animation/demos/animation.demo.d.ts +0 -5
- package/dist/animation/demos/animation.demo.js +0 -92
- package/dist/animation/demos/animation.demo.js.map +0 -1
- package/dist/animation/demos/spring.demo.d.ts +0 -6
- package/dist/animation/demos/spring.demo.js +0 -304
- package/dist/animation/demos/spring.demo.js.map +0 -1
- package/dist/components/accordion/accordion.d.ts +0 -92
- package/dist/components/accordion/accordion.js +0 -335
- package/dist/components/accordion/accordion.js.map +0 -1
- package/dist/components/accordion/demos/card.demo.d.ts +0 -7
- package/dist/components/accordion/demos/card.demo.js +0 -59
- package/dist/components/accordion/demos/card.demo.js.map +0 -1
- package/dist/components/accordion/demos/multiple.demo.d.ts +0 -7
- package/dist/components/accordion/demos/multiple.demo.js +0 -20
- package/dist/components/accordion/demos/multiple.demo.js.map +0 -1
- package/dist/components/accordion/demos/overview.demo.d.ts +0 -7
- package/dist/components/accordion/demos/overview.demo.js +0 -20
- package/dist/components/accordion/demos/overview.demo.js.map +0 -1
- package/dist/components/anchor/anchor.js.map +0 -1
- package/dist/components/breadcrumbs/basic.demo.d.ts +0 -6
- package/dist/components/breadcrumbs/basic.demo.js +0 -15
- package/dist/components/breadcrumbs/basic.demo.js.map +0 -1
- package/dist/components/breadcrumbs/breadcrumbs.js.map +0 -1
- package/dist/components/breadcrumbs/separator.demo.d.ts +0 -6
- package/dist/components/breadcrumbs/separator.demo.js +0 -15
- package/dist/components/breadcrumbs/separator.demo.js.map +0 -1
- package/dist/components/button/button.d.ts +0 -105
- package/dist/components/button/button.js +0 -207
- package/dist/components/button/button.js.map +0 -1
- package/dist/components/button/demos/aliases.demo.d.ts +0 -7
- package/dist/components/button/demos/aliases.demo.js +0 -19
- package/dist/components/button/demos/aliases.demo.js.map +0 -1
- package/dist/components/button/demos/basic.demo.d.ts +0 -7
- package/dist/components/button/demos/basic.demo.js +0 -20
- package/dist/components/button/demos/basic.demo.js.map +0 -1
- package/dist/components/button/demos/states.demo.d.ts +0 -7
- package/dist/components/button/demos/states.demo.js +0 -30
- package/dist/components/button/demos/states.demo.js.map +0 -1
- package/dist/components/combobox/combobox.js.map +0 -1
- package/dist/components/combobox/overview.demo.d.ts +0 -7
- package/dist/components/combobox/overview.demo.js +0 -154
- package/dist/components/combobox/overview.demo.js.map +0 -1
- package/dist/components/glyph/glyph.d.ts +0 -14
- package/dist/components/glyph/glyph.js +0 -65
- package/dist/components/glyph/glyph.js.map +0 -1
- package/dist/components/listbox/listbox.js.map +0 -1
- package/dist/components/listbox/overview.demo.d.ts +0 -7
- package/dist/components/listbox/overview.demo.js +0 -65
- package/dist/components/listbox/overview.demo.js.map +0 -1
- package/dist/components/menu/demos/bubbling.demo.d.ts +0 -6
- package/dist/components/menu/demos/bubbling.demo.js +0 -16
- package/dist/components/menu/demos/bubbling.demo.js.map +0 -1
- package/dist/components/menu/demos/context-trigger.demo.d.ts +0 -7
- package/dist/components/menu/demos/context-trigger.demo.js +0 -87
- package/dist/components/menu/demos/context-trigger.demo.js.map +0 -1
- package/dist/components/menu/demos/overview.demo.d.ts +0 -7
- package/dist/components/menu/demos/overview.demo.js +0 -33
- package/dist/components/menu/demos/overview.demo.js.map +0 -1
- package/dist/components/menu/hover-aim.js.map +0 -1
- package/dist/components/menu/menu.js.map +0 -1
- package/dist/components/popover/overview.demo.d.ts +0 -7
- package/dist/components/popover/overview.demo.js +0 -65
- package/dist/components/popover/overview.demo.js.map +0 -1
- package/dist/components/popover/popover.js.map +0 -1
- package/dist/components/select/deconstructed.demo.d.ts +0 -7
- package/dist/components/select/deconstructed.demo.js +0 -54
- package/dist/components/select/deconstructed.demo.js.map +0 -1
- package/dist/components/select/overview.demo.d.ts +0 -6
- package/dist/components/select/overview.demo.js +0 -28
- package/dist/components/select/overview.demo.js.map +0 -1
- package/dist/components/select/select.js.map +0 -1
- package/dist/components/separator/separator.d.ts +0 -2
- package/dist/components/separator/separator.js +0 -15
- package/dist/components/separator/separator.js.map +0 -1
- package/dist/components/tabs/tabs.d.ts +0 -78
- package/dist/components/tabs/tabs.js +0 -339
- package/dist/components/tabs/tabs.js.map +0 -1
- package/dist/interactions/keydown/keydown.js.map +0 -1
- package/dist/interactions/outside-click/outside-click-mixin.js.map +0 -1
- package/dist/interactions/typeahead/typeahead-mixin.js.map +0 -1
- package/dist/runtime/demos/basic.demo.d.ts +0 -6
- package/dist/runtime/demos/basic.demo.js +0 -16
- package/dist/runtime/demos/basic.demo.js.map +0 -1
- package/dist/runtime/demos/controlled-uncontrolled-values.demo.d.ts +0 -6
- package/dist/runtime/demos/controlled-uncontrolled-values.demo.js +0 -77
- package/dist/runtime/demos/controlled-uncontrolled-values.demo.js.map +0 -1
- package/dist/runtime/demos/keyed-list.demo.d.ts +0 -6
- package/dist/runtime/demos/keyed-list.demo.js +0 -62
- package/dist/runtime/demos/keyed-list.demo.js.map +0 -1
- package/dist/runtime/demos/readme.demo.d.ts +0 -5
- package/dist/runtime/demos/readme.demo.js +0 -396
- package/dist/runtime/demos/readme.demo.js.map +0 -1
- package/dist/theme/contract.d.ts +0 -61
- package/dist/theme/contract.js +0 -131
- package/dist/theme/contract.js.map +0 -1
- package/dist/theme/glyph-contract.d.ts +0 -11
- package/dist/theme/glyph-contract.js +0 -34
- package/dist/theme/glyph-contract.js.map +0 -1
- package/dist/theme/presets/rmx-01/glyphs.d.ts +0 -2
- package/dist/theme/presets/rmx-01/glyphs.js +0 -252
- package/dist/theme/presets/rmx-01/glyphs.js.map +0 -1
- package/dist/theme/presets/rmx-01/index.d.ts +0 -4
- package/dist/theme/presets/rmx-01/index.js +0 -119
- package/dist/theme/presets/rmx-01/index.js.map +0 -1
- package/dist/theme/runtime.d.ts +0 -2
- package/dist/theme/runtime.js +0 -84
- package/dist/theme/runtime.js.map +0 -1
- package/dist/theme/theme.d.ts +0 -6
- package/dist/theme/theme.js +0 -5
- package/dist/theme/theme.js.map +0 -1
- package/dist/utils/flash-attribute.js.map +0 -1
- package/dist/utils/scroll-lock.d.ts +0 -3
- package/dist/utils/scroll-lock.js.map +0 -1
- package/dist/utils/wait-for-css-transition.js.map +0 -1
- package/dist/utils/wait.js.map +0 -1
- package/src/animation/demos/animation.demo.tsx +0 -194
- package/src/animation/demos/spring.demo.tsx +0 -385
- package/src/components/accordion/accordion.tsx +0 -565
- package/src/components/accordion/demos/card.demo.tsx +0 -114
- package/src/components/accordion/demos/multiple.demo.tsx +0 -57
- package/src/components/accordion/demos/overview.demo.tsx +0 -57
- package/src/components/breadcrumbs/basic.demo.tsx +0 -18
- package/src/components/breadcrumbs/separator.demo.tsx +0 -19
- package/src/components/button/README.md +0 -44
- package/src/components/button/button.tsx +0 -286
- package/src/components/button/demos/aliases.demo.tsx +0 -28
- package/src/components/button/demos/basic.demo.tsx +0 -31
- package/src/components/button/demos/states.demo.tsx +0 -53
- package/src/components/combobox/overview.demo.tsx +0 -200
- package/src/components/glyph/README.md +0 -72
- package/src/components/glyph/glyph.tsx +0 -110
- package/src/components/listbox/overview.demo.tsx +0 -102
- package/src/components/menu/demos/bubbling.demo.tsx +0 -35
- package/src/components/menu/demos/context-trigger.demo.tsx +0 -133
- package/src/components/menu/demos/overview.demo.tsx +0 -77
- package/src/components/popover/overview.demo.tsx +0 -144
- package/src/components/select/deconstructed.demo.tsx +0 -96
- package/src/components/select/overview.demo.tsx +0 -52
- package/src/components/separator/separator.ts +0 -19
- package/src/components/tabs/README.md +0 -105
- package/src/components/tabs/tabs.tsx +0 -504
- package/src/runtime/demos/basic.demo.tsx +0 -21
- package/src/runtime/demos/controlled-uncontrolled-values.demo.tsx +0 -177
- package/src/runtime/demos/keyed-list.demo.tsx +0 -94
- package/src/theme/README.md +0 -103
- package/src/theme/contract.ts +0 -215
- package/src/theme/glyph-contract.ts +0 -59
- package/src/theme/presets/rmx-01/glyphs.tsx +0 -308
- package/src/theme/presets/rmx-01/index.ts +0 -123
- package/src/theme/runtime.ts +0 -119
- package/src/theme/theme.ts +0 -15
- package/src/utils/scroll-lock/README.md +0 -33
- /package/dist/{components/anchor/anchor.d.ts → anchor/index.d.ts} +0 -0
- /package/dist/{components/breadcrumbs/breadcrumbs.d.ts → breadcrumbs/index.d.ts} +0 -0
- /package/dist/{utils → listbox}/flash-attribute.d.ts +0 -0
- /package/dist/{utils → listbox}/flash-attribute.js +0 -0
- /package/dist/{components/menu → menu}/hover-aim.d.ts +0 -0
- /package/dist/{components/menu → menu}/hover-aim.js +0 -0
- /package/dist/{interactions/outside-click/outside-click-mixin.d.ts → popover/outside-click.d.ts} +0 -0
- /package/dist/{interactions/keydown → select}/keydown.d.ts +0 -0
- /package/dist/{interactions/keydown → select}/keydown.js +0 -0
- /package/dist/{interactions/typeahead/typeahead-mixin.d.ts → shared/typeahead.d.ts} +0 -0
- /package/dist/{utils → shared}/wait-for-css-transition.d.ts +0 -0
- /package/dist/{utils → shared}/wait-for-css-transition.js +0 -0
- /package/dist/{utils → shared}/wait.d.ts +0 -0
- /package/dist/{utils → shared}/wait.js +0 -0
- /package/src/{components/anchor/anchor.ts → anchor/index.ts} +0 -0
- /package/src/{utils → listbox}/flash-attribute.ts +0 -0
- /package/src/{components/menu → menu}/hover-aim.ts +0 -0
- /package/src/{interactions/outside-click/outside-click-mixin.ts → popover/outside-click.ts} +0 -0
- /package/src/{interactions/keydown → select}/keydown.ts +0 -0
- /package/src/{interactions/typeahead/typeahead-mixin.ts → shared/typeahead.ts} +0 -0
- /package/src/{utils → shared}/wait-for-css-transition.ts +0 -0
- /package/src/{utils → shared}/wait.ts +0 -0
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import { createComponent
|
|
2
|
-
import { createFrame } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
1
|
+
import { createComponent } from './component.js';
|
|
2
|
+
import { createFrame, isFrameRuntime } from './frame.js';
|
|
3
|
+
import { unwrapFrameResolution } from './frame-resolution.js';
|
|
4
|
+
import { createRangeRoot } from './vdom.js';
|
|
5
|
+
import { isCommittedComponentNode, isCommittedHostNode, isCommittedTextNode, isFragmentNode, isHostNode, findContextFromAncestry, } from './vnode.js';
|
|
6
|
+
import { invariant } from './invariant.js';
|
|
7
|
+
import { patchHostProps } from './core/props.js';
|
|
8
|
+
import { skipComments, logHydrationMismatch } from './client-entries.js';
|
|
9
|
+
import { toVNode } from './to-vnode.js';
|
|
10
|
+
import { bindMixinRuntime, cancelPendingMixinRemoval, dispatchMixinBeforeUpdate, dispatchMixinCommit, getMixinRuntimeSignal, prepareMixinRemoval, resolveMixedProps, teardownMixins, } from './mixins/mixin.js';
|
|
11
|
+
import { isOnMixinDescriptor } from './mixins/on-mixin.js';
|
|
12
|
+
import { createComponentErrorEvent } from './error-event.js';
|
|
13
|
+
import { componentStalenessCheck } from './refresh.js';
|
|
11
14
|
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
12
15
|
let idCounter = 0;
|
|
13
16
|
let persistedRemovalToken = 0;
|
|
@@ -15,40 +18,36 @@ const persistedMixinNodes = new Set();
|
|
|
15
18
|
let activeSchedulerUpdateParents;
|
|
16
19
|
// Compute SVG context for a node based on its parent and type.
|
|
17
20
|
// Returns true if the node is within an SVG subtree, false otherwise.
|
|
18
|
-
function getSvgContext(vParent,
|
|
21
|
+
function getSvgContext(vParent, node) {
|
|
19
22
|
// Only host elements (strings) can affect SVG context
|
|
20
|
-
if (
|
|
23
|
+
if (node.kind === 'host') {
|
|
21
24
|
// svg element creates SVG context
|
|
22
|
-
if (
|
|
25
|
+
if (node.type === 'svg')
|
|
23
26
|
return true;
|
|
24
27
|
// foreignObject switches back to HTML context
|
|
25
|
-
if (
|
|
28
|
+
if (node.type === 'foreignObject')
|
|
26
29
|
return false;
|
|
27
30
|
}
|
|
28
31
|
// Otherwise inherit from parent
|
|
29
|
-
return vParent._svg
|
|
32
|
+
return vParent._svg;
|
|
30
33
|
}
|
|
31
34
|
function getHostProps(node) {
|
|
32
|
-
return node._mixedProps
|
|
35
|
+
return '_mixedProps' in node ? node._mixedProps : node.props;
|
|
33
36
|
}
|
|
34
37
|
function markNodePersistedByMixins(node, domParent, token) {
|
|
35
|
-
node.
|
|
36
|
-
node._persistedParentByMixins = domParent;
|
|
37
|
-
node._persistedRemovalToken = token;
|
|
38
|
+
node._persistence = { parent: domParent, token };
|
|
38
39
|
persistedMixinNodes.add(node);
|
|
39
40
|
bindMixinRuntime(node._mixState, undefined);
|
|
40
41
|
}
|
|
41
42
|
function unmarkNodePersistedByMixins(node) {
|
|
42
|
-
node.
|
|
43
|
-
node._persistedParentByMixins = undefined;
|
|
44
|
-
node._persistedRemovalToken = undefined;
|
|
43
|
+
node._persistence = undefined;
|
|
45
44
|
persistedMixinNodes.delete(node);
|
|
46
45
|
}
|
|
47
46
|
function findMatchingPersistedMixinNode(type, key, domParent) {
|
|
48
47
|
if (key == null)
|
|
49
48
|
return null;
|
|
50
49
|
for (let node of persistedMixinNodes) {
|
|
51
|
-
if (node.
|
|
50
|
+
if (node._persistence?.parent !== domParent)
|
|
52
51
|
continue;
|
|
53
52
|
if (node.type !== type)
|
|
54
53
|
continue;
|
|
@@ -59,6 +58,7 @@ function findMatchingPersistedMixinNode(type, key, domParent) {
|
|
|
59
58
|
return null;
|
|
60
59
|
}
|
|
61
60
|
const EMPTY_DIRECT_EVENT_DESCRIPTORS = [];
|
|
61
|
+
const EMPTY_COMMITTED_CHILDREN = [];
|
|
62
62
|
function shouldRestoreControlledReflectionOnInput(node, state) {
|
|
63
63
|
// Some controls dispatch `input` before `change` for the same interaction.
|
|
64
64
|
// When checked/value state is typically handled on `change`, restoring on the
|
|
@@ -152,6 +152,15 @@ function teardownControlledReflection(node) {
|
|
|
152
152
|
state.listenersAttached = false;
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
|
+
// See abandonDirectEventListeners: skips removeEventListener for discarded subtrees.
|
|
156
|
+
function abandonControlledReflection(node) {
|
|
157
|
+
let state = node._controlledState;
|
|
158
|
+
if (!state)
|
|
159
|
+
return;
|
|
160
|
+
state.disposed = true;
|
|
161
|
+
state.pendingRestoreVersion++;
|
|
162
|
+
state.listenersAttached = false;
|
|
163
|
+
}
|
|
155
164
|
function canManageValue(type, element) {
|
|
156
165
|
if (type === 'progress')
|
|
157
166
|
return false;
|
|
@@ -176,23 +185,16 @@ function setPropertyReflection(element, key, value) {
|
|
|
176
185
|
return;
|
|
177
186
|
element[key] = value == null ? '' : value;
|
|
178
187
|
}
|
|
179
|
-
function resolveNodeMixProps(node, frame, scheduler, state) {
|
|
188
|
+
function resolveNodeMixProps(node, parent, frame, scheduler, state) {
|
|
180
189
|
let mix = node.props.mix;
|
|
181
190
|
let directEventDescriptors = resolveDirectEventDescriptors(mix);
|
|
182
191
|
if (directEventDescriptors) {
|
|
183
|
-
if (state)
|
|
192
|
+
if (state)
|
|
184
193
|
teardownMixins(state);
|
|
185
|
-
}
|
|
186
|
-
node._mixState = undefined;
|
|
187
|
-
node._mixedProps = node.props;
|
|
188
|
-
node._directEventDescriptors = directEventDescriptors;
|
|
189
|
-
return node.props;
|
|
194
|
+
return { props: node.props, directEventDescriptors };
|
|
190
195
|
}
|
|
191
|
-
node._directEventDescriptors = undefined;
|
|
192
196
|
if (state == null && (mix == null || (Array.isArray(mix) && mix.length === 0))) {
|
|
193
|
-
node.
|
|
194
|
-
node._mixedProps = node.props;
|
|
195
|
-
return node.props;
|
|
197
|
+
return { props: node.props };
|
|
196
198
|
}
|
|
197
199
|
let resolved = resolveMixedProps({
|
|
198
200
|
hostType: node.type,
|
|
@@ -202,14 +204,17 @@ function resolveNodeMixProps(node, frame, scheduler, state) {
|
|
|
202
204
|
if (typeof type !== 'function') {
|
|
203
205
|
return undefined;
|
|
204
206
|
}
|
|
205
|
-
return findContextFromAncestry(
|
|
207
|
+
return findContextFromAncestry(parent, type);
|
|
206
208
|
},
|
|
207
209
|
props: node.props,
|
|
208
210
|
state,
|
|
209
211
|
});
|
|
210
|
-
|
|
212
|
+
return { props: resolved.props, mixState: resolved.state };
|
|
213
|
+
}
|
|
214
|
+
function applyResolvedHostProps(node, resolved) {
|
|
211
215
|
node._mixedProps = resolved.props;
|
|
212
|
-
|
|
216
|
+
node._mixState = resolved.mixState;
|
|
217
|
+
node._directEventDescriptors = resolved.directEventDescriptors;
|
|
213
218
|
}
|
|
214
219
|
function resolveDirectEventDescriptors(mix) {
|
|
215
220
|
if (!mix)
|
|
@@ -220,8 +225,8 @@ function resolveDirectEventDescriptors(mix) {
|
|
|
220
225
|
return areOnMixinDescriptors(mix) ? mix : null;
|
|
221
226
|
}
|
|
222
227
|
function areOnMixinDescriptors(descriptors) {
|
|
223
|
-
for (let
|
|
224
|
-
if (!isOnMixinDescriptor(
|
|
228
|
+
for (let i = 0; i < descriptors.length; i++) {
|
|
229
|
+
if (!isOnMixinDescriptor(descriptors[i]))
|
|
225
230
|
return false;
|
|
226
231
|
}
|
|
227
232
|
return true;
|
|
@@ -237,8 +242,13 @@ function enqueueMixinBindingUpdate(done) {
|
|
|
237
242
|
}
|
|
238
243
|
dispatchMixinBeforeUpdate(state);
|
|
239
244
|
let prevProps = getHostProps(node);
|
|
240
|
-
let
|
|
241
|
-
|
|
245
|
+
let resolved = resolveNodeMixProps(node, node._parent, this.frame, this.scheduler, state);
|
|
246
|
+
applyResolvedHostProps(node, resolved);
|
|
247
|
+
patchHostProps(prevProps, resolved.props, this.node);
|
|
248
|
+
if (node._controlledState || shouldTrackControlledReflection(resolved.props)) {
|
|
249
|
+
ensureControlledReflection(node, this.scheduler);
|
|
250
|
+
syncControlledReflection(node, resolved.props);
|
|
251
|
+
}
|
|
242
252
|
dispatchMixinCommit(state);
|
|
243
253
|
done(state ? getMixinRuntimeSignal(state) : AbortSignal.abort());
|
|
244
254
|
},
|
|
@@ -248,7 +258,7 @@ function bindNodeMixRuntime(node, frame, scheduler, styles, reclaimed = false, p
|
|
|
248
258
|
let state = node._mixState;
|
|
249
259
|
bindMixinRuntime(state, {
|
|
250
260
|
node: node._dom,
|
|
251
|
-
parent: parent ?? node._dom
|
|
261
|
+
parent: parent ?? getRequiredDomParent(node._dom),
|
|
252
262
|
key: node.key,
|
|
253
263
|
target: node,
|
|
254
264
|
frame,
|
|
@@ -263,6 +273,11 @@ function isHeadHostNode(node) {
|
|
|
263
273
|
return false;
|
|
264
274
|
return node.type.toLowerCase() === 'head';
|
|
265
275
|
}
|
|
276
|
+
function getRequiredDomParent(node) {
|
|
277
|
+
let parent = node.parentNode;
|
|
278
|
+
invariant(parent, 'Expected mounted host node to have a DOM parent');
|
|
279
|
+
return parent;
|
|
280
|
+
}
|
|
266
281
|
function getDocumentHead(domParent) {
|
|
267
282
|
if (domParent instanceof Document) {
|
|
268
283
|
return domParent.head;
|
|
@@ -272,65 +287,112 @@ function getDocumentHead(domParent) {
|
|
|
272
287
|
}
|
|
273
288
|
return null;
|
|
274
289
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
290
|
+
function commitNonRenderNode(node, parent, svg) {
|
|
291
|
+
let committed = node;
|
|
292
|
+
committed._parent = parent;
|
|
293
|
+
committed._svg = svg;
|
|
294
|
+
return committed;
|
|
295
|
+
}
|
|
296
|
+
function commitTextNode(node, parent, svg, dom) {
|
|
297
|
+
let committed = node;
|
|
298
|
+
committed._parent = parent;
|
|
299
|
+
committed._svg = svg;
|
|
300
|
+
committed._dom = dom;
|
|
301
|
+
return committed;
|
|
302
|
+
}
|
|
303
|
+
function beginFragmentNode(node, parent, svg) {
|
|
304
|
+
let committed = node;
|
|
305
|
+
committed._parent = parent;
|
|
306
|
+
committed._svg = svg;
|
|
307
|
+
committed._children = EMPTY_COMMITTED_CHILDREN;
|
|
308
|
+
return committed;
|
|
309
|
+
}
|
|
310
|
+
function commitHostNode(node, parent, svg, dom, resolved, children = EMPTY_COMMITTED_CHILDREN) {
|
|
311
|
+
let committed = node;
|
|
312
|
+
committed._parent = parent;
|
|
313
|
+
committed._svg = svg;
|
|
314
|
+
committed._dom = dom;
|
|
315
|
+
committed._children = children;
|
|
316
|
+
committed._mixedProps = resolved.props;
|
|
317
|
+
committed._mixState = resolved.mixState;
|
|
318
|
+
committed._directEventDescriptors = resolved.directEventDescriptors;
|
|
319
|
+
return committed;
|
|
320
|
+
}
|
|
321
|
+
function beginComponentNode(node, parent, svg, handle, context) {
|
|
322
|
+
let mounting = node;
|
|
323
|
+
mounting._parent = parent;
|
|
324
|
+
mounting._svg = svg;
|
|
325
|
+
mounting._handle = handle;
|
|
326
|
+
mounting._context = context;
|
|
327
|
+
return mounting;
|
|
328
|
+
}
|
|
329
|
+
function commitComponentNode(node, content) {
|
|
330
|
+
let committed = node;
|
|
331
|
+
committed._content = content;
|
|
332
|
+
return committed;
|
|
333
|
+
}
|
|
334
|
+
export function diffVNodes(curr, next, domParent, vParent, context, anchor, cursor) {
|
|
279
335
|
if (curr === null) {
|
|
280
|
-
return insert(next, domParent,
|
|
281
|
-
}
|
|
282
|
-
if (curr.type !== next.type) {
|
|
283
|
-
replace(curr, next, domParent, frame, scheduler, styles, vParent, rootTarget, anchor);
|
|
284
|
-
return rootCursor;
|
|
336
|
+
return insert(next, domParent, vParent, context, anchor, cursor);
|
|
285
337
|
}
|
|
286
|
-
if (
|
|
287
|
-
|
|
338
|
+
if (componentStalenessCheck !== null &&
|
|
339
|
+
curr.kind === 'component' &&
|
|
340
|
+
next.kind === 'component' &&
|
|
341
|
+
componentStalenessCheck(curr.type) === true) {
|
|
342
|
+
return replace(curr, next, domParent, vParent, context, anchor);
|
|
288
343
|
}
|
|
289
|
-
if (
|
|
290
|
-
|
|
291
|
-
return rootCursor;
|
|
344
|
+
if (curr.kind !== next.kind || curr.type !== next.type) {
|
|
345
|
+
return replace(curr, next, domParent, vParent, context, anchor);
|
|
292
346
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
347
|
+
switch (next.kind) {
|
|
348
|
+
case 'host': {
|
|
349
|
+
return diffHost(curr, next, vParent, context);
|
|
350
|
+
}
|
|
351
|
+
case 'text': {
|
|
352
|
+
return diffText(curr, next, vParent, getSvgContext(vParent, next));
|
|
353
|
+
}
|
|
354
|
+
case 'empty': {
|
|
355
|
+
return commitNonRenderNode(next, vParent, getSvgContext(vParent, next));
|
|
356
|
+
}
|
|
357
|
+
case 'fragment': {
|
|
358
|
+
let childInputs = next._children;
|
|
359
|
+
let committed = beginFragmentNode(next, vParent, getSvgContext(vParent, next));
|
|
360
|
+
committed._children = diffChildren(curr._children, childInputs, domParent, committed, context, undefined, anchor);
|
|
361
|
+
return committed;
|
|
362
|
+
}
|
|
363
|
+
case 'frame': {
|
|
364
|
+
return diffFrame(curr, next, domParent, vParent, context, getSvgContext(vParent, next), anchor);
|
|
365
|
+
}
|
|
366
|
+
case 'component': {
|
|
367
|
+
return diffComponent(curr, next, domParent, vParent, context, getSvgContext(vParent, next), anchor, cursor);
|
|
368
|
+
}
|
|
308
369
|
}
|
|
309
|
-
invariant(false, 'Unexpected diff case');
|
|
310
370
|
}
|
|
311
|
-
function replace(curr, next, domParent,
|
|
371
|
+
function replace(curr, next, domParent, vParent, context, anchor) {
|
|
312
372
|
let currAnchor = findFirstDomAnchor(curr);
|
|
313
373
|
if (currAnchor && currAnchor.parentNode === domParent) {
|
|
314
374
|
let replacementAnchor = document.createComment('rmx:replace');
|
|
315
375
|
domParent.insertBefore(replacementAnchor, currAnchor);
|
|
316
376
|
try {
|
|
317
|
-
remove(curr, domParent,
|
|
318
|
-
insert(next, domParent,
|
|
377
|
+
remove(curr, domParent, context);
|
|
378
|
+
return insert(next, domParent, vParent, context, replacementAnchor);
|
|
319
379
|
}
|
|
320
380
|
finally {
|
|
321
381
|
replacementAnchor.parentNode?.removeChild(replacementAnchor);
|
|
322
382
|
}
|
|
323
|
-
return;
|
|
324
383
|
}
|
|
325
384
|
let replacementAnchor = findNextSiblingDomAnchor(curr) ?? anchor;
|
|
326
|
-
remove(curr, domParent,
|
|
327
|
-
insert(next, domParent,
|
|
385
|
+
remove(curr, domParent, context);
|
|
386
|
+
return insert(next, domParent, vParent, context, replacementAnchor);
|
|
328
387
|
}
|
|
329
|
-
function diffHost(curr, next,
|
|
388
|
+
function diffHost(curr, next, vParent, context) {
|
|
389
|
+
let { frame, scheduler, styles } = context;
|
|
330
390
|
let mixState = curr._mixState;
|
|
331
391
|
let currProps = getHostProps(curr);
|
|
332
|
-
let
|
|
333
|
-
let
|
|
392
|
+
let resolved = resolveNodeMixProps(next, vParent, frame, scheduler, mixState);
|
|
393
|
+
let childInputs = next._children;
|
|
394
|
+
let nextProps = resolved.props;
|
|
395
|
+
let nextMixState = resolved.mixState;
|
|
334
396
|
let shouldDispatchMixinLifecycle = (nextMixState?.runners.length ?? 0) > 0 && shouldDispatchInlineMixinLifecycle(curr._dom);
|
|
335
397
|
if (shouldDispatchMixinLifecycle) {
|
|
336
398
|
dispatchMixinBeforeUpdate(nextMixState);
|
|
@@ -346,34 +408,30 @@ function diffHost(curr, next, frame, scheduler, styles, vParent, rootTarget) {
|
|
|
346
408
|
// innerHTML was removed, clear it before adding children
|
|
347
409
|
curr._dom.innerHTML = '';
|
|
348
410
|
}
|
|
349
|
-
|
|
411
|
+
let committed = commitHostNode(next, vParent, getSvgContext(vParent, next), curr._dom, resolved);
|
|
412
|
+
committed._directEventState = curr._directEventState;
|
|
413
|
+
committed._controlledState = curr._controlledState;
|
|
414
|
+
committed._children = diffChildren(curr._children, childInputs, curr._dom, committed, context);
|
|
350
415
|
patchHostProps(currProps, nextProps, curr._dom);
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
ensureControlledReflection(next, scheduler);
|
|
359
|
-
syncControlledReflection(next, nextProps);
|
|
360
|
-
}
|
|
361
|
-
if (next._mixState) {
|
|
362
|
-
bindNodeMixRuntime(next, frame, scheduler, styles);
|
|
416
|
+
syncDirectEventListeners(committed);
|
|
417
|
+
if (committed._controlledState || shouldTrackControlledReflection(nextProps)) {
|
|
418
|
+
ensureControlledReflection(committed, scheduler);
|
|
419
|
+
syncControlledReflection(committed, nextProps);
|
|
420
|
+
}
|
|
421
|
+
if (committed._mixState) {
|
|
422
|
+
bindNodeMixRuntime(committed, frame, scheduler, styles);
|
|
363
423
|
}
|
|
364
424
|
if (shouldDispatchMixinLifecycle) {
|
|
365
425
|
scheduler.enqueueCommitPhase([() => dispatchMixinCommit(nextMixState)]);
|
|
366
426
|
}
|
|
367
|
-
return;
|
|
427
|
+
return committed;
|
|
368
428
|
}
|
|
369
|
-
function setupHostNode(node,
|
|
370
|
-
node._dom = dom;
|
|
429
|
+
function setupHostNode(node, scheduler) {
|
|
371
430
|
let props = getHostProps(node);
|
|
372
|
-
|
|
373
|
-
syncDirectEventListeners(committedNode);
|
|
431
|
+
syncDirectEventListeners(node);
|
|
374
432
|
if (shouldTrackControlledReflection(props)) {
|
|
375
|
-
ensureControlledReflection(
|
|
376
|
-
syncControlledReflection(
|
|
433
|
+
ensureControlledReflection(node, scheduler);
|
|
434
|
+
syncControlledReflection(node, props);
|
|
377
435
|
}
|
|
378
436
|
}
|
|
379
437
|
function syncDirectEventListeners(node) {
|
|
@@ -393,8 +451,12 @@ function syncDirectEventListeners(node) {
|
|
|
393
451
|
}
|
|
394
452
|
let bindings = state.bindings;
|
|
395
453
|
for (let index = 0; index < descriptors.length; index++) {
|
|
396
|
-
|
|
397
|
-
|
|
454
|
+
// Indexed access instead of array destructuring: destructuring goes through
|
|
455
|
+
// the iterator protocol and allocates on every host-node update.
|
|
456
|
+
let args = descriptors[index].args;
|
|
457
|
+
let type = args[0];
|
|
458
|
+
let handler = args[1];
|
|
459
|
+
let captureBoolean = args[2] ?? false;
|
|
398
460
|
let binding = bindings[index];
|
|
399
461
|
if (!binding) {
|
|
400
462
|
binding = createDirectEventBinding(type, handler, captureBoolean);
|
|
@@ -453,256 +515,286 @@ function teardownDirectEventListeners(node) {
|
|
|
453
515
|
state.bindings.length = 0;
|
|
454
516
|
node._directEventState = undefined;
|
|
455
517
|
}
|
|
518
|
+
// Teardown for a node whose DOM subtree is being discarded wholesale: abort
|
|
519
|
+
// pending handler work but skip removeEventListener — the listeners die with
|
|
520
|
+
// the detached node, and removing them one-by-one dominates large teardowns.
|
|
521
|
+
function abandonDirectEventListeners(node) {
|
|
522
|
+
let state = node._directEventState;
|
|
523
|
+
if (!state)
|
|
524
|
+
return;
|
|
525
|
+
for (let binding of state.bindings) {
|
|
526
|
+
binding.reentry?.abort(new DOMException('', 'AbortError'));
|
|
527
|
+
binding.reentry = null;
|
|
528
|
+
}
|
|
529
|
+
state.bindings.length = 0;
|
|
530
|
+
node._directEventState = undefined;
|
|
531
|
+
}
|
|
456
532
|
function invokeDirectEventBinding(binding, event) {
|
|
457
533
|
binding.reentry?.abort(new DOMException('', 'EventReentry'));
|
|
458
534
|
binding.reentry = new AbortController();
|
|
459
535
|
void binding.handler(event, binding.reentry.signal);
|
|
460
536
|
}
|
|
461
|
-
function diffText(curr, next, vParent) {
|
|
537
|
+
function diffText(curr, next, vParent, svg) {
|
|
462
538
|
if (curr._text !== next._text) {
|
|
463
539
|
curr._dom.textContent = next._text;
|
|
464
540
|
}
|
|
465
|
-
next
|
|
466
|
-
next._parent = vParent;
|
|
541
|
+
return commitTextNode(next, vParent, svg, curr._dom);
|
|
467
542
|
}
|
|
468
|
-
function insert(node, domParent,
|
|
469
|
-
|
|
470
|
-
|
|
543
|
+
function insert(node, domParent, vParent, context, anchor, cursor) {
|
|
544
|
+
let { frame, scheduler, styles } = context;
|
|
545
|
+
let svg = getSvgContext(vParent, node);
|
|
546
|
+
let hydrationNode = cursor?.current;
|
|
471
547
|
// Stop hydration if cursor has reached the anchor (end boundary)
|
|
472
548
|
// Check BEFORE skipComments to prevent escaping range root markers
|
|
473
|
-
if (
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
549
|
+
if (hydrationNode && anchor && hydrationNode === anchor) {
|
|
550
|
+
hydrationNode = null;
|
|
551
|
+
}
|
|
552
|
+
// Preserve frame-start markers for non-Frame nodes too, so a following <Frame>
|
|
553
|
+
// (e.g. the first child of a bare Fragment at a clientEntry boundary) can still
|
|
554
|
+
// claim its rmx:f marker during hydration instead of being re-inserted fresh.
|
|
555
|
+
// A rmx:f marker always belongs to a <Frame>, so no non-Frame node should
|
|
556
|
+
// consume one.
|
|
557
|
+
hydrationNode = skipCommentsExceptFrameStart(hydrationNode ?? null);
|
|
480
558
|
// Also check after skipComments in case we skipped past the anchor
|
|
481
|
-
if (
|
|
482
|
-
|
|
559
|
+
if (hydrationNode && anchor && hydrationNode === anchor) {
|
|
560
|
+
hydrationNode = null;
|
|
483
561
|
}
|
|
562
|
+
if (cursor)
|
|
563
|
+
cursor.current = hydrationNode;
|
|
484
564
|
let doInsert = anchor
|
|
485
565
|
? (dom) => domParent.insertBefore(dom, anchor)
|
|
486
566
|
: (dom) => domParent.appendChild(dom);
|
|
487
|
-
if (
|
|
488
|
-
return
|
|
567
|
+
if (node.kind === 'empty') {
|
|
568
|
+
return commitNonRenderNode(node, vParent, svg);
|
|
489
569
|
}
|
|
490
|
-
if (
|
|
491
|
-
if (
|
|
492
|
-
node._parent = vParent;
|
|
570
|
+
if (node.kind === 'text') {
|
|
571
|
+
if (hydrationNode instanceof Text) {
|
|
493
572
|
// Handle text node consolidation: server renders adjacent text as single node
|
|
494
573
|
// e.g., <span>Hello {world}</span> → server: "Hello world", client: ["Hello ", "world"]
|
|
495
|
-
if (
|
|
496
|
-
if (
|
|
574
|
+
if (hydrationNode.data !== node._text) {
|
|
575
|
+
if (hydrationNode.data.startsWith(node._text) &&
|
|
576
|
+
node._text.length < hydrationNode.data.length) {
|
|
497
577
|
// Consolidation case: split the text node at the boundary
|
|
498
578
|
// cursor becomes the first part (node._text), remainder is returned for next vnode
|
|
499
|
-
let remainder =
|
|
500
|
-
|
|
501
|
-
|
|
579
|
+
let remainder = hydrationNode.splitText(node._text.length);
|
|
580
|
+
if (cursor)
|
|
581
|
+
cursor.current = remainder;
|
|
582
|
+
return commitTextNode(node, vParent, svg, hydrationNode);
|
|
502
583
|
}
|
|
503
584
|
// Genuine mismatch - correct it
|
|
504
|
-
logHydrationMismatch('text mismatch',
|
|
505
|
-
|
|
585
|
+
logHydrationMismatch('text mismatch', hydrationNode.data, node._text);
|
|
586
|
+
hydrationNode.data = node._text;
|
|
506
587
|
}
|
|
507
|
-
|
|
508
|
-
|
|
588
|
+
if (cursor)
|
|
589
|
+
cursor.current = hydrationNode.nextSibling;
|
|
590
|
+
return commitTextNode(node, vParent, svg, hydrationNode);
|
|
509
591
|
}
|
|
510
592
|
let dom = document.createTextNode(node._text);
|
|
511
|
-
node._dom = dom;
|
|
512
|
-
node._parent = vParent;
|
|
513
593
|
doInsert(dom);
|
|
514
|
-
return
|
|
594
|
+
return commitTextNode(node, vParent, svg, dom);
|
|
515
595
|
}
|
|
516
|
-
if (
|
|
517
|
-
let
|
|
596
|
+
if (node.kind === 'host') {
|
|
597
|
+
let resolved = resolveNodeMixProps(node, vParent, frame, scheduler);
|
|
598
|
+
let hostProps = resolved.props;
|
|
599
|
+
let childInputs = node._children;
|
|
518
600
|
if (isHeadHostNode(node)) {
|
|
519
601
|
let targetHead = getDocumentHead(domParent);
|
|
520
602
|
if (targetHead) {
|
|
521
|
-
let childCursor = cursor;
|
|
522
|
-
if (
|
|
523
|
-
childCursor
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
603
|
+
let childCursor = cursor ? { current: hydrationNode } : undefined;
|
|
604
|
+
if (hydrationNode instanceof Element && hydrationNode.tagName.toLowerCase() === 'head') {
|
|
605
|
+
if (childCursor)
|
|
606
|
+
childCursor.current = hydrationNode.firstChild;
|
|
607
|
+
let nextCursor = hydrationNode.nextSibling;
|
|
608
|
+
if (hydrationNode !== targetHead) {
|
|
609
|
+
while (hydrationNode.firstChild) {
|
|
610
|
+
targetHead.appendChild(hydrationNode.firstChild);
|
|
528
611
|
}
|
|
529
|
-
|
|
612
|
+
hydrationNode.remove();
|
|
530
613
|
}
|
|
531
|
-
cursor
|
|
614
|
+
if (cursor)
|
|
615
|
+
cursor.current = nextCursor;
|
|
532
616
|
}
|
|
617
|
+
let committed = commitHostNode(node, vParent, svg, targetHead, resolved);
|
|
533
618
|
// Render explicit <head> children directly into document.head.
|
|
534
|
-
diffChildren(null,
|
|
619
|
+
committed._children = diffChildren(null, childInputs, targetHead, committed, context, childCursor);
|
|
535
620
|
patchHostProps({}, hostProps, targetHead);
|
|
536
|
-
setupHostNode(
|
|
537
|
-
if (
|
|
538
|
-
bindNodeMixRuntime(
|
|
621
|
+
setupHostNode(committed, scheduler);
|
|
622
|
+
if (committed._mixState) {
|
|
623
|
+
bindNodeMixRuntime(committed, frame, scheduler, styles);
|
|
539
624
|
}
|
|
540
|
-
return
|
|
625
|
+
return committed;
|
|
541
626
|
}
|
|
542
627
|
}
|
|
543
628
|
// Check for matching mixin-persisted node that can be reclaimed
|
|
544
629
|
let persistedNode = findMatchingPersistedMixinNode(node.type, node.key, domParent);
|
|
545
630
|
if (persistedNode) {
|
|
546
|
-
reclaimPersistedMixinNode(persistedNode, node,
|
|
547
|
-
return cursor;
|
|
631
|
+
return reclaimPersistedMixinNode(persistedNode, node, vParent, context);
|
|
548
632
|
}
|
|
549
|
-
if (
|
|
633
|
+
if (hydrationNode instanceof Element) {
|
|
550
634
|
// SVG elements have case-sensitive tag names (e.g. linearGradient, clipPath)
|
|
551
635
|
// HTML elements are case-insensitive, so we lowercase for comparison
|
|
552
|
-
let cursorTag =
|
|
636
|
+
let cursorTag = svg ? hydrationNode.tagName : hydrationNode.tagName.toLowerCase();
|
|
553
637
|
if (cursorTag === node.type) {
|
|
554
|
-
let nextCursor =
|
|
555
|
-
patchHostProps({}, hostProps,
|
|
638
|
+
let nextCursor = hydrationNode.nextSibling;
|
|
639
|
+
patchHostProps({}, hostProps, hydrationNode);
|
|
640
|
+
let committed = commitHostNode(node, vParent, svg, hydrationNode, resolved);
|
|
556
641
|
// Handle innerHTML prop
|
|
557
642
|
if (hostProps.innerHTML != null) {
|
|
558
|
-
|
|
643
|
+
hydrationNode.innerHTML = hostProps.innerHTML;
|
|
559
644
|
}
|
|
560
645
|
else {
|
|
561
|
-
let childCursor =
|
|
646
|
+
let childCursor = { current: hydrationNode.firstChild };
|
|
562
647
|
// Ignore excess nodes - browser extensions may inject content
|
|
563
|
-
|
|
648
|
+
committed._children = diffChildren(null, childInputs, hydrationNode, committed, context, childCursor);
|
|
564
649
|
}
|
|
565
|
-
setupHostNode(
|
|
566
|
-
if (
|
|
567
|
-
bindNodeMixRuntime(
|
|
650
|
+
setupHostNode(committed, scheduler);
|
|
651
|
+
if (committed._mixState) {
|
|
652
|
+
bindNodeMixRuntime(committed, frame, scheduler, styles);
|
|
568
653
|
}
|
|
569
|
-
|
|
654
|
+
if (cursor)
|
|
655
|
+
cursor.current = nextCursor;
|
|
656
|
+
return committed;
|
|
570
657
|
}
|
|
571
658
|
else {
|
|
572
659
|
// Type mismatch - try single-advance retry to handle browser extension injections
|
|
573
660
|
// at the start of containers. Skip this node and try the next sibling once.
|
|
574
|
-
let nextSibling = skipComments(
|
|
661
|
+
let nextSibling = skipComments(hydrationNode.nextSibling);
|
|
575
662
|
if (nextSibling instanceof Element) {
|
|
576
|
-
let nextTag =
|
|
663
|
+
let nextTag = svg ? nextSibling.tagName : nextSibling.tagName.toLowerCase();
|
|
577
664
|
if (nextTag === node.type) {
|
|
578
665
|
let nextCursor = nextSibling.nextSibling;
|
|
579
666
|
// Found a match after skipping - adopt it and leave skipped node in place
|
|
580
667
|
patchHostProps({}, hostProps, nextSibling);
|
|
668
|
+
let committed = commitHostNode(node, vParent, svg, nextSibling, resolved);
|
|
581
669
|
if (hostProps.innerHTML != null) {
|
|
582
670
|
nextSibling.innerHTML = hostProps.innerHTML;
|
|
583
671
|
}
|
|
584
672
|
else {
|
|
585
|
-
let childCursor = nextSibling.firstChild;
|
|
586
|
-
diffChildren(null,
|
|
673
|
+
let childCursor = { current: nextSibling.firstChild };
|
|
674
|
+
committed._children = diffChildren(null, childInputs, nextSibling, committed, context, childCursor);
|
|
587
675
|
}
|
|
588
|
-
setupHostNode(
|
|
589
|
-
if (
|
|
590
|
-
bindNodeMixRuntime(
|
|
676
|
+
setupHostNode(committed, scheduler);
|
|
677
|
+
if (committed._mixState) {
|
|
678
|
+
bindNodeMixRuntime(committed, frame, scheduler, styles);
|
|
591
679
|
}
|
|
592
|
-
|
|
680
|
+
if (cursor)
|
|
681
|
+
cursor.current = nextCursor;
|
|
682
|
+
return committed;
|
|
593
683
|
}
|
|
594
684
|
}
|
|
595
685
|
// Retry failed - log mismatch and create new element (don't remove mismatched nodes)
|
|
596
686
|
logHydrationMismatch('tag', cursorTag, node.type);
|
|
597
|
-
cursor
|
|
687
|
+
if (cursor)
|
|
688
|
+
cursor.current = undefined; // stop hydration for this tree
|
|
598
689
|
}
|
|
599
690
|
}
|
|
600
|
-
let dom = node.
|
|
601
|
-
? document.createElementNS(SVG_NS, node.type)
|
|
602
|
-
: document.createElement(node.type);
|
|
691
|
+
let dom = svg ? document.createElementNS(SVG_NS, node.type) : document.createElement(node.type);
|
|
603
692
|
patchHostProps({}, hostProps, dom);
|
|
693
|
+
let committed = commitHostNode(node, vParent, svg, dom, resolved);
|
|
604
694
|
// Handle innerHTML prop
|
|
605
695
|
if (hostProps.innerHTML != null) {
|
|
606
696
|
dom.innerHTML = hostProps.innerHTML;
|
|
607
697
|
}
|
|
608
698
|
else {
|
|
609
|
-
diffChildren(null,
|
|
699
|
+
committed._children = diffChildren(null, childInputs, dom, committed, context);
|
|
610
700
|
}
|
|
611
|
-
setupHostNode(
|
|
612
|
-
if (
|
|
613
|
-
bindNodeMixRuntime(
|
|
701
|
+
setupHostNode(committed, scheduler);
|
|
702
|
+
if (committed._mixState) {
|
|
703
|
+
bindNodeMixRuntime(committed, frame, scheduler, styles, false, domParent);
|
|
614
704
|
}
|
|
615
705
|
doInsert(dom);
|
|
616
|
-
return
|
|
706
|
+
return committed;
|
|
617
707
|
}
|
|
618
|
-
if (
|
|
708
|
+
if (node.kind === 'fragment') {
|
|
709
|
+
let childInputs = node._children;
|
|
710
|
+
let committed = beginFragmentNode(node, vParent, svg);
|
|
711
|
+
let children = childInputs;
|
|
619
712
|
// Insert fragment children in order before the same anchor
|
|
620
|
-
for (let
|
|
621
|
-
|
|
713
|
+
for (let i = 0; i < childInputs.length; i++) {
|
|
714
|
+
children[i] = insert(childInputs[i], domParent, committed, context, anchor, cursor);
|
|
622
715
|
}
|
|
623
|
-
|
|
716
|
+
committed._children = children;
|
|
717
|
+
return committed;
|
|
624
718
|
}
|
|
625
|
-
if (
|
|
626
|
-
return diffComponent(null, node,
|
|
719
|
+
if (node.kind === 'component') {
|
|
720
|
+
return diffComponent(null, node, domParent, vParent, context, svg, anchor, cursor);
|
|
627
721
|
}
|
|
628
|
-
if (node.
|
|
629
|
-
return insertFrame(node, domParent,
|
|
722
|
+
if (node.kind === 'frame') {
|
|
723
|
+
return insertFrame(node, domParent, vParent, context, svg, anchor, cursor);
|
|
630
724
|
}
|
|
631
725
|
invariant(false, 'Unexpected node type');
|
|
632
726
|
}
|
|
633
|
-
function diffFrame(curr, next, domParent,
|
|
727
|
+
function diffFrame(curr, next, domParent, vParent, context, svg, anchor) {
|
|
728
|
+
let { frame } = context;
|
|
634
729
|
let currSrc = getFrameSrc(curr);
|
|
635
730
|
let nextSrc = getFrameSrc(next);
|
|
636
731
|
let currName = getFrameName(curr);
|
|
637
732
|
let nextName = getFrameName(next);
|
|
638
733
|
if (currName !== nextName) {
|
|
639
|
-
let replaceAnchor = curr._rangeEnd
|
|
640
|
-
remove(curr, domParent,
|
|
641
|
-
|
|
642
|
-
return;
|
|
734
|
+
let replaceAnchor = curr._rangeEnd.nextSibling ?? anchor;
|
|
735
|
+
remove(curr, domParent, context);
|
|
736
|
+
return insertFrame(next, domParent, vParent, context, svg, replaceAnchor);
|
|
643
737
|
}
|
|
644
738
|
// If the frame hasn't resolved yet, preserve existing cancel/remount behavior
|
|
645
739
|
// so pending streams from the old src cannot take over the new src.
|
|
646
|
-
if (currSrc !== nextSrc && !curr.
|
|
647
|
-
let replaceAnchor = curr._rangeEnd
|
|
648
|
-
remove(curr, domParent,
|
|
649
|
-
|
|
650
|
-
return;
|
|
740
|
+
if (currSrc !== nextSrc && !curr._state.resolved) {
|
|
741
|
+
let replaceAnchor = curr._rangeEnd.nextSibling ?? anchor;
|
|
742
|
+
remove(curr, domParent, context);
|
|
743
|
+
return insertFrame(next, domParent, vParent, context, svg, replaceAnchor);
|
|
651
744
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
745
|
+
let committed = next;
|
|
746
|
+
Object.assign(committed, {
|
|
747
|
+
_rangeStart: curr._rangeStart,
|
|
748
|
+
_rangeEnd: curr._rangeEnd,
|
|
749
|
+
_state: curr._state,
|
|
750
|
+
_parent: vParent,
|
|
751
|
+
_svg: svg,
|
|
752
|
+
});
|
|
753
|
+
let frameRuntime = getFrameRuntime(frame);
|
|
754
|
+
let frameInstance = committed._state.instance;
|
|
755
|
+
let serverFrameReload = frameRuntime?.serverFrameReload;
|
|
659
756
|
if (currSrc !== nextSrc) {
|
|
660
|
-
let frameInstance = next._frameInstance;
|
|
661
757
|
if (frameInstance) {
|
|
662
758
|
frameInstance.handle.src = nextSrc;
|
|
663
759
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
resolveClientFrame(next, runtime);
|
|
760
|
+
if (frameRuntime) {
|
|
761
|
+
resolveClientFrame(committed, frameRuntime, serverFrameReload);
|
|
667
762
|
}
|
|
668
763
|
}
|
|
669
|
-
if (
|
|
670
|
-
|
|
764
|
+
else if (frameRuntime && frameInstance && serverFrameReload) {
|
|
765
|
+
// Reload client frames that have the same src during a render triggered by an ancestor frame reload
|
|
766
|
+
resolveClientFrame(committed, frameRuntime, serverFrameReload);
|
|
671
767
|
}
|
|
768
|
+
if (!committed._state.resolved && committed._state.fallbackRoot) {
|
|
769
|
+
committed._state.fallbackRoot.render(committed.props.fallback ?? null);
|
|
770
|
+
}
|
|
771
|
+
return committed;
|
|
672
772
|
}
|
|
673
|
-
function insertFrame(node, domParent,
|
|
773
|
+
function insertFrame(node, domParent, vParent, context, svg, anchor, cursor) {
|
|
774
|
+
let { frame, styles } = context;
|
|
674
775
|
let runtime = getFrameRuntime(frame);
|
|
675
776
|
if (!runtime || runtime.canResolveFrames === false) {
|
|
676
777
|
throw new Error('Cannot render <Frame /> without frame runtime. Use run() or pass frameInit to createRoot/createRangeRoot.');
|
|
677
778
|
}
|
|
678
779
|
// Hydration path: adopt server-rendered frame markers and reuse the existing
|
|
679
780
|
// frame instance created during createSubFrames().
|
|
680
|
-
if (isFrameStartComment(cursor)) {
|
|
681
|
-
let start = cursor;
|
|
781
|
+
if (isFrameStartComment(cursor?.current)) {
|
|
782
|
+
let start = cursor.current;
|
|
682
783
|
let end = findFrameEndComment(start);
|
|
683
784
|
if (end) {
|
|
684
|
-
node._rangeStart = start;
|
|
685
|
-
node._rangeEnd = end;
|
|
686
|
-
node._parent = vParent;
|
|
687
|
-
node._frameResolveToken = 0;
|
|
688
|
-
node._frameResolveController = undefined;
|
|
689
|
-
node._frameFallbackRoot = undefined;
|
|
690
|
-
node._frameResolved = true;
|
|
691
|
-
let frameId = getFrameIdFromComment(start);
|
|
692
|
-
let marker = frameId ? runtime.data.f?.[frameId] : undefined;
|
|
693
|
-
let src = marker?.src ?? getFrameSrc(node);
|
|
694
785
|
let instance = runtime.frameInstances.get(start);
|
|
786
|
+
let src = instance?.handle.src ?? getFrameSrc(node);
|
|
695
787
|
if (!instance) {
|
|
696
788
|
instance = createFrame([start, end], {
|
|
697
789
|
name: getFrameName(node),
|
|
698
790
|
src,
|
|
699
|
-
marker: frameId && marker ? { ...marker, id: frameId } : undefined,
|
|
700
791
|
errorTarget: runtime.errorTarget,
|
|
701
792
|
loadModule: runtime.loadModule,
|
|
702
793
|
resolveFrame: runtime.resolveFrame,
|
|
703
794
|
pendingClientEntries: runtime.pendingClientEntries,
|
|
704
795
|
scheduler: runtime.scheduler,
|
|
705
|
-
|
|
796
|
+
styleManager: runtime.styleManager,
|
|
797
|
+
data: {},
|
|
706
798
|
moduleCache: runtime.moduleCache,
|
|
707
799
|
moduleLoads: runtime.moduleLoads,
|
|
708
800
|
frameInstances: runtime.frameInstances,
|
|
@@ -710,8 +802,20 @@ function insertFrame(node, domParent, frame, scheduler, styles, vParent, rootTar
|
|
|
710
802
|
});
|
|
711
803
|
runtime.frameInstances.set(start, instance);
|
|
712
804
|
}
|
|
713
|
-
|
|
714
|
-
return
|
|
805
|
+
cursor.current = end.nextSibling;
|
|
806
|
+
return Object.assign(node, {
|
|
807
|
+
_rangeStart: start,
|
|
808
|
+
_rangeEnd: end,
|
|
809
|
+
_parent: vParent,
|
|
810
|
+
_svg: svg,
|
|
811
|
+
_state: {
|
|
812
|
+
instance,
|
|
813
|
+
resolveToken: 0,
|
|
814
|
+
resolveController: undefined,
|
|
815
|
+
fallbackRoot: undefined,
|
|
816
|
+
resolved: true,
|
|
817
|
+
},
|
|
818
|
+
});
|
|
715
819
|
}
|
|
716
820
|
}
|
|
717
821
|
let start = document.createComment(` rmx:f:${randomFrameId()} `);
|
|
@@ -721,17 +825,11 @@ function insertFrame(node, domParent, frame, scheduler, styles, vParent, rootTar
|
|
|
721
825
|
: (dom) => domParent.appendChild(dom);
|
|
722
826
|
doInsert(start);
|
|
723
827
|
doInsert(end);
|
|
724
|
-
node._rangeStart = start;
|
|
725
|
-
node._rangeEnd = end;
|
|
726
|
-
node._parent = vParent;
|
|
727
828
|
let fallbackRoot = createRangeRoot([start, end], {
|
|
728
829
|
frame,
|
|
729
830
|
styleManager: styles,
|
|
730
831
|
});
|
|
731
|
-
fallbackRoot.render(node.props
|
|
732
|
-
node._frameFallbackRoot = fallbackRoot;
|
|
733
|
-
node._frameResolved = false;
|
|
734
|
-
node._frameResolveToken = 0;
|
|
832
|
+
fallbackRoot.render(node.props.fallback ?? null);
|
|
735
833
|
let instance = createFrame([start, end], {
|
|
736
834
|
name: getFrameName(node),
|
|
737
835
|
src: getFrameSrc(node),
|
|
@@ -740,57 +838,84 @@ function insertFrame(node, domParent, frame, scheduler, styles, vParent, rootTar
|
|
|
740
838
|
resolveFrame: runtime.resolveFrame,
|
|
741
839
|
pendingClientEntries: runtime.pendingClientEntries,
|
|
742
840
|
scheduler: runtime.scheduler,
|
|
743
|
-
|
|
841
|
+
styleManager: runtime.styleManager,
|
|
842
|
+
data: {},
|
|
744
843
|
moduleCache: runtime.moduleCache,
|
|
745
844
|
moduleLoads: runtime.moduleLoads,
|
|
746
845
|
frameInstances: runtime.frameInstances,
|
|
747
846
|
namedFrames: runtime.namedFrames,
|
|
748
847
|
});
|
|
749
|
-
node._frameInstance = instance;
|
|
750
848
|
runtime.frameInstances.set(start, instance);
|
|
751
|
-
|
|
752
|
-
|
|
849
|
+
let committed = Object.assign(node, {
|
|
850
|
+
_rangeStart: start,
|
|
851
|
+
_rangeEnd: end,
|
|
852
|
+
_parent: vParent,
|
|
853
|
+
_svg: svg,
|
|
854
|
+
_state: {
|
|
855
|
+
instance,
|
|
856
|
+
fallbackRoot,
|
|
857
|
+
resolved: false,
|
|
858
|
+
resolveToken: 0,
|
|
859
|
+
resolveController: undefined,
|
|
860
|
+
},
|
|
861
|
+
});
|
|
862
|
+
resolveClientFrame(committed, runtime);
|
|
863
|
+
return committed;
|
|
753
864
|
}
|
|
754
|
-
function resolveClientFrame(node, runtime) {
|
|
865
|
+
function resolveClientFrame(node, runtime, serverFrameReload) {
|
|
755
866
|
let frameSrc = getFrameSrc(node);
|
|
756
|
-
let
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
.
|
|
766
|
-
|
|
867
|
+
let state = node._state;
|
|
868
|
+
let instance = state.instance;
|
|
869
|
+
let token = state.resolveToken + 1;
|
|
870
|
+
state.resolveToken = token;
|
|
871
|
+
state.resolveController?.abort();
|
|
872
|
+
let reload = serverFrameReload
|
|
873
|
+
? instance.beginClientFrameReloadForAncestorReload(serverFrameReload.signal)
|
|
874
|
+
: undefined;
|
|
875
|
+
if (!reload) {
|
|
876
|
+
instance.cancelReload();
|
|
877
|
+
}
|
|
878
|
+
let resolveController = reload?.controller ?? new AbortController();
|
|
879
|
+
state.resolveController = resolveController;
|
|
880
|
+
Promise.resolve()
|
|
881
|
+
.then(() => runtime.resolveFrame(frameSrc, {
|
|
882
|
+
signal: resolveController.signal,
|
|
883
|
+
target: getFrameName(node),
|
|
884
|
+
}))
|
|
885
|
+
.then(async (resolution) => {
|
|
886
|
+
if (state.resolveToken !== token || resolveController.signal.aborted)
|
|
887
|
+
return;
|
|
888
|
+
let { content } = await unwrapFrameResolution(resolution);
|
|
889
|
+
if (state.resolveToken !== token || resolveController.signal.aborted)
|
|
767
890
|
return;
|
|
768
|
-
|
|
769
|
-
|
|
891
|
+
state.fallbackRoot?.dispose();
|
|
892
|
+
state.fallbackRoot = undefined;
|
|
770
893
|
let nextContent = asAbortableFrameContent(content, resolveController.signal);
|
|
771
894
|
await instance.render(nextContent, { signal: resolveController.signal });
|
|
772
|
-
if (
|
|
895
|
+
if (state.resolveToken !== token || resolveController.signal.aborted)
|
|
773
896
|
return;
|
|
774
|
-
|
|
897
|
+
state.resolved = true;
|
|
898
|
+
})
|
|
899
|
+
.catch((error) => {
|
|
900
|
+
if (reload && state.resolveToken === token && !resolveController.signal.aborted) {
|
|
901
|
+
runtime.errorTarget.dispatchEvent(createComponentErrorEvent(error));
|
|
902
|
+
}
|
|
775
903
|
})
|
|
776
|
-
.catch(() => { })
|
|
777
904
|
.finally(() => {
|
|
778
|
-
|
|
779
|
-
|
|
905
|
+
reload?.complete();
|
|
906
|
+
if (state.resolveController === resolveController) {
|
|
907
|
+
state.resolveController = undefined;
|
|
780
908
|
}
|
|
781
909
|
});
|
|
782
910
|
}
|
|
783
911
|
function disposeFrameResources(node) {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
frameInstance.dispose();
|
|
792
|
-
node._frameInstance = undefined;
|
|
793
|
-
}
|
|
912
|
+
let state = node._state;
|
|
913
|
+
state.resolveToken++;
|
|
914
|
+
state.resolveController?.abort();
|
|
915
|
+
state.resolveController = undefined;
|
|
916
|
+
state.fallbackRoot?.dispose();
|
|
917
|
+
state.fallbackRoot = undefined;
|
|
918
|
+
state.instance.dispose();
|
|
794
919
|
}
|
|
795
920
|
function asAbortableFrameContent(content, signal) {
|
|
796
921
|
if (!(content instanceof ReadableStream))
|
|
@@ -826,13 +951,13 @@ function createAbortableReadableStream(source, signal) {
|
|
|
826
951
|
removeAbortReadListener = () => signal.removeEventListener('abort', onAbortRead);
|
|
827
952
|
signal.addEventListener('abort', onAbortRead, { once: true });
|
|
828
953
|
});
|
|
829
|
-
let
|
|
954
|
+
let result = await Promise.race([reader.read(), abortRead]);
|
|
830
955
|
removeAbortReadListener?.();
|
|
831
|
-
if (done) {
|
|
956
|
+
if (result.done) {
|
|
832
957
|
controller.close();
|
|
833
958
|
return;
|
|
834
959
|
}
|
|
835
|
-
controller.enqueue(value);
|
|
960
|
+
controller.enqueue(result.value);
|
|
836
961
|
},
|
|
837
962
|
cancel(reason) {
|
|
838
963
|
signal.removeEventListener('abort', onAbort);
|
|
@@ -843,8 +968,6 @@ function createAbortableReadableStream(source, signal) {
|
|
|
843
968
|
function removeFrameDomRange(node, domParent) {
|
|
844
969
|
let start = node._rangeStart;
|
|
845
970
|
let end = node._rangeEnd;
|
|
846
|
-
if (!(start instanceof Comment) || !(end instanceof Comment))
|
|
847
|
-
return;
|
|
848
971
|
let cursor = start;
|
|
849
972
|
while (cursor) {
|
|
850
973
|
let nextSibling = cursor.nextSibling;
|
|
@@ -855,19 +978,16 @@ function removeFrameDomRange(node, domParent) {
|
|
|
855
978
|
break;
|
|
856
979
|
cursor = nextSibling;
|
|
857
980
|
}
|
|
858
|
-
node._rangeStart = undefined;
|
|
859
|
-
node._rangeEnd = undefined;
|
|
860
981
|
}
|
|
861
982
|
function getFrameRuntime(frame) {
|
|
862
|
-
|
|
983
|
+
let runtime = frame.$runtime;
|
|
984
|
+
return isFrameRuntime(runtime) ? runtime : undefined;
|
|
863
985
|
}
|
|
864
986
|
function getFrameSrc(node) {
|
|
865
|
-
|
|
866
|
-
invariant(typeof src === 'string' && src.length > 0, '<Frame /> requires a src prop');
|
|
867
|
-
return src;
|
|
987
|
+
return node.props.src;
|
|
868
988
|
}
|
|
869
989
|
function getFrameName(node) {
|
|
870
|
-
let name = node.props
|
|
990
|
+
let name = node.props.name;
|
|
871
991
|
return typeof name === 'string' && name.length > 0 ? name : undefined;
|
|
872
992
|
}
|
|
873
993
|
function randomFrameId() {
|
|
@@ -882,16 +1002,13 @@ function skipCommentsExceptFrameStart(cursor) {
|
|
|
882
1002
|
return cursor;
|
|
883
1003
|
}
|
|
884
1004
|
function isFrameStartComment(node) {
|
|
885
|
-
return node
|
|
1005
|
+
return isCommentNode(node) && node.data.trim().startsWith('rmx:f:');
|
|
886
1006
|
}
|
|
887
1007
|
function isFrameEndComment(node) {
|
|
888
|
-
return node
|
|
1008
|
+
return isCommentNode(node) && node.data.trim() === '/rmx:f';
|
|
889
1009
|
}
|
|
890
|
-
function
|
|
891
|
-
|
|
892
|
-
if (!text.startsWith('rmx:f:'))
|
|
893
|
-
return undefined;
|
|
894
|
-
return text.slice('rmx:f:'.length);
|
|
1010
|
+
function isCommentNode(node) {
|
|
1011
|
+
return node?.nodeType === Node.COMMENT_NODE;
|
|
895
1012
|
}
|
|
896
1013
|
function findFrameEndComment(start) {
|
|
897
1014
|
let depth = 1;
|
|
@@ -908,32 +1025,32 @@ function findFrameEndComment(start) {
|
|
|
908
1025
|
}
|
|
909
1026
|
return null;
|
|
910
1027
|
}
|
|
911
|
-
export function renderComponent(
|
|
912
|
-
|
|
913
|
-
|
|
1028
|
+
export function renderComponent(currContent, next, domParent, context, anchor, cursor) {
|
|
1029
|
+
let { scheduler } = context;
|
|
1030
|
+
let handle = next._handle;
|
|
1031
|
+
if (handle.isRemoved()) {
|
|
1032
|
+
invariant('_content' in next, 'Expected removed component to be committed');
|
|
1033
|
+
return next;
|
|
1034
|
+
}
|
|
914
1035
|
let [element, tasks] = handle.render(next.props);
|
|
915
|
-
let content = toVNode(element);
|
|
916
|
-
let
|
|
917
|
-
|
|
918
|
-
next._handle = handle;
|
|
919
|
-
next._parent = vParent;
|
|
920
|
-
let committed = next;
|
|
921
|
-
handle.setScheduleUpdate(() => {
|
|
922
|
-
scheduler.enqueue(committed, domParent);
|
|
923
|
-
});
|
|
1036
|
+
let content = diffVNodes(currContent, toVNode(element), domParent, next, context, anchor, cursor);
|
|
1037
|
+
let committed = commitComponentNode(next, content);
|
|
1038
|
+
handle.setScheduleUpdate(scheduler, committed, domParent);
|
|
924
1039
|
scheduler.enqueueTasks(tasks);
|
|
925
|
-
return
|
|
1040
|
+
return committed;
|
|
926
1041
|
}
|
|
927
|
-
function diffComponent(curr, next,
|
|
1042
|
+
function diffComponent(curr, next, domParent, vParent, context, svg, anchor, cursor) {
|
|
1043
|
+
let { frame } = context;
|
|
928
1044
|
if (curr === null) {
|
|
929
|
-
let componentId = vParent._pendingHydrationComponentId;
|
|
1045
|
+
let componentId = vParent.kind === 'root' ? vParent._pendingHydrationComponentId : undefined;
|
|
930
1046
|
if (componentId) {
|
|
931
|
-
vParent.
|
|
1047
|
+
if (vParent.kind === 'root')
|
|
1048
|
+
vParent._pendingHydrationComponentId = undefined;
|
|
932
1049
|
}
|
|
933
1050
|
else {
|
|
934
1051
|
componentId = `c${++idCounter}`;
|
|
935
1052
|
}
|
|
936
|
-
|
|
1053
|
+
let handle = createComponent({
|
|
937
1054
|
id: componentId,
|
|
938
1055
|
frame,
|
|
939
1056
|
type: next.type,
|
|
@@ -947,52 +1064,54 @@ function diffComponent(curr, next, frame, scheduler, styles, domParent, vParent,
|
|
|
947
1064
|
return runtime?.topFrame;
|
|
948
1065
|
},
|
|
949
1066
|
});
|
|
950
|
-
|
|
1067
|
+
let mounting = beginComponentNode(next, vParent, svg, handle, context);
|
|
1068
|
+
return renderComponent(null, mounting, domParent, context, anchor, cursor);
|
|
951
1069
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
return renderComponent(_handle, _content, next, domParent, frame, scheduler, styles, rootTarget, vParent, anchor, cursor);
|
|
1070
|
+
let mounting = beginComponentNode(next, vParent, svg, curr._handle, context);
|
|
1071
|
+
return renderComponent(curr._content, mounting, domParent, context, anchor, cursor);
|
|
955
1072
|
}
|
|
956
1073
|
// Cleanup without DOM removal - used for descendants when parent DOM node is removed
|
|
957
|
-
function cleanupDescendants(node,
|
|
1074
|
+
function cleanupDescendants(node, context) {
|
|
1075
|
+
let { scheduler } = context;
|
|
958
1076
|
if (isCommittedTextNode(node)) {
|
|
959
1077
|
return;
|
|
960
1078
|
}
|
|
961
1079
|
if (isCommittedHostNode(node)) {
|
|
962
|
-
|
|
963
|
-
|
|
1080
|
+
let children = node._children;
|
|
1081
|
+
for (let i = 0; i < children.length; i++) {
|
|
1082
|
+
cleanupDescendants(children[i], context);
|
|
964
1083
|
}
|
|
965
1084
|
teardownMixins(node._mixState);
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
if (node._controller)
|
|
969
|
-
node._controller.abort();
|
|
1085
|
+
abandonDirectEventListeners(node);
|
|
1086
|
+
abandonControlledReflection(node);
|
|
970
1087
|
return;
|
|
971
1088
|
}
|
|
972
1089
|
if (isFragmentNode(node)) {
|
|
973
|
-
|
|
974
|
-
|
|
1090
|
+
let children = node._children;
|
|
1091
|
+
for (let i = 0; i < children.length; i++) {
|
|
1092
|
+
cleanupDescendants(children[i], context);
|
|
975
1093
|
}
|
|
976
1094
|
return;
|
|
977
1095
|
}
|
|
978
1096
|
if (isCommittedComponentNode(node)) {
|
|
979
|
-
cleanupDescendants(node._content,
|
|
1097
|
+
cleanupDescendants(node._content, context);
|
|
980
1098
|
let tasks = node._handle.remove();
|
|
981
1099
|
scheduler.enqueueTasks(tasks);
|
|
982
1100
|
return;
|
|
983
1101
|
}
|
|
984
|
-
if (node.
|
|
1102
|
+
if (node.kind === 'frame') {
|
|
985
1103
|
disposeFrameResources(node);
|
|
986
1104
|
return;
|
|
987
1105
|
}
|
|
988
1106
|
}
|
|
989
|
-
export function remove(node, domParent,
|
|
1107
|
+
export function remove(node, domParent, context) {
|
|
1108
|
+
let { scheduler } = context;
|
|
990
1109
|
if (isCommittedTextNode(node)) {
|
|
991
1110
|
node._dom.parentNode?.removeChild(node._dom);
|
|
992
1111
|
return;
|
|
993
1112
|
}
|
|
994
1113
|
if (isCommittedHostNode(node)) {
|
|
995
|
-
if (node.
|
|
1114
|
+
if (node._persistence)
|
|
996
1115
|
return;
|
|
997
1116
|
let persistedRemoval = prepareMixinRemoval(node._mixState);
|
|
998
1117
|
if (persistedRemoval) {
|
|
@@ -1001,106 +1120,108 @@ export function remove(node, domParent, scheduler, styles) {
|
|
|
1001
1120
|
void persistedRemoval
|
|
1002
1121
|
.catch(() => { })
|
|
1003
1122
|
.finally(() => {
|
|
1004
|
-
if (!node.
|
|
1123
|
+
if (!node._persistence)
|
|
1005
1124
|
return;
|
|
1006
|
-
if (node.
|
|
1125
|
+
if (node._persistence.token !== token)
|
|
1007
1126
|
return;
|
|
1008
1127
|
unmarkNodePersistedByMixins(node);
|
|
1009
|
-
performHostNodeRemoval(node, domParent,
|
|
1128
|
+
performHostNodeRemoval(node, domParent, context);
|
|
1010
1129
|
});
|
|
1011
1130
|
return;
|
|
1012
1131
|
}
|
|
1013
|
-
performHostNodeRemoval(node, domParent,
|
|
1132
|
+
performHostNodeRemoval(node, domParent, context);
|
|
1014
1133
|
return;
|
|
1015
1134
|
}
|
|
1016
1135
|
if (isFragmentNode(node)) {
|
|
1017
|
-
|
|
1018
|
-
|
|
1136
|
+
let children = node._children;
|
|
1137
|
+
for (let i = 0; i < children.length; i++) {
|
|
1138
|
+
remove(children[i], domParent, context);
|
|
1019
1139
|
}
|
|
1020
1140
|
return;
|
|
1021
1141
|
}
|
|
1022
1142
|
if (isCommittedComponentNode(node)) {
|
|
1023
|
-
remove(node._content, domParent,
|
|
1143
|
+
remove(node._content, domParent, context);
|
|
1024
1144
|
let tasks = node._handle.remove();
|
|
1025
1145
|
scheduler.enqueueTasks(tasks);
|
|
1026
1146
|
return;
|
|
1027
1147
|
}
|
|
1028
|
-
if (node.
|
|
1148
|
+
if (node.kind === 'frame') {
|
|
1029
1149
|
disposeFrameResources(node);
|
|
1030
1150
|
removeFrameDomRange(node, domParent);
|
|
1031
1151
|
return;
|
|
1032
1152
|
}
|
|
1033
1153
|
}
|
|
1034
1154
|
// Actually remove a host node from DOM and clean up
|
|
1035
|
-
function performHostNodeRemoval(node, domParent,
|
|
1155
|
+
function performHostNodeRemoval(node, domParent, context) {
|
|
1156
|
+
let children = node._children;
|
|
1036
1157
|
if (isHeadHostNode(node)) {
|
|
1037
|
-
for (let
|
|
1038
|
-
remove(
|
|
1158
|
+
for (let i = 0; i < children.length; i++) {
|
|
1159
|
+
remove(children[i], node._dom, context);
|
|
1039
1160
|
}
|
|
1040
1161
|
}
|
|
1041
1162
|
else {
|
|
1042
1163
|
// Clean up all descendants first (before removing DOM subtree)
|
|
1043
|
-
for (let
|
|
1044
|
-
cleanupDescendants(
|
|
1164
|
+
for (let i = 0; i < children.length; i++) {
|
|
1165
|
+
cleanupDescendants(children[i], context);
|
|
1045
1166
|
}
|
|
1046
1167
|
}
|
|
1047
1168
|
teardownMixins(node._mixState);
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1169
|
+
// Never remove the real document.head node when reconciling a <head> vnode,
|
|
1170
|
+
// and since it stays alive, detach its listeners for real.
|
|
1171
|
+
if (isHeadHostNode(node)) {
|
|
1172
|
+
teardownDirectEventListeners(node);
|
|
1173
|
+
teardownControlledReflection(node);
|
|
1174
|
+
}
|
|
1175
|
+
else {
|
|
1176
|
+
abandonDirectEventListeners(node);
|
|
1177
|
+
abandonControlledReflection(node);
|
|
1052
1178
|
node._dom.parentNode?.removeChild(node._dom);
|
|
1053
1179
|
}
|
|
1054
|
-
if (node._controller)
|
|
1055
|
-
node._controller.abort();
|
|
1056
1180
|
}
|
|
1057
|
-
function diffChildren(curr, next, domParent,
|
|
1181
|
+
function diffChildren(curr, next, domParent, vParent, context, cursor, anchor) {
|
|
1058
1182
|
let hasKeys = hasKeyedChildren(next);
|
|
1183
|
+
let committed = next;
|
|
1059
1184
|
if (curr === null) {
|
|
1060
1185
|
if (hasKeys) {
|
|
1061
1186
|
warnDuplicateKeys(next);
|
|
1062
1187
|
}
|
|
1063
|
-
for (let
|
|
1064
|
-
|
|
1188
|
+
for (let i = 0; i < next.length; i++) {
|
|
1189
|
+
committed[i] = insert(next[i], domParent, vParent, context, anchor, cursor);
|
|
1065
1190
|
}
|
|
1066
|
-
|
|
1067
|
-
return cursor;
|
|
1191
|
+
return committed;
|
|
1068
1192
|
}
|
|
1069
1193
|
if (next.length === 0 &&
|
|
1070
1194
|
anchor === undefined &&
|
|
1071
1195
|
!parentUsesInnerHTML(vParent) &&
|
|
1072
1196
|
canBulkClearChildren(curr)) {
|
|
1073
|
-
for (let
|
|
1074
|
-
cleanupDescendants(
|
|
1197
|
+
for (let i = 0; i < curr.length; i++) {
|
|
1198
|
+
cleanupDescendants(curr[i], context);
|
|
1075
1199
|
}
|
|
1076
1200
|
domParent.textContent = '';
|
|
1077
|
-
|
|
1078
|
-
return;
|
|
1201
|
+
return EMPTY_COMMITTED_CHILDREN;
|
|
1079
1202
|
}
|
|
1080
1203
|
if (!hasKeys) {
|
|
1081
1204
|
for (let i = 0; i < next.length; i++) {
|
|
1082
1205
|
let currentNode = i < curr.length ? curr[i] : null;
|
|
1083
|
-
diffVNodes(currentNode, next[i], domParent,
|
|
1206
|
+
committed[i] = diffVNodes(currentNode, next[i], domParent, vParent, context, anchor, cursor);
|
|
1084
1207
|
}
|
|
1085
1208
|
if (curr.length > next.length) {
|
|
1086
1209
|
for (let i = next.length; i < curr.length; i++) {
|
|
1087
1210
|
let node = curr[i];
|
|
1088
1211
|
if (node)
|
|
1089
|
-
remove(node, domParent,
|
|
1212
|
+
remove(node, domParent, context);
|
|
1090
1213
|
}
|
|
1091
1214
|
}
|
|
1092
|
-
|
|
1093
|
-
return;
|
|
1215
|
+
return committed;
|
|
1094
1216
|
}
|
|
1095
|
-
patchKeyedChildren(curr, next, domParent,
|
|
1096
|
-
return;
|
|
1217
|
+
return patchKeyedChildren(curr, next, domParent, vParent, context, cursor, anchor);
|
|
1097
1218
|
}
|
|
1098
1219
|
function parentUsesInnerHTML(parent) {
|
|
1099
1220
|
return isHostNode(parent) && getHostProps(parent).innerHTML != null;
|
|
1100
1221
|
}
|
|
1101
1222
|
function canBulkClearChildren(children) {
|
|
1102
|
-
for (let
|
|
1103
|
-
if (!canBulkClearNode(
|
|
1223
|
+
for (let i = 0; i < children.length; i++) {
|
|
1224
|
+
if (!canBulkClearNode(children[i]))
|
|
1104
1225
|
return false;
|
|
1105
1226
|
}
|
|
1106
1227
|
return true;
|
|
@@ -1111,11 +1232,7 @@ function canBulkClearNode(node) {
|
|
|
1111
1232
|
if (isCommittedHostNode(node)) {
|
|
1112
1233
|
if (node._mixState)
|
|
1113
1234
|
return false;
|
|
1114
|
-
|
|
1115
|
-
if (!canBulkClearNode(child))
|
|
1116
|
-
return false;
|
|
1117
|
-
}
|
|
1118
|
-
return true;
|
|
1235
|
+
return canBulkClearChildren(node._children);
|
|
1119
1236
|
}
|
|
1120
1237
|
if (isFragmentNode(node)) {
|
|
1121
1238
|
return canBulkClearChildren(node._children);
|
|
@@ -1126,8 +1243,8 @@ function canBulkClearNode(node) {
|
|
|
1126
1243
|
return false;
|
|
1127
1244
|
}
|
|
1128
1245
|
function hasKeyedChildren(children) {
|
|
1129
|
-
for (let
|
|
1130
|
-
if (
|
|
1246
|
+
for (let i = 0; i < children.length; i++) {
|
|
1247
|
+
if (children[i].key != null)
|
|
1131
1248
|
return true;
|
|
1132
1249
|
}
|
|
1133
1250
|
return false;
|
|
@@ -1151,11 +1268,11 @@ function warnDuplicateKeys(children) {
|
|
|
1151
1268
|
}
|
|
1152
1269
|
}
|
|
1153
1270
|
if (duplicateKeys?.size) {
|
|
1154
|
-
let quotedKeys = Array.from(duplicateKeys, (key) => `"${key}"`);
|
|
1271
|
+
let quotedKeys = Array.from(duplicateKeys, (key) => `"${String(key)}"`);
|
|
1155
1272
|
console.warn(`Duplicate keys detected in siblings: ${quotedKeys.join(', ')}. Keys should be unique.`);
|
|
1156
1273
|
}
|
|
1157
1274
|
}
|
|
1158
|
-
function patchKeyedChildren(curr, next, domParent,
|
|
1275
|
+
function patchKeyedChildren(curr, next, domParent, vParent, context, cursor, anchor) {
|
|
1159
1276
|
let matches = matchKeyedChildrenInOrder(curr, next) ??
|
|
1160
1277
|
matchKeyedChildrenAfterSingleRemoval(curr, next) ??
|
|
1161
1278
|
matchKeyedChildrenAfterPairSwap(curr, next);
|
|
@@ -1163,34 +1280,36 @@ function patchKeyedChildren(curr, next, domParent, frame, scheduler, styles, vPa
|
|
|
1163
1280
|
warnDuplicateKeys(next);
|
|
1164
1281
|
matches = matchKeyedChildren(curr, next);
|
|
1165
1282
|
}
|
|
1283
|
+
let committed = next;
|
|
1166
1284
|
let matchAnalysis = analyzeKeyedChildMatches(curr.length, matches);
|
|
1167
1285
|
if (matchAnalysis.hasRemovals) {
|
|
1168
1286
|
let usedOldIndexes = new Uint8Array(curr.length);
|
|
1169
|
-
for (let
|
|
1170
|
-
|
|
1171
|
-
|
|
1287
|
+
for (let index = 0; index < matches.length; index++) {
|
|
1288
|
+
let oldIndex = matches[index];
|
|
1289
|
+
if (oldIndex >= 0) {
|
|
1290
|
+
usedOldIndexes[oldIndex] = 1;
|
|
1172
1291
|
}
|
|
1173
1292
|
}
|
|
1174
1293
|
for (let oldIndex = 0; oldIndex < curr.length; oldIndex++) {
|
|
1175
1294
|
if (usedOldIndexes[oldIndex] === 0) {
|
|
1176
|
-
remove(curr[oldIndex], domParent,
|
|
1295
|
+
remove(curr[oldIndex], domParent, context);
|
|
1177
1296
|
}
|
|
1178
1297
|
}
|
|
1179
1298
|
}
|
|
1180
|
-
vParent._children = next;
|
|
1181
1299
|
for (let index = 0; index < next.length; index++) {
|
|
1182
|
-
let
|
|
1183
|
-
let oldNode =
|
|
1184
|
-
diffVNodes(oldNode, next[index], domParent,
|
|
1300
|
+
let oldIndex = matches[index];
|
|
1301
|
+
let oldNode = oldIndex >= 0 ? curr[oldIndex] : null;
|
|
1302
|
+
committed[index] = diffVNodes(oldNode, next[index], domParent, vParent, context, anchor, cursor);
|
|
1185
1303
|
}
|
|
1304
|
+
let committedChildren = committed;
|
|
1186
1305
|
if (matchAnalysis.canSkipPlacement) {
|
|
1187
|
-
return;
|
|
1306
|
+
return committedChildren;
|
|
1188
1307
|
}
|
|
1189
1308
|
let stableIndexes = lisMatches(matches);
|
|
1190
1309
|
let stableCursor = stableIndexes.length - 1;
|
|
1191
1310
|
let placementAnchor = anchor ?? null;
|
|
1192
1311
|
for (let index = next.length - 1; index >= 0; index--) {
|
|
1193
|
-
let nextNode =
|
|
1312
|
+
let nextNode = committedChildren[index];
|
|
1194
1313
|
let isStable = stableIndexes[stableCursor] === index;
|
|
1195
1314
|
if (isStable) {
|
|
1196
1315
|
stableCursor--;
|
|
@@ -1200,7 +1319,11 @@ function patchKeyedChildren(curr, next, domParent, frame, scheduler, styles, vPa
|
|
|
1200
1319
|
}
|
|
1201
1320
|
placementAnchor = findFirstDomAnchor(nextNode) ?? placementAnchor;
|
|
1202
1321
|
}
|
|
1322
|
+
return committedChildren;
|
|
1203
1323
|
}
|
|
1324
|
+
// Keyed child matches are arrays of old indexes (-1 = no match / new node),
|
|
1325
|
+
// parallel to `next`. Plain numbers instead of wrapper objects keep large
|
|
1326
|
+
// keyed diffs (1000-row tables) allocation-free.
|
|
1204
1327
|
function matchKeyedChildren(curr, next) {
|
|
1205
1328
|
let oldKeyMap = new Map();
|
|
1206
1329
|
let usedOldIndexes = new Set();
|
|
@@ -1210,7 +1333,9 @@ function matchKeyedChildren(curr, next) {
|
|
|
1210
1333
|
if (key != null)
|
|
1211
1334
|
oldKeyMap.set(key, index);
|
|
1212
1335
|
}
|
|
1213
|
-
|
|
1336
|
+
let matches = [];
|
|
1337
|
+
for (let nextIndex = 0; nextIndex < next.length; nextIndex++) {
|
|
1338
|
+
let nextNode = next[nextIndex];
|
|
1214
1339
|
let oldIndex = -1;
|
|
1215
1340
|
if (nextNode.key != null) {
|
|
1216
1341
|
let keyedOldIndex = oldKeyMap.get(nextNode.key);
|
|
@@ -1234,8 +1359,9 @@ function matchKeyedChildren(curr, next) {
|
|
|
1234
1359
|
}
|
|
1235
1360
|
if (oldIndex >= 0)
|
|
1236
1361
|
usedOldIndexes.add(oldIndex);
|
|
1237
|
-
|
|
1238
|
-
}
|
|
1362
|
+
matches.push(oldIndex);
|
|
1363
|
+
}
|
|
1364
|
+
return matches;
|
|
1239
1365
|
}
|
|
1240
1366
|
function matchKeyedChildrenInOrder(curr, next) {
|
|
1241
1367
|
let length = Math.min(curr.length, next.length);
|
|
@@ -1248,12 +1374,12 @@ function matchKeyedChildrenInOrder(curr, next) {
|
|
|
1248
1374
|
if (oldNode.key !== nextNode.key || oldNode.type !== nextNode.type) {
|
|
1249
1375
|
return null;
|
|
1250
1376
|
}
|
|
1251
|
-
matches.push(
|
|
1377
|
+
matches.push(index);
|
|
1252
1378
|
}
|
|
1253
1379
|
for (let index = length; index < next.length; index++) {
|
|
1254
1380
|
if (next[index].key == null)
|
|
1255
1381
|
return null;
|
|
1256
|
-
matches.push(
|
|
1382
|
+
matches.push(-1);
|
|
1257
1383
|
}
|
|
1258
1384
|
return matches;
|
|
1259
1385
|
}
|
|
@@ -1269,7 +1395,7 @@ function matchKeyedChildrenAfterSingleRemoval(curr, next) {
|
|
|
1269
1395
|
return null;
|
|
1270
1396
|
let oldNode = curr[oldIndex];
|
|
1271
1397
|
if (oldNode.key === nextNode.key && oldNode.type === nextNode.type) {
|
|
1272
|
-
matches.push(
|
|
1398
|
+
matches.push(oldIndex);
|
|
1273
1399
|
oldIndex++;
|
|
1274
1400
|
continue;
|
|
1275
1401
|
}
|
|
@@ -1281,7 +1407,7 @@ function matchKeyedChildrenAfterSingleRemoval(curr, next) {
|
|
|
1281
1407
|
if (oldNode.key !== nextNode.key || oldNode.type !== nextNode.type) {
|
|
1282
1408
|
return null;
|
|
1283
1409
|
}
|
|
1284
|
-
matches.push(
|
|
1410
|
+
matches.push(oldIndex);
|
|
1285
1411
|
oldIndex++;
|
|
1286
1412
|
}
|
|
1287
1413
|
return matches;
|
|
@@ -1298,7 +1424,7 @@ function matchKeyedChildrenAfterPairSwap(curr, next) {
|
|
|
1298
1424
|
return null;
|
|
1299
1425
|
let oldNode = curr[index];
|
|
1300
1426
|
if (oldNode.key === nextNode.key && oldNode.type === nextNode.type) {
|
|
1301
|
-
matches.push(
|
|
1427
|
+
matches.push(index);
|
|
1302
1428
|
continue;
|
|
1303
1429
|
}
|
|
1304
1430
|
if (firstMismatch === -1) {
|
|
@@ -1310,7 +1436,7 @@ function matchKeyedChildrenAfterPairSwap(curr, next) {
|
|
|
1310
1436
|
else {
|
|
1311
1437
|
return null;
|
|
1312
1438
|
}
|
|
1313
|
-
matches.push(
|
|
1439
|
+
matches.push(-1);
|
|
1314
1440
|
}
|
|
1315
1441
|
if (firstMismatch === -1)
|
|
1316
1442
|
return matches;
|
|
@@ -1326,8 +1452,8 @@ function matchKeyedChildrenAfterPairSwap(curr, next) {
|
|
|
1326
1452
|
secondOldNode.type !== firstNextNode.type) {
|
|
1327
1453
|
return null;
|
|
1328
1454
|
}
|
|
1329
|
-
matches[firstMismatch] =
|
|
1330
|
-
matches[secondMismatch] =
|
|
1455
|
+
matches[firstMismatch] = secondMismatch;
|
|
1456
|
+
matches[secondMismatch] = firstMismatch;
|
|
1331
1457
|
return matches;
|
|
1332
1458
|
}
|
|
1333
1459
|
function analyzeKeyedChildMatches(currentLength, matches) {
|
|
@@ -1335,16 +1461,17 @@ function analyzeKeyedChildMatches(currentLength, matches) {
|
|
|
1335
1461
|
let canSkipPlacement = true;
|
|
1336
1462
|
let lastOldIndex = -1;
|
|
1337
1463
|
let sawNewNode = false;
|
|
1338
|
-
for (let
|
|
1339
|
-
|
|
1464
|
+
for (let index = 0; index < matches.length; index++) {
|
|
1465
|
+
let oldIndex = matches[index];
|
|
1466
|
+
if (oldIndex < 0) {
|
|
1340
1467
|
hasRemovals = true;
|
|
1341
1468
|
sawNewNode = true;
|
|
1342
1469
|
continue;
|
|
1343
1470
|
}
|
|
1344
|
-
if (sawNewNode ||
|
|
1471
|
+
if (sawNewNode || oldIndex < lastOldIndex) {
|
|
1345
1472
|
canSkipPlacement = false;
|
|
1346
1473
|
}
|
|
1347
|
-
lastOldIndex =
|
|
1474
|
+
lastOldIndex = oldIndex;
|
|
1348
1475
|
}
|
|
1349
1476
|
return { hasRemovals, canSkipPlacement };
|
|
1350
1477
|
}
|
|
@@ -1352,14 +1479,14 @@ function lisMatches(matches) {
|
|
|
1352
1479
|
let predecessors = Array.from({ length: matches.length });
|
|
1353
1480
|
let tails = [];
|
|
1354
1481
|
for (let index = 0; index < matches.length; index++) {
|
|
1355
|
-
let value = matches[index]
|
|
1482
|
+
let value = matches[index] + 1;
|
|
1356
1483
|
if (value === 0)
|
|
1357
1484
|
continue;
|
|
1358
1485
|
let low = 0;
|
|
1359
1486
|
let high = tails.length;
|
|
1360
1487
|
while (low < high) {
|
|
1361
1488
|
let middle = (low + high) >> 1;
|
|
1362
|
-
if (matches[tails[middle]]
|
|
1489
|
+
if (matches[tails[middle]] + 1 < value) {
|
|
1363
1490
|
low = middle + 1;
|
|
1364
1491
|
}
|
|
1365
1492
|
else {
|
|
@@ -1398,11 +1525,12 @@ export function findFirstDomAnchor(node) {
|
|
|
1398
1525
|
return node._dom;
|
|
1399
1526
|
if (isCommittedComponentNode(node))
|
|
1400
1527
|
return findFirstDomAnchor(node._content);
|
|
1401
|
-
if (node.
|
|
1402
|
-
return node._rangeStart
|
|
1528
|
+
if (node.kind === 'frame')
|
|
1529
|
+
return node._rangeStart;
|
|
1403
1530
|
if (isFragmentNode(node)) {
|
|
1404
|
-
|
|
1405
|
-
|
|
1531
|
+
let children = node._children;
|
|
1532
|
+
for (let i = 0; i < children.length; i++) {
|
|
1533
|
+
let dom = findFirstDomAnchor(children[i]);
|
|
1406
1534
|
if (dom)
|
|
1407
1535
|
return dom;
|
|
1408
1536
|
}
|
|
@@ -1418,8 +1546,8 @@ export function findLastDomAnchor(node) {
|
|
|
1418
1546
|
return node._dom;
|
|
1419
1547
|
if (isCommittedComponentNode(node))
|
|
1420
1548
|
return findLastDomAnchor(node._content);
|
|
1421
|
-
if (node.
|
|
1422
|
-
return node._rangeEnd
|
|
1549
|
+
if (node.kind === 'frame')
|
|
1550
|
+
return node._rangeEnd;
|
|
1423
1551
|
if (isFragmentNode(node)) {
|
|
1424
1552
|
for (let i = node._children.length - 1; i >= 0; i--) {
|
|
1425
1553
|
let dom = findLastDomAnchor(node._children[i]);
|
|
@@ -1458,6 +1586,8 @@ function shouldDispatchInlineMixinLifecycle(node) {
|
|
|
1458
1586
|
if (!parents?.length)
|
|
1459
1587
|
return true;
|
|
1460
1588
|
for (let parent of parents) {
|
|
1589
|
+
if (!(parent instanceof Node))
|
|
1590
|
+
continue;
|
|
1461
1591
|
let parentNode = parent;
|
|
1462
1592
|
if (parentNode === node)
|
|
1463
1593
|
return false;
|
|
@@ -1468,11 +1598,16 @@ function shouldDispatchInlineMixinLifecycle(node) {
|
|
|
1468
1598
|
}
|
|
1469
1599
|
export function findNextSiblingDomAnchor(curr) {
|
|
1470
1600
|
let vParent = curr._parent;
|
|
1471
|
-
if (
|
|
1472
|
-
return null;
|
|
1473
|
-
let children = vParent._children;
|
|
1474
|
-
if (children.length === 0)
|
|
1601
|
+
if (vParent.kind === 'component')
|
|
1475
1602
|
return findNextSiblingDomAnchor(vParent);
|
|
1603
|
+
let children = vParent._children;
|
|
1604
|
+
if (children.length === 0) {
|
|
1605
|
+
if (vParent.kind === 'root')
|
|
1606
|
+
return vParent._rangeEnd ?? null;
|
|
1607
|
+
if (vParent.kind === 'fragment')
|
|
1608
|
+
return findNextSiblingDomAnchor(vParent);
|
|
1609
|
+
return null;
|
|
1610
|
+
}
|
|
1476
1611
|
let idx = children.indexOf(curr);
|
|
1477
1612
|
if (idx === -1)
|
|
1478
1613
|
return null;
|
|
@@ -1484,34 +1619,33 @@ export function findNextSiblingDomAnchor(curr) {
|
|
|
1484
1619
|
if (isFragmentNode(vParent)) {
|
|
1485
1620
|
return findNextSiblingDomAnchor(vParent);
|
|
1486
1621
|
}
|
|
1487
|
-
return null;
|
|
1622
|
+
return vParent.kind === 'root' ? (vParent._rangeEnd ?? null) : null;
|
|
1488
1623
|
}
|
|
1489
|
-
function reclaimPersistedMixinNode(persistedNode, newNode,
|
|
1624
|
+
function reclaimPersistedMixinNode(persistedNode, newNode, vParent, context) {
|
|
1625
|
+
let { frame, scheduler, styles } = context;
|
|
1490
1626
|
cancelPendingMixinRemoval(persistedNode._mixState);
|
|
1491
1627
|
unmarkNodePersistedByMixins(persistedNode);
|
|
1492
|
-
newNode._dom = persistedNode._dom;
|
|
1493
|
-
newNode._parent = vParent;
|
|
1494
|
-
newNode._controller = persistedNode._controller;
|
|
1495
|
-
newNode._mixState = persistedNode._mixState;
|
|
1496
|
-
newNode._directEventState = persistedNode._directEventState;
|
|
1497
|
-
newNode._controlledState = persistedNode._controlledState;
|
|
1498
1628
|
let prevProps = getHostProps(persistedNode);
|
|
1499
|
-
let
|
|
1629
|
+
let childInputs = newNode._children;
|
|
1630
|
+
let resolved = resolveNodeMixProps(newNode, vParent, frame, scheduler, persistedNode._mixState);
|
|
1631
|
+
let nextProps = resolved.props;
|
|
1632
|
+
let committed = commitHostNode(newNode, vParent, getSvgContext(vParent, newNode), persistedNode._dom, resolved);
|
|
1633
|
+
committed._directEventState = persistedNode._directEventState;
|
|
1634
|
+
committed._controlledState = persistedNode._controlledState;
|
|
1500
1635
|
if (shouldDispatchInlineMixinLifecycle(persistedNode._dom)) {
|
|
1501
|
-
dispatchMixinBeforeUpdate(
|
|
1636
|
+
dispatchMixinBeforeUpdate(committed._mixState);
|
|
1502
1637
|
}
|
|
1503
1638
|
patchHostProps(prevProps, nextProps, persistedNode._dom);
|
|
1504
|
-
syncDirectEventListeners(
|
|
1505
|
-
ensureControlledReflection(
|
|
1506
|
-
syncControlledReflection(
|
|
1507
|
-
diffChildren(persistedNode._children,
|
|
1508
|
-
if (
|
|
1509
|
-
bindNodeMixRuntime(
|
|
1639
|
+
syncDirectEventListeners(committed);
|
|
1640
|
+
ensureControlledReflection(committed, scheduler);
|
|
1641
|
+
syncControlledReflection(committed, nextProps);
|
|
1642
|
+
committed._children = diffChildren(persistedNode._children, childInputs, persistedNode._dom, committed, context);
|
|
1643
|
+
if (committed._mixState) {
|
|
1644
|
+
bindNodeMixRuntime(committed, frame, scheduler, styles, true);
|
|
1510
1645
|
}
|
|
1511
1646
|
if (shouldDispatchInlineMixinLifecycle(persistedNode._dom)) {
|
|
1512
|
-
scheduler.enqueueCommitPhase([
|
|
1513
|
-
() => dispatchMixinCommit(newNode._mixState),
|
|
1514
|
-
]);
|
|
1647
|
+
scheduler.enqueueCommitPhase([() => dispatchMixinCommit(committed._mixState)]);
|
|
1515
1648
|
}
|
|
1649
|
+
return committed;
|
|
1516
1650
|
}
|
|
1517
1651
|
//# sourceMappingURL=reconcile.js.map
|