hippofish/packages/client/src/components/form/radios.vue
2023-05-15 16:19:33 -04:00

117 lines
1.8 KiB
Vue

<script lang="ts">
import { defineComponent, h } from "vue";
import MkRadio from "./radio.vue";
export default defineComponent({
components: {
MkRadio,
},
props: {
modelValue: {
required: false,
},
},
data() {
return {
value: this.modelValue,
};
},
watch: {
value() {
this.$emit("update:modelValue", this.value);
},
},
render() {
let options = this.$slots.default();
const label = this.$slots.label && this.$slots.label();
const caption = this.$slots.caption && this.$slots.caption();
// なぜかFragmentになることがあるため
if (options.length === 1 && options[0].props == null)
options = options[0].children;
return h(
"fieldset",
{
class: "novjtcto",
},
[
...(label
? [
h(
"legend",
{
class: "label",
},
[label]
),
]
: []),
h(
"div",
{
class: "body",
},
options.map((option) =>
h(
MkRadio,
{
key: option.key,
value: option.props?.value,
disabled: option.props?.disabled,
modelValue: this.value,
"onUpdate:modelValue": (value) =>
(this.value = value),
},
option.children
)
)
),
...(caption
? [
h(
"div",
{
class: "caption",
},
[caption]
),
]
: []),
]
);
},
});
</script>
<style lang="scss">
.novjtcto {
border: 0;
padding: 0;
> .label {
font-size: 0.85em;
padding: 0 0 8px 0;
user-select: none;
&:empty {
display: none;
}
}
> .body {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
> .caption {
font-size: 0.85em;
padding: 8px 0 0 0;
color: var(--fgTransparentWeak);
&:empty {
display: none;
}
}
}
</style>