foldkit 0.17.0 → 0.19.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/README.md +11 -16
- package/dist/effectExtensions/optionExtensions.d.ts +4 -0
- package/dist/effectExtensions/optionExtensions.d.ts.map +1 -1
- package/dist/effectExtensions/optionExtensions.js +2 -1
- package/dist/fieldValidation/index.d.ts +8 -8
- package/dist/fieldValidation/index.d.ts.map +1 -1
- package/dist/fieldValidation/index.js +9 -8
- package/dist/html/index.d.ts +57 -1
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +69 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/message/index.d.ts +2 -0
- package/dist/message/index.d.ts.map +1 -0
- package/dist/message/index.js +1 -0
- package/dist/message/public.d.ts +2 -0
- package/dist/message/public.d.ts.map +1 -0
- package/dist/message/public.js +1 -0
- package/dist/route/index.d.ts +1 -0
- package/dist/route/index.d.ts.map +1 -1
- package/dist/route/index.js +1 -0
- package/dist/route/parser.js +17 -17
- package/dist/route/public.d.ts +1 -1
- package/dist/route/public.d.ts.map +1 -1
- package/dist/route/public.js +1 -1
- package/dist/runtime/browserListeners.d.ts.map +1 -1
- package/dist/runtime/browserListeners.js +2 -2
- package/dist/runtime/runtime.d.ts +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +8 -8
- package/dist/runtime/urlRequest.d.ts +4 -4
- package/dist/runtime/urlRequest.d.ts.map +1 -1
- package/dist/runtime/urlRequest.js +3 -2
- package/dist/schema/index.d.ts +44 -10
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +19 -15
- package/dist/schema/public.d.ts +1 -0
- package/dist/schema/public.d.ts.map +1 -1
- package/dist/task/dom.d.ts +59 -0
- package/dist/task/dom.d.ts.map +1 -0
- package/dist/task/dom.js +113 -0
- package/dist/task/index.d.ts +6 -85
- package/dist/task/index.d.ts.map +1 -1
- package/dist/task/index.js +6 -131
- package/dist/task/inert.d.ts +25 -0
- package/dist/task/inert.d.ts.map +1 -0
- package/dist/task/inert.js +88 -0
- package/dist/task/public.d.ts +1 -1
- package/dist/task/public.d.ts.map +1 -1
- package/dist/task/public.js +1 -1
- package/dist/task/random.d.ts +12 -0
- package/dist/task/random.d.ts.map +1 -0
- package/dist/task/random.js +11 -0
- package/dist/task/scrollLock.d.ts +24 -0
- package/dist/task/scrollLock.d.ts.map +1 -0
- package/dist/task/scrollLock.js +48 -0
- package/dist/task/time.d.ts +42 -0
- package/dist/task/time.d.ts.map +1 -0
- package/dist/task/time.js +54 -0
- package/dist/task/timing.d.ts +36 -0
- package/dist/task/timing.d.ts.map +1 -0
- package/dist/task/timing.js +55 -0
- package/dist/ui/dialog/index.d.ts +4 -4
- package/dist/ui/dialog/index.d.ts.map +1 -1
- package/dist/ui/dialog/index.js +8 -8
- package/dist/ui/disclosure/index.d.ts +4 -4
- package/dist/ui/disclosure/index.d.ts.map +1 -1
- package/dist/ui/disclosure/index.js +8 -8
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +1 -0
- package/dist/ui/keyboard.d.ts +4 -0
- package/dist/ui/keyboard.d.ts.map +1 -0
- package/dist/ui/keyboard.js +7 -0
- package/dist/ui/menu/index.d.ts +189 -0
- package/dist/ui/menu/index.d.ts.map +1 -0
- package/dist/ui/menu/index.js +502 -0
- package/dist/ui/menu/public.d.ts +3 -0
- package/dist/ui/menu/public.d.ts.map +1 -0
- package/dist/ui/menu/public.js +1 -0
- package/dist/ui/tabs/index.d.ts +8 -10
- package/dist/ui/tabs/index.d.ts.map +1 -1
- package/dist/ui/tabs/index.js +17 -28
- package/dist/url/index.d.ts +1 -1
- package/dist/url/index.js +4 -4
- package/package.json +14 -1
package/dist/route/parser.js
CHANGED
|
@@ -19,7 +19,7 @@ parser;
|
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
export const literal = (segment) => ({
|
|
22
|
-
parse:
|
|
22
|
+
parse: segments => Array.matchLeft(segments, {
|
|
23
23
|
onEmpty: () => Effect.fail(new ParseError({
|
|
24
24
|
message: `Expected '${segment}'`,
|
|
25
25
|
expected: segment,
|
|
@@ -48,14 +48,14 @@ export const literal = (segment) => ({
|
|
|
48
48
|
* @param print - Converts the parsed value back into a URL segment string.
|
|
49
49
|
*/
|
|
50
50
|
export const param = (label, parse, print) => ({
|
|
51
|
-
parse:
|
|
51
|
+
parse: segments => Array.matchLeft(segments, {
|
|
52
52
|
onEmpty: () => Effect.fail(new ParseError({
|
|
53
53
|
message: `Expected ${label}`,
|
|
54
54
|
expected: label,
|
|
55
55
|
actual: 'end of path',
|
|
56
56
|
position: 0,
|
|
57
57
|
})),
|
|
58
|
-
onNonEmpty: (head, tail) => pipe(head, parse, Effect.map(
|
|
58
|
+
onNonEmpty: (head, tail) => pipe(head, parse, Effect.map(value => [value, tail])),
|
|
59
59
|
}),
|
|
60
60
|
print: (value, state) => Effect.succeed({
|
|
61
61
|
...state,
|
|
@@ -72,7 +72,7 @@ export const param = (label, parse, print) => ({
|
|
|
72
72
|
*/
|
|
73
73
|
export const string = (name) => param(`string (${name})`,
|
|
74
74
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
75
|
-
|
|
75
|
+
segment => Effect.succeed({ [name]: segment }), record => record[name]);
|
|
76
76
|
/**
|
|
77
77
|
* Creates a parser that captures a URL segment as a named integer field.
|
|
78
78
|
*
|
|
@@ -83,7 +83,7 @@ export const string = (name) => param(`string (${name})`,
|
|
|
83
83
|
* int('id') // parses /42 into { id: 42 }
|
|
84
84
|
* ```
|
|
85
85
|
*/
|
|
86
|
-
export const int = (name) => param(`integer (${name})`,
|
|
86
|
+
export const int = (name) => param(`integer (${name})`, segment => {
|
|
87
87
|
const parsed = parseInt(segment, 10);
|
|
88
88
|
return isNaN(parsed) || parsed.toString() !== segment
|
|
89
89
|
? Effect.fail(new ParseError({
|
|
@@ -93,14 +93,14 @@ export const int = (name) => param(`integer (${name})`, (segment) => {
|
|
|
93
93
|
}))
|
|
94
94
|
: /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
95
95
|
Effect.succeed({ [name]: parsed });
|
|
96
|
-
},
|
|
96
|
+
}, record => record[name].toString());
|
|
97
97
|
/**
|
|
98
98
|
* A parser that matches the root path with no remaining segments.
|
|
99
99
|
*
|
|
100
100
|
* Succeeds only when the URL path is exactly `/`.
|
|
101
101
|
*/
|
|
102
102
|
export const root = {
|
|
103
|
-
parse:
|
|
103
|
+
parse: segments => Array.matchLeft(segments, {
|
|
104
104
|
onEmpty: () => Effect.succeed([{}, []]),
|
|
105
105
|
onNonEmpty: (_, tail) => Effect.fail(new ParseError({
|
|
106
106
|
message: 'Expected root path',
|
|
@@ -111,7 +111,7 @@ export const root = {
|
|
|
111
111
|
print: (_, state) => Effect.succeed(state),
|
|
112
112
|
};
|
|
113
113
|
export function oneOf(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) {
|
|
114
|
-
const parsers = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10].filter(
|
|
114
|
+
const parsers = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10].filter(p => p !== undefined);
|
|
115
115
|
return {
|
|
116
116
|
parse: (segments, search) => Array.matchLeft(parsers, {
|
|
117
117
|
onEmpty: () => {
|
|
@@ -120,7 +120,7 @@ export function oneOf(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) {
|
|
|
120
120
|
message: `No parsers provided for path: ${segmentsStr}`,
|
|
121
121
|
}));
|
|
122
122
|
},
|
|
123
|
-
onNonEmpty: () => Effect.firstSuccessOf(Array.map(parsers,
|
|
123
|
+
onNonEmpty: () => Effect.firstSuccessOf(Array.map(parsers, parser => parser.parse(segments, search))),
|
|
124
124
|
}),
|
|
125
125
|
};
|
|
126
126
|
}
|
|
@@ -164,7 +164,7 @@ export const slash = (parserB) => (parserA) => ({
|
|
|
164
164
|
{ ...valueA, ...valueB },
|
|
165
165
|
remainingB,
|
|
166
166
|
])))),
|
|
167
|
-
print: (value, state) => pipe(parserA.print(value, state), Effect.flatMap(
|
|
167
|
+
print: (value, state) => pipe(parserA.print(value, state), Effect.flatMap(newState => parserB.print(value, newState))),
|
|
168
168
|
});
|
|
169
169
|
/**
|
|
170
170
|
* Adds query parameter parsing to a `Biparser` using an Effect `Schema`.
|
|
@@ -189,17 +189,17 @@ export const query = (schema) => (parser) => {
|
|
|
189
189
|
return pipe(parser.parse(segments, search), Effect.flatMap(([pathValue, remainingSegments]) => {
|
|
190
190
|
const searchParams = new URLSearchParams(search ?? '');
|
|
191
191
|
const queryRecord = Record.fromEntries(searchParams.entries());
|
|
192
|
-
return pipe(queryRecord, Schema.decodeUnknown(schema), Effect.mapError(
|
|
192
|
+
return pipe(queryRecord, Schema.decodeUnknown(schema), Effect.mapError(error => new ParseError({
|
|
193
193
|
message: `Query parameter validation failed: ${error.message}`,
|
|
194
194
|
expected: 'valid query parameters',
|
|
195
195
|
actual: search || 'empty',
|
|
196
|
-
})), Effect.map(
|
|
196
|
+
})), Effect.map(queryValue =>
|
|
197
197
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
198
198
|
[{ ...pathValue, ...queryValue }, remainingSegments]));
|
|
199
199
|
}));
|
|
200
200
|
},
|
|
201
|
-
print: (value, state) => pipe(parser.print(value, state), Effect.flatMap(
|
|
202
|
-
return pipe(Schema.encode(schema)(value), Effect.map(
|
|
201
|
+
print: (value, state) => pipe(parser.print(value, state), Effect.flatMap(newState => {
|
|
202
|
+
return pipe(Schema.encode(schema)(value), Effect.map(queryValue => {
|
|
203
203
|
const newQueryParams = new URLSearchParams(newState.queryParams);
|
|
204
204
|
pipe(queryValue, Record.toEntries, Array.forEach(([key, val]) => {
|
|
205
205
|
if (Predicate.isNotNullable(val)) {
|
|
@@ -210,7 +210,7 @@ export const query = (schema) => (parser) => {
|
|
|
210
210
|
...newState,
|
|
211
211
|
queryParams: newQueryParams,
|
|
212
212
|
};
|
|
213
|
-
}), Effect.mapError(
|
|
213
|
+
}), Effect.mapError(error => new ParseError({
|
|
214
214
|
message: `Query parameter encoding failed: ${error.message}`,
|
|
215
215
|
})));
|
|
216
216
|
})),
|
|
@@ -229,7 +229,7 @@ const complete = ([value, remaining]) => Array.match(remaining, {
|
|
|
229
229
|
},
|
|
230
230
|
});
|
|
231
231
|
const parseUrl = (parser) => (url) => {
|
|
232
|
-
return pipe(pathToSegments(url.pathname),
|
|
232
|
+
return pipe(pathToSegments(url.pathname), segments => parser.parse(segments, Option.getOrUndefined(url.search)), Effect.flatMap(complete));
|
|
233
233
|
};
|
|
234
234
|
/**
|
|
235
235
|
* Parses a URL against a parser, falling back to a not-found route if no
|
|
@@ -245,7 +245,7 @@ const buildUrl = (parser) => (data) => {
|
|
|
245
245
|
segments: [],
|
|
246
246
|
queryParams: new URLSearchParams(),
|
|
247
247
|
};
|
|
248
|
-
return pipe(parser.print(data, initialState), Effect.map(
|
|
248
|
+
return pipe(parser.print(data, initialState), Effect.map(state => {
|
|
249
249
|
const path = '/' + Array.join(state.segments, '/');
|
|
250
250
|
const query = state.queryParams.toString();
|
|
251
251
|
return query ? `${path}?${query}` : path;
|
package/dist/route/public.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ParseError, literal, param, string, int, root, oneOf, mapTo, slash, query, parseUrlWithFallback, } from './index';
|
|
1
|
+
export { ParseError, literal, param, string, int, root, oneOf, mapTo, slash, query, parseUrlWithFallback, r, } from './index';
|
|
2
2
|
export type { ParseResult, Biparser, Router, TerminalParser, Parser, } from './index';
|
|
3
3
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/route/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,OAAO,EACP,KAAK,EACL,MAAM,EACN,GAAG,EACH,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,oBAAoB,
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/route/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,OAAO,EACP,KAAK,EACL,MAAM,EACN,GAAG,EACH,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,oBAAoB,EACpB,CAAC,GACF,MAAM,SAAS,CAAA;AAEhB,YAAY,EACV,WAAW,EACX,QAAQ,EACR,MAAM,EACN,cAAc,EACd,MAAM,GACP,MAAM,SAAS,CAAA"}
|
package/dist/route/public.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ParseError, literal, param, string, int, root, oneOf, mapTo, slash, query, parseUrlWithFallback, } from './index';
|
|
1
|
+
export { ParseError, literal, param, string, int, root, oneOf, mapTo, slash, query, parseUrlWithFallback, r, } from './index';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserListeners.d.ts","sourceRoot":"","sources":["../../src/runtime/browserListeners.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,EAAU,MAAM,QAAQ,CAAA;AAI9C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAGzC,eAAO,MAAM,2BAA2B,GAAI,OAAO,EACjD,cAAc,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAClC,eAAe,aAAa,CAAC,OAAO,CAAC,SAKtC,CAAA;
|
|
1
|
+
{"version":3,"file":"browserListeners.d.ts","sourceRoot":"","sources":["../../src/runtime/browserListeners.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,EAAU,MAAM,QAAQ,CAAA;AAI9C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAGzC,eAAO,MAAM,2BAA2B,GAAI,OAAO,EACjD,cAAc,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAClC,eAAe,aAAa,CAAC,OAAO,CAAC,SAKtC,CAAA;AAkFD,eAAO,MAAM,yBAAyB,YASrC,CAAA"}
|
|
@@ -31,10 +31,10 @@ const addLinkClickListener = (messageQueue, browserConfig) => {
|
|
|
31
31
|
const linkUrl = new URL(href);
|
|
32
32
|
const currentUrl = new URL(window.location.href);
|
|
33
33
|
if (linkUrl.origin !== currentUrl.origin) {
|
|
34
|
-
Queue.unsafeOffer(messageQueue, browserConfig.onUrlRequest(External
|
|
34
|
+
Queue.unsafeOffer(messageQueue, browserConfig.onUrlRequest(External({ href })));
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
Queue.unsafeOffer(messageQueue, browserConfig.onUrlRequest(Internal
|
|
37
|
+
Queue.unsafeOffer(messageQueue, browserConfig.onUrlRequest(Internal({ url: urlToFoldkitUrl(linkUrl) })));
|
|
38
38
|
};
|
|
39
39
|
document.addEventListener('click', onLinkClick);
|
|
40
40
|
};
|
|
@@ -10,7 +10,7 @@ declare const Dispatch_base: Context.TagClass<Dispatch, "@foldkit/Dispatch", {
|
|
|
10
10
|
export declare class Dispatch extends Dispatch_base {
|
|
11
11
|
}
|
|
12
12
|
/** An `Effect` that produces a message, used for side effects in the update function. */
|
|
13
|
-
export type Command<
|
|
13
|
+
export type Command<T, E = never, R = never> = Effect.Effect<T extends Schema.Schema.Any ? Schema.Schema.Type<T> : T, E, R>;
|
|
14
14
|
/** Configuration for browser URL integration with handlers for URL requests and URL changes. */
|
|
15
15
|
export type BrowserConfig<Message> = {
|
|
16
16
|
readonly onUrlRequest: (request: UrlRequest) => Message;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,OAAO,EACP,MAAM,EASN,MAAM,EACN,MAAM,EAGP,MAAM,QAAQ,CAAA;AAGf,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAE,GAAG,EAA+B,MAAM,QAAQ,CAAA;AAOzD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;;4BAMb,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;2BAC1C,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI;;AALrD,8EAA8E;AAC9E,qBAAa,QAAS,SAAQ,aAM3B;CAAG;AAEN,yFAAyF;AACzF,MAAM,MAAM,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/runtime.js
CHANGED
|
@@ -23,11 +23,11 @@ const makeRuntime = ({ Model, Flags: _Flags, flags: flags_, init, update, view,
|
|
|
23
23
|
const [initModel, initCommands] = Predicate.isNotUndefined(hmrModel)
|
|
24
24
|
? pipe(hmrModel, Schema.decodeUnknownEither(Model), Either.match({
|
|
25
25
|
onLeft: () => init(flags, Option.getOrUndefined(currentUrl)),
|
|
26
|
-
onRight:
|
|
26
|
+
onRight: restoredModel => [restoredModel, []],
|
|
27
27
|
}))
|
|
28
28
|
: init(flags, Option.getOrUndefined(currentUrl));
|
|
29
29
|
const modelSubscriptionRef = yield* SubscriptionRef.make(initModel);
|
|
30
|
-
yield* Effect.forEach(initCommands,
|
|
30
|
+
yield* Effect.forEach(initCommands, command => Effect.forkDaemon(command.pipe(Effect.flatMap(enqueueMessage))));
|
|
31
31
|
if (browserConfig) {
|
|
32
32
|
addNavigationEventListeners(messageQueue, browserConfig);
|
|
33
33
|
}
|
|
@@ -43,7 +43,7 @@ const makeRuntime = ({ Model, Flags: _Flags, flags: flags_, init, update, view,
|
|
|
43
43
|
yield* SubscriptionRef.set(modelSubscriptionRef, nextModel);
|
|
44
44
|
preserveModel(nextModel);
|
|
45
45
|
}
|
|
46
|
-
yield* Effect.forEach(commands,
|
|
46
|
+
yield* Effect.forEach(commands, command => Effect.forkDaemon(command.pipe(Effect.flatMap(enqueueMessage))));
|
|
47
47
|
});
|
|
48
48
|
const runProcessMessage = (messageEffect) => (runtime) => {
|
|
49
49
|
try {
|
|
@@ -69,7 +69,7 @@ const makeRuntime = ({ Model, Flags: _Flags, flags: flags_, init, update, view,
|
|
|
69
69
|
const dispatchAsync = (message) =>
|
|
70
70
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
71
71
|
enqueueMessage(message);
|
|
72
|
-
const render = (model) => view(model).pipe(Effect.flatMap(
|
|
72
|
+
const render = (model) => view(model).pipe(Effect.flatMap(nextVNodeNullish => Effect.gen(function* () {
|
|
73
73
|
const maybeCurrentVNode = yield* Ref.get(maybeCurrentVNodeRef);
|
|
74
74
|
const patchedVNode = yield* Effect.sync(() => patchVNode(maybeCurrentVNode, nextVNodeNullish, container));
|
|
75
75
|
yield* Ref.set(maybeCurrentVNodeRef, Option.some(patchedVNode));
|
|
@@ -93,7 +93,7 @@ const makeRuntime = ({ Model, Flags: _Flags, flags: flags_, init, update, view,
|
|
|
93
93
|
yield* pipe(Effect.forever(Effect.gen(function* () {
|
|
94
94
|
const message = yield* Queue.take(messageQueue);
|
|
95
95
|
yield* processMessage(message);
|
|
96
|
-
})), Effect.catchAllCause(
|
|
96
|
+
})), Effect.catchAllCause(cause => Effect.sync(() => {
|
|
97
97
|
const squashed = Cause.squash(cause);
|
|
98
98
|
const appError = squashed instanceof Error ? squashed : new Error(String(squashed));
|
|
99
99
|
renderErrorView(appError, errorView, container, maybeCurrentVNodeRef);
|
|
@@ -105,7 +105,7 @@ const patchVNode = (maybeCurrentVNode, nextVNodeNullish, container) => {
|
|
|
105
105
|
: h('#text', {}, '');
|
|
106
106
|
return Option.match(maybeCurrentVNode, {
|
|
107
107
|
onNone: () => patch(toVNode(container), nextVNode),
|
|
108
|
-
onSome:
|
|
108
|
+
onSome: currentVNode => patch(currentVNode, nextVNode),
|
|
109
109
|
});
|
|
110
110
|
};
|
|
111
111
|
const renderErrorView = (appError, errorView, container, maybeCurrentVNodeRef) => {
|
|
@@ -140,7 +140,7 @@ export function makeElement(config) {
|
|
|
140
140
|
...baseConfig,
|
|
141
141
|
Flags: config.Flags,
|
|
142
142
|
flags: config.flags,
|
|
143
|
-
init:
|
|
143
|
+
init: flags => config.init(flags),
|
|
144
144
|
});
|
|
145
145
|
}
|
|
146
146
|
else {
|
|
@@ -188,7 +188,7 @@ const preserveModel = (model) => {
|
|
|
188
188
|
/** Starts a Foldkit runtime, with HMR support for development. */
|
|
189
189
|
export const run = (foldkitRuntime) => {
|
|
190
190
|
if (import.meta.hot) {
|
|
191
|
-
import.meta.hot.on('foldkit:restore-model',
|
|
191
|
+
import.meta.hot.on('foldkit:restore-model', model => {
|
|
192
192
|
BrowserRuntime.runMain(foldkitRuntime(model));
|
|
193
193
|
});
|
|
194
194
|
import.meta.hot.send('foldkit:request-model');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Schema as S } from 'effect';
|
|
2
2
|
/** A URL request to a page within the application (same origin). */
|
|
3
|
-
export declare const Internal:
|
|
3
|
+
export declare const Internal: import("../schema").CallableTaggedStruct<"Internal", {
|
|
4
4
|
url: S.Struct<{
|
|
5
5
|
protocol: typeof S.String;
|
|
6
6
|
host: typeof S.String;
|
|
@@ -13,13 +13,13 @@ export declare const Internal: S.TaggedStruct<"Internal", {
|
|
|
13
13
|
/** A URL request to a page within the application (same origin). */
|
|
14
14
|
export type Internal = typeof Internal.Type;
|
|
15
15
|
/** A URL request to an external page (different origin). */
|
|
16
|
-
export declare const External:
|
|
16
|
+
export declare const External: import("../schema").CallableTaggedStruct<"External", {
|
|
17
17
|
href: typeof S.String;
|
|
18
18
|
}>;
|
|
19
19
|
/** A URL request to an external page (different origin). */
|
|
20
20
|
export type External = typeof External.Type;
|
|
21
21
|
/** Union of `Internal` and `External` URL request types. */
|
|
22
|
-
export declare const UrlRequest: S.Union<[
|
|
22
|
+
export declare const UrlRequest: S.Union<[import("../schema").CallableTaggedStruct<"Internal", {
|
|
23
23
|
url: S.Struct<{
|
|
24
24
|
protocol: typeof S.String;
|
|
25
25
|
host: typeof S.String;
|
|
@@ -28,7 +28,7 @@ export declare const UrlRequest: S.Union<[S.TaggedStruct<"Internal", {
|
|
|
28
28
|
search: S.OptionFromSelf<typeof S.String>;
|
|
29
29
|
hash: S.OptionFromSelf<typeof S.String>;
|
|
30
30
|
}>;
|
|
31
|
-
}>,
|
|
31
|
+
}>, import("../schema").CallableTaggedStruct<"External", {
|
|
32
32
|
href: typeof S.String;
|
|
33
33
|
}>]>;
|
|
34
34
|
/** Union of `Internal` and `External` URL request types. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urlRequest.d.ts","sourceRoot":"","sources":["../../src/runtime/urlRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"urlRequest.d.ts","sourceRoot":"","sources":["../../src/runtime/urlRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAKpC,oEAAoE;AACpE,eAAO,MAAM,QAAQ;;;;;;;;;EAEnB,CAAA;AACF,oEAAoE;AACpE,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C,4DAA4D;AAC5D,eAAO,MAAM,QAAQ;;EAEnB,CAAA;AACF,4DAA4D;AAC5D,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C,4DAA4D;AAC5D,eAAO,MAAM,UAAU;;;;;;;;;;;IAA8B,CAAA;AACrD,4DAA4D;AAC5D,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Schema as S } from 'effect';
|
|
2
|
+
import { ts } from '../schema';
|
|
2
3
|
import { Url } from '../url';
|
|
3
4
|
/** A URL request to a page within the application (same origin). */
|
|
4
|
-
export const Internal =
|
|
5
|
+
export const Internal = ts('Internal', {
|
|
5
6
|
url: Url,
|
|
6
7
|
});
|
|
7
8
|
/** A URL request to an external page (different origin). */
|
|
8
|
-
export const External =
|
|
9
|
+
export const External = ts('External', {
|
|
9
10
|
href: S.String,
|
|
10
11
|
});
|
|
11
12
|
/** Union of `Internal` and `External` URL request types. */
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -1,20 +1,54 @@
|
|
|
1
1
|
import { Schema as S } from 'effect';
|
|
2
|
+
/** A `TaggedStruct` schema that can be called directly as a constructor: `Foo({ count: 1 })` instead of `Foo.make({ count: 1 })`. */
|
|
3
|
+
export type CallableTaggedStruct<Tag extends string, Fields extends S.Struct.Fields> = S.TaggedStruct<Tag, Fields> & (keyof Fields extends never ? (value?: Parameters<S.TaggedStruct<Tag, Fields>['make']>[0] | void) => S.Simplify<S.Struct.Type<{
|
|
4
|
+
readonly _tag: S.tag<Tag>;
|
|
5
|
+
} & Fields>> : (value: Parameters<S.TaggedStruct<Tag, Fields>['make']>[0]) => S.Simplify<S.Struct.Type<{
|
|
6
|
+
readonly _tag: S.tag<Tag>;
|
|
7
|
+
} & Fields>>);
|
|
2
8
|
/**
|
|
3
|
-
*
|
|
9
|
+
* Wraps `Schema.TaggedStruct` to create a message variant you can call directly as a constructor.
|
|
10
|
+
* Use `m` for message types — enabling `ClickedReset()` instead of `ClickedReset.make()`.
|
|
4
11
|
*
|
|
5
|
-
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const ClickedReset = m('ClickedReset')
|
|
15
|
+
* ClickedReset() // { _tag: 'ClickedReset' }
|
|
16
|
+
*
|
|
17
|
+
* const ChangedCount = m('ChangedCount', { count: S.Number })
|
|
18
|
+
* ChangedCount({ count: 1 }) // { _tag: 'ChangedCount', count: 1 }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function m<Tag extends string>(tag: Tag): CallableTaggedStruct<Tag, {}>;
|
|
22
|
+
export declare function m<Tag extends string, Fields extends S.Struct.Fields>(tag: Tag, fields: Fields): CallableTaggedStruct<Tag, Fields>;
|
|
23
|
+
/**
|
|
24
|
+
* Wraps `Schema.TaggedStruct` to create a route variant you can call directly as a constructor.
|
|
25
|
+
* Use `r` for route types — enabling `Home()` instead of `Home.make()`.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const Home = r('Home')
|
|
30
|
+
* Home() // { _tag: 'Home' }
|
|
31
|
+
*
|
|
32
|
+
* const UserProfile = r('UserProfile', { id: S.String })
|
|
33
|
+
* UserProfile({ id: 'abc' }) // { _tag: 'UserProfile', id: 'abc' }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function r<Tag extends string>(tag: Tag): CallableTaggedStruct<Tag, {}>;
|
|
37
|
+
export declare function r<Tag extends string, Fields extends S.Struct.Fields>(tag: Tag, fields: Fields): CallableTaggedStruct<Tag, Fields>;
|
|
38
|
+
/**
|
|
39
|
+
* Wraps `Schema.TaggedStruct` to create a callable tagged struct you can call directly as a constructor.
|
|
40
|
+
* Use `ts` for non-message, non-route tagged structs — enabling `Loading()`
|
|
41
|
+
* instead of `Loading.make()`.
|
|
6
42
|
*
|
|
7
43
|
* @example
|
|
8
44
|
* ```typescript
|
|
9
|
-
*
|
|
10
|
-
*
|
|
45
|
+
* const Loading = ts('Loading')
|
|
46
|
+
* Loading() // { _tag: 'Loading' }
|
|
11
47
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
48
|
+
* const Ok = ts('Ok', { data: S.String })
|
|
49
|
+
* Ok({ data: 'hello' }) // { _tag: 'Ok', data: 'hello' }
|
|
14
50
|
* ```
|
|
15
51
|
*/
|
|
16
|
-
export declare
|
|
17
|
-
|
|
18
|
-
<Tag extends string, Fields extends S.Struct.Fields>(tag: Tag, fields: Fields): S.TaggedStruct<Tag, Fields>;
|
|
19
|
-
};
|
|
52
|
+
export declare function ts<Tag extends string>(tag: Tag): CallableTaggedStruct<Tag, {}>;
|
|
53
|
+
export declare function ts<Tag extends string, Fields extends S.Struct.Fields>(tag: Tag, fields: Fields): CallableTaggedStruct<Tag, Fields>;
|
|
20
54
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEpC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEpC,qIAAqI;AACrI,MAAM,MAAM,oBAAoB,CAC9B,GAAG,SAAS,MAAM,EAClB,MAAM,SAAS,CAAC,CAAC,MAAM,CAAC,MAAM,IAC5B,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,GAC7B,CAAC,MAAM,MAAM,SAAS,KAAK,GACvB,CACE,KAAK,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAC9D,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;CAAE,GAAG,MAAM,CAAC,CAAC,GACtE,CACE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KACtD,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;CAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;AAe7E;;;;;;;;;;;;GAYG;AACH,wBAAgB,CAAC,CAAC,GAAG,SAAS,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,oBAAoB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AAC9E,wBAAgB,CAAC,CAAC,GAAG,SAAS,MAAM,EAAE,MAAM,SAAS,CAAC,CAAC,MAAM,CAAC,MAAM,EAClE,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,GACb,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;AAKpC;;;;;;;;;;;;GAYG;AACH,wBAAgB,CAAC,CAAC,GAAG,SAAS,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,oBAAoB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AAC9E,wBAAgB,CAAC,CAAC,GAAG,SAAS,MAAM,EAAE,MAAM,SAAS,CAAC,CAAC,MAAM,CAAC,MAAM,EAClE,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,GACb,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;AAKpC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,EAAE,CAAC,GAAG,SAAS,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,oBAAoB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AAC/E,wBAAgB,EAAE,CAAC,GAAG,SAAS,MAAM,EAAE,MAAM,SAAS,CAAC,CAAC,MAAM,CAAC,MAAM,EACnE,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,GACb,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA"}
|
package/dist/schema/index.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { Schema as S } from 'effect';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
const makeCallable = (schema) =>
|
|
3
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
4
|
+
new Proxy(schema, {
|
|
5
|
+
apply(_target, _thisArg, argumentsList) {
|
|
6
|
+
return schema.make(argumentsList[0]);
|
|
7
|
+
},
|
|
8
|
+
get(target, property, receiver) {
|
|
9
|
+
return Reflect.get(target, property, receiver);
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
export function m(tag, fields = {}) {
|
|
13
|
+
return makeCallable(S.TaggedStruct(tag, fields));
|
|
14
|
+
}
|
|
15
|
+
export function r(tag, fields = {}) {
|
|
16
|
+
return makeCallable(S.TaggedStruct(tag, fields));
|
|
17
|
+
}
|
|
18
|
+
export function ts(tag, fields = {}) {
|
|
19
|
+
return makeCallable(S.TaggedStruct(tag, fields));
|
|
20
|
+
}
|
package/dist/schema/public.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/schema/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/schema/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAC5B,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a command that focuses an element by selector and passes the result to a message constructor.
|
|
4
|
+
* Passes true if the element was found and focused, false otherwise.
|
|
5
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to focus.
|
|
6
|
+
* This follows the same approach as Elm's Browser.Dom.focus.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* Task.focus('#email-input', success => InputFocused({ success }))
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare const focus: <Message>(selector: string, f: (success: boolean) => Message) => Effect.Effect<Message>;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a command that opens a dialog element as a modal using `showModal()`.
|
|
16
|
+
* Passes true if the element was found and opened, false otherwise.
|
|
17
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to show.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* Task.showModal('#my-dialog', success => ModalOpened({ success }))
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare const showModal: <Message>(selector: string, f: (success: boolean) => Message) => Effect.Effect<Message>;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a command that closes a dialog element using `.close()`.
|
|
27
|
+
* Passes true if the element was found and closed, false otherwise.
|
|
28
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to close.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* Task.closeModal('#my-dialog', success => ModalClosed({ success }))
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const closeModal: <Message>(selector: string, f: (success: boolean) => Message) => Effect.Effect<Message>;
|
|
36
|
+
/**
|
|
37
|
+
* Creates a command that programmatically clicks an element by selector and passes the result to a message constructor.
|
|
38
|
+
* Passes true if the element was found and clicked, false otherwise.
|
|
39
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to click.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* Task.clickElement('#menu-item-2', success => ItemClicked({ success }))
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare const clickElement: <Message>(selector: string, f: (success: boolean) => Message) => Effect.Effect<Message>;
|
|
47
|
+
/**
|
|
48
|
+
* Creates a command that scrolls an element into view by selector and passes the result to a message constructor.
|
|
49
|
+
* Passes true if the element was found and scrolled, false otherwise.
|
|
50
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to scroll.
|
|
51
|
+
* Uses `{ block: 'nearest' }` to avoid unnecessary scrolling when the element is already visible.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* Task.scrollIntoView('#active-item', success => ItemScrolled({ success }))
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare const scrollIntoView: <Message>(selector: string, f: (success: boolean) => Message) => Effect.Effect<Message>;
|
|
59
|
+
//# sourceMappingURL=dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/task/dom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,EAC3B,UAAU,MAAM,EAChB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,KAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,CAWpB,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,EAC/B,UAAU,MAAM,EAChB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,KAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,CAWpB,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,EAChC,UAAU,MAAM,EAChB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,KAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,CAWpB,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,EAClC,UAAU,MAAM,EAChB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,KAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,CAWpB,CAAA;AAEJ;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,EACpC,UAAU,MAAM,EAChB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,KAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,CAWpB,CAAA"}
|
package/dist/task/dom.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a command that focuses an element by selector and passes the result to a message constructor.
|
|
4
|
+
* Passes true if the element was found and focused, false otherwise.
|
|
5
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to focus.
|
|
6
|
+
* This follows the same approach as Elm's Browser.Dom.focus.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* Task.focus('#email-input', success => InputFocused({ success }))
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export const focus = (selector, f) => Effect.async(resume => {
|
|
14
|
+
requestAnimationFrame(() => {
|
|
15
|
+
const element = document.querySelector(selector);
|
|
16
|
+
if (element instanceof HTMLElement) {
|
|
17
|
+
element.focus();
|
|
18
|
+
resume(Effect.succeed(f(true)));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
resume(Effect.succeed(f(false)));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Creates a command that opens a dialog element as a modal using `showModal()`.
|
|
27
|
+
* Passes true if the element was found and opened, false otherwise.
|
|
28
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to show.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* Task.showModal('#my-dialog', success => ModalOpened({ success }))
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export const showModal = (selector, f) => Effect.async(resume => {
|
|
36
|
+
requestAnimationFrame(() => {
|
|
37
|
+
const element = document.querySelector(selector);
|
|
38
|
+
if (element instanceof HTMLDialogElement) {
|
|
39
|
+
element.showModal();
|
|
40
|
+
resume(Effect.succeed(f(true)));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
resume(Effect.succeed(f(false)));
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Creates a command that closes a dialog element using `.close()`.
|
|
49
|
+
* Passes true if the element was found and closed, false otherwise.
|
|
50
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to close.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* Task.closeModal('#my-dialog', success => ModalClosed({ success }))
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export const closeModal = (selector, f) => Effect.async(resume => {
|
|
58
|
+
requestAnimationFrame(() => {
|
|
59
|
+
const element = document.querySelector(selector);
|
|
60
|
+
if (element instanceof HTMLDialogElement) {
|
|
61
|
+
element.close();
|
|
62
|
+
resume(Effect.succeed(f(true)));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
resume(Effect.succeed(f(false)));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Creates a command that programmatically clicks an element by selector and passes the result to a message constructor.
|
|
71
|
+
* Passes true if the element was found and clicked, false otherwise.
|
|
72
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to click.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* Task.clickElement('#menu-item-2', success => ItemClicked({ success }))
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export const clickElement = (selector, f) => Effect.async(resume => {
|
|
80
|
+
requestAnimationFrame(() => {
|
|
81
|
+
const element = document.querySelector(selector);
|
|
82
|
+
if (element instanceof HTMLElement) {
|
|
83
|
+
element.click();
|
|
84
|
+
resume(Effect.succeed(f(true)));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
resume(Effect.succeed(f(false)));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
/**
|
|
92
|
+
* Creates a command that scrolls an element into view by selector and passes the result to a message constructor.
|
|
93
|
+
* Passes true if the element was found and scrolled, false otherwise.
|
|
94
|
+
* Uses requestAnimationFrame to ensure the DOM tree is updated and nodes exist before attempting to scroll.
|
|
95
|
+
* Uses `{ block: 'nearest' }` to avoid unnecessary scrolling when the element is already visible.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* Task.scrollIntoView('#active-item', success => ItemScrolled({ success }))
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export const scrollIntoView = (selector, f) => Effect.async(resume => {
|
|
103
|
+
requestAnimationFrame(() => {
|
|
104
|
+
const element = document.querySelector(selector);
|
|
105
|
+
if (element instanceof HTMLElement) {
|
|
106
|
+
element.scrollIntoView({ block: 'nearest' });
|
|
107
|
+
resume(Effect.succeed(f(true)));
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
resume(Effect.succeed(f(false)));
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
});
|