@kudzujs/core 0.8.10 → 0.8.12

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
@@ -14,7 +14,7 @@ Kudzu compiles ordinary React-shaped TypeScript and TSX into complete static HTM
14
14
 
15
15
  > Experimental `0.8.x`: the compiler API and supported TSX surface may change.
16
16
 
17
- **Latest release: 0.8.10 - Native dialog migration.** A reduced shadcn/Radix-shaped dialog now proves how AI migration can preserve `forwardRef`, props, children, refs, and handlers while replacing package-owned Portal and Context behavior with native `<dialog>`. Read the [release notes](./RELEASES.md#0810---native-dialog-migration) or open the [release page](https://kudzujs.cloud/releases/0.8.10).
17
+ **Latest release: 0.8.12 - Static icon migration.** Used Lucide-shaped icons move to relative TSX and compile to accessible static SVG while build-folded evaluator JavaScript disappears from deploy output. Read the [release notes](./RELEASES.md#0812---static-icon-migration) or open the [release page](https://kudzujs.cloud/releases/0.8.12).
18
18
 
19
19
  - [Documentation](https://kudzujs.cloud/docs)
20
20
  - [Installation guide](https://kudzujs.cloud/docs#install)
package/RELEASES.md CHANGED
@@ -1,5 +1,60 @@
1
1
  # Kudzu Releases
2
2
 
3
+ ## 0.8.12 - Static icon migration
4
+
5
+ Kudzu 0.8.12 proves a source migration path from Lucide React-shaped icon usage to accessible static SVG without a package factory or browser runtime.
6
+
7
+ ### New in 0.8.12
8
+
9
+ - Used icons move into relative TSX components with direct intrinsic SVG roots and familiar size, stroke, class, fill, ARIA, and title props.
10
+ - Meaningful icons retain explicit roles and titles, while decorative icons remain hidden from assistive technology.
11
+ - React-shaped SVG presentation attributes normalize to native output and complete icon routes ship zero JavaScript.
12
+ - Unreachable icon modules are excluded from compilation instead of becoming deploy artifacts.
13
+ - Public documentation records the migration recipe and its deliberate package boundary.
14
+
15
+ ### Fixed in 0.8.12
16
+
17
+ - Handler emission now follows references in the final route plan and HTML, removing evaluator modules left behind by build-folded component conditions while preserving list-expression evaluators.
18
+ - The complete suite passes 143/143 tests.
19
+
20
+ ### Boundary
21
+
22
+ This release does not execute `lucide-react`. Dynamic icon lookup, `createLucideIcon()`, package-owned factories, and a generic icon runtime remain unsupported source migration work.
23
+
24
+ ### Upgrade
25
+
26
+ ```bash
27
+ npm install @kudzujs/core@^0.8.12
28
+ ```
29
+
30
+ ## 0.8.11 - Stale-safe data migration
31
+
32
+ Kudzu 0.8.11 proves source migration paths for TanStack Query-shaped data and React Hook Form-shaped forms while strengthening dependency-effect stale-write isolation.
33
+
34
+ ### New in 0.8.11
35
+
36
+ - Build-known query data moves to async pages and emits complete zero-JavaScript HTML.
37
+ - Browser-only query data uses one dependency effect with application-owned loading, error, result, and primitive refetch state.
38
+ - Superseded unowned dependency effects invalidate their invocation before cleanup, so late promise or fetch setters cannot overwrite newer state.
39
+ - A deterministic Chrome race verifies that a fast refetch remains visible after a delayed prior response arrives, followed by HTTP failure and recovery.
40
+ - React Hook Form-shaped signup source migrates to native controls, constraint validation, `FormData`, one async submit handler, accessible server errors, and retained uncontrolled values.
41
+ - Static sibling routes remain JavaScript-free, with no TanStack Query or React Hook Form runtime in deploy output.
42
+
43
+ ### Fixed in 0.8.11
44
+
45
+ - Mobile documentation now uses a true 100% layout wrapper with explicit inner gutters instead of a reduced outer width.
46
+ - The complete suite passes 142/142 tests.
47
+
48
+ ### Boundary
49
+
50
+ This release does not execute TanStack Query or React Hook Form. Query clients, Providers, caches, retries, deduplication, optimistic cache updates, query-key arrays, Suspense, controllers, watchers, resolvers, and dynamic field registration remain source migration work.
51
+
52
+ ### Upgrade
53
+
54
+ ```bash
55
+ npm install @kudzujs/core@^0.8.11
56
+ ```
57
+
3
58
  ## 0.8.10 - Native dialog migration
4
59
 
5
60
  Kudzu 0.8.10 proves a source migration path from a shadcn/Radix-shaped dialog to the native `<dialog>` element without adding package compatibility runtime.
@@ -145,7 +145,8 @@ export async function build({ quiet = false, minify = true } = {}) {
145
145
  runtimeParams: runtimeSchema?.params,
146
146
  ...(navigable ? { navigationAsset: navigationGroup.assetPath, applicationId: navigationGroup.applicationId, layoutId: navigationGroup.layoutId, routeId: applicationRoute } : {})
147
147
  }, props, module.layout)
148
- for (const url of result.handlerModules) renderedHandlerUrls.add(url)
148
+ const renderedOutput = `${JSON.stringify(result.plan)}\n${result.html}`
149
+ for (const url of result.handlerModules) if (renderedOutput.includes(JSON.stringify(url))) renderedHandlerUrls.add(url)
149
150
  if (navigationGroup) {
150
151
  navigationGroup.hasEffects ||= result.hasEffects
151
152
  navigationGroup.hasParams ||= result.hasParams
@@ -581,7 +582,7 @@ addEventListener("pagehide", event => {
581
582
  if (hasDependencies) return `${imports.join("\n")}
582
583
  const effects = ${inlineJson(effects)}
583
584
  const modules = new Map([${entries}])
584
- const records = effects.map((effect, index) => ({ effect, index, values: undefined, cleanup: undefined }))
585
+ const records = effects.map((effect, index) => ({ effect, index, values: undefined, cleanup: undefined, token: undefined }))
585
586
  const dependencies = new Map()
586
587
  const pending = new Set()
587
588
  let scheduled = false
@@ -649,7 +650,9 @@ ${hasDependencyExpressions ? printDerivedDependencyRead("browserState") : ""}
649
650
  function invoke(record) {
650
651
  try {
651
652
  const effect = record.effect
652
- const result = modules.get(effect.module)[effect.handler](createEffectContext(browserState, effect.states, commitDom, effect.scope))
653
+ const token = { active: true }
654
+ record.token = token
655
+ const result = modules.get(effect.module)[effect.handler](createEffectContext(browserState, effect.states, commitDom, effect.scope, () => active && token.active && record.token === token))
653
656
  if (effect.cleanup && typeof result === "function") record.cleanup = result
654
657
  else if (result && typeof result.then === "function") result.catch(error => console.error(error))
655
658
  } catch (error) {
@@ -657,6 +660,8 @@ function invoke(record) {
657
660
  }
658
661
  }
659
662
  async function invokeCleanup(record) {
663
+ if (record.token) record.token.active = false
664
+ record.token = undefined
660
665
  const cleanup = record.cleanup
661
666
  record.cleanup = undefined
662
667
  if (!cleanup) return
@@ -1352,6 +1357,7 @@ const effect = ${inlineJson(effect)}
1352
1357
  const dependency = effect.dependencies[0]
1353
1358
  let value
1354
1359
  let cleanup
1360
+ let token
1355
1361
  let active = true
1356
1362
  let pending = false
1357
1363
  let scheduled = false
@@ -1402,7 +1408,9 @@ function readDependency() {
1402
1408
  }
1403
1409
  function invoke() {
1404
1410
  try {
1405
- const result = __kEffectModule0[effect.handler](createEffectContext(browserState, effect.states, commitDom, effect.scope))
1411
+ const current = { active: true }
1412
+ token = current
1413
+ const result = __kEffectModule0[effect.handler](createEffectContext(browserState, effect.states, commitDom, effect.scope, () => active && current.active && token === current))
1406
1414
  if (effect.cleanup && typeof result === "function") cleanup = result
1407
1415
  else if (result && typeof result.then === "function") result.catch(error => console.error(error))
1408
1416
  } catch (error) {
@@ -1410,6 +1418,8 @@ function invoke() {
1410
1418
  }
1411
1419
  }
1412
1420
  async function invokeCleanup() {
1421
+ if (token) token.active = false
1422
+ token = undefined
1413
1423
  const current = cleanup
1414
1424
  cleanup = undefined
1415
1425
  if (!current) return
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.8.10",
3
+ "version": "0.8.12",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",