@genispace/geniapp 0.1.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 (258) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/dist/CrossAppRecordPicker-BXchXcK5.js +624 -0
  4. package/dist/CrossAppRecordPicker-BXchXcK5.js.map +1 -0
  5. package/dist/Page-wHZrMN17.js +24 -0
  6. package/dist/Page-wHZrMN17.js.map +1 -0
  7. package/dist/ai/adopt/AiSuggestionPanel.d.ts +30 -0
  8. package/dist/ai/adopt/BusinessGuidancePanel.d.ts +31 -0
  9. package/dist/ai/adopt/DetailPageAiLayout.d.ts +7 -0
  10. package/dist/ai/adopt/adoptPresets.d.ts +11 -0
  11. package/dist/ai/adopt/guidanceContent.d.ts +27 -0
  12. package/dist/ai/adopt/parseAiSummary.d.ts +7 -0
  13. package/dist/ai/components/AgentJobProgress.d.ts +124 -0
  14. package/dist/ai/components/AsyncCombobox.d.ts +44 -0
  15. package/dist/ai/components/BulkActionBar.d.ts +44 -0
  16. package/dist/ai/components/EntityRef.d.ts +39 -0
  17. package/dist/ai/components/JobProgress.d.ts +64 -0
  18. package/dist/ai/components/ServerDataTable.d.ts +89 -0
  19. package/dist/ai/components/Timeline.d.ts +35 -0
  20. package/dist/ai/components/useInfiniteRows.d.ts +25 -0
  21. package/dist/ai/errors/userFacingError.d.ts +14 -0
  22. package/dist/ai/errors/userFacingError.js +48 -0
  23. package/dist/ai/errors/userFacingError.js.map +1 -0
  24. package/dist/ai/index.d.ts +34 -0
  25. package/dist/ai/integrations/partner/createPartnerRecordPickerHook.d.ts +15 -0
  26. package/dist/ai/integrations/partner/partnerRecordPicker.d.ts +20 -0
  27. package/dist/ai/layout/ModalWithAiLayout.d.ts +11 -0
  28. package/dist/ai/layout/aiUi.d.ts +16 -0
  29. package/dist/ai/layout/layoutConstants.d.ts +19 -0
  30. package/dist/ai/layout/modalSizeForAi.d.ts +5 -0
  31. package/dist/ai/locales/sharedAiCopy.d.ts +6 -0
  32. package/dist/ai/managed-data/DatasourceReadonlyTable.d.ts +11 -0
  33. package/dist/ai/managed-data/createTableClient.d.ts +7 -0
  34. package/dist/ai/managed-data/emitManagedEvent.d.ts +18 -0
  35. package/dist/ai/managed-data/executeManagedDatasource.d.ts +21 -0
  36. package/dist/ai/managed-data/queryManagedDatasource.d.ts +28 -0
  37. package/dist/ai/providers/AppUiProviders.d.ts +6 -0
  38. package/dist/ai/types/app-ai.types.d.ts +29 -0
  39. package/dist/ai/types/index.d.ts +1 -0
  40. package/dist/ai.d.ts +1 -0
  41. package/dist/ai.js +1817 -0
  42. package/dist/ai.js.map +1 -0
  43. package/dist/case-workspace/domain.d.ts +41 -0
  44. package/dist/case-workspace/domain.js +24 -0
  45. package/dist/case-workspace/domain.js.map +1 -0
  46. package/dist/case-workspace/index.d.ts +91 -0
  47. package/dist/case-workspace.d.ts +1 -0
  48. package/dist/case-workspace.js +392 -0
  49. package/dist/case-workspace.js.map +1 -0
  50. package/dist/cn-B6yFEsav.js +9 -0
  51. package/dist/cn-B6yFEsav.js.map +1 -0
  52. package/dist/components/ui/calendar.css +7 -0
  53. package/dist/cookieSettings-D_v3KS02.js +97 -0
  54. package/dist/cookieSettings-D_v3KS02.js.map +1 -0
  55. package/dist/dashboard/index.d.ts +16 -0
  56. package/dist/dashboard/src/ChartFrame.d.ts +18 -0
  57. package/dist/dashboard/src/ChartTooltip.d.ts +38 -0
  58. package/dist/dashboard/src/FilterBar.d.ts +23 -0
  59. package/dist/dashboard/src/KpiStatCard.d.ts +29 -0
  60. package/dist/dashboard/src/StatGrid.d.ts +15 -0
  61. package/dist/dashboard/src/TimeRangePicker.d.ts +14 -0
  62. package/dist/dashboard/src/chart.d.ts +10 -0
  63. package/dist/dashboard/src/format.d.ts +16 -0
  64. package/dist/dashboard/src/links.d.ts +2 -0
  65. package/dist/dashboard/src/useDashboardRange.d.ts +27 -0
  66. package/dist/dashboard.d.ts +1 -0
  67. package/dist/dashboard.js +361 -0
  68. package/dist/dashboard.js.map +1 -0
  69. package/dist/fonts.css +15 -0
  70. package/dist/hooks/access/AppAccessGate.d.ts +20 -0
  71. package/dist/hooks/access/AppAccessNotice.d.ts +8 -0
  72. package/dist/hooks/access/useAppAccess.d.ts +26 -0
  73. package/dist/hooks/config/businessLocale.d.ts +12 -0
  74. package/dist/hooks/config/currencies.d.ts +9 -0
  75. package/dist/hooks/index.d.ts +17 -0
  76. package/dist/hooks/picker/CrossAppRecordPicker.d.ts +37 -0
  77. package/dist/hooks/picker/managedAppPicker.d.ts +21 -0
  78. package/dist/hooks/picker/partnerPayload.d.ts +6 -0
  79. package/dist/hooks/routing/draftEntityId.d.ts +5 -0
  80. package/dist/hooks/routing/useRefetchOnRouteMatch.d.ts +6 -0
  81. package/dist/hooks/shell/resolveApiRoot.d.ts +13 -0
  82. package/dist/hooks/shell/shell.d.ts +4 -0
  83. package/dist/hooks/shell/useGenispacePlatformClient.d.ts +7 -0
  84. package/dist/hooks.d.ts +1 -0
  85. package/dist/hooks.js +42 -0
  86. package/dist/hooks.js.map +1 -0
  87. package/dist/index.d.ts +3 -0
  88. package/dist/index.js +77 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/kit.d.ts +50 -0
  91. package/dist/kit.js +2067 -0
  92. package/dist/kit.js.map +1 -0
  93. package/dist/page.d.ts +1 -0
  94. package/dist/page.js +5 -0
  95. package/dist/page.js.map +1 -0
  96. package/dist/shell-DIHnXIUb.js +6 -0
  97. package/dist/shell-DIHnXIUb.js.map +1 -0
  98. package/dist/shell.d.ts +30 -0
  99. package/dist/shell.js +104 -0
  100. package/dist/shell.js.map +1 -0
  101. package/dist/storage/assetPreview.d.ts +12 -0
  102. package/dist/storage/components/AssetThumbnail.d.ts +15 -0
  103. package/dist/storage/components/CopyStorageLinkButton.d.ts +13 -0
  104. package/dist/storage/components/StorageImage.d.ts +9 -0
  105. package/dist/storage/components/StoragePreviewContent.d.ts +22 -0
  106. package/dist/storage/components/StorageVideo.d.ts +9 -0
  107. package/dist/storage/copyTextToClipboard.d.ts +5 -0
  108. package/dist/storage/hooks/useAuthenticatedStorageBlobs.d.ts +3 -0
  109. package/dist/storage/hooks/useImageThumbnailBlobs.d.ts +4 -0
  110. package/dist/storage/hooks/useShareableStorageLink.d.ts +7 -0
  111. package/dist/storage/index.d.ts +12 -0
  112. package/dist/storage/openUrlInNewTab.d.ts +6 -0
  113. package/dist/storage/platformStorage.d.ts +43 -0
  114. package/dist/storage.d.ts +1 -0
  115. package/dist/storage.js +605 -0
  116. package/dist/storage.js.map +1 -0
  117. package/dist/style.css +1 -0
  118. package/dist/styles/base.css +616 -0
  119. package/dist/styles/reduced-motion.css +14 -0
  120. package/dist/styles/tailwind-preset.js +269 -0
  121. package/dist/task-workspace/domain.d.ts +35 -0
  122. package/dist/task-workspace/domain.js +45 -0
  123. package/dist/task-workspace/domain.js.map +1 -0
  124. package/dist/task-workspace/experience.d.ts +50 -0
  125. package/dist/task-workspace/index.d.ts +172 -0
  126. package/dist/task-workspace.d.ts +1 -0
  127. package/dist/task-workspace.js +626 -0
  128. package/dist/task-workspace.js.map +1 -0
  129. package/dist/ui/components/features/app/AppCheckboxInput.d.ts +9 -0
  130. package/dist/ui/components/features/app/AppConfirmDialog.d.ts +12 -0
  131. package/dist/ui/components/features/app/AppDashboardSkeleton.d.ts +9 -0
  132. package/dist/ui/components/features/app/AppDatePicker.d.ts +69 -0
  133. package/dist/ui/components/features/app/AppModal.d.ts +27 -0
  134. package/dist/ui/components/features/app/AppPageStates.d.ts +17 -0
  135. package/dist/ui/components/features/app/AppSelectInput.d.ts +10 -0
  136. package/dist/ui/components/features/app/AppTemporalInput.d.ts +19 -0
  137. package/dist/ui/components/features/app/Page.d.ts +14 -0
  138. package/dist/ui/components/features/app/QueryErrorAlert.d.ts +7 -0
  139. package/dist/ui/components/features/app/Sidebar.d.ts +47 -0
  140. package/dist/ui/components/features/app/index.d.ts +17 -0
  141. package/dist/ui/components/features/user/UserAvatar.d.ts +17 -0
  142. package/dist/ui/components/features/user/UserDisplay.d.ts +10 -0
  143. package/dist/ui/components/features/user/UserSelect.d.ts +14 -0
  144. package/dist/ui/components/features/user/useUserDirectory.d.ts +13 -0
  145. package/dist/ui/components/features/user/userDirectoryTypes.d.ts +18 -0
  146. package/dist/ui/components/patterns/form-section.d.ts +11 -0
  147. package/dist/ui/components/primitives/feedback/index.d.ts +2 -0
  148. package/dist/ui/components/primitives/feedback/toaster.d.ts +1 -0
  149. package/dist/ui/components/primitives/feedback/use-toast.d.ts +46 -0
  150. package/dist/ui/components/primitives/page-skeleton/ChartAreaSkeleton.d.ts +13 -0
  151. package/dist/ui/components/primitives/page-skeleton/ChartEmptyState.d.ts +14 -0
  152. package/dist/ui/components/primitives/page-skeleton/ComponentSkeletonShell.d.ts +16 -0
  153. package/dist/ui/components/primitives/page-skeleton/ConfigEditorSkeleton.d.ts +5 -0
  154. package/dist/ui/components/primitives/page-skeleton/DetailTabsSkeleton.d.ts +6 -0
  155. package/dist/ui/components/primitives/page-skeleton/EmptyStateBadge.d.ts +13 -0
  156. package/dist/ui/components/primitives/page-skeleton/FormCardSkeleton.d.ts +7 -0
  157. package/dist/ui/components/primitives/page-skeleton/FormFieldSkeleton.d.ts +6 -0
  158. package/dist/ui/components/primitives/page-skeleton/FormPageSkeleton.d.ts +6 -0
  159. package/dist/ui/components/primitives/page-skeleton/GridCardsSkeleton.d.ts +6 -0
  160. package/dist/ui/components/primitives/page-skeleton/ListSkeleton.d.ts +26 -0
  161. package/dist/ui/components/primitives/page-skeleton/PageHeaderSkeleton.d.ts +6 -0
  162. package/dist/ui/components/primitives/page-skeleton/SplitPaneSkeleton.d.ts +4 -0
  163. package/dist/ui/components/primitives/page-skeleton/StatsRowSkeleton.d.ts +5 -0
  164. package/dist/ui/components/primitives/page-skeleton/TableEmptyState.d.ts +27 -0
  165. package/dist/ui/components/primitives/page-skeleton/TablePageSkeleton.d.ts +8 -0
  166. package/dist/ui/components/primitives/page-skeleton/TabsBarSkeleton.d.ts +6 -0
  167. package/dist/ui/components/primitives/page-skeleton/index.d.ts +24 -0
  168. package/dist/ui/components/primitives/page-skeleton/skeletonMetrics.d.ts +9 -0
  169. package/dist/ui/components/primitives/page-skeleton/useVisibleCenter.d.ts +34 -0
  170. package/dist/ui/components/ui/accordion.d.ts +7 -0
  171. package/dist/ui/components/ui/ai-draft-banner.d.ts +21 -0
  172. package/dist/ui/components/ui/alert-dialog.d.ts +48 -0
  173. package/dist/ui/components/ui/alert.d.ts +8 -0
  174. package/dist/ui/components/ui/avatar.d.ts +6 -0
  175. package/dist/ui/components/ui/badge.d.ts +9 -0
  176. package/dist/ui/components/ui/breadcrumb.d.ts +19 -0
  177. package/dist/ui/components/ui/button.d.ts +11 -0
  178. package/dist/ui/components/ui/calendar.d.ts +8 -0
  179. package/dist/ui/components/ui/card.d.ts +8 -0
  180. package/dist/ui/components/ui/chart.d.ts +16 -0
  181. package/dist/ui/components/ui/checkbox.d.ts +4 -0
  182. package/dist/ui/components/ui/collapsible.d.ts +5 -0
  183. package/dist/ui/components/ui/column-config.d.ts +42 -0
  184. package/dist/ui/components/ui/date-picker.d.ts +9 -0
  185. package/dist/ui/components/ui/date-range-filter.d.ts +32 -0
  186. package/dist/ui/components/ui/date-range-picker.d.ts +11 -0
  187. package/dist/ui/components/ui/dialog-input.d.ts +17 -0
  188. package/dist/ui/components/ui/dialog-safe-select.d.ts +13 -0
  189. package/dist/ui/components/ui/dialog.d.ts +25 -0
  190. package/dist/ui/components/ui/dropdown-menu.d.ts +27 -0
  191. package/dist/ui/components/ui/feature-guide.d.ts +43 -0
  192. package/dist/ui/components/ui/form.d.ts +25 -0
  193. package/dist/ui/components/ui/help-tip.d.ts +29 -0
  194. package/dist/ui/components/ui/hint-notice.d.ts +22 -0
  195. package/dist/ui/components/ui/index.d.ts +6 -0
  196. package/dist/ui/components/ui/input.d.ts +3 -0
  197. package/dist/ui/components/ui/label.d.ts +5 -0
  198. package/dist/ui/components/ui/modal-container.d.ts +56 -0
  199. package/dist/ui/components/ui/modal-templates.d.ts +46 -0
  200. package/dist/ui/components/ui/multi-select.d.ts +20 -0
  201. package/dist/ui/components/ui/pagination.d.ts +28 -0
  202. package/dist/ui/components/ui/popover.d.ts +7 -0
  203. package/dist/ui/components/ui/progress.d.ts +7 -0
  204. package/dist/ui/components/ui/radio-button-group.d.ts +18 -0
  205. package/dist/ui/components/ui/radio-group.d.ts +5 -0
  206. package/dist/ui/components/ui/scroll-area.d.ts +5 -0
  207. package/dist/ui/components/ui/select.d.ts +16 -0
  208. package/dist/ui/components/ui/separator.d.ts +7 -0
  209. package/dist/ui/components/ui/sheet.d.ts +25 -0
  210. package/dist/ui/components/ui/sidebar-rail.d.ts +9 -0
  211. package/dist/ui/components/ui/skeleton.d.ts +2 -0
  212. package/dist/ui/components/ui/slider.d.ts +13 -0
  213. package/dist/ui/components/ui/switch.d.ts +4 -0
  214. package/dist/ui/components/ui/table.d.ts +10 -0
  215. package/dist/ui/components/ui/tabs.d.ts +10 -0
  216. package/dist/ui/components/ui/textarea.d.ts +3 -0
  217. package/dist/ui/components/ui/toast.d.ts +21 -0
  218. package/dist/ui/components/ui/toggle-group.d.ts +12 -0
  219. package/dist/ui/components/ui/toggle.d.ts +12 -0
  220. package/dist/ui/components/ui/tooltip.d.ts +7 -0
  221. package/dist/ui/components/ui/typography.d.ts +15 -0
  222. package/dist/ui/components/ui/underline-tabs.d.ts +13 -0
  223. package/dist/ui/components/ui/view-mode-toggle.d.ts +9 -0
  224. package/dist/ui/hooks/useIsMobile.d.ts +16 -0
  225. package/dist/ui/styles/design-tokens.d.ts +189 -0
  226. package/dist/ui/styles/z-index-layers.d.ts +46 -0
  227. package/dist/ui.d.ts +2 -0
  228. package/dist/ui.js +35 -0
  229. package/dist/ui.js.map +1 -0
  230. package/dist/useUserDirectory-CqkyCQoR.js +2377 -0
  231. package/dist/useUserDirectory-CqkyCQoR.js.map +1 -0
  232. package/dist/utils/cookieSettings.d.ts +12 -0
  233. package/dist/utils/data/countryCodes.d.ts +26 -0
  234. package/dist/utils/index.d.ts +18 -0
  235. package/dist/utils/utils/appPath.d.ts +5 -0
  236. package/dist/utils/utils/chunkLoadRecovery.d.ts +7 -0
  237. package/dist/utils/utils/cn.d.ts +3 -0
  238. package/dist/utils/utils/crossApp.d.ts +71 -0
  239. package/dist/utils/utils/debounce.d.ts +1 -0
  240. package/dist/utils/utils/formatUserLabel.d.ts +8 -0
  241. package/dist/utils/utils/formatting.d.ts +18 -0
  242. package/dist/utils/utils/logoutNotification.d.ts +28 -0
  243. package/dist/utils/utils/operatorLocale.d.ts +32 -0
  244. package/dist/utils/utils/routeLocalePrefetch.d.ts +5 -0
  245. package/dist/utils/utils/shellIframeUrl.d.ts +20 -0
  246. package/dist/utils/utils/spaceSettings.d.ts +20 -0
  247. package/dist/utils/utils/sso.d.ts +42 -0
  248. package/dist/utils/utils/throttle.d.ts +1 -0
  249. package/dist/utils/utils/timezones.d.ts +14 -0
  250. package/dist/utils/utils/toDateInputValue.d.ts +5 -0
  251. package/dist/utils/utils/watermark.d.ts +1 -0
  252. package/dist/utils.d.ts +1 -0
  253. package/dist/utils.js +1334 -0
  254. package/dist/utils.js.map +1 -0
  255. package/dist/vite.d.ts +22 -0
  256. package/dist/vite.js +74 -0
  257. package/dist/vite.js.map +1 -0
  258. package/package.json +191 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sources":["../src/storage/platformStorage.ts","../src/storage/copyTextToClipboard.ts","../src/storage/openUrlInNewTab.ts","../src/storage/assetPreview.ts","../src/storage/hooks/useAuthenticatedStorageBlobs.ts","../src/storage/hooks/useImageThumbnailBlobs.ts","../src/storage/hooks/useShareableStorageLink.ts","../src/storage/components/StorageImage.tsx","../src/storage/components/StorageVideo.tsx","../src/storage/components/AssetThumbnail.tsx","../src/storage/components/StoragePreviewContent.tsx","../src/storage/components/CopyStorageLinkButton.tsx"],"sourcesContent":["/** Minimal GeniSpace storage surface used by GeniApps. */\nexport interface StorageFileRecord {\n id: string;\n url: string;\n publicUrl?: string;\n mimeType?: string;\n}\n\nexport interface PlatformStorageClient {\n storage: {\n getFile(fileId: string): Promise<StorageFileRecord | { data?: StorageFileRecord }>;\n getFileContent(fileId: string): Promise<ArrayBuffer | ArrayBufferView>;\n };\n}\n\n/** SDK `get()` returns `{ success, data: file }` — unwrap to the file record. */\nexport function unwrapStorageFileRecord(raw: unknown): StorageFileRecord {\n if (!raw || typeof raw !== 'object') {\n throw new Error('Invalid storage file response');\n }\n const obj = raw as StorageFileRecord & { data?: StorageFileRecord };\n if (obj.data && typeof obj.data === 'object' && obj.data.id) {\n return obj.data;\n }\n if (obj.id) {\n return obj;\n }\n throw new Error('Invalid storage file response');\n}\n\nexport interface AuthenticatedBlobResult {\n blobUrl: string;\n revoke: () => void;\n}\n\nconst blobCache = new Map<string, { blobUrl: string; refCount: number }>();\n\n/** Normalize SDK binary payloads into a Blob-safe byte view (avoids Buffer pool slicing bugs). */\nfunction toBlobPart(data: ArrayBuffer | ArrayBufferView): BlobPart {\n if (data instanceof ArrayBuffer) {\n return data.slice(0);\n }\n const copy = new Uint8Array(data.byteLength);\n copy.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n return copy;\n}\n\n/** JWT-backed `/content` URLs cannot be used in `<img src>` — browser sends no Authorization header. */\nexport function isAuthenticatedStorageContentUrl(url: string | null | undefined): boolean {\n if (!url?.trim()) return false;\n return /\\/storage\\/files\\/[^/?#]+\\/content(?:[/?#]|$)/i.test(url.trim());\n}\n\n/** JWT-backed in-app preview: fetch /content and return a blob: URL. */\nexport async function fetchAuthenticatedBlobUrl(\n client: PlatformStorageClient,\n fileId: string,\n mimeType?: string\n): Promise<AuthenticatedBlobResult> {\n const cached = blobCache.get(fileId);\n if (cached) {\n cached.refCount += 1;\n return {\n blobUrl: cached.blobUrl,\n revoke: () => releaseBlobCache(fileId),\n };\n }\n\n const meta = unwrapStorageFileRecord(await client.storage.getFile(fileId));\n const content = await client.storage.getFileContent(fileId);\n const type = mimeType || meta.mimeType || 'application/octet-stream';\n const blob = new Blob([toBlobPart(content)], { type });\n const blobUrl = URL.createObjectURL(blob);\n blobCache.set(fileId, { blobUrl, refCount: 1 });\n\n return {\n blobUrl,\n revoke: () => releaseBlobCache(fileId),\n };\n}\n\nfunction releaseBlobCache(fileId: string): void {\n const entry = blobCache.get(fileId);\n if (!entry) return;\n entry.refCount -= 1;\n if (entry.refCount <= 0) {\n URL.revokeObjectURL(entry.blobUrl);\n blobCache.delete(fileId);\n }\n}\n\n/** Batch fetch blob URLs with limited concurrency. */\nexport async function resolveAuthenticatedBlobUrls(\n client: PlatformStorageClient,\n fileIds: string[],\n concurrency = 4\n): Promise<Record<string, string>> {\n const unique = [...new Set(fileIds.filter(Boolean))];\n const out: Record<string, string> = {};\n if (unique.length === 0) return out;\n\n let index = 0;\n async function worker() {\n while (index < unique.length) {\n const id = unique[index++];\n try {\n const { blobUrl } = await fetchAuthenticatedBlobUrl(client, id);\n out[id] = blobUrl;\n } catch {\n /* skip failed */\n }\n }\n }\n\n await Promise.all(Array.from({ length: Math.min(concurrency, unique.length) }, () => worker()));\n return out;\n}\n\n/** Share/copy/external HTTP: fresh signed publicUrl (TTL ~1h on server). */\nexport async function resolveShareablePublicUrl(\n client: PlatformStorageClient,\n fileId: string\n): Promise<string> {\n const file = unwrapStorageFileRecord(await client.storage.getFile(fileId));\n if (!file.publicUrl?.trim()) {\n throw new Error('Shareable public URL is not available for this file.');\n }\n return file.publicUrl;\n}\n\nexport async function resolveShareablePublicUrls(\n client: PlatformStorageClient,\n fileIds: string[]\n): Promise<Record<string, string>> {\n const unique = [...new Set(fileIds.filter(Boolean))];\n const out: Record<string, string> = {};\n await Promise.all(\n unique.map(async (id) => {\n try {\n out[id] = await resolveShareablePublicUrl(client, id);\n } catch {\n /* skip */\n }\n })\n );\n return out;\n}\n\n/** Pick blob URL for display, else external/content fallback. */\nexport function pickStorageDisplayUrl(\n storageFileId: string | null | undefined,\n fallbackUrl: string | null | undefined,\n blobUrls: Record<string, string>\n): string | null {\n if (storageFileId && blobUrls[storageFileId]) return blobUrls[storageFileId];\n const fallback = fallbackUrl?.trim();\n if (fallback && !isAuthenticatedStorageContentUrl(fallback)) return fallback;\n return null;\n}\n\n/** Persist content endpoint URL from upload response — never publicUrl. */\nexport function contentUrlFromUpload(file: { url: string; publicUrl?: string }): string {\n return file.url;\n}\n\nexport function createPlatformStorageHelpers(client: PlatformStorageClient) {\n return {\n fetchAuthenticatedBlobUrl: (fileId: string, mimeType?: string) =>\n fetchAuthenticatedBlobUrl(client, fileId, mimeType),\n resolveAuthenticatedBlobUrls: (fileIds: string[]) =>\n resolveAuthenticatedBlobUrls(client, fileIds),\n resolveShareablePublicUrl: (fileId: string) => resolveShareablePublicUrl(client, fileId),\n resolveShareablePublicUrls: (fileIds: string[]) => resolveShareablePublicUrls(client, fileIds),\n };\n}\n","function execCommandCopy(text: string): boolean {\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.left = '-9999px';\n textArea.style.opacity = '0';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n try {\n return document.execCommand('copy');\n } finally {\n document.body.removeChild(textArea);\n }\n}\n\nfunction canUseAsyncClipboardItem(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n typeof navigator.clipboard?.write === 'function' &&\n typeof ClipboardItem !== 'undefined'\n );\n}\n\n/**\n * Copy text while preserving the user-gesture window for async content.\n * Pass a Promise when the text is not yet available (e.g. after a network fetch).\n */\nexport async function copyTextToClipboard(textOrPromise: string | Promise<string>): Promise<void> {\n if (typeof textOrPromise === 'string') {\n await copyResolvedText(textOrPromise);\n return;\n }\n\n const textPromise = textOrPromise;\n\n if (canUseAsyncClipboardItem()) {\n try {\n const item = new ClipboardItem({\n 'text/plain': textPromise.then((text) => new Blob([text], { type: 'text/plain' })),\n });\n await navigator.clipboard.write([item]);\n await textPromise;\n return;\n } catch {\n /* fall through to resolved-text strategies */\n }\n }\n\n const text = await textPromise;\n await copyResolvedText(text);\n}\n\nasync function copyResolvedText(text: string): Promise<void> {\n if (navigator.clipboard?.writeText) {\n try {\n await navigator.clipboard.writeText(text);\n return;\n } catch {\n /* fall through */\n }\n }\n\n if (execCommandCopy(text)) return;\n\n throw new Error('Failed to copy to clipboard');\n}\n","function openUrlDirect(url: string): void {\n const opened = window.open(url, '_blank', 'noopener,noreferrer');\n if (opened) return;\n\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.target = '_blank';\n anchor.rel = 'noopener noreferrer';\n document.body.appendChild(anchor);\n anchor.click();\n document.body.removeChild(anchor);\n}\n\n/**\n * Open a URL in a new tab after async resolution.\n * Uses a synchronous `about:blank` popup (without `noopener`) so the opener can navigate it\n * once the URL is ready; then clears `opener` for security.\n */\nexport async function openUrlInNewTab(urlOrPromise: string | Promise<string>): Promise<string> {\n if (typeof urlOrPromise === 'string') {\n openUrlDirect(urlOrPromise);\n return urlOrPromise;\n }\n\n const popup = window.open('about:blank', '_blank');\n if (!popup) {\n throw new Error('Popup blocked. Allow popups for this site and try again.');\n }\n\n try {\n const url = await urlOrPromise;\n popup.location.replace(url);\n popup.opener = null;\n return url;\n } catch (err) {\n popup.close();\n throw err;\n }\n}\n","export type AssetPreviewKind = 'image' | 'video' | 'audio' | 'text' | 'download' | 'unknown';\n\nexport interface AssetPreviewInput {\n type?: string | null;\n format?: string | null;\n name?: string | null;\n url?: string | null;\n storage_file_id?: string | null;\n}\n\nconst IMAGE_EXTS = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg']);\nconst VIDEO_EXTS = new Set(['mp4', 'webm', 'ogg', 'mov', 'avi', 'mkv']);\nconst AUDIO_EXTS = new Set(['mp3', 'wav', 'm4a', 'aac', 'flac', 'ogg']);\nconst TEXT_EXTS = new Set(['txt', 'md', 'markdown', 'json', 'log', 'csv', 'xml']);\nconst DOWNLOAD_EXTS = new Set(['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'zip']);\n\nconst IMAGE_TYPES = new Set(['image', 'thumbnail', 'reference']);\nconst VIDEO_TYPES = new Set(['video_clip', 'final_video']);\nconst TEXT_TYPES = new Set(['script', 'subtitle']);\n\nfunction normalizeExt(value: string | null | undefined): string {\n if (!value?.trim()) return '';\n const cleaned = value.trim().toLowerCase().replace(/^\\./, '');\n return cleaned.split(/[?#]/)[0] ?? '';\n}\n\nfunction extFromName(name: string | null | undefined): string {\n if (!name?.trim()) return '';\n const base = name.trim().split('/').pop() ?? '';\n const dot = base.lastIndexOf('.');\n if (dot < 0) return '';\n return normalizeExt(base.slice(dot + 1));\n}\n\nfunction extFromUrl(url: string | null | undefined): string {\n if (!url?.trim()) return '';\n try {\n const pathname = new URL(url, 'https://placeholder.local').pathname;\n return extFromName(pathname);\n } catch {\n return extFromName(url);\n }\n}\n\nfunction resolveExt(input: AssetPreviewInput): string {\n return normalizeExt(input.format) || extFromName(input.name) || extFromUrl(input.url);\n}\n\nfunction hasPreviewSource(input: AssetPreviewInput): boolean {\n return Boolean(input.storage_file_id?.trim()) || Boolean(input.url?.trim());\n}\n\nconst EXT_TO_MIME: Record<string, string> = {\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n bmp: 'image/bmp',\n svg: 'image/svg+xml',\n mp4: 'video/mp4',\n webm: 'video/webm',\n mov: 'video/quicktime',\n avi: 'video/x-msvideo',\n mkv: 'video/x-matroska',\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n m4a: 'audio/mp4',\n aac: 'audio/aac',\n flac: 'audio/flac',\n txt: 'text/plain',\n md: 'text/markdown',\n markdown: 'text/markdown',\n json: 'application/json',\n csv: 'text/csv',\n xml: 'application/xml',\n pdf: 'application/pdf',\n};\n\n/** Infer preview category from asset type, format, and filename — not from blob URL suffix. */\nexport function inferAssetPreviewKind(input: AssetPreviewInput): AssetPreviewKind {\n if (!hasPreviewSource(input)) return 'unknown';\n\n const type = String(input.type ?? '').trim().toLowerCase();\n const ext = resolveExt(input);\n\n if (VIDEO_TYPES.has(type) || VIDEO_EXTS.has(ext)) return 'video';\n if (type === 'audio' || AUDIO_EXTS.has(ext)) return 'audio';\n if (TEXT_EXTS.has(ext) || (TEXT_TYPES.has(type) && !VIDEO_EXTS.has(ext) && !IMAGE_EXTS.has(ext))) {\n return 'text';\n }\n if (DOWNLOAD_EXTS.has(ext)) return 'download';\n if (IMAGE_TYPES.has(type) && ext && !VIDEO_EXTS.has(ext) && !AUDIO_EXTS.has(ext) && !TEXT_EXTS.has(ext)) {\n return IMAGE_EXTS.has(ext) || ext === '' ? 'image' : inferFromExtOnly(ext);\n }\n if (IMAGE_EXTS.has(ext)) return 'image';\n if (type === 'other' && ext) return inferFromExtOnly(ext);\n if (IMAGE_TYPES.has(type)) return 'image';\n return 'download';\n}\n\nfunction inferFromExtOnly(ext: string): AssetPreviewKind {\n if (IMAGE_EXTS.has(ext)) return 'image';\n if (VIDEO_EXTS.has(ext)) return 'video';\n if (AUDIO_EXTS.has(ext)) return 'audio';\n if (TEXT_EXTS.has(ext)) return 'text';\n if (DOWNLOAD_EXTS.has(ext)) return 'download';\n return 'download';\n}\n\nexport function inferMimeType(input: AssetPreviewInput): string {\n const ext = resolveExt(input);\n if (ext && EXT_TO_MIME[ext]) return EXT_TO_MIME[ext];\n\n const kind = inferAssetPreviewKind(input);\n switch (kind) {\n case 'image':\n return 'image/jpeg';\n case 'video':\n return 'video/mp4';\n case 'audio':\n return 'audio/mpeg';\n case 'text':\n return 'text/plain';\n default:\n return 'application/octet-stream';\n }\n}\n\nexport function isImagePreviewKind(kind: AssetPreviewKind): boolean {\n return kind === 'image';\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type { PlatformStorageClient } from '../platformStorage';\nimport { resolveAuthenticatedBlobUrls } from '../platformStorage';\n\nexport function useAuthenticatedStorageBlobs(\n client: PlatformStorageClient | null,\n storageFileIds: Array<string | null | undefined>\n): Record<string, string> {\n const ids = useMemo(\n () => [...new Set(storageFileIds.filter((id): id is string => Boolean(id?.trim())))],\n [storageFileIds]\n );\n const [blobUrls, setBlobUrls] = useState<Record<string, string>>({});\n\n useEffect(() => {\n if (!client || ids.length === 0) {\n setBlobUrls({});\n return;\n }\n let cancelled = false;\n void resolveAuthenticatedBlobUrls(client, ids).then((map) => {\n if (!cancelled) setBlobUrls(map);\n });\n return () => {\n cancelled = true;\n };\n }, [client, ids.join('|')]);\n\n return blobUrls;\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type { PlatformStorageClient } from '../platformStorage';\nimport { resolveAuthenticatedBlobUrls } from '../platformStorage';\nimport type { AssetPreviewInput } from '../assetPreview';\nimport { inferAssetPreviewKind, isImagePreviewKind } from '../assetPreview';\n\nexport function useImageThumbnailBlobs(\n client: PlatformStorageClient | null,\n items: AssetPreviewInput[]\n): Record<string, string> {\n const imageIds = useMemo(() => {\n const ids = new Set<string>();\n for (const item of items) {\n const id = item.storage_file_id?.trim();\n if (!id) continue;\n if (isImagePreviewKind(inferAssetPreviewKind(item))) ids.add(id);\n }\n return [...ids];\n }, [items]);\n\n const idKey = imageIds.join('|');\n const [blobUrls, setBlobUrls] = useState<Record<string, string>>({});\n\n useEffect(() => {\n if (!client || imageIds.length === 0) {\n setBlobUrls({});\n return;\n }\n let cancelled = false;\n void resolveAuthenticatedBlobUrls(client, imageIds).then((map) => {\n if (!cancelled) setBlobUrls(map);\n });\n return () => {\n cancelled = true;\n };\n }, [client, idKey]);\n\n return blobUrls;\n}\n","import { useCallback, useState } from 'react';\nimport { copyTextToClipboard } from '../copyTextToClipboard';\nimport { openUrlInNewTab } from '../openUrlInNewTab';\nimport type { PlatformStorageClient } from '../platformStorage';\nimport { resolveShareablePublicUrl } from '../platformStorage';\n\nexport function useShareableStorageLink(\n client: PlatformStorageClient | null,\n onError?: (message: string) => void\n) {\n const [loading, setLoading] = useState(false);\n\n const copyLink = useCallback(\n async (fileId: string): Promise<string | null> => {\n if (!client || !fileId.trim()) return null;\n setLoading(true);\n try {\n const urlPromise = resolveShareablePublicUrl(client, fileId);\n await copyTextToClipboard(urlPromise);\n return await urlPromise;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n onError?.(message);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [client, onError]\n );\n\n const openShareTab = useCallback(\n async (fileId: string): Promise<string | null> => {\n if (!client || !fileId.trim()) return null;\n setLoading(true);\n try {\n const urlPromise = resolveShareablePublicUrl(client, fileId);\n return await openUrlInNewTab(urlPromise);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n onError?.(message);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [client, onError]\n );\n\n return { copyLink, openShareTab, loading };\n}\n","import { pickStorageDisplayUrl } from '../platformStorage';\n\nimport type { ImgHTMLAttributes } from 'react';\n\ninterface StorageImageProps extends ImgHTMLAttributes<HTMLImageElement> {\n storageFileId?: string | null;\n fallbackUrl?: string | null;\n blobUrls: Record<string, string>;\n}\n\nexport function StorageImage({\n storageFileId,\n fallbackUrl,\n blobUrls,\n src,\n alt = '',\n ...rest\n}: StorageImageProps) {\n const resolved =\n pickStorageDisplayUrl(storageFileId, fallbackUrl ?? (typeof src === 'string' ? src : null), blobUrls) ??\n undefined;\n if (!resolved) return null;\n return <img src={resolved} alt={alt} {...rest} />;\n}\n","import { pickStorageDisplayUrl } from '../platformStorage';\n\nimport type { VideoHTMLAttributes } from 'react';\n\ninterface StorageVideoProps extends VideoHTMLAttributes<HTMLVideoElement> {\n storageFileId?: string | null;\n fallbackUrl?: string | null;\n blobUrls: Record<string, string>;\n}\n\nexport function StorageVideo({\n storageFileId,\n fallbackUrl,\n blobUrls,\n src,\n ...rest\n}: StorageVideoProps) {\n const resolved =\n pickStorageDisplayUrl(storageFileId, fallbackUrl ?? (typeof src === 'string' ? src : null), blobUrls) ??\n undefined;\n if (!resolved) return null;\n return <video src={resolved} {...rest} />;\n}\n","import type { MouseEvent, ReactNode } from 'react';\nimport { FileText, Film, Music, Play } from 'lucide-react';\nimport type { AssetPreviewInput } from '../assetPreview';\nimport { inferAssetPreviewKind } from '../assetPreview';\nimport { isAuthenticatedStorageContentUrl } from '../platformStorage';\nimport { StorageImage } from './StorageImage';\n\nexport type AssetThumbnailSize = 'sm' | 'md' | 'lg';\n\nconst SIZE_CLASS: Record<AssetThumbnailSize, string> = {\n sm: 'h-8 w-8',\n md: 'h-32 w-full',\n lg: 'h-40 w-full',\n};\n\nconst TYPE_EMOJI: Record<string, string> = {\n video_clip: '🎬',\n final_video: '🎥',\n image: '🖼️',\n audio: '🎵',\n script: '📄',\n subtitle: '💬',\n thumbnail: '🖼️',\n reference: '📎',\n other: '📁',\n};\n\nexport interface AssetThumbnailProps {\n asset: AssetPreviewInput & { name?: string | null; type?: string | null };\n blobUrls?: Record<string, string>;\n size?: AssetThumbnailSize;\n onClick?: () => void;\n className?: string;\n interactive?: boolean;\n}\n\nfunction Placeholder({\n children,\n size,\n className,\n onClick,\n interactive,\n label,\n}: {\n children: ReactNode;\n size: AssetThumbnailSize;\n className?: string;\n onClick?: () => void;\n interactive?: boolean;\n label?: string;\n}) {\n const clickable = Boolean(onClick && interactive !== false);\n return (\n <div\n role={clickable ? 'button' : undefined}\n tabIndex={clickable ? 0 : undefined}\n aria-label={clickable ? label : undefined}\n onClick={onClick}\n onKeyDown={\n clickable\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick?.();\n }\n }\n : undefined\n }\n className={`flex items-center justify-center bg-muted text-muted-foreground ${SIZE_CLASS[size]} ${clickable ? 'cursor-pointer hover:opacity-90' : ''} ${className ?? ''}`}\n >\n {children}\n </div>\n );\n}\n\nexport function AssetThumbnail({\n asset,\n blobUrls = {},\n size = 'md',\n onClick,\n className = '',\n interactive = true,\n}: AssetThumbnailProps) {\n const kind = inferAssetPreviewKind(asset);\n const label = asset.name?.trim() || 'Asset preview';\n\n const handleClick = (e?: MouseEvent) => {\n if (!onClick) return;\n e?.stopPropagation();\n onClick();\n };\n\n if (kind === 'image') {\n const blobUrl = asset.storage_file_id ? blobUrls[asset.storage_file_id] : undefined;\n const externalUrl =\n asset.url?.trim() && !isAuthenticatedStorageContentUrl(asset.url) ? asset.url.trim() : null;\n const resolved = blobUrl || externalUrl;\n const clickable = Boolean(onClick && interactive !== false);\n return (\n <div\n role={clickable ? 'button' : undefined}\n tabIndex={clickable ? 0 : undefined}\n aria-label={clickable ? label : undefined}\n onClick={() => handleClick()}\n onKeyDown={\n clickable\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick?.();\n }\n }\n : undefined\n }\n className={`relative overflow-hidden bg-muted ${SIZE_CLASS[size]} ${clickable ? 'cursor-pointer' : ''} ${className}`}\n >\n {resolved ? (\n <StorageImage\n storageFileId={asset.storage_file_id}\n fallbackUrl={asset.url}\n blobUrls={blobUrls}\n alt={label}\n className={`h-full w-full object-cover ${size === 'sm' ? 'rounded' : ''}`}\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center text-2xl\">\n {TYPE_EMOJI[asset.type ?? ''] ?? '🖼️'}\n </div>\n )}\n </div>\n );\n }\n\n if (kind === 'video') {\n return (\n <Placeholder\n size={size}\n className={`relative bg-neutral-900 text-white ${className}`}\n onClick={() => handleClick()}\n interactive={interactive}\n label={label}\n >\n <Film className={size === 'sm' ? 'h-4 w-4 opacity-70' : 'h-8 w-8 opacity-50'} />\n {size !== 'sm' && (\n <span className=\"absolute inset-0 flex items-center justify-center\">\n <Play className=\"h-10 w-10 fill-white/90 text-white/90\" />\n </span>\n )}\n </Placeholder>\n );\n }\n\n if (kind === 'audio') {\n return (\n <Placeholder\n size={size}\n className={className}\n onClick={() => handleClick()}\n interactive={interactive}\n label={label}\n >\n <Music className={size === 'sm' ? 'h-4 w-4' : 'h-8 w-8'} />\n </Placeholder>\n );\n }\n\n if (kind === 'text') {\n return (\n <Placeholder\n size={size}\n className={className}\n onClick={() => handleClick()}\n interactive={interactive}\n label={label}\n >\n <div className=\"flex flex-col items-center gap-1\">\n <FileText className={size === 'sm' ? 'h-4 w-4' : 'h-8 w-8'} />\n {size !== 'sm' && asset.format && (\n <span className=\"text-[10px] uppercase tracking-wide\">{asset.format}</span>\n )}\n </div>\n </Placeholder>\n );\n }\n\n return (\n <Placeholder\n size={size}\n className={className}\n onClick={() => handleClick()}\n interactive={interactive}\n label={label}\n >\n <span className={size === 'sm' ? 'text-base' : 'text-4xl'}>\n {TYPE_EMOJI[asset.type ?? ''] ?? '📁'}\n </span>\n </Placeholder>\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { Download, FileText } from 'lucide-react';\nimport type { AssetPreviewInput } from '../assetPreview';\nimport { inferAssetPreviewKind, inferMimeType } from '../assetPreview';\nimport {\n fetchAuthenticatedBlobUrl,\n pickStorageDisplayUrl,\n type PlatformStorageClient,\n} from '../platformStorage';\n\nexport interface StoragePreviewContentProps {\n open: boolean;\n asset: AssetPreviewInput & {\n name?: string | null;\n size_bytes?: number | null;\n format?: string | null;\n };\n client: PlatformStorageClient | null;\n blobUrls?: Record<string, string>;\n onDownload?: () => void | Promise<void>;\n labels?: {\n loading?: string;\n loadFailed?: string;\n downloadOnly?: string;\n download?: string;\n emptyText?: string;\n };\n}\n\nasync function loadPreviewUrl(\n client: PlatformStorageClient | null,\n asset: AssetPreviewInput,\n mimeType: string,\n existingBlob?: string | null\n): Promise<{ url: string; revoke?: () => void }> {\n if (existingBlob) {\n return { url: existingBlob };\n }\n const storageId = asset.storage_file_id?.trim();\n if (storageId && client) {\n const { blobUrl, revoke } = await fetchAuthenticatedBlobUrl(client, storageId, mimeType);\n return { url: blobUrl, revoke };\n }\n const external = asset.url?.trim();\n if (external && !external.startsWith('blob:')) {\n return { url: external };\n }\n throw new Error('Preview source unavailable');\n}\n\nexport function StoragePreviewContent({\n open,\n asset,\n client,\n blobUrls = {},\n onDownload,\n labels = {},\n}: StoragePreviewContentProps) {\n const kind = inferAssetPreviewKind(asset);\n const mimeType = inferMimeType(asset);\n const fileName = asset.name?.trim() || 'file';\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const [textContent, setTextContent] = useState<string>('');\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const revokeRef = useRef<(() => void) | null>(null);\n\n useEffect(() => {\n if (!open) {\n revokeRef.current?.();\n revokeRef.current = null;\n setPreviewUrl(null);\n setTextContent('');\n setLoading(false);\n setError(null);\n return;\n }\n\n let cancelled = false;\n setLoading(true);\n setError(null);\n\n const existingBlob = pickStorageDisplayUrl(asset.storage_file_id, asset.url, blobUrls);\n\n void (async () => {\n try {\n if (kind === 'download') {\n if (!cancelled) {\n setPreviewUrl(null);\n setLoading(false);\n }\n return;\n }\n\n const { url, revoke } = await loadPreviewUrl(client, asset, mimeType, existingBlob);\n if (cancelled) {\n revoke?.();\n return;\n }\n revokeRef.current?.();\n revokeRef.current = revoke ?? null;\n setPreviewUrl(url);\n\n if (kind === 'text') {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const text = await res.text();\n if (!cancelled) setTextContent(text);\n }\n } catch (e) {\n if (!cancelled) {\n setError(e instanceof Error ? e.message : String(e));\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n\n return () => {\n cancelled = true;\n revokeRef.current?.();\n revokeRef.current = null;\n };\n }, [open, asset.storage_file_id, asset.url, kind, mimeType, blobUrls, client]);\n\n if (loading) {\n return (\n <div className=\"min-h-[240px] animate-pulse space-y-4 p-6\" role=\"status\" aria-busy=\"true\">\n <div className=\"h-6 w-48 rounded bg-muted\" />\n <div className=\"h-40 w-full rounded-xl bg-muted\" />\n <div className=\"space-y-2\">\n <div className=\"h-4 w-4/5 rounded bg-muted\" />\n <div className=\"h-4 w-2/3 rounded bg-muted\" />\n </div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex min-h-[240px] flex-col items-center justify-center gap-3 p-8 text-center text-muted-foreground\">\n <p>{labels.loadFailed ?? 'Failed to load preview'}</p>\n <p className=\"text-sm\">{error}</p>\n </div>\n );\n }\n\n if (kind === 'image' && previewUrl) {\n return (\n <div className=\"flex min-h-[240px] items-center justify-center bg-neutral-950/5 p-4 dark:bg-neutral-950\">\n <img\n src={previewUrl}\n alt={fileName}\n className=\"max-h-[70vh] max-w-full rounded-lg object-contain shadow-lg\"\n />\n </div>\n );\n }\n\n if (kind === 'video' && previewUrl) {\n return (\n <div className=\"flex min-h-[240px] items-center justify-center bg-neutral-950 p-4\">\n <video controls className=\"max-h-[70vh] max-w-full rounded-lg shadow-lg\" src={previewUrl}>\n Video\n </video>\n </div>\n );\n }\n\n if (kind === 'audio' && previewUrl) {\n return (\n <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-4 p-8\">\n <p className=\"text-sm font-medium\">{fileName}</p>\n <audio controls className=\"w-full max-w-md\" src={previewUrl}>\n Audio\n </audio>\n </div>\n );\n }\n\n if (kind === 'text') {\n return (\n <div className=\"max-h-[70vh] overflow-auto p-4\">\n <pre className=\"whitespace-pre-wrap rounded-lg bg-muted p-4 font-mono text-sm\">\n {textContent || labels.emptyText || '(empty)'}\n </pre>\n </div>\n );\n }\n\n return (\n <div className=\"flex min-h-[240px] flex-col items-center justify-center gap-4 p-8 text-center\">\n <FileText className=\"h-12 w-12 text-muted-foreground\" />\n <div>\n <p className=\"font-medium\">{fileName}</p>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {labels.downloadOnly ?? 'Preview is not available for this file type.'}\n </p>\n </div>\n {onDownload && (\n <button\n type=\"button\"\n onClick={() => void onDownload()}\n className=\"inline-flex items-center gap-2 rounded-lg bg-rose-600 px-4 py-2 text-sm font-medium text-white hover:bg-rose-700\"\n >\n <Download className=\"h-4 w-4\" />\n {labels.download ?? 'Download'}\n </button>\n )}\n </div>\n );\n}\n","import { Copy, Check, ExternalLink } from 'lucide-react';\nimport { useState } from 'react';\nimport { useShareableStorageLink } from '../hooks/useShareableStorageLink';\nimport type { PlatformStorageClient } from '../platformStorage';\n\ninterface CopyStorageLinkButtonProps {\n client: PlatformStorageClient | null;\n storageFileId: string | null | undefined;\n copyLabel?: string;\n openLabel?: string;\n expiryHint?: string;\n className?: string;\n onError?: (message: string) => void;\n}\n\nexport function CopyStorageLinkButton({\n client,\n storageFileId,\n copyLabel = 'Copy link',\n openLabel = 'Open share link',\n expiryHint = 'Link valid ~1 hour',\n className = '',\n onError,\n}: CopyStorageLinkButtonProps) {\n const { copyLink, openShareTab, loading } = useShareableStorageLink(client, onError);\n const [copied, setCopied] = useState(false);\n\n if (!storageFileId?.trim()) return null;\n\n const disabled = loading || !client;\n\n async function handleCopy() {\n const url = await copyLink(storageFileId!);\n if (url) {\n setCopied(true);\n window.setTimeout(() => setCopied(false), 2000);\n }\n }\n\n return (\n <div className={`flex items-center gap-1 ${className}`}>\n <button\n type=\"button\"\n disabled={disabled}\n title={copied ? 'Copied' : client ? expiryHint : 'Session not ready'}\n onClick={() => void handleCopy()}\n className=\"rounded-lg border border-border p-2 text-muted-foreground hover:bg-accent disabled:opacity-60\"\n aria-label={copyLabel}\n >\n {copied ? <Check className=\"h-4 w-4 text-emerald-600\" /> : <Copy className=\"h-4 w-4\" />}\n </button>\n <button\n type=\"button\"\n disabled={disabled}\n title={client ? expiryHint : 'Session not ready'}\n onClick={() => void openShareTab(storageFileId)}\n className=\"rounded-lg border border-border p-2 text-muted-foreground hover:bg-accent disabled:opacity-60\"\n aria-label={openLabel}\n >\n <ExternalLink className=\"h-4 w-4\" />\n </button>\n </div>\n );\n}\n"],"names":["unwrapStorageFileRecord","raw","obj","blobCache","toBlobPart","data","copy","isAuthenticatedStorageContentUrl","url","fetchAuthenticatedBlobUrl","client","fileId","mimeType","cached","releaseBlobCache","meta","content","type","blob","blobUrl","entry","resolveAuthenticatedBlobUrls","fileIds","concurrency","unique","out","index","worker","id","resolveShareablePublicUrl","file","resolveShareablePublicUrls","pickStorageDisplayUrl","storageFileId","fallbackUrl","blobUrls","fallback","contentUrlFromUpload","createPlatformStorageHelpers","execCommandCopy","text","textArea","canUseAsyncClipboardItem","copyTextToClipboard","textOrPromise","copyResolvedText","textPromise","item","openUrlDirect","anchor","openUrlInNewTab","urlOrPromise","popup","err","IMAGE_EXTS","VIDEO_EXTS","AUDIO_EXTS","TEXT_EXTS","DOWNLOAD_EXTS","IMAGE_TYPES","VIDEO_TYPES","TEXT_TYPES","normalizeExt","value","extFromName","name","base","dot","extFromUrl","pathname","resolveExt","input","hasPreviewSource","EXT_TO_MIME","inferAssetPreviewKind","ext","inferFromExtOnly","inferMimeType","isImagePreviewKind","kind","useAuthenticatedStorageBlobs","storageFileIds","ids","useMemo","setBlobUrls","useState","useEffect","cancelled","map","useImageThumbnailBlobs","items","imageIds","idKey","useShareableStorageLink","onError","loading","setLoading","copyLink","useCallback","urlPromise","message","openShareTab","StorageImage","src","alt","rest","resolved","StorageVideo","jsx","SIZE_CLASS","TYPE_EMOJI","Placeholder","children","size","className","onClick","interactive","label","clickable","e","AssetThumbnail","asset","handleClick","externalUrl","jsxs","Film","Play","Music","FileText","loadPreviewUrl","existingBlob","storageId","revoke","external","StoragePreviewContent","open","onDownload","labels","fileName","previewUrl","setPreviewUrl","textContent","setTextContent","error","setError","revokeRef","useRef","res","Download","CopyStorageLinkButton","copyLabel","openLabel","expiryHint","copied","setCopied","disabled","handleCopy","Check","Copy","ExternalLink"],"mappings":"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"}
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .gs-calendar-single.rdp .rdp-cell:has([aria-selected]){border-radius:.375rem}