foldkit 0.133.0 → 0.135.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 +13 -17
- package/dist/canvas/view.d.ts +18 -11
- package/dist/canvas/view.d.ts.map +1 -1
- package/dist/canvas/view.js +18 -11
- package/dist/customElement/index.d.ts +12 -6
- package/dist/customElement/index.d.ts.map +1 -1
- package/dist/customElement/index.js +17 -4
- package/dist/html/index.d.ts +625 -1601
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +52 -15
- package/dist/html/public.d.ts +2 -2
- package/dist/html/public.d.ts.map +1 -1
- package/dist/html/public.js +1 -1
- package/dist/html/runtimeSingleton.d.ts +1 -1
- package/dist/html/runtimeSingleton.d.ts.map +1 -1
- package/dist/html/runtimeSingleton.js +1 -1
- package/dist/html/submodel.d.ts +51 -19
- package/dist/html/submodel.d.ts.map +1 -1
- package/dist/html/submodel.js +37 -13
- package/dist/managedResource/managedResource.d.ts +21 -10
- package/dist/managedResource/managedResource.d.ts.map +1 -1
- package/dist/managedResource/managedResource.js +6 -1
- package/dist/runtime/crashUI.d.ts.map +1 -1
- package/dist/runtime/crashUI.js +29 -30
- package/dist/runtime/runtime.d.ts +9 -6
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +9 -8
- package/dist/test/apps/attributes.d.ts +2 -2
- package/dist/test/apps/attributes.d.ts.map +1 -1
- package/dist/test/apps/attributes.js +1 -3
- package/dist/test/apps/bubbling.d.ts +2 -2
- package/dist/test/apps/bubbling.d.ts.map +1 -1
- package/dist/test/apps/bubbling.js +1 -3
- package/dist/test/apps/colorPicker.d.ts +28 -0
- package/dist/test/apps/colorPicker.d.ts.map +1 -0
- package/dist/test/apps/colorPicker.js +43 -0
- package/dist/test/apps/counter.d.ts +5 -3
- package/dist/test/apps/counter.d.ts.map +1 -1
- package/dist/test/apps/counter.js +12 -7
- package/dist/test/apps/crashOnRender.d.ts +2 -2
- package/dist/test/apps/crashOnRender.d.ts.map +1 -1
- package/dist/test/apps/crashOnRender.js +1 -3
- package/dist/test/apps/drafts.d.ts +2 -2
- package/dist/test/apps/drafts.d.ts.map +1 -1
- package/dist/test/apps/drafts.js +1 -3
- package/dist/test/apps/feedSocket.d.ts +74 -0
- package/dist/test/apps/feedSocket.d.ts.map +1 -0
- package/dist/test/apps/feedSocket.js +69 -0
- package/dist/test/apps/fileUpload.d.ts +2 -2
- package/dist/test/apps/fileUpload.d.ts.map +1 -1
- package/dist/test/apps/fileUpload.js +1 -3
- package/dist/test/apps/interactions.d.ts +2 -2
- package/dist/test/apps/interactions.d.ts.map +1 -1
- package/dist/test/apps/interactions.js +1 -3
- package/dist/test/apps/keypress.d.ts +2 -2
- package/dist/test/apps/keypress.d.ts.map +1 -1
- package/dist/test/apps/keypress.js +1 -3
- package/dist/test/apps/login.d.ts +2 -2
- package/dist/test/apps/login.d.ts.map +1 -1
- package/dist/test/apps/login.js +1 -3
- package/dist/test/apps/logoutButton.d.ts +2 -2
- package/dist/test/apps/logoutButton.d.ts.map +1 -1
- package/dist/test/apps/logoutButton.js +1 -3
- package/dist/test/apps/mountPanel.d.ts +4 -4
- package/dist/test/apps/mountPanel.d.ts.map +1 -1
- package/dist/test/apps/mountPanel.js +3 -7
- package/dist/test/apps/multiRole.d.ts +2 -2
- package/dist/test/apps/multiRole.d.ts.map +1 -1
- package/dist/test/apps/multiRole.js +1 -3
- package/dist/test/apps/pointer.d.ts +2 -2
- package/dist/test/apps/pointer.d.ts.map +1 -1
- package/dist/test/apps/pointer.js +1 -3
- package/dist/test/apps/resumeUpload.d.ts +2 -2
- package/dist/test/apps/resumeUpload.d.ts.map +1 -1
- package/dist/test/apps/resumeUpload.js +3 -6
- package/dist/test/apps/scorePanel.d.ts +32 -0
- package/dist/test/apps/scorePanel.d.ts.map +1 -0
- package/dist/test/apps/scorePanel.js +19 -0
- package/dist/test/apps/uploads.d.ts +2 -2
- package/dist/test/apps/uploads.d.ts.map +1 -1
- package/dist/test/apps/uploads.js +1 -3
- package/dist/test/scene.d.ts +81 -9
- package/dist/test/scene.d.ts.map +1 -1
- package/dist/test/scene.js +206 -26
- package/dist/test/story.d.ts +4 -5
- package/dist/test/story.d.ts.map +1 -1
- package/dist/test/story.js +1 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ A complete Foldkit program. State lives in a single Model, events become Message
|
|
|
41
41
|
// src/main.ts
|
|
42
42
|
import { Match as M, Schema as S } from 'effect'
|
|
43
43
|
import { Command, Runtime } from 'foldkit'
|
|
44
|
-
import { Document,
|
|
44
|
+
import { Document, HtmlBuilder } from 'foldkit/html'
|
|
45
45
|
import { m } from 'foldkit/message'
|
|
46
46
|
|
|
47
47
|
// MODEL
|
|
@@ -88,22 +88,18 @@ export const init: Runtime.ApplicationInit<Model, Message> = () => [
|
|
|
88
88
|
|
|
89
89
|
// VIEW
|
|
90
90
|
|
|
91
|
-
export const view = (model: Model): Document => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
[],
|
|
98
|
-
[
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
],
|
|
104
|
-
),
|
|
105
|
-
}
|
|
106
|
-
}
|
|
91
|
+
export const view = (model: Model, h: HtmlBuilder<Message>): Document => ({
|
|
92
|
+
title: `Counter: ${model.count}`,
|
|
93
|
+
body: h.div(
|
|
94
|
+
[],
|
|
95
|
+
[
|
|
96
|
+
h.p([], [model.count.toString()]),
|
|
97
|
+
h.button([h.OnClick(ClickedDecrement())], ['-']),
|
|
98
|
+
h.button([h.OnClick(ClickedReset())], ['Reset']),
|
|
99
|
+
h.button([h.OnClick(ClickedIncrement())], ['+']),
|
|
100
|
+
],
|
|
101
|
+
),
|
|
102
|
+
})
|
|
107
103
|
```
|
|
108
104
|
|
|
109
105
|
```ts
|
package/dist/canvas/view.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Html } from '../html/index.js';
|
|
1
|
+
import { type Html, type HtmlBuilder } from '../html/index.js';
|
|
2
2
|
import type { Point, Shape } from './shape.js';
|
|
3
3
|
/**
|
|
4
4
|
* Configuration for `Canvas.view`. Pointer handlers are optional and
|
|
@@ -21,18 +21,25 @@ export type ViewConfig<Message> = Readonly<{
|
|
|
21
21
|
* postpatch hook re-paints on every render. The canvas is a pure function of
|
|
22
22
|
* `shapes`. Same shapes produce the same pixels.
|
|
23
23
|
*
|
|
24
|
+
* The trailing `h` fixes `Message` to the calling view's frame; the pointer
|
|
25
|
+
* handlers dispatch through that frame at fire time, so passing the builder
|
|
26
|
+
* that built the surrounding view is what makes the handler types truthful.
|
|
27
|
+
*
|
|
24
28
|
* @example
|
|
25
29
|
* ```typescript
|
|
26
|
-
* Canvas.view
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* })
|
|
30
|
+
* Canvas.view(
|
|
31
|
+
* {
|
|
32
|
+
* width: 400,
|
|
33
|
+
* height: 300,
|
|
34
|
+
* shapes: [
|
|
35
|
+
* Canvas.Rect({ x: 0, y: 0, width: 400, height: 300, fill: '#000' }),
|
|
36
|
+
* Canvas.Circle({ x: 200, y: 150, radius: 50, fill: '#f0a' }),
|
|
37
|
+
* ],
|
|
38
|
+
* onPointerDown: ({ x, y }) => ClickedCanvas({ x, y }),
|
|
39
|
+
* },
|
|
40
|
+
* h,
|
|
41
|
+
* )
|
|
35
42
|
* ```
|
|
36
43
|
*/
|
|
37
|
-
export declare const view: <Message>(config: ViewConfig<Message>) => Html;
|
|
44
|
+
export declare const view: <Message>(config: ViewConfig<NoInfer<Message>>, _h: HtmlBuilder<Message>) => Html;
|
|
38
45
|
//# sourceMappingURL=view.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/canvas/view.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/canvas/view.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,IAAI,EACT,KAAK,WAAW,EAEjB,MAAM,kBAAkB,CAAA;AAIzB,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;GAKG;AACH,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,aAAa,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,SAAS,CAAA;IACvD,aAAa,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,SAAS,CAAA;IACvD,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,SAAS,CAAA;CACtD,CAAC,CAAA;AA8BF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,EAC1B,QAAQ,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EACpC,IAAI,WAAW,CAAC,OAAO,CAAC,KACvB,IAwEF,CAAA"}
|
package/dist/canvas/view.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Array, Predicate, Record, String, pipe } from 'effect';
|
|
2
|
-
import { __requireDispatch } from '../html/index.js';
|
|
2
|
+
import { __requireDispatch, } from '../html/index.js';
|
|
3
3
|
import { h } from '../snabbdom/index.js';
|
|
4
4
|
import { paintScene } from './paint.js';
|
|
5
5
|
/**
|
|
@@ -24,20 +24,27 @@ const classesFromClassName = (className) => pipe(className, String.split(/\s+/),
|
|
|
24
24
|
* postpatch hook re-paints on every render. The canvas is a pure function of
|
|
25
25
|
* `shapes`. Same shapes produce the same pixels.
|
|
26
26
|
*
|
|
27
|
+
* The trailing `h` fixes `Message` to the calling view's frame; the pointer
|
|
28
|
+
* handlers dispatch through that frame at fire time, so passing the builder
|
|
29
|
+
* that built the surrounding view is what makes the handler types truthful.
|
|
30
|
+
*
|
|
27
31
|
* @example
|
|
28
32
|
* ```typescript
|
|
29
|
-
* Canvas.view
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* })
|
|
33
|
+
* Canvas.view(
|
|
34
|
+
* {
|
|
35
|
+
* width: 400,
|
|
36
|
+
* height: 300,
|
|
37
|
+
* shapes: [
|
|
38
|
+
* Canvas.Rect({ x: 0, y: 0, width: 400, height: 300, fill: '#000' }),
|
|
39
|
+
* Canvas.Circle({ x: 200, y: 150, radius: 50, fill: '#f0a' }),
|
|
40
|
+
* ],
|
|
41
|
+
* onPointerDown: ({ x, y }) => ClickedCanvas({ x, y }),
|
|
42
|
+
* },
|
|
43
|
+
* h,
|
|
44
|
+
* )
|
|
38
45
|
* ```
|
|
39
46
|
*/
|
|
40
|
-
export const view = (config) => {
|
|
47
|
+
export const view = (config, _h) => {
|
|
41
48
|
const dispatchSync = __requireDispatch();
|
|
42
49
|
const { width, height, shapes, className, onPointerDown, onPointerMove, onPointerUp, } = config;
|
|
43
50
|
const pointerListener = (toMessage) => (event) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Schema } from 'effect';
|
|
2
|
-
import type { Attribute, Child, Html } from '../html/index.js';
|
|
2
|
+
import type { Attribute, Child, Html, HtmlBuilder } from '../html/index.js';
|
|
3
3
|
/** Type-level kebab-case to PascalCase, used to convert event names like
|
|
4
4
|
* `'change-rating'` into the corresponding factory name `'OnChangeRating'`. */
|
|
5
5
|
type KebabToPascal<S extends string> = S extends `${infer Head}-${infer Tail}` ? `${Capitalize<Head>}${KebabToPascal<Tail>}` : Capitalize<S>;
|
|
@@ -24,19 +24,24 @@ export interface CustomElementConfig<Tag extends string, Properties extends Reco
|
|
|
24
24
|
readonly events: Events;
|
|
25
25
|
}
|
|
26
26
|
/** A defined custom element, untyped on Message at definition time so the
|
|
27
|
-
* spec can be exported and shared across modules. Call `.withMessage
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* spec can be exported and shared across modules. Call `.withMessage(h)`
|
|
28
|
+
* with a view's builder to mint a typed `ElementBuilder` bound to that
|
|
29
|
+
* frame's Message universe. The builder argument is a type witness: it
|
|
30
|
+
* fixes `Message` to the frame the element renders in, so the spec cannot
|
|
31
|
+
* be bound to a Message universe its events will not dispatch into. */
|
|
30
32
|
export interface CustomElementSpec<Tag extends string, Properties extends Record<string, Schema.Top>, Events extends Record<string, Schema.Top>> {
|
|
31
33
|
readonly tag: Tag;
|
|
32
34
|
readonly properties: Properties;
|
|
33
35
|
readonly events: Events;
|
|
34
|
-
readonly withMessage: <Message>() => ElementBuilder<Message, Properties, Events>;
|
|
36
|
+
readonly withMessage: <Message>(h: HtmlBuilder<Message>) => ElementBuilder<Message, Properties, Events>;
|
|
35
37
|
}
|
|
36
38
|
/** The typed builder for a given spec and Message universe. Equivalent to
|
|
37
39
|
* the value `Spec.withMessage<Message>()` returns, expressed as a type
|
|
38
40
|
* consumers can name without reaching for `ReturnType<typeof ...>`. */
|
|
39
41
|
export type Builder<Spec, Message> = Spec extends CustomElementSpec<string, infer Properties, infer Events> ? ElementBuilder<Message, Properties, Events> : never;
|
|
42
|
+
/** @internal Shared with the Scene test helpers so their error messages name
|
|
43
|
+
* the same `On*` factory this module generates. */
|
|
44
|
+
export declare const kebabToPascal: (input: string) => string;
|
|
40
45
|
/**
|
|
41
46
|
* Define a typed binding for a custom element. The returned spec describes
|
|
42
47
|
* the element's properties and events with Schema, and exposes a
|
|
@@ -62,7 +67,8 @@ export type Builder<Spec, Message> = Spec extends CustomElementSpec<string, infe
|
|
|
62
67
|
* },
|
|
63
68
|
* })
|
|
64
69
|
*
|
|
65
|
-
*
|
|
70
|
+
* // Inside a view, with its `h` in scope:
|
|
71
|
+
* const picker = hexColorPicker.withMessage(h)
|
|
66
72
|
*
|
|
67
73
|
* picker(
|
|
68
74
|
* [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/customElement/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,MAAM,EAAgB,MAAM,QAAQ,CAAA;AAEzD,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/customElement/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Array, String, pipe } from 'effect';
|
|
2
2
|
import { OnCustomEvent, Prop, customElement as customElementVNode, } from '../html/index.js';
|
|
3
|
-
|
|
3
|
+
/** @internal Shared with the Scene test helpers so their error messages name
|
|
4
|
+
* the same `On*` factory this module generates. */
|
|
5
|
+
export const kebabToPascal = (input) => pipe(input, String.split('-'), Array.map(String.capitalize), Array.join(''));
|
|
4
6
|
const IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
5
7
|
const isValidPropertyName = (name) => IDENTIFIER_PATTERN.test(name);
|
|
6
8
|
const isValidEventName = (name) => {
|
|
@@ -38,7 +40,8 @@ const eventFactoryName = (eventName) => `On${kebabToPascal(eventName)}`;
|
|
|
38
40
|
* },
|
|
39
41
|
* })
|
|
40
42
|
*
|
|
41
|
-
*
|
|
43
|
+
* // Inside a view, with its `h` in scope:
|
|
44
|
+
* const picker = hexColorPicker.withMessage(h)
|
|
42
45
|
*
|
|
43
46
|
* picker(
|
|
44
47
|
* [
|
|
@@ -53,7 +56,7 @@ export const define = (config) => {
|
|
|
53
56
|
const propertyNames = Object.keys(config.properties);
|
|
54
57
|
const eventNames = Object.keys(config.events);
|
|
55
58
|
validateNames({ tag: config.tag, propertyNames, eventNames });
|
|
56
|
-
const
|
|
59
|
+
const buildElementBuilder = () => {
|
|
57
60
|
const createVNode = customElementVNode()(config.tag);
|
|
58
61
|
const elementFn = (attributes = [], children = []) => createVNode(attributes, children);
|
|
59
62
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
@@ -70,11 +73,21 @@ export const define = (config) => {
|
|
|
70
73
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
71
74
|
return builder;
|
|
72
75
|
};
|
|
76
|
+
// NOTE: `withMessage` is called once per render, so the ElementBuilder is
|
|
77
|
+
// constructed once and retyped per call. Message is erased at runtime: the
|
|
78
|
+
// factories close over nothing Message-specific, exactly like the html
|
|
79
|
+
// builder singleton.
|
|
80
|
+
let cachedElementBuilder;
|
|
81
|
+
const withMessage = (_h) => {
|
|
82
|
+
cachedElementBuilder ??= buildElementBuilder();
|
|
83
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
84
|
+
return cachedElementBuilder;
|
|
85
|
+
};
|
|
73
86
|
return {
|
|
74
87
|
tag: config.tag,
|
|
75
88
|
properties: config.properties,
|
|
76
89
|
events: config.events,
|
|
77
|
-
withMessage
|
|
90
|
+
withMessage,
|
|
78
91
|
};
|
|
79
92
|
};
|
|
80
93
|
const validateNames = (input) => {
|