chore(RadioGroup): rename options prop to items (#98)

Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
Romain Hamel
2024-05-10 12:31:20 +02:00
committed by GitHub
parent 2480efe6e5
commit 810d278ea7
7 changed files with 128 additions and 99 deletions

View File

@@ -11,15 +11,15 @@ const radioGroup = tv({ extend: tv(theme), ...(appConfig.ui?.radioGroup || {}) }
type RadioGroupVariants = VariantProps<typeof radioGroup>
export type RadioGroupOption<T> = {
export type RadioGroupItem = {
label: string
value: T
value: string
description?: string
}
export interface RadioGroupProps<T> extends Omit<RadioGroupRootProps, 'asChild' | 'dir'> {
legend?: string
options?: string[] | RadioGroupOption<T>[]
items?: T[]
class?: any
size?: RadioGroupVariants['size']
color?: RadioGroupVariants['color']
@@ -30,14 +30,16 @@ export type RadioGroupEmits = {
change: [value: any]
} & RadioGroupRootEmits
type SlotProps<T> = (props: { item: T }) => any
export interface RadioGroupSlots<T> {
legend(): any
label(props: { option: RadioGroupOption<T> }): any
description(props: { option: RadioGroupOption<T> }): any
label: SlotProps<T>
description: SlotProps<T>
}
</script>
<script setup lang="ts" generic="T extends string | undefined">
<script setup lang="ts" generic="T extends RadioGroupItem | string">
import { computed } from 'vue'
import { RadioGroupRoot, RadioGroupItem, RadioGroupIndicator, Label, useForwardPropsEmits } from 'radix-vue'
import { reactivePick } from '@vueuse/core'
@@ -47,7 +49,7 @@ const props = withDefaults(defineProps<RadioGroupProps<T>>(), { orientation: 've
const emits = defineEmits<RadioGroupEmits>()
const slots = defineSlots<RadioGroupSlots<T>>()
const modelValue = defineModel<T>({
const modelValue = defineModel<string>({
set(value) {
emits('change', value)
return value
@@ -67,24 +69,24 @@ const ui = computed(() => tv({ extend: radioGroup, slots: props.ui })({
orientation: props.orientation
}))
function normalizeOption(option: any) {
if (['string', 'number', 'boolean'].includes(typeof option)) {
function normalizeItem(item: any) {
if (['string', 'number', 'boolean'].includes(typeof item)) {
return {
id: `${id}:${option}`,
value: option,
label: option
id: `${id}:${item}`,
value: item,
label: item
}
}
return {
...option,
id: `${id}:${option.value}`
...item,
id: `${id}:${item.value}`
}
}
const normalizedOptions = computed(() => {
if (!props.options) return []
return props.options.map(normalizeOption)
const normalizedItems = computed(() => {
if (!props.items) return []
return props.items.map(normalizeItem)
})
// FIXME: I think there's a race condition between this and the v-model event.
@@ -111,11 +113,11 @@ function onUpdate() {
{{ legend }}
</slot>
</legend>
<div v-for="option in normalizedOptions" :key="option.value" :class="ui.option()">
<div v-for="item in normalizedItems" :key="item.value" :class="ui.item()">
<div :class="ui.container()">
<RadioGroupItem
:id="option.id"
:value="option.value"
:id="item.id"
:value="item.value"
:disabled="disabled"
:class="ui.base()"
>
@@ -124,12 +126,12 @@ function onUpdate() {
</div>
<div :class="ui.wrapper()">
<Label :class="ui.label()" :for="option.id">
<slot name="label" v-bind="{ option }">{{ option.label }}</slot>
<Label :class="ui.label()" :for="item.id">
<slot name="label" :item="item">{{ item.label }}</slot>
</Label>
<p v-if="option.description || !!slots.description" :class="ui.description()">
<slot name="description" v-bind="{ option }">
{{ option.description }}
<p v-if="item.description || !!slots.description" :class="ui.description()">
<slot name="description" :item="item">
{{ item.description }}
</slot>
</p>
</div>