@txstate-mws/svelte-components 1.0.2 → 1.1.1
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/README.md +33 -14
- package/{dist/ts/actions → actions}/buttonify.d.ts +0 -0
- package/{dist/actions → actions}/buttonify.js +1 -6
- package/{dist/ts/actions → actions}/glue.d.ts +1 -1
- package/{dist/actions → actions}/glue.js +8 -13
- package/actions/index.d.ts +7 -0
- package/actions/index.js +7 -0
- package/actions/offset.d.ts +15 -0
- package/actions/offset.js +35 -0
- package/{dist/ts/actions → actions}/portal.d.ts +0 -0
- package/actions/portal.js +13 -0
- package/{dist/ts/actions → actions}/resize.d.ts +6 -2
- package/actions/resize.js +57 -0
- package/{dist/ts/actions → actions}/sticky.d.ts +2 -2
- package/{dist/actions → actions}/sticky.js +11 -19
- package/{dist/ts/actions → actions}/stickyfixed.d.ts +2 -2
- package/{dist/actions → actions}/stickyfixed.js +15 -24
- package/components/Card.svelte +23 -0
- package/components/Card.svelte.d.ts +18 -0
- package/components/CardLayout.svelte +197 -0
- package/components/CardLayout.svelte.d.ts +21 -0
- package/{dist/components → components}/CollapsingTable.svelte +12 -13
- package/components/CollapsingTable.svelte.d.ts +59 -0
- package/{dist/ts/components → components}/ConditionalWrapper.svelte +6 -7
- package/components/ConditionalWrapper.svelte.d.ts +23 -0
- package/{dist/components → components}/FocusLock.svelte +11 -9
- package/components/FocusLock.svelte.d.ts +26 -0
- package/{dist/components → components}/Modal.svelte +5 -4
- package/components/Modal.svelte.d.ts +27 -0
- package/components/MultiSelect.svelte +179 -0
- package/components/MultiSelect.svelte.d.ts +35 -0
- package/{dist/components → components}/PopupMenu.svelte +29 -24
- package/components/PopupMenu.svelte.d.ts +45 -0
- package/{dist/components → components}/ScreenReaderOnly.svelte +1 -1
- package/components/ScreenReaderOnly.svelte.d.ts +20 -0
- package/{dist/ts/components → components}/index.d.ts +3 -0
- package/components/index.js +9 -0
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/package.json +47 -77
- package/types/CardLayout.d.ts +14 -0
- package/types/CardLayout.js +1 -0
- package/{dist/ts/types → types}/CollapsingTable.d.ts +0 -0
- package/{dist/ts/tests/Actions/Actions.stories.d.ts → types/CollapsingTable.js} +0 -0
- package/{dist/ts/types → types}/PopupMenu.d.ts +0 -0
- package/{dist/ts/tests/CollapsingTable/CollapsingTable.stories.d.ts → types/PopupMenu.js} +0 -0
- package/types/index.d.ts +3 -0
- package/types/index.js +3 -0
- package/{dist/ts/lib → util}/bodyoffset.d.ts +2 -1
- package/{dist/lib → util}/bodyoffset.js +10 -14
- package/util/index.d.ts +3 -0
- package/util/index.js +3 -0
- package/{dist/ts/lib → util}/repositioned.d.ts +1 -2
- package/{dist/lib → util}/repositioned.js +13 -24
- package/util/util.d.ts +5 -0
- package/util/util.js +33 -0
- package/LICENSE +0 -21
- package/dist/actions/buttonify.js.map +0 -1
- package/dist/actions/glue.js.map +0 -1
- package/dist/actions/index.js +0 -20
- package/dist/actions/index.js.map +0 -1
- package/dist/actions/offset.js +0 -35
- package/dist/actions/offset.js.map +0 -1
- package/dist/actions/portal.js +0 -19
- package/dist/actions/portal.js.map +0 -1
- package/dist/actions/resize.js +0 -48
- package/dist/actions/resize.js.map +0 -1
- package/dist/actions/sticky.js.map +0 -1
- package/dist/actions/stickyfixed.js.map +0 -1
- package/dist/components/ConditionalWrapper.svelte +0 -38
- package/dist/components/index.js +0 -19
- package/dist/components/index.js.map +0 -1
- package/dist/index.js +0 -17
- package/dist/index.js.map +0 -1
- package/dist/lib/activestore.js +0 -123
- package/dist/lib/activestore.js.map +0 -1
- package/dist/lib/bodyoffset.js.map +0 -1
- package/dist/lib/convertedstore.js +0 -41
- package/dist/lib/convertedstore.js.map +0 -1
- package/dist/lib/derivedstore.js +0 -65
- package/dist/lib/derivedstore.js.map +0 -1
- package/dist/lib/index.js +0 -22
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/repositioned.js.map +0 -1
- package/dist/lib/safestore.js +0 -16
- package/dist/lib/safestore.js.map +0 -1
- package/dist/lib/store.js +0 -27
- package/dist/lib/store.js.map +0 -1
- package/dist/lib/substore.js +0 -47
- package/dist/lib/substore.js.map +0 -1
- package/dist/lib/util.js +0 -16
- package/dist/lib/util.js.map +0 -1
- package/dist/ts/actions/index.d.ts +0 -7
- package/dist/ts/actions/offset.d.ts +0 -15
- package/dist/ts/components/CollapsingTable.svelte +0 -147
- package/dist/ts/components/FocusLock.svelte +0 -101
- package/dist/ts/components/Modal.svelte +0 -54
- package/dist/ts/components/PopupMenu.svelte +0 -279
- package/dist/ts/components/ScreenReaderOnly.svelte +0 -26
- package/dist/ts/index.d.ts +0 -4
- package/dist/ts/lib/activestore.d.ts +0 -60
- package/dist/ts/lib/convertedstore.d.ts +0 -16
- package/dist/ts/lib/derivedstore.d.ts +0 -23
- package/dist/ts/lib/index.d.ts +0 -9
- package/dist/ts/lib/safestore.d.ts +0 -4
- package/dist/ts/lib/store.d.ts +0 -16
- package/dist/ts/lib/substore.d.ts +0 -24
- package/dist/ts/lib/util.d.ts +0 -2
- package/dist/ts/tests/Actions/Offset.svelte +0 -34
- package/dist/ts/tests/Actions/Resize.svelte +0 -31
- package/dist/ts/tests/Actions/Sticky.svelte +0 -65
- package/dist/ts/tests/CollapsingTable/CollapsingTable.test.d.ts +0 -1
- package/dist/ts/tests/CollapsingTable/CollapsingTableTest.svelte +0 -36
- package/dist/ts/tests/Modal/Modal.stories.d.ts +0 -1
- package/dist/ts/tests/Modal/Modal.test.d.ts +0 -1
- package/dist/ts/tests/Modal/ModalTest.svelte +0 -58
- package/dist/ts/tests/PopupMenu/PopupMenu.stories.d.ts +0 -1
- package/dist/ts/tests/PopupMenu/PopupMenu.test.d.ts +0 -1
- package/dist/ts/tests/PopupMenu/PopupMenuBody.svelte +0 -34
- package/dist/ts/tests/PopupMenu/PopupMenuButtonIsParent.svelte +0 -36
- package/dist/ts/tests/PopupMenu/PopupMenuComplex.svelte +0 -34
- package/dist/ts/tests/PopupMenu/PopupMenuSimple.svelte +0 -36
- package/dist/ts/tests/stores/deepstore.test.d.ts +0 -1
- package/dist/ts/types/index.d.ts +0 -2
- package/dist/types/CollapsingTable.js +0 -3
- package/dist/types/CollapsingTable.js.map +0 -1
- package/dist/types/PopupMenu.js +0 -3
- package/dist/types/PopupMenu.js.map +0 -1
- package/dist/types/index.js +0 -15
- package/dist/types/index.js.map +0 -1
- package/docs/CollapsingTable.md +0 -79
- package/docs/ConditionalWrapper.md +0 -35
- package/docs/Modal.md +0 -63
- package/docs/PopupMenu.md +0 -31
- package/docs/ScreenReaderOnly.md +0 -10
- package/docs/actions.md +0 -84
- package/docs/stores.md +0 -203
- package/esm/index.js +0 -1
- package/esm/package.json +0 -3
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<script >import { createEventDispatcher } from 'svelte';
|
|
2
|
+
import { randomid } from 'txstate-utils';
|
|
3
|
+
import ScreenReaderOnly from './ScreenReaderOnly.svelte';
|
|
4
|
+
import DefaultPopupMenu from './PopupMenu.svelte';
|
|
5
|
+
import { debouncedPromise, modifierKey, selectionIsLeft } from '../util';
|
|
6
|
+
export let id = randomid();
|
|
7
|
+
export let name;
|
|
8
|
+
export let getOptions;
|
|
9
|
+
export let menuContainerClass = undefined;
|
|
10
|
+
export let menuClass = undefined;
|
|
11
|
+
export let menuItemClass = undefined;
|
|
12
|
+
export let menuItemHilitedClass = undefined;
|
|
13
|
+
export let selected = [];
|
|
14
|
+
export let placeholder = '';
|
|
15
|
+
export let emptyText = undefined;
|
|
16
|
+
export let PopupMenu = DefaultPopupMenu;
|
|
17
|
+
let menushown;
|
|
18
|
+
let options = [];
|
|
19
|
+
let hilitedpill;
|
|
20
|
+
let inputvalue = '';
|
|
21
|
+
let popupvalue = undefined;
|
|
22
|
+
let inputelement;
|
|
23
|
+
const descriptionid = randomid();
|
|
24
|
+
$: debouncedGetOptions = debouncedPromise(getOptions, 100, []);
|
|
25
|
+
$: selectedSet = new Set(selected.map(s => s.value));
|
|
26
|
+
async function reactToInput(..._) {
|
|
27
|
+
const saveval = inputvalue;
|
|
28
|
+
const rawOptions = await debouncedGetOptions(saveval);
|
|
29
|
+
if (inputvalue !== saveval)
|
|
30
|
+
return; // ignore any results that are out of date
|
|
31
|
+
options = rawOptions.filter(o => !selectedSet.has(o.value));
|
|
32
|
+
if (typeof document !== 'undefined' && inputelement === document.activeElement)
|
|
33
|
+
menushown = true;
|
|
34
|
+
}
|
|
35
|
+
$: reactToInput(inputvalue, debouncedGetOptions, selectedSet);
|
|
36
|
+
$: availablemessage = options.filter(o => o.value).length + ' autocomplete choices available';
|
|
37
|
+
function addSelection(e) {
|
|
38
|
+
inputvalue = '';
|
|
39
|
+
const opt = { ...e.detail, label: e.detail.label || e.detail.value };
|
|
40
|
+
selected = [...selected, opt];
|
|
41
|
+
popupvalue = undefined;
|
|
42
|
+
}
|
|
43
|
+
function removeSelection(opt, idx, nextfocus = 1) {
|
|
44
|
+
if (hilitedpill === opt.value) {
|
|
45
|
+
hilitedpill = selected[idx + nextfocus]?.value;
|
|
46
|
+
}
|
|
47
|
+
selected = selected.filter(s => s.value !== opt.value);
|
|
48
|
+
}
|
|
49
|
+
function inputkeydown(e) {
|
|
50
|
+
if (modifierKey(e))
|
|
51
|
+
return;
|
|
52
|
+
if (e.key === 'ArrowLeft' && selectionIsLeft(inputelement)) {
|
|
53
|
+
const idx = hilitedpill ? selected.findIndex(s => s.value === hilitedpill) : selected.length;
|
|
54
|
+
if (idx !== 0)
|
|
55
|
+
hilitedpill = selected[idx - 1].value;
|
|
56
|
+
}
|
|
57
|
+
else if (e.key === 'ArrowRight' && selectionIsLeft(inputelement)) {
|
|
58
|
+
if (hilitedpill)
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
const idx = hilitedpill ? selected.findIndex(s => s.value === hilitedpill) : undefined;
|
|
61
|
+
if (idx != null) {
|
|
62
|
+
if (idx === selected.length - 1)
|
|
63
|
+
hilitedpill = undefined;
|
|
64
|
+
else
|
|
65
|
+
hilitedpill = selected[idx + 1].value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (['Backspace', 'Delete', 'Clear', ' ', 'Enter'].includes(e.key)) {
|
|
69
|
+
if (hilitedpill) {
|
|
70
|
+
const idx = selected.findIndex(s => s.value === hilitedpill);
|
|
71
|
+
removeSelection(selected[idx], idx, e.key === 'Delete' ? 1 : -1);
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
}
|
|
74
|
+
else if (e.key === 'Backspace' && selectionIsLeft(inputelement)) {
|
|
75
|
+
removeSelection(selected[selected.length - 1], selected.length - 1, -1);
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function inputfocus() {
|
|
81
|
+
reactToInput();
|
|
82
|
+
}
|
|
83
|
+
let popuphilited;
|
|
84
|
+
$: if (popuphilited != null)
|
|
85
|
+
hilitedpill = undefined;
|
|
86
|
+
function reactToHilite(..._) {
|
|
87
|
+
if (!inputelement)
|
|
88
|
+
return;
|
|
89
|
+
if (hilitedpill) {
|
|
90
|
+
popuphilited = undefined;
|
|
91
|
+
inputelement.setAttribute('aria-activedescendant', id + hilitedpill);
|
|
92
|
+
}
|
|
93
|
+
else
|
|
94
|
+
inputelement.removeAttribute('aria-activedescendant');
|
|
95
|
+
}
|
|
96
|
+
$: reactToHilite(hilitedpill, id);
|
|
97
|
+
const dispatch = createEventDispatcher();
|
|
98
|
+
$: dispatch('change', selected);
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<fieldset>
|
|
102
|
+
<ul class="multiselect-selected" role="listbox" on:click={() => inputelement.focus()}>
|
|
103
|
+
{#each selected as option, i}
|
|
104
|
+
<li id={id + option.value} role="option" tabindex="-1" class="multiselect-pill" class:hilited={hilitedpill === option.value}
|
|
105
|
+
on:click|preventDefault|stopPropagation={() => removeSelection(option, i, 1)}
|
|
106
|
+
aria-selected="true">
|
|
107
|
+
{option.label || option.value}
|
|
108
|
+
<ScreenReaderOnly>, click to remove</ScreenReaderOnly>
|
|
109
|
+
</li>
|
|
110
|
+
{/each}
|
|
111
|
+
<li class="input">
|
|
112
|
+
<input type="text" id={id} name={name} placeholder={placeholder}
|
|
113
|
+
bind:this={inputelement} bind:value={inputvalue}
|
|
114
|
+
on:focus={inputfocus} on:keydown={inputkeydown}
|
|
115
|
+
autocomplete="off" autocorrect="off" spellcheck="false" aria-autocomplete="list"
|
|
116
|
+
aria-describedby="{descriptionid}">
|
|
117
|
+
</li>
|
|
118
|
+
</ul>
|
|
119
|
+
<ScreenReaderOnly id={descriptionid} arialive="assertive">
|
|
120
|
+
<span>{selected.length ? selected.length + ' selected' : 'select multiple, none selected'}, up down to choose, left right to hilite existing choices</span>
|
|
121
|
+
{#if menushown}<span>{availablemessage}, touch users explore to find autocomplete menu</span>{/if}
|
|
122
|
+
</ScreenReaderOnly>
|
|
123
|
+
<slot></slot>
|
|
124
|
+
</fieldset>
|
|
125
|
+
<svelte:component this={PopupMenu} bind:menushown bind:hilited={popuphilited} bind:value={popupvalue} align='bottomleft' {emptyText} {menuContainerClass} {menuClass} {menuItemClass} {menuItemHilitedClass} items={options} buttonelement={inputelement} on:change={addSelection}></svelte:component>
|
|
126
|
+
|
|
127
|
+
<style>
|
|
128
|
+
fieldset {
|
|
129
|
+
border: 0;
|
|
130
|
+
padding: 0;
|
|
131
|
+
margin: 0;
|
|
132
|
+
}
|
|
133
|
+
fieldset * {
|
|
134
|
+
box-sizing: border-box;
|
|
135
|
+
}
|
|
136
|
+
.multiselect-selected {
|
|
137
|
+
margin: 0;
|
|
138
|
+
padding: 0;
|
|
139
|
+
list-style: none;
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-wrap: wrap;
|
|
142
|
+
align-items: stretch;
|
|
143
|
+
padding: var(--multiselect-padding, 0.3em);
|
|
144
|
+
border: var(--multiselect-border, 1px solid #666666);
|
|
145
|
+
border-radius: var(--multiselect-radius, 0.3em);
|
|
146
|
+
}
|
|
147
|
+
.multiselect-selected:focus-within {
|
|
148
|
+
outline-width: var(--multiselect-focus-width, 2px);
|
|
149
|
+
outline-style: solid;
|
|
150
|
+
outline-color: var(--multiselect-focus-color, Highlight);
|
|
151
|
+
}
|
|
152
|
+
li.input {
|
|
153
|
+
flex-grow: 1;
|
|
154
|
+
}
|
|
155
|
+
input {
|
|
156
|
+
outline: 0;
|
|
157
|
+
border: 0;
|
|
158
|
+
min-width: 0;
|
|
159
|
+
width: 100%;
|
|
160
|
+
height: 100%;
|
|
161
|
+
}
|
|
162
|
+
.multiselect-pill {
|
|
163
|
+
cursor: pointer;
|
|
164
|
+
flex-grow: 0;
|
|
165
|
+
margin-right: 0.3em;
|
|
166
|
+
line-height: 1;
|
|
167
|
+
border-radius: var(--multiselect-pill-radius, 0.8em);
|
|
168
|
+
border: var(--multiselect-pill-border, 1px solid gray);
|
|
169
|
+
background-color: var(--multiselect-pill-bg, transparent);
|
|
170
|
+
color: var(--multiselect-pill-text, black);
|
|
171
|
+
padding: var(--multiselect-pill-padding, 0.3em 0.5em);
|
|
172
|
+
}
|
|
173
|
+
.multiselect-pill.hilited {
|
|
174
|
+
outline: 0;
|
|
175
|
+
background-color: var(--multiselect-pill-selected, gray);
|
|
176
|
+
border: var(--multiselect-pill-selected-border, 1px solid transparent);
|
|
177
|
+
color: var(--multiselect-pill-selected-text, white);
|
|
178
|
+
}
|
|
179
|
+
</style>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import DefaultPopupMenu from './PopupMenu.svelte';
|
|
3
|
+
import type { PopupMenuItem } from '../types';
|
|
4
|
+
declare const __propDef: {
|
|
5
|
+
props: {
|
|
6
|
+
id?: string;
|
|
7
|
+
name: string;
|
|
8
|
+
getOptions: (search: string) => Promise<PopupMenuItem[]> | PopupMenuItem[];
|
|
9
|
+
menuContainerClass?: string | undefined;
|
|
10
|
+
menuClass?: string | undefined;
|
|
11
|
+
menuItemClass?: string | undefined;
|
|
12
|
+
menuItemHilitedClass?: string | undefined;
|
|
13
|
+
selected?: {
|
|
14
|
+
value: string;
|
|
15
|
+
label: string;
|
|
16
|
+
}[];
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
emptyText?: string | undefined;
|
|
19
|
+
PopupMenu?: typeof DefaultPopupMenu;
|
|
20
|
+
};
|
|
21
|
+
events: {
|
|
22
|
+
change: CustomEvent<any>;
|
|
23
|
+
} & {
|
|
24
|
+
[evt: string]: CustomEvent<any>;
|
|
25
|
+
};
|
|
26
|
+
slots: {
|
|
27
|
+
default: {};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export declare type MultiSelectProps = typeof __propDef.props;
|
|
31
|
+
export declare type MultiSelectEvents = typeof __propDef.events;
|
|
32
|
+
export declare type MultiSelectSlots = typeof __propDef.slots;
|
|
33
|
+
export default class MultiSelect extends SvelteComponentTyped<MultiSelectProps, MultiSelectEvents, MultiSelectSlots> {
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
<script>import {
|
|
2
|
-
import { createEventDispatcher, onDestroy, tick } from 'svelte';
|
|
1
|
+
<script >import { createEventDispatcher, onDestroy, tick } from 'svelte';
|
|
3
2
|
import { randomid } from 'txstate-utils';
|
|
4
|
-
import { Store } from '
|
|
3
|
+
import { Store } from '@txstate-mws/svelte-store';
|
|
4
|
+
import { glue, portal } from '../actions';
|
|
5
5
|
import ScreenReaderOnly from './ScreenReaderOnly.svelte';
|
|
6
|
+
import { modifierKey } from '../util';
|
|
6
7
|
const dispatch = createEventDispatcher();
|
|
7
8
|
export let menushown = false;
|
|
8
9
|
export let menuContainerClass = '';
|
|
@@ -20,9 +21,9 @@ export let computedalign = new Store({ valign: 'bottom', halign: 'left' });
|
|
|
20
21
|
export let usePortal = undefined;
|
|
21
22
|
export let emptyText = undefined;
|
|
22
23
|
export let value = undefined;
|
|
23
|
-
let hilited = undefined;
|
|
24
|
+
export let hilited = undefined;
|
|
24
25
|
let menuelement;
|
|
25
|
-
|
|
26
|
+
const itemelements = [];
|
|
26
27
|
const menuid = randomid();
|
|
27
28
|
let firstactive = 0;
|
|
28
29
|
let lastactive = items.length - 1;
|
|
@@ -30,10 +31,9 @@ function hiddenItem(item) {
|
|
|
30
31
|
return !!item && !showSelected && item.value === value;
|
|
31
32
|
}
|
|
32
33
|
async function reactToItems(..._) {
|
|
33
|
-
var _a;
|
|
34
34
|
firstactive = items.findIndex(itm => !itm.disabled && !hiddenItem(itm));
|
|
35
35
|
lastactive = items.length - [...items].reverse().findIndex(itm => !itm.disabled && !hiddenItem(itm)) - 1;
|
|
36
|
-
if (hilited &&
|
|
36
|
+
if (hilited && items[hilited]?.disabled)
|
|
37
37
|
hilited = firstactive;
|
|
38
38
|
}
|
|
39
39
|
$: reactToItems(items, value);
|
|
@@ -44,53 +44,55 @@ async function reactToMenuShown(_) {
|
|
|
44
44
|
}
|
|
45
45
|
await tick();
|
|
46
46
|
if (!menushown) {
|
|
47
|
-
hilited = undefined;
|
|
48
47
|
buttonelement.removeAttribute('aria-controls');
|
|
49
48
|
buttonelement.setAttribute('aria-expanded', 'false');
|
|
49
|
+
if (hilited)
|
|
50
|
+
buttonelement.removeAttribute('aria-activedescendant');
|
|
51
|
+
hilited = undefined;
|
|
50
52
|
}
|
|
51
53
|
else {
|
|
52
54
|
buttonelement.setAttribute('aria-controls', menuid);
|
|
53
55
|
buttonelement.setAttribute('aria-expanded', 'true');
|
|
56
|
+
buttonelement.focus();
|
|
54
57
|
}
|
|
55
|
-
buttonelement.focus();
|
|
56
58
|
}
|
|
57
59
|
$: reactToMenuShown(menushown);
|
|
58
60
|
function move(idx) {
|
|
59
|
-
var _a;
|
|
60
61
|
if (!menushown)
|
|
61
62
|
return;
|
|
62
|
-
if (
|
|
63
|
+
if (items[idx]?.disabled)
|
|
63
64
|
return;
|
|
64
65
|
hilited = Math.max(firstactive, Math.min(lastactive, idx));
|
|
65
66
|
itemelements[hilited].scrollIntoView({ block: 'center' });
|
|
66
67
|
buttonelement.setAttribute('aria-activedescendant', `${menuid}-${hilited}`);
|
|
67
68
|
}
|
|
68
69
|
function onkeydown(e) {
|
|
69
|
-
|
|
70
|
+
if (modifierKey(e))
|
|
71
|
+
return;
|
|
70
72
|
if (e.key === 'ArrowDown') {
|
|
71
73
|
e.preventDefault();
|
|
72
74
|
if (menushown) {
|
|
73
|
-
let i = (hilited
|
|
74
|
-
while (
|
|
75
|
+
let i = (hilited ?? firstactive - 1) + 1;
|
|
76
|
+
while (items[i]?.disabled || hiddenItem(items[i]))
|
|
75
77
|
i++;
|
|
76
78
|
move(i);
|
|
77
79
|
}
|
|
78
80
|
else {
|
|
79
81
|
menushown = true;
|
|
80
|
-
move(firstactive);
|
|
82
|
+
tick().then(() => move(firstactive));
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
else if (e.key === 'ArrowUp') {
|
|
84
86
|
e.preventDefault();
|
|
85
87
|
if (menushown) {
|
|
86
|
-
let i = (hilited
|
|
87
|
-
while (
|
|
88
|
+
let i = (hilited ?? lastactive + 1) - 1;
|
|
89
|
+
while (items[i]?.disabled || hiddenItem(items[i]))
|
|
88
90
|
i--;
|
|
89
91
|
move(i);
|
|
90
92
|
}
|
|
91
93
|
else {
|
|
92
94
|
menushown = true;
|
|
93
|
-
move(lastactive);
|
|
95
|
+
tick().then(() => move(lastactive));
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
98
|
else if (e.key === 'Enter') {
|
|
@@ -98,13 +100,13 @@ function onkeydown(e) {
|
|
|
98
100
|
if (menushown) {
|
|
99
101
|
menushown = false;
|
|
100
102
|
if (typeof hilited !== 'undefined') {
|
|
101
|
-
value =
|
|
103
|
+
value = items[hilited]?.value;
|
|
102
104
|
dispatch('change', items[hilited]);
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
else {
|
|
106
108
|
menushown = true;
|
|
107
|
-
move(firstactive);
|
|
109
|
+
tick().then(() => move(firstactive));
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
112
|
else if (e.key === ' ') {
|
|
@@ -114,7 +116,7 @@ function onkeydown(e) {
|
|
|
114
116
|
if (typeof hilited !== 'undefined') {
|
|
115
117
|
e.preventDefault();
|
|
116
118
|
menushown = false;
|
|
117
|
-
value =
|
|
119
|
+
value = items[hilited]?.value;
|
|
118
120
|
dispatch('change', items[hilited]);
|
|
119
121
|
}
|
|
120
122
|
else {
|
|
@@ -128,7 +130,7 @@ function onkeydown(e) {
|
|
|
128
130
|
if (buttonelement.tagName !== 'INPUT') {
|
|
129
131
|
e.preventDefault();
|
|
130
132
|
menushown = true;
|
|
131
|
-
move(firstactive);
|
|
133
|
+
tick().then(() => move(firstactive));
|
|
132
134
|
}
|
|
133
135
|
}
|
|
134
136
|
}
|
|
@@ -138,14 +140,17 @@ function onkeydown(e) {
|
|
|
138
140
|
menushown = false;
|
|
139
141
|
}
|
|
140
142
|
}
|
|
143
|
+
let blurTimer;
|
|
141
144
|
function onbuttonclick(e) {
|
|
142
145
|
e.preventDefault();
|
|
146
|
+
cancelAnimationFrame(blurTimer);
|
|
143
147
|
menushown = !menushown;
|
|
144
148
|
}
|
|
145
149
|
async function onblur(e) {
|
|
146
150
|
// tabindex=-1 on our menu elements means e.relatedTarget will be set
|
|
147
|
-
if (!(e.relatedTarget instanceof HTMLElement &&
|
|
148
|
-
menushown = false;
|
|
151
|
+
if (!(e.relatedTarget instanceof HTMLElement && menuelement?.contains(e.relatedTarget))) {
|
|
152
|
+
blurTimer = requestAnimationFrame(() => { menushown = false; });
|
|
153
|
+
}
|
|
149
154
|
}
|
|
150
155
|
function cleanup(element) {
|
|
151
156
|
if (element) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { Store } from '@txstate-mws/svelte-store';
|
|
3
|
+
import type { GlueAlignOpts, GlueAlignStore } from '../actions';
|
|
4
|
+
import type { PopupMenuItem } from '../types';
|
|
5
|
+
declare const __propDef: {
|
|
6
|
+
props: {
|
|
7
|
+
menushown?: boolean;
|
|
8
|
+
menuContainerClass?: string;
|
|
9
|
+
menuClass?: string;
|
|
10
|
+
menuItemClass?: string;
|
|
11
|
+
menuItemHilitedClass?: string;
|
|
12
|
+
menuItemSelectedClass?: string;
|
|
13
|
+
items?: PopupMenuItem[];
|
|
14
|
+
buttonelement: HTMLElement;
|
|
15
|
+
align?: GlueAlignOpts;
|
|
16
|
+
cover?: boolean;
|
|
17
|
+
showSelected?: boolean;
|
|
18
|
+
width?: string | undefined;
|
|
19
|
+
computedalign?: Store<GlueAlignStore>;
|
|
20
|
+
usePortal?: HTMLElement | true | undefined;
|
|
21
|
+
emptyText?: string | undefined;
|
|
22
|
+
value?: string | undefined;
|
|
23
|
+
hilited?: number | undefined;
|
|
24
|
+
};
|
|
25
|
+
events: {
|
|
26
|
+
change: CustomEvent<any>;
|
|
27
|
+
} & {
|
|
28
|
+
[evt: string]: CustomEvent<any>;
|
|
29
|
+
};
|
|
30
|
+
slots: {
|
|
31
|
+
default: {
|
|
32
|
+
item: PopupMenuItem;
|
|
33
|
+
label: string;
|
|
34
|
+
hilited: boolean;
|
|
35
|
+
selected: boolean;
|
|
36
|
+
};
|
|
37
|
+
noresults: {};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export declare type PopupMenuProps = typeof __propDef.props;
|
|
41
|
+
export declare type PopupMenuEvents = typeof __propDef.events;
|
|
42
|
+
export declare type PopupMenuSlots = typeof __propDef.slots;
|
|
43
|
+
export default class PopupMenu extends SvelteComponentTyped<PopupMenuProps, PopupMenuEvents, PopupMenuSlots> {
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
id?: string | undefined;
|
|
5
|
+
arialive?: 'off' | 'assertive' | 'polite' | undefined;
|
|
6
|
+
ariaatomic?: boolean | 'false' | 'true' | undefined;
|
|
7
|
+
};
|
|
8
|
+
events: {
|
|
9
|
+
[evt: string]: CustomEvent<any>;
|
|
10
|
+
};
|
|
11
|
+
slots: {
|
|
12
|
+
default: {};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export declare type ScreenReaderOnlyProps = typeof __propDef.props;
|
|
16
|
+
export declare type ScreenReaderOnlyEvents = typeof __propDef.events;
|
|
17
|
+
export declare type ScreenReaderOnlySlots = typeof __propDef.slots;
|
|
18
|
+
export default class ScreenReaderOnly extends SvelteComponentTyped<ScreenReaderOnlyProps, ScreenReaderOnlyEvents, ScreenReaderOnlySlots> {
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
export { default as CardLayout } from './CardLayout.svelte';
|
|
2
|
+
export { default as Card } from './Card.svelte';
|
|
1
3
|
export { default as CollapsingTable } from './CollapsingTable.svelte';
|
|
2
4
|
export { default as FocusLock } from './FocusLock.svelte';
|
|
3
5
|
export { default as ConditionalWrapper } from './ConditionalWrapper.svelte';
|
|
4
6
|
export { default as Modal } from './Modal.svelte';
|
|
7
|
+
export { default as MultiSelect } from './MultiSelect.svelte';
|
|
5
8
|
export { default as PopupMenu } from './PopupMenu.svelte';
|
|
6
9
|
export { default as ScreenReaderOnly } from './ScreenReaderOnly.svelte';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { default as CardLayout } from './CardLayout.svelte';
|
|
2
|
+
export { default as Card } from './Card.svelte';
|
|
3
|
+
export { default as CollapsingTable } from './CollapsingTable.svelte';
|
|
4
|
+
export { default as FocusLock } from './FocusLock.svelte';
|
|
5
|
+
export { default as ConditionalWrapper } from './ConditionalWrapper.svelte';
|
|
6
|
+
export { default as Modal } from './Modal.svelte';
|
|
7
|
+
export { default as MultiSelect } from './MultiSelect.svelte';
|
|
8
|
+
export { default as PopupMenu } from './PopupMenu.svelte';
|
|
9
|
+
export { default as ScreenReaderOnly } from './ScreenReaderOnly.svelte';
|
package/index.d.ts
ADDED
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,86 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@txstate-mws/svelte-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Svelte components that are generically useful.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "esm/index.js",
|
|
7
|
-
"svelte": "esm/index.js",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"require": "./dist/index.js",
|
|
11
|
-
"import": "./esm/index.js"
|
|
12
|
-
},
|
|
13
|
-
"./package.json": "./package.json"
|
|
14
|
-
},
|
|
15
|
-
"types": "dist/ts/index.d.ts",
|
|
16
|
-
"scripts": {
|
|
17
|
-
"test": "jest src",
|
|
18
|
-
"test:watch": "npm run test -- --watch",
|
|
19
|
-
"svelte-check": "svelte-check --ignore 'dist'",
|
|
20
|
-
"prebuild": "rm -rf ./dist",
|
|
21
|
-
"build": "npm run svelte-check && tsc -m commonjs && node scripts/preprocess.js && rm -rf dist/tests",
|
|
22
|
-
"prepublishOnly": "npm run build"
|
|
23
|
-
},
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "git",
|
|
26
|
-
"url": "git@github.com:txstate-etc/svelte-components.git"
|
|
27
|
-
},
|
|
28
|
-
"author": "Nick Wing",
|
|
29
|
-
"license": "MIT",
|
|
30
5
|
"dependencies": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"txstate-utils": "^1.4.0"
|
|
6
|
+
"@txstate-mws/svelte-store": "^1.0.3",
|
|
7
|
+
"tabbable": "^5.2.1",
|
|
8
|
+
"txstate-utils": "^1.6.0"
|
|
35
9
|
},
|
|
36
10
|
"devDependencies": {
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"@
|
|
40
|
-
"@
|
|
41
|
-
"@tsconfig/svelte": "^3.0.0",
|
|
42
|
-
"@types/jest": "^27.0.2",
|
|
43
|
-
"@types/node": "^15.3.1",
|
|
44
|
-
"babel-jest": "^27.3.1",
|
|
11
|
+
"@playwright/test": "^1.18.1",
|
|
12
|
+
"@sveltejs/adapter-auto": "next",
|
|
13
|
+
"@sveltejs/kit": "next",
|
|
14
|
+
"@types/tabbable": "^3.1.2",
|
|
45
15
|
"eslint-config-standard-with-typescript": "^21.0.1",
|
|
46
|
-
"eslint-plugin-svelte3": "^3.
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"svelte-preprocess": "^4.6.5",
|
|
54
|
-
"ts-jest": "^27.0.7",
|
|
55
|
-
"tslib": "^2.1.0",
|
|
56
|
-
"typescript": "^4.1.3"
|
|
16
|
+
"eslint-plugin-svelte3": "^3.2.1",
|
|
17
|
+
"svelte": "^3.44.0",
|
|
18
|
+
"svelte-check": "^2.2.6",
|
|
19
|
+
"svelte-preprocess": "^4.9.4",
|
|
20
|
+
"svelte2tsx": "^0.5.2",
|
|
21
|
+
"tslib": "^2.3.1",
|
|
22
|
+
"typescript": "^4.4.3"
|
|
57
23
|
},
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
24
|
+
"type": "module",
|
|
25
|
+
"exports": {
|
|
26
|
+
"./package.json": "./package.json",
|
|
27
|
+
"./actions/buttonify": "./actions/buttonify.js",
|
|
28
|
+
"./actions/glue": "./actions/glue.js",
|
|
29
|
+
"./actions": "./actions/index.js",
|
|
30
|
+
"./actions/offset": "./actions/offset.js",
|
|
31
|
+
"./actions/portal": "./actions/portal.js",
|
|
32
|
+
"./actions/resize": "./actions/resize.js",
|
|
33
|
+
"./actions/sticky": "./actions/sticky.js",
|
|
34
|
+
"./actions/stickyfixed": "./actions/stickyfixed.js",
|
|
35
|
+
"./components/Card.svelte": "./components/Card.svelte",
|
|
36
|
+
"./components/CardLayout.svelte": "./components/CardLayout.svelte",
|
|
37
|
+
"./components/CollapsingTable.svelte": "./components/CollapsingTable.svelte",
|
|
38
|
+
"./components/ConditionalWrapper.svelte": "./components/ConditionalWrapper.svelte",
|
|
39
|
+
"./components/FocusLock.svelte": "./components/FocusLock.svelte",
|
|
40
|
+
"./components/Modal.svelte": "./components/Modal.svelte",
|
|
41
|
+
"./components/MultiSelect.svelte": "./components/MultiSelect.svelte",
|
|
42
|
+
"./components/PopupMenu.svelte": "./components/PopupMenu.svelte",
|
|
43
|
+
"./components/ScreenReaderOnly.svelte": "./components/ScreenReaderOnly.svelte",
|
|
44
|
+
"./components": "./components/index.js",
|
|
45
|
+
".": "./index.js",
|
|
46
|
+
"./types/CardLayout": "./types/CardLayout.js",
|
|
47
|
+
"./types/CollapsingTable": "./types/CollapsingTable.js",
|
|
48
|
+
"./types/PopupMenu": "./types/PopupMenu.js",
|
|
49
|
+
"./types": "./types/index.js",
|
|
50
|
+
"./util/bodyoffset": "./util/bodyoffset.js",
|
|
51
|
+
"./util": "./util/index.js",
|
|
52
|
+
"./util/repositioned": "./util/repositioned.js",
|
|
53
|
+
"./util/util": "./util/util.js"
|
|
79
54
|
},
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
"dist",
|
|
83
|
-
"esm",
|
|
84
|
-
"docs"
|
|
85
|
-
]
|
|
86
|
-
}
|
|
55
|
+
"svelte": "./index.js"
|
|
56
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SettableSubject } from '@txstate-mws/svelte-store';
|
|
2
|
+
export declare const CARDLAYOUT: {};
|
|
3
|
+
export interface Block {
|
|
4
|
+
element: HTMLElement;
|
|
5
|
+
order?: SettableSubject<number>;
|
|
6
|
+
linebreak?: SettableSubject<boolean>;
|
|
7
|
+
width?: SettableSubject<string>;
|
|
8
|
+
height?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface CardLayoutContext {
|
|
11
|
+
registerBlock: (block: Block) => Block;
|
|
12
|
+
recalculate: () => void;
|
|
13
|
+
gutter: SettableSubject<number>;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CARDLAYOUT = {};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/types/index.d.ts
ADDED
package/types/index.js
ADDED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare type ElementOffsets = Partial<ReturnType<typeof bodyOffset>>;
|
|
1
2
|
export declare function bodyOffset(ele: HTMLElement): {
|
|
2
3
|
right: number;
|
|
3
4
|
bottom: number;
|
|
@@ -10,4 +11,4 @@ export declare function targetOffset(ele: HTMLElement, target: HTMLElement): {
|
|
|
10
11
|
top: number;
|
|
11
12
|
left: number;
|
|
12
13
|
};
|
|
13
|
-
export declare function sharedOffsetParent(a: HTMLElement, b: HTMLElement): HTMLElement
|
|
14
|
+
export declare function sharedOffsetParent(a: HTMLElement, b: HTMLElement): HTMLElement;
|