@anthusai/papyrus 0.0.0 → 1.0.0-next.10

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 (282) hide show
  1. package/LICENSE +21 -0
  2. package/amplify/auth/resource.js +61 -0
  3. package/amplify/auth/resource.ts +65 -0
  4. package/amplify/data/resource.js +2069 -0
  5. package/amplify/data/resource.ts +2185 -0
  6. package/amplify/data/schema.js +1882 -0
  7. package/amplify/data/schema.ts +1990 -0
  8. package/amplify/functions/assignment-action/handler.ts +1416 -0
  9. package/amplify/functions/assignment-action/resource.js +8 -0
  10. package/amplify/functions/assignment-action/resource.ts +9 -0
  11. package/amplify/functions/category-action/handler.ts +2259 -0
  12. package/amplify/functions/category-action/resource.js +8 -0
  13. package/amplify/functions/category-action/resource.ts +9 -0
  14. package/amplify/functions/console-chat-responder/Cargo.lock +3456 -0
  15. package/amplify/functions/console-chat-responder/Cargo.toml +26 -0
  16. package/amplify/functions/console-chat-responder/Dockerfile +19 -0
  17. package/amplify/functions/console-chat-responder/py/execute_tactus_runner.py +116 -0
  18. package/amplify/functions/console-chat-responder/resource.js +153 -0
  19. package/amplify/functions/console-chat-responder/resource.ts +179 -0
  20. package/amplify/functions/console-chat-responder/src/main.rs +3242 -0
  21. package/amplify/functions/content-actions/handler.py +149 -0
  22. package/amplify/functions/content-actions/requirements.txt +4 -0
  23. package/amplify/functions/content-actions/resource.js +40 -0
  24. package/amplify/functions/content-actions/resource.ts +54 -0
  25. package/amplify/functions/email-submission-processor/handler.py +46 -0
  26. package/amplify/functions/email-submission-processor/requirements.txt +2 -0
  27. package/amplify/functions/email-submission-processor/resource.js +56 -0
  28. package/amplify/functions/email-submission-processor/resource.ts +69 -0
  29. package/amplify/functions/graphql-jwt-authorizer/handler.ts +193 -0
  30. package/amplify/functions/graphql-jwt-authorizer/resource.js +14 -0
  31. package/amplify/functions/graphql-jwt-authorizer/resource.ts +15 -0
  32. package/amplify/functions/knowledge-query/handler.py +1 -0
  33. package/amplify/functions/knowledge-query/requirements.txt +3 -0
  34. package/amplify/functions/knowledge-query/resource.js +50 -0
  35. package/amplify/functions/knowledge-query/resource.ts +61 -0
  36. package/amplify/functions/manage-user-role/handler.ts +799 -0
  37. package/amplify/functions/manage-user-role/resource.js +8 -0
  38. package/amplify/functions/manage-user-role/resource.ts +9 -0
  39. package/amplify/functions/model-attachment-upload/handler.ts +387 -0
  40. package/amplify/functions/model-attachment-upload/resource.js +8 -0
  41. package/amplify/functions/model-attachment-upload/resource.ts +9 -0
  42. package/amplify/functions/newsroom-summary/handler.ts +321 -0
  43. package/amplify/functions/newsroom-summary/resource.js +8 -0
  44. package/amplify/functions/newsroom-summary/resource.ts +9 -0
  45. package/amplify/functions/procedure-action/handler.ts +621 -0
  46. package/amplify/functions/procedure-action/resource.js +8 -0
  47. package/amplify/functions/procedure-action/resource.ts +9 -0
  48. package/amplify/functions/reader-settings/handler.ts +322 -0
  49. package/amplify/functions/reader-settings/resource.js +8 -0
  50. package/amplify/functions/reader-settings/resource.ts +9 -0
  51. package/amplify/functions/ses-inbound-receive/handler.ts +493 -0
  52. package/amplify/functions/ses-inbound-receive/resource.js +8 -0
  53. package/amplify/functions/ses-inbound-receive/resource.ts +9 -0
  54. package/amplify/functions/shared/amplify-secrets.ts +65 -0
  55. package/amplify/functions/shared/console-chat-enqueue.ts +117 -0
  56. package/amplify/functions/shared/email-mime-intake.ts +196 -0
  57. package/amplify/functions/shared/email-submission.ts +415 -0
  58. package/amplify/functions/shared/inbound-email-intake.ts +37 -0
  59. package/amplify/functions/shared/lambda-data-client.ts +21 -0
  60. package/amplify/functions/shared/model-payloads.ts +186 -0
  61. package/amplify/functions/shared/python-bundle.js +130 -0
  62. package/amplify/functions/shared/python-bundle.ts +162 -0
  63. package/amplify/functions/shared/slack-events.ts +111 -0
  64. package/amplify/functions/slack-delivery/handler.py +112 -0
  65. package/amplify/functions/slack-delivery/requirements.txt +2 -0
  66. package/amplify/functions/slack-delivery/resource.js +38 -0
  67. package/amplify/functions/slack-delivery/resource.ts +51 -0
  68. package/amplify/functions/slack-events/handler.ts +155 -0
  69. package/amplify/functions/slack-events/resource.js +11 -0
  70. package/amplify/functions/slack-events/resource.ts +12 -0
  71. package/amplify/inbound-email/stack.js +46 -0
  72. package/amplify/inbound-email/stack.ts +61 -0
  73. package/amplify/package.json +3 -0
  74. package/amplify/rebuild-trigger-settings.js +22 -0
  75. package/amplify/rebuild-trigger-settings.ts +42 -0
  76. package/amplify/site-backend-config.js +1 -0
  77. package/amplify/site-backend-config.ts +36 -0
  78. package/amplify/site-backend.js +615 -0
  79. package/amplify/site-backend.ts +739 -0
  80. package/amplify/storage/resource.js +21 -0
  81. package/amplify/storage/resource.ts +22 -0
  82. package/app/%5F_preview/[[...path]]/route.ts +8 -0
  83. package/app/[year]/[month]/[day]/[articleSlug]/page.tsx +62 -0
  84. package/app/[year]/[month]/[day]/edition-route-page.tsx +53 -0
  85. package/app/[year]/[month]/[day]/page/[pageNumber]/page.tsx +32 -0
  86. package/app/[year]/[month]/[day]/page.tsx +22 -0
  87. package/app/[year]/[month]/[day]/section/[sectionKey]/page.tsx +32 -0
  88. package/app/api/archive/editions/route.ts +18 -0
  89. package/app/api/media/[...path]/route.ts +35 -0
  90. package/app/api/revalidate/route.ts +94 -0
  91. package/app/archive/page.tsx +24 -0
  92. package/app/articles/[slug]/page.tsx +35 -0
  93. package/app/globals.css +10345 -0
  94. package/app/layout.tsx +142 -0
  95. package/app/newsroom/[section]/[...selection]/page.tsx +50 -0
  96. package/app/newsroom/[section]/page.tsx +47 -0
  97. package/app/newsroom/articles/[id]/page.tsx +15 -0
  98. package/app/newsroom/articles/page.tsx +13 -0
  99. package/app/newsroom/forum/[threadId]/page.tsx +35 -0
  100. package/app/newsroom/insights/[threadId]/page.tsx +22 -0
  101. package/app/newsroom/insights/page.tsx +14 -0
  102. package/app/newsroom/layout.tsx +12 -0
  103. package/app/newsroom/page.tsx +31 -0
  104. package/app/newsroom/sections/[sectionId]/page.tsx +17 -0
  105. package/app/page.tsx +272 -0
  106. package/app/papyrus-theme.css +11 -0
  107. package/app/robots.ts +11 -0
  108. package/app/settings/page.tsx +14 -0
  109. package/app/tailwind.css +65 -0
  110. package/bin/papyrus-app.mjs +20 -0
  111. package/bin/papyrus-infra.mjs +95 -0
  112. package/components/ai-elements/conversation.tsx +168 -0
  113. package/components/ai-elements/message.tsx +360 -0
  114. package/components/ai-elements/model-selector.tsx +30 -0
  115. package/components/ai-elements/prompt-input.tsx +1461 -0
  116. package/components/ai-elements/shimmer.tsx +76 -0
  117. package/components/ai-elements/suggestion.tsx +54 -0
  118. package/components/ai-elements/tool.tsx +173 -0
  119. package/components/amplify-client-provider.tsx +140 -0
  120. package/components/archive-grid.tsx +89 -0
  121. package/components/archive-shell.tsx +41 -0
  122. package/components/article-video.tsx +156 -0
  123. package/components/blog-page-background.tsx +20 -0
  124. package/components/dev-sandbox-editor-sign-in.tsx +60 -0
  125. package/components/markus-ir-preview.tsx +300 -0
  126. package/components/news-desk-client-provider.tsx +211 -0
  127. package/components/news-desk-page.tsx +116 -0
  128. package/components/news-desk-taxonomy-client.ts +3684 -0
  129. package/components/newspaper.tsx +1929 -0
  130. package/components/newsroom-access-gate.tsx +66 -0
  131. package/components/newsroom-article-editor.tsx +741 -0
  132. package/components/newsroom-articles-view.tsx +129 -0
  133. package/components/newsroom-assignments-view.tsx +664 -0
  134. package/components/newsroom-ops-overview.tsx +226 -0
  135. package/components/newsroom-ops-shell.tsx +321 -0
  136. package/components/newsroom-references-view.tsx +598 -0
  137. package/components/newsroom-topics-view.tsx +425 -0
  138. package/components/papyrus-console-shell.tsx +1912 -0
  139. package/components/pictogram-figure.tsx +65 -0
  140. package/components/presentation-footer.tsx +146 -0
  141. package/components/reader-auth-control.tsx +162 -0
  142. package/components/reader-auth-state.ts +122 -0
  143. package/components/reader-settings.ts +332 -0
  144. package/components/reader-theme-control.tsx +85 -0
  145. package/components/reference-source-preview.tsx +163 -0
  146. package/components/settings-page.tsx +239 -0
  147. package/components/staging-banner.tsx +11 -0
  148. package/components/topic-steering-workspace.tsx +18005 -0
  149. package/components/ui/badge.tsx +30 -0
  150. package/components/ui/button-group.tsx +87 -0
  151. package/components/ui/button.tsx +58 -0
  152. package/components/ui/card.tsx +32 -0
  153. package/components/ui/command.tsx +194 -0
  154. package/components/ui/dialog.tsx +158 -0
  155. package/components/ui/dropdown-menu.tsx +266 -0
  156. package/components/ui/hover-card.tsx +51 -0
  157. package/components/ui/input-group.tsx +158 -0
  158. package/components/ui/input.tsx +20 -0
  159. package/components/ui/scroll-area.tsx +16 -0
  160. package/components/ui/select.tsx +199 -0
  161. package/components/ui/separator.tsx +23 -0
  162. package/components/ui/sheet.tsx +92 -0
  163. package/components/ui/spinner.tsx +10 -0
  164. package/components/ui/tabs.tsx +113 -0
  165. package/components/ui/textarea.tsx +18 -0
  166. package/components/ui/tooltip.tsx +66 -0
  167. package/components/use-resolved-papyrus-theme.ts +47 -0
  168. package/infra/amplify-app-shell.js +234 -0
  169. package/infra/amplify-app-shell.ts +284 -0
  170. package/infra/build-specs.js +85 -0
  171. package/infra/build-specs.ts +131 -0
  172. package/infra/github-oidc-provider.js +24 -0
  173. package/infra/github-oidc-provider.ts +30 -0
  174. package/infra/index.js +15 -0
  175. package/infra/site-config.js +186 -0
  176. package/infra/site-config.ts +235 -0
  177. package/lib/amplify-outputs-guard.ts +24 -0
  178. package/lib/amplify-outputs-path.ts +16 -0
  179. package/lib/amplify-server-runtime.ts +63 -0
  180. package/lib/archive-data.ts +30 -0
  181. package/lib/archive-types.ts +15 -0
  182. package/lib/articles.ts +320 -0
  183. package/lib/cached-content-repository.ts +90 -0
  184. package/lib/category-dashboard.ts +37 -0
  185. package/lib/category-repository.ts +1907 -0
  186. package/lib/console-chat-client.ts +1316 -0
  187. package/lib/console-web-context.ts +118 -0
  188. package/lib/content-actions-client.ts +98 -0
  189. package/lib/content-actions-demo.ts +190 -0
  190. package/lib/content-load-timing.ts +23 -0
  191. package/lib/content-repository.ts +43 -0
  192. package/lib/content-source-context.ts +26 -0
  193. package/lib/content-types.ts +104 -0
  194. package/lib/define-site.js +3 -0
  195. package/lib/define-site.ts +21 -0
  196. package/lib/demo-amplify-outputs.ts +15 -0
  197. package/lib/dev-sandbox-editor-auth.ts +18 -0
  198. package/lib/doctrine.ts +128 -0
  199. package/lib/edition-routes.ts +155 -0
  200. package/lib/edition-sections.ts +111 -0
  201. package/lib/empty-edition-layout-plan.ts +109 -0
  202. package/lib/empty-theme.css +1 -0
  203. package/lib/excerpts.ts +8 -0
  204. package/lib/graphql-content-repository.ts +1140 -0
  205. package/lib/image-url.ts +10 -0
  206. package/lib/layout-plan.ts +981 -0
  207. package/lib/layout-scenarios.ts +564 -0
  208. package/lib/markus-body.ts +168 -0
  209. package/lib/markus-ir.ts +235 -0
  210. package/lib/markus-projection.ts +243 -0
  211. package/lib/markus-to-article.ts +93 -0
  212. package/lib/news-desk-session.ts +160 -0
  213. package/lib/newspaper-layout.ts +3459 -0
  214. package/lib/newsroom-articles.ts +325 -0
  215. package/lib/newsroom-assignments.ts +173 -0
  216. package/lib/newsroom-base-path.ts +48 -0
  217. package/lib/newsroom-card-layout.ts +102 -0
  218. package/lib/newsroom-category-drilldown.ts +133 -0
  219. package/lib/newsroom-demo-articles.ts +90 -0
  220. package/lib/newsroom-demo-dashboard.ts +267 -0
  221. package/lib/newsroom-demo-profile.ts +46 -0
  222. package/lib/newsroom-forum-routes.ts +153 -0
  223. package/lib/newsroom-index-filters.ts +202 -0
  224. package/lib/newsroom-knowledge-query-request.ts +51 -0
  225. package/lib/newsroom-list-selection.ts +42 -0
  226. package/lib/newsroom-media-backend.ts +142 -0
  227. package/lib/newsroom-media.ts +182 -0
  228. package/lib/newsroom-nav.ts +44 -0
  229. package/lib/newsroom-references.ts +116 -0
  230. package/lib/newsroom-sections.ts +52 -0
  231. package/lib/newsroom-topics.ts +118 -0
  232. package/lib/papyrus-object-kinds.ts +24 -0
  233. package/lib/papyrus-web-locations.ts +480 -0
  234. package/lib/pilobol-sample.ts +167 -0
  235. package/lib/presentation-footer.ts +92 -0
  236. package/lib/pretext-layout.ts +179 -0
  237. package/lib/public-placeholder-config.ts +102 -0
  238. package/lib/publication-items.ts +181 -0
  239. package/lib/reader-route-config.ts +1 -0
  240. package/lib/reader-static-params.ts +56 -0
  241. package/lib/reader-storage-url.ts +63 -0
  242. package/lib/reference-display.ts +74 -0
  243. package/lib/reference-policy.ts +97 -0
  244. package/lib/reference-source-preview.ts +175 -0
  245. package/lib/renderer-config.ts +50 -0
  246. package/lib/renderer.ts +87 -0
  247. package/lib/reporting-story-budget.ts +638 -0
  248. package/lib/semantic-graph.ts +554 -0
  249. package/lib/site-brand-tenant.ts +22 -0
  250. package/lib/site-brand.ts +194 -0
  251. package/lib/site-env.ts +52 -0
  252. package/lib/site-renderer.ts +17 -0
  253. package/lib/site-stack.ts +195 -0
  254. package/lib/staging-gate.ts +37 -0
  255. package/lib/staging-preview-object.ts +98 -0
  256. package/lib/themed-image.ts +30 -0
  257. package/lib/utils.ts +6 -0
  258. package/lib/video-mode.ts +42 -0
  259. package/lib/video-script.ts +63 -0
  260. package/middleware.ts +103 -0
  261. package/package.json +318 -1
  262. package/renderers/markus/index.ts +25 -0
  263. package/renderers/markus/stubs.tsx +33 -0
  264. package/renderers/pretext/article-page.tsx +169 -0
  265. package/renderers/pretext/index.ts +30 -0
  266. package/renderers/pretext/layouts.ts +16 -0
  267. package/renderers/pretext/presentation-shell.tsx +470 -0
  268. package/routes.manifest.json +208 -0
  269. package/scripts/fixtures/pilobol-sample.ast.json +234 -0
  270. package/scripts/videoml/build-browser-bundle.mjs +22 -0
  271. package/scripts/videoml/build-preview-bundle.mjs +50 -0
  272. package/scripts/videoml/bundle-common.mjs +129 -0
  273. package/scripts/videoml/preview/preview-entry.tsx +381 -0
  274. package/scripts/videoml/preview/preview-stage-fit.ts +28 -0
  275. package/scripts/videoml/preview/preview-timing.ts +42 -0
  276. package/scripts/videoml/preview.html +77 -0
  277. package/scripts/videoml/standard-entry.tsx +46 -0
  278. package/src/backend.js +1 -0
  279. package/src/backend.ts +3 -0
  280. package/src/sync.mjs +87 -0
  281. package/src/with-papyrus.d.mts +2 -0
  282. package/src/with-papyrus.mjs +60 -0
@@ -0,0 +1,199 @@
1
+ import * as React from "react"
2
+ import { Select as SelectPrimitive } from "@base-ui/react/select"
3
+
4
+ import { cn } from "../../lib/utils"
5
+ import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
6
+
7
+ const Select = SelectPrimitive.Root
8
+
9
+ function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {
10
+ return (
11
+ <SelectPrimitive.Group
12
+ data-slot="select-group"
13
+ className={cn("scroll-my-1 p-1", className)}
14
+ {...props}
15
+ />
16
+ )
17
+ }
18
+
19
+ function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
20
+ return (
21
+ <SelectPrimitive.Value
22
+ data-slot="select-value"
23
+ className={cn("flex flex-1 text-left", className)}
24
+ {...props}
25
+ />
26
+ )
27
+ }
28
+
29
+ function SelectTrigger({
30
+ className,
31
+ size = "default",
32
+ children,
33
+ ...props
34
+ }: SelectPrimitive.Trigger.Props & {
35
+ size?: "sm" | "default"
36
+ }) {
37
+ return (
38
+ <SelectPrimitive.Trigger
39
+ data-slot="select-trigger"
40
+ data-size={size}
41
+ className={cn(
42
+ "flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
43
+ className
44
+ )}
45
+ {...props}
46
+ >
47
+ {children}
48
+ <SelectPrimitive.Icon
49
+ render={
50
+ <ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
51
+ }
52
+ />
53
+ </SelectPrimitive.Trigger>
54
+ )
55
+ }
56
+
57
+ function SelectContent({
58
+ className,
59
+ children,
60
+ side = "bottom",
61
+ sideOffset = 4,
62
+ align = "center",
63
+ alignOffset = 0,
64
+ alignItemWithTrigger = true,
65
+ ...props
66
+ }: SelectPrimitive.Popup.Props &
67
+ Pick<
68
+ SelectPrimitive.Positioner.Props,
69
+ "align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
70
+ >) {
71
+ return (
72
+ <SelectPrimitive.Portal>
73
+ <SelectPrimitive.Positioner
74
+ side={side}
75
+ sideOffset={sideOffset}
76
+ align={align}
77
+ alignOffset={alignOffset}
78
+ alignItemWithTrigger={alignItemWithTrigger}
79
+ className="isolate z-50"
80
+ >
81
+ <SelectPrimitive.Popup
82
+ data-slot="select-content"
83
+ data-align-trigger={alignItemWithTrigger}
84
+ className={cn("relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
85
+ {...props}
86
+ >
87
+ <SelectScrollUpButton />
88
+ <SelectPrimitive.List>{children}</SelectPrimitive.List>
89
+ <SelectScrollDownButton />
90
+ </SelectPrimitive.Popup>
91
+ </SelectPrimitive.Positioner>
92
+ </SelectPrimitive.Portal>
93
+ )
94
+ }
95
+
96
+ function SelectLabel({
97
+ className,
98
+ ...props
99
+ }: SelectPrimitive.GroupLabel.Props) {
100
+ return (
101
+ <SelectPrimitive.GroupLabel
102
+ data-slot="select-label"
103
+ className={cn("px-1.5 py-1 text-xs text-muted-foreground", className)}
104
+ {...props}
105
+ />
106
+ )
107
+ }
108
+
109
+ function SelectItem({
110
+ className,
111
+ children,
112
+ ...props
113
+ }: SelectPrimitive.Item.Props) {
114
+ return (
115
+ <SelectPrimitive.Item
116
+ data-slot="select-item"
117
+ className={cn(
118
+ "relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
119
+ className
120
+ )}
121
+ {...props}
122
+ >
123
+ <SelectPrimitive.ItemText className="flex flex-1 shrink-0 gap-2 whitespace-nowrap">
124
+ {children}
125
+ </SelectPrimitive.ItemText>
126
+ <SelectPrimitive.ItemIndicator
127
+ render={
128
+ <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
129
+ }
130
+ >
131
+ <CheckIcon className="pointer-events-none" />
132
+ </SelectPrimitive.ItemIndicator>
133
+ </SelectPrimitive.Item>
134
+ )
135
+ }
136
+
137
+ function SelectSeparator({
138
+ className,
139
+ ...props
140
+ }: SelectPrimitive.Separator.Props) {
141
+ return (
142
+ <SelectPrimitive.Separator
143
+ data-slot="select-separator"
144
+ className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
145
+ {...props}
146
+ />
147
+ )
148
+ }
149
+
150
+ function SelectScrollUpButton({
151
+ className,
152
+ ...props
153
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {
154
+ return (
155
+ <SelectPrimitive.ScrollUpArrow
156
+ data-slot="select-scroll-up-button"
157
+ className={cn(
158
+ "top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
159
+ className
160
+ )}
161
+ {...props}
162
+ >
163
+ <ChevronUpIcon
164
+ />
165
+ </SelectPrimitive.ScrollUpArrow>
166
+ )
167
+ }
168
+
169
+ function SelectScrollDownButton({
170
+ className,
171
+ ...props
172
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {
173
+ return (
174
+ <SelectPrimitive.ScrollDownArrow
175
+ data-slot="select-scroll-down-button"
176
+ className={cn(
177
+ "bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
178
+ className
179
+ )}
180
+ {...props}
181
+ >
182
+ <ChevronDownIcon
183
+ />
184
+ </SelectPrimitive.ScrollDownArrow>
185
+ )
186
+ }
187
+
188
+ export {
189
+ Select,
190
+ SelectContent,
191
+ SelectGroup,
192
+ SelectItem,
193
+ SelectLabel,
194
+ SelectScrollDownButton,
195
+ SelectScrollUpButton,
196
+ SelectSeparator,
197
+ SelectTrigger,
198
+ SelectValue,
199
+ }
@@ -0,0 +1,23 @@
1
+ import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
2
+
3
+ import { cn } from "../../lib/utils"
4
+
5
+ function Separator({
6
+ className,
7
+ orientation = "horizontal",
8
+ ...props
9
+ }: SeparatorPrimitive.Props) {
10
+ return (
11
+ <SeparatorPrimitive
12
+ data-slot="separator"
13
+ orientation={orientation}
14
+ className={cn(
15
+ "shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ export { Separator }
@@ -0,0 +1,92 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
5
+ import { XIcon } from "lucide-react";
6
+
7
+ import { cn } from "../../lib/utils";
8
+ import { Button } from "./button";
9
+
10
+ type SheetSide = "bottom" | "left" | "right";
11
+
12
+ const sideClasses: Record<SheetSide, string> = {
13
+ bottom:
14
+ "inset-x-0 bottom-0 top-auto max-h-[85dvh] w-full rounded-t-2xl border-t data-open:slide-in-from-bottom data-closed:slide-out-to-bottom",
15
+ left: "inset-y-0 left-0 h-full w-[min(100vw,20rem)] rounded-r-2xl border-r data-open:slide-in-from-left data-closed:slide-out-to-left",
16
+ right: "inset-y-0 right-0 h-full w-[min(100vw,20rem)] rounded-l-2xl border-l data-open:slide-in-from-right data-closed:slide-out-to-right",
17
+ };
18
+
19
+ function Sheet({ ...props }: DialogPrimitive.Root.Props) {
20
+ return <DialogPrimitive.Root data-slot="sheet" {...props} />;
21
+ }
22
+
23
+ function SheetTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
24
+ return <DialogPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
25
+ }
26
+
27
+ function SheetClose({ ...props }: DialogPrimitive.Close.Props) {
28
+ return <DialogPrimitive.Close data-slot="sheet-close" {...props} />;
29
+ }
30
+
31
+ function SheetContent({
32
+ children,
33
+ className,
34
+ showCloseButton = true,
35
+ side = "bottom",
36
+ ...props
37
+ }: DialogPrimitive.Popup.Props & {
38
+ showCloseButton?: boolean;
39
+ side?: SheetSide;
40
+ }) {
41
+ return (
42
+ <DialogPrimitive.Portal>
43
+ <DialogPrimitive.Backdrop
44
+ className="fixed inset-0 z-50 bg-black/40 data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0"
45
+ />
46
+ <DialogPrimitive.Popup
47
+ className={cn(
48
+ "fixed z-50 grid gap-4 bg-background p-4 text-foreground shadow-lg outline-none duration-200 data-open:animate-in data-closed:animate-out",
49
+ sideClasses[side],
50
+ className,
51
+ )}
52
+ {...props}
53
+ >
54
+ {children}
55
+ {showCloseButton ? (
56
+ <DialogPrimitive.Close
57
+ render={
58
+ <Button className="absolute top-3 right-3" size="icon-sm" variant="ghost" />
59
+ }
60
+ >
61
+ <XIcon className="size-4" />
62
+ <span className="sr-only">Close</span>
63
+ </DialogPrimitive.Close>
64
+ ) : null}
65
+ </DialogPrimitive.Popup>
66
+ </DialogPrimitive.Portal>
67
+ );
68
+ }
69
+
70
+ function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
71
+ return <div className={cn("flex flex-col gap-1 pr-8", className)} {...props} />;
72
+ }
73
+
74
+ function SheetTitle({ className, ...props }: DialogPrimitive.Title.Props) {
75
+ return (
76
+ <DialogPrimitive.Title
77
+ className={cn("text-base font-semibold tracking-tight", className)}
78
+ {...props}
79
+ />
80
+ );
81
+ }
82
+
83
+ function SheetDescription({ className, ...props }: DialogPrimitive.Description.Props) {
84
+ return (
85
+ <DialogPrimitive.Description
86
+ className={cn("text-sm text-muted-foreground", className)}
87
+ {...props}
88
+ />
89
+ );
90
+ }
91
+
92
+ export { Sheet, SheetClose, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger };
@@ -0,0 +1,10 @@
1
+ import { cn } from "../../lib/utils"
2
+ import { Loader2Icon } from "lucide-react"
3
+
4
+ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
5
+ return (
6
+ <Loader2Icon role="status" aria-label="Loading" className={cn("size-4 animate-spin", className)} {...props} />
7
+ )
8
+ }
9
+
10
+ export { Spinner }
@@ -0,0 +1,113 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+
5
+ import { cn } from "../../lib/utils";
6
+
7
+ type TabsContextValue = {
8
+ value: string;
9
+ setValue: (value: string) => void;
10
+ };
11
+
12
+ const TabsContext = React.createContext<TabsContextValue | null>(null);
13
+
14
+ function useTabsContext(componentName: string): TabsContextValue {
15
+ const context = React.useContext(TabsContext);
16
+ if (!context) {
17
+ throw new Error(`${componentName} must be used within <Tabs>.`);
18
+ }
19
+ return context;
20
+ }
21
+
22
+ function Tabs({
23
+ children,
24
+ className,
25
+ defaultValue,
26
+ onValueChange,
27
+ value,
28
+ }: React.PropsWithChildren<{
29
+ className?: string;
30
+ defaultValue: string;
31
+ onValueChange?: (value: string) => void;
32
+ value?: string;
33
+ }>) {
34
+ const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
35
+ const activeValue = value ?? uncontrolledValue;
36
+ const setValue = React.useCallback(
37
+ (nextValue: string) => {
38
+ if (value === undefined) {
39
+ setUncontrolledValue(nextValue);
40
+ }
41
+ onValueChange?.(nextValue);
42
+ },
43
+ [onValueChange, value],
44
+ );
45
+
46
+ return (
47
+ <TabsContext.Provider value={{ value: activeValue, setValue }}>
48
+ <div className={cn("flex flex-col gap-3", className)}>{children}</div>
49
+ </TabsContext.Provider>
50
+ );
51
+ }
52
+
53
+ function TabsList({
54
+ children,
55
+ className,
56
+ }: React.PropsWithChildren<{ className?: string }>) {
57
+ return (
58
+ <div
59
+ aria-orientation="horizontal"
60
+ className={cn(
61
+ "inline-flex h-9 w-fit items-center rounded-lg bg-muted/50 p-1 text-muted-foreground",
62
+ className,
63
+ )}
64
+ role="tablist"
65
+ >
66
+ {children}
67
+ </div>
68
+ );
69
+ }
70
+
71
+ function TabsTrigger({
72
+ children,
73
+ className,
74
+ value,
75
+ }: React.PropsWithChildren<{ className?: string; value: string }>) {
76
+ const context = useTabsContext("TabsTrigger");
77
+ const active = context.value === value;
78
+ return (
79
+ <button
80
+ aria-selected={active}
81
+ className={cn(
82
+ "inline-flex min-w-[7rem] items-center justify-center rounded-md px-3 py-1.5 text-sm font-medium transition-all",
83
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgb(var(--ink-solid-rgb)_/_0.18)]",
84
+ active
85
+ ? "bg-primary/10 text-foreground shadow-none ring-1 ring-primary/15"
86
+ : "text-muted-foreground hover:bg-primary/5 hover:text-foreground",
87
+ className,
88
+ )}
89
+ data-state={active ? "active" : "inactive"}
90
+ onClick={() => context.setValue(value)}
91
+ role="tab"
92
+ type="button"
93
+ >
94
+ {children}
95
+ </button>
96
+ );
97
+ }
98
+
99
+ function TabsContent({
100
+ children,
101
+ className,
102
+ value,
103
+ }: React.PropsWithChildren<{ className?: string; value: string }>) {
104
+ const context = useTabsContext("TabsContent");
105
+ if (context.value !== value) return null;
106
+ return (
107
+ <div className={className} data-state="active" role="tabpanel">
108
+ {children}
109
+ </div>
110
+ );
111
+ }
112
+
113
+ export { Tabs, TabsContent, TabsList, TabsTrigger };
@@ -0,0 +1,18 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "../../lib/utils"
4
+
5
+ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
+ return (
7
+ <textarea
8
+ data-slot="textarea"
9
+ className={cn(
10
+ "flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
11
+ className
12
+ )}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ export { Textarea }
@@ -0,0 +1,66 @@
1
+ "use client"
2
+
3
+ import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
4
+
5
+ import { cn } from "../../lib/utils"
6
+
7
+ function TooltipProvider({
8
+ delay = 0,
9
+ ...props
10
+ }: TooltipPrimitive.Provider.Props) {
11
+ return (
12
+ <TooltipPrimitive.Provider
13
+ data-slot="tooltip-provider"
14
+ delay={delay}
15
+ {...props}
16
+ />
17
+ )
18
+ }
19
+
20
+ function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
21
+ return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
22
+ }
23
+
24
+ function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
25
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
26
+ }
27
+
28
+ function TooltipContent({
29
+ className,
30
+ side = "top",
31
+ sideOffset = 4,
32
+ align = "center",
33
+ alignOffset = 0,
34
+ children,
35
+ ...props
36
+ }: TooltipPrimitive.Popup.Props &
37
+ Pick<
38
+ TooltipPrimitive.Positioner.Props,
39
+ "align" | "alignOffset" | "side" | "sideOffset"
40
+ >) {
41
+ return (
42
+ <TooltipPrimitive.Portal>
43
+ <TooltipPrimitive.Positioner
44
+ align={align}
45
+ alignOffset={alignOffset}
46
+ side={side}
47
+ sideOffset={sideOffset}
48
+ className="isolate z-50"
49
+ >
50
+ <TooltipPrimitive.Popup
51
+ data-slot="tooltip-content"
52
+ className={cn(
53
+ "z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
54
+ className
55
+ )}
56
+ {...props}
57
+ >
58
+ {children}
59
+ <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" />
60
+ </TooltipPrimitive.Popup>
61
+ </TooltipPrimitive.Positioner>
62
+ </TooltipPrimitive.Portal>
63
+ )
64
+ }
65
+
66
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
@@ -0,0 +1,47 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+ import type { ResolvedTheme } from "../lib/themed-image";
5
+
6
+ const SETTINGS_EVENT = "papyrus:settings-changed";
7
+
8
+ function readResolvedTheme(): ResolvedTheme {
9
+ if (typeof document === "undefined" || typeof window === "undefined") return "light";
10
+ const theme = document.documentElement.dataset.papyrusTheme;
11
+ if (theme === "dark") return "dark";
12
+ if (theme === "light") return "light";
13
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
14
+ }
15
+
16
+ export function useResolvedPapyrusTheme(): ResolvedTheme {
17
+ const [resolvedTheme, setResolvedTheme] = useState<ResolvedTheme>("light");
18
+
19
+ useEffect(() => {
20
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
21
+ const refresh = () => setResolvedTheme(readResolvedTheme());
22
+ refresh();
23
+ media.addEventListener("change", refresh);
24
+ window.addEventListener(SETTINGS_EVENT, refresh);
25
+ window.addEventListener("storage", refresh);
26
+ const observer = new MutationObserver((mutations) => {
27
+ for (const mutation of mutations) {
28
+ if (mutation.type === "attributes" && mutation.attributeName === "data-papyrus-theme") {
29
+ refresh();
30
+ break;
31
+ }
32
+ }
33
+ });
34
+ observer.observe(document.documentElement, {
35
+ attributes: true,
36
+ attributeFilter: ["data-papyrus-theme"],
37
+ });
38
+ return () => {
39
+ media.removeEventListener("change", refresh);
40
+ window.removeEventListener(SETTINGS_EVENT, refresh);
41
+ window.removeEventListener("storage", refresh);
42
+ observer.disconnect();
43
+ };
44
+ }, []);
45
+
46
+ return resolvedTheme;
47
+ }