Skip to content

Commit 6ef3d22

Browse files
committed
feat(useSelection): watch for initialValue changes
closes #151
1 parent 0f4802d commit 6ef3d22

File tree

6 files changed

+73
-11
lines changed

6 files changed

+73
-11
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script setup lang="ts">
2+
import { useSelection } from 'anu-vue'
3+
4+
const { options, select, value } = useSelection({
5+
items: ['apple', 'banana', 'orange', 'watermelon'],
6+
initialValue: 'banana', // [!code hl]
7+
})
8+
</script>
9+
10+
<template>
11+
<div>
12+
<div class="flex flex-wrap gap-6 mb-4">
13+
<ABtn
14+
v-for="option in options"
15+
:key="option.value"
16+
:variant="option.isSelected ? 'fill' : 'light'"
17+
@click="select(option.value)"
18+
>
19+
{{ option.value }}
20+
</ABtn>
21+
</div>
22+
<small class="block">Selected: {{ value }}</small>
23+
</div>
24+
</template>

docs/components/demos/composables/useSelection/DemoUseSelectionObject.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ const { options, select, value } = useSelection({
88
{ title: 'Cart', icon: 'i-bx-basket' },
99
{ title: 'Profile', icon: 'i-bx-user-circle' },
1010
],
11-
initialValue: { title: 'Home', icon: 'i-bx-home' },
1211
})
1312
</script>
1413

docs/guide/composables/useSelection.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,20 @@ description
3434
:::
3535

3636
::::
37+
38+
<!-- 👉 Initial Value -->
39+
:::::card Initial Value
40+
41+
You can set initial value for selection by passing it to `initialValue` property.
42+
43+
::::code DemoUseSelectionInitialValue
44+
<<< @/components/demos/composables/useSelection/DemoUseSelectionInitialValue.vue
45+
::::
46+
47+
::::after-demo
48+
:::info
49+
`useSelection` will watch for changes in `initialValue` and update selection.
50+
:::
51+
::::
52+
53+
:::::

packages/anu-vue/src/components/list/AList.vue

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
import type { AListEvents, AListPropItems, aListSlots } from './meta'
33
import { aListListItemSlotsWithPrefixMeta, aListProps } from './meta'
44
import { AListItem } from '@/components/list-item'
5-
import { useSelection } from '@/composables'
6-
import { isObject } from '@/utils/helpers'
5+
import { calculateSelectionItems, extractItemValueFromItemOption, useSelection } from '@/composables/useSelection'
76
87
const props = defineProps(aListProps)
98
const emit = defineEmits<AListEvents>()
@@ -13,13 +12,10 @@ defineOptions({
1312
name: 'AList',
1413
})
1514
16-
function extractItemValueFromItemOption(item: AListPropItems[number]) {
17-
return isObject(item) ? (item.value || item) : item
18-
}
19-
2015
const { options, select: selectListItem, value } = useSelection({
21-
items: props.items.map(i => extractItemValueFromItemOption(i)),
22-
multi: props.multi,
16+
items: calculateSelectionItems(toRef(() => props.items)),
17+
multi: toRef(() => props.multi),
18+
initialValue: toRef(() => props.modelValue),
2319
})
2420
2521
// const isActive = computed(() => options.value[itemIndex].isSelected)

packages/anu-vue/src/composables/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export * from './useIndeterminateCheckbox'
77
export * from './useLayer'
88
export * from './useParent'
99
export * from './useSearch'
10-
export * from './useSelection'
10+
export { useSelection } from './useSelection'
1111
export * from './useSort'
1212
export * from './useTeleport'
1313

packages/anu-vue/src/composables/useSelection.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export function useSelection<const Item, Multi extends boolean, InitialValue ext
3232

3333
// _initialValue.value,
3434

35-
_items.value.find(i => {
35+
(_items.value as Item[]).find(i => {
3636
// ℹ️ If initial value is object compare using `JSON.stringify` else just use `===`
3737
return (isObject(_initialValue.value) && isObject(i))
3838
? JSON.stringify(_initialValue.value) === JSON.stringify(i)
@@ -71,9 +71,35 @@ export function useSelection<const Item, Multi extends boolean, InitialValue ext
7171
: item === _val.value,
7272
}))) as ReturnValue<Item, Multi>['options']
7373

74+
// Watch for external changes to initialValue aka modelValue
75+
watch(_initialValue, val => {
76+
select(val as Item)
77+
})
78+
7479
return {
7580
value: _val,
7681
select,
7782
options: _options,
7883
}
7984
}
85+
86+
export function calculateSelectionItems(items: MaybeRefOrGetter<unknown[]>) {
87+
return computed(() => {
88+
const _items = toRef(items)
89+
90+
if (_items.value.length === 0)
91+
return []
92+
93+
const firstItem = _items.value[0]
94+
if (isObject(firstItem)) {
95+
if ('value' in firstItem)
96+
return _items.value.map(item => (item as { value: unknown }).value)
97+
}
98+
99+
return _items.value
100+
})
101+
}
102+
103+
export function extractItemValueFromItemOption(item: unknown) {
104+
return isObject(item) ? (item.value || item) : item
105+
}

0 commit comments

Comments
 (0)