@treenity/mods 3.0.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 (486) hide show
  1. package/board/board.test.ts +212 -0
  2. package/board/client.ts +1 -0
  3. package/board/seed.ts +26 -0
  4. package/board/server.ts +5 -0
  5. package/board/types.ts +87 -0
  6. package/board/view.tsx +574 -0
  7. package/brahman/CLAUDE.md +18 -0
  8. package/brahman/brahman.test.ts +855 -0
  9. package/brahman/client.ts +2 -0
  10. package/brahman/helpers.ts +374 -0
  11. package/brahman/server.ts +2 -0
  12. package/brahman/service.ts +328 -0
  13. package/brahman/types.ts +727 -0
  14. package/brahman/view.tsx +73 -0
  15. package/brahman/views/action-cards.tsx +615 -0
  16. package/brahman/views/bot-view.tsx +76 -0
  17. package/brahman/views/chat-editor.tsx +782 -0
  18. package/brahman/views/chat-preview.tsx +266 -0
  19. package/brahman/views/menu-editor.tsx +451 -0
  20. package/brahman/views/page-layout.tsx +285 -0
  21. package/brahman/views/tstring-input.tsx +84 -0
  22. package/cafe/CLAUDE.md +7 -0
  23. package/cafe/seed.ts +8 -0
  24. package/cafe/server.ts +2 -0
  25. package/cafe/types.ts +32 -0
  26. package/canary/seed.ts +8 -0
  27. package/canary/server.ts +3 -0
  28. package/canary/service.ts +101 -0
  29. package/canary/types.ts +16 -0
  30. package/dist/board/client.d.ts +2 -0
  31. package/dist/board/client.d.ts.map +1 -0
  32. package/dist/board/client.js +2 -0
  33. package/dist/board/client.js.map +1 -0
  34. package/dist/board/seed.d.ts +2 -0
  35. package/dist/board/seed.d.ts.map +1 -0
  36. package/dist/board/seed.js +23 -0
  37. package/dist/board/seed.js.map +1 -0
  38. package/dist/board/server.d.ts +3 -0
  39. package/dist/board/server.d.ts.map +1 -0
  40. package/dist/board/server.js +5 -0
  41. package/dist/board/server.js.map +1 -0
  42. package/dist/board/types.d.ts +45 -0
  43. package/dist/board/types.d.ts.map +1 -0
  44. package/dist/board/types.js +82 -0
  45. package/dist/board/types.js.map +1 -0
  46. package/dist/board/view.d.ts +2 -0
  47. package/dist/board/view.d.ts.map +1 -0
  48. package/dist/board/view.js +254 -0
  49. package/dist/board/view.js.map +1 -0
  50. package/dist/brahman/client.d.ts +3 -0
  51. package/dist/brahman/client.d.ts.map +1 -0
  52. package/dist/brahman/client.js +3 -0
  53. package/dist/brahman/client.js.map +1 -0
  54. package/dist/brahman/helpers.d.ts +51 -0
  55. package/dist/brahman/helpers.d.ts.map +1 -0
  56. package/dist/brahman/helpers.js +321 -0
  57. package/dist/brahman/helpers.js.map +1 -0
  58. package/dist/brahman/server.d.ts +3 -0
  59. package/dist/brahman/server.d.ts.map +1 -0
  60. package/dist/brahman/server.js +3 -0
  61. package/dist/brahman/server.js.map +1 -0
  62. package/dist/brahman/service.d.ts +2 -0
  63. package/dist/brahman/service.d.ts.map +1 -0
  64. package/dist/brahman/service.js +310 -0
  65. package/dist/brahman/service.js.map +1 -0
  66. package/dist/brahman/types.d.ts +335 -0
  67. package/dist/brahman/types.d.ts.map +1 -0
  68. package/dist/brahman/types.js +633 -0
  69. package/dist/brahman/types.js.map +1 -0
  70. package/dist/brahman/view.d.ts +2 -0
  71. package/dist/brahman/view.d.ts.map +1 -0
  72. package/dist/brahman/view.js +47 -0
  73. package/dist/brahman/view.js.map +1 -0
  74. package/dist/brahman/views/action-cards.d.ts +60 -0
  75. package/dist/brahman/views/action-cards.d.ts.map +1 -0
  76. package/dist/brahman/views/action-cards.js +283 -0
  77. package/dist/brahman/views/action-cards.js.map +1 -0
  78. package/dist/brahman/views/bot-view.d.ts +5 -0
  79. package/dist/brahman/views/bot-view.d.ts.map +1 -0
  80. package/dist/brahman/views/bot-view.js +14 -0
  81. package/dist/brahman/views/bot-view.js.map +1 -0
  82. package/dist/brahman/views/chat-editor.d.ts +5 -0
  83. package/dist/brahman/views/chat-editor.d.ts.map +1 -0
  84. package/dist/brahman/views/chat-editor.js +306 -0
  85. package/dist/brahman/views/chat-editor.js.map +1 -0
  86. package/dist/brahman/views/chat-preview.d.ts +5 -0
  87. package/dist/brahman/views/chat-preview.d.ts.map +1 -0
  88. package/dist/brahman/views/chat-preview.js +145 -0
  89. package/dist/brahman/views/chat-preview.js.map +1 -0
  90. package/dist/brahman/views/menu-editor.d.ts +11 -0
  91. package/dist/brahman/views/menu-editor.d.ts.map +1 -0
  92. package/dist/brahman/views/menu-editor.js +171 -0
  93. package/dist/brahman/views/menu-editor.js.map +1 -0
  94. package/dist/brahman/views/page-layout.d.ts +5 -0
  95. package/dist/brahman/views/page-layout.d.ts.map +1 -0
  96. package/dist/brahman/views/page-layout.js +114 -0
  97. package/dist/brahman/views/page-layout.js.map +1 -0
  98. package/dist/brahman/views/tstring-input.d.ts +15 -0
  99. package/dist/brahman/views/tstring-input.d.ts.map +1 -0
  100. package/dist/brahman/views/tstring-input.js +23 -0
  101. package/dist/brahman/views/tstring-input.js.map +1 -0
  102. package/dist/cafe/seed.d.ts +2 -0
  103. package/dist/cafe/seed.d.ts.map +1 -0
  104. package/dist/cafe/seed.js +7 -0
  105. package/dist/cafe/seed.js.map +1 -0
  106. package/dist/cafe/server.d.ts +3 -0
  107. package/dist/cafe/server.d.ts.map +1 -0
  108. package/dist/cafe/server.js +3 -0
  109. package/dist/cafe/server.js.map +1 -0
  110. package/dist/cafe/types.d.ts +2 -0
  111. package/dist/cafe/types.d.ts.map +1 -0
  112. package/dist/cafe/types.js +31 -0
  113. package/dist/cafe/types.js.map +1 -0
  114. package/dist/canary/seed.d.ts +2 -0
  115. package/dist/canary/seed.d.ts.map +1 -0
  116. package/dist/canary/seed.js +7 -0
  117. package/dist/canary/seed.js.map +1 -0
  118. package/dist/canary/server.d.ts +4 -0
  119. package/dist/canary/server.d.ts.map +1 -0
  120. package/dist/canary/server.js +4 -0
  121. package/dist/canary/server.js.map +1 -0
  122. package/dist/canary/service.d.ts +2 -0
  123. package/dist/canary/service.d.ts.map +1 -0
  124. package/dist/canary/service.js +101 -0
  125. package/dist/canary/service.js.map +1 -0
  126. package/dist/canary/types.d.ts +9 -0
  127. package/dist/canary/types.d.ts.map +1 -0
  128. package/dist/canary/types.js +13 -0
  129. package/dist/canary/types.js.map +1 -0
  130. package/dist/doc/client.d.ts +3 -0
  131. package/dist/doc/client.d.ts.map +1 -0
  132. package/dist/doc/client.js +5 -0
  133. package/dist/doc/client.js.map +1 -0
  134. package/dist/doc/fs-codec.d.ts +2 -0
  135. package/dist/doc/fs-codec.d.ts.map +1 -0
  136. package/dist/doc/fs-codec.js +44 -0
  137. package/dist/doc/fs-codec.js.map +1 -0
  138. package/dist/doc/markdown.d.ts +13 -0
  139. package/dist/doc/markdown.d.ts.map +1 -0
  140. package/dist/doc/markdown.js +250 -0
  141. package/dist/doc/markdown.js.map +1 -0
  142. package/dist/doc/prefab.d.ts +2 -0
  143. package/dist/doc/prefab.d.ts.map +1 -0
  144. package/dist/doc/prefab.js +23 -0
  145. package/dist/doc/prefab.js.map +1 -0
  146. package/dist/doc/renderers.d.ts +2 -0
  147. package/dist/doc/renderers.d.ts.map +1 -0
  148. package/dist/doc/renderers.js +94 -0
  149. package/dist/doc/renderers.js.map +1 -0
  150. package/dist/doc/seed.d.ts +2 -0
  151. package/dist/doc/seed.d.ts.map +1 -0
  152. package/dist/doc/seed.js +9 -0
  153. package/dist/doc/seed.js.map +1 -0
  154. package/dist/doc/server.d.ts +6 -0
  155. package/dist/doc/server.d.ts.map +1 -0
  156. package/dist/doc/server.js +6 -0
  157. package/dist/doc/server.js.map +1 -0
  158. package/dist/doc/slash-command.d.ts +3 -0
  159. package/dist/doc/slash-command.d.ts.map +1 -0
  160. package/dist/doc/slash-command.js +123 -0
  161. package/dist/doc/slash-command.js.map +1 -0
  162. package/dist/doc/slash-menu.d.ts +15 -0
  163. package/dist/doc/slash-menu.d.ts.map +1 -0
  164. package/dist/doc/slash-menu.js +54 -0
  165. package/dist/doc/slash-menu.js.map +1 -0
  166. package/dist/doc/text.d.ts +2 -0
  167. package/dist/doc/text.d.ts.map +1 -0
  168. package/dist/doc/text.js +22 -0
  169. package/dist/doc/text.js.map +1 -0
  170. package/dist/doc/toolbar.d.ts +5 -0
  171. package/dist/doc/toolbar.d.ts.map +1 -0
  172. package/dist/doc/toolbar.js +15 -0
  173. package/dist/doc/toolbar.js.map +1 -0
  174. package/dist/doc/treenity-block-view.d.ts +2 -0
  175. package/dist/doc/treenity-block-view.d.ts.map +1 -0
  176. package/dist/doc/treenity-block-view.js +37 -0
  177. package/dist/doc/treenity-block-view.js.map +1 -0
  178. package/dist/doc/treenity-block.d.ts +3 -0
  179. package/dist/doc/treenity-block.d.ts.map +1 -0
  180. package/dist/doc/treenity-block.js +27 -0
  181. package/dist/doc/treenity-block.js.map +1 -0
  182. package/dist/doc/types.d.ts +2 -0
  183. package/dist/doc/types.d.ts.map +1 -0
  184. package/dist/doc/types.js +10 -0
  185. package/dist/doc/types.js.map +1 -0
  186. package/dist/launcher/client.d.ts +5 -0
  187. package/dist/launcher/client.d.ts.map +1 -0
  188. package/dist/launcher/client.js +5 -0
  189. package/dist/launcher/client.js.map +1 -0
  190. package/dist/launcher/icons.d.ts +2 -0
  191. package/dist/launcher/icons.d.ts.map +1 -0
  192. package/dist/launcher/icons.js +57 -0
  193. package/dist/launcher/icons.js.map +1 -0
  194. package/dist/launcher/seed.d.ts +2 -0
  195. package/dist/launcher/seed.d.ts.map +1 -0
  196. package/dist/launcher/seed.js +36 -0
  197. package/dist/launcher/seed.js.map +1 -0
  198. package/dist/launcher/server.d.ts +3 -0
  199. package/dist/launcher/server.d.ts.map +1 -0
  200. package/dist/launcher/server.js +3 -0
  201. package/dist/launcher/server.js.map +1 -0
  202. package/dist/launcher/types.d.ts +21 -0
  203. package/dist/launcher/types.d.ts.map +1 -0
  204. package/dist/launcher/types.js +47 -0
  205. package/dist/launcher/types.js.map +1 -0
  206. package/dist/launcher/view.d.ts +2 -0
  207. package/dist/launcher/view.d.ts.map +1 -0
  208. package/dist/launcher/view.js +187 -0
  209. package/dist/launcher/view.js.map +1 -0
  210. package/dist/launcher/widgets.d.ts +2 -0
  211. package/dist/launcher/widgets.d.ts.map +1 -0
  212. package/dist/launcher/widgets.js +73 -0
  213. package/dist/launcher/widgets.js.map +1 -0
  214. package/dist/mindmap/branch.d.ts +17 -0
  215. package/dist/mindmap/branch.d.ts.map +1 -0
  216. package/dist/mindmap/branch.js +47 -0
  217. package/dist/mindmap/branch.js.map +1 -0
  218. package/dist/mindmap/client.d.ts +3 -0
  219. package/dist/mindmap/client.d.ts.map +1 -0
  220. package/dist/mindmap/client.js +3 -0
  221. package/dist/mindmap/client.js.map +1 -0
  222. package/dist/mindmap/radial-tree.d.ts +14 -0
  223. package/dist/mindmap/radial-tree.d.ts.map +1 -0
  224. package/dist/mindmap/radial-tree.js +184 -0
  225. package/dist/mindmap/radial-tree.js.map +1 -0
  226. package/dist/mindmap/sidebar.d.ts +8 -0
  227. package/dist/mindmap/sidebar.d.ts.map +1 -0
  228. package/dist/mindmap/sidebar.js +24 -0
  229. package/dist/mindmap/sidebar.js.map +1 -0
  230. package/dist/mindmap/types.d.ts +8 -0
  231. package/dist/mindmap/types.d.ts.map +1 -0
  232. package/dist/mindmap/types.js +10 -0
  233. package/dist/mindmap/types.js.map +1 -0
  234. package/dist/mindmap/use-tree-data.d.ts +14 -0
  235. package/dist/mindmap/use-tree-data.d.ts.map +1 -0
  236. package/dist/mindmap/use-tree-data.js +95 -0
  237. package/dist/mindmap/use-tree-data.js.map +1 -0
  238. package/dist/mindmap/view.d.ts +3 -0
  239. package/dist/mindmap/view.d.ts.map +1 -0
  240. package/dist/mindmap/view.js +141 -0
  241. package/dist/mindmap/view.js.map +1 -0
  242. package/dist/sensor-demo/client.d.ts +2 -0
  243. package/dist/sensor-demo/client.d.ts.map +1 -0
  244. package/dist/sensor-demo/client.js +2 -0
  245. package/dist/sensor-demo/client.js.map +1 -0
  246. package/dist/sensor-demo/server.d.ts +2 -0
  247. package/dist/sensor-demo/server.d.ts.map +1 -0
  248. package/dist/sensor-demo/server.js +2 -0
  249. package/dist/sensor-demo/server.js.map +1 -0
  250. package/dist/sensor-demo/service.d.ts +2 -0
  251. package/dist/sensor-demo/service.d.ts.map +1 -0
  252. package/dist/sensor-demo/service.js +27 -0
  253. package/dist/sensor-demo/service.js.map +1 -0
  254. package/dist/sensor-demo/types.d.ts +15 -0
  255. package/dist/sensor-demo/types.d.ts.map +1 -0
  256. package/dist/sensor-demo/types.js +18 -0
  257. package/dist/sensor-demo/types.js.map +1 -0
  258. package/dist/sensor-demo/view.d.ts +2 -0
  259. package/dist/sensor-demo/view.d.ts.map +1 -0
  260. package/dist/sensor-demo/view.js +33 -0
  261. package/dist/sensor-demo/view.js.map +1 -0
  262. package/dist/sensor-generator/action.d.ts +2 -0
  263. package/dist/sensor-generator/action.d.ts.map +1 -0
  264. package/dist/sensor-generator/action.js +23 -0
  265. package/dist/sensor-generator/action.js.map +1 -0
  266. package/dist/sensor-generator/client.d.ts +2 -0
  267. package/dist/sensor-generator/client.d.ts.map +1 -0
  268. package/dist/sensor-generator/client.js +2 -0
  269. package/dist/sensor-generator/client.js.map +1 -0
  270. package/dist/sensor-generator/server.d.ts +2 -0
  271. package/dist/sensor-generator/server.d.ts.map +1 -0
  272. package/dist/sensor-generator/server.js +2 -0
  273. package/dist/sensor-generator/server.js.map +1 -0
  274. package/dist/sensor-generator/view.d.ts +2 -0
  275. package/dist/sensor-generator/view.d.ts.map +1 -0
  276. package/dist/sensor-generator/view.js +64 -0
  277. package/dist/sensor-generator/view.js.map +1 -0
  278. package/dist/sim/client.d.ts +2 -0
  279. package/dist/sim/client.d.ts.map +1 -0
  280. package/dist/sim/client.js +2 -0
  281. package/dist/sim/client.js.map +1 -0
  282. package/dist/sim/seed.d.ts +2 -0
  283. package/dist/sim/seed.d.ts.map +1 -0
  284. package/dist/sim/seed.js +50 -0
  285. package/dist/sim/seed.js.map +1 -0
  286. package/dist/sim/server.d.ts +3 -0
  287. package/dist/sim/server.d.ts.map +1 -0
  288. package/dist/sim/server.js +3 -0
  289. package/dist/sim/server.js.map +1 -0
  290. package/dist/sim/service.d.ts +4 -0
  291. package/dist/sim/service.d.ts.map +1 -0
  292. package/dist/sim/service.js +528 -0
  293. package/dist/sim/service.js.map +1 -0
  294. package/dist/sim/types.d.ts +63 -0
  295. package/dist/sim/types.d.ts.map +1 -0
  296. package/dist/sim/types.js +57 -0
  297. package/dist/sim/types.js.map +1 -0
  298. package/dist/sim/view.d.ts +2 -0
  299. package/dist/sim/view.d.ts.map +1 -0
  300. package/dist/sim/view.js +205 -0
  301. package/dist/sim/view.js.map +1 -0
  302. package/dist/table/client.d.ts +4 -0
  303. package/dist/table/client.d.ts.map +1 -0
  304. package/dist/table/client.js +4 -0
  305. package/dist/table/client.js.map +1 -0
  306. package/dist/table/edit.d.ts +2 -0
  307. package/dist/table/edit.d.ts.map +1 -0
  308. package/dist/table/edit.js +115 -0
  309. package/dist/table/edit.js.map +1 -0
  310. package/dist/table/server.d.ts +2 -0
  311. package/dist/table/server.d.ts.map +1 -0
  312. package/dist/table/server.js +2 -0
  313. package/dist/table/server.js.map +1 -0
  314. package/dist/table/types.d.ts +18 -0
  315. package/dist/table/types.d.ts.map +1 -0
  316. package/dist/table/types.js +13 -0
  317. package/dist/table/types.js.map +1 -0
  318. package/dist/table/use-debounced-sync.d.ts +8 -0
  319. package/dist/table/use-debounced-sync.d.ts.map +1 -0
  320. package/dist/table/use-debounced-sync.js +56 -0
  321. package/dist/table/use-debounced-sync.js.map +1 -0
  322. package/dist/table/view.d.ts +2 -0
  323. package/dist/table/view.d.ts.map +1 -0
  324. package/dist/table/view.js +199 -0
  325. package/dist/table/view.js.map +1 -0
  326. package/dist/tasks/server.d.ts +2 -0
  327. package/dist/tasks/server.d.ts.map +1 -0
  328. package/dist/tasks/server.js +2 -0
  329. package/dist/tasks/server.js.map +1 -0
  330. package/dist/tasks/types.d.ts +22 -0
  331. package/dist/tasks/types.d.ts.map +1 -0
  332. package/dist/tasks/types.js +34 -0
  333. package/dist/tasks/types.js.map +1 -0
  334. package/dist/three/client.d.ts +2 -0
  335. package/dist/three/client.d.ts.map +1 -0
  336. package/dist/three/client.js +2 -0
  337. package/dist/three/client.js.map +1 -0
  338. package/dist/three/seed.d.ts +2 -0
  339. package/dist/three/seed.d.ts.map +1 -0
  340. package/dist/three/seed.js +45 -0
  341. package/dist/three/seed.js.map +1 -0
  342. package/dist/three/server.d.ts +3 -0
  343. package/dist/three/server.d.ts.map +1 -0
  344. package/dist/three/server.js +3 -0
  345. package/dist/three/server.js.map +1 -0
  346. package/dist/three/types.d.ts +178 -0
  347. package/dist/three/types.d.ts.map +1 -0
  348. package/dist/three/types.js +209 -0
  349. package/dist/three/types.js.map +1 -0
  350. package/dist/three/view.d.ts +2 -0
  351. package/dist/three/view.d.ts.map +1 -0
  352. package/dist/three/view.js +307 -0
  353. package/dist/three/view.js.map +1 -0
  354. package/dist/todo/client.d.ts +3 -0
  355. package/dist/todo/client.d.ts.map +1 -0
  356. package/dist/todo/client.js +3 -0
  357. package/dist/todo/client.js.map +1 -0
  358. package/dist/todo/seed.d.ts +2 -0
  359. package/dist/todo/seed.d.ts.map +1 -0
  360. package/dist/todo/seed.js +8 -0
  361. package/dist/todo/seed.js.map +1 -0
  362. package/dist/todo/server.d.ts +3 -0
  363. package/dist/todo/server.d.ts.map +1 -0
  364. package/dist/todo/server.js +3 -0
  365. package/dist/todo/server.js.map +1 -0
  366. package/dist/todo/types.d.ts +15 -0
  367. package/dist/todo/types.d.ts.map +1 -0
  368. package/dist/todo/types.js +29 -0
  369. package/dist/todo/types.js.map +1 -0
  370. package/dist/todo/view.d.ts +2 -0
  371. package/dist/todo/view.d.ts.map +1 -0
  372. package/dist/todo/view.js +27 -0
  373. package/dist/todo/view.js.map +1 -0
  374. package/dist/whisper/client.d.ts +2 -0
  375. package/dist/whisper/client.d.ts.map +1 -0
  376. package/dist/whisper/client.js +2 -0
  377. package/dist/whisper/client.js.map +1 -0
  378. package/dist/whisper/inbox.d.ts +2 -0
  379. package/dist/whisper/inbox.d.ts.map +1 -0
  380. package/dist/whisper/inbox.js +50 -0
  381. package/dist/whisper/inbox.js.map +1 -0
  382. package/dist/whisper/route.d.ts +10 -0
  383. package/dist/whisper/route.d.ts.map +1 -0
  384. package/dist/whisper/route.js +154 -0
  385. package/dist/whisper/route.js.map +1 -0
  386. package/dist/whisper/seed.d.ts +2 -0
  387. package/dist/whisper/seed.d.ts.map +1 -0
  388. package/dist/whisper/seed.js +14 -0
  389. package/dist/whisper/seed.js.map +1 -0
  390. package/dist/whisper/server.d.ts +5 -0
  391. package/dist/whisper/server.d.ts.map +1 -0
  392. package/dist/whisper/server.js +5 -0
  393. package/dist/whisper/server.js.map +1 -0
  394. package/dist/whisper/service.d.ts +2 -0
  395. package/dist/whisper/service.d.ts.map +1 -0
  396. package/dist/whisper/service.js +26 -0
  397. package/dist/whisper/service.js.map +1 -0
  398. package/dist/whisper/types.d.ts +38 -0
  399. package/dist/whisper/types.d.ts.map +1 -0
  400. package/dist/whisper/types.js +45 -0
  401. package/dist/whisper/types.js.map +1 -0
  402. package/dist/whisper/view.d.ts +2 -0
  403. package/dist/whisper/view.d.ts.map +1 -0
  404. package/dist/whisper/view.js +40 -0
  405. package/dist/whisper/view.js.map +1 -0
  406. package/doc/CLAUDE.md +49 -0
  407. package/doc/client.ts +5 -0
  408. package/doc/editor.css +283 -0
  409. package/doc/fs-codec.test.ts +119 -0
  410. package/doc/fs-codec.ts +50 -0
  411. package/doc/markdown.test.ts +152 -0
  412. package/doc/markdown.ts +284 -0
  413. package/doc/prefab.ts +26 -0
  414. package/doc/renderers.tsx +126 -0
  415. package/doc/seed.ts +10 -0
  416. package/doc/server.ts +5 -0
  417. package/doc/slash-command.ts +136 -0
  418. package/doc/slash-menu.tsx +91 -0
  419. package/doc/text.ts +20 -0
  420. package/doc/toolbar.tsx +86 -0
  421. package/doc/treenity-block-view.tsx +116 -0
  422. package/doc/treenity-block.ts +31 -0
  423. package/doc/types.ts +10 -0
  424. package/launcher/client.ts +4 -0
  425. package/launcher/icons.tsx +234 -0
  426. package/launcher/launcher.css +64 -0
  427. package/launcher/seed.ts +41 -0
  428. package/launcher/server.ts +2 -0
  429. package/launcher/types.ts +53 -0
  430. package/launcher/view.tsx +401 -0
  431. package/launcher/widgets.tsx +171 -0
  432. package/mindmap/branch.tsx +163 -0
  433. package/mindmap/client.ts +2 -0
  434. package/mindmap/mindmap.css +243 -0
  435. package/mindmap/sidebar.tsx +127 -0
  436. package/mindmap/types.ts +10 -0
  437. package/mindmap/view.tsx +247 -0
  438. package/package.json +75 -0
  439. package/sensor-demo/CLAUDE.md +3 -0
  440. package/sensor-demo/client.ts +1 -0
  441. package/sensor-demo/server.ts +1 -0
  442. package/sensor-demo/service.ts +27 -0
  443. package/sensor-demo/types.ts +20 -0
  444. package/sensor-demo/view.tsx +64 -0
  445. package/sensor-generator/CLAUDE.md +3 -0
  446. package/sensor-generator/action.ts +28 -0
  447. package/sensor-generator/client.ts +1 -0
  448. package/sensor-generator/server.ts +1 -0
  449. package/sensor-generator/view.tsx +107 -0
  450. package/sim/CLAUDE.md +16 -0
  451. package/sim/client.ts +1 -0
  452. package/sim/seed.ts +55 -0
  453. package/sim/server.ts +2 -0
  454. package/sim/service.ts +594 -0
  455. package/sim/sim.test.ts +282 -0
  456. package/sim/types.ts +87 -0
  457. package/sim/view.tsx +446 -0
  458. package/table/client.ts +3 -0
  459. package/table/edit.tsx +241 -0
  460. package/table/server.ts +1 -0
  461. package/table/types.ts +22 -0
  462. package/table/use-debounced-sync.ts +67 -0
  463. package/table/view.tsx +339 -0
  464. package/tasks/CLAUDE.md +6 -0
  465. package/tasks/server.ts +1 -0
  466. package/tasks/types.ts +36 -0
  467. package/three/CLAUDE.md +6 -0
  468. package/three/client.ts +1 -0
  469. package/three/seed.ts +54 -0
  470. package/three/server.ts +2 -0
  471. package/three/types.ts +238 -0
  472. package/three/view.tsx +453 -0
  473. package/todo/client.ts +2 -0
  474. package/todo/seed.ts +9 -0
  475. package/todo/server.ts +2 -0
  476. package/todo/types.ts +32 -0
  477. package/todo/view.tsx +67 -0
  478. package/whisper/CLAUDE.md +16 -0
  479. package/whisper/client.ts +1 -0
  480. package/whisper/inbox.ts +54 -0
  481. package/whisper/route.ts +182 -0
  482. package/whisper/seed.ts +15 -0
  483. package/whisper/server.ts +4 -0
  484. package/whisper/service.ts +29 -0
  485. package/whisper/types.ts +51 -0
  486. package/whisper/view.tsx +81 -0
package/doc/text.ts ADDED
@@ -0,0 +1,20 @@
1
+ import { register } from '@treenity/core';
2
+ import { type TiptapNode, tiptapToMd } from './markdown';
3
+
4
+ register('doc.page', 'text', (data: unknown) => {
5
+ const d = data as { title?: string; content?: string };
6
+ const lines: string[] = [];
7
+ if (d.title) lines.push(`# ${d.title}`);
8
+
9
+ if (d.content) {
10
+ try {
11
+ const doc = JSON.parse(d.content) as TiptapNode;
12
+ const text = tiptapToMd(doc);
13
+ if (text) lines.push(text);
14
+ } catch {
15
+ if (d.content) lines.push(d.content);
16
+ }
17
+ }
18
+
19
+ return lines.join('\n\n');
20
+ });
@@ -0,0 +1,86 @@
1
+ import type { Editor } from '@tiptap/react';
2
+ import {
3
+ Bold,
4
+ Code,
5
+ Code2,
6
+ Heading1,
7
+ Heading2,
8
+ Heading3,
9
+ Italic,
10
+ List,
11
+ ListOrdered,
12
+ Minus,
13
+ Quote,
14
+ } from 'lucide-react';
15
+
16
+ function Btn({ active, onClick, title, children }: {
17
+ active?: boolean; onClick: () => void; title: string; children: React.ReactNode;
18
+ }) {
19
+ return (
20
+ <button
21
+ onMouseDown={(e) => { e.preventDefault(); onClick(); }}
22
+ title={title}
23
+ className={`flex items-center justify-center w-7 h-7 rounded transition-colors ${
24
+ active
25
+ ? 'bg-[var(--accent-color)] text-white'
26
+ : 'text-[var(--text-2)] hover:text-[var(--text)] hover:bg-[var(--surface-3)]'
27
+ }`}
28
+ >
29
+ {children}
30
+ </button>
31
+ );
32
+ }
33
+
34
+ function Sep() {
35
+ return <span className="w-px h-4 bg-[var(--border)] mx-1 flex-shrink-0" />;
36
+ }
37
+
38
+ export function Toolbar({ editor }: { editor: Editor }) {
39
+ const sz = 14;
40
+ return (
41
+ <div className="doc-toolbar flex items-center flex-wrap gap-0.5 px-1 py-1 mb-2 border-b border-[var(--border)]">
42
+ <Btn active={editor.isActive('bold')} onClick={() => editor.chain().focus().toggleBold().run()} title="Bold (⌘B)">
43
+ <Bold size={sz} />
44
+ </Btn>
45
+ <Btn active={editor.isActive('italic')} onClick={() => editor.chain().focus().toggleItalic().run()} title="Italic (⌘I)">
46
+ <Italic size={sz} />
47
+ </Btn>
48
+ <Btn active={editor.isActive('code')} onClick={() => editor.chain().focus().toggleCode().run()} title="Inline code">
49
+ <Code size={sz} />
50
+ </Btn>
51
+
52
+ <Sep />
53
+
54
+ <Btn active={editor.isActive('heading', { level: 1 })} onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} title="Heading 1">
55
+ <Heading1 size={sz} />
56
+ </Btn>
57
+ <Btn active={editor.isActive('heading', { level: 2 })} onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} title="Heading 2">
58
+ <Heading2 size={sz} />
59
+ </Btn>
60
+ <Btn active={editor.isActive('heading', { level: 3 })} onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} title="Heading 3">
61
+ <Heading3 size={sz} />
62
+ </Btn>
63
+
64
+ <Sep />
65
+
66
+ <Btn active={editor.isActive('bulletList')} onClick={() => editor.chain().focus().toggleBulletList().run()} title="Bullet list">
67
+ <List size={sz} />
68
+ </Btn>
69
+ <Btn active={editor.isActive('orderedList')} onClick={() => editor.chain().focus().toggleOrderedList().run()} title="Ordered list">
70
+ <ListOrdered size={sz} />
71
+ </Btn>
72
+ <Btn active={editor.isActive('blockquote')} onClick={() => editor.chain().focus().toggleBlockquote().run()} title="Quote">
73
+ <Quote size={sz} />
74
+ </Btn>
75
+ <Btn active={editor.isActive('codeBlock')} onClick={() => editor.chain().focus().toggleCodeBlock().run()} title="Code block">
76
+ <Code2 size={sz} />
77
+ </Btn>
78
+
79
+ <Sep />
80
+
81
+ <Btn onClick={() => editor.chain().focus().setHorizontalRule().run()} title="Horizontal rule">
82
+ <Minus size={sz} />
83
+ </Btn>
84
+ </div>
85
+ );
86
+ }
@@ -0,0 +1,116 @@
1
+ import { NodeViewWrapper } from '@tiptap/react';
2
+ import { getContextsForType } from '@treenity/core';
3
+ import { getRegistryVersion, subscribeRegistry } from '@treenity/core/core/registry';
4
+ import { Render, RenderContext } from '@treenity/react/context';
5
+ import { usePath } from '@treenity/react/hooks';
6
+ import { useSyncExternalStore } from 'react';
7
+
8
+ export function TreenityBlockView({ node, updateAttributes, deleteNode, editor }: any) {
9
+ const ref = node.attrs.ref as string | null;
10
+ const type = node.attrs.type as string | null;
11
+ const ctx = (node.attrs.context as string | null) ?? 'react';
12
+ const refNode = usePath(ref);
13
+ const editable = editor?.isEditable;
14
+
15
+ // Re-check available contexts when registry changes (views load asynchronously)
16
+ useSyncExternalStore(subscribeRegistry, getRegistryVersion);
17
+
18
+ const effectiveType = refNode?.$type ?? type ?? '';
19
+ const availableContexts = effectiveType
20
+ ? getContextsForType(effectiveType).filter((c) => c.startsWith('react')).sort()
21
+ : [];
22
+
23
+ const renderContent = () => {
24
+ if (ref && refNode) {
25
+ return (
26
+ <RenderContext name={ctx}>
27
+ <Render value={refNode} />
28
+ </RenderContext>
29
+ );
30
+ }
31
+
32
+ if (ref && !refNode) {
33
+ return (
34
+ <div className="text-sm italic p-4" style={{ color: 'var(--text-3)' }}>
35
+ Loading {ref}…
36
+ </div>
37
+ );
38
+ }
39
+
40
+ if (type && node.attrs.props) {
41
+ return (
42
+ <RenderContext name={ctx}>
43
+ <Render value={{ $type: type, ...node.attrs.props }} />
44
+ </RenderContext>
45
+ );
46
+ }
47
+
48
+ return (
49
+ <div className="text-sm italic p-4" style={{ color: 'var(--text-3)' }}>
50
+ Empty component block
51
+ </div>
52
+ );
53
+ };
54
+
55
+ const label = effectiveType || ref?.split('/').at(-1) || '?';
56
+ const shortLabel = label.includes('.') ? label.slice(label.lastIndexOf('.') + 1) : label;
57
+ const shortCtx = ctx.startsWith('react:') ? ctx.slice(6) : ctx;
58
+
59
+ return (
60
+ <NodeViewWrapper className="my-2">
61
+ <div
62
+ className="relative group"
63
+ style={{ border: '1px solid var(--border)', borderRadius: 6, overflow: 'hidden', background: 'var(--surface)' }}
64
+ >
65
+ {editable && (
66
+ <div
67
+ className="absolute top-1 right-1 z-10 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity"
68
+ contentEditable={false}
69
+ >
70
+ {/* type badge */}
71
+ <span
72
+ className="text-[10px] px-1.5 py-0.5 rounded font-mono"
73
+ style={{ background: 'var(--surface-3)', color: 'var(--text-3)' }}
74
+ >
75
+ {shortLabel}
76
+ </span>
77
+
78
+ {/* context switcher — only when multiple react* contexts registered */}
79
+ {availableContexts.length > 1 ? (
80
+ <select
81
+ value={ctx}
82
+ onChange={(e) => updateAttributes({ context: e.target.value })}
83
+ className="text-[10px] rounded px-1 py-0.5 cursor-pointer"
84
+ style={{ background: 'var(--surface-3)', color: 'var(--text-2)', border: 'none' }}
85
+ >
86
+ {availableContexts.map((c) => (
87
+ <option key={c} value={c}>
88
+ {c.startsWith('react:') ? c.slice(6) : c}
89
+ </option>
90
+ ))}
91
+ </select>
92
+ ) : (
93
+ <span
94
+ className="text-[10px] px-1.5 py-0.5 rounded font-mono"
95
+ style={{ background: 'var(--surface-3)', color: 'var(--text-3)' }}
96
+ >
97
+ {shortCtx}
98
+ </span>
99
+ )}
100
+
101
+ {/* delete */}
102
+ <button
103
+ onClick={deleteNode}
104
+ className="text-[12px] px-1.5 py-0.5 rounded leading-none cursor-pointer"
105
+ style={{ background: 'var(--surface-3)', color: 'var(--text-3)' }}
106
+ >
107
+ ×
108
+ </button>
109
+ </div>
110
+ )}
111
+
112
+ <div contentEditable={false}>{renderContent()}</div>
113
+ </div>
114
+ </NodeViewWrapper>
115
+ );
116
+ }
@@ -0,0 +1,31 @@
1
+ import { mergeAttributes, Node } from '@tiptap/core';
2
+ import { ReactNodeViewRenderer } from '@tiptap/react';
3
+ import { TreenityBlockView } from './treenity-block-view';
4
+
5
+ export const TreenityBlock = Node.create({
6
+ name: 'treenityBlock',
7
+ group: 'block',
8
+ atom: true,
9
+ draggable: true,
10
+
11
+ addAttributes() {
12
+ return {
13
+ ref: { default: null },
14
+ type: { default: null },
15
+ props: { default: {} },
16
+ context: { default: 'react' },
17
+ };
18
+ },
19
+
20
+ parseHTML() {
21
+ return [{ tag: 'div[data-treenity-block]' }];
22
+ },
23
+
24
+ renderHTML({ HTMLAttributes }) {
25
+ return ['div', mergeAttributes(HTMLAttributes, { 'data-treenity-block': '' })];
26
+ },
27
+
28
+ addNodeView() {
29
+ return ReactNodeViewRenderer(TreenityBlockView);
30
+ },
31
+ });
package/doc/types.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { registerType } from '@treenity/core/comp';
2
+
3
+ /** Rich document — Tiptap JSON with embedded Treenity components */
4
+ class DocPage {
5
+ /** @title Title */
6
+ title = '';
7
+ /** @title Content @format hidden */
8
+ content = '';
9
+ }
10
+ registerType('doc.page', DocPage);
@@ -0,0 +1,4 @@
1
+ import './icons';
2
+ import './widgets';
3
+ import './view';
4
+ import './launcher.css';
@@ -0,0 +1,234 @@
1
+ // Launcher icons — react:icon context with iOS-style SVG icons
2
+
3
+ import { register } from '@treenity/core';
4
+ import type { RenderProps } from '@treenity/react/context';
5
+ import type { FC, ReactNode } from 'react';
6
+
7
+ // ── Icon shell — rounded rect with gradient + glow ──
8
+
9
+ function IconShell({ children, g1, g2, glow }: {
10
+ children: ReactNode; g1: string; g2: string; glow?: string;
11
+ }) {
12
+ const id = `g-${g1.replace('#', '')}`;
13
+ return (
14
+ <svg viewBox="0 0 120 120" className="h-full w-full" xmlns="http://www.w3.org/2000/svg">
15
+ <defs>
16
+ <linearGradient id={id} x1="0" y1="0" x2="0.5" y2="1">
17
+ <stop offset="0%" stopColor={g1} />
18
+ <stop offset="100%" stopColor={g2} />
19
+ </linearGradient>
20
+ {/* Highlight sheen */}
21
+ <linearGradient id={`${id}-sheen`} x1="0.5" y1="0" x2="0.5" y2="0.5">
22
+ <stop offset="0%" stopColor="white" stopOpacity="0.3" />
23
+ <stop offset="100%" stopColor="white" stopOpacity="0" />
24
+ </linearGradient>
25
+ </defs>
26
+ {/* Background */}
27
+ <rect x="4" y="4" width="112" height="112" rx="26" fill={`url(#${id})`} />
28
+ {/* Top sheen */}
29
+ <rect x="4" y="4" width="112" height="56" rx="26" fill={`url(#${id}-sheen)`} />
30
+ {/* Subtle inner border */}
31
+ <rect x="4" y="4" width="112" height="112" rx="26" fill="none"
32
+ stroke="white" strokeOpacity="0.15" strokeWidth="1" />
33
+ {/* Icon content */}
34
+ <g fill="white" fillOpacity="0.95">
35
+ {children}
36
+ </g>
37
+ </svg>
38
+ );
39
+ }
40
+
41
+ // ── Board (Kanban) ──
42
+ const BoardIcon: FC<RenderProps> = () => (
43
+ <IconShell g1="#6366f1" g2="#4338ca">
44
+ {/* 4 cards in 2 columns */}
45
+ <rect x="28" y="32" width="26" height="20" rx="4" />
46
+ <rect x="28" y="58" width="26" height="30" rx="4" />
47
+ <rect x="66" y="32" width="26" height="30" rx="4" />
48
+ <rect x="66" y="68" width="26" height="20" rx="4" />
49
+ {/* Column divider */}
50
+ <rect x="59" y="30" width="2" height="62" rx="1" fillOpacity="0.3" />
51
+ </IconShell>
52
+ );
53
+
54
+ // ── Todo (Checklist) ──
55
+ const TodoIcon: FC<RenderProps> = () => (
56
+ <IconShell g1="#22c55e" g2="#15803d">
57
+ {/* 3 checkbox rows */}
58
+ <rect x="30" y="34" width="14" height="14" rx="4" fillOpacity="0.4" />
59
+ <path d="M34 41 l3 3 l6-6" stroke="white" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" />
60
+ <rect x="52" y="37" width="36" height="6" rx="3" fillOpacity="0.6" />
61
+
62
+ <rect x="30" y="54" width="14" height="14" rx="4" fillOpacity="0.4" />
63
+ <path d="M34 61 l3 3 l6-6" stroke="white" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" />
64
+ <rect x="52" y="57" width="28" height="6" rx="3" fillOpacity="0.6" />
65
+
66
+ <rect x="30" y="74" width="14" height="14" rx="4" fillOpacity="0.25" />
67
+ <rect x="52" y="77" width="32" height="6" rx="3" fillOpacity="0.35" />
68
+ </IconShell>
69
+ );
70
+
71
+ // ── Contact (Mail) ──
72
+ const ContactIcon: FC<RenderProps> = () => (
73
+ <IconShell g1="#f59e0b" g2="#d97706">
74
+ {/* Envelope body */}
75
+ <rect x="24" y="38" width="72" height="48" rx="8" fillOpacity="0.4" />
76
+ {/* Envelope flap — V shape */}
77
+ <path d="M24 42 l36 26 l36-26" fill="none" stroke="white" strokeWidth="4" strokeLinecap="round" strokeLinejoin="round" strokeOpacity="0.9" />
78
+ {/* Bottom fold */}
79
+ <path d="M24 86 l24-18 M96 86 l-24-18" fill="none" stroke="white" strokeWidth="2" strokeOpacity="0.3" strokeLinecap="round" />
80
+ </IconShell>
81
+ );
82
+
83
+ // ── Docs (Files) ──
84
+ const DocsIcon: FC<RenderProps> = () => (
85
+ <IconShell g1="#64748b" g2="#334155">
86
+ {/* Back page */}
87
+ <rect x="38" y="28" width="48" height="62" rx="6" fillOpacity="0.35" />
88
+ {/* Front page */}
89
+ <rect x="30" y="34" width="48" height="62" rx="6" fillOpacity="0.7" />
90
+ {/* Folded corner */}
91
+ <path d="M62 34 l16 0 l0 0 l-16 16 z" fillOpacity="0.3" />
92
+ {/* Text lines */}
93
+ <rect x="38" y="58" width="30" height="4" rx="2" fillOpacity="0.5" />
94
+ <rect x="38" y="68" width="24" height="4" rx="2" fillOpacity="0.4" />
95
+ <rect x="38" y="78" width="28" height="4" rx="2" fillOpacity="0.35" />
96
+ </IconShell>
97
+ );
98
+
99
+ // ── System (Gear) ──
100
+ const SystemIcon: FC<RenderProps> = () => (
101
+ <IconShell g1="#475569" g2="#1e293b">
102
+ {/* Gear — outer ring with teeth */}
103
+ <path d="
104
+ M60 28 l5 0 l2 8 l7 3 l7-5 l4 4 l-5 7 l3 7 l8 2 l0 5 l-8 2 l-3 7 l5 7 l-4 4 l-7-5 l-7 3 l-2 8 l-5 0 l-2-8 l-7-3 l-7 5 l-4-4 l5-7 l-3-7 l-8-2 l0-5 l8-2 l3-7 l-5-7 l4-4 l7 5 l7-3 z
105
+ " fillOpacity="0.8" fillRule="evenodd" />
106
+ {/* Inner circle (hole) */}
107
+ <circle cx="60" cy="60" r="14" fill="#334155" />
108
+ <circle cx="60" cy="60" r="14" fill="white" fillOpacity="0.15" />
109
+ </IconShell>
110
+ );
111
+
112
+ // ── Whisper (Audio Waves) ──
113
+ const WhisperIcon: FC<RenderProps> = () => (
114
+ <IconShell g1="#8b5cf6" g2="#6d28d9">
115
+ {/* Sound waveform bars */}
116
+ <rect x="30" y="50" width="6" height="20" rx="3" fillOpacity="0.6" />
117
+ <rect x="42" y="38" width="6" height="44" rx="3" fillOpacity="0.8" />
118
+ <rect x="54" y="30" width="6" height="60" rx="3" />
119
+ <rect x="66" y="42" width="6" height="36" rx="3" fillOpacity="0.8" />
120
+ <rect x="78" y="34" width="6" height="52" rx="3" fillOpacity="0.9" />
121
+ <rect x="90" y="48" width="6" height="24" rx="3" fillOpacity="0.5" />
122
+ {/* Subtle glow circle */}
123
+ <circle cx="60" cy="60" r="38" fill="white" fillOpacity="0.05" />
124
+ </IconShell>
125
+ );
126
+
127
+ // ── Sim (Network/Agents) ──
128
+ const SimIcon: FC<RenderProps> = () => (
129
+ <IconShell g1="#06b6d4" g2="#0e7490">
130
+ {/* 3 connected nodes */}
131
+ <circle cx="60" cy="38" r="10" fillOpacity="0.9" />
132
+ <circle cx="38" cy="78" r="10" fillOpacity="0.7" />
133
+ <circle cx="82" cy="78" r="10" fillOpacity="0.7" />
134
+ {/* Connecting lines */}
135
+ <line x1="54" y1="46" x2="42" y2="70" stroke="white" strokeWidth="3" strokeOpacity="0.5" strokeLinecap="round" />
136
+ <line x1="66" y1="46" x2="78" y2="70" stroke="white" strokeWidth="3" strokeOpacity="0.5" strokeLinecap="round" />
137
+ <line x1="48" y1="78" x2="72" y2="78" stroke="white" strokeWidth="3" strokeOpacity="0.5" strokeLinecap="round" />
138
+ {/* Center pulse */}
139
+ <circle cx="60" cy="60" r="6" fillOpacity="0.4" />
140
+ </IconShell>
141
+ );
142
+
143
+ // ── LLM (Brain/AI) ──
144
+ const LlmIcon: FC<RenderProps> = () => (
145
+ <IconShell g1="#a855f7" g2="#c026d3">
146
+ {/* Brain left half */}
147
+ <path d="M58 36 C48 36, 32 40, 32 56 C32 68, 40 78, 50 82 C52 82, 56 80, 58 76"
148
+ fill="none" stroke="white" strokeWidth="4" strokeLinecap="round" strokeOpacity="0.85" />
149
+ {/* Brain right half */}
150
+ <path d="M62 36 C72 36, 88 40, 88 56 C88 68, 80 78, 70 82 C68 82, 64 80, 62 76"
151
+ fill="none" stroke="white" strokeWidth="4" strokeLinecap="round" strokeOpacity="0.85" />
152
+ {/* Center line */}
153
+ <line x1="60" y1="34" x2="60" y2="84" stroke="white" strokeWidth="2" strokeOpacity="0.4" />
154
+ {/* Neural connection dots */}
155
+ <circle cx="44" cy="52" r="3" fillOpacity="0.7" />
156
+ <circle cx="76" cy="52" r="3" fillOpacity="0.7" />
157
+ <circle cx="48" cy="68" r="3" fillOpacity="0.5" />
158
+ <circle cx="72" cy="68" r="3" fillOpacity="0.5" />
159
+ {/* Sparkle top */}
160
+ <path d="M60 28 l0-4 M56 30 l-2-3 M64 30 l2-3" stroke="white" strokeWidth="1.5" strokeLinecap="round" strokeOpacity="0.6" />
161
+ </IconShell>
162
+ );
163
+
164
+ // ── Sensor (Thermometer + gauge) ──
165
+ const SensorIcon: FC<RenderProps> = () => (
166
+ <IconShell g1="#10b981" g2="#047857">
167
+ {/* Thermometer body */}
168
+ <rect x="50" y="28" width="12" height="46" rx="6" fillOpacity="0.4" />
169
+ {/* Mercury */}
170
+ <rect x="53" y="42" width="6" height="32" rx="3" />
171
+ {/* Bulb */}
172
+ <circle cx="56" cy="80" r="12" fillOpacity="0.9" />
173
+ <circle cx="56" cy="80" r="7" fill="#047857" />
174
+ <circle cx="56" cy="80" r="7" fill="white" fillOpacity="0.8" />
175
+ {/* Tick marks */}
176
+ <rect x="64" y="34" width="10" height="2" rx="1" fillOpacity="0.4" />
177
+ <rect x="64" y="42" width="14" height="2" rx="1" fillOpacity="0.5" />
178
+ <rect x="64" y="50" width="10" height="2" rx="1" fillOpacity="0.4" />
179
+ <rect x="64" y="58" width="14" height="2" rx="1" fillOpacity="0.5" />
180
+ </IconShell>
181
+ );
182
+
183
+ // ── Folder ──
184
+ const FolderIcon: FC<RenderProps> = () => (
185
+ <IconShell g1="#3b82f6" g2="#1d4ed8">
186
+ {/* Folder tab */}
187
+ <path d="M28 40 l0-6 a4 4 0 0 1 4-4 l18 0 l6 8 l36 0 a4 4 0 0 1 4 4 l0 0 z" fillOpacity="0.5" />
188
+ {/* Folder body */}
189
+ <rect x="28" y="40" width="64" height="48" rx="6" fillOpacity="0.8" />
190
+ {/* Subtle front face highlight */}
191
+ <rect x="28" y="52" width="64" height="36" rx="6" fillOpacity="0.15" />
192
+ </IconShell>
193
+ );
194
+
195
+ // ── Default fallback — hue from type hash ──
196
+
197
+ const HUES = [0, 25, 45, 60, 90, 140, 170, 200, 220, 260, 290, 320];
198
+
199
+ function hashHue(str: string): number {
200
+ let h = 0;
201
+ for (let i = 0; i < str.length; i++) h = ((h << 5) - h + str.charCodeAt(i)) | 0;
202
+ return HUES[Math.abs(h) % HUES.length];
203
+ }
204
+
205
+ const DefaultIcon: FC<RenderProps> = ({ value }) => {
206
+ const hue = hashHue(value.$type);
207
+ const parts = value.$type.split('.');
208
+ const letter = (parts.at(-1) || value.$type)[0]?.toUpperCase() || '?';
209
+ const g1 = `hsl(${hue}, 65%, 55%)`;
210
+ const g2 = `hsl(${hue}, 70%, 35%)`;
211
+
212
+ return (
213
+ <IconShell g1={g1} g2={g2}>
214
+ <text x="60" y="68" textAnchor="middle" fontSize="40" fontWeight="700" fontFamily="system-ui"
215
+ fill="white" fillOpacity="0.9">
216
+ {letter}
217
+ </text>
218
+ </IconShell>
219
+ );
220
+ };
221
+
222
+ // ── Register all ──
223
+
224
+ register('default', 'react:icon', DefaultIcon);
225
+ register('dir', 'react:icon', FolderIcon);
226
+ register('board.kanban', 'react:icon', BoardIcon);
227
+ register('board.task', 'react:icon', BoardIcon);
228
+ register('todo.list', 'react:icon', TodoIcon);
229
+ register('cafe.contact', 'react:icon', ContactIcon);
230
+ register('mount-point', 'react:icon', DocsIcon);
231
+ register('treenity.system', 'react:icon', SystemIcon);
232
+ register('whisper.service', 'react:icon', WhisperIcon);
233
+ register('examples.demo.sensor', 'react:icon', SensorIcon);
234
+ register('t.llm', 'react:icon', LlmIcon);
@@ -0,0 +1,64 @@
1
+ /* Launcher — iPhone home screen styles */
2
+
3
+ /* Edit mode — scale down + pulsing dashed border */
4
+ @keyframes launcher-pulse {
5
+ 0%, 100% { opacity: 0.15; }
6
+ 50% { opacity: 0.4; }
7
+ }
8
+
9
+ .launcher-edit-item {
10
+ scale: 0.98;
11
+ position: relative;
12
+ }
13
+
14
+ .launcher-edit-item::after {
15
+ content: '';
16
+ position: absolute;
17
+ inset: 0;
18
+ border-radius: 1rem;
19
+ border: 1.5px dashed rgba(255, 255, 255, 0.3);
20
+ pointer-events: none;
21
+ animation: launcher-pulse 2s ease-in-out infinite;
22
+ }
23
+
24
+ .launcher-edit-item:nth-child(2n)::after { animation-delay: 0.4s; }
25
+ .launcher-edit-item:nth-child(3n)::after { animation-delay: 0.8s; }
26
+
27
+ /* Glass-morphism for widgets */
28
+ .launcher-glass {
29
+ backdrop-filter: blur(20px);
30
+ -webkit-backdrop-filter: blur(20px);
31
+ }
32
+
33
+ /* Override react-grid-layout defaults for launcher */
34
+ .launcher-grid .react-grid-item {
35
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
36
+ overflow: visible !important;
37
+ }
38
+
39
+ .launcher-grid .react-grid-item.react-draggable-dragging {
40
+ z-index: 100;
41
+ transition: none !important;
42
+ filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.4));
43
+ }
44
+
45
+ .launcher-grid .react-grid-item > .react-resizable-handle {
46
+ opacity: 0;
47
+ transition: opacity 0.2s;
48
+ }
49
+
50
+ .launcher-editing .react-grid-item > .react-resizable-handle {
51
+ opacity: 0.6;
52
+ }
53
+
54
+ /* Grid placeholder during drag */
55
+ .launcher-grid .react-grid-placeholder {
56
+ background: rgba(255, 255, 255, 0.1) !important;
57
+ border: 2px dashed rgba(255, 255, 255, 0.3) !important;
58
+ border-radius: 1rem;
59
+ }
60
+
61
+ /* External drop placeholder */
62
+ .launcher-grid .react-grid-item.dropping {
63
+ opacity: 0.6;
64
+ }
@@ -0,0 +1,41 @@
1
+ // Launcher seed — demo home screen with app shortcuts
2
+
3
+ import type { NodeData } from '@treenity/core';
4
+ import { registerPrefab } from '@treenity/core/mod';
5
+
6
+ const layout = JSON.stringify([
7
+ { i: 'board', x: 0, y: 0, w: 1, h: 1 },
8
+ { i: 'todo', x: 1, y: 0, w: 1, h: 1 },
9
+ { i: 'contact', x: 2, y: 0, w: 1, h: 1 },
10
+ { i: 'docs', x: 3, y: 0, w: 1, h: 1 },
11
+ { i: 'sys', x: 0, y: 1, w: 1, h: 1 },
12
+ { i: 'whisper', x: 1, y: 1, w: 1, h: 1 },
13
+ { i: 'sim', x: 2, y: 1, w: 1, h: 1 },
14
+ { i: 'llm', x: 3, y: 1, w: 1, h: 1 },
15
+ { i: 'board-widget', x: 0, y: 2, w: 2, h: 2 },
16
+ { i: 'sensors', x: 2, y: 2, w: 2, h: 1 },
17
+ ]);
18
+
19
+ registerPrefab('launcher', 'seed', [
20
+ {
21
+ $path: 'launcher',
22
+ $type: 'launcher',
23
+ columns: 4,
24
+ wallpaper: 'linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%)',
25
+ layout,
26
+ },
27
+
28
+ // App icons (1×1)
29
+ { $path: 'launcher/board', $type: 'ref', $ref: '/board' },
30
+ { $path: 'launcher/todo', $type: 'ref', $ref: '/todo' },
31
+ { $path: 'launcher/contact', $type: 'ref', $ref: '/cafe/contact' },
32
+ { $path: 'launcher/docs', $type: 'ref', $ref: '/docs' },
33
+ { $path: 'launcher/sys', $type: 'ref', $ref: '/sys' },
34
+ { $path: 'launcher/whisper', $type: 'ref', $ref: '/whisper' },
35
+ { $path: 'launcher/sim', $type: 'ref', $ref: '/sim' },
36
+ { $path: 'launcher/llm', $type: 'ref', $ref: '/llm' },
37
+
38
+ // Widgets (larger)
39
+ { $path: 'launcher/board-widget', $type: 'ref', $ref: '/board' },
40
+ { $path: 'launcher/sensors', $type: 'ref', $ref: '/demo/sensors' },
41
+ ] as NodeData[]);
@@ -0,0 +1,2 @@
1
+ import './types';
2
+ import './seed';
@@ -0,0 +1,53 @@
1
+ // Launcher — iPhone-like home screen for Treenity
2
+
3
+ import type { NodeData } from '@treenity/core';
4
+ import { getCtx, registerType } from '@treenity/core/comp';
5
+
6
+ /** Home screen with icon grid + widgets. Layout via react-grid-layout. */
7
+ export class Launcher {
8
+ columns = 4;
9
+ wallpaper = 'linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%)';
10
+ /** JSON-stringified RGL layout: [{i, x, y, w, h}] */
11
+ layout = '[]';
12
+
13
+ /** Add an app shortcut (ref) to the launcher */
14
+ async addApp(data: { /** Target node path */ path: string; /** Layout item id */ id?: string }) {
15
+ if (!data.path?.trim()) throw new Error('path required');
16
+ const ctx = getCtx();
17
+ const id = data.id || data.path.split('/').at(-1) || Date.now().toString(36);
18
+ const refPath = `${ctx.node.$path}/${id}`;
19
+
20
+ await ctx.store.set({ $path: refPath, $type: 'ref', $ref: data.path } as NodeData);
21
+
22
+ // Auto-place in layout as 1×1
23
+ const items: { i: string; x: number; y: number; w: number; h: number }[] = JSON.parse(this.layout || '[]');
24
+ const maxY = items.reduce((m, it) => Math.max(m, it.y + it.h), 0);
25
+ const lastRowItems = items.filter(it => it.y + it.h === maxY);
26
+ const nextX = lastRowItems.reduce((m, it) => Math.max(m, it.x + it.w), 0);
27
+
28
+ if (nextX < this.columns) {
29
+ items.push({ i: id, x: nextX, y: maxY > 0 ? maxY - 1 : 0, w: 1, h: 1 });
30
+ } else {
31
+ items.push({ i: id, x: 0, y: maxY, w: 1, h: 1 });
32
+ }
33
+ this.layout = JSON.stringify(items);
34
+ }
35
+
36
+ /** Remove an app from the launcher */
37
+ async removeApp(data: { /** Child id (last path segment) */ id: string }) {
38
+ if (!data.id?.trim()) throw new Error('id required');
39
+ const ctx = getCtx();
40
+ await ctx.store.remove(`${ctx.node.$path}/${data.id}`);
41
+
42
+ const items: { i: string }[] = JSON.parse(this.layout || '[]');
43
+ this.layout = JSON.stringify(items.filter(it => it.i !== data.id));
44
+ }
45
+
46
+ /** Persist layout after drag/resize */
47
+ updateLayout(data: { /** JSON-stringified RGL layout */ layout: string }) {
48
+ if (!data.layout) throw new Error('layout required');
49
+ this.layout = data.layout;
50
+ }
51
+ }
52
+
53
+ registerType('launcher', Launcher);