@barefootjs/client 0.5.3 → 0.6.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.
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/runtime/component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAS3C,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAExD;AAWD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;;;GAGG;AACH;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,GAAG,YAAY,EAChC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACnC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,IAAI,CAAC,EAAE,uBAAuB,GAC7B,WAAW,CAyIb;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAE3F;AAuBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAE7G;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAiDR;AA+DD;;;;;GAKG;AACH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjD;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,gBAAgB,CAcjF"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/runtime/component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAS3C,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAExD;AAWD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;;;GAGG;AACH;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,GAAG,YAAY,EAChC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACnC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,IAAI,CAAC,EAAE,uBAAuB,GAC7B,WAAW,CAgLb;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAE3F;AAuBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAE7G;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAiDR;AA+DD;;;;;GAKG;AACH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjD;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,gBAAgB,CAcjF"}
@@ -123,6 +123,7 @@ function loopEndMarker(markerId) {
123
123
  return `${BF_LOOP_END}:${markerId}`;
124
124
  }
125
125
  var BF_KEY = "data-key";
126
+ var BF_PLACEHOLDER = "data-bf-ph";
126
127
  var BF_ASYNC = "bf-async";
127
128
  var BF_ASYNC_RESOLVE = "bf-async-resolve";
128
129
  var BF_PARENT_SCOPE_PLACEHOLDER = "__BF_PARENT_SCOPE__";
@@ -793,7 +794,7 @@ function upsertChild(parent, name, slotId, props, key, anchorScope) {
793
794
  return ssr;
794
795
  }
795
796
  const phId = slotId ?? name;
796
- const ph = parent.querySelector(`[data-bf-ph="${phId}"]`);
797
+ const ph = parent.getAttribute(BF_PLACEHOLDER) === phId ? parent : parent.querySelector(`[${BF_PLACEHOLDER}="${phId}"]`);
797
798
  if (ph) {
798
799
  const slot = slotId ? buildSlotInfo(parent, slotId, anchorScope) : undefined;
799
800
  const comp = createComponent(name, props, key, slot);
@@ -1019,10 +1020,24 @@ function createComponent(nameOrDef, props = {}, key, slot) {
1019
1020
  element.setAttribute(BF_KEY, String(key));
1020
1021
  }
1021
1022
  const prevScope = setCurrentScope(element);
1023
+ const rootIsDeferredPlaceholder = element.hasAttribute(BF_PLACEHOLDER);
1024
+ let placeholderWrapper = null;
1025
+ if (rootIsDeferredPlaceholder) {
1026
+ placeholderWrapper = parseHTML("<div></div>").firstChild;
1027
+ placeholderWrapper.appendChild(element);
1028
+ }
1022
1029
  const initFn = getComponentInit(name);
1023
1030
  if (initFn) {
1024
1031
  initFn(element, props);
1025
1032
  }
1033
+ if (rootIsDeferredPlaceholder && placeholderWrapper) {
1034
+ const materialised = placeholderWrapper.firstElementChild;
1035
+ if (materialised && !materialised.hasAttribute(BF_PLACEHOLDER)) {
1036
+ setCurrentScope(prevScope);
1037
+ return materialised;
1038
+ }
1039
+ placeholderWrapper.removeChild(element);
1040
+ }
1026
1041
  if (childrenIsGetter) {
1027
1042
  const children = untrack(() => childrenDescriptor.get());
1028
1043
  if (children != null) {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/runtime/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAarC;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAclE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,OAAO,GAAG,IAAI,EAC1B,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAClC,IAAI,CAoCN;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,GAC3B,WAAW,GAAG,IAAI,CAwBpB"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/runtime/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAarC;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAclE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,OAAO,GAAG,IAAI,EAC1B,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAClC,IAAI,CAoCN;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,GAC3B,WAAW,GAAG,IAAI,CA8BpB"}
@@ -314,6 +314,7 @@ function loopEndMarker(markerId) {
314
314
  return `${BF_LOOP_END}:${markerId}`;
315
315
  }
316
316
  var BF_KEY = "data-key";
317
+ var BF_PLACEHOLDER = "data-bf-ph";
317
318
  var BF_ASYNC = "bf-async";
318
319
  var BF_ASYNC_RESOLVE = "bf-async-resolve";
319
320
  var BF_PARENT_SCOPE_PLACEHOLDER = "__BF_PARENT_SCOPE__";
@@ -984,7 +985,7 @@ function upsertChild(parent, name, slotId, props, key, anchorScope) {
984
985
  return ssr;
985
986
  }
986
987
  const phId = slotId ?? name;
987
- const ph = parent.querySelector(`[data-bf-ph="${phId}"]`);
988
+ const ph = parent.getAttribute(BF_PLACEHOLDER) === phId ? parent : parent.querySelector(`[${BF_PLACEHOLDER}="${phId}"]`);
988
989
  if (ph) {
989
990
  const slot = slotId ? buildSlotInfo(parent, slotId, anchorScope) : undefined;
990
991
  const comp = createComponent(name, props, key, slot);
@@ -1209,10 +1210,24 @@ function createComponent(nameOrDef, props = {}, key, slot) {
1209
1210
  element.setAttribute(BF_KEY, String(key));
1210
1211
  }
1211
1212
  const prevScope = setCurrentScope(element);
1213
+ const rootIsDeferredPlaceholder = element.hasAttribute(BF_PLACEHOLDER);
1214
+ let placeholderWrapper = null;
1215
+ if (rootIsDeferredPlaceholder) {
1216
+ placeholderWrapper = parseHTML("<div></div>").firstChild;
1217
+ placeholderWrapper.appendChild(element);
1218
+ }
1212
1219
  const initFn = getComponentInit(name);
1213
1220
  if (initFn) {
1214
1221
  initFn(element, props);
1215
1222
  }
1223
+ if (rootIsDeferredPlaceholder && placeholderWrapper) {
1224
+ const materialised = placeholderWrapper.firstElementChild;
1225
+ if (materialised && !materialised.hasAttribute(BF_PLACEHOLDER)) {
1226
+ setCurrentScope(prevScope);
1227
+ return materialised;
1228
+ }
1229
+ placeholderWrapper.removeChild(element);
1230
+ }
1216
1231
  if (childrenIsGetter) {
1217
1232
  const children = untrack(() => childrenDescriptor.get());
1218
1233
  if (children != null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/client",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "description": "BarefootJS client package: reactive primitives (SSR-safe) plus browser runtime under the `/runtime` subpath (compiler target)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -55,7 +55,7 @@
55
55
  "directory": "packages/client"
56
56
  },
57
57
  "dependencies": {
58
- "@barefootjs/shared": "0.5.3"
58
+ "@barefootjs/shared": "0.6.0"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@barefootjs/jsx": ">=0.2.0"
@@ -11,7 +11,7 @@ import { getRegisteredDef } from './hydrate'
11
11
  import { hydratedScopes } from './hydration-state'
12
12
  import { untrack } from '@barefootjs/client/reactive'
13
13
  import { setCurrentScope } from './context'
14
- import { BF_SCOPE, BF_KEY, BF_HOST, BF_AT, BF_PARENT_SCOPE_PLACEHOLDER } from '@barefootjs/shared'
14
+ import { BF_SCOPE, BF_KEY, BF_HOST, BF_AT, BF_PARENT_SCOPE_PLACEHOLDER, BF_PLACEHOLDER } from '@barefootjs/shared'
15
15
  import type { ComponentDef } from './types'
16
16
 
17
17
  // Parent scope ID context for renderChild() inside insert() branch templates.
@@ -186,13 +186,52 @@ export function createComponent(
186
186
  // This allows context providers in initFn to store context on this element.
187
187
  const prevScope = setCurrentScope(element)
188
188
 
189
+ // 8b. Root-level deferred child (dropped-prop fix): a comment-wrapper
190
+ // parent whose entire render is a single deferred child renders as a
191
+ // bare `data-bf-ph` placeholder. The parent's init calls
192
+ // `upsertChild(__scope, ...)` which replaces the placeholder via
193
+ // `replaceWith` — but a detached root node can't replace itself in
194
+ // place. Park it in a throwaway wrapper so the replacement lands
195
+ // somewhere we can recover, then return the materialised child.
196
+ const rootIsDeferredPlaceholder = element.hasAttribute(BF_PLACEHOLDER)
197
+ let placeholderWrapper: HTMLElement | null = null
198
+ if (rootIsDeferredPlaceholder) {
199
+ placeholderWrapper = parseHTML('<div></div>').firstChild as HTMLElement
200
+ placeholderWrapper.appendChild(element)
201
+ }
202
+
189
203
  // 9. Initialize the component (context providers set up here).
190
204
  const initFn = getComponentInit(name)
191
205
  if (initFn) {
192
- // Pass original props (with getters) for reactivity
206
+ // Pass original props (with getters) for reactivity. For a root
207
+ // deferred placeholder, init's `upsertChild(element, ...)` matches the
208
+ // placeholder element itself and replaces it inside the wrapper.
193
209
  initFn(element, props)
194
210
  }
195
211
 
212
+ if (rootIsDeferredPlaceholder && placeholderWrapper) {
213
+ const materialised = placeholderWrapper.firstElementChild as HTMLElement | null
214
+ if (materialised && !materialised.hasAttribute(BF_PLACEHOLDER)) {
215
+ // The deferred child was created in place of the placeholder.
216
+ // `materialised` is the child's OWN element, created via
217
+ // upsertChild -> createComponent, which already registered itself
218
+ // (hydratedScopes / propsMap / registerPropsUpdate) keyed to the
219
+ // child with the child's own props. We must NOT re-register it here:
220
+ // overwriting propsMap/registerPropsUpdate with the *parent's* props
221
+ // would mis-key the child (e.g. a later getComponentProps would read
222
+ // the parent's props), and re-running the parent's init on an element
223
+ // whose placeholder is already gone could not re-materialise. So just
224
+ // restore the scope and return the already-registered child.
225
+ // (Parent-scope effects are unaffected: createEffect ownership lives
226
+ // in the EffectContext tree, not the discarded placeholder element.)
227
+ setCurrentScope(prevScope)
228
+ return materialised
229
+ }
230
+ // Placeholder was not replaced (no init / no matching child): fall
231
+ // through with the original placeholder element detached from wrapper.
232
+ placeholderWrapper.removeChild(element)
233
+ }
234
+
196
235
  // 10. Evaluate getter children and insert them.
197
236
  // Children are evaluated NOW (after initFn) so that context provided by
198
237
  // the parent is in the global store when children call useContext().
@@ -5,7 +5,7 @@
5
5
  * Each component registers its init function so parents can initialize children with props.
6
6
  */
7
7
 
8
- import { BF_SCOPE, BF_HOST } from '@barefootjs/shared'
8
+ import { BF_SCOPE, BF_HOST, BF_PLACEHOLDER } from '@barefootjs/shared'
9
9
  import { hydratedScopes } from './hydration-state'
10
10
  import { setCurrentScope } from './context'
11
11
  import { createComponent } from './component'
@@ -148,8 +148,14 @@ export function upsertChild(
148
148
  return ssr
149
149
  }
150
150
  // CSR: replace placeholder with a freshly-created component.
151
+ // The placeholder is normally a descendant of `parent`; but a
152
+ // comment-scope parent whose root IS the deferred child renders the
153
+ // placeholder as `parent` itself (no wrapper element), so match the
154
+ // parent element directly before falling back to a subtree query.
151
155
  const phId = slotId ?? name
152
- const ph = parent.querySelector(`[data-bf-ph="${phId}"]`) as HTMLElement | null
156
+ const ph = (parent.getAttribute(BF_PLACEHOLDER) === phId
157
+ ? (parent as HTMLElement)
158
+ : parent.querySelector(`[${BF_PLACEHOLDER}="${phId}"]`)) as HTMLElement | null
153
159
  if (ph) {
154
160
  const slot = slotId ? buildSlotInfo(parent, slotId, anchorScope) : undefined
155
161
  const comp = createComponent(name, props, key, slot)