mirror of
https://github.com/tabler/tabler.git
synced 2026-10-12 21:27:06 +04:00
94 lines
3.8 KiB
Plaintext
94 lines
3.8 KiB
Plaintext
---
|
|
// Demo select fed from @data/selects.json (+ people); builds the option list and delegates rendering to ui/Select.
|
|
import selects from '@data/selects.json';
|
|
import { people } from '@shared/lib/people'
|
|
import type { FormValidationState } from '@shared/lib/tokens';
|
|
import { firstLetters } from '@shared/lib/string-format';
|
|
import Select from '@ui/Select.astro';
|
|
import type { SelectOption, SelectOptgroup } from '@ui/Select.astro';
|
|
|
|
interface Props {
|
|
id?: string;
|
|
/** key into @data/selects.json (default 'people') */
|
|
key?: string;
|
|
class?: string;
|
|
state?: FormValidationState | undefined;
|
|
placeholder?: string;
|
|
/** option decoration: 'avatar' | 'flag' | 'label' | 'signal' */
|
|
indicator?: string;
|
|
/** plain value list — overrides the selects.json lookup */
|
|
values?: string[];
|
|
}
|
|
|
|
const {
|
|
id: idProp,
|
|
key: keyProp,
|
|
class: className,
|
|
state,
|
|
placeholder,
|
|
indicator,
|
|
values,
|
|
} = Astro.props;
|
|
|
|
const id = idProp ?? keyProp;
|
|
if (!id) {
|
|
throw new Error('DataSelect: pass an `id` or a `key` — the select needs one for its id');
|
|
}
|
|
const key = keyProp ?? 'people';
|
|
let data = (selects as Record<string, any>)[key];
|
|
if (!data && !values) {
|
|
throw new Error(`DataSelect: unknown key "${key}" — not in @data/selects.json`);
|
|
}
|
|
// `values` alone needs no selects.json entry.
|
|
data ??= {};
|
|
|
|
const isMultiple = Boolean(data.multiple);
|
|
|
|
// `value` in selects.json marks the preselected option(s): a string/number or an array of them.
|
|
const preselected = new Set<string>(
|
|
(Array.isArray(data.value) ? data.value : data.value === undefined ? [] : [data.value]).map(String),
|
|
);
|
|
const isSelected = (value: string) => preselected.has(value);
|
|
|
|
// Same markup as ui/Signal.astro, as a string: TomSelect renders the indicator from an attribute.
|
|
const signalHtml = (value: number, color?: string) =>
|
|
`<span class="signal${color ? ` signal-${color}` : ''}" aria-hidden="true">${[1, 2, 3].map((bar) => `<span class="signal-bar${bar <= value ? ' active' : ''}"></span>`).join('')}</span>`;
|
|
|
|
// Build the option list.
|
|
let options: SelectOption[] = [];
|
|
let optgroups: SelectOptgroup[] = [];
|
|
|
|
if (values) {
|
|
options = values.map((v) => ({ value: v, text: v }));
|
|
} else if (data.data === 'people') {
|
|
options = people.slice(0, 20).map((person) => {
|
|
let custom: string | undefined;
|
|
if (indicator === 'avatar') {
|
|
custom = person.photo
|
|
? `<span class="avatar avatar-xs" style="background-image: url(./${person.photo})"></span>`
|
|
: `<span class="avatar avatar-xs">${firstLetters(person.full_name ?? '')}</span>`;
|
|
}
|
|
const value = String(person.id);
|
|
return { value, text: person.full_name ?? '', custom, selected: isSelected(value) };
|
|
});
|
|
} else if (data.data === 'optgroup') {
|
|
optgroups = (data.options as { title: string; options: string[] }[]).map((group) => ({
|
|
label: group.title,
|
|
options: group.options.map((option) => ({ value: option, text: option, selected: isSelected(option) })),
|
|
}));
|
|
} else if (Array.isArray(data.options)) {
|
|
options = (data.options as string[]).map((option) => ({ value: option, text: option, selected: isSelected(option) }));
|
|
} else if (data.options) {
|
|
// object of { key: { name, flag?, label?, signal?, color?, selected? } } — with optional indicator
|
|
options = Object.entries(data.options as Record<string, any>).map(([optKey, v]) => {
|
|
let custom: string | undefined;
|
|
if (indicator === 'flag') custom = `<span class="flag flag-xs flag-country-${v.flag}"></span>`;
|
|
else if (indicator === 'label') custom = `<span class="badge bg-primary-lt">${v.label}</span>`;
|
|
else if (indicator === 'signal') custom = signalHtml(v.signal, v.color);
|
|
return { value: optKey, text: v.name, custom, selected: Boolean(v.selected) || isSelected(optKey) };
|
|
});
|
|
}
|
|
---
|
|
|
|
<Select id={id} class={className} state={state} placeholder={placeholder} multiple={isMultiple} options={options} optgroups={optgroups} />
|