@barefootjs/jsx 0.3.0 → 0.4.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.
package/dist/index.js CHANGED
@@ -1652,6 +1652,9 @@ function irToComponentTemplateWithOpts(node, opts) {
1652
1652
  }
1653
1653
  return `\${${transformExpr(node.expr, node.templateExpr)}}`;
1654
1654
  case "conditional": {
1655
+ if (node.clientOnly && node.slotId) {
1656
+ return `<!--bf-cond-start:${node.slotId}--><!--bf-cond-end:${node.slotId}-->`;
1657
+ }
1655
1658
  const trueBranch = recurse(node.whenTrue);
1656
1659
  const falseBranch = recurse(node.whenFalse);
1657
1660
  const trueHtml = node.slotId ? addCondAttrToTemplate(trueBranch, node.slotId) : trueBranch;
@@ -1882,6 +1885,9 @@ function generateCsrTemplateWithOpts(node, opts) {
1882
1885
  return `\${${expr}}`;
1883
1886
  }
1884
1887
  case "conditional": {
1888
+ if (node.clientOnly && node.slotId) {
1889
+ return `<!--bf-cond-start:${node.slotId}--><!--bf-cond-end:${node.slotId}-->`;
1890
+ }
1885
1891
  const trueBranch = recurse(node.whenTrue);
1886
1892
  const falseBranch = recurse(node.whenFalse);
1887
1893
  const trueHtml = node.slotId ? addCondAttrToTemplate(trueBranch, node.slotId) : trueBranch;
@@ -1 +1 @@
1
- {"version":3,"file":"html-template.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/html-template.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"html-template.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/html-template.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,EAAE,MAAM,UAAU,CAAA;AAG9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAG5C,OAAO,EAAwD,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACpG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAI9C;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI;IACvC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9B,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAC/B,CAaA;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAwBnE;AAED;;;;;GAKG;AACH,wBAAgB,kCAAkC,IAAI;IACpD,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9B,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAC/B,CAeA;AA+LD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,gBAAgB,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,KAAK,OAAO,CAAA;IACxE,+EAA+E;IAC/E,eAAe,EAAE,OAAO,CAAA;CACzB;AAiFD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,SAAI,EAAE,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,aAAa,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,UAAU,UAAQ,EAAE,iBAAiB,UAAQ,GAAG,MAAM,CAqM/N;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,SAAI,EAAE,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,aAAa,CAAC,GAAG,MAAM,CAoG9J;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAM7D;AA0ED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAM1E;AAeD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC9B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACxC,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,GAC9B,MAAM,CAER;AAoPD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACxC,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAC7B,OAAO,CA8ET;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACnD,GAAG,EAAE,eAAe,EACpB,UAAU,CAAC,EAAE,OAAO,EACpB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAC7B,MAAM,CAeR;AA4RD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAiBpF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/jsx",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "JSX compiler for BarefootJS - transforms JSX to server HTML + client JS",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,7 +49,7 @@
49
49
  "directory": "packages/jsx"
50
50
  },
51
51
  "dependencies": {
52
- "@barefootjs/shared": "0.3.0"
52
+ "@barefootjs/shared": "0.4.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@barefootjs/client": ">=0.2.0",
@@ -201,3 +201,84 @@ describe('auto-defer brand-package reactive bindings (#1638)', () => {
201
201
  expect(templateBody).toContain('data-count=')
202
202
  })
203
203
  })
204
+
205
+ describe('client hydrate template defers brand conditionals (#1645)', () => {
206
+ // The `template: (_p) => ...` lambda runs at module scope when the
207
+ // component is client-rendered via `createComponent` (not when hydrating
208
+ // existing SSR DOM). It cannot reproduce per-instance `createForm` state,
209
+ // so an auto-deferred conditional must emit empty cond markers — exactly
210
+ // like the SSR adapter — and let `init`'s `insert()` populate the branch.
211
+
212
+ test('non-inlinable createForm (onSubmit): no undefined.field, emits cond markers', () => {
213
+ const { templateBody } = compileWithBrand(`
214
+ 'use client'
215
+ import { createForm } from './_form-defs'
216
+
217
+ export function SignupForm() {
218
+ const form = createForm({
219
+ onSubmit: async (data) => { await fetch('/signup', { method: 'POST', body: JSON.stringify(data) }) },
220
+ })
221
+ const email = form.field('email')
222
+ return (
223
+ <form>
224
+ <input value={email.value()} />
225
+ {email.error() && <p>{email.error()}</p>}
226
+ </form>
227
+ )
228
+ }
229
+ `)
230
+
231
+ // Never re-derive the form at module scope: `undefined.field(...)` throws.
232
+ expect(templateBody).not.toContain('undefined.field')
233
+ expect(templateBody).not.toContain('.field(')
234
+ // The deferred conditional collapses to the same empty markers SSR emits.
235
+ expect(templateBody).toMatch(/<!--bf-cond-start:s\d+--><!--bf-cond-end:s\d+-->/)
236
+ })
237
+
238
+ test('inlinable createForm (no onSubmit): no re-inlined createForm in template', () => {
239
+ const { templateBody } = compileWithBrand(`
240
+ 'use client'
241
+ import { createForm } from './_form-defs'
242
+
243
+ export function SignupForm() {
244
+ const form = createForm({ defaultValues: { email: '' } })
245
+ const email = form.field('email')
246
+ return (
247
+ <form>
248
+ <input value={email.value()} />
249
+ {email.error() && <p>{email.error()}</p>}
250
+ </form>
251
+ )
252
+ }
253
+ `)
254
+
255
+ // A re-inlined `createForm({...})` would build a throwaway instance on
256
+ // every template render (error always '', never the live instance).
257
+ expect(templateBody).not.toContain('createForm(')
258
+ expect(templateBody).not.toContain('undefined.field')
259
+ expect(templateBody).toMatch(/<!--bf-cond-start:s\d+--><!--bf-cond-end:s\d+-->/)
260
+ })
261
+
262
+ test('init still wires the deferred conditional via insert()', () => {
263
+ const { initBody } = compileWithBrand(`
264
+ 'use client'
265
+ import { createForm } from './_form-defs'
266
+
267
+ export function SignupForm() {
268
+ const form = createForm()
269
+ const email = form.field('email')
270
+ return (
271
+ <form>
272
+ <input value={email.value()} />
273
+ {email.error() && <p>{email.error()}</p>}
274
+ </form>
275
+ )
276
+ }
277
+ `)
278
+
279
+ // The reactive binding lives in init (where `email`/`form` are in scope),
280
+ // not in the module-scope template lambda.
281
+ expect(initBody).toMatch(/insert\(/)
282
+ expect(initBody).toContain('email.error()')
283
+ })
284
+ })
@@ -1040,6 +1040,14 @@ function irToComponentTemplateWithOpts(node: IRNode, opts: TemplateOptions): str
1040
1040
  return `\${${transformExpr(node.expr, node.templateExpr)}}`
1041
1041
 
1042
1042
  case 'conditional': {
1043
+ // A client-only conditional (auto-deferred brand read or manual
1044
+ // `/* @client */`) is owned by init's `insert()`, not the module-scope
1045
+ // template lambda. Match the SSR adapter: emit empty cond markers so
1046
+ // the client-render path (`createComponent`) produces the same DOM SSR
1047
+ // does, instead of evaluating an init-scope condition here (#1645).
1048
+ if (node.clientOnly && node.slotId) {
1049
+ return `<!--bf-cond-start:${node.slotId}--><!--bf-cond-end:${node.slotId}-->`
1050
+ }
1043
1051
  const trueBranch = recurse(node.whenTrue)
1044
1052
  const falseBranch = recurse(node.whenFalse)
1045
1053
  const trueHtml = node.slotId ? addCondAttrToTemplate(trueBranch, node.slotId) : trueBranch
@@ -1418,6 +1426,15 @@ function generateCsrTemplateWithOpts(node: IRNode, opts: TemplateOptions): strin
1418
1426
  }
1419
1427
 
1420
1428
  case 'conditional': {
1429
+ // An auto-deferred conditional (e.g. `{form.field('x').error() && …}`)
1430
+ // reads per-instance init-scope state the module-scope template lambda
1431
+ // can't evaluate — re-deriving it here yields `undefined.field(...)` or
1432
+ // a throwaway re-inlined `createForm({...})`. Match the SSR adapter:
1433
+ // emit empty cond markers and let init's `insert()` populate the branch
1434
+ // at hydrate time via the reactive binding (#1645).
1435
+ if (node.clientOnly && node.slotId) {
1436
+ return `<!--bf-cond-start:${node.slotId}--><!--bf-cond-end:${node.slotId}-->`
1437
+ }
1421
1438
  const trueBranch = recurse(node.whenTrue)
1422
1439
  const falseBranch = recurse(node.whenFalse)
1423
1440
  const trueHtml = node.slotId ? addCondAttrToTemplate(trueBranch, node.slotId) : trueBranch