@txstate-mws/svelte-components 0.0.66 → 1.0.2
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 +12 -0
- package/dist/actions/{a11y.js → buttonify.js} +1 -1
- package/dist/actions/buttonify.js.map +1 -0
- package/dist/actions/glue.js +1 -3
- package/dist/actions/glue.js.map +1 -1
- package/dist/actions/index.js +1 -1
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/portal.js +3 -7
- package/dist/actions/portal.js.map +1 -1
- package/dist/actions/stickyfixed.js +5 -5
- package/dist/components/CollapsingTable.svelte +3 -3
- package/dist/components/ConditionalWrapper.svelte +1 -1
- package/dist/components/FocusLock.svelte +13 -11
- package/dist/components/Modal.svelte +19 -11
- package/dist/components/PopupMenu.svelte +19 -18
- package/dist/components/ScreenReaderOnly.svelte +4 -5
- package/dist/lib/activestore.js +123 -0
- package/dist/lib/activestore.js.map +1 -0
- package/dist/lib/convertedstore.js +41 -0
- package/dist/lib/convertedstore.js.map +1 -0
- package/dist/lib/derivedstore.js +37 -25
- package/dist/lib/derivedstore.js.map +1 -1
- package/dist/lib/index.js +3 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/safestore.js +2 -2
- package/dist/lib/safestore.js.map +1 -1
- package/dist/lib/store.js +27 -0
- package/dist/lib/store.js.map +1 -0
- package/dist/lib/substore.js +10 -9
- package/dist/lib/substore.js.map +1 -1
- package/dist/ts/actions/{a11y.d.ts → buttonify.d.ts} +0 -0
- package/dist/ts/actions/glue.d.ts +1 -1
- package/dist/ts/actions/index.d.ts +1 -1
- package/dist/ts/actions/stickyfixed.d.ts +5 -5
- package/dist/ts/components/CollapsingTable.svelte +3 -3
- package/dist/ts/components/ConditionalWrapper.svelte +1 -1
- package/dist/ts/components/FocusLock.svelte +13 -10
- package/dist/ts/components/Modal.svelte +20 -11
- package/dist/ts/components/PopupMenu.svelte +18 -17
- package/dist/ts/components/ScreenReaderOnly.svelte +5 -5
- package/dist/ts/lib/activestore.d.ts +60 -0
- package/dist/ts/lib/convertedstore.d.ts +16 -0
- package/dist/ts/lib/derivedstore.d.ts +15 -8
- package/dist/ts/lib/index.d.ts +3 -1
- package/dist/ts/lib/safestore.d.ts +2 -2
- package/dist/ts/lib/store.d.ts +16 -0
- package/dist/ts/lib/substore.d.ts +7 -6
- package/dist/ts/tests/Modal/ModalTest.svelte +2 -2
- package/dist/ts/tests/PopupMenu/PopupMenuSimple.svelte +8 -2
- package/docs/CollapsingTable.md +11 -12
- package/docs/ConditionalWrapper.md +35 -0
- package/docs/Modal.md +63 -0
- package/docs/PopupMenu.md +31 -0
- package/docs/ScreenReaderOnly.md +10 -0
- package/docs/actions.md +76 -2
- package/docs/stores.md +203 -0
- package/package.json +17 -9
- package/dist/actions/a11y.js.map +0 -1
- package/dist/lib/deepstore.js +0 -80
- package/dist/lib/deepstore.js.map +0 -1
- package/dist/ts/lib/deepstore.d.ts +0 -42
package/dist/lib/derivedstore.js
CHANGED
|
@@ -1,53 +1,65 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DerivedStore = void 0;
|
|
4
|
-
const
|
|
3
|
+
exports.derivedStore = exports.DerivedStore = void 0;
|
|
4
|
+
const store_1 = require("./store");
|
|
5
5
|
const txstate_utils_1 = require("txstate-utils");
|
|
6
|
-
const store_1 = require("svelte/store");
|
|
7
6
|
/**
|
|
8
7
|
* Watch one or more parent stores for changes. Each time, run a function to derive
|
|
9
8
|
* a new state from the parent state(s). Subscribers will only be notified if the
|
|
10
9
|
* derived state has changed (uses fast-deep-equal).
|
|
11
10
|
*
|
|
12
11
|
* If only one parent store, it's possible to use a dot-prop string as the getter.
|
|
13
|
-
*
|
|
14
|
-
* If you create one of these in a component, be sure to call .complete() in onDestroy
|
|
15
|
-
* to free up memory.
|
|
16
12
|
*/
|
|
17
|
-
class DerivedStore extends
|
|
18
|
-
constructor(store, getter) {
|
|
13
|
+
class DerivedStore extends store_1.Store {
|
|
14
|
+
constructor(store, getter, options) {
|
|
19
15
|
if (typeof getter === 'string') {
|
|
20
16
|
const accessor = getter;
|
|
21
17
|
getter = (parentValue) => (0, txstate_utils_1.get)(parentValue, accessor);
|
|
22
18
|
}
|
|
23
19
|
super({});
|
|
24
20
|
if (Array.isArray(store)) {
|
|
25
|
-
const values =
|
|
21
|
+
const values = [];
|
|
22
|
+
let timer;
|
|
23
|
+
const superSet = () => super.set(getter(values));
|
|
24
|
+
const superSetDebounced = (options === null || options === void 0 ? void 0 : options.debounce) == null || (options === null || options === void 0 ? void 0 : options.debounce) === false || (options === null || options === void 0 ? void 0 : options.debounce) < 0
|
|
25
|
+
? superSet
|
|
26
|
+
: () => {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
timer = setTimeout(superSet, options.debounce === true ? 0 : options.debounce);
|
|
29
|
+
};
|
|
26
30
|
for (let i = 0; i < store.length; i++) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const idx = i;
|
|
32
|
+
const st = store[i];
|
|
33
|
+
if (st instanceof store_1.Store) {
|
|
34
|
+
this.registerSource(() => st.subscribe(v => {
|
|
35
|
+
values[idx] = st.clone(v);
|
|
36
|
+
superSetDebounced();
|
|
37
|
+
}));
|
|
33
38
|
}
|
|
34
39
|
else {
|
|
35
|
-
|
|
36
|
-
values[
|
|
37
|
-
|
|
38
|
-
});
|
|
40
|
+
this.registerSource(() => st.subscribe(v => {
|
|
41
|
+
values[idx] = v;
|
|
42
|
+
superSetDebounced();
|
|
43
|
+
}));
|
|
39
44
|
}
|
|
40
|
-
this.cleanup(unsubscribe);
|
|
41
45
|
}
|
|
42
|
-
super.set(getter(values));
|
|
43
46
|
}
|
|
44
47
|
else {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
let timer;
|
|
49
|
+
const superSet = (v) => super.set(getter(v));
|
|
50
|
+
const superSetDebounced = (options === null || options === void 0 ? void 0 : options.debounce) == null || (options === null || options === void 0 ? void 0 : options.debounce) === false || (options === null || options === void 0 ? void 0 : options.debounce) < 0
|
|
51
|
+
? superSet
|
|
52
|
+
: (v) => {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
timer = setTimeout(() => superSet(v), options.debounce === true ? 0 : options.debounce);
|
|
55
|
+
};
|
|
56
|
+
this.registerSource(() => store.subscribe(superSetDebounced));
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
}
|
|
52
60
|
exports.DerivedStore = DerivedStore;
|
|
61
|
+
function derivedStore(store, getter, options) {
|
|
62
|
+
return new DerivedStore(store, getter, options);
|
|
63
|
+
}
|
|
64
|
+
exports.derivedStore = derivedStore;
|
|
53
65
|
//# sourceMappingURL=derivedstore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derivedstore.js","sourceRoot":"","sources":["../../src/lib/derivedstore.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"derivedstore.js","sourceRoot":"","sources":["../../src/lib/derivedstore.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/index.js
CHANGED
|
@@ -11,10 +11,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
__exportStar(require("./bodyoffset"), exports);
|
|
14
|
-
__exportStar(require("./
|
|
14
|
+
__exportStar(require("./convertedstore"), exports);
|
|
15
15
|
__exportStar(require("./derivedstore"), exports);
|
|
16
|
+
__exportStar(require("./activestore"), exports);
|
|
16
17
|
__exportStar(require("./repositioned"), exports);
|
|
17
18
|
__exportStar(require("./safestore"), exports);
|
|
19
|
+
__exportStar(require("./store"), exports);
|
|
18
20
|
__exportStar(require("./substore"), exports);
|
|
19
21
|
__exportStar(require("./util"), exports);
|
|
20
22
|
//# sourceMappingURL=index.js.map
|
package/dist/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+CAA4B;AAC5B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+CAA4B;AAC5B,mDAAgC;AAChC,iDAA8B;AAC9B,gDAA6B;AAC7B,iDAA8B;AAC9B,8CAA2B;AAC3B,0CAAuB;AACvB,6CAA0B;AAC1B,yCAAsB"}
|
package/dist/lib/safestore.js
CHANGED
|
@@ -4,10 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.SafeStore = void 0;
|
|
7
|
-
const
|
|
7
|
+
const store_1 = require("./store");
|
|
8
8
|
const rfdc_1 = __importDefault(require("rfdc"));
|
|
9
9
|
const cloneDeep = (0, rfdc_1.default)();
|
|
10
|
-
class SafeStore extends
|
|
10
|
+
class SafeStore extends store_1.Store {
|
|
11
11
|
clone(value) {
|
|
12
12
|
return cloneDeep(value);
|
|
13
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safestore.js","sourceRoot":"","sources":["../../src/lib/safestore.ts"],"names":[],"mappings":";;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"safestore.js","sourceRoot":"","sources":["../../src/lib/safestore.ts"],"names":[],"mappings":";;;;;;AAAA,mCAA+B;AAC/B,gDAAuB;AACvB,MAAM,SAAS,GAAG,IAAA,cAAI,GAAE,CAAA;AAExB,MAAa,SAAa,SAAQ,aAAQ;IACxC,KAAK,CAAE,KAAQ;QACb,OAAO,SAAS,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;CACF;AAJD,8BAIC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Store = void 0;
|
|
7
|
+
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
|
|
8
|
+
const activestore_1 = require("./activestore");
|
|
9
|
+
/**
|
|
10
|
+
* An alternative to svelte's "writable" that also checks deep equality (fast-deep-equal) before
|
|
11
|
+
* notifying subscribers. A writable will notify subscribers after a shallow equality check, which
|
|
12
|
+
* only works for scalars.
|
|
13
|
+
*
|
|
14
|
+
* Note that this strategy is weak against mutable state updates:
|
|
15
|
+
* store.update(v => { v.someprop = 'newvalue'; return v })
|
|
16
|
+
*
|
|
17
|
+
* This line would NOT notify subscribers because the state will be compared against
|
|
18
|
+
* itself and always found to be equal. If you are making updates in a mutable fashion,
|
|
19
|
+
* use a SafeStore instead.
|
|
20
|
+
*/
|
|
21
|
+
class Store extends activestore_1.ActiveStore {
|
|
22
|
+
equal(a, b) {
|
|
23
|
+
return (0, fast_deep_equal_1.default)(a, b);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.Store = Store;
|
|
27
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/lib/store.ts"],"names":[],"mappings":";;;;;;AAAA,sEAAuC;AACvC,+CAA2C;AAE3C;;;;;;;;;;;GAWG;AACH,MAAa,KAAS,SAAQ,yBAAc;IAC1C,KAAK,CAAE,CAAI,EAAE,CAAI;QACf,OAAO,IAAA,yBAAS,EAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACxB,CAAC;CACF;AAJD,sBAIC"}
|
package/dist/lib/substore.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SubStore = void 0;
|
|
3
|
+
exports.subStore = exports.SubStore = void 0;
|
|
4
4
|
const txstate_utils_1 = require("txstate-utils");
|
|
5
|
-
const
|
|
5
|
+
const store_1 = require("./store");
|
|
6
6
|
/**
|
|
7
7
|
* Create a store that represents a part of a larger store. Updates to the parent store will propagate
|
|
8
8
|
* down to the SubStore as appropriate, and updates to the SubStore will propagate
|
|
@@ -14,23 +14,20 @@ const deepstore_1 = require("./deepstore");
|
|
|
14
14
|
* generated. For example, a parent store containing state { deep: { value: 'here' }, hello: 'world' }
|
|
15
15
|
* could be used with the getter string "deep.value". The SubStore's initial state would be "here", and
|
|
16
16
|
* updating it to "there" would update the parent store state to { deep: { value: 'there' }, hello: 'world' }
|
|
17
|
-
*
|
|
18
|
-
* If you create one of these in a component, be sure to call .complete() in onDestroy to free up memory.
|
|
19
17
|
*/
|
|
20
|
-
class SubStore extends
|
|
18
|
+
class SubStore extends store_1.Store {
|
|
21
19
|
constructor(store, getter, setter) {
|
|
20
|
+
super({});
|
|
22
21
|
if (typeof getter === 'string') {
|
|
23
22
|
const accessor = getter;
|
|
24
23
|
getter = parentValue => (0, txstate_utils_1.get)(parentValue, accessor);
|
|
25
24
|
setter = (newValue, parentValue) => (0, txstate_utils_1.set)(parentValue, accessor, newValue);
|
|
26
25
|
}
|
|
27
|
-
super({});
|
|
28
26
|
this.parentStore = store;
|
|
29
27
|
this.setter = setter;
|
|
30
|
-
|
|
28
|
+
this.registerSource(() => store.subscribe(v => {
|
|
31
29
|
super.set(getter(v));
|
|
32
|
-
});
|
|
33
|
-
this.cleanup(unsubscribe);
|
|
30
|
+
}));
|
|
34
31
|
}
|
|
35
32
|
set(value) {
|
|
36
33
|
this.parentStore.update(parentValue => this.setter(value, parentValue));
|
|
@@ -43,4 +40,8 @@ class SubStore extends deepstore_1.DeepStore {
|
|
|
43
40
|
}
|
|
44
41
|
}
|
|
45
42
|
exports.SubStore = SubStore;
|
|
43
|
+
function subStore(store, getter, setter) {
|
|
44
|
+
return new SubStore(store, getter, setter);
|
|
45
|
+
}
|
|
46
|
+
exports.subStore = subStore;
|
|
46
47
|
//# sourceMappingURL=substore.js.map
|
package/dist/lib/substore.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"substore.js","sourceRoot":"","sources":["../../src/lib/substore.ts"],"names":[],"mappings":";;;AAAA,iDAAwC;AACxC,
|
|
1
|
+
{"version":3,"file":"substore.js","sourceRoot":"","sources":["../../src/lib/substore.ts"],"names":[],"mappings":";;;AAAA,iDAAwC;AACxC,mCAA+B;AAG/B;;;;;;;;;;;GAWG;AACH,MAAa,QAAoC,SAAQ,aAAc;IAIrE,YAAa,KAAkC,EAAE,MAAgE,EAAE,MAA0D;QAC3K,KAAK,CAAC,EAAS,CAAC,CAAA;QAChB,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;YAC9B,MAAM,QAAQ,GAAG,MAAM,CAAA;YACvB,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC,IAAA,mBAAG,EAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;YAClD,MAAM,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,CAAC,IAAA,mBAAG,EAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;SACzE;QACD,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;QACxB,IAAI,CAAC,MAAM,GAAG,MAAO,CAAA;QACrB,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;YAC5C,KAAK,CAAC,GAAG,CAAE,MAAc,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/B,CAAC,CAAC,CAAC,CAAA;IACL,CAAC;IAED,GAAG,CAAE,KAAc;QACjB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAA;IACzE,CAAC;IAED,KAAK,CAAE,KAAc;;QACnB,6EAA6E;QAC7E,sDAAsD;QACtD,OAAO,MAAA,MAAA,MAAC,IAAI,CAAC,WAA0B,0CAAE,KAAK,mDAAG,KAAK,CAAC,mCAAI,KAAK,CAAA;IAClE,CAAC;CACF;AA3BD,4BA2BC;AAKD,SAAgB,QAAQ,CAAwB,KAAkC,EAAE,MAAgE,EAAE,MAA0D;IAC9M,OAAO,IAAI,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC5C,CAAC;AAFD,4BAEC"}
|
|
File without changes
|
|
@@ -12,5 +12,5 @@ export interface GlueAlignStore {
|
|
|
12
12
|
}
|
|
13
13
|
export declare function glue(el: HTMLElement, { target, align, cover, store }: GlueArgs): {
|
|
14
14
|
update({ target: utarget, align: ualign, cover: ucover, store: ustore }: GlueArgs): void;
|
|
15
|
-
destroy()
|
|
15
|
+
destroy: () => void;
|
|
16
16
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StickyArgs } from './sticky';
|
|
2
2
|
/**
|
|
3
|
-
* An implementation of stickyness based on `
|
|
3
|
+
* An implementation of stickyness based on `positon: fixed`. Only use when
|
|
4
4
|
* `position: sticky` won't work for you. If `position: sticky` does work for you, use it,
|
|
5
5
|
* it performs better.
|
|
6
6
|
*
|
|
@@ -10,10 +10,10 @@ import { StickyArgs } from './sticky';
|
|
|
10
10
|
* 3) it always stays within the boundaries of the closest parent element that has a `position`
|
|
11
11
|
* * use:sticky accepts a `target` element as a parameter, defining the bounding container
|
|
12
12
|
*
|
|
13
|
-
* Note that this implementation
|
|
14
|
-
* work like cloning the element you place it on, placing the cloned element next
|
|
15
|
-
* setting widths to match between them, watching for mutations to keep them
|
|
16
|
-
* this work may get foiled if you have a complex html/css/js situation.
|
|
13
|
+
* Note that this implementation gets great animation performance at the cost of extra complexity.
|
|
14
|
+
* It does a lot of work like cloning the element you place it on, placing the cloned element next
|
|
15
|
+
* to yours in the DOM, setting widths to match between them, watching for mutations to keep them
|
|
16
|
+
* in sync, etc. Some of this work may get foiled if you have a complex html/css/js situation.
|
|
17
17
|
*
|
|
18
18
|
* You may also want to try use:sticky. It is based on setting `transform: translateY()` as appropriate,
|
|
19
19
|
* and is less fragile than this. However, it cannot do its work before the scroll on mobile, only after,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { Store, classes } from '../lib'
|
|
3
3
|
import type { CollapsingTableColumn, PopupMenuItem } from '../types'
|
|
4
4
|
import { derived } from 'svelte/store'
|
|
5
5
|
import DefaultPopupMenu from './PopupMenu.svelte'
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
$: itemkeys = items.map(item => item.id ?? item._id ?? identifyingkeys.map(k => item[k]).join('.'))
|
|
47
47
|
|
|
48
|
-
const state = new
|
|
48
|
+
const state = new Store({
|
|
49
49
|
keepcolumns: [] as (CollapsingTableColumn & { widthPercent?: number })[],
|
|
50
50
|
hiddencolumns: [] as CollapsingTableColumn[],
|
|
51
51
|
dropdowncolumn: undefined as (CollapsingTableColumn & { widthPercent?: number }) | undefined
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
</table>
|
|
114
114
|
</div>
|
|
115
115
|
{#if $menuitems.length > 0}
|
|
116
|
-
<svelte:component this={PopupMenu} {menuContainerClass} {menuClass} {menuItemClass} {menuItemHilitedClass} items={$menuitems} buttonelement={menubuttonelement}
|
|
116
|
+
<svelte:component this={PopupMenu} {menuContainerClass} {menuClass} {menuItemClass} {menuItemHilitedClass} items={$menuitems} buttonelement={menubuttonelement} on:change={e => selected = e.detail}></svelte:component>
|
|
117
117
|
{/if}
|
|
118
118
|
|
|
119
119
|
<style>
|
|
@@ -13,14 +13,16 @@
|
|
|
13
13
|
|
|
14
14
|
import { onMount, onDestroy, createEventDispatcher, tick } from 'svelte'
|
|
15
15
|
import { tabbable } from 'tabbable'
|
|
16
|
+
import { sleep } from 'txstate-utils'
|
|
16
17
|
import { buttonify } from '../actions'
|
|
17
18
|
import ScreenReaderOnly from './ScreenReaderOnly.svelte'
|
|
18
19
|
const dispatch = createEventDispatcher()
|
|
19
20
|
let lockelement: HTMLElement
|
|
20
21
|
let abovelockelement: HTMLElement
|
|
21
22
|
let active = true
|
|
23
|
+
let listenforescape = false
|
|
22
24
|
if (initialfocus) hidefocus = false
|
|
23
|
-
onMount(() => {
|
|
25
|
+
onMount(async () => {
|
|
24
26
|
const prevFocusLock = FocusLockStack.slice(-1)[0]
|
|
25
27
|
if (prevFocusLock) prevFocusLock.pause()
|
|
26
28
|
FocusLockStack.push({
|
|
@@ -30,25 +32,20 @@
|
|
|
30
32
|
if (typeof returnfocusto === 'undefined') {
|
|
31
33
|
returnfocusto = document.querySelector(':focus') as HTMLElement
|
|
32
34
|
}
|
|
35
|
+
await sleep(1) // sapper resets focus on page load, so we'll wait a millisecond in case our modal is on screen at load
|
|
33
36
|
if (initialfocus) {
|
|
34
37
|
const focusEl = lockelement.querySelector(initialfocus)
|
|
35
38
|
if (focusEl instanceof HTMLElement) focusEl.focus()
|
|
36
39
|
} else {
|
|
37
40
|
setInitialFocus()
|
|
38
41
|
}
|
|
42
|
+
setTimeout(() => listenforescape = true, 0)
|
|
39
43
|
})
|
|
40
44
|
onDestroy(async () => {
|
|
41
45
|
const wasactive = active
|
|
42
|
-
let focuswasinside
|
|
43
|
-
try {
|
|
44
|
-
focuswasinside = lockelement.matches(':focus-within')
|
|
45
|
-
} catch (e: any) {
|
|
46
|
-
// browser doesn't support :focus-within
|
|
47
|
-
focuswasinside = true
|
|
48
|
-
}
|
|
49
46
|
active = false
|
|
50
47
|
await tick()
|
|
51
|
-
if (returnfocusto && wasactive
|
|
48
|
+
if (returnfocusto && wasactive) {
|
|
52
49
|
returnfocusto.focus()
|
|
53
50
|
}
|
|
54
51
|
FocusLockStack.pop()
|
|
@@ -79,8 +76,14 @@
|
|
|
79
76
|
else setInitialFocus()
|
|
80
77
|
}
|
|
81
78
|
}
|
|
79
|
+
const windowclick = (_: MouseEvent) => {
|
|
80
|
+
if (listenforescape && active) {
|
|
81
|
+
returnfocusto = undefined
|
|
82
|
+
dispatch('escape')
|
|
83
|
+
}
|
|
84
|
+
}
|
|
82
85
|
</script>
|
|
83
|
-
|
|
86
|
+
<svelte:window on:click={windowclick} />
|
|
84
87
|
<div class={className} role="alertdialog" aria-modal="true" on:click|stopPropagation on:keydown|stopPropagation={keydown} on:focusin={focusin}>
|
|
85
88
|
<div bind:this={abovelockelement} tabindex="0"></div>
|
|
86
89
|
<div bind:this={lockelement} on:keydown={keydown}>
|
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
export let
|
|
2
|
+
export let escapable = true
|
|
3
3
|
export let hidefocus = true
|
|
4
4
|
export let hidefocuslabel: string|undefined = undefined
|
|
5
5
|
export let returnfocusto: HTMLElement|undefined = undefined
|
|
6
6
|
export let initialfocus: string|undefined = undefined
|
|
7
|
+
export let containerClass = ''
|
|
8
|
+
export let opaque = false
|
|
7
9
|
import FocusLock from './FocusLock.svelte'
|
|
8
10
|
import { createEventDispatcher, onMount } from 'svelte'
|
|
9
11
|
import { portal } from '../actions';
|
|
12
|
+
|
|
10
13
|
const dispatch = createEventDispatcher()
|
|
11
14
|
const endmodal = () => {
|
|
12
|
-
dispatch('
|
|
15
|
+
dispatch('escape')
|
|
13
16
|
}
|
|
14
17
|
onMount(() => {
|
|
18
|
+
document.body.style.marginRight = (window.innerWidth - document.body.clientWidth) + 'px'
|
|
15
19
|
document.body.style.overflow = 'hidden'
|
|
16
20
|
return () => {
|
|
17
21
|
document.body.style.overflow = ''
|
|
22
|
+
document.body.style.marginRight = ''
|
|
18
23
|
}
|
|
19
24
|
})
|
|
20
25
|
</script>
|
|
21
26
|
|
|
22
|
-
<div use:portal class="modal-backdrop" on:click={() =>
|
|
23
|
-
<FocusLock class="modal-container" escapable
|
|
27
|
+
<div use:portal class="modal-backdrop" class:opaque on:click|stopPropagation|preventDefault={() => escapable && endmodal()}>
|
|
28
|
+
<FocusLock class="modal-container {containerClass}" {escapable} on:escape {hidefocus} {hidefocuslabel} {returnfocusto} {initialfocus}>
|
|
24
29
|
<slot></slot>
|
|
25
30
|
</FocusLock>
|
|
26
31
|
</div>
|
|
@@ -30,16 +35,20 @@
|
|
|
30
35
|
position: fixed;
|
|
31
36
|
top: 0;
|
|
32
37
|
left: 0;
|
|
33
|
-
width:
|
|
34
|
-
height:
|
|
38
|
+
width: 100vw;
|
|
39
|
+
height: 100vh;
|
|
35
40
|
background-color: var(--modal-bg, rgba(0, 0, 0, 0.7));
|
|
36
|
-
overflow: auto;
|
|
37
41
|
z-index: 100;
|
|
42
|
+
display: flex;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
align-items: center
|
|
45
|
+
}
|
|
46
|
+
.modal-backdrop.opaque {
|
|
47
|
+
background-color: var(--modal-bg-opaque, #4c4c4c);
|
|
38
48
|
}
|
|
39
49
|
.modal-backdrop :global(.modal-container) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
transform: translate(-50%, -50%);
|
|
50
|
+
max-width: 100vw;
|
|
51
|
+
max-height: 100vh;
|
|
52
|
+
overflow: auto;
|
|
44
53
|
}
|
|
45
54
|
</style>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { createEventDispatcher, onDestroy, tick } from 'svelte'
|
|
5
5
|
import { randomid } from 'txstate-utils'
|
|
6
6
|
import type { PopupMenuItem } from '../types'
|
|
7
|
-
import {
|
|
7
|
+
import { Store } from '../lib'
|
|
8
8
|
import ScreenReaderOnly from './ScreenReaderOnly.svelte'
|
|
9
9
|
const dispatch = createEventDispatcher()
|
|
10
10
|
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
export let cover = false
|
|
21
21
|
export let showSelected = true
|
|
22
22
|
export let width:string|undefined = undefined
|
|
23
|
-
export let computedalign
|
|
23
|
+
export let computedalign = new Store<GlueAlignStore>({ valign: 'bottom', halign: 'left' })
|
|
24
24
|
export let usePortal: HTMLElement|true|undefined = undefined
|
|
25
25
|
export let emptyText: string|undefined = undefined
|
|
26
|
-
export let
|
|
27
|
-
export let selected: PopupMenuItem|undefined = undefined
|
|
26
|
+
export let value: string|undefined = undefined
|
|
28
27
|
|
|
28
|
+
let hilited: number|undefined = undefined
|
|
29
29
|
let menuelement: HTMLElement|undefined
|
|
30
30
|
let itemelements: HTMLElement[] = []
|
|
31
31
|
const menuid = randomid()
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
let lastactive = items.length - 1
|
|
34
34
|
|
|
35
35
|
function hiddenItem (item: PopupMenuItem) {
|
|
36
|
-
return !!item && !showSelected && item.value ===
|
|
36
|
+
return !!item && !showSelected && item.value === value
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
async function reactToItems (..._: any[]) {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
lastactive = items.length - [...items].reverse().findIndex(itm => !itm.disabled && !hiddenItem(itm)) - 1
|
|
42
42
|
if (hilited && items[hilited]?.disabled) hilited = firstactive
|
|
43
43
|
}
|
|
44
|
-
$: reactToItems(items,
|
|
44
|
+
$: reactToItems(items, value)
|
|
45
45
|
|
|
46
46
|
async function reactToMenuShown (_: boolean) {
|
|
47
47
|
if (!buttonelement) {
|
|
@@ -95,8 +95,8 @@
|
|
|
95
95
|
if (menushown) {
|
|
96
96
|
menushown = false
|
|
97
97
|
if (typeof hilited !== 'undefined') {
|
|
98
|
-
|
|
99
|
-
dispatch('change', items[hilited]
|
|
98
|
+
value = items[hilited]?.value
|
|
99
|
+
dispatch('change', items[hilited])
|
|
100
100
|
}
|
|
101
101
|
} else {
|
|
102
102
|
menushown = true
|
|
@@ -109,8 +109,8 @@
|
|
|
109
109
|
if (typeof hilited !== 'undefined') {
|
|
110
110
|
e.preventDefault()
|
|
111
111
|
menushown = false
|
|
112
|
-
|
|
113
|
-
dispatch('change', items[hilited]
|
|
112
|
+
value = items[hilited]?.value
|
|
113
|
+
dispatch('change', items[hilited])
|
|
114
114
|
} else {
|
|
115
115
|
if (buttonelement.tagName !== 'INPUT') {
|
|
116
116
|
e.preventDefault()
|
|
@@ -146,6 +146,7 @@
|
|
|
146
146
|
element.removeEventListener('click', onbuttonclick)
|
|
147
147
|
element.removeEventListener('keydown', onkeydown)
|
|
148
148
|
element.removeEventListener('blur', onblur)
|
|
149
|
+
element.removeAttribute('aria-disabled')
|
|
149
150
|
element.removeAttribute('aria-haspopup')
|
|
150
151
|
element.removeAttribute('aria-expanded')
|
|
151
152
|
element.removeAttribute('aria-controls')
|
|
@@ -174,30 +175,30 @@
|
|
|
174
175
|
e.preventDefault()
|
|
175
176
|
if (item.disabled) return
|
|
176
177
|
menushown = false
|
|
177
|
-
|
|
178
|
-
dispatch('change', item
|
|
178
|
+
value = item.value
|
|
179
|
+
dispatch('change', item)
|
|
179
180
|
}
|
|
180
181
|
|
|
181
|
-
$: hasSelected = showSelected &&
|
|
182
|
+
$: hasSelected = showSelected && items.some(itm => itm.value === value)
|
|
182
183
|
</script>
|
|
183
184
|
|
|
184
185
|
{#if menushown}
|
|
185
186
|
<div use:portal={usePortal === true ? document.body : (usePortal || null)} use:glue={{ target: buttonelement, align, cover, store: computedalign }} class={menuContainerClass}>
|
|
186
187
|
<ul bind:this={menuelement} id={menuid} role='listbox' style={width ? `width: ${width}` : ''} class={menuClass} class:hasSelected class:defaultmenu={!menuClass && !menuContainerClass} on:keydown={onkeydown}>
|
|
187
188
|
{#each items as item, i (item.value)}
|
|
188
|
-
{#if showSelected ||
|
|
189
|
+
{#if showSelected || item.value !== value}
|
|
189
190
|
<li
|
|
190
191
|
id={`${menuid}-${i}`}
|
|
191
192
|
bind:this={itemelements[i]}
|
|
192
|
-
class={`${menuItemClass} ${i === hilited ? menuItemHilitedClass || '' : ''} ${
|
|
193
|
+
class={`${menuItemClass} ${i === hilited ? menuItemHilitedClass || '' : ''} ${value === item.value ? menuItemSelectedClass || '' : ''}`}
|
|
193
194
|
class:disabled={!!item.disabled}
|
|
194
195
|
class:hilited={!menuItemHilitedClass && i === hilited}
|
|
195
|
-
class:selected={showSelected && !menuItemSelectedClass &&
|
|
196
|
+
class:selected={showSelected && !menuItemSelectedClass && value === item.value}
|
|
196
197
|
on:click={onclick(item)}
|
|
197
198
|
role="option"
|
|
198
199
|
tabindex=-1
|
|
199
200
|
aria-disabled={item.disabled}
|
|
200
|
-
><slot {item} label={item.label || item.value} hilited={i === hilited} selected={
|
|
201
|
+
><slot {item} label={item.label || item.value} hilited={i === hilited} selected={value === item.value}>{item.label || item.value}</slot></li>
|
|
201
202
|
{/if}
|
|
202
203
|
{/each}
|
|
203
204
|
{#if items.length === 0}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
export let id =
|
|
3
|
-
export let arialive =
|
|
4
|
-
export let ariaatomic =
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export let id: string|undefined = undefined
|
|
3
|
+
export let arialive: svelte.JSX.AriaAttributes['aria-live'] = undefined
|
|
4
|
+
export let ariaatomic: svelte.JSX.AriaAttributes['aria-atomic'] = undefined
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
7
|
<style>
|
|
@@ -23,4 +23,4 @@
|
|
|
23
23
|
}
|
|
24
24
|
</style>
|
|
25
25
|
|
|
26
|
-
<span
|
|
26
|
+
<span {id} class="sr-only" aria-live={arialive} aria-atomic={ariaatomic}><slot/></span>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Writable } from 'svelte/store';
|
|
2
|
+
export interface UsableSubject<T> {
|
|
3
|
+
subscribe: (observer: (value: T) => void) => () => void;
|
|
4
|
+
}
|
|
5
|
+
export interface WritableSubject<T> extends UsableSubject<T> {
|
|
6
|
+
update: (updater: (value: T) => T) => void;
|
|
7
|
+
}
|
|
8
|
+
export interface SettableSubject<T> extends WritableSubject<T> {
|
|
9
|
+
set: (value: T) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function isUsable<T>(value: T | UsableSubject<T> | undefined): value is UsableSubject<T>;
|
|
12
|
+
export declare function isWritable<T>(value: T | UsableSubject<T> | undefined): value is WritableSubject<T>;
|
|
13
|
+
export declare function isSettable<T>(value: T | UsableSubject<T> | undefined): value is SettableSubject<T>;
|
|
14
|
+
/**
|
|
15
|
+
* An alternative to svelte's "writable" that does not check equality before notifying
|
|
16
|
+
* subscribers. A writable will notify subscribers after a shallow equality check, which
|
|
17
|
+
* does not work with mutated states:
|
|
18
|
+
* store.update(v => { v.someprop = 'newvalue'; return v })
|
|
19
|
+
*
|
|
20
|
+
* With a writable, this line would NOT notify subscribers because the state will be compared
|
|
21
|
+
* against itself and always found to be equal.
|
|
22
|
+
*
|
|
23
|
+
* An alternative to this store type is SafeStore, which will do a deep equality check but
|
|
24
|
+
* clone data so that it is safe against mutations. It costs more CPU cycles but results in
|
|
25
|
+
* fewer notifications to subscribers which could be an overall win.
|
|
26
|
+
*/
|
|
27
|
+
export declare class ActiveStore<T> implements Writable<T> {
|
|
28
|
+
protected value: T;
|
|
29
|
+
protected subscribers: Map<string, (s: T) => void>;
|
|
30
|
+
private cleanups;
|
|
31
|
+
private sourceInits;
|
|
32
|
+
constructor(value: T);
|
|
33
|
+
clone(value: T): T;
|
|
34
|
+
equal(a: T, b: T): boolean;
|
|
35
|
+
set(value: T): void;
|
|
36
|
+
update(updater: (value: T) => T): void;
|
|
37
|
+
subscribe(run: (s: T) => any): () => void;
|
|
38
|
+
/**
|
|
39
|
+
* Provided as a last ditch avenue to clean up memory after rogue subscribers forget
|
|
40
|
+
* to unsubscribe themselves. For example, in an SSR environment one could clear out
|
|
41
|
+
* global stores anytime a request finishes and no other requests are being processed.
|
|
42
|
+
*/
|
|
43
|
+
clearSubscribers(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Stores that subscribe to external events should set it up with a start/stop mentality
|
|
46
|
+
* so that the external events can be unsubscribed when the store itself has no listeners
|
|
47
|
+
* to notify. This helps ensure unused stores can be garbage collected.
|
|
48
|
+
*
|
|
49
|
+
* To do this, pass registerSource a function that initializes the subscription to the external
|
|
50
|
+
* event, and returns a function that can unsubscribe from the external event. This parent
|
|
51
|
+
* class will take care of running those functions at appropriate times.
|
|
52
|
+
*/
|
|
53
|
+
protected registerSource(fn: () => () => void): void;
|
|
54
|
+
/**
|
|
55
|
+
* Provided in case a child class has a need to change out the external resources
|
|
56
|
+
*/
|
|
57
|
+
protected unregisterSources(): void;
|
|
58
|
+
private subscribeToSources;
|
|
59
|
+
private unsubscribeFromSources;
|
|
60
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Store } from './store';
|
|
2
|
+
import { UsableSubject } from './activestore';
|
|
3
|
+
/**
|
|
4
|
+
* A store that allows you to pass in a traditional svelte store in the constructor.
|
|
5
|
+
*
|
|
6
|
+
* Updates to the original store will be sent to subscribers of this store, but only after a deep equality check.
|
|
7
|
+
*
|
|
8
|
+
* Updates to this store will also be sent to the original store after a deep equality check.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ConvertedStore<T> extends Store<T> {
|
|
11
|
+
private valueStore;
|
|
12
|
+
private pause;
|
|
13
|
+
constructor(value: UsableSubject<T>);
|
|
14
|
+
set(value: T): void;
|
|
15
|
+
}
|
|
16
|
+
export declare function convertStore<T>(store: UsableSubject<T>): ConvertedStore<T>;
|