@gjsify/adwaita-web 0.64.12-next.280 → 0.64.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.
@@ -101,6 +101,8 @@ interface BuildRecord {
101
101
  menus?: SharedTreeNode['menus'];
102
102
  /** Present when the tree is the template of a registered class (ADR 0096): handlers and binds go through it. */
103
103
  template?: TemplateScope;
104
+ /** A template's handler connections, made once every id exists: `object=` may name a node built later. */
105
+ connects?: (() => void)[];
104
106
  }
105
107
 
106
108
  /** Calls `onSize` with the host's measured size, now and on every change; returns its disposer. */
@@ -229,13 +231,8 @@ function refuseSiblings(node: SharedTreeNode, door: string): void {
229
231
  );
230
232
  }
231
233
 
232
- /** Every node, its siblings in the same id scope, then the binds and breakpoints that name them. */
233
- function buildTree(node: SharedTreeNode, record: BuildRecord): BuiltTree {
234
- // ADR 0093 § 2: the whole tree is checked against the capability table before an element is
235
- // created. A refused `layout` is named with its node and the reason the table gives.
236
- assertTreeConstructs('adwaita-web', capabilities, node, Object.keys(ARIA_OF));
237
- if (node.menus !== undefined) record.menus = node.menus;
238
- const root = buildNode(node, record);
234
+ /** The sibling objects of `node` built in `record`'s id scope, by id; each has to have one, or nothing could ask for it. */
235
+ function buildSiblings(node: SharedTreeNode, record: BuildRecord): Map<string, HTMLElement> {
239
236
  const siblings = new Map<string, HTMLElement>();
240
237
  for (const sibling of node.siblings ?? []) {
241
238
  if (sibling.id === undefined) {
@@ -245,6 +242,17 @@ function buildTree(node: SharedTreeNode, record: BuildRecord): BuiltTree {
245
242
  }
246
243
  siblings.set(sibling.id, buildNode(sibling, record));
247
244
  }
245
+ return siblings;
246
+ }
247
+
248
+ /** Every node, its siblings in the same id scope, then the binds and breakpoints that name them. */
249
+ function buildTree(node: SharedTreeNode, record: BuildRecord): BuiltTree {
250
+ // ADR 0093 § 2: the whole tree is checked against the capability table before an element is
251
+ // created. A refused `layout` is named with its node and the reason the table gives.
252
+ assertTreeConstructs('adwaita-web', capabilities, node, Object.keys(ARIA_OF));
253
+ if (node.menus !== undefined) record.menus = node.menus;
254
+ const root = buildNode(node, record);
255
+ const siblings = buildSiblings(node, record);
248
256
  for (const bind of record.binds) bindProperty(bind, record);
249
257
  for (const host of record.breakpointHosts) bindBreakpoints(host.el, host.node, record);
250
258
  return { root, siblings, objects: new Map(record.ids) };
@@ -265,7 +273,7 @@ function newRecord(
265
273
  disposers: [],
266
274
  ...(scope === undefined ? {} : { scope }),
267
275
  ...(observeSize === undefined ? {} : { observeSize }),
268
- ...(template === undefined ? {} : { template }),
276
+ ...(template === undefined ? {} : { template, connects: [] }),
269
277
  };
270
278
  }
271
279
 
@@ -606,9 +614,13 @@ export interface BuiltTemplateTree {
606
614
  * to their handlers and binds through `scope`, none appended and nothing written to `host`'s
607
615
  * attributes, because `host` is still inside its constructor. `finish` and the caller's own append
608
616
  * belong to the first `connectedCallback`.
617
+ *
618
+ * Objects written beside the template (`Adw.AlertDialog dialog { }`, `$Learn learn { }`) are built in
619
+ * the same id scope and named in `objects`, which is what `InternalChildren` and `Children` read —
620
+ * `gtk_widget_class_bind_template_child` reaches any object id of the template's builder. They are
621
+ * not in `children`: a sibling is an independent object, placed by the class or not at all.
609
622
  */
610
623
  export function buildTemplateTree(tree: SharedTreeNode, scope: TemplateScope, host: HTMLElement): BuiltTemplateTree {
611
- refuseSiblings(tree, 'buildTemplateTree');
612
624
  assertTreeConstructs('adwaita-web', capabilities, tree, Object.keys(ARIA_OF));
613
625
  const record = newRecord(undefined, undefined, scope);
614
626
  record.menus = tree.menus;
@@ -616,6 +628,8 @@ export function buildTemplateTree(tree: SharedTreeNode, scope: TemplateScope, ho
616
628
  collectNode(host, tree, record);
617
629
  bindSignals(host, tree, record);
618
630
  const children = buildChildren(host, tree, record);
631
+ buildSiblings(tree, record);
632
+ for (const connect of record.connects ?? []) connect();
619
633
  for (const bind of record.binds) bindProperty(bind, record);
620
634
  for (const breakpointHost of record.breakpointHosts) {
621
635
  bindBreakpoints(breakpointHost.el, breakpointHost.node, record);
@@ -648,21 +662,26 @@ function bindSignals(el: HTMLElement, node: SharedTreeNode, record: BuildRecord)
648
662
  `the handler '${signal.handler}' for '${name}' uses after, which is not in the GObject subset.`,
649
663
  );
650
664
  }
651
- const object =
652
- signal.object === undefined
653
- ? undefined
654
- : signal.object === 'template'
655
- ? record.template.instance
656
- : record.ids.get(signal.object);
657
- if (signal.object !== undefined && object === undefined) {
658
- throw new Error(
659
- `the handler '${signal.handler}' for '${name}' names the object '${signal.object}', which nothing in this tree has.`,
665
+ const template = record.template;
666
+ // `object=` is resolved when the whole tree exists, as `gtk_builder_connect_signals` does: it may
667
+ // name a node built after this one, or a sibling object written beside the template.
668
+ record.connects!.push(() => {
669
+ const object =
670
+ signal.object === undefined
671
+ ? undefined
672
+ : signal.object === 'template'
673
+ ? template.instance
674
+ : record.ids.get(signal.object);
675
+ if (signal.object !== undefined && object === undefined) {
676
+ throw new Error(
677
+ `the handler '${signal.handler}' for '${name}' names the object '${signal.object}', which nothing in this tree has.`,
678
+ );
679
+ }
680
+ (el as unknown as GObjectInstance).connect(
681
+ name,
682
+ template.handler(signal.handler, { object, flags: signal.flags }),
660
683
  );
661
- }
662
- (el as unknown as GObjectInstance).connect(
663
- name,
664
- record.template.handler(signal.handler, { object, flags: signal.flags }),
665
- );
684
+ });
666
685
  continue;
667
686
  }
668
687
  if (signal.object !== undefined || (signal.flags?.length ?? 0) > 0) {
@@ -51,8 +51,8 @@ export const AdwValueListsTest = async () => {
51
51
  await it(vector.rule, () => {
52
52
  mounted(blueprintTree(vector.blueprint), (root) => {
53
53
  if (vector.strings !== undefined) {
54
- const model = (root as unknown as Pick<AdwComboRow, 'model'>).model;
55
- expect(JSON.stringify(model.map((option) => option.label))).toBe(
54
+ const options = (root as unknown as Pick<AdwComboRow, 'options'>).options;
55
+ expect(JSON.stringify(options.map((option) => option.label))).toBe(
56
56
  JSON.stringify(vector.strings),
57
57
  );
58
58
  expect(JSON.stringify(paintedOptions(root))).toBe(JSON.stringify(vector.strings));