|
8 | 8 | :class="inputClasses"
|
9 | 9 | type="checkbox"
|
10 | 10 | :disabled="disabled"
|
11 |
| - :required="name && required" |
| 11 | + :required="!!name && !!required" |
12 | 12 | :name="name"
|
13 | 13 | :form="form"
|
14 | 14 | :aria-label="ariaLabel"
|
15 | 15 | :aria-labelledby="ariaLabelledBy"
|
16 |
| - :aria-required="name && required ? 'true' : null" |
| 16 | + :aria-required="name && required ? 'true' : undefined" |
17 | 17 | :value="value"
|
18 | 18 | :indeterminate="indeterminate"
|
19 | 19 | @focus="isFocused = true"
|
|
29 | 29 | </div>
|
30 | 30 | </template>
|
31 | 31 |
|
32 |
| -<script lang="ts"> |
33 |
| -import {getClasses, getInputClasses, getLabelClasses} from '../../composables/useFormCheck' |
34 |
| -import {computed, defineComponent, onMounted, PropType, Ref, ref} from 'vue' |
35 |
| -import {InputSize} from '../../types' |
36 |
| -import useId from '../../composables/useId' |
| 32 | +<script setup lang="ts"> |
| 33 | +// import type {BFormCheckboxEmits, BFormCheckboxProps} from '@/types/components' |
| 34 | +import {getClasses, getInputClasses, getLabelClasses} from '@/composables/useFormCheck' |
| 35 | +import type {ButtonVariant, InputSize} from '@/types' |
| 36 | +import useId from '@/composables/useId' |
37 | 37 |
|
38 |
| -export default defineComponent({ |
39 |
| - name: 'BFormCheckbox', |
40 |
| - inheritAttrs: false, |
41 |
| - props: { |
42 |
| - id: {type: String, default: undefined}, |
43 |
| - ariaLabel: {type: String}, |
44 |
| - ariaLabelledBy: {type: String}, |
45 |
| - autofocus: {type: Boolean, default: false}, |
46 |
| - plain: {type: Boolean, default: false}, |
47 |
| - button: {type: Boolean, default: false}, |
48 |
| - switch: {type: Boolean, default: false}, |
49 |
| - disabled: {type: Boolean, default: false}, |
50 |
| - buttonVariant: {type: String, default: 'secondary'}, |
51 |
| - form: {type: String}, |
52 |
| - indeterminate: {type: Boolean}, |
53 |
| - inline: {type: Boolean, default: false}, |
54 |
| - name: {type: String}, |
55 |
| - required: {type: Boolean, default: undefined}, |
56 |
| - size: {type: String as PropType<InputSize>, default: 'md'}, |
57 |
| - state: {type: Boolean, default: null}, |
58 |
| - uncheckedValue: {type: [Boolean, String, Array, Object, Number], default: false}, |
59 |
| - value: {type: [Boolean, String, Array, Object, Number], default: true}, |
60 |
| - modelValue: {type: [Boolean, String, Array, Object, Number], default: null}, |
61 |
| - }, |
62 |
| - emits: ['update:modelValue', 'input', 'change'], |
63 |
| - setup(props, {emit}) { |
64 |
| - const computedId = useId(props.id, 'form-check') |
65 |
| - const input: Ref<HTMLElement> = ref(null as unknown as HTMLElement) |
66 |
| - const isFocused = ref(false) |
| 38 | +interface BFormCheckboxProps { |
| 39 | + ariaLabel?: string |
| 40 | + ariaLabelledBy?: string |
| 41 | + form?: string |
| 42 | + indeterminate?: boolean |
| 43 | + name?: string |
| 44 | + id?: string |
| 45 | + autofocus?: boolean |
| 46 | + plain?: boolean |
| 47 | + button?: boolean |
| 48 | + switch?: boolean |
| 49 | + disabled?: boolean |
| 50 | + buttonVariant?: ButtonVariant |
| 51 | + inline?: boolean |
| 52 | + required?: boolean |
| 53 | + size?: InputSize |
| 54 | + state?: boolean |
| 55 | + uncheckedValue?: Array<unknown> | Set<unknown> | boolean |
| 56 | + value?: Array<unknown> | Set<unknown> | boolean |
| 57 | + modelValue?: Array<unknown> | Set<unknown> | boolean |
| 58 | +} |
67 | 59 |
|
68 |
| - const localValue = computed({ |
69 |
| - get: () => { |
70 |
| - if (props.uncheckedValue) { |
71 |
| - if (!Array.isArray(props.modelValue)) { |
72 |
| - return props.modelValue === props.value |
73 |
| - } |
74 |
| - return props.modelValue.indexOf(props.value) > -1 |
75 |
| - } |
76 |
| - return props.modelValue |
77 |
| - }, |
78 |
| - set: (newValue: any) => { |
79 |
| - let emitValue = newValue |
80 |
| - if (!Array.isArray(props.modelValue)) { |
81 |
| - emitValue = newValue ? props.value : props.uncheckedValue |
82 |
| - } else { |
83 |
| - if (props.uncheckedValue) { |
84 |
| - emitValue = props.modelValue |
85 |
| - if (newValue) { |
86 |
| - if (emitValue.indexOf(props.uncheckedValue) > -1) |
87 |
| - emitValue.splice(emitValue.indexOf(props.uncheckedValue), 1) |
88 |
| - emitValue.push(props.value) |
89 |
| - } else { |
90 |
| - if (emitValue.indexOf(props.value) > -1) |
91 |
| - emitValue.splice(emitValue.indexOf(props.value), 1) |
92 |
| - emitValue.push(props.uncheckedValue) |
93 |
| - } |
94 |
| - } |
95 |
| - } |
96 |
| - emit('input', emitValue) |
97 |
| - emit('update:modelValue', emitValue) |
98 |
| - emit('change', emitValue) |
99 |
| - }, |
100 |
| - }) |
| 60 | +const props = withDefaults(defineProps<BFormCheckboxProps>(), { |
| 61 | + id: undefined, |
| 62 | + autofocus: false, |
| 63 | + plain: false, |
| 64 | + button: false, |
| 65 | + switch: false, |
| 66 | + disabled: false, |
| 67 | + buttonVariant: 'secondary', |
| 68 | + inline: false, |
| 69 | + required: undefined, |
| 70 | + size: 'md', |
| 71 | + state: undefined, |
| 72 | + uncheckedValue: false, |
| 73 | + value: true, |
| 74 | + modelValue: undefined, |
| 75 | +}) |
101 | 76 |
|
102 |
| - const isChecked = computed(() => { |
103 |
| - if (Array.isArray(props.modelValue)) { |
104 |
| - return props.modelValue.indexOf(props.value) > -1 |
105 |
| - } |
106 |
| - return JSON.stringify(props.modelValue) === JSON.stringify(props.value) |
107 |
| - }) |
| 77 | +interface BFormCheckboxEmits { |
| 78 | + (e: 'update:modelValue', value: unknown): void |
| 79 | + (e: 'input', value: unknown): void |
| 80 | + (e: 'change', value: unknown): void |
| 81 | +} |
108 | 82 |
|
109 |
| - const classes = getClasses(props) |
110 |
| - const inputClasses = getInputClasses(props) |
111 |
| - const labelClasses = getLabelClasses(props) |
| 83 | +const emit = defineEmits<BFormCheckboxEmits>() |
112 | 84 |
|
113 |
| - // TODO: make tests compatible with the v-focus directive |
114 |
| - if (props.autofocus) { |
115 |
| - onMounted(() => { |
116 |
| - input.value.focus() |
117 |
| - }) |
118 |
| - } |
| 85 | +const computedId = useId(props.id, 'form-check') |
| 86 | +const input = ref<HTMLElement>(null as unknown as HTMLElement) |
| 87 | +const isFocused = ref<boolean>(false) |
119 | 88 |
|
120 |
| - return { |
121 |
| - input, |
122 |
| - computedId, |
123 |
| - classes, |
124 |
| - inputClasses, |
125 |
| - labelClasses, |
126 |
| - localValue, |
127 |
| - isChecked, |
128 |
| - isFocused, |
| 89 | +const localValue = computed({ |
| 90 | + get: () => { |
| 91 | + if (props.uncheckedValue) { |
| 92 | + if (!Array.isArray(props.modelValue)) { |
| 93 | + return props.modelValue === props.value |
| 94 | + } |
| 95 | + return props.modelValue.indexOf(props.value) > -1 |
129 | 96 | }
|
| 97 | + return props.modelValue |
130 | 98 | },
|
| 99 | + set: (newValue: any) => { |
| 100 | + let emitValue = newValue |
| 101 | + if (!Array.isArray(props.modelValue)) { |
| 102 | + emitValue = newValue ? props.value : props.uncheckedValue |
| 103 | + } else { |
| 104 | + if (props.uncheckedValue) { |
| 105 | + emitValue = props.modelValue |
| 106 | + if (newValue) { |
| 107 | + if (emitValue.indexOf(props.uncheckedValue) > -1) |
| 108 | + emitValue.splice(emitValue.indexOf(props.uncheckedValue), 1) |
| 109 | + emitValue.push(props.value) |
| 110 | + } else { |
| 111 | + if (emitValue.indexOf(props.value) > -1) |
| 112 | + emitValue.splice(emitValue.indexOf(props.value), 1) |
| 113 | + emitValue.push(props.uncheckedValue) |
| 114 | + } |
| 115 | + } |
| 116 | + } |
| 117 | + emit('input', emitValue) |
| 118 | + emit('update:modelValue', emitValue) |
| 119 | + emit('change', emitValue) |
| 120 | + }, |
| 121 | +}) |
| 122 | +
|
| 123 | +const isChecked = computed<boolean>(() => { |
| 124 | + if (Array.isArray(props.modelValue)) { |
| 125 | + return props.modelValue.indexOf(props.value) > -1 |
| 126 | + } |
| 127 | + return JSON.stringify(props.modelValue) === JSON.stringify(props.value) |
| 128 | +}) |
| 129 | +
|
| 130 | +const classes = getClasses(props) |
| 131 | +const inputClasses = getInputClasses(props) |
| 132 | +const labelClasses = getLabelClasses(props) |
| 133 | +
|
| 134 | +// TODO: make tests compatible with the v-focus directive |
| 135 | +onMounted((): void => { |
| 136 | + if (props.autofocus) { |
| 137 | + input.value.focus() |
| 138 | + } |
| 139 | +}) |
| 140 | +</script> |
| 141 | + |
| 142 | +<script lang="ts"> |
| 143 | +import {computed, defineComponent, onMounted, ref} from 'vue' |
| 144 | +export default defineComponent({ |
| 145 | + inheritAttrs: false, |
131 | 146 | })
|
132 | 147 | </script>
|
0 commit comments