@kudzujs/core 0.16.30 → 0.16.33

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.16.x`: the compiler API and supported TSX surface may change.
16
16
 
17
- **Current release: [0.16.30](https://github.com/kudzujs/kudzu/releases/tag/v0.16.30).** Write reusable components, native event handlers, and pure collection expressions; Kudzu specializes supported source into static content and direct browser updates, retaining only required binding targets and capabilities.
17
+ **Current release: [0.16.33](https://github.com/kudzujs/kudzu/releases/tag/v0.16.33).** Write reusable components, native event handlers, and pure collection expressions; Kudzu specializes supported source into static content and direct browser updates. Presentation-only conditional branches omit descendant lifecycle traversal when no owner in their runtime family needs it, removing a further 215 raw / 116 aggregate gzip JavaScript bytes from search. Stateful remounts and effect cleanup are preserved; measured search-transition medians remain approximately equal. AI-cost and 1.0 gates remain blocked.
18
18
 
19
19
  - [Documentation](https://kudzujs.cloud/docs)
20
20
  - [Installation guide](https://kudzujs.cloud/docs#install)
@@ -131,8 +131,8 @@ function mountConditions(root) {
131
131
  const truthy = globalThis.__KUDZU_SVG_CONDITIONS__ && descriptor.svg ? start.dataset.kSvgTrue : start.content.querySelector("template[data-k-true]")
132
132
  const falsy = globalThis.__KUDZU_SVG_CONDITIONS__ && descriptor.svg ? start.dataset.kSvgFalse : start.content.querySelector("template[data-k-false]")
133
133
  if (!end || !truthy || !falsy) continue
134
- const condition = { start, end, truthy, falsy, svg: globalThis.__KUDZU_SVG_CONDITIONS__ && descriptor.svg, kind: descriptor.kind, current: conditionKey(descriptor.kind, descriptor.initial), mount: descriptor.mount, owned: descriptor.owned }
135
- mountConditionStates(condition, Boolean(descriptor.initial), false)
134
+ const condition = { start, end, truthy, falsy, svg: globalThis.__KUDZU_SVG_CONDITIONS__ && descriptor.svg, kind: descriptor.kind, current: conditionKey(descriptor.kind, descriptor.initial), mount: globalThis.__KUDZU_CONDITION_MOUNTS__ !== false && descriptor.mount, owned: globalThis.__KUDZU_CONDITION_STATE__ !== false && descriptor.owned }
135
+ if (globalThis.__KUDZU_CONDITION_STATE__ !== false) mountConditionStates(condition, Boolean(descriptor.initial), false)
136
136
  const mount = evaluator => {
137
137
  if (!start.isConnected) return
138
138
  condition.read = evaluator.read
@@ -155,7 +155,7 @@ function updateCondition(condition) {
155
155
  if (next === condition.current) return
156
156
  const previous = condition.current === "true"
157
157
  removeConditionRange(condition.start, condition.end, condition.mount)
158
- unmountConditionStates(condition, previous)
158
+ if (globalThis.__KUDZU_CONDITION_STATE__ !== false) unmountConditionStates(condition, previous)
159
159
  const truthy = Boolean(value)
160
160
  const falseText = condition.kind === "and" && !truthy ? renderFalsy(value) : ""
161
161
  const fragment = falseText
@@ -163,11 +163,11 @@ function updateCondition(condition) {
163
163
  : globalThis.__KUDZU_SVG_CONDITIONS__ && condition.svg
164
164
  ? svgFragment(condition.start, truthy ? condition.truthy : condition.falsy)
165
165
  : (truthy ? condition.truthy : condition.falsy).content.cloneNode(true)
166
- const nodes = condition.mount ? [...fragment.childNodes] : undefined
167
- mountConditionStates(condition, truthy, true)
166
+ const nodes = globalThis.__KUDZU_CONDITION_MOUNTS__ !== false && condition.mount ? [...fragment.childNodes] : undefined
167
+ if (globalThis.__KUDZU_CONDITION_STATE__ !== false) mountConditionStates(condition, truthy, true)
168
168
  condition.end.parentNode.insertBefore(fragment, condition.end)
169
169
  condition.current = next
170
- if (condition.mount) for (const node of nodes) mountDom(node)
170
+ if (globalThis.__KUDZU_CONDITION_MOUNTS__ !== false && condition.mount) for (const node of nodes) mountDom(node)
171
171
  const select = globalThis.__KUDZU_VALUE_BINDINGS__ !== false && condition.start.closest("select[data-k-bind-value]")
172
172
  if (select) {
173
173
  for (const binding of new Set((bindingRegistrations.get(select) ?? []).map(([, entry]) => entry))) {
@@ -195,7 +195,7 @@ function unmountConditions(root) {
195
195
  for (const start of matching(root, "template[data-k-if]")) {
196
196
  const registration = conditionRegistrations.get(start)
197
197
  for (const [id, condition] of registration?.registrations ?? []) conditionTargets.get(id)?.delete(condition)
198
- if (registration?.condition) unmountConditionStates(registration.condition, registration.condition.current === "true")
198
+ if (globalThis.__KUDZU_CONDITION_STATE__ !== false && registration?.condition) unmountConditionStates(registration.condition, registration.condition.current === "true")
199
199
  conditionRegistrations.delete(start)
200
200
  mountedConditions.delete(start)
201
201
  }
@@ -211,7 +211,7 @@ function releaseBindings(id) {
211
211
  for (const condition of conditionTargets.get(id) ?? []) {
212
212
  const registration = conditionRegistrations.get(condition.start)
213
213
  for (const [conditionId, entry] of registration?.registrations ?? []) conditionTargets.get(conditionId)?.delete(entry)
214
- unmountConditionStates(condition, condition.current === "true")
214
+ if (globalThis.__KUDZU_CONDITION_STATE__ !== false) unmountConditionStates(condition, condition.current === "true")
215
215
  conditionRegistrations.delete(condition.start)
216
216
  }
217
217
  conditionTargets.delete(id)
@@ -232,7 +232,7 @@ function removeConditionRange(start, end, mount) {
232
232
  const range = start.ownerDocument.createRange()
233
233
  range.setStartAfter(start)
234
234
  range.setEndBefore(end)
235
- if (mount) {
235
+ if (globalThis.__KUDZU_CONDITION_MOUNTS__ !== false && mount) {
236
236
  const root = range.commonAncestorContainer
237
237
  const nodes = matching(root, "*").filter(node => range.comparePoint(node, 0) === 0)
238
238
  for (const node of nodes) if (!nodes.some(parent => parent !== node && parent.contains(node))) unmountDom(node)
@@ -15,7 +15,7 @@ export function planRouteCapabilities(records, { navigationRouteCount = 0 } = {}
15
15
  for (const plan of plans) assertRouteIR(plan, { concrete: true })
16
16
  const commandEvents = new Set()
17
17
  const nativeEvents = new Set()
18
- const bindings = { count: 0, text: false, style: false, conditions: false, svgConditions: false }
18
+ const bindings = { count: 0, text: false, style: false, conditions: false, conditionState: false, conditionMounts: false, svgConditions: false }
19
19
  const lists = {
20
20
  count: 0,
21
21
  styleCount: 0,
@@ -54,6 +54,8 @@ export function planRouteCapabilities(records, { navigationRouteCount = 0 } = {}
54
54
  bindings.text ||= plan.bindings.some(binding => binding.target === "text")
55
55
  bindings.style ||= plan.bindings.some(binding => binding.target === "style")
56
56
  bindings.conditions ||= plan.conditions.length > 0
57
+ bindings.conditionState ||= plan.conditions.some(condition => Object.values(condition.owned ?? {}).some(states => states.length > 0))
58
+ bindings.conditionMounts ||= plan.conditions.some(condition => condition.mount)
57
59
  bindings.svgConditions ||= plan.conditions.some(condition => condition.svg)
58
60
  effects.any ||= plan.effects.length > 0
59
61
  effects.derivedDependencies ||= plan.effects.some(effect => effect.dependencyExpressions?.length)
@@ -125,7 +127,9 @@ export function assertCapabilityIR(capabilityIR, records, options = {}) {
125
127
  if (!sections.every(name => isRecord(capabilityIR[name]))) throw new Error("Invalid CapabilityIR v1 structure")
126
128
  if (!["behaviors", "regularBehaviors", "regularStateSeeds", "dependencyStateSeeds"].every(name => isCount(capabilityIR.routes[name]))) throw new Error("Invalid CapabilityIR v1 route counts")
127
129
  if (!["command", "native"].every(name => Array.isArray(capabilityIR.events[name]) && capabilityIR.events[name].every(event => typeof event === "string")) || typeof capabilityIR.events.hasNativeHandlers !== "boolean") throw new Error("Invalid CapabilityIR v1 events")
128
- if (!isCount(capabilityIR.bindings.count) || !["text", "style", "conditions", "svgConditions", "attributes"].every(name => typeof capabilityIR.bindings[name] === "boolean")) throw new Error("Invalid CapabilityIR v1 bindings")
130
+ if (!isCount(capabilityIR.bindings.count) || !["text", "style", "conditions", "conditionState", "conditionMounts", "svgConditions", "attributes"].every(name => typeof capabilityIR.bindings[name] === "boolean")) throw new Error("Invalid CapabilityIR v1 bindings")
131
+ if (capabilityIR.bindings.conditionState && !capabilityIR.bindings.conditions) throw new Error("CapabilityIR conditional state requires conditions")
132
+ if (capabilityIR.bindings.conditionMounts && !capabilityIR.bindings.conditions) throw new Error("CapabilityIR conditional mounts require conditions")
129
133
  if (!Array.isArray(capabilityIR.bindings.properties) || capabilityIR.bindings.properties.some(target => !propertyBindings.includes(target)) || new Set(capabilityIR.bindings.properties).size !== capabilityIR.bindings.properties.length) throw new Error("Invalid CapabilityIR v1 binding properties")
130
134
  if (capabilityIR.bindings.style !== capabilityIR.bindings.properties.includes("style")) throw new Error("CapabilityIR binding style flag does not match its properties")
131
135
  const listFlags = ["conditions", "svg", "deepConditions", "textRanges", "attributes", "events", "expressions", "expressionAttributes", "seeds", "effects", "rowHooks", "rowRefs", "complexRowState", "nested", "selectors", "calculated", "static", "indexes", "stableFastPaths", "generalRowHooks", "asyncParts", "mounts"]
@@ -30,6 +30,7 @@ export function generateBindingRuntime(source, capabilityIR, navigable) {
30
30
  const { properties, attributes } = capabilityIR.bindings
31
31
  let runtime = replaceRequired(source, '"./shared-runtime.js"', '"./kudzu.js"', "shared runtime import", "binding-runtime.js")
32
32
  runtime = replaceRequired(runtime, '"./serialization.js"', '"./kudzu-serialization.js"', "serialization import", "binding-runtime.js")
33
+ if (!capabilityIR.bindings.conditionMounts) runtime = replaceRequired(runtime, ", unmountDom }", " }", "unused conditional unmount import", "binding-runtime.js")
33
34
  runtime = replaceRequired(runtime, /const bindingTypes = \[[^\n]+\]/, `const bindingTypes = ${JSON.stringify(properties)}`, "binding properties", "binding-runtime.js")
34
35
  const selectors = [...properties.map(target => `[data-k-bind-${target}]`), ...(attributes ? ["[data-k-bind-attrs]"] : [])]
35
36
  // The existing generic selector is smaller when all five property kinds are used.
@@ -53,6 +54,8 @@ export function generateBindingRuntime(source, capabilityIR, navigable) {
53
54
  "globalThis.__KUDZU_CHECKED_BINDINGS__": String(properties.includes("checked")),
54
55
  "globalThis.__KUDZU_VALUE_BINDINGS__": String(properties.includes("value")),
55
56
  "globalThis.__KUDZU_CONDITIONS__": String(capabilityIR.bindings.conditions),
57
+ "globalThis.__KUDZU_CONDITION_STATE__": String(capabilityIR.bindings.conditionState),
58
+ "globalThis.__KUDZU_CONDITION_MOUNTS__": String(capabilityIR.bindings.conditionMounts),
56
59
  "globalThis.__KUDZU_SVG_CONDITIONS__": String(capabilityIR.bindings.svgConditions),
57
60
  "globalThis.__KUDZU_CAPTURE_STATE__": String(capabilityIR.captures.nestedState)
58
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudzujs/core",
3
- "version": "0.16.30",
3
+ "version": "0.16.33",
4
4
  "description": "HTML-first TSX framework with synchronous state semantics and no virtual DOM",
5
5
  "type": "module",
6
6
  "license": "MIT",