stitch2 0.22.9 → 0.22.10

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/elements.js CHANGED
@@ -37,14 +37,22 @@ export const screenLocale = () => globalThis.__stitch2?.lang;
37
37
  */
38
38
  let idCount = 0;
39
39
  const ID_REFS = ['for', 'aria-labelledby', 'aria-describedby', 'aria-controls', 'aria-owns', 'aria-activedescendant', 'list'];
40
- function uniqueIds(content) {
40
+ function uniqueIds(content, replacing) {
41
+ // The element's children are about to be replaced, not duplicated. Their IDs may also be
42
+ // referenced from outside the component (labels, descriptions and navigation anchors).
43
+ const occupied = new Set(Array.from(document.querySelectorAll('[id]'))
44
+ .filter((el) => !replacing.contains(el)).map((el) => el.id));
41
45
  const renamed = new Map();
42
46
  for (const el of Array.from(content.querySelectorAll('[id]'))) {
43
- if (!document.getElementById(el.id))
47
+ if (!occupied.has(el.id))
44
48
  continue;
45
- const next = el.id + '-s2-' + ++idCount;
49
+ let next;
50
+ do
51
+ next = el.id + '-s2-' + ++idCount;
52
+ while (occupied.has(next) || content.getElementById(next));
46
53
  renamed.set(el.id, next);
47
54
  el.id = next;
55
+ occupied.add(next);
48
56
  }
49
57
  if (!renamed.size)
50
58
  return;
@@ -95,7 +103,7 @@ export function defineElements(components, options) {
95
103
  if (typeof props[key] === 'string' && !root.hasAttribute(`data-${key}`))
96
104
  root.setAttribute(`data-${key}`, props[key]);
97
105
  }
98
- uniqueIds(t.content);
106
+ uniqueIds(t.content, this);
99
107
  this.replaceWith(t.content);
100
108
  if (options.after && !pending++)
101
109
  queueMicrotask(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitch2",
3
- "version": "0.22.9",
3
+ "version": "0.22.10",
4
4
  "description": "A design canvas, layout and type checks, component consistency and screen versioning for agent-built UI, on Google's DESIGN.md format.",
5
5
  "license": "MIT",
6
6
  "author": "ifokeev",
@@ -61,6 +61,10 @@ never patch the bundle or restyle the element on a screen. Props are the element
61
61
  an empty attribute is true) and its content is children. A component the screens need but the app lacks is
62
62
  added to the app first, with the same name.
63
63
 
64
+ Keep native field IDs and their external label, ARIA and fragment references stable when nesting components.
65
+ `stitch2/elements` preserves IDs from the element being replaced; only real collisions outside that element
66
+ are renamed, together with references inside the component. Test both cases when changing a shared form.
67
+
64
68
  ## Colours come from DESIGN.md
65
69
 
66
70
  Every colour on a screen and in a component is one of DESIGN.md's: a token class (`bg-surface`,