Skip to content

Commit

Permalink
feat: remove active from nested composable (#14711)
Browse files Browse the repository at this point in the history
  • Loading branch information
nekosaur committed Mar 8, 2022
1 parent 7472a9f commit 41aca14
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 133 deletions.
2 changes: 1 addition & 1 deletion packages/vuetify/cypress/support/mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Cypress.Commands.add('mount', (component, options, vuetifyOptions) => {
},
}

return cyMount(component, mergeDeep(defaultOptions, options)).as('wrapper')
return cyMount(component, mergeDeep(defaultOptions, options, (a, b) => a.concat(b))).as('wrapper')
})

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export const VAutocomplete = genericComponent<new <T>() => {
(v: any) => props.multiple ? v : v[0]
)
const menu = ref(false)
const active = computed({
const selected = computed({
get: () => model.value,
set: val => {
model.value = val
Expand Down Expand Up @@ -174,7 +174,7 @@ export const VAutocomplete = genericComponent<new <T>() => {
activator.value = val.$el.querySelector('.v-input__control')
})

watch(() => active.value, () => {
watch(() => selected.value, () => {
if (!isFocused.value || props.multiple) return

search.value = selections.value[0]?.title
Expand Down Expand Up @@ -237,8 +237,8 @@ export const VAutocomplete = genericComponent<new <T>() => {
transition={ props.transition }
>
<VList
v-model:active={ active.value }
activeStrategy={ props.multiple ? 'multiple' : 'single' }
v-model:selected={ selected.value }
selectStrategy={ props.multiple ? 'independent' : 'single-independent' }
>
{ !filteredItems.value.length && !props.hideNoData && (
<VListItem title={ t(props.noDataText) } />
Expand Down
9 changes: 4 additions & 5 deletions packages/vuetify/src/components/VList/VList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,8 @@ export const VList = genericComponent<new <T>() => {
items: Array as Prop<ListItem[]>,

...makeNestedProps({
selectStrategy: 'leaf' as const,
selectStrategy: 'single-leaf' as const,
openStrategy: 'multiple' as const,
activeStrategy: 'single' as const,
}),
...makeBorderProps(),
...makeDensityProps(),
Expand All @@ -91,7 +90,8 @@ export const VList = genericComponent<new <T>() => {
emits: {
'update:selected': (val: string[]) => true,
'update:opened': (val: string[]) => true,
'update:active': (val: string[]) => true,
'click:open': (value: { id: string, value: boolean, path: string[] }) => true,
'click:select': (value: { id: string, value: boolean, path: string[] }) => true,
},

setup (props, { slots }) {
Expand All @@ -103,7 +103,7 @@ export const VList = genericComponent<new <T>() => {
const { dimensionStyles } = useDimension(props)
const { elevationClasses } = useElevation(props)
const { roundedClasses } = useRounded(props)
const { open, select, activate } = useNested(props)
const { open, select } = useNested(props)

createList()

Expand Down Expand Up @@ -145,7 +145,6 @@ export const VList = genericComponent<new <T>() => {
return {
open,
select,
activate,
}
},
})
Expand Down
6 changes: 3 additions & 3 deletions packages/vuetify/src/components/VList/VListChildren.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ export const VListChildren = genericComponent<new <T extends InternalListItem>()
value={ itemProps?.value }
>
{{
default: () => (
<VListChildren items={ children } v-slots={ slots } />
),
activator: ({ props: activatorProps }) => slots.header
? slots.header({ ...itemProps, ...activatorProps })
: <VListItem { ...itemProps } { ...activatorProps } />,
default: () => (
<VListChildren items={ children } v-slots={ slots } />
),
}}
</VListGroup>
) : (
Expand Down
30 changes: 22 additions & 8 deletions packages/vuetify/src/components/VList/VListGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import { VExpandTransition } from '@/components/transitions'
// Composables
import { useList } from './list'
import { makeTagProps } from '@/composables/tag'
import { useNestedGroup } from '@/composables/nested/nested'
import { useNestedGroupActivator, useNestedItem } from '@/composables/nested/nested'

// Utilities
import { computed } from 'vue'
import { computed, defineComponent, toRef } from 'vue'
import { genericComponent } from '@/util'

// Types
import type { InternalListItem } from './VList'
import type { Ref } from 'vue'
import type { MakeSlots } from '@/util'
import type { InternalListItem } from './VList'

export type ListGroupActivatorSlot = {
props: {
Expand All @@ -22,6 +23,16 @@ export type ListGroupActivatorSlot = {
}
}

const VListGroupActivator = defineComponent({
name: 'VListGroupActivator',

setup (_, { slots }) {
useNestedGroupActivator()

return () => slots.default?.()
},
})

export const VListGroup = genericComponent<new <T extends InternalListItem>() => {
$props: {
items?: T[]
Expand All @@ -34,7 +45,6 @@ export const VListGroup = genericComponent<new <T extends InternalListItem>() =>
name: 'VListGroup',

props: {
value: null,
collapseIcon: {
type: String,
default: '$collapse',
Expand All @@ -43,23 +53,23 @@ export const VListGroup = genericComponent<new <T extends InternalListItem>() =>
type: String,
default: '$expand',
},
value: null,

...makeTagProps(),
},

setup (props, { slots }) {
const { isOpen, open } = useNestedGroup(props)
const { isOpen, open } = useNestedItem(toRef(props, 'value'), true)
const list = useList()

const onClick = (e: Event) => {
open(!isOpen.value, e)
}

const activatorProps = computed(() => ({
const activatorProps: Ref<ListGroupActivatorSlot['props']> = computed(() => ({
onClick,
appendIcon: isOpen.value ? props.collapseIcon : props.expandIcon,
class: 'v-list-group__header',
value: `${props.value}_header`,
}))

return () => {
Expand All @@ -72,7 +82,11 @@ export const VListGroup = genericComponent<new <T extends InternalListItem>() =>
},
]}
>
{ slots.activator?.({ props: activatorProps.value }) }
{ slots.activator && (
<VListGroupActivator>
{ slots.activator({ props: activatorProps.value }) }
</VListGroupActivator>
) }
<VExpandTransition>
<div class="v-list-group__items" v-show={isOpen.value}>
{ slots.default?.() }
Expand Down
21 changes: 11 additions & 10 deletions packages/vuetify/src/components/VList/VListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,19 @@ export const VListItem = genericComponent<new () => {
setup (props, { attrs, slots }) {
const link = useLink(props, attrs)
const id = computed(() => props.value ?? link.href.value)
const { activate, isActive: isNestedActive, select, isSelected, root, parent } = useNestedItem(id)
const { select, isSelected, root, parent } = useNestedItem(id, false)
const list = useList()
const isActive = computed(() => {
return props.active || link.isExactActive?.value || isNestedActive.value
return props.active || link.isExactActive?.value || isSelected.value
})
const variantProps = computed(() => {
const activeColor = props.activeColor ?? props.color
return {
color: isActive.value ? activeColor : props.color,
textColor: props.textColor,
variant: props.variant,
}
})
const activeColor = props.activeColor ?? props.color
const variantProps = computed(() => ({
color: isActive.value ? activeColor : props.color,
textColor: props.textColor,
variant: props.variant,
}))

onMounted(() => {
if (link.isExactActive?.value && parent.value != null) {
Expand All @@ -121,7 +123,6 @@ export const VListItem = genericComponent<new () => {

const slotProps = computed(() => ({
isActive: isActive.value,
activate,
select,
isSelected: isSelected.value,
}))
Expand Down Expand Up @@ -164,7 +165,7 @@ export const VListItem = genericComponent<new () => {
tabindex={ isClickable ? 0 : undefined }
onClick={ isClickable && ((e: MouseEvent) => {
link.navigate?.(e)
props.value != null && activate(!isNestedActive.value, e)
select(!isSelected.value, e)
})}
v-ripple={ isClickable }
>
Expand Down
73 changes: 73 additions & 0 deletions packages/vuetify/src/components/VList/__tests__/VList.spec.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference types="../../../../types/cypress" />

import { CenteredGrid } from '@/../cypress/templates'
import { createRouter, createWebHistory } from 'vue-router'
import { VList, VListItem } from '..'

describe('VList', () => {
Expand Down Expand Up @@ -111,4 +112,76 @@ describe('VList', () => {

wrapper.get('.v-icon.mdi-home').should('have.length', 2)
})

it('should set active item on route change', () => {
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: { template: 'Home' },
},
{
path: '/about',
component: { template: 'About' },
},
],
})

cy.mount(() => (
<CenteredGrid width="400px">
<VList>
<VListItem to="/" title="Home" />
<VListItem to="/about" title="About" />
</VList>
</CenteredGrid>
), {
global: {
plugins: [router],
},
})

cy.get('.v-list').then(() => {
router.push('/about')
})

cy.get('.v-list-item--active').should('exist').should('have.text', 'About')
})

it('should change route when clicking item with to prop', () => {
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: { template: 'Home' },
},
{
path: '/about',
component: { template: 'About' },
},
],
})

cy.mount(() => (
<CenteredGrid width="400px">
<VList>
<VListItem to="/" title="Home" />
<VListItem to="/team" title="Team" />
</VList>
</CenteredGrid>
), {
global: {
plugins: [router],
},
})

cy.get('.v-list').then(() => {
router.push('/team')
})

cy.get('.v-list-item').eq(1).trigger('click').then(() => {
expect(router.currentRoute.value.path).to.equal('/team')
})
})
})
8 changes: 4 additions & 4 deletions packages/vuetify/src/components/VSelect/VSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const VSelect = genericComponent<new <T>() => {
)

const menu = ref(false)
const active = computed({
const selected = computed({
get: () => model.value,
set: val => {
model.value = val
Expand Down Expand Up @@ -136,7 +136,7 @@ export const VSelect = genericComponent<new <T>() => {
})

function onClear (e: MouseEvent) {
active.value = []
selected.value = []

if (props.openOnClear) {
menu.value = true
Expand Down Expand Up @@ -209,8 +209,8 @@ export const VSelect = genericComponent<new <T>() => {
transition={ props.transition }
>
<VList
v-model:active={ active.value }
activeStrategy={ props.multiple ? 'multiple' : 'single' }
v-model:selected={ selected.value }
selectStrategy={ props.multiple ? 'independent' : 'single-independent' }
>
{ !items.value.length && !props.hideNoData && (
<VListItem title={ t(props.noDataText) } />
Expand Down
22 changes: 0 additions & 22 deletions packages/vuetify/src/composables/nested/activeStrategies.ts

This file was deleted.

Loading

0 comments on commit 41aca14

Please sign in to comment.