@pfern/elements 0.1.9 → 0.1.11

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 CHANGED
@@ -1,63 +1,16 @@
1
1
  # Elements.js
2
2
 
3
- Elements.js is a minimalist declarative UI toolkit designed around purity,
4
- immutability, and HTML semantics.
3
+ Elements.js is a tiny, functional UI toolkit for building DOM trees with plain
4
+ functions. Components are just functions; updates are just calling the function
5
+ again with new arguments.
5
6
 
6
- ## Features
7
+ ## Install
7
8
 
8
- * Zero-dependency functional UI engine
9
- * Stateless components defined as pure functions
10
- * Fully declarative, deeply composable view trees
11
- * HTML element functions with JSDoc and TypeScript-friendly signatures
12
- * No hooks, no classes, no virtual DOM heuristics
13
-
14
- ---
15
-
16
- ## Why Elements.js?
17
-
18
- Modern frameworks introduced declarative UI—but buried it beneath lifecycle
19
- hooks, mutable state, and complex diffing algorithms.
20
-
21
- **Elements.js goes further:**
22
-
23
- * Pure functions represent both logic and view
24
- * The DOM *is* your state model
25
- * Re-rendering is *recursion*, not reconciliation
26
-
27
- > Can UI be defined as a tree of pure function calls—nothing more?
28
-
29
- Yes. Elements.js proves it.
30
-
31
- ---
32
-
33
- ## Philosophy
34
-
35
- ### Declarative from top to bottom
36
-
37
- * No internal component state
38
- * No lifecycle methods or effects
39
- * Every component is a function
40
-
41
- To update a view: just **call the function again** with new arguments. The DOM
42
- subtree is replaced in place.
43
-
44
- ### State lives in the DOM
45
-
46
- There is no observer graph, no `useState`, and no memory of previous renders.
47
- The DOM node *is the history*. Input state is passed as an argument.
48
-
49
- ### Minimal abstraction
50
-
51
- * No keys, refs, proxies, or context systems
52
- * No transpilation step
53
- * No reactive graph to debug
54
-
55
- Elements.js embraces the full truth of each function call as the only valid
56
- state.
57
-
58
- ---
9
+ ```bash
10
+ npm install @pfern/elements
11
+ ```
59
12
 
60
- ## Example: Counter
13
+ ## Quick Example: Counter
61
14
 
62
15
  ```js
63
16
  import { button, component, div, output } from '@pfern/elements'
@@ -70,13 +23,7 @@ export const counter = component((count = 0) =>
70
23
  'Increment')))
71
24
  ```
72
25
 
73
- * Each click returns a new call to `counter(count + 1)`
74
- * The old DOM node is replaced with the new one
75
- * No virtual DOM, no diffing
76
-
77
- ---
78
-
79
- ## Form Example: Todos App
26
+ ## Example: Todos App
80
27
 
81
28
  ```js
82
29
 
@@ -111,18 +58,6 @@ export const todos = component(
111
58
 
112
59
  ```
113
60
 
114
- This is a complete MVC-style app:
115
-
116
- * Stateless
117
- * Immutable
118
- * Pure
119
-
120
- You can view these examples live on [Github
121
- Pages](https://pfernandez.github.io/elements/) or by running them locally with
122
- `npm run dev`.
123
-
124
- ---
125
-
126
61
  ## Root Rendering Shortcut
127
62
 
128
63
  If you use `html`, `head`, or `body` as the top-level tag, `render()` will
@@ -152,21 +87,15 @@ render(
152
87
  todos())))))
153
88
  ```
154
89
 
155
- ---
156
-
157
90
  ## Declarative Events
158
91
 
159
- All event listeners in Elements.js are pure functions. You can return a vnode
160
- from a listener to declaratively update the component tree—- no mutation or
161
- imperative logic required.
162
-
163
92
  ### General Behavior
164
93
 
165
94
  * Any event handler (e.g. `onclick`, `onsubmit`, `oninput`) may return a new
166
95
  vnode to trigger a subtree replacement.
167
96
  * If the handler returns `undefined`, the event is treated as passive (no update
168
97
  occurs).
169
- * Returned vnodes are passed to `component()` to re-render declaratively.
98
+ * Returned vnodes are applied at the closest component boundary.
170
99
 
171
100
  ### Form Events
172
101
 
@@ -195,8 +124,6 @@ form({
195
124
  If the handler returns nothing, `preventDefault()` is skipped and the form
196
125
  submits natively.
197
126
 
198
- ---
199
-
200
127
  ## API
201
128
 
202
129
  ### `component(fn)`
@@ -232,48 +159,10 @@ Elements are data-in, data-out only, so mocking and headless browsers like
232
159
  `jsdom` are unnecessary out of the box. See the tests [in this
233
160
  repository](test/README.md) for some examples.
234
161
 
235
- ---
236
-
237
- ## Status
238
-
239
- * 🧪 Fully tested (data-in/data-out behavior)
240
- * ⚡ Under 2kB min+gzip
241
- * ✅ Node and browser compatible
242
-
243
- ---
244
-
245
- ## Installation
246
-
247
- ```bash
248
- npm install @pfern/elements
249
- ```
250
-
251
- Or clone the repo and use as an ES module:
252
-
253
- ```js
254
- import { render, div, component, ... } from './elements.js';
255
- ```
256
-
257
- ---
258
-
259
- ## Summary
260
-
261
- Elements.js is a thought experiment turned practical:
262
-
263
- > Can UI be nothing but functions?
264
-
265
- Turns out, yes.
266
-
267
- * No diffing
268
- * No state hooks
269
- * No lifecycle
270
- * No reconciliation heuristics
271
-
272
- Just pure declarative HTML—rewritten in JavaScript.
273
-
274
- ---
275
-
276
- **Lightweight. Immutable. Composable.**
277
-
278
- Give it a try. You might never go back.
162
+ ## Notes
279
163
 
164
+ - Elements.js is intended to be small and easy to reason about.
165
+ - For a starter app template, use `@pfern/create-elements`:
166
+ - https://github.com/pfernandez/create-elements
167
+ - `npx @pfern/create-elements my-app`
168
+ - More examples live in `examples/`.
package/elements.js CHANGED
@@ -309,34 +309,6 @@ export const render = (vtree, container = null) => {
309
309
  rootMap.set(vtree, target)
310
310
  }
311
311
 
312
- /**
313
- * Updates the browser URL via the History API (no full page load).
314
- * No-ops outside the browser.
315
- *
316
- * @param {string} to - The target URL (path/search/hash).
317
- * @param {Object} [options]
318
- * @param {boolean} [options.replace=false] - Use replaceState instead of pushState.
319
- * @param {boolean} [options.force=false] - Update even if URL is already `to`.
320
- * @param {any} [options.state={}] - History state.
321
- * @param {string} [options.title=''] - History title (mostly ignored by browsers).
322
- */
323
- export const navigate = (to, {
324
- replace = false,
325
- force = false,
326
- state = {},
327
- title = ''
328
- } = {}) => {
329
- if (typeof window === 'undefined') return
330
- if (typeof to !== 'string' || !to.length) return
331
-
332
- const { pathname, search, hash } = window.location
333
- const current = `${pathname}${search}${hash}`
334
- if (!force && current === to) return
335
-
336
- const method = replace ? 'replaceState' : 'pushState'
337
- window.history[method](state, title, to)
338
- }
339
-
340
312
  /**
341
313
  * Wraps a function component so that it participates in reconciliation.
342
314
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pfern/elements",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "A minimalist, pure functional declarative UI toolkit.",
5
5
  "type": "module",
6
6
  "main": "elements.js",
@@ -12,15 +12,6 @@
12
12
  export const DEBUG: boolean;
13
13
  export function render(vtree: any, container?: any): void;
14
14
  export function component(fn: (...args: any[]) => any): (...args: any[]) => any;
15
- export function navigate(
16
- to: string,
17
- options?: {
18
- replace?: boolean;
19
- force?: boolean;
20
- state?: any;
21
- title?: string;
22
- }
23
- ): void;
24
15
  /**
25
16
  * @typedef {Record<string, any>} Props
26
17
  * @typedef {any[] | string | number | boolean | null | undefined | Node} Child