mirror of
https://github.com/versia-pub/frontend.git
synced 2026-03-13 19:49:16 +01:00
refactor: ♻️ Rewrite entire preferences panel and emoji manager from scratch
This commit is contained in:
parent
0443a37508
commit
17bb75733c
51 changed files with 1982 additions and 17 deletions
37
components/preferences2/types/base.vue
Normal file
37
components/preferences2/types/base.vue
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<div class="grid grid-cols-[minmax(0,1fr)_auto] gap-2 hover:bg-muted/40 duration-75 p-4">
|
||||
<div class="flex flex-col gap-1">
|
||||
<h3 class="text-sm font-semibold tracking-tight">{{ pref.options.name }}</h3>
|
||||
<small v-if="pref.options.description" class="text-xs font-medium leading-none text-muted-foreground">{{
|
||||
pref.options.description }}</small>
|
||||
</div>
|
||||
<div class="flex items-center justify-end">
|
||||
<slot :value="value" :set-value="setValue" />
|
||||
</div>
|
||||
<slot name="extra" :value="value" :set-value="setValue" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Preference } from "../types";
|
||||
|
||||
const { pref } = defineProps<{
|
||||
pref: Preference<any>;
|
||||
}>();
|
||||
|
||||
const value = ref<any>(pref.options.defaultValue);
|
||||
const setValue = (newValue: MaybeRef<any>) => {
|
||||
value.value = toValue(newValue);
|
||||
};
|
||||
|
||||
defineSlots<{
|
||||
default(props: {
|
||||
value: any;
|
||||
setValue: (value: MaybeRef<any>) => void;
|
||||
}): any;
|
||||
extra(props: {
|
||||
value: any;
|
||||
setValue: (value: MaybeRef<any>) => void;
|
||||
}): any;
|
||||
}>();
|
||||
</script>
|
||||
15
components/preferences2/types/boolean.vue
Normal file
15
components/preferences2/types/boolean.vue
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<template>
|
||||
<Base :pref="pref" v-slot="{ setValue, value }">
|
||||
<Switch @update:model-value="setValue" :model-value="value" />
|
||||
</Base>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Switch } from "~/components/ui/switch";
|
||||
import type { BooleanPreference } from "../types";
|
||||
import Base from "./base.vue";
|
||||
|
||||
const { pref } = defineProps<{
|
||||
pref: BooleanPreference;
|
||||
}>();
|
||||
</script>
|
||||
34
components/preferences2/types/code.vue
Normal file
34
components/preferences2/types/code.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<template>
|
||||
<Collapsible as-child>
|
||||
<Base :pref="pref">
|
||||
<template #default>
|
||||
<CollapsibleTrigger as-child>
|
||||
<Button variant="outline">
|
||||
Open code
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</template>
|
||||
<template #extra="{ setValue, value }">
|
||||
<CollapsibleContent class="col-span-2 mt-2">
|
||||
<Textarea :rows="10" :model-value="value" @update:model-value="setValue" />
|
||||
</CollapsibleContent>
|
||||
</template>
|
||||
</Base>
|
||||
</Collapsible>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Button } from "~/components/ui/button";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "~/components/ui/collapsible";
|
||||
import { Textarea } from "~/components/ui/textarea";
|
||||
import type { CodePreference } from "../types";
|
||||
import Base from "./base.vue";
|
||||
|
||||
const { pref } = defineProps<{
|
||||
pref: CodePreference;
|
||||
}>();
|
||||
</script>
|
||||
39
components/preferences2/types/multiselect.vue
Normal file
39
components/preferences2/types/multiselect.vue
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<template>
|
||||
<Base :pref="pref" v-slot="{ setValue, value }">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="outline">
|
||||
Pick
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="w-56">
|
||||
<DropdownMenuCheckboxItem v-for="[option, title] in Object.entries(pref.options.options)" :key="option"
|
||||
:model-value="value.includes(option)" @update:model-value="checked => {
|
||||
if (checked) {
|
||||
setValue([...value, option]);
|
||||
} else {
|
||||
setValue(value.filter((v: any) => v !== option));
|
||||
}
|
||||
}">
|
||||
{{ title }}
|
||||
</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</Base>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Button } from "~/components/ui/button";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuTrigger,
|
||||
} from "~/components/ui/dropdown-menu";
|
||||
import type { MultiSelectPreference } from "../types";
|
||||
import Base from "./base.vue";
|
||||
|
||||
const { pref } = defineProps<{
|
||||
pref: MultiSelectPreference<string>;
|
||||
}>();
|
||||
</script>
|
||||
27
components/preferences2/types/number.vue
Normal file
27
components/preferences2/types/number.vue
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<Base :pref="pref" v-slot="{ setValue, value }">
|
||||
<NumberField :model-value="value" @update:model-value="setValue" :min="pref.options.min" :max="pref.options.max" :step="pref.options.integer ? 1 : pref.options.step">
|
||||
<NumberFieldContent>
|
||||
<NumberFieldDecrement />
|
||||
<NumberFieldInput />
|
||||
<NumberFieldIncrement />
|
||||
</NumberFieldContent>
|
||||
</NumberField>
|
||||
</Base>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
NumberField,
|
||||
NumberFieldContent,
|
||||
NumberFieldDecrement,
|
||||
NumberFieldIncrement,
|
||||
NumberFieldInput,
|
||||
} from "~/components/ui/number-field";
|
||||
import type { NumberPreference } from "../types";
|
||||
import Base from "./base.vue";
|
||||
|
||||
const { pref } = defineProps<{
|
||||
pref: NumberPreference;
|
||||
}>();
|
||||
</script>
|
||||
33
components/preferences2/types/select.vue
Normal file
33
components/preferences2/types/select.vue
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<template>
|
||||
<Base :pref="pref" v-slot="{ setValue, value }">
|
||||
<Select :model-value="value" @update:model-value="setValue">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select an option" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem v-for="[val, title] in Object.entries(pref.options.options)" :value="val">
|
||||
{{ title }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Base>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "~/components/ui/select";
|
||||
import type { SelectPreference } from "../types";
|
||||
import Base from "./base.vue";
|
||||
|
||||
const { pref } = defineProps<{
|
||||
pref: SelectPreference<string>;
|
||||
}>();
|
||||
</script>
|
||||
15
components/preferences2/types/text.vue
Normal file
15
components/preferences2/types/text.vue
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<template>
|
||||
<Base :pref="pref" v-slot="{ setValue, value }">
|
||||
<Input placeholder="Content here..." :model-value="value" @update:model-value="setValue" />
|
||||
</Base>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Input } from "~/components/ui/input";
|
||||
import type { TextPreference } from "../types";
|
||||
import Base from "./base.vue";
|
||||
|
||||
const { pref } = defineProps<{
|
||||
pref: TextPreference;
|
||||
}>();
|
||||
</script>
|
||||
34
components/preferences2/types/url.vue
Normal file
34
components/preferences2/types/url.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<template>
|
||||
<Collapsible as-child>
|
||||
<Base :pref="pref">
|
||||
<template #default>
|
||||
<CollapsibleTrigger as-child>
|
||||
<Button variant="outline">
|
||||
Edit URL
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
</template>
|
||||
<template #extra="{ setValue, value }">
|
||||
<CollapsibleContent class="col-span-2 mt-2">
|
||||
<UrlInput placeholder="Type URL or domain here..." :model-value="value" @update:model-value="setValue" />
|
||||
</CollapsibleContent>
|
||||
</template>
|
||||
</Base>
|
||||
</Collapsible>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Button } from "~/components/ui/button";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "~/components/ui/collapsible";
|
||||
import { Input, UrlInput } from "~/components/ui/input";
|
||||
import type { TextPreference } from "../types";
|
||||
import Base from "./base.vue";
|
||||
|
||||
const { pref } = defineProps<{
|
||||
pref: TextPreference;
|
||||
}>();
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue