@burdenoff/microfe-files 2026.525.2 → 2026.527.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/dist/files/components/ActionMenu.js +3 -1
  2. package/dist/files/components/ActionMenu.js.map +1 -1
  3. package/dist/files/components/ContextMenu.js +16 -112
  4. package/dist/files/components/ContextMenu.js.map +1 -1
  5. package/dist/files/components/CopyDialog.js +8 -0
  6. package/dist/files/components/CopyDialog.js.map +1 -1
  7. package/dist/files/components/EmptyState.js +2 -0
  8. package/dist/files/components/EmptyState.js.map +1 -1
  9. package/dist/files/components/FileBrowser.js +6 -1
  10. package/dist/files/components/FileBrowser.js.map +1 -1
  11. package/dist/files/components/FileCard.js +4 -0
  12. package/dist/files/components/FileCard.js.map +1 -1
  13. package/dist/files/components/FileInfoPanel.js +2 -0
  14. package/dist/files/components/FileInfoPanel.js.map +1 -1
  15. package/dist/files/components/FileListItem.js +6 -0
  16. package/dist/files/components/FileListItem.js.map +1 -1
  17. package/dist/files/components/FilePreviewModal.js +9 -3
  18. package/dist/files/components/FilePreviewModal.js.map +1 -1
  19. package/dist/files/components/FileVersionPanel.js +5 -0
  20. package/dist/files/components/FileVersionPanel.js.map +1 -1
  21. package/dist/files/components/FolderCard.js +3 -0
  22. package/dist/files/components/FolderCard.js.map +1 -1
  23. package/dist/files/components/MoveDialog.js +8 -0
  24. package/dist/files/components/MoveDialog.js.map +1 -1
  25. package/dist/files/components/SearchBar.js +4 -0
  26. package/dist/files/components/SearchBar.js.map +1 -1
  27. package/dist/files/components/ShareDialog.js +109 -104
  28. package/dist/files/components/ShareDialog.js.map +1 -1
  29. package/dist/files/components/TabBar.js +1 -0
  30. package/dist/files/components/TabBar.js.map +1 -1
  31. package/dist/files/components/Toast.js +1 -0
  32. package/dist/files/components/Toast.js.map +1 -1
  33. package/dist/files/components/UploadQueue.js +5 -0
  34. package/dist/files/components/UploadQueue.js.map +1 -1
  35. package/dist/files/components/contextMenuItems.js +103 -0
  36. package/dist/files/components/contextMenuItems.js.map +1 -0
  37. package/dist/files/components/viewers/AudioPlayer.js +4 -1
  38. package/dist/files/components/viewers/AudioPlayer.js.map +1 -1
  39. package/dist/files/components/viewers/CodeViewer.js +2 -0
  40. package/dist/files/components/viewers/CodeViewer.js.map +1 -1
  41. package/dist/files/components/viewers/ImageViewer.js +4 -0
  42. package/dist/files/components/viewers/ImageViewer.js.map +1 -1
  43. package/dist/files/components/viewers/PDFViewer.js +2 -0
  44. package/dist/files/components/viewers/PDFViewer.js.map +1 -1
  45. package/dist/files/components/viewers/TextViewer.js +4 -2
  46. package/dist/files/components/viewers/TextViewer.js.map +1 -1
  47. package/dist/files/components/viewers/VideoPlayer.js +5 -1
  48. package/dist/files/components/viewers/VideoPlayer.js.map +1 -1
  49. package/dist/files/hooks/useBatchOperations.js.map +1 -1
  50. package/dist/files/hooks/useFileVersions.js.map +1 -1
  51. package/dist/files/pages/BrowserPage.js +18 -2
  52. package/dist/files/pages/BrowserPage.js.map +1 -1
  53. package/dist/files/pages/ShareAccessPage.js +6 -5
  54. package/dist/files/pages/ShareAccessPage.js.map +1 -1
  55. package/dist/files/utils/index.js +1 -1
  56. package/dist/files/utils/index.js.map +1 -1
  57. package/dist/files/utils/thumbnail.js.map +1 -1
  58. package/dist/files.js +2 -1
  59. package/dist/translations/en.js +259 -0
  60. package/dist/translations/en.js.map +1 -0
  61. package/package.json +1 -4
  62. package/dist/config/index.d.ts +0 -33
  63. package/dist/config/index.d.ts.map +0 -1
  64. package/dist/dev/main.d.ts +0 -1
  65. package/dist/dev/main.d.ts.map +0 -1
  66. package/dist/files/FilesRoot.d.ts +0 -31
  67. package/dist/files/FilesRoot.d.ts.map +0 -1
  68. package/dist/files/FilesRoutes.d.ts +0 -12
  69. package/dist/files/FilesRoutes.d.ts.map +0 -1
  70. package/dist/files/components/ActionMenu.d.ts +0 -19
  71. package/dist/files/components/ActionMenu.d.ts.map +0 -1
  72. package/dist/files/components/ConfirmDialog.d.ts +0 -14
  73. package/dist/files/components/ConfirmDialog.d.ts.map +0 -1
  74. package/dist/files/components/ContextMenu.d.ts +0 -59
  75. package/dist/files/components/ContextMenu.d.ts.map +0 -1
  76. package/dist/files/components/CopyDialog.d.ts +0 -12
  77. package/dist/files/components/CopyDialog.d.ts.map +0 -1
  78. package/dist/files/components/EmptyState.d.ts +0 -8
  79. package/dist/files/components/EmptyState.d.ts.map +0 -1
  80. package/dist/files/components/FileBrowser.d.ts +0 -37
  81. package/dist/files/components/FileBrowser.d.ts.map +0 -1
  82. package/dist/files/components/FileCard.d.ts +0 -30
  83. package/dist/files/components/FileCard.d.ts.map +0 -1
  84. package/dist/files/components/FileInfoPanel.d.ts +0 -9
  85. package/dist/files/components/FileInfoPanel.d.ts.map +0 -1
  86. package/dist/files/components/FileListItem.d.ts +0 -29
  87. package/dist/files/components/FileListItem.d.ts.map +0 -1
  88. package/dist/files/components/FilePreviewModal.d.ts +0 -17
  89. package/dist/files/components/FilePreviewModal.d.ts.map +0 -1
  90. package/dist/files/components/FileVersionPanel.d.ts +0 -9
  91. package/dist/files/components/FileVersionPanel.d.ts.map +0 -1
  92. package/dist/files/components/FolderCard.d.ts +0 -34
  93. package/dist/files/components/FolderCard.d.ts.map +0 -1
  94. package/dist/files/components/MoveDialog.d.ts +0 -12
  95. package/dist/files/components/MoveDialog.d.ts.map +0 -1
  96. package/dist/files/components/SearchBar.d.ts +0 -13
  97. package/dist/files/components/SearchBar.d.ts.map +0 -1
  98. package/dist/files/components/ShareDialog.d.ts +0 -24
  99. package/dist/files/components/ShareDialog.d.ts.map +0 -1
  100. package/dist/files/components/TabBar.d.ts +0 -14
  101. package/dist/files/components/TabBar.d.ts.map +0 -1
  102. package/dist/files/components/Toast.d.ts +0 -14
  103. package/dist/files/components/Toast.d.ts.map +0 -1
  104. package/dist/files/components/UploadQueue.d.ts +0 -21
  105. package/dist/files/components/UploadQueue.d.ts.map +0 -1
  106. package/dist/files/components/index.d.ts +0 -43
  107. package/dist/files/components/index.d.ts.map +0 -1
  108. package/dist/files/components/viewers/AudioPlayer.d.ts +0 -8
  109. package/dist/files/components/viewers/AudioPlayer.d.ts.map +0 -1
  110. package/dist/files/components/viewers/CodeViewer.d.ts +0 -16
  111. package/dist/files/components/viewers/CodeViewer.d.ts.map +0 -1
  112. package/dist/files/components/viewers/ImageViewer.d.ts +0 -8
  113. package/dist/files/components/viewers/ImageViewer.d.ts.map +0 -1
  114. package/dist/files/components/viewers/PDFViewer.d.ts +0 -15
  115. package/dist/files/components/viewers/PDFViewer.d.ts.map +0 -1
  116. package/dist/files/components/viewers/TextViewer.d.ts +0 -8
  117. package/dist/files/components/viewers/TextViewer.d.ts.map +0 -1
  118. package/dist/files/components/viewers/VideoPlayer.d.ts +0 -8
  119. package/dist/files/components/viewers/VideoPlayer.d.ts.map +0 -1
  120. package/dist/files/components/viewers/index.d.ts +0 -7
  121. package/dist/files/components/viewers/index.d.ts.map +0 -1
  122. package/dist/files/components/viewers/index.js +0 -6
  123. package/dist/files/graphql-types.d.ts +0 -317
  124. package/dist/files/graphql-types.d.ts.map +0 -1
  125. package/dist/files/hooks/useBatchOperations.d.ts +0 -32
  126. package/dist/files/hooks/useBatchOperations.d.ts.map +0 -1
  127. package/dist/files/hooks/useBinItems.d.ts +0 -11
  128. package/dist/files/hooks/useBinItems.d.ts.map +0 -1
  129. package/dist/files/hooks/useBrowsePage.d.ts +0 -18
  130. package/dist/files/hooks/useBrowsePage.d.ts.map +0 -1
  131. package/dist/files/hooks/useCopyFile.d.ts +0 -14
  132. package/dist/files/hooks/useCopyFile.d.ts.map +0 -1
  133. package/dist/files/hooks/useCreateFolder.d.ts +0 -14
  134. package/dist/files/hooks/useCreateFolder.d.ts.map +0 -1
  135. package/dist/files/hooks/useCreateFolderShare.d.ts +0 -16
  136. package/dist/files/hooks/useCreateFolderShare.d.ts.map +0 -1
  137. package/dist/files/hooks/useCreateShare.d.ts +0 -16
  138. package/dist/files/hooks/useCreateShare.d.ts.map +0 -1
  139. package/dist/files/hooks/useDeleteFile.d.ts +0 -9
  140. package/dist/files/hooks/useDeleteFile.d.ts.map +0 -1
  141. package/dist/files/hooks/useDeleteFolder.d.ts +0 -10
  142. package/dist/files/hooks/useDeleteFolder.d.ts.map +0 -1
  143. package/dist/files/hooks/useDragDrop.d.ts +0 -31
  144. package/dist/files/hooks/useDragDrop.d.ts.map +0 -1
  145. package/dist/files/hooks/useFileVersions.d.ts +0 -52
  146. package/dist/files/hooks/useFileVersions.d.ts.map +0 -1
  147. package/dist/files/hooks/useFiles.d.ts +0 -18
  148. package/dist/files/hooks/useFiles.d.ts.map +0 -1
  149. package/dist/files/hooks/useFolder.d.ts +0 -7
  150. package/dist/files/hooks/useFolder.d.ts.map +0 -1
  151. package/dist/files/hooks/useFolderPath.d.ts +0 -2
  152. package/dist/files/hooks/useFolderPath.d.ts.map +0 -1
  153. package/dist/files/hooks/useFoldersQuery.d.ts +0 -7
  154. package/dist/files/hooks/useFoldersQuery.d.ts.map +0 -1
  155. package/dist/files/hooks/useKeyboardNavigation.d.ts +0 -17
  156. package/dist/files/hooks/useKeyboardNavigation.d.ts.map +0 -1
  157. package/dist/files/hooks/useMoveFile.d.ts +0 -10
  158. package/dist/files/hooks/useMoveFile.d.ts.map +0 -1
  159. package/dist/files/hooks/useMoveFolder.d.ts +0 -10
  160. package/dist/files/hooks/useMoveFolder.d.ts.map +0 -1
  161. package/dist/files/hooks/usePermanentlyDeleteFile.d.ts +0 -9
  162. package/dist/files/hooks/usePermanentlyDeleteFile.d.ts.map +0 -1
  163. package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts +0 -9
  164. package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts.map +0 -1
  165. package/dist/files/hooks/useRecentFiles.d.ts +0 -10
  166. package/dist/files/hooks/useRecentFiles.d.ts.map +0 -1
  167. package/dist/files/hooks/useRenameFile.d.ts +0 -10
  168. package/dist/files/hooks/useRenameFile.d.ts.map +0 -1
  169. package/dist/files/hooks/useRenameFolder.d.ts +0 -10
  170. package/dist/files/hooks/useRenameFolder.d.ts.map +0 -1
  171. package/dist/files/hooks/useRestoreFile.d.ts +0 -9
  172. package/dist/files/hooks/useRestoreFile.d.ts.map +0 -1
  173. package/dist/files/hooks/useRestoreFolder.d.ts +0 -9
  174. package/dist/files/hooks/useRestoreFolder.d.ts.map +0 -1
  175. package/dist/files/hooks/useSearch.d.ts +0 -15
  176. package/dist/files/hooks/useSearch.d.ts.map +0 -1
  177. package/dist/files/hooks/useStarredItems.d.ts +0 -10
  178. package/dist/files/hooks/useStarredItems.d.ts.map +0 -1
  179. package/dist/files/hooks/useToast.d.ts +0 -11
  180. package/dist/files/hooks/useToast.d.ts.map +0 -1
  181. package/dist/files/hooks/useToggleStar.d.ts +0 -10
  182. package/dist/files/hooks/useToggleStar.d.ts.map +0 -1
  183. package/dist/files/hooks/useUploadFile.d.ts +0 -25
  184. package/dist/files/hooks/useUploadFile.d.ts.map +0 -1
  185. package/dist/files/index.d.ts +0 -29
  186. package/dist/files/index.d.ts.map +0 -1
  187. package/dist/files/pages/BrowserPage.d.ts +0 -5
  188. package/dist/files/pages/BrowserPage.d.ts.map +0 -1
  189. package/dist/files/pages/ShareAccessPage.d.ts +0 -2
  190. package/dist/files/pages/ShareAccessPage.d.ts.map +0 -1
  191. package/dist/files/providers/FilesProvider.d.ts +0 -25
  192. package/dist/files/providers/FilesProvider.d.ts.map +0 -1
  193. package/dist/files/store/filesStore.d.ts +0 -99
  194. package/dist/files/store/filesStore.d.ts.map +0 -1
  195. package/dist/files/types.d.ts +0 -266
  196. package/dist/files/types.d.ts.map +0 -1
  197. package/dist/files/utils/events.d.ts +0 -6
  198. package/dist/files/utils/events.d.ts.map +0 -1
  199. package/dist/files/utils/i18n.d.ts +0 -5
  200. package/dist/files/utils/i18n.d.ts.map +0 -1
  201. package/dist/files/utils/index.d.ts +0 -74
  202. package/dist/files/utils/index.d.ts.map +0 -1
  203. package/dist/files/utils/thumbnail.d.ts +0 -5
  204. package/dist/files/utils/thumbnail.d.ts.map +0 -1
  205. package/dist/files.d.ts +0 -2
  206. package/dist/generated/global-operations.d.ts +0 -2
  207. package/dist/generated/global-operations.d.ts.map +0 -1
  208. package/dist/generated/global-types.d.ts +0 -23527
  209. package/dist/generated/global-types.d.ts.map +0 -1
  210. package/dist/generated/wspace-operations.d.ts +0 -2706
  211. package/dist/generated/wspace-operations.d.ts.map +0 -1
  212. package/dist/generated/wspace-types.d.ts +0 -57851
  213. package/dist/generated/wspace-types.d.ts.map +0 -1
  214. package/dist/index.d.ts +0 -30
  215. package/dist/index.d.ts.map +0 -1
  216. package/dist/shared/types/index.d.ts +0 -101
  217. package/dist/shared/types/index.d.ts.map +0 -1
  218. package/dist/translations/en.d.ts +0 -315
  219. package/dist/translations/en.d.ts.map +0 -1
  220. package/dist/utils/nativeBridge.d.ts +0 -3
  221. package/dist/utils/nativeBridge.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SearchBar.js","names":[],"sources":["../../../src/files/components/SearchBar.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { Search, X, Filter } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileFilterInput, FolderFilterInput } from \"../graphql-types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface SearchBarProps {\n onSearch: (\n query: string,\n filters?: {\n fileFilter?: FileFilterInput;\n folderFilter?: FolderFilterInput;\n },\n ) => void;\n placeholder?: string;\n initialQuery?: string;\n showFilters?: boolean;\n}\n\nconst FILE_TYPE_MIME_MAP: Record<string, string[]> = {\n image: [\n \"image/jpeg\",\n \"image/png\",\n \"image/gif\",\n \"image/webp\",\n \"image/svg+xml\",\n ],\n video: [\"video/mp4\", \"video/webm\", \"video/quicktime\"],\n document: [\n \"application/msword\",\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n \"application/vnd.ms-excel\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n \"application/vnd.ms-powerpoint\",\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n \"text/plain\",\n \"text/csv\",\n \"application/json\",\n ],\n pdf: [\"application/pdf\"],\n archive: [\n \"application/zip\",\n \"application/x-tar\",\n \"application/x-7z-compressed\",\n \"application/gzip\",\n \"application/x-rar-compressed\",\n ],\n};\n\nexport function SearchBar({\n onSearch,\n placeholder = \"Search files and folders...\",\n initialQuery = \"\",\n showFilters = true,\n}: SearchBarProps) {\n const { t } = useI18n();\n const [query, setQuery] = useState(initialQuery);\n const [showFilterPanel, setShowFilterPanel] = useState(false);\n const [filters, setFilters] = useState<{\n fileType?: string;\n status?: string;\n visibility?: string;\n starred?: boolean;\n }>({});\n const fileStatus = filters.status as FileFilterInput[\"status\"] | undefined;\n const folderStatus = filters.status as\n | FolderFilterInput[\"status\"]\n | undefined;\n const fileVisibility = filters.visibility as\n | FileFilterInput[\"visibility\"]\n | undefined;\n const fileMimeTypes = filters.fileType\n ? FILE_TYPE_MIME_MAP[filters.fileType]\n : undefined;\n\n useEffect(() => {\n setQuery(initialQuery);\n }, [initialQuery]);\n\n // Debounced search\n useEffect(() => {\n const timer = setTimeout(() => {\n if (query.length >= 2 || query.length === 0) {\n const fileFilter: FileFilterInput = {\n ...(fileMimeTypes && { mimeTypes: fileMimeTypes }),\n ...(fileStatus && { status: fileStatus }),\n ...(fileVisibility && { visibility: fileVisibility }),\n ...(filters.starred !== undefined && { starred: filters.starred }),\n };\n\n const folderFilter: FolderFilterInput = {\n ...(folderStatus && { status: folderStatus }),\n ...(filters.starred !== undefined && { starred: filters.starred }),\n };\n\n onSearch(query, { fileFilter, folderFilter });\n }\n }, 300);\n\n return () => clearTimeout(timer);\n }, [\n fileStatus,\n fileMimeTypes,\n fileVisibility,\n folderStatus,\n filters,\n onSearch,\n query,\n ]);\n\n const handleClear = useCallback(() => {\n setQuery(\"\");\n setFilters({});\n onSearch(\"\");\n }, [onSearch]);\n\n const activeFilterCount = Object.values(filters).filter(\n (v) => v !== undefined,\n ).length;\n\n return (\n <div className=\"relative\">\n {/* Search Input */}\n <div className=\"relative flex items-center\">\n <Search className=\"absolute left-3 size-4 text-text-tertiary\" />\n <label htmlFor=\"files-search-input\" className=\"sr-only\">\n {tWithFallback(\n t,\n \"files.search.input.label\",\n \"Search files and folders\",\n )}\n </label>\n <input\n id=\"files-search-input\"\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={placeholder}\n className=\"w-full pl-[3.25rem] pr-20 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border focus:border-action-primary-border transition-colors duration-200\"\n />\n <div className=\"absolute right-2 flex items-center gap-1\">\n {query && (\n <button\n onClick={handleClear}\n className=\"p-1.5 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title={tWithFallback(\n t,\n \"files.search.actions.clearSearch\",\n \"Clear search\",\n )}\n aria-label={tWithFallback(\n t,\n \"files.search.actions.clearSearch\",\n \"Clear search\",\n )}\n >\n <X className=\"size-4\" />\n </button>\n )}\n {showFilters && (\n <button\n onClick={() => setShowFilterPanel(!showFilterPanel)}\n aria-expanded={showFilterPanel}\n aria-controls=\"files-search-filter-panel\"\n aria-label={tWithFallback(\n t,\n \"files.search.filters.toggleAria\",\n \"Toggle filters\",\n )}\n className={`p-1.5 rounded transition-colors duration-200 relative ${\n showFilterPanel || activeFilterCount > 0\n ? \"text-text-link bg-bg-accent hover:bg-action-primary-bg/20\"\n : \"text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover\"\n }`}\n title={tWithFallback(t, \"files.search.filters.title\", \"Filters\")}\n >\n <Filter className=\"size-4\" />\n {activeFilterCount > 0 && (\n <span className=\"absolute -top-1 -right-1 size-4 bg-action-primary-bg text-text-inverse text-[10px] font-bold rounded-full flex items-center justify-center\">\n {activeFilterCount}\n </span>\n )}\n </button>\n )}\n </div>\n </div>\n\n {/* Filter Panel */}\n {showFilterPanel && (\n <div\n id=\"files-search-filter-panel\"\n className=\"absolute top-full left-0 right-0 mt-2 p-4 bg-bg-surface border border-border-default rounded-lg shadow-lg z-10 animate-in fade-in duration-200\"\n >\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.label\",\n \"File Type\",\n )}\n </label>\n <select\n value={filters.fileType || \"\"}\n onChange={(e) =>\n setFilters({\n ...filters,\n fileType: e.target.value || undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border transition-colors duration-200\"\n >\n <option value=\"\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.all\",\n \"All types\",\n )}\n </option>\n <option value=\"image\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.image\",\n \"Images\",\n )}\n </option>\n <option value=\"video\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.video\",\n \"Videos\",\n )}\n </option>\n <option value=\"document\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.document\",\n \"Documents\",\n )}\n </option>\n <option value=\"pdf\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.pdf\",\n \"PDFs\",\n )}\n </option>\n <option value=\"archive\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.archive\",\n \"Archives\",\n )}\n </option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tWithFallback(\n t,\n \"files.search.filters.status.label\",\n \"Status\",\n )}\n </label>\n <select\n value={filters.status || \"\"}\n onChange={(e) =>\n setFilters({\n ...filters,\n status: e.target.value || undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border transition-colors duration-200\"\n >\n <option value=\"\">\n {tWithFallback(\n t,\n \"files.search.filters.status.options.all\",\n \"All statuses\",\n )}\n </option>\n <option value=\"ACTIVE\">\n {tWithFallback(\n t,\n \"files.search.filters.status.options.active\",\n \"Active\",\n )}\n </option>\n <option value=\"ARCHIVED\">\n {tWithFallback(\n t,\n \"files.search.filters.status.options.archived\",\n \"Archived\",\n )}\n </option>\n <option value=\"DELETED\">\n {tWithFallback(\n t,\n \"files.search.filters.status.options.deleted\",\n \"Deleted\",\n )}\n </option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.label\",\n \"Visibility\",\n )}\n </label>\n <select\n value={filters.visibility || \"\"}\n onChange={(e) =>\n setFilters({\n ...filters,\n visibility: e.target.value || undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border transition-colors duration-200\"\n >\n <option value=\"\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.all\",\n \"All visibility\",\n )}\n </option>\n <option value=\"PRIVATE\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.private\",\n \"Private\",\n )}\n </option>\n <option value=\"TEAM\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.team\",\n \"Team\",\n )}\n </option>\n <option value=\"WORKSPACE\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.workspace\",\n \"Workspace\",\n )}\n </option>\n <option value=\"PUBLIC\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.public\",\n \"Public\",\n )}\n </option>\n </select>\n </div>\n\n <div className=\"flex items-center\">\n <input\n type=\"checkbox\"\n id=\"starred-filter\"\n checked={filters.starred || false}\n onChange={(e) =>\n setFilters({\n ...filters,\n starred: e.target.checked || undefined,\n })\n }\n className=\"size-4 text-action-primary-bg border-border-default rounded focus:ring-action-primary-border transition-colors duration-200\"\n />\n <label\n htmlFor=\"starred-filter\"\n className=\"ml-2 text-sm text-text-primary\"\n >\n {tWithFallback(\n t,\n \"files.search.filters.starredOnly\",\n \"Starred only\",\n )}\n </label>\n </div>\n\n <div className=\"flex justify-end gap-2 pt-2 border-t border-border-default\">\n <button\n onClick={() => {\n setFilters({});\n setShowFilterPanel(false);\n }}\n className=\"px-3 py-1.5 text-sm text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n >\n {tWithFallback(\n t,\n \"files.search.filters.actions.clear\",\n \"Clear filters\",\n )}\n </button>\n <button\n onClick={() => setShowFilterPanel(false)}\n className=\"px-3 py-1.5 text-sm bg-action-primary-bg text-text-inverse rounded hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {tWithFallback(\n t,\n \"files.search.filters.actions.apply\",\n \"Apply\",\n )}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SearchBar.js","names":[],"sources":["../../../src/files/components/SearchBar.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { Search, X, Filter } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileFilterInput, FolderFilterInput } from \"../graphql-types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface SearchBarProps {\n onSearch: (\n query: string,\n filters?: {\n fileFilter?: FileFilterInput;\n folderFilter?: FolderFilterInput;\n },\n ) => void;\n placeholder?: string;\n initialQuery?: string;\n showFilters?: boolean;\n}\n\nconst FILE_TYPE_MIME_MAP: Record<string, string[]> = {\n image: [\n \"image/jpeg\",\n \"image/png\",\n \"image/gif\",\n \"image/webp\",\n \"image/svg+xml\",\n ],\n video: [\"video/mp4\", \"video/webm\", \"video/quicktime\"],\n document: [\n \"application/msword\",\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n \"application/vnd.ms-excel\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n \"application/vnd.ms-powerpoint\",\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n \"text/plain\",\n \"text/csv\",\n \"application/json\",\n ],\n pdf: [\"application/pdf\"],\n archive: [\n \"application/zip\",\n \"application/x-tar\",\n \"application/x-7z-compressed\",\n \"application/gzip\",\n \"application/x-rar-compressed\",\n ],\n};\n\nexport function SearchBar({\n onSearch,\n placeholder = \"Search files and folders...\",\n initialQuery = \"\",\n showFilters = true,\n}: SearchBarProps) {\n const { t } = useI18n();\n const [query, setQuery] = useState(initialQuery);\n const [showFilterPanel, setShowFilterPanel] = useState(false);\n const [filters, setFilters] = useState<{\n fileType?: string;\n status?: string;\n visibility?: string;\n starred?: boolean;\n }>({});\n const fileStatus = filters.status as FileFilterInput[\"status\"] | undefined;\n const folderStatus = filters.status as\n | FolderFilterInput[\"status\"]\n | undefined;\n const fileVisibility = filters.visibility as\n | FileFilterInput[\"visibility\"]\n | undefined;\n const fileMimeTypes = filters.fileType\n ? FILE_TYPE_MIME_MAP[filters.fileType]\n : undefined;\n\n useEffect(() => {\n setQuery(initialQuery);\n }, [initialQuery]);\n\n // Debounced search\n useEffect(() => {\n const timer = setTimeout(() => {\n if (query.length >= 2 || query.length === 0) {\n const fileFilter: FileFilterInput = {\n ...(fileMimeTypes && { mimeTypes: fileMimeTypes }),\n ...(fileStatus && { status: fileStatus }),\n ...(fileVisibility && { visibility: fileVisibility }),\n ...(filters.starred !== undefined && { starred: filters.starred }),\n };\n\n const folderFilter: FolderFilterInput = {\n ...(folderStatus && { status: folderStatus }),\n ...(filters.starred !== undefined && { starred: filters.starred }),\n };\n\n onSearch(query, { fileFilter, folderFilter });\n }\n }, 300);\n\n return () => clearTimeout(timer);\n }, [\n fileStatus,\n fileMimeTypes,\n fileVisibility,\n folderStatus,\n filters,\n onSearch,\n query,\n ]);\n\n const handleClear = useCallback(() => {\n setQuery(\"\");\n setFilters({});\n onSearch(\"\");\n }, [onSearch]);\n\n const activeFilterCount = Object.values(filters).filter(\n (v) => v !== undefined,\n ).length;\n\n return (\n <div className=\"relative\">\n {/* Search Input */}\n <div className=\"relative flex items-center\">\n <Search className=\"absolute left-3 size-4 text-text-tertiary\" />\n <label htmlFor=\"files-search-input\" className=\"sr-only\">\n {tWithFallback(\n t,\n \"files.search.input.label\",\n \"Search files and folders\",\n )}\n </label>\n <input\n id=\"files-search-input\"\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={placeholder}\n className=\"w-full pl-[3.25rem] pr-20 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border focus:border-action-primary-border transition-colors duration-200\"\n />\n <div className=\"absolute right-2 flex items-center gap-1\">\n {query && (\n <button\n type=\"button\"\n onClick={handleClear}\n className=\"p-1.5 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n title={tWithFallback(\n t,\n \"files.search.actions.clearSearch\",\n \"Clear search\",\n )}\n aria-label={tWithFallback(\n t,\n \"files.search.actions.clearSearch\",\n \"Clear search\",\n )}\n >\n <X className=\"size-4\" />\n </button>\n )}\n {showFilters && (\n <button\n type=\"button\"\n onClick={() => setShowFilterPanel(!showFilterPanel)}\n aria-expanded={showFilterPanel}\n aria-controls=\"files-search-filter-panel\"\n aria-label={tWithFallback(\n t,\n \"files.search.filters.toggleAria\",\n \"Toggle filters\",\n )}\n className={`p-1.5 rounded transition-colors duration-200 relative ${\n showFilterPanel || activeFilterCount > 0\n ? \"text-text-link bg-bg-accent hover:bg-action-primary-bg/20\"\n : \"text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover\"\n }`}\n title={tWithFallback(t, \"files.search.filters.title\", \"Filters\")}\n >\n <Filter className=\"size-4\" />\n {activeFilterCount > 0 && (\n <span className=\"absolute -top-1 -right-1 size-4 bg-action-primary-bg text-text-inverse text-[10px] font-bold rounded-full flex items-center justify-center\">\n {activeFilterCount}\n </span>\n )}\n </button>\n )}\n </div>\n </div>\n\n {/* Filter Panel */}\n {showFilterPanel && (\n <div\n id=\"files-search-filter-panel\"\n className=\"absolute top-full left-0 right-0 mt-2 p-4 bg-bg-surface border border-border-default rounded-lg shadow-lg z-10 animate-in fade-in duration-200\"\n >\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.label\",\n \"File Type\",\n )}\n </label>\n <select\n value={filters.fileType || \"\"}\n onChange={(e) =>\n setFilters({\n ...filters,\n fileType: e.target.value || undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border transition-colors duration-200\"\n >\n <option value=\"\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.all\",\n \"All types\",\n )}\n </option>\n <option value=\"image\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.image\",\n \"Images\",\n )}\n </option>\n <option value=\"video\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.video\",\n \"Videos\",\n )}\n </option>\n <option value=\"document\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.document\",\n \"Documents\",\n )}\n </option>\n <option value=\"pdf\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.pdf\",\n \"PDFs\",\n )}\n </option>\n <option value=\"archive\">\n {tWithFallback(\n t,\n \"files.search.filters.fileType.options.archive\",\n \"Archives\",\n )}\n </option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tWithFallback(\n t,\n \"files.search.filters.status.label\",\n \"Status\",\n )}\n </label>\n <select\n value={filters.status || \"\"}\n onChange={(e) =>\n setFilters({\n ...filters,\n status: e.target.value || undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border transition-colors duration-200\"\n >\n <option value=\"\">\n {tWithFallback(\n t,\n \"files.search.filters.status.options.all\",\n \"All statuses\",\n )}\n </option>\n <option value=\"ACTIVE\">\n {tWithFallback(\n t,\n \"files.search.filters.status.options.active\",\n \"Active\",\n )}\n </option>\n <option value=\"ARCHIVED\">\n {tWithFallback(\n t,\n \"files.search.filters.status.options.archived\",\n \"Archived\",\n )}\n </option>\n <option value=\"DELETED\">\n {tWithFallback(\n t,\n \"files.search.filters.status.options.deleted\",\n \"Deleted\",\n )}\n </option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.label\",\n \"Visibility\",\n )}\n </label>\n <select\n value={filters.visibility || \"\"}\n onChange={(e) =>\n setFilters({\n ...filters,\n visibility: e.target.value || undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border transition-colors duration-200\"\n >\n <option value=\"\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.all\",\n \"All visibility\",\n )}\n </option>\n <option value=\"PRIVATE\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.private\",\n \"Private\",\n )}\n </option>\n <option value=\"TEAM\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.team\",\n \"Team\",\n )}\n </option>\n <option value=\"WORKSPACE\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.workspace\",\n \"Workspace\",\n )}\n </option>\n <option value=\"PUBLIC\">\n {tWithFallback(\n t,\n \"files.search.filters.visibility.options.public\",\n \"Public\",\n )}\n </option>\n </select>\n </div>\n\n <div className=\"flex items-center\">\n <input\n type=\"checkbox\"\n id=\"starred-filter\"\n checked={filters.starred || false}\n onChange={(e) =>\n setFilters({\n ...filters,\n starred: e.target.checked || undefined,\n })\n }\n className=\"size-4 text-action-primary-bg border-border-default rounded focus:ring-action-primary-border transition-colors duration-200\"\n />\n <label\n htmlFor=\"starred-filter\"\n className=\"ml-2 text-sm text-text-primary\"\n >\n {tWithFallback(\n t,\n \"files.search.filters.starredOnly\",\n \"Starred only\",\n )}\n </label>\n </div>\n\n <div className=\"flex justify-end gap-2 pt-2 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={() => {\n setFilters({});\n setShowFilterPanel(false);\n }}\n className=\"px-3 py-1.5 text-sm text-text-primary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n >\n {tWithFallback(\n t,\n \"files.search.filters.actions.clear\",\n \"Clear filters\",\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => setShowFilterPanel(false)}\n className=\"px-3 py-1.5 text-sm bg-action-primary-bg text-text-inverse rounded hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {tWithFallback(\n t,\n \"files.search.filters.actions.apply\",\n \"Apply\",\n )}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,206 +1,211 @@
1
1
  import { tWithFallback as e } from "../utils/i18n.js";
2
- import { useEffect as t, useMemo as n, useState as r } from "react";
3
- import { Calendar as i, Check as a, Copy as o, Download as s, Link as c, Loader2 as l, Lock as u, Mail as d, X as f } from "lucide-react";
4
- import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
5
- import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
2
+ import { useEffect as t, useState as n } from "react";
3
+ import { Calendar as r, Check as i, Copy as a, Download as o, Link as s, Loader2 as c, Lock as l, Mail as u, X as d } from "lucide-react";
4
+ import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
5
+ import { useI18n as h } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
6
6
  //#region src/files/components/ShareDialog.tsx
7
- function _({ item: _, itemType: v, onClose: y, onCreateShare: b, isLoading: x }) {
8
- let { t: S } = g(), [C, w] = r(null), [T, E] = r(null), [D, O] = r(!1), [k, A] = r(7), [j, M] = r(0), [N, P] = r(!1), [F, I] = r(""), [L, R] = r(""), [z, B] = r(null), V = n(() => `share-dialog-title-${_.id}`, [_.id]);
7
+ function g({ item: g, itemType: _, onClose: v, onCreateShare: y, isLoading: b }) {
8
+ let { t: x } = h(), [S, C] = n(null), [w, T] = n(null), [E, D] = n(!1), [O, k] = n(7), [A, j] = n(0), [M, N] = n(!1), [P, F] = n(""), [I, L] = n(""), [R, z] = n(null), B = `share-dialog-title-${g.id}`;
9
9
  return t(() => {
10
10
  let e = (e) => {
11
- e.key === "Escape" && y();
11
+ e.key === "Escape" && v();
12
12
  };
13
13
  return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
14
- }, [y]), t(() => {
15
- if (D) {
16
- let e = setTimeout(() => O(!1), 2e3);
14
+ }, [v]), t(() => {
15
+ if (E) {
16
+ let e = setTimeout(() => D(!1), 2e3);
17
17
  return () => clearTimeout(e);
18
18
  }
19
- }, [D]), /* @__PURE__ */ m("div", {
19
+ }, [E]), /* @__PURE__ */ p("div", {
20
20
  className: "fixed inset-0 bg-bg-overlay flex items-center justify-center z-[100] animate-in fade-in duration-200",
21
21
  role: "dialog",
22
22
  "aria-modal": "true",
23
- "aria-labelledby": V,
24
- children: /* @__PURE__ */ h("div", {
23
+ "aria-labelledby": B,
24
+ children: /* @__PURE__ */ m("div", {
25
25
  className: "bg-bg-surface rounded-lg shadow-xl p-6 w-full max-w-md mx-4 animate-in zoom-in-95 duration-200",
26
- children: [/* @__PURE__ */ h("div", {
26
+ children: [/* @__PURE__ */ m("div", {
27
27
  className: "flex items-center justify-between mb-4",
28
- children: [/* @__PURE__ */ m("h2", {
29
- id: V,
28
+ children: [/* @__PURE__ */ p("h2", {
29
+ id: B,
30
30
  className: "text-lg font-semibold text-text-primary",
31
- children: e(S, "files.shareDialog.title", "Share {{itemType}} \"{{name}}\"", {
32
- itemType: e(S, v === "folder" ? "files.shareDialog.itemType.folder" : "files.shareDialog.itemType.file", v === "folder" ? "folder" : "file"),
33
- name: _.name
31
+ children: e(x, "files.shareDialog.title", "Share {{itemType}} \"{{name}}\"", {
32
+ itemType: e(x, _ === "folder" ? "files.shareDialog.itemType.folder" : "files.shareDialog.itemType.file", _ === "folder" ? "folder" : "file"),
33
+ name: g.name
34
34
  })
35
- }), /* @__PURE__ */ m("button", {
36
- onClick: y,
35
+ }), /* @__PURE__ */ p("button", {
36
+ type: "button",
37
+ onClick: v,
37
38
  className: "text-text-tertiary hover:text-text-secondary transition-colors duration-200",
38
- "aria-label": e(S, "files.shareDialog.actions.close", "Close share dialog"),
39
- children: /* @__PURE__ */ m(f, { className: "size-5" })
39
+ "aria-label": e(x, "files.shareDialog.actions.close", "Close share dialog"),
40
+ children: /* @__PURE__ */ p(d, { className: "size-5" })
40
41
  })]
41
- }), T === null ? /* @__PURE__ */ h(p, { children: [
42
- z && /* @__PURE__ */ m("div", {
42
+ }), w === null ? /* @__PURE__ */ m(f, { children: [
43
+ R && /* @__PURE__ */ p("div", {
43
44
  className: "mb-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
44
- children: z
45
+ children: R
45
46
  }),
46
- /* @__PURE__ */ h("div", {
47
+ /* @__PURE__ */ m("div", {
47
48
  className: "space-y-4",
48
49
  children: [
49
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("label", {
50
+ /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ m("label", {
50
51
  className: "flex items-center gap-2 text-sm font-medium text-text-primary mb-2",
51
- children: [/* @__PURE__ */ m(i, { className: "size-4" }), e(S, "files.shareDialog.expiry.label", "Link expires in")]
52
- }), /* @__PURE__ */ h("select", {
53
- value: k,
54
- onChange: (e) => A(Number(e.target.value)),
52
+ children: [/* @__PURE__ */ p(r, { className: "size-4" }), e(x, "files.shareDialog.expiry.label", "Link expires in")]
53
+ }), /* @__PURE__ */ m("select", {
54
+ value: O,
55
+ onChange: (e) => k(Number(e.target.value)),
55
56
  className: "w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200",
56
57
  children: [
57
- /* @__PURE__ */ m("option", {
58
+ /* @__PURE__ */ p("option", {
58
59
  value: 0,
59
- children: e(S, "files.shareDialog.expiry.options.never", "Never")
60
+ children: e(x, "files.shareDialog.expiry.options.never", "Never")
60
61
  }),
61
- /* @__PURE__ */ m("option", {
62
+ /* @__PURE__ */ p("option", {
62
63
  value: 1,
63
- children: e(S, "files.shareDialog.expiry.options.oneDay", "1 day")
64
+ children: e(x, "files.shareDialog.expiry.options.oneDay", "1 day")
64
65
  }),
65
- /* @__PURE__ */ m("option", {
66
+ /* @__PURE__ */ p("option", {
66
67
  value: 7,
67
- children: e(S, "files.shareDialog.expiry.options.sevenDays", "7 days")
68
+ children: e(x, "files.shareDialog.expiry.options.sevenDays", "7 days")
68
69
  }),
69
- /* @__PURE__ */ m("option", {
70
+ /* @__PURE__ */ p("option", {
70
71
  value: 30,
71
- children: e(S, "files.shareDialog.expiry.options.thirtyDays", "30 days")
72
+ children: e(x, "files.shareDialog.expiry.options.thirtyDays", "30 days")
72
73
  }),
73
- /* @__PURE__ */ m("option", {
74
+ /* @__PURE__ */ p("option", {
74
75
  value: 90,
75
- children: e(S, "files.shareDialog.expiry.options.ninetyDays", "90 days")
76
+ children: e(x, "files.shareDialog.expiry.options.ninetyDays", "90 days")
76
77
  })
77
78
  ]
78
79
  })] }),
79
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("label", {
80
+ /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ m("label", {
80
81
  className: "flex items-center gap-2 text-sm font-medium text-text-primary mb-2",
81
- children: [/* @__PURE__ */ m(s, { className: "size-4" }), e(S, "files.shareDialog.downloads.label", "Maximum downloads")]
82
- }), /* @__PURE__ */ m("input", {
82
+ children: [/* @__PURE__ */ p(o, { className: "size-4" }), e(x, "files.shareDialog.downloads.label", "Maximum downloads")]
83
+ }), /* @__PURE__ */ p("input", {
83
84
  type: "number",
84
85
  min: "0",
85
- value: j,
86
- onChange: (e) => M(Number(e.target.value)),
87
- placeholder: e(S, "files.shareDialog.downloads.placeholder", "Unlimited"),
86
+ value: A,
87
+ onChange: (e) => j(Number(e.target.value)),
88
+ placeholder: e(x, "files.shareDialog.downloads.placeholder", "Unlimited"),
88
89
  className: "w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200"
89
90
  })] }),
90
- /* @__PURE__ */ h("div", { children: [
91
- /* @__PURE__ */ h("label", {
91
+ /* @__PURE__ */ m("div", { children: [
92
+ /* @__PURE__ */ m("label", {
92
93
  className: "flex items-center gap-2 text-sm font-medium text-text-primary mb-2",
93
- children: [/* @__PURE__ */ m(u, { className: "size-4" }), e(S, "files.shareDialog.password.label", "Password protection")]
94
+ children: [/* @__PURE__ */ p(l, { className: "size-4" }), e(x, "files.shareDialog.password.label", "Password protection")]
94
95
  }),
95
- /* @__PURE__ */ h("div", {
96
+ /* @__PURE__ */ m("div", {
96
97
  className: "flex items-center gap-2",
97
- children: [/* @__PURE__ */ m("input", {
98
+ children: [/* @__PURE__ */ p("input", {
98
99
  type: "checkbox",
99
- checked: N,
100
- onChange: (e) => P(e.target.checked),
100
+ checked: M,
101
+ onChange: (e) => N(e.target.checked),
101
102
  className: "rounded transition-colors duration-200"
102
- }), /* @__PURE__ */ m("span", {
103
+ }), /* @__PURE__ */ p("span", {
103
104
  className: "text-sm text-text-secondary",
104
- children: e(S, "files.shareDialog.password.require", "Require password")
105
+ children: e(x, "files.shareDialog.password.require", "Require password")
105
106
  })]
106
107
  }),
107
- N && /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("input", {
108
+ M && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("input", {
108
109
  type: "password",
109
- value: F,
110
- onChange: (e) => I(e.target.value),
111
- placeholder: e(S, "files.shareDialog.password.placeholder", "Enter password"),
110
+ value: P,
111
+ onChange: (e) => F(e.target.value),
112
+ placeholder: e(x, "files.shareDialog.password.placeholder", "Enter password"),
112
113
  className: "w-full mt-2 px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200"
113
- }), /* @__PURE__ */ m("p", {
114
+ }), /* @__PURE__ */ p("p", {
114
115
  className: "mt-1 text-xs text-text-tertiary",
115
- children: e(S, "files.shareDialog.password.help", "Password must be at least 8 characters and contain uppercase, lowercase, and number")
116
+ children: e(x, "files.shareDialog.password.help", "Password must be at least 8 characters and contain uppercase, lowercase, and number")
116
117
  })] })
117
118
  ] }),
118
- /* @__PURE__ */ h("div", { children: [
119
- /* @__PURE__ */ h("label", {
119
+ /* @__PURE__ */ m("div", { children: [
120
+ /* @__PURE__ */ m("label", {
120
121
  className: "flex items-center gap-2 text-sm font-medium text-text-primary mb-2",
121
- children: [/* @__PURE__ */ m(d, { className: "size-4" }), e(S, "files.shareDialog.invite.label", "Invite specific person (optional)")]
122
+ children: [/* @__PURE__ */ p(u, { className: "size-4" }), e(x, "files.shareDialog.invite.label", "Invite specific person (optional)")]
122
123
  }),
123
- /* @__PURE__ */ m("input", {
124
+ /* @__PURE__ */ p("input", {
124
125
  type: "email",
125
- value: L,
126
- onChange: (e) => R(e.target.value),
126
+ value: I,
127
+ onChange: (e) => L(e.target.value),
127
128
  placeholder: "user@example.com",
128
129
  className: "w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200"
129
130
  }),
130
- /* @__PURE__ */ m("p", {
131
+ /* @__PURE__ */ p("p", {
131
132
  className: "mt-1 text-xs text-text-secondary",
132
- children: e(S, "files.shareDialog.invite.help", "Leave empty for public link")
133
+ children: e(x, "files.shareDialog.invite.help", "Leave empty for public link")
133
134
  })
134
135
  ] })
135
136
  ]
136
137
  }),
137
- /* @__PURE__ */ h("div", {
138
+ /* @__PURE__ */ m("div", {
138
139
  className: "flex justify-end gap-2 mt-6",
139
- children: [/* @__PURE__ */ m("button", {
140
- onClick: y,
140
+ children: [/* @__PURE__ */ p("button", {
141
+ type: "button",
142
+ onClick: v,
141
143
  className: "px-4 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200",
142
- children: e(S, "files.common.actions.cancel", "Cancel")
143
- }), /* @__PURE__ */ m("button", {
144
+ children: e(x, "files.common.actions.cancel", "Cancel")
145
+ }), /* @__PURE__ */ p("button", {
146
+ type: "button",
144
147
  onClick: async () => {
145
148
  try {
146
- B(null);
147
- let e = k > 0 ? new Date(Date.now() + k * 24 * 60 * 60 * 1e3).toISOString() : void 0, t = L ? "EMAIL_INVITE" : "PUBLIC_LINK", n = await b({
148
- ...v === "file" ? { fileId: _.id } : { folderId: _.id },
149
+ z(null);
150
+ let e = O > 0 ? new Date(Date.now() + O * 24 * 60 * 60 * 1e3).toISOString() : void 0, t = I ? "EMAIL_INVITE" : "PUBLIC_LINK", n = await y({
151
+ ..._ === "file" ? { fileId: g.id } : { folderId: g.id },
149
152
  shareType: t,
150
153
  accessLevel: "DOWNLOAD",
151
154
  expiresAt: e,
152
- maxDownloads: j > 0 ? j : void 0,
153
- password: N && F ? F : void 0,
154
- invitedEmail: L || void 0
155
+ maxDownloads: A > 0 ? A : void 0,
156
+ password: M && P ? P : void 0,
157
+ invitedEmail: I || void 0
155
158
  });
156
- E(t), w(n.publicUrl || "");
159
+ T(t), C(n.publicUrl || "");
157
160
  } catch (e) {
158
- B(e instanceof Error ? e.message : "Failed to create share");
161
+ z(e instanceof Error ? e.message : "Failed to create share");
159
162
  }
160
163
  },
161
- disabled: x || N && !F,
164
+ disabled: b || M && !P,
162
165
  className: "flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200",
163
- children: x ? /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(l, { className: "size-4 animate-spin" }), e(S, "files.shareDialog.actions.creating", "Creating...")] }) : /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(c, { className: "size-4" }), e(S, "files.shareDialog.actions.createLink", "Create share link")] })
166
+ children: b ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(c, { className: "size-4 animate-spin" }), e(x, "files.shareDialog.actions.creating", "Creating...")] }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(s, { className: "size-4" }), e(x, "files.shareDialog.actions.createLink", "Create share link")] })
164
167
  })]
165
168
  })
166
- ] }) : /* @__PURE__ */ m(p, { children: /* @__PURE__ */ h("div", {
169
+ ] }) : /* @__PURE__ */ p(f, { children: /* @__PURE__ */ m("div", {
167
170
  className: "space-y-4",
168
- children: [/* @__PURE__ */ m("div", {
171
+ children: [/* @__PURE__ */ p("div", {
169
172
  className: "bg-status-success-bg-subtle border border-status-success-border rounded-lg p-4",
170
- children: T === "EMAIL_INVITE" ? /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("p", {
173
+ children: w === "EMAIL_INVITE" ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("p", {
171
174
  className: "text-sm font-medium text-status-success-text mb-2",
172
- children: e(S, "files.shareDialog.success.invitationSent", "Invitation sent successfully!")
173
- }), /* @__PURE__ */ m("p", {
175
+ children: e(x, "files.shareDialog.success.invitationSent", "Invitation sent successfully!")
176
+ }), /* @__PURE__ */ p("p", {
174
177
  className: "text-sm text-text-secondary",
175
- children: e(S, "files.shareDialog.success.invitationSentTo", "An invitation has been sent to {{email}}", { email: L })
176
- })] }) : /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("p", {
178
+ children: e(x, "files.shareDialog.success.invitationSentTo", "An invitation has been sent to {{email}}", { email: I })
179
+ })] }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("p", {
177
180
  className: "text-sm font-medium text-status-success-text mb-2",
178
- children: e(S, "files.shareDialog.success.linkCreated", "Share link created successfully!")
179
- }), /* @__PURE__ */ h("div", {
181
+ children: e(x, "files.shareDialog.success.linkCreated", "Share link created successfully!")
182
+ }), /* @__PURE__ */ m("div", {
180
183
  className: "flex items-center gap-2",
181
- children: [/* @__PURE__ */ m("input", {
184
+ children: [/* @__PURE__ */ p("input", {
182
185
  type: "text",
183
- value: C || "",
186
+ value: S || "",
184
187
  readOnly: !0,
185
188
  className: "flex-1 px-3 py-2 bg-bg-surface border border-status-success-border rounded-lg text-sm"
186
- }), /* @__PURE__ */ m("button", {
189
+ }), /* @__PURE__ */ p("button", {
190
+ type: "button",
187
191
  onClick: async () => {
188
- C && (await navigator.clipboard.writeText(C), O(!0));
192
+ S && (await navigator.clipboard.writeText(S), D(!0));
189
193
  },
190
194
  className: "flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200",
191
- children: D ? /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(a, { className: "size-4" }), e(S, "files.shareDialog.actions.copied", "Copied!")] }) : /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(o, { className: "size-4" }), e(S, "files.common.actions.copy", "Copy")] })
195
+ children: E ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(i, { className: "size-4" }), e(x, "files.shareDialog.actions.copied", "Copied!")] }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(a, { className: "size-4" }), e(x, "files.common.actions.copy", "Copy")] })
192
196
  })]
193
197
  })] })
194
- }), /* @__PURE__ */ m("button", {
195
- onClick: y,
198
+ }), /* @__PURE__ */ p("button", {
199
+ type: "button",
200
+ onClick: v,
196
201
  className: "w-full px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200",
197
- children: e(S, "files.common.actions.done", "Done")
202
+ children: e(x, "files.common.actions.done", "Done")
198
203
  })]
199
204
  }) })]
200
205
  })
201
206
  });
202
207
  }
203
208
  //#endregion
204
- export { _ as ShareDialog };
209
+ export { g as ShareDialog };
205
210
 
206
211
  //# sourceMappingURL=ShareDialog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ShareDialog.js","names":[],"sources":["../../../src/files/components/ShareDialog.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport {\n X,\n Link,\n Mail,\n Calendar,\n Download,\n Lock,\n Copy,\n Check,\n Loader2,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\nexport interface ShareDialogInput {\n fileId?: string;\n folderId?: string;\n shareType: \"PUBLIC_LINK\" | \"EMAIL_INVITE\";\n accessLevel: \"VIEW\" | \"DOWNLOAD\" | \"EDIT\";\n expiresAt?: string;\n maxDownloads?: number;\n password?: string;\n invitedEmail?: string;\n}\n\ninterface ShareDialogProps {\n item: FileItem | FolderItem;\n itemType: \"file\" | \"folder\";\n onClose: () => void;\n onCreateShare: (\n input: ShareDialogInput,\n ) => Promise<{ publicUrl: string; token: string }>;\n isLoading?: boolean;\n}\n\nexport function ShareDialog({\n item,\n itemType,\n onClose,\n onCreateShare,\n isLoading,\n}: ShareDialogProps) {\n const { t } = useI18n();\n const [shareUrl, setShareUrl] = useState<string | null>(null);\n const [shareType, setShareType] = useState<\n \"PUBLIC_LINK\" | \"EMAIL_INVITE\" | null\n >(null);\n const [copied, setCopied] = useState(false);\n const [expiryDays, setExpiryDays] = useState<number>(7);\n const [maxDownloads, setMaxDownloads] = useState<number>(0);\n const [hasPassword, setHasPassword] = useState(false);\n const [password, setPassword] = useState(\"\");\n const [invitedEmail, setInvitedEmail] = useState(\"\");\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const titleId = useMemo(() => `share-dialog-title-${item.id}`, [item.id]);\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, [onClose]);\n\n const handleCreateShare = async () => {\n try {\n setErrorMessage(null);\n const expiresAt =\n expiryDays > 0\n ? new Date(\n Date.now() + expiryDays * 24 * 60 * 60 * 1000,\n ).toISOString()\n : undefined;\n\n const type: ShareDialogInput[\"shareType\"] = invitedEmail\n ? \"EMAIL_INVITE\"\n : \"PUBLIC_LINK\";\n\n const shareInput: ShareDialogInput = {\n ...(itemType === \"file\" ? { fileId: item.id } : { folderId: item.id }),\n shareType: type,\n accessLevel: \"DOWNLOAD\",\n expiresAt,\n maxDownloads: maxDownloads > 0 ? maxDownloads : undefined,\n password: hasPassword && password ? password : undefined,\n invitedEmail: invitedEmail || undefined,\n };\n\n const result = await onCreateShare(shareInput);\n\n setShareType(type);\n setShareUrl(result.publicUrl || \"\");\n } catch (error) {\n setErrorMessage(\n error instanceof Error ? error.message : \"Failed to create share\",\n );\n }\n };\n\n const handleCopyLink = async () => {\n if (shareUrl) {\n await navigator.clipboard.writeText(shareUrl);\n setCopied(true);\n }\n };\n\n // Cleanup timeout on unmount to prevent React state update warning\n useEffect(() => {\n if (copied) {\n const timer = setTimeout(() => setCopied(false), 2000);\n return () => clearTimeout(timer);\n }\n return undefined;\n }, [copied]);\n\n return (\n <div\n className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n >\n <div className=\"bg-bg-surface rounded-lg shadow-xl p-6 w-full max-w-md mx-4 animate-in zoom-in-95 duration-200\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 id={titleId} className=\"text-lg font-semibold text-text-primary\">\n {tWithFallback(\n t,\n \"files.shareDialog.title\",\n 'Share {{itemType}} \"{{name}}\"',\n {\n itemType: tWithFallback(\n t,\n itemType === \"folder\"\n ? \"files.shareDialog.itemType.folder\"\n : \"files.shareDialog.itemType.file\",\n itemType === \"folder\" ? \"folder\" : \"file\",\n ),\n name: item.name,\n },\n )}\n </h2>\n <button\n onClick={onClose}\n className=\"text-text-tertiary hover:text-text-secondary transition-colors duration-200\"\n aria-label={tWithFallback(\n t,\n \"files.shareDialog.actions.close\",\n \"Close share dialog\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {shareType === null ? (\n <>\n {errorMessage && (\n <div className=\"mb-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {errorMessage}\n </div>\n )}\n\n {/* Share Settings */}\n <div className=\"space-y-4\">\n {/* Expiry */}\n <div>\n <label className=\"flex items-center gap-2 text-sm font-medium text-text-primary mb-2\">\n <Calendar className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.label\",\n \"Link expires in\",\n )}\n </label>\n <select\n value={expiryDays}\n onChange={(e) => setExpiryDays(Number(e.target.value))}\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n >\n <option value={0}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.never\",\n \"Never\",\n )}\n </option>\n <option value={1}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.oneDay\",\n \"1 day\",\n )}\n </option>\n <option value={7}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.sevenDays\",\n \"7 days\",\n )}\n </option>\n <option value={30}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.thirtyDays\",\n \"30 days\",\n )}\n </option>\n <option value={90}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.ninetyDays\",\n \"90 days\",\n )}\n </option>\n </select>\n </div>\n\n {/* Max Downloads */}\n <div>\n <label className=\"flex items-center gap-2 text-sm font-medium text-text-primary mb-2\">\n <Download className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.downloads.label\",\n \"Maximum downloads\",\n )}\n </label>\n <input\n type=\"number\"\n min=\"0\"\n value={maxDownloads}\n onChange={(e) => setMaxDownloads(Number(e.target.value))}\n placeholder={tWithFallback(\n t,\n \"files.shareDialog.downloads.placeholder\",\n \"Unlimited\",\n )}\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n </div>\n\n {/* Password Protection */}\n <div>\n <label className=\"flex items-center gap-2 text-sm font-medium text-text-primary mb-2\">\n <Lock className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.password.label\",\n \"Password protection\",\n )}\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={hasPassword}\n onChange={(e) => setHasPassword(e.target.checked)}\n className=\"rounded transition-colors duration-200\"\n />\n <span className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.shareDialog.password.require\",\n \"Require password\",\n )}\n </span>\n </div>\n {hasPassword && (\n <>\n <input\n type=\"password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder={tWithFallback(\n t,\n \"files.shareDialog.password.placeholder\",\n \"Enter password\",\n )}\n className=\"w-full mt-2 px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n <p className=\"mt-1 text-xs text-text-tertiary\">\n {tWithFallback(\n t,\n \"files.shareDialog.password.help\",\n \"Password must be at least 8 characters and contain uppercase, lowercase, and number\",\n )}\n </p>\n </>\n )}\n </div>\n\n {/* Invited Email */}\n <div>\n <label className=\"flex items-center gap-2 text-sm font-medium text-text-primary mb-2\">\n <Mail className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.invite.label\",\n \"Invite specific person (optional)\",\n )}\n </label>\n <input\n type=\"email\"\n value={invitedEmail}\n onChange={(e) => setInvitedEmail(e.target.value)}\n placeholder=\"user@example.com\"\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n <p className=\"mt-1 text-xs text-text-secondary\">\n {tWithFallback(\n t,\n \"files.shareDialog.invite.help\",\n \"Leave empty for public link\",\n )}\n </p>\n </div>\n </div>\n\n {/* Create Button */}\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n onClick={onClose}\n className=\"px-4 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.cancel\", \"Cancel\")}\n </button>\n <button\n onClick={handleCreateShare}\n disabled={isLoading || (hasPassword && !password)}\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200\"\n >\n {isLoading ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n {tWithFallback(\n t,\n \"files.shareDialog.actions.creating\",\n \"Creating...\",\n )}\n </>\n ) : (\n <>\n <Link className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.actions.createLink\",\n \"Create share link\",\n )}\n </>\n )}\n </button>\n </div>\n </>\n ) : (\n <>\n {/* Share Created Success */}\n <div className=\"space-y-4\">\n <div className=\"bg-status-success-bg-subtle border border-status-success-border rounded-lg p-4\">\n {shareType === \"EMAIL_INVITE\" ? (\n <>\n <p className=\"text-sm font-medium text-status-success-text mb-2\">\n {tWithFallback(\n t,\n \"files.shareDialog.success.invitationSent\",\n \"Invitation sent successfully!\",\n )}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.shareDialog.success.invitationSentTo\",\n \"An invitation has been sent to {{email}}\",\n { email: invitedEmail },\n )}\n </p>\n </>\n ) : (\n <>\n <p className=\"text-sm font-medium text-status-success-text mb-2\">\n {tWithFallback(\n t,\n \"files.shareDialog.success.linkCreated\",\n \"Share link created successfully!\",\n )}\n </p>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"text\"\n value={shareUrl || \"\"}\n readOnly\n className=\"flex-1 px-3 py-2 bg-bg-surface border border-status-success-border rounded-lg text-sm\"\n />\n <button\n onClick={handleCopyLink}\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {copied ? (\n <>\n <Check className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.actions.copied\",\n \"Copied!\",\n )}\n </>\n ) : (\n <>\n <Copy className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.common.actions.copy\",\n \"Copy\",\n )}\n </>\n )}\n </button>\n </div>\n </>\n )}\n </div>\n\n <button\n onClick={onClose}\n className=\"w-full px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.done\", \"Done\")}\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ShareDialog.js","names":[],"sources":["../../../src/files/components/ShareDialog.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport {\n X,\n Link,\n Mail,\n Calendar,\n Download,\n Lock,\n Copy,\n Check,\n Loader2,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\nexport interface ShareDialogInput {\n fileId?: string;\n folderId?: string;\n shareType: \"PUBLIC_LINK\" | \"EMAIL_INVITE\";\n accessLevel: \"VIEW\" | \"DOWNLOAD\" | \"EDIT\";\n expiresAt?: string;\n maxDownloads?: number;\n password?: string;\n invitedEmail?: string;\n}\n\ninterface ShareDialogProps {\n item: FileItem | FolderItem;\n itemType: \"file\" | \"folder\";\n onClose: () => void;\n onCreateShare: (\n input: ShareDialogInput,\n ) => Promise<{ publicUrl: string; token: string }>;\n isLoading?: boolean;\n}\n\nexport function ShareDialog({\n item,\n itemType,\n onClose,\n onCreateShare,\n isLoading,\n}: ShareDialogProps) {\n const { t } = useI18n();\n const [shareUrl, setShareUrl] = useState<string | null>(null);\n const [shareType, setShareType] = useState<\n \"PUBLIC_LINK\" | \"EMAIL_INVITE\" | null\n >(null);\n const [copied, setCopied] = useState(false);\n const [expiryDays, setExpiryDays] = useState<number>(7);\n const [maxDownloads, setMaxDownloads] = useState<number>(0);\n const [hasPassword, setHasPassword] = useState(false);\n const [password, setPassword] = useState(\"\");\n const [invitedEmail, setInvitedEmail] = useState(\"\");\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const titleId = `share-dialog-title-${item.id}`;\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, [onClose]);\n\n const handleCreateShare = async () => {\n try {\n setErrorMessage(null);\n const expiresAt =\n expiryDays > 0\n ? new Date(\n Date.now() + expiryDays * 24 * 60 * 60 * 1000,\n ).toISOString()\n : undefined;\n\n const type: ShareDialogInput[\"shareType\"] = invitedEmail\n ? \"EMAIL_INVITE\"\n : \"PUBLIC_LINK\";\n\n const shareInput: ShareDialogInput = {\n ...(itemType === \"file\" ? { fileId: item.id } : { folderId: item.id }),\n shareType: type,\n accessLevel: \"DOWNLOAD\",\n expiresAt,\n maxDownloads: maxDownloads > 0 ? maxDownloads : undefined,\n password: hasPassword && password ? password : undefined,\n invitedEmail: invitedEmail || undefined,\n };\n\n const result = await onCreateShare(shareInput);\n\n setShareType(type);\n setShareUrl(result.publicUrl || \"\");\n } catch (error) {\n setErrorMessage(\n error instanceof Error ? error.message : \"Failed to create share\",\n );\n }\n };\n\n const handleCopyLink = async () => {\n if (shareUrl) {\n await navigator.clipboard.writeText(shareUrl);\n setCopied(true);\n }\n };\n\n // Cleanup timeout on unmount to prevent React state update warning\n useEffect(() => {\n if (copied) {\n const timer = setTimeout(() => setCopied(false), 2000);\n return () => clearTimeout(timer);\n }\n return undefined;\n }, [copied]);\n\n return (\n <div\n className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n >\n <div className=\"bg-bg-surface rounded-lg shadow-xl p-6 w-full max-w-md mx-4 animate-in zoom-in-95 duration-200\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 id={titleId} className=\"text-lg font-semibold text-text-primary\">\n {tWithFallback(\n t,\n \"files.shareDialog.title\",\n 'Share {{itemType}} \"{{name}}\"',\n {\n itemType: tWithFallback(\n t,\n itemType === \"folder\"\n ? \"files.shareDialog.itemType.folder\"\n : \"files.shareDialog.itemType.file\",\n itemType === \"folder\" ? \"folder\" : \"file\",\n ),\n name: item.name,\n },\n )}\n </h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"text-text-tertiary hover:text-text-secondary transition-colors duration-200\"\n aria-label={tWithFallback(\n t,\n \"files.shareDialog.actions.close\",\n \"Close share dialog\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {shareType === null ? (\n <>\n {errorMessage && (\n <div className=\"mb-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {errorMessage}\n </div>\n )}\n\n {/* Share Settings */}\n <div className=\"space-y-4\">\n {/* Expiry */}\n <div>\n <label className=\"flex items-center gap-2 text-sm font-medium text-text-primary mb-2\">\n <Calendar className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.label\",\n \"Link expires in\",\n )}\n </label>\n <select\n value={expiryDays}\n onChange={(e) => setExpiryDays(Number(e.target.value))}\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n >\n <option value={0}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.never\",\n \"Never\",\n )}\n </option>\n <option value={1}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.oneDay\",\n \"1 day\",\n )}\n </option>\n <option value={7}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.sevenDays\",\n \"7 days\",\n )}\n </option>\n <option value={30}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.thirtyDays\",\n \"30 days\",\n )}\n </option>\n <option value={90}>\n {tWithFallback(\n t,\n \"files.shareDialog.expiry.options.ninetyDays\",\n \"90 days\",\n )}\n </option>\n </select>\n </div>\n\n {/* Max Downloads */}\n <div>\n <label className=\"flex items-center gap-2 text-sm font-medium text-text-primary mb-2\">\n <Download className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.downloads.label\",\n \"Maximum downloads\",\n )}\n </label>\n <input\n type=\"number\"\n min=\"0\"\n value={maxDownloads}\n onChange={(e) => setMaxDownloads(Number(e.target.value))}\n placeholder={tWithFallback(\n t,\n \"files.shareDialog.downloads.placeholder\",\n \"Unlimited\",\n )}\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n </div>\n\n {/* Password Protection */}\n <div>\n <label className=\"flex items-center gap-2 text-sm font-medium text-text-primary mb-2\">\n <Lock className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.password.label\",\n \"Password protection\",\n )}\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={hasPassword}\n onChange={(e) => setHasPassword(e.target.checked)}\n className=\"rounded transition-colors duration-200\"\n />\n <span className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.shareDialog.password.require\",\n \"Require password\",\n )}\n </span>\n </div>\n {hasPassword && (\n <>\n <input\n type=\"password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder={tWithFallback(\n t,\n \"files.shareDialog.password.placeholder\",\n \"Enter password\",\n )}\n className=\"w-full mt-2 px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n <p className=\"mt-1 text-xs text-text-tertiary\">\n {tWithFallback(\n t,\n \"files.shareDialog.password.help\",\n \"Password must be at least 8 characters and contain uppercase, lowercase, and number\",\n )}\n </p>\n </>\n )}\n </div>\n\n {/* Invited Email */}\n <div>\n <label className=\"flex items-center gap-2 text-sm font-medium text-text-primary mb-2\">\n <Mail className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.invite.label\",\n \"Invite specific person (optional)\",\n )}\n </label>\n <input\n type=\"email\"\n value={invitedEmail}\n onChange={(e) => setInvitedEmail(e.target.value)}\n placeholder=\"user@example.com\"\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:border-action-primary-border text-sm transition-colors duration-200\"\n />\n <p className=\"mt-1 text-xs text-text-secondary\">\n {tWithFallback(\n t,\n \"files.shareDialog.invite.help\",\n \"Leave empty for public link\",\n )}\n </p>\n </div>\n </div>\n\n {/* Create Button */}\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={handleCreateShare}\n disabled={isLoading || (hasPassword && !password)}\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200\"\n >\n {isLoading ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n {tWithFallback(\n t,\n \"files.shareDialog.actions.creating\",\n \"Creating...\",\n )}\n </>\n ) : (\n <>\n <Link className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.actions.createLink\",\n \"Create share link\",\n )}\n </>\n )}\n </button>\n </div>\n </>\n ) : (\n <>\n {/* Share Created Success */}\n <div className=\"space-y-4\">\n <div className=\"bg-status-success-bg-subtle border border-status-success-border rounded-lg p-4\">\n {shareType === \"EMAIL_INVITE\" ? (\n <>\n <p className=\"text-sm font-medium text-status-success-text mb-2\">\n {tWithFallback(\n t,\n \"files.shareDialog.success.invitationSent\",\n \"Invitation sent successfully!\",\n )}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.shareDialog.success.invitationSentTo\",\n \"An invitation has been sent to {{email}}\",\n { email: invitedEmail },\n )}\n </p>\n </>\n ) : (\n <>\n <p className=\"text-sm font-medium text-status-success-text mb-2\">\n {tWithFallback(\n t,\n \"files.shareDialog.success.linkCreated\",\n \"Share link created successfully!\",\n )}\n </p>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"text\"\n value={shareUrl || \"\"}\n readOnly\n className=\"flex-1 px-3 py-2 bg-bg-surface border border-status-success-border rounded-lg text-sm\"\n />\n <button\n type=\"button\"\n onClick={handleCopyLink}\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {copied ? (\n <>\n <Check className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.shareDialog.actions.copied\",\n \"Copied!\",\n )}\n </>\n ) : (\n <>\n <Copy className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.common.actions.copy\",\n \"Copy\",\n )}\n </>\n )}\n </button>\n </div>\n </>\n )}\n </div>\n\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-full px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.done\", \"Done\")}\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAqCA,SAAgB,EAAY,EAC1B,SACA,aACA,YACA,kBACA,gBACmB;CACnB,IAAM,EAAE,SAAM,GAAS,EACjB,CAAC,GAAU,KAAe,EAAwB,KAAK,EACvD,CAAC,GAAW,KAAgB,EAEhC,KAAK,EACD,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,CAAC,GAAY,KAAiB,EAAiB,EAAE,EACjD,CAAC,GAAc,KAAmB,EAAiB,EAAE,EACrD,CAAC,GAAa,KAAkB,EAAS,GAAM,EAC/C,CAAC,GAAU,KAAe,EAAS,GAAG,EACtC,CAAC,GAAc,KAAmB,EAAS,GAAG,EAC9C,CAAC,GAAc,KAAmB,EAAwB,KAAK,EAC/D,IAAU,sBAAsB,EAAK;AAgE3C,QA9DA,QAAgB;EACd,IAAM,KAAgB,MAAyB;AAC7C,GAAI,EAAM,QAAQ,YAChB,GAAS;;AAKb,SADA,SAAS,iBAAiB,WAAW,EAAa,QACrC,SAAS,oBAAoB,WAAW,EAAa;IACjE,CAAC,EAAQ,CAAC,EA6Cb,QAAgB;AACd,MAAI,GAAQ;GACV,IAAM,IAAQ,iBAAiB,EAAU,GAAM,EAAE,IAAK;AACtD,gBAAa,aAAa,EAAM;;IAGjC,CAAC,EAAO,CAAC,EAGV,kBAAC,OAAD;EACE,WAAU;EACV,MAAK;EACL,cAAW;EACX,mBAAiB;YAEjB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,IAAI;KAAS,WAAU;eACxB,EACC,GACA,2BACA,mCACA;MACE,UAAU,EACR,GACA,MAAa,WACT,sCACA,mCACJ,MAAa,WAAW,WAAW,OACpC;MACD,MAAM,EAAK;MACZ,CACF;KACE,CAAA,EACL,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;KACV,cAAY,EACV,GACA,mCACA,qBACD;eAED,kBAAC,GAAD,EAAG,WAAU,UAAW,CAAA;KACjB,CAAA,CACL;OAEL,MAAc,OACb,kBAAA,GAAA,EAAA,UAAA;IACG,KACC,kBAAC,OAAD;KAAK,WAAU;eACZ;KACG,CAAA;IAIR,kBAAC,OAAD;KAAK,WAAU;eAAf;MAEE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA,EAC9B,EACC,GACA,kCACA,kBACD,CACK;UACR,kBAAC,UAAD;OACE,OAAO;OACP,WAAW,MAAM,EAAc,OAAO,EAAE,OAAO,MAAM,CAAC;OACtD,WAAU;iBAHZ;QAKE,kBAAC,UAAD;SAAQ,OAAO;mBACZ,EACC,GACA,0CACA,QACD;SACM,CAAA;QACT,kBAAC,UAAD;SAAQ,OAAO;mBACZ,EACC,GACA,2CACA,QACD;SACM,CAAA;QACT,kBAAC,UAAD;SAAQ,OAAO;mBACZ,EACC,GACA,8CACA,SACD;SACM,CAAA;QACT,kBAAC,UAAD;SAAQ,OAAO;mBACZ,EACC,GACA,+CACA,UACD;SACM,CAAA;QACT,kBAAC,UAAD;SAAQ,OAAO;mBACZ,EACC,GACA,+CACA,UACD;SACM,CAAA;QACF;SACL,EAAA,CAAA;MAGN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA,EAC9B,EACC,GACA,qCACA,oBACD,CACK;UACR,kBAAC,SAAD;OACE,MAAK;OACL,KAAI;OACJ,OAAO;OACP,WAAW,MAAM,EAAgB,OAAO,EAAE,OAAO,MAAM,CAAC;OACxD,aAAa,EACX,GACA,2CACA,YACD;OACD,WAAU;OACV,CAAA,CACE,EAAA,CAAA;MAGN,kBAAC,OAAD,EAAA,UAAA;OACE,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA,EAC1B,EACC,GACA,oCACA,sBACD,CACK;;OACR,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SACE,MAAK;SACL,SAAS;SACT,WAAW,MAAM,EAAe,EAAE,OAAO,QAAQ;SACjD,WAAU;SACV,CAAA,EACF,kBAAC,QAAD;SAAM,WAAU;mBACb,EACC,GACA,sCACA,mBACD;SACI,CAAA,CACH;;OACL,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,SAAD;QACE,MAAK;QACL,OAAO;QACP,WAAW,MAAM,EAAY,EAAE,OAAO,MAAM;QAC5C,aAAa,EACX,GACA,0CACA,iBACD;QACD,WAAU;QACV,CAAA,EACF,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,GACA,mCACA,sFACD;QACC,CAAA,CACH,EAAA,CAAA;OAED,EAAA,CAAA;MAGN,kBAAC,OAAD,EAAA,UAAA;OACE,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA,EAC1B,EACC,GACA,kCACA,oCACD,CACK;;OACR,kBAAC,SAAD;QACE,MAAK;QACL,OAAO;QACP,WAAW,MAAM,EAAgB,EAAE,OAAO,MAAM;QAChD,aAAY;QACZ,WAAU;QACV,CAAA;OACF,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,GACA,iCACA,8BACD;QACC,CAAA;OACA,EAAA,CAAA;MACF;;IAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;gBAET,EAAc,GAAG,+BAA+B,SAAS;MACnD,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,SAzQY,YAAY;AACpC,WAAI;AACF,UAAgB,KAAK;QACrB,IAAM,IACJ,IAAa,IACT,IAAI,KACF,KAAK,KAAK,GAAG,IAAa,KAAK,KAAK,KAAK,IAC1C,CAAC,aAAa,GACf,KAAA,GAEA,IAAsC,IACxC,iBACA,eAYE,IAAS,MAAM,EAVgB;SACnC,GAAI,MAAa,SAAS,EAAE,QAAQ,EAAK,IAAI,GAAG,EAAE,UAAU,EAAK,IAAI;SACrE,WAAW;SACX,aAAa;SACb;SACA,cAAc,IAAe,IAAI,IAAe,KAAA;SAChD,UAAU,KAAe,IAAW,IAAW,KAAA;SAC/C,cAAc,KAAgB,KAAA;SAC/B,CAE6C;AAG9C,QADA,EAAa,EAAK,EAClB,EAAY,EAAO,aAAa,GAAG;gBAC5B,GAAO;AACd,UACE,aAAiB,QAAQ,EAAM,UAAU,yBAC1C;;;MA2OS,UAAU,KAAc,KAAe,CAAC;MACxC,WAAU;gBAET,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,EAC1C,EACC,GACA,sCACA,cACD,CACA,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA,EAC1B,EACC,GACA,wCACA,oBACD,CACA,EAAA,CAAA;MAEE,CAAA,CACL;;IACL,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACZ,MAAc,iBACb,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,GACA,4CACA,gCACD;MACC,CAAA,EACJ,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,GACA,8CACA,4CACA,EAAE,OAAO,GAAc,CACxB;MACC,CAAA,CACH,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,GACA,yCACA,mCACD;MACC,CAAA,EACJ,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,SAAD;OACE,MAAK;OACL,OAAO,KAAY;OACnB,UAAA;OACA,WAAU;OACV,CAAA,EACF,kBAAC,UAAD;OACE,MAAK;OACL,SAzSC,YAAY;AACjC,QAAI,MACF,MAAM,UAAU,UAAU,UAAU,EAAS,EAC7C,EAAU,GAAK;;OAuSG,WAAU;iBAET,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAO,WAAU,UAAW,CAAA,EAC3B,EACC,GACA,oCACA,UACD,CACA,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA,EAC1B,EACC,GACA,6BACA,OACD,CACA,EAAA,CAAA;OAEE,CAAA,CACL;QACL,EAAA,CAAA;KAED,CAAA,EAEN,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAET,EAAc,GAAG,6BAA6B,OAAO;KAC/C,CAAA,CACL;OACL,CAAA,CAED;;EACF,CAAA"}
@@ -46,6 +46,7 @@ function l({ activeTab: t, onTabChange: n, tabs: r = [
46
46
  role: "tablist",
47
47
  "aria-label": e(i, "files.browser.tabs.ariaLabel", "Files sections"),
48
48
  children: l.map((e) => /* @__PURE__ */ o("button", {
49
+ type: "button",
49
50
  onClick: () => n(e.id),
50
51
  role: "tab",
51
52
  "aria-selected": t === e.id,
@@ -1 +1 @@
1
- {"version":3,"file":"TabBar.js","names":[],"sources":["../../../src/files/components/TabBar.tsx"],"sourcesContent":["import { Clock, Star, Trash2, Folder } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { tWithFallback } from \"../utils/i18n\";\n\nexport type TabView = \"all\" | \"recent\" | \"starred\" | \"bin\";\n\ninterface TabBarProps {\n activeTab: TabView;\n onTabChange: (tab: TabView) => void;\n /**\n * Which tabs to render. Order is preserved. Parent filters out\n * feature-flag-gated tabs (e.g. bin/starred) before passing.\n * @default [\"all\", \"recent\", \"starred\", \"bin\"]\n */\n tabs?: TabView[];\n}\n\nconst ALL_TABS: { id: TabView; label: string; icon: React.ReactNode }[] = [\n { id: \"all\", label: \"All Files\", icon: <Folder className=\"size-5\" /> },\n { id: \"recent\", label: \"Recent\", icon: <Clock className=\"size-5\" /> },\n { id: \"starred\", label: \"Starred\", icon: <Star className=\"size-5\" /> },\n { id: \"bin\", label: \"Bin\", icon: <Trash2 className=\"size-5\" /> },\n];\n\nexport function TabBar({\n activeTab,\n onTabChange,\n tabs = [\"all\", \"recent\", \"starred\", \"bin\"],\n}: TabBarProps) {\n const { t } = useI18n();\n const visibleTabs = ALL_TABS.filter((tab) => tabs.includes(tab.id));\n const labels: Record<TabView, string> = {\n all: tWithFallback(t, \"files.browser.tabs.all\", \"All Files\"),\n recent: tWithFallback(t, \"files.browser.tabs.recent\", \"Recent\"),\n starred: tWithFallback(t, \"files.browser.tabs.starred\", \"Starred\"),\n bin: tWithFallback(t, \"files.browser.tabs.bin\", \"Bin\"),\n };\n\n return (\n <div className=\"bg-bg-surface border-b border-border-default\">\n <div className=\"overflow-x-auto px-4 sm:px-6 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]\">\n <nav\n className=\"-mb-px flex min-w-max gap-1\"\n role=\"tablist\"\n aria-label={tWithFallback(\n t,\n \"files.browser.tabs.ariaLabel\",\n \"Files sections\",\n )}\n >\n {visibleTabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => onTabChange(tab.id)}\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n className={`\n flex items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium border-b-2 transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-border focus-visible:ring-offset-2\n ${\n activeTab === tab.id\n ? \"border-action-primary-bg text-text-primary bg-action-ghost-bg-hover\"\n : \"border-transparent text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover\"\n }\n `}\n >\n {tab.icon}\n {labels[tab.id] ?? tab.label}\n </button>\n ))}\n </nav>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAiBA,IAAM,IAAoE;CACxE;EAAE,IAAI;EAAO,OAAO;EAAa,MAAM,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA;EAAE;CACtE;EAAE,IAAI;EAAU,OAAO;EAAU,MAAM,kBAAC,GAAD,EAAO,WAAU,UAAW,CAAA;EAAE;CACrE;EAAE,IAAI;EAAW,OAAO;EAAW,MAAM,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA;EAAE;CACtE;EAAE,IAAI;EAAO,OAAO;EAAO,MAAM,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA;EAAE;CACjE;AAED,SAAgB,EAAO,EACrB,cACA,gBACA,UAAO;CAAC;CAAO;CAAU;CAAW;CAAM,IAC5B;CACd,IAAM,EAAE,SAAM,GAAS,EACjB,IAAc,EAAS,QAAQ,MAAQ,EAAK,SAAS,EAAI,GAAG,CAAC,EAC7D,IAAkC;EACtC,KAAK,EAAc,GAAG,0BAA0B,YAAY;EAC5D,QAAQ,EAAc,GAAG,6BAA6B,SAAS;EAC/D,SAAS,EAAc,GAAG,8BAA8B,UAAU;EAClE,KAAK,EAAc,GAAG,0BAA0B,MAAM;EACvD;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IACE,WAAU;IACV,MAAK;IACL,cAAY,EACV,GACA,gCACA,iBACD;cAEA,EAAY,KAAK,MAChB,kBAAC,UAAD;KAEE,eAAe,EAAY,EAAI,GAAG;KAClC,MAAK;KACL,iBAAe,MAAc,EAAI;KACjC,WAAW;;kBAGP,MAAc,EAAI,KACd,wEACA,gGACL;;eAXL,CAcG,EAAI,MACJ,EAAO,EAAI,OAAO,EAAI,MAChB;OAfF,EAAI,GAeF,CACT;IACE,CAAA;GACF,CAAA;EACF,CAAA"}
1
+ {"version":3,"file":"TabBar.js","names":[],"sources":["../../../src/files/components/TabBar.tsx"],"sourcesContent":["import { Clock, Star, Trash2, Folder } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { tWithFallback } from \"../utils/i18n\";\n\nexport type TabView = \"all\" | \"recent\" | \"starred\" | \"bin\";\n\ninterface TabBarProps {\n activeTab: TabView;\n onTabChange: (tab: TabView) => void;\n /**\n * Which tabs to render. Order is preserved. Parent filters out\n * feature-flag-gated tabs (e.g. bin/starred) before passing.\n * @default [\"all\", \"recent\", \"starred\", \"bin\"]\n */\n tabs?: TabView[];\n}\n\nconst ALL_TABS: { id: TabView; label: string; icon: React.ReactNode }[] = [\n { id: \"all\", label: \"All Files\", icon: <Folder className=\"size-5\" /> },\n { id: \"recent\", label: \"Recent\", icon: <Clock className=\"size-5\" /> },\n { id: \"starred\", label: \"Starred\", icon: <Star className=\"size-5\" /> },\n { id: \"bin\", label: \"Bin\", icon: <Trash2 className=\"size-5\" /> },\n];\n\nexport function TabBar({\n activeTab,\n onTabChange,\n tabs = [\"all\", \"recent\", \"starred\", \"bin\"],\n}: TabBarProps) {\n const { t } = useI18n();\n const visibleTabs = ALL_TABS.filter((tab) => tabs.includes(tab.id));\n const labels: Record<TabView, string> = {\n all: tWithFallback(t, \"files.browser.tabs.all\", \"All Files\"),\n recent: tWithFallback(t, \"files.browser.tabs.recent\", \"Recent\"),\n starred: tWithFallback(t, \"files.browser.tabs.starred\", \"Starred\"),\n bin: tWithFallback(t, \"files.browser.tabs.bin\", \"Bin\"),\n };\n\n return (\n <div className=\"bg-bg-surface border-b border-border-default\">\n <div className=\"overflow-x-auto px-4 sm:px-6 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]\">\n <nav\n className=\"-mb-px flex min-w-max gap-1\"\n role=\"tablist\"\n aria-label={tWithFallback(\n t,\n \"files.browser.tabs.ariaLabel\",\n \"Files sections\",\n )}\n >\n {visibleTabs.map((tab) => (\n <button\n type=\"button\"\n key={tab.id}\n onClick={() => onTabChange(tab.id)}\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n className={`\n flex items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium border-b-2 transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-border focus-visible:ring-offset-2\n ${\n activeTab === tab.id\n ? \"border-action-primary-bg text-text-primary bg-action-ghost-bg-hover\"\n : \"border-transparent text-text-secondary hover:text-text-primary hover:bg-action-ghost-bg-hover\"\n }\n `}\n >\n {tab.icon}\n {labels[tab.id] ?? tab.label}\n </button>\n ))}\n </nav>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAiBA,IAAM,IAAoE;CACxE;EAAE,IAAI;EAAO,OAAO;EAAa,MAAM,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA;EAAE;CACtE;EAAE,IAAI;EAAU,OAAO;EAAU,MAAM,kBAAC,GAAD,EAAO,WAAU,UAAW,CAAA;EAAE;CACrE;EAAE,IAAI;EAAW,OAAO;EAAW,MAAM,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA;EAAE;CACtE;EAAE,IAAI;EAAO,OAAO;EAAO,MAAM,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA;EAAE;CACjE;AAED,SAAgB,EAAO,EACrB,cACA,gBACA,UAAO;CAAC;CAAO;CAAU;CAAW;CAAM,IAC5B;CACd,IAAM,EAAE,SAAM,GAAS,EACjB,IAAc,EAAS,QAAQ,MAAQ,EAAK,SAAS,EAAI,GAAG,CAAC,EAC7D,IAAkC;EACtC,KAAK,EAAc,GAAG,0BAA0B,YAAY;EAC5D,QAAQ,EAAc,GAAG,6BAA6B,SAAS;EAC/D,SAAS,EAAc,GAAG,8BAA8B,UAAU;EAClE,KAAK,EAAc,GAAG,0BAA0B,MAAM;EACvD;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IACE,WAAU;IACV,MAAK;IACL,cAAY,EACV,GACA,gCACA,iBACD;cAEA,EAAY,KAAK,MAChB,kBAAC,UAAD;KACE,MAAK;KAEL,eAAe,EAAY,EAAI,GAAG;KAClC,MAAK;KACL,iBAAe,MAAc,EAAI;KACjC,WAAW;;kBAGP,MAAc,EAAI,KACd,wEACA,gGACL;;eAZL,CAeG,EAAI,MACJ,EAAO,EAAI,OAAO,EAAI,MAChB;OAfF,EAAI,GAeF,CACT;IACE,CAAA;GACF,CAAA;EACF,CAAA"}
@@ -29,6 +29,7 @@ function c({ toast: c, onClose: l }) {
29
29
  children: c.message
30
30
  }),
31
31
  /* @__PURE__ */ o("button", {
32
+ type: "button",
32
33
  onClick: () => l(c.id),
33
34
  className: "text-text-muted hover:text-text-secondary transition-colors",
34
35
  children: /* @__PURE__ */ o(i, { className: "size-4" })
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.js","names":[],"sources":["../../../src/files/components/Toast.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { X, CheckCircle, XCircle, AlertCircle, Info } from \"lucide-react\";\n\nexport type ToastType = \"success\" | \"error\" | \"warning\" | \"info\";\n\nexport interface Toast {\n id: string;\n type: ToastType;\n message: string;\n duration?: number;\n}\n\ninterface ToastItemProps {\n toast: Toast;\n onClose: (id: string) => void;\n}\n\nfunction ToastItem({ toast, onClose }: ToastItemProps) {\n useEffect(() => {\n const duration = toast.duration || 5000;\n const timer = setTimeout(() => {\n onClose(toast.id);\n }, duration);\n\n return () => clearTimeout(timer);\n }, [toast, onClose]);\n\n const icons = {\n success: <CheckCircle className=\"size-5 text-status-success-bg\" />,\n error: <XCircle className=\"size-5 text-status-error-bg\" />,\n warning: <AlertCircle className=\"size-5 text-status-warning-bg\" />,\n info: <Info className=\"size-5 text-status-info-bg\" />,\n };\n\n const colors = {\n success: \"bg-status-success-bg-subtle border-status-success-border\",\n error: \"bg-status-error-bg-subtle border-status-error-border\",\n warning: \"bg-status-warning-bg-subtle border-status-warning-border\",\n info: \"bg-status-info-bg-subtle border-status-info-border\",\n };\n\n return (\n <div\n className={`flex items-center gap-3 p-4 rounded-lg shadow-lg border ${colors[toast.type]} w-80 max-w-[90vw] md:max-w-md animate-in slide-in-from-right duration-300`}\n >\n {icons[toast.type]}\n <p className=\"flex-1 text-sm font-medium text-text-primary\">\n {toast.message}\n </p>\n <button\n onClick={() => onClose(toast.id)}\n className=\"text-text-muted hover:text-text-secondary transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n );\n}\n\ninterface ToastContainerProps {\n toasts: Toast[];\n onClose: (id: string) => void;\n}\n\nexport function ToastContainer({ toasts, onClose }: ToastContainerProps) {\n return (\n <div className=\"fixed bottom-4 right-4 z-50 flex flex-col gap-2\">\n {toasts.map((toast) => (\n <ToastItem key={toast.id} toast={toast} onClose={onClose} />\n ))}\n </div>\n );\n}\n"],"mappings":";;;;AAiBA,SAAS,EAAU,EAAE,UAAO,cAA2B;AACrD,SAAgB;EACd,IAAM,IAAW,EAAM,YAAY,KAC7B,IAAQ,iBAAiB;AAC7B,KAAQ,EAAM,GAAG;KAChB,EAAS;AAEZ,eAAa,aAAa,EAAM;IAC/B,CAAC,GAAO,EAAQ,CAAC;CAEpB,IAAM,IAAQ;EACZ,SAAS,kBAAC,GAAD,EAAa,WAAU,iCAAkC,CAAA;EAClE,OAAO,kBAAC,GAAD,EAAS,WAAU,+BAAgC,CAAA;EAC1D,SAAS,kBAAC,GAAD,EAAa,WAAU,iCAAkC,CAAA;EAClE,MAAM,kBAAC,GAAD,EAAM,WAAU,8BAA+B,CAAA;EACtD;AASD,QACE,kBAAC,OAAD;EACE,WAAW,2DATA;GACb,SAAS;GACT,OAAO;GACP,SAAS;GACT,MAAM;GACP,CAIgF,EAAM,MAAM;YAD3F;GAGG,EAAM,EAAM;GACb,kBAAC,KAAD;IAAG,WAAU;cACV,EAAM;IACL,CAAA;GACJ,kBAAC,UAAD;IACE,eAAe,EAAQ,EAAM,GAAG;IAChC,WAAU;cAEV,kBAAC,GAAD,EAAG,WAAU,UAAW,CAAA;IACjB,CAAA;GACL;;;AASV,SAAgB,EAAe,EAAE,WAAQ,cAAgC;AACvE,QACE,kBAAC,OAAD;EAAK,WAAU;YACZ,EAAO,KAAK,MACX,kBAAC,GAAD;GAAiC;GAAgB;GAAW,EAA5C,EAAM,GAAsC,CAC5D;EACE,CAAA"}
1
+ {"version":3,"file":"Toast.js","names":[],"sources":["../../../src/files/components/Toast.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { X, CheckCircle, XCircle, AlertCircle, Info } from \"lucide-react\";\n\nexport type ToastType = \"success\" | \"error\" | \"warning\" | \"info\";\n\nexport interface Toast {\n id: string;\n type: ToastType;\n message: string;\n duration?: number;\n}\n\ninterface ToastItemProps {\n toast: Toast;\n onClose: (id: string) => void;\n}\n\nfunction ToastItem({ toast, onClose }: ToastItemProps) {\n useEffect(() => {\n const duration = toast.duration || 5000;\n const timer = setTimeout(() => {\n onClose(toast.id);\n }, duration);\n\n return () => clearTimeout(timer);\n }, [toast, onClose]);\n\n const icons = {\n success: <CheckCircle className=\"size-5 text-status-success-bg\" />,\n error: <XCircle className=\"size-5 text-status-error-bg\" />,\n warning: <AlertCircle className=\"size-5 text-status-warning-bg\" />,\n info: <Info className=\"size-5 text-status-info-bg\" />,\n };\n\n const colors = {\n success: \"bg-status-success-bg-subtle border-status-success-border\",\n error: \"bg-status-error-bg-subtle border-status-error-border\",\n warning: \"bg-status-warning-bg-subtle border-status-warning-border\",\n info: \"bg-status-info-bg-subtle border-status-info-border\",\n };\n\n return (\n <div\n className={`flex items-center gap-3 p-4 rounded-lg shadow-lg border ${colors[toast.type]} w-80 max-w-[90vw] md:max-w-md animate-in slide-in-from-right duration-300`}\n >\n {icons[toast.type]}\n <p className=\"flex-1 text-sm font-medium text-text-primary\">\n {toast.message}\n </p>\n <button\n type=\"button\"\n onClick={() => onClose(toast.id)}\n className=\"text-text-muted hover:text-text-secondary transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n );\n}\n\ninterface ToastContainerProps {\n toasts: Toast[];\n onClose: (id: string) => void;\n}\n\nexport function ToastContainer({ toasts, onClose }: ToastContainerProps) {\n return (\n <div className=\"fixed bottom-4 right-4 z-50 flex flex-col gap-2\">\n {toasts.map((toast) => (\n <ToastItem key={toast.id} toast={toast} onClose={onClose} />\n ))}\n </div>\n );\n}\n"],"mappings":";;;;AAiBA,SAAS,EAAU,EAAE,UAAO,cAA2B;AACrD,SAAgB;EACd,IAAM,IAAW,EAAM,YAAY,KAC7B,IAAQ,iBAAiB;AAC7B,KAAQ,EAAM,GAAG;KAChB,EAAS;AAEZ,eAAa,aAAa,EAAM;IAC/B,CAAC,GAAO,EAAQ,CAAC;CAEpB,IAAM,IAAQ;EACZ,SAAS,kBAAC,GAAD,EAAa,WAAU,iCAAkC,CAAA;EAClE,OAAO,kBAAC,GAAD,EAAS,WAAU,+BAAgC,CAAA;EAC1D,SAAS,kBAAC,GAAD,EAAa,WAAU,iCAAkC,CAAA;EAClE,MAAM,kBAAC,GAAD,EAAM,WAAU,8BAA+B,CAAA;EACtD;AASD,QACE,kBAAC,OAAD;EACE,WAAW,2DATA;GACb,SAAS;GACT,OAAO;GACP,SAAS;GACT,MAAM;GACP,CAIgF,EAAM,MAAM;YAD3F;GAGG,EAAM,EAAM;GACb,kBAAC,KAAD;IAAG,WAAU;cACV,EAAM;IACL,CAAA;GACJ,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAQ,EAAM,GAAG;IAChC,WAAU;cAEV,kBAAC,GAAD,EAAG,WAAU,UAAW,CAAA;IACjB,CAAA;GACL;;;AASV,SAAgB,EAAe,EAAE,WAAQ,cAAgC;AACvE,QACE,kBAAC,OAAD;EAAK,WAAU;YACZ,EAAO,KAAK,MACX,kBAAC,GAAD;GAAiC;GAAgB;GAAW,EAA5C,EAAM,GAAsC,CAC5D;EACE,CAAA"}