-
Notifications
You must be signed in to change notification settings - Fork 0
/
Choice.svelte
71 lines (58 loc) · 1.79 KB
/
Choice.svelte
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<script>
import { Dropdown } from '@src/components'
import { gameAssetsUrl } from '@src/utils'
import { _, locale } from 'svelte-intl'
import { findViolations } from './utils'
export let name
export let property
export let values
// only build options for valid candidates
$: options = findCandidates(property, name, values).map(value => ({
value,
label: translate(value),
image: findImage(property, value)
}))
// value must be one of the option because DropDown + Menu are using strict equality
$: value = options.find(candidate => candidate.value === values[name])
// when defauling to first option, mutates values
$: if (!value && options.length) {
setTimeout(() => handleSelection({ detail: options[0] }), 0)
}
function handleSelection({ detail }) {
values[name] = detail.value
}
function translate(key) {
return property.metadata?.[$locale]?.[key] ?? key
}
function findImage(property, key) {
return property.metadata?.images?.[key]
}
function findCandidates(property, name, values) {
const candidates = property.enum
const schema = { type: 'object', properties: { [name]: property } }
const result = candidates.filter(
value => findViolations({ [name]: value }, schema, values).length === 0
)
return result
}
</script>
<label for={name}>{translate('name') + $_('labels.colon')}</label>
<span on:click|preventDefault on:keyup|preventDefault>
<Dropdown id={name} {options} {value} on:select={handleSelection} />
{#if value?.image}
<img src="{gameAssetsUrl}{value.image}" alt="" />
{/if}
</span>
<style lang="postcss">
label {
@apply leading-[2.5] text-right;
}
span {
@apply flex items-start;
}
img {
@apply inline-block ml-4;
max-width: 33vw;
max-height: 50vh;
}
</style>