|
|
|
|
@ -8,7 +8,7 @@ import { Soma } from '../../core/soma.svelte';
|
|
|
|
|
import { TAGS_INPUT_LANGS } from './langs';
|
|
|
|
|
|
|
|
|
|
import { tagsInputMorfo } from '../../../morfo/components/tags-input';
|
|
|
|
|
import type { SomaRuntimePart } from '../../runtime.svelte';
|
|
|
|
|
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
|
|
|
|
|
|
|
|
|
|
const attrs = createAttrs(tagsInputMorfo);
|
|
|
|
|
|
|
|
|
|
@ -40,6 +40,8 @@ interface TagsInputOpts
|
|
|
|
|
export class TagsInputProvider {
|
|
|
|
|
readonly opts: TagsInputOpts;
|
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
|
|
|
|
readonly soma: Soma;
|
|
|
|
|
readonly runtime: SomaRuntime;
|
|
|
|
|
static readonly ctx = context<TagsInputProvider>('TagsInput');
|
|
|
|
|
static get(): TagsInputProvider | undefined {
|
|
|
|
|
return this.ctx.getOr(undefined) as TagsInputProvider | undefined;
|
|
|
|
|
@ -52,22 +54,20 @@ export class TagsInputProvider {
|
|
|
|
|
return new TagsInputProvider(opts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly soma = Soma.get();
|
|
|
|
|
|
|
|
|
|
// Focus tracking
|
|
|
|
|
highlightedIndex = $state(-1);
|
|
|
|
|
inputRef = state<HTMLElement | null>(null);
|
|
|
|
|
|
|
|
|
|
private constructor(opts: TagsInputOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(tagsInputMorfo, {})
|
|
|
|
|
.part('provider', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
context: TagsInputProvider.ctx
|
|
|
|
|
});
|
|
|
|
|
this.soma = Soma.require();
|
|
|
|
|
this.runtime = this.soma.runtime(tagsInputMorfo, {});
|
|
|
|
|
this.runtimePart = this.runtime.part('provider', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
context: TagsInputProvider.ctx
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly isEmpty = $derived.by(() => this.opts.value.current.length === 0);
|
|
|
|
|
@ -224,10 +224,12 @@ export class TagsInputControlProvider {
|
|
|
|
|
|
|
|
|
|
private constructor(opts: TagsInputControlOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(tagsInputMorfo, {})
|
|
|
|
|
.part('control', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
this.provider = TagsInputProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('control', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly onclick = () => {
|
|
|
|
|
@ -264,17 +266,15 @@ export class TagsInputInputProvider {
|
|
|
|
|
|
|
|
|
|
private constructor(opts: TagsInputInputOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(tagsInputMorfo, {})
|
|
|
|
|
.part('input', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
onRefChange: (el) => {
|
|
|
|
|
this.provider.inputRef.current = el;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.provider = TagsInputProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('input', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
onRefChange: (el) => {
|
|
|
|
|
this.provider.inputRef.current = el;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly oninput = (e: Event) => {
|
|
|
|
|
@ -406,15 +406,13 @@ export class TagsInputItemProvider {
|
|
|
|
|
|
|
|
|
|
private constructor(opts: TagsInputItemOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(tagsInputMorfo, {})
|
|
|
|
|
.part('item', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
context: TagsInputItemProvider.ctx
|
|
|
|
|
});
|
|
|
|
|
this.provider = TagsInputProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('item', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this,
|
|
|
|
|
context: TagsInputItemProvider.ctx
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly isHighlighted = $derived.by(
|
|
|
|
|
@ -488,10 +486,12 @@ export class TagsInputItemTextProvider {
|
|
|
|
|
|
|
|
|
|
private constructor(opts: TagsInputItemTextOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(tagsInputMorfo, {})
|
|
|
|
|
.part('item-text', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
this.item = TagsInputItemProvider.require();
|
|
|
|
|
this.runtimePart = this.item.provider.runtime.part('item-text', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
|
@ -519,11 +519,13 @@ export class TagsInputItemDeleteTriggerProvider {
|
|
|
|
|
|
|
|
|
|
private constructor(opts: TagsInputItemDeleteTriggerOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(tagsInputMorfo, {})
|
|
|
|
|
.part('item-delete-trigger', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
this.item = TagsInputItemProvider.require();
|
|
|
|
|
this.provider = this.item.provider;
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('item-delete-trigger', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly onclick = (e: SomaMouseEvent<HTMLButtonElement>) => {
|
|
|
|
|
@ -538,7 +540,7 @@ export class TagsInputItemDeleteTriggerProvider {
|
|
|
|
|
...this.runtimePart.props,
|
|
|
|
|
type: 'button' as const,
|
|
|
|
|
tabindex: -1,
|
|
|
|
|
'aria-label': this.provider.soma?.langs.ts(TAGS_INPUT_LANGS.REMOVE),
|
|
|
|
|
'aria-label': this.provider.soma.langs.ts(TAGS_INPUT_LANGS.REMOVE),
|
|
|
|
|
disabled: this.item.isDisabled || this.provider.opts.readonly.current || undefined,
|
|
|
|
|
'data-disabled': boolToEmptyStrOrUndef(this.item.isDisabled),
|
|
|
|
|
onclick: this.onclick
|
|
|
|
|
@ -561,10 +563,12 @@ export class TagsInputClearTriggerProvider {
|
|
|
|
|
|
|
|
|
|
private constructor(opts: TagsInputClearTriggerOpts) {
|
|
|
|
|
this.opts = opts;
|
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
.runtime(tagsInputMorfo, {})
|
|
|
|
|
.part('clear-trigger', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
this.provider = TagsInputProvider.require();
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('clear-trigger', {
|
|
|
|
|
id: opts.id,
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
owner: this
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readonly onclick = (_e: SomaMouseEvent<HTMLButtonElement>) => {
|
|
|
|
|
@ -576,7 +580,7 @@ export class TagsInputClearTriggerProvider {
|
|
|
|
|
this.runtimePart.assert({
|
|
|
|
|
...this.runtimePart.props,
|
|
|
|
|
type: 'button' as const,
|
|
|
|
|
'aria-label': this.provider.soma?.langs.ts(TAGS_INPUT_LANGS.CLEAR),
|
|
|
|
|
'aria-label': this.provider.soma.langs.ts(TAGS_INPUT_LANGS.CLEAR),
|
|
|
|
|
hidden:
|
|
|
|
|
this.provider.isEmpty ||
|
|
|
|
|
this.provider.opts.disabled.current ||
|
|
|
|
|
|