Skip to content

Commit

Permalink
fix: improve checkbox typing
Browse files Browse the repository at this point in the history
  • Loading branch information
stafyniaksacha committed Oct 14, 2023
1 parent 6d68fa5 commit 9d1e985
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 35 deletions.
29 changes: 24 additions & 5 deletions .playground/pages/tests/form/input-models.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ definePageMeta({
const autocomplete1 = ref<string>()
const autocomplete2 = ref<{ name: string }>()
const checkbox1 = ref()
const checkbox2 = ref()
const checkbox3 = ref([])
const checkbox1 = ref<boolean>()
const checkbox2 = ref<{ checked: boolean }>()
const checkbox3 = ref<string[]>([])
const radio1 = ref<boolean>()
const radio2 = ref<string>()
const radio3 = ref<{ [key: string]: number }>()
const checkboxCustom1 = ref()
const radioCustom1 = ref<'yes' | 'no'>()
const animatedCheckbox1 = ref()
const animatedCheckbox2 = ref([])
const animatedCheckbox1 = ref<boolean>()
const animatedCheckbox2 = ref<string[]>([])
const switchBall = ref()
const switchThin = ref()
const input1 = ref()
Expand All @@ -32,6 +32,7 @@ const select1 = ref()
const select2 = ref()
const textarea1 = ref()
const textarea2 = ref()
const textarea3 = ref()
</script>

<template>
Expand Down Expand Up @@ -656,5 +657,23 @@ inputFileCustom1: {{
</div>
</div>
</div>
<div>
<BaseHeading size="xl" weight="medium" class="mb-10">
BaseTextarea (v-model.lazy)
</BaseHeading>
<div>
<div class="grid grid-cols-4 gap-6">
<div class="col-span-2">
<BaseTextarea v-model.lazy="textarea3" />
</div>
<BaseCard class="col-span-2 p-2">
<pre>textarea3: {{ textarea3 }}({{ typeof textarea3 }})</pre>
<BaseButtonAction @click="textarea3 = undefined">
reset
</BaseButtonAction>
</BaseCard>
</div>
</div>
</div>
</div>
</template>
21 changes: 14 additions & 7 deletions components/form/BaseCheckbox.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup lang="ts" generic="T extends any = boolean">
defineOptions({
inheritAttrs: false,
})
Expand All @@ -10,20 +10,25 @@ const props = withDefaults(
*/
label?: string
/**
* Defines the value of the checkbox when it's checked.
*/
value?: T
/**
* The value to set when the checkbox is checked.
*/
trueValue?: any
trueValue?: T
/**
* The value to set when the checkbox is unchecked.
*/
falseValue?: any
falseValue?: T
/**
* The model value of the checkbox.
*/
modelValue?: any
modelValue?: T | T[]
/**
* The form input identifier.
Expand Down Expand Up @@ -83,18 +88,19 @@ const props = withDefaults(
}>(),
{
modelValue: undefined,
value: undefined,
id: undefined,
label: undefined,
error: '',
trueValue: true,
falseValue: false,
trueValue: true as any,
falseValue: false as any,
shape: undefined,
color: undefined,
classes: () => ({}),
},
)
const emits = defineEmits<{
(e: 'update:modelValue', value: string | number | boolean): void
(e: 'update:modelValue', value: T | T[]): void
}>()
const appConfig = useAppConfig()
const shape = computed(() => props.shape ?? appConfig.nui.defaultShapes?.input)
Expand Down Expand Up @@ -153,6 +159,7 @@ const id = useNinjaId(() => props.id)
:id="id"
ref="inputRef"
v-model="value"
:value="props.value"
:true-value="props.trueValue"
:false-value="props.falseValue"
:class="props.classes?.input"
Expand Down
26 changes: 15 additions & 11 deletions components/form/BaseCheckboxAnimated.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup lang="ts" generic="T extends any = boolean">
defineOptions({
inheritAttrs: false,
})
Expand All @@ -8,7 +8,7 @@ const props = withDefaults(
/**
* The value of the component.
*/
value?: any
value?: T
/**
* The form input identifier.
Expand All @@ -18,17 +18,17 @@ const props = withDefaults(
/**
* The model value of the component.
*/
modelValue?: any
modelValue?: T | T[]
/**
* The value to set when the component is checked.
*/
trueValue?: any
trueValue?: T
/**
* The value to set when the component is unchecked.
*/
falseValue?: any
falseValue?: T
/** The color of the checkbox. Can be 'default', 'primary', 'info', 'success', 'warning', or 'danger' */
color?:
Expand Down Expand Up @@ -63,9 +63,9 @@ const props = withDefaults(
{
id: undefined,
value: undefined,
trueValue: true,
falseValue: false,
modelValue: false,
trueValue: true as any,
falseValue: false as any,
modelValue: undefined,
color: undefined,
classes: () => ({
wrapper: [],
Expand All @@ -75,11 +75,11 @@ const props = withDefaults(
},
)
const emits = defineEmits<{
(e: 'update:modelValue', value: any): void
(e: 'update:modelValue', value: T | T[]): void
}>()
const value = useVModel(props, 'modelValue', emits, {
passive: true,
})
}) as any
const element = ref<HTMLElement>()
const inputRef = ref<HTMLInputElement>()
Expand All @@ -92,7 +92,11 @@ const checked = computed(() => {
return false
}
return props.value === undefined ? false : value.value.includes(props.value)
return props.value === undefined
? false
: Array.isArray(value.value)
? value.value.includes(props.value)
: value.value === props.value
})
const colorStyle = {
Expand Down
29 changes: 18 additions & 11 deletions components/form/BaseCheckboxHeadless.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup lang="ts" generic="T extends any = boolean">
defineOptions({
inheritAttrs: false,
})
Expand All @@ -10,20 +10,25 @@ const props = withDefaults(
*/
label?: string
/**
* Defines the value of the checkbox when it's checked.
*/
value?: T
/**
* The value to set when the checkbox is checked.
*/
trueValue?: string | number | boolean
trueValue?: T
/**
* The value to set when the checkbox is unchecked.
*/
falseValue?: string | number | boolean
falseValue?: T
/**
* The model value of the checkbox.
*/
modelValue?: any
modelValue?: T | T[]
/**
* The form input identifier.
Expand All @@ -32,19 +37,20 @@ const props = withDefaults(
}>(),
{
modelValue: undefined,
value: undefined,
id: undefined,
label: undefined,
trueValue: true,
falseValue: false,
trueValue: true as any,
falseValue: false as any,
},
)
const emits = defineEmits<{
(e: 'update:modelValue', value: string | number | boolean): void
(e: 'update:modelValue', value: T | T[]): void
}>()
const inputRef = ref<HTMLInputElement>()
const value = useVModel(props, 'modelValue', emits, {
const internal = useVModel(props, 'modelValue', emits, {
passive: true,
})
}) as any
defineExpose({
/**
Expand All @@ -69,14 +75,15 @@ const id = useNinjaId(() => props.id)
<input
:id="id"
ref="inputRef"
v-model="value"
v-model="internal"
:value="props.value"
:true-value="props.trueValue"
:false-value="props.falseValue"
v-bind="$attrs"
class="peer absolute inset-0 z-20 h-full w-full cursor-pointer opacity-0"
type="checkbox"
/>
<slot v-bind="{ value }"></slot>
<slot v-bind="{ value: internal }"></slot>
</div>
</div>
</template>
2 changes: 1 addition & 1 deletion components/form/BaseListbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ const props = withDefaults(
},
)
const emits = defineEmits<{
(event: 'update:modelValue', value?: T): void
(event: 'update:modelValue', value?: T | T[]): void
}>()
const appConfig = useAppConfig()
const shape = computed(() => props.shape ?? appConfig.nui.defaultShapes?.input)
Expand Down

0 comments on commit 9d1e985

Please sign in to comment.