@kudzujs/core 0.8.2 → 0.8.4

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
@@ -10,7 +10,7 @@ Kudzu compiles ordinary React-shaped TypeScript and TSX into complete static HTM
10
10
 
11
11
  > Experimental `0.8.x`: the compiler API and supported TSX surface may change.
12
12
 
13
- **Latest release: 0.8.1 - Custom-hook reset actions.** Relative custom hooks can batch direct primitive state resets into one behavior command, including imported negative and null literals, while dependent URL and storage effects observe the same commit. Read the [release notes](./RELEASES.md#081---custom-hook-reset-actions) or open the [release page](https://kudzujs.cloud/releases/0.8.1).
13
+ **Latest release: 0.8.4 - Browser-native handlers.** Named event handlers now keep `localStorage`, `FileReader`, and `alert` in browser ESM instead of attempting to serialize them during static rendering. Read the [release notes](./RELEASES.md#084---browser-native-handlers) or open the [release page](https://kudzujs.cloud/releases/0.8.4).
14
14
 
15
15
  - [Documentation](https://kudzujs.cloud/docs)
16
16
  - [Installation guide](https://kudzujs.cloud/docs#install)
package/RELEASES.md CHANGED
@@ -1,5 +1,50 @@
1
1
  # Kudzu Releases
2
2
 
3
+ ## 0.8.4 - Browser-native handlers
4
+
5
+ Kudzu 0.8.4 fixes named event handlers that use standard browser globals during real React application migrations.
6
+
7
+ ### New in 0.8.4
8
+
9
+ - Named and inline event handlers keep `localStorage`, `FileReader`, and `alert` in route-specific browser ESM instead of serializing them as component captures during static rendering.
10
+ - FrugalHQ backup export, file import, and reset handlers now build without evaluating browser-only globals in Node.
11
+ - Browser regression coverage verifies that the globals remain absent from SSR capture scope and resolve normally after a real click.
12
+ - The fix adds no runtime, shared bytes, hydration, or browser component tree.
13
+ - The complete suite passes 133/133 tests.
14
+
15
+ ### Boundary
16
+
17
+ Application-owned handler captures must still be JSON-safe. This release only corrects classification of the proven standard browser globals; it does not execute browser APIs during static rendering or add arbitrary callback support.
18
+
19
+ ### Upgrade
20
+
21
+ ```bash
22
+ npm install @kudzujs/core@^0.8.4
23
+ ```
24
+
25
+ ## 0.8.3 - Native interaction composition
26
+
27
+ Kudzu 0.8.3 characterizes ordinary clipboard, debounce, and accessible SVG point interactions through existing route-specific capabilities instead of dedicated browser runtimes.
28
+
29
+ ### New in 0.8.3
30
+
31
+ - Direct async handlers and directly returned relative custom-hook callbacks may call native `navigator.clipboard.writeText()` while application state owns success and permission-failure feedback.
32
+ - Dependency effects may own debounced synchronization with `setTimeout()` and directly returned `clearTimeout()` cleanup; dependency changes and conditional unmount cancel pending work.
33
+ - Calculated keyed SVG points may use focus, click, Space, and Enter handlers to update parent state rendered in an external accessible HTML tooltip.
34
+ - Retained SVG rows preserve DOM identity and read the latest point labels after recalculation and reorder.
35
+ - Clipboard, timer, and chart-specific runtimes remain absent, and unaffected static sibling routes continue to ship zero JavaScript.
36
+ - The complete suite passes 133/133 tests with focused Chrome coverage for clipboard success/failure, latest-only debounce, unmount cleanup, fresh remount, accessible tooltip input, and retained SVG identity.
37
+
38
+ ### Boundary
39
+
40
+ Debounce requires explicit effect ownership and direct cleanup. Private timer refs, unowned delayed event writes, intervals, arbitrary callback graphs, keyed-item SVG conditions, nested calculated SVG lists, and chart runtimes remain unsupported until a reduced migration fixture proves they are necessary.
41
+
42
+ ### Upgrade
43
+
44
+ ```bash
45
+ npm install @kudzujs/core@^0.8.3
46
+ ```
47
+
3
48
  ## 0.8.2 - Calculated keyed collections
4
49
 
5
50
  Kudzu 0.8.2 lets one direct array field from a synchronous relative calculation result drive an intrinsic keyed list, preserving static HTML and existing DOM ownership while improving list and navigation hot paths.
@@ -6,6 +6,8 @@ Migration source may retain conventional `react` imports for supported named or
6
6
 
7
7
  Compilation begins from page entries and follows relative runtime imports, re-exports, and validated Worker references; unreachable TypeScript migration files are not transformed. Direct maps over imported immutable JSON-safe arrays fold to literals for zero-JavaScript static rows. Synchronous relative calculation functions may return objects whose direct static fields feed reactive JSX bindings; build rendering uses current signal values and route-specific binding ESM reevaluates the same helper after state commits. One direct array field may instead feed a keyed intrinsic map: its evaluator refreshes a compiler-owned array anchor before the existing list reconciler runs, preserving keyed DOM and SVG identity without a calculation runtime. That field must remain a JSON-safe array after every source-state commit. Package imports have a separate narrow boundary: direct references inside intrinsic JSX event callbacks are erased from build modules and bundled into route handler ESM, while render-time, effect, helper-indirect, and mixed package use fails.
8
8
 
9
+ Native platform work remains ordinary source. A direct async handler or directly returned relative custom-hook callback may call `navigator.clipboard.writeText()` and update application-owned success/failure state; Kudzu emits only its existing route handler ESM. Debounced synchronization uses a dependency effect that creates `setTimeout()` work and directly returns `clearTimeout()` cleanup, reusing dependency, conditional, keyed, and route ownership. Private timer refs, timers started by unowned event callbacks, and arbitrary timed callback graphs are not supported as owned debounce patterns.
10
+
9
11
  A named or aliased `Link` import from `react-router-dom` may render directly with one static root-relative `to` plus native anchor props. The compiler prefixes the configured `base`, changes the element to `<a href>`, and erases the import, so native navigation remains the default and configured navigation groups see an ordinary eligible anchor. Dynamic or relative destinations, `NavLink`, router-only props, spreads, default/namespace imports, and non-JSX uses fail with source diagnostics. No React Router package code or router runtime is emitted.
10
12
 
11
13
  A named or aliased React Router `useParams` import may also be called directly without runtime arguments on a bracket route exporting `runtimeParams = true`. The compiler redirects that local binding to `@kudzujs/core`, preserving one optional TypeScript type argument, and reuses the existing route-specific pathname matcher. Indirect calls and other router hooks remain unsupported. Build-known `getStaticPaths()` routes use page props instead because no browser pathname capability is needed.
@@ -41,7 +43,7 @@ Exact relative `.worker.ts` constructors in inline effects are validated and bun
41
43
 
42
44
  Page `metadata` can emit description, canonical, favicon, manifest, Open Graph, and Twitter Card tags without a client runtime. Source CSS and global `kudzu.config` styles are emitted in document heads before `afterBuild()` runs; static stylesheet links in component JSX fail compilation instead of loading from the body.
43
45
 
44
- Inline SVG rendering normalizes an explicit set of common React presentation aliases before static serialization and binding descriptor creation. Reactive aliases use the existing generic `setAttribute` path. Reactive conditionals and flat intrinsic keyed lists store inert branch or row markup on SVG markers and parse it in the actual parent namespace only when replacement nodes are needed; existing condition/list ownership then handles insertion, identity, updates, and removal. Builds without structural SVG compile out that fragment path, and static SVG adds no JavaScript. Keyed-item conditions, nested SVG lists, MathML structures, and namespaced attributes remain unsupported.
46
+ Inline SVG rendering normalizes an explicit set of common React presentation aliases before static serialization and binding descriptor creation. Reactive aliases use the existing generic `setAttribute` path. Reactive conditionals and flat intrinsic keyed lists store inert branch or row markup on SVG markers and parse it in the actual parent namespace only when replacement nodes are needed; existing condition/list ownership then handles insertion, identity, updates, and removal. Focus, keyboard, and click handlers on keyed SVG points may update parent state for an external accessible HTML tooltip, and retained handlers read the latest item after list updates. Builds without structural SVG compile out that fragment path, and static SVG adds no JavaScript. Keyed-item conditions, nested SVG lists, MathML structures, and namespaced attributes remain unsupported.
45
47
 
46
48
  Same-file, directly exported same-file, and relative-imported component chains receiving a direct local-state array or keyed item are recursively specialized to intrinsic JSX before keyed-list analysis, so their component functions are not retained in the browser. A directly exported row may be reused across static and keyed JSX sites; export-list/default aliases and non-JSX references remain rejected. Missing destructured props use directly serializable primitive, plain-object, or array literal defaults during specialization. One final identifier rest binding may be expanded exactly once at the direct intrinsic root. Rows may own multiple direct-property child maps recursively, nested conditions, latest-item handlers, multiple directly serializable state slots, effects, and `null`-initialized object refs. A block-bodied keyed `map` callback may declare one top-level `const` computed from a direct child collection through the supported pure selector pipeline and then return JSX; the alias must feed exactly one nested keyed list source. Structural list sites and ancestor key paths scope hooks across updates and reorder and release them on removal. Handler modules are emitted only when a rendered descriptor references them. Direct JSON-safe primitive keyed-item dependencies subscribe each row record to its owning list commit and compare selected fields after `list-runtime.js` synchronously refreshes the row marker. Only changed rows rerun with the complete latest item; reorder compares equal and unrelated fields do nothing. Builds without item dependencies emit no item reader or list-state subscription code.
47
49
 
@@ -5127,7 +5127,7 @@ function compileOptimizedEvent(expression, setters, factory) {
5127
5127
  }
5128
5128
 
5129
5129
  const nativeGlobals = new Set([
5130
- "Array", "ArrayBuffer", "BigInt", "Blob", "Boolean", "Date", "Error", "Event", "FormData", "Infinity", "Intl", "JSON", "Map", "Math", "NaN", "Number", "Object", "Promise", "Proxy", "RangeError", "ReferenceError", "Reflect", "RegExp", "Set", "String", "Symbol", "TypeError", "URL", "URLSearchParams", "WeakMap", "WeakSet", "WebSocket", "Worker", "atob", "btoa", "clearInterval", "clearTimeout", "console", "crypto", "document", "fetch", "globalThis", "history", "isFinite", "isNaN", "location", "navigator", "parseFloat", "parseInt", "queueMicrotask", "requestAnimationFrame", "setInterval", "setTimeout", "structuredClone", "undefined", "window"
5130
+ "Array", "ArrayBuffer", "BigInt", "Blob", "Boolean", "Date", "Error", "Event", "FileReader", "FormData", "Infinity", "Intl", "JSON", "Map", "Math", "NaN", "Number", "Object", "Promise", "Proxy", "RangeError", "ReferenceError", "Reflect", "RegExp", "Set", "String", "Symbol", "TypeError", "URL", "URLSearchParams", "WeakMap", "WeakSet", "WebSocket", "Worker", "alert", "atob", "btoa", "clearInterval", "clearTimeout", "console", "crypto", "document", "fetch", "globalThis", "history", "isFinite", "isNaN", "localStorage", "location", "navigator", "parseFloat", "parseInt", "queueMicrotask", "requestAnimationFrame", "setInterval", "setTimeout", "structuredClone", "undefined", "window"
5131
5131
  ])
5132
5132
 
5133
5133
  function rewriteEffectWorkers(callback, file, sourceFile, sourceFiles, workerReferences, factory, context) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",