foldkit 0.18.0 → 0.20.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 +14 -14
- package/dist/command/index.d.ts +4 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/command/index.js +1 -0
- package/dist/command/public.d.ts +2 -0
- package/dist/command/public.d.ts.map +1 -0
- package/dist/command/public.js +1 -0
- 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.map +1 -1
- package/dist/fieldValidation/index.js +4 -4
- package/dist/html/index.d.ts +45 -3
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +53 -7
- package/dist/index.d.ts +2 -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/public.d.ts +1 -1
- package/dist/runtime/public.d.ts.map +1 -1
- package/dist/runtime/runtime.d.ts +2 -3
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +9 -9
- package/dist/schema/index.d.ts +36 -8
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +6 -0
- package/dist/task/dom.d.ts +58 -0
- package/dist/task/dom.d.ts.map +1 -0
- package/dist/task/dom.js +112 -0
- package/dist/task/error.d.ts +18 -0
- package/dist/task/error.d.ts.map +1 -0
- package/dist/task/error.js +7 -0
- package/dist/task/index.d.ts +7 -108
- package/dist/task/index.d.ts.map +1 -1
- package/dist/task/index.js +7 -168
- package/dist/task/inert.d.ts +26 -0
- package/dist/task/inert.d.ts.map +1 -0
- package/dist/task/inert.js +87 -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 +11 -0
- package/dist/task/random.d.ts.map +1 -0
- package/dist/task/random.js +10 -0
- package/dist/task/scrollLock.d.ts +24 -0
- package/dist/task/scrollLock.d.ts.map +1 -0
- package/dist/task/scrollLock.js +46 -0
- package/dist/task/time.d.ts +43 -0
- package/dist/task/time.d.ts.map +1 -0
- package/dist/task/time.js +53 -0
- package/dist/task/timing.d.ts +35 -0
- package/dist/task/timing.d.ts.map +1 -0
- package/dist/task/timing.js +51 -0
- package/dist/ui/dialog/index.d.ts +1 -1
- package/dist/ui/dialog/index.d.ts.map +1 -1
- package/dist/ui/dialog/index.js +7 -7
- package/dist/ui/disclosure/index.d.ts +1 -1
- package/dist/ui/disclosure/index.d.ts.map +1 -1
- package/dist/ui/disclosure/index.js +7 -7
- package/dist/ui/keyboard.d.ts.map +1 -1
- package/dist/ui/keyboard.js +1 -1
- package/dist/ui/menu/index.d.ts +71 -18
- package/dist/ui/menu/index.d.ts.map +1 -1
- package/dist/ui/menu/index.js +325 -113
- package/dist/ui/menu/public.d.ts +2 -2
- package/dist/ui/menu/public.d.ts.map +1 -1
- package/dist/ui/menu/public.js +1 -1
- package/dist/ui/tabs/index.d.ts +4 -5
- package/dist/ui/tabs/index.d.ts.map +1 -1
- package/dist/ui/tabs/index.js +12 -14
- package/dist/url/index.js +4 -4
- package/package.json +13 -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';
|
package/dist/runtime/public.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { makeElement, makeApplication, run, makeCommandStreams, } from './runtime';
|
|
2
|
-
export type { BrowserConfig,
|
|
2
|
+
export type { BrowserConfig, CommandStream, CommandStreams, ElementConfigWithFlags, ElementConfigWithoutFlags, ApplicationConfigWithFlags, ApplicationConfigWithoutFlags, ElementInit, ApplicationInit, MakeRuntimeReturn, } from './runtime';
|
|
3
3
|
export { UrlRequest } from './urlRequest';
|
|
4
4
|
export type { Internal, External } from './urlRequest';
|
|
5
5
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/runtime/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,eAAe,EACf,GAAG,EACH,kBAAkB,GACnB,MAAM,WAAW,CAAA;AAElB,YAAY,EACV,aAAa,EACb,
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/runtime/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,eAAe,EACf,GAAG,EACH,kBAAkB,GACnB,MAAM,WAAW,CAAA;AAElB,YAAY,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,EAC1B,6BAA6B,EAC7B,WAAW,EACX,eAAe,EACf,iBAAiB,GAClB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Context, Effect, Schema, Stream } from 'effect';
|
|
2
|
+
import type { Command } from '../command';
|
|
2
3
|
import { Html } from '../html';
|
|
3
4
|
import { Url } from '../url';
|
|
4
5
|
import { UrlRequest } from './urlRequest';
|
|
@@ -9,8 +10,7 @@ declare const Dispatch_base: Context.TagClass<Dispatch, "@foldkit/Dispatch", {
|
|
|
9
10
|
/** Effect service tag that provides message dispatching to the view layer. */
|
|
10
11
|
export declare class Dispatch extends Dispatch_base {
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
-
export type Command<T, E = never, R = never> = Effect.Effect<T extends Schema.Schema.Any ? Schema.Schema.Type<T> : T, E, R>;
|
|
13
|
+
export type { Command } from '../command';
|
|
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;
|
|
@@ -109,5 +109,4 @@ export declare function makeApplication<Model, Message extends {
|
|
|
109
109
|
}, StreamDepsMap extends Schema.Struct<Schema.Struct.Fields>>(config: ApplicationConfigWithoutFlags<Model, Message, StreamDepsMap>): MakeRuntimeReturn;
|
|
110
110
|
/** Starts a Foldkit runtime, with HMR support for development. */
|
|
111
111
|
export declare const run: (foldkitRuntime: MakeRuntimeReturn) => void;
|
|
112
|
-
export {};
|
|
113
112
|
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -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,
|
|
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);
|
|
@@ -102,10 +102,10 @@ const makeRuntime = ({ Model, Flags: _Flags, flags: flags_, init, update, view,
|
|
|
102
102
|
const patchVNode = (maybeCurrentVNode, nextVNodeNullish, container) => {
|
|
103
103
|
const nextVNode = Predicate.isNotNull(nextVNodeNullish)
|
|
104
104
|
? nextVNodeNullish
|
|
105
|
-
: h('
|
|
105
|
+
: h('!');
|
|
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');
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -6,19 +6,47 @@ export type CallableTaggedStruct<Tag extends string, Fields extends S.Struct.Fie
|
|
|
6
6
|
readonly _tag: S.tag<Tag>;
|
|
7
7
|
} & Fields>>);
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
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()`.
|
|
10
11
|
*
|
|
11
|
-
*
|
|
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()`.
|
|
12
42
|
*
|
|
13
43
|
* @example
|
|
14
44
|
* ```typescript
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* Reset() // { _tag: 'Reset' }
|
|
45
|
+
* const Loading = ts('Loading')
|
|
46
|
+
* Loading() // { _tag: 'Loading' }
|
|
18
47
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* SetCount({ count: 1 }) // { _tag: 'SetCount', count: 1 }
|
|
48
|
+
* const Ok = ts('Ok', { data: S.String })
|
|
49
|
+
* Ok({ data: 'hello' }) // { _tag: 'Ok', data: 'hello' }
|
|
22
50
|
* ```
|
|
23
51
|
*/
|
|
24
52
|
export declare function ts<Tag extends string>(tag: Tag): CallableTaggedStruct<Tag, {}>;
|
|
@@ -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,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
|
|
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
|
@@ -9,6 +9,12 @@ new Proxy(schema, {
|
|
|
9
9
|
return Reflect.get(target, property, receiver);
|
|
10
10
|
},
|
|
11
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
|
+
}
|
|
12
18
|
export function ts(tag, fields = {}) {
|
|
13
19
|
return makeCallable(S.TaggedStruct(tag, fields));
|
|
14
20
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
import { ElementNotFound } from './error';
|
|
3
|
+
/**
|
|
4
|
+
* Focuses an element matching the given selector.
|
|
5
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to focus.
|
|
6
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* Task.focus('#email-input').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare const focus: (selector: string) => Effect.Effect<void, ElementNotFound>;
|
|
14
|
+
/**
|
|
15
|
+
* Opens a dialog element as a modal using `showModal()`.
|
|
16
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to show.
|
|
17
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLDialogElement`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* Task.showModal('#my-dialog').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare const showModal: (selector: string) => Effect.Effect<void, ElementNotFound>;
|
|
25
|
+
/**
|
|
26
|
+
* Closes a dialog element using `.close()`.
|
|
27
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to close.
|
|
28
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLDialogElement`.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* Task.closeModal('#my-dialog').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const closeModal: (selector: string) => Effect.Effect<void, ElementNotFound>;
|
|
36
|
+
/**
|
|
37
|
+
* Programmatically clicks an element matching the given selector.
|
|
38
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to click.
|
|
39
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* Task.clickElement('#menu-item-2').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare const clickElement: (selector: string) => Effect.Effect<void, ElementNotFound>;
|
|
47
|
+
/**
|
|
48
|
+
* Scrolls an element into view by selector using `{ block: 'nearest' }`.
|
|
49
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to scroll.
|
|
50
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* Task.scrollIntoView('#active-item').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare const scrollIntoView: (selector: string) => Effect.Effect<void, ElementNotFound>;
|
|
58
|
+
//# 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,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,GAAI,UAAU,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAWxE,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,GACpB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAWlC,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GACrB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAWlC,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAWlC,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,GACzB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAWlC,CAAA"}
|
package/dist/task/dom.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
import { ElementNotFound } from './error';
|
|
3
|
+
/**
|
|
4
|
+
* Focuses an element matching the given selector.
|
|
5
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to focus.
|
|
6
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* Task.focus('#email-input').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export const focus = (selector) => Effect.async(resume => {
|
|
14
|
+
requestAnimationFrame(() => {
|
|
15
|
+
const element = document.querySelector(selector);
|
|
16
|
+
if (element instanceof HTMLElement) {
|
|
17
|
+
element.focus();
|
|
18
|
+
resume(Effect.void);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Opens a dialog element as a modal using `showModal()`.
|
|
27
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to show.
|
|
28
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLDialogElement`.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* Task.showModal('#my-dialog').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export const showModal = (selector) => Effect.async(resume => {
|
|
36
|
+
requestAnimationFrame(() => {
|
|
37
|
+
const element = document.querySelector(selector);
|
|
38
|
+
if (element instanceof HTMLDialogElement) {
|
|
39
|
+
element.showModal();
|
|
40
|
+
resume(Effect.void);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Closes a dialog element using `.close()`.
|
|
49
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to close.
|
|
50
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLDialogElement`.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* Task.closeModal('#my-dialog').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export const closeModal = (selector) => Effect.async(resume => {
|
|
58
|
+
requestAnimationFrame(() => {
|
|
59
|
+
const element = document.querySelector(selector);
|
|
60
|
+
if (element instanceof HTMLDialogElement) {
|
|
61
|
+
element.close();
|
|
62
|
+
resume(Effect.void);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Programmatically clicks an element matching the given selector.
|
|
71
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to click.
|
|
72
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* Task.clickElement('#menu-item-2').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export const clickElement = (selector) => Effect.async(resume => {
|
|
80
|
+
requestAnimationFrame(() => {
|
|
81
|
+
const element = document.querySelector(selector);
|
|
82
|
+
if (element instanceof HTMLElement) {
|
|
83
|
+
element.click();
|
|
84
|
+
resume(Effect.void);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
/**
|
|
92
|
+
* Scrolls an element into view by selector using `{ block: 'nearest' }`.
|
|
93
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to scroll.
|
|
94
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* Task.scrollIntoView('#active-item').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export const scrollIntoView = (selector) => Effect.async(resume => {
|
|
102
|
+
requestAnimationFrame(() => {
|
|
103
|
+
const element = document.querySelector(selector);
|
|
104
|
+
if (element instanceof HTMLElement) {
|
|
105
|
+
element.scrollIntoView({ block: 'nearest' });
|
|
106
|
+
resume(Effect.void);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare const ElementNotFound_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
|
2
|
+
readonly _tag: "ElementNotFound";
|
|
3
|
+
} & Readonly<A>;
|
|
4
|
+
/** Error indicating that a DOM element matching the given selector was not found. */
|
|
5
|
+
export declare class ElementNotFound extends ElementNotFound_base<{
|
|
6
|
+
readonly selector: string;
|
|
7
|
+
}> {
|
|
8
|
+
}
|
|
9
|
+
declare const TimeZoneError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
|
10
|
+
readonly _tag: "TimeZoneError";
|
|
11
|
+
} & Readonly<A>;
|
|
12
|
+
/** Error indicating that the given timezone ID is invalid. */
|
|
13
|
+
export declare class TimeZoneError extends TimeZoneError_base<{
|
|
14
|
+
readonly zoneId: string;
|
|
15
|
+
}> {
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/task/error.ts"],"names":[],"mappings":";;;AAEA,qFAAqF;AACrF,qBAAa,eAAgB,SAAQ,qBAAoC;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,CAAC;CAAG;;;;AAEL,8DAA8D;AAC9D,qBAAa,aAAc,SAAQ,mBAAkC;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,CAAC;CAAG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Data } from 'effect';
|
|
2
|
+
/** Error indicating that a DOM element matching the given selector was not found. */
|
|
3
|
+
export class ElementNotFound extends Data.TaggedError('ElementNotFound') {
|
|
4
|
+
}
|
|
5
|
+
/** Error indicating that the given timezone ID is invalid. */
|
|
6
|
+
export class TimeZoneError extends Data.TaggedError('TimeZoneError') {
|
|
7
|
+
}
|