@dosgato/dialog 0.0.1 → 0.0.4
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/FieldChooserLink.svelte +3 -4
- package/FieldDualListbox.svelte +118 -0
- package/FieldDualListbox.svelte.d.ts +26 -0
- package/FieldMultiple.svelte.d.ts +2 -2
- package/FieldStandard.svelte.d.ts +1 -1
- package/FileIcon.svelte +11 -11
- package/Form.svelte +4 -33
- package/Form.svelte.d.ts +11 -6
- package/InlineMessage.svelte +4 -4
- package/Listbox.svelte +166 -0
- package/Listbox.svelte.d.ts +28 -0
- package/chooser/Asset.svelte +14 -9
- package/chooser/AssetFolder.svelte +13 -11
- package/chooser/Chooser.svelte +10 -8
- package/chooser/Chooser.svelte.d.ts +18 -16
- package/chooser/ChooserAPI.d.ts +5 -3
- package/chooser/ChooserAPI.js +1 -1
- package/chooser/ChooserStore.d.ts +8 -7
- package/chooser/ChooserStore.js +6 -6
- package/chooser/Page.svelte +12 -10
- package/chooser/Thumbnail.svelte +2 -2
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/package.json +6 -3
package/FieldChooserLink.svelte
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
<script context="module">export {};
|
|
2
2
|
</script>
|
|
3
3
|
<script >import { FORM_CONTEXT } from '@txstate-mws/svelte-forms';
|
|
4
|
-
import { getContext
|
|
4
|
+
import { getContext } from 'svelte';
|
|
5
5
|
import { randomid } from 'txstate-utils';
|
|
6
|
-
import { Chooser, ChooserStore,
|
|
6
|
+
import { Chooser, ChooserStore, CHOOSER_API_CONTEXT } from './chooser';
|
|
7
7
|
import Details from './chooser/Details.svelte';
|
|
8
8
|
import Thumbnail from './chooser/Thumbnail.svelte';
|
|
9
9
|
import FieldStandard from './FieldStandard.svelte';
|
|
10
|
-
import { ASSET_API_CONTEXT } from './Form.svelte';
|
|
11
10
|
export let id = undefined;
|
|
12
11
|
export let path;
|
|
13
12
|
export let label = '';
|
|
@@ -24,7 +23,7 @@ export let initialSource = undefined;
|
|
|
24
23
|
export let initialPath = undefined;
|
|
25
24
|
const formStore = getContext(FORM_CONTEXT);
|
|
26
25
|
const value = formStore.getField(path);
|
|
27
|
-
const chooserClient = getContext(
|
|
26
|
+
const chooserClient = getContext(CHOOSER_API_CONTEXT);
|
|
28
27
|
const store = new ChooserStore(chooserClient);
|
|
29
28
|
const descid = randomid();
|
|
30
29
|
let modalshown = false;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<script >import menuRight from '@iconify-icons/mdi/menu-right.js';
|
|
2
|
+
import menuLeft from '@iconify-icons/mdi/menu-left.js';
|
|
3
|
+
import FieldStandard from './FieldStandard.svelte';
|
|
4
|
+
import { ScreenReaderOnly, modifierKey } from '@txstate-mws/svelte-components';
|
|
5
|
+
import Icon from './Icon.svelte';
|
|
6
|
+
import Listbox from './Listbox.svelte';
|
|
7
|
+
import { randomid } from 'txstate-utils';
|
|
8
|
+
export let id = undefined;
|
|
9
|
+
export let path;
|
|
10
|
+
export let label = '';
|
|
11
|
+
export let sourceLabel = 'Available';
|
|
12
|
+
export let selectedLabel = 'Selected';
|
|
13
|
+
export let multiselect = false;
|
|
14
|
+
export let choices;
|
|
15
|
+
export let defaultValue = [];
|
|
16
|
+
export let conditional = undefined;
|
|
17
|
+
export let required = false;
|
|
18
|
+
let itemsToAdd = []; //the items selected in the left listbox
|
|
19
|
+
let itemsToRemove = []; //the items selected in the right listbox
|
|
20
|
+
let instructions = 'test';
|
|
21
|
+
$: {
|
|
22
|
+
if (itemsToAdd.length === 1)
|
|
23
|
+
instructions = `Press right arrow key to move selected ${sourceLabel} items to ${selectedLabel} items list.`;
|
|
24
|
+
else
|
|
25
|
+
instructions = '';
|
|
26
|
+
}
|
|
27
|
+
$: {
|
|
28
|
+
if (itemsToRemove.length === 1)
|
|
29
|
+
instructions = `Press left arrow key to move selected ${selectedLabel} items to ${sourceLabel} list.`;
|
|
30
|
+
else
|
|
31
|
+
instructions = '';
|
|
32
|
+
}
|
|
33
|
+
const descid = randomid();
|
|
34
|
+
function addToSelected(value, setVal) {
|
|
35
|
+
return () => {
|
|
36
|
+
const selected = value.concat(itemsToAdd.map(item => item.value));
|
|
37
|
+
itemsToAdd = [];
|
|
38
|
+
setVal(selected);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function addToAvailable(value, setVal) {
|
|
42
|
+
return () => {
|
|
43
|
+
const itemsToRemoveSet = new Set(itemsToRemove.map(i => i.value));
|
|
44
|
+
const selected = value.filter(v => !itemsToRemoveSet.has(v));
|
|
45
|
+
itemsToRemove = [];
|
|
46
|
+
setVal(selected);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
let valueToLabel = {};
|
|
50
|
+
for (const choice of choices) {
|
|
51
|
+
valueToLabel[choice.value] = choice.label || choice.value;
|
|
52
|
+
}
|
|
53
|
+
function valueToSelectedChoices(value) {
|
|
54
|
+
// keep the selected options ordered as they were in the available options
|
|
55
|
+
const valueSet = new Set(value);
|
|
56
|
+
const ret = [];
|
|
57
|
+
for (const choice of choices) {
|
|
58
|
+
if (valueSet.has(choice.value))
|
|
59
|
+
ret.push({ value: choice.value, label: choice.label || choice.value });
|
|
60
|
+
}
|
|
61
|
+
return ret;
|
|
62
|
+
}
|
|
63
|
+
function getAvailable(value) {
|
|
64
|
+
return choices.filter(choice => value.indexOf(choice.value) === -1);
|
|
65
|
+
}
|
|
66
|
+
function onkeydown(value, setVal) {
|
|
67
|
+
return (e) => {
|
|
68
|
+
if (modifierKey(e))
|
|
69
|
+
return;
|
|
70
|
+
if (e.key === 'ArrowRight') {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
if (itemsToAdd.length === 0)
|
|
73
|
+
return;
|
|
74
|
+
addToSelected(value, setVal)();
|
|
75
|
+
}
|
|
76
|
+
else if (e.key === 'ArrowLeft') {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
if (itemsToRemove.length === 0)
|
|
79
|
+
return;
|
|
80
|
+
addToAvailable(value, setVal)();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} {descid} let:value let:valid let:invalid let:id let:onBlur let:setVal>
|
|
87
|
+
<div {id} role="group" class="dual-list-container" on:keydown={onkeydown(value, setVal)}>
|
|
88
|
+
<ScreenReaderOnly>
|
|
89
|
+
<span aria-live="polite">{instructions}</span>
|
|
90
|
+
</ScreenReaderOnly>
|
|
91
|
+
<Listbox label={sourceLabel} multiselect={multiselect} items={getAvailable(value)} {descid} {valid} {invalid} on:change={e => itemsToAdd = e.detail} selected={itemsToAdd} on:blur={onBlur}/>
|
|
92
|
+
<div class="toolbar">
|
|
93
|
+
<button type="button" class="toolbar-button" title="Move selection to {selectedLabel}" disabled={itemsToAdd.length === 0} on:click={addToSelected(value, setVal)}>
|
|
94
|
+
<Icon icon={menuRight} width='3em'/>
|
|
95
|
+
</button>
|
|
96
|
+
<button type="button" class="toolbar-button" title="Remove selection from {selectedLabel}" disabled={itemsToRemove.length === 0} on:click={addToAvailable(value, setVal)}>
|
|
97
|
+
<Icon icon={menuLeft} width='3em'/>
|
|
98
|
+
</button>
|
|
99
|
+
</div>
|
|
100
|
+
<Listbox label={selectedLabel} multiselect={multiselect} items={valueToSelectedChoices(value)} {descid} {valid} {invalid} on:change={e => itemsToRemove = e.detail} selected={itemsToRemove} on:blur={onBlur}/>
|
|
101
|
+
</div>
|
|
102
|
+
</FieldStandard>
|
|
103
|
+
|
|
104
|
+
<style>
|
|
105
|
+
.dual-list-container {
|
|
106
|
+
display: flex;
|
|
107
|
+
}
|
|
108
|
+
.toolbar {
|
|
109
|
+
display: flex;
|
|
110
|
+
flex-direction: column;
|
|
111
|
+
justify-content: center;
|
|
112
|
+
}
|
|
113
|
+
.toolbar .toolbar-button {
|
|
114
|
+
background-color: transparent;
|
|
115
|
+
border: 0;
|
|
116
|
+
padding: 0;
|
|
117
|
+
}
|
|
118
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { type PopupMenuItem } from '@txstate-mws/svelte-components';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
id?: string | undefined;
|
|
6
|
+
path: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
sourceLabel?: string;
|
|
9
|
+
selectedLabel?: string;
|
|
10
|
+
multiselect?: boolean;
|
|
11
|
+
choices: PopupMenuItem[];
|
|
12
|
+
defaultValue?: string[];
|
|
13
|
+
conditional?: boolean | undefined;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
};
|
|
16
|
+
events: {
|
|
17
|
+
[evt: string]: CustomEvent<any>;
|
|
18
|
+
};
|
|
19
|
+
slots: {};
|
|
20
|
+
};
|
|
21
|
+
export declare type FieldDualListboxProps = typeof __propDef.props;
|
|
22
|
+
export declare type FieldDualListboxEvents = typeof __propDef.events;
|
|
23
|
+
export declare type FieldDualListboxSlots = typeof __propDef.slots;
|
|
24
|
+
export default class FieldDualListbox extends SvelteComponentTyped<FieldDualListboxProps, FieldDualListboxEvents, FieldDualListboxSlots> {
|
|
25
|
+
}
|
|
26
|
+
export {};
|
package/FileIcon.svelte
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
<script context="module">import archiveOutline from '@iconify/
|
|
2
|
-
import fileCodeOutline from '@iconify/
|
|
3
|
-
import fileDocumentOutline from '@iconify/
|
|
4
|
-
import fileMusicOutline from '@iconify/
|
|
5
|
-
import fileOutline from '@iconify/
|
|
6
|
-
import fileTableOutline from '@iconify/
|
|
7
|
-
import fileVideoOutline from '@iconify/
|
|
8
|
-
import fileImageOutline from '@iconify/
|
|
9
|
-
import microsoftExcel from '@iconify/
|
|
10
|
-
import microsoftWord from '@iconify/
|
|
11
|
-
import noteTextOutline from '@iconify/
|
|
1
|
+
<script context="module">import archiveOutline from '@iconify-icons/mdi/archive-outline.js';
|
|
2
|
+
import fileCodeOutline from '@iconify-icons/mdi/file-code-outline.js';
|
|
3
|
+
import fileDocumentOutline from '@iconify-icons/mdi/file-document-outline.js';
|
|
4
|
+
import fileMusicOutline from '@iconify-icons/mdi/file-music-outline.js';
|
|
5
|
+
import fileOutline from '@iconify-icons/mdi/file-outline.js';
|
|
6
|
+
import fileTableOutline from '@iconify-icons/mdi/file-table-outline.js';
|
|
7
|
+
import fileVideoOutline from '@iconify-icons/mdi/file-video-outline.js';
|
|
8
|
+
import fileImageOutline from '@iconify-icons/mdi/file-image-outline.js';
|
|
9
|
+
import microsoftExcel from '@iconify-icons/mdi/microsoft-excel.js';
|
|
10
|
+
import microsoftWord from '@iconify-icons/mdi/microsoft-word.js';
|
|
11
|
+
import noteTextOutline from '@iconify-icons/mdi/note-text-outline.js';
|
|
12
12
|
const icons = {
|
|
13
13
|
'application/vnd.ms-excel': microsoftExcel,
|
|
14
14
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': microsoftExcel,
|
package/Form.svelte
CHANGED
|
@@ -1,32 +1,20 @@
|
|
|
1
|
-
<script context="module">export const ASSET_API_CONTEXT = {};
|
|
2
|
-
</script>
|
|
3
1
|
<script >import { Form, FormStore } from '@txstate-mws/svelte-forms';
|
|
4
|
-
import {
|
|
2
|
+
import { setContext } from 'svelte';
|
|
3
|
+
import { CHOOSER_API_CONTEXT } from './chooser';
|
|
5
4
|
let className = '';
|
|
6
5
|
export { className as class };
|
|
7
6
|
export let submit = undefined;
|
|
8
7
|
export let validate = undefined;
|
|
9
|
-
export let success = undefined;
|
|
10
8
|
export let store = undefined;
|
|
11
9
|
export let chooserClient = undefined;
|
|
12
10
|
export let autocomplete = undefined;
|
|
13
11
|
export let name = undefined;
|
|
14
12
|
export let preload = undefined;
|
|
15
|
-
setContext(
|
|
16
|
-
const dispatch = createEventDispatcher();
|
|
17
|
-
function onCancel() {
|
|
18
|
-
dispatch('close');
|
|
19
|
-
}
|
|
13
|
+
setContext(CHOOSER_API_CONTEXT, chooserClient);
|
|
20
14
|
</script>
|
|
21
15
|
|
|
22
|
-
<Form bind:store class="{className} dialog-form" {submit} {validate}
|
|
16
|
+
<Form bind:store class="{className} dialog-form" {submit} {validate} on:saved {autocomplete} {name} {preload} let:messages let:saved let:valid let:invalid let:validating let:submitting>
|
|
23
17
|
<slot {messages} {saved} {validating} {submitting} {valid} {invalid} />
|
|
24
|
-
<div class="dialog-buttons">
|
|
25
|
-
<slot name="buttons" {onCancel}>
|
|
26
|
-
<button type="button" on:click={onCancel}>Cancel</button>
|
|
27
|
-
<button>Save</button>
|
|
28
|
-
</slot>
|
|
29
|
-
</div>
|
|
30
18
|
</Form>
|
|
31
19
|
|
|
32
20
|
<style>
|
|
@@ -36,21 +24,4 @@ function onCancel() {
|
|
|
36
24
|
:global(.dialog-form) {
|
|
37
25
|
padding: 0;
|
|
38
26
|
}
|
|
39
|
-
:global(.dialog-form fieldset) {
|
|
40
|
-
border: 1px solid #666666;
|
|
41
|
-
border-width: 1px 0;
|
|
42
|
-
padding: 1em 0;
|
|
43
|
-
margin: 2em 0;
|
|
44
|
-
}
|
|
45
|
-
.dialog-buttons {
|
|
46
|
-
display: flex;
|
|
47
|
-
justify-content: flex-end;
|
|
48
|
-
}
|
|
49
|
-
.dialog-buttons > * {
|
|
50
|
-
margin-left: 1em;
|
|
51
|
-
}
|
|
52
|
-
.dialog-buttons :global(button) {
|
|
53
|
-
padding: 0.4em 0.8em;
|
|
54
|
-
min-width: 8em;
|
|
55
|
-
}
|
|
56
27
|
</style>
|
package/Form.svelte.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
declare class __sveltets_Render<T, F> {
|
|
3
|
+
props(): any;
|
|
4
|
+
events(): {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots(): any;
|
|
8
|
+
}
|
|
9
|
+
export declare type FormProps<T, F> = ReturnType<__sveltets_Render<T, F>['props']>;
|
|
10
|
+
export declare type FormEvents<T, F> = ReturnType<__sveltets_Render<T, F>['events']>;
|
|
11
|
+
export declare type FormSlots<T, F> = ReturnType<__sveltets_Render<T, F>['slots']>;
|
|
12
|
+
export default class Form<T, F> extends SvelteComponentTyped<FormProps<T, F>, FormEvents<T, F>, FormSlots<T, F>> {
|
|
8
13
|
}
|
|
9
14
|
export {};
|
package/InlineMessage.svelte
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<script >import alertCircleOutline from '@iconify/
|
|
2
|
-
import checkCircleOutline from '@iconify/
|
|
3
|
-
import informationOutline from '@iconify/
|
|
4
|
-
import closeOctagonOutline from '@iconify/
|
|
1
|
+
<script >import alertCircleOutline from '@iconify-icons/mdi/alert-circle-outline.js';
|
|
2
|
+
import checkCircleOutline from '@iconify-icons/mdi/check-circle-outline.js';
|
|
3
|
+
import informationOutline from '@iconify-icons/mdi/information-outline.js';
|
|
4
|
+
import closeOctagonOutline from '@iconify-icons/mdi/close-octagon-outline.js';
|
|
5
5
|
import Icon from './Icon.svelte';
|
|
6
6
|
export let message;
|
|
7
7
|
const icons = {
|
package/Listbox.svelte
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<script >import { createEventDispatcher } from 'svelte';
|
|
2
|
+
import { modifierKey } from '@txstate-mws/svelte-components';
|
|
3
|
+
import check from '@iconify-icons/mdi/check.js';
|
|
4
|
+
import Icon from './Icon.svelte';
|
|
5
|
+
const dispatch = createEventDispatcher();
|
|
6
|
+
export let items = [];
|
|
7
|
+
export let label;
|
|
8
|
+
export let multiselect = false;
|
|
9
|
+
export let selected = [];
|
|
10
|
+
export let descid = undefined;
|
|
11
|
+
export let valid = false;
|
|
12
|
+
export let invalid = false;
|
|
13
|
+
import { randomid } from 'txstate-utils';
|
|
14
|
+
const listId = randomid();
|
|
15
|
+
const labelId = randomid();
|
|
16
|
+
let listboxElement;
|
|
17
|
+
let hilited = undefined;
|
|
18
|
+
let firstactive = 0;
|
|
19
|
+
let lastactive = items.length - 1;
|
|
20
|
+
const itemelements = [];
|
|
21
|
+
$: selectedSet = new Set(selected.map(s => s.value));
|
|
22
|
+
async function reactToItems(..._) {
|
|
23
|
+
firstactive = items.findIndex(itm => !itm.disabled);
|
|
24
|
+
lastactive = items.length - [...items].reverse().findIndex(itm => !itm.disabled) - 1;
|
|
25
|
+
hilited = undefined;
|
|
26
|
+
if (listboxElement)
|
|
27
|
+
listboxElement.setAttribute('aria-activedescendant', null);
|
|
28
|
+
}
|
|
29
|
+
$: reactToItems(items);
|
|
30
|
+
const selectItem = (item, index) => (e) => {
|
|
31
|
+
e.stopPropagation();
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
if (item.disabled)
|
|
34
|
+
return;
|
|
35
|
+
listboxElement.setAttribute('aria-activedescendant', `${listId}-${index}`);
|
|
36
|
+
hilited = index;
|
|
37
|
+
if (multiselect) {
|
|
38
|
+
if (selectedSet.has(item.value)) {
|
|
39
|
+
// remove it from selected
|
|
40
|
+
selected = selected.filter(s => s.value !== item.value);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
selected = [...selected, item];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
selected = [item];
|
|
48
|
+
}
|
|
49
|
+
dispatch('change', selected);
|
|
50
|
+
};
|
|
51
|
+
function move(idx) {
|
|
52
|
+
if (items[idx]?.disabled)
|
|
53
|
+
return;
|
|
54
|
+
hilited = Math.max(firstactive, Math.min(lastactive, idx));
|
|
55
|
+
itemelements[hilited].scrollIntoView({ block: 'center' });
|
|
56
|
+
listboxElement.setAttribute('aria-activedescendant', `${listId}-${hilited}`);
|
|
57
|
+
if (!multiselect) {
|
|
58
|
+
selected = [items[hilited]];
|
|
59
|
+
dispatch('change', selected);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function onkeydown(e) {
|
|
63
|
+
if (modifierKey(e))
|
|
64
|
+
return;
|
|
65
|
+
if (e.key === 'ArrowDown') {
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
if (items.length < 1)
|
|
68
|
+
return;
|
|
69
|
+
let i = (hilited ?? firstactive - 1) + 1;
|
|
70
|
+
while (items[i]?.disabled)
|
|
71
|
+
i++;
|
|
72
|
+
move(i);
|
|
73
|
+
}
|
|
74
|
+
else if (e.key === 'ArrowUp') {
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
if (items.length < 1)
|
|
77
|
+
return;
|
|
78
|
+
let i = (hilited ?? lastactive + 1) - 1;
|
|
79
|
+
while (items[i]?.disabled)
|
|
80
|
+
i--;
|
|
81
|
+
move(i);
|
|
82
|
+
}
|
|
83
|
+
else if (e.key === ' ') {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
if (items.length < 1)
|
|
86
|
+
return;
|
|
87
|
+
if (multiselect) {
|
|
88
|
+
if (typeof hilited !== 'undefined') {
|
|
89
|
+
if (selectedSet.has(items[hilited].value)) {
|
|
90
|
+
// remove it from selected
|
|
91
|
+
selected = selected.filter(s => s.value !== items[hilited].value);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
selected = [...selected, items[hilited]];
|
|
95
|
+
}
|
|
96
|
+
dispatch('change', selected);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function focusListbox() {
|
|
102
|
+
if (selected.length) {
|
|
103
|
+
for (let i = 0; i < items.length; i++) {
|
|
104
|
+
if (items[i].value === selected[0].value) {
|
|
105
|
+
hilited = i;
|
|
106
|
+
listboxElement.setAttribute('aria-activedescendant', `${listId}-${hilited}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
hilited = firstactive;
|
|
112
|
+
listboxElement.setAttribute('aria-activedescendant', `${listId}-${hilited}`);
|
|
113
|
+
if (!multiselect) {
|
|
114
|
+
selected = [items[hilited]];
|
|
115
|
+
dispatch('change', selected);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
</script>
|
|
120
|
+
|
|
121
|
+
<div class="listbox-container" class:valid class:invalid>
|
|
122
|
+
<span id={labelId}>{label}</span>
|
|
123
|
+
<ul bind:this={listboxElement} role="listbox" id={listId} class="listbox-items" tabindex="0" aria-describedby={descid} aria-labelledby={labelId} aria-multiselectable={multiselect} on:keydown={onkeydown} on:focus={focusListbox}>
|
|
124
|
+
{#each items as item, i (item.value)}
|
|
125
|
+
<li
|
|
126
|
+
bind:this={itemelements[i]}
|
|
127
|
+
id={`${listId}-${i}`}
|
|
128
|
+
role="option"
|
|
129
|
+
class="listbox-item"
|
|
130
|
+
class:hilited={hilited === i}
|
|
131
|
+
class:disabled={!!item.disabled}
|
|
132
|
+
aria-selected={selectedSet.has(item.value)}
|
|
133
|
+
aria-disabled={item.disabled}
|
|
134
|
+
on:click={selectItem(item, i)}
|
|
135
|
+
>
|
|
136
|
+
<span class:invisible={!multiselect || !selectedSet.has(item.value)}><Icon icon={check} width='0.8em'/></span>
|
|
137
|
+
{item.label || item.value}
|
|
138
|
+
</li>
|
|
139
|
+
{/each}
|
|
140
|
+
</ul>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<style>
|
|
144
|
+
.listbox-container {
|
|
145
|
+
width: 25%;
|
|
146
|
+
}
|
|
147
|
+
.listbox-items {
|
|
148
|
+
list-style: none;
|
|
149
|
+
padding-left: 0;
|
|
150
|
+
border: 1px solid #666;
|
|
151
|
+
height: 40vh;
|
|
152
|
+
overflow-y: scroll;
|
|
153
|
+
}
|
|
154
|
+
.listbox-item {
|
|
155
|
+
padding: 0.2em;
|
|
156
|
+
}
|
|
157
|
+
.listbox-item span.invisible {
|
|
158
|
+
visibility: hidden;
|
|
159
|
+
}
|
|
160
|
+
.listbox-item.hilited {
|
|
161
|
+
background-color: lightcyan;
|
|
162
|
+
}
|
|
163
|
+
.listbox-item.disabled {
|
|
164
|
+
color: rgba(0,0,0,0.6);
|
|
165
|
+
}
|
|
166
|
+
</style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { type PopupMenuItem } from '@txstate-mws/svelte-components';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
items?: PopupMenuItem[];
|
|
6
|
+
label: string;
|
|
7
|
+
multiselect?: boolean;
|
|
8
|
+
selected?: {
|
|
9
|
+
value: string;
|
|
10
|
+
label?: string;
|
|
11
|
+
}[];
|
|
12
|
+
descid?: string | undefined;
|
|
13
|
+
valid?: boolean;
|
|
14
|
+
invalid?: boolean;
|
|
15
|
+
};
|
|
16
|
+
events: {
|
|
17
|
+
change: CustomEvent<any>;
|
|
18
|
+
} & {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
};
|
|
23
|
+
export declare type ListboxProps = typeof __propDef.props;
|
|
24
|
+
export declare type ListboxEvents = typeof __propDef.events;
|
|
25
|
+
export declare type ListboxSlots = typeof __propDef.slots;
|
|
26
|
+
export default class Listbox extends SvelteComponentTyped<ListboxProps, ListboxEvents, ListboxSlots> {
|
|
27
|
+
}
|
|
28
|
+
export {};
|
package/chooser/Asset.svelte
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script >import { modifierKey } from '@txstate-mws/svelte-components';
|
|
2
2
|
import { createEventDispatcher, getContext } from 'svelte';
|
|
3
3
|
import { hashid } from 'txstate-utils';
|
|
4
|
-
import {
|
|
4
|
+
import { CHOOSER_STORE_CONTEXT } from './ChooserStore';
|
|
5
5
|
import FileIcon from '../FileIcon.svelte';
|
|
6
6
|
export let asset;
|
|
7
7
|
export let level;
|
|
@@ -10,7 +10,7 @@ export let setsize;
|
|
|
10
10
|
export let next;
|
|
11
11
|
export let prev;
|
|
12
12
|
export let parent = undefined;
|
|
13
|
-
const store = getContext(
|
|
13
|
+
const store = getContext(CHOOSER_STORE_CONTEXT);
|
|
14
14
|
$: id = hashid(asset.id);
|
|
15
15
|
$: haveFocus = $store?.focus === asset.id;
|
|
16
16
|
$: isPreview = $store.preview?.id === asset.id;
|
|
@@ -19,12 +19,7 @@ function onKeyDown(e) {
|
|
|
19
19
|
if (modifierKey(e))
|
|
20
20
|
return;
|
|
21
21
|
if (['Enter', ' '].includes(e.key)) {
|
|
22
|
-
e
|
|
23
|
-
e.stopPropagation();
|
|
24
|
-
if ($store.preview?.id === asset.id)
|
|
25
|
-
dispatch('choose', asset);
|
|
26
|
-
else
|
|
27
|
-
store.preview(asset);
|
|
22
|
+
onClick(e);
|
|
28
23
|
}
|
|
29
24
|
else if (e.key === 'ArrowDown') {
|
|
30
25
|
e.preventDefault();
|
|
@@ -53,6 +48,16 @@ function onKeyDown(e) {
|
|
|
53
48
|
}
|
|
54
49
|
}
|
|
55
50
|
}
|
|
51
|
+
function onClick(e) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
e.stopPropagation();
|
|
54
|
+
// if the id was already the same as the one that was clicked, the user
|
|
55
|
+
// has clicked it twice, so we should choose the item and end the modal
|
|
56
|
+
if ($store.preview?.id === asset.id)
|
|
57
|
+
dispatch('choose', asset);
|
|
58
|
+
else
|
|
59
|
+
store.preview(asset);
|
|
60
|
+
}
|
|
56
61
|
</script>
|
|
57
62
|
|
|
58
63
|
<li
|
|
@@ -65,7 +70,7 @@ function onKeyDown(e) {
|
|
|
65
70
|
class="dialog-asset-file"
|
|
66
71
|
class:isPreview
|
|
67
72
|
on:keydown={onKeyDown}
|
|
68
|
-
on:click={
|
|
73
|
+
on:click={onClick}
|
|
69
74
|
>
|
|
70
75
|
<FileIcon mime={asset.mime} inline /> {asset.name}
|
|
71
76
|
</li>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
<script >import folderOutline from '@iconify/
|
|
2
|
-
import folderOpenOutline from '@iconify/
|
|
3
|
-
import folderSyncOutline from '@iconify/
|
|
1
|
+
<script >import folderOutline from '@iconify-icons/mdi/folder-outline.js';
|
|
2
|
+
import folderOpenOutline from '@iconify-icons/mdi/folder-open-outline.js';
|
|
3
|
+
import folderSyncOutline from '@iconify-icons/mdi/folder-sync-outline.js';
|
|
4
4
|
import { modifierKey } from '@txstate-mws/svelte-components';
|
|
5
5
|
import { createEventDispatcher, getContext } from 'svelte';
|
|
6
6
|
import { hashid } from 'txstate-utils';
|
|
7
|
-
import {
|
|
7
|
+
import { CHOOSER_STORE_CONTEXT } from './ChooserStore';
|
|
8
8
|
import Asset from './Asset.svelte';
|
|
9
9
|
import Icon from '../Icon.svelte';
|
|
10
10
|
export let folder;
|
|
@@ -14,7 +14,7 @@ export let setsize;
|
|
|
14
14
|
export let next;
|
|
15
15
|
export let prev;
|
|
16
16
|
export let parent = undefined;
|
|
17
|
-
const store = getContext(
|
|
17
|
+
const store = getContext(CHOOSER_STORE_CONTEXT);
|
|
18
18
|
$: open = folder.open && folder.children?.length;
|
|
19
19
|
$: nextlevel = level + 1;
|
|
20
20
|
$: id = hashid(folder.id);
|
|
@@ -26,10 +26,6 @@ function onKeyDown(e) {
|
|
|
26
26
|
return;
|
|
27
27
|
if (['Enter', ' '].includes(e.key)) {
|
|
28
28
|
onClick(e);
|
|
29
|
-
if ($store.preview?.id === folder.id)
|
|
30
|
-
dispatch('choose', folder);
|
|
31
|
-
else
|
|
32
|
-
store.preview(folder);
|
|
33
29
|
}
|
|
34
30
|
else if (e.key === 'ArrowRight') {
|
|
35
31
|
e.preventDefault();
|
|
@@ -77,8 +73,14 @@ function onKeyDown(e) {
|
|
|
77
73
|
function onClick(e) {
|
|
78
74
|
e.preventDefault();
|
|
79
75
|
e.stopPropagation();
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
// if the id was already the same as the one that was clicked, the user
|
|
77
|
+
// has clicked it twice, so we should choose the item and end the modal
|
|
78
|
+
if ($store.preview?.id === folder.id)
|
|
79
|
+
dispatch('choose', folder);
|
|
80
|
+
else {
|
|
81
|
+
store.preview(folder);
|
|
82
|
+
store.toggle(folder);
|
|
83
|
+
}
|
|
82
84
|
}
|
|
83
85
|
</script>
|
|
84
86
|
|
package/chooser/Chooser.svelte
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<script >import fileTree from '@iconify/
|
|
2
|
-
import viewGrid from '@iconify/
|
|
1
|
+
<script >import fileTree from '@iconify-icons/mdi/file-tree.js';
|
|
2
|
+
import viewGrid from '@iconify-icons/mdi/view-grid.js';
|
|
3
3
|
import { Loading, Modal } from '@txstate-mws/svelte-components';
|
|
4
4
|
import { derivedStore } from '@txstate-mws/svelte-store';
|
|
5
5
|
import { createEventDispatcher, getContext, onMount, setContext } from 'svelte';
|
|
@@ -7,13 +7,13 @@ import { hashid, randomid } from 'txstate-utils';
|
|
|
7
7
|
import Asset from './Asset.svelte';
|
|
8
8
|
import AssetFolder from './AssetFolder.svelte';
|
|
9
9
|
import ButtonGroup from '../ButtonGroup.svelte';
|
|
10
|
-
import {
|
|
10
|
+
import { CHOOSER_API_CONTEXT } from './ChooserAPI';
|
|
11
|
+
import { CHOOSER_STORE_CONTEXT, ChooserStore } from './ChooserStore';
|
|
11
12
|
import Details from './Details.svelte';
|
|
12
13
|
import Icon from '../Icon.svelte';
|
|
13
14
|
import Page from './Page.svelte';
|
|
14
15
|
import Thumbnail from './Thumbnail.svelte';
|
|
15
|
-
|
|
16
|
-
const chooserClient = getContext(ASSET_API_CONTEXT);
|
|
16
|
+
const chooserClient = getContext(CHOOSER_API_CONTEXT);
|
|
17
17
|
export let label = undefined;
|
|
18
18
|
export let images = false;
|
|
19
19
|
export let pages = false;
|
|
@@ -23,8 +23,10 @@ export let initialType = undefined;
|
|
|
23
23
|
export let initialSource = undefined;
|
|
24
24
|
export let initialPath = undefined;
|
|
25
25
|
export let activeSources = undefined;
|
|
26
|
+
export let passthruFilters = undefined;
|
|
27
|
+
export let filter = undefined;
|
|
26
28
|
export let store = new ChooserStore(chooserClient);
|
|
27
|
-
setContext(
|
|
29
|
+
setContext(CHOOSER_STORE_CONTEXT, store);
|
|
28
30
|
$: if (!pages && !assets)
|
|
29
31
|
assets = true;
|
|
30
32
|
$: activeTypes = [...(assets ? ['asset'] : []), ...(pages ? ['page'] : [])];
|
|
@@ -38,7 +40,7 @@ function onChoose() {
|
|
|
38
40
|
dispatch('change', $store.preview);
|
|
39
41
|
}
|
|
40
42
|
onMount(async () => {
|
|
41
|
-
await store.init({ activeTypes, activeSources, initialType, initialSource, initialPath, onlyImages: images, chooseFolder: folders });
|
|
43
|
+
await store.init({ activeTypes, activeSources, initialType, initialSource, initialPath, passthruFilters, filter, onlyImages: images, chooseFolder: folders });
|
|
42
44
|
if ($store.focus)
|
|
43
45
|
document.getElementById(hashid($store.focus))?.scrollIntoView();
|
|
44
46
|
});
|
|
@@ -55,7 +57,7 @@ onMount(async () => {
|
|
|
55
57
|
<div class="dialog-chooser-source">
|
|
56
58
|
<select on:change={function () { store.changeSource(Number(this.value)) }}>
|
|
57
59
|
{#each $sources as source, i}
|
|
58
|
-
<option value={i}>{source.name}</option>
|
|
60
|
+
<option value={i}>{source.label || source.name}</option>
|
|
59
61
|
{/each}
|
|
60
62
|
</select>
|
|
61
63
|
</div>
|
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
import type
|
|
2
|
+
import { type AnyItem, type ChooserType } from './ChooserAPI';
|
|
3
3
|
import { ChooserStore } from './ChooserStore';
|
|
4
|
-
declare
|
|
5
|
-
props: {
|
|
6
|
-
label?: string
|
|
4
|
+
declare class __sveltets_Render<F> {
|
|
5
|
+
props(): {
|
|
6
|
+
label?: string;
|
|
7
7
|
images?: boolean;
|
|
8
8
|
pages?: boolean;
|
|
9
9
|
assets?: boolean;
|
|
10
10
|
folders?: boolean;
|
|
11
|
-
initialType?: ChooserType
|
|
12
|
-
initialSource?: string
|
|
13
|
-
initialPath?: string
|
|
14
|
-
activeSources?: string[]
|
|
15
|
-
|
|
11
|
+
initialType?: ChooserType;
|
|
12
|
+
initialSource?: string;
|
|
13
|
+
initialPath?: string;
|
|
14
|
+
activeSources?: string[];
|
|
15
|
+
passthruFilters?: F;
|
|
16
|
+
filter?: (item: AnyItem) => boolean | Promise<boolean>;
|
|
17
|
+
store?: ChooserStore<F>;
|
|
16
18
|
};
|
|
17
|
-
events: {
|
|
19
|
+
events(): {
|
|
18
20
|
escape: CustomEvent<any>;
|
|
19
21
|
change: CustomEvent<any>;
|
|
20
22
|
} & {
|
|
21
23
|
[evt: string]: CustomEvent<any>;
|
|
22
24
|
};
|
|
23
|
-
slots: {};
|
|
24
|
-
}
|
|
25
|
-
export declare type ChooserProps =
|
|
26
|
-
export declare type ChooserEvents =
|
|
27
|
-
export declare type ChooserSlots =
|
|
28
|
-
export default class Chooser extends SvelteComponentTyped<ChooserProps
|
|
25
|
+
slots(): {};
|
|
26
|
+
}
|
|
27
|
+
export declare type ChooserProps<F> = ReturnType<__sveltets_Render<F>['props']>;
|
|
28
|
+
export declare type ChooserEvents<F> = ReturnType<__sveltets_Render<F>['events']>;
|
|
29
|
+
export declare type ChooserSlots<F> = ReturnType<__sveltets_Render<F>['slots']>;
|
|
30
|
+
export default class Chooser<F> extends SvelteComponentTyped<ChooserProps<F>, ChooserEvents<F>, ChooserSlots<F>> {
|
|
29
31
|
}
|
|
30
32
|
export {};
|
package/chooser/ChooserAPI.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export declare const CHOOSER_API_CONTEXT: {};
|
|
1
2
|
export declare type ChooserType = 'asset' | 'page';
|
|
2
3
|
export declare type AnyItem = Asset | Folder | Page;
|
|
3
|
-
export interface Client {
|
|
4
|
+
export interface Client<F = any> {
|
|
4
5
|
getSources: (type: ChooserType) => Promise<Source[]>;
|
|
5
|
-
getChildren: (source: string, path: string,
|
|
6
|
-
find: (source: string, path: string, searchstring: string,
|
|
6
|
+
getChildren: (source: string, path: string, filters: F) => Promise<(AnyItem)[]>;
|
|
7
|
+
find: (source: string, path: string, searchstring: string, filters: F) => Promise<(AnyItem)[]>;
|
|
7
8
|
findById: (id: string) => Promise<AnyItem>;
|
|
8
9
|
findByUrl?: (url: string) => Promise<AnyItem>;
|
|
9
10
|
urlToValue?: (url: string) => string;
|
|
@@ -12,6 +13,7 @@ export interface Client {
|
|
|
12
13
|
export interface Source {
|
|
13
14
|
type: ChooserType;
|
|
14
15
|
name: string;
|
|
16
|
+
label?: string;
|
|
15
17
|
rootAcceptsUpload?: boolean;
|
|
16
18
|
}
|
|
17
19
|
interface Item {
|
package/chooser/ChooserAPI.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export const CHOOSER_API_CONTEXT = {};
|
|
@@ -32,8 +32,9 @@ export interface IAssetStore {
|
|
|
32
32
|
focus?: string;
|
|
33
33
|
focusPath?: string;
|
|
34
34
|
}
|
|
35
|
-
export interface ChooserStoreOptions {
|
|
35
|
+
export interface ChooserStoreOptions<F> {
|
|
36
36
|
filter?: (itm: AnyItem) => boolean | Promise<boolean>;
|
|
37
|
+
passthruFilters?: F;
|
|
37
38
|
activeTypes?: ChooserType[];
|
|
38
39
|
activeSources?: string[];
|
|
39
40
|
initialType?: ChooserType;
|
|
@@ -42,20 +43,20 @@ export interface ChooserStoreOptions {
|
|
|
42
43
|
chooseFolder?: boolean;
|
|
43
44
|
onlyImages?: boolean;
|
|
44
45
|
}
|
|
45
|
-
interface InternalStoreOptions extends Omit<ChooserStoreOptions
|
|
46
|
+
interface InternalStoreOptions<F> extends Omit<ChooserStoreOptions<F>, 'activeSources'> {
|
|
46
47
|
activeSources?: Set<string>;
|
|
47
48
|
}
|
|
48
|
-
export declare const
|
|
49
|
+
export declare const CHOOSER_STORE_CONTEXT: {};
|
|
49
50
|
export declare function combinePath(path: string, name: string): string;
|
|
50
51
|
export declare function bytesToHuman(bytes: number): string;
|
|
51
|
-
export declare class ChooserStore extends SafeStore<IAssetStore> {
|
|
52
|
+
export declare class ChooserStore<F = any> extends SafeStore<IAssetStore> {
|
|
52
53
|
client: Client;
|
|
53
|
-
options: InternalStoreOptions
|
|
54
|
+
options: InternalStoreOptions<F>;
|
|
54
55
|
constructor(client: Client);
|
|
55
|
-
setOptions(options: ChooserStoreOptions): void;
|
|
56
|
+
setOptions(options: ChooserStoreOptions<F>): void;
|
|
56
57
|
getSource(state?: IAssetStore): UISource;
|
|
57
58
|
getSourceIndex(name: string, state?: IAssetStore, type?: ChooserType): number;
|
|
58
|
-
init(options: ChooserStoreOptions): Promise<void>;
|
|
59
|
+
init(options: ChooserStoreOptions<F>): Promise<void>;
|
|
59
60
|
itemByPath(state: IAssetStore, path: string): AnyUIItem;
|
|
60
61
|
open(folder: UIFolder | UIPage): Promise<void>;
|
|
61
62
|
openPath(path: string): Promise<void>;
|
package/chooser/ChooserStore.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SafeStore } from '@txstate-mws/svelte-store';
|
|
2
|
-
import { findIndex, isNotBlank } from 'txstate-utils';
|
|
3
|
-
export const
|
|
2
|
+
import { filterAsync, findIndex, isNotBlank } from 'txstate-utils';
|
|
3
|
+
export const CHOOSER_STORE_CONTEXT = {};
|
|
4
4
|
const nofilter = (x) => true;
|
|
5
5
|
export function combinePath(path, name) {
|
|
6
6
|
if (path.endsWith('/'))
|
|
@@ -88,7 +88,7 @@ export class ChooserStore extends SafeStore {
|
|
|
88
88
|
return v;
|
|
89
89
|
});
|
|
90
90
|
try {
|
|
91
|
-
const children = await this.client.getChildren(this.getSource().name, path, this.options.filter);
|
|
91
|
+
const children = await filterAsync(await this.client.getChildren(this.getSource().name, path, this.options.passthruFilters), this.options.filter);
|
|
92
92
|
this.update(v => {
|
|
93
93
|
const folder = this.itemByPath(v, path);
|
|
94
94
|
folder.open = true;
|
|
@@ -110,13 +110,13 @@ export class ChooserStore extends SafeStore {
|
|
|
110
110
|
const parts = path.substring(1).split('/');
|
|
111
111
|
const source = this.getSource(this.clone(this.value));
|
|
112
112
|
if (!source.children)
|
|
113
|
-
source.children = await this.client.getChildren(source.name, '/', this.options.filter);
|
|
113
|
+
source.children = await filterAsync(await this.client.getChildren(source.name, '/', this.options.passthruFilters), this.options.filter);
|
|
114
114
|
let current = source.children.find(c => c.name === parts[0]) ?? source.children[0];
|
|
115
115
|
for (const part of parts.slice(1).filter(isNotBlank)) {
|
|
116
116
|
if (!current || current.type === 'asset')
|
|
117
117
|
break;
|
|
118
118
|
if (!current.open) {
|
|
119
|
-
current.children = await this.client.getChildren(source.name, combinePath(current.path, current.name), this.options.filter);
|
|
119
|
+
current.children = await filterAsync(await this.client.getChildren(source.name, combinePath(current.path, current.name), this.options.passthruFilters), this.options.filter);
|
|
120
120
|
current.loading = false;
|
|
121
121
|
current.open = true;
|
|
122
122
|
}
|
|
@@ -175,7 +175,7 @@ export class ChooserStore extends SafeStore {
|
|
|
175
175
|
return v;
|
|
176
176
|
});
|
|
177
177
|
const source = this.getSource();
|
|
178
|
-
const children = await this.client.getChildren(source.name, '/', this.options.filter);
|
|
178
|
+
const children = await filterAsync(await this.client.getChildren(source.name, '/', this.options.passthruFilters), this.options.filter);
|
|
179
179
|
this.update(v => {
|
|
180
180
|
const source = this.getSource(v);
|
|
181
181
|
source.children = children;
|
package/chooser/Page.svelte
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
<script >import fileOutline from '@iconify/
|
|
2
|
-
import fileSyncOutline from '@iconify/
|
|
1
|
+
<script >import fileOutline from '@iconify-icons/mdi/file-outline.js';
|
|
2
|
+
import fileSyncOutline from '@iconify-icons/mdi/file-sync-outline.js';
|
|
3
3
|
import { modifierKey } from '@txstate-mws/svelte-components';
|
|
4
4
|
import { createEventDispatcher, getContext } from 'svelte';
|
|
5
5
|
import { hashid } from 'txstate-utils';
|
|
6
|
-
import {
|
|
6
|
+
import { CHOOSER_STORE_CONTEXT } from './ChooserStore';
|
|
7
7
|
import Icon from '../Icon.svelte';
|
|
8
8
|
export let page;
|
|
9
9
|
export let level;
|
|
@@ -12,7 +12,7 @@ export let setsize;
|
|
|
12
12
|
export let next;
|
|
13
13
|
export let prev;
|
|
14
14
|
export let parent = undefined;
|
|
15
|
-
const store = getContext(
|
|
15
|
+
const store = getContext(CHOOSER_STORE_CONTEXT);
|
|
16
16
|
$: open = page.open && page.children?.length;
|
|
17
17
|
$: nextlevel = level + 1;
|
|
18
18
|
$: id = hashid(page.id);
|
|
@@ -24,10 +24,6 @@ function onKeyDown(e) {
|
|
|
24
24
|
return;
|
|
25
25
|
if (['Enter', ' '].includes(e.key)) {
|
|
26
26
|
onClick(e);
|
|
27
|
-
if ($store.preview?.id === page.id)
|
|
28
|
-
dispatch('choose', page);
|
|
29
|
-
else
|
|
30
|
-
store.preview(page);
|
|
31
27
|
}
|
|
32
28
|
else if (e.key === 'ArrowRight') {
|
|
33
29
|
e.preventDefault();
|
|
@@ -75,8 +71,14 @@ function onKeyDown(e) {
|
|
|
75
71
|
function onClick(e) {
|
|
76
72
|
e.preventDefault();
|
|
77
73
|
e.stopPropagation();
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
// if the id was already the same as the one that was clicked, the user
|
|
75
|
+
// has clicked it twice, so we should choose the item and end the modal
|
|
76
|
+
if ($store.preview?.id === page.id)
|
|
77
|
+
dispatch('choose', page);
|
|
78
|
+
else {
|
|
79
|
+
store.preview(page);
|
|
80
|
+
store.toggle(page);
|
|
81
|
+
}
|
|
80
82
|
}
|
|
81
83
|
</script>
|
|
82
84
|
|
package/chooser/Thumbnail.svelte
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<script >import folderOutline from '@iconify/
|
|
2
|
-
import fileLinkOutline from '@iconify/
|
|
1
|
+
<script >import folderOutline from '@iconify-icons/mdi/folder-outline.js';
|
|
2
|
+
import fileLinkOutline from '@iconify-icons/mdi/file-link-outline.js';
|
|
3
3
|
import FileIcon from '../FileIcon.svelte';
|
|
4
4
|
import Icon from '../Icon.svelte';
|
|
5
5
|
export let item;
|
package/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { default as FieldChoices } from './FieldChoices.svelte';
|
|
|
5
5
|
export { default as FieldChooserLink } from './FieldChooserLink.svelte';
|
|
6
6
|
export { default as FieldDate } from './FieldDate.svelte';
|
|
7
7
|
export { default as FieldDateTime } from './FieldDateTime.svelte';
|
|
8
|
+
export { default as FieldDualListbox } from './FieldDualListbox.svelte';
|
|
8
9
|
export { default as FieldMultiple } from './FieldMultiple.svelte';
|
|
9
10
|
export { default as FieldMultiselect } from './FieldMultiselect.svelte';
|
|
10
11
|
export { default as FieldNumber } from './FieldNumber.svelte';
|
|
@@ -20,5 +21,6 @@ export { default as Input } from './Input.svelte';
|
|
|
20
21
|
export { default as Radio } from './Radio.svelte';
|
|
21
22
|
export { default as Tab } from './Tab.svelte';
|
|
22
23
|
export { default as Tabs } from './Tabs.svelte';
|
|
24
|
+
export { default as Listbox } from './Listbox.svelte';
|
|
23
25
|
export * from './chooser/index.js';
|
|
24
26
|
export * from './TabStore.js';
|
package/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { default as FieldChoices } from './FieldChoices.svelte';
|
|
|
5
5
|
export { default as FieldChooserLink } from './FieldChooserLink.svelte';
|
|
6
6
|
export { default as FieldDate } from './FieldDate.svelte';
|
|
7
7
|
export { default as FieldDateTime } from './FieldDateTime.svelte';
|
|
8
|
+
export { default as FieldDualListbox } from './FieldDualListbox.svelte';
|
|
8
9
|
export { default as FieldMultiple } from './FieldMultiple.svelte';
|
|
9
10
|
export { default as FieldMultiselect } from './FieldMultiselect.svelte';
|
|
10
11
|
export { default as FieldNumber } from './FieldNumber.svelte';
|
|
@@ -20,5 +21,6 @@ export { default as Input } from './Input.svelte';
|
|
|
20
21
|
export { default as Radio } from './Radio.svelte';
|
|
21
22
|
export { default as Tab } from './Tab.svelte';
|
|
22
23
|
export { default as Tabs } from './Tabs.svelte';
|
|
24
|
+
export { default as Listbox } from './Listbox.svelte';
|
|
23
25
|
export * from './chooser/index.js';
|
|
24
26
|
export * from './TabStore.js';
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dosgato/dialog",
|
|
3
|
-
"
|
|
3
|
+
"description": "A component library for building forms that edit a JSON document.",
|
|
4
|
+
"version": "0.0.4",
|
|
4
5
|
"dependencies": {
|
|
5
6
|
"@txstate-mws/svelte-components": "^1.2.5",
|
|
6
|
-
"@txstate-mws/svelte-forms": "^0.0.
|
|
7
|
+
"@txstate-mws/svelte-forms": "^0.0.15",
|
|
7
8
|
"@iconify/svelte": "^2.1.1",
|
|
8
|
-
"@iconify/
|
|
9
|
+
"@iconify-icons/mdi": "^1.2.6",
|
|
9
10
|
"txstate-utils": "^1.6.6"
|
|
10
11
|
},
|
|
11
12
|
"devDependencies": {
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"./FieldChooserLink.svelte": "./FieldChooserLink.svelte",
|
|
32
33
|
"./FieldDate.svelte": "./FieldDate.svelte",
|
|
33
34
|
"./FieldDateTime.svelte": "./FieldDateTime.svelte",
|
|
35
|
+
"./FieldDualListbox.svelte": "./FieldDualListbox.svelte",
|
|
34
36
|
"./FieldMultiple.svelte": "./FieldMultiple.svelte",
|
|
35
37
|
"./FieldMultiselect.svelte": "./FieldMultiselect.svelte",
|
|
36
38
|
"./FieldNumber.svelte": "./FieldNumber.svelte",
|
|
@@ -44,6 +46,7 @@
|
|
|
44
46
|
"./InlineMessage.svelte": "./InlineMessage.svelte",
|
|
45
47
|
"./InlineMessages.svelte": "./InlineMessages.svelte",
|
|
46
48
|
"./Input.svelte": "./Input.svelte",
|
|
49
|
+
"./Listbox.svelte": "./Listbox.svelte",
|
|
47
50
|
"./Radio.svelte": "./Radio.svelte",
|
|
48
51
|
"./Tab.svelte": "./Tab.svelte",
|
|
49
52
|
"./TabStore": "./TabStore.js",
|