nodality 1.3.4 → 1.3.6

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.
Files changed (207) hide show
  1. package/dist/animator.cjs.js.LICENSE.txt +1 -1
  2. package/dist/animator.esm.js.LICENSE.txt +1 -1
  3. package/dist/audionew.cjs.js.LICENSE.txt +1 -1
  4. package/dist/audionew.esm.js.LICENSE.txt +1 -1
  5. package/dist/base.cjs.js.LICENSE.txt +1 -1
  6. package/dist/base.esm.js.LICENSE.txt +1 -1
  7. package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
  8. package/dist/beta-desktop-bar.esm.js.LICENSE.txt +1 -1
  9. package/dist/beta-mobile-bar.cjs.js.LICENSE.txt +1 -1
  10. package/dist/beta-mobile-bar.esm.js.LICENSE.txt +1 -1
  11. package/dist/bundle.umd.js +1 -1
  12. package/dist/bundle.umd.js.LICENSE.txt +1 -1
  13. package/dist/button.cjs.js.LICENSE.txt +1 -1
  14. package/dist/button.esm.js.LICENSE.txt +1 -1
  15. package/dist/card-getter.cjs.js.LICENSE.txt +1 -1
  16. package/dist/card-getter.esm.js.LICENSE.txt +1 -1
  17. package/dist/center.cjs.js.LICENSE.txt +1 -1
  18. package/dist/center.esm.js.LICENSE.txt +1 -1
  19. package/dist/checkbox.cjs.js.LICENSE.txt +1 -1
  20. package/dist/checkbox.esm.js.LICENSE.txt +1 -1
  21. package/dist/code.cjs.js.LICENSE.txt +1 -1
  22. package/dist/code.esm.js.LICENSE.txt +1 -1
  23. package/dist/container.cjs.js.LICENSE.txt +1 -1
  24. package/dist/container.esm.js.LICENSE.txt +1 -1
  25. package/dist/data-list.cjs.js.LICENSE.txt +1 -1
  26. package/dist/data-list.esm.js.LICENSE.txt +1 -1
  27. package/dist/designer.cjs.js +1 -1
  28. package/dist/designer.cjs.js.LICENSE.txt +1 -1
  29. package/dist/designer.esm.js +1 -1
  30. package/dist/designer.esm.js.LICENSE.txt +1 -1
  31. package/dist/element-mapper.cjs.js +1 -1
  32. package/dist/element-mapper.cjs.js.LICENSE.txt +1 -1
  33. package/dist/element-mapper.esm.js +1 -1
  34. package/dist/element-mapper.esm.js.LICENSE.txt +1 -1
  35. package/dist/finalresult.esm.js +1 -1
  36. package/dist/finalresult.esm.js.LICENSE.txt +1 -1
  37. package/dist/flex-card.cjs.js.LICENSE.txt +1 -1
  38. package/dist/flex-card.esm.js.LICENSE.txt +1 -1
  39. package/dist/flex-grid.cjs.js.LICENSE.txt +1 -1
  40. package/dist/flex-grid.esm.js.LICENSE.txt +1 -1
  41. package/dist/flex-row.cjs.js.LICENSE.txt +1 -1
  42. package/dist/flex-row.esm.js.LICENSE.txt +1 -1
  43. package/dist/floating-input.cjs.js.LICENSE.txt +1 -1
  44. package/dist/floating-input.esm.js.LICENSE.txt +1 -1
  45. package/dist/free.cjs.js.LICENSE.txt +1 -1
  46. package/dist/free.esm.js.LICENSE.txt +1 -1
  47. package/dist/horizontal-scroller.cjs.js.LICENSE.txt +1 -1
  48. package/dist/horizontal-scroller.esm.js.LICENSE.txt +1 -1
  49. package/dist/image-picker.cjs.js.LICENSE.txt +1 -1
  50. package/dist/image-picker.esm.js.LICENSE.txt +1 -1
  51. package/dist/image.cjs.js.LICENSE.txt +1 -1
  52. package/dist/image.esm.js.LICENSE.txt +1 -1
  53. package/dist/index.cjs.js +1 -1
  54. package/dist/index.cjs.js.LICENSE.txt +1 -1
  55. package/dist/index.d.ts +1 -1
  56. package/dist/index.esm.js +1 -1
  57. package/dist/index.esm.js.LICENSE.txt +1 -1
  58. package/dist/keyframe-animation.cjs.js.LICENSE.txt +1 -1
  59. package/dist/keyframe-animation.esm.js.LICENSE.txt +1 -1
  60. package/dist/link-getter.cjs.js.LICENSE.txt +1 -1
  61. package/dist/link-getter.esm.js.LICENSE.txt +1 -1
  62. package/dist/link.cjs.js.LICENSE.txt +1 -1
  63. package/dist/link.esm.js.LICENSE.txt +1 -1
  64. package/dist/meta-adder.cjs.js.LICENSE.txt +1 -1
  65. package/dist/meta-adder.esm.js.LICENSE.txt +1 -1
  66. package/dist/modal-2025.cjs.js.LICENSE.txt +1 -1
  67. package/dist/modal-2025.esm.js.LICENSE.txt +1 -1
  68. package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
  69. package/dist/multiswitcher.esm.js.LICENSE.txt +1 -1
  70. package/dist/new-nav-bar.cjs.js.LICENSE.txt +1 -1
  71. package/dist/new-nav-bar.esm.js.LICENSE.txt +1 -1
  72. package/dist/picker.cjs.js.LICENSE.txt +1 -1
  73. package/dist/picker.esm.js.LICENSE.txt +1 -1
  74. package/dist/progress.cjs.js.LICENSE.txt +1 -1
  75. package/dist/progress.esm.js.LICENSE.txt +1 -1
  76. package/dist/radio.cjs.js.LICENSE.txt +1 -1
  77. package/dist/radio.esm.js.LICENSE.txt +1 -1
  78. package/dist/range.cjs.js.LICENSE.txt +1 -1
  79. package/dist/range.esm.js.LICENSE.txt +1 -1
  80. package/dist/scroll-video.cjs.js.LICENSE.txt +1 -1
  81. package/dist/scroll-video.esm.js.LICENSE.txt +1 -1
  82. package/dist/side-bar.cjs.js.LICENSE.txt +1 -1
  83. package/dist/side-bar.esm.js.LICENSE.txt +1 -1
  84. package/dist/side-nav-bar.cjs.js.LICENSE.txt +1 -1
  85. package/dist/side-nav-bar.esm.js.LICENSE.txt +1 -1
  86. package/dist/simple-bar.cjs.js.LICENSE.txt +1 -1
  87. package/dist/simple-bar.esm.js.LICENSE.txt +1 -1
  88. package/dist/slider-2025.cjs.js.LICENSE.txt +1 -1
  89. package/dist/slider-2025.esm.js.LICENSE.txt +1 -1
  90. package/dist/spacer.cjs.js.LICENSE.txt +1 -1
  91. package/dist/spacer.esm.js.LICENSE.txt +1 -1
  92. package/dist/stack.cjs.js.LICENSE.txt +1 -1
  93. package/dist/stack.esm.js.LICENSE.txt +1 -1
  94. package/dist/stacker.cjs.js.LICENSE.txt +1 -1
  95. package/dist/stacker.esm.js.LICENSE.txt +1 -1
  96. package/dist/table.cjs.js.LICENSE.txt +1 -1
  97. package/dist/table.esm.js.LICENSE.txt +1 -1
  98. package/dist/text-field.cjs.js.LICENSE.txt +1 -1
  99. package/dist/text-field.esm.js.LICENSE.txt +1 -1
  100. package/dist/text.cjs.js.LICENSE.txt +1 -1
  101. package/dist/text.esm.js.LICENSE.txt +1 -1
  102. package/dist/theme.cjs.js.LICENSE.txt +1 -1
  103. package/dist/theme.esm.js.LICENSE.txt +1 -1
  104. package/dist/transform-anim.cjs.js.LICENSE.txt +1 -1
  105. package/dist/transform-anim.esm.js.LICENSE.txt +1 -1
  106. package/dist/ulist.cjs.js +1 -1
  107. package/dist/ulist.cjs.js.LICENSE.txt +1 -1
  108. package/dist/ulist.esm.js +1 -1
  109. package/dist/ulist.esm.js.LICENSE.txt +1 -1
  110. package/dist/video.cjs.js.LICENSE.txt +1 -1
  111. package/dist/video.esm.js.LICENSE.txt +1 -1
  112. package/dist/wrap.cjs.js.LICENSE.txt +1 -1
  113. package/dist/wrap.esm.js.LICENSE.txt +1 -1
  114. package/dist/zoom-card.cjs.js.LICENSE.txt +1 -1
  115. package/dist/zoom-card.esm.js.LICENSE.txt +1 -1
  116. package/layout/animator.js +1 -1
  117. package/layout/audio.js +1 -1
  118. package/layout/audionew.js +1 -1
  119. package/layout/base.js +1 -1
  120. package/layout/beta-desktop-bar.js +1 -1
  121. package/layout/beta-mobile-bar.js +1 -1
  122. package/layout/button.js +1 -1
  123. package/layout/center.js +1 -1
  124. package/layout/checkbox.js +1 -1
  125. package/layout/circle.js +1 -1
  126. package/layout/code.js +1 -1
  127. package/layout/container.js +1 -1
  128. package/layout/dropdown-2025.js +1 -1
  129. package/layout/flex-card.js +1 -1
  130. package/layout/flex-grid.js +1 -1
  131. package/layout/flex-row.js +1 -1
  132. package/layout/form-components/custom.js +1 -1
  133. package/layout/form-components/data-list.js +1 -1
  134. package/layout/form-components/floating-input.js +1 -1
  135. package/layout/form-components/form-all.js +1 -1
  136. package/layout/form-components/form.js +1 -1
  137. package/layout/form-components/image-picker.js +1 -1
  138. package/layout/form-components/picker.js +1 -1
  139. package/layout/form-components/radio.js +1 -1
  140. package/layout/form-components/radiogroup.js +1 -1
  141. package/layout/form-components/range.js +1 -1
  142. package/layout/free.js +1 -1
  143. package/layout/grid-switcher.js +1 -1
  144. package/layout/grid.js +1 -1
  145. package/layout/horizontal-scroller.js +1 -1
  146. package/layout/image.js +1 -1
  147. package/layout/index.js +1 -1
  148. package/layout/link.js +1 -1
  149. package/layout/list.js +1 -1
  150. package/layout/meta-adder.js +1 -1
  151. package/layout/modal-2025.js +1 -1
  152. package/layout/morph.js +1 -1
  153. package/layout/multiswitcher.js +1 -1
  154. package/layout/nav-bar.js +1 -1
  155. package/layout/nav-factor/custom-div.js +1 -1
  156. package/layout/new-nav-bar.js +1 -1
  157. package/layout/polygon.js +1 -1
  158. package/layout/prerender-site.js +1 -1
  159. package/layout/prerender.js +1 -1
  160. package/layout/progress.js +1 -1
  161. package/layout/row.js +1 -1
  162. package/layout/scroll-video.js +1 -1
  163. package/layout/side-bar.js +1 -1
  164. package/layout/side-nav-bar.js +1 -1
  165. package/layout/simple-bar.js +1 -1
  166. package/layout/slider-2025.js +1 -1
  167. package/layout/spacer.js +1 -1
  168. package/layout/stack.js +1 -1
  169. package/layout/svg.js +1 -1
  170. package/layout/switcher.js +1 -1
  171. package/layout/table.js +1 -1
  172. package/layout/text-field.js +1 -1
  173. package/layout/text.js +1 -1
  174. package/layout/ulist.js +16 -1
  175. package/layout/video.js +1 -1
  176. package/layout/wrap.js +1 -1
  177. package/layout/zoom-card.js +1 -1
  178. package/lib/agent-surface.js +1 -1
  179. package/lib/card-getter.js +1 -1
  180. package/lib/check-page.js +1 -1
  181. package/lib/codegen.js +1 -1
  182. package/lib/data.js +1 -1
  183. package/lib/designer.js +1 -1
  184. package/lib/element-mapper.js +98 -5
  185. package/lib/element-params.generated.js +1 -1
  186. package/lib/keyframe-animation.js +1 -1
  187. package/lib/link-getter.js +1 -1
  188. package/lib/morph-node.js +1 -1
  189. package/lib/normalize-spec.js +1 -1
  190. package/lib/parse-html.js +1 -1
  191. package/lib/raster-inspect.js +1 -1
  192. package/lib/raster-ops.js +1 -1
  193. package/lib/raster-presets.js +1 -1
  194. package/lib/resolve-refs.js +1 -1
  195. package/lib/scroll-video.js +1 -1
  196. package/lib/seo.js +1 -1
  197. package/lib/stacker.js +1 -1
  198. package/lib/suggest.js +1 -1
  199. package/lib/theme.js +1 -1
  200. package/lib/transform-anim.js +1 -1
  201. package/lib/transition.js +1 -1
  202. package/lib/validate-nodes.js +83 -2
  203. package/lib/webmcp-adapter.js +1 -1
  204. package/package.json +1 -1
  205. package/schema.json +609 -3264
  206. package/scripts/generate-schema.mjs +102 -12
  207. package/skills/nodality/SKILL.md +20 -2
@@ -138,21 +138,77 @@ function paramsOf(file) {
138
138
  }
139
139
 
140
140
  // ── 6. descriptions from //@ annotations, wherever they live ─────────
141
- const DESCRIPTIONS = {}, DEPRECATED = {};
141
+ //
142
+ // Keyed by the FILE the annotation was found in, not by parameter name alone.
143
+ // A flat name->text map with first-writer-wins looks harmless while every
144
+ // parameter name means one thing across the library, and stops being harmless
145
+ // the moment two components read the same name differently. `items` is that
146
+ // name: the picker documents it as "the choices, each a [value, text] pair",
147
+ // the picker's file was scanned first, and so every composite in the schema --
148
+ // cards, nav, sideNav, table, ulist -- advertised the picker's contract. The
149
+ // MCP `get_schema` tool serves this file, so the on-demand path that §7.4
150
+ // argues for was the path that lied.
151
+ //
152
+ // Params are already resolved per file by paramsOf(); only the descriptions
153
+ // were global. Now both are scoped the same way, and a `//@ <type>.<param>:`
154
+ // annotation overrides for one element type where the mapper, not the
155
+ // component, decides what the slot means.
156
+ const DESC_BY_FILE = new Map(), DEPR_BY_FILE = new Map();
157
+ const DESC_BY_TYPE = {};
158
+ // Names whose meaning depends on the element type, declared with `//@scoped
159
+ // <name>`. For these a description is never BORROWED from a file that does not
160
+ // contribute the parameter: `items` is documented once, in picker.js, and is
161
+ // correct there and wrong for every composite; `type` is documented once, in
162
+ // text-field.js, and means the input's type there and the element's type
163
+ // everywhere else. Neither is ambiguous by the usual test of two files
164
+ // disagreeing -- each has exactly one annotation -- which is why the test has
165
+ // to be declared rather than inferred.
166
+ const SCOPED = new Set();
167
+ // Every annotation, first writer winning, exactly as before this change. Names
168
+ // outside SCOPED still resolve through it, so a parameter documented once in a
169
+ // shared helper -- `mar`, `pad`, `transform` in animator.js -- keeps its
170
+ // description on every type that accepts it.
171
+ const DESC_GLOBAL = {}, DEPR_GLOBAL = {};
142
172
  {
143
173
  const files = new Set(Object.values(IMPORTS)
144
174
  .map((rel) => join(ROOT, "lib", rel)).filter(existsSync));
145
175
  files.add(MAPPER);
146
176
  for (const f of files) {
177
+ const desc = {}, depr = {};
147
178
  for (const line of readFileSync(f, "utf8").split("\n")) {
148
- let m = line.match(/\/\/@deprecated\s+([a-zA-Z][a-zA-Z0-9]*)\s*:\s*(.+)$/);
149
- if (m) { DEPRECATED[m[1]] ??= m[2].trim(); continue; }
179
+ let m = line.match(/\/\/@scoped\s+([a-zA-Z][a-zA-Z0-9]*)\s*$/);
180
+ if (m) { SCOPED.add(m[1]); continue; }
181
+ m = line.match(/\/\/@deprecated\s+([a-zA-Z][a-zA-Z0-9]*)\s*:\s*(.+)$/);
182
+ if (m) { depr[m[1]] ??= m[2].trim(); DEPR_GLOBAL[m[1]] ??= m[2].trim(); continue; }
183
+ // Qualified first: `//@ cards.items: …` binds to one type only.
184
+ m = line.match(/\/\/@\s+([a-zA-Z][a-zA-Z0-9]*)\.([a-zA-Z][a-zA-Z0-9]*)\s*:\s*(.+)$/);
185
+ if (m) { (DESC_BY_TYPE[m[1]] ??= {})[m[2]] ??= m[3].trim(); continue; }
150
186
  m = line.match(/\/\/@\s+([a-zA-Z][a-zA-Z0-9]*)\s*:\s*(.+)$/);
151
- if (m) DESCRIPTIONS[m[1]] ??= m[2].trim();
187
+ if (m) { desc[m[1]] ??= m[2].trim(); DESC_GLOBAL[m[1]] ??= m[2].trim(); }
152
188
  }
189
+ DESC_BY_FILE.set(f, desc); DEPR_BY_FILE.set(f, depr);
153
190
  }
154
191
  }
155
192
 
193
+ /**
194
+ * Look a parameter's annotation up along the chain that actually built the
195
+ * type: the type's own qualified override, then the files of the components it
196
+ * assembles, then the mapper. A parameter no component of this type documents
197
+ * gets no description, which is the honest answer and strictly better than
198
+ * another type's.
199
+ */
200
+ function annotationFor(table, name, from, type, qualified) {
201
+ if (qualified && DESC_BY_TYPE[type] && DESC_BY_TYPE[type][name]) {
202
+ return DESC_BY_TYPE[type][name];
203
+ }
204
+ for (const f of from) {
205
+ const got = table.get(f);
206
+ if (got && got[name]) return got[name];
207
+ }
208
+ if (SCOPED.has(name)) return undefined;
209
+ return (qualified ? DESC_GLOBAL : DEPR_GLOBAL)[name];
210
+ }
211
+
156
212
  // ── 7. assemble ──────────────────────────────────────────────────────
157
213
  const schema = { generated: "scripts/generate-schema.mjs", types: {} };
158
214
  let resolved = 0;
@@ -167,6 +223,14 @@ for (const type of TYPES) {
167
223
  const b = methodBody(name);
168
224
  let out = b;
169
225
  for (const m of b.matchAll(/\bthis\.([a-zA-Z][a-zA-Z0-9_]*)\s*\(/g)) {
226
+ // NOT through mapType. It is the dispatcher: a composite calls it to
227
+ // build its CHILDREN, which are separate elements with their own types
228
+ // and their own schema entries. Following it made every composite
229
+ // inherit the whole library -- which is why `nav` advertised 157
230
+ // parameters for a component that has no `set()` at all, and `cards`
231
+ // 141. Those were its children's parameters, and its children's
232
+ // children's, reported as its own.
233
+ if (m[1] === "mapType") continue;
170
234
  if (seen.size < 12) out += "\n" + bodyOf(m[1], seen);
171
235
  }
172
236
  return out;
@@ -175,30 +239,56 @@ for (const type of TYPES) {
175
239
  const classes = body ? classesIn(body) : [];
176
240
  const files = classes.map(fileFor).filter(Boolean);
177
241
 
242
+ // Which file contributed each parameter. The description lookup walks this
243
+ // rather than the whole component list, so a parameter is documented by the
244
+ // file that actually reads it and by nothing else. Scoping to the type's
245
+ // components alone was not enough: `alt` is contributed to `img` by
246
+ // image.js, and an annotation living in any other file would have been
247
+ // dropped -- which cost `img.alt` its description on the first attempt at
248
+ // this fix, the one parameter the comment in paramsOf() exists to protect.
178
249
  const params = new Set();
179
- for (const f of files) for (const p of paramsOf(f)) params.add(p);
250
+ const from = new Map();
251
+ const contributed = (name, file) => {
252
+ params.add(name);
253
+ if (!from.has(name)) from.set(name, []);
254
+ if (!from.get(name).includes(file)) from.get(name).push(file);
255
+ };
256
+ for (const f of files) for (const p of paramsOf(f)) contributed(p, f);
180
257
 
181
258
  // The mapper's OWN `el.<name>` reads. Scanning components alone missed
182
259
  // these, because a mapper often passes an element field as a constructor
183
260
  // argument rather than an option — `new Text(el.text)`. That left `text`
184
261
  // off every heading, which would have been the single worst error the
185
262
  // schema could contain: the most-used parameter of the most-used type.
186
- for (const m of body.matchAll(/\bel\.([a-zA-Z][a-zA-Z0-9]*)/g)) params.add(m[1]);
263
+ for (const m of body.matchAll(/\bel\.([a-zA-Z][a-zA-Z0-9]*)/g)) contributed(m[1], MAPPER);
187
264
 
188
265
  // Read off the element by every mapper regardless of component.
189
- for (const p of ["type", "id"]) params.add(p);
266
+ for (const p of ["type", "id"]) contributed(p, MAPPER);
190
267
 
268
+ // NOTE. A `settable` flag was attempted here and removed. The question it
269
+ // was meant to answer -- which of these parameters an AUTHOR can set on the
270
+ // element, as opposed to which the components READ -- is real and still
271
+ // open, but no static rule tried here agreed with what rendering shows. The
272
+ // heuristic marked 151 of nav's parameters settable for a component that
273
+ // accepts none, and a schema that states a falsehood in a new field is worse
274
+ // than one that states less. What IS fixed below is the largest part of the
275
+ // over-claim: composites no longer inherit their children's vocabulary.
191
276
  const ok = files.length > 0;
192
277
  if (ok) resolved++;
193
278
  schema.types[type] = {
194
279
  resolved: ok,
195
280
  mapper: method,
196
281
  components: classes,
197
- params: [...params].sort().map((name) => ({
198
- name,
199
- ...(DESCRIPTIONS[name] ? { description: DESCRIPTIONS[name] } : {}),
200
- ...(DEPRECATED[name] ? { deprecated: DEPRECATED[name] } : {}),
201
- })),
282
+ params: [...params].sort().map((name) => {
283
+ const where = from.get(name) || [];
284
+ const description = annotationFor(DESC_BY_FILE, name, where, type, true);
285
+ const deprecated = annotationFor(DEPR_BY_FILE, name, where, type, false);
286
+ return {
287
+ name,
288
+ ...(description ? { description } : {}),
289
+ ...(deprecated ? { deprecated } : {}),
290
+ };
291
+ }),
202
292
  };
203
293
  }
204
294
  schema.summary = { types: TYPES.length, resolved, unresolved: TYPES.length - resolved };
@@ -89,8 +89,26 @@ key you use is part of the type**:
89
89
 
90
90
  | slot | types |
91
91
  |---|---|
92
- | `items` | `cards`, `nav`, `sideNav`, `table`, `ulist` |
93
- | `children` | `row`, `form`, `wrap` |
92
+ | `items` | `cards`, `nav`, `sideNav`, `table`, `ulist`, `dropdown`, `picker`, `radio` |
93
+ | `children` | `row`, `form`, `stack`, `wrap` |
94
+
95
+ And **what an entry may be depends on the type**, because an element spec is
96
+ not accepted everywhere:
97
+
98
+ | type | an entry is |
99
+ |---|---|
100
+ | `cards` | `{ title, link, img }`, or an **array** of element specs |
101
+ | `nav`, `sideNav` | `{ title, link }`, or a string |
102
+ | `table` | `{ title, link }` / `{ text, url }`, a `[value, text]` pair, or an element spec |
103
+ | `ulist` | an element spec, or a string |
104
+ | `dropdown`, `picker` | a string, or a `[value, text]` pair |
105
+ | `radio` | a string |
106
+
107
+ Writing `items: [{ type: "h2", text: "…" }]` on `cards` or `nav` is the one
108
+ mistake worth naming, because it is well-formed and does nothing: `cards`
109
+ renders an empty card and `nav` drops the entry. Wrap it — `items: [[{ type:
110
+ "h2", … }]]` — and `cards` builds a card containing it. `validate_nodes`
111
+ reports this as `WRONG_ITEM_SHAPE` and hands back the corrected entry.
94
112
 
95
113
  ```js
96
114
  { type: "cards", items: [ // shorthand