@notis_ai/cli 0.2.0-beta.137.1 → 0.2.0-beta.144.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 (294) hide show
  1. package/README.md +82 -20
  2. package/dist/agent-hooks/notis-agent-hook.mjs +19750 -0
  3. package/{skills → dist/base-skills}/notis-apps/SKILL.md +84 -53
  4. package/{skills → dist/base-skills}/notis-cli/SKILL.md +9 -9
  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 +38 -17
  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 +871 -387
  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-roots.js +284 -0
  25. package/src/runtime/app-dev-server.js +212 -22
  26. package/src/runtime/app-dev-sessions.js +105 -145
  27. package/src/runtime/app-platform.js +1291 -165
  28. package/src/runtime/app-registry-scaffolds.js +367 -0
  29. package/src/runtime/base-skills.d.ts +20 -0
  30. package/src/runtime/base-skills.js +167 -0
  31. package/src/runtime/login-listener.js +15 -0
  32. package/src/runtime/oauth.js +1506 -141
  33. package/src/runtime/output.js +7 -0
  34. package/src/runtime/ports.js +16 -0
  35. package/src/runtime/profiles.js +0 -5
  36. package/src/runtime/skill-sync/cloud-client.ts +96 -0
  37. package/src/runtime/skill-sync/index.ts +644 -0
  38. package/src/runtime/skill-sync/local-scanner.ts +1046 -0
  39. package/src/runtime/skill-sync/symlink-manager.ts +383 -0
  40. package/src/runtime/skill-sync/sync-plan.ts +22 -0
  41. package/src/runtime/skill-sync/types.ts +103 -0
  42. package/src/runtime/skill-sync/write-cloud-skill.ts +50 -0
  43. package/src/runtime/store-screenshot.js +6 -1
  44. package/src/runtime/sync-skills.d.ts +37 -0
  45. package/src/runtime/sync-skills.js +215 -0
  46. package/template/app/layout.tsx +5 -1
  47. package/template/notis.config.ts +1 -0
  48. package/template/packages/sdk/package.json +2 -1
  49. package/template/packages/sdk/src/components/MarkdownEditor.tsx +121 -0
  50. package/template/packages/sdk/src/components/MultiSelectActionBar.tsx +37 -119
  51. package/template/packages/sdk/src/components/MultiSelectCheckbox.tsx +5 -1
  52. package/template/packages/sdk/src/components/MultiSelectDragOverlay.tsx +1 -1
  53. package/template/packages/sdk/src/components/NotisSelectionBoundary.tsx +55 -0
  54. package/template/packages/sdk/src/components/ShortcutHints.tsx +56 -0
  55. package/template/packages/sdk/src/config.ts +19 -0
  56. package/template/packages/sdk/src/hooks/useActiveResource.ts +19 -0
  57. package/template/packages/sdk/src/hooks/useCollectionInteractions.ts +709 -0
  58. package/template/packages/sdk/src/hooks/useHandover.ts +3 -0
  59. package/template/packages/sdk/src/hooks/useMultiSelect.ts +44 -482
  60. package/template/packages/sdk/src/hooks/useTool.ts +5 -4
  61. package/template/packages/sdk/src/index.ts +47 -2
  62. package/template/packages/sdk/src/interactions/actions.ts +46 -0
  63. package/template/packages/sdk/src/interactions/shortcuts.tsx +628 -0
  64. package/template/packages/sdk/src/interactions.ts +41 -0
  65. package/template/packages/sdk/src/provider.tsx +2 -1
  66. package/template/packages/sdk/src/runtime.ts +85 -3
  67. package/dist/scaffolds/notis-database/CHANGELOG.md +0 -5
  68. package/dist/scaffolds/notis-database/app/globals.css +0 -44
  69. package/dist/scaffolds/notis-database/app/layout.tsx +0 -6
  70. package/dist/scaffolds/notis-database/app/page.tsx +0 -1088
  71. package/dist/scaffolds/notis-database/components/ui/badge.tsx +0 -28
  72. package/dist/scaffolds/notis-database/components/ui/button.tsx +0 -53
  73. package/dist/scaffolds/notis-database/components/ui/card.tsx +0 -56
  74. package/dist/scaffolds/notis-database/components/ui/table.tsx +0 -120
  75. package/dist/scaffolds/notis-database/components.json +0 -20
  76. package/dist/scaffolds/notis-database/index.html +0 -12
  77. package/dist/scaffolds/notis-database/lib/types.ts +0 -132
  78. package/dist/scaffolds/notis-database/lib/utils.ts +0 -6
  79. package/dist/scaffolds/notis-database/metadata/screenshot-1.png +0 -0
  80. package/dist/scaffolds/notis-database/metadata/screenshot-2.png +0 -0
  81. package/dist/scaffolds/notis-database/metadata/screenshot-3.png +0 -0
  82. package/dist/scaffolds/notis-database/metadata/screenshot-4.png +0 -0
  83. package/dist/scaffolds/notis-database/metadata/screenshot-5.png +0 -0
  84. package/dist/scaffolds/notis-database/metadata/screenshot-fixtures.json +0 -1839
  85. package/dist/scaffolds/notis-database/notis.config.ts +0 -73
  86. package/dist/scaffolds/notis-database/package-lock.json +0 -3935
  87. package/dist/scaffolds/notis-database/package.json +0 -32
  88. package/dist/scaffolds/notis-database/packages/sdk/package.json +0 -36
  89. package/dist/scaffolds/notis-database/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  90. package/dist/scaffolds/notis-database/packages/sdk/src/components/Markdown.tsx +0 -60
  91. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  92. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  93. package/dist/scaffolds/notis-database/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  94. package/dist/scaffolds/notis-database/packages/sdk/src/config.ts +0 -234
  95. package/dist/scaffolds/notis-database/packages/sdk/src/documents.ts +0 -250
  96. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useBackend.ts +0 -41
  97. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  98. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  99. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  100. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDocument.ts +0 -78
  101. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useDocuments.ts +0 -121
  102. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useHandover.ts +0 -75
  103. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  104. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useNotis.ts +0 -34
  105. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  106. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTool.ts +0 -64
  107. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTools.ts +0 -56
  108. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  109. package/dist/scaffolds/notis-database/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  110. package/dist/scaffolds/notis-database/packages/sdk/src/index.ts +0 -100
  111. package/dist/scaffolds/notis-database/packages/sdk/src/provider.tsx +0 -43
  112. package/dist/scaffolds/notis-database/packages/sdk/src/runtime.ts +0 -351
  113. package/dist/scaffolds/notis-database/packages/sdk/src/styles.css +0 -186
  114. package/dist/scaffolds/notis-database/packages/sdk/src/ui.ts +0 -15
  115. package/dist/scaffolds/notis-database/packages/sdk/src/vite.ts +0 -56
  116. package/dist/scaffolds/notis-database/packages/sdk/tsconfig.json +0 -15
  117. package/dist/scaffolds/notis-database/postcss.config.mjs +0 -8
  118. package/dist/scaffolds/notis-database/src/dev-main.tsx +0 -23
  119. package/dist/scaffolds/notis-database/src/mock-runtime.ts +0 -561
  120. package/dist/scaffolds/notis-database/tailwind.config.ts +0 -59
  121. package/dist/scaffolds/notis-database/tsconfig.json +0 -23
  122. package/dist/scaffolds/notis-database/vite.config.ts +0 -22
  123. package/dist/scaffolds/notis-journal/CHANGELOG.md +0 -29
  124. package/dist/scaffolds/notis-journal/app/globals.css +0 -37
  125. package/dist/scaffolds/notis-journal/app/insights/page.tsx +0 -513
  126. package/dist/scaffolds/notis-journal/app/journal-core.tsx +0 -362
  127. package/dist/scaffolds/notis-journal/app/journal-ui.tsx +0 -337
  128. package/dist/scaffolds/notis-journal/app/layout.tsx +0 -6
  129. package/dist/scaffolds/notis-journal/app/page.tsx +0 -486
  130. package/dist/scaffolds/notis-journal/components/ui/badge.tsx +0 -28
  131. package/dist/scaffolds/notis-journal/components/ui/button.tsx +0 -53
  132. package/dist/scaffolds/notis-journal/components/ui/card.tsx +0 -56
  133. package/dist/scaffolds/notis-journal/components.json +0 -20
  134. package/dist/scaffolds/notis-journal/index.html +0 -12
  135. package/dist/scaffolds/notis-journal/lib/utils.ts +0 -6
  136. package/dist/scaffolds/notis-journal/metadata/screenshot-1.png +0 -0
  137. package/dist/scaffolds/notis-journal/metadata/screenshot-2.png +0 -0
  138. package/dist/scaffolds/notis-journal/metadata/screenshot-3.png +0 -0
  139. package/dist/scaffolds/notis-journal/metadata/screenshot-4.png +0 -0
  140. package/dist/scaffolds/notis-journal/metadata/screenshot-5.png +0 -0
  141. package/dist/scaffolds/notis-journal/metadata/screenshot-6.png +0 -0
  142. package/dist/scaffolds/notis-journal/metadata/screenshot-fixtures.json +0 -132
  143. package/dist/scaffolds/notis-journal/notis.config.ts +0 -93
  144. package/dist/scaffolds/notis-journal/package-lock.json +0 -4615
  145. package/dist/scaffolds/notis-journal/package.json +0 -34
  146. package/dist/scaffolds/notis-journal/packages/sdk/package.json +0 -36
  147. package/dist/scaffolds/notis-journal/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  148. package/dist/scaffolds/notis-journal/packages/sdk/src/components/Markdown.tsx +0 -60
  149. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  150. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  151. package/dist/scaffolds/notis-journal/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  152. package/dist/scaffolds/notis-journal/packages/sdk/src/config.ts +0 -234
  153. package/dist/scaffolds/notis-journal/packages/sdk/src/documents.ts +0 -250
  154. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useBackend.ts +0 -41
  155. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  156. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  157. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  158. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDocument.ts +0 -78
  159. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useDocuments.ts +0 -121
  160. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useHandover.ts +0 -75
  161. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  162. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useNotis.ts +0 -34
  163. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  164. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTool.ts +0 -64
  165. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTools.ts +0 -56
  166. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  167. package/dist/scaffolds/notis-journal/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  168. package/dist/scaffolds/notis-journal/packages/sdk/src/index.ts +0 -100
  169. package/dist/scaffolds/notis-journal/packages/sdk/src/provider.tsx +0 -43
  170. package/dist/scaffolds/notis-journal/packages/sdk/src/runtime.ts +0 -351
  171. package/dist/scaffolds/notis-journal/packages/sdk/src/styles.css +0 -186
  172. package/dist/scaffolds/notis-journal/packages/sdk/src/ui.ts +0 -15
  173. package/dist/scaffolds/notis-journal/packages/sdk/src/vite.ts +0 -56
  174. package/dist/scaffolds/notis-journal/packages/sdk/tsconfig.json +0 -15
  175. package/dist/scaffolds/notis-journal/postcss.config.mjs +0 -8
  176. package/dist/scaffolds/notis-journal/skills/journal-onboarding/SKILL.md +0 -120
  177. package/dist/scaffolds/notis-journal/src/dev-main.tsx +0 -58
  178. package/dist/scaffolds/notis-journal/src/mock-runtime.ts +0 -199
  179. package/dist/scaffolds/notis-journal/tailwind.config.ts +0 -58
  180. package/dist/scaffolds/notis-journal/tsconfig.json +0 -23
  181. package/dist/scaffolds/notis-journal/vite.config.ts +0 -10
  182. package/dist/scaffolds/notis-notes/CHANGELOG.md +0 -5
  183. package/dist/scaffolds/notis-notes/app/globals.css +0 -3
  184. package/dist/scaffolds/notis-notes/app/layout.tsx +0 -6
  185. package/dist/scaffolds/notis-notes/app/page.tsx +0 -1943
  186. package/dist/scaffolds/notis-notes/app/phosphor-icons.ts +0 -596
  187. package/dist/scaffolds/notis-notes/components/ui/badge.tsx +0 -28
  188. package/dist/scaffolds/notis-notes/components/ui/button.tsx +0 -53
  189. package/dist/scaffolds/notis-notes/components/ui/card.tsx +0 -56
  190. package/dist/scaffolds/notis-notes/components.json +0 -20
  191. package/dist/scaffolds/notis-notes/lib/utils.ts +0 -6
  192. package/dist/scaffolds/notis-notes/lib/visible-properties.ts +0 -144
  193. package/dist/scaffolds/notis-notes/metadata/screenshot-1.png +0 -0
  194. package/dist/scaffolds/notis-notes/metadata/screenshot-2.png +0 -0
  195. package/dist/scaffolds/notis-notes/metadata/screenshot-3.png +0 -0
  196. package/dist/scaffolds/notis-notes/metadata/screenshot-4.png +0 -0
  197. package/dist/scaffolds/notis-notes/metadata/screenshot-5.png +0 -0
  198. package/dist/scaffolds/notis-notes/metadata/screenshot-fixtures.json +0 -752
  199. package/dist/scaffolds/notis-notes/notis.config.ts +0 -80
  200. package/dist/scaffolds/notis-notes/package-lock.json +0 -4636
  201. package/dist/scaffolds/notis-notes/package.json +0 -35
  202. package/dist/scaffolds/notis-notes/packages/sdk/package.json +0 -36
  203. package/dist/scaffolds/notis-notes/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  204. package/dist/scaffolds/notis-notes/packages/sdk/src/components/Markdown.tsx +0 -60
  205. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  206. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  207. package/dist/scaffolds/notis-notes/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  208. package/dist/scaffolds/notis-notes/packages/sdk/src/config.ts +0 -234
  209. package/dist/scaffolds/notis-notes/packages/sdk/src/documents.ts +0 -250
  210. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useBackend.ts +0 -41
  211. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  212. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  213. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  214. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDocument.ts +0 -78
  215. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useDocuments.ts +0 -121
  216. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useHandover.ts +0 -75
  217. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  218. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useNotis.ts +0 -34
  219. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  220. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTool.ts +0 -64
  221. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTools.ts +0 -56
  222. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  223. package/dist/scaffolds/notis-notes/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  224. package/dist/scaffolds/notis-notes/packages/sdk/src/index.ts +0 -100
  225. package/dist/scaffolds/notis-notes/packages/sdk/src/provider.tsx +0 -43
  226. package/dist/scaffolds/notis-notes/packages/sdk/src/runtime.ts +0 -351
  227. package/dist/scaffolds/notis-notes/packages/sdk/src/styles.css +0 -186
  228. package/dist/scaffolds/notis-notes/packages/sdk/src/ui.ts +0 -15
  229. package/dist/scaffolds/notis-notes/packages/sdk/src/vite.ts +0 -56
  230. package/dist/scaffolds/notis-notes/packages/sdk/tsconfig.json +0 -15
  231. package/dist/scaffolds/notis-notes/postcss.config.mjs +0 -8
  232. package/dist/scaffolds/notis-notes/tailwind.config.ts +0 -58
  233. package/dist/scaffolds/notis-notes/tsconfig.json +0 -23
  234. package/dist/scaffolds/notis-notes/vite.config.ts +0 -10
  235. package/dist/scaffolds/notis-random/CHANGELOG.md +0 -15
  236. package/dist/scaffolds/notis-random/README.md +0 -33
  237. package/dist/scaffolds/notis-random/app/globals.css +0 -11
  238. package/dist/scaffolds/notis-random/app/history/page.tsx +0 -67
  239. package/dist/scaffolds/notis-random/app/layout.tsx +0 -7
  240. package/dist/scaffolds/notis-random/app/page.tsx +0 -289
  241. package/dist/scaffolds/notis-random/components/ui/button.tsx +0 -50
  242. package/dist/scaffolds/notis-random/components/ui/card.tsx +0 -16
  243. package/dist/scaffolds/notis-random/components/ui/input.tsx +0 -23
  244. package/dist/scaffolds/notis-random/components.json +0 -20
  245. package/dist/scaffolds/notis-random/index.html +0 -12
  246. package/dist/scaffolds/notis-random/lib/notis-tools.ts +0 -128
  247. package/dist/scaffolds/notis-random/lib/rng.ts +0 -202
  248. package/dist/scaffolds/notis-random/lib/roll-record.ts +0 -189
  249. package/dist/scaffolds/notis-random/lib/utils.ts +0 -25
  250. package/dist/scaffolds/notis-random/metadata/screenshot-1.png +0 -0
  251. package/dist/scaffolds/notis-random/metadata/screenshot-2.png +0 -0
  252. package/dist/scaffolds/notis-random/metadata/screenshot-3.png +0 -0
  253. package/dist/scaffolds/notis-random/metadata/screenshot-4.png +0 -0
  254. package/dist/scaffolds/notis-random/metadata/screenshot-5.png +0 -0
  255. package/dist/scaffolds/notis-random/metadata/screenshot-fixtures.json +0 -753
  256. package/dist/scaffolds/notis-random/notis.config.ts +0 -86
  257. package/dist/scaffolds/notis-random/package-lock.json +0 -4513
  258. package/dist/scaffolds/notis-random/package.json +0 -36
  259. package/dist/scaffolds/notis-random/packages/sdk/package.json +0 -36
  260. package/dist/scaffolds/notis-random/packages/sdk/src/components/DocumentEditor.tsx +0 -93
  261. package/dist/scaffolds/notis-random/packages/sdk/src/components/Markdown.tsx +0 -60
  262. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectActionBar.tsx +0 -278
  263. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectCheckbox.tsx +0 -91
  264. package/dist/scaffolds/notis-random/packages/sdk/src/components/MultiSelectDragOverlay.tsx +0 -39
  265. package/dist/scaffolds/notis-random/packages/sdk/src/config.ts +0 -234
  266. package/dist/scaffolds/notis-random/packages/sdk/src/documents.ts +0 -250
  267. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useBackend.ts +0 -41
  268. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  269. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  270. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDatabaseSubscription.ts +0 -76
  271. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDocument.ts +0 -78
  272. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useDocuments.ts +0 -121
  273. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useHandover.ts +0 -75
  274. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useMultiSelect.ts +0 -539
  275. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useNotis.ts +0 -34
  276. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useNotisNavigation.ts +0 -49
  277. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTool.ts +0 -64
  278. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTools.ts +0 -56
  279. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  280. package/dist/scaffolds/notis-random/packages/sdk/src/hooks/useUpsertDocument.ts +0 -95
  281. package/dist/scaffolds/notis-random/packages/sdk/src/index.ts +0 -100
  282. package/dist/scaffolds/notis-random/packages/sdk/src/provider.tsx +0 -43
  283. package/dist/scaffolds/notis-random/packages/sdk/src/runtime.ts +0 -351
  284. package/dist/scaffolds/notis-random/packages/sdk/src/styles.css +0 -186
  285. package/dist/scaffolds/notis-random/packages/sdk/src/ui.ts +0 -15
  286. package/dist/scaffolds/notis-random/packages/sdk/src/vite.ts +0 -56
  287. package/dist/scaffolds/notis-random/packages/sdk/tsconfig.json +0 -15
  288. package/dist/scaffolds/notis-random/postcss.config.mjs +0 -6
  289. package/dist/scaffolds/notis-random/src/dev-main.tsx +0 -70
  290. package/dist/scaffolds/notis-random/src/mock-runtime.ts +0 -129
  291. package/dist/scaffolds/notis-random/tailwind.config.ts +0 -50
  292. package/dist/scaffolds/notis-random/tsconfig.json +0 -23
  293. package/dist/scaffolds/notis-random/vite.config.ts +0 -11
  294. package/dist/scaffolds.json +0 -49
@@ -1,362 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * Shared data layer + domain model for Journal.
5
- *
6
- * The journal is capture-less by design: entries are created and completed by
7
- * the Notis morning and evening automations, and the app only reads
8
- * `journal_entries`. Everything both routes need lives here — the mood scale,
9
- * the entry adapter over SDK-normalized documents, completeness helpers, and
10
- * formatting utilities.
11
- */
12
-
13
- import { useMemo } from 'react';
14
- import { useDocuments, type DocumentRecord } from '@notis/sdk';
15
-
16
- export const JOURNAL_DATABASE_SLUG = 'journal_entries';
17
-
18
- // Canonical property names as defined on the journal_entries schema.
19
- export const PROP = {
20
- title: 'Name',
21
- date: 'Date',
22
- morningMood: 'Morning Mood',
23
- morningMoodWord: 'Morning Mood Word',
24
- morningFeeling: 'Morning Feeling',
25
- energy: 'Energy',
26
- motivation: 'Motivation',
27
- gratitude1: 'Gratitude 1',
28
- gratitude2: 'Gratitude 2',
29
- gratitude3: 'Gratitude 3',
30
- intention: 'Intention',
31
- affirmation: 'Affirmation',
32
- dayMood: 'Day Mood',
33
- dayMoodWord: 'Day Mood Word',
34
- highlight: 'Highlight',
35
- lesson: 'Lesson',
36
- } as const;
37
-
38
- export interface JournalEntry {
39
- id: string;
40
- title: string;
41
- date: string | null; // YYYY-MM-DD for the day this entry is for
42
- /** Waking mood on the 1–7 pleasant scale. */
43
- morningMood: number | null;
44
- morningMoodWord: string | null;
45
- morningFeeling: string | null;
46
- energy: number | null; // 1–10
47
- motivation: number | null; // 1–10
48
- gratitudes: [string | null, string | null, string | null];
49
- intention: string | null;
50
- affirmation: string | null;
51
- /** Whole-day mood on the 1–7 pleasant scale, filled in the evening. */
52
- dayMood: number | null;
53
- dayMoodWord: string | null;
54
- highlight: string | null;
55
- lesson: string | null;
56
- /** Markdown body — the optional free-form entry dictated to Notis. */
57
- freeEntry: string | null;
58
- createdAt: string | null;
59
- lastEditedTime: string | null;
60
- }
61
-
62
- // ---------------------------------------------------------------------------
63
- // The pleasant–unpleasant mood scale (Apple-watch style, 1..7)
64
- // ---------------------------------------------------------------------------
65
-
66
- export interface MoodStep {
67
- value: number; // 1..7
68
- label: string;
69
- color: string; // accent used for dots / bars
70
- soft: string; // translucent background
71
- }
72
-
73
- export const MOOD_SCALE: MoodStep[] = [
74
- { value: 1, label: 'Very unpleasant', color: '#8b5cf6', soft: 'rgba(139,92,246,0.15)' },
75
- { value: 2, label: 'Unpleasant', color: '#6366f1', soft: 'rgba(99,102,241,0.15)' },
76
- { value: 3, label: 'Slightly unpleasant', color: '#3b82f6', soft: 'rgba(59,130,246,0.15)' },
77
- { value: 4, label: 'Neutral', color: '#0ea5e9', soft: 'rgba(14,165,233,0.15)' },
78
- { value: 5, label: 'Slightly pleasant', color: '#14b8a6', soft: 'rgba(20,184,166,0.15)' },
79
- { value: 6, label: 'Pleasant', color: '#10b981', soft: 'rgba(16,185,129,0.15)' },
80
- { value: 7, label: 'Very pleasant', color: '#f59e0b', soft: 'rgba(245,158,11,0.17)' },
81
- ];
82
-
83
- export function moodStep(value: number | null | undefined): MoodStep | null {
84
- if (value == null) return null;
85
- const rounded = Math.round(value);
86
- return MOOD_SCALE.find((step) => step.value === rounded) ?? null;
87
- }
88
-
89
- export const ENERGY_COLOR = '#f59e0b';
90
- export const MOTIVATION_COLOR = '#3b82f6';
91
- export const MORNING_MOOD_COLOR = '#f59e0b';
92
- export const DAY_MOOD_COLOR = '#6366f1';
93
-
94
- // ---------------------------------------------------------------------------
95
- // Entry adapter over SDK-normalized documents
96
- // ---------------------------------------------------------------------------
97
-
98
- function str(value: unknown): string | null {
99
- return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;
100
- }
101
-
102
- function num(value: unknown): number | null {
103
- return typeof value === 'number' && Number.isFinite(value) ? value : null;
104
- }
105
-
106
- export function entryFromDocument(document: DocumentRecord): JournalEntry {
107
- const props = document.properties;
108
- return {
109
- id: document.id,
110
- title: str(props[PROP.title]) ?? str(document.title) ?? 'Untitled entry',
111
- date: str(props[PROP.date]),
112
- morningMood: num(props[PROP.morningMood]),
113
- morningMoodWord: str(props[PROP.morningMoodWord]),
114
- morningFeeling: str(props[PROP.morningFeeling]),
115
- energy: num(props[PROP.energy]),
116
- motivation: num(props[PROP.motivation]),
117
- gratitudes: [
118
- str(props[PROP.gratitude1]),
119
- str(props[PROP.gratitude2]),
120
- str(props[PROP.gratitude3]),
121
- ],
122
- intention: str(props[PROP.intention]),
123
- affirmation: str(props[PROP.affirmation]),
124
- dayMood: num(props[PROP.dayMood]),
125
- dayMoodWord: str(props[PROP.dayMoodWord]),
126
- highlight: str(props[PROP.highlight]),
127
- lesson: str(props[PROP.lesson]),
128
- freeEntry: document.contentMarkdown ?? document.plainText ?? null,
129
- createdAt: document.createdAt ?? null,
130
- lastEditedTime: document.lastEditedTime ?? null,
131
- };
132
- }
133
-
134
- /** Newest first, using the entry Date then falling back to creation time. */
135
- export function sortEntries(entries: JournalEntry[]): JournalEntry[] {
136
- return [...entries].sort((a, b) => {
137
- const av = a.date ?? a.createdAt ?? '';
138
- const bv = b.date ?? b.createdAt ?? '';
139
- return av < bv ? 1 : av > bv ? -1 : 0;
140
- });
141
- }
142
-
143
- // ---------------------------------------------------------------------------
144
- // Completeness — what the automations still need to ask for
145
- // ---------------------------------------------------------------------------
146
-
147
- export function gratitudeCount(entry: JournalEntry): number {
148
- return entry.gratitudes.filter(Boolean).length;
149
- }
150
-
151
- /** True when any of the morning ritual fields has been captured. */
152
- export function morningStarted(entry: JournalEntry): boolean {
153
- return (
154
- entry.morningMood != null ||
155
- entry.morningMoodWord != null ||
156
- entry.morningFeeling != null ||
157
- entry.energy != null ||
158
- entry.motivation != null ||
159
- gratitudeCount(entry) > 0 ||
160
- entry.intention != null ||
161
- entry.affirmation != null
162
- );
163
- }
164
-
165
- export function morningComplete(entry: JournalEntry): boolean {
166
- return (
167
- entry.morningMood != null &&
168
- entry.morningMoodWord != null &&
169
- entry.energy != null &&
170
- entry.motivation != null &&
171
- gratitudeCount(entry) === 3 &&
172
- entry.intention != null &&
173
- entry.affirmation != null
174
- );
175
- }
176
-
177
- export function eveningStarted(entry: JournalEntry): boolean {
178
- return (
179
- entry.dayMood != null ||
180
- entry.dayMoodWord != null ||
181
- entry.highlight != null ||
182
- entry.lesson != null
183
- );
184
- }
185
-
186
- export function eveningComplete(entry: JournalEntry): boolean {
187
- return (
188
- entry.dayMood != null &&
189
- entry.dayMoodWord != null &&
190
- entry.highlight != null &&
191
- entry.lesson != null
192
- );
193
- }
194
-
195
- // ---------------------------------------------------------------------------
196
- // Formatting
197
- // ---------------------------------------------------------------------------
198
-
199
- function toDate(value: string | null): Date | null {
200
- if (!value) return null;
201
- const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
202
- if (dateOnly) {
203
- const [, year, month, day] = dateOnly;
204
- const localDate = new Date(Number(year), Number(month) - 1, Number(day));
205
- return Number.isNaN(localDate.getTime()) ? null : localDate;
206
- }
207
- const d = new Date(value);
208
- return Number.isNaN(d.getTime()) ? null : d;
209
- }
210
-
211
- /** YYYY-MM-DD in local time, for grouping and comparisons. */
212
- export function dayKey(value: string | null): string | null {
213
- const d = toDate(value);
214
- if (!d) return null;
215
- const y = d.getFullYear();
216
- const m = String(d.getMonth() + 1).padStart(2, '0');
217
- const day = String(d.getDate()).padStart(2, '0');
218
- return `${y}-${m}-${day}`;
219
- }
220
-
221
- export function todayKey(): string {
222
- return dayKey(new Date().toISOString()) ?? '';
223
- }
224
-
225
- export function formatDay(value: string | null, opts: { weekday?: boolean } = {}): string {
226
- const d = toDate(value);
227
- if (!d) return 'No date';
228
- return d.toLocaleDateString(undefined, {
229
- weekday: opts.weekday ? 'short' : undefined,
230
- month: 'short',
231
- day: 'numeric',
232
- year: d.getFullYear() === new Date().getFullYear() ? undefined : 'numeric',
233
- });
234
- }
235
-
236
- /** "Wednesday, July 16" — the headline identity of a day spread. */
237
- export function formatDayLong(value: string | null): string {
238
- const d = toDate(value);
239
- if (!d) return 'No date';
240
- return d.toLocaleDateString(undefined, {
241
- weekday: 'long',
242
- month: 'long',
243
- day: 'numeric',
244
- year: d.getFullYear() === new Date().getFullYear() ? undefined : 'numeric',
245
- });
246
- }
247
-
248
- export function relativeDay(value: string | null): string | null {
249
- const key = dayKey(value);
250
- if (!key) return null;
251
- const today = todayKey();
252
- if (key === today) return 'Today';
253
- const yesterday = dayKey(new Date(Date.now() - 86400000).toISOString());
254
- if (key === yesterday) return 'Yesterday';
255
- return null;
256
- }
257
-
258
- /** Short weekday + day-of-month pieces for the timeline rail. */
259
- export function railDate(value: string | null): { weekday: string; day: string } {
260
- const d = toDate(value);
261
- if (!d) return { weekday: '—', day: '·' };
262
- return {
263
- weekday: d.toLocaleDateString(undefined, { weekday: 'short' }),
264
- day: String(d.getDate()),
265
- };
266
- }
267
-
268
- export function round1(n: number): number {
269
- return Math.round(n * 10) / 10;
270
- }
271
-
272
- export function average(values: Array<number | null | undefined>): number | null {
273
- const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v));
274
- if (!nums.length) return null;
275
- return round1(nums.reduce((sum, v) => sum + v, 0) / nums.length);
276
- }
277
-
278
- /** Compute a current daily-journaling streak (consecutive days up to today). */
279
- export function computeStreak(entries: JournalEntry[]): number {
280
- const keys = new Set(entries.map((e) => dayKey(e.date)).filter(Boolean) as string[]);
281
- if (!keys.size) return 0;
282
- let streak = 0;
283
- const cursor = new Date();
284
- // Allow the streak to "start" yesterday if today has no entry yet.
285
- if (!keys.has(dayKey(cursor.toISOString()) ?? '')) {
286
- cursor.setDate(cursor.getDate() - 1);
287
- }
288
- while (keys.has(dayKey(cursor.toISOString()) ?? '')) {
289
- streak += 1;
290
- cursor.setDate(cursor.getDate() - 1);
291
- }
292
- return streak;
293
- }
294
-
295
- /** "July 2026" style label for timeline month grouping. */
296
- export function monthLabel(value: string | null): string {
297
- const key = dayKey(value);
298
- if (!key) return 'Undated';
299
- const [y, m] = key.split('-').map(Number);
300
- return new Date(y, m - 1, 1).toLocaleDateString(undefined, {
301
- month: 'long',
302
- year: 'numeric',
303
- });
304
- }
305
-
306
- /**
307
- * Most frequent mood adjectives across entries (morning + day words),
308
- * lower-cased, best first.
309
- */
310
- export function topMoodWords(
311
- entries: JournalEntry[],
312
- limit = 12,
313
- ): Array<{ word: string; count: number }> {
314
- const counts = new Map<string, number>();
315
- for (const entry of entries) {
316
- for (const word of [entry.morningMoodWord, entry.dayMoodWord]) {
317
- if (!word) continue;
318
- const key = word.trim().toLowerCase();
319
- if (!key) continue;
320
- counts.set(key, (counts.get(key) ?? 0) + 1);
321
- }
322
- }
323
- return [...counts.entries()]
324
- .map(([word, count]) => ({ word, count }))
325
- .sort((a, b) => b.count - a.count || a.word.localeCompare(b.word))
326
- .slice(0, limit);
327
- }
328
-
329
- /** Recent gratitudes, newest first, flattened from the three slots. */
330
- export function recentGratitudes(
331
- entries: JournalEntry[],
332
- limit = 12,
333
- ): Array<{ text: string; date: string | null }> {
334
- const items: Array<{ text: string; date: string | null }> = [];
335
- for (const entry of entries) {
336
- for (const text of entry.gratitudes) {
337
- if (text) items.push({ text, date: entry.date });
338
- }
339
- if (items.length >= limit) break;
340
- }
341
- return items.slice(0, limit);
342
- }
343
-
344
- // ---------------------------------------------------------------------------
345
- // Hooks
346
- // ---------------------------------------------------------------------------
347
-
348
- export function useJournalEntries() {
349
- const { documents, loading, error, refetch } = useDocuments(JOURNAL_DATABASE_SLUG, {
350
- // A one-year window keeps the embedded app fast while preserving enough
351
- // history for useful trends. Older entries remain available in Notis.
352
- pageSize: 365,
353
- fetchAll: false,
354
- });
355
-
356
- const entries = useMemo(
357
- () => sortEntries(documents.map(entryFromDocument)),
358
- [documents],
359
- );
360
-
361
- return { entries, loading, error: error?.message ?? null, refresh: refetch };
362
- }
@@ -1,337 +0,0 @@
1
- 'use client';
2
-
3
- /** Shared presentational building blocks for Journal. */
4
-
5
- import type { ReactNode } from 'react';
6
- import { CircleNotchIcon, type Icon } from '@phosphor-icons/react';
7
- import { cn } from '@/lib/utils';
8
- import { MOOD_SCALE, moodStep } from './journal-core';
9
-
10
- /**
11
- * The signature mood control: seven dots from very unpleasant to very
12
- * pleasant, with the recorded step enlarged and colored, plus the adjective
13
- * the user gave. Read-only — the automations do the asking.
14
- */
15
- export function MoodScale({
16
- value,
17
- word,
18
- size = 'md',
19
- }: {
20
- value: number | null;
21
- word?: string | null;
22
- size?: 'sm' | 'md';
23
- }) {
24
- const active = moodStep(value);
25
- const dot = size === 'sm' ? 7 : 9;
26
- const activeDot = size === 'sm' ? 13 : 18;
27
- return (
28
- <div className="flex items-center gap-3">
29
- <div className="flex items-center gap-1.5" role="img" aria-label={active ? `${active.label} (${active.value} of 7)` : 'No mood recorded'}>
30
- {MOOD_SCALE.map((step) => {
31
- const isActive = active?.value === step.value;
32
- return (
33
- <span
34
- key={step.value}
35
- className="rounded-full transition-all"
36
- title={step.label}
37
- style={{
38
- width: isActive ? activeDot : dot,
39
- height: isActive ? activeDot : dot,
40
- backgroundColor: isActive ? step.color : 'transparent',
41
- boxShadow: isActive
42
- ? `0 0 0 3px ${step.soft}`
43
- : `inset 0 0 0 1.5px ${step.color}55`,
44
- }}
45
- />
46
- );
47
- })}
48
- </div>
49
- {active ? (
50
- <span className={cn('font-medium leading-tight', size === 'sm' ? 'text-xs' : 'text-sm')}>
51
- {word ? <span className="capitalize">{word}</span> : active.label}
52
- {word ? (
53
- <span className="ml-1.5 font-normal text-muted-foreground">{active.label.toLowerCase()}</span>
54
- ) : null}
55
- </span>
56
- ) : (
57
- <span className="text-xs text-muted-foreground">Not recorded</span>
58
- )}
59
- </div>
60
- );
61
- }
62
-
63
- /** Small colored dot for the timeline rail. Hollow when missing. */
64
- export function MoodDot({ value, size = 8 }: { value: number | null; size?: number }) {
65
- const step = moodStep(value);
66
- return (
67
- <span
68
- aria-hidden
69
- className="inline-block shrink-0 rounded-full"
70
- style={{
71
- width: size,
72
- height: size,
73
- backgroundColor: step?.color ?? 'transparent',
74
- boxShadow: step ? undefined : 'inset 0 0 0 1px hsl(var(--muted-foreground) / 0.4)',
75
- }}
76
- />
77
- );
78
- }
79
-
80
- /** Compact mood pill: colored dot + adjective (or scale label). */
81
- export function MoodPill({ value, word }: { value: number | null; word?: string | null }) {
82
- const step = moodStep(value);
83
- if (!step) return <span className="text-xs text-muted-foreground">—</span>;
84
- return (
85
- <span
86
- className="inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium capitalize"
87
- style={{ backgroundColor: step.soft, color: step.color }}
88
- >
89
- <span className="h-1.5 w-1.5 rounded-full" style={{ backgroundColor: step.color }} />
90
- {word ?? step.label}
91
- </span>
92
- );
93
- }
94
-
95
- /** 1..10 level rendered as a labelled row of ten ticks. */
96
- export function LevelTicks({
97
- label,
98
- value,
99
- color,
100
- icon: IconCmp,
101
- }: {
102
- label: string;
103
- value: number | null;
104
- color: string;
105
- icon: Icon;
106
- }) {
107
- return (
108
- <div className="flex items-center gap-3">
109
- <span className="flex w-28 shrink-0 items-center gap-1.5 text-xs font-medium text-muted-foreground">
110
- <IconCmp size={14} weight="bold" style={{ color }} />
111
- {label}
112
- </span>
113
- <div className="flex flex-1 items-center gap-1" role="img" aria-label={`${label}: ${value ?? 'not recorded'} out of 10`}>
114
- {Array.from({ length: 10 }, (_, i) => {
115
- const filled = value != null && i < value;
116
- return (
117
- <span
118
- key={i}
119
- className="h-3.5 flex-1 rounded-sm transition-all"
120
- style={{
121
- maxWidth: 18,
122
- backgroundColor: filled ? color : 'hsl(var(--muted))',
123
- opacity: filled ? 0.4 + 0.6 * ((i + 1) / 10) : 1,
124
- }}
125
- />
126
- );
127
- })}
128
- </div>
129
- <span className="w-9 shrink-0 text-right text-sm font-semibold tabular-nums">
130
- {value ?? '—'}
131
- </span>
132
- </div>
133
- );
134
- }
135
-
136
- /** Section wrapper for the morning / evening halves of a day spread. */
137
- export function RitualSection({
138
- icon: IconCmp,
139
- title,
140
- accent,
141
- aside,
142
- children,
143
- }: {
144
- icon: Icon;
145
- title: string;
146
- accent: string;
147
- aside?: ReactNode;
148
- children: ReactNode;
149
- }) {
150
- return (
151
- <section className="rounded-2xl border border-border bg-card text-card-foreground shadow-sm">
152
- <header className="flex items-center justify-between gap-3 border-b border-border/60 px-5 py-3.5 sm:px-6">
153
- <div className="flex items-center gap-2.5">
154
- <span
155
- className="flex h-7 w-7 items-center justify-center rounded-full"
156
- style={{ backgroundColor: `${accent}1f`, color: accent }}
157
- >
158
- <IconCmp size={15} weight="fill" />
159
- </span>
160
- <h2 className="text-[11px] font-semibold uppercase tracking-[0.14em] text-muted-foreground">
161
- {title}
162
- </h2>
163
- </div>
164
- {aside}
165
- </header>
166
- <div className="space-y-5 px-5 py-5 sm:px-6">{children}</div>
167
- </section>
168
- );
169
- }
170
-
171
- /** A prompt of the ritual with its answer, or a gentle "not captured" hint. */
172
- export function PromptBlock({
173
- prompt,
174
- children,
175
- missingHint,
176
- }: {
177
- prompt: string;
178
- children?: ReactNode;
179
- missingHint?: string;
180
- }) {
181
- return (
182
- <div>
183
- <p className="text-[11px] font-medium uppercase tracking-[0.12em] text-muted-foreground">
184
- {prompt}
185
- </p>
186
- {children ? (
187
- <div className="mt-1.5 text-sm leading-relaxed">{children}</div>
188
- ) : (
189
- <p className="mt-1.5 text-sm italic text-muted-foreground/70">
190
- {missingHint ?? 'Not captured.'}
191
- </p>
192
- )}
193
- </div>
194
- );
195
- }
196
-
197
- /** Status chip for morning / evening capture state on rail rows and headers. */
198
- export function RitualChip({
199
- icon: IconCmp,
200
- label,
201
- state,
202
- accent,
203
- }: {
204
- icon: Icon;
205
- label: string;
206
- state: 'complete' | 'partial' | 'missing';
207
- accent: string;
208
- }) {
209
- return (
210
- <span
211
- className={cn(
212
- 'inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-[11px] font-medium',
213
- state === 'missing'
214
- ? 'border-dashed border-border text-muted-foreground'
215
- : 'border-transparent',
216
- )}
217
- style={
218
- state === 'missing'
219
- ? undefined
220
- : { backgroundColor: `${accent}1a`, color: accent }
221
- }
222
- >
223
- <IconCmp size={12} weight={state === 'missing' ? 'regular' : 'fill'} />
224
- {label}
225
- {state === 'partial' ? <span className="opacity-70">· partial</span> : null}
226
- </span>
227
- );
228
- }
229
-
230
- export function StatTile({
231
- label,
232
- value,
233
- suffix,
234
- hint,
235
- icon: IconCmp,
236
- accent,
237
- }: {
238
- label: string;
239
- value: ReactNode;
240
- suffix?: string;
241
- hint?: string;
242
- icon?: Icon;
243
- accent?: string;
244
- }) {
245
- return (
246
- <div className="rounded-xl border border-border bg-card p-4">
247
- <div className="flex items-center justify-between">
248
- <span className="text-xs font-medium text-muted-foreground">{label}</span>
249
- {IconCmp ? (
250
- <IconCmp size={15} weight="bold" style={{ color: accent ?? 'hsl(var(--muted-foreground))' }} />
251
- ) : null}
252
- </div>
253
- <div className="mt-2 flex items-baseline gap-1">
254
- <span className="text-2xl font-semibold tracking-tight tabular-nums">{value}</span>
255
- {suffix ? <span className="text-sm text-muted-foreground">{suffix}</span> : null}
256
- </div>
257
- {hint ? <p className="mt-1 text-[11px] text-muted-foreground">{hint}</p> : null}
258
- </div>
259
- );
260
- }
261
-
262
- export function SectionCard({
263
- title,
264
- description,
265
- action,
266
- icon: IconCmp,
267
- children,
268
- className,
269
- }: {
270
- title: string;
271
- description?: string;
272
- action?: ReactNode;
273
- icon?: Icon;
274
- children: ReactNode;
275
- className?: string;
276
- }) {
277
- return (
278
- <section
279
- className={cn(
280
- 'rounded-2xl border border-border bg-card text-card-foreground shadow-sm',
281
- className,
282
- )}
283
- >
284
- <header className="flex items-start justify-between gap-3 px-5 pt-4 pb-3">
285
- <div className="flex items-start gap-2.5">
286
- {IconCmp ? (
287
- <span className="mt-0.5 flex h-7 w-7 items-center justify-center rounded-lg bg-muted text-muted-foreground">
288
- <IconCmp size={16} weight="bold" />
289
- </span>
290
- ) : null}
291
- <div>
292
- <h2 className="text-sm font-semibold tracking-tight">{title}</h2>
293
- {description ? (
294
- <p className="mt-0.5 text-xs text-muted-foreground">{description}</p>
295
- ) : null}
296
- </div>
297
- </div>
298
- {action}
299
- </header>
300
- <div className="px-5 pb-5">{children}</div>
301
- </section>
302
- );
303
- }
304
-
305
- export function LoadingState({ label = 'Loading…' }: { label?: string }) {
306
- return (
307
- <div className="flex items-center justify-center gap-2 py-16 text-sm text-muted-foreground">
308
- <CircleNotchIcon size={16} className="animate-spin" />
309
- {label}
310
- </div>
311
- );
312
- }
313
-
314
- export function EmptyState({
315
- icon: IconCmp,
316
- title,
317
- description,
318
- action,
319
- }: {
320
- icon: Icon;
321
- title: string;
322
- description?: string;
323
- action?: ReactNode;
324
- }) {
325
- return (
326
- <div className="flex flex-col items-center justify-center rounded-2xl border border-dashed border-border bg-card/40 px-6 py-14 text-center">
327
- <span className="flex h-11 w-11 items-center justify-center rounded-xl bg-muted text-muted-foreground">
328
- <IconCmp size={20} weight="bold" />
329
- </span>
330
- <h3 className="mt-3 text-sm font-semibold">{title}</h3>
331
- {description ? (
332
- <p className="mt-1 max-w-sm text-xs text-muted-foreground">{description}</p>
333
- ) : null}
334
- {action ? <div className="mt-4">{action}</div> : null}
335
- </div>
336
- );
337
- }
@@ -1,6 +0,0 @@
1
- import '@notis/sdk/styles.css';
2
- import './globals.css';
3
-
4
- export default function AppShell({ children }: { children: React.ReactNode }) {
5
- return children;
6
- }