ctrl-fx 0.0.1 → 0.1.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/dist/clipboard.d.ts +7 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +3 -0
- package/dist/db/effects.d.ts +78 -0
- package/dist/db/effects.d.ts.map +1 -0
- package/dist/db/effects.js +98 -0
- package/dist/db/errors.d.ts +21 -0
- package/dist/db/errors.d.ts.map +1 -0
- package/dist/db/errors.js +13 -0
- package/dist/db/index.d.ts +32 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +19 -0
- package/dist/db/keypath.d.ts +40 -0
- package/dist/db/keypath.d.ts.map +1 -0
- package/dist/db/keypath.js +20 -0
- package/dist/db/setup.d.ts +83 -0
- package/dist/db/setup.d.ts.map +1 -0
- package/dist/db/setup.js +100 -0
- package/dist/db/testdb.d.ts +19 -0
- package/dist/db/testdb.d.ts.map +1 -0
- package/dist/db/testdb.js +34 -0
- package/dist/dom/attrs.d.ts +67 -0
- package/dist/dom/attrs.d.ts.map +1 -0
- package/dist/dom/attrs.js +154 -0
- package/dist/dom/components.d.ts +43 -0
- package/dist/dom/components.d.ts.map +1 -0
- package/dist/dom/components.js +86 -0
- package/dist/dom/elems.d.ts +121 -0
- package/dist/dom/elems.d.ts.map +1 -0
- package/dist/dom/elems.js +52 -0
- package/dist/dom/events.d.ts +232 -0
- package/dist/dom/events.d.ts.map +1 -0
- package/dist/dom/events.js +289 -0
- package/dist/dom/index.d.ts +248 -0
- package/dist/dom/index.d.ts.map +1 -0
- package/dist/dom/index.js +266 -0
- package/dist/dom/nodeid.d.ts +9 -0
- package/dist/dom/nodeid.d.ts.map +1 -0
- package/dist/dom/nodeid.js +27 -0
- package/dist/dom/svg.d.ts +23 -0
- package/dist/dom/svg.d.ts.map +1 -0
- package/dist/dom/svg.js +1 -0
- package/dist/dom/views.d.ts +60 -0
- package/dist/dom/views.d.ts.map +1 -0
- package/dist/dom/views.js +154 -0
- package/dist/effects.d.ts +580 -0
- package/dist/effects.d.ts.map +1 -0
- package/dist/effects.js +1556 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/internal/clipboard.d.ts +5 -0
- package/dist/internal/clipboard.d.ts.map +1 -0
- package/dist/internal/clipboard.js +33 -0
- package/dist/internal/cmpmgr.d.ts +46 -0
- package/dist/internal/cmpmgr.d.ts.map +1 -0
- package/dist/internal/cmpmgr.js +561 -0
- package/dist/internal/dbmgr.d.ts +11 -0
- package/dist/internal/dbmgr.d.ts.map +1 -0
- package/dist/internal/dbmgr.js +200 -0
- package/dist/internal/dominterpreter.d.ts +5 -0
- package/dist/internal/dominterpreter.d.ts.map +1 -0
- package/dist/internal/dominterpreter.js +337 -0
- package/dist/internal/eventmgr.d.ts +41 -0
- package/dist/internal/eventmgr.d.ts.map +1 -0
- package/dist/internal/eventmgr.js +696 -0
- package/dist/internal/index.d.ts +19 -0
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +38 -0
- package/dist/internal/interpreter.d.ts +10 -0
- package/dist/internal/interpreter.d.ts.map +1 -0
- package/dist/internal/interpreter.js +1 -0
- package/dist/internal/locutils.d.ts +4 -0
- package/dist/internal/locutils.d.ts.map +1 -0
- package/dist/internal/locutils.js +22 -0
- package/dist/internal/net.d.ts +4 -0
- package/dist/internal/net.d.ts.map +1 -0
- package/dist/internal/net.js +64 -0
- package/dist/internal/realdom.d.ts +249 -0
- package/dist/internal/realdom.d.ts.map +1 -0
- package/dist/internal/realdom.js +1 -0
- package/dist/internal/styleregistry.d.ts +6 -0
- package/dist/internal/styleregistry.d.ts.map +1 -0
- package/dist/internal/styleregistry.js +18 -0
- package/dist/internal/taskreg.d.ts +9 -0
- package/dist/internal/taskreg.d.ts.map +1 -0
- package/dist/internal/taskreg.js +28 -0
- package/dist/internal/testing.d.ts +12 -0
- package/dist/internal/testing.d.ts.map +1 -0
- package/dist/internal/testing.js +974 -0
- package/dist/internal/testinginterpreter.d.ts +10 -0
- package/dist/internal/testinginterpreter.d.ts.map +1 -0
- package/dist/internal/testinginterpreter.js +646 -0
- package/dist/internal/vdom.d.ts +93 -0
- package/dist/internal/vdom.d.ts.map +1 -0
- package/dist/internal/vdom.js +470 -0
- package/dist/json/index.d.ts +5 -0
- package/dist/json/index.d.ts.map +1 -0
- package/dist/json/index.js +2 -0
- package/dist/json/validation.d.ts +28 -0
- package/dist/json/validation.d.ts.map +1 -0
- package/dist/json/validation.js +8 -0
- package/dist/net/fragment.d.ts +10 -0
- package/dist/net/fragment.d.ts.map +1 -0
- package/dist/net/fragment.js +27 -0
- package/dist/net/index.d.ts +42 -0
- package/dist/net/index.d.ts.map +1 -0
- package/dist/net/index.js +60 -0
- package/dist/net/location.d.ts +21 -0
- package/dist/net/location.d.ts.map +1 -0
- package/dist/net/location.js +41 -0
- package/dist/net/path.d.ts +12 -0
- package/dist/net/path.d.ts.map +1 -0
- package/dist/net/path.js +29 -0
- package/dist/net/queryparam.d.ts +10 -0
- package/dist/net/queryparam.d.ts.map +1 -0
- package/dist/net/queryparam.js +34 -0
- package/dist/router.d.ts +40 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +77 -0
- package/dist/scroll.d.ts +7 -0
- package/dist/scroll.d.ts.map +1 -0
- package/dist/scroll.js +3 -0
- package/dist/testing.d.ts +248 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +159 -0
- package/dist/utils/apply.d.ts +9 -0
- package/dist/utils/apply.d.ts.map +1 -0
- package/dist/utils/apply.js +10 -0
- package/dist/utils/index.d.ts +22 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +138 -0
- package/dist/utils/lens.d.ts +18 -0
- package/dist/utils/lens.d.ts.map +1 -0
- package/dist/utils/lens.js +27 -0
- package/dist/utils/match.d.ts +17 -0
- package/dist/utils/match.d.ts.map +1 -0
- package/dist/utils/match.js +28 -0
- package/dist/utils/result.d.ts +47 -0
- package/dist/utils/result.d.ts.map +1 -0
- package/dist/utils/result.js +97 -0
- package/dist/webcomponent.d.ts +15 -0
- package/dist/webcomponent.d.ts.map +1 -0
- package/dist/webcomponent.js +43 -0
- package/package.json +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Effect } from '../effects';
|
|
2
|
+
import { type Result } from '../utils/result';
|
|
3
|
+
export type Method = 'GET' | 'POST' | 'DELETE' | 'PUT' | 'HEAD' | 'OPTIONS';
|
|
4
|
+
export type HttpRequest = {
|
|
5
|
+
readonly uri: string;
|
|
6
|
+
readonly method: Method;
|
|
7
|
+
readonly headers: Headers;
|
|
8
|
+
readonly body?: string;
|
|
9
|
+
};
|
|
10
|
+
export type Headers = {
|
|
11
|
+
[key: string]: string;
|
|
12
|
+
};
|
|
13
|
+
export type HttpResponse = {
|
|
14
|
+
readonly headers: Headers;
|
|
15
|
+
readonly body: ResponseBody;
|
|
16
|
+
};
|
|
17
|
+
export type HttpError = {
|
|
18
|
+
_type: 'HttpError';
|
|
19
|
+
};
|
|
20
|
+
export type RequestError = {
|
|
21
|
+
_type: 'RequestError';
|
|
22
|
+
cause: 'RequestAborted' | 'NetworkFailure' | 'UnexpectedError';
|
|
23
|
+
message: string;
|
|
24
|
+
};
|
|
25
|
+
export type DecodingError = {
|
|
26
|
+
_type: 'DecodingError';
|
|
27
|
+
message: string;
|
|
28
|
+
};
|
|
29
|
+
export declare class Json {
|
|
30
|
+
private wrapped;
|
|
31
|
+
constructor(wrapped: any);
|
|
32
|
+
decodeUnsafe<A>(): A;
|
|
33
|
+
}
|
|
34
|
+
export declare class ResponseBody {
|
|
35
|
+
private data;
|
|
36
|
+
constructor(data: ArrayBuffer);
|
|
37
|
+
asString(): string;
|
|
38
|
+
asBlob(): Blob;
|
|
39
|
+
asJson(): Result<Json, DecodingError>;
|
|
40
|
+
}
|
|
41
|
+
export declare function getJson<State, Event>(uri: string): Effect<State, Event, Result<Json, HttpError | RequestError | DecodingError>>;
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/net/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,YAAY,CAAA;AAEzD,OAAO,EAAoB,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE/D,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;AAE3E,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,WAAW,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,iBAAiB,CAAA;IAC9D,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,eAAe,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,qBAAa,IAAI;IAEf,OAAO,CAAC,OAAO,CAAK;gBAGR,OAAO,EAAE,GAAG;IAIxB,YAAY,CAAC,CAAC,KAAK,CAAC;CAGrB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAa;gBAEb,IAAI,EAAE,WAAW;IAI7B,QAAQ,IAAI,MAAM;IAIlB,MAAM,IAAI,IAAI;IAId,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;CActC;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAClC,GAAG,EAAE,MAAM,GACV,MAAM,CACP,KAAK,EACL,KAAK,EACL,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,aAAa,CAAC,CACvD,CAUA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { makeHttpRequest } from '../effects';
|
|
2
|
+
import { failure, success } from '../utils/result';
|
|
3
|
+
export class Json {
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
constructor(wrapped) {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
Object.defineProperty(this, "wrapped", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true,
|
|
11
|
+
value: void 0
|
|
12
|
+
});
|
|
13
|
+
this.wrapped = wrapped;
|
|
14
|
+
}
|
|
15
|
+
decodeUnsafe() {
|
|
16
|
+
return this.wrapped;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class ResponseBody {
|
|
20
|
+
constructor(data) {
|
|
21
|
+
Object.defineProperty(this, "data", {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
configurable: true,
|
|
24
|
+
writable: true,
|
|
25
|
+
value: void 0
|
|
26
|
+
});
|
|
27
|
+
this.data = data;
|
|
28
|
+
}
|
|
29
|
+
asString() {
|
|
30
|
+
return new TextDecoder().decode(this.data);
|
|
31
|
+
}
|
|
32
|
+
asBlob() {
|
|
33
|
+
return new Blob([this.data]);
|
|
34
|
+
}
|
|
35
|
+
asJson() {
|
|
36
|
+
try {
|
|
37
|
+
return success(new Json(JSON.parse(this.asString())));
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (err instanceof SyntaxError) {
|
|
41
|
+
return failure({ _type: 'DecodingError', message: err.message });
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return failure({
|
|
45
|
+
_type: 'DecodingError',
|
|
46
|
+
message: `Unexpected decoding error: ${err}`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function getJson(uri) {
|
|
53
|
+
return makeHttpRequest({
|
|
54
|
+
uri,
|
|
55
|
+
method: 'GET',
|
|
56
|
+
headers: {},
|
|
57
|
+
}).map(result => result.andThen(rsp => {
|
|
58
|
+
return rsp.body.asJson();
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Fragment } from './fragment';
|
|
2
|
+
import { type Path } from './path';
|
|
3
|
+
import type { QueryParam } from './queryparam';
|
|
4
|
+
export interface InternalLocation {
|
|
5
|
+
readonly path: Path;
|
|
6
|
+
readonly queryParams: readonly QueryParam[];
|
|
7
|
+
readonly fragment?: Fragment;
|
|
8
|
+
}
|
|
9
|
+
export declare function formatLocation(loc: InternalLocation): string;
|
|
10
|
+
export declare function parseInternalLocation(s: string): InternalLocation;
|
|
11
|
+
export interface Location {
|
|
12
|
+
readonly protocol?: string;
|
|
13
|
+
readonly hostname?: string;
|
|
14
|
+
readonly port?: number;
|
|
15
|
+
readonly path: Path;
|
|
16
|
+
readonly queryParams: readonly QueryParam[];
|
|
17
|
+
readonly fragment?: Fragment;
|
|
18
|
+
}
|
|
19
|
+
export declare function internalLocationFromLocation(location: Location): InternalLocation;
|
|
20
|
+
export declare const emptyLocation: InternalLocation;
|
|
21
|
+
//# sourceMappingURL=location.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../src/net/location.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAA;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAC7B;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAE5D;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,gBAAgB,CA4BjE;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAA;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAC7B;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,QAAQ,GACjB,gBAAgB,CAMlB;AAED,eAAO,MAAM,aAAa,EAAE,gBAA4C,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { parseFragment } from './fragment';
|
|
2
|
+
import { parsePath } from './path';
|
|
3
|
+
import { formatQueryString, parseAllQueryParams } from './queryparam';
|
|
4
|
+
export function formatLocation(loc) {
|
|
5
|
+
return `${loc.path.format()}${formatQueryString(loc.queryParams)}${loc.fragment != null ? '#' + loc.fragment.format : ''}`;
|
|
6
|
+
}
|
|
7
|
+
export function parseInternalLocation(s) {
|
|
8
|
+
const fragStart = s.indexOf('#');
|
|
9
|
+
let pathAndParams, fragment;
|
|
10
|
+
if (fragStart < 0) {
|
|
11
|
+
pathAndParams = s;
|
|
12
|
+
fragment = undefined;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
pathAndParams = s.substring(0, fragStart);
|
|
16
|
+
fragment = parseFragment(s.substring(fragStart + 1));
|
|
17
|
+
}
|
|
18
|
+
let path, queryParams;
|
|
19
|
+
const paramsStart = pathAndParams.indexOf('?');
|
|
20
|
+
if (paramsStart < 0) {
|
|
21
|
+
path = parsePath(pathAndParams);
|
|
22
|
+
queryParams = [];
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
path = parsePath(pathAndParams.substring(0, paramsStart));
|
|
26
|
+
queryParams = parseAllQueryParams(pathAndParams.substring(paramsStart + 1));
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
path,
|
|
30
|
+
queryParams,
|
|
31
|
+
fragment,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function internalLocationFromLocation(location) {
|
|
35
|
+
return {
|
|
36
|
+
path: location.path,
|
|
37
|
+
queryParams: location.queryParams,
|
|
38
|
+
fragment: location.fragment,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export const emptyLocation = parseInternalLocation('');
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type Path = {
|
|
2
|
+
readonly elems: readonly string[];
|
|
3
|
+
format(): string;
|
|
4
|
+
matches(that: Path): boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare const emptyPath: {
|
|
7
|
+
elems: never[];
|
|
8
|
+
format(): string;
|
|
9
|
+
matches(that: Path): boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function parsePath(s: string): Path;
|
|
12
|
+
//# sourceMappingURL=path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/net/path.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,MAAM,IAAI,MAAM,CAAA;IAChB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAA;CAC7B,CAAA;AAED,eAAO,MAAM,SAAS;;;kBAKN,IAAI,GAAG,OAAO;CAG7B,CAAA;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAuBzC"}
|
package/dist/net/path.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const emptyPath = {
|
|
2
|
+
elems: [],
|
|
3
|
+
format() {
|
|
4
|
+
return '';
|
|
5
|
+
},
|
|
6
|
+
matches(that) {
|
|
7
|
+
return that.elems.length === 0;
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
export function parsePath(s) {
|
|
11
|
+
return {
|
|
12
|
+
elems: s.split('/'),
|
|
13
|
+
format() {
|
|
14
|
+
return this.elems.join('/');
|
|
15
|
+
},
|
|
16
|
+
matches(that) {
|
|
17
|
+
if (this.elems.length !== that.elems.length) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
for (let i = 0; i < this.elems.length; i++) {
|
|
21
|
+
if (this.elems[i].toLocaleLowerCase() !==
|
|
22
|
+
that.elems[i].toLocaleLowerCase()) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface QueryParam {
|
|
2
|
+
name: string;
|
|
3
|
+
value?: string;
|
|
4
|
+
format: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseQueryParam(str: string): QueryParam;
|
|
7
|
+
export declare function parseAllQueryParams(str: string): readonly QueryParam[];
|
|
8
|
+
export declare function formatQueryString(queryParams: readonly QueryParam[]): string;
|
|
9
|
+
export declare function findQueryParam(haystack: readonly QueryParam[], predicate: (queryParam: QueryParam) => boolean): QueryParam | undefined;
|
|
10
|
+
//# sourceMappingURL=queryparam.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queryparam.d.ts","sourceRoot":"","sources":["../../src/net/queryparam.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAiBvD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAItE;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAM5E;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,SAAS,UAAU,EAAE,EAC/B,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,OAAO,GAC7C,UAAU,GAAG,SAAS,CAExB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function parseQueryParam(str) {
|
|
2
|
+
const eqIndx = str.indexOf('=');
|
|
3
|
+
if (eqIndx < 0) {
|
|
4
|
+
return {
|
|
5
|
+
name: str,
|
|
6
|
+
format: str,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
const name = str.substring(0, eqIndx);
|
|
11
|
+
const value = str.substring(eqIndx + 1);
|
|
12
|
+
return {
|
|
13
|
+
name,
|
|
14
|
+
value,
|
|
15
|
+
format: str,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function parseAllQueryParams(str) {
|
|
20
|
+
const normalizedInput = str.startsWith('?') ? str.substring(1) : str;
|
|
21
|
+
const qps = normalizedInput.split('&').filter(s => s.length > 0);
|
|
22
|
+
return qps.map(parseQueryParam);
|
|
23
|
+
}
|
|
24
|
+
export function formatQueryString(queryParams) {
|
|
25
|
+
if (queryParams.length === 0) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return '?' + queryParams.map(qp => qp.format).join('&');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function findQueryParam(haystack, predicate) {
|
|
33
|
+
return haystack.find(qp => predicate(qp));
|
|
34
|
+
}
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { EventActions } from './dom/events';
|
|
2
|
+
import { type Effect } from './effects';
|
|
3
|
+
import type { InternalLocation } from './net/location';
|
|
4
|
+
export type { EventActions } from './dom/events';
|
|
5
|
+
export type { InternalLocation } from './net/location';
|
|
6
|
+
/** Named path-segment parameters extracted from a matched route. */
|
|
7
|
+
export type Params = Record<string, string>;
|
|
8
|
+
/** A map of URL patterns to handler functions. Pattern keys use `:param` syntax for named path segments. */
|
|
9
|
+
export type RouteMap<Route> = {
|
|
10
|
+
[pattern: string]: (params: Params) => Route;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Creates a route-matching function from a pattern map. Pattern keys use `:param` syntax for
|
|
14
|
+
* named path segments. Returns `null` when no pattern matches.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* const match = router({ '/': () => 'home', '/users/:id': ({ id }) => `user-${id}` })
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function router<Route>(routes: RouteMap<Route>): (location: InternalLocation) => Route | null;
|
|
21
|
+
/**
|
|
22
|
+
* An effect describing a `history.pushState` to `path`, suitable for use as an `onClick` handler on an `<a>` element.
|
|
23
|
+
* Produces `{ preventDefault: true }` to suppress the default browser navigation.
|
|
24
|
+
*/
|
|
25
|
+
export declare function link<State, Event>(path: string): Effect<State, Event, EventActions>;
|
|
26
|
+
/** An effect describing a `history.pushState` to `path`. Use in effect chains or button handlers. */
|
|
27
|
+
export declare function navigate<State, Event>(path: string): Effect<State, Event, void>;
|
|
28
|
+
/**
|
|
29
|
+
* Bundled router that strips `options.basePath` before matching and prepends it before navigating.
|
|
30
|
+
* Use when your app is mounted at a sub-path (e.g. a GitHub Pages subdirectory).
|
|
31
|
+
* Returns a `{ match, link, navigate }` object.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createRouter<Route>(routes: RouteMap<Route>, options?: {
|
|
34
|
+
basePath?: string;
|
|
35
|
+
}): {
|
|
36
|
+
match(location: InternalLocation): Route | null;
|
|
37
|
+
link<State, Event>(path: string): Effect<State, Event, EventActions>;
|
|
38
|
+
navigate<State, Event>(path: string): Effect<State, Event, void>;
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAoB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAA;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAGtD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD,oEAAoE;AACpE,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAE3C,4GAA4G;AAC5G,MAAM,MAAM,QAAQ,CAAC,KAAK,IAAI;IAC5B,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,KAAK,CAAA;CAC7C,CAAA;AA0CD;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAC1B,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,GACtB,CAAC,QAAQ,EAAE,gBAAgB,KAAK,KAAK,GAAG,IAAI,CAG9C;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,KAAK,EAC/B,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,CAIpC;AAED,qGAAqG;AACrG,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EACnC,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAE5B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAChC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,EACvB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B;IACD,KAAK,CAAC,QAAQ,EAAE,gBAAgB,GAAG,KAAK,GAAG,IAAI,CAAA;IAC/C,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,CAAA;IACpE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;CACjE,CAeA"}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { async, pushState } from './effects';
|
|
2
|
+
import { parseInternalLocation } from './net/location';
|
|
3
|
+
function compile(routes) {
|
|
4
|
+
return Object.entries(routes).map(([pattern, handler]) => ({
|
|
5
|
+
segments: pattern.split('/'),
|
|
6
|
+
handler,
|
|
7
|
+
}));
|
|
8
|
+
}
|
|
9
|
+
function matchRoute(compiled, location) {
|
|
10
|
+
const pathSegs = location.path.elems;
|
|
11
|
+
for (const { segments, handler } of compiled) {
|
|
12
|
+
if (segments.length !== pathSegs.length)
|
|
13
|
+
continue;
|
|
14
|
+
const params = {};
|
|
15
|
+
let matched = true;
|
|
16
|
+
for (let i = 0; i < segments.length; i++) {
|
|
17
|
+
const seg = segments[i];
|
|
18
|
+
if (seg.startsWith(':')) {
|
|
19
|
+
params[seg.slice(1)] = pathSegs[i];
|
|
20
|
+
}
|
|
21
|
+
else if (seg.toLowerCase() !== pathSegs[i].toLowerCase()) {
|
|
22
|
+
matched = false;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (matched)
|
|
27
|
+
return handler(params);
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a route-matching function from a pattern map. Pattern keys use `:param` syntax for
|
|
33
|
+
* named path segments. Returns `null` when no pattern matches.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* const match = router({ '/': () => 'home', '/users/:id': ({ id }) => `user-${id}` })
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function router(routes) {
|
|
40
|
+
const compiled = compile(routes);
|
|
41
|
+
return location => matchRoute(compiled, location);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* An effect describing a `history.pushState` to `path`, suitable for use as an `onClick` handler on an `<a>` element.
|
|
45
|
+
* Produces `{ preventDefault: true }` to suppress the default browser navigation.
|
|
46
|
+
*/
|
|
47
|
+
export function link(path) {
|
|
48
|
+
return async(pushState(parseInternalLocation(path)), 0).as({
|
|
49
|
+
preventDefault: true,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/** An effect describing a `history.pushState` to `path`. Use in effect chains or button handlers. */
|
|
53
|
+
export function navigate(path) {
|
|
54
|
+
return pushState(parseInternalLocation(path));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Bundled router that strips `options.basePath` before matching and prepends it before navigating.
|
|
58
|
+
* Use when your app is mounted at a sub-path (e.g. a GitHub Pages subdirectory).
|
|
59
|
+
* Returns a `{ match, link, navigate }` object.
|
|
60
|
+
*/
|
|
61
|
+
export function createRouter(routes, options) {
|
|
62
|
+
const compiled = compile(routes);
|
|
63
|
+
const base = options?.basePath ?? '';
|
|
64
|
+
return {
|
|
65
|
+
match(location) {
|
|
66
|
+
if (!base)
|
|
67
|
+
return matchRoute(compiled, location);
|
|
68
|
+
const fullPath = location.path.elems.join('/');
|
|
69
|
+
if (!fullPath.startsWith(base))
|
|
70
|
+
return null;
|
|
71
|
+
const relative = fullPath.slice(base.length) || '/';
|
|
72
|
+
return matchRoute(compiled, parseInternalLocation(relative));
|
|
73
|
+
},
|
|
74
|
+
link: (path) => link(base + path),
|
|
75
|
+
navigate: (path) => navigate(base + path),
|
|
76
|
+
};
|
|
77
|
+
}
|
package/dist/scroll.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../src/scroll.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,oBAAoB,CAAA;IAC3B,KAAK,EAAE,iBAAiB,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAEvE"}
|
package/dist/scroll.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { type NonEmptyArray } from './utils';
|
|
2
|
+
import { type Attr } from './dom/attrs';
|
|
3
|
+
import type { Node } from './dom';
|
|
4
|
+
import type { Component } from './dom/components';
|
|
5
|
+
import { type NodeGroup } from './dom/views';
|
|
6
|
+
import { type Effect, type ScrollOptions } from './effects';
|
|
7
|
+
import { type HttpError, type HttpRequest, type HttpResponse, type RequestError } from './net';
|
|
8
|
+
import { type Result } from './utils/result';
|
|
9
|
+
import { TestDatabaseData } from './db/testdb';
|
|
10
|
+
import type { DbStoreSnapshot } from './db/testdb';
|
|
11
|
+
import type { InternalLocation } from './net/location';
|
|
12
|
+
export { TestDatabaseData };
|
|
13
|
+
export type { DbStoreSnapshot };
|
|
14
|
+
export type { InternalLocation };
|
|
15
|
+
export type { HttpRequest, HttpResponse, HttpError, RequestError };
|
|
16
|
+
export type DownloadRecord = {
|
|
17
|
+
readonly filename: string;
|
|
18
|
+
readonly content: string;
|
|
19
|
+
readonly contentType: string;
|
|
20
|
+
};
|
|
21
|
+
export type BroadcastSentRecord = {
|
|
22
|
+
readonly channel: string;
|
|
23
|
+
readonly message: unknown;
|
|
24
|
+
};
|
|
25
|
+
export type SetAppBadge = {
|
|
26
|
+
_type: 'SetAppBadge';
|
|
27
|
+
count: number;
|
|
28
|
+
};
|
|
29
|
+
export type ClearAppBadge = {
|
|
30
|
+
_type: 'ClearAppBadge';
|
|
31
|
+
};
|
|
32
|
+
export type AppBadgeOperation = SetAppBadge | ClearAppBadge;
|
|
33
|
+
export declare const clearAppBadge: ClearAppBadge;
|
|
34
|
+
export declare function setAppBadge(count: number): SetAppBadge;
|
|
35
|
+
export declare function appBadgeCount(operations: readonly AppBadgeOperation[]): number;
|
|
36
|
+
export type HttpInteraction = {
|
|
37
|
+
readonly request: HttpRequest;
|
|
38
|
+
readonly response: Result<HttpResponse, RequestError | HttpError>;
|
|
39
|
+
};
|
|
40
|
+
export type HttpHandler = (request: HttpRequest, prior: readonly HttpInteraction[]) => Result<HttpResponse, RequestError | HttpError>;
|
|
41
|
+
/** Configuration passed to `testApplication`/`testComponent` to control how side effects behave during tests. */
|
|
42
|
+
export type TestConfig = {
|
|
43
|
+
readonly http: {
|
|
44
|
+
/** Called for each HTTP request. Throw or return a failure Result to simulate errors. */
|
|
45
|
+
readonly handler: HttpHandler;
|
|
46
|
+
};
|
|
47
|
+
readonly clock: {
|
|
48
|
+
/** Scripted return values for `getTime()`, consumed in order. When exhausted, returns `new Date(0)`. */
|
|
49
|
+
readonly values: readonly Date[];
|
|
50
|
+
};
|
|
51
|
+
readonly random: {
|
|
52
|
+
/** Scripted return values for `getRandom()`, consumed in order. When exhausted, uses a deterministic seeded PRNG. */
|
|
53
|
+
readonly values: readonly number[];
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
/** Creates a TestConfig that throws on any HTTP request. */
|
|
57
|
+
export declare function defaultTestConfig(): TestConfig;
|
|
58
|
+
export type ConfirmInteraction = {
|
|
59
|
+
message: string;
|
|
60
|
+
response: boolean;
|
|
61
|
+
};
|
|
62
|
+
export type PromptInteraction = {
|
|
63
|
+
message: string;
|
|
64
|
+
default: string | undefined;
|
|
65
|
+
response: string | null;
|
|
66
|
+
};
|
|
67
|
+
/** Snapshot of every observable side effect that occurred during a test run. */
|
|
68
|
+
export type TestData<Custom = {}> = {
|
|
69
|
+
readonly window: {
|
|
70
|
+
readonly alerts: readonly any[];
|
|
71
|
+
readonly confirms: readonly ConfirmInteraction[];
|
|
72
|
+
readonly confirmResponses: readonly boolean[];
|
|
73
|
+
readonly prompts: readonly PromptInteraction[];
|
|
74
|
+
readonly promptResponses: readonly (string | null)[];
|
|
75
|
+
};
|
|
76
|
+
readonly navigator: {
|
|
77
|
+
readonly appBadgeOperations: readonly AppBadgeOperation[];
|
|
78
|
+
};
|
|
79
|
+
readonly clipboard: {
|
|
80
|
+
readonly content: string;
|
|
81
|
+
readonly writes: readonly string[];
|
|
82
|
+
};
|
|
83
|
+
readonly document: {
|
|
84
|
+
readonly title: string | null;
|
|
85
|
+
};
|
|
86
|
+
readonly http: {
|
|
87
|
+
readonly interactions: readonly HttpInteraction[];
|
|
88
|
+
};
|
|
89
|
+
readonly clock: {
|
|
90
|
+
/** Values returned by each `getTime()` call, in order. */
|
|
91
|
+
readonly calls: readonly Date[];
|
|
92
|
+
};
|
|
93
|
+
readonly random: {
|
|
94
|
+
/** Values returned by each `getRandom()` call, in order. */
|
|
95
|
+
readonly calls: readonly number[];
|
|
96
|
+
};
|
|
97
|
+
readonly console: {
|
|
98
|
+
readonly logs: readonly any[];
|
|
99
|
+
};
|
|
100
|
+
readonly db: TestDatabaseData;
|
|
101
|
+
readonly storage: {
|
|
102
|
+
readonly local: ReadonlyMap<string, string>;
|
|
103
|
+
readonly session: ReadonlyMap<string, string>;
|
|
104
|
+
};
|
|
105
|
+
readonly navigation: {
|
|
106
|
+
readonly locationHistory: readonly InternalLocation[];
|
|
107
|
+
};
|
|
108
|
+
readonly scroll: {
|
|
109
|
+
readonly windowScrolls: readonly ScrollOptions[];
|
|
110
|
+
readonly elementScrolls: readonly {
|
|
111
|
+
selector: string;
|
|
112
|
+
options: ScrollOptions;
|
|
113
|
+
}[];
|
|
114
|
+
};
|
|
115
|
+
readonly downloads: readonly DownloadRecord[];
|
|
116
|
+
readonly broadcasts: {
|
|
117
|
+
readonly sent: readonly BroadcastSentRecord[];
|
|
118
|
+
};
|
|
119
|
+
readonly custom: Custom;
|
|
120
|
+
};
|
|
121
|
+
/** Creates an empty TestData, optionally initialising the `custom` field. */
|
|
122
|
+
export declare function newTestData<Custom = {}>(custom?: Custom): TestData<Custom>;
|
|
123
|
+
export type TestInput<State, Params, Custom = {}> = {
|
|
124
|
+
state?: State;
|
|
125
|
+
params?: Params;
|
|
126
|
+
testData?: TestData<Custom>;
|
|
127
|
+
};
|
|
128
|
+
export type Click = {
|
|
129
|
+
type: 'Click';
|
|
130
|
+
selector: QuerySelector;
|
|
131
|
+
};
|
|
132
|
+
/** Simulates a click on the element(s) matching `selector`. */
|
|
133
|
+
export declare function click(selector: QuerySelector): Click;
|
|
134
|
+
export type AdvanceTime = {
|
|
135
|
+
_type: 'AdvanceTime';
|
|
136
|
+
milliseconds: number;
|
|
137
|
+
};
|
|
138
|
+
/** Advances the test scheduler clock by `milliseconds`, firing any scheduled tasks that come due. */
|
|
139
|
+
export declare function advanceTime(milliseconds: number): AdvanceTime;
|
|
140
|
+
export type ReceiveBroadcast = {
|
|
141
|
+
_type: 'ReceiveBroadcast';
|
|
142
|
+
channel: string;
|
|
143
|
+
message: unknown;
|
|
144
|
+
};
|
|
145
|
+
/** Delivers a BroadcastChannel message to any active subscriber on `channel`. */
|
|
146
|
+
export declare function receiveBroadcast(channel: string, message: unknown): ReceiveBroadcast;
|
|
147
|
+
export type FireCustomEvent = {
|
|
148
|
+
_type: 'FireCustomEvent';
|
|
149
|
+
selector: QuerySelector;
|
|
150
|
+
eventName: string;
|
|
151
|
+
detail: unknown;
|
|
152
|
+
};
|
|
153
|
+
/** Dispatches a custom DOM event on the element matching `selector`, invoking any `onEvent` handler. */
|
|
154
|
+
export declare function fireCustomEvent(selector: QuerySelector, eventName: string, detail?: unknown): FireCustomEvent;
|
|
155
|
+
export type Submit = {
|
|
156
|
+
_type: 'Submit';
|
|
157
|
+
selector: QuerySelector;
|
|
158
|
+
};
|
|
159
|
+
/** Simulates a form submit event on the element(s) matching `selector`. */
|
|
160
|
+
export declare function submit(selector: QuerySelector): Submit;
|
|
161
|
+
export type TextInput = {
|
|
162
|
+
_type: 'TextInput';
|
|
163
|
+
selector: QuerySelector;
|
|
164
|
+
value: string;
|
|
165
|
+
};
|
|
166
|
+
/** Simulates an `input` event on the element(s) matching `selector`. */
|
|
167
|
+
export declare function textInput(selector: QuerySelector, value: string): TextInput;
|
|
168
|
+
/** Creates an attribute object `{ name, value }` for use with `findOne(...).attrs.toContainEqual(attr(...))`. */
|
|
169
|
+
export declare function attr(name: string, value: string): {
|
|
170
|
+
name: string;
|
|
171
|
+
value: string;
|
|
172
|
+
};
|
|
173
|
+
export type Interaction = Click | AdvanceTime | ReceiveBroadcast | FireCustomEvent | Submit | TextInput;
|
|
174
|
+
export type { NonEmptyArray };
|
|
175
|
+
export type DomElement = {
|
|
176
|
+
readonly tag: string;
|
|
177
|
+
readonly attrs: readonly Attr[];
|
|
178
|
+
readonly childNodes: readonly DomNode[];
|
|
179
|
+
};
|
|
180
|
+
export type DomNode = DomElement | string;
|
|
181
|
+
export type TestableDom = {
|
|
182
|
+
head: DomElement;
|
|
183
|
+
body: DomElement;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* The result of mounting a component for testing. Supports running interactions
|
|
187
|
+
* and querying the virtual DOM. Each call to `run` returns a new
|
|
188
|
+
* `TestableComponent` reflecting the state after those interactions, so tests
|
|
189
|
+
* can chain calls to build up complex scenarios step by step.
|
|
190
|
+
*/
|
|
191
|
+
export type TestableComponent<State, Params, Event, Custom = {}> = {
|
|
192
|
+
readonly config: TestConfig;
|
|
193
|
+
readonly state: State;
|
|
194
|
+
readonly data: TestData<Custom>;
|
|
195
|
+
/** Returns a copy with the given TestConfig. */
|
|
196
|
+
withConfig(config: TestConfig): TestableComponent<State, Params, Event, Custom>;
|
|
197
|
+
/** Returns a copy with the given TestData as the starting data. */
|
|
198
|
+
withData(data: TestData<Custom>): TestableComponent<State, Params, Event, Custom>;
|
|
199
|
+
readonly dom: TestableDom;
|
|
200
|
+
/**
|
|
201
|
+
* Applies one or more interactions in order and returns a new
|
|
202
|
+
* `TestableComponent` reflecting the resulting state and DOM. The original
|
|
203
|
+
* instance is unchanged, so you can branch from the same starting point to
|
|
204
|
+
* test different sequences.
|
|
205
|
+
*/
|
|
206
|
+
run(...interactions: Interaction[]): TestableComponent<State, Params, Event, Custom>;
|
|
207
|
+
/** Returns all elements matching `selector`. */
|
|
208
|
+
find(selector: string): readonly DomElement[];
|
|
209
|
+
/** Returns the single element matching `selector`. Throws if not exactly one match. */
|
|
210
|
+
findOne(selector: string): DomElement;
|
|
211
|
+
/** Returns all elements matching `selector`. Throws if no match. */
|
|
212
|
+
findOneOrMore(selector: string): NonEmptyArray<DomElement>;
|
|
213
|
+
/** Returns the element matching `selector`, or undefined. */
|
|
214
|
+
findMaybeOne(selector: string): DomElement | undefined;
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* Creates a testable wrapper around a `Component`. Use this when testing a
|
|
218
|
+
* component that was created with `component()`. For testing a top-level view
|
|
219
|
+
* function directly, use `testApplication` instead.
|
|
220
|
+
*/
|
|
221
|
+
export declare function testComponent<State, Params, Event, Custom = {}>(component: Component<State, Params, Event>, config?: TestConfig, data?: TestData<Custom>): TestableComponent<State, Params, Event, Custom>;
|
|
222
|
+
/**
|
|
223
|
+
* The main entry point for testing a ctrl-fx application. Wraps a view
|
|
224
|
+
* function and initial state into a `TestableComponent`. Call `.run(...)`
|
|
225
|
+
* with interactions to simulate user actions, then inspect `.state`, `.data`,
|
|
226
|
+
* and the `findOne`/`find` DOM query methods on the result.
|
|
227
|
+
*/
|
|
228
|
+
export declare function testApplication<State, Custom = {}>(app: (state: State) => NodeGroup<State, never> | Node<State, never>, initialState: State | Effect<State, never, State>, config?: TestConfig, data?: TestData<Custom>): TestableComponent<State, void, never, Custom>;
|
|
229
|
+
export type ExactlyOne = {
|
|
230
|
+
_type: 'ExactlyOne';
|
|
231
|
+
selector: string;
|
|
232
|
+
};
|
|
233
|
+
export type ZeroOrMore = {
|
|
234
|
+
_type: 'ZeroOrMore';
|
|
235
|
+
selector: string;
|
|
236
|
+
};
|
|
237
|
+
export type ZeroOrOne = {
|
|
238
|
+
_type: 'ZeroOrOne';
|
|
239
|
+
selector: string;
|
|
240
|
+
};
|
|
241
|
+
export type OneOrMore = {
|
|
242
|
+
_type: 'OneOrMore';
|
|
243
|
+
selector: string;
|
|
244
|
+
};
|
|
245
|
+
/** Selects elements matching `selector`; throws during `run` if none are found. */
|
|
246
|
+
export declare function one(selector: string): OneOrMore;
|
|
247
|
+
export type QuerySelector = ExactlyOne | OneOrMore | ZeroOrMore | ZeroOrOne;
|
|
248
|
+
//# sourceMappingURL=testing.d.ts.map
|