@notis_ai/cli 0.2.14 → 0.2.16

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 (299) hide show
  1. package/README.md +83 -21
  2. package/dist/agent-hooks/notis-agent-hook.mjs +20168 -0
  3. package/{skills → dist/base-skills}/notis-apps/SKILL.md +167 -72
  4. package/{skills → dist/base-skills}/notis-cli/SKILL.md +86 -28
  5. package/dist/base-skills/notis-query/SKILL.md +705 -0
  6. package/dist/skill-sync/index.js +1528 -0
  7. package/dist/skill-sync/index.js.map +7 -0
  8. package/package.json +5 -2
  9. package/skills/notis-apps/cli.md +39 -18
  10. package/skills/notis-cli/AGENT_INSTRUCTIONS.md +39 -0
  11. package/skills/notis-onboarding/BRIEF.md +16 -0
  12. package/src/agent-hook-entry.js +5 -0
  13. package/src/cli.js +23 -14
  14. package/src/command-specs/agents.js +392 -0
  15. package/src/command-specs/apps.js +1021 -424
  16. package/src/command-specs/auth.js +63 -10
  17. package/src/command-specs/index.js +6 -0
  18. package/src/command-specs/onboarding.js +69 -5
  19. package/src/command-specs/skills.js +56 -0
  20. package/src/runtime/agent-memory-state.js +126 -0
  21. package/src/runtime/agent-setup.js +383 -0
  22. package/src/runtime/app-dev-consumers.js +154 -0
  23. package/src/runtime/app-dev-host-lock.js +80 -0
  24. package/src/runtime/app-dev-process-identity.js +111 -0
  25. package/src/runtime/app-dev-roots.js +284 -0
  26. package/src/runtime/app-dev-server.js +447 -29
  27. package/src/runtime/app-dev-sessions.js +105 -145
  28. package/src/runtime/app-platform.js +1314 -166
  29. package/src/runtime/app-registry-scaffolds.js +367 -0
  30. package/src/runtime/base-skills.d.ts +20 -0
  31. package/src/runtime/base-skills.js +167 -0
  32. package/src/runtime/login-listener.js +15 -0
  33. package/src/runtime/oauth.js +1506 -141
  34. package/src/runtime/output.js +7 -0
  35. package/src/runtime/ports.js +16 -0
  36. package/src/runtime/profiles.js +19 -16
  37. package/src/runtime/skill-sync/cloud-client.ts +96 -0
  38. package/src/runtime/skill-sync/index.ts +644 -0
  39. package/src/runtime/skill-sync/local-scanner.ts +1046 -0
  40. package/src/runtime/skill-sync/symlink-manager.ts +383 -0
  41. package/src/runtime/skill-sync/sync-plan.ts +22 -0
  42. package/src/runtime/skill-sync/types.ts +103 -0
  43. package/src/runtime/skill-sync/write-cloud-skill.ts +50 -0
  44. package/src/runtime/store-screenshot.js +6 -1
  45. package/src/runtime/sync-skills.d.ts +37 -0
  46. package/src/runtime/sync-skills.js +231 -0
  47. package/template/app/layout.tsx +5 -1
  48. package/template/notis.config.ts +1 -0
  49. package/template/packages/sdk/package.json +2 -1
  50. package/template/packages/sdk/src/components/DocumentEditor.tsx +13 -3
  51. package/template/packages/sdk/src/components/MarkdownEditor.tsx +121 -0
  52. package/template/packages/sdk/src/components/MultiSelectActionBar.tsx +43 -119
  53. package/template/packages/sdk/src/components/MultiSelectCheckbox.tsx +5 -1
  54. package/template/packages/sdk/src/components/MultiSelectDragOverlay.tsx +1 -1
  55. package/template/packages/sdk/src/components/NotisSelectionBoundary.tsx +55 -0
  56. package/template/packages/sdk/src/components/ShortcutHints.tsx +56 -0
  57. package/template/packages/sdk/src/config.ts +25 -0
  58. package/template/packages/sdk/src/documents.ts +7 -1
  59. package/template/packages/sdk/src/hooks/useActiveResource.ts +19 -0
  60. package/template/packages/sdk/src/hooks/useCollectionInteractions.ts +726 -0
  61. package/template/packages/sdk/src/hooks/useHandover.ts +3 -0
  62. package/template/packages/sdk/src/hooks/useMultiSelect.ts +44 -482
  63. package/template/packages/sdk/src/hooks/useNotis.ts +3 -0
  64. package/template/packages/sdk/src/hooks/useNotisNavigation.ts +7 -4
  65. package/template/packages/sdk/src/hooks/useTool.ts +5 -4
  66. package/template/packages/sdk/src/index.ts +47 -2
  67. package/template/packages/sdk/src/interactions/actions.ts +46 -0
  68. package/template/packages/sdk/src/interactions/shortcuts.tsx +634 -0
  69. package/template/packages/sdk/src/interactions.ts +41 -0
  70. package/template/packages/sdk/src/provider.tsx +2 -1
  71. package/template/packages/sdk/src/runtime.ts +92 -4
  72. package/dist/scaffolds/notis-database/CHANGELOG.md +0 -5
  73. package/dist/scaffolds/notis-database/app/globals.css +0 -44
  74. package/dist/scaffolds/notis-database/app/layout.tsx +0 -6
  75. package/dist/scaffolds/notis-database/app/page.tsx +0 -1088
  76. package/dist/scaffolds/notis-database/components/ui/badge.tsx +0 -28
  77. package/dist/scaffolds/notis-database/components/ui/button.tsx +0 -53
  78. package/dist/scaffolds/notis-database/components/ui/card.tsx +0 -56
  79. package/dist/scaffolds/notis-database/components/ui/table.tsx +0 -120
  80. package/dist/scaffolds/notis-database/components.json +0 -20
  81. package/dist/scaffolds/notis-database/index.html +0 -12
  82. package/dist/scaffolds/notis-database/lib/types.ts +0 -132
  83. package/dist/scaffolds/notis-database/lib/utils.ts +0 -6
  84. package/dist/scaffolds/notis-database/metadata/screenshot-1.png +0 -0
  85. package/dist/scaffolds/notis-database/metadata/screenshot-2.png +0 -0
  86. package/dist/scaffolds/notis-database/metadata/screenshot-3.png +0 -0
  87. package/dist/scaffolds/notis-database/metadata/screenshot-4.png +0 -0
  88. package/dist/scaffolds/notis-database/metadata/screenshot-5.png +0 -0
  89. package/dist/scaffolds/notis-database/metadata/screenshot-fixtures.json +0 -1839
  90. package/dist/scaffolds/notis-database/notis.config.ts +0 -73
  91. package/dist/scaffolds/notis-database/package-lock.json +0 -3935
  92. package/dist/scaffolds/notis-database/package.json +0 -32
  93. package/dist/scaffolds/notis-database/packages/sdk/package.json +0 -36
  94. package/dist/scaffolds/notis-database/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  95. package/dist/scaffolds/notis-database/packages/sdk/src/components/Markdown.tsx +0 -60
  96. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  97. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  98. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  99. package/dist/scaffolds/notis-database/packages/sdk/src/config.ts +0 -234
  100. package/dist/scaffolds/notis-database/packages/sdk/src/documents.ts +0 -250
  101. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useBackend.ts +0 -41
  102. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  103. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  104. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  105. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDocument.ts +0 -78
  106. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDocuments.ts +0 -121
  107. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useHandover.ts +0 -75
  108. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  109. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useNotis.ts +0 -34
  110. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  111. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTool.ts +0 -64
  112. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTools.ts +0 -56
  113. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  114. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  115. package/dist/scaffolds/notis-database/packages/sdk/src/index.ts +0 -100
  116. package/dist/scaffolds/notis-database/packages/sdk/src/provider.tsx +0 -43
  117. package/dist/scaffolds/notis-database/packages/sdk/src/runtime.ts +0 -351
  118. package/dist/scaffolds/notis-database/packages/sdk/src/styles.css +0 -186
  119. package/dist/scaffolds/notis-database/packages/sdk/src/ui.ts +0 -15
  120. package/dist/scaffolds/notis-database/packages/sdk/src/vite.ts +0 -56
  121. package/dist/scaffolds/notis-database/packages/sdk/tsconfig.json +0 -15
  122. package/dist/scaffolds/notis-database/postcss.config.mjs +0 -8
  123. package/dist/scaffolds/notis-database/src/dev-main.tsx +0 -23
  124. package/dist/scaffolds/notis-database/src/mock-runtime.ts +0 -561
  125. package/dist/scaffolds/notis-database/tailwind.config.ts +0 -59
  126. package/dist/scaffolds/notis-database/tsconfig.json +0 -23
  127. package/dist/scaffolds/notis-database/vite.config.ts +0 -22
  128. package/dist/scaffolds/notis-journal/CHANGELOG.md +0 -29
  129. package/dist/scaffolds/notis-journal/app/globals.css +0 -37
  130. package/dist/scaffolds/notis-journal/app/insights/page.tsx +0 -513
  131. package/dist/scaffolds/notis-journal/app/journal-core.tsx +0 -362
  132. package/dist/scaffolds/notis-journal/app/journal-ui.tsx +0 -337
  133. package/dist/scaffolds/notis-journal/app/layout.tsx +0 -6
  134. package/dist/scaffolds/notis-journal/app/page.tsx +0 -486
  135. package/dist/scaffolds/notis-journal/components/ui/badge.tsx +0 -28
  136. package/dist/scaffolds/notis-journal/components/ui/button.tsx +0 -53
  137. package/dist/scaffolds/notis-journal/components/ui/card.tsx +0 -56
  138. package/dist/scaffolds/notis-journal/components.json +0 -20
  139. package/dist/scaffolds/notis-journal/index.html +0 -12
  140. package/dist/scaffolds/notis-journal/lib/utils.ts +0 -6
  141. package/dist/scaffolds/notis-journal/metadata/screenshot-1.png +0 -0
  142. package/dist/scaffolds/notis-journal/metadata/screenshot-2.png +0 -0
  143. package/dist/scaffolds/notis-journal/metadata/screenshot-3.png +0 -0
  144. package/dist/scaffolds/notis-journal/metadata/screenshot-4.png +0 -0
  145. package/dist/scaffolds/notis-journal/metadata/screenshot-5.png +0 -0
  146. package/dist/scaffolds/notis-journal/metadata/screenshot-6.png +0 -0
  147. package/dist/scaffolds/notis-journal/metadata/screenshot-fixtures.json +0 -132
  148. package/dist/scaffolds/notis-journal/notis.config.ts +0 -93
  149. package/dist/scaffolds/notis-journal/package-lock.json +0 -4615
  150. package/dist/scaffolds/notis-journal/package.json +0 -34
  151. package/dist/scaffolds/notis-journal/packages/sdk/package.json +0 -36
  152. package/dist/scaffolds/notis-journal/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  153. package/dist/scaffolds/notis-journal/packages/sdk/src/components/Markdown.tsx +0 -60
  154. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  155. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  156. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  157. package/dist/scaffolds/notis-journal/packages/sdk/src/config.ts +0 -234
  158. package/dist/scaffolds/notis-journal/packages/sdk/src/documents.ts +0 -250
  159. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useBackend.ts +0 -41
  160. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  161. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  162. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  163. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDocument.ts +0 -78
  164. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDocuments.ts +0 -121
  165. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useHandover.ts +0 -75
  166. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  167. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useNotis.ts +0 -34
  168. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  169. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTool.ts +0 -64
  170. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTools.ts +0 -56
  171. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  172. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  173. package/dist/scaffolds/notis-journal/packages/sdk/src/index.ts +0 -100
  174. package/dist/scaffolds/notis-journal/packages/sdk/src/provider.tsx +0 -43
  175. package/dist/scaffolds/notis-journal/packages/sdk/src/runtime.ts +0 -351
  176. package/dist/scaffolds/notis-journal/packages/sdk/src/styles.css +0 -186
  177. package/dist/scaffolds/notis-journal/packages/sdk/src/ui.ts +0 -15
  178. package/dist/scaffolds/notis-journal/packages/sdk/src/vite.ts +0 -56
  179. package/dist/scaffolds/notis-journal/packages/sdk/tsconfig.json +0 -15
  180. package/dist/scaffolds/notis-journal/postcss.config.mjs +0 -8
  181. package/dist/scaffolds/notis-journal/skills/journal-onboarding/SKILL.md +0 -120
  182. package/dist/scaffolds/notis-journal/src/dev-main.tsx +0 -58
  183. package/dist/scaffolds/notis-journal/src/mock-runtime.ts +0 -199
  184. package/dist/scaffolds/notis-journal/tailwind.config.ts +0 -58
  185. package/dist/scaffolds/notis-journal/tsconfig.json +0 -23
  186. package/dist/scaffolds/notis-journal/vite.config.ts +0 -10
  187. package/dist/scaffolds/notis-notes/CHANGELOG.md +0 -5
  188. package/dist/scaffolds/notis-notes/app/globals.css +0 -3
  189. package/dist/scaffolds/notis-notes/app/layout.tsx +0 -6
  190. package/dist/scaffolds/notis-notes/app/page.tsx +0 -1943
  191. package/dist/scaffolds/notis-notes/app/phosphor-icons.ts +0 -596
  192. package/dist/scaffolds/notis-notes/components/ui/badge.tsx +0 -28
  193. package/dist/scaffolds/notis-notes/components/ui/button.tsx +0 -53
  194. package/dist/scaffolds/notis-notes/components/ui/card.tsx +0 -56
  195. package/dist/scaffolds/notis-notes/components.json +0 -20
  196. package/dist/scaffolds/notis-notes/lib/utils.ts +0 -6
  197. package/dist/scaffolds/notis-notes/lib/visible-properties.ts +0 -144
  198. package/dist/scaffolds/notis-notes/metadata/screenshot-1.png +0 -0
  199. package/dist/scaffolds/notis-notes/metadata/screenshot-2.png +0 -0
  200. package/dist/scaffolds/notis-notes/metadata/screenshot-3.png +0 -0
  201. package/dist/scaffolds/notis-notes/metadata/screenshot-4.png +0 -0
  202. package/dist/scaffolds/notis-notes/metadata/screenshot-5.png +0 -0
  203. package/dist/scaffolds/notis-notes/metadata/screenshot-fixtures.json +0 -752
  204. package/dist/scaffolds/notis-notes/notis.config.ts +0 -80
  205. package/dist/scaffolds/notis-notes/package-lock.json +0 -4636
  206. package/dist/scaffolds/notis-notes/package.json +0 -35
  207. package/dist/scaffolds/notis-notes/packages/sdk/package.json +0 -36
  208. package/dist/scaffolds/notis-notes/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  209. package/dist/scaffolds/notis-notes/packages/sdk/src/components/Markdown.tsx +0 -60
  210. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  211. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  212. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  213. package/dist/scaffolds/notis-notes/packages/sdk/src/config.ts +0 -234
  214. package/dist/scaffolds/notis-notes/packages/sdk/src/documents.ts +0 -250
  215. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useBackend.ts +0 -41
  216. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  217. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  218. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  219. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDocument.ts +0 -78
  220. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDocuments.ts +0 -121
  221. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useHandover.ts +0 -75
  222. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  223. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useNotis.ts +0 -34
  224. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  225. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTool.ts +0 -64
  226. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTools.ts +0 -56
  227. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  228. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  229. package/dist/scaffolds/notis-notes/packages/sdk/src/index.ts +0 -100
  230. package/dist/scaffolds/notis-notes/packages/sdk/src/provider.tsx +0 -43
  231. package/dist/scaffolds/notis-notes/packages/sdk/src/runtime.ts +0 -351
  232. package/dist/scaffolds/notis-notes/packages/sdk/src/styles.css +0 -186
  233. package/dist/scaffolds/notis-notes/packages/sdk/src/ui.ts +0 -15
  234. package/dist/scaffolds/notis-notes/packages/sdk/src/vite.ts +0 -56
  235. package/dist/scaffolds/notis-notes/packages/sdk/tsconfig.json +0 -15
  236. package/dist/scaffolds/notis-notes/postcss.config.mjs +0 -8
  237. package/dist/scaffolds/notis-notes/tailwind.config.ts +0 -58
  238. package/dist/scaffolds/notis-notes/tsconfig.json +0 -23
  239. package/dist/scaffolds/notis-notes/vite.config.ts +0 -10
  240. package/dist/scaffolds/notis-random/CHANGELOG.md +0 -15
  241. package/dist/scaffolds/notis-random/README.md +0 -33
  242. package/dist/scaffolds/notis-random/app/globals.css +0 -11
  243. package/dist/scaffolds/notis-random/app/history/page.tsx +0 -67
  244. package/dist/scaffolds/notis-random/app/layout.tsx +0 -7
  245. package/dist/scaffolds/notis-random/app/page.tsx +0 -289
  246. package/dist/scaffolds/notis-random/components/ui/button.tsx +0 -50
  247. package/dist/scaffolds/notis-random/components/ui/card.tsx +0 -16
  248. package/dist/scaffolds/notis-random/components/ui/input.tsx +0 -23
  249. package/dist/scaffolds/notis-random/components.json +0 -20
  250. package/dist/scaffolds/notis-random/index.html +0 -12
  251. package/dist/scaffolds/notis-random/lib/notis-tools.ts +0 -128
  252. package/dist/scaffolds/notis-random/lib/rng.ts +0 -202
  253. package/dist/scaffolds/notis-random/lib/roll-record.ts +0 -189
  254. package/dist/scaffolds/notis-random/lib/utils.ts +0 -25
  255. package/dist/scaffolds/notis-random/metadata/screenshot-1.png +0 -0
  256. package/dist/scaffolds/notis-random/metadata/screenshot-2.png +0 -0
  257. package/dist/scaffolds/notis-random/metadata/screenshot-3.png +0 -0
  258. package/dist/scaffolds/notis-random/metadata/screenshot-4.png +0 -0
  259. package/dist/scaffolds/notis-random/metadata/screenshot-5.png +0 -0
  260. package/dist/scaffolds/notis-random/metadata/screenshot-fixtures.json +0 -753
  261. package/dist/scaffolds/notis-random/notis.config.ts +0 -86
  262. package/dist/scaffolds/notis-random/package-lock.json +0 -4513
  263. package/dist/scaffolds/notis-random/package.json +0 -36
  264. package/dist/scaffolds/notis-random/packages/sdk/package.json +0 -36
  265. package/dist/scaffolds/notis-random/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  266. package/dist/scaffolds/notis-random/packages/sdk/src/components/Markdown.tsx +0 -60
  267. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  268. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  269. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  270. package/dist/scaffolds/notis-random/packages/sdk/src/config.ts +0 -234
  271. package/dist/scaffolds/notis-random/packages/sdk/src/documents.ts +0 -250
  272. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useBackend.ts +0 -41
  273. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  274. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  275. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  276. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDocument.ts +0 -78
  277. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDocuments.ts +0 -121
  278. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useHandover.ts +0 -75
  279. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  280. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useNotis.ts +0 -34
  281. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  282. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTool.ts +0 -64
  283. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTools.ts +0 -56
  284. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  285. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  286. package/dist/scaffolds/notis-random/packages/sdk/src/index.ts +0 -100
  287. package/dist/scaffolds/notis-random/packages/sdk/src/provider.tsx +0 -43
  288. package/dist/scaffolds/notis-random/packages/sdk/src/runtime.ts +0 -351
  289. package/dist/scaffolds/notis-random/packages/sdk/src/styles.css +0 -186
  290. package/dist/scaffolds/notis-random/packages/sdk/src/ui.ts +0 -15
  291. package/dist/scaffolds/notis-random/packages/sdk/src/vite.ts +0 -56
  292. package/dist/scaffolds/notis-random/packages/sdk/tsconfig.json +0 -15
  293. package/dist/scaffolds/notis-random/postcss.config.mjs +0 -6
  294. package/dist/scaffolds/notis-random/src/dev-main.tsx +0 -70
  295. package/dist/scaffolds/notis-random/src/mock-runtime.ts +0 -129
  296. package/dist/scaffolds/notis-random/tailwind.config.ts +0 -50
  297. package/dist/scaffolds/notis-random/tsconfig.json +0 -23
  298. package/dist/scaffolds/notis-random/vite.config.ts +0 -11
  299. package/dist/scaffolds.json +0 -49
@@ -1,539 +0,0 @@
1
- 'use client';
2
-
3
- import {
4
- useCallback,
5
- useEffect,
6
- useMemo,
7
- useRef,
8
- useState,
9
- type MouseEvent as ReactMouseEvent,
10
- } from 'react';
11
-
12
- const ROW_ATTR = 'data-notis-row-id';
13
- const INTERACTIVE_SELECTOR = 'button, a, input, textarea, select, [role="button"]';
14
-
15
- export interface DragRect {
16
- left: number;
17
- top: number;
18
- width: number;
19
- height: number;
20
- }
21
-
22
- export interface UseMultiSelectOptions<T> {
23
- items: T[];
24
- getId: (item: T) => string;
25
- /** When false, suppresses the global Esc / Cmd+A / X / Shift+Arrow listeners. Default true. */
26
- bindKeyboardShortcuts?: boolean;
27
- /** When false, disables the rubber-band drag-select rectangle. Default true. */
28
- enableDragSelect?: boolean;
29
- /** Distance (px) the cursor must move past mousedown before a drag begins. Default 5. */
30
- dragThreshold?: number;
31
- /** Initial head id (the row that Shift+Arrow extends from). */
32
- initialHeadId?: string | null;
33
- /** Fires when the head moves via Shift+Arrow so the consumer can scroll the row into view. */
34
- onHeadChange?: (id: string | null) => void;
35
- }
36
-
37
- export interface MultiSelectController<T> {
38
- selectedIds: ReadonlySet<string>;
39
- selectedCount: number;
40
- lastClickedId: string | null;
41
- headId: string | null;
42
- /** Viewport-fixed drag rectangle, or null when no drag is active. */
43
- dragRect: DragRect | null;
44
-
45
- isSelected: (id: string) => boolean;
46
- getSelectedItems: () => T[];
47
-
48
- toggle: (id: string) => void;
49
- select: (ids: string[]) => void;
50
- clear: () => void;
51
- selectAll: () => void;
52
- selectRange: (anchorId: string, targetId: string) => void;
53
- setHead: (id: string | null) => void;
54
-
55
- /** Click handler for a row's hover checkbox. Toggles, with shift-click range from lastClickedId. */
56
- onCheckboxClick: (id: string) => (event: ReactMouseEvent) => void;
57
- /** mousedown on a row body — handles Cmd/Ctrl+click toggle without opening detail. */
58
- onRowMouseDown: (id: string) => (event: ReactMouseEvent) => void;
59
-
60
- /** Spread on each selectable row so drag-select can find them. */
61
- getRowProps: (id: string) => { [ROW_ATTR]: string };
62
- /**
63
- * Spread on each selectable row/card — bundles `getRowProps` (the drag-select
64
- * attribute) with the Cmd/Ctrl+click `onMouseDown` handler in one spread.
65
- */
66
- getItemProps: (id: string) => {
67
- [ROW_ATTR]: string;
68
- onMouseDown: (event: ReactMouseEvent) => void;
69
- };
70
- /** Spread onto `<MultiSelectCheckbox {...getCheckboxProps(id)} />`. */
71
- getCheckboxProps: (id: string) => {
72
- isSelected: boolean;
73
- onClick: (event: ReactMouseEvent) => void;
74
- };
75
- /** Spread on the list container — owns the drag-select mousedown/move/up + click-empty-to-clear. */
76
- getContainerProps: () => {
77
- ref: (node: HTMLElement | null) => void;
78
- onMouseDown: (event: ReactMouseEvent) => void;
79
- onClickCapture: (event: ReactMouseEvent) => void;
80
- style: { userSelect: 'none' };
81
- };
82
- }
83
-
84
- function isEditableEvent(event: Event): boolean {
85
- // Notis apps mount inside a Shadow DOM, so a document-level listener sees
86
- // `event.target` retargeted to the shadow host rather than the real focused
87
- // element. `composedPath()[0]` pierces the shadow boundary to the actual
88
- // target, so typing in an app input doesn't trigger selection shortcuts.
89
- const target = event.composedPath?.()[0] ?? event.target;
90
- if (!(target instanceof HTMLElement)) return false;
91
- if (target.isContentEditable) return true;
92
- const tag = target.tagName;
93
- return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';
94
- }
95
-
96
- function rectsIntersect(
97
- a: { left: number; top: number; right: number; bottom: number },
98
- b: { left: number; top: number; right: number; bottom: number },
99
- ): boolean {
100
- return a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top;
101
- }
102
-
103
- export function useMultiSelect<T>(opts: UseMultiSelectOptions<T>): MultiSelectController<T> {
104
- const {
105
- items,
106
- getId,
107
- bindKeyboardShortcuts = true,
108
- enableDragSelect = true,
109
- dragThreshold = 5,
110
- initialHeadId = null,
111
- onHeadChange,
112
- } = opts;
113
-
114
- const [selectedIds, setSelectedIds] = useState<Set<string>>(() => new Set());
115
- const [lastClickedId, setLastClickedId] = useState<string | null>(null);
116
- const [headId, setHeadIdState] = useState<string | null>(initialHeadId);
117
- const [dragRect, setDragRect] = useState<DragRect | null>(null);
118
-
119
- // Latest-state refs so document listeners and stable callbacks read fresh
120
- // values without retriggering the effect.
121
- const itemsRef = useRef(items);
122
- const getIdRef = useRef(getId);
123
- const selectedIdsRef = useRef(selectedIds);
124
- const lastClickedIdRef = useRef(lastClickedId);
125
- const headIdRef = useRef(headId);
126
- const onHeadChangeRef = useRef(onHeadChange);
127
- const containerRef = useRef<HTMLElement | null>(null);
128
-
129
- itemsRef.current = items;
130
- getIdRef.current = getId;
131
- selectedIdsRef.current = selectedIds;
132
- lastClickedIdRef.current = lastClickedId;
133
- headIdRef.current = headId;
134
- onHeadChangeRef.current = onHeadChange;
135
-
136
- const orderedIds = useMemo(() => items.map((item) => getId(item)), [items, getId]);
137
- const orderedIdsRef = useRef(orderedIds);
138
- orderedIdsRef.current = orderedIds;
139
-
140
- const isSelected = useCallback((id: string) => selectedIds.has(id), [selectedIds]);
141
-
142
- const getSelectedItems = useCallback(() => {
143
- const set = selectedIdsRef.current;
144
- return itemsRef.current.filter((item) => set.has(getIdRef.current(item)));
145
- }, []);
146
-
147
- const setHead = useCallback((id: string | null) => {
148
- setHeadIdState((prev) => {
149
- if (prev === id) return prev;
150
- onHeadChangeRef.current?.(id);
151
- return id;
152
- });
153
- }, []);
154
-
155
- const toggle = useCallback((id: string) => {
156
- setSelectedIds((prev) => {
157
- const next = new Set(prev);
158
- if (next.has(id)) {
159
- next.delete(id);
160
- } else {
161
- next.add(id);
162
- }
163
- return next;
164
- });
165
- setLastClickedId(id);
166
- }, []);
167
-
168
- const select = useCallback((ids: string[]) => {
169
- setSelectedIds(new Set(ids));
170
- setLastClickedId(ids.length > 0 ? ids[ids.length - 1] ?? null : null);
171
- }, []);
172
-
173
- const clear = useCallback(() => {
174
- setSelectedIds((prev) => (prev.size === 0 ? prev : new Set()));
175
- }, []);
176
-
177
- const selectAll = useCallback(() => {
178
- const all = orderedIdsRef.current;
179
- setSelectedIds(new Set(all));
180
- setLastClickedId(all.length > 0 ? all[all.length - 1] ?? null : null);
181
- }, []);
182
-
183
- const selectRange = useCallback((anchorId: string, targetId: string) => {
184
- const all = orderedIdsRef.current;
185
- const anchorIdx = all.indexOf(anchorId);
186
- const targetIdx = all.indexOf(targetId);
187
- if (anchorIdx === -1 || targetIdx === -1) {
188
- setSelectedIds(new Set([targetId]));
189
- setLastClickedId(targetId);
190
- return;
191
- }
192
- const start = Math.min(anchorIdx, targetIdx);
193
- const end = Math.max(anchorIdx, targetIdx);
194
- const range = all.slice(start, end + 1);
195
- setSelectedIds((prev) => {
196
- const next = new Set(prev);
197
- for (const id of range) next.add(id);
198
- return next;
199
- });
200
- setLastClickedId(targetId);
201
- }, []);
202
-
203
- const onCheckboxClick = useCallback(
204
- (id: string) =>
205
- (event: ReactMouseEvent) => {
206
- event.stopPropagation();
207
- if (event.shiftKey && lastClickedIdRef.current && lastClickedIdRef.current !== id) {
208
- selectRange(lastClickedIdRef.current, id);
209
- return;
210
- }
211
- toggle(id);
212
- },
213
- [selectRange, toggle],
214
- );
215
-
216
- const onRowMouseDown = useCallback(
217
- (id: string) =>
218
- (event: ReactMouseEvent) => {
219
- if (event.button !== 0) return;
220
- if (!(event.metaKey || event.ctrlKey)) return;
221
- const target = event.target as HTMLElement | null;
222
- if (target && target.closest(INTERACTIVE_SELECTOR)) return;
223
- event.preventDefault();
224
- event.stopPropagation();
225
- toggle(id);
226
- // The trailing click on the row should NOT open it.
227
- armSuppressNextClick();
228
- },
229
- [toggle],
230
- );
231
-
232
- const getRowProps = useCallback(
233
- (id: string) => ({
234
- [ROW_ATTR]: id,
235
- }),
236
- [],
237
- );
238
-
239
- const getItemProps = useCallback(
240
- (id: string) => ({
241
- [ROW_ATTR]: id,
242
- onMouseDown: onRowMouseDown(id),
243
- }),
244
- [onRowMouseDown],
245
- );
246
-
247
- const getCheckboxProps = useCallback(
248
- (id: string) => ({
249
- isSelected: selectedIdsRef.current.has(id),
250
- onClick: onCheckboxClick(id),
251
- }),
252
- [onCheckboxClick],
253
- );
254
-
255
- // ---------------------------------------------------------------------------
256
- // Drag-select
257
- // ---------------------------------------------------------------------------
258
-
259
- const dragPendingRef = useRef(false);
260
- const dragActiveRef = useRef(false);
261
- const dragStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
262
- const dragCurrentRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
263
- // Tracks whether the most recent mousedown originated outside any row, which
264
- // means a bare click should clear the selection.
265
- const clickShouldClearRef = useRef(false);
266
- // Set true after a gesture that should NOT trigger the row's onClick: an
267
- // active drag-select, or a cmd/ctrl-click toggle. The container's
268
- // onClickCapture consumes the next click before it reaches the row.
269
- const suppressNextClickRef = useRef(false);
270
-
271
- const armSuppressNextClick = () => {
272
- suppressNextClickRef.current = true;
273
- setTimeout(() => {
274
- suppressNextClickRef.current = false;
275
- }, 0);
276
- };
277
-
278
- const computeDragRect = useCallback((): DragRect => {
279
- const start = dragStartRef.current;
280
- const current = dragCurrentRef.current;
281
- return {
282
- left: Math.min(start.x, current.x),
283
- top: Math.min(start.y, current.y),
284
- width: Math.abs(current.x - start.x),
285
- height: Math.abs(current.y - start.y),
286
- };
287
- }, []);
288
-
289
- const computeIntersectingIds = useCallback(
290
- (rect: { left: number; top: number; right: number; bottom: number }): string[] => {
291
- const container = containerRef.current;
292
- if (!container) return [];
293
- const nodes = container.querySelectorAll<HTMLElement>(`[${ROW_ATTR}]`);
294
- const ids: string[] = [];
295
- nodes.forEach((node) => {
296
- const rowRect = node.getBoundingClientRect();
297
- if (rectsIntersect(rect, rowRect)) {
298
- const id = node.getAttribute(ROW_ATTR);
299
- if (id) ids.push(id);
300
- }
301
- });
302
- return ids;
303
- },
304
- [],
305
- );
306
-
307
- const setContainerRef = useCallback(
308
- (node: HTMLElement | null) => {
309
- containerRef.current = node;
310
- },
311
- [],
312
- );
313
-
314
- const handleContainerMouseDown = useCallback(
315
- (event: ReactMouseEvent) => {
316
- if (event.button !== 0) return;
317
- const target = event.target as HTMLElement | null;
318
- if (!target) return;
319
- // Cmd/Ctrl-click on a row is handled by `onRowMouseDown` (which calls
320
- // stopPropagation), so we never reach here for that case. Skip if the
321
- // mousedown lands on an interactive element so its native focus/text
322
- // behavior is preserved.
323
- if (target.closest(INTERACTIVE_SELECTOR)) {
324
- clickShouldClearRef.current = false;
325
- return;
326
- }
327
- const isOnRow = Boolean(target.closest(`[${ROW_ATTR}]`));
328
- // A click on empty space (not on a row) should clear the selection.
329
- clickShouldClearRef.current = !isOnRow;
330
- if (!enableDragSelect) return;
331
- // Arm a possible drag from anywhere in the container — including row
332
- // bodies. If the user moves past the threshold we activate a rubber-band
333
- // selection AND suppress the trailing click on the row.
334
- dragPendingRef.current = true;
335
- dragStartRef.current = { x: event.clientX, y: event.clientY };
336
- dragCurrentRef.current = { x: event.clientX, y: event.clientY };
337
- },
338
- [enableDragSelect],
339
- );
340
-
341
- // Capture-phase click handler intercepts the trailing click after a drag so
342
- // the row's bubble-phase onClick (which would open the row) never fires.
343
- const handleContainerClickCapture = useCallback(
344
- (event: ReactMouseEvent) => {
345
- if (suppressNextClickRef.current) {
346
- suppressNextClickRef.current = false;
347
- event.stopPropagation();
348
- event.preventDefault();
349
- }
350
- },
351
- [],
352
- );
353
-
354
- // Attach document mousemove/mouseup while a drag is pending or active.
355
- useEffect(() => {
356
- if (!enableDragSelect) return;
357
-
358
- const handleMouseMove = (event: MouseEvent) => {
359
- if (dragPendingRef.current) {
360
- const dx = event.clientX - dragStartRef.current.x;
361
- const dy = event.clientY - dragStartRef.current.y;
362
- if (Math.abs(dx) > dragThreshold || Math.abs(dy) > dragThreshold) {
363
- dragPendingRef.current = false;
364
- dragActiveRef.current = true;
365
- window.getSelection()?.removeAllRanges();
366
- dragCurrentRef.current = { x: event.clientX, y: event.clientY };
367
- setDragRect(computeDragRect());
368
- }
369
- return;
370
- }
371
- if (!dragActiveRef.current) return;
372
- event.preventDefault();
373
- dragCurrentRef.current = { x: event.clientX, y: event.clientY };
374
- const rect = computeDragRect();
375
- setDragRect(rect);
376
- const ids = computeIntersectingIds({
377
- left: rect.left,
378
- top: rect.top,
379
- right: rect.left + rect.width,
380
- bottom: rect.top + rect.height,
381
- });
382
- setSelectedIds(new Set(ids));
383
- setLastClickedId(ids.length > 0 ? ids[ids.length - 1] ?? null : null);
384
- };
385
-
386
- const handleMouseUp = () => {
387
- const wasPending = dragPendingRef.current;
388
- const wasActive = dragActiveRef.current;
389
- dragPendingRef.current = false;
390
- dragActiveRef.current = false;
391
- if (wasActive) {
392
- setDragRect(null);
393
- clickShouldClearRef.current = false;
394
- // The trailing click on the row should not open it.
395
- armSuppressNextClick();
396
- return;
397
- }
398
- if (wasPending && clickShouldClearRef.current) {
399
- // Bare click on empty space — clear the selection.
400
- clickShouldClearRef.current = false;
401
- if (selectedIdsRef.current.size > 0) {
402
- setSelectedIds(new Set());
403
- }
404
- }
405
- };
406
-
407
- document.addEventListener('mousemove', handleMouseMove);
408
- document.addEventListener('mouseup', handleMouseUp);
409
- return () => {
410
- document.removeEventListener('mousemove', handleMouseMove);
411
- document.removeEventListener('mouseup', handleMouseUp);
412
- };
413
- }, [computeDragRect, computeIntersectingIds, dragThreshold, enableDragSelect]);
414
-
415
- // ---------------------------------------------------------------------------
416
- // Keyboard shortcuts
417
- // ---------------------------------------------------------------------------
418
-
419
- useEffect(() => {
420
- if (!bindKeyboardShortcuts) return;
421
-
422
- const handleKeyDown = (event: KeyboardEvent) => {
423
- if (isEditableEvent(event)) return;
424
-
425
- // Esc — clear selection
426
- if (event.key === 'Escape') {
427
- if (selectedIdsRef.current.size > 0) {
428
- event.preventDefault();
429
- setSelectedIds(new Set());
430
- }
431
- return;
432
- }
433
-
434
- // Cmd/Ctrl + A — select all
435
- if ((event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey) {
436
- const key = event.key.toLowerCase();
437
- if (key === 'a') {
438
- if (orderedIdsRef.current.length === 0) return;
439
- event.preventDefault();
440
- const all = orderedIdsRef.current;
441
- setSelectedIds(new Set(all));
442
- setLastClickedId(all[all.length - 1] ?? null);
443
- return;
444
- }
445
- }
446
-
447
- // X — toggle the focused/head row
448
- if (
449
- event.key === 'x' &&
450
- !event.shiftKey &&
451
- !event.metaKey &&
452
- !event.ctrlKey &&
453
- !event.altKey
454
- ) {
455
- const targetId = headIdRef.current ?? lastClickedIdRef.current;
456
- if (!targetId) return;
457
- event.preventDefault();
458
- toggle(targetId);
459
- return;
460
- }
461
-
462
- // Shift + ArrowUp / ArrowDown — extend range from anchor
463
- if (
464
- (event.key === 'ArrowDown' || event.key === 'ArrowUp') &&
465
- event.shiftKey &&
466
- !event.metaKey &&
467
- !event.ctrlKey &&
468
- !event.altKey
469
- ) {
470
- const all = orderedIdsRef.current;
471
- if (all.length === 0) return;
472
- event.preventDefault();
473
- const direction = event.key === 'ArrowDown' ? 1 : -1;
474
- const currentHead = headIdRef.current;
475
- const currentIdx = currentHead ? all.indexOf(currentHead) : -1;
476
- const newIdx =
477
- currentIdx === -1
478
- ? direction === 1
479
- ? 0
480
- : all.length - 1
481
- : Math.min(all.length - 1, Math.max(0, currentIdx + direction));
482
- if (newIdx === currentIdx) return;
483
- const newHead = all[newIdx];
484
- if (!newHead) return;
485
- const anchorId = lastClickedIdRef.current ?? currentHead ?? newHead;
486
- const anchorIdx = all.indexOf(anchorId);
487
- if (anchorIdx === -1) {
488
- setSelectedIds(new Set([newHead]));
489
- } else {
490
- const start = Math.min(anchorIdx, newIdx);
491
- const end = Math.max(anchorIdx, newIdx);
492
- setSelectedIds(new Set(all.slice(start, end + 1)));
493
- }
494
- if (lastClickedIdRef.current === null) {
495
- setLastClickedId(anchorId);
496
- }
497
- setHead(newHead);
498
- return;
499
- }
500
- };
501
-
502
- document.addEventListener('keydown', handleKeyDown);
503
- return () => {
504
- document.removeEventListener('keydown', handleKeyDown);
505
- };
506
- }, [bindKeyboardShortcuts, setHead, toggle]);
507
-
508
- const getContainerProps = useCallback(
509
- () => ({
510
- ref: setContainerRef,
511
- onMouseDown: handleContainerMouseDown,
512
- onClickCapture: handleContainerClickCapture,
513
- style: { userSelect: 'none' as const },
514
- }),
515
- [handleContainerClickCapture, handleContainerMouseDown, setContainerRef],
516
- );
517
-
518
- return {
519
- selectedIds,
520
- selectedCount: selectedIds.size,
521
- lastClickedId,
522
- headId,
523
- dragRect,
524
- isSelected,
525
- getSelectedItems,
526
- toggle,
527
- select,
528
- clear,
529
- selectAll,
530
- selectRange,
531
- setHead,
532
- onCheckboxClick,
533
- onRowMouseDown,
534
- getRowProps,
535
- getItemProps,
536
- getCheckboxProps,
537
- getContainerProps,
538
- };
539
- }
@@ -1,34 +0,0 @@
1
- 'use client';
2
-
3
- import { useNotisRuntime } from '../provider';
4
- import type { AppDescriptor, CollectionItemDetail, DatabaseDescriptor, RouteDescriptor } from '../runtime';
5
-
6
- interface NotisContext {
7
- /** App metadata (id, name, icon, description). Null before runtime loads. */
8
- app: AppDescriptor | null;
9
- /** Current route descriptor. Null before runtime loads. */
10
- route: RouteDescriptor | null;
11
- /** Databases declared by this app. Empty before runtime loads. */
12
- databases: DatabaseDescriptor[];
13
- /** Selected collection item for the current route, when applicable. */
14
- collectionItem: CollectionItemDetail | null;
15
- /** Whether the runtime is loaded and available. */
16
- ready: boolean;
17
- }
18
-
19
- /**
20
- * Access app-level metadata, the current route, declared databases, and the
21
- * selected collection item. Returns safe defaults when the portal runtime is
22
- * not available.
23
- */
24
- export function useNotis(): NotisContext {
25
- const runtime = useNotisRuntime();
26
-
27
- return {
28
- app: runtime?.app ?? null,
29
- route: runtime?.route ?? null,
30
- databases: runtime?.databases ?? [],
31
- collectionItem: runtime?.context?.collectionItem ?? null,
32
- ready: runtime !== null,
33
- };
34
- }
@@ -1,49 +0,0 @@
1
- 'use client';
2
-
3
- import { useCallback } from 'react';
4
- import { useNotisRuntime } from '../provider';
5
-
6
- interface NavigationActions {
7
- /** Navigate to a route within the app by its path. */
8
- toRoute: (path: string) => void;
9
- /** Navigate to a document detail view. */
10
- toDocument: (documentId: string, title?: string | null) => void;
11
- /** Navigate to the app's default route. */
12
- toApp: () => void;
13
- }
14
-
15
- /**
16
- * Navigation helpers for moving between routes and documents within the app.
17
- * When rendered inside the portal, uses the runtime.navigate() bridge.
18
- * Without a portal runtime, falls back to window.location for route navigation.
19
- *
20
- * ```tsx
21
- * const nav = useNotisNavigation();
22
- * nav.toRoute('/settings');
23
- * ```
24
- */
25
- export function useNotisNavigation(): NavigationActions {
26
- const runtime = useNotisRuntime();
27
-
28
- const toRoute = useCallback((path: string) => {
29
- if (runtime?.navigate) {
30
- runtime.navigate({ kind: 'route', path });
31
- } else if (typeof window !== 'undefined') {
32
- window.location.href = path;
33
- }
34
- }, [runtime]);
35
-
36
- const toDocument = useCallback((documentId: string, title?: string | null) => {
37
- if (runtime?.navigate) {
38
- runtime.navigate({ kind: 'document', documentId, title: title ?? undefined });
39
- }
40
- }, [runtime]);
41
-
42
- const toApp = useCallback(() => {
43
- if (runtime?.navigate) {
44
- runtime.navigate({ kind: 'app' });
45
- }
46
- }, [runtime]);
47
-
48
- return { toRoute, toDocument, toApp };
49
- }
@@ -1,64 +0,0 @@
1
- 'use client';
2
-
3
- import { useCallback, useState } from 'react';
4
- import { useNotisRuntime } from '../provider';
5
-
6
- type ToolArguments = Record<string, unknown>;
7
-
8
- type ToolCall<TArgs extends ToolArguments | undefined, TResult> = undefined extends TArgs
9
- ? (args?: Exclude<TArgs, undefined>) => Promise<TResult>
10
- : (args: TArgs) => Promise<TResult>;
11
-
12
- export interface ToolCallState {
13
- loading: boolean;
14
- error: Error | null;
15
- }
16
-
17
- export interface UseToolResult<
18
- TArgs extends ToolArguments | undefined = ToolArguments | undefined,
19
- TResult = unknown,
20
- > extends ToolCallState {
21
- call: ToolCall<TArgs, TResult>;
22
- }
23
-
24
- /**
25
- * Call a specific Notis tool by name.
26
- *
27
- * ```tsx
28
- * const { call, loading } = useTool('LOCAL_NOTIS_WEB_SEARCH');
29
- * const result = await call({ query: 'latest news' });
30
- * ```
31
- */
32
- export function useTool<
33
- TArgs extends ToolArguments | undefined = ToolArguments | undefined,
34
- TResult = unknown,
35
- >(toolName: string): UseToolResult<TArgs, TResult> {
36
- const runtime = useNotisRuntime();
37
- const [loading, setLoading] = useState(false);
38
- const [error, setError] = useState<Error | null>(null);
39
-
40
- const call = useCallback(
41
- async (args?: ToolArguments): Promise<TResult> => {
42
- if (!runtime) {
43
- throw new Error('Notis runtime not available. Ensure NotisProvider is mounted.');
44
- }
45
-
46
- setLoading(true);
47
- setError(null);
48
-
49
- try {
50
- const result = await runtime.callTool<TResult>(toolName, args);
51
- return result;
52
- } catch (err) {
53
- const e = err instanceof Error ? err : new Error(String(err));
54
- setError(e);
55
- throw e;
56
- } finally {
57
- setLoading(false);
58
- }
59
- },
60
- [runtime, toolName],
61
- ) as ToolCall<TArgs, TResult>;
62
-
63
- return { call, loading, error };
64
- }