@fun-land/fun-web 0.3.2 → 0.5.0-alpha.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 +6 -24
- package/dist/esm/src/dom.d.ts +53 -31
- package/dist/esm/src/dom.js +83 -50
- package/dist/esm/src/dom.js.map +1 -1
- package/dist/esm/src/index.d.ts +1 -1
- package/dist/esm/src/index.js +1 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/tsconfig.publish.tsbuildinfo +1 -1
- package/dist/src/dom.d.ts +53 -31
- package/dist/src/dom.js +86 -55
- package/dist/src/dom.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +2 -4
- package/dist/src/index.js.map +1 -1
- package/dist/tsconfig.publish.tsbuildinfo +1 -1
- package/examples/todo-app/AddTodoForm.ts +4 -4
- package/examples/todo-app/DraggableTodoList.ts +52 -47
- package/examples/todo-app/Todo.ts +7 -7
- package/examples/todo-app/TodoApp.js +94 -51
- package/examples/todo-app/TodoApp.ts +9 -9
- package/package.json +2 -2
- package/src/dom.test.ts +92 -60
- package/src/dom.ts +190 -159
- package/src/index.ts +1 -3
- package/src/types.ts +2 -6
package/README.md
CHANGED
|
@@ -341,43 +341,25 @@ const div = h("div", { id: "app" }, [
|
|
|
341
341
|
- Everything else → property assignment
|
|
342
342
|
|
|
343
343
|
#### bindProperty
|
|
344
|
-
```ts
|
|
345
|
-
<E extends Element, K extends keyof E>(
|
|
346
|
-
el: E,
|
|
347
|
-
key: K,
|
|
348
|
-
fs: FunState<E[K]>,
|
|
349
|
-
signal: AbortSignal
|
|
350
|
-
): E
|
|
351
|
-
```
|
|
352
344
|
|
|
353
|
-
Bind element property to state. Returns
|
|
345
|
+
Bind element property to state. Returns `Enhancer`.
|
|
354
346
|
|
|
355
347
|
```typescript
|
|
356
|
-
|
|
357
|
-
bindProperty(input, "value", state.prop("name"), signal);
|
|
348
|
+
enhance(h("input"), bindProperty(input, "value", state.prop("name"), signal));
|
|
358
349
|
// input.value syncs with state.name
|
|
359
350
|
```
|
|
360
351
|
|
|
361
352
|
#### on
|
|
362
|
-
```ts
|
|
363
|
-
<E extends Element, K extends keyof HTMLElementEventMap>(
|
|
364
|
-
el: E,
|
|
365
|
-
type: K,
|
|
366
|
-
handler: (ev: HTMLElementEventMap[K] & { currentTarget: E }) => void,
|
|
367
|
-
signal: AbortSignal
|
|
368
|
-
): E
|
|
369
|
-
```
|
|
370
353
|
|
|
371
|
-
Add type-safe event listener. Returns
|
|
354
|
+
Add type-safe event listener. Returns `Enhancer`.
|
|
372
355
|
|
|
373
356
|
```typescript
|
|
374
|
-
|
|
375
|
-
// e.currentTarget is typed as HTMLButtonElement
|
|
357
|
+
enhance(h("button"), on("click", (e) => {
|
|
376
358
|
e.currentTarget.disabled = true;
|
|
377
|
-
}, signal);
|
|
359
|
+
}, signal));
|
|
378
360
|
```
|
|
379
361
|
|
|
380
|
-
#### keyedChildren
|
|
362
|
+
#### keyedChildren TODO replace this with bindListChildren
|
|
381
363
|
```ts
|
|
382
364
|
<T extends { key: string }>(
|
|
383
365
|
parent: Element,
|
package/dist/esm/src/dom.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** DOM utilities for functional element creation and manipulation */
|
|
2
2
|
import { type FunState } from "@fun-land/fun-state";
|
|
3
|
-
import type { ElementChild } from "./types";
|
|
3
|
+
import type { Component, ElementChild } from "./types";
|
|
4
|
+
import { Accessor } from "@fun-land/accessor";
|
|
4
5
|
export type Enhancer<El extends Element> = (element: El) => El;
|
|
5
6
|
/**
|
|
6
7
|
* Create an HTML element with attributes and children
|
|
@@ -17,28 +18,36 @@ export type Enhancer<El extends Element> = (element: El) => El;
|
|
|
17
18
|
export declare const h: <Tag extends keyof HTMLElementTagNameMap>(tag: Tag, attrs?: Record<string, any> | null, children?: ElementChild | ElementChild[]) => HTMLElementTagNameMap[Tag];
|
|
18
19
|
/**
|
|
19
20
|
* Set text content of an element (returns element for chaining)
|
|
21
|
+
* @returns {Enhancer}
|
|
20
22
|
*/
|
|
21
23
|
export declare const text: (content: string | number) => <El extends Element>(el: El) => El;
|
|
22
24
|
/**
|
|
23
25
|
* Set an attribute on an element (returns element for chaining)
|
|
26
|
+
* @returns {Enhancer}
|
|
24
27
|
*/
|
|
25
28
|
export declare const attr: (name: string, value: string) => <El extends Element>(el: El) => El;
|
|
26
29
|
/**
|
|
27
30
|
* Set multiple attributes on an element (returns element for chaining)
|
|
28
31
|
*/
|
|
29
32
|
export declare const attrs: (obj: Record<string, string>) => <El extends Element>(el: El) => El;
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
/**
|
|
34
|
+
* update property `key` of element when state updates
|
|
35
|
+
* @returns {Enhancer}
|
|
36
|
+
*/
|
|
37
|
+
export declare const bindProperty: <E extends Element, K extends keyof E & string>(key: K, state: FunState<E[K]>, signal: AbortSignal) => (el: E) => E;
|
|
32
38
|
/**
|
|
33
39
|
* Add CSS classes to an element (returns element for chaining)
|
|
40
|
+
* @returns {Enhancer}
|
|
34
41
|
*/
|
|
35
42
|
export declare const addClass: (...classes: string[]) => <El extends Element>(el: El) => El;
|
|
36
43
|
/**
|
|
37
44
|
* Remove CSS classes from an element (returns element for chaining)
|
|
45
|
+
* @returns {Enhancer}
|
|
38
46
|
*/
|
|
39
47
|
export declare const removeClass: (...classes: string[]) => <El extends Element>(el: El) => El;
|
|
40
48
|
/**
|
|
41
49
|
* Toggle a CSS class on an element (returns element for chaining)
|
|
50
|
+
* @returns {Enhancer}
|
|
42
51
|
*/
|
|
43
52
|
export declare const toggleClass: (className: string, force?: boolean) => (el: Element) => Element;
|
|
44
53
|
/**
|
|
@@ -49,24 +58,15 @@ export declare const append: (...children: Element[]) => <El extends Element>(el
|
|
|
49
58
|
/**
|
|
50
59
|
* Add event listener with required AbortSignal (returns element for chaining)
|
|
51
60
|
* Signal is required to prevent forgetting cleanup
|
|
61
|
+
* @returns {Enhancer}
|
|
52
62
|
*/
|
|
53
|
-
export declare const on: <E extends Element, K extends keyof HTMLElementEventMap>(
|
|
54
|
-
currentTarget: E;
|
|
55
|
-
}) => void, signal: AbortSignal) => E;
|
|
56
|
-
/** Enhancer version of `on()` */
|
|
57
|
-
export declare const onTo: <E extends Element, K extends keyof HTMLElementEventMap>(type: K, handler: (ev: HTMLElementEventMap[K] & {
|
|
63
|
+
export declare const on: <E extends Element, K extends keyof HTMLElementEventMap>(type: K, handler: (ev: HTMLElementEventMap[K] & {
|
|
58
64
|
currentTarget: E;
|
|
59
65
|
}) => void, signal: AbortSignal) => (el: E) => E;
|
|
60
66
|
/**
|
|
61
67
|
* Apply enhancers to an HTMLElement.
|
|
62
68
|
*/
|
|
63
69
|
export declare const enhance: <El extends Element>(x: El, ...fns: Array<Enhancer<El>>) => El;
|
|
64
|
-
/**
|
|
65
|
-
*
|
|
66
|
-
*/
|
|
67
|
-
type Keyed = {
|
|
68
|
-
key: string;
|
|
69
|
-
};
|
|
70
70
|
export type KeyedChildren = {
|
|
71
71
|
/** Reconcile DOM children to match current list state */
|
|
72
72
|
reconcile: () => void;
|
|
@@ -74,29 +74,51 @@ export type KeyedChildren = {
|
|
|
74
74
|
dispose: () => void;
|
|
75
75
|
};
|
|
76
76
|
/**
|
|
77
|
-
* Keep
|
|
78
|
-
*
|
|
79
|
-
* - No VDOM
|
|
80
|
-
* - Preserves existing row elements across updates
|
|
81
|
-
* - Creates one AbortController per row (cleaned up on removal or parent abort)
|
|
82
|
-
* - Reorders by DOM moves (appendChild)
|
|
83
|
-
* - Only remounts if order changes
|
|
77
|
+
* Keep an element's children in sync with a FunState<T[]> by stable identity.
|
|
78
|
+
* Cleanup is driven by `signal` abort (no handle returned).
|
|
84
79
|
*/
|
|
85
|
-
export declare
|
|
80
|
+
export declare const bindListChildren: <T>(options: {
|
|
86
81
|
signal: AbortSignal;
|
|
87
|
-
state: FunState<T>;
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
state: FunState<T[]>;
|
|
83
|
+
key: Accessor<T, string>;
|
|
84
|
+
row: (args: {
|
|
85
|
+
signal: AbortSignal;
|
|
86
|
+
state: FunState<T>;
|
|
87
|
+
remove: () => void;
|
|
88
|
+
}) => Element;
|
|
89
|
+
}) => <El extends Element>(parent: El) => El;
|
|
90
90
|
/**
|
|
91
|
-
* Conditionally render a component based on
|
|
92
|
-
* Returns a container element that mounts/unmounts the component as the
|
|
91
|
+
* Conditionally render a component based on state and an optional predicate.
|
|
92
|
+
* Returns a container element that mounts/unmounts the component as the condition changes.
|
|
93
93
|
*
|
|
94
94
|
* @example
|
|
95
|
-
*
|
|
96
|
-
* const
|
|
95
|
+
* // With boolean state
|
|
96
|
+
* const showDetails = funState(false);
|
|
97
|
+
* const detailsEl = renderWhen({
|
|
98
|
+
* state: showDetails,
|
|
99
|
+
* component: DetailsComponent,
|
|
100
|
+
* props: {id: 123},
|
|
101
|
+
* signal
|
|
102
|
+
* });
|
|
97
103
|
* parent.appendChild(detailsEl);
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* // With predicate
|
|
107
|
+
* const rollType = funState(RollType.action);
|
|
108
|
+
* const actionEl = renderWhen({
|
|
109
|
+
* state: rollType,
|
|
110
|
+
* predicate: (type) => type === RollType.action,
|
|
111
|
+
* component: ActionForm,
|
|
112
|
+
* props: {roll, uid},
|
|
113
|
+
* signal
|
|
114
|
+
* });
|
|
98
115
|
*/
|
|
99
|
-
export declare function renderWhen<Props>(
|
|
116
|
+
export declare function renderWhen<State, Props>(options: {
|
|
117
|
+
state: FunState<State>;
|
|
118
|
+
predicate?: (value: State) => boolean;
|
|
119
|
+
component: Component<Props>;
|
|
120
|
+
props: Props;
|
|
121
|
+
signal: AbortSignal;
|
|
122
|
+
}): Element;
|
|
100
123
|
export declare const $: <T extends Element>(selector: string) => T | undefined;
|
|
101
124
|
export declare const $$: <T extends Element>(selector: string) => T[];
|
|
102
|
-
export {};
|
package/dist/esm/src/dom.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { filter } from "@fun-land/accessor";
|
|
2
1
|
/**
|
|
3
2
|
* Create an HTML element with attributes and children
|
|
4
3
|
*
|
|
@@ -39,16 +38,17 @@ attrs, children) => {
|
|
|
39
38
|
}
|
|
40
39
|
// Append children
|
|
41
40
|
if (children != null) {
|
|
42
|
-
appendChildren(
|
|
41
|
+
appendChildren(children)(element);
|
|
43
42
|
}
|
|
44
43
|
return element;
|
|
45
44
|
};
|
|
46
45
|
/**
|
|
47
46
|
* Append children to an element, flattening arrays and converting primitives to text nodes
|
|
47
|
+
* @returns {Enhancer}
|
|
48
48
|
*/
|
|
49
|
-
const appendChildren = (
|
|
49
|
+
const appendChildren = (children) => (parent) => {
|
|
50
50
|
if (Array.isArray(children)) {
|
|
51
|
-
children.forEach((child) => appendChildren(
|
|
51
|
+
children.forEach((child) => appendChildren(child)(parent));
|
|
52
52
|
}
|
|
53
53
|
else if (children != null) {
|
|
54
54
|
if (typeof children === "string" || typeof children === "number") {
|
|
@@ -58,23 +58,24 @@ const appendChildren = (parent, children) => {
|
|
|
58
58
|
parent.appendChild(children);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
+
return parent;
|
|
61
62
|
};
|
|
62
63
|
/**
|
|
63
64
|
* Set text content of an element (returns element for chaining)
|
|
65
|
+
* @returns {Enhancer}
|
|
64
66
|
*/
|
|
65
67
|
export const text = (content) => (el) => {
|
|
66
68
|
el.textContent = String(content);
|
|
67
69
|
return el;
|
|
68
70
|
};
|
|
69
|
-
;
|
|
70
71
|
/**
|
|
71
72
|
* Set an attribute on an element (returns element for chaining)
|
|
73
|
+
* @returns {Enhancer}
|
|
72
74
|
*/
|
|
73
75
|
export const attr = (name, value) => (el) => {
|
|
74
76
|
el.setAttribute(name, value);
|
|
75
77
|
return el;
|
|
76
78
|
};
|
|
77
|
-
;
|
|
78
79
|
/**
|
|
79
80
|
* Set multiple attributes on an element (returns element for chaining)
|
|
80
81
|
*/
|
|
@@ -84,35 +85,38 @@ export const attrs = (obj) => (el) => {
|
|
|
84
85
|
});
|
|
85
86
|
return el;
|
|
86
87
|
};
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
/**
|
|
89
|
+
* update property `key` of element when state updates
|
|
90
|
+
* @returns {Enhancer}
|
|
91
|
+
*/
|
|
92
|
+
export const bindProperty = (key, state, signal) => (el) => {
|
|
89
93
|
// initial sync
|
|
90
|
-
el[key] =
|
|
94
|
+
el[key] = state.get();
|
|
91
95
|
// reactive sync
|
|
92
|
-
|
|
96
|
+
state.watch(signal, (v) => {
|
|
93
97
|
el[key] = v;
|
|
94
98
|
});
|
|
95
99
|
return el;
|
|
96
|
-
}
|
|
97
|
-
export const bindPropertyTo = (key, state, signal) => (el) => bindProperty(el, key, state, signal);
|
|
100
|
+
};
|
|
98
101
|
/**
|
|
99
102
|
* Add CSS classes to an element (returns element for chaining)
|
|
103
|
+
* @returns {Enhancer}
|
|
100
104
|
*/
|
|
101
105
|
export const addClass = (...classes) => (el) => {
|
|
102
106
|
el.classList.add(...classes);
|
|
103
107
|
return el;
|
|
104
108
|
};
|
|
105
|
-
;
|
|
106
109
|
/**
|
|
107
110
|
* Remove CSS classes from an element (returns element for chaining)
|
|
111
|
+
* @returns {Enhancer}
|
|
108
112
|
*/
|
|
109
113
|
export const removeClass = (...classes) => (el) => {
|
|
110
114
|
el.classList.remove(...classes);
|
|
111
115
|
return el;
|
|
112
116
|
};
|
|
113
|
-
;
|
|
114
117
|
/**
|
|
115
118
|
* Toggle a CSS class on an element (returns element for chaining)
|
|
119
|
+
* @returns {Enhancer}
|
|
116
120
|
*/
|
|
117
121
|
export const toggleClass = (className, force) => (el) => {
|
|
118
122
|
el.classList.toggle(className, force);
|
|
@@ -126,37 +130,52 @@ export const append = (...children) => (el) => {
|
|
|
126
130
|
children.forEach((child) => el.appendChild(child));
|
|
127
131
|
return el;
|
|
128
132
|
};
|
|
129
|
-
;
|
|
130
133
|
/**
|
|
131
134
|
* Add event listener with required AbortSignal (returns element for chaining)
|
|
132
135
|
* Signal is required to prevent forgetting cleanup
|
|
136
|
+
* @returns {Enhancer}
|
|
133
137
|
*/
|
|
134
|
-
export const on = (
|
|
138
|
+
export const on = (type, handler, signal) => (el) => {
|
|
135
139
|
el.addEventListener(type, handler, { signal });
|
|
136
140
|
return el;
|
|
137
141
|
};
|
|
138
|
-
/** Enhancer version of `on()` */
|
|
139
|
-
export const onTo = (type, handler, signal) => (el) => on(el, type, handler, signal);
|
|
140
142
|
/**
|
|
141
143
|
* Apply enhancers to an HTMLElement.
|
|
142
144
|
*/
|
|
143
145
|
export const enhance = (x, ...fns) => fns.reduce((acc, fn) => fn(acc), x);
|
|
146
|
+
const keyOf = (keyAcc, item) => {
|
|
147
|
+
const k = keyAcc.query(item)[0];
|
|
148
|
+
if (k == null)
|
|
149
|
+
throw new Error("bindListChildren: key accessor returned no value");
|
|
150
|
+
return k;
|
|
151
|
+
};
|
|
152
|
+
const byKey = (keyAcc, key) => ({
|
|
153
|
+
query: (xs) => {
|
|
154
|
+
const hit = xs.find((t) => keyOf(keyAcc, t) === key);
|
|
155
|
+
return hit ? [hit] : [];
|
|
156
|
+
},
|
|
157
|
+
mod: (f) => (xs) => {
|
|
158
|
+
let found = false;
|
|
159
|
+
return xs.map((t) => {
|
|
160
|
+
if (keyOf(keyAcc, t) !== key)
|
|
161
|
+
return t;
|
|
162
|
+
if (found)
|
|
163
|
+
throw new Error(`bindListChildren: duplicate key "${key}"`);
|
|
164
|
+
found = true;
|
|
165
|
+
return f(t);
|
|
166
|
+
});
|
|
167
|
+
},
|
|
168
|
+
});
|
|
144
169
|
/**
|
|
145
|
-
* Keep
|
|
146
|
-
*
|
|
147
|
-
* - No VDOM
|
|
148
|
-
* - Preserves existing row elements across updates
|
|
149
|
-
* - Creates one AbortController per row (cleaned up on removal or parent abort)
|
|
150
|
-
* - Reorders by DOM moves (appendChild)
|
|
151
|
-
* - Only remounts if order changes
|
|
170
|
+
* Keep an element's children in sync with a FunState<T[]> by stable identity.
|
|
171
|
+
* Cleanup is driven by `signal` abort (no handle returned).
|
|
152
172
|
*/
|
|
153
|
-
export
|
|
173
|
+
export const bindListChildren = (options) => (parent) => {
|
|
174
|
+
const { signal, state: list, key: keyAcc, row: renderRow } = options;
|
|
154
175
|
const rows = new Map();
|
|
155
176
|
const dispose = () => {
|
|
156
177
|
for (const row of rows.values()) {
|
|
157
|
-
// Abort first so listeners/subscriptions clean up
|
|
158
178
|
row.ctrl.abort();
|
|
159
|
-
// Remove from DOM (safe even if already removed)
|
|
160
179
|
row.el.remove();
|
|
161
180
|
}
|
|
162
181
|
rows.clear();
|
|
@@ -166,13 +185,13 @@ export function keyedChildren(parent, signal, list, renderRow) {
|
|
|
166
185
|
const nextKeys = [];
|
|
167
186
|
const seen = new Set();
|
|
168
187
|
for (const it of items) {
|
|
169
|
-
const k = it
|
|
188
|
+
const k = keyOf(keyAcc, it);
|
|
170
189
|
if (seen.has(k))
|
|
171
|
-
throw new Error(`
|
|
190
|
+
throw new Error(`bindListChildren: duplicate key "${k}"`);
|
|
172
191
|
seen.add(k);
|
|
173
192
|
nextKeys.push(k);
|
|
174
193
|
}
|
|
175
|
-
//
|
|
194
|
+
// remove missing
|
|
176
195
|
for (const [k, row] of rows) {
|
|
177
196
|
if (!seen.has(k)) {
|
|
178
197
|
row.ctrl.abort();
|
|
@@ -180,58 +199,72 @@ export function keyedChildren(parent, signal, list, renderRow) {
|
|
|
180
199
|
rows.delete(k);
|
|
181
200
|
}
|
|
182
201
|
}
|
|
183
|
-
//
|
|
202
|
+
// ensure present
|
|
184
203
|
for (const k of nextKeys) {
|
|
185
204
|
if (!rows.has(k)) {
|
|
186
205
|
const ctrl = new AbortController();
|
|
187
|
-
const itemState = list.focus(
|
|
206
|
+
const itemState = list.focus(byKey(keyAcc, k));
|
|
188
207
|
const el = renderRow({
|
|
189
208
|
signal: ctrl.signal,
|
|
190
209
|
state: itemState,
|
|
191
|
-
remove: () => list.mod((
|
|
210
|
+
remove: () => list.mod((xs) => xs.filter((t) => keyOf(keyAcc, t) !== k)),
|
|
192
211
|
});
|
|
193
|
-
rows.set(k, {
|
|
212
|
+
rows.set(k, { el, ctrl });
|
|
194
213
|
}
|
|
195
214
|
}
|
|
196
|
-
//
|
|
215
|
+
// reorder with minimal DOM moves
|
|
197
216
|
const children = parent.children; // live
|
|
198
217
|
for (let i = 0; i < nextKeys.length; i++) {
|
|
199
218
|
const k = nextKeys[i];
|
|
200
219
|
const row = rows.get(k);
|
|
201
220
|
const currentAtI = children[i];
|
|
202
|
-
if (currentAtI !== row.el)
|
|
221
|
+
if (currentAtI !== row.el)
|
|
203
222
|
parent.insertBefore(row.el, currentAtI !== null && currentAtI !== void 0 ? currentAtI : null);
|
|
204
|
-
}
|
|
205
223
|
}
|
|
206
224
|
};
|
|
207
|
-
// Reconcile whenever the list changes; `subscribe` will unsubscribe on abort (per your fix).
|
|
208
225
|
list.watch(signal, reconcile);
|
|
209
|
-
// Ensure all children clean up when parent aborts
|
|
210
226
|
signal.addEventListener("abort", dispose, { once: true });
|
|
211
|
-
// Initial mount
|
|
212
227
|
reconcile();
|
|
213
|
-
return
|
|
214
|
-
}
|
|
228
|
+
return parent;
|
|
229
|
+
};
|
|
215
230
|
/**
|
|
216
|
-
* Conditionally render a component based on
|
|
217
|
-
* Returns a container element that mounts/unmounts the component as the
|
|
231
|
+
* Conditionally render a component based on state and an optional predicate.
|
|
232
|
+
* Returns a container element that mounts/unmounts the component as the condition changes.
|
|
218
233
|
*
|
|
219
234
|
* @example
|
|
220
|
-
*
|
|
221
|
-
* const
|
|
235
|
+
* // With boolean state
|
|
236
|
+
* const showDetails = funState(false);
|
|
237
|
+
* const detailsEl = renderWhen({
|
|
238
|
+
* state: showDetails,
|
|
239
|
+
* component: DetailsComponent,
|
|
240
|
+
* props: {id: 123},
|
|
241
|
+
* signal
|
|
242
|
+
* });
|
|
222
243
|
* parent.appendChild(detailsEl);
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* // With predicate
|
|
247
|
+
* const rollType = funState(RollType.action);
|
|
248
|
+
* const actionEl = renderWhen({
|
|
249
|
+
* state: rollType,
|
|
250
|
+
* predicate: (type) => type === RollType.action,
|
|
251
|
+
* component: ActionForm,
|
|
252
|
+
* props: {roll, uid},
|
|
253
|
+
* signal
|
|
254
|
+
* });
|
|
223
255
|
*/
|
|
224
|
-
export function renderWhen(
|
|
256
|
+
export function renderWhen(options) {
|
|
257
|
+
const { state, predicate = (x) => x, component, props, signal, } = options;
|
|
225
258
|
const container = document.createElement("span");
|
|
226
259
|
container.style.display = "contents";
|
|
227
260
|
let childCtrl = null;
|
|
228
261
|
let childEl = null;
|
|
229
262
|
const reconcile = () => {
|
|
230
|
-
const shouldRender = state.get();
|
|
263
|
+
const shouldRender = predicate(state.get());
|
|
231
264
|
if (shouldRender && !childEl) {
|
|
232
265
|
// Mount the component
|
|
233
266
|
childCtrl = new AbortController();
|
|
234
|
-
childEl =
|
|
267
|
+
childEl = component(childCtrl.signal, props);
|
|
235
268
|
container.appendChild(childEl);
|
|
236
269
|
}
|
|
237
270
|
else if (!shouldRender && childEl) {
|
package/dist/esm/src/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../../src/dom.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../../src/dom.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/src/index.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ export type { FunState } from "./state";
|
|
|
3
3
|
export type { MountedComponent } from "./mount";
|
|
4
4
|
export type { KeyedChildren } from "./dom";
|
|
5
5
|
export { funState } from "./state";
|
|
6
|
-
export { h, text, attr, attrs, addClass, removeClass, toggleClass, append, on,
|
|
6
|
+
export { h, text, attr, attrs, addClass, removeClass, toggleClass, append, on, bindProperty, bindListChildren, renderWhen, enhance, $, $$, } from "./dom";
|
|
7
7
|
export { mount } from "./mount";
|
package/dist/esm/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @fun-land/fun-web - Web component library for fun-land
|
|
2
2
|
export { funState } from "./state";
|
|
3
|
-
export { h, text, attr, attrs, addClass, removeClass, toggleClass, append, on,
|
|
3
|
+
export { h, text, attr, attrs, addClass, removeClass, toggleClass, append, on, bindProperty, bindListChildren, renderWhen, enhance, $, $$, } from "./dom";
|
|
4
4
|
export { mount } from "./mount";
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAOzD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EACL,CAAC,EACD,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,WAAW,EACX,WAAW,EACX,MAAM,EACN,EAAE,EACF,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAOzD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EACL,CAAC,EACD,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,WAAW,EACX,WAAW,EACX,MAAM,EACN,EAAE,EACF,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,CAAC,EACD,EAAE,GACH,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
|