@marianmeres/stuic 2.60.0 → 2.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/popover/popover.svelte.js +18 -4
- package/dist/actions/tooltip/tooltip.svelte.js +15 -11
- package/dist/components/AppShell/AppShellSimple.svelte +5 -2
- package/dist/components/AssetsPreview/AssetsPreview.svelte +15 -17
- package/dist/components/AssetsPreview/AssetsPreview.svelte.d.ts +2 -4
- package/dist/components/CommandMenu/CommandMenu.svelte +145 -147
- package/dist/components/CommandMenu/README.md +6 -0
- package/dist/components/DropdownMenu/README.md +2 -2
- package/dist/components/Input/FieldOptions.svelte +255 -252
- package/dist/components/Input/FieldOptions.svelte.d.ts +2 -2
- package/dist/components/Modal/Modal.svelte +37 -48
- package/dist/components/Modal/Modal.svelte.d.ts +3 -13
- package/dist/components/Modal/README.md +17 -6
- package/dist/components/ModalDialog/ModalDialog.svelte +50 -13
- package/dist/components/ModalDialog/ModalDialog.svelte.d.ts +9 -0
- package/dist/components/ModalDialog/README.md +27 -8
- package/dist/components/Notifications/Notifications.svelte +135 -96
- package/dist/components/Notifications/notifications-icons.js +4 -4
- package/dist/components/X/X.svelte +1 -1
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { strHash } from "../../utils/str-hash.js";
|
|
17
17
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
18
18
|
import Button from "../Button/Button.svelte";
|
|
19
|
-
import
|
|
19
|
+
import { ModalDialog } from "../ModalDialog/index.js";
|
|
20
20
|
import { NotificationsStack } from "../Notifications/index.js";
|
|
21
21
|
import Spinner from "../Spinner/Spinner.svelte";
|
|
22
22
|
import type { THC } from "../Thc/Thc.svelte";
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
type SnippetWithId = Snippet<[{ id: string }]>;
|
|
33
33
|
|
|
34
34
|
export interface Props extends Record<string, any> {
|
|
35
|
-
trigger?: Snippet<[{ value: string; modal:
|
|
35
|
+
trigger?: Snippet<[{ value: string; modal: ModalDialog }]>;
|
|
36
36
|
input?: HTMLInputElement;
|
|
37
37
|
value: string;
|
|
38
38
|
label?: SnippetWithId | THC;
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
tabindex = 0,
|
|
135
135
|
description,
|
|
136
136
|
class: classProp,
|
|
137
|
-
renderSize = "
|
|
137
|
+
renderSize = "lg",
|
|
138
138
|
useTrim = true,
|
|
139
139
|
//
|
|
140
140
|
required = false,
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
...rest
|
|
184
184
|
}: Props = $props();
|
|
185
185
|
|
|
186
|
-
let
|
|
186
|
+
let modalDialog: ModalDialog = $state()!;
|
|
187
187
|
let innerValue = $state("");
|
|
188
188
|
let isFetching = $state(false);
|
|
189
189
|
let cardinality = $derived(_cardinality === -1 ? Infinity : _cardinality);
|
|
@@ -268,7 +268,6 @@
|
|
|
268
268
|
|
|
269
269
|
let activeEl: HTMLButtonElement | undefined = $state();
|
|
270
270
|
let optionsBox: HTMLDivElement | undefined = $state();
|
|
271
|
-
let modalEl: HTMLDivElement | undefined = $state();
|
|
272
271
|
|
|
273
272
|
// add_new dance...
|
|
274
273
|
let addNewBtn: HTMLButtonElement | undefined = $state();
|
|
@@ -277,7 +276,7 @@
|
|
|
277
276
|
|
|
278
277
|
// set value on open
|
|
279
278
|
// watch(
|
|
280
|
-
// () =>
|
|
279
|
+
// () => modalDialog.visibility().visible,
|
|
281
280
|
// (isVisible, wasVisible) => {
|
|
282
281
|
// // modal was just opened
|
|
283
282
|
// if (isVisible) {
|
|
@@ -300,7 +299,7 @@
|
|
|
300
299
|
// suggest options as a typeahead feature
|
|
301
300
|
const debounced = new Debounced(() => innerValue, 150);
|
|
302
301
|
watch(
|
|
303
|
-
[() =>
|
|
302
|
+
[() => modalDialog.visibility().visible, () => debounced.current],
|
|
304
303
|
([isVisible, currVal]) => {
|
|
305
304
|
if (!isVisible) return;
|
|
306
305
|
isFetching = true;
|
|
@@ -325,7 +324,7 @@
|
|
|
325
324
|
);
|
|
326
325
|
|
|
327
326
|
$effect(() => {
|
|
328
|
-
if (
|
|
327
|
+
if (modalDialog.visibility().visible && touch) {
|
|
329
328
|
_selectedColl.clear().addMany(maybeJsonParse(value) as Item[]);
|
|
330
329
|
// IMPORTANT: focus first selected so it scrolls into view on open
|
|
331
330
|
if (_selectedColl.size) {
|
|
@@ -409,16 +408,15 @@
|
|
|
409
408
|
value = JSON.stringify(selected.items);
|
|
410
409
|
innerValue = "";
|
|
411
410
|
_optionsColl.clear();
|
|
412
|
-
|
|
411
|
+
modalDialog.close();
|
|
413
412
|
_dispatch_change_to_owner();
|
|
414
413
|
onChange?.(value);
|
|
415
414
|
}
|
|
416
415
|
|
|
417
|
-
// clears
|
|
416
|
+
// clears state and dispatches change; close is handled by ModalDialog's preEscapeClose
|
|
418
417
|
function escape() {
|
|
419
418
|
innerValue = "";
|
|
420
419
|
_optionsColl.clear();
|
|
421
|
-
modal?.close();
|
|
422
420
|
_dispatch_change_to_owner();
|
|
423
421
|
}
|
|
424
422
|
|
|
@@ -483,7 +481,7 @@
|
|
|
483
481
|
<!-- this must be on window as we're catching any typing anywhere -->
|
|
484
482
|
<svelte:window
|
|
485
483
|
onkeydown={(e) => {
|
|
486
|
-
if (
|
|
484
|
+
if (modalDialog.visibility().visible) {
|
|
487
485
|
// arrow navigation
|
|
488
486
|
if (["ArrowDown", "ArrowUp"].includes(e.key)) {
|
|
489
487
|
e.preventDefault();
|
|
@@ -514,7 +512,7 @@
|
|
|
514
512
|
<!-- must wrap both -->
|
|
515
513
|
<div>
|
|
516
514
|
{#if trigger}
|
|
517
|
-
{@render trigger({ value, modal })}
|
|
515
|
+
{@render trigger({ value, modal: modalDialog })}
|
|
518
516
|
{:else}
|
|
519
517
|
<FieldLikeButton
|
|
520
518
|
bind:value
|
|
@@ -561,274 +559,279 @@
|
|
|
561
559
|
return `${e}`; // either invalid json or not array...
|
|
562
560
|
}
|
|
563
561
|
}}
|
|
564
|
-
onclick={
|
|
562
|
+
onclick={modalDialog?.open}
|
|
565
563
|
/>
|
|
566
564
|
{/if}
|
|
567
565
|
|
|
568
|
-
<
|
|
569
|
-
bind:this={
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
bind:el={modalEl}
|
|
566
|
+
<ModalDialog
|
|
567
|
+
bind:this={modalDialog}
|
|
568
|
+
preEscapeClose={escape}
|
|
569
|
+
classDialog="items-start"
|
|
570
|
+
class="w-full max-w-2xl bg-transparent pointer-events-none"
|
|
574
571
|
{noScrollLock}
|
|
575
572
|
>
|
|
576
|
-
<
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
e
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
<
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
onclick={() => {
|
|
629
|
-
_selectedColl.clear();
|
|
630
|
-
input?.focus();
|
|
631
|
-
}}
|
|
632
|
-
class={twMerge(
|
|
633
|
-
"control flex items-center p-1 m-1 text-sm opacity-75 underline rounded",
|
|
634
|
-
"hover:opacity-100 focus-visible:outline-neutral-400 focus-visible:opacity-100"
|
|
635
|
-
)}
|
|
636
|
-
class:opacity-20={!selected.items.length}
|
|
637
|
-
tabindex={5}
|
|
638
|
-
disabled={!selected.items.length}
|
|
639
|
-
>
|
|
640
|
-
{@html t(cardinality === 1 ? "clear" : "clear_all")}
|
|
641
|
-
</button>
|
|
642
|
-
|
|
643
|
-
<span class="p-1 m-1 text-sm"> </span>
|
|
644
|
-
<span class="flex-1 block justify-end opacity-50 text-right text-sm p-1 pr-2">
|
|
645
|
-
{selected.items.length}
|
|
646
|
-
{#if cardinality > 0 && cardinality < Infinity}
|
|
647
|
-
{@html t("cardinality_of")} {cardinality}
|
|
648
|
-
{/if}
|
|
649
|
-
{@html t("cardinality_selected")}
|
|
650
|
-
</span>
|
|
651
|
-
</div>
|
|
652
|
-
|
|
653
|
-
<!-- {#if options.items.length} -->
|
|
654
|
-
<div
|
|
655
|
-
class={[
|
|
656
|
-
"options overflow-y-auto overflow-x-hidden space-y-1 scrollbar-thin",
|
|
657
|
-
"h-55 max-h-55",
|
|
658
|
-
]}
|
|
659
|
-
bind:this={optionsBox}
|
|
660
|
-
tabindex="-1"
|
|
661
|
-
>
|
|
662
|
-
{#if isFetching && !options.items.length}
|
|
663
|
-
<!-- <div class="p-4 opacity-50"> -->
|
|
664
|
-
<div class="flex opacity-50 text-sm h-full items-center justify-center">
|
|
665
|
-
<Spinner class="w-4" />
|
|
666
|
-
</div>
|
|
667
|
-
{:else if !options.items.length && !allowUnknown}
|
|
668
|
-
<div class="flex opacity-50 text-sm h-full items-center justify-center">
|
|
669
|
-
{@html t("no_results")}
|
|
670
|
-
</div>
|
|
671
|
-
{/if}
|
|
672
|
-
|
|
673
|
-
{#if !isFetching && allowUnknown && innerValue && !have_option_label_like(options.items, innerValue)}
|
|
674
|
-
<div class="px-1">
|
|
573
|
+
<div class="pt-0 md:pt-[20vh] w-full">
|
|
574
|
+
<div class="pointer-events-auto">
|
|
575
|
+
<InputWrap
|
|
576
|
+
size={renderSize}
|
|
577
|
+
class={twMerge("m-2 mb-12 shadow-xl", classModalField)}
|
|
578
|
+
classInputBoxWrap={twMerge(
|
|
579
|
+
// always look like focused
|
|
580
|
+
`border border-input-accent dark:border-input-accent-dark`,
|
|
581
|
+
`ring-input-accent/20 dark:ring-input-accent-dark/20 ring-4`
|
|
582
|
+
)}
|
|
583
|
+
{id}
|
|
584
|
+
{required}
|
|
585
|
+
>
|
|
586
|
+
<input
|
|
587
|
+
bind:value={innerValue}
|
|
588
|
+
bind:this={input}
|
|
589
|
+
{type}
|
|
590
|
+
{id}
|
|
591
|
+
class={twMerge("form-input", renderSize, classInput)}
|
|
592
|
+
tabindex={1}
|
|
593
|
+
{required}
|
|
594
|
+
{disabled}
|
|
595
|
+
placeholder={searchPlaceholder ??
|
|
596
|
+
t(allowUnknown ? "search_submit_placeholder" : "search_placeholder")}
|
|
597
|
+
onkeydown={(e) => {
|
|
598
|
+
if (e.key === "Enter") {
|
|
599
|
+
e.preventDefault();
|
|
600
|
+
try_submit();
|
|
601
|
+
}
|
|
602
|
+
}}
|
|
603
|
+
autocomplete="off"
|
|
604
|
+
name={`rand-${Math.random().toString(36).slice(2)}`}
|
|
605
|
+
{...rest}
|
|
606
|
+
/>
|
|
607
|
+
|
|
608
|
+
{#snippet inputBelow()}
|
|
609
|
+
<div class="h-full border-t p-2 border-black/20">
|
|
610
|
+
<div class="text-sm -mt-1 flex items-center">
|
|
611
|
+
{#if isMultiple}
|
|
612
|
+
<button
|
|
613
|
+
type="button"
|
|
614
|
+
onclick={() => _selectedColl.addMany(options.items)}
|
|
615
|
+
class={twMerge(
|
|
616
|
+
"control flex items-center p-1 m-1 text-sm opacity-75 underline rounded",
|
|
617
|
+
"hover:opacity-100 focus-visible:outline-neutral-400 focus-visible:opacity-100"
|
|
618
|
+
)}
|
|
619
|
+
tabindex={4}
|
|
620
|
+
disabled={!options.size}
|
|
621
|
+
>
|
|
622
|
+
{@html t("select_all")}
|
|
623
|
+
</button>
|
|
624
|
+
{/if}
|
|
675
625
|
<button
|
|
676
626
|
type="button"
|
|
677
|
-
|
|
678
|
-
|
|
627
|
+
onclick={() => {
|
|
628
|
+
_selectedColl.clear();
|
|
629
|
+
input?.focus();
|
|
630
|
+
}}
|
|
679
631
|
class={twMerge(
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
isAddNewBtnActive && classOptionActive
|
|
632
|
+
"control flex items-center p-1 m-1 text-sm opacity-75 underline rounded",
|
|
633
|
+
"hover:opacity-100 focus-visible:outline-neutral-400 focus-visible:opacity-100"
|
|
683
634
|
)}
|
|
635
|
+
class:opacity-20={!selected.items.length}
|
|
636
|
+
tabindex={5}
|
|
637
|
+
disabled={!selected.items.length}
|
|
684
638
|
>
|
|
685
|
-
{t("
|
|
639
|
+
{@html t(cardinality === 1 ? "clear" : "clear_all")}
|
|
686
640
|
</button>
|
|
687
|
-
</div>
|
|
688
|
-
{/if}
|
|
689
641
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
class={twMerge(
|
|
694
|
-
"text-sm capitalize opacity-50 border-b border-black/10 mb-0.5 p-1 mx-1",
|
|
695
|
-
classOptgroup
|
|
696
|
-
)}
|
|
642
|
+
<span class="p-1 m-1 text-sm"> </span>
|
|
643
|
+
<span
|
|
644
|
+
class="flex-1 block justify-end opacity-50 text-right text-sm p-1 pr-2"
|
|
697
645
|
>
|
|
698
|
-
{
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
646
|
+
{selected.items.length}
|
|
647
|
+
{#if cardinality > 0 && cardinality < Infinity}
|
|
648
|
+
{@html t("cardinality_of")} {cardinality}
|
|
649
|
+
{/if}
|
|
650
|
+
{@html t("cardinality_selected")}
|
|
651
|
+
</span>
|
|
652
|
+
</div>
|
|
653
|
+
|
|
654
|
+
<!-- {#if options.items.length} -->
|
|
655
|
+
<div
|
|
656
|
+
class={[
|
|
657
|
+
"options overflow-y-auto overflow-x-hidden space-y-1 scrollbar-thin",
|
|
658
|
+
"h-55 max-h-55",
|
|
659
|
+
]}
|
|
660
|
+
bind:this={optionsBox}
|
|
661
|
+
tabindex="-1"
|
|
662
|
+
>
|
|
663
|
+
{#if isFetching && !options.items.length}
|
|
664
|
+
<!-- <div class="p-4 opacity-50"> -->
|
|
665
|
+
<div class="flex opacity-50 text-sm h-full items-center justify-center">
|
|
666
|
+
<Spinner class="w-4" />
|
|
667
|
+
</div>
|
|
668
|
+
{:else if !options.items.length && !allowUnknown}
|
|
669
|
+
<div class="flex opacity-50 text-sm h-full items-center justify-center">
|
|
670
|
+
{@html t("no_results")}
|
|
671
|
+
</div>
|
|
672
|
+
{/if}
|
|
673
|
+
|
|
674
|
+
{#if !isFetching && allowUnknown && innerValue && !have_option_label_like(options.items, innerValue)}
|
|
675
|
+
<div class="px-1">
|
|
709
676
|
<button
|
|
710
677
|
type="button"
|
|
711
|
-
|
|
712
|
-
onclick={
|
|
713
|
-
if (isMultiple) {
|
|
714
|
-
if (selected.isFull && !_selectedColl.exists(item)) {
|
|
715
|
-
return notifications?.error(t("cardinality_full"), {
|
|
716
|
-
ttl: 1000,
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
_selectedColl.toggleAdd(item);
|
|
720
|
-
} else {
|
|
721
|
-
_selectedColl.clear();
|
|
722
|
-
_selectedColl.add(item);
|
|
723
|
-
submit();
|
|
724
|
-
}
|
|
725
|
-
}}
|
|
726
|
-
class:active
|
|
727
|
-
class:selected={isSelected}
|
|
678
|
+
bind:this={addNewBtn}
|
|
679
|
+
onclick={add_new}
|
|
728
680
|
class={twMerge(
|
|
729
681
|
BTN_CLS,
|
|
730
|
-
isSelected && "bg-neutral-200 dark:bg-neutral-800",
|
|
731
682
|
classOption,
|
|
732
|
-
|
|
733
|
-
active && classOptionActive
|
|
683
|
+
isAddNewBtnActive && classOptionActive
|
|
734
684
|
)}
|
|
735
|
-
tabindex="-1"
|
|
736
|
-
role="checkbox"
|
|
737
|
-
aria-checked={isSelected}
|
|
738
685
|
>
|
|
739
|
-
{
|
|
740
|
-
<span class={isSelected ? "opacity-100" : "opacity-25"}>
|
|
741
|
-
{#if isMultiple}
|
|
742
|
-
{#if isSelected}
|
|
743
|
-
{@html iconCheckboxCheck()}
|
|
744
|
-
{:else}
|
|
745
|
-
{@html iconCheckboxEmpty()}
|
|
746
|
-
{/if}
|
|
747
|
-
{:else if isSelected}
|
|
748
|
-
{@html iconRadioCheck()}
|
|
749
|
-
{:else}
|
|
750
|
-
{@html iconRadioEmpty()}
|
|
751
|
-
{/if}
|
|
752
|
-
</span>
|
|
753
|
-
{/if}
|
|
754
|
-
<span
|
|
755
|
-
class={twMerge(
|
|
756
|
-
"min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap"
|
|
757
|
-
)}>{_renderOptionLabel(item)}</span
|
|
758
|
-
>
|
|
686
|
+
{t("add_new", { value: innerValue })}
|
|
759
687
|
</button>
|
|
760
|
-
</
|
|
688
|
+
</div>
|
|
689
|
+
{/if}
|
|
690
|
+
|
|
691
|
+
{#each _normalize_and_group_options(options.items) as [_optgroup, _opts]}
|
|
692
|
+
{#if _optgroup}
|
|
693
|
+
<div
|
|
694
|
+
class={twMerge(
|
|
695
|
+
"text-sm capitalize opacity-50 border-b border-black/10 mb-0.5 p-1 mx-1",
|
|
696
|
+
classOptgroup
|
|
697
|
+
)}
|
|
698
|
+
>
|
|
699
|
+
{_optgroup}
|
|
700
|
+
</div>
|
|
701
|
+
{/if}
|
|
702
|
+
<ul class="space-y-0.5">
|
|
703
|
+
<!-- {#each options.items as item} -->
|
|
704
|
+
{#each _opts as item (item[itemIdPropName])}
|
|
705
|
+
{@const active =
|
|
706
|
+
item[itemIdPropName] === options.active?.[itemIdPropName]}
|
|
707
|
+
{@const isSelected =
|
|
708
|
+
selected.items && _selectedColl.exists(item[itemIdPropName])}
|
|
709
|
+
<li class:active class="px-1">
|
|
710
|
+
<button
|
|
711
|
+
type="button"
|
|
712
|
+
id={btn_id(item[itemIdPropName])}
|
|
713
|
+
onclick={() => {
|
|
714
|
+
if (isMultiple) {
|
|
715
|
+
if (selected.isFull && !_selectedColl.exists(item)) {
|
|
716
|
+
return notifications?.error(t("cardinality_full"), {
|
|
717
|
+
ttl: 1000,
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
_selectedColl.toggleAdd(item);
|
|
721
|
+
} else {
|
|
722
|
+
_selectedColl.clear();
|
|
723
|
+
_selectedColl.add(item);
|
|
724
|
+
submit();
|
|
725
|
+
}
|
|
726
|
+
}}
|
|
727
|
+
class:active
|
|
728
|
+
class:selected={isSelected}
|
|
729
|
+
class={twMerge(
|
|
730
|
+
BTN_CLS,
|
|
731
|
+
isSelected && "bg-neutral-200 dark:bg-neutral-800",
|
|
732
|
+
classOption,
|
|
733
|
+
// active && "border-neutral-400",
|
|
734
|
+
active && classOptionActive
|
|
735
|
+
)}
|
|
736
|
+
tabindex="-1"
|
|
737
|
+
role="checkbox"
|
|
738
|
+
aria-checked={isSelected}
|
|
739
|
+
>
|
|
740
|
+
{#if showIcons}
|
|
741
|
+
<span class={isSelected ? "opacity-100" : "opacity-25"}>
|
|
742
|
+
{#if isMultiple}
|
|
743
|
+
{#if isSelected}
|
|
744
|
+
{@html iconCheckboxCheck()}
|
|
745
|
+
{:else}
|
|
746
|
+
{@html iconCheckboxEmpty()}
|
|
747
|
+
{/if}
|
|
748
|
+
{:else if isSelected}
|
|
749
|
+
{@html iconRadioCheck()}
|
|
750
|
+
{:else}
|
|
751
|
+
{@html iconRadioEmpty()}
|
|
752
|
+
{/if}
|
|
753
|
+
</span>
|
|
754
|
+
{/if}
|
|
755
|
+
<span
|
|
756
|
+
class={twMerge(
|
|
757
|
+
"min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap"
|
|
758
|
+
)}>{_renderOptionLabel(item)}</span
|
|
759
|
+
>
|
|
760
|
+
</button>
|
|
761
|
+
</li>
|
|
762
|
+
{/each}
|
|
763
|
+
</ul>
|
|
761
764
|
{/each}
|
|
762
|
-
</
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
765
|
+
</div>
|
|
766
|
+
<!-- {/if} -->
|
|
767
|
+
<div class="p-2 px-3 flex items-end justify-between">
|
|
768
|
+
<div class="text-sm opacity-50">
|
|
769
|
+
<!-- Use arrows to navigate. Spacebar and Enter to select and/or submit. -->
|
|
770
|
+
{#if allowUnknown}
|
|
771
|
+
{@html t("unknown_allowed")}
|
|
772
|
+
{:else}
|
|
773
|
+
{@html t("unknown_not_allowed")}
|
|
774
|
+
{/if}
|
|
775
|
+
</div>
|
|
776
|
+
<div>
|
|
777
|
+
<Button
|
|
778
|
+
class="control"
|
|
779
|
+
type="button"
|
|
780
|
+
variant="primary"
|
|
781
|
+
onclick={async (e) => {
|
|
782
|
+
e.preventDefault();
|
|
783
|
+
try_submit(true);
|
|
784
|
+
}}
|
|
785
|
+
tabindex={3}
|
|
786
|
+
>
|
|
787
|
+
{@html t("submit")}
|
|
788
|
+
</Button>
|
|
789
|
+
</div>
|
|
790
|
+
</div>
|
|
791
|
+
</div>
|
|
792
|
+
{/snippet}
|
|
793
|
+
|
|
794
|
+
{#snippet inputAfter()}
|
|
795
|
+
<div class="flex pl-2 items-center justify-center opacity-50">
|
|
796
|
+
{#if isFetching}
|
|
797
|
+
<Spinner class="w-4" />
|
|
773
798
|
{/if}
|
|
774
799
|
</div>
|
|
775
|
-
<div>
|
|
776
|
-
<
|
|
777
|
-
class="control"
|
|
800
|
+
<div class="flex pl-2 pr-1 items-center justify-center">
|
|
801
|
+
<button
|
|
778
802
|
type="button"
|
|
779
|
-
|
|
780
|
-
|
|
803
|
+
class={twMerge(
|
|
804
|
+
"opacity-75 rounded",
|
|
805
|
+
"hover:opacity-100 hover:bg-neutral-200 dark:hover:bg-neutral-800",
|
|
806
|
+
"focus-visible:opacity-100 focus-visible:outline-0",
|
|
807
|
+
"focus-visible:bg-neutral-200 dark:focus-visible:bg-neutral-800"
|
|
808
|
+
)}
|
|
809
|
+
use:tooltip
|
|
810
|
+
aria-label={t("x_close")}
|
|
811
|
+
onclick={(e) => {
|
|
781
812
|
e.preventDefault();
|
|
782
|
-
|
|
813
|
+
if (innerValue.trim() == "") {
|
|
814
|
+
return escape();
|
|
815
|
+
}
|
|
816
|
+
innerValue = "";
|
|
817
|
+
input?.focus();
|
|
783
818
|
}}
|
|
784
|
-
tabindex={
|
|
819
|
+
tabindex={2}
|
|
785
820
|
>
|
|
786
|
-
|
|
787
|
-
</
|
|
821
|
+
<X class="m-2 size-6" />
|
|
822
|
+
</button>
|
|
788
823
|
</div>
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
{
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
<button
|
|
801
|
-
type="button"
|
|
802
|
-
class={twMerge(
|
|
803
|
-
"opacity-50 rounded",
|
|
804
|
-
"hover:opacity-100 hover:bg-neutral-200 dark:hover:bg-neutral-800",
|
|
805
|
-
"focus-visible:opacity-100 focus-visible:outline-0",
|
|
806
|
-
"focus-visible:bg-neutral-200 dark:focus-visible:bg-neutral-800"
|
|
807
|
-
)}
|
|
808
|
-
use:tooltip
|
|
809
|
-
aria-label={t("x_close")}
|
|
810
|
-
onclick={(e) => {
|
|
811
|
-
e.preventDefault();
|
|
812
|
-
if (innerValue.trim() == "") {
|
|
813
|
-
return escape();
|
|
814
|
-
}
|
|
815
|
-
innerValue = "";
|
|
816
|
-
input?.focus();
|
|
817
|
-
}}
|
|
818
|
-
tabindex={2}
|
|
819
|
-
>
|
|
820
|
-
<X class="m-2 size-4 " />
|
|
821
|
-
</button>
|
|
822
|
-
</div>
|
|
823
|
-
{/snippet}
|
|
824
|
-
|
|
825
|
-
{#snippet inputBefore()}
|
|
826
|
-
<div class="flex flex-col items-center justify-center pl-3 opacity-50">
|
|
827
|
-
{@html iconSearch({ size: 14 })}
|
|
828
|
-
</div>
|
|
829
|
-
{/snippet}
|
|
830
|
-
</InputWrap>
|
|
831
|
-
</Modal>
|
|
824
|
+
{/snippet}
|
|
825
|
+
|
|
826
|
+
{#snippet inputBefore()}
|
|
827
|
+
<div class="flex flex-col items-center justify-center pl-3 opacity-75">
|
|
828
|
+
{@html iconSearch({ size: 19, strokeWidth: 3 })}
|
|
829
|
+
</div>
|
|
830
|
+
{/snippet}
|
|
831
|
+
</InputWrap>
|
|
832
|
+
</div>
|
|
833
|
+
</div>
|
|
834
|
+
</ModalDialog>
|
|
832
835
|
</div>
|
|
833
836
|
|
|
834
837
|
<style>
|
|
@@ -2,7 +2,7 @@ import { ItemCollection, type Item } from "@marianmeres/item-collection";
|
|
|
2
2
|
import { type Snippet } from "svelte";
|
|
3
3
|
import { type ValidateOptions } from "../../actions/validate.svelte.js";
|
|
4
4
|
import type { TranslateFn } from "../../types.js";
|
|
5
|
-
import
|
|
5
|
+
import { ModalDialog } from "../ModalDialog/index.js";
|
|
6
6
|
import { NotificationsStack } from "../Notifications/index.js";
|
|
7
7
|
import type { THC } from "../Thc/Thc.svelte";
|
|
8
8
|
export interface Option {
|
|
@@ -15,7 +15,7 @@ type SnippetWithId = Snippet<[{
|
|
|
15
15
|
export interface Props extends Record<string, any> {
|
|
16
16
|
trigger?: Snippet<[{
|
|
17
17
|
value: string;
|
|
18
|
-
modal:
|
|
18
|
+
modal: ModalDialog;
|
|
19
19
|
}]>;
|
|
20
20
|
input?: HTMLInputElement;
|
|
21
21
|
value: string;
|