@fun-land/fun-web 0.2.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.
Files changed (71) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +515 -0
  3. package/coverage/clover.xml +136 -0
  4. package/coverage/coverage-final.json +4 -0
  5. package/coverage/lcov-report/base.css +224 -0
  6. package/coverage/lcov-report/block-navigation.js +87 -0
  7. package/coverage/lcov-report/dom.ts.html +961 -0
  8. package/coverage/lcov-report/favicon.png +0 -0
  9. package/coverage/lcov-report/index.html +146 -0
  10. package/coverage/lcov-report/mount.ts.html +202 -0
  11. package/coverage/lcov-report/prettify.css +1 -0
  12. package/coverage/lcov-report/prettify.js +2 -0
  13. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  14. package/coverage/lcov-report/sorter.js +196 -0
  15. package/coverage/lcov-report/state.ts.html +91 -0
  16. package/coverage/lcov.info +260 -0
  17. package/dist/esm/src/dom.d.ts +85 -0
  18. package/dist/esm/src/dom.js +207 -0
  19. package/dist/esm/src/dom.js.map +1 -0
  20. package/dist/esm/src/index.d.ts +7 -0
  21. package/dist/esm/src/index.js +5 -0
  22. package/dist/esm/src/index.js.map +1 -0
  23. package/dist/esm/src/mount.d.ts +21 -0
  24. package/dist/esm/src/mount.js +27 -0
  25. package/dist/esm/src/mount.js.map +1 -0
  26. package/dist/esm/src/state.d.ts +2 -0
  27. package/dist/esm/src/state.js +3 -0
  28. package/dist/esm/src/state.js.map +1 -0
  29. package/dist/esm/src/types.d.ts +3 -0
  30. package/dist/esm/src/types.js +3 -0
  31. package/dist/esm/src/types.js.map +1 -0
  32. package/dist/esm/tsconfig.publish.tsbuildinfo +1 -0
  33. package/dist/src/dom.d.ts +85 -0
  34. package/dist/src/dom.js +224 -0
  35. package/dist/src/dom.js.map +1 -0
  36. package/dist/src/index.d.ts +7 -0
  37. package/dist/src/index.js +24 -0
  38. package/dist/src/index.js.map +1 -0
  39. package/dist/src/mount.d.ts +21 -0
  40. package/dist/src/mount.js +31 -0
  41. package/dist/src/mount.js.map +1 -0
  42. package/dist/src/state.d.ts +2 -0
  43. package/dist/src/state.js +7 -0
  44. package/dist/src/state.js.map +1 -0
  45. package/dist/src/types.d.ts +3 -0
  46. package/dist/src/types.js +4 -0
  47. package/dist/src/types.js.map +1 -0
  48. package/dist/tsconfig.publish.tsbuildinfo +1 -0
  49. package/eslint.config.js +54 -0
  50. package/examples/README.md +67 -0
  51. package/examples/counter/bundle.js +219 -0
  52. package/examples/counter/counter.ts +112 -0
  53. package/examples/counter/index.html +44 -0
  54. package/examples/todo-app/Todo.ts +79 -0
  55. package/examples/todo-app/index.html +142 -0
  56. package/examples/todo-app/todo-app.ts +120 -0
  57. package/examples/todo-app/todo-bundle.js +410 -0
  58. package/jest.config.js +5 -0
  59. package/package.json +49 -0
  60. package/src/dom.test.ts +768 -0
  61. package/src/dom.ts +296 -0
  62. package/src/index.ts +25 -0
  63. package/src/mount.test.ts +220 -0
  64. package/src/mount.ts +39 -0
  65. package/src/state.test.ts +225 -0
  66. package/src/state.ts +2 -0
  67. package/src/types.ts +9 -0
  68. package/tsconfig.json +16 -0
  69. package/tsconfig.publish.json +6 -0
  70. package/wip/hx-magic-properties-plan.md +575 -0
  71. package/wip/next.md +22 -0
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.$$ = exports.$ = exports.pipeEndo = exports.on = exports.append = exports.toggleClass = exports.removeClass = exports.addClass = exports.attrs = exports.attr = exports.text = exports.h = void 0;
4
+ exports.bindProperty = bindProperty;
5
+ exports.keyedChildren = keyedChildren;
6
+ const accessor_1 = require("@fun-land/accessor");
7
+ /**
8
+ * Create an HTML element with attributes and children
9
+ *
10
+ * Convention:
11
+ * - Properties with dashes (data-*, aria-*) become attributes
12
+ * - Properties starting with 'on' become event listeners
13
+ * - Everything else becomes element properties
14
+ *
15
+ * @example
16
+ * h('button', {className: 'btn', onclick: handler}, 'Click me')
17
+ * h('div', {id: 'app', 'data-test': 'foo'}, [child1, child2])
18
+ */
19
+ const h = (tag,
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ attrs, children) => {
22
+ const element = document.createElement(tag);
23
+ // Apply attributes/properties/events
24
+ if (attrs) {
25
+ for (const [key, value] of Object.entries(attrs)) {
26
+ if (value == null)
27
+ continue;
28
+ if (key.startsWith("on") && typeof value === "function") {
29
+ // Event listener: onclick, onchange, etc.
30
+ const eventName = key.slice(2).toLowerCase();
31
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
32
+ element.addEventListener(eventName, value);
33
+ }
34
+ else if (key.includes("-") || key === "role") {
35
+ // Attribute: data-*, aria-*, role, etc.
36
+ element.setAttribute(key, String(value));
37
+ }
38
+ else {
39
+ // Property: className, id, textContent, etc.
40
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
41
+ element[key] = value;
42
+ }
43
+ }
44
+ }
45
+ // Append children
46
+ if (children != null) {
47
+ appendChildren(element, children);
48
+ }
49
+ return element;
50
+ };
51
+ exports.h = h;
52
+ /**
53
+ * Append children to an element, flattening arrays and converting primitives to text nodes
54
+ */
55
+ const appendChildren = (parent, children) => {
56
+ if (Array.isArray(children)) {
57
+ children.forEach((child) => appendChildren(parent, child));
58
+ }
59
+ else if (children != null) {
60
+ if (typeof children === "string" || typeof children === "number") {
61
+ parent.appendChild(document.createTextNode(String(children)));
62
+ }
63
+ else {
64
+ parent.appendChild(children);
65
+ }
66
+ }
67
+ };
68
+ /**
69
+ * Set text content of an element (returns element for chaining)
70
+ */
71
+ const text = (content) => (el) => {
72
+ el.textContent = String(content);
73
+ return el;
74
+ };
75
+ exports.text = text;
76
+ /**
77
+ * Set an attribute on an element (returns element for chaining)
78
+ */
79
+ const attr = (name, value) => (el) => {
80
+ el.setAttribute(name, value);
81
+ return el;
82
+ };
83
+ exports.attr = attr;
84
+ /**
85
+ * Set multiple attributes on an element (returns element for chaining)
86
+ */
87
+ const attrs = (obj) => (el) => {
88
+ Object.entries(obj).forEach(([name, value]) => {
89
+ el.setAttribute(name, value);
90
+ });
91
+ return el;
92
+ };
93
+ exports.attrs = attrs;
94
+ function bindProperty(el, key, fs, signal) {
95
+ // initial sync
96
+ el[key] = fs.get();
97
+ // reactive sync
98
+ fs.subscribe(signal, (v) => {
99
+ el[key] = v;
100
+ });
101
+ return el;
102
+ }
103
+ /**
104
+ * Add CSS classes to an element (returns element for chaining)
105
+ */
106
+ const addClass = (...classes) => (el) => {
107
+ el.classList.add(...classes);
108
+ return el;
109
+ };
110
+ exports.addClass = addClass;
111
+ /**
112
+ * Remove CSS classes from an element (returns element for chaining)
113
+ */
114
+ const removeClass = (...classes) => (el) => {
115
+ el.classList.remove(...classes);
116
+ return el;
117
+ };
118
+ exports.removeClass = removeClass;
119
+ /**
120
+ * Toggle a CSS class on an element (returns element for chaining)
121
+ */
122
+ const toggleClass = (className, force) => (el) => {
123
+ el.classList.toggle(className, force);
124
+ return el;
125
+ };
126
+ exports.toggleClass = toggleClass;
127
+ /**
128
+ * Append children to an element (returns parent for chaining)
129
+ */
130
+ const append = (...children) => (el) => {
131
+ children.forEach((child) => el.appendChild(child));
132
+ return el;
133
+ };
134
+ exports.append = append;
135
+ /**
136
+ * Add event listener with required AbortSignal (returns element for chaining)
137
+ * Signal is required to prevent forgetting cleanup
138
+ */
139
+ const on = (el, type, handler, signal) => {
140
+ el.addEventListener(type, handler, { signal });
141
+ return el;
142
+ };
143
+ exports.on = on;
144
+ /**
145
+ * Functional composition - apply endomorphic functions (`<T>(x: T) => T`) left to right
146
+ */
147
+ const pipeEndo = (...fns) => (x) => fns.reduce((acc, fn) => fn(acc), x);
148
+ exports.pipeEndo = pipeEndo;
149
+ /**
150
+ * Keep a DOM container's children in sync with a FunState<Array<T>> using stable `t.key`.
151
+ *
152
+ * - No VDOM
153
+ * - Preserves existing row elements across updates
154
+ * - Creates one AbortController per row (cleaned up on removal or parent abort)
155
+ * - Reorders by DOM moves (appendChild)
156
+ * - Only remounts if order changes
157
+ */
158
+ function keyedChildren(parent, signal, list, renderRow) {
159
+ const rows = new Map();
160
+ const dispose = () => {
161
+ for (const row of rows.values()) {
162
+ // Abort first so listeners/subscriptions clean up
163
+ row.ctrl.abort();
164
+ // Remove from DOM (safe even if already removed)
165
+ row.el.remove();
166
+ }
167
+ rows.clear();
168
+ };
169
+ const reconcile = () => {
170
+ const items = list.get();
171
+ const nextKeys = [];
172
+ const seen = new Set();
173
+ for (const it of items) {
174
+ const k = it.key;
175
+ if (seen.has(k))
176
+ throw new Error(`keyedChildren: duplicate key "${k}"`);
177
+ seen.add(k);
178
+ nextKeys.push(k);
179
+ }
180
+ // Remove missing
181
+ for (const [k, row] of rows) {
182
+ if (!seen.has(k)) {
183
+ row.ctrl.abort();
184
+ row.el.remove();
185
+ rows.delete(k);
186
+ }
187
+ }
188
+ // Ensure present
189
+ for (const k of nextKeys) {
190
+ if (!rows.has(k)) {
191
+ const ctrl = new AbortController();
192
+ const itemState = list.focus((0, accessor_1.filter)((t) => t.key === k));
193
+ const el = renderRow({
194
+ signal: ctrl.signal,
195
+ state: itemState,
196
+ remove: () => list.mod((list) => list.filter((t) => t.key !== k)),
197
+ });
198
+ rows.set(k, { key: k, el, ctrl });
199
+ }
200
+ }
201
+ // Reorder with minimal DOM movement (prevents focus loss)
202
+ const children = parent.children; // live
203
+ for (let i = 0; i < nextKeys.length; i++) {
204
+ const k = nextKeys[i];
205
+ const row = rows.get(k);
206
+ const currentAtI = children[i];
207
+ if (currentAtI !== row.el) {
208
+ parent.insertBefore(row.el, currentAtI !== null && currentAtI !== void 0 ? currentAtI : null);
209
+ }
210
+ }
211
+ };
212
+ // Reconcile whenever the list changes; `subscribe` will unsubscribe on abort (per your fix).
213
+ list.subscribe(signal, reconcile);
214
+ // Ensure all children clean up when parent aborts
215
+ signal.addEventListener("abort", dispose, { once: true });
216
+ // Initial mount
217
+ reconcile();
218
+ return { reconcile, dispose };
219
+ }
220
+ const $ = (selector) => { var _a; return (_a = document.querySelector(selector)) !== null && _a !== void 0 ? _a : undefined; };
221
+ exports.$ = $;
222
+ const $$ = (selector) => Array.from(document.querySelectorAll(selector));
223
+ exports.$$ = $$;
224
+ //# sourceMappingURL=dom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/dom.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export type { Component, ElementChild } from "./types";
2
+ export type { FunState } from "./state";
3
+ export type { MountedComponent } from "./mount";
4
+ export type { KeyedChildren } from "./dom";
5
+ export { funState } from "./state";
6
+ export { h, text, attr, attrs, addClass, removeClass, toggleClass, append, on, bindProperty, keyedChildren, pipeEndo, $, $$, } from "./dom";
7
+ export { mount } from "./mount";
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ // @fun-land/fun-web - Web component library for fun-land
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.mount = exports.$$ = exports.$ = exports.pipeEndo = exports.keyedChildren = exports.bindProperty = exports.on = exports.append = exports.toggleClass = exports.removeClass = exports.addClass = exports.attrs = exports.attr = exports.text = exports.h = exports.funState = void 0;
5
+ var state_1 = require("./state");
6
+ Object.defineProperty(exports, "funState", { enumerable: true, get: function () { return state_1.funState; } });
7
+ var dom_1 = require("./dom");
8
+ Object.defineProperty(exports, "h", { enumerable: true, get: function () { return dom_1.h; } });
9
+ Object.defineProperty(exports, "text", { enumerable: true, get: function () { return dom_1.text; } });
10
+ Object.defineProperty(exports, "attr", { enumerable: true, get: function () { return dom_1.attr; } });
11
+ Object.defineProperty(exports, "attrs", { enumerable: true, get: function () { return dom_1.attrs; } });
12
+ Object.defineProperty(exports, "addClass", { enumerable: true, get: function () { return dom_1.addClass; } });
13
+ Object.defineProperty(exports, "removeClass", { enumerable: true, get: function () { return dom_1.removeClass; } });
14
+ Object.defineProperty(exports, "toggleClass", { enumerable: true, get: function () { return dom_1.toggleClass; } });
15
+ Object.defineProperty(exports, "append", { enumerable: true, get: function () { return dom_1.append; } });
16
+ Object.defineProperty(exports, "on", { enumerable: true, get: function () { return dom_1.on; } });
17
+ Object.defineProperty(exports, "bindProperty", { enumerable: true, get: function () { return dom_1.bindProperty; } });
18
+ Object.defineProperty(exports, "keyedChildren", { enumerable: true, get: function () { return dom_1.keyedChildren; } });
19
+ Object.defineProperty(exports, "pipeEndo", { enumerable: true, get: function () { return dom_1.pipeEndo; } });
20
+ Object.defineProperty(exports, "$", { enumerable: true, get: function () { return dom_1.$; } });
21
+ Object.defineProperty(exports, "$$", { enumerable: true, get: function () { return dom_1.$$; } });
22
+ var mount_1 = require("./mount");
23
+ Object.defineProperty(exports, "mount", { enumerable: true, get: function () { return mount_1.mount; } });
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;AAOzD,iCAAmC;AAA1B,iGAAA,QAAQ,OAAA;AACjB,6BAee;AAdb,wFAAA,CAAC,OAAA;AACD,2FAAA,IAAI,OAAA;AACJ,2FAAA,IAAI,OAAA;AACJ,4FAAA,KAAK,OAAA;AACL,+FAAA,QAAQ,OAAA;AACR,kGAAA,WAAW,OAAA;AACX,kGAAA,WAAW,OAAA;AACX,6FAAA,MAAM,OAAA;AACN,yFAAA,EAAE,OAAA;AACF,mGAAA,YAAY,OAAA;AACZ,oGAAA,aAAa,OAAA;AACb,+FAAA,QAAQ,OAAA;AACR,wFAAA,CAAC,OAAA;AACD,yFAAA,EAAE,OAAA;AAEJ,iCAAgC;AAAvB,8FAAA,KAAK,OAAA"}
@@ -0,0 +1,21 @@
1
+ /** Component mounting utilities */
2
+ import type { Component } from "./types";
3
+ export interface MountedComponent {
4
+ element: Element;
5
+ unmount: () => void;
6
+ }
7
+ /**
8
+ * Mount a component to the DOM
9
+ * Creates an AbortController to manage component lifecycle
10
+ *
11
+ * @param component - Component function to mount
12
+ * @param props - Props passed to component (including any state)
13
+ * @param container - DOM element to mount into
14
+ * @returns Object with element reference and unmount function
15
+ *
16
+ * @example
17
+ * const mounted = mount(Counter, {label: 'Count', state: counterState}, document.body)
18
+ * // Later:
19
+ * mounted.unmount() // cleanup all subscriptions and listeners
20
+ */
21
+ export declare const mount: <Props>(component: Component<Props>, props: Props, container: Element) => MountedComponent;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mount = void 0;
4
+ /**
5
+ * Mount a component to the DOM
6
+ * Creates an AbortController to manage component lifecycle
7
+ *
8
+ * @param component - Component function to mount
9
+ * @param props - Props passed to component (including any state)
10
+ * @param container - DOM element to mount into
11
+ * @returns Object with element reference and unmount function
12
+ *
13
+ * @example
14
+ * const mounted = mount(Counter, {label: 'Count', state: counterState}, document.body)
15
+ * // Later:
16
+ * mounted.unmount() // cleanup all subscriptions and listeners
17
+ */
18
+ const mount = (component, props, container) => {
19
+ const controller = new AbortController();
20
+ const element = component(controller.signal, props);
21
+ container.appendChild(element);
22
+ return {
23
+ element,
24
+ unmount: () => {
25
+ controller.abort(); // cleanup all subscriptions and listeners
26
+ element.remove();
27
+ },
28
+ };
29
+ };
30
+ exports.mount = mount;
31
+ //# sourceMappingURL=mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../../src/mount.ts"],"names":[],"mappings":";;;AAQA;;;;;;;;;;;;;GAaG;AACI,MAAM,KAAK,GAAG,CACnB,SAA2B,EAC3B,KAAY,EACZ,SAAkB,EACA,EAAE;IACpB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACpD,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAE/B,OAAO;QACL,OAAO;QACP,OAAO,EAAE,GAAG,EAAE;YACZ,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,0CAA0C;YAC9D,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAhBW,QAAA,KAAK,SAgBhB"}
@@ -0,0 +1,2 @@
1
+ /** Re-export FunState and funState from fun-state with subscribe support */
2
+ export { funState, type FunState } from "@fun-land/fun-state";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.funState = void 0;
4
+ /** Re-export FunState and funState from fun-state with subscribe support */
5
+ var fun_state_1 = require("@fun-land/fun-state");
6
+ Object.defineProperty(exports, "funState", { enumerable: true, get: function () { return fun_state_1.funState; } });
7
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":";;;AAAA,4EAA4E;AAC5E,iDAA8D;AAArD,qGAAA,QAAQ,OAAA"}
@@ -0,0 +1,3 @@
1
+ /** Core types for fun-web */
2
+ export type Component<Props = {}> = (signal: AbortSignal, props: Props) => Element;
3
+ export type ElementChild = string | number | Element | null | undefined;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /** Core types for fun-web */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA,6BAA6B"}