feat(isac): support deferred item icons
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ItemIcon from './ItemIcon.svelte';
|
||||
|
||||
let {
|
||||
items,
|
||||
value = $bindable(''),
|
||||
@@ -24,7 +26,7 @@
|
||||
<div class="builder-picker">
|
||||
<span>{label}</span>
|
||||
<button type="button" class="builder-picker-current" aria-expanded={open} onclick={() => open = !open}>
|
||||
{#if selected?.iconUrl}<img src={selected.iconUrl} alt=""/>{:else}<i>◇</i>{/if}
|
||||
<ItemIcon src={selected?.iconUrl} alt=""/>
|
||||
<b>{selected?.name ?? 'SELECT ITEM'}</b><small>{selected?.category ?? (selected ? 'EQUIPPED' : 'UNASSIGNED')}</small><em>{open ? '×' : '+'}</em>
|
||||
</button>
|
||||
{#if open}
|
||||
@@ -34,7 +36,7 @@
|
||||
{#if selected}<button type="button" class="builder-picker-clear" onclick={() => choose('')}><i>×</i><span><b>CLEAR SLOT</b><small>REMOVE CURRENT SELECTION</small></span><em>CLEAR</em></button>{/if}
|
||||
{#each results as item}
|
||||
<button type="button" class:selected={item.id === value} disabled={disabledIds.includes(item.id)} onclick={() => choose(item.id)}>
|
||||
{#if item.iconUrl}<img src={item.iconUrl} alt=""/>{:else}<i>◇</i>{/if}
|
||||
<ItemIcon src={item.iconUrl} alt=""/>
|
||||
<span><b>{item.name}</b><small>{item.category ?? 'AVAILABLE'}</small></span><em>{item.id === value ? 'EQUIPPED' : disabledIds.includes(item.id) ? 'CONFLICT' : 'SELECT'}</em>
|
||||
</button>
|
||||
{:else}<p>NO MATCHING ITEMS</p>{/each}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ItemIcon from './ItemIcon.svelte';
|
||||
|
||||
let {
|
||||
label,
|
||||
name,
|
||||
@@ -42,7 +44,7 @@
|
||||
<label title={item.name}>
|
||||
<input type="radio" {name} value={item.id} checked={value === item.id} {required} aria-label={item.name} onchange={() => choose(item.id)}/>
|
||||
<span>
|
||||
{#if item.iconUrl}<img src={item.iconUrl} alt=""/>{:else}<i>{item.name.slice(0,2).toUpperCase()}</i>{/if}
|
||||
<ItemIcon src={item.iconUrl} alt=""/>
|
||||
<b>{item.name}</b>
|
||||
{#if item.category}<small>{item.category}</small>{/if}
|
||||
</span>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<fieldset class="icon-upload-field">
|
||||
<legend>{label}</legend>
|
||||
<ImageUploadInput name="icon" accept="image/svg+xml,image/png,image/webp,image/avif" {currentUrl} {resetToken} emptyLabel="NO ICON" browseLabel={currentUrl ? 'REPLACE ICON' : 'CHOOSE ICON'}/>
|
||||
<ImageUploadInput name="icon" accept="image/svg+xml,image/png,image/webp,image/avif" {currentUrl} placeholderUrl="/missing-item-icon.svg" {resetToken} emptyLabel="ICON AWAITING CONTRIBUTION" browseLabel={currentUrl ? 'REPLACE ICON' : 'ADD ICON'}/>
|
||||
{#if currentUrl}<label class="icon-remove"><input name="removeIcon" type="checkbox" value="1"/><span>REMOVE CURRENT ICON</span></label>{/if}
|
||||
<small>TRANSPARENT SVG, PNG, WEBP, OR AVIF · 2 MiB MAX</small>
|
||||
<small>OPTIONAL · MAY BE CONTRIBUTED LATER · TRANSPARENT SVG, PNG, WEBP, OR AVIF · 2 MiB MAX</small>
|
||||
</fieldset>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
accept,
|
||||
required = false,
|
||||
currentUrl = '',
|
||||
placeholderUrl = '',
|
||||
emptyLabel = 'NO IMAGE',
|
||||
browseLabel = 'CHOOSE FILE',
|
||||
resetToken = 0
|
||||
@@ -14,6 +15,7 @@
|
||||
accept: string;
|
||||
required?: boolean;
|
||||
currentUrl?: string | null;
|
||||
placeholderUrl?: string | null;
|
||||
emptyLabel?: string;
|
||||
browseLabel?: string;
|
||||
resetToken?: string | number;
|
||||
@@ -120,8 +122,8 @@
|
||||
>
|
||||
<input bind:this={input} class="image-file-input" {name} type="file" {accept} {required} onchange={choose}/>
|
||||
<div class="image-upload-preview">
|
||||
{#if previewUrl || currentUrl}
|
||||
<img src={previewUrl || currentUrl || ''} alt="Selected upload preview"/>
|
||||
{#if previewUrl || currentUrl || placeholderUrl}
|
||||
<img class:missing-item-icon={!previewUrl && !currentUrl && Boolean(placeholderUrl)} src={previewUrl || currentUrl || placeholderUrl || ''} alt={previewUrl || currentUrl ? 'Selected upload preview' : emptyLabel}/>
|
||||
{:else}
|
||||
<span>{emptyLabel}</span>
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
let {
|
||||
src = '',
|
||||
alt = '',
|
||||
className = ''
|
||||
}: {
|
||||
src?: string | null;
|
||||
alt?: string;
|
||||
className?: string;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<img src={src || '/missing-item-icon.svg'} {alt} class:missing-item-icon={!src} class={className}/>
|
||||
Reference in New Issue
Block a user