shelving 1.102.2 → 1.103.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/Resource.js +7 -2
- package/db/CollectionReference.js +3 -0
- package/db/Database.js +2 -0
- package/db/ItemReference.js +4 -0
- package/db/ItemState.js +9 -9
- package/db/QueryReference.js +4 -0
- package/db/QueryState.js +12 -11
- package/error/AssertionError.js +2 -0
- package/error/ThroughError.d.ts +0 -1
- package/feedback/Feedback.js +4 -0
- package/feedback/Feedbacks.js +2 -0
- package/firestore/client/FirestoreClientProvider.js +1 -0
- package/firestore/lite/FirestoreLiteProvider.js +1 -0
- package/firestore/server/FirestoreServerProvider.js +1 -0
- package/iterate/AbstractGenerator.js +2 -5
- package/iterate/InspectGenerator.js +7 -10
- package/iterate/ThroughGenerator.js +1 -0
- package/markup/regexp.js +1 -2
- package/markup/rule.js +26 -1
- package/markup/rules.js +1 -1
- package/package.json +1 -1
- package/provider/CacheProvider.js +2 -0
- package/provider/DebugProvider.js +2 -0
- package/provider/MemoryProvider.js +8 -12
- package/provider/ThroughProvider.js +2 -0
- package/provider/ValidationProvider.js +3 -0
- package/react/createCache.js +1 -2
- package/react/useData.js +1 -1
- package/react/useFocus.js +2 -4
- package/react/useInstance.js +2 -3
- package/react/useLazy.js +2 -3
- package/react/useState.js +3 -2
- package/schema/AllowSchema.js +2 -0
- package/schema/ArraySchema.js +4 -0
- package/schema/ColorSchema.js +5 -5
- package/schema/DataSchema.js +1 -0
- package/schema/DateSchema.js +2 -0
- package/schema/DictionarySchema.js +3 -0
- package/schema/EmailSchema.js +5 -5
- package/schema/KeySchema.js +3 -6
- package/schema/LinkSchema.js +5 -3
- package/schema/NumberSchema.js +3 -0
- package/schema/OptionalSchema.js +1 -1
- package/schema/PhoneSchema.js +4 -4
- package/schema/Schema.js +8 -0
- package/schema/SlugSchema.js +3 -6
- package/schema/StringSchema.js +6 -0
- package/schema/ThroughSchema.js +1 -0
- package/schema/TimeSchema.js +7 -0
- package/sequence/AbstractSequence.js +2 -5
- package/sequence/DeferredSequence.d.ts +1 -5
- package/sequence/DeferredSequence.js +33 -40
- package/sequence/InspectSequence.js +7 -10
- package/sequence/IteratorSequence.d.ts +9 -0
- package/sequence/IteratorSequence.js +13 -0
- package/sequence/LazyDeferredSequence.js +8 -3
- package/sequence/ThroughSequence.js +1 -0
- package/sequence/index.d.ts +1 -0
- package/sequence/index.js +1 -0
- package/state/State.d.ts +0 -5
- package/state/State.js +5 -13
- package/util/async.js +4 -0
- package/util/callback.d.ts +2 -2
- package/util/callback.js +1 -1
- package/util/color.js +4 -0
- package/util/data.js +1 -1
- package/util/date.js +1 -1
- package/util/dictionary.js +1 -1
- package/util/dispose.js +1 -3
- package/util/object.d.ts +1 -1
- package/util/object.js +1 -1
- package/util/sequence.d.ts +0 -2
- package/util/sequence.js +19 -32
- package/util/serialise.js +1 -2
- package/util/template.js +1 -2
- package/util/time.js +3 -1
- package/util/timeout.js +3 -1
- package/util/units.js +14 -4
package/api/Resource.js
CHANGED
|
@@ -9,6 +9,12 @@ import { UNDEFINED_VALIDATOR } from "../util/validate.js";
|
|
|
9
9
|
* @param returns The `Validator` the resource's returned value must conform to (defaults to `undefined` if not specified).
|
|
10
10
|
*/
|
|
11
11
|
export class Resource {
|
|
12
|
+
/** Resource name.. */
|
|
13
|
+
name;
|
|
14
|
+
/** Payload validator. */
|
|
15
|
+
payload;
|
|
16
|
+
/** Result validator. */
|
|
17
|
+
result;
|
|
12
18
|
constructor(name, payload = UNDEFINED_VALIDATOR, result = UNDEFINED_VALIDATOR) {
|
|
13
19
|
this.name = name;
|
|
14
20
|
this.payload = payload;
|
|
@@ -21,8 +27,7 @@ export class Resource {
|
|
|
21
27
|
* @throws Feedback if the payload could not be validated.
|
|
22
28
|
*/
|
|
23
29
|
prepare(unsafePayload) {
|
|
24
|
-
|
|
25
|
-
return (_a = this.payload) === null || _a === void 0 ? void 0 : _a.validate(unsafePayload);
|
|
30
|
+
return this.payload?.validate(unsafePayload);
|
|
26
31
|
}
|
|
27
32
|
/**
|
|
28
33
|
* Validate a result for this resource.
|
|
@@ -3,6 +3,7 @@ import { AsyncItemReference, ItemReference } from "./ItemReference.js";
|
|
|
3
3
|
import { AsyncQueryReference, QueryReference } from "./QueryReference.js";
|
|
4
4
|
/** Reference to a collection in a synchronous or asynchronous provider. */
|
|
5
5
|
class AbstractCollectionReference {
|
|
6
|
+
collection;
|
|
6
7
|
constructor(collection) {
|
|
7
8
|
this.collection = collection;
|
|
8
9
|
}
|
|
@@ -29,6 +30,7 @@ class AbstractCollectionReference {
|
|
|
29
30
|
}
|
|
30
31
|
/** Reference to a collection in a synchronous provider. */
|
|
31
32
|
export class CollectionReference extends AbstractCollectionReference {
|
|
33
|
+
provider;
|
|
32
34
|
constructor(provider, collection) {
|
|
33
35
|
super(collection);
|
|
34
36
|
this.provider = provider;
|
|
@@ -75,6 +77,7 @@ export class CollectionReference extends AbstractCollectionReference {
|
|
|
75
77
|
}
|
|
76
78
|
/** Reference to a collection in an asynchronous provider. */
|
|
77
79
|
export class AsyncCollectionReference extends AbstractCollectionReference {
|
|
80
|
+
provider;
|
|
78
81
|
constructor(provider, collection) {
|
|
79
82
|
super(collection);
|
|
80
83
|
this.provider = provider;
|
package/db/Database.js
CHANGED
|
@@ -23,6 +23,7 @@ class AbstractDatabase {
|
|
|
23
23
|
}
|
|
24
24
|
/** Database with a synchronous provider. */
|
|
25
25
|
export class Database extends AbstractDatabase {
|
|
26
|
+
provider;
|
|
26
27
|
constructor(provider) {
|
|
27
28
|
super();
|
|
28
29
|
this.provider = provider;
|
|
@@ -57,6 +58,7 @@ export class Database extends AbstractDatabase {
|
|
|
57
58
|
}
|
|
58
59
|
/** Database with a synchronous provider. */
|
|
59
60
|
export class AsyncDatabase extends AbstractDatabase {
|
|
61
|
+
provider;
|
|
60
62
|
constructor(provider) {
|
|
61
63
|
super();
|
|
62
64
|
this.provider = provider;
|
package/db/ItemReference.js
CHANGED
|
@@ -13,6 +13,8 @@ export const getItemData = (id, data) => (data.id === id ? data : { ...data, id
|
|
|
13
13
|
export const getItemQuery = (id) => ({ id, $limit: 1 });
|
|
14
14
|
/** Reference to an item in a synchronous or asynchronous database. */
|
|
15
15
|
class AbstractItemReference {
|
|
16
|
+
collection;
|
|
17
|
+
id;
|
|
16
18
|
constructor(collection, id) {
|
|
17
19
|
this.collection = collection;
|
|
18
20
|
this.id = id;
|
|
@@ -44,6 +46,7 @@ class AbstractItemReference {
|
|
|
44
46
|
}
|
|
45
47
|
/** Reference to an item in a synchronous database. */
|
|
46
48
|
export class ItemReference extends AbstractItemReference {
|
|
49
|
+
provider;
|
|
47
50
|
constructor(provider, collection, id) {
|
|
48
51
|
super(collection, id);
|
|
49
52
|
this.provider = provider;
|
|
@@ -69,6 +72,7 @@ export class ItemReference extends AbstractItemReference {
|
|
|
69
72
|
}
|
|
70
73
|
/** Reference to an item in an asynchronous database. */
|
|
71
74
|
export class AsyncItemReference extends AbstractItemReference {
|
|
75
|
+
provider;
|
|
72
76
|
constructor(provider, collection, id) {
|
|
73
77
|
super(collection, id);
|
|
74
78
|
this.provider = provider;
|
package/db/ItemState.js
CHANGED
|
@@ -4,10 +4,13 @@ import { State } from "../state/State.js";
|
|
|
4
4
|
import { call } from "../util/callback.js";
|
|
5
5
|
import { NONE } from "../util/constants.js";
|
|
6
6
|
import { getRequired } from "../util/optional.js";
|
|
7
|
+
import { runSequence } from "../util/sequence.js";
|
|
7
8
|
import { getOptionalSource } from "../util/source.js";
|
|
8
9
|
import { getItemData } from "./ItemReference.js";
|
|
9
10
|
/** Hold the current state of a item. */
|
|
10
11
|
export class ItemState extends State {
|
|
12
|
+
ref;
|
|
13
|
+
busy = new BooleanState();
|
|
11
14
|
/** Get the data of this state (throws `RequiredError` if item doesn't exist). */
|
|
12
15
|
get data() {
|
|
13
16
|
return getRequired(this.value);
|
|
@@ -21,14 +24,10 @@ export class ItemState extends State {
|
|
|
21
24
|
return !!this.value;
|
|
22
25
|
}
|
|
23
26
|
constructor(ref) {
|
|
24
|
-
var _a;
|
|
25
27
|
const { provider, collection, id } = ref;
|
|
26
|
-
const memory =
|
|
28
|
+
const memory = getOptionalSource(CacheProvider, provider)?.memory;
|
|
27
29
|
const time = memory ? memory.getItemTime(collection, id) : undefined;
|
|
28
30
|
super(memory && typeof time === "number" ? memory.getItem(collection, id) : NONE, time);
|
|
29
|
-
this.busy = new BooleanState();
|
|
30
|
-
this._iterating = 0;
|
|
31
|
-
this._stop = undefined;
|
|
32
31
|
this.ref = ref;
|
|
33
32
|
// Queue a request to refresh the value if it doesn't exist.
|
|
34
33
|
if (this.loading)
|
|
@@ -59,7 +58,7 @@ export class ItemState extends State {
|
|
|
59
58
|
}
|
|
60
59
|
/** Subscribe this state to a provider. */
|
|
61
60
|
connect(provider = this.ref.provider) {
|
|
62
|
-
return this.
|
|
61
|
+
return runSequence(this.through(provider.getItemSequence(this.ref.collection, this.ref.id)));
|
|
63
62
|
}
|
|
64
63
|
// Override to subscribe to `MemoryProvider` while things are iterating over this state.
|
|
65
64
|
async *[Symbol.asyncIterator]() {
|
|
@@ -74,14 +73,14 @@ export class ItemState extends State {
|
|
|
74
73
|
this.stop();
|
|
75
74
|
}
|
|
76
75
|
}
|
|
76
|
+
_iterating = 0;
|
|
77
77
|
/** Start subscription to `MemoryProvider` if there is one. */
|
|
78
78
|
start() {
|
|
79
|
-
var _a;
|
|
80
79
|
if (!this._stop) {
|
|
81
80
|
const { collection, id, provider } = this.ref;
|
|
82
|
-
const memory =
|
|
81
|
+
const memory = getOptionalSource(CacheProvider, provider)?.memory;
|
|
83
82
|
if (memory)
|
|
84
|
-
this._stop = this.
|
|
83
|
+
this._stop = runSequence(this.through(memory.getCachedItemSequence(collection, id)));
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
/** Stop subscription to `MemoryProvider` if there is one. */
|
|
@@ -89,6 +88,7 @@ export class ItemState extends State {
|
|
|
89
88
|
if (this._stop)
|
|
90
89
|
this._stop = void call(this._stop);
|
|
91
90
|
}
|
|
91
|
+
_stop = undefined;
|
|
92
92
|
// Implement `Disposable`
|
|
93
93
|
[Symbol.dispose]() {
|
|
94
94
|
this.stop();
|
package/db/QueryReference.js
CHANGED
|
@@ -4,6 +4,8 @@ import { getRequired } from "../util/optional.js";
|
|
|
4
4
|
import { runSequence } from "../util/sequence.js";
|
|
5
5
|
/** Reference to a set of items in a sync or async provider. */
|
|
6
6
|
class AbstractQueryReference {
|
|
7
|
+
collection;
|
|
8
|
+
query;
|
|
7
9
|
constructor(collection, query = {}) {
|
|
8
10
|
this.collection = collection;
|
|
9
11
|
this.query = query;
|
|
@@ -27,6 +29,7 @@ class AbstractQueryReference {
|
|
|
27
29
|
}
|
|
28
30
|
/** Reference to a set of items in a provider. */
|
|
29
31
|
export class QueryReference extends AbstractQueryReference {
|
|
32
|
+
provider;
|
|
30
33
|
constructor(provider, collection, query) {
|
|
31
34
|
super(collection, query);
|
|
32
35
|
this.provider = provider;
|
|
@@ -61,6 +64,7 @@ export class QueryReference extends AbstractQueryReference {
|
|
|
61
64
|
}
|
|
62
65
|
/** Reference to a set of items in a provider. */
|
|
63
66
|
export class AsyncQueryReference extends AbstractQueryReference {
|
|
67
|
+
provider;
|
|
64
68
|
constructor(provider, collection, query) {
|
|
65
69
|
super(collection, query);
|
|
66
70
|
this.provider = provider;
|
package/db/QueryState.js
CHANGED
|
@@ -6,13 +6,18 @@ import { call } from "../util/callback.js";
|
|
|
6
6
|
import { NONE } from "../util/constants.js";
|
|
7
7
|
import { getRequired } from "../util/optional.js";
|
|
8
8
|
import { getAfterQuery, getLimit } from "../util/query.js";
|
|
9
|
+
import { runSequence } from "../util/sequence.js";
|
|
9
10
|
import { getOptionalSource } from "../util/source.js";
|
|
10
11
|
/** Hold the current state of a query. */
|
|
11
12
|
export class QueryState extends State {
|
|
13
|
+
ref;
|
|
14
|
+
busy = new BooleanState();
|
|
15
|
+
limit;
|
|
12
16
|
/** Can more items be loaded after the current result. */
|
|
13
17
|
get hasMore() {
|
|
14
18
|
return this._hasMore;
|
|
15
19
|
}
|
|
20
|
+
_hasMore = false;
|
|
16
21
|
/** Get the items currently stored in this query. */
|
|
17
22
|
get items() {
|
|
18
23
|
return this.value;
|
|
@@ -38,17 +43,12 @@ export class QueryState extends State {
|
|
|
38
43
|
return this.value.length;
|
|
39
44
|
}
|
|
40
45
|
constructor(ref) {
|
|
41
|
-
var _a, _b;
|
|
42
46
|
const { provider, collection, query } = ref;
|
|
43
|
-
const memory =
|
|
47
|
+
const memory = getOptionalSource(CacheProvider, provider)?.memory;
|
|
44
48
|
const time = memory ? memory.getQueryTime(collection, query) : undefined;
|
|
45
49
|
super(memory && typeof time === "number" ? memory.getQuery(collection, query) : NONE, time);
|
|
46
|
-
this.busy = new BooleanState();
|
|
47
|
-
this._hasMore = false;
|
|
48
|
-
this._iterating = 0;
|
|
49
|
-
this._stop = undefined;
|
|
50
50
|
this.ref = ref;
|
|
51
|
-
this.limit =
|
|
51
|
+
this.limit = getLimit(query) ?? Infinity;
|
|
52
52
|
// Queue a request to refresh the value if it doesn't exist.
|
|
53
53
|
if (this.loading)
|
|
54
54
|
this.refresh();
|
|
@@ -80,7 +80,7 @@ export class QueryState extends State {
|
|
|
80
80
|
}
|
|
81
81
|
/** Subscribe this state to a provider. */
|
|
82
82
|
connect(provider = this.ref.provider) {
|
|
83
|
-
return this.
|
|
83
|
+
return runSequence(this.through(provider.getQuerySequence(this.ref.collection, this.ref.query)));
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
86
|
* Load more items after the last once.
|
|
@@ -120,14 +120,14 @@ export class QueryState extends State {
|
|
|
120
120
|
this.stop();
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
+
_iterating = 0;
|
|
123
124
|
/** Start subscription to `MemoryProvider` if there is one. */
|
|
124
125
|
start() {
|
|
125
|
-
var _a;
|
|
126
126
|
if (!this._stop) {
|
|
127
127
|
const { collection, query, provider } = this.ref;
|
|
128
|
-
const memory =
|
|
128
|
+
const memory = getOptionalSource(CacheProvider, provider)?.memory;
|
|
129
129
|
if (memory)
|
|
130
|
-
this._stop = this.
|
|
130
|
+
this._stop = runSequence(this.through(memory.getCachedQuerySequence(collection, query)));
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
/** Stop subscription to `MemoryProvider` if there is one. */
|
|
@@ -135,6 +135,7 @@ export class QueryState extends State {
|
|
|
135
135
|
if (this._stop)
|
|
136
136
|
this._stop = void call(this._stop);
|
|
137
137
|
}
|
|
138
|
+
_stop = undefined;
|
|
138
139
|
// Implement `Disposable`
|
|
139
140
|
[Symbol.dispose]() {
|
|
140
141
|
this.stop();
|
package/error/AssertionError.js
CHANGED
|
@@ -7,6 +7,8 @@ import { debug, indent } from "../util/debug.js";
|
|
|
7
7
|
* @param expected The value that made the assertion fail.
|
|
8
8
|
*/
|
|
9
9
|
export class AssertionError extends Error {
|
|
10
|
+
received;
|
|
11
|
+
expected;
|
|
10
12
|
constructor(message = "Failed assertion", ...receivedExpected) {
|
|
11
13
|
super(receivedExpected.length >= 2 //
|
|
12
14
|
? `${message}\nReceived:${indent(debug(receivedExpected[0]))}\nExpected:${indent(debug(receivedExpected[0]))}`
|
package/error/ThroughError.d.ts
CHANGED
package/feedback/Feedback.js
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* - `Feedback`: generated in reaction to something a user did, and helps them understand what to do next.
|
|
8
8
|
*/
|
|
9
9
|
export class Feedback {
|
|
10
|
+
/** String feedback message that is safe to show to a user. */
|
|
11
|
+
message;
|
|
12
|
+
/** Nested details providing deeper feedback. */
|
|
13
|
+
value;
|
|
10
14
|
constructor(feedback, value) {
|
|
11
15
|
this.message = feedback;
|
|
12
16
|
this.value = value;
|
package/feedback/Feedbacks.js
CHANGED
|
@@ -4,6 +4,8 @@ import { mapDictionary } from "../util/transform.js";
|
|
|
4
4
|
import { Feedback } from "./Feedback.js";
|
|
5
5
|
/** Feedback with a list of sub-feedbacks. */
|
|
6
6
|
export class Feedbacks extends Feedback {
|
|
7
|
+
/** List of sub-feedbacks. */
|
|
8
|
+
feedbacks;
|
|
7
9
|
/** List of sub-messages. */
|
|
8
10
|
get messages() {
|
|
9
11
|
return mapDictionary(this.feedbacks, getProp, "message");
|
|
@@ -51,6 +51,7 @@ const _getFieldValue = ({ key, action, value }) => [key, action === "sum" ? Fiel
|
|
|
51
51
|
* - Works with the Firebase Admin SDK for Node.JS
|
|
52
52
|
*/
|
|
53
53
|
export class FirestoreServerProvider {
|
|
54
|
+
_firestore;
|
|
54
55
|
constructor(firestore = new Firestore()) {
|
|
55
56
|
this._firestore = firestore;
|
|
56
57
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
var _a;
|
|
2
1
|
/** Abstract generator designed to be extended that implements the full generator protocol. */
|
|
3
2
|
export class AbstractGenerator {
|
|
4
|
-
|
|
5
|
-
this[_a] = "Generator";
|
|
6
|
-
}
|
|
3
|
+
[Symbol.toStringTag] = "Generator";
|
|
7
4
|
throw(thrown) {
|
|
8
5
|
// Default behaviour for a generator is to throw the error back out of the iterator and not continue.
|
|
9
6
|
throw thrown;
|
|
@@ -13,7 +10,7 @@ export class AbstractGenerator {
|
|
|
13
10
|
return { done: true, value };
|
|
14
11
|
}
|
|
15
12
|
// Implement `Iterable`
|
|
16
|
-
[
|
|
13
|
+
[Symbol.iterator]() {
|
|
17
14
|
return this;
|
|
18
15
|
}
|
|
19
16
|
}
|
|
@@ -13,34 +13,31 @@ const _NOVALUE = Symbol("shelving/InspectGenerator.NOVALUE");
|
|
|
13
13
|
* console.log("RETURNED", watch.returned);
|
|
14
14
|
*/
|
|
15
15
|
export class InspectGenerator extends ThroughGenerator {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/** Is the iteration done? */
|
|
21
|
-
this.done = false;
|
|
22
|
-
this._first = _NOVALUE;
|
|
23
|
-
this._last = _NOVALUE;
|
|
24
|
-
this._returned = _NOVALUE;
|
|
25
|
-
}
|
|
16
|
+
/** Get the number of results received by this iterator so far. */
|
|
17
|
+
count = 0;
|
|
18
|
+
/** Is the iteration done? */
|
|
19
|
+
done = false;
|
|
26
20
|
/** The first yielded value (throws if the iteration yielded no values, i.e. `this.count === 0`). */
|
|
27
21
|
get first() {
|
|
28
22
|
if (this._first === _NOVALUE)
|
|
29
23
|
throw new ConditionError("Iteration not started");
|
|
30
24
|
return this._first;
|
|
31
25
|
}
|
|
26
|
+
_first = _NOVALUE;
|
|
32
27
|
/** The last yielded value (throws if the iteration yielded no values, i.e. `this.count === 0`). */
|
|
33
28
|
get last() {
|
|
34
29
|
if (this._last === _NOVALUE)
|
|
35
30
|
throw new ConditionError("Iteration not started");
|
|
36
31
|
return this._last;
|
|
37
32
|
}
|
|
33
|
+
_last = _NOVALUE;
|
|
38
34
|
/** The returned value (throws if the iteration is not done, i.e. `this.done === false`). */
|
|
39
35
|
get returned() {
|
|
40
36
|
if (this._returned === _NOVALUE)
|
|
41
37
|
throw new ConditionError("Iteration not done");
|
|
42
38
|
return this._returned;
|
|
43
39
|
}
|
|
40
|
+
_returned = _NOVALUE;
|
|
44
41
|
// Override to watch returned values.
|
|
45
42
|
next(value) {
|
|
46
43
|
return this._inspect(this.next(value));
|
package/markup/regexp.js
CHANGED
|
@@ -30,11 +30,10 @@ export class WordRegExp extends RegExp {
|
|
|
30
30
|
super(`(?<lookbehind>^|[^\\p{L}\\p{N}])${pattern}(?![\\p{L}\\p{N}])`, flags);
|
|
31
31
|
}
|
|
32
32
|
exec(input) {
|
|
33
|
-
var _a;
|
|
34
33
|
const match = super.exec(input);
|
|
35
34
|
if (match) {
|
|
36
35
|
const { 0: zero, groups } = match;
|
|
37
|
-
const offset =
|
|
36
|
+
const offset = groups?.lookbehind?.length || 0;
|
|
38
37
|
if (zero && offset) {
|
|
39
38
|
match[0] = zero.slice(offset); // Slice off the start of the match to remove the matched first character.
|
|
40
39
|
match.index += offset; // Increment the index to remove the matched first character.
|
package/markup/rule.js
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { formatURL, getOptionalURL } from "../util/url.js";
|
|
2
2
|
export class MarkupRule {
|
|
3
|
+
/**
|
|
4
|
+
* Contexts this rule should be applied in,
|
|
5
|
+
*
|
|
6
|
+
* @example `["block", "inline", "list"]`
|
|
7
|
+
*/
|
|
8
|
+
contexts;
|
|
9
|
+
/**
|
|
10
|
+
* Context that children should be rendered with.
|
|
11
|
+
*
|
|
12
|
+
* @example `"inline"` // Children of the element rendered by this rule will be parsed against markup rules applied in the "inline" context.
|
|
13
|
+
*/
|
|
14
|
+
subcontext;
|
|
15
|
+
/**
|
|
16
|
+
* Priority for this rule (defaults to zero).
|
|
17
|
+
*
|
|
18
|
+
* @example e.g. `<p>` rule is lower priority than other blocks so it matches last and paragraphs can be interrupted by e.g. `<ul>` and `<blockquote>`.
|
|
19
|
+
* @example e.g. `<code>` rule is higher priority than other inlines so e.g. `<strong>` or `<em>` don't match inside a code block.
|
|
20
|
+
*/
|
|
21
|
+
priority;
|
|
3
22
|
constructor(contexts, //
|
|
4
23
|
subcontext = null, priority = 0) {
|
|
5
24
|
this.contexts = contexts;
|
|
@@ -8,6 +27,8 @@ export class MarkupRule {
|
|
|
8
27
|
}
|
|
9
28
|
}
|
|
10
29
|
export class RegExpMarkupRule extends MarkupRule {
|
|
30
|
+
regexp;
|
|
31
|
+
render;
|
|
11
32
|
constructor(regexp, //
|
|
12
33
|
render, contexts, subcontext, priority) {
|
|
13
34
|
super(contexts, subcontext, priority);
|
|
@@ -19,6 +40,8 @@ export class RegExpMarkupRule extends MarkupRule {
|
|
|
19
40
|
}
|
|
20
41
|
}
|
|
21
42
|
export class NamedRegExpMarkupRule extends MarkupRule {
|
|
43
|
+
regexp;
|
|
44
|
+
render;
|
|
22
45
|
constructor(regexp, //
|
|
23
46
|
render, contexts, subcontext, priority) {
|
|
24
47
|
super(contexts, subcontext, priority);
|
|
@@ -30,6 +53,8 @@ export class NamedRegExpMarkupRule extends MarkupRule {
|
|
|
30
53
|
}
|
|
31
54
|
}
|
|
32
55
|
export class LinkRegExpMarkupRule extends MarkupRule {
|
|
56
|
+
regexp;
|
|
57
|
+
render;
|
|
33
58
|
constructor(regexp, //
|
|
34
59
|
render, contexts, subcontext, priority) {
|
|
35
60
|
super(contexts, subcontext, priority);
|
|
@@ -46,7 +71,7 @@ export class LinkRegExpMarkupRule extends MarkupRule {
|
|
|
46
71
|
const { href, title } = groups;
|
|
47
72
|
const url = getOptionalURL(href, base);
|
|
48
73
|
if (url && schemes.includes(url.protocol)) {
|
|
49
|
-
return { 0: first, index, groups: { href: url.href, title:
|
|
74
|
+
return { 0: first, index, groups: { href: url.href, title: title?.trim() || formatURL(url) } };
|
|
50
75
|
}
|
|
51
76
|
}
|
|
52
77
|
return null;
|
package/markup/rules.js
CHANGED
|
@@ -118,7 +118,7 @@ getLineRegExp(`(?<wrap>\`{3,}|~{3,}) *(?<title>${LINE_REGEXP.source})\n(?<code>$
|
|
|
118
118
|
key: null,
|
|
119
119
|
ref: null,
|
|
120
120
|
$$typeof,
|
|
121
|
-
props: { title:
|
|
121
|
+
props: { title: title?.trim() || undefined, children: code.trim() },
|
|
122
122
|
},
|
|
123
123
|
},
|
|
124
124
|
}), ["block", "list"], null, 10);
|
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { MemoryProvider } from "./MemoryProvider.js";
|
|
2
2
|
/** Keep a copy of asynchronous remote data in a local synchronous cache. */
|
|
3
3
|
export class CacheProvider {
|
|
4
|
+
source;
|
|
5
|
+
memory;
|
|
4
6
|
constructor(source, cache = new MemoryProvider()) {
|
|
5
7
|
this.source = source;
|
|
6
8
|
this.memory = cache;
|
|
@@ -30,6 +30,7 @@ class AbstractDebugProvider {
|
|
|
30
30
|
}
|
|
31
31
|
/** Provider that logs operations to a synchronous source provider to the console. */
|
|
32
32
|
export class DebugProvider extends AbstractDebugProvider {
|
|
33
|
+
source;
|
|
33
34
|
constructor(source) {
|
|
34
35
|
super();
|
|
35
36
|
this.source = source;
|
|
@@ -133,6 +134,7 @@ export class DebugProvider extends AbstractDebugProvider {
|
|
|
133
134
|
}
|
|
134
135
|
/** Provider that logs operations to a synchronous source provider to the console. */
|
|
135
136
|
export class AsyncDebugProvider extends AbstractDebugProvider {
|
|
137
|
+
source;
|
|
136
138
|
constructor(source) {
|
|
137
139
|
super();
|
|
138
140
|
this.source = source;
|
|
@@ -13,10 +13,8 @@ import { updateData } from "../util/update.js";
|
|
|
13
13
|
* - `get()` etc return the exact same instance of an object that's passed into `set()`
|
|
14
14
|
*/
|
|
15
15
|
export class MemoryProvider {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this._tables = {};
|
|
19
|
-
}
|
|
16
|
+
/** List of tables in `{ collection: Table }` format. */
|
|
17
|
+
_tables = {};
|
|
20
18
|
/** Get a table for a collection. */
|
|
21
19
|
getTable(collection) {
|
|
22
20
|
return this._tables[collection] || (this._tables[collection] = new MemoryTable());
|
|
@@ -69,14 +67,12 @@ export class MemoryProvider {
|
|
|
69
67
|
}
|
|
70
68
|
/** An individual table of data. */
|
|
71
69
|
export class MemoryTable {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this._changed = new DeferredSequence();
|
|
79
|
-
}
|
|
70
|
+
/** Actual data in this table. */
|
|
71
|
+
_data = new Map();
|
|
72
|
+
/** Times data was last updated. */
|
|
73
|
+
_times = new Map();
|
|
74
|
+
/** Deferred sequence of next values. */
|
|
75
|
+
_changed = new DeferredSequence();
|
|
80
76
|
getItemTime(id) {
|
|
81
77
|
return this._times.get(id);
|
|
82
78
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** A provider that passes through to a synchronous source. */
|
|
2
2
|
export class ThroughProvider {
|
|
3
|
+
source;
|
|
3
4
|
constructor(source) {
|
|
4
5
|
this.source = source;
|
|
5
6
|
}
|
|
@@ -39,6 +40,7 @@ export class ThroughProvider {
|
|
|
39
40
|
}
|
|
40
41
|
/** A provider that passes through to an asynchronous source. */
|
|
41
42
|
export class AsyncThroughProvider {
|
|
43
|
+
source;
|
|
42
44
|
constructor(source) {
|
|
43
45
|
this.source = source;
|
|
44
46
|
}
|
|
@@ -9,6 +9,7 @@ const VALIDATION_CONTEXT_SET = { action: "set" };
|
|
|
9
9
|
const VALIDATION_CONTEXT_UPDATE = { action: "update", partial: true };
|
|
10
10
|
/** Validate a source provider (source can have any type because validation guarantees the type). */
|
|
11
11
|
class BaseValidationProvider {
|
|
12
|
+
schemas;
|
|
12
13
|
constructor(schemas) {
|
|
13
14
|
this.schemas = schemas;
|
|
14
15
|
}
|
|
@@ -28,6 +29,7 @@ class BaseValidationProvider {
|
|
|
28
29
|
}
|
|
29
30
|
/** Validate a synchronous source provider (source can have any type because validation guarantees the type). */
|
|
30
31
|
export class ValidationProvider extends BaseValidationProvider {
|
|
32
|
+
source;
|
|
31
33
|
constructor(source, schemas) {
|
|
32
34
|
super(schemas);
|
|
33
35
|
this.source = source;
|
|
@@ -64,6 +66,7 @@ export class ValidationProvider extends BaseValidationProvider {
|
|
|
64
66
|
}
|
|
65
67
|
/** Validate an asynchronous source provider (source can have any type because validation guarantees the type). */
|
|
66
68
|
export class AsyncValidationProvider extends BaseValidationProvider {
|
|
69
|
+
source;
|
|
67
70
|
constructor(source, schemas) {
|
|
68
71
|
super(schemas);
|
|
69
72
|
this.source = source;
|
package/react/createCache.js
CHANGED
|
@@ -11,8 +11,7 @@ export function createCache() {
|
|
|
11
11
|
return cache;
|
|
12
12
|
},
|
|
13
13
|
Cache: ({ children }) => {
|
|
14
|
-
|
|
15
|
-
const cache = ((_a = useRef()).current || (_a.current = new Map()));
|
|
14
|
+
const cache = (useRef().current ||= new Map());
|
|
16
15
|
return createElement(context.Provider, { children, value: cache });
|
|
17
16
|
},
|
|
18
17
|
};
|
package/react/useData.js
CHANGED
|
@@ -8,7 +8,7 @@ import { useState } from "./useState.js";
|
|
|
8
8
|
const { Cache, useCache } = createCache();
|
|
9
9
|
export function useData(ref) {
|
|
10
10
|
const cache = useCache();
|
|
11
|
-
const key = ref
|
|
11
|
+
const key = ref?.toString();
|
|
12
12
|
const state = ref && key ? cache.get(key) || setMapItem(cache, key, ref instanceof AsyncItemReference ? new ItemState(ref) : new QueryState(ref)) : undefined;
|
|
13
13
|
return useState(state);
|
|
14
14
|
}
|
package/react/useFocus.js
CHANGED
|
@@ -17,16 +17,14 @@ export function useFocus(active = true) {
|
|
|
17
17
|
const ref = useRef(null);
|
|
18
18
|
// Effect that runs when element is first attached to the DOM.
|
|
19
19
|
useEffect(() => {
|
|
20
|
-
var _a;
|
|
21
20
|
// Set up a global listener the first time `useFocus()` is actually used.
|
|
22
21
|
if (!FOCUS_STACK) {
|
|
23
22
|
FOCUS_STACK = [];
|
|
24
23
|
// Add a focus listener on the body that listens for changes in focus.
|
|
25
24
|
document.body.addEventListener("focusin", () => {
|
|
26
|
-
var _a;
|
|
27
25
|
const el = getLastItem(FOCUS_STACK);
|
|
28
26
|
if (el && !el.contains(document.activeElement))
|
|
29
|
-
|
|
27
|
+
getFirstFocusable(el)?.focus();
|
|
30
28
|
});
|
|
31
29
|
}
|
|
32
30
|
// Only run if the element is open and the ref is attached.
|
|
@@ -35,7 +33,7 @@ export function useFocus(active = true) {
|
|
|
35
33
|
// Keep reference to the element that was focused before this element took the focus.
|
|
36
34
|
const lastEl = document.activeElement;
|
|
37
35
|
// Focus immediately on the first auto-focusable element now (e.g. this might just be the close button).
|
|
38
|
-
|
|
36
|
+
getFirstFocusable(el)?.focus();
|
|
39
37
|
// Add this element to the stack of elements to keep focused.
|
|
40
38
|
addArrayItem(FOCUS_STACK, el);
|
|
41
39
|
return () => {
|
package/react/useInstance.js
CHANGED
|
@@ -6,11 +6,10 @@ import { isArrayEqual } from "../util/equal.js";
|
|
|
6
6
|
* - Returns same instance for as long as `args` is equal to previous `args`.
|
|
7
7
|
*/
|
|
8
8
|
export function useInstance(Constructor, ...args) {
|
|
9
|
-
|
|
10
|
-
const internals = ((_a = useRef()).current || (_a.current = {
|
|
9
|
+
const internals = (useRef().current ||= {
|
|
11
10
|
value: new Constructor(...args),
|
|
12
11
|
args,
|
|
13
|
-
})
|
|
12
|
+
});
|
|
14
13
|
if (!isArrayEqual(args, internals.args)) {
|
|
15
14
|
internals.value = new Constructor(...args);
|
|
16
15
|
internals.args = args;
|