@purposeinplay/payload-ai-translate 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +714 -0
  3. package/dist/alerts-collection.d.ts +21 -0
  4. package/dist/alerts-collection.js +159 -0
  5. package/dist/api.d.ts +4 -0
  6. package/dist/api.js +918 -0
  7. package/dist/bulk-translate-batches-collection.d.ts +29 -0
  8. package/dist/bulk-translate-batches-collection.js +404 -0
  9. package/dist/bulk-translate-units-collection.d.ts +35 -0
  10. package/dist/bulk-translate-units-collection.js +310 -0
  11. package/dist/client/estimated-cost-cell.d.ts +6 -0
  12. package/dist/client/estimated-cost-cell.js +12 -0
  13. package/dist/client/excluded-fields-field.d.ts +45 -0
  14. package/dist/client/excluded-fields-field.js +553 -0
  15. package/dist/client/field-translate-button.d.ts +6 -0
  16. package/dist/client/field-translate-button.js +199 -0
  17. package/dist/client/index.d.ts +6 -0
  18. package/dist/client/index.js +6 -0
  19. package/dist/client/lib/use-global-kill-switches.d.ts +20 -0
  20. package/dist/client/lib/use-global-kill-switches.js +58 -0
  21. package/dist/client/translate-button.d.ts +2 -0
  22. package/dist/client/translate-button.js +228 -0
  23. package/dist/client/translate-modal.d.ts +16 -0
  24. package/dist/client/translate-modal.js +549 -0
  25. package/dist/client/translation-progress.d.ts +10 -0
  26. package/dist/client/translation-progress.js +297 -0
  27. package/dist/components/TranslationNavGroup.d.ts +45 -0
  28. package/dist/components/TranslationNavGroup.js +104 -0
  29. package/dist/defaults.d.ts +11 -0
  30. package/dist/defaults.js +16 -0
  31. package/dist/endpoints/client-config.d.ts +44 -0
  32. package/dist/endpoints/client-config.js +145 -0
  33. package/dist/endpoints/estimate.d.ts +5 -0
  34. package/dist/endpoints/estimate.js +237 -0
  35. package/dist/endpoints/progress.d.ts +2 -0
  36. package/dist/endpoints/progress.js +314 -0
  37. package/dist/endpoints/translate.d.ts +11 -0
  38. package/dist/endpoints/translate.js +376 -0
  39. package/dist/endpoints/translation-hub/_helpers.d.ts +140 -0
  40. package/dist/endpoints/translation-hub/_helpers.js +297 -0
  41. package/dist/endpoints/translation-hub/active.d.ts +21 -0
  42. package/dist/endpoints/translation-hub/active.js +220 -0
  43. package/dist/endpoints/translation-hub/cancel.d.ts +22 -0
  44. package/dist/endpoints/translation-hub/cancel.js +233 -0
  45. package/dist/endpoints/translation-hub/enqueue.d.ts +70 -0
  46. package/dist/endpoints/translation-hub/enqueue.js +529 -0
  47. package/dist/endpoints/translation-hub/failures.d.ts +12 -0
  48. package/dist/endpoints/translation-hub/failures.js +67 -0
  49. package/dist/endpoints/translation-hub/force-reset.d.ts +20 -0
  50. package/dist/endpoints/translation-hub/force-reset.js +144 -0
  51. package/dist/endpoints/translation-hub/index.d.ts +21 -0
  52. package/dist/endpoints/translation-hub/index.js +20 -0
  53. package/dist/endpoints/translation-hub/list.d.ts +40 -0
  54. package/dist/endpoints/translation-hub/list.js +182 -0
  55. package/dist/endpoints/translation-hub/preflight.d.ts +19 -0
  56. package/dist/endpoints/translation-hub/preflight.js +141 -0
  57. package/dist/endpoints/translation-hub/retry-failed.d.ts +38 -0
  58. package/dist/endpoints/translation-hub/retry-failed.js +235 -0
  59. package/dist/endpoints/translation-hub/revert.d.ts +88 -0
  60. package/dist/endpoints/translation-hub/revert.js +405 -0
  61. package/dist/endpoints/translation-hub/status.d.ts +45 -0
  62. package/dist/endpoints/translation-hub/status.js +391 -0
  63. package/dist/endpoints/translation-hub/usage-summary.d.ts +114 -0
  64. package/dist/endpoints/translation-hub/usage-summary.js +481 -0
  65. package/dist/exports/client.d.ts +6 -0
  66. package/dist/exports/client.js +6 -0
  67. package/dist/exports/components.d.ts +6 -0
  68. package/dist/exports/components.js +5 -0
  69. package/dist/exports/index.d.ts +8 -0
  70. package/dist/exports/index.js +7 -0
  71. package/dist/exports/providers.d.ts +9 -0
  72. package/dist/exports/providers.js +5 -0
  73. package/dist/exports/views-client.d.ts +23 -0
  74. package/dist/exports/views-client.js +22 -0
  75. package/dist/exports/views.d.ts +30 -0
  76. package/dist/exports/views.js +29 -0
  77. package/dist/hooks/after-change-global.d.ts +4 -0
  78. package/dist/hooks/after-change-global.js +109 -0
  79. package/dist/hooks/after-change.d.ts +16 -0
  80. package/dist/hooks/after-change.js +205 -0
  81. package/dist/hooks/after-delete.d.ts +30 -0
  82. package/dist/hooks/after-delete.js +95 -0
  83. package/dist/index.d.ts +5 -0
  84. package/dist/index.js +5 -0
  85. package/dist/jobs-collection.d.ts +17 -0
  86. package/dist/jobs-collection.js +139 -0
  87. package/dist/lexical/classifier.d.ts +3 -0
  88. package/dist/lexical/classifier.js +108 -0
  89. package/dist/lexical/deserializer.d.ts +4 -0
  90. package/dist/lexical/deserializer.js +263 -0
  91. package/dist/lexical/placeholder-integrity.d.ts +6 -0
  92. package/dist/lexical/placeholder-integrity.js +21 -0
  93. package/dist/lexical/placeholders.d.ts +21 -0
  94. package/dist/lexical/placeholders.js +117 -0
  95. package/dist/lexical/serializer.d.ts +21 -0
  96. package/dist/lexical/serializer.js +233 -0
  97. package/dist/lexical/types.d.ts +32 -0
  98. package/dist/lexical/types.js +1 -0
  99. package/dist/lib/auth-diagnostics.d.ts +14 -0
  100. package/dist/lib/auth-diagnostics.js +19 -0
  101. package/dist/lib/batch-counts.d.ts +58 -0
  102. package/dist/lib/batch-counts.js +105 -0
  103. package/dist/lib/bulk-translate-migrations.d.ts +92 -0
  104. package/dist/lib/bulk-translate-migrations.js +153 -0
  105. package/dist/lib/coalescing-queue.d.ts +38 -0
  106. package/dist/lib/coalescing-queue.js +69 -0
  107. package/dist/lib/content-extractor.d.ts +16 -0
  108. package/dist/lib/content-extractor.js +410 -0
  109. package/dist/lib/content-hash.d.ts +1 -0
  110. package/dist/lib/content-hash.js +19 -0
  111. package/dist/lib/content-patcher.d.ts +15 -0
  112. package/dist/lib/content-patcher.js +293 -0
  113. package/dist/lib/cost-guards.d.ts +2 -0
  114. package/dist/lib/cost-guards.js +18 -0
  115. package/dist/lib/daily-spend-cap.d.ts +58 -0
  116. package/dist/lib/daily-spend-cap.js +233 -0
  117. package/dist/lib/effective-locales.d.ts +181 -0
  118. package/dist/lib/effective-locales.js +302 -0
  119. package/dist/lib/error-messages.d.ts +245 -0
  120. package/dist/lib/error-messages.js +626 -0
  121. package/dist/lib/events.d.ts +39 -0
  122. package/dist/lib/events.js +146 -0
  123. package/dist/lib/exclude-fields.d.ts +3 -0
  124. package/dist/lib/exclude-fields.js +64 -0
  125. package/dist/lib/field-breadcrumb.d.ts +31 -0
  126. package/dist/lib/field-breadcrumb.js +227 -0
  127. package/dist/lib/field-diff.d.ts +1 -0
  128. package/dist/lib/field-diff.js +25 -0
  129. package/dist/lib/field-empty.d.ts +2 -0
  130. package/dist/lib/field-empty.js +68 -0
  131. package/dist/lib/field-resolver.d.ts +3 -0
  132. package/dist/lib/field-resolver.js +164 -0
  133. package/dist/lib/group-soft-skips.d.ts +39 -0
  134. package/dist/lib/group-soft-skips.js +45 -0
  135. package/dist/lib/locale-merge.d.ts +44 -0
  136. package/dist/lib/locale-merge.js +357 -0
  137. package/dist/lib/locale-row-check.d.ts +30 -0
  138. package/dist/lib/locale-row-check.js +64 -0
  139. package/dist/lib/logger.d.ts +74 -0
  140. package/dist/lib/logger.js +97 -0
  141. package/dist/lib/manual-edit-guard.d.ts +128 -0
  142. package/dist/lib/manual-edit-guard.js +393 -0
  143. package/dist/lib/output-validation.d.ts +48 -0
  144. package/dist/lib/output-validation.js +148 -0
  145. package/dist/lib/payload-read.d.ts +16 -0
  146. package/dist/lib/payload-read.js +51 -0
  147. package/dist/lib/per-doc-claim.d.ts +90 -0
  148. package/dist/lib/per-doc-claim.js +140 -0
  149. package/dist/lib/per-doc-lock.d.ts +94 -0
  150. package/dist/lib/per-doc-lock.js +119 -0
  151. package/dist/lib/persist-usage.d.ts +91 -0
  152. package/dist/lib/persist-usage.js +116 -0
  153. package/dist/lib/progress-store.d.ts +103 -0
  154. package/dist/lib/progress-store.js +314 -0
  155. package/dist/lib/rate-limiter.d.ts +3 -0
  156. package/dist/lib/rate-limiter.js +53 -0
  157. package/dist/lib/snapshot-select.d.ts +43 -0
  158. package/dist/lib/snapshot-select.js +108 -0
  159. package/dist/lib/translate-prompt.d.ts +31 -0
  160. package/dist/lib/translate-prompt.js +66 -0
  161. package/dist/lib/translation-token-bucket.d.ts +57 -0
  162. package/dist/lib/translation-token-bucket.js +365 -0
  163. package/dist/lib/truncate-source-value.d.ts +1 -0
  164. package/dist/lib/truncate-source-value.js +27 -0
  165. package/dist/manual-edit-collection.d.ts +22 -0
  166. package/dist/manual-edit-collection.js +124 -0
  167. package/dist/plugin.d.ts +3 -0
  168. package/dist/plugin.js +934 -0
  169. package/dist/providers/ai-sdk-adapter.d.ts +35 -0
  170. package/dist/providers/ai-sdk-adapter.js +100 -0
  171. package/dist/providers/anthropic.d.ts +31 -0
  172. package/dist/providers/anthropic.js +66 -0
  173. package/dist/providers/custom.d.ts +36 -0
  174. package/dist/providers/custom.js +24 -0
  175. package/dist/providers/gemini.d.ts +20 -0
  176. package/dist/providers/gemini.js +48 -0
  177. package/dist/providers/mock.d.ts +2 -0
  178. package/dist/providers/mock.js +29 -0
  179. package/dist/providers/openai.d.ts +28 -0
  180. package/dist/providers/openai.js +69 -0
  181. package/dist/settings-global.d.ts +74 -0
  182. package/dist/settings-global.js +216 -0
  183. package/dist/tasks/bulk-translate-coordinator.d.ts +115 -0
  184. package/dist/tasks/bulk-translate-coordinator.js +708 -0
  185. package/dist/tasks/bulk-translate-doc-task.d.ts +142 -0
  186. package/dist/tasks/bulk-translate-doc-task.js +1000 -0
  187. package/dist/tasks/bulk-translate-janitor.d.ts +87 -0
  188. package/dist/tasks/bulk-translate-janitor.js +311 -0
  189. package/dist/tasks/translate-job-task.d.ts +51 -0
  190. package/dist/tasks/translate-job-task.js +154 -0
  191. package/dist/translate.d.ts +113 -0
  192. package/dist/translate.js +911 -0
  193. package/dist/translation-daily-spend-collection.d.ts +24 -0
  194. package/dist/translation-daily-spend-collection.js +133 -0
  195. package/dist/translation-rate-limits-collection.d.ts +30 -0
  196. package/dist/translation-rate-limits-collection.js +144 -0
  197. package/dist/types.d.ts +672 -0
  198. package/dist/types.js +1 -0
  199. package/dist/usage-collection.d.ts +14 -0
  200. package/dist/usage-collection.js +377 -0
  201. package/dist/views/BulkRunsHub/BatchRow.d.ts +32 -0
  202. package/dist/views/BulkRunsHub/BatchRow.js +1222 -0
  203. package/dist/views/BulkRunsHub/BucketRow.d.ts +62 -0
  204. package/dist/views/BulkRunsHub/BucketRow.js +982 -0
  205. package/dist/views/BulkRunsHub/BulkRunsHub.client.d.ts +18 -0
  206. package/dist/views/BulkRunsHub/BulkRunsHub.client.js +331 -0
  207. package/dist/views/BulkRunsHub/EmptyState.d.ts +6 -0
  208. package/dist/views/BulkRunsHub/EmptyState.js +64 -0
  209. package/dist/views/BulkRunsHub/FilterBar.d.ts +16 -0
  210. package/dist/views/BulkRunsHub/FilterBar.js +284 -0
  211. package/dist/views/BulkRunsHub/InFlightBanner.d.ts +14 -0
  212. package/dist/views/BulkRunsHub/InFlightBanner.js +59 -0
  213. package/dist/views/BulkRunsHub/StatusBadge.d.ts +64 -0
  214. package/dist/views/BulkRunsHub/StatusBadge.js +248 -0
  215. package/dist/views/BulkRunsHub/SummaryStrip.d.ts +22 -0
  216. package/dist/views/BulkRunsHub/SummaryStrip.js +249 -0
  217. package/dist/views/BulkRunsHub/bucket-grouping.d.ts +200 -0
  218. package/dist/views/BulkRunsHub/bucket-grouping.js +344 -0
  219. package/dist/views/BulkRunsHub/bucketFailureSummary.d.ts +9 -0
  220. package/dist/views/BulkRunsHub/bucketFailureSummary.js +36 -0
  221. package/dist/views/BulkRunsHub/dedupedStatusFetch.d.ts +5 -0
  222. package/dist/views/BulkRunsHub/dedupedStatusFetch.js +45 -0
  223. package/dist/views/BulkRunsHub/index.d.ts +17 -0
  224. package/dist/views/BulkRunsHub/index.js +80 -0
  225. package/dist/views/BulkRunsHub/urlFilters.d.ts +14 -0
  226. package/dist/views/BulkRunsHub/urlFilters.js +50 -0
  227. package/dist/views/BulkRunsHub/useBulkRunsList.d.ts +26 -0
  228. package/dist/views/BulkRunsHub/useBulkRunsList.js +204 -0
  229. package/dist/views/BulkRunsHub/useUrlFilters.d.ts +10 -0
  230. package/dist/views/BulkRunsHub/useUrlFilters.js +88 -0
  231. package/dist/views/TranslationHub/ActiveJobs.d.ts +6 -0
  232. package/dist/views/TranslationHub/ActiveJobs.js +320 -0
  233. package/dist/views/TranslationHub/AdvancedPanel.d.ts +17 -0
  234. package/dist/views/TranslationHub/AdvancedPanel.js +996 -0
  235. package/dist/views/TranslationHub/AlertBanner.d.ts +6 -0
  236. package/dist/views/TranslationHub/AlertBanner.js +568 -0
  237. package/dist/views/TranslationHub/AuditPanel.d.ts +6 -0
  238. package/dist/views/TranslationHub/AuditPanel.helpers.d.ts +44 -0
  239. package/dist/views/TranslationHub/AuditPanel.helpers.js +71 -0
  240. package/dist/views/TranslationHub/AuditPanel.js +1367 -0
  241. package/dist/views/TranslationHub/BulkTranslate.types.d.ts +242 -0
  242. package/dist/views/TranslationHub/BulkTranslate.types.js +36 -0
  243. package/dist/views/TranslationHub/BulkTranslateFailureDrawer.d.ts +19 -0
  244. package/dist/views/TranslationHub/BulkTranslateFailureDrawer.js +332 -0
  245. package/dist/views/TranslationHub/BulkTranslateMonitor.d.ts +28 -0
  246. package/dist/views/TranslationHub/BulkTranslateMonitor.js +305 -0
  247. package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.d.ts +3 -0
  248. package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.js +42 -0
  249. package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.d.ts +26 -0
  250. package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.js +95 -0
  251. package/dist/views/TranslationHub/BulkTranslatePreflightModal.d.ts +22 -0
  252. package/dist/views/TranslationHub/BulkTranslatePreflightModal.js +879 -0
  253. package/dist/views/TranslationHub/BulkTranslateTerminalCard.d.ts +29 -0
  254. package/dist/views/TranslationHub/BulkTranslateTerminalCard.js +445 -0
  255. package/dist/views/TranslationHub/BulkTranslateTrigger.d.ts +66 -0
  256. package/dist/views/TranslationHub/BulkTranslateTrigger.js +161 -0
  257. package/dist/views/TranslationHub/EditorRecentRunsPanel.d.ts +33 -0
  258. package/dist/views/TranslationHub/EditorRecentRunsPanel.js +290 -0
  259. package/dist/views/TranslationHub/Hub.client.d.ts +74 -0
  260. package/dist/views/TranslationHub/Hub.client.js +357 -0
  261. package/dist/views/TranslationHub/ModelCombobox.d.ts +14 -0
  262. package/dist/views/TranslationHub/ModelCombobox.js +415 -0
  263. package/dist/views/TranslationHub/PerCollectionConfig.d.ts +10 -0
  264. package/dist/views/TranslationHub/PerCollectionConfig.helpers.d.ts +16 -0
  265. package/dist/views/TranslationHub/PerCollectionConfig.helpers.js +19 -0
  266. package/dist/views/TranslationHub/PerCollectionConfig.js +759 -0
  267. package/dist/views/TranslationHub/SettingsRail.d.ts +11 -0
  268. package/dist/views/TranslationHub/SettingsRail.js +382 -0
  269. package/dist/views/TranslationHub/StatusStrip.d.ts +6 -0
  270. package/dist/views/TranslationHub/StatusStrip.js +451 -0
  271. package/dist/views/TranslationHub/UsageTable.d.ts +6 -0
  272. package/dist/views/TranslationHub/UsageTable.helpers.d.ts +69 -0
  273. package/dist/views/TranslationHub/UsageTable.helpers.js +49 -0
  274. package/dist/views/TranslationHub/UsageTable.js +1240 -0
  275. package/dist/views/TranslationHub/alertGrouping.d.ts +70 -0
  276. package/dist/views/TranslationHub/alertGrouping.js +99 -0
  277. package/dist/views/TranslationHub/index.d.ts +20 -0
  278. package/dist/views/TranslationHub/index.js +109 -0
  279. package/dist/views/TranslationHub/tabNavigation.d.ts +53 -0
  280. package/dist/views/TranslationHub/tabNavigation.js +74 -0
  281. package/dist/views/TranslationHub/terminalBannerVisibility.d.ts +33 -0
  282. package/dist/views/TranslationHub/terminalBannerVisibility.js +124 -0
  283. package/dist/views/TranslationHub/useBulkTranslateActive.d.ts +49 -0
  284. package/dist/views/TranslationHub/useBulkTranslateActive.js +251 -0
  285. package/dist/views/TranslationHub/useFocusTrap.d.ts +6 -0
  286. package/dist/views/TranslationHub/useFocusTrap.js +81 -0
  287. package/dist/views/TranslationHub/useTranslationHubUsageSummary.d.ts +77 -0
  288. package/dist/views/TranslationHub/useTranslationHubUsageSummary.js +267 -0
  289. package/dist/views/shared/EditorError.d.ts +97 -0
  290. package/dist/views/shared/EditorError.js +205 -0
  291. package/dist/views/shared/ModelCell.d.ts +18 -0
  292. package/dist/views/shared/ModelCell.js +31 -0
  293. package/dist/views/shared/docHref.d.ts +16 -0
  294. package/dist/views/shared/docHref.js +26 -0
  295. package/dist/views/shared/fetch-error-body.d.ts +25 -0
  296. package/dist/views/shared/fetch-error-body.js +42 -0
  297. package/dist/views/shared/filterPillStyle.d.ts +35 -0
  298. package/dist/views/shared/filterPillStyle.js +40 -0
  299. package/dist/views/shared/format.d.ts +75 -0
  300. package/dist/views/shared/format.js +131 -0
  301. package/package.json +141 -0
@@ -0,0 +1,357 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
+ import { ActiveJobs } from './ActiveJobs.js';
5
+ import { AdvancedPanel } from './AdvancedPanel.js';
6
+ import { AlertBanner } from './AlertBanner.js';
7
+ import { AuditPanel } from './AuditPanel.js';
8
+ import { isActiveStatus, isTerminalStatus } from './BulkTranslate.types.js';
9
+ import { BulkTranslateMonitor } from './BulkTranslateMonitor.js';
10
+ import { BulkTranslateNarrowViewportBanner } from './BulkTranslateNarrowViewportBanner.js';
11
+ import { BulkTranslateTerminalCard } from './BulkTranslateTerminalCard.js';
12
+ import { BulkTranslateTrigger } from './BulkTranslateTrigger.js';
13
+ import { EditorRecentRunsPanel } from './EditorRecentRunsPanel.js';
14
+ import { PerCollectionConfig } from './PerCollectionConfig.js';
15
+ import { SettingsRail } from './SettingsRail.js';
16
+ import { StatusStrip } from './StatusStrip.js';
17
+ import { panelIdFor, resolveTabKey, tabIdFor } from './tabNavigation.js';
18
+ import { useTerminalBannerVisibility } from './terminalBannerVisibility.js';
19
+ import { UsageTable } from './UsageTable.js';
20
+ import { useBulkTranslateActive } from './useBulkTranslateActive.js';
21
+ // Derives the Next.js basePath from the current admin URL (everything
22
+ // before `/admin/`). Hardcoding via env vars would couple the component
23
+ // to one consumer's config — blog-wild uses `/blog`, wild-payload-cms
24
+ // uses ''. Detect at runtime.
25
+ function getBasePath() {
26
+ if (typeof window === 'undefined') {
27
+ return '';
28
+ }
29
+ const idx = window.location.pathname.indexOf('/admin/');
30
+ return idx > 0 ? window.location.pathname.slice(0, idx) : '';
31
+ }
32
+ const TAB_LABELS = {
33
+ overview: 'Overview',
34
+ configuration: 'Configuration',
35
+ audit: 'Audit & Cost',
36
+ advanced: 'Advanced'
37
+ };
38
+ const TAB_DESCRIPTIONS = {
39
+ overview: 'Live status, alerts, in-flight jobs, and recent translation activity.',
40
+ configuration: 'Provider, model, target locales, and per-collection overrides.',
41
+ audit: 'Full translation history with date range and per-collection breakdowns.',
42
+ advanced: 'Developer tools: meta-table inspection, raw event log access.'
43
+ };
44
+ const ADMIN_TAB_ORDER = [
45
+ 'overview',
46
+ 'configuration',
47
+ 'audit',
48
+ 'advanced'
49
+ ];
50
+ // 1.2.8: editors only see Overview. Configuration (provider keys,
51
+ // cost limits), Audit & Cost (global $ / token telemetry), and
52
+ // Advanced (operational tools like force-reset) stay admin-only.
53
+ const EDITOR_TAB_ORDER = [
54
+ 'overview'
55
+ ];
56
+ function getTabOrder(role) {
57
+ return role === 'admin' ? ADMIN_TAB_ORDER : EDITOR_TAB_ORDER;
58
+ }
59
+ export const TranslationHubClient = ({ locales, role, currentUserId, currentUserEmail })=>{
60
+ const basePath = useMemo(getBasePath, []);
61
+ const [activeTab, setActiveTab] = useState('overview');
62
+ // 1.2.8: per-role tab visibility. Editors see Overview only;
63
+ // admins see the full strip. Kept memoized so the array identity
64
+ // is stable across renders (keyboard handler depends on it).
65
+ const tabOrder = useMemo(()=>getTabOrder(role), [
66
+ role
67
+ ]);
68
+ // NEW-4 (v1.2.6): refs onto each `<button role="tab">` so the
69
+ // keyboard handler can move DOM focus to the next tab without
70
+ // waiting for React to re-render. Following the WAI-ARIA Authoring
71
+ // Practices roving-tabindex pattern: only the active tab is
72
+ // `tabIndex=0`; the rest are `-1`, so Tab from outside the strip
73
+ // lands on the active tab, and the next Tab moves to the panel.
74
+ const tabRefs = useRef({
75
+ overview: null,
76
+ configuration: null,
77
+ audit: null,
78
+ advanced: null
79
+ });
80
+ const handleTabKeyDown = useCallback((e)=>{
81
+ const currentIndex = tabOrder.indexOf(activeTab);
82
+ const action = resolveTabKey(e.key, currentIndex, tabOrder.length);
83
+ if (action?.kind !== 'move') {
84
+ return;
85
+ }
86
+ e.preventDefault();
87
+ const nextTab = tabOrder[action.nextIndex];
88
+ if (!nextTab) {
89
+ return;
90
+ }
91
+ setActiveTab(nextTab);
92
+ // Focus the now-active tab so screen-reader users hear the
93
+ // selection move. `useEffect`-after-state would also work but
94
+ // the imperative ref keeps the keystroke → focus pair atomic.
95
+ tabRefs.current[nextTab]?.focus();
96
+ }, [
97
+ activeTab
98
+ ]);
99
+ const [translationSettings, setTranslationSettings] = useState(null);
100
+ const [openRouterSettings, setOpenRouterSettings] = useState(null);
101
+ const [loadError, setLoadError] = useState(null);
102
+ // Single source of truth for bulk-translate state, shared across the
103
+ // monitor + terminal card. The trigger runs its own hook because it
104
+ // ships independently of these surfaces (e.g. cancellation puts the
105
+ // trigger back into "loading" while the terminal card still wants
106
+ // the last known terminal-state snapshot).
107
+ const bulkActive = useBulkTranslateActive(basePath);
108
+ const activeBatch = bulkActive.data?.batch ?? null;
109
+ // HUB-3 (v1.2.6): terminal-card visibility is now a derived,
110
+ // per-batch-id concern. The hook combines a freshness check
111
+ // (≤ 1h past completedAt) with a localStorage-persisted dismissed
112
+ // set keyed by batch id. Previously the in-memory `terminalDismissed`
113
+ // flag reset on every reload, leaving the destructive "Revert this
114
+ // batch" affordance pinned to the Hub for the full 24h revert window.
115
+ const terminalBanner = useTerminalBannerVisibility(activeBatch?.id ?? null, activeBatch?.completedAt ?? null);
116
+ const showBulkMonitor = activeBatch !== null && isActiveStatus(activeBatch.status);
117
+ const showBulkTerminal = activeBatch !== null && isTerminalStatus(activeBatch.status) && terminalBanner.shouldShow;
118
+ // Initial load of both globals.
119
+ useEffect(()=>{
120
+ let cancelled = false;
121
+ Promise.all([
122
+ fetch(`${basePath}/api/globals/translation-settings?depth=0`, {
123
+ credentials: 'include'
124
+ }).then((r)=>r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`))),
125
+ fetch(`${basePath}/api/globals/openrouter-settings?depth=0`, {
126
+ credentials: 'include'
127
+ }).then((r)=>r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`)))
128
+ ]).then(([ts, ors])=>{
129
+ if (cancelled) {
130
+ return;
131
+ }
132
+ setTranslationSettings(ts);
133
+ setOpenRouterSettings(ors);
134
+ }).catch((e)=>{
135
+ if (cancelled) {
136
+ return;
137
+ }
138
+ setLoadError(e instanceof Error ? e.message : String(e));
139
+ });
140
+ return ()=>{
141
+ cancelled = true;
142
+ };
143
+ }, [
144
+ basePath
145
+ ]);
146
+ return /*#__PURE__*/ _jsxs("div", {
147
+ style: {
148
+ padding: '1.5rem 2rem',
149
+ maxWidth: '1400px',
150
+ margin: '0 auto'
151
+ },
152
+ children: [
153
+ /*#__PURE__*/ _jsxs("header", {
154
+ style: {
155
+ marginBottom: '1rem'
156
+ },
157
+ children: [
158
+ /*#__PURE__*/ _jsxs("div", {
159
+ style: {
160
+ display: 'flex',
161
+ alignItems: 'baseline',
162
+ justifyContent: 'space-between',
163
+ marginBottom: '0.75rem'
164
+ },
165
+ children: [
166
+ /*#__PURE__*/ _jsx("h1", {
167
+ style: {
168
+ fontSize: '1.5rem',
169
+ margin: 0,
170
+ color: 'var(--theme-elevation-1000)'
171
+ },
172
+ children: "Translation"
173
+ }),
174
+ /*#__PURE__*/ _jsxs("div", {
175
+ style: {
176
+ display: 'flex',
177
+ alignItems: 'center',
178
+ gap: '1rem'
179
+ },
180
+ children: [
181
+ /*#__PURE__*/ _jsx("p", {
182
+ style: {
183
+ margin: 0,
184
+ color: 'var(--theme-elevation-500)',
185
+ fontSize: '0.875rem'
186
+ },
187
+ children: TAB_DESCRIPTIONS[activeTab]
188
+ }),
189
+ activeTab === 'overview' && /*#__PURE__*/ _jsx(BulkTranslateTrigger, {
190
+ basePath: basePath,
191
+ currentUserId: currentUserId
192
+ })
193
+ ]
194
+ })
195
+ ]
196
+ }),
197
+ /*#__PURE__*/ _jsx("div", {
198
+ "aria-label": "Translation Hub sections",
199
+ role: "tablist",
200
+ style: {
201
+ display: 'flex',
202
+ gap: '0.25rem',
203
+ borderBottom: '1px solid var(--theme-elevation-150)'
204
+ },
205
+ children: tabOrder.map((t)=>{
206
+ const isActive = activeTab === t;
207
+ return /*#__PURE__*/ _jsx("button", {
208
+ "aria-controls": panelIdFor(t),
209
+ "aria-current": isActive ? 'page' : undefined,
210
+ "aria-selected": isActive,
211
+ id: tabIdFor(t),
212
+ onClick: ()=>setActiveTab(t),
213
+ onKeyDown: handleTabKeyDown,
214
+ ref: (el)=>{
215
+ tabRefs.current[t] = el;
216
+ },
217
+ role: "tab",
218
+ style: {
219
+ padding: '0.5rem 0.85rem',
220
+ background: 'transparent',
221
+ border: 'none',
222
+ borderBottom: isActive ? '2px solid var(--theme-success-500, #16a34a)' : '2px solid transparent',
223
+ color: isActive ? 'var(--theme-elevation-1000)' : 'var(--theme-elevation-500)',
224
+ fontWeight: isActive ? 600 : 500,
225
+ fontSize: '0.875rem',
226
+ cursor: 'pointer',
227
+ marginBottom: '-1px'
228
+ },
229
+ tabIndex: isActive ? 0 : -1,
230
+ type: "button",
231
+ children: TAB_LABELS[t]
232
+ }, t);
233
+ })
234
+ })
235
+ ]
236
+ }),
237
+ loadError && /*#__PURE__*/ _jsxs("div", {
238
+ style: {
239
+ padding: '0.75rem 1rem',
240
+ background: 'var(--theme-error-100, #fee2e2)',
241
+ border: '1px solid var(--theme-error-500, #b91c1c)',
242
+ borderRadius: '4px',
243
+ marginBottom: '1rem',
244
+ color: 'var(--theme-error-500, #b91c1c)',
245
+ fontSize: '0.875rem'
246
+ },
247
+ children: [
248
+ "Failed to load translation data: ",
249
+ loadError
250
+ ]
251
+ }),
252
+ /*#__PURE__*/ _jsxs("main", {
253
+ style: {
254
+ marginTop: '1rem',
255
+ display: 'flex',
256
+ flexDirection: 'column',
257
+ gap: '1.5rem'
258
+ },
259
+ children: [
260
+ activeTab === 'overview' && /*#__PURE__*/ _jsxs("div", {
261
+ "aria-labelledby": tabIdFor('overview'),
262
+ id: panelIdFor('overview'),
263
+ role: "tabpanel",
264
+ style: {
265
+ display: 'flex',
266
+ flexDirection: 'column',
267
+ gap: '1.5rem'
268
+ },
269
+ tabIndex: 0,
270
+ children: [
271
+ /*#__PURE__*/ _jsx(BulkTranslateNarrowViewportBanner, {}),
272
+ /*#__PURE__*/ _jsx(AlertBanner, {
273
+ basePath: basePath
274
+ }),
275
+ role === 'admin' && /*#__PURE__*/ _jsx(StatusStrip, {
276
+ basePath: basePath
277
+ }),
278
+ showBulkMonitor && activeBatch ? /*#__PURE__*/ _jsx(BulkTranslateMonitor, {
279
+ basePath: basePath,
280
+ batch: activeBatch,
281
+ isOffline: bulkActive.isOffline,
282
+ onRetry: bulkActive.refetch
283
+ }) : null,
284
+ showBulkTerminal && activeBatch ? /*#__PURE__*/ _jsx(BulkTranslateTerminalCard, {
285
+ basePath: basePath,
286
+ batch: activeBatch,
287
+ onAfterRevert: bulkActive.refetch,
288
+ onDismiss: terminalBanner.dismiss
289
+ }) : null,
290
+ showBulkMonitor ? null : /*#__PURE__*/ _jsx(ActiveJobs, {
291
+ basePath: basePath
292
+ }),
293
+ role === 'admin' ? /*#__PURE__*/ _jsx(UsageTable, {
294
+ basePath: basePath
295
+ }) : /*#__PURE__*/ _jsx(EditorRecentRunsPanel, {
296
+ basePath: basePath,
297
+ currentUserId: currentUserId,
298
+ currentUserEmail: currentUserEmail
299
+ })
300
+ ]
301
+ }),
302
+ role === 'admin' && activeTab === 'configuration' && /*#__PURE__*/ _jsxs("div", {
303
+ "aria-labelledby": tabIdFor('configuration'),
304
+ id: panelIdFor('configuration'),
305
+ role: "tabpanel",
306
+ style: {
307
+ display: 'flex',
308
+ flexDirection: 'column',
309
+ gap: '1rem'
310
+ },
311
+ tabIndex: 0,
312
+ children: [
313
+ /*#__PURE__*/ _jsx(SettingsRail, {
314
+ basePath: basePath,
315
+ locales: locales,
316
+ onSettingsChange: (ts, ors)=>{
317
+ if (ts) {
318
+ setTranslationSettings(ts);
319
+ }
320
+ if (ors) {
321
+ setOpenRouterSettings(ors);
322
+ }
323
+ },
324
+ openRouterSettings: openRouterSettings,
325
+ translationSettings: translationSettings
326
+ }),
327
+ /*#__PURE__*/ _jsx(PerCollectionConfig, {
328
+ basePath: basePath,
329
+ locales: locales,
330
+ onSettingsChange: (ts)=>setTranslationSettings(ts),
331
+ translationSettings: translationSettings
332
+ })
333
+ ]
334
+ }),
335
+ role === 'admin' && activeTab === 'audit' && /*#__PURE__*/ _jsx("div", {
336
+ "aria-labelledby": tabIdFor('audit'),
337
+ id: panelIdFor('audit'),
338
+ role: "tabpanel",
339
+ tabIndex: 0,
340
+ children: /*#__PURE__*/ _jsx(AuditPanel, {
341
+ basePath: basePath
342
+ })
343
+ }),
344
+ role === 'admin' && activeTab === 'advanced' && /*#__PURE__*/ _jsx("div", {
345
+ "aria-labelledby": tabIdFor('advanced'),
346
+ id: panelIdFor('advanced'),
347
+ role: "tabpanel",
348
+ tabIndex: 0,
349
+ children: /*#__PURE__*/ _jsx(AdvancedPanel, {
350
+ basePath: basePath
351
+ })
352
+ })
353
+ ]
354
+ })
355
+ ]
356
+ });
357
+ };
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ interface Props {
3
+ basePath: string;
4
+ disabled?: boolean;
5
+ onChange: (modelId: string) => void;
6
+ value: string;
7
+ }
8
+ /**
9
+ * Compact combobox for the Translation Hub's settings rail. Same data
10
+ * source as the standalone OpenRouter Settings page (`/api/openrouter/models`)
11
+ * but slimmer styling — fits the 320px rail.
12
+ */
13
+ export declare const ModelCombobox: React.FC<Props>;
14
+ export {};