From 4ed312d296d6431188a46188a8572b3f8ff671b3 Mon Sep 17 00:00:00 2001 From: Kael Date: Tue, 7 Jun 2022 19:10:48 +1000 Subject: [PATCH 1/6] fix(groups): use suspense to delay rendering of group items --- packages/vuetify/src/components/VBtn/VBtn.tsx | 10 +++++++--- .../src/components/VBtnToggle/VBtnToggle.tsx | 19 ++++++++++++------- packages/vuetify/src/composables/group.ts | 8 +++++++- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/packages/vuetify/src/components/VBtn/VBtn.tsx b/packages/vuetify/src/components/VBtn/VBtn.tsx index dba34115b51..6fc6754c445 100644 --- a/packages/vuetify/src/components/VBtn/VBtn.tsx +++ b/packages/vuetify/src/components/VBtn/VBtn.tsx @@ -27,7 +27,7 @@ import { Ripple } from '@/directives/ripple' // Utilities import { computed } from 'vue' -import { defineComponent } from '@/util' +import { defineComponent, useRender } from '@/util' // Types import type { PropType } from 'vue' @@ -91,7 +91,7 @@ export const VBtn = defineComponent({ useSelectLink(link, group?.select) - return () => { + useRender(() => { const Tag = (link.isLink.value) ? 'a' : props.tag const hasColor = !group || group.isSelected.value @@ -171,7 +171,11 @@ export const VBtn = defineComponent({ ) } ) - } + }) + + const expose = {} + + return group ? group.isReady.then(() => expose) : expose }, }) diff --git a/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx b/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx index 2314bc3fdc3..a0d3800c008 100644 --- a/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx +++ b/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx @@ -2,6 +2,7 @@ import './VBtnToggle.sass' // Components +import { Suspense } from 'vue' import { VBtnGroup } from '@/components/VBtnGroup' // Composables @@ -38,13 +39,17 @@ export const VBtnToggle = genericComponent() => { useRender(() => ( - { slots.default?.({ - isSelected, - next, - prev, - select, - selected, - } as DefaultBtnToggleSlot) } + + <> + { slots.default?.({ + isSelected, + next, + prev, + select, + selected, + } as DefaultBtnToggleSlot) } + + )) diff --git a/packages/vuetify/src/composables/group.ts b/packages/vuetify/src/composables/group.ts index 73127173b2c..572370268c7 100644 --- a/packages/vuetify/src/composables/group.ts +++ b/packages/vuetify/src/composables/group.ts @@ -2,7 +2,7 @@ import { useProxiedModel } from './proxiedModel' // Utilities -import { computed, inject, onBeforeUnmount, onMounted, provide, reactive, toRef, watch } from 'vue' +import { computed, inject, nextTick, onBeforeUnmount, onMounted, provide, reactive, toRef, watch } from 'vue' import { consoleWarn, deepEqual, findChildrenWithProvide, getCurrentInstance, getUid, propsFactory, wrapInArray } from '@/util' // Types @@ -45,6 +45,7 @@ export interface GroupProvide { export interface GroupItemProvide { id: number isSelected: Ref + isReady: Promise toggle: () => void select: (value: boolean) => void selectedClass: Ref<(string | undefined)[] | false> @@ -132,9 +133,14 @@ export function useGroupItem ( vm.emit('group:selected', { value }) }) + let resolve: (val?: any) => void + const isReady = new Promise(_resolve => resolve = _resolve) + nextTick(() => resolve()) + return { id, isSelected, + isReady, toggle: () => group.select(id, !isSelected.value), select: (value: boolean) => group.select(id, value), selectedClass, From 016b64966e9eab00dc2cc014b042354392bfbef6 Mon Sep 17 00:00:00 2001 From: Kael Date: Thu, 9 Jun 2022 01:33:23 +1000 Subject: [PATCH 2/6] everything else --- package.json | 4 +- packages/api-generator/package.json | 2 +- packages/docs/package.json | 4 +- packages/vuetify/package.json | 2 +- .../VBottomNavigation/VBottomNavigation.tsx | 14 ++- .../VBottomNavigation.spec.tsx.snap | 2 + .../vuetify/src/components/VChip/VChip.tsx | 8 +- .../src/components/VChipGroup/VChipGroup.tsx | 20 +-- .../VExpansionPanel/VExpansionPanel.tsx | 2 +- .../VExpansionPanel/VExpansionPanels.tsx | 11 +- .../src/components/VItemGroup/VItem.tsx | 11 +- .../src/components/VItemGroup/VItemGroup.tsx | 19 +-- .../VItemGroup/__tests__/VItemGroup.spec.ts | 12 +- .../components/VSlideGroup/VSlideGroup.tsx | 12 +- .../VSlideGroup/VSlideGroupItem.tsx | 8 +- .../src/components/VWindow/VWindow.tsx | 8 +- .../src/components/VWindow/VWindowItem.tsx | 8 +- packages/vuetify/src/composables/group.ts | 4 +- packages/vuetify/src/util/useRender.ts | 4 +- patches/@vue+runtime-core+3.2.37.patch | 22 ++++ yarn.lock | 117 +++++++++++++++--- 21 files changed, 220 insertions(+), 74 deletions(-) create mode 100644 patches/@vue+runtime-core+3.2.37.patch diff --git a/package.json b/package.json index e4cbf830b25..aa97b7d0805 100755 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@mdi/svg": "6.2.95", "@typescript-eslint/eslint-plugin": "^5.26.0", "@typescript-eslint/parser": "^5.26.0", - "@vue/compiler-sfc": "^3.2.36", + "@vue/compiler-sfc": "^3.2.37", "babel-eslint": "^10.1.0", "babel-jest": "^26.6.3", "conventional-changelog-cli": "^2.2.2", @@ -72,7 +72,7 @@ "shelljs": "^0.8.5", "typescript": "^4.7.2", "vite-plugin-inspect": "^0.4.3", - "vue": "^3.2.36", + "vue": "^3.2.37", "vue-analytics": "^5.16.1", "vue-router": "^4.0.15" } diff --git a/packages/api-generator/package.json b/packages/api-generator/package.json index 57c74987c4c..a8302add69c 100755 --- a/packages/api-generator/package.json +++ b/packages/api-generator/package.json @@ -16,7 +16,7 @@ "dependencies": { "deepmerge": "^4.0.0", "rimraf": "^3.0.2", - "vue": "^3.2.36", + "vue": "^3.2.37", "vuetify": "^3.0.0-beta.3" }, "devDependencies": { diff --git a/packages/docs/package.json b/packages/docs/package.json index 5a42e57db90..2aea624e0a6 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -27,7 +27,7 @@ "prism-theme-vars": "^0.2.3", "prismjs": "^1.28.0", "roboto-fontface": "^0.10.0", - "vue": "^3.2.36", + "vue": "^3.2.37", "vue-i18n": "^9.2.0-beta.35", "vue-prism-component": "^2.0.0", "vuetify": "^3.0.0-beta.3" @@ -39,7 +39,7 @@ "@types/prismjs": "^1.26.0", "@types/rimraf": "^3.0.2", "@vitejs/plugin-vue": "^2.3.3", - "@vue/compiler-sfc": "^3.2.36", + "@vue/compiler-sfc": "^3.2.37", "@vuetify/vite-ssg": "^0.19.0", "ajv": "^8.11.0", "front-matter": "^4.0.2", diff --git a/packages/vuetify/package.json b/packages/vuetify/package.json index d6eec4ffc17..bea5b021e0d 100755 --- a/packages/vuetify/package.json +++ b/packages/vuetify/package.json @@ -155,7 +155,7 @@ }, "peerDependencies": { "@formatjs/intl": "^1.0.0 || ^2.0.0", - "vue": "^3.2.36", + "vue": "^3.2.37", "vue-i18n": "^9.0.0" }, "peerDependenciesMeta": { diff --git a/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx b/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx index 213b2f3d215..270855dd089 100644 --- a/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx +++ b/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx @@ -15,7 +15,7 @@ import { useBackgroundColor } from '@/composables/color' import { useProxiedModel } from '@/composables/proxiedModel' // Utilities -import { computed, toRef } from 'vue' +import { computed, Suspense, toRef } from 'vue' import { convertToUnit, defineComponent } from '@/util' // Types @@ -114,11 +114,13 @@ export const VBottomNavigation = defineComponent({ }, ]} > - { slots.default && ( -
- { slots.default() } -
- ) } +
+ + <> + { slots.default?.() } + + +
) } diff --git a/packages/vuetify/src/components/VBottomNavigation/__tests__/__snapshots__/VBottomNavigation.spec.tsx.snap b/packages/vuetify/src/components/VBottomNavigation/__tests__/__snapshots__/VBottomNavigation.spec.tsx.snap index 9530ad9105b..03f0f925882 100644 --- a/packages/vuetify/src/components/VBottomNavigation/__tests__/__snapshots__/VBottomNavigation.spec.tsx.snap +++ b/packages/vuetify/src/components/VBottomNavigation/__tests__/__snapshots__/VBottomNavigation.spec.tsx.snap @@ -16,5 +16,7 @@ exports[`VBottomNavigation should not render content with no default slot and ma
+
+
`; diff --git a/packages/vuetify/src/components/VChip/VChip.tsx b/packages/vuetify/src/components/VChip/VChip.tsx index 65ce6da736b..7cf3fb8a35d 100644 --- a/packages/vuetify/src/components/VChip/VChip.tsx +++ b/packages/vuetify/src/components/VChip/VChip.tsx @@ -25,7 +25,7 @@ import { IconValue } from '@/composables/icons' import { Ripple } from '@/directives/ripple' // Utilities -import { defineComponent } from '@/util' +import { defineComponent, useRender } from '@/util' export const VChip = defineComponent({ name: 'VChip', @@ -103,7 +103,7 @@ export const VChip = defineComponent({ emit('click:close', e) } - return () => { + useRender(() => { const Tag = (link.isLink.value) ? 'a' : props.tag const hasAppend = !!(slots.append || props.appendIcon || props.appendAvatar) const hasClose = !!(slots.close || props.closable) @@ -215,7 +215,9 @@ export const VChip = defineComponent({ ) } ) - } + }) + + return group ? group.isReady : undefined }, }) diff --git a/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx b/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx index 9cd9bf4583c..d926820f9bb 100644 --- a/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx +++ b/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx @@ -9,8 +9,8 @@ import { makeVariantProps } from '@/composables/variant' import { provideDefaults } from '@/composables/defaults' // Utilities +import { Suspense, toRef } from 'vue' import { deepEqual, defineComponent } from '@/util' -import { toRef } from 'vue' // Types import type { PropType } from 'vue' @@ -60,13 +60,17 @@ export const VChipGroup = defineComponent({ themeClasses.value, ]} > - { slots.default?.({ - isSelected, - select, - next, - prev, - selected: selected.value, - }) } + + <> + { slots.default?.({ + isSelected, + select, + next, + prev, + selected: selected.value, + }) } + + ) }, diff --git a/packages/vuetify/src/components/VExpansionPanel/VExpansionPanel.tsx b/packages/vuetify/src/components/VExpansionPanel/VExpansionPanel.tsx index 2f008a51ae3..16ac578a7b8 100644 --- a/packages/vuetify/src/components/VExpansionPanel/VExpansionPanel.tsx +++ b/packages/vuetify/src/components/VExpansionPanel/VExpansionPanel.tsx @@ -107,7 +107,7 @@ export const VExpansionPanel = defineComponent({ ) }) - return {} + return groupItem.isReady }, }) diff --git a/packages/vuetify/src/components/VExpansionPanel/VExpansionPanels.tsx b/packages/vuetify/src/components/VExpansionPanel/VExpansionPanels.tsx index 6a2a45a8066..90b3acbd3d2 100644 --- a/packages/vuetify/src/components/VExpansionPanel/VExpansionPanels.tsx +++ b/packages/vuetify/src/components/VExpansionPanel/VExpansionPanels.tsx @@ -8,7 +8,7 @@ import { makeThemeProps, provideTheme } from '@/composables/theme' import { provideDefaults } from '@/composables/defaults' // Utilities -import { computed, toRef } from 'vue' +import { computed, Suspense, toRef } from 'vue' import { defineComponent, useRender } from '@/util' // Types @@ -65,8 +65,13 @@ export const VExpansionPanels = defineComponent({ themeClasses.value, variantClass.value, ]} - v-slots={ slots } - /> + > + + <> + { slots.default?.() } + + + )) return {} diff --git a/packages/vuetify/src/components/VItemGroup/VItem.tsx b/packages/vuetify/src/components/VItemGroup/VItem.tsx index 2ff7544217d..c85b64e0016 100644 --- a/packages/vuetify/src/components/VItemGroup/VItem.tsx +++ b/packages/vuetify/src/components/VItemGroup/VItem.tsx @@ -3,7 +3,7 @@ import { makeGroupItemProps, useGroupItem } from '@/composables/group' import { VItemGroupSymbol } from './VItemGroup' // Utilities -import { genericComponent } from '@/util' +import { genericComponent, useRender } from '@/util' // Types import type { MakeSlots } from '@/util' @@ -19,15 +19,18 @@ export const VItem = genericComponent { props: makeGroupItemProps(), setup (props, { slots }) { - const { isSelected, select, toggle, selectedClass, value, disabled } = useGroupItem(props, VItemGroupSymbol) - return () => slots.default?.({ + const { isSelected, isReady, select, toggle, selectedClass, value, disabled } = useGroupItem(props, VItemGroupSymbol) + + useRender(() => slots.default?.({ isSelected: isSelected.value, selectedClass: selectedClass.value, select, toggle, value: value.value, disabled: disabled.value, - }) + })) + + return isReady }, }) diff --git a/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx b/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx index f541df2aef3..66bdb6af6d9 100644 --- a/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx +++ b/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx @@ -7,6 +7,7 @@ import { makeTagProps } from '@/composables/tag' import { makeThemeProps, provideTheme } from '@/composables/theme' // Utilities +import { Suspense } from 'vue' import { defineComponent } from '@/util' export const VItemGroupSymbol = Symbol.for('vuetify:v-item-group') @@ -37,13 +38,17 @@ export const VItemGroup = defineComponent({ themeClasses.value, ]} > - { slots.default?.({ - isSelected, - select, - next, - prev, - selected: selected.value, - }) } + + <> + { slots.default?.({ + isSelected, + select, + next, + prev, + selected: selected.value, + }) } + + ) }, diff --git a/packages/vuetify/src/components/VItemGroup/__tests__/VItemGroup.spec.ts b/packages/vuetify/src/components/VItemGroup/__tests__/VItemGroup.spec.ts index ddd3ad4c22a..2a79d8e9d16 100644 --- a/packages/vuetify/src/components/VItemGroup/__tests__/VItemGroup.spec.ts +++ b/packages/vuetify/src/components/VItemGroup/__tests__/VItemGroup.spec.ts @@ -3,7 +3,7 @@ import { VItem } from '../VItem' import { VItemGroup } from '../VItemGroup' // Utilities -import { h } from 'vue' +import { h, nextTick } from 'vue' import { mount } from '@vue/test-utils' import { describe, expect, it } from '@jest/globals' import { createVuetify } from '@/framework' @@ -35,6 +35,8 @@ describe('VItemGroup', () => { }, }) + await nextTick() + const items = wrapper.findAll('#item') await items[0].trigger('click') @@ -56,6 +58,9 @@ describe('VItemGroup', () => { }, }) + await nextTick() + await nextTick() + const items = wrapper.findAll('#item') await items[0].trigger('click') @@ -76,6 +81,9 @@ describe('VItemGroup', () => { }, }) + await nextTick() + await nextTick() + const items = wrapper.findAll('#item') await items[0].trigger('click') @@ -106,6 +114,8 @@ describe('VItemGroup', () => { }, }) + await nextTick() + const items = wrapper.findAll('#item') await items[0].trigger('click') diff --git a/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx b/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx index 1242a8c5071..80c6c0af878 100644 --- a/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx +++ b/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx @@ -14,13 +14,13 @@ import { useRtl } from '@/composables/rtl' import { IconValue } from '@/composables/icons' // Utilities -import { bias, calculateCenteredOffset, calculateUpdatedOffset } from './helpers' +import { computed, ref, Suspense, watch, watchEffect } from 'vue' import { clamp, defineComponent, useRender } from '@/util' -import { computed, ref, watch, watchEffect } from 'vue' +import { bias, calculateCenteredOffset, calculateUpdatedOffset } from './helpers' // Types -import type { GroupProvide } from '@/composables/group' import type { InjectionKey } from 'vue' +import type { GroupProvide } from '@/composables/group' export const VSlideGroupSymbol: InjectionKey = Symbol.for('vuetify:v-slide-group') @@ -377,7 +377,11 @@ export const VSlideGroup = defineComponent({ onFocusout={ onFocusout } onKeydown={ onKeydown } > - { slots.default?.(slotProps.value) } + + <> + { slots.default?.(slotProps.value) } + + diff --git a/packages/vuetify/src/components/VSlideGroup/VSlideGroupItem.tsx b/packages/vuetify/src/components/VSlideGroup/VSlideGroupItem.tsx index 2ee3b938e0c..1ae465806e9 100644 --- a/packages/vuetify/src/components/VSlideGroup/VSlideGroupItem.tsx +++ b/packages/vuetify/src/components/VSlideGroup/VSlideGroupItem.tsx @@ -3,7 +3,7 @@ import { makeGroupItemProps, useGroupItem } from '@/composables/group' import { VSlideGroupSymbol } from './VSlideGroup' // Utilities -import { defineComponent } from '@/util' +import { defineComponent, useRender } from '@/util' export const VSlideGroupItem = defineComponent({ name: 'VSlideGroupItem', @@ -15,11 +15,13 @@ export const VSlideGroupItem = defineComponent({ setup (props, { slots }) { const slideGroupItem = useGroupItem(props, VSlideGroupSymbol) - return () => slots.default?.({ + useRender(() => slots.default?.({ isSelected: slideGroupItem.isSelected.value, select: slideGroupItem.select, toggle: slideGroupItem.toggle, selectedClass: slideGroupItem.selectedClass.value, - }) + })) + + return slideGroupItem.isReady }, }) diff --git a/packages/vuetify/src/components/VWindow/VWindow.tsx b/packages/vuetify/src/components/VWindow/VWindow.tsx index 95f634f01ac..7b8920386f0 100644 --- a/packages/vuetify/src/components/VWindow/VWindow.tsx +++ b/packages/vuetify/src/components/VWindow/VWindow.tsx @@ -15,7 +15,7 @@ import { useRtl } from '@/composables/rtl' import { Touch } from '@/directives/touch' // Utilities -import { computed, provide, ref, watch } from 'vue' +import { computed, provide, ref, Suspense, watch } from 'vue' import { genericComponent, useRender } from '@/util' // Types @@ -234,7 +234,11 @@ export const VWindow = genericComponent { height: transitionHeight.value, }} > - { slots.default?.({ group }) } + + <> + { slots.default?.({ group }) } + + { props.showArrows !== false && (
diff --git a/packages/vuetify/src/components/VWindow/VWindowItem.tsx b/packages/vuetify/src/components/VWindow/VWindowItem.tsx index 1cd430ba283..acc4091364e 100644 --- a/packages/vuetify/src/components/VWindow/VWindowItem.tsx +++ b/packages/vuetify/src/components/VWindow/VWindowItem.tsx @@ -9,7 +9,7 @@ import Touch from '@/directives/touch' // Utilities import { computed, inject, nextTick, ref } from 'vue' -import { convertToUnit, defineComponent } from '@/util' +import { convertToUnit, defineComponent, useRender } from '@/util' import { VWindowGroupSymbol, VWindowSymbol } from './VWindow' export const VWindowItem = defineComponent({ @@ -114,7 +114,7 @@ export const VWindowItem = defineComponent({ const { hasContent } = useLazy(props, groupItem.isSelected) - return () => { + useRender(() => { return (
) - } + }) + + return groupItem.isReady }, }) diff --git a/packages/vuetify/src/composables/group.ts b/packages/vuetify/src/composables/group.ts index 572370268c7..b2aa5a8e4b7 100644 --- a/packages/vuetify/src/composables/group.ts +++ b/packages/vuetify/src/composables/group.ts @@ -133,9 +133,7 @@ export function useGroupItem ( vm.emit('group:selected', { value }) }) - let resolve: (val?: any) => void - const isReady = new Promise(_resolve => resolve = _resolve) - nextTick(() => resolve()) + const isReady = nextTick() return { id, diff --git a/packages/vuetify/src/util/useRender.ts b/packages/vuetify/src/util/useRender.ts index ddc13e9b1cc..7e33289f2ec 100644 --- a/packages/vuetify/src/util/useRender.ts +++ b/packages/vuetify/src/util/useRender.ts @@ -2,9 +2,9 @@ import { getCurrentInstance } from './getCurrentInstance' // Types -import type { VNode } from 'vue' +import type { VNodeChild } from 'vue' -export function useRender (render: () => VNode): void { +export function useRender (render: () => VNodeChild): void { const vm = getCurrentInstance('useRender') as any vm.render = render } diff --git a/patches/@vue+runtime-core+3.2.37.patch b/patches/@vue+runtime-core+3.2.37.patch new file mode 100644 index 00000000000..c72de2efdea --- /dev/null +++ b/patches/@vue+runtime-core+3.2.37.patch @@ -0,0 +1,22 @@ +diff --git a/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js b/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +index 9c71d2d..554c9cc 100644 +--- a/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js ++++ b/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +@@ -5659,7 +5659,7 @@ function baseCreateRenderer(options, createHydrationFns) { + } + patch(prevTree, nextTree, + // parent may have changed if it's in a teleport +- hostParentNode(prevTree.el), ++ prevTree.el && hostParentNode(prevTree.el), + // anchor may have changed if it's in a fragment + getNextHostNode(prevTree), instance, parentSuspense, isSVG); + if ((process.env.NODE_ENV !== 'production')) { +@@ -6191,7 +6191,7 @@ function baseCreateRenderer(options, createHydrationFns) { + } + }; + const getNextHostNode = vnode => { +- if (vnode.shapeFlag & 6 /* COMPONENT */) { ++ if (vnode.shapeFlag & 6 /* COMPONENT */ && vnode.component.subTree) { + return getNextHostNode(vnode.component.subTree); + } + if (vnode.shapeFlag & 128 /* SUSPENSE */) { diff --git a/yarn.lock b/yarn.lock index 9c6c146c0f0..a627eb7def1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3209,6 +3209,16 @@ estree-walker "^2.0.2" source-map "^0.6.1" +"@vue/compiler-core@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.37.tgz#b3c42e04c0e0f2c496ff1784e543fbefe91e215a" + integrity sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/shared" "3.2.37" + estree-walker "^2.0.2" + source-map "^0.6.1" + "@vue/compiler-dom@3.2.36", "@vue/compiler-dom@^3.2.36": version "3.2.36" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz#16d911ff163ed5fc8087a01645bf14bb7f325401" @@ -3217,7 +3227,31 @@ "@vue/compiler-core" "3.2.36" "@vue/shared" "3.2.36" -"@vue/compiler-sfc@3.2.36", "@vue/compiler-sfc@^3.2.36", "@vue/compiler-sfc@^3.2.4": +"@vue/compiler-dom@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz#10d2427a789e7c707c872da9d678c82a0c6582b5" + integrity sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ== + dependencies: + "@vue/compiler-core" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/compiler-sfc@3.2.37", "@vue/compiler-sfc@^3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz#3103af3da2f40286edcd85ea495dcb35bc7f5ff4" + integrity sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.37" + "@vue/compiler-dom" "3.2.37" + "@vue/compiler-ssr" "3.2.37" + "@vue/reactivity-transform" "3.2.37" + "@vue/shared" "3.2.37" + estree-walker "^2.0.2" + magic-string "^0.25.7" + postcss "^8.1.10" + source-map "^0.6.1" + +"@vue/compiler-sfc@^3.2.36", "@vue/compiler-sfc@^3.2.4": version "3.2.36" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz#e5065e7c0e5170ffa750e3c3dd93a29db109d0f2" integrity sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA== @@ -3241,6 +3275,14 @@ "@vue/compiler-dom" "3.2.36" "@vue/shared" "3.2.36" +"@vue/compiler-ssr@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz#4899d19f3a5fafd61524a9d1aee8eb0505313cff" + integrity sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw== + dependencies: + "@vue/compiler-dom" "3.2.37" + "@vue/shared" "3.2.37" + "@vue/devtools-api@^6.0.0", "@vue/devtools-api@^6.0.0-beta.13", "@vue/devtools-api@^6.1.4": version "6.1.4" resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.1.4.tgz#b4aec2f4b4599e11ba774a50c67fa378c9824e53" @@ -3257,6 +3299,17 @@ estree-walker "^2.0.2" magic-string "^0.25.7" +"@vue/reactivity-transform@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz#0caa47c4344df4ae59f5a05dde2a8758829f8eca" + integrity sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.37" + "@vue/shared" "3.2.37" + estree-walker "^2.0.2" + magic-string "^0.25.7" + "@vue/reactivity@3.2.36", "@vue/reactivity@^3.2.36": version "3.2.36" resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.36.tgz#026b14e716febffe80cd284fd8a2b33378968646" @@ -3264,7 +3317,22 @@ dependencies: "@vue/shared" "3.2.36" -"@vue/runtime-core@3.2.36", "@vue/runtime-core@^3.2.33": +"@vue/reactivity@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.37.tgz#5bc3847ac58828e2b78526e08219e0a1089f8848" + integrity sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A== + dependencies: + "@vue/shared" "3.2.37" + +"@vue/runtime-core@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.37.tgz#7ba7c54bb56e5d70edfc2f05766e1ca8519966e3" + integrity sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ== + dependencies: + "@vue/reactivity" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/runtime-core@^3.2.33": version "3.2.36" resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.36.tgz#be5115e665679c26bf3807d2326675dc1d847134" integrity sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ== @@ -3272,16 +3340,24 @@ "@vue/reactivity" "3.2.36" "@vue/shared" "3.2.36" -"@vue/runtime-dom@3.2.36": - version "3.2.36" - resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz#cd5d403ea23c18ee7c17767103a1b2f8263c54bb" - integrity sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg== +"@vue/runtime-dom@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz#002bdc8228fa63949317756fb1e92cdd3f9f4bbd" + integrity sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw== dependencies: - "@vue/runtime-core" "3.2.36" - "@vue/shared" "3.2.36" + "@vue/runtime-core" "3.2.37" + "@vue/shared" "3.2.37" csstype "^2.6.8" -"@vue/server-renderer@3.2.36", "@vue/server-renderer@^3.2.26": +"@vue/server-renderer@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.37.tgz#840a29c8dcc29bddd9b5f5ffa22b95c0e72afdfc" + integrity sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA== + dependencies: + "@vue/compiler-ssr" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/server-renderer@^3.2.26": version "3.2.36" resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.36.tgz#1e7c1cf63bd17df7828d04e8c780ee6ca7a9ed7c" integrity sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg== @@ -3294,6 +3370,11 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.36.tgz#35e11200542cf29068ba787dad57da9bdb82f644" integrity sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ== +"@vue/shared@3.2.37": + version "3.2.37" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702" + integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw== + "@vue/test-utils@2.0.0", "@vue/test-utils@^2.0.0-rc.10": version "2.0.0" resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.0.tgz#06455934091d237d71d81bac6617485de38b1c58" @@ -13036,16 +13117,16 @@ vue-tsc@^0.35.2: dependencies: "@volar/vue-typescript" "0.35.2" -vue@^3.2.36: - version "3.2.36" - resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.36.tgz#8daa996e2ced521708de97d066c7c998e8bc3378" - integrity sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw== +vue@^3.2.37: + version "3.2.37" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.37.tgz#da220ccb618d78579d25b06c7c21498ca4e5452e" + integrity sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ== dependencies: - "@vue/compiler-dom" "3.2.36" - "@vue/compiler-sfc" "3.2.36" - "@vue/runtime-dom" "3.2.36" - "@vue/server-renderer" "3.2.36" - "@vue/shared" "3.2.36" + "@vue/compiler-dom" "3.2.37" + "@vue/compiler-sfc" "3.2.37" + "@vue/runtime-dom" "3.2.37" + "@vue/server-renderer" "3.2.37" + "@vue/shared" "3.2.37" w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2: version "1.0.2" From 74095f784320bcd04ad4ee9e5354243097500861 Mon Sep 17 00:00:00 2001 From: Kael Date: Sun, 9 Apr 2023 14:31:40 +1000 Subject: [PATCH 3/6] chore: remove outdated patch --- patches/@vue+runtime-core+3.2.37.patch | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 patches/@vue+runtime-core+3.2.37.patch diff --git a/patches/@vue+runtime-core+3.2.37.patch b/patches/@vue+runtime-core+3.2.37.patch deleted file mode 100644 index c72de2efdea..00000000000 --- a/patches/@vue+runtime-core+3.2.37.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js b/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js -index 9c71d2d..554c9cc 100644 ---- a/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js -+++ b/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js -@@ -5659,7 +5659,7 @@ function baseCreateRenderer(options, createHydrationFns) { - } - patch(prevTree, nextTree, - // parent may have changed if it's in a teleport -- hostParentNode(prevTree.el), -+ prevTree.el && hostParentNode(prevTree.el), - // anchor may have changed if it's in a fragment - getNextHostNode(prevTree), instance, parentSuspense, isSVG); - if ((process.env.NODE_ENV !== 'production')) { -@@ -6191,7 +6191,7 @@ function baseCreateRenderer(options, createHydrationFns) { - } - }; - const getNextHostNode = vnode => { -- if (vnode.shapeFlag & 6 /* COMPONENT */) { -+ if (vnode.shapeFlag & 6 /* COMPONENT */ && vnode.component.subTree) { - return getNextHostNode(vnode.component.subTree); - } - if (vnode.shapeFlag & 128 /* SUSPENSE */) { From a65492fff56a45463533852b57133f43a9898e8d Mon Sep 17 00:00:00 2001 From: Kael Date: Wed, 7 Feb 2024 22:42:52 +1100 Subject: [PATCH 4/6] recursive find suspense children --- packages/vuetify/src/util/helpers.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/vuetify/src/util/helpers.ts b/packages/vuetify/src/util/helpers.ts index 3a777fd3a72..5c9c1cd958b 100644 --- a/packages/vuetify/src/util/helpers.ts +++ b/packages/vuetify/src/util/helpers.ts @@ -547,6 +547,8 @@ export function findChildrenWithProvide ( } else if (vnode.component.subTree) { return findChildrenWithProvide(key, vnode.component.subTree).flat(1) } + } else if (vnode.suspense) { + return findChildrenWithProvide(key, vnode.suspense.activeBranch ?? vnode.suspense.pendingBranch) } return [] From 0d32d957a80c5777ff2f186a3d7b15f83f3754a0 Mon Sep 17 00:00:00 2001 From: Kael Date: Wed, 7 Feb 2024 22:52:45 +1100 Subject: [PATCH 5/6] set mandatory after items render --- .../components/VBottomNavigation/VBottomNavigation.tsx | 4 ++-- .../vuetify/src/components/VBtnToggle/VBtnToggle.tsx | 4 ++-- .../vuetify/src/components/VChipGroup/VChipGroup.tsx | 4 ++-- .../components/VExpansionPanel/VExpansionPanels.tsx | 4 ++-- .../vuetify/src/components/VItemGroup/VItemGroup.tsx | 4 ++-- .../vuetify/src/components/VSlideGroup/VSlideGroup.tsx | 2 +- packages/vuetify/src/components/VWindow/VWindow.tsx | 2 +- packages/vuetify/src/composables/group.ts | 10 ++++++---- 8 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx b/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx index 0d2b477e91e..5d1eb8e99c2 100644 --- a/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx +++ b/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx @@ -95,7 +95,7 @@ export const VBottomNavigation = genericComponent( absolute: toRef(props, 'absolute'), }) - useGroup(props, VBtnToggleSymbol) + const group = useGroup(props, VBtnToggleSymbol) provideDefaults({ VBtn: { @@ -136,7 +136,7 @@ export const VBottomNavigation = genericComponent( ]} >
- + <> { slots.default?.() } diff --git a/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx b/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx index af93c0aeb69..2c2afea94f1 100644 --- a/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx +++ b/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx @@ -46,7 +46,7 @@ export const VBtnToggle = genericComponent( }, setup (props, { slots }) { - const { isSelected, next, prev, select, selected } = useGroup(props, VBtnToggleSymbol) + const { isSelected, next, prev, select, selected, ready } = useGroup(props, VBtnToggleSymbol) useRender(() => { const btnGroupProps = VBtnGroup.filterProps(props) @@ -60,7 +60,7 @@ export const VBtnToggle = genericComponent( { ...btnGroupProps } style={ props.style } > - + <> { slots.default?.({ isSelected, diff --git a/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx b/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx index cd77140f7dd..bec41176247 100644 --- a/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx +++ b/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx @@ -65,7 +65,7 @@ export const VChipGroup = genericComponent( setup (props, { slots }) { const { themeClasses } = provideTheme(props) - const { isSelected, select, next, prev, selected } = useGroup(props, VChipGroupSymbol) + const { isSelected, select, next, prev, selected, ready } = useGroup(props, VChipGroupSymbol) provideDefaults({ VChip: { @@ -92,7 +92,7 @@ export const VChipGroup = genericComponent( ]} style={ props.style } > - + <> { slots.default?.({ isSelected, diff --git a/packages/vuetify/src/components/VExpansionPanel/VExpansionPanels.tsx b/packages/vuetify/src/components/VExpansionPanel/VExpansionPanels.tsx index edb4d7d8e21..bd26c264fdf 100644 --- a/packages/vuetify/src/components/VExpansionPanel/VExpansionPanels.tsx +++ b/packages/vuetify/src/components/VExpansionPanel/VExpansionPanels.tsx @@ -48,7 +48,7 @@ export const VExpansionPanels = genericComponent()({ }, setup (props, { slots }) { - useGroup(props, VExpansionPanelSymbol) + const group = useGroup(props, VExpansionPanelSymbol) const { themeClasses } = provideTheme(props) @@ -72,7 +72,7 @@ export const VExpansionPanels = genericComponent()({ ]} style={ props.style } > - + <> { slots.default?.() } diff --git a/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx b/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx index cd924316a11..d66ea357b67 100644 --- a/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx +++ b/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx @@ -52,7 +52,7 @@ export const VItemGroup = genericComponent( setup (props, { slots }) { const { themeClasses } = provideTheme(props) - const { isSelected, select, next, prev, selected } = useGroup(props, VItemGroupSymbol) + const { isSelected, select, next, prev, selected, ready } = useGroup(props, VItemGroupSymbol) return () => ( ( ]} style={ props.style } > - + <> { slots.default?.({ isSelected, diff --git a/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx b/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx index 5e75f7c68ca..cdb920d8c1f 100644 --- a/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx +++ b/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx @@ -398,7 +398,7 @@ export const VSlideGroup = genericComponent( onFocusout={ onFocusout } onKeydown={ onKeydown } > - + <> { slots.default?.(slotProps.value) } diff --git a/packages/vuetify/src/components/VWindow/VWindow.tsx b/packages/vuetify/src/components/VWindow/VWindow.tsx index 0de654230b8..20ee1171817 100644 --- a/packages/vuetify/src/components/VWindow/VWindow.tsx +++ b/packages/vuetify/src/components/VWindow/VWindow.tsx @@ -243,7 +243,7 @@ export const VWindow = genericComponent( height: transitionHeight.value, }} > - + <> { slots.default?.({ group }) } diff --git a/packages/vuetify/src/composables/group.ts b/packages/vuetify/src/composables/group.ts index d69a2baf867..d69b0492b1c 100644 --- a/packages/vuetify/src/composables/group.ts +++ b/packages/vuetify/src/composables/group.ts @@ -2,7 +2,7 @@ import { useProxiedModel } from './proxiedModel' // Utilities -import { computed, inject, nextTick, onBeforeUnmount, onMounted, provide, reactive, toRef, unref, watch } from 'vue' +import { computed, inject, nextTick, onBeforeUnmount, provide, reactive, toRef, unref, watch } from 'vue' import { consoleWarn, deepEqual, findChildrenWithProvide, getCurrentInstance, getUid, propsFactory, wrapInArray } from '@/util' // Types @@ -28,6 +28,7 @@ export interface GroupProps { export interface GroupProvide { register: (item: GroupItem, cmp: ComponentInternalInstance) => void unregister: (id: number) => void + ready: () => void select: (id: number, value: boolean) => void selected: Ref> isSelected: (id: number) => boolean @@ -215,9 +216,9 @@ export function useGroup ( } } - onMounted(() => { - forceMandatoryValue() - }) + function ready () { + nextTick(forceMandatoryValue) + } onBeforeUnmount(() => { isUnmounted = true @@ -292,6 +293,7 @@ export function useGroup ( unregister, selected, select, + ready, disabled: toRef(props, 'disabled'), prev: () => step(items.length - 1), next: () => step(1), From 11ac04a8903497a8b4bed3e148089d230bf84d2b Mon Sep 17 00:00:00 2001 From: Kael Date: Wed, 14 Feb 2024 19:54:03 +1100 Subject: [PATCH 6/6] chore: update tests --- .../src/composables/__tests__/group.spec.ts | 81 +++++++++++-------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/packages/vuetify/src/composables/__tests__/group.spec.ts b/packages/vuetify/src/composables/__tests__/group.spec.ts index 625e89dccd4..4f2fdabb8ef 100644 --- a/packages/vuetify/src/composables/__tests__/group.spec.ts +++ b/packages/vuetify/src/composables/__tests__/group.spec.ts @@ -3,7 +3,8 @@ import { makeGroupProps, useGroup, useGroupItem } from '../group' // Utilities import { describe, expect, it } from '@jest/globals' import { mount } from '@vue/test-utils' -import { defineComponent, h, nextTick, reactive } from 'vue' +import { defineComponent, Fragment, h, nextTick, reactive, Suspense } from 'vue' +import { useRender } from '@/util' describe('group', () => { describe('with complex values', () => { @@ -14,12 +15,17 @@ describe('group', () => { setup (props) { // @ts-expect-error missing emit const item = useGroupItem(props, Symbol.for('test')) - return () => h('div', { + return item.isReady.then(() => ({ + item, + })) + }, + render (ctx: any) { + return h('div', { class: { - selected: item.isSelected.value, + selected: ctx.item.isSelected.value, }, - onClick: item.toggle, - }, [JSON.stringify(props.value)]) + onClick: ctx.item.toggle, + }, [JSON.stringify(ctx.value)]) }, }) @@ -29,11 +35,11 @@ describe('group', () => { }, setup (props) { // @ts-expect-error missing emit - useGroup(props, Symbol.for('test')) - return () => h('div', [ + const group = useGroup(props, Symbol.for('test')) + return () => h(Suspense, { onResolve: group.ready }, [h(Fragment, [ h(GroupItemComponent, { value: { foo: 1 } }), h(GroupItemComponent, { value: { bar: 2 } }), - ]) + ])]) }, }) @@ -54,7 +60,7 @@ describe('group', () => { await item[1].trigger('click') - expect(wrapper.emitted('update:modelValue')).toEqual([ + expect(wrapper.emitted('update:modelValue')).toStrictEqual([ [{ bar: 2 }], ]) @@ -71,12 +77,17 @@ describe('group', () => { setup (props) { // @ts-expect-error missing emit const item = useGroupItem(props, Symbol.for('test')) - return () => h('div', { - class: { - selected: item.isSelected.value, - }, - onClick: item.toggle, - }, [props.value]) + + useRender(() => { + return h('div', { + class: { + selected: item.isSelected.value, + }, + onClick: item.toggle, + }, [props.value]) + }) + + return item.isReady }, }) @@ -85,26 +96,26 @@ describe('group', () => { ...makeGroupProps(), disabledItems: Array, }, - setup (props) { + setup (props, { slots }) { // @ts-expect-error missing emit - return useGroup(props, Symbol.for('test')) - }, - render () { - return h('div', this.$slots.default?.() ?? [ - h(GroupItemComponent, { value: 'one', disabled: !!this.disabledItems?.[0] }), - h(GroupItemComponent, { value: 'two', disabled: !!this.disabledItems?.[1] }), - ]) + const group = useGroup(props, Symbol.for('test')) + return h(Suspense, { onResolve: group.ready }, slots.default?.() ?? [h(Fragment, [ + h(GroupItemComponent, { value: 'one', disabled: !!props.disabledItems?.[0] }), + h(GroupItemComponent, { value: 'two', disabled: !!props.disabledItems?.[1] }), + ])]) }, }) it('should emit new selection', async () => { const wrapper = mount(GroupComponent) + await nextTick() + const item = wrapper.findComponent(GroupItemComponent) await item.trigger('click') - expect(wrapper.emitted('update:modelValue')).toEqual([ + expect(wrapper.emitted('update:modelValue')).toStrictEqual([ ['one'], ]) @@ -160,7 +171,7 @@ describe('group', () => { await items[1].trigger('click') await items[0].trigger('click') - expect(wrapper.emitted()['update:modelValue']).toEqual([ + expect(wrapper.emitted('update:modelValue')).toStrictEqual([ [['two']], [['two', 'one']], ]) @@ -175,7 +186,10 @@ describe('group', () => { }, }) - expect(wrapper.emitted()['update:modelValue']).toEqual([ + await nextTick() + await nextTick() + + expect(wrapper.emitted('update:modelValue')).toStrictEqual([ ['two'], ]) }) @@ -195,7 +209,7 @@ describe('group', () => { await items[0].trigger('click') - expect(wrapper.emitted()).not.toHaveProperty('update:modelValue') + expect(wrapper.emitted('update:modelValue')).toBeUndefined() }) it('should not allow selection bigger than max', async () => { @@ -214,7 +228,7 @@ describe('group', () => { await items[0].trigger('click') await items[1].trigger('click') - expect(wrapper.emitted()['update:modelValue']).toEqual([ + expect(wrapper.emitted('update:modelValue')).toStrictEqual([ [['one']], ]) }) @@ -239,7 +253,7 @@ describe('group', () => { wrapper.vm.next() await nextTick() - expect(wrapper.emitted()['update:modelValue']).toEqual([ + expect(wrapper.emitted('update:modelValue')).toStrictEqual([ ['three'], ]) }) @@ -327,12 +341,11 @@ describe('group', () => { }, }) - // selection happens in mounted so we need to await - // to be able to match snapshot - await wrapper.vm.$nextTick() + await nextTick() - expect(wrapper.emitted()['update:modelValue']).toHaveLength(1) - expect(wrapper.html()).toMatchSnapshot() + expect(wrapper.emitted('update:modelValue')).toStrictEqual([ + ['two'], + ]) }) it('should not allow empty value when mandatory', async () => {