chore: Typescript: Rewrite VehicleIcon (#21633)

Co-authored-by: Michael Geers <michael@geers.tv>
This commit is contained in:
Maschga 2025-06-06 12:44:53 +02:00 • committed by GitHub
parent b6c1fa70db
commit 50657c1d8f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 312 additions and 231 deletions

View file

@ -1,3 +1,4 @@
import { ICON_SIZE } from "@/types/evcc";
import MultiIcon from "./MultiIcon.vue";
import type { Meta, StoryFn } from "@storybook/vue3";
@ -10,7 +11,8 @@ export default {
description: "Number of icons to display",
},
size: {
control: { type: "select", options: ["sm", "md", "lg", "xl"] },
options: Object.values(ICON_SIZE),
control: { type: "select" },
description: "Size of the icons",
},
},
@ -41,5 +43,5 @@ export const AllCounts: StoryFn<typeof MultiIcon> = (args) => ({
});
AllCounts.args = {
size: "xl",
size: ICON_SIZE.XL,
};

View file

@ -3,7 +3,7 @@
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { defineComponent, type PropType } from "vue";
import _1 from "./1.vue";
import _2 from "./2.vue";
import _3 from "./3.vue";
@ -14,6 +14,7 @@ import _7 from "./7.vue";
import _8 from "./8.vue";
import _9 from "./9.vue";
import Plus from "./Plus.vue";
import { ICON_SIZE } from "@/types/evcc";
const icons = {
_1,
@ -31,7 +32,7 @@ export default defineComponent({
name: "MultiIcon",
props: {
count: { type: Number, default: 1 },
size: { type: String, default: "s" },
size: { type: String as PropType<ICON_SIZE>, default: ICON_SIZE.S },
},
computed: {
icon() {

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Airpurifier",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Battery",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Bike",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Bulb",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Bus",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Climate",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Coffeemaker",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Compute",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Cooking",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Cooler",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Desktop",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Device",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Dishwasher",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Dryer",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Floorlamp",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Plug",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Heater",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Heatexchange",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Heatpump",
};
});
</script>

View file

@ -7,8 +7,9 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Kettle",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Laundry",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Laundry2",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Machine",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Meter",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Microwave",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Moped",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Motorcycle",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Pump",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Rickshaw",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Rocket",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Scooter",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Shuttle",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "SmartConsumer",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Taxi",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Tool",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Tractor",
};
});
</script>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Van",
};
});
</script>

View file

@ -1,104 +0,0 @@
import VehicleIcon from "./VehicleIcon.vue";
const icons = [
"car",
"bike",
"bus",
"moped",
"motorcycle",
"rocket",
"scooter",
"taxi",
"tractor",
"rickshaw",
"shuttle",
"van",
"airpurifier",
"battery",
"bulb",
"climate",
"coffeemaker",
"compute",
"cooking",
"cooler",
"desktop",
"device",
"dishwasher",
"dryer",
"floorlamp",
"generic",
"heater",
"heatexchange",
"heatpump",
"kettle",
"laundry",
"laundry2",
"machine",
"meter",
"smartconsumer",
"microwave",
"pump",
"tool",
"waterheater",
];
export default {
title: "VehicleIcon/VehicleIcon",
component: VehicleIcon,
argTypes: {
name: {
control: "select",
options: icons,
},
names: { control: "object" },
size: {
control: "select",
options: ["sm", "md", "lg", "xl"],
defaultValue: "xl",
},
},
};
const Template = (args) => ({
components: { VehicleIcon },
setup() {
return { args };
},
template: '<VehicleIcon v-bind="args" />',
});
// Single icon story that can be controlled via args
export const SingleIcon = Template.bind({});
SingleIcon.args = {
name: "car",
size: "xl",
};
// Multiple icons stories
export const TwoCars = Template.bind({});
TwoCars.args = {
names: ["car", "car"],
size: "xl",
};
export const CarAndThreeBikes = Template.bind({});
CarAndThreeBikes.args = {
names: ["car", "bike", "bike", "bike"],
size: "xl",
};
// Story showing all icons at once
export const AllIcons = () => ({
components: { VehicleIcon },
setup() {
return { icons };
},
template: `
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 30px;">
<div v-for="icon in icons" :key="icon" style="display: flex; flex-direction: column; align-items: center; gap: 10px;">
<VehicleIcon :name="icon" size="xl" />
<small>{{ icon }}</small>
</div>
</div>
`,
});

View file

@ -0,0 +1,106 @@
import { ICON_SIZE } from "@/types/evcc";
import VehicleIcon from "./VehicleIcon.vue";
import type { Meta, StoryFn } from "@storybook/vue3";
const icons = [
"car",
"bike",
"bus",
"moped",
"motorcycle",
"rocket",
"scooter",
"taxi",
"tractor",
"rickshaw",
"shuttle",
"van",
"airpurifier",
"battery",
"bulb",
"climate",
"coffeemaker",
"compute",
"cooking",
"cooler",
"desktop",
"device",
"dishwasher",
"dryer",
"floorlamp",
"generic",
"heater",
"heatexchange",
"heatpump",
"kettle",
"laundry",
"laundry2",
"machine",
"meter",
"smartconsumer",
"microwave",
"pump",
"tool",
"waterheater",
];
export default {
title: "VehicleIcon/VehicleIcon",
component: VehicleIcon,
argTypes: {
name: {
control: "select",
options: icons,
},
names: { control: "object" },
size: {
control: "select",
options: Object.values(ICON_SIZE),
defaultValue: ICON_SIZE.XL,
},
},
} as Meta<typeof VehicleIcon>;
const Template: StoryFn<typeof VehicleIcon> = (args) => ({
components: { VehicleIcon },
setup() {
return { args };
},
template: '<VehicleIcon v-bind="args" />',
});
// Single icon story that can be controlled via args
export const SingleIcon = Template.bind({});
SingleIcon.args = {
name: "car",
size: ICON_SIZE.XL,
};
// Multiple icons stories
export const TwoCars = Template.bind({});
TwoCars.args = {
names: ["car", "car"],
size: ICON_SIZE.XL,
};
export const CarAndThreeBikes = Template.bind({});
CarAndThreeBikes.args = {
names: ["car", "bike", "bike", "bike"],
size: ICON_SIZE.XL,
};
// Story showing all icons at once
export const AllIcons = () => ({
components: { VehicleIcon },
setup() {
return { icons };
},
template: `
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 30px;">
<div v-for="icon in icons" :key="icon" style="display: flex; flex-direction: column; align-items: center; gap: 10px;">
<VehicleIcon :name="icon" size="xl" />
<small>{{ icon }}</small>
</div>
</div>
`,
});

View file

@ -3,7 +3,8 @@
<MultiIcon v-else :count="count" :size="size"></MultiIcon>
</template>
<script>
<script lang="ts">
import { defineComponent, type Component, type PropType } from "vue";
import "@h2d2/shopicons/es/regular/car3";
import MultiIcon from "../MultiIcon";
@ -45,8 +46,9 @@ import tool from "./Tool.vue";
import tractor from "./Tractor.vue";
import van from "./Van.vue";
import waterheater from "./WaterHeater.vue";
import { ICON_SIZE } from "@/types/evcc";
const icons = {
const icons: Record<string, Component | string> = {
airpurifier,
battery,
bike,
@ -90,20 +92,20 @@ const icons = {
export const ICONS = Object.keys(icons);
export default {
export default defineComponent({
name: "VehicleIcon",
components: { MultiIcon },
props: {
name: { type: String, default: "car" },
names: { type: Array },
size: { type: String, default: "s" },
names: { type: Array as PropType<string[]>, default: () => [] },
size: { type: String as PropType<ICON_SIZE>, default: ICON_SIZE.S },
},
computed: {
uniqueNames() {
return [...new Set(this.names || [this.name])];
uniqueNames(): string[] {
return [...new Set(this.names && this.names.length ? this.names : [this.name])];
},
count() {
return this.names?.length || 0;
return this.names.length;
},
single() {
return this.uniqueNames.length == 1;
@ -112,7 +114,7 @@ export default {
return icons[this.uniqueNames[0]] || `shopicon-regular-car3`;
},
},
};
});
</script>
<style scoped>

View file

@ -7,8 +7,10 @@
</svg>
</template>
<script>
export default {
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "WaterHeater",
};
});
</script>

View file

@ -54,6 +54,14 @@ export enum CURRENCY {
DKK = "DKK",
}
export enum ICON_SIZE {
XS = "xs",
S = "s",
M = "m",
L = "l",
XL = "xl",
}
export enum CHARGE_MODE {
OFF = "off",
NOW = "now",