@overcrow/mcp 0.0.0 → 0.1.1

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 (489) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -1
  3. package/dist/audit/index.js +103 -0
  4. package/dist/audit/lexer.js +417 -0
  5. package/dist/audit/project.js +200 -0
  6. package/dist/audit/rules.js +661 -0
  7. package/dist/bootstrap/download.js +229 -0
  8. package/dist/bootstrap/install.js +280 -0
  9. package/dist/bootstrap/pin.js +85 -0
  10. package/dist/bootstrap/pin.json +119 -0
  11. package/dist/bootstrap/zip.js +258 -0
  12. package/dist/cli.js +200 -0
  13. package/dist/confine.js +244 -0
  14. package/dist/content/docs/en/cli.md +768 -0
  15. package/dist/content/docs/en/creator-space.md +78 -0
  16. package/dist/content/docs/en/dev-channel.md +130 -0
  17. package/dist/content/docs/en/elements.md +469 -0
  18. package/dist/content/docs/en/forms.md +328 -0
  19. package/dist/content/docs/en/guide.md +252 -0
  20. package/dist/content/docs/en/index.md +85 -0
  21. package/dist/content/docs/en/limits.md +241 -0
  22. package/dist/content/docs/en/logic.md +446 -0
  23. package/dist/content/docs/en/manifest.md +388 -0
  24. package/dist/content/docs/en/mcp.md +165 -0
  25. package/dist/content/docs/en/package.md +131 -0
  26. package/dist/content/docs/en/publish-a-widget.md +94 -0
  27. package/dist/content/docs/en/publish-keys.md +95 -0
  28. package/dist/content/docs/en/publishing.md +167 -0
  29. package/dist/content/docs/en/reference.md +55 -0
  30. package/dist/content/docs/en/result-shapes.md +332 -0
  31. package/dist/content/docs/en/sdk.md +295 -0
  32. package/dist/content/docs/en/security.md +115 -0
  33. package/dist/content/docs/en/service-reference.md +344 -0
  34. package/dist/content/docs/en/services.md +517 -0
  35. package/dist/content/docs/en/style-properties.md +270 -0
  36. package/dist/content/docs/en/style.md +266 -0
  37. package/dist/content/docs/en/testing.md +400 -0
  38. package/dist/content/docs/en/verified-domain.md +46 -0
  39. package/dist/content/docs/en/view.md +338 -0
  40. package/dist/content/docs/en/widget-listing.md +65 -0
  41. package/dist/content/docs/en/widget-review.md +57 -0
  42. package/dist/content/docs/en/widget-statistics.md +134 -0
  43. package/dist/content/docs/en/widgets.md +76 -0
  44. package/dist/content/docs/fr/cli.md +802 -0
  45. package/dist/content/docs/fr/creator-space.md +83 -0
  46. package/dist/content/docs/fr/dev-channel.md +140 -0
  47. package/dist/content/docs/fr/elements.md +475 -0
  48. package/dist/content/docs/fr/forms.md +341 -0
  49. package/dist/content/docs/fr/guide.md +263 -0
  50. package/dist/content/docs/fr/index.md +90 -0
  51. package/dist/content/docs/fr/limits.md +244 -0
  52. package/dist/content/docs/fr/logic.md +461 -0
  53. package/dist/content/docs/fr/manifest.md +401 -0
  54. package/dist/content/docs/fr/mcp.md +173 -0
  55. package/dist/content/docs/fr/package.md +139 -0
  56. package/dist/content/docs/fr/publish-a-widget.md +101 -0
  57. package/dist/content/docs/fr/publish-keys.md +97 -0
  58. package/dist/content/docs/fr/publishing.md +177 -0
  59. package/dist/content/docs/fr/reference.md +59 -0
  60. package/dist/content/docs/fr/result-shapes.md +333 -0
  61. package/dist/content/docs/fr/sdk.md +301 -0
  62. package/dist/content/docs/fr/security.md +129 -0
  63. package/dist/content/docs/fr/service-reference.md +346 -0
  64. package/dist/content/docs/fr/services.md +540 -0
  65. package/dist/content/docs/fr/style-properties.md +272 -0
  66. package/dist/content/docs/fr/style.md +281 -0
  67. package/dist/content/docs/fr/testing.md +417 -0
  68. package/dist/content/docs/fr/verified-domain.md +49 -0
  69. package/dist/content/docs/fr/view.md +352 -0
  70. package/dist/content/docs/fr/widget-listing.md +69 -0
  71. package/dist/content/docs/fr/widget-review.md +59 -0
  72. package/dist/content/docs/fr/widget-statistics.md +141 -0
  73. package/dist/content/docs/fr/widgets.md +81 -0
  74. package/dist/content/examples/clock/LICENSE +21 -0
  75. package/dist/content/examples/clock/README.md +75 -0
  76. package/dist/content/examples/clock/listing.json +19 -0
  77. package/dist/content/examples/clock/locales/en.json +4 -0
  78. package/dist/content/examples/clock/locales/fr.json +4 -0
  79. package/dist/content/examples/clock/logic.ts +85 -0
  80. package/dist/content/examples/clock/manifest.json +44 -0
  81. package/dist/content/examples/clock/package.json +16 -0
  82. package/dist/content/examples/clock/style.ocss +26 -0
  83. package/dist/content/examples/clock/tests/hidden.scenario.json +68 -0
  84. package/dist/content/examples/clock/tests/load-logic.mjs +22 -0
  85. package/dist/content/examples/clock/tests/logic.test.mjs +89 -0
  86. package/dist/content/examples/clock/tests/options.scenario.json +108 -0
  87. package/dist/content/examples/clock/tests/preview.scenario.json +25 -0
  88. package/dist/content/examples/clock/tests/render.scenario.json +94 -0
  89. package/dist/content/examples/clock/tests/summer-time.scenario.json +74 -0
  90. package/dist/content/examples/clock/tests/ticks.scenario.json +120 -0
  91. package/dist/content/examples/clock/tsconfig.json +16 -0
  92. package/dist/content/examples/clock/view.ocml +8 -0
  93. package/dist/content/examples/countdown/LICENSE +20 -0
  94. package/dist/content/examples/countdown/listing.json +10 -0
  95. package/dist/content/examples/countdown/locales/en.json +15 -0
  96. package/dist/content/examples/countdown/locales/fr.json +15 -0
  97. package/dist/content/examples/countdown/logic.ts +179 -0
  98. package/dist/content/examples/countdown/manifest.json +34 -0
  99. package/dist/content/examples/countdown/package.json +15 -0
  100. package/dist/content/examples/countdown/style.ocss +94 -0
  101. package/dist/content/examples/countdown/tsconfig.json +16 -0
  102. package/dist/content/examples/countdown/view.ocml +42 -0
  103. package/dist/content/examples/fps/LICENSE +21 -0
  104. package/dist/content/examples/fps/README.md +64 -0
  105. package/dist/content/examples/fps/listing.json +19 -0
  106. package/dist/content/examples/fps/locales/en.json +11 -0
  107. package/dist/content/examples/fps/locales/fr.json +11 -0
  108. package/dist/content/examples/fps/logic.ts +64 -0
  109. package/dist/content/examples/fps/manifest.json +30 -0
  110. package/dist/content/examples/fps/package.json +16 -0
  111. package/dist/content/examples/fps/style.ocss +31 -0
  112. package/dist/content/examples/fps/submission.json +8 -0
  113. package/dist/content/examples/fps/tests/label.scenario.json +63 -0
  114. package/dist/content/examples/fps/tests/load-logic.mjs +22 -0
  115. package/dist/content/examples/fps/tests/logic.test.mjs +60 -0
  116. package/dist/content/examples/fps/tests/preview.scenario.json +29 -0
  117. package/dist/content/examples/fps/tests/refused.scenario.json +20 -0
  118. package/dist/content/examples/fps/tests/render.scenario.json +96 -0
  119. package/dist/content/examples/fps/tests/stale.scenario.json +91 -0
  120. package/dist/content/examples/fps/tests/unavailable.scenario.json +111 -0
  121. package/dist/content/examples/fps/tsconfig.json +16 -0
  122. package/dist/content/examples/fps/view.ocml +11 -0
  123. package/dist/content/examples/media/LICENSE +21 -0
  124. package/dist/content/examples/media/README.md +147 -0
  125. package/dist/content/examples/media/listing.json +19 -0
  126. package/dist/content/examples/media/locales/en.json +11 -0
  127. package/dist/content/examples/media/locales/fr.json +11 -0
  128. package/dist/content/examples/media/logic.ts +191 -0
  129. package/dist/content/examples/media/manifest.json +35 -0
  130. package/dist/content/examples/media/package.json +16 -0
  131. package/dist/content/examples/media/style.ocss +148 -0
  132. package/dist/content/examples/media/submission.json +12 -0
  133. package/dist/content/examples/media/tests/covers.scenario.json +144 -0
  134. package/dist/content/examples/media/tests/gesture.scenario.json +173 -0
  135. package/dist/content/examples/media/tests/load-logic.mjs +22 -0
  136. package/dist/content/examples/media/tests/logic.test.mjs +176 -0
  137. package/dist/content/examples/media/tests/marquee.scenario.json +127 -0
  138. package/dist/content/examples/media/tests/preview.scenario.json +52 -0
  139. package/dist/content/examples/media/tests/read-only.scenario.json +53 -0
  140. package/dist/content/examples/media/tests/refused.scenario.json +22 -0
  141. package/dist/content/examples/media/tests/refused.test.mjs +31 -0
  142. package/dist/content/examples/media/tests/render.scenario.json +136 -0
  143. package/dist/content/examples/media/tests/states.scenario.json +257 -0
  144. package/dist/content/examples/media/tests/unavailable.scenario.json +120 -0
  145. package/dist/content/examples/media/tsconfig.json +16 -0
  146. package/dist/content/examples/media/view.ocml +41 -0
  147. package/dist/content/examples/notes/LICENSE +21 -0
  148. package/dist/content/examples/notes/README.md +219 -0
  149. package/dist/content/examples/notes/listing.json +19 -0
  150. package/dist/content/examples/notes/locales/en.json +25 -0
  151. package/dist/content/examples/notes/locales/fr.json +25 -0
  152. package/dist/content/examples/notes/logic.ts +799 -0
  153. package/dist/content/examples/notes/manifest.json +40 -0
  154. package/dist/content/examples/notes/package.json +16 -0
  155. package/dist/content/examples/notes/style.ocss +469 -0
  156. package/dist/content/examples/notes/submission.json +12 -0
  157. package/dist/content/examples/notes/tests/checks.scenario.json +237 -0
  158. package/dist/content/examples/notes/tests/create.scenario.json +260 -0
  159. package/dist/content/examples/notes/tests/delete.scenario.json +342 -0
  160. package/dist/content/examples/notes/tests/drafts.scenario.json +714 -0
  161. package/dist/content/examples/notes/tests/editor.scenario.json +232 -0
  162. package/dist/content/examples/notes/tests/frame.scenario.json +93 -0
  163. package/dist/content/examples/notes/tests/interactive.scenario.json +344 -0
  164. package/dist/content/examples/notes/tests/limits.scenario.json +1351 -0
  165. package/dist/content/examples/notes/tests/load-logic.mjs +22 -0
  166. package/dist/content/examples/notes/tests/logic.test.mjs +514 -0
  167. package/dist/content/examples/notes/tests/preview.scenario.json +99 -0
  168. package/dist/content/examples/notes/tests/read-only.scenario.json +105 -0
  169. package/dist/content/examples/notes/tests/refused.scenario.json +33 -0
  170. package/dist/content/examples/notes/tests/save.scenario.json +378 -0
  171. package/dist/content/examples/notes/tests/states.scenario.json +640 -0
  172. package/dist/content/examples/notes/tests/typing.scenario.json +562 -0
  173. package/dist/content/examples/notes/tests/unavailable.scenario.json +246 -0
  174. package/dist/content/examples/notes/tsconfig.json +16 -0
  175. package/dist/content/examples/notes/view.ocml +154 -0
  176. package/dist/content/examples/performance/LICENSE +21 -0
  177. package/dist/content/examples/performance/README.md +134 -0
  178. package/dist/content/examples/performance/listing.json +19 -0
  179. package/dist/content/examples/performance/locales/en.json +20 -0
  180. package/dist/content/examples/performance/locales/fr.json +20 -0
  181. package/dist/content/examples/performance/logic.ts +210 -0
  182. package/dist/content/examples/performance/manifest.json +83 -0
  183. package/dist/content/examples/performance/package.json +16 -0
  184. package/dist/content/examples/performance/style.ocss +75 -0
  185. package/dist/content/examples/performance/submission.json +12 -0
  186. package/dist/content/examples/performance/tests/fahrenheit.scenario.json +110 -0
  187. package/dist/content/examples/performance/tests/horizontal.scenario.json +96 -0
  188. package/dist/content/examples/performance/tests/load-logic.mjs +22 -0
  189. package/dist/content/examples/performance/tests/logic.test.mjs +226 -0
  190. package/dist/content/examples/performance/tests/menu.scenario.json +170 -0
  191. package/dist/content/examples/performance/tests/no-fps-source.scenario.json +47 -0
  192. package/dist/content/examples/performance/tests/preview.scenario.json +45 -0
  193. package/dist/content/examples/performance/tests/refused.scenario.json +20 -0
  194. package/dist/content/examples/performance/tests/refused.test.mjs +19 -0
  195. package/dist/content/examples/performance/tests/region.scenario.json +89 -0
  196. package/dist/content/examples/performance/tests/render.scenario.json +112 -0
  197. package/dist/content/examples/performance/tests/sources.scenario.json +151 -0
  198. package/dist/content/examples/performance/tests/stale.scenario.json +111 -0
  199. package/dist/content/examples/performance/tests/telemetry-only.scenario.json +44 -0
  200. package/dist/content/examples/performance/tests/thresholds.scenario.json +147 -0
  201. package/dist/content/examples/performance/tests/waiting.scenario.json +105 -0
  202. package/dist/content/examples/performance/tsconfig.json +16 -0
  203. package/dist/content/examples/performance/view.ocml +18 -0
  204. package/dist/content/examples/playervox-journal/LICENSE +21 -0
  205. package/dist/content/examples/playervox-journal/README.md +150 -0
  206. package/dist/content/examples/playervox-journal/listing.json +19 -0
  207. package/dist/content/examples/playervox-journal/locales/en.json +25 -0
  208. package/dist/content/examples/playervox-journal/locales/fr.json +25 -0
  209. package/dist/content/examples/playervox-journal/logic.ts +556 -0
  210. package/dist/content/examples/playervox-journal/manifest.json +19 -0
  211. package/dist/content/examples/playervox-journal/package.json +16 -0
  212. package/dist/content/examples/playervox-journal/style.ocss +142 -0
  213. package/dist/content/examples/playervox-journal/submission.json +12 -0
  214. package/dist/content/examples/playervox-journal/tests/changes.scenario.json +482 -0
  215. package/dist/content/examples/playervox-journal/tests/delete.scenario.json +432 -0
  216. package/dist/content/examples/playervox-journal/tests/frame.scenario.json +169 -0
  217. package/dist/content/examples/playervox-journal/tests/load-logic.mjs +22 -0
  218. package/dist/content/examples/playervox-journal/tests/logic.test.mjs +349 -0
  219. package/dist/content/examples/playervox-journal/tests/paging.scenario.json +428 -0
  220. package/dist/content/examples/playervox-journal/tests/preview.scenario.json +184 -0
  221. package/dist/content/examples/playervox-journal/tests/read-only.scenario.json +157 -0
  222. package/dist/content/examples/playervox-journal/tests/refused.scenario.json +39 -0
  223. package/dist/content/examples/playervox-journal/tests/scale.scenario.json +286 -0
  224. package/dist/content/examples/playervox-journal/tests/signed-out.scenario.json +134 -0
  225. package/dist/content/examples/playervox-journal/tests/states.scenario.json +741 -0
  226. package/dist/content/examples/playervox-journal/tests/unavailable.scenario.json +183 -0
  227. package/dist/content/examples/playervox-journal/tsconfig.json +16 -0
  228. package/dist/content/examples/playervox-journal/view.ocml +52 -0
  229. package/dist/content/examples/playervox-rating/LICENSE +21 -0
  230. package/dist/content/examples/playervox-rating/README.md +166 -0
  231. package/dist/content/examples/playervox-rating/listing.json +19 -0
  232. package/dist/content/examples/playervox-rating/locales/en.json +35 -0
  233. package/dist/content/examples/playervox-rating/locales/fr.json +35 -0
  234. package/dist/content/examples/playervox-rating/logic.ts +581 -0
  235. package/dist/content/examples/playervox-rating/manifest.json +19 -0
  236. package/dist/content/examples/playervox-rating/package.json +16 -0
  237. package/dist/content/examples/playervox-rating/style.ocss +333 -0
  238. package/dist/content/examples/playervox-rating/submission.json +12 -0
  239. package/dist/content/examples/playervox-rating/tests/account.scenario.json +125 -0
  240. package/dist/content/examples/playervox-rating/tests/bounds.scenario.json +73 -0
  241. package/dist/content/examples/playervox-rating/tests/draft.scenario.json +199 -0
  242. package/dist/content/examples/playervox-rating/tests/form.scenario.json +142 -0
  243. package/dist/content/examples/playervox-rating/tests/load-logic.mjs +22 -0
  244. package/dist/content/examples/playervox-rating/tests/logic.test.mjs +346 -0
  245. package/dist/content/examples/playervox-rating/tests/offline.scenario.json +142 -0
  246. package/dist/content/examples/playervox-rating/tests/preview.scenario.json +44 -0
  247. package/dist/content/examples/playervox-rating/tests/publish-keyboard.scenario.json +221 -0
  248. package/dist/content/examples/playervox-rating/tests/publish-pointer.scenario.json +314 -0
  249. package/dist/content/examples/playervox-rating/tests/read-only.scenario.json +70 -0
  250. package/dist/content/examples/playervox-rating/tests/refused.scenario.json +45 -0
  251. package/dist/content/examples/playervox-rating/tests/states.scenario.json +362 -0
  252. package/dist/content/examples/playervox-rating/tsconfig.json +16 -0
  253. package/dist/content/examples/playervox-rating/view.ocml +62 -0
  254. package/dist/content/examples/playervox-reviews/LICENSE +21 -0
  255. package/dist/content/examples/playervox-reviews/README.md +194 -0
  256. package/dist/content/examples/playervox-reviews/listing.json +19 -0
  257. package/dist/content/examples/playervox-reviews/locales/en.json +32 -0
  258. package/dist/content/examples/playervox-reviews/locales/fr.json +32 -0
  259. package/dist/content/examples/playervox-reviews/logic.ts +822 -0
  260. package/dist/content/examples/playervox-reviews/manifest.json +30 -0
  261. package/dist/content/examples/playervox-reviews/package.json +16 -0
  262. package/dist/content/examples/playervox-reviews/style.ocss +260 -0
  263. package/dist/content/examples/playervox-reviews/submission.json +8 -0
  264. package/dist/content/examples/playervox-reviews/tests/account.scenario.json +249 -0
  265. package/dist/content/examples/playervox-reviews/tests/bounds.scenario.json +336 -0
  266. package/dist/content/examples/playervox-reviews/tests/changes.scenario.json +515 -0
  267. package/dist/content/examples/playervox-reviews/tests/filter.scenario.json +400 -0
  268. package/dist/content/examples/playervox-reviews/tests/frame.scenario.json +185 -0
  269. package/dist/content/examples/playervox-reviews/tests/keyboard.scenario.json +188 -0
  270. package/dist/content/examples/playervox-reviews/tests/load-logic.mjs +22 -0
  271. package/dist/content/examples/playervox-reviews/tests/logic.test.mjs +559 -0
  272. package/dist/content/examples/playervox-reviews/tests/offline-start.scenario.json +152 -0
  273. package/dist/content/examples/playervox-reviews/tests/offline.scenario.json +311 -0
  274. package/dist/content/examples/playervox-reviews/tests/paging.scenario.json +497 -0
  275. package/dist/content/examples/playervox-reviews/tests/preview.scenario.json +286 -0
  276. package/dist/content/examples/playervox-reviews/tests/reading.scenario.json +591 -0
  277. package/dist/content/examples/playervox-reviews/tests/refused.scenario.json +54 -0
  278. package/dist/content/examples/playervox-reviews/tests/scale.scenario.json +303 -0
  279. package/dist/content/examples/playervox-reviews/tests/states.scenario.json +700 -0
  280. package/dist/content/examples/playervox-reviews/tests/unavailable.scenario.json +192 -0
  281. package/dist/content/examples/playervox-reviews/tsconfig.json +16 -0
  282. package/dist/content/examples/playervox-reviews/view.ocml +110 -0
  283. package/dist/content/examples/playervox-score/LICENSE +21 -0
  284. package/dist/content/examples/playervox-score/README.md +131 -0
  285. package/dist/content/examples/playervox-score/listing.json +19 -0
  286. package/dist/content/examples/playervox-score/locales/en.json +23 -0
  287. package/dist/content/examples/playervox-score/locales/fr.json +23 -0
  288. package/dist/content/examples/playervox-score/logic.ts +430 -0
  289. package/dist/content/examples/playervox-score/manifest.json +47 -0
  290. package/dist/content/examples/playervox-score/package.json +16 -0
  291. package/dist/content/examples/playervox-score/style.ocss +247 -0
  292. package/dist/content/examples/playervox-score/submission.json +8 -0
  293. package/dist/content/examples/playervox-score/tests/grades.scenario.json +279 -0
  294. package/dist/content/examples/playervox-score/tests/load-logic.mjs +22 -0
  295. package/dist/content/examples/playervox-score/tests/logic.test.mjs +229 -0
  296. package/dist/content/examples/playervox-score/tests/options.scenario.json +302 -0
  297. package/dist/content/examples/playervox-score/tests/preview.scenario.json +68 -0
  298. package/dist/content/examples/playervox-score/tests/pulse.scenario.json +157 -0
  299. package/dist/content/examples/playervox-score/tests/refused.scenario.json +21 -0
  300. package/dist/content/examples/playervox-score/tests/signed-out.scenario.json +46 -0
  301. package/dist/content/examples/playervox-score/tests/states.scenario.json +450 -0
  302. package/dist/content/examples/playervox-score/tests/unavailable.scenario.json +84 -0
  303. package/dist/content/examples/playervox-score/tsconfig.json +16 -0
  304. package/dist/content/examples/playervox-score/view.ocml +51 -0
  305. package/dist/content/examples/session/LICENSE +21 -0
  306. package/dist/content/examples/session/README.md +57 -0
  307. package/dist/content/examples/session/listing.json +19 -0
  308. package/dist/content/examples/session/locales/en.json +3 -0
  309. package/dist/content/examples/session/locales/fr.json +3 -0
  310. package/dist/content/examples/session/logic.ts +26 -0
  311. package/dist/content/examples/session/manifest.json +19 -0
  312. package/dist/content/examples/session/package.json +16 -0
  313. package/dist/content/examples/session/style.ocss +16 -0
  314. package/dist/content/examples/session/submission.json +8 -0
  315. package/dist/content/examples/session/tests/hidden.scenario.json +45 -0
  316. package/dist/content/examples/session/tests/load-logic.mjs +22 -0
  317. package/dist/content/examples/session/tests/logic.test.mjs +37 -0
  318. package/dist/content/examples/session/tests/preview.scenario.json +28 -0
  319. package/dist/content/examples/session/tests/refused.scenario.json +20 -0
  320. package/dist/content/examples/session/tests/refused.test.mjs +16 -0
  321. package/dist/content/examples/session/tests/render.scenario.json +95 -0
  322. package/dist/content/examples/session/tests/ticks.scenario.json +139 -0
  323. package/dist/content/examples/session/tests/unknown.scenario.json +37 -0
  324. package/dist/content/examples/session/tsconfig.json +16 -0
  325. package/dist/content/examples/session/view.ocml +11 -0
  326. package/dist/content/examples/stopwatch/LICENSE +21 -0
  327. package/dist/content/examples/stopwatch/README.md +99 -0
  328. package/dist/content/examples/stopwatch/listing.json +19 -0
  329. package/dist/content/examples/stopwatch/locales/en.json +8 -0
  330. package/dist/content/examples/stopwatch/locales/fr.json +8 -0
  331. package/dist/content/examples/stopwatch/logic.ts +93 -0
  332. package/dist/content/examples/stopwatch/manifest.json +19 -0
  333. package/dist/content/examples/stopwatch/package.json +16 -0
  334. package/dist/content/examples/stopwatch/style.ocss +54 -0
  335. package/dist/content/examples/stopwatch/submission.json +12 -0
  336. package/dist/content/examples/stopwatch/tests/errors.scenario.json +121 -0
  337. package/dist/content/examples/stopwatch/tests/gesture.scenario.json +154 -0
  338. package/dist/content/examples/stopwatch/tests/hidden.scenario.json +57 -0
  339. package/dist/content/examples/stopwatch/tests/hundredths.scenario.json +173 -0
  340. package/dist/content/examples/stopwatch/tests/load-logic.mjs +22 -0
  341. package/dist/content/examples/stopwatch/tests/logic.test.mjs +99 -0
  342. package/dist/content/examples/stopwatch/tests/preview.scenario.json +36 -0
  343. package/dist/content/examples/stopwatch/tests/read-only.scenario.json +42 -0
  344. package/dist/content/examples/stopwatch/tests/read-only.test.mjs +18 -0
  345. package/dist/content/examples/stopwatch/tests/refused.scenario.json +22 -0
  346. package/dist/content/examples/stopwatch/tests/refused.test.mjs +18 -0
  347. package/dist/content/examples/stopwatch/tests/render.scenario.json +105 -0
  348. package/dist/content/examples/stopwatch/tests/states.scenario.json +246 -0
  349. package/dist/content/examples/stopwatch/tests/unknown.scenario.json +40 -0
  350. package/dist/content/examples/stopwatch/tsconfig.json +16 -0
  351. package/dist/content/examples/stopwatch/view.ocml +29 -0
  352. package/dist/content/examples/twitch-chat/LICENSE +21 -0
  353. package/dist/content/examples/twitch-chat/README.md +283 -0
  354. package/dist/content/examples/twitch-chat/listing.json +19 -0
  355. package/dist/content/examples/twitch-chat/locales/en.json +52 -0
  356. package/dist/content/examples/twitch-chat/locales/fr.json +52 -0
  357. package/dist/content/examples/twitch-chat/logic.ts +887 -0
  358. package/dist/content/examples/twitch-chat/manifest.json +33 -0
  359. package/dist/content/examples/twitch-chat/package.json +16 -0
  360. package/dist/content/examples/twitch-chat/style.ocss +544 -0
  361. package/dist/content/examples/twitch-chat/submission.json +12 -0
  362. package/dist/content/examples/twitch-chat/tests/account.scenario.json +325 -0
  363. package/dist/content/examples/twitch-chat/tests/burst.scenario.json +1866 -0
  364. package/dist/content/examples/twitch-chat/tests/channel-refused.scenario.json +372 -0
  365. package/dist/content/examples/twitch-chat/tests/channel.scenario.json +480 -0
  366. package/dist/content/examples/twitch-chat/tests/draft.scenario.json +279 -0
  367. package/dist/content/examples/twitch-chat/tests/fade.scenario.json +269 -0
  368. package/dist/content/examples/twitch-chat/tests/failures.scenario.json +420 -0
  369. package/dist/content/examples/twitch-chat/tests/favorites.scenario.json +376 -0
  370. package/dist/content/examples/twitch-chat/tests/frame.scenario.json +152 -0
  371. package/dist/content/examples/twitch-chat/tests/lifetime.scenario.json +186 -0
  372. package/dist/content/examples/twitch-chat/tests/load-logic.mjs +22 -0
  373. package/dist/content/examples/twitch-chat/tests/logic.test.mjs +1053 -0
  374. package/dist/content/examples/twitch-chat/tests/passive.scenario.json +536 -0
  375. package/dist/content/examples/twitch-chat/tests/preview.scenario.json +147 -0
  376. package/dist/content/examples/twitch-chat/tests/read-only.scenario.json +202 -0
  377. package/dist/content/examples/twitch-chat/tests/read-only.test.mjs +63 -0
  378. package/dist/content/examples/twitch-chat/tests/refused.scenario.json +65 -0
  379. package/dist/content/examples/twitch-chat/tests/refused.test.mjs +43 -0
  380. package/dist/content/examples/twitch-chat/tests/render.scenario.json +347 -0
  381. package/dist/content/examples/twitch-chat/tests/reply.scenario.json +384 -0
  382. package/dist/content/examples/twitch-chat/tests/send-refused.scenario.json +383 -0
  383. package/dist/content/examples/twitch-chat/tests/send.scenario.json +300 -0
  384. package/dist/content/examples/twitch-chat/tests/states.scenario.json +455 -0
  385. package/dist/content/examples/twitch-chat/tests/unavailable.scenario.json +256 -0
  386. package/dist/content/examples/twitch-chat/tests/unread.scenario.json +997 -0
  387. package/dist/content/examples/twitch-chat/tsconfig.json +16 -0
  388. package/dist/content/examples/twitch-chat/view.ocml +141 -0
  389. package/dist/content/examples/warframe-market/LICENSE +21 -0
  390. package/dist/content/examples/warframe-market/README.md +176 -0
  391. package/dist/content/examples/warframe-market/listing.json +19 -0
  392. package/dist/content/examples/warframe-market/locales/en.json +44 -0
  393. package/dist/content/examples/warframe-market/locales/fr.json +44 -0
  394. package/dist/content/examples/warframe-market/logic.ts +1265 -0
  395. package/dist/content/examples/warframe-market/manifest.json +92 -0
  396. package/dist/content/examples/warframe-market/package.json +16 -0
  397. package/dist/content/examples/warframe-market/style.ocss +422 -0
  398. package/dist/content/examples/warframe-market/submission.json +24 -0
  399. package/dist/content/examples/warframe-market/tests/bounds.scenario.json +60 -0
  400. package/dist/content/examples/warframe-market/tests/cached.scenario.json +70 -0
  401. package/dist/content/examples/warframe-market/tests/detail.scenario.json +251 -0
  402. package/dist/content/examples/warframe-market/tests/errors.scenario.json +105 -0
  403. package/dist/content/examples/warframe-market/tests/fixtures.json +295 -0
  404. package/dist/content/examples/warframe-market/tests/load-logic.mjs +22 -0
  405. package/dist/content/examples/warframe-market/tests/logic.test.mjs +505 -0
  406. package/dist/content/examples/warframe-market/tests/no-clipboard.scenario.json +104 -0
  407. package/dist/content/examples/warframe-market/tests/passive.scenario.json +87 -0
  408. package/dist/content/examples/warframe-market/tests/preview.scenario.json +146 -0
  409. package/dist/content/examples/warframe-market/tests/refresh.scenario.json +56 -0
  410. package/dist/content/examples/warframe-market/tests/refused.scenario.json +74 -0
  411. package/dist/content/examples/warframe-market/tests/render.scenario.json +210 -0
  412. package/dist/content/examples/warframe-market/tests/search.scenario.json +189 -0
  413. package/dist/content/examples/warframe-market/tests/unavailable.scenario.json +54 -0
  414. package/dist/content/examples/warframe-market/tsconfig.json +16 -0
  415. package/dist/content/examples/warframe-market/view.ocml +116 -0
  416. package/dist/content/examples/weather/LICENSE +20 -0
  417. package/dist/content/examples/weather/listing.json +10 -0
  418. package/dist/content/examples/weather/locales/en.json +9 -0
  419. package/dist/content/examples/weather/locales/fr.json +9 -0
  420. package/dist/content/examples/weather/logic.ts +62 -0
  421. package/dist/content/examples/weather/manifest.json +51 -0
  422. package/dist/content/examples/weather/package.json +15 -0
  423. package/dist/content/examples/weather/style.ocss +29 -0
  424. package/dist/content/examples/weather/submission.json +17 -0
  425. package/dist/content/examples/weather/tsconfig.json +16 -0
  426. package/dist/content/examples/weather/view.ocml +12 -0
  427. package/dist/content/index.json +3705 -0
  428. package/dist/content/reference/errors.json +1924 -0
  429. package/dist/content/reference/limits.json +1154 -0
  430. package/dist/content/reference/manifest.md +223 -0
  431. package/dist/content/reference/permissions.json +413 -0
  432. package/dist/content/templates/blank/locales/en.json +3 -0
  433. package/dist/content/templates/blank/locales/fr.json +3 -0
  434. package/dist/content/templates/blank/logic.ts +7 -0
  435. package/dist/content/templates/blank/manifest.json +16 -0
  436. package/dist/content/templates/blank/style.ocss +10 -0
  437. package/dist/content/templates/blank/tests/example.scenario.json +10 -0
  438. package/dist/content/templates/blank/view.ocml +6 -0
  439. package/dist/content/templates/chart/locales/en.json +3 -0
  440. package/dist/content/templates/chart/locales/fr.json +3 -0
  441. package/dist/content/templates/chart/logic.ts +27 -0
  442. package/dist/content/templates/chart/manifest.json +16 -0
  443. package/dist/content/templates/chart/style.ocss +27 -0
  444. package/dist/content/templates/chart/tests/example.scenario.json +10 -0
  445. package/dist/content/templates/chart/view.ocml +10 -0
  446. package/dist/content/templates/counter/locales/en.json +4 -0
  447. package/dist/content/templates/counter/locales/fr.json +4 -0
  448. package/dist/content/templates/counter/logic.ts +20 -0
  449. package/dist/content/templates/counter/manifest.json +16 -0
  450. package/dist/content/templates/counter/style.ocss +26 -0
  451. package/dist/content/templates/counter/tests/example.scenario.json +11 -0
  452. package/dist/content/templates/counter/view.ocml +13 -0
  453. package/dist/content/templates/list/locales/en.json +8 -0
  454. package/dist/content/templates/list/locales/fr.json +8 -0
  455. package/dist/content/templates/list/logic.ts +35 -0
  456. package/dist/content/templates/list/manifest.json +16 -0
  457. package/dist/content/templates/list/style.ocss +42 -0
  458. package/dist/content/templates/list/tests/example.scenario.json +10 -0
  459. package/dist/content/templates/list/view.ocml +17 -0
  460. package/dist/content/templates/shared/LICENSE +20 -0
  461. package/dist/content/templates/shared/package.json +14 -0
  462. package/dist/content/templates/shared/tsconfig.json +16 -0
  463. package/dist/content.js +68 -0
  464. package/dist/env.js +156 -0
  465. package/dist/fingerprint.js +32 -0
  466. package/dist/hidden.js +47 -0
  467. package/dist/ids.js +27 -0
  468. package/dist/index.js +82 -0
  469. package/dist/knowledge.js +222 -0
  470. package/dist/npm.js +149 -0
  471. package/dist/prompts.js +47 -0
  472. package/dist/resources.js +82 -0
  473. package/dist/run.js +120 -0
  474. package/dist/server.js +43 -0
  475. package/dist/session.js +205 -0
  476. package/dist/sources.js +218 -0
  477. package/dist/text.js +80 -0
  478. package/dist/texts.js +44 -0
  479. package/dist/tools/audit.js +105 -0
  480. package/dist/tools/build.js +453 -0
  481. package/dist/tools/common.js +122 -0
  482. package/dist/tools/docs.js +196 -0
  483. package/dist/tools/preview.js +87 -0
  484. package/dist/tools/project.js +183 -0
  485. package/dist/tools/setup.js +146 -0
  486. package/dist/tools/submission.js +369 -0
  487. package/dist/version.js +3 -0
  488. package/npm-shrinkwrap.json +402 -0
  489. package/package.json +50 -4
@@ -0,0 +1,328 @@
1
+ # Forms and write intents
2
+
3
+ A PlayerVox OverCrow widget takes input through controls that OverCrow
4
+ draws and edits itself: buttons, toggles, checkboxes, sliders, drop-down
5
+ lists, text fields. The logic hears about them through events. A `form`
6
+ groups controls and submits them together, and a form bound to a **write
7
+ intent** is how a widget lets the user write to their notes, publish a
8
+ rating or send a chat message, without the text ever passing through the
9
+ widget's code.
10
+
11
+ Widgets receive input only in OverCrow's Interactive mode. In Passive mode
12
+ a click goes through the widget to the game: hide or disable what cannot be
13
+ used, as the built-ins do with `host.mode`.
14
+
15
+ ## Controls
16
+
17
+ | Element | Value | Events |
18
+ | --- | --- | --- |
19
+ | `button` | none | `activate` |
20
+ | `toggle`, `checkbox` | `checked` | `change` |
21
+ | `slider` | `value`, between `min` and `max` | `input` while dragging, `change` on release |
22
+ | `select` with `option` children | `value` of the chosen option | `change` |
23
+ | `field` | one line of text | `input` at each edit, `change` on Enter or when the focus leaves, `submit` on Enter |
24
+ | `textarea` | several lines of text | `input`, `change`, `submit` on Ctrl+Enter |
25
+
26
+ Each takes a `label`, its accessible name, and `disabled`. Their attributes
27
+ are in [elements and attributes](elements.md).
28
+
29
+ <!-- source: docs/content/examples/countdown/view.ocml -->
30
+ ```xml
31
+ <select class="duration" value={minutesValue(state.minutes)} label={t("duration")} disabled={state.running} on:change={setMinutes}>
32
+ <for each={state.durations} as="minutes" key={minutes}>
33
+ <option value={minutesValue(minutes)}>{t("minutes", { count: minutes })}</option>
34
+ </for>
35
+ </select>
36
+ ```
37
+
38
+ <!-- source: docs/content/examples/countdown/logic.ts -->
39
+ ```ts
40
+ export function setMinutes(event: { value: unknown }): void {
41
+ const minutes = Number(event.value);
42
+ if (state.durations.includes(minutes)) {
43
+ state.minutes = minutes;
44
+ state.remainingMs = total(minutes);
45
+ }
46
+ }
47
+ ```
48
+
49
+ The view binds the control to the state (`value={…}`, `checked={…}`), and
50
+ the handler writes the new value back. The detail of `input` and `change`
51
+ is `{ value }`: a boolean for a toggle or a checkbox, a number for a
52
+ slider, text for the others.
53
+
54
+ <!-- source: docs/content/examples/countdown/view.ocml -->
55
+ ```xml
56
+ <toggle class="repeat" label={t("repeat")} tooltip={t("repeat")} checked={state.repeat} on:change={setRepeat}/>
57
+ ```
58
+
59
+ ### Text fields
60
+
61
+ OverCrow edits the text of a `field` or a `textarea` itself: the caret, the
62
+ selection, copy and paste, and input methods for languages that compose
63
+ characters. The logic receives a copy of the text in each `input` event.
64
+
65
+ <!-- source: widgets/warframe-market/view.ocml -->
66
+ ```xml
67
+ <field class="query" label={t("search-field")} value={state.query} placeholder={t("placeholder")} max-length="256" on:input={search}/>
68
+ ```
69
+
70
+ <!-- source: widgets/warframe-market/logic.ts -->
71
+ ```ts
72
+ export function search(detail: { value: unknown }): void {
73
+ state.query = typeof detail.value === "string" ? detail.value : "";
74
+ state.results = searchItems(items, lowered, state.query);
75
+ state.detail = null;
76
+ state.loadingOrders = false;
77
+ state.refreshing = false;
78
+ state.copy = null;
79
+ if (state.error === "orders_unavailable") {
80
+ state.error = null;
81
+ }
82
+ selection += 1;
83
+ stopRefresh();
84
+ saveQuery();
85
+ }
86
+ ```
87
+
88
+ Binding `value` replaces what the field holds: bind it to the state your
89
+ `input` handler writes, as above, or leave it out and only listen.
90
+ `max-length` bounds the text in bytes, and `placeholder` shows a hint while
91
+ the field is empty.
92
+
93
+ A field also sends `keydown` when you ask for it, with the key and its
94
+ modifiers, for shortcuts such as Escape to cancel. Keys that OverCrow
95
+ reserves (Tab to move the focus, its own shortcuts, a composition in
96
+ progress) are not delivered.
97
+
98
+ ### The focus when an editor opens
99
+
100
+ The logic cannot move the keyboard focus. A `field` or a `textarea` that
101
+ carries `autofocus` takes it by itself when it appears while the logic
102
+ handles a user action: a click on an Edit button that opens an editor puts
103
+ the caret in the field, after its text, as a click in it would.
104
+
105
+ <!-- source: widgets/notes/view.ocml -->
106
+ ```xml
107
+ <field class="title-field" name="title" autofocus placeholder={t("title-hint")} label={t("title-hint")} on:input={titleInput(editor.key, event.value)} on:keydown={keyed(editor.key, event.key, event.ctrl)}/>
108
+ ```
109
+
110
+ OverCrow gives that focus only when the element appears during a
111
+ [user action](services.md#calls-that-need-a-user-action), in Interactive
112
+ mode, in the widget the user acted on; when several such elements appear
113
+ together, the first one of the view takes it. An element that appears when
114
+ the widget starts, from a timer or from the answer of a service (after an
115
+ `await` in the handler of the click too) does not take the focus, and
116
+ neither does an element that was already shown: `autofocus` is read when
117
+ the element appears. Give it to one field of an editor, and not to a field
118
+ that appears while the user types, such as a new row of a list.
119
+
120
+ ## Forms
121
+
122
+ A `form` groups controls and gives them one `submit` event. It is
123
+ submitted by Enter in a `field`, by Ctrl+Enter in a `field` or a
124
+ `textarea`, or by activating a button with the `submit` attribute.
125
+
126
+ <!-- source: widgets/twitch-chat/view.ocml -->
127
+ ```xml
128
+ <form class="selector" on:submit={join}>
129
+ <field class="input channel" max-length="26" autofocus placeholder={t("channel-name")} label={t("channel-name")} on:input={channelTyped(event.value)}/>
130
+ <button class="action" submit disabled={!canJoin(state)}>
131
+ <text class="action-label">{t("join")}</text>
132
+ </button>
133
+ </form>
134
+ ```
135
+
136
+ <!-- source: widgets/twitch-chat/logic.ts -->
137
+ ```ts
138
+ export function join(): void {
139
+ const channel = normalizeChannel(state.channelDraft);
140
+ if (channel !== null) {
141
+ joinChannel(channel);
142
+ }
143
+ }
144
+ ```
145
+
146
+ This form has no intent: its `submit` handler reads what the `input`
147
+ handler kept in the state, and calls a service. `submit` is a user action,
148
+ so the handler may call a service that needs one
149
+ (`twitch.chat.join` here).
150
+
151
+ A form keeps what the user entered for as long as it stays in the view.
152
+ Hide it with `display: none` to keep a draft; remove it from the view to
153
+ discard one. To start over with empty fields, give the form a new key in a
154
+ `for`: a new key is a new form.
155
+
156
+ ## Forms that write user data
157
+
158
+ Three things a widget can do write text that the user typed into the
159
+ user's own data: saving a note, publishing a PlayerVox rating with its
160
+ review, and sending a Twitch chat message. They are not service calls. A
161
+ form with an `intent` attribute sends them:
162
+
163
+ <!-- source: widgets/twitch-chat/view.ocml -->
164
+ ```xml
165
+ <form class={composerClass(state)} intent="twitch.chat.send" target={replyTarget(state)} on:submit={submitted(event.outcome, event.error)}>
166
+ <if test={state.reply}>
167
+ <box class="replying">
168
+ <text class="replying-label">{replyingTo(state)}</text>
169
+ <button class="icon-button small" label={t("cancel-reply")} tooltip={t("cancel-reply")} on:activate={cancelReply}>
170
+ <icon name="x"/>
171
+ </button>
172
+ </box>
173
+ </if>
174
+ <if test={state.sendError != ""}>
175
+ <text class="error">{t(state.sendError)}</text>
176
+ </if>
177
+ <box class="compose">
178
+ <field class="input message-field" name="message" max-length="500" placeholder={t(composerHint(state))} label={t("message-label")} disabled={!state.canSend} on:input={drafted(event.value)} on:keydown={keyed(event.key)}/>
179
+ <if test={sendMark(state) != ""}>
180
+ <text class={sendMarkClass(state)}>{t(sendMark(state))}</text>
181
+ </if>
182
+ <button class="action" submit disabled={!canSubmit(state)} on:activate={sendPressed}>
183
+ <text class="action-label">{t("send")}</text>
184
+ </button>
185
+ </box>
186
+ </form>
187
+ ```
188
+
189
+ When the user submits such a form, **OverCrow reads the values of the
190
+ form's own controls and sends them itself**. The widget's logic never
191
+ supplies the text, so a widget cannot write something the user did not
192
+ type, and cannot submit without the user: the form goes only on a user
193
+ action, in Interactive mode, with the capability granted.
194
+
195
+ What this changes for the view and the logic:
196
+
197
+ - **The controls belong to OverCrow.** The `field`, `textarea` and `slider`
198
+ controls of the form take no `value`: `overcrow-widget check` refuses it
199
+ (`view.bound_value`), and OverCrow stops a widget that sets one at run
200
+ time. Their `name` attribute says which field of the intent each one is.
201
+ - **OverCrow fills them** where the intent says so: the note's title, body
202
+ and checklist, the user's published rating. A fill sends the control's
203
+ `input` event with the value, so the logic knows what is shown; that
204
+ event is not a user action.
205
+ - **The logic follows through `input` events**, to show a counter or to
206
+ enable the button, and may disable the controls.
207
+ - **The outcome arrives in the form's `submit` event**: `event.outcome` is
208
+ `accepted`, `rejected` (with the [error code](services.md#errors) in
209
+ `event.error`) or `cancelled`. A form without an intent gives
210
+ `submitted`.
211
+
212
+ <!-- source: widgets/playervox-rating/view.ocml -->
213
+ ```xml
214
+ <slider class="criterion-slider" name="gameplay" min="0" max="100" step="1" label={t("gameplay")} disabled={!editable(state)} on:input={scored("gameplay", event.value)}/>
215
+ ```
216
+
217
+ <!-- source: widgets/playervox-rating/logic.ts -->
218
+ ```ts
219
+ export function scored(key: CriterionKey, value: number): void {
220
+ state[key] = value;
221
+ edited();
222
+ }
223
+ ```
224
+
225
+ <!-- source: widgets/playervox-rating/logic.ts -->
226
+ ```ts
227
+ export function submitted(outcome: string, error: ServiceErrorPayload | undefined): void {
228
+ state.pending = Math.max(0, state.pending - 1);
229
+ if (state.pending === 0) {
230
+ answer?.cancel();
231
+ answer = null;
232
+ }
233
+ if (outcome === "accepted") {
234
+ // The subscription sends the stored rating; nothing is read again.
235
+ state.saved = true;
236
+ state.error = "";
237
+ } else if (outcome !== "cancelled") {
238
+ state.error = errorKey(error?.code ?? null);
239
+ }
240
+ }
241
+ ```
242
+
243
+ A write does not change what a subscription says by itself: after an
244
+ accepted rating, `playervox.rating.subscribe` delivers the stored rating,
245
+ and the widget shows that.
246
+
247
+ ### The intents
248
+
249
+ <!-- generated:write-intents -->
250
+ ### `notes.save`
251
+
252
+ Capability `notes.write`; `target` attribute required (note ID; the host fills the bound controls from that note). Enter in a `field` of the form moves the focus to its next `field` or `textarea` and does not submit; Ctrl+Enter and a `submit` button do.
253
+
254
+ | Field | Type | Required | Meaning |
255
+ | --- | --- | --- | --- |
256
+ | `title` | text ≤ 96 bytes | yes | `field`; saved trimmed, and not empty. |
257
+ | `body` | text ≤ 8 KiB | no | `textarea`; saved as written. |
258
+ | `item` | list of `NoteItem` ≤ 64 | no | One `field` per checklist row, in order, each ≤ 256 bytes. The host remembers which item it filled each field with: a row keeps that item's ID and check whichever rows the widget removes or moves, and a field that appeared since is a new, unchecked item. Rows are saved trimmed; an empty row is dropped. A note saved as it is stored is accepted without a write. |
259
+
260
+ ### `playervox.rating.publish`
261
+
262
+ Capability `playervox.rating.write`; `target` attribute refused.
263
+
264
+ | Field | Type | Required | Meaning |
265
+ | --- | --- | --- | --- |
266
+ | `gameplay` | integer 0 to 100 | yes | `slider`; filled from the user's rating, 50 before the first one. |
267
+ | `art` | integer 0 to 100 | yes | `slider`; filled like `gameplay`. |
268
+ | `tech` | integer 0 to 100 | yes | `slider`; filled like `gameplay`. |
269
+ | `review` | text ≤ 2000 characters | no | `textarea`; filled from the published review. An unchanged review is not sent again; an emptied one removes it. |
270
+
271
+ ### `twitch.chat.send`
272
+
273
+ Capability `twitch.chat.compose`; `target` attribute optional (ID of the message replied to).
274
+
275
+ | Field | Type | Required | Meaning |
276
+ | --- | --- | --- | --- |
277
+ | `message` | text ≤ 500 characters | yes | `field`; the host clears it after a successful send. |
278
+ <!-- /generated:write-intents -->
279
+
280
+ `target` is the form's attribute that names the object written: the note's
281
+ ID for `notes.save`, the ID of the message replied to for
282
+ `twitch.chat.send`.
283
+
284
+ ### Several rows of one field
285
+
286
+ The `notes.save` intent takes one `item` field per checklist row. The
287
+ logic decides which rows the form has, with a `for`; OverCrow fills each
288
+ row's field from the stored note and remembers which checklist entry it
289
+ put there. A row that the logic removes or moves keeps its entry, and a
290
+ row added since is a new entry.
291
+
292
+ <!-- source: widgets/notes/view.ocml -->
293
+ ```xml
294
+ <for each={editor.rows} as="row" key={row.key}>
295
+ <box class="row">
296
+ <if test={rowStored(state, editor, row)}>
297
+ <checkbox class="row-check" checked={rowChecked(state, editor, row)} label={rowLabel(row)} on:change={check(editor.note, row.id, event.value)}/>
298
+ </if>
299
+ <else>
300
+ <icon class="row-new" name="circle"/>
301
+ </else>
302
+ <field class="row-field" name="item" placeholder={rowHint(editor, row)} label={t("item-hint")} on:input={rowInput(editor.key, row.key, event.value)} on:keydown={keyed(editor.key, event.key, event.ctrl)}/>
303
+ ```
304
+
305
+ In that form, Enter moves to the next field instead of submitting;
306
+ Ctrl+Enter or the `submit` button saves.
307
+
308
+ ## Confirmations
309
+
310
+ Two services delete user data: `notes.delete` and `journal.delete`. They
311
+ are ordinary calls that need a user action, and OverCrow then asks the
312
+ user to confirm in a dialog that it draws itself, outside the widget. The
313
+ call resolves when the user confirms and fails with `cancelled` when they
314
+ decline. Do not draw your own "Are you sure?": OverCrow's is the one that
315
+ counts.
316
+
317
+ ## Checklist for a form
318
+
319
+ - Every control has a `label`.
320
+ - Buttons that cannot act are `disabled`, and nothing that needs input
321
+ shows in Passive mode.
322
+ - The `submit` handler handles a refusal: `not_connected` when the account
323
+ is signed out, `busy` when the user sends too fast, `unavailable`.
324
+ - A form bound to an intent has no `value` on its text fields and
325
+ sliders, and every named control is a field of the intent.
326
+ - Test it with a scenario: `text` steps type into the focused field,
327
+ `key` steps press Enter, and `expect.intents` checks exactly what
328
+ OverCrow sent. See [testing a widget](testing.md#steps).
@@ -0,0 +1,252 @@
1
+ # Creator guide
2
+
3
+ This guide takes a PlayerVox OverCrow widget from an empty directory to a
4
+ submission: create a project, edit its view, style and logic, run it in
5
+ OverCrow, test it, package it and submit it. Each step links to the page
6
+ that covers it in full.
7
+
8
+ To work with an AI assistant instead, add OverCrow's MCP server to it: see
9
+ [MCP](mcp.md).
10
+
11
+ ## 1. Install the tools
12
+
13
+ - **`overcrow-widget`**, the widget CLI, one binary for Linux and Windows.
14
+ See [installing the CLI](cli.md#installing).
15
+ - **Node.js 22 or later** and npm, so that `check` can type-check your
16
+ logic with the project's own TypeScript and the SDK from npm. The CLI checks and packages without it, but
17
+ warns that types were not checked.
18
+ - **OverCrow**, to run the widget while you write it.
19
+
20
+ `overcrow-widget doctor` tells what your setup has and lacks.
21
+
22
+ ## 2. Create a project
23
+
24
+ ```sh
25
+ overcrow-widget init my-counter --template counter
26
+ cd my-counter
27
+ npm install
28
+ ```
29
+
30
+ `npm install` brings TypeScript and `@overcrow/sdk` 1.0.0, named in the
31
+ project's `package.json`.
32
+
33
+ The templates are `blank`, `counter`, `list` and `chart`. The ID defaults to
34
+ `com.example.<dir>`: pass `--id` with a reverse-DNS name you control
35
+ (`com.playervox.*` is reserved). [Files of a project](cli.md#files-of-a-project)
36
+ lists every file and says which ones are packaged;
37
+ [the SDK types](cli.md#the-sdk-types) says how to add the SDK to another
38
+ project.
39
+
40
+ ## 3. The view
41
+
42
+ `view.ocml` is markup: elements, attributes, `{…}` expressions bound to the
43
+ state, and `on:<event>` handlers that call functions exported by the logic.
44
+
45
+ <!-- source: templates/counter/view.ocml -->
46
+ ```xml
47
+ <box class="counter">
48
+ <text class="value">{state.count}</text>
49
+ <box class="actions">
50
+ <button class="step" label={t("decrement")} on:activate={decrement}>
51
+ <icon name="minus"/>
52
+ </button>
53
+ <button class="step" label={t("increment")} on:activate={increment}>
54
+ <icon name="plus"/>
55
+ </button>
56
+ </box>
57
+ </box>
58
+ ```
59
+
60
+ The view also has `if`, `for` with a mandatory key, and local components:
61
+ see [the view](view.md). Every element and attribute is in
62
+ [elements and attributes](elements.md).
63
+
64
+ ## 4. The style
65
+
66
+ `style.ocss` is a bounded subset of CSS: class, element, descendant and
67
+ child selectors, the `:hover`, `:active`, `:focus`, `:disabled` and
68
+ `:checked` states, flex and grid layout, and the theme's design tokens as
69
+ `var(--…)`, which follow the user's light or dark theme.
70
+
71
+ <!-- source: templates/counter/style.ocss -->
72
+ ```css
73
+ .step {
74
+ width: var(--icon-button-size);
75
+ height: var(--icon-button-size);
76
+ border-radius: var(--radius-md);
77
+ background: var(--color-surface-raised);
78
+ }
79
+ ```
80
+
81
+ <!-- source: templates/counter/style.ocss -->
82
+ ```css
83
+ .step:hover {
84
+ background: var(--color-surface-hover);
85
+ }
86
+ ```
87
+
88
+ There is no `@media`, `@import`, `url()` or `calc()`: an unknown
89
+ property or selector is an error, not a silent no-op. See
90
+ [the style](style.md) and [style properties and tokens](style-properties.md).
91
+
92
+ ## 5. The logic
93
+
94
+ `logic.ts` owns the state. Declare its type once, mutate it in your
95
+ handlers, and the view follows: after each turn the VM evaluates the view
96
+ again and sends only what changed.
97
+
98
+ <!-- source: templates/counter/logic.ts -->
99
+ ```ts
100
+ import { initState } from "@overcrow/sdk";
101
+
102
+ declare module "@overcrow/sdk" {
103
+ interface WidgetState {
104
+ count: number;
105
+ }
106
+ }
107
+ ```
108
+
109
+ <!-- source: templates/counter/logic.ts -->
110
+ ```ts
111
+ export function increment(): void {
112
+ state.count += 1;
113
+ }
114
+ ```
115
+
116
+ The logic runs in a sandboxed VM, not in a browser: there is no DOM,
117
+ `fetch`, `setTimeout`, `console` or `Intl`. The SDK provides timers,
118
+ services, formatting helpers for times and numbers in the user's regional
119
+ format, messages and drawing. See [the logic](logic.md) and the
120
+ [SDK reference](sdk.md).
121
+
122
+ ## 6. Messages
123
+
124
+ `t("key")` in the view or the logic reads `locales/en.json` or
125
+ `locales/fr.json` for the user's language, and fills `{name}` parameters.
126
+
127
+ <!-- source: templates/counter/locales/en.json -->
128
+ ```json
129
+ {
130
+ "decrement": "Decrease",
131
+ "increment": "Increase"
132
+ }
133
+ ```
134
+
135
+ Provide both files or neither, with the same keys. See
136
+ [messages](logic.md#messages).
137
+
138
+ ## 7. Check
139
+
140
+ ```sh
141
+ overcrow-widget check
142
+ ```
143
+
144
+ `check` runs the same validators as OverCrow: manifest, view, style,
145
+ locales, a lint of the logic against what the VM runs, the project's
146
+ TypeScript, and a package built in memory and read back. Each problem has a
147
+ stable code, a position and a help line; see
148
+ [diagnostics](cli.md#diagnostics).
149
+
150
+ ## 8. Run it in OverCrow
151
+
152
+ ```sh
153
+ overcrow-widget dev
154
+ ```
155
+
156
+ `dev` sends the widget to the OverCrow overlay running on your machine and
157
+ reloads it each time you save. OverCrow offers this only when it was
158
+ started with development installs allowed (`OVERCROW_WIDGET_DEVELOPMENT=1`;
159
+ `overcrow-widget doctor` prints the commands). The widget shows an
160
+ **Unverified · development package** marker; its declared permissions are
161
+ granted for the session only, and nothing is stored. `log.info(…)` from your
162
+ logic prints in the terminal. See
163
+ [the development channel](dev-channel.md).
164
+
165
+ ## 9. Test it
166
+
167
+ Two kinds of tests, both described in [testing a widget](testing.md):
168
+
169
+ - unit tests of the logic with `@overcrow/sdk/testing`, which runs your
170
+ module with virtual time and simulated services;
171
+ - scenarios played by `overcrow-widget test` in OverCrow's headless
172
+ runtime: the real VM and renderer, services answered by fixtures, and
173
+ images compared with references.
174
+
175
+ <!-- source: templates/counter/tests/example.scenario.json -->
176
+ ```json
177
+ "host": { "mode": "interactive" },
178
+ "steps": [
179
+ { "expect": { "state": "running", "text": ["0"], "image": "initial" } },
180
+ { "pointer": { "click": { "label": "Increase" } } },
181
+ { "expect": { "text": ["1"], "noText": ["0"], "image": "increased", "fault": "none" } }
182
+ ]
183
+ ```
184
+
185
+ ```sh
186
+ overcrow-widget test
187
+ ```
188
+
189
+ ## 10. Ask for what you need
190
+
191
+ A widget gets nothing by default. To call an API, keep data or read game
192
+ information, declare it in `manifest.json`; the user consents in the
193
+ Control Center before the widget gets it. A network rule names one HTTPS origin, one method and one
194
+ complete path, with typed parameters:
195
+
196
+ <!-- source: docs/content/examples/weather/manifest.json -->
197
+ ```json
198
+ "permissions": {
199
+ "network": [
200
+ {
201
+ "origin": "https://api.example.com",
202
+ "method": "GET",
203
+ "path": "/v1/forecast/{city}",
204
+ "pathParams": { "city": { "type": "slug", "maxLength": 32 } },
205
+ "queryParams": {
206
+ "units": { "type": "enum", "values": ["metric", "imperial"], "required": true }
207
+ }
208
+ }
209
+ ],
210
+ "storage": true
211
+ },
212
+ ```
213
+
214
+ <!-- source: docs/content/examples/weather/logic.ts -->
215
+ ```ts
216
+ const url = `https://api.example.com/v1/forecast/${state.city}?units=${state.units}`;
217
+ const { status, body } = await http.fetch(url, { as: "json" });
218
+ ```
219
+
220
+ Game and system data come from subscriptions (`fps.subscribe`,
221
+ `media.subscribe`…), which update your state until you cancel them. See
222
+ [services and permissions](services.md) for what each permission allows,
223
+ and [security](security.md) for what a widget can never do. The complete
224
+ example is in
225
+ [`docs/content/examples/weather`](../examples/weather/).
226
+
227
+ ## 11. Package
228
+
229
+ ```sh
230
+ overcrow-widget package
231
+ overcrow-widget inspect dist/com.example.my-counter-0.1.0.ocpkg
232
+ ```
233
+
234
+ `package` writes a deterministic `.ocpkg` to `dist/`: the same sources and
235
+ CLI version give the same bytes on every system. `inspect` shows what a
236
+ package holds and asks for, as a reviewer sees it. A package installed
237
+ locally stays unverified; users get widgets from the signed catalog. See
238
+ [the package](package.md).
239
+
240
+ ## 12. Submit
241
+
242
+ Add a `listing.json` with the marketplace text and run the admission
243
+ yourself. Widgets are no longer proposed by pull request: you will send
244
+ yours from the OverCrow creator space when it opens.
245
+
246
+ ```sh
247
+ overcrow-widget admit
248
+ ```
249
+
250
+ `admit` runs exactly the checks of the marketplace CI. What happens next,
251
+ from review to the signed catalog, is in
252
+ [publishing and review](publishing.md).
@@ -0,0 +1,85 @@
1
+ # Build widgets for PlayerVox OverCrow
2
+
3
+ A PlayerVox OverCrow widget is a small package that the overlay draws over
4
+ your game: a clock, a frame-rate counter, a checklist, a chat. You describe
5
+ its view in markup, style it with a small subset of CSS, and write its logic
6
+ in TypeScript against `@overcrow/sdk`. The `overcrow-widget` command-line
7
+ tool checks, tests and packages it; the signed catalog brings it to users.
8
+
9
+ Every built-in widget of OverCrow is written this way, with the same public
10
+ SDK, package format and sandbox as yours. Their sources are the
11
+ [reference widgets](widgets.md).
12
+
13
+ ## What a widget is made of
14
+
15
+ | File | Role | Page |
16
+ | --- | --- | --- |
17
+ | `manifest.json` | Identity, version, names, size rules, the options menu and the permissions the widget asks for. | [The manifest](manifest.md) |
18
+ | `view.ocml` | The view: elements such as `box`, `text`, `button`, `list` or `chart`, bound to the state with `{…}` expressions. | [The view](view.md) |
19
+ | `style.ocss` | Optional style: flex and grid layout, colours, borders, typography, with the theme's design tokens. | [The style](style.md) |
20
+ | `logic.ts` | The logic: the state, the event handlers, timers and calls to services. | [The logic](logic.md) |
21
+ | `locales/en.json`, `locales/fr.json` | Optional messages in English and French. | [Messages](logic.md#messages) |
22
+ | `LICENSE` | The license of your widget. | [The package](package.md) |
23
+
24
+ The view and the logic meet like this: the view reads `state.count` and
25
+ calls the handlers the logic exports.
26
+
27
+ <!-- source: templates/counter/view.ocml -->
28
+ ```xml
29
+ <box class="counter">
30
+ <text class="value">{state.count}</text>
31
+ <box class="actions">
32
+ <button class="step" label={t("decrement")} on:activate={decrement}>
33
+ <icon name="minus"/>
34
+ </button>
35
+ <button class="step" label={t("increment")} on:activate={increment}>
36
+ <icon name="plus"/>
37
+ </button>
38
+ </box>
39
+ </box>
40
+ ```
41
+
42
+ <!-- source: templates/counter/logic.ts -->
43
+ ```ts
44
+ const state = initState({ count: 0 });
45
+
46
+ export function increment(): void {
47
+ state.count += 1;
48
+ }
49
+ ```
50
+
51
+ ## How a widget runs
52
+
53
+ - The logic runs in its own small JavaScript VM, in its own sandboxed
54
+ process. It has no DOM, no file system, no network and no access to other
55
+ widgets; it reaches OverCrow only through the SDK.
56
+ - After each event, timer tick or service answer, the VM evaluates the view
57
+ again and sends OverCrow only what changed. OverCrow lays out and paints
58
+ the widget itself: no web engine is involved.
59
+ - Everything that reaches the outside (network, storage, clipboard, game
60
+ data) is a service of OverCrow, which checks the widget's declared and
61
+ consented permissions at each call. See
62
+ [services and permissions](services.md).
63
+
64
+ These pages call OverCrow **the host** when they describe what it does for a
65
+ widget: the host draws the view, answers the services and keeps the user's
66
+ data.
67
+
68
+ ## Where to start
69
+
70
+ 1. Follow the [creator guide](guide.md): from `overcrow-widget init` to a
71
+ submitted widget, in twelve short steps.
72
+ 2. Read the [reference widgets](widgets.md): the built-ins, with their tests.
73
+ 3. Go deeper, one topic per page: the [manifest](manifest.md), the
74
+ [view](view.md), the [style](style.md), the [logic](logic.md),
75
+ [services and permissions](services.md), [forms](forms.md).
76
+ 4. Use the tools: the [CLI](cli.md), [tests](testing.md) and the
77
+ [development channel](dev-channel.md) that runs your widget in OverCrow
78
+ while you write it.
79
+ 5. Look up an element, a style property, a service or an SDK function in the
80
+ [reference](reference.md).
81
+ 6. Before you publish, read [the package](package.md),
82
+ [security](security.md) and [publishing and review](publishing.md).
83
+
84
+ Widgets run on Windows and Linux alike: the same package, the same SDK and
85
+ the same rendering.