dsh-motion-ui 0.5.6 → 0.7.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.
Files changed (164) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/README.md +112 -4
  3. package/VERIFICATION.md +145 -0
  4. package/client.js +4869 -22533
  5. package/examples/mechanism-assembly.json +50 -0
  6. package/examples/mechanism-crank.json +103 -0
  7. package/examples/mechanism-gears.json +103 -0
  8. package/index.js +52 -15
  9. package/lib/assets/echarts-core.js +47 -0
  10. package/lib/assets/echarts-full.js +78 -0
  11. package/lib/assets/katex-fonts/KaTeX_AMS-Regular.woff2 +0 -0
  12. package/lib/assets/katex-fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  13. package/lib/assets/katex-fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  14. package/lib/assets/katex-fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  15. package/lib/assets/katex-fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  16. package/lib/assets/katex-fonts/KaTeX_Main-Bold.woff2 +0 -0
  17. package/lib/assets/katex-fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  18. package/lib/assets/katex-fonts/KaTeX_Main-Italic.woff2 +0 -0
  19. package/lib/assets/katex-fonts/KaTeX_Main-Regular.woff2 +0 -0
  20. package/lib/assets/katex-fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  21. package/lib/assets/katex-fonts/KaTeX_Math-Italic.woff2 +0 -0
  22. package/lib/assets/katex-fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  23. package/lib/assets/katex-fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  24. package/lib/assets/katex-fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  25. package/lib/assets/katex-fonts/KaTeX_Script-Regular.woff2 +0 -0
  26. package/lib/assets/katex-fonts/KaTeX_Size1-Regular.woff2 +0 -0
  27. package/lib/assets/katex-fonts/KaTeX_Size2-Regular.woff2 +0 -0
  28. package/lib/assets/katex-fonts/KaTeX_Size3-Regular.woff2 +0 -0
  29. package/lib/assets/katex-fonts/KaTeX_Size4-Regular.woff2 +0 -0
  30. package/lib/assets/katex-fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  31. package/lib/assets/katex.css +1 -0
  32. package/lib/assets/mermaid.js +3644 -0
  33. package/lib/assets/standalone-runtime.css +1 -0
  34. package/lib/assets/standalone-runtime.js +330 -0
  35. package/lib/assets/three.js +3842 -0
  36. package/lib/assets/visual.css +1 -0
  37. package/lib/assets/visual.js +416 -0
  38. package/lib/author-expression.js +3 -2
  39. package/lib/authoring-guide.js +4 -3
  40. package/lib/build-info.js +1 -1
  41. package/lib/canvas-system.js +3 -3
  42. package/lib/catalog.js +94 -92
  43. package/lib/components.js +11 -6
  44. package/lib/delivery.js +18 -0
  45. package/lib/diagnostics-route.js +6 -0
  46. package/lib/document-update.js +27 -0
  47. package/lib/export-runtime-bundle.js +1 -1
  48. package/lib/expressive-examples.js +6 -0
  49. package/lib/fence-feedback.js +61 -0
  50. package/lib/fence-route.js +14 -0
  51. package/lib/fences.js +9 -0
  52. package/lib/freeform.js +4 -3
  53. package/lib/inspection.js +3 -2
  54. package/lib/links.js +13 -0
  55. package/lib/mechanism-catalog.js +24 -0
  56. package/lib/mechanism-css.js +13 -0
  57. package/lib/mechanism-entry.js +20 -0
  58. package/lib/mechanism-geometry.js +62 -0
  59. package/lib/mechanism-render.js +24 -0
  60. package/lib/mechanism-runtime-bundle.js +2 -0
  61. package/lib/mechanism-scenes.js +20 -0
  62. package/lib/motion-library.js +18 -0
  63. package/lib/normalize-authoring.js +52 -3
  64. package/lib/normalize-visual.js +36 -0
  65. package/lib/presentation.js +1 -1
  66. package/lib/protocol.js +361 -318
  67. package/lib/sandbox.js +2 -0
  68. package/lib/scene-library.js +13 -0
  69. package/lib/store.js +17 -2
  70. package/lib/stream.js +12 -0
  71. package/lib/style-system.js +28 -0
  72. package/lib/text-document.js +25 -0
  73. package/lib/text-guide.js +13 -0
  74. package/lib/third-party/anatomy-LICENSE.txt +21 -0
  75. package/lib/third-party/anatomy-NOTICE.md +13 -0
  76. package/lib/third-party/anatomy-iso.mjs +674 -0
  77. package/lib/third-party/bundled/@braintree_sanitize-url-LICENSE +21 -0
  78. package/lib/third-party/bundled/@iconify_utils-license.txt +21 -0
  79. package/lib/third-party/bundled/@mermaid-js_parser-LICENSE +21 -0
  80. package/lib/third-party/bundled/@upsetjs_venn.js-LICENSE +22 -0
  81. package/lib/third-party/bundled/cose-base-LICENSE +21 -0
  82. package/lib/third-party/bundled/cytoscape-LICENSE +19 -0
  83. package/lib/third-party/bundled/cytoscape-cose-bilkent-LICENSE +21 -0
  84. package/lib/third-party/bundled/cytoscape-fcose-LICENSE +19 -0
  85. package/lib/third-party/bundled/cytoscape-license-update.mjs +32 -0
  86. package/lib/third-party/bundled/d3-LICENSE +13 -0
  87. package/lib/third-party/bundled/d3-array-LICENSE +27 -0
  88. package/lib/third-party/bundled/d3-axis-LICENSE +13 -0
  89. package/lib/third-party/bundled/d3-brush-LICENSE +13 -0
  90. package/lib/third-party/bundled/d3-chord-LICENSE +13 -0
  91. package/lib/third-party/bundled/d3-color-LICENSE +13 -0
  92. package/lib/third-party/bundled/d3-contour-LICENSE +13 -0
  93. package/lib/third-party/bundled/d3-delaunay-LICENSE +14 -0
  94. package/lib/third-party/bundled/d3-dispatch-LICENSE +13 -0
  95. package/lib/third-party/bundled/d3-drag-LICENSE +13 -0
  96. package/lib/third-party/bundled/d3-dsv-LICENSE +13 -0
  97. package/lib/third-party/bundled/d3-ease-LICENSE +28 -0
  98. package/lib/third-party/bundled/d3-fetch-LICENSE +13 -0
  99. package/lib/third-party/bundled/d3-force-LICENSE +13 -0
  100. package/lib/third-party/bundled/d3-format-LICENSE +13 -0
  101. package/lib/third-party/bundled/d3-geo-LICENSE +34 -0
  102. package/lib/third-party/bundled/d3-hierarchy-LICENSE +13 -0
  103. package/lib/third-party/bundled/d3-interpolate-LICENSE +13 -0
  104. package/lib/third-party/bundled/d3-path-LICENSE +27 -0
  105. package/lib/third-party/bundled/d3-polygon-LICENSE +13 -0
  106. package/lib/third-party/bundled/d3-quadtree-LICENSE +13 -0
  107. package/lib/third-party/bundled/d3-random-LICENSE +13 -0
  108. package/lib/third-party/bundled/d3-sankey-LICENSE +27 -0
  109. package/lib/third-party/bundled/d3-scale-LICENSE +13 -0
  110. package/lib/third-party/bundled/d3-scale-chromatic-LICENSE +28 -0
  111. package/lib/third-party/bundled/d3-selection-LICENSE +13 -0
  112. package/lib/third-party/bundled/d3-shape-LICENSE +13 -0
  113. package/lib/third-party/bundled/d3-time-LICENSE +13 -0
  114. package/lib/third-party/bundled/d3-time-format-LICENSE +13 -0
  115. package/lib/third-party/bundled/d3-timer-LICENSE +13 -0
  116. package/lib/third-party/bundled/d3-transition-LICENSE +13 -0
  117. package/lib/third-party/bundled/d3-zoom-LICENSE +13 -0
  118. package/lib/third-party/bundled/dagre-d3-es-LICENSE.md +23 -0
  119. package/lib/third-party/bundled/dayjs-LICENSE +21 -0
  120. package/lib/third-party/bundled/delaunator-LICENSE +15 -0
  121. package/lib/third-party/bundled/dompurify-LICENSE +202 -0
  122. package/lib/third-party/bundled/dompurify-LICENSE-MPL +373 -0
  123. package/lib/third-party/bundled/echarts-LICENSE +222 -0
  124. package/lib/third-party/bundled/echarts-NOTICE +5 -0
  125. package/lib/third-party/bundled/es-toolkit-LICENSE +21 -0
  126. package/lib/third-party/bundled/es-toolkit-NOTICE +39 -0
  127. package/lib/third-party/bundled/internmap-LICENSE +13 -0
  128. package/lib/third-party/bundled/katex-LICENSE +21 -0
  129. package/lib/third-party/bundled/khroma-license +21 -0
  130. package/lib/third-party/bundled/layout-base-LICENSE +21 -0
  131. package/lib/third-party/bundled/lodash-es-LICENSE +47 -0
  132. package/lib/third-party/bundled/marked-LICENSE.md +44 -0
  133. package/lib/third-party/bundled/mermaid-LICENSE +21 -0
  134. package/lib/third-party/bundled/react-LICENSE +21 -0
  135. package/lib/third-party/bundled/react-dom-LICENSE +21 -0
  136. package/lib/third-party/bundled/robust-predicates-LICENSE +24 -0
  137. package/lib/third-party/bundled/roughjs-LICENSE +21 -0
  138. package/lib/third-party/bundled/scheduler-LICENSE +21 -0
  139. package/lib/third-party/bundled/stylis-LICENSE +21 -0
  140. package/lib/third-party/bundled/three-LICENSE +21 -0
  141. package/lib/third-party/bundled/ts-dedent-LICENSE +21 -0
  142. package/lib/third-party/bundled/tslib-LICENSE.txt +12 -0
  143. package/lib/third-party/bundled/uuid-LICENSE.md +9 -0
  144. package/lib/third-party/bundled/zrender-LICENSE +29 -0
  145. package/lib/third-party/dsh-genui-LICENSE.txt +21 -0
  146. package/lib/third-party/dsh-genui-NOTICE.md +26 -0
  147. package/lib/third-party/echarts-LICENSE.txt +222 -0
  148. package/lib/third-party/echarts-NOTICE.txt +5 -0
  149. package/lib/third-party/katex-LICENSE.txt +21 -0
  150. package/lib/third-party/lucian-uxui-LICENSE.txt +21 -0
  151. package/lib/third-party/lucian-uxui-NOTICE.md +1 -0
  152. package/lib/third-party/mermaid-LICENSE.txt +21 -0
  153. package/lib/third-party/three-LICENSE.txt +21 -0
  154. package/lib/tool-schema.js +20 -9
  155. package/lib/typography.js +16 -0
  156. package/lib/ui-intent.js +15 -14
  157. package/lib/ui-skill.js +54 -47
  158. package/lib/visual-assets.js +7 -0
  159. package/lib/visual-defaults.js +2 -0
  160. package/lib/visual-guard.js +2 -0
  161. package/lib/visual-styles.js +142 -0
  162. package/lib/visual.js +40 -0
  163. package/package.json +20 -5
  164. package/skills/intelligent-ui/SKILL.md +22 -2
@@ -1,10 +1,12 @@
1
1
  // Lossless transport repairs only at protocol-typed positions. Never traverse
2
2
  // arbitrary data/state payloads or rewrite labels, HTML, CSS or JavaScript.
3
3
  const object = v => v !== null && typeof v === 'object' && !Array.isArray(v);
4
+ import {visualDocument,VISUAL_TYPES} from './visual.js';
5
+ import {COMPONENTS} from './components.js';
4
6
  const own = (v,k) => Object.hasOwn(v,k);
5
7
  const singleItem = v => object(v) && Object.keys(v).length === 1 && own(v,'item');
6
- const array = v => singleItem(v) && Array.isArray(v.item) ? v.item : v;
7
- const numericOps = new Set(['add','sub','mul','div','min','max','round','abs','lt','lte','gt','gte']);
8
+ const array = v => {let candidate=v;for(let i=0;i<8&&singleItem(candidate);i++)candidate=candidate.item;return Array.isArray(candidate)?candidate:v};
9
+ const numericOps = new Set(['add','sub','mul','div','min','max','round','ceil','floor','abs','lt','lte','gt','gte']);
8
10
  function number(v) {
9
11
  if (typeof v !== 'string' || !/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(v.trim())) return v;
10
12
  const n = Number(v);
@@ -23,6 +25,8 @@ function expression(e, numeric = false, logical = false) {
23
25
  return e;
24
26
  }
25
27
  export function normalizeAuthoring(doc) {
28
+ if (Array.isArray(doc)) doc=visualDocument(doc);
29
+ if (object(doc)&&!own(doc,'nodes')&&(own(doc,'items')||typeof doc.type==='string')) doc=visualDocument(doc);
26
30
  if (!object(doc)) return doc;
27
31
  if (own(doc,'version')) doc.version = number(doc.version);
28
32
  if (object(doc.state)) for (const k of Object.keys(doc.state)) {
@@ -50,14 +54,59 @@ export function normalizeAuthoring(doc) {
50
54
  if (!Array.isArray(list)) return list;
51
55
  for (const node of list) {
52
56
  if (!object(node)) continue;
57
+ if(['text','heading','callout'].includes(node.type)&&own(node,'content')){
58
+ // Collapse aliases only when no conflicting content would be lost.
59
+ if(!own(node,'text')){node.text=node.content;delete node.content}
60
+ else if(node.text===node.content)delete node.content;
61
+ }
62
+ if(['text','heading','callout'].includes(node.type)&&typeof node.text==='string'){
63
+ const spans=array(node.spans);
64
+ if(Array.isArray(spans)&&spans.every(s=>object(s)&&typeof s.text==='string')&&spans.map(s=>s.text).join('')===node.text)delete node.text;
65
+ }
66
+ if(node.type==='table'&&own(node,'types')){
67
+ const columns=array(node.columns),rows=array(node.rows),types=array(node.types);
68
+ const allowed=['id','type','label','columns','rows','types'];
69
+ if(Object.keys(node).every(k=>allowed.includes(k))&&Array.isArray(columns)&&columns.length&&columns.every(c=>object(c)&&typeof c.key==='string'&&typeof c.label==='string'&&Object.keys(c).every(k=>['key','label','unit'].includes(k)))&&new Set(columns.map(c=>c.key)).size===columns.length&&Array.isArray(rows)&&rows.every(object)&&Array.isArray(types)&&types.length===columns.length&&types.every(t=>['text','num','delta','bar','badge'].includes(t))){
70
+ const spec={...(node.label?{title:node.label}:{}),items:[{type:'table',columns:columns.map(c=>c.label+(c.unit?` (${c.unit})`:'')),rows:rows.map(row=>columns.map(c=>row[c.key]??null)),types}]},id=node.id;
71
+ for(const k of Object.keys(node))delete node[k];
72
+ Object.assign(node,{...(id!==undefined?{id}:{}),type:'visual',spec});
73
+ }
74
+ }
75
+ // Extended-only nodes have an unambiguous native visual wrapper. Keep
76
+ // the author's ID so mixed documents need no extra repair round.
77
+ if(typeof node.id==='string'&&VISUAL_TYPES.includes(node.type)&&!own(COMPONENTS,node.type)){
78
+ const spec={items:[{...node}]},id=node.id;
79
+ for(const k of Object.keys(node))delete node[k];
80
+ Object.assign(node,{id,type:'visual',spec});
81
+ }
82
+ // Positional cells map losslessly to an explicit ordered, unique column list.
83
+ if(node.type==='table'&&Array.isArray(node.columns)&&node.columns.length&&node.columns.every(c=>object(c)&&typeof c.key==='string')&&new Set(node.columns.map(c=>c.key)).size===node.columns.length&&Array.isArray(node.rows)&&node.rows.every(row=>Array.isArray(row)&&row.length===node.columns.length)){
84
+ node.rows=node.rows.map(row=>Object.fromEntries(node.columns.map((c,i)=>[c.key,row[i]])));
85
+ }
86
+ if(node.type==='table'&&Array.isArray(node.columns)&&node.columns.length&&Array.isArray(node.rows)&&node.rows.every(Array.isArray)&&node.columns.every(c=>object(c)&&Number.isInteger(c.key)&&c.key>=0)&&new Set(node.columns.map(c=>c.key)).size===node.columns.length){
87
+ const columns=node.columns.map(c=>({...c,key:'col_'+c.key}));
88
+ node.rows=node.rows.map(row=>Object.fromEntries(node.columns.map(c=>['col_'+c.key,row[c.key]??null])));node.columns=columns;
89
+ }
90
+ if(node.type==='visual'&&typeof node.id==='string'){
91
+ node.stateKey??='visual_'+node.id;doc.state??={};
92
+ if(!own(doc.state,node.stateKey))doc.state[node.stateKey]={type:'json',default:{}};
93
+ }
53
94
  if (node.type === 'sandbox') {
54
95
  if (!own(node,'title')) node.title = doc.title;
55
96
  if (!own(node,'fallback')) node.fallback = doc.fallback;
56
97
  }
57
- for (const field of ['children','items','columns','stateKeys','dataKeys','derivedKeys']) if (own(node,field)) node[field] = array(node[field]);
98
+ for (const field of ['children','items','columns','libraries','stateKeys','dataKeys','derivedKeys']) if (own(node,field)) node[field] = array(node[field]);
58
99
  if (['table','chart'].includes(node.type) && own(node,'rows')) node.rows = array(node.rows);
59
100
  for (const field of ['decimals','height']) if (own(node,field)) node[field] = number(node[field]);
101
+ if(['row','column'].includes(node.type)){if(own(node,'gap'))node.gap=number(node.gap);if(node.type==='row'&&own(node,'columns'))node.columns=number(node.columns)}
102
+ if(['text','heading','callout'].includes(node.type)){
103
+ for(const field of ['size','weight','lineHeight'])if(own(node,field))node[field]=number(node[field]);
104
+ if(own(node,'spans'))node.spans=array(node.spans);
105
+ if(Array.isArray(node.spans))for(const span of node.spans)if(object(span))for(const field of ['size','weight','lineHeight'])if(own(span,field))span[field]=number(span[field]);
106
+ }
60
107
  if (node.type === 'details' && own(node,'open')) node.open = boolean(node.open);
108
+ if(node.type==='text'&&own(node,'copyable'))node.copyable=boolean(node.copyable);
109
+ if(node.type==='code'&&own(node,'wrap'))node.wrap=boolean(node.wrap);
61
110
  for (const field of ['text','value','max','rows']) if (own(node,field)) expression(node[field],node.type === 'progress');
62
111
  if (['row','column','card','details'].includes(node.type) && own(node,'children')) node.children = nodes(node.children);
63
112
  }
@@ -0,0 +1,36 @@
1
+ // Repair transport encodings only where the component schema declares a type.
2
+ // Opaque JSON, ECharts options, source code and user data retain their contents.
3
+ export function normalizeVisual(value, schemas) {
4
+ const unwrap=v=>v&&typeof v==='object'&&!Array.isArray(v)&&Object.keys(v).length===1&&Array.isArray(v.item)?v.item:v;
5
+ const scalar=(v,kind)=>kind==='number'&&typeof v==='string'&&v.trim()!==''&&Number.isFinite(Number(v))?Number(v):kind==='boolean'&&(v==='true'||v==='false')?v==='true':v;
6
+ function record(input,schema,depth=0){
7
+ if(!input||typeof input!=='object'||Array.isArray(input)||depth>32)return input;
8
+ const out={...input};
9
+ for(const [key,v]of Object.entries(input)){
10
+ const target=schema.aliases?.[key]??key,kind=schema.fields?.[target];
11
+ if(kind==='array'||kind==='nodes'){
12
+ let array=unwrap(v);
13
+ if(Array.isArray(array))array=array.map(x=>kind==='nodes'?node(x,depth+1):schema.nested?.[target]?record(x,schema.nested[target],depth+1):x);
14
+ out[key]=array;
15
+ }else out[key]=scalar(v,kind);
16
+ }
17
+ return out;
18
+ }
19
+ function node(v,depth){
20
+ if(!v||typeof v!=='object'||Array.isArray(v))return v;
21
+ // Native v1 uses heading, while the extended vocabulary calls it text.
22
+ // This spelling has an unambiguous equivalent and should not cost a retry.
23
+ if(v.type==='heading'){v={...v,type:'text',content:v.content??v.text??v.title,size:v.size??'h3'};delete v.text;delete v.title}
24
+ if(['card','row','col','grid'].includes(v.type)&&v.items===undefined&&Array.isArray(unwrap(v.children))){v={...v,items:unwrap(v.children)};delete v.children}
25
+ const out=record(v,schemas[v.type]??{},depth);
26
+ if(v.type==='quiz'&&Array.isArray(out.options))out.options=out.options.map(x=>record(x,{fields:{correct:'boolean'}}));
27
+ if(v.type==='table')for(const key of ['rows','data','items','details'])if(Array.isArray(out[key]))out[key]=out[key].map(row=>{row=unwrap(row);return key==='details'&&Array.isArray(row)?row.map(x=>node(x,depth+1)):row});
28
+ if(v.type==='echart')for(const key of ['data','series','links'])if(Array.isArray(out[key]))out[key]=out[key].map(x=>record(x,{fields:{value:'number',data:'array'},nested:{data:{fields:{value:'number'}}}}));
29
+ return out;
30
+ }
31
+ if(Array.isArray(value))return {items:value.map(x=>node(x,0))};
32
+ if(!value||typeof value!=='object')return value;
33
+ const out={...value},items=unwrap(value.items);
34
+ if(Array.isArray(items))out.items=items.map(x=>node(x,0));
35
+ return out;
36
+ }
@@ -1,5 +1,5 @@
1
1
  // Public, bounded presentation vocabulary. Never accept arbitrary CSS or SVG from the model.
2
- export const UI_ICONS = Object.freeze(['sparkles', 'sliders', 'layers', 'chart', 'gauge', 'cpu', 'database', 'info', 'check', 'warning', 'arrow', 'target']);
2
+ export const UI_ICONS = Object.freeze(['sparkles', 'sliders', 'layers', 'chart', 'gauge', 'cpu', 'database', 'info', 'check', 'warning', 'arrow', 'target','external','file','globe']);
3
3
  export const UI_TONES = Object.freeze(['neutral', 'accent', 'success', 'warning', 'danger']);
4
4
  export const UI_LAYOUTS = Object.freeze(['dashboard', 'workbench', 'comparison', 'guide', 'status', 'report']);
5
5
  export const UI_ACCENTS = Object.freeze(['blue', 'teal', 'violet', 'amber', 'rose']);