@dxos/plugin-magazine 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/LICENSE +105 -0
  2. package/PLUGIN.mdl +653 -0
  3. package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs +90 -0
  4. package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs.map +7 -0
  5. package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs +97 -0
  6. package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs.map +7 -0
  7. package/dist/lib/neutral/MagazineArticle-DEUTR23F.mjs +325 -0
  8. package/dist/lib/neutral/MagazineArticle-DEUTR23F.mjs.map +7 -0
  9. package/dist/lib/neutral/MagazinePlugin.mjs +62 -0
  10. package/dist/lib/neutral/MagazinePlugin.mjs.map +7 -0
  11. package/dist/lib/neutral/MagazinePlugin.workerd.mjs +12 -0
  12. package/dist/lib/neutral/MagazinePlugin.workerd.mjs.map +7 -0
  13. package/dist/lib/neutral/PostArticle-RERHXPXC.mjs +230 -0
  14. package/dist/lib/neutral/PostArticle-RERHXPXC.mjs.map +7 -0
  15. package/dist/lib/neutral/PostCard-VDGN7BBA.mjs +60 -0
  16. package/dist/lib/neutral/PostCard-VDGN7BBA.mjs.map +7 -0
  17. package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs +121 -0
  18. package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs.map +7 -0
  19. package/dist/lib/neutral/capabilities/index.mjs +21 -0
  20. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  21. package/dist/lib/neutral/chunk-3K4AQKBZ.mjs +12 -0
  22. package/dist/lib/neutral/chunk-3K4AQKBZ.mjs.map +7 -0
  23. package/dist/lib/neutral/chunk-AFPBWBTK.mjs +591 -0
  24. package/dist/lib/neutral/chunk-AFPBWBTK.mjs.map +7 -0
  25. package/dist/lib/neutral/chunk-APQRTYT3.mjs +57 -0
  26. package/dist/lib/neutral/chunk-APQRTYT3.mjs.map +7 -0
  27. package/dist/lib/neutral/chunk-GU725ZF4.mjs +11 -0
  28. package/dist/lib/neutral/chunk-GU725ZF4.mjs.map +7 -0
  29. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
  30. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
  31. package/dist/lib/neutral/chunk-JFPR6OV4.mjs +60 -0
  32. package/dist/lib/neutral/chunk-JFPR6OV4.mjs.map +7 -0
  33. package/dist/lib/neutral/chunk-KTYLUOUG.mjs +36 -0
  34. package/dist/lib/neutral/chunk-KTYLUOUG.mjs.map +7 -0
  35. package/dist/lib/neutral/chunk-MBPX7RPI.mjs +14 -0
  36. package/dist/lib/neutral/chunk-MBPX7RPI.mjs.map +7 -0
  37. package/dist/lib/neutral/chunk-MJ2AY2CK.mjs +8 -0
  38. package/dist/lib/neutral/chunk-MJ2AY2CK.mjs.map +7 -0
  39. package/dist/lib/neutral/chunk-OYCDRSWB.mjs +624 -0
  40. package/dist/lib/neutral/chunk-OYCDRSWB.mjs.map +7 -0
  41. package/dist/lib/neutral/chunk-SAWKLGJU.mjs +28 -0
  42. package/dist/lib/neutral/chunk-SAWKLGJU.mjs.map +7 -0
  43. package/dist/lib/neutral/chunk-XCNCK47N.mjs +15 -0
  44. package/dist/lib/neutral/chunk-XCNCK47N.mjs.map +7 -0
  45. package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs +59 -0
  46. package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs.map +7 -0
  47. package/dist/lib/neutral/components/index.mjs +338 -0
  48. package/dist/lib/neutral/components/index.mjs.map +7 -0
  49. package/dist/lib/neutral/containers/index.mjs +17 -0
  50. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  51. package/dist/lib/neutral/create-object-SYZMRR4H.mjs +98 -0
  52. package/dist/lib/neutral/create-object-SYZMRR4H.mjs.map +7 -0
  53. package/dist/lib/neutral/curate-magazine-MA6OLK2X.mjs +184 -0
  54. package/dist/lib/neutral/curate-magazine-MA6OLK2X.mjs.map +7 -0
  55. package/dist/lib/neutral/fetch-article-content-CZO6D3QD.mjs +31 -0
  56. package/dist/lib/neutral/fetch-article-content-CZO6D3QD.mjs.map +7 -0
  57. package/dist/lib/neutral/index.mjs +18 -0
  58. package/dist/lib/neutral/index.mjs.map +7 -0
  59. package/dist/lib/neutral/load-post-content-XGL6VFF6.mjs +65 -0
  60. package/dist/lib/neutral/load-post-content-XGL6VFF6.mjs.map +7 -0
  61. package/dist/lib/neutral/meta.json +1 -0
  62. package/dist/lib/neutral/meta.mjs +8 -0
  63. package/dist/lib/neutral/meta.mjs.map +7 -0
  64. package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs +18 -0
  65. package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs.map +7 -0
  66. package/dist/lib/neutral/operation-handler-JE3743BU.mjs +8 -0
  67. package/dist/lib/neutral/operation-handler-JE3743BU.mjs.map +7 -0
  68. package/dist/lib/neutral/operations/index.mjs +8 -0
  69. package/dist/lib/neutral/operations/index.mjs.map +7 -0
  70. package/dist/lib/neutral/plugin.mjs +16 -0
  71. package/dist/lib/neutral/plugin.mjs.map +7 -0
  72. package/dist/lib/neutral/plugin.workerd.mjs +16 -0
  73. package/dist/lib/neutral/plugin.workerd.mjs.map +7 -0
  74. package/dist/lib/neutral/react-surface-TZESAMG2.mjs +60 -0
  75. package/dist/lib/neutral/react-surface-TZESAMG2.mjs.map +7 -0
  76. package/dist/lib/neutral/routine-templates-A2XTJOZO.mjs +52 -0
  77. package/dist/lib/neutral/routine-templates-A2XTJOZO.mjs.map +7 -0
  78. package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs +8 -0
  79. package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs.map +7 -0
  80. package/dist/lib/neutral/skills/index.mjs +46 -0
  81. package/dist/lib/neutral/skills/index.mjs.map +7 -0
  82. package/dist/lib/neutral/sync-feed-UZX2XHSQ.mjs +99 -0
  83. package/dist/lib/neutral/sync-feed-UZX2XHSQ.mjs.map +7 -0
  84. package/dist/lib/neutral/translations.mjs +81 -0
  85. package/dist/lib/neutral/translations.mjs.map +7 -0
  86. package/dist/lib/neutral/types/index.mjs +14 -0
  87. package/dist/lib/neutral/types/index.mjs.map +7 -0
  88. package/dist/types/dx.config.d.ts +28 -0
  89. package/dist/types/dx.config.d.ts.map +1 -0
  90. package/dist/types/src/MagazinePlugin.d.ts +4 -0
  91. package/dist/types/src/MagazinePlugin.d.ts.map +1 -0
  92. package/dist/types/src/MagazinePlugin.test.d.ts +2 -0
  93. package/dist/types/src/MagazinePlugin.test.d.ts.map +1 -0
  94. package/dist/types/src/MagazinePlugin.workerd.d.ts +4 -0
  95. package/dist/types/src/MagazinePlugin.workerd.d.ts.map +1 -0
  96. package/dist/types/src/atoms/atoms.test.d.ts +2 -0
  97. package/dist/types/src/atoms/atoms.test.d.ts.map +1 -0
  98. package/dist/types/src/atoms/index.d.ts +7 -0
  99. package/dist/types/src/atoms/index.d.ts.map +1 -0
  100. package/dist/types/src/atoms/magazine-posts.d.ts +16 -0
  101. package/dist/types/src/atoms/magazine-posts.d.ts.map +1 -0
  102. package/dist/types/src/atoms/post-content.d.ts +7 -0
  103. package/dist/types/src/atoms/post-content.d.ts.map +1 -0
  104. package/dist/types/src/atoms/post-curation.d.ts +16 -0
  105. package/dist/types/src/atoms/post-curation.d.ts.map +1 -0
  106. package/dist/types/src/atoms/post-display.d.ts +22 -0
  107. package/dist/types/src/atoms/post-display.d.ts.map +1 -0
  108. package/dist/types/src/atoms/post-read.d.ts +14 -0
  109. package/dist/types/src/atoms/post-read.d.ts.map +1 -0
  110. package/dist/types/src/atoms/post-tags.d.ts +16 -0
  111. package/dist/types/src/atoms/post-tags.d.ts.map +1 -0
  112. package/dist/types/src/capabilities/app-graph-builder.d.ts +5 -0
  113. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  114. package/dist/types/src/capabilities/create-object.d.ts +5 -0
  115. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  116. package/dist/types/src/capabilities/index.d.ts +10 -0
  117. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  118. package/dist/types/src/capabilities/navigation-resolver.d.ts +5 -0
  119. package/dist/types/src/capabilities/navigation-resolver.d.ts.map +1 -0
  120. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  121. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  122. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  123. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  124. package/dist/types/src/capabilities/routine-templates.d.ts +5 -0
  125. package/dist/types/src/capabilities/routine-templates.d.ts.map +1 -0
  126. package/dist/types/src/capabilities/skill-definition.d.ts +5 -0
  127. package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -0
  128. package/dist/types/src/components/PostContent/PostContent.d.ts +30 -0
  129. package/dist/types/src/components/PostContent/PostContent.d.ts.map +1 -0
  130. package/dist/types/src/components/PostContent/PostContent.test.d.ts +2 -0
  131. package/dist/types/src/components/PostContent/PostContent.test.d.ts.map +1 -0
  132. package/dist/types/src/components/PostContent/index.d.ts +2 -0
  133. package/dist/types/src/components/PostContent/index.d.ts.map +1 -0
  134. package/dist/types/src/components/PostStack/PostStack.d.ts +17 -0
  135. package/dist/types/src/components/PostStack/PostStack.d.ts.map +1 -0
  136. package/dist/types/src/components/PostStack/PostStack.stories.d.ts +10 -0
  137. package/dist/types/src/components/PostStack/PostStack.stories.d.ts.map +1 -0
  138. package/dist/types/src/components/PostStack/index.d.ts +2 -0
  139. package/dist/types/src/components/PostStack/index.d.ts.map +1 -0
  140. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts +23 -0
  141. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts.map +1 -0
  142. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.stories.d.ts +8 -0
  143. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.stories.d.ts.map +1 -0
  144. package/dist/types/src/components/SubscriptionStack/index.d.ts +2 -0
  145. package/dist/types/src/components/SubscriptionStack/index.d.ts.map +1 -0
  146. package/dist/types/src/components/index.d.ts +4 -0
  147. package/dist/types/src/components/index.d.ts.map +1 -0
  148. package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts +6 -0
  149. package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts.map +1 -0
  150. package/dist/types/src/containers/FeedArticle/FeedArticle.stories.d.ts +12 -0
  151. package/dist/types/src/containers/FeedArticle/FeedArticle.stories.d.ts.map +1 -0
  152. package/dist/types/src/containers/FeedArticle/FeedToolbar.d.ts +10 -0
  153. package/dist/types/src/containers/FeedArticle/FeedToolbar.d.ts.map +1 -0
  154. package/dist/types/src/containers/FeedArticle/index.d.ts +2 -0
  155. package/dist/types/src/containers/FeedArticle/index.d.ts.map +1 -0
  156. package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts +6 -0
  157. package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts.map +1 -0
  158. package/dist/types/src/containers/FeedProperties/index.d.ts +2 -0
  159. package/dist/types/src/containers/FeedProperties/index.d.ts.map +1 -0
  160. package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts +6 -0
  161. package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts.map +1 -0
  162. package/dist/types/src/containers/MagazineArticle/MagazineArticle.stories.d.ts +9 -0
  163. package/dist/types/src/containers/MagazineArticle/MagazineArticle.stories.d.ts.map +1 -0
  164. package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts +11 -0
  165. package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts.map +1 -0
  166. package/dist/types/src/containers/MagazineArticle/index.d.ts +2 -0
  167. package/dist/types/src/containers/MagazineArticle/index.d.ts.map +1 -0
  168. package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts +18 -0
  169. package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts.map +1 -0
  170. package/dist/types/src/containers/PostArticle/PostArticle.d.ts +6 -0
  171. package/dist/types/src/containers/PostArticle/PostArticle.d.ts.map +1 -0
  172. package/dist/types/src/containers/PostArticle/PostArticle.stories.d.ts +8 -0
  173. package/dist/types/src/containers/PostArticle/PostArticle.stories.d.ts.map +1 -0
  174. package/dist/types/src/containers/PostArticle/PostToolbar.d.ts +19 -0
  175. package/dist/types/src/containers/PostArticle/PostToolbar.d.ts.map +1 -0
  176. package/dist/types/src/containers/PostArticle/index.d.ts +2 -0
  177. package/dist/types/src/containers/PostArticle/index.d.ts.map +1 -0
  178. package/dist/types/src/containers/PostCard/PostCard.d.ts +11 -0
  179. package/dist/types/src/containers/PostCard/PostCard.d.ts.map +1 -0
  180. package/dist/types/src/containers/PostCard/index.d.ts +2 -0
  181. package/dist/types/src/containers/PostCard/index.d.ts.map +1 -0
  182. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts +5 -0
  183. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts.map +1 -0
  184. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.d.ts +8 -0
  185. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.d.ts.map +1 -0
  186. package/dist/types/src/containers/SubscriptionsArticle/index.d.ts +2 -0
  187. package/dist/types/src/containers/SubscriptionsArticle/index.d.ts.map +1 -0
  188. package/dist/types/src/containers/index.d.ts +7 -0
  189. package/dist/types/src/containers/index.d.ts.map +1 -0
  190. package/dist/types/src/index.d.ts +3 -0
  191. package/dist/types/src/index.d.ts.map +1 -0
  192. package/dist/types/src/meta.d.ts +33 -0
  193. package/dist/types/src/meta.d.ts.map +1 -0
  194. package/dist/types/src/operations/clear-magazine.d.ts +10 -0
  195. package/dist/types/src/operations/clear-magazine.d.ts.map +1 -0
  196. package/dist/types/src/operations/curate-magazine.d.ts +25 -0
  197. package/dist/types/src/operations/curate-magazine.d.ts.map +1 -0
  198. package/dist/types/src/operations/curate-magazine.skill.test.d.ts +2 -0
  199. package/dist/types/src/operations/curate-magazine.skill.test.d.ts.map +1 -0
  200. package/dist/types/src/operations/curate-magazine.test.d.ts +2 -0
  201. package/dist/types/src/operations/curate-magazine.test.d.ts.map +1 -0
  202. package/dist/types/src/operations/extraction/article.d.ts +37 -0
  203. package/dist/types/src/operations/extraction/article.d.ts.map +1 -0
  204. package/dist/types/src/operations/extraction/article.test.d.ts +2 -0
  205. package/dist/types/src/operations/extraction/article.test.d.ts.map +1 -0
  206. package/dist/types/src/operations/extraction/index.d.ts +2 -0
  207. package/dist/types/src/operations/extraction/index.d.ts.map +1 -0
  208. package/dist/types/src/operations/fetch-article-content.d.ts +5 -0
  209. package/dist/types/src/operations/fetch-article-content.d.ts.map +1 -0
  210. package/dist/types/src/operations/index.d.ts +3 -0
  211. package/dist/types/src/operations/index.d.ts.map +1 -0
  212. package/dist/types/src/operations/load-post-content.d.ts +8 -0
  213. package/dist/types/src/operations/load-post-content.d.ts.map +1 -0
  214. package/dist/types/src/operations/sources/article.d.ts +24 -0
  215. package/dist/types/src/operations/sources/article.d.ts.map +1 -0
  216. package/dist/types/src/operations/sources/cors.d.ts +12 -0
  217. package/dist/types/src/operations/sources/cors.d.ts.map +1 -0
  218. package/dist/types/src/operations/sources/feed-fetcher.d.ts +22 -0
  219. package/dist/types/src/operations/sources/feed-fetcher.d.ts.map +1 -0
  220. package/dist/types/src/operations/sources/feed-fetcher.test.d.ts +2 -0
  221. package/dist/types/src/operations/sources/feed-fetcher.test.d.ts.map +1 -0
  222. package/dist/types/src/operations/sources/http.d.ts +9 -0
  223. package/dist/types/src/operations/sources/http.d.ts.map +1 -0
  224. package/dist/types/src/operations/sources/index.d.ts +6 -0
  225. package/dist/types/src/operations/sources/index.d.ts.map +1 -0
  226. package/dist/types/src/operations/sources/rss.d.ts +4 -0
  227. package/dist/types/src/operations/sources/rss.d.ts.map +1 -0
  228. package/dist/types/src/operations/sources/rss.test.d.ts +2 -0
  229. package/dist/types/src/operations/sources/rss.test.d.ts.map +1 -0
  230. package/dist/types/src/operations/sources/standard-site.d.ts +33 -0
  231. package/dist/types/src/operations/sources/standard-site.d.ts.map +1 -0
  232. package/dist/types/src/operations/sync-feed.d.ts +5 -0
  233. package/dist/types/src/operations/sync-feed.d.ts.map +1 -0
  234. package/dist/types/src/operations/sync-feed.test.d.ts +2 -0
  235. package/dist/types/src/operations/sync-feed.test.d.ts.map +1 -0
  236. package/dist/types/src/operations/util.d.ts +25 -0
  237. package/dist/types/src/operations/util.d.ts.map +1 -0
  238. package/dist/types/src/operations/util.test.d.ts +2 -0
  239. package/dist/types/src/operations/util.test.d.ts.map +1 -0
  240. package/dist/types/src/paths.d.ts +3 -0
  241. package/dist/types/src/paths.d.ts.map +1 -0
  242. package/dist/types/src/plugin.d.ts +4 -0
  243. package/dist/types/src/plugin.d.ts.map +1 -0
  244. package/dist/types/src/plugin.workerd.d.ts +3 -0
  245. package/dist/types/src/plugin.workerd.d.ts.map +1 -0
  246. package/dist/types/src/skills/index.d.ts +2 -0
  247. package/dist/types/src/skills/index.d.ts.map +1 -0
  248. package/dist/types/src/skills/magazine-skill.d.ts +4 -0
  249. package/dist/types/src/skills/magazine-skill.d.ts.map +1 -0
  250. package/dist/types/src/stories/ArticleExtractor.stories.d.ts +267 -0
  251. package/dist/types/src/stories/ArticleExtractor.stories.d.ts.map +1 -0
  252. package/dist/types/src/stories/MagazineCurate.stories.d.ts +32 -0
  253. package/dist/types/src/stories/MagazineCurate.stories.d.ts.map +1 -0
  254. package/dist/types/src/stories/theregister-fixture.test.d.ts +2 -0
  255. package/dist/types/src/stories/theregister-fixture.test.d.ts.map +1 -0
  256. package/dist/types/src/templates/magazine-curation.d.ts +7 -0
  257. package/dist/types/src/templates/magazine-curation.d.ts.map +1 -0
  258. package/dist/types/src/testing/builder.d.ts +28 -0
  259. package/dist/types/src/testing/builder.d.ts.map +1 -0
  260. package/dist/types/src/testing/index.d.ts +2 -0
  261. package/dist/types/src/testing/index.d.ts.map +1 -0
  262. package/dist/types/src/translations.d.ts +247 -0
  263. package/dist/types/src/translations.d.ts.map +1 -0
  264. package/dist/types/src/types/CreateSubscription.d.ts +29 -0
  265. package/dist/types/src/types/CreateSubscription.d.ts.map +1 -0
  266. package/dist/types/src/types/FeedOperation.d.ts +52 -0
  267. package/dist/types/src/types/FeedOperation.d.ts.map +1 -0
  268. package/dist/types/src/types/Magazine.d.ts +87 -0
  269. package/dist/types/src/types/Magazine.d.ts.map +1 -0
  270. package/dist/types/src/types/Magazine.test.d.ts +2 -0
  271. package/dist/types/src/types/Magazine.test.d.ts.map +1 -0
  272. package/dist/types/src/types/Subscription.d.ts +144 -0
  273. package/dist/types/src/types/Subscription.d.ts.map +1 -0
  274. package/dist/types/src/types/Subscription.test.d.ts +2 -0
  275. package/dist/types/src/types/Subscription.test.d.ts.map +1 -0
  276. package/dist/types/src/types/index.d.ts +5 -0
  277. package/dist/types/src/types/index.d.ts.map +1 -0
  278. package/dist/types/src/util/date.d.ts +8 -0
  279. package/dist/types/src/util/date.d.ts.map +1 -0
  280. package/dist/types/src/util/index.d.ts +4 -0
  281. package/dist/types/src/util/index.d.ts.map +1 -0
  282. package/dist/types/src/util/post-content.d.ts +14 -0
  283. package/dist/types/src/util/post-content.d.ts.map +1 -0
  284. package/dist/types/src/util/text.d.ts +18 -0
  285. package/dist/types/src/util/text.d.ts.map +1 -0
  286. package/dist/types/tsconfig.tsbuildinfo +1 -0
  287. package/dx.config.ts +48 -0
  288. package/package.json +164 -0
  289. package/src/MagazinePlugin.test.ts +36 -0
  290. package/src/MagazinePlugin.tsx +61 -0
  291. package/src/MagazinePlugin.workerd.ts +31 -0
  292. package/src/atoms/atoms.test.ts +323 -0
  293. package/src/atoms/index.ts +10 -0
  294. package/src/atoms/magazine-posts.ts +70 -0
  295. package/src/atoms/post-content.ts +34 -0
  296. package/src/atoms/post-curation.ts +36 -0
  297. package/src/atoms/post-display.ts +59 -0
  298. package/src/atoms/post-read.ts +40 -0
  299. package/src/atoms/post-tags.ts +66 -0
  300. package/src/capabilities/app-graph-builder.ts +125 -0
  301. package/src/capabilities/create-object.ts +127 -0
  302. package/src/capabilities/index.ts +17 -0
  303. package/src/capabilities/navigation-resolver.ts +21 -0
  304. package/src/capabilities/operation-handler.ts +16 -0
  305. package/src/capabilities/react-surface.tsx +53 -0
  306. package/src/capabilities/routine-templates.ts +16 -0
  307. package/src/capabilities/skill-definition.ts +14 -0
  308. package/src/components/PostContent/PostContent.test.ts +81 -0
  309. package/src/components/PostContent/PostContent.tsx +111 -0
  310. package/src/components/PostContent/index.ts +5 -0
  311. package/src/components/PostStack/PostStack.stories.tsx +39 -0
  312. package/src/components/PostStack/PostStack.tsx +151 -0
  313. package/src/components/PostStack/index.ts +5 -0
  314. package/src/components/SubscriptionStack/SubscriptionStack.stories.tsx +52 -0
  315. package/src/components/SubscriptionStack/SubscriptionStack.tsx +161 -0
  316. package/src/components/SubscriptionStack/index.ts +5 -0
  317. package/src/components/index.ts +7 -0
  318. package/src/containers/FeedArticle/FeedArticle.stories.tsx +102 -0
  319. package/src/containers/FeedArticle/FeedArticle.tsx +68 -0
  320. package/src/containers/FeedArticle/FeedToolbar.tsx +47 -0
  321. package/src/containers/FeedArticle/index.ts +5 -0
  322. package/src/containers/FeedProperties/FeedProperties.tsx +107 -0
  323. package/src/containers/FeedProperties/index.ts +5 -0
  324. package/src/containers/MagazineArticle/MagazineArticle.stories.tsx +244 -0
  325. package/src/containers/MagazineArticle/MagazineArticle.tsx +146 -0
  326. package/src/containers/MagazineArticle/MagazineTile.tsx +88 -0
  327. package/src/containers/MagazineArticle/index.ts +5 -0
  328. package/src/containers/MagazineArticle/useToolbar.tsx +145 -0
  329. package/src/containers/PostArticle/PostArticle.stories.tsx +117 -0
  330. package/src/containers/PostArticle/PostArticle.tsx +140 -0
  331. package/src/containers/PostArticle/PostToolbar.tsx +120 -0
  332. package/src/containers/PostArticle/index.ts +5 -0
  333. package/src/containers/PostCard/PostCard.tsx +70 -0
  334. package/src/containers/PostCard/index.ts +5 -0
  335. package/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.tsx +80 -0
  336. package/src/containers/SubscriptionsArticle/SubscriptionsArticle.tsx +99 -0
  337. package/src/containers/SubscriptionsArticle/index.ts +5 -0
  338. package/src/containers/index.ts +11 -0
  339. package/src/index.ts +6 -0
  340. package/src/meta.ts +9 -0
  341. package/src/operations/clear-magazine.ts +83 -0
  342. package/src/operations/curate-magazine.skill.conversations.json +1 -0
  343. package/src/operations/curate-magazine.skill.test.ts +167 -0
  344. package/src/operations/curate-magazine.test.ts +91 -0
  345. package/src/operations/curate-magazine.ts +178 -0
  346. package/src/operations/extraction/article.test.ts +154 -0
  347. package/src/operations/extraction/article.ts +270 -0
  348. package/src/operations/extraction/index.ts +5 -0
  349. package/src/operations/fetch-article-content.ts +27 -0
  350. package/src/operations/index.ts +13 -0
  351. package/src/operations/load-post-content.ts +76 -0
  352. package/src/operations/sources/article.ts +122 -0
  353. package/src/operations/sources/cors.ts +19 -0
  354. package/src/operations/sources/feed-fetcher.test.ts +200 -0
  355. package/src/operations/sources/feed-fetcher.ts +26 -0
  356. package/src/operations/sources/http.ts +42 -0
  357. package/src/operations/sources/index.ts +9 -0
  358. package/src/operations/sources/rss.test.ts +201 -0
  359. package/src/operations/sources/rss.ts +138 -0
  360. package/src/operations/sources/standard-site.ts +381 -0
  361. package/src/operations/sources/testing/feed.xml +477 -0
  362. package/src/operations/sync-feed.test.ts +146 -0
  363. package/src/operations/sync-feed.ts +140 -0
  364. package/src/operations/util.test.ts +67 -0
  365. package/src/operations/util.ts +65 -0
  366. package/src/paths.ts +14 -0
  367. package/src/plugin.ts +11 -0
  368. package/src/plugin.workerd.ts +6 -0
  369. package/src/skills/index.ts +5 -0
  370. package/src/skills/magazine-skill.ts +45 -0
  371. package/src/stories/ArticleExtractor.stories.tsx +204 -0
  372. package/src/stories/MagazineCurate.stories.tsx +217 -0
  373. package/src/stories/fixtures/theregister-ai.xml +45 -0
  374. package/src/stories/theregister-fixture.test.ts +35 -0
  375. package/src/templates/magazine-curation.ts +47 -0
  376. package/src/testing/builder.ts +77 -0
  377. package/src/testing/index.ts +5 -0
  378. package/src/translations.ts +81 -0
  379. package/src/types/CreateSubscription.ts +61 -0
  380. package/src/types/FeedOperation.ts +134 -0
  381. package/src/types/Magazine.test.ts +69 -0
  382. package/src/types/Magazine.ts +214 -0
  383. package/src/types/Subscription.test.ts +171 -0
  384. package/src/types/Subscription.ts +366 -0
  385. package/src/types/index.ts +8 -0
  386. package/src/util/date.ts +27 -0
  387. package/src/util/index.ts +7 -0
  388. package/src/util/post-content.ts +19 -0
  389. package/src/util/text.ts +98 -0
  390. package/src/vite-env.d.ts +10 -0
@@ -0,0 +1,90 @@
1
+ import "./chunk-J5LGTIGS.mjs";
2
+
3
+ // src/containers/FeedArticle/FeedArticle.tsx
4
+ import React2, { useCallback, useState } from "react";
5
+ import { useOperationInvoker } from "@dxos/app-framework/ui";
6
+ import { Filter, Obj, Query, Ref, Scope } from "@dxos/echo";
7
+ import { useObject, useQuery } from "@dxos/react-client/echo";
8
+ import { Panel as Panel2 } from "@dxos/react-ui";
9
+ import { PostStack } from "#components";
10
+ import { meta as meta2 } from "#meta";
11
+ import { FeedOperation } from "#types";
12
+ import { Subscription } from "#types";
13
+
14
+ // src/containers/FeedArticle/FeedToolbar.tsx
15
+ import React from "react";
16
+ import { Panel } from "@dxos/react-ui";
17
+ import { Menu, MenuBuilder, useMenuBuilder } from "@dxos/react-ui-menu";
18
+ import { meta } from "#meta";
19
+ var FeedToolbar = ({ attendableId, onSync }) => {
20
+ const menuActions = useMenuBuilder(() => MenuBuilder.make().action("sync", {
21
+ label: [
22
+ "sync-feed.label",
23
+ {
24
+ ns: meta.profile.key
25
+ }
26
+ ],
27
+ icon: "ph--arrows-clockwise--regular",
28
+ iconOnly: true
29
+ }, onSync).build(), [
30
+ onSync
31
+ ]);
32
+ return /* @__PURE__ */ React.createElement(Menu.Root, {
33
+ ...menuActions,
34
+ attendableId
35
+ }, /* @__PURE__ */ React.createElement(Panel.Toolbar, {
36
+ asChild: true
37
+ }, /* @__PURE__ */ React.createElement(Menu.Toolbar, null)));
38
+ };
39
+ FeedToolbar.displayName = "FeedToolbar";
40
+
41
+ // src/containers/FeedArticle/FeedArticle.tsx
42
+ var FeedArticle = ({ role, subject, attendableId }) => {
43
+ const { invokePromise } = useOperationInvoker();
44
+ const [currentPostId, setCurrentPostId] = useState();
45
+ const [subscription] = useObject(subject);
46
+ const [postFeed] = useObject(subscription?.feed);
47
+ const db = Obj.getDatabase(subscription);
48
+ const posts = useQuery(db, postFeed ? Query.select(Filter.type(Subscription.Post)).from(Scope.feed(Obj.getURI(postFeed))) : Query.select(Filter.nothing()));
49
+ const handleAction = useCallback((action) => {
50
+ if (action.type === "current") {
51
+ setCurrentPostId(action.postId);
52
+ }
53
+ }, []);
54
+ const handleSync = useCallback(() => {
55
+ void invokePromise(FeedOperation.SyncFeed, {
56
+ feed: Ref.make(subject)
57
+ }, {
58
+ spaceId: Obj.getDatabase(subject)?.spaceId,
59
+ notify: {
60
+ error: [
61
+ "sync-feed-error.title",
62
+ {
63
+ ns: meta2.profile.key
64
+ }
65
+ ]
66
+ }
67
+ });
68
+ }, [
69
+ subject,
70
+ invokePromise
71
+ ]);
72
+ return /* @__PURE__ */ React2.createElement(Panel2.Root, {
73
+ role,
74
+ className: "dx-document"
75
+ }, /* @__PURE__ */ React2.createElement(FeedToolbar, {
76
+ attendableId,
77
+ onSync: handleSync
78
+ }), /* @__PURE__ */ React2.createElement(Panel2.Content, {
79
+ asChild: true
80
+ }, /* @__PURE__ */ React2.createElement(PostStack, {
81
+ id: subscription?.id ?? subject.id,
82
+ posts,
83
+ currentId: currentPostId,
84
+ onAction: handleAction
85
+ })));
86
+ };
87
+ export {
88
+ FeedArticle as default
89
+ };
90
+ //# sourceMappingURL=FeedArticle-PEWCFFSP.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/containers/FeedArticle/FeedArticle.tsx", "../../../src/containers/FeedArticle/FeedToolbar.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { useOperationInvoker } from '@dxos/app-framework/ui';\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { Filter, Obj, Query, Ref, Scope } from '@dxos/echo';\nimport { useObject, useQuery } from '@dxos/react-client/echo';\nimport { Panel } from '@dxos/react-ui';\n\nimport { PostStack, type PostStackAction } from '#components';\nimport { meta } from '#meta';\nimport { FeedOperation } from '#types';\nimport { Subscription } from '#types';\n\nimport { FeedToolbar } from './FeedToolbar';\n\nexport type FeedArticleProps = AppSurface.ObjectArticleProps<Subscription.Subscription>;\n\nexport const FeedArticle = ({ role, subject, attendableId }: FeedArticleProps) => {\n const { invokePromise } = useOperationInvoker();\n const [currentPostId, setCurrentPostId] = useState<string>();\n const [subscription] = useObject(subject);\n // Subscribe to the backing queue via its Ref — `.target` alone does not re-render when the\n // feed loads after navigation (same pitfall as plugin-inbox MailboxArticle).\n const [postFeed] = useObject(subscription?.feed);\n const db = Obj.getDatabase(subscription);\n const posts = useQuery(\n db,\n postFeed\n ? Query.select(Filter.type(Subscription.Post)).from(Scope.feed(Obj.getURI(postFeed)))\n : Query.select(Filter.nothing()),\n );\n\n const handleAction = useCallback((action: PostStackAction) => {\n if (action.type === 'current') {\n setCurrentPostId(action.postId);\n }\n }, []);\n\n const handleSync = useCallback(() => {\n // Failures surface as a toast via `notify`; invokePromise resolves with `{ error }`, never throws.\n void invokePromise(\n FeedOperation.SyncFeed,\n { feed: Ref.make(subject) },\n {\n spaceId: Obj.getDatabase(subject)?.spaceId,\n notify: { error: ['sync-feed-error.title', { ns: meta.profile.key }] },\n },\n );\n }, [subject, invokePromise]);\n\n return (\n <Panel.Root role={role} className='dx-document'>\n <FeedToolbar attendableId={attendableId} onSync={handleSync} />\n <Panel.Content asChild>\n <PostStack\n id={subscription?.id ?? subject.id}\n posts={posts}\n currentId={currentPostId}\n onAction={handleAction}\n />\n </Panel.Content>\n </Panel.Root>\n );\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport React from 'react';\n\nimport { Panel } from '@dxos/react-ui';\nimport { Menu, MenuBuilder, useMenuBuilder } from '@dxos/react-ui-menu';\n\nimport { meta } from '#meta';\n\nexport type FeedToolbarProps = {\n attendableId?: string;\n onSync: () => void;\n};\n\n/**\n * Reactive feed toolbar built from the menu action-graph idiom: a single Sync action. Matches the\n * magazine/post toolbars; the feed's name is surfaced by the plank chrome, not duplicated here.\n */\nexport const FeedToolbar = ({ attendableId, onSync }: FeedToolbarProps) => {\n const menuActions = useMenuBuilder(\n () =>\n MenuBuilder.make()\n .action(\n 'sync',\n {\n label: ['sync-feed.label', { ns: meta.profile.key }],\n icon: 'ph--arrows-clockwise--regular',\n iconOnly: true,\n },\n onSync,\n )\n .build(),\n [onSync],\n );\n\n return (\n <Menu.Root {...menuActions} attendableId={attendableId}>\n <Panel.Toolbar asChild>\n <Menu.Toolbar />\n </Panel.Toolbar>\n </Menu.Root>\n );\n};\n\nFeedToolbar.displayName = 'FeedToolbar';\n"],
5
+ "mappings": ";;;AAIA,OAAOA,UAASC,aAAaC,gBAAgB;AAE7C,SAASC,2BAA2B;AAEpC,SAASC,QAAQC,KAAKC,OAAOC,KAAKC,aAAa;AAC/C,SAASC,WAAWC,gBAAgB;AACpC,SAASC,SAAAA,cAAa;AAEtB,SAASC,iBAAuC;AAChD,SAASC,QAAAA,aAAY;AACrB,SAASC,qBAAqB;AAC9B,SAASC,oBAAoB;;;ACX7B,OAAOC,WAAW;AAElB,SAASC,aAAa;AACtB,SAASC,MAAMC,aAAaC,sBAAsB;AAElD,SAASC,YAAY;AAWd,IAAMC,cAAc,CAAC,EAAEC,cAAcC,OAAM,MAAoB;AACpE,QAAMC,cAAcL,eAClB,MACED,YAAYO,KAAI,EACbC,OACC,QACA;IACEC,OAAO;MAAC;MAAmB;QAAEC,IAAIR,KAAKS,QAAQC;MAAI;;IAClDC,MAAM;IACNC,UAAU;EACZ,GACAT,MAAAA,EAEDU,MAAK,GACV;IAACV;GAAO;AAGV,SACE,sBAAA,cAACN,KAAKiB,MAAI;IAAE,GAAGV;IAAaF;KAC1B,sBAAA,cAACN,MAAMmB,SAAO;IAACC,SAAAA;KACb,sBAAA,cAACnB,KAAKkB,SAAO,IAAA,CAAA,CAAA;AAIrB;AAEAd,YAAYgB,cAAc;;;ADzBnB,IAAMC,cAAc,CAAC,EAAEC,MAAMC,SAASC,aAAY,MAAoB;AAC3E,QAAM,EAAEC,cAAa,IAAKC,oBAAAA;AAC1B,QAAM,CAACC,eAAeC,gBAAAA,IAAoBC,SAAAA;AAC1C,QAAM,CAACC,YAAAA,IAAgBC,UAAUR,OAAAA;AAGjC,QAAM,CAACS,QAAAA,IAAYD,UAAUD,cAAcG,IAAAA;AAC3C,QAAMC,KAAKC,IAAIC,YAAYN,YAAAA;AAC3B,QAAMO,QAAQC,SACZJ,IACAF,WACIO,MAAMC,OAAOC,OAAOC,KAAKC,aAAaC,IAAI,CAAA,EAAGC,KAAKC,MAAMb,KAAKE,IAAIY,OAAOf,QAAAA,CAAAA,CAAAA,IACxEO,MAAMC,OAAOC,OAAOO,QAAO,CAAA,CAAA;AAGjC,QAAMC,eAAeC,YAAY,CAACC,WAAAA;AAChC,QAAIA,OAAOT,SAAS,WAAW;AAC7Bd,uBAAiBuB,OAAOC,MAAM;IAChC;EACF,GAAG,CAAA,CAAE;AAEL,QAAMC,aAAaH,YAAY,MAAA;AAE7B,SAAKzB,cACH6B,cAAcC,UACd;MAAEtB,MAAMuB,IAAIC,KAAKlC,OAAAA;IAAS,GAC1B;MACEmC,SAASvB,IAAIC,YAAYb,OAAAA,GAAUmC;MACnCC,QAAQ;QAAEC,OAAO;UAAC;UAAyB;YAAEC,IAAIC,MAAKC,QAAQC;UAAI;;MAAG;IACvE,CAAA;EAEJ,GAAG;IAACzC;IAASE;GAAc;AAE3B,SACE,gBAAAwC,OAAA,cAACC,OAAMC,MAAI;IAAC7C;IAAY8C,WAAU;KAChC,gBAAAH,OAAA,cAACI,aAAAA;IAAY7C;IAA4B8C,QAAQjB;MACjD,gBAAAY,OAAA,cAACC,OAAMK,SAAO;IAACC,SAAAA;KACb,gBAAAP,OAAA,cAACQ,WAAAA;IACCC,IAAI5C,cAAc4C,MAAMnD,QAAQmD;IAChCrC;IACAsC,WAAWhD;IACXiD,UAAU3B;;AAKpB;",
6
+ "names": ["React", "useCallback", "useState", "useOperationInvoker", "Filter", "Obj", "Query", "Ref", "Scope", "useObject", "useQuery", "Panel", "PostStack", "meta", "FeedOperation", "Subscription", "React", "Panel", "Menu", "MenuBuilder", "useMenuBuilder", "meta", "FeedToolbar", "attendableId", "onSync", "menuActions", "make", "action", "label", "ns", "profile", "key", "icon", "iconOnly", "build", "Root", "Toolbar", "asChild", "displayName", "FeedArticle", "role", "subject", "attendableId", "invokePromise", "useOperationInvoker", "currentPostId", "setCurrentPostId", "useState", "subscription", "useObject", "postFeed", "feed", "db", "Obj", "getDatabase", "posts", "useQuery", "Query", "select", "Filter", "type", "Subscription", "Post", "from", "Scope", "getURI", "nothing", "handleAction", "useCallback", "action", "postId", "handleSync", "FeedOperation", "SyncFeed", "Ref", "make", "spaceId", "notify", "error", "ns", "meta", "profile", "key", "React", "Panel", "Root", "className", "FeedToolbar", "onSync", "Content", "asChild", "PostStack", "id", "currentId", "onAction"]
7
+ }
@@ -0,0 +1,97 @@
1
+ import "./chunk-J5LGTIGS.mjs";
2
+
3
+ // src/containers/FeedProperties/FeedProperties.tsx
4
+ import React, { useCallback, useMemo, useState } from "react";
5
+ import { useOperationInvoker } from "@dxos/app-framework/ui";
6
+ import { LayoutOperation, Paths } from "@dxos/app-toolkit";
7
+ import { Operation, Trigger } from "@dxos/compute";
8
+ import { Filter, Obj, Query, Ref } from "@dxos/echo";
9
+ import { useObject, useQuery } from "@dxos/react-client/echo";
10
+ import { IconButton, Input, useTranslation } from "@dxos/react-ui";
11
+ import { Form } from "@dxos/react-ui-form";
12
+ import { meta } from "#meta";
13
+ import { FeedOperation } from "#types";
14
+ var FeedProperties = ({ subject }) => {
15
+ const { t } = useTranslation(meta.profile.key);
16
+ const { invokePromise } = useOperationInvoker();
17
+ const db = useMemo(() => Obj.getDatabase(subject), [
18
+ subject
19
+ ]);
20
+ const [pending, setPending] = useState(false);
21
+ const childTriggers = useQuery(db, Query.select(Filter.and(Filter.type(Trigger.Trigger), Filter.childOf(subject, {
22
+ transitive: false
23
+ }))).debugLabel("plugin-magazine.FeedProperties.syncTrigger"));
24
+ const syncTrigger = useMemo(() => childTriggers.find((trigger) => trigger.spec?.kind === "timer"), [
25
+ childTriggers
26
+ ]);
27
+ const [syncEnabled, setSyncEnabled] = useObject(syncTrigger, "enabled");
28
+ const handleToggleSync = useCallback(async () => {
29
+ if (!db) {
30
+ return;
31
+ }
32
+ if (syncTrigger) {
33
+ setSyncEnabled((enabled) => !enabled);
34
+ return;
35
+ }
36
+ setPending(true);
37
+ try {
38
+ const operation = await ensureSyncFeedOperation(db);
39
+ db.add(Trigger.make({
40
+ [Obj.Parent]: subject,
41
+ enabled: true,
42
+ spec: Trigger.specTimer("*/5 * * * *"),
43
+ runnable: Ref.make(operation),
44
+ input: {
45
+ feed: db.makeRef(Obj.getURI(subject))
46
+ }
47
+ }));
48
+ } finally {
49
+ setPending(false);
50
+ }
51
+ }, [
52
+ syncTrigger,
53
+ db,
54
+ subject,
55
+ setSyncEnabled
56
+ ]);
57
+ const handleViewTrigger = useCallback(() => {
58
+ if (!db) {
59
+ return;
60
+ }
61
+ void invokePromise(LayoutOperation.Open, {
62
+ subject: [
63
+ Paths.getSpacePath(db.spaceId, "settings", "org.dxos.plugin.routine.routines")
64
+ ],
65
+ workspace: Paths.getSpacePath(db.spaceId)
66
+ });
67
+ }, [
68
+ invokePromise,
69
+ db
70
+ ]);
71
+ return /* @__PURE__ */ React.createElement(Form.Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, null, t("feed-sync.label")), /* @__PURE__ */ React.createElement("div", {
72
+ className: "flex flex-row items-center"
73
+ }, /* @__PURE__ */ React.createElement(Input.Switch, {
74
+ checked: syncEnabled ?? false,
75
+ disabled: pending,
76
+ onCheckedChange: () => {
77
+ void handleToggleSync();
78
+ }
79
+ }), syncTrigger && /* @__PURE__ */ React.createElement(IconButton, {
80
+ iconOnly: true,
81
+ icon: "ph--gear--regular",
82
+ label: t("view-trigger.label"),
83
+ onClick: handleViewTrigger
84
+ }))));
85
+ };
86
+ var ensureSyncFeedOperation = async (db) => {
87
+ const existing = await db.query(Filter.and(Filter.type(Operation.PersistentOperation), Filter.key(FeedOperation.SyncFeed.meta.key))).run();
88
+ const [existingOperation] = existing;
89
+ if (existingOperation) {
90
+ return existingOperation;
91
+ }
92
+ return db.add(Operation.serialize(FeedOperation.SyncFeed));
93
+ };
94
+ export {
95
+ FeedProperties as default
96
+ };
97
+ //# sourceMappingURL=FeedProperties-EIO7IZOA.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/containers/FeedProperties/FeedProperties.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { useOperationInvoker } from '@dxos/app-framework/ui';\nimport { LayoutOperation, Paths } from '@dxos/app-toolkit';\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { Operation, Trigger } from '@dxos/compute';\nimport { Filter, Obj, Query, Ref } from '@dxos/echo';\nimport { useObject, useQuery } from '@dxos/react-client/echo';\nimport { IconButton, Input, useTranslation } from '@dxos/react-ui';\nimport { Form } from '@dxos/react-ui-form';\n\nimport { meta } from '#meta';\nimport { FeedOperation, Subscription } from '#types';\n\nexport type FeedPropertiesProps = AppSurface.ObjectPropertiesProps<Subscription.Subscription>;\n\nexport const FeedProperties = ({ subject }: FeedPropertiesProps) => {\n const { t } = useTranslation(meta.profile.key);\n const { invokePromise } = useOperationInvoker();\n const db = useMemo(() => Obj.getDatabase(subject), [subject]);\n const [pending, setPending] = useState(false);\n\n const childTriggers = useQuery(\n db,\n Query.select(Filter.and(Filter.type(Trigger.Trigger), Filter.childOf(subject, { transitive: false }))).debugLabel(\n 'plugin-magazine.FeedProperties.syncTrigger',\n ),\n );\n\n const syncTrigger = useMemo(() => childTriggers.find((trigger) => trigger.spec?.kind === 'timer'), [childTriggers]);\n\n const [syncEnabled, setSyncEnabled] = useObject(syncTrigger, 'enabled');\n\n const handleToggleSync = useCallback(async () => {\n if (!db) {\n return;\n }\n\n if (syncTrigger) {\n setSyncEnabled((enabled) => !enabled);\n return;\n }\n\n setPending(true);\n try {\n const operation = await ensureSyncFeedOperation(db);\n db.add(\n Trigger.make({\n [Obj.Parent]: subject,\n enabled: true,\n spec: Trigger.specTimer('*/5 * * * *'),\n runnable: Ref.make(operation),\n input: { feed: db.makeRef(Obj.getURI(subject)) },\n }),\n );\n } finally {\n setPending(false);\n }\n }, [syncTrigger, db, subject, setSyncEnabled]);\n\n const handleViewTrigger = useCallback(() => {\n if (!db) {\n return;\n }\n\n void invokePromise(LayoutOperation.Open, {\n subject: [Paths.getSpacePath(db.spaceId, 'settings', 'org.dxos.plugin.routine.routines')],\n workspace: Paths.getSpacePath(db.spaceId),\n });\n }, [invokePromise, db]);\n\n return (\n <Form.Section>\n <Input.Root>\n <Input.Label>{t('feed-sync.label')}</Input.Label>\n <div className='flex flex-row items-center'>\n <Input.Switch\n checked={syncEnabled ?? false}\n disabled={pending}\n onCheckedChange={() => {\n void handleToggleSync();\n }}\n />\n {syncTrigger && (\n <IconButton iconOnly icon='ph--gear--regular' label={t('view-trigger.label')} onClick={handleViewTrigger} />\n )}\n </div>\n </Input.Root>\n </Form.Section>\n );\n};\n\nconst ensureSyncFeedOperation = async (db: NonNullable<ReturnType<typeof Obj.getDatabase>>) => {\n const existing = await db\n .query(Filter.and(Filter.type(Operation.PersistentOperation), Filter.key(FeedOperation.SyncFeed.meta.key)))\n .run();\n const [existingOperation] = existing;\n if (existingOperation) {\n return existingOperation;\n }\n\n return db.add(Operation.serialize(FeedOperation.SyncFeed));\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "useCallback", "useMemo", "useState", "useOperationInvoker", "LayoutOperation", "Paths", "Operation", "Trigger", "Filter", "Obj", "Query", "Ref", "useObject", "useQuery", "IconButton", "Input", "useTranslation", "Form", "meta", "FeedOperation", "FeedProperties", "subject", "t", "profile", "key", "invokePromise", "db", "getDatabase", "pending", "setPending", "childTriggers", "select", "and", "type", "childOf", "transitive", "debugLabel", "syncTrigger", "find", "trigger", "spec", "kind", "syncEnabled", "setSyncEnabled", "handleToggleSync", "enabled", "operation", "ensureSyncFeedOperation", "add", "make", "Parent", "specTimer", "runnable", "input", "feed", "makeRef", "getURI", "handleViewTrigger", "Open", "getSpacePath", "spaceId", "workspace", "Section", "Root", "Label", "div", "className", "Switch", "checked", "disabled", "onCheckedChange", "iconOnly", "icon", "label", "onClick", "existing", "query", "PersistentOperation", "SyncFeed", "run", "existingOperation", "serialize"]
7
+ }
@@ -0,0 +1,325 @@
1
+ import {
2
+ formatDate
3
+ } from "./chunk-SAWKLGJU.mjs";
4
+ import "./chunk-J5LGTIGS.mjs";
5
+
6
+ // src/containers/MagazineArticle/MagazineArticle.tsx
7
+ import { useAtomValue } from "@effect-atom/atom-react";
8
+ import React2, { useCallback as useCallback3, useEffect, useMemo as useMemo2 } from "react";
9
+ import { useOperationInvoker as useOperationInvoker2 } from "@dxos/app-framework/ui";
10
+ import { LayoutOperation, Paths } from "@dxos/app-toolkit";
11
+ import { useShowItem } from "@dxos/app-toolkit/ui";
12
+ import { Obj as Obj2, Ref as Ref2 } from "@dxos/echo";
13
+ import { log } from "@dxos/log";
14
+ import { useObject } from "@dxos/react-client/echo";
15
+ import { Panel, useTranslation } from "@dxos/react-ui";
16
+ import { linkedSegment, useSelection } from "@dxos/react-ui-attention";
17
+ import { Masonry } from "@dxos/react-ui-masonry";
18
+ import { Menu } from "@dxos/react-ui-menu";
19
+ import { useVisibleMagazinePosts } from "#atoms";
20
+ import { meta as meta2 } from "#meta";
21
+ import { FeedOperation as FeedOperation2, Subscription } from "#types";
22
+
23
+ // src/containers/MagazineArticle/MagazineTile.tsx
24
+ import React, { useCallback } from "react";
25
+ import { Card, Focus, SystemIconButton } from "@dxos/react-ui";
26
+ import { mx } from "@dxos/ui-theme";
27
+ import { useMagazinePostData } from "#atoms";
28
+ var MagazineTile = ({ post, magazine, current, onToggleStar, onOpen }) => {
29
+ const { post: snapshot, feedName, read, starred, snippet, imageUrl } = useMagazinePostData(post, magazine);
30
+ const handleCurrentChange = useCallback(() => {
31
+ onOpen?.(post);
32
+ }, [
33
+ onOpen,
34
+ post
35
+ ]);
36
+ const handleToggleStar = useCallback((event) => {
37
+ event.stopPropagation();
38
+ onToggleStar?.(post, starred);
39
+ }, [
40
+ onToggleStar,
41
+ post,
42
+ starred
43
+ ]);
44
+ return /* @__PURE__ */ React.createElement(Focus.Item, {
45
+ asChild: true,
46
+ current,
47
+ onCurrentChange: handleCurrentChange
48
+ }, /* @__PURE__ */ React.createElement(Card.Root, {
49
+ fullWidth: true,
50
+ classNames: mx("dx-hover dx-current cursor-pointer transition-opacity", read && !current && "opacity-60")
51
+ }, imageUrl && /* @__PURE__ */ React.createElement(Card.Poster, {
52
+ alt: snapshot.title ?? "Article",
53
+ image: imageUrl,
54
+ fit: "cover",
55
+ classNames: "rounded-t-xs"
56
+ }), /* @__PURE__ */ React.createElement(Card.Header, null, /* @__PURE__ */ React.createElement(Card.Block, null, /* @__PURE__ */ React.createElement(SystemIconButton.Star, {
57
+ variant: "ghost",
58
+ iconOnly: true,
59
+ square: true,
60
+ size: 4,
61
+ active: starred,
62
+ onClick: handleToggleStar
63
+ })), snapshot.title ? /* @__PURE__ */ React.createElement(Card.Title, {
64
+ classNames: "line-clamp-2"
65
+ }, snapshot.title) : /* @__PURE__ */ React.createElement("div", null), /* @__PURE__ */ React.createElement(Card.Block, {
66
+ end: true
67
+ })), /* @__PURE__ */ React.createElement(Card.Body, null, snippet && /* @__PURE__ */ React.createElement(Card.Row, null, /* @__PURE__ */ React.createElement(Card.Text, {
68
+ variant: "description",
69
+ classNames: "line-clamp-3"
70
+ }, snippet)), /* @__PURE__ */ React.createElement(Card.Row, null, /* @__PURE__ */ React.createElement("div", {
71
+ className: "grid grid-cols-[minmax(0,1fr)_auto] items-center gap-2 py-1.5 text-sm text-description overflow-hidden"
72
+ }, /* @__PURE__ */ React.createElement("span", {
73
+ className: "truncate"
74
+ }, feedName ?? ""), /* @__PURE__ */ React.createElement("span", {
75
+ className: "text-end shrink-0"
76
+ }, formatPublished(snapshot) ?? ""))))));
77
+ };
78
+ var formatPublished = (post) => post.published ? formatDate(post.published) : void 0;
79
+
80
+ // src/containers/MagazineArticle/useToolbar.tsx
81
+ import { Atom, RegistryContext, useAtomSet } from "@effect-atom/atom-react";
82
+ import * as Effect from "effect/Effect";
83
+ import { useCallback as useCallback2, useContext, useMemo } from "react";
84
+ import { useOperationInvoker } from "@dxos/app-framework/ui";
85
+ import { Obj, Ref } from "@dxos/echo";
86
+ import { EffectEx } from "@dxos/effect";
87
+ import { MenuBuilder, useMenuBuilder } from "@dxos/react-ui-menu";
88
+ import { meta } from "#meta";
89
+ import { FeedOperation } from "#types";
90
+ var useToolbar = ({ magazine }) => {
91
+ const invoker = useOperationInvoker();
92
+ const registry = useContext(RegistryContext);
93
+ const db = Obj.getDatabase(magazine);
94
+ const viewAtom = useMemo(() => Atom.make("default"), []);
95
+ const busyAtom = useMemo(() => Atom.make(false), []);
96
+ const setView = useAtomSet(viewAtom);
97
+ const runExclusive = useCallback2((effect) => {
98
+ if (registry.get(busyAtom)) {
99
+ return;
100
+ }
101
+ registry.set(busyAtom, true);
102
+ void EffectEx.runAndForwardErrors(effect.pipe(Effect.ensuring(Effect.sync(() => registry.set(busyAtom, false)))));
103
+ }, [
104
+ registry,
105
+ busyAtom
106
+ ]);
107
+ const handleCurate = useCallback2(() => runExclusive(invoker.invoke(FeedOperation.CurateMagazine, {
108
+ magazine: Ref.make(magazine)
109
+ }, {
110
+ spaceId: db?.spaceId,
111
+ notify: {
112
+ error: [
113
+ "curate-error.message",
114
+ {
115
+ ns: meta.profile.key
116
+ }
117
+ ]
118
+ }
119
+ })), [
120
+ runExclusive,
121
+ invoker,
122
+ magazine,
123
+ db
124
+ ]);
125
+ const handleClear = useCallback2(() => runExclusive(invoker.invoke(FeedOperation.ClearMagazine, {
126
+ magazine: Ref.make(magazine)
127
+ }, {
128
+ spaceId: db?.spaceId,
129
+ notify: {
130
+ error: [
131
+ "clear-error.message",
132
+ {
133
+ ns: meta.profile.key
134
+ }
135
+ ]
136
+ }
137
+ })), [
138
+ runExclusive,
139
+ invoker,
140
+ magazine,
141
+ db
142
+ ]);
143
+ const menu = useMenuBuilder((get) => {
144
+ const view = get(viewAtom);
145
+ const busy = get(busyAtom);
146
+ const hasFeeds = (get(Obj.atomProperty(magazine, "feeds")) ?? []).length > 0;
147
+ const hasRoutine = Boolean(get(Obj.atomProperty(magazine, "instructions")));
148
+ const curateLabel = !hasFeeds ? "no-feeds.label" : busy ? "refreshing-magazine.label" : "curate.label";
149
+ return MenuBuilder.make().group("view", {
150
+ label: [
151
+ "view-filter.label",
152
+ {
153
+ ns: meta.profile.key
154
+ }
155
+ ],
156
+ variant: "toggleGroup",
157
+ selectCardinality: "single",
158
+ value: view
159
+ }, (group) => {
160
+ group.action("starred", {
161
+ label: [
162
+ "only-starred.label",
163
+ {
164
+ ns: meta.profile.key
165
+ }
166
+ ],
167
+ icon: view === "starred" ? "ph--star--fill" : "ph--star--regular"
168
+ }, () => setView(view === "starred" ? "default" : "starred"));
169
+ group.action("archived", {
170
+ label: [
171
+ "show-archived.label",
172
+ {
173
+ ns: meta.profile.key
174
+ }
175
+ ],
176
+ icon: "ph--archive--regular"
177
+ }, () => setView(view === "archived" ? "default" : "archived"));
178
+ }).separator("gap").action("clear", {
179
+ label: [
180
+ "clear-magazine.label",
181
+ {
182
+ ns: meta.profile.key
183
+ }
184
+ ],
185
+ icon: "ph--broom--regular",
186
+ iconOnly: true,
187
+ disabled: busy
188
+ }, handleClear).action("curate", {
189
+ label: [
190
+ curateLabel,
191
+ {
192
+ ns: meta.profile.key
193
+ }
194
+ ],
195
+ icon: busy ? "ph--circle-notch--regular" : "ph--sparkle--regular",
196
+ iconClassNames: busy ? "animate-spin" : void 0,
197
+ iconOnly: true,
198
+ disabled: busy || !hasFeeds || !hasRoutine
199
+ }, handleCurate).build();
200
+ }, [
201
+ magazine,
202
+ viewAtom,
203
+ busyAtom,
204
+ setView,
205
+ handleClear,
206
+ handleCurate
207
+ ]);
208
+ return {
209
+ menu,
210
+ viewAtom
211
+ };
212
+ };
213
+
214
+ // src/containers/MagazineArticle/MagazineArticle.tsx
215
+ var __dxlog_file = "/Users/jdw/Code/dxos/packages/plugins/plugin-magazine/src/containers/MagazineArticle/MagazineArticle.tsx";
216
+ var MagazineArticle = ({ role, subject, attendableId }) => {
217
+ const { t } = useTranslation(meta2.profile.key);
218
+ const invoker = useOperationInvoker2();
219
+ const [magazine] = useObject(subject);
220
+ const { menu, viewAtom } = useToolbar({
221
+ magazine: subject
222
+ });
223
+ const view = useAtomValue(viewAtom);
224
+ const showItem = useShowItem();
225
+ const id = attendableId ?? Obj2.getURI(magazine);
226
+ const currentId = useSelection(id, "single");
227
+ const db = Obj2.getDatabase(magazine);
228
+ const posts = useVisibleMagazinePosts(subject, view);
229
+ const handleToggleStar = useCallback3(async (post, starred) => {
230
+ const subscription = await post.source?.load();
231
+ if (db && subscription) {
232
+ void Subscription.setTag(subscription, post.id, db, "starred", !starred);
233
+ }
234
+ }, [
235
+ db
236
+ ]);
237
+ const handleOpen = useCallback3(async (post) => {
238
+ const subscription = await post.source?.load();
239
+ if (subscription && !Subscription.getReadAt(subscription, post.id)) {
240
+ void Subscription.setReadAt(subscription, post.id, (/* @__PURE__ */ new Date()).toISOString());
241
+ }
242
+ if (post.link) {
243
+ void invoker.invokePromise(FeedOperation2.LoadPostContent, {
244
+ post: Ref2.make(post)
245
+ }).catch((err) => log.catch(err, {
246
+ postLink: post.link
247
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 52, S: void 0 }));
248
+ }
249
+ void showItem({
250
+ contextId: id,
251
+ selectionId: post.id,
252
+ companion: linkedSegment("post"),
253
+ path: Paths.getObjectPathFromObject(subject)
254
+ });
255
+ }, [
256
+ id,
257
+ showItem,
258
+ invoker,
259
+ subject
260
+ ]);
261
+ const noPosts = posts.length === 0;
262
+ useEffect(() => {
263
+ if (noPosts) {
264
+ void invoker.invokePromise(LayoutOperation.UpdateCompanion, {
265
+ subject: linkedSegment("settings")
266
+ });
267
+ }
268
+ }, [
269
+ noPosts,
270
+ invoker
271
+ ]);
272
+ const tileItems = useMemo2(() => posts.map((post) => ({
273
+ id: post.id,
274
+ post,
275
+ magazine: subject,
276
+ current: currentId === post.id,
277
+ onToggleStar: handleToggleStar,
278
+ onOpen: handleOpen
279
+ })), [
280
+ posts,
281
+ currentId,
282
+ handleOpen,
283
+ handleToggleStar
284
+ ]);
285
+ return /* @__PURE__ */ React2.createElement(Panel.Root, {
286
+ role
287
+ }, /* @__PURE__ */ React2.createElement(Menu.Root, {
288
+ ...menu,
289
+ attendableId
290
+ }, /* @__PURE__ */ React2.createElement(Panel.Toolbar, {
291
+ asChild: true
292
+ }, /* @__PURE__ */ React2.createElement(Menu.Toolbar, null))), /* @__PURE__ */ React2.createElement(Panel.Content, null, noPosts ? (
293
+ // TODO(burdon): Factor out common EmptyState component; of push into Masonry, List, etc.
294
+ /* @__PURE__ */ React2.createElement("div", {
295
+ className: "h-full flex items-center justify-center text-subdued text-sm"
296
+ }, t("empty-magazine.message"))
297
+ ) : /* @__PURE__ */ React2.createElement(Masonry.Root, {
298
+ Tile: TileAdapter,
299
+ minColumnWidth: 20,
300
+ maxColumnWidth: 25
301
+ }, /* @__PURE__ */ React2.createElement(Masonry.Content, {
302
+ thin: true,
303
+ centered: true,
304
+ padding: true
305
+ }, /* @__PURE__ */ React2.createElement(Masonry.Viewport, {
306
+ classNames: "py-2",
307
+ items: tileItems
308
+ })))));
309
+ };
310
+ var TileAdapter = ({ data }) => {
311
+ if (!data?.post) {
312
+ return null;
313
+ }
314
+ return /* @__PURE__ */ React2.createElement(MagazineTile, {
315
+ post: data.post,
316
+ magazine: data.magazine,
317
+ current: data.current,
318
+ onOpen: data.onOpen,
319
+ onToggleStar: data.onToggleStar
320
+ });
321
+ };
322
+ export {
323
+ MagazineArticle as default
324
+ };
325
+ //# sourceMappingURL=MagazineArticle-DEUTR23F.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/containers/MagazineArticle/MagazineArticle.tsx", "../../../src/containers/MagazineArticle/MagazineTile.tsx", "../../../src/containers/MagazineArticle/useToolbar.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport { useAtomValue } from '@effect-atom/atom-react';\nimport React, { useCallback, useEffect, useMemo } from 'react';\n\nimport { useOperationInvoker } from '@dxos/app-framework/ui';\nimport { LayoutOperation, Paths } from '@dxos/app-toolkit';\nimport { type AppSurface, useShowItem } from '@dxos/app-toolkit/ui';\nimport { Obj, Ref } from '@dxos/echo';\nimport { log } from '@dxos/log';\nimport { useObject } from '@dxos/react-client/echo';\nimport { Panel, useTranslation } from '@dxos/react-ui';\nimport { linkedSegment, useSelection } from '@dxos/react-ui-attention';\nimport { Masonry } from '@dxos/react-ui-masonry';\nimport { Menu } from '@dxos/react-ui-menu';\n\nimport { useVisibleMagazinePosts } from '#atoms';\nimport { meta } from '#meta';\nimport { FeedOperation, Magazine, Subscription } from '#types';\n\nimport { MagazineTile } from './MagazineTile';\nimport { useToolbar } from './useToolbar';\n\nexport type MagazineArticleProps = AppSurface.ObjectArticleProps<Magazine.Magazine>;\n\nexport const MagazineArticle = ({ role, subject, attendableId }: MagazineArticleProps) => {\n const { t } = useTranslation(meta.profile.key);\n const invoker = useOperationInvoker();\n const [magazine] = useObject(subject);\n\n // The toolbar owns the view-filter atom and the curate/clear handlers; the article reads `view` to\n // filter the visible posts.\n const { menu, viewAtom } = useToolbar({ magazine: subject });\n const view = useAtomValue(viewAtom);\n\n const showItem = useShowItem();\n const id = attendableId ?? Obj.getURI(magazine);\n const currentId = useSelection(id, 'single');\n const db = Obj.getDatabase(magazine);\n const posts = useVisibleMagazinePosts(subject, view);\n\n const handleToggleStar = useCallback(\n async (post: Subscription.Post, starred: boolean) => {\n const subscription = await post.source?.load();\n if (db && subscription) {\n void Subscription.setTag(subscription, post.id, db, 'starred', !starred);\n }\n },\n [db],\n );\n\n const handleOpen = useCallback(\n async (post: Subscription.Post) => {\n const subscription = await post.source?.load();\n if (subscription && !Subscription.getReadAt(subscription, post.id)) {\n void Subscription.setReadAt(subscription, post.id, new Date().toISOString());\n }\n if (post.link) {\n void invoker\n .invokePromise(FeedOperation.LoadPostContent, { post: Ref.make(post) })\n .catch((err) => log.catch(err, { postLink: post.link }));\n }\n void showItem({\n contextId: id,\n selectionId: post.id,\n companion: linkedSegment('post'),\n path: Paths.getObjectPathFromObject(subject),\n });\n },\n [id, showItem, invoker, subject],\n );\n\n const noPosts = posts.length === 0;\n useEffect(() => {\n if (noPosts) {\n void invoker.invokePromise(LayoutOperation.UpdateCompanion, {\n subject: linkedSegment('settings'),\n });\n }\n }, [noPosts, invoker]);\n\n const tileItems = useMemo<TileData[]>(\n () =>\n posts.map((post) => ({\n id: post.id,\n post,\n magazine: subject,\n current: currentId === post.id,\n onToggleStar: handleToggleStar,\n onOpen: handleOpen,\n })),\n [posts, currentId, handleOpen, handleToggleStar],\n );\n\n return (\n <Panel.Root role={role}>\n <Menu.Root {...menu} attendableId={attendableId}>\n <Panel.Toolbar asChild>\n <Menu.Toolbar />\n </Panel.Toolbar>\n </Menu.Root>\n <Panel.Content>\n {noPosts ? (\n // TODO(burdon): Factor out common EmptyState component; of push into Masonry, List, etc.\n <div className='h-full flex items-center justify-center text-subdued text-sm'>\n {t('empty-magazine.message')}\n </div>\n ) : (\n <Masonry.Root Tile={TileAdapter} minColumnWidth={20} maxColumnWidth={25}>\n <Masonry.Content thin centered padding>\n {/* TODO(burdon): Move items into Root. */}\n <Masonry.Viewport classNames='py-2' items={tileItems} />\n </Masonry.Content>\n </Masonry.Root>\n )}\n </Panel.Content>\n </Panel.Root>\n );\n};\n\ntype TileData = {\n id: string;\n post: Subscription.Post;\n magazine: Magazine.Magazine;\n current: boolean;\n onToggleStar?: (post: Subscription.Post, starred: boolean) => void;\n onOpen?: (post: Subscription.Post) => void;\n};\n\nconst TileAdapter = ({ data }: { data: TileData | undefined; index: number }) => {\n if (!data?.post) {\n return null;\n }\n\n return (\n <MagazineTile\n post={data.post}\n magazine={data.magazine}\n current={data.current}\n onOpen={data.onOpen}\n onToggleStar={data.onToggleStar}\n />\n );\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { type MouseEvent, useCallback } from 'react';\n\nimport { Obj } from '@dxos/echo';\nimport { Card, Focus, SystemIconButton } from '@dxos/react-ui';\nimport { mx } from '@dxos/ui-theme';\n\nimport { useMagazinePostData } from '#atoms';\nimport { type Magazine, type Subscription } from '#types';\n\nimport { formatDate } from '../../util/date';\n\nexport type MagazineTileProps = {\n post: Subscription.Post;\n magazine: Magazine.Magazine;\n current?: boolean;\n onOpen?: (post: Subscription.Post) => void;\n onToggleStar?: (post: Subscription.Post, starred: boolean) => void;\n};\n\nexport const MagazineTile = ({ post, magazine, current, onToggleStar, onOpen }: MagazineTileProps) => {\n // All per-Post derivation (snapshot, read, starred, snippet, image, feed name) happens in\n // atom-land; this tile re-renders only when THIS post's slice changes, not when a sibling does.\n const { post: snapshot, feedName, read, starred, snippet, imageUrl } = useMagazinePostData(post, magazine);\n\n // `Focus.Item` calls `onCurrentChange` on click and on Enter.\n const handleCurrentChange = useCallback(() => {\n onOpen?.(post);\n }, [onOpen, post]);\n\n const handleToggleStar = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n // Prevent Focus.Item's onClick from firing the open action — clicks on the star toggle should not open the post.\n event.stopPropagation();\n onToggleStar?.(post, starred);\n },\n [onToggleStar, post, starred],\n );\n\n return (\n <Focus.Item asChild current={current} onCurrentChange={handleCurrentChange}>\n <Card.Root\n fullWidth\n classNames={mx('dx-hover dx-current cursor-pointer transition-opacity', read && !current && 'opacity-60')}\n >\n {imageUrl && (\n <Card.Poster alt={snapshot.title ?? 'Article'} image={imageUrl} fit='cover' classNames='rounded-t-xs' />\n )}\n <Card.Header>\n <Card.Block>\n <SystemIconButton.Star\n variant='ghost'\n iconOnly\n square\n size={4}\n active={starred}\n onClick={handleToggleStar}\n />\n </Card.Block>\n {snapshot.title ? <Card.Title classNames='line-clamp-2'>{snapshot.title}</Card.Title> : <div />}\n <Card.Block end />\n </Card.Header>\n <Card.Body>\n {snippet && (\n <Card.Row>\n <Card.Text variant='description' classNames='line-clamp-3'>\n {snippet}\n </Card.Text>\n </Card.Row>\n )}\n <Card.Row>\n <div className='grid grid-cols-[minmax(0,1fr)_auto] items-center gap-2 py-1.5 text-sm text-description overflow-hidden'>\n <span className='truncate'>{feedName ?? ''}</span>\n <span className='text-end shrink-0'>{formatPublished(snapshot) ?? ''}</span>\n </div>\n </Card.Row>\n </Card.Body>\n </Card.Root>\n </Focus.Item>\n );\n};\n\n/** Convenience: format a Post's published date the way the magazine view shows it. */\nconst formatPublished = (post: Obj.Snapshot<Subscription.Post>): string | undefined =>\n post.published ? formatDate(post.published) : undefined;\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { Atom, RegistryContext, useAtomSet } from '@effect-atom/atom-react';\nimport * as Effect from 'effect/Effect';\nimport { useCallback, useContext, useMemo } from 'react';\n\nimport { useOperationInvoker } from '@dxos/app-framework/ui';\nimport { Obj, Ref } from '@dxos/echo';\nimport { EffectEx } from '@dxos/effect';\nimport { MenuBuilder, useMenuBuilder } from '@dxos/react-ui-menu';\n\nimport { type MagazineView } from '#atoms';\nimport { meta } from '#meta';\nimport { FeedOperation, type Magazine } from '#types';\n\nexport type UseToolbarProps = {\n magazine: Magazine.Magazine;\n};\n\n/**\n * Owns the magazine toolbar: the view-filter and curate-busy atoms, the Curate/Clear operation\n * handlers, and the reactive menu action graph. The action graph reads its state — view filter,\n * curate-busy flag, and whether the magazine has feeds — via `get` inside the builder, so it\n * subscribes to those atoms and rebuilds whenever they change. Returns the menu props (spread into\n * `Menu.Root`) plus `viewAtom`, which the article also reads to filter the visible posts.\n */\nexport const useToolbar = ({ magazine }: UseToolbarProps) => {\n const invoker = useOperationInvoker();\n const registry = useContext(RegistryContext);\n const db = Obj.getDatabase(magazine);\n const viewAtom = useMemo(() => Atom.make<MagazineView>('default'), []);\n const busyAtom = useMemo(() => Atom.make(false), []);\n const setView = useAtomSet(viewAtom);\n\n // Curate and Clear share the busy guard: ignore re-entry while a run is in flight, flip the busy flag\n // for the duration, then run the supplied invocation (failures surface via its own notify config).\n const runExclusive = useCallback(\n <A, E>(effect: Effect.Effect<A, E>) => {\n if (registry.get(busyAtom)) {\n return;\n }\n registry.set(busyAtom, true);\n void EffectEx.runAndForwardErrors(effect.pipe(Effect.ensuring(Effect.sync(() => registry.set(busyAtom, false)))));\n },\n [registry, busyAtom],\n );\n\n const handleCurate = useCallback(\n () =>\n runExclusive(\n invoker.invoke(\n FeedOperation.CurateMagazine,\n { magazine: Ref.make(magazine) },\n { spaceId: db?.spaceId, notify: { error: ['curate-error.message', { ns: meta.profile.key }] } },\n ),\n ),\n [runExclusive, invoker, magazine, db],\n );\n\n const handleClear = useCallback(\n () =>\n runExclusive(\n invoker.invoke(\n FeedOperation.ClearMagazine,\n { magazine: Ref.make(magazine) },\n { spaceId: db?.spaceId, notify: { error: ['clear-error.message', { ns: meta.profile.key }] } },\n ),\n ),\n [runExclusive, invoker, magazine, db],\n );\n\n const menu = useMenuBuilder(\n (get) => {\n const view = get(viewAtom);\n const busy = get(busyAtom);\n const hasFeeds = (get(Obj.atomProperty(magazine, 'feeds')) ?? []).length > 0;\n // Curate runs the magazine's Routine, so it is unavailable until that Routine exists.\n const hasRoutine = Boolean(get(Obj.atomProperty(magazine, 'instructions')));\n // Curate is disabled while busy or until there is at least one feed; the tooltip explains why.\n const curateLabel = !hasFeeds ? 'no-feeds.label' : busy ? 'refreshing-magazine.label' : 'curate.label';\n\n return (\n MenuBuilder.make()\n // Single-select filter: `value` is the active child id; `'default'` matches neither, so both\n // toggles read as off. Re-clicking the active toggle returns to `'default'`.\n .group(\n 'view',\n {\n label: ['view-filter.label', { ns: meta.profile.key }],\n variant: 'toggleGroup',\n selectCardinality: 'single',\n value: view,\n },\n (group) => {\n group.action(\n 'starred',\n {\n label: ['only-starred.label', { ns: meta.profile.key }],\n icon: view === 'starred' ? 'ph--star--fill' : 'ph--star--regular',\n },\n () => setView(view === 'starred' ? 'default' : 'starred'),\n );\n group.action(\n 'archived',\n {\n label: ['show-archived.label', { ns: meta.profile.key }],\n icon: 'ph--archive--regular',\n },\n () => setView(view === 'archived' ? 'default' : 'archived'),\n );\n },\n )\n // `gap` is a flexible spacer that pushes Clear + Curate to the trailing edge.\n .separator('gap')\n .action(\n 'clear',\n {\n label: ['clear-magazine.label', { ns: meta.profile.key }],\n icon: 'ph--broom--regular',\n iconOnly: true,\n disabled: busy,\n },\n handleClear,\n )\n .action(\n 'curate',\n {\n label: [curateLabel, { ns: meta.profile.key }],\n icon: busy ? 'ph--circle-notch--regular' : 'ph--sparkle--regular',\n iconClassNames: busy ? 'animate-spin' : undefined,\n iconOnly: true,\n disabled: busy || !hasFeeds || !hasRoutine,\n },\n handleCurate,\n )\n .build()\n );\n },\n [magazine, viewAtom, busyAtom, setView, handleClear, handleCurate],\n );\n\n return { menu, viewAtom };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["useAtomValue", "React", "useCallback", "useEffect", "useMemo", "useOperationInvoker", "LayoutOperation", "Paths", "useShowItem", "Obj", "Ref", "log", "useObject", "Panel", "useTranslation", "linkedSegment", "useSelection", "Masonry", "Menu", "useVisibleMagazinePosts", "meta", "FeedOperation", "Subscription", "React", "useCallback", "Card", "Focus", "SystemIconButton", "mx", "useMagazinePostData", "MagazineTile", "post", "magazine", "current", "onToggleStar", "onOpen", "snapshot", "feedName", "read", "starred", "snippet", "imageUrl", "useMagazinePostData", "handleCurrentChange", "useCallback", "handleToggleStar", "event", "stopPropagation", "Focus", "Item", "asChild", "onCurrentChange", "Card", "Root", "fullWidth", "classNames", "mx", "Poster", "alt", "title", "image", "fit", "Header", "Block", "SystemIconButton", "Star", "variant", "iconOnly", "square", "size", "active", "onClick", "Title", "div", "end", "Body", "Row", "Text", "className", "span", "formatPublished", "published", "formatDate", "undefined", "Atom", "RegistryContext", "useAtomSet", "Effect", "useCallback", "useContext", "useMemo", "useOperationInvoker", "Obj", "Ref", "EffectEx", "MenuBuilder", "useMenuBuilder", "meta", "FeedOperation", "useToolbar", "magazine", "invoker", "registry", "db", "getDatabase", "viewAtom", "make", "busyAtom", "setView", "runExclusive", "effect", "get", "set", "runAndForwardErrors", "pipe", "ensuring", "sync", "handleCurate", "invoke", "CurateMagazine", "spaceId", "notify", "error", "ns", "profile", "key", "handleClear", "ClearMagazine", "menu", "view", "busy", "hasFeeds", "atomProperty", "length", "hasRoutine", "Boolean", "curateLabel", "group", "label", "variant", "selectCardinality", "value", "action", "icon", "separator", "iconOnly", "disabled", "iconClassNames", "undefined", "build", "MagazineArticle", "invoker", "useOperationInvoker", "magazine", "subject", "useAtomValue", "id", "attendableId", "getURI", "currentId", "useSelection", "db", "Obj", "posts", "useVisibleMagazinePosts", "handleToggleStar", "useCallback", "subscription", "source", "load", "Subscription", "setTag", "post", "getReadAt", "setReadAt", "link", "Ref", "catch", "err", "postLink", "showItem", "selectionId", "companion", "linkedSegment", "path", "getObjectPathFromObject", "useEffect", "noPosts", "current", "onToggleStar", "onOpen", "handleOpen", "React", "Menu", "asChild", "Toolbar", "Tile", "TileAdapter", "minColumnWidth", "maxColumnWidth", "thin", "centered", "padding", "classNames", "tileItems", "data"]
7
+ }