@dosgato/dialog 0.0.6 → 0.0.9
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/Container.svelte +4 -0
- package/FieldAutocomplete.svelte +62 -0
- package/FieldAutocomplete.svelte.d.ts +31 -0
- package/FieldSelect.svelte.d.ts +1 -1
- package/FileIcon.svelte +2 -46
- package/chooser/ChooserAPI.d.ts +4 -4
- package/chooser/ChooserStore.js +9 -9
- package/chooser/Details.svelte +2 -2
- package/fileIcons.d.ts +1 -0
- package/fileIcons.js +47 -0
- package/iconpicker/FieldIconPicker.svelte +256 -0
- package/iconpicker/FieldIconPicker.svelte.d.ts +24 -0
- package/iconpicker/iconpicker.d.ts +13 -0
- package/iconpicker/iconpicker.js +24784 -0
- package/iconpicker/index.d.ts +1 -0
- package/iconpicker/index.js +1 -0
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +7 -1
package/Container.svelte
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script>import { nullableSerialize, nullableDeserialize } from '@txstate-mws/svelte-forms';
|
|
2
|
+
import FieldStandard from './FieldStandard.svelte';
|
|
3
|
+
import { randomid } from 'txstate-utils';
|
|
4
|
+
import { PopupMenu, ScreenReaderOnly } from '@txstate-mws/svelte-components';
|
|
5
|
+
export let id = undefined;
|
|
6
|
+
export let path;
|
|
7
|
+
export let label = '';
|
|
8
|
+
export let placeholder = 'Select' + (label ? ' ' + label : '');
|
|
9
|
+
let className = '';
|
|
10
|
+
export { className as class };
|
|
11
|
+
export let notNull = false;
|
|
12
|
+
export let disabled = false;
|
|
13
|
+
export let choices;
|
|
14
|
+
export let defaultValue = notNull ? choices[0].value : undefined;
|
|
15
|
+
export let conditional = undefined;
|
|
16
|
+
export let required = false;
|
|
17
|
+
export let helptext = '';
|
|
18
|
+
let inputelement;
|
|
19
|
+
let inputvalue = '';
|
|
20
|
+
let popupvalue = undefined;
|
|
21
|
+
let savedLabel = '';
|
|
22
|
+
let changed = false;
|
|
23
|
+
if (defaultValue) {
|
|
24
|
+
const selected = choices.find(c => c.value === defaultValue);
|
|
25
|
+
inputvalue = selected.label || selected.value;
|
|
26
|
+
savedLabel = inputvalue;
|
|
27
|
+
}
|
|
28
|
+
const listId = randomid();
|
|
29
|
+
const liveTextId = randomid();
|
|
30
|
+
const helpTextId = randomid();
|
|
31
|
+
$: filteredChoices = changed
|
|
32
|
+
? choices.filter((item) => {
|
|
33
|
+
return item.label?.toLowerCase().includes(inputvalue.toLowerCase()) || item.value.toLowerCase().includes(inputvalue.toLowerCase());
|
|
34
|
+
})
|
|
35
|
+
: choices;
|
|
36
|
+
function onchangepopup(setVal) {
|
|
37
|
+
return (e) => {
|
|
38
|
+
inputvalue = e.detail.label || e.detail.value;
|
|
39
|
+
savedLabel = inputvalue;
|
|
40
|
+
popupvalue = undefined;
|
|
41
|
+
setVal(e.detail.value);
|
|
42
|
+
changed = false;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function checkifchanged(e) {
|
|
46
|
+
await setTimeout(function () {
|
|
47
|
+
if (inputelement.value !== savedLabel)
|
|
48
|
+
changed = true;
|
|
49
|
+
}, 1);
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} serialize={!notNull && nullableSerialize} deserialize={!notNull && nullableDeserialize} let:setVal let:valid let:invalid let:id let:onBlur let:onChange>
|
|
54
|
+
<input bind:this={inputelement} bind:value={inputvalue} {id} {placeholder} class="dialog-input {className}" class:valid class:invalid aria-invalid={invalid} {onBlur} {onChange} aria-owns={listId} autocapitalize="none" type="text" autocomplete="off" aria-autocomplete="list" role="combobox" aria-expanded="false" {disabled} aria-describedby={helptext.length ? helpTextId : ''} on:keydown={checkifchanged}>
|
|
55
|
+
<PopupMenu align="bottomleft" items={filteredChoices} buttonelement={inputelement} bind:value={popupvalue} on:change={onchangepopup(setVal)} emptyText="No options available"/>
|
|
56
|
+
{#if helptext.length}
|
|
57
|
+
<span id={helpTextId} class="field-help-text">{helptext}</span>
|
|
58
|
+
{/if}
|
|
59
|
+
<ScreenReaderOnly arialive="polite" ariaatomic={true} id={liveTextId}>
|
|
60
|
+
{filteredChoices.length} {filteredChoices.length === 1 ? 'option' : 'options'} available.
|
|
61
|
+
</ScreenReaderOnly>
|
|
62
|
+
</FieldStandard>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
id?: string | undefined;
|
|
5
|
+
path: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
class?: string;
|
|
9
|
+
notNull?: boolean;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
choices: {
|
|
12
|
+
label?: string;
|
|
13
|
+
value: string;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
}[];
|
|
16
|
+
defaultValue?: any;
|
|
17
|
+
conditional?: boolean | undefined;
|
|
18
|
+
required?: boolean;
|
|
19
|
+
helptext?: string;
|
|
20
|
+
};
|
|
21
|
+
events: {
|
|
22
|
+
[evt: string]: CustomEvent<any>;
|
|
23
|
+
};
|
|
24
|
+
slots: {};
|
|
25
|
+
};
|
|
26
|
+
export declare type FieldAutocompleteProps = typeof __propDef.props;
|
|
27
|
+
export declare type FieldAutocompleteEvents = typeof __propDef.events;
|
|
28
|
+
export declare type FieldAutocompleteSlots = typeof __propDef.slots;
|
|
29
|
+
export default class FieldAutocomplete extends SvelteComponentTyped<FieldAutocompleteProps, FieldAutocompleteEvents, FieldAutocompleteSlots> {
|
|
30
|
+
}
|
|
31
|
+
export {};
|
package/FieldSelect.svelte.d.ts
CHANGED
package/FileIcon.svelte
CHANGED
|
@@ -1,56 +1,12 @@
|
|
|
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
|
-
const icons = {
|
|
13
|
-
'application/vnd.ms-excel': microsoftExcel,
|
|
14
|
-
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': microsoftExcel,
|
|
15
|
-
'application/vnd.oasis.opendocument.spreadsheet': microsoftExcel,
|
|
16
|
-
'text/csv': fileTableOutline,
|
|
17
|
-
'application/msword': microsoftWord,
|
|
18
|
-
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': microsoftWord,
|
|
19
|
-
'application/vnd.oasis.opendocument.text': microsoftWord,
|
|
20
|
-
'application/rtf': microsoftWord,
|
|
21
|
-
'application/pdf': fileDocumentOutline,
|
|
22
|
-
'application/json': fileCodeOutline,
|
|
23
|
-
'application/x-httpd-php': fileCodeOutline,
|
|
24
|
-
'application/x-sh': fileCodeOutline,
|
|
25
|
-
'application/xml': fileCodeOutline,
|
|
26
|
-
'text/css': fileCodeOutline,
|
|
27
|
-
'text/html': fileCodeOutline,
|
|
28
|
-
'text/javascript': fileCodeOutline,
|
|
29
|
-
'application/gzip': archiveOutline,
|
|
30
|
-
'application/java-archive': archiveOutline,
|
|
31
|
-
'application/zip': archiveOutline,
|
|
32
|
-
'application/vnd.apple.installer+xml': archiveOutline,
|
|
33
|
-
'application/vnd.rar': archiveOutline,
|
|
34
|
-
'application/x-7z-compressed': archiveOutline,
|
|
35
|
-
'application/x-bzip': archiveOutline,
|
|
36
|
-
'application/x-bzip2': archiveOutline,
|
|
37
|
-
'application/x-tar': archiveOutline
|
|
38
|
-
};
|
|
39
|
-
const prefixes = {
|
|
40
|
-
image: fileImageOutline,
|
|
41
|
-
text: noteTextOutline,
|
|
42
|
-
video: fileVideoOutline,
|
|
43
|
-
audio: fileMusicOutline
|
|
44
|
-
};
|
|
45
|
-
</script>
|
|
46
1
|
<script>import Icon from './Icon.svelte';
|
|
2
|
+
import { iconForMime } from './fileIcons';
|
|
47
3
|
export let mime;
|
|
48
4
|
export let hiddenLabel = undefined;
|
|
49
5
|
export let inline = false;
|
|
50
6
|
export let width = '1em';
|
|
51
7
|
export let height = width;
|
|
52
8
|
export let vAlign = 'middle';
|
|
53
|
-
$: icon =
|
|
9
|
+
$: icon = iconForMime(mime);
|
|
54
10
|
</script>
|
|
55
11
|
|
|
56
12
|
<Icon {icon} {hiddenLabel} {inline} {width} {height} {vAlign} />
|
package/chooser/ChooserAPI.d.ts
CHANGED
|
@@ -3,10 +3,10 @@ export declare type ChooserType = 'asset' | 'page';
|
|
|
3
3
|
export declare type AnyItem = Asset | Folder | Page;
|
|
4
4
|
export interface Client<F = any> {
|
|
5
5
|
getSources: (type: ChooserType) => Promise<Source[]>;
|
|
6
|
-
getChildren: (source: string, path: string, filters: F) => Promise<
|
|
7
|
-
find: (source: string, path: string, searchstring: string, filters: F) => Promise<
|
|
8
|
-
findById: (id: string) => Promise<AnyItem>;
|
|
9
|
-
findByUrl?: (url: string) => Promise<AnyItem>;
|
|
6
|
+
getChildren: (source: string, path: string, filters: F) => Promise<AnyItem[]>;
|
|
7
|
+
find: (source: string, path: string, searchstring: string, filters: F) => Promise<AnyItem[]>;
|
|
8
|
+
findById: (id: string) => Promise<AnyItem | undefined>;
|
|
9
|
+
findByUrl?: (url: string) => Promise<AnyItem | undefined>;
|
|
10
10
|
urlToValue?: (url: string) => string;
|
|
11
11
|
upload: (source: string, path: string, files: FileList) => Promise<void>;
|
|
12
12
|
}
|
package/chooser/ChooserStore.js
CHANGED
|
@@ -58,7 +58,7 @@ export class ChooserStore extends SafeStore {
|
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
if (this.value.preview)
|
|
61
|
-
await this.openPathRecursive(
|
|
61
|
+
await this.openPathRecursive(this.value.preview.path);
|
|
62
62
|
else if (this.options.initialPath)
|
|
63
63
|
await this.openPathRecursive(this.options.initialPath);
|
|
64
64
|
else
|
|
@@ -77,7 +77,7 @@ export class ChooserStore extends SafeStore {
|
|
|
77
77
|
return item;
|
|
78
78
|
}
|
|
79
79
|
async open(folder) {
|
|
80
|
-
return await this.openPath(
|
|
80
|
+
return await this.openPath(folder.path);
|
|
81
81
|
}
|
|
82
82
|
async openPath(path) {
|
|
83
83
|
const folder = this.itemByPath(this.value, path);
|
|
@@ -118,7 +118,7 @@ export class ChooserStore extends SafeStore {
|
|
|
118
118
|
if (!current || current.type === 'asset')
|
|
119
119
|
break;
|
|
120
120
|
if (!current.open) {
|
|
121
|
-
current.children = await filterAsync(await this.client.getChildren(source.name,
|
|
121
|
+
current.children = await filterAsync(await this.client.getChildren(source.name, current.path, this.options.passthruFilters), this.options.filter);
|
|
122
122
|
current.loading = false;
|
|
123
123
|
current.open = true;
|
|
124
124
|
}
|
|
@@ -132,12 +132,12 @@ export class ChooserStore extends SafeStore {
|
|
|
132
132
|
if (!current)
|
|
133
133
|
return v;
|
|
134
134
|
v.focus = current.id;
|
|
135
|
-
v.focusPath =
|
|
135
|
+
v.focusPath = current.path;
|
|
136
136
|
return v;
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
139
|
async close(folder) {
|
|
140
|
-
return await this.closePath(
|
|
140
|
+
return await this.closePath(folder.path);
|
|
141
141
|
}
|
|
142
142
|
async closePath(path) {
|
|
143
143
|
this.update(v => {
|
|
@@ -158,7 +158,7 @@ export class ChooserStore extends SafeStore {
|
|
|
158
158
|
return this.clearPreview();
|
|
159
159
|
if (item.type === 'folder' && !this.options.chooseFolder)
|
|
160
160
|
return;
|
|
161
|
-
this.update(v => ({ ...v, preview: item, focus: item.id, focusPath:
|
|
161
|
+
this.update(v => ({ ...v, preview: item, focus: item.id, focusPath: item.path }));
|
|
162
162
|
}
|
|
163
163
|
clearPreview() {
|
|
164
164
|
this.update(v => ({ ...v, preview: undefined }));
|
|
@@ -172,7 +172,7 @@ export class ChooserStore extends SafeStore {
|
|
|
172
172
|
if (source.children?.length) {
|
|
173
173
|
const firstchild = source.children[0];
|
|
174
174
|
v.focus = firstchild.id;
|
|
175
|
-
v.focusPath =
|
|
175
|
+
v.focusPath = firstchild.path;
|
|
176
176
|
}
|
|
177
177
|
return v;
|
|
178
178
|
});
|
|
@@ -182,7 +182,7 @@ export class ChooserStore extends SafeStore {
|
|
|
182
182
|
const source = this.getSource(v);
|
|
183
183
|
source.children = children;
|
|
184
184
|
v.focus = children[0]?.id;
|
|
185
|
-
v.focusPath = children[0] ?
|
|
185
|
+
v.focusPath = children[0] ? children[0]?.path : undefined;
|
|
186
186
|
return v;
|
|
187
187
|
});
|
|
188
188
|
}
|
|
@@ -195,7 +195,7 @@ export class ChooserStore extends SafeStore {
|
|
|
195
195
|
return;
|
|
196
196
|
this.update(v => {
|
|
197
197
|
v.focus = itm.id;
|
|
198
|
-
v.focusPath =
|
|
198
|
+
v.focusPath = itm.path;
|
|
199
199
|
return v;
|
|
200
200
|
});
|
|
201
201
|
}
|
package/chooser/Details.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script>import { bytesToHuman
|
|
1
|
+
<script>import { bytesToHuman } from './ChooserStore';
|
|
2
2
|
export let item;
|
|
3
3
|
</script>
|
|
4
4
|
|
|
@@ -11,7 +11,7 @@ export let item;
|
|
|
11
11
|
{:else if item.type === 'page'}
|
|
12
12
|
<li>{item.title}</li>
|
|
13
13
|
{:else if item.type === 'folder'}
|
|
14
|
-
<li>{
|
|
14
|
+
<li>{item.path}</li>
|
|
15
15
|
{/if}
|
|
16
16
|
{#if item.type === 'asset'}
|
|
17
17
|
<li>{item.mime}</li>
|
package/fileIcons.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function iconForMime(mime: string): import("@iconify/types").IconifyIcon;
|
package/fileIcons.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
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
|
+
const fileIconsByMime = {
|
|
13
|
+
'application/vnd.ms-excel': microsoftExcel,
|
|
14
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': microsoftExcel,
|
|
15
|
+
'application/vnd.oasis.opendocument.spreadsheet': microsoftExcel,
|
|
16
|
+
'text/csv': fileTableOutline,
|
|
17
|
+
'application/msword': microsoftWord,
|
|
18
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': microsoftWord,
|
|
19
|
+
'application/vnd.oasis.opendocument.text': microsoftWord,
|
|
20
|
+
'application/rtf': microsoftWord,
|
|
21
|
+
'application/pdf': fileDocumentOutline,
|
|
22
|
+
'application/json': fileCodeOutline,
|
|
23
|
+
'application/x-httpd-php': fileCodeOutline,
|
|
24
|
+
'application/x-sh': fileCodeOutline,
|
|
25
|
+
'application/xml': fileCodeOutline,
|
|
26
|
+
'text/css': fileCodeOutline,
|
|
27
|
+
'text/html': fileCodeOutline,
|
|
28
|
+
'text/javascript': fileCodeOutline,
|
|
29
|
+
'application/gzip': archiveOutline,
|
|
30
|
+
'application/java-archive': archiveOutline,
|
|
31
|
+
'application/zip': archiveOutline,
|
|
32
|
+
'application/vnd.apple.installer+xml': archiveOutline,
|
|
33
|
+
'application/vnd.rar': archiveOutline,
|
|
34
|
+
'application/x-7z-compressed': archiveOutline,
|
|
35
|
+
'application/x-bzip': archiveOutline,
|
|
36
|
+
'application/x-bzip2': archiveOutline,
|
|
37
|
+
'application/x-tar': archiveOutline
|
|
38
|
+
};
|
|
39
|
+
const prefixes = {
|
|
40
|
+
image: fileImageOutline,
|
|
41
|
+
text: noteTextOutline,
|
|
42
|
+
video: fileVideoOutline,
|
|
43
|
+
audio: fileMusicOutline
|
|
44
|
+
};
|
|
45
|
+
export function iconForMime(mime) {
|
|
46
|
+
return fileIconsByMime[mime] ?? prefixes[mime.split('/', 2)[0]] ?? fileOutline;
|
|
47
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
<script>import FieldStandard from '../FieldStandard.svelte';
|
|
2
|
+
import { ScreenReaderOnly, Modal, modifierKey } from '@txstate-mws/svelte-components';
|
|
3
|
+
import { FontAwesomeIcons, IconCategories } from './iconpicker';
|
|
4
|
+
import Icon from '@iconify/svelte';
|
|
5
|
+
import { randomid, keyby } from 'txstate-utils';
|
|
6
|
+
export let id = undefined;
|
|
7
|
+
export let path;
|
|
8
|
+
export let label = '';
|
|
9
|
+
export let required = false;
|
|
10
|
+
export let defaultValue = { icon: 'fa-graduation-cap', prefix: 'fas' };
|
|
11
|
+
export let conditional = undefined;
|
|
12
|
+
const labelid = randomid();
|
|
13
|
+
const descid = randomid();
|
|
14
|
+
let modalOpen = false;
|
|
15
|
+
let selected = defaultValue;
|
|
16
|
+
const iconToPrefix = {};
|
|
17
|
+
const categoriesToIcons = keyby(IconCategories, 'key');
|
|
18
|
+
for (const icon of FontAwesomeIcons) {
|
|
19
|
+
iconToPrefix[icon.class] = icon.free.indexOf('brands') > -1 ? 'fab' : 'fas';
|
|
20
|
+
}
|
|
21
|
+
const iconElements = [];
|
|
22
|
+
let visibleIcons = FontAwesomeIcons;
|
|
23
|
+
let searchVal = '';
|
|
24
|
+
let category = 'all';
|
|
25
|
+
$: iconCountMessage = visibleIcons.length === FontAwesomeIcons.length ? 'Showing all icons' : `Showing ${visibleIcons.length} icons`;
|
|
26
|
+
function onSelectIcon(iconClass) {
|
|
27
|
+
selected = { icon: iconClass, prefix: iconToPrefix[iconClass] };
|
|
28
|
+
}
|
|
29
|
+
function onSaveIconSelection(setVal) {
|
|
30
|
+
return function () {
|
|
31
|
+
setVal(selected);
|
|
32
|
+
category = 'all';
|
|
33
|
+
searchVal = '';
|
|
34
|
+
visibleIcons = FontAwesomeIcons;
|
|
35
|
+
modalOpen = false;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function onCancel(val) {
|
|
39
|
+
return function () {
|
|
40
|
+
selected = val;
|
|
41
|
+
category = 'all';
|
|
42
|
+
searchVal = '';
|
|
43
|
+
visibleIcons = FontAwesomeIcons;
|
|
44
|
+
modalOpen = false;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function onSearch() {
|
|
48
|
+
visibleIcons = FontAwesomeIcons.filter(i => {
|
|
49
|
+
if (i.class.includes(searchVal))
|
|
50
|
+
return true;
|
|
51
|
+
for (const term of i.search.terms) {
|
|
52
|
+
if (term.includes(searchVal))
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
});
|
|
57
|
+
if (visibleIcons.findIndex(i => i.class === selected.icon) < 0) {
|
|
58
|
+
onSelectIcon(visibleIcons[0].class);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function onSelectCategory() {
|
|
62
|
+
if (category === 'all') {
|
|
63
|
+
visibleIcons = FontAwesomeIcons;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
visibleIcons = FontAwesomeIcons.filter(i => {
|
|
67
|
+
return categoriesToIcons[category].icons.includes(i.class);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (visibleIcons.findIndex(i => i.class === selected.icon) < 0) {
|
|
71
|
+
onSelectIcon(visibleIcons[0].class);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function onKeyDown(e) {
|
|
75
|
+
const currentSelectionIndex = visibleIcons.findIndex(i => i.class === selected.icon);
|
|
76
|
+
let newIndex;
|
|
77
|
+
if (modifierKey(e))
|
|
78
|
+
return;
|
|
79
|
+
else if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
if (currentSelectionIndex === visibleIcons.length - 1) {
|
|
82
|
+
newIndex = 0;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
newIndex = currentSelectionIndex + 1;
|
|
86
|
+
}
|
|
87
|
+
onSelectIcon(visibleIcons[newIndex].class);
|
|
88
|
+
iconElements[newIndex].focus();
|
|
89
|
+
}
|
|
90
|
+
else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
if (currentSelectionIndex === 0) {
|
|
93
|
+
newIndex = visibleIcons.length - 1;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
newIndex = currentSelectionIndex - 1;
|
|
97
|
+
}
|
|
98
|
+
onSelectIcon(visibleIcons[newIndex].class);
|
|
99
|
+
iconElements[newIndex].focus();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<FieldStandard bind:id {path} {label} {required} {defaultValue} {conditional} let:value let:valid let:invalid let:id let:onBlur let:setVal>
|
|
105
|
+
<Icon icon={`${value.prefix === 'fab' ? 'fa-brands' : 'fa-solid'}:${value.icon.slice(3)}`}/>
|
|
106
|
+
<button id="btnSelectIcon" on:click={() => { modalOpen = true }}>Select New Icon</button>
|
|
107
|
+
{#if modalOpen}
|
|
108
|
+
<Modal>
|
|
109
|
+
<section>
|
|
110
|
+
<header id={labelid}>
|
|
111
|
+
Select Icon
|
|
112
|
+
</header>
|
|
113
|
+
<div id={descid} class="content">
|
|
114
|
+
<div class="icon-modal-content">
|
|
115
|
+
<div class="filters">
|
|
116
|
+
<div class="search-wrapper">
|
|
117
|
+
<input bind:value={searchVal} id="search_for" placeholder="Search Icons" on:keyup={onSearch}/>
|
|
118
|
+
<label for="search_for" class="fa fa-search" rel="tooltip" title="search"></label>
|
|
119
|
+
</div>
|
|
120
|
+
<select bind:value={category} class="icon-category" aria-label="Select Category" on:change={onSelectCategory}>
|
|
121
|
+
<option value="all">All</option>
|
|
122
|
+
{#each IconCategories as category (category.key)}
|
|
123
|
+
<option value={category.key}>{category.label}</option>
|
|
124
|
+
{/each}
|
|
125
|
+
</select>
|
|
126
|
+
</div>
|
|
127
|
+
<fieldset tabindex="0">
|
|
128
|
+
<ScreenReaderOnly><legend class="sr-only">Icons</legend></ScreenReaderOnly>
|
|
129
|
+
<div class="icon-picker-items" role="radiogroup" on:keydown={onKeyDown}>
|
|
130
|
+
{#each visibleIcons as icon, idx (icon.class)}
|
|
131
|
+
<div bind:this={iconElements[idx]} id={icon.class} class="icon-picker-item" role="radio" aria-checked={icon.class === selected.icon} tabindex={icon.class === selected.icon ? 0 : -1} data-index={idx} on:click={() => onSelectIcon(icon.class)}>
|
|
132
|
+
<Icon icon={`${iconToPrefix[icon.class] === 'fab' ? 'fa-brands' : 'fa-solid'}:${icon.class.slice(3)}`}/>
|
|
133
|
+
<ScreenReaderOnly>{icon.label}</ScreenReaderOnly>
|
|
134
|
+
</div>
|
|
135
|
+
{:else}
|
|
136
|
+
<div id="no-icons">No Icons Found</div>
|
|
137
|
+
{/each}
|
|
138
|
+
</div>
|
|
139
|
+
<ScreenReaderOnly arialive="polite">{iconCountMessage}</ScreenReaderOnly>
|
|
140
|
+
</fieldset>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
<footer class="actions">
|
|
144
|
+
<button aria-describedby="{labelid} {descid}" on:click={onCancel(value)}>Cancel</button>
|
|
145
|
+
<button aria-describedby="{labelid} {descid}" on:click={onSaveIconSelection(setVal)}>Save Changes</button>
|
|
146
|
+
</footer>
|
|
147
|
+
</section>
|
|
148
|
+
</Modal>
|
|
149
|
+
{/if}
|
|
150
|
+
</FieldStandard>
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
<style>
|
|
154
|
+
section {
|
|
155
|
+
position: relative;
|
|
156
|
+
background-color: #f4f4f4;
|
|
157
|
+
border-radius: 0.5em;
|
|
158
|
+
padding: 1em;
|
|
159
|
+
overflow: hidden;
|
|
160
|
+
width: 75vw;
|
|
161
|
+
min-width: 250px;
|
|
162
|
+
max-width: 650px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
footer {
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
justify-content: flex-end;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.icon-modal-content {
|
|
172
|
+
display:flex;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
height: 100%;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.icon-modal-content .filters {
|
|
178
|
+
display: flex;
|
|
179
|
+
justify-content: center;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.icon-modal-content .filters select {
|
|
183
|
+
width: 40%;
|
|
184
|
+
margin: 10px 0 5px 0;
|
|
185
|
+
height: 30px;
|
|
186
|
+
border-radius: 10px;
|
|
187
|
+
background-color: white;
|
|
188
|
+
border: 1px solid #999;
|
|
189
|
+
font-family: 'Nunito Sans', sans-serif !important;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.icon-modal-content fieldset {
|
|
193
|
+
max-height: 80%;
|
|
194
|
+
overflow-y: scroll;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* Styles for search field */
|
|
198
|
+
|
|
199
|
+
.search-wrapper{
|
|
200
|
+
position: relative;
|
|
201
|
+
margin-top: 10px;
|
|
202
|
+
margin-bottom: 5px;
|
|
203
|
+
margin-right: 15px;
|
|
204
|
+
align-self: center;
|
|
205
|
+
width: 50%;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
#search_for{
|
|
209
|
+
width: 90%;
|
|
210
|
+
border-radius: 10px;
|
|
211
|
+
border: 1px solid #999;
|
|
212
|
+
height: 30px;
|
|
213
|
+
padding: 0px 0px 0px 30px;
|
|
214
|
+
font-family: 'Nunito Sans', sans-serif !important;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
#search_for + label{
|
|
218
|
+
position: absolute;
|
|
219
|
+
left: 7px;
|
|
220
|
+
top: 7px;
|
|
221
|
+
color: #999;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* Styles for the icon picker grid */
|
|
225
|
+
|
|
226
|
+
.icon-picker-items{
|
|
227
|
+
margin-top: 5px;
|
|
228
|
+
padding: 5px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.icon-picker-item {
|
|
232
|
+
float: left;
|
|
233
|
+
margin: 0px 11px 12px 11px;
|
|
234
|
+
text-align: center;
|
|
235
|
+
cursor: pointer;
|
|
236
|
+
color: inherit;
|
|
237
|
+
width: 10%;
|
|
238
|
+
position: relative;
|
|
239
|
+
font-size: 28px;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.icon-picker-item[aria-checked=true] {
|
|
243
|
+
outline: 4px solid #93BBC4;
|
|
244
|
+
background-color: #eee;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* Message when no icons are returned from search */
|
|
248
|
+
#no-icons{
|
|
249
|
+
margin-top: 10px;
|
|
250
|
+
font-size: 1.5rem;
|
|
251
|
+
text-align: center;
|
|
252
|
+
vertical-align: middle;
|
|
253
|
+
line-height: 250px;
|
|
254
|
+
color: #999;
|
|
255
|
+
}
|
|
256
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
id?: string | undefined;
|
|
5
|
+
path: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
defaultValue?: {
|
|
9
|
+
icon: string;
|
|
10
|
+
prefix: string;
|
|
11
|
+
};
|
|
12
|
+
conditional?: boolean | undefined;
|
|
13
|
+
};
|
|
14
|
+
events: {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
};
|
|
17
|
+
slots: {};
|
|
18
|
+
};
|
|
19
|
+
export declare type FieldIconPickerProps = typeof __propDef.props;
|
|
20
|
+
export declare type FieldIconPickerEvents = typeof __propDef.events;
|
|
21
|
+
export declare type FieldIconPickerSlots = typeof __propDef.slots;
|
|
22
|
+
export default class FieldIconPicker extends SvelteComponentTyped<FieldIconPickerProps, FieldIconPickerEvents, FieldIconPickerSlots> {
|
|
23
|
+
}
|
|
24
|
+
export {};
|