Files
PhotonVision/photon-client/src/components/common/pv-select.vue
Sam Freund 2372e110f9 TypeCheck Frontend (#2394)
We recently had an error that would've been caught by type checking in the frontend (see #2393). This PR implements type checking so that future errors will be caught.

Additionally, this PR contains miscellaneous frontend cleanup that's tangentially related to type-checking.
2026-05-05 15:24:19 +00:00

71 lines
1.7 KiB
Vue

<script setup lang="ts" generic="T extends string | number">
import { computed } from "vue";
import TooltippedLabel from "@/components/common/pv-tooltipped-label.vue";
export interface SelectItem<TValue extends string | number> {
name: string | number;
value: TValue;
disabled?: boolean;
}
type SelectItems = SelectItem<T>[] | ReadonlyArray<T>;
const value = defineModel<T>({ required: true });
const props = withDefaults(
defineProps<{
label?: string;
tooltip?: string;
selectCols?: number;
disabled?: boolean;
items: SelectItems;
}>(),
{
selectCols: 9,
disabled: false
}
);
const areSelectItems = (items: SelectItems): items is SelectItem<T>[] => typeof items[0] === "object";
// Computed in case items changes
const items = computed<SelectItem<T>[]>(() => {
// Trivial case for empty list; we have no data
if (!props.items.length) {
return [];
}
if (areSelectItems(props.items)) {
return props.items;
}
return props.items.map((item) => ({ name: item, value: item }));
});
</script>
<template>
<div class="d-flex">
<v-col :cols="12 - selectCols" class="d-flex align-center pl-0 pt-10px pb-10px">
<tooltipped-label :tooltip="tooltip" :label="label" />
</v-col>
<v-col :cols="selectCols" class="d-flex align-center pr-0 pt-10px pb-10px">
<v-select
v-model="value"
:items="items"
item-title="name"
item-value="value"
item-props
:disabled="disabled"
hide-details="auto"
variant="underlined"
density="compact"
/>
</v-col>
</div>
</template>
<style scoped>
.v-select {
padding-top: 0px;
margin-top: 0px;
}
</style>