@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.
- package/LICENSE +21 -0
- package/README.md +714 -0
- package/dist/alerts-collection.d.ts +21 -0
- package/dist/alerts-collection.js +159 -0
- package/dist/api.d.ts +4 -0
- package/dist/api.js +918 -0
- package/dist/bulk-translate-batches-collection.d.ts +29 -0
- package/dist/bulk-translate-batches-collection.js +404 -0
- package/dist/bulk-translate-units-collection.d.ts +35 -0
- package/dist/bulk-translate-units-collection.js +310 -0
- package/dist/client/estimated-cost-cell.d.ts +6 -0
- package/dist/client/estimated-cost-cell.js +12 -0
- package/dist/client/excluded-fields-field.d.ts +45 -0
- package/dist/client/excluded-fields-field.js +553 -0
- package/dist/client/field-translate-button.d.ts +6 -0
- package/dist/client/field-translate-button.js +199 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +6 -0
- package/dist/client/lib/use-global-kill-switches.d.ts +20 -0
- package/dist/client/lib/use-global-kill-switches.js +58 -0
- package/dist/client/translate-button.d.ts +2 -0
- package/dist/client/translate-button.js +228 -0
- package/dist/client/translate-modal.d.ts +16 -0
- package/dist/client/translate-modal.js +549 -0
- package/dist/client/translation-progress.d.ts +10 -0
- package/dist/client/translation-progress.js +297 -0
- package/dist/components/TranslationNavGroup.d.ts +45 -0
- package/dist/components/TranslationNavGroup.js +104 -0
- package/dist/defaults.d.ts +11 -0
- package/dist/defaults.js +16 -0
- package/dist/endpoints/client-config.d.ts +44 -0
- package/dist/endpoints/client-config.js +145 -0
- package/dist/endpoints/estimate.d.ts +5 -0
- package/dist/endpoints/estimate.js +237 -0
- package/dist/endpoints/progress.d.ts +2 -0
- package/dist/endpoints/progress.js +314 -0
- package/dist/endpoints/translate.d.ts +11 -0
- package/dist/endpoints/translate.js +376 -0
- package/dist/endpoints/translation-hub/_helpers.d.ts +140 -0
- package/dist/endpoints/translation-hub/_helpers.js +297 -0
- package/dist/endpoints/translation-hub/active.d.ts +21 -0
- package/dist/endpoints/translation-hub/active.js +220 -0
- package/dist/endpoints/translation-hub/cancel.d.ts +22 -0
- package/dist/endpoints/translation-hub/cancel.js +233 -0
- package/dist/endpoints/translation-hub/enqueue.d.ts +70 -0
- package/dist/endpoints/translation-hub/enqueue.js +529 -0
- package/dist/endpoints/translation-hub/failures.d.ts +12 -0
- package/dist/endpoints/translation-hub/failures.js +67 -0
- package/dist/endpoints/translation-hub/force-reset.d.ts +20 -0
- package/dist/endpoints/translation-hub/force-reset.js +144 -0
- package/dist/endpoints/translation-hub/index.d.ts +21 -0
- package/dist/endpoints/translation-hub/index.js +20 -0
- package/dist/endpoints/translation-hub/list.d.ts +40 -0
- package/dist/endpoints/translation-hub/list.js +182 -0
- package/dist/endpoints/translation-hub/preflight.d.ts +19 -0
- package/dist/endpoints/translation-hub/preflight.js +141 -0
- package/dist/endpoints/translation-hub/retry-failed.d.ts +38 -0
- package/dist/endpoints/translation-hub/retry-failed.js +235 -0
- package/dist/endpoints/translation-hub/revert.d.ts +88 -0
- package/dist/endpoints/translation-hub/revert.js +405 -0
- package/dist/endpoints/translation-hub/status.d.ts +45 -0
- package/dist/endpoints/translation-hub/status.js +391 -0
- package/dist/endpoints/translation-hub/usage-summary.d.ts +114 -0
- package/dist/endpoints/translation-hub/usage-summary.js +481 -0
- package/dist/exports/client.d.ts +6 -0
- package/dist/exports/client.js +6 -0
- package/dist/exports/components.d.ts +6 -0
- package/dist/exports/components.js +5 -0
- package/dist/exports/index.d.ts +8 -0
- package/dist/exports/index.js +7 -0
- package/dist/exports/providers.d.ts +9 -0
- package/dist/exports/providers.js +5 -0
- package/dist/exports/views-client.d.ts +23 -0
- package/dist/exports/views-client.js +22 -0
- package/dist/exports/views.d.ts +30 -0
- package/dist/exports/views.js +29 -0
- package/dist/hooks/after-change-global.d.ts +4 -0
- package/dist/hooks/after-change-global.js +109 -0
- package/dist/hooks/after-change.d.ts +16 -0
- package/dist/hooks/after-change.js +205 -0
- package/dist/hooks/after-delete.d.ts +30 -0
- package/dist/hooks/after-delete.js +95 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/jobs-collection.d.ts +17 -0
- package/dist/jobs-collection.js +139 -0
- package/dist/lexical/classifier.d.ts +3 -0
- package/dist/lexical/classifier.js +108 -0
- package/dist/lexical/deserializer.d.ts +4 -0
- package/dist/lexical/deserializer.js +263 -0
- package/dist/lexical/placeholder-integrity.d.ts +6 -0
- package/dist/lexical/placeholder-integrity.js +21 -0
- package/dist/lexical/placeholders.d.ts +21 -0
- package/dist/lexical/placeholders.js +117 -0
- package/dist/lexical/serializer.d.ts +21 -0
- package/dist/lexical/serializer.js +233 -0
- package/dist/lexical/types.d.ts +32 -0
- package/dist/lexical/types.js +1 -0
- package/dist/lib/auth-diagnostics.d.ts +14 -0
- package/dist/lib/auth-diagnostics.js +19 -0
- package/dist/lib/batch-counts.d.ts +58 -0
- package/dist/lib/batch-counts.js +105 -0
- package/dist/lib/bulk-translate-migrations.d.ts +92 -0
- package/dist/lib/bulk-translate-migrations.js +153 -0
- package/dist/lib/coalescing-queue.d.ts +38 -0
- package/dist/lib/coalescing-queue.js +69 -0
- package/dist/lib/content-extractor.d.ts +16 -0
- package/dist/lib/content-extractor.js +410 -0
- package/dist/lib/content-hash.d.ts +1 -0
- package/dist/lib/content-hash.js +19 -0
- package/dist/lib/content-patcher.d.ts +15 -0
- package/dist/lib/content-patcher.js +293 -0
- package/dist/lib/cost-guards.d.ts +2 -0
- package/dist/lib/cost-guards.js +18 -0
- package/dist/lib/daily-spend-cap.d.ts +58 -0
- package/dist/lib/daily-spend-cap.js +233 -0
- package/dist/lib/effective-locales.d.ts +181 -0
- package/dist/lib/effective-locales.js +302 -0
- package/dist/lib/error-messages.d.ts +245 -0
- package/dist/lib/error-messages.js +626 -0
- package/dist/lib/events.d.ts +39 -0
- package/dist/lib/events.js +146 -0
- package/dist/lib/exclude-fields.d.ts +3 -0
- package/dist/lib/exclude-fields.js +64 -0
- package/dist/lib/field-breadcrumb.d.ts +31 -0
- package/dist/lib/field-breadcrumb.js +227 -0
- package/dist/lib/field-diff.d.ts +1 -0
- package/dist/lib/field-diff.js +25 -0
- package/dist/lib/field-empty.d.ts +2 -0
- package/dist/lib/field-empty.js +68 -0
- package/dist/lib/field-resolver.d.ts +3 -0
- package/dist/lib/field-resolver.js +164 -0
- package/dist/lib/group-soft-skips.d.ts +39 -0
- package/dist/lib/group-soft-skips.js +45 -0
- package/dist/lib/locale-merge.d.ts +44 -0
- package/dist/lib/locale-merge.js +357 -0
- package/dist/lib/locale-row-check.d.ts +30 -0
- package/dist/lib/locale-row-check.js +64 -0
- package/dist/lib/logger.d.ts +74 -0
- package/dist/lib/logger.js +97 -0
- package/dist/lib/manual-edit-guard.d.ts +128 -0
- package/dist/lib/manual-edit-guard.js +393 -0
- package/dist/lib/output-validation.d.ts +48 -0
- package/dist/lib/output-validation.js +148 -0
- package/dist/lib/payload-read.d.ts +16 -0
- package/dist/lib/payload-read.js +51 -0
- package/dist/lib/per-doc-claim.d.ts +90 -0
- package/dist/lib/per-doc-claim.js +140 -0
- package/dist/lib/per-doc-lock.d.ts +94 -0
- package/dist/lib/per-doc-lock.js +119 -0
- package/dist/lib/persist-usage.d.ts +91 -0
- package/dist/lib/persist-usage.js +116 -0
- package/dist/lib/progress-store.d.ts +103 -0
- package/dist/lib/progress-store.js +314 -0
- package/dist/lib/rate-limiter.d.ts +3 -0
- package/dist/lib/rate-limiter.js +53 -0
- package/dist/lib/snapshot-select.d.ts +43 -0
- package/dist/lib/snapshot-select.js +108 -0
- package/dist/lib/translate-prompt.d.ts +31 -0
- package/dist/lib/translate-prompt.js +66 -0
- package/dist/lib/translation-token-bucket.d.ts +57 -0
- package/dist/lib/translation-token-bucket.js +365 -0
- package/dist/lib/truncate-source-value.d.ts +1 -0
- package/dist/lib/truncate-source-value.js +27 -0
- package/dist/manual-edit-collection.d.ts +22 -0
- package/dist/manual-edit-collection.js +124 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.js +934 -0
- package/dist/providers/ai-sdk-adapter.d.ts +35 -0
- package/dist/providers/ai-sdk-adapter.js +100 -0
- package/dist/providers/anthropic.d.ts +31 -0
- package/dist/providers/anthropic.js +66 -0
- package/dist/providers/custom.d.ts +36 -0
- package/dist/providers/custom.js +24 -0
- package/dist/providers/gemini.d.ts +20 -0
- package/dist/providers/gemini.js +48 -0
- package/dist/providers/mock.d.ts +2 -0
- package/dist/providers/mock.js +29 -0
- package/dist/providers/openai.d.ts +28 -0
- package/dist/providers/openai.js +69 -0
- package/dist/settings-global.d.ts +74 -0
- package/dist/settings-global.js +216 -0
- package/dist/tasks/bulk-translate-coordinator.d.ts +115 -0
- package/dist/tasks/bulk-translate-coordinator.js +708 -0
- package/dist/tasks/bulk-translate-doc-task.d.ts +142 -0
- package/dist/tasks/bulk-translate-doc-task.js +1000 -0
- package/dist/tasks/bulk-translate-janitor.d.ts +87 -0
- package/dist/tasks/bulk-translate-janitor.js +311 -0
- package/dist/tasks/translate-job-task.d.ts +51 -0
- package/dist/tasks/translate-job-task.js +154 -0
- package/dist/translate.d.ts +113 -0
- package/dist/translate.js +911 -0
- package/dist/translation-daily-spend-collection.d.ts +24 -0
- package/dist/translation-daily-spend-collection.js +133 -0
- package/dist/translation-rate-limits-collection.d.ts +30 -0
- package/dist/translation-rate-limits-collection.js +144 -0
- package/dist/types.d.ts +672 -0
- package/dist/types.js +1 -0
- package/dist/usage-collection.d.ts +14 -0
- package/dist/usage-collection.js +377 -0
- package/dist/views/BulkRunsHub/BatchRow.d.ts +32 -0
- package/dist/views/BulkRunsHub/BatchRow.js +1222 -0
- package/dist/views/BulkRunsHub/BucketRow.d.ts +62 -0
- package/dist/views/BulkRunsHub/BucketRow.js +982 -0
- package/dist/views/BulkRunsHub/BulkRunsHub.client.d.ts +18 -0
- package/dist/views/BulkRunsHub/BulkRunsHub.client.js +331 -0
- package/dist/views/BulkRunsHub/EmptyState.d.ts +6 -0
- package/dist/views/BulkRunsHub/EmptyState.js +64 -0
- package/dist/views/BulkRunsHub/FilterBar.d.ts +16 -0
- package/dist/views/BulkRunsHub/FilterBar.js +284 -0
- package/dist/views/BulkRunsHub/InFlightBanner.d.ts +14 -0
- package/dist/views/BulkRunsHub/InFlightBanner.js +59 -0
- package/dist/views/BulkRunsHub/StatusBadge.d.ts +64 -0
- package/dist/views/BulkRunsHub/StatusBadge.js +248 -0
- package/dist/views/BulkRunsHub/SummaryStrip.d.ts +22 -0
- package/dist/views/BulkRunsHub/SummaryStrip.js +249 -0
- package/dist/views/BulkRunsHub/bucket-grouping.d.ts +200 -0
- package/dist/views/BulkRunsHub/bucket-grouping.js +344 -0
- package/dist/views/BulkRunsHub/bucketFailureSummary.d.ts +9 -0
- package/dist/views/BulkRunsHub/bucketFailureSummary.js +36 -0
- package/dist/views/BulkRunsHub/dedupedStatusFetch.d.ts +5 -0
- package/dist/views/BulkRunsHub/dedupedStatusFetch.js +45 -0
- package/dist/views/BulkRunsHub/index.d.ts +17 -0
- package/dist/views/BulkRunsHub/index.js +80 -0
- package/dist/views/BulkRunsHub/urlFilters.d.ts +14 -0
- package/dist/views/BulkRunsHub/urlFilters.js +50 -0
- package/dist/views/BulkRunsHub/useBulkRunsList.d.ts +26 -0
- package/dist/views/BulkRunsHub/useBulkRunsList.js +204 -0
- package/dist/views/BulkRunsHub/useUrlFilters.d.ts +10 -0
- package/dist/views/BulkRunsHub/useUrlFilters.js +88 -0
- package/dist/views/TranslationHub/ActiveJobs.d.ts +6 -0
- package/dist/views/TranslationHub/ActiveJobs.js +320 -0
- package/dist/views/TranslationHub/AdvancedPanel.d.ts +17 -0
- package/dist/views/TranslationHub/AdvancedPanel.js +996 -0
- package/dist/views/TranslationHub/AlertBanner.d.ts +6 -0
- package/dist/views/TranslationHub/AlertBanner.js +568 -0
- package/dist/views/TranslationHub/AuditPanel.d.ts +6 -0
- package/dist/views/TranslationHub/AuditPanel.helpers.d.ts +44 -0
- package/dist/views/TranslationHub/AuditPanel.helpers.js +71 -0
- package/dist/views/TranslationHub/AuditPanel.js +1367 -0
- package/dist/views/TranslationHub/BulkTranslate.types.d.ts +242 -0
- package/dist/views/TranslationHub/BulkTranslate.types.js +36 -0
- package/dist/views/TranslationHub/BulkTranslateFailureDrawer.d.ts +19 -0
- package/dist/views/TranslationHub/BulkTranslateFailureDrawer.js +332 -0
- package/dist/views/TranslationHub/BulkTranslateMonitor.d.ts +28 -0
- package/dist/views/TranslationHub/BulkTranslateMonitor.js +305 -0
- package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.d.ts +3 -0
- package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.js +42 -0
- package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.d.ts +26 -0
- package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.js +95 -0
- package/dist/views/TranslationHub/BulkTranslatePreflightModal.d.ts +22 -0
- package/dist/views/TranslationHub/BulkTranslatePreflightModal.js +879 -0
- package/dist/views/TranslationHub/BulkTranslateTerminalCard.d.ts +29 -0
- package/dist/views/TranslationHub/BulkTranslateTerminalCard.js +445 -0
- package/dist/views/TranslationHub/BulkTranslateTrigger.d.ts +66 -0
- package/dist/views/TranslationHub/BulkTranslateTrigger.js +161 -0
- package/dist/views/TranslationHub/EditorRecentRunsPanel.d.ts +33 -0
- package/dist/views/TranslationHub/EditorRecentRunsPanel.js +290 -0
- package/dist/views/TranslationHub/Hub.client.d.ts +74 -0
- package/dist/views/TranslationHub/Hub.client.js +357 -0
- package/dist/views/TranslationHub/ModelCombobox.d.ts +14 -0
- package/dist/views/TranslationHub/ModelCombobox.js +415 -0
- package/dist/views/TranslationHub/PerCollectionConfig.d.ts +10 -0
- package/dist/views/TranslationHub/PerCollectionConfig.helpers.d.ts +16 -0
- package/dist/views/TranslationHub/PerCollectionConfig.helpers.js +19 -0
- package/dist/views/TranslationHub/PerCollectionConfig.js +759 -0
- package/dist/views/TranslationHub/SettingsRail.d.ts +11 -0
- package/dist/views/TranslationHub/SettingsRail.js +382 -0
- package/dist/views/TranslationHub/StatusStrip.d.ts +6 -0
- package/dist/views/TranslationHub/StatusStrip.js +451 -0
- package/dist/views/TranslationHub/UsageTable.d.ts +6 -0
- package/dist/views/TranslationHub/UsageTable.helpers.d.ts +69 -0
- package/dist/views/TranslationHub/UsageTable.helpers.js +49 -0
- package/dist/views/TranslationHub/UsageTable.js +1240 -0
- package/dist/views/TranslationHub/alertGrouping.d.ts +70 -0
- package/dist/views/TranslationHub/alertGrouping.js +99 -0
- package/dist/views/TranslationHub/index.d.ts +20 -0
- package/dist/views/TranslationHub/index.js +109 -0
- package/dist/views/TranslationHub/tabNavigation.d.ts +53 -0
- package/dist/views/TranslationHub/tabNavigation.js +74 -0
- package/dist/views/TranslationHub/terminalBannerVisibility.d.ts +33 -0
- package/dist/views/TranslationHub/terminalBannerVisibility.js +124 -0
- package/dist/views/TranslationHub/useBulkTranslateActive.d.ts +49 -0
- package/dist/views/TranslationHub/useBulkTranslateActive.js +251 -0
- package/dist/views/TranslationHub/useFocusTrap.d.ts +6 -0
- package/dist/views/TranslationHub/useFocusTrap.js +81 -0
- package/dist/views/TranslationHub/useTranslationHubUsageSummary.d.ts +77 -0
- package/dist/views/TranslationHub/useTranslationHubUsageSummary.js +267 -0
- package/dist/views/shared/EditorError.d.ts +97 -0
- package/dist/views/shared/EditorError.js +205 -0
- package/dist/views/shared/ModelCell.d.ts +18 -0
- package/dist/views/shared/ModelCell.js +31 -0
- package/dist/views/shared/docHref.d.ts +16 -0
- package/dist/views/shared/docHref.js +26 -0
- package/dist/views/shared/fetch-error-body.d.ts +25 -0
- package/dist/views/shared/fetch-error-body.js +42 -0
- package/dist/views/shared/filterPillStyle.d.ts +35 -0
- package/dist/views/shared/filterPillStyle.js +40 -0
- package/dist/views/shared/format.d.ts +75 -0
- package/dist/views/shared/format.js +131 -0
- package/package.json +141 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { type EditorErrorContext } from '../../lib/error-messages.js';
|
|
3
|
+
/**
|
|
4
|
+
* Plain-English error render component. Every editor-facing error site
|
|
5
|
+
* (AlertBanner, UsageTable expanded row, BulkRunsHub DrillDown failed-unit
|
|
6
|
+
* detail, FailureDrawer rows, action toasts) routes through this rather
|
|
7
|
+
* than dumping raw `err.message` text or internal codes like
|
|
8
|
+
* `permanent.config`.
|
|
9
|
+
*
|
|
10
|
+
* What it gives the editor:
|
|
11
|
+
* - A friendly title + body (from `editorMessageFor(code, context)`).
|
|
12
|
+
* - An optional action CTA — what to actually do next.
|
|
13
|
+
* - When `details` is non-empty: a collapsible "Show technical details"
|
|
14
|
+
* `<details>` element holding the raw provider / validator string.
|
|
15
|
+
* Collapsed by default; engineering can expand to debug.
|
|
16
|
+
* - When the code is a permanent failure (`bulk.permanent.*`,
|
|
17
|
+
* `cost-guard.*`): an inline expandable "Why won't this work?" block
|
|
18
|
+
* explaining the failure mode, and (if `onRetry` is supplied) a
|
|
19
|
+
* disabled retry button with the same explanation as its tooltip.
|
|
20
|
+
*
|
|
21
|
+
* What it explicitly avoids:
|
|
22
|
+
* - Showing the raw `code` string anywhere visible.
|
|
23
|
+
* - Showing the raw `details` string at the top level.
|
|
24
|
+
* - Encouraging a retry click on a permanent failure (which would just
|
|
25
|
+
* fail again with the same root cause).
|
|
26
|
+
*/
|
|
27
|
+
type EditorErrorTone = 'error' | 'warning' | 'info' | 'muted';
|
|
28
|
+
export type EditorErrorProps = {
|
|
29
|
+
/**
|
|
30
|
+
* Editor-facing code from `lib/error-messages.ts`. Renders the catalogue
|
|
31
|
+
* message for it. When omitted or unknown the catalogue falls back to a
|
|
32
|
+
* generic "Something went wrong" message — never undefined/blank.
|
|
33
|
+
*/
|
|
34
|
+
code: string | null | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Context for templating the code's message (count, locale, $spent,
|
|
37
|
+
* etc.). Each formatter in the catalogue uses what it needs and ignores
|
|
38
|
+
* the rest, so over-supplying is safe.
|
|
39
|
+
*/
|
|
40
|
+
context?: EditorErrorContext;
|
|
41
|
+
/**
|
|
42
|
+
* Raw provider / validator / exception text. When non-empty, surfaces
|
|
43
|
+
* as a collapsible "Show technical details" disclosure under the body.
|
|
44
|
+
* Never rendered at the top level — engineering-only detail.
|
|
45
|
+
*/
|
|
46
|
+
details?: string | null;
|
|
47
|
+
/**
|
|
48
|
+
* Visual severity. Default is inferred from the code: permanent
|
|
49
|
+
* failures + persistent alerts render as `error`, cost-guards and
|
|
50
|
+
* soft-skips as `warning`, markers (cancel/reset) as `muted`.
|
|
51
|
+
*/
|
|
52
|
+
tone?: EditorErrorTone;
|
|
53
|
+
/**
|
|
54
|
+
* Compact layout for in-table / inline contexts (no banner background,
|
|
55
|
+
* no border, tighter spacing). The action CTA still renders. Use this
|
|
56
|
+
* inside an already-styled card (e.g. UsageTable expanded row).
|
|
57
|
+
*/
|
|
58
|
+
compact?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Hide the action CTA (e.g. when the surrounding component already
|
|
61
|
+
* provides its own Retry / Open Document button and the CTA copy
|
|
62
|
+
* would duplicate it).
|
|
63
|
+
*/
|
|
64
|
+
hideAction?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Optional retry callback. When supplied:
|
|
67
|
+
* - For non-permanent codes: renders an enabled "Try again" button
|
|
68
|
+
* that calls this callback.
|
|
69
|
+
* - For permanent codes: renders the button disabled with the
|
|
70
|
+
* "Why won't this work?" explanation as tooltip + inline block.
|
|
71
|
+
* When omitted, no retry surface renders.
|
|
72
|
+
*/
|
|
73
|
+
onRetry?: () => void;
|
|
74
|
+
/** Loading state for the retry button. */
|
|
75
|
+
retryPending?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Inline `style` overrides for the outer container. Used by callers
|
|
78
|
+
* that need to slot the component into a specific layout.
|
|
79
|
+
*/
|
|
80
|
+
style?: React.CSSProperties;
|
|
81
|
+
};
|
|
82
|
+
export declare const EditorError: React.FC<EditorErrorProps>;
|
|
83
|
+
/**
|
|
84
|
+
* Lightweight one-liner for in-table / chip / status-cell contexts.
|
|
85
|
+
* Renders ONLY the title from `editorMessageFor`. When you need more
|
|
86
|
+
* (body, action, details disclosure), use `<EditorError>` instead.
|
|
87
|
+
*
|
|
88
|
+
* Useful for spaces where the row already has its own row-level affordance
|
|
89
|
+
* and we just want the friendly text in place of `failureCode` or
|
|
90
|
+
* `reason` strings.
|
|
91
|
+
*/
|
|
92
|
+
export declare const EditorErrorChip: React.FC<{
|
|
93
|
+
code: string | null | undefined;
|
|
94
|
+
context?: EditorErrorContext;
|
|
95
|
+
title?: string;
|
|
96
|
+
}>;
|
|
97
|
+
export {};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { editorMessageFor, isPermanentFailure } from '../../lib/error-messages.js';
|
|
5
|
+
const TONE_COLORS = {
|
|
6
|
+
error: {
|
|
7
|
+
bg: 'var(--theme-error-100, #fee2e2)',
|
|
8
|
+
border: 'var(--theme-error-500, #b91c1c)',
|
|
9
|
+
fg: 'var(--theme-error-500, #b91c1c)'
|
|
10
|
+
},
|
|
11
|
+
warning: {
|
|
12
|
+
bg: 'var(--theme-warning-100, #fef3c7)',
|
|
13
|
+
border: 'var(--theme-warning-500, #d97706)',
|
|
14
|
+
fg: 'var(--theme-warning-500, #d97706)'
|
|
15
|
+
},
|
|
16
|
+
info: {
|
|
17
|
+
bg: 'var(--theme-elevation-50, #f1f5f9)',
|
|
18
|
+
border: 'var(--theme-elevation-200, #cbd5e1)',
|
|
19
|
+
fg: 'var(--theme-elevation-800, #1e293b)'
|
|
20
|
+
},
|
|
21
|
+
muted: {
|
|
22
|
+
bg: 'transparent',
|
|
23
|
+
border: 'var(--theme-elevation-100, #e5e7eb)',
|
|
24
|
+
fg: 'var(--theme-elevation-700, #475569)'
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Default tone derived from the code prefix. Callers can override via
|
|
29
|
+
* the `tone` prop when context warrants (e.g. an error-tone banner for
|
|
30
|
+
* a soft-skip when many fields failed).
|
|
31
|
+
*/ function defaultToneForCode(code) {
|
|
32
|
+
if (!code) return 'error';
|
|
33
|
+
if (code.startsWith('marker.')) return 'muted';
|
|
34
|
+
if (code.startsWith('soft-skip.')) return 'warning';
|
|
35
|
+
if (code.startsWith('cost-guard.')) return 'warning';
|
|
36
|
+
if (code === 'alert.cost-guard-abort') return 'warning';
|
|
37
|
+
if (code === 'bulk.transient.rate_limited') return 'warning';
|
|
38
|
+
if (code === 'bulk.transient.provider') return 'warning';
|
|
39
|
+
if (code === 'bulk.permanent.deleted') return 'info';
|
|
40
|
+
return 'error';
|
|
41
|
+
}
|
|
42
|
+
export const EditorError = ({ code, context, details, tone, compact = false, hideAction = false, onRetry, retryPending = false, style })=>{
|
|
43
|
+
const message = editorMessageFor(code ?? undefined, context ?? {});
|
|
44
|
+
const resolvedTone = tone ?? defaultToneForCode(code);
|
|
45
|
+
const colors = TONE_COLORS[resolvedTone];
|
|
46
|
+
const permanent = isPermanentFailure(code);
|
|
47
|
+
const [explanationOpen, setExplanationOpen] = useState(false);
|
|
48
|
+
const containerStyle = compact ? {
|
|
49
|
+
display: 'flex',
|
|
50
|
+
flexDirection: 'column',
|
|
51
|
+
gap: '0.35rem',
|
|
52
|
+
padding: 0,
|
|
53
|
+
background: 'transparent',
|
|
54
|
+
border: 'none',
|
|
55
|
+
borderRadius: 0,
|
|
56
|
+
...style
|
|
57
|
+
} : {
|
|
58
|
+
display: 'flex',
|
|
59
|
+
flexDirection: 'column',
|
|
60
|
+
gap: '0.5rem',
|
|
61
|
+
padding: '0.75rem 1rem',
|
|
62
|
+
background: colors.bg,
|
|
63
|
+
border: `1px solid ${colors.border}`,
|
|
64
|
+
borderRadius: '6px',
|
|
65
|
+
...style
|
|
66
|
+
};
|
|
67
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
68
|
+
style: containerStyle,
|
|
69
|
+
children: [
|
|
70
|
+
/*#__PURE__*/ _jsx("div", {
|
|
71
|
+
style: {
|
|
72
|
+
fontSize: compact ? '0.8rem' : '0.875rem',
|
|
73
|
+
fontWeight: 600,
|
|
74
|
+
color: colors.fg,
|
|
75
|
+
lineHeight: 1.3
|
|
76
|
+
},
|
|
77
|
+
children: message.title
|
|
78
|
+
}),
|
|
79
|
+
/*#__PURE__*/ _jsx("div", {
|
|
80
|
+
style: {
|
|
81
|
+
fontSize: compact ? '0.75rem' : '0.8rem',
|
|
82
|
+
color: 'var(--theme-elevation-900)',
|
|
83
|
+
lineHeight: 1.5
|
|
84
|
+
},
|
|
85
|
+
children: message.body
|
|
86
|
+
}),
|
|
87
|
+
!hideAction && message.action && /*#__PURE__*/ _jsx("div", {
|
|
88
|
+
style: {
|
|
89
|
+
fontSize: compact ? '0.7rem' : '0.75rem',
|
|
90
|
+
color: 'var(--theme-elevation-700)',
|
|
91
|
+
fontStyle: 'italic'
|
|
92
|
+
},
|
|
93
|
+
children: message.action
|
|
94
|
+
}),
|
|
95
|
+
permanent && message.explanation && /*#__PURE__*/ _jsxs("div", {
|
|
96
|
+
style: {
|
|
97
|
+
marginTop: '0.15rem'
|
|
98
|
+
},
|
|
99
|
+
children: [
|
|
100
|
+
/*#__PURE__*/ _jsx("button", {
|
|
101
|
+
"aria-expanded": explanationOpen,
|
|
102
|
+
onClick: ()=>setExplanationOpen((v)=>!v),
|
|
103
|
+
style: {
|
|
104
|
+
background: 'transparent',
|
|
105
|
+
border: 'none',
|
|
106
|
+
padding: 0,
|
|
107
|
+
cursor: 'pointer',
|
|
108
|
+
color: colors.fg,
|
|
109
|
+
fontSize: '0.75rem',
|
|
110
|
+
fontWeight: 500,
|
|
111
|
+
textDecoration: 'underline'
|
|
112
|
+
},
|
|
113
|
+
type: "button",
|
|
114
|
+
children: explanationOpen ? 'Hide explanation' : 'Why won’t this work?'
|
|
115
|
+
}),
|
|
116
|
+
explanationOpen && /*#__PURE__*/ _jsx("div", {
|
|
117
|
+
style: {
|
|
118
|
+
fontSize: '0.75rem',
|
|
119
|
+
color: 'var(--theme-elevation-800)',
|
|
120
|
+
lineHeight: 1.5,
|
|
121
|
+
marginTop: '0.35rem',
|
|
122
|
+
padding: '0.5rem 0.65rem',
|
|
123
|
+
background: 'var(--theme-elevation-50, #f8fafc)',
|
|
124
|
+
borderLeft: `2px solid ${colors.border}`,
|
|
125
|
+
borderRadius: '3px'
|
|
126
|
+
},
|
|
127
|
+
children: message.explanation
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
}),
|
|
131
|
+
onRetry && /*#__PURE__*/ _jsx("div", {
|
|
132
|
+
style: {
|
|
133
|
+
marginTop: '0.25rem'
|
|
134
|
+
},
|
|
135
|
+
children: /*#__PURE__*/ _jsx("button", {
|
|
136
|
+
disabled: permanent || retryPending,
|
|
137
|
+
onClick: onRetry,
|
|
138
|
+
style: {
|
|
139
|
+
padding: '0.3rem 0.7rem',
|
|
140
|
+
background: permanent ? 'var(--theme-elevation-100, #e5e7eb)' : colors.fg,
|
|
141
|
+
color: permanent ? 'var(--theme-elevation-600, #64748b)' : '#fff',
|
|
142
|
+
border: 'none',
|
|
143
|
+
borderRadius: '4px',
|
|
144
|
+
fontSize: '0.75rem',
|
|
145
|
+
fontWeight: 500,
|
|
146
|
+
cursor: permanent || retryPending ? 'not-allowed' : 'pointer',
|
|
147
|
+
opacity: retryPending ? 0.6 : 1
|
|
148
|
+
},
|
|
149
|
+
title: permanent ? message.explanation ?? 'This error won’t be fixed by retrying.' : undefined,
|
|
150
|
+
type: "button",
|
|
151
|
+
children: retryPending ? 'Retrying…' : 'Try again'
|
|
152
|
+
})
|
|
153
|
+
}),
|
|
154
|
+
details && /*#__PURE__*/ _jsxs("details", {
|
|
155
|
+
style: {
|
|
156
|
+
marginTop: '0.25rem',
|
|
157
|
+
fontSize: '0.7rem',
|
|
158
|
+
color: 'var(--theme-elevation-600, #64748b)'
|
|
159
|
+
},
|
|
160
|
+
children: [
|
|
161
|
+
/*#__PURE__*/ _jsx("summary", {
|
|
162
|
+
style: {
|
|
163
|
+
cursor: 'pointer',
|
|
164
|
+
userSelect: 'none',
|
|
165
|
+
padding: '0.1rem 0'
|
|
166
|
+
},
|
|
167
|
+
children: "Show technical details"
|
|
168
|
+
}),
|
|
169
|
+
/*#__PURE__*/ _jsx("pre", {
|
|
170
|
+
style: {
|
|
171
|
+
marginTop: '0.35rem',
|
|
172
|
+
padding: '0.5rem 0.65rem',
|
|
173
|
+
background: 'var(--theme-elevation-50, #f8fafc)',
|
|
174
|
+
border: '1px solid var(--theme-elevation-100, #e5e7eb)',
|
|
175
|
+
borderRadius: '3px',
|
|
176
|
+
fontSize: '0.7rem',
|
|
177
|
+
fontFamily: 'ui-monospace, SFMono-Regular, monospace',
|
|
178
|
+
whiteSpace: 'pre-wrap',
|
|
179
|
+
wordBreak: 'break-word',
|
|
180
|
+
maxHeight: '12rem',
|
|
181
|
+
overflowY: 'auto',
|
|
182
|
+
margin: 0
|
|
183
|
+
},
|
|
184
|
+
children: details
|
|
185
|
+
})
|
|
186
|
+
]
|
|
187
|
+
})
|
|
188
|
+
]
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* Lightweight one-liner for in-table / chip / status-cell contexts.
|
|
193
|
+
* Renders ONLY the title from `editorMessageFor`. When you need more
|
|
194
|
+
* (body, action, details disclosure), use `<EditorError>` instead.
|
|
195
|
+
*
|
|
196
|
+
* Useful for spaces where the row already has its own row-level affordance
|
|
197
|
+
* and we just want the friendly text in place of `failureCode` or
|
|
198
|
+
* `reason` strings.
|
|
199
|
+
*/ export const EditorErrorChip = ({ code, context, title })=>{
|
|
200
|
+
const message = editorMessageFor(code ?? undefined, context ?? {});
|
|
201
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
202
|
+
title: title ?? message.body,
|
|
203
|
+
children: message.title
|
|
204
|
+
});
|
|
205
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a usage-row `model` value in a table cell. Real OpenRouter
|
|
4
|
+
* model ids (`provider/model`) render verbatim; falsy / provider-only
|
|
5
|
+
* fallbacks (`'openrouter'`, `null`, `''`) collapse to a friendly
|
|
6
|
+
* italic "Failed before model selection" — the run never reached a
|
|
7
|
+
* specific model.
|
|
8
|
+
*
|
|
9
|
+
* Used by:
|
|
10
|
+
* - `TranslationHub/UsageTable.tsx` (Overview → Recent translations)
|
|
11
|
+
* - `TranslationHub/AuditPanel.tsx` (Audit & Cost → Recent failures)
|
|
12
|
+
*
|
|
13
|
+
* Kept in sync via this single component so both surfaces agree on the
|
|
14
|
+
* same copy / styling. See ROUND4-1.
|
|
15
|
+
*/
|
|
16
|
+
export declare const ModelCell: React.FC<{
|
|
17
|
+
model: string | null | undefined;
|
|
18
|
+
}>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { isRealModelId } from '../TranslationHub/AuditPanel.helpers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Renders a usage-row `model` value in a table cell. Real OpenRouter
|
|
5
|
+
* model ids (`provider/model`) render verbatim; falsy / provider-only
|
|
6
|
+
* fallbacks (`'openrouter'`, `null`, `''`) collapse to a friendly
|
|
7
|
+
* italic "Failed before model selection" — the run never reached a
|
|
8
|
+
* specific model.
|
|
9
|
+
*
|
|
10
|
+
* Used by:
|
|
11
|
+
* - `TranslationHub/UsageTable.tsx` (Overview → Recent translations)
|
|
12
|
+
* - `TranslationHub/AuditPanel.tsx` (Audit & Cost → Recent failures)
|
|
13
|
+
*
|
|
14
|
+
* Kept in sync via this single component so both surfaces agree on the
|
|
15
|
+
* same copy / styling. See ROUND4-1.
|
|
16
|
+
*/ export const ModelCell = ({ model })=>{
|
|
17
|
+
if (isRealModelId(model)) {
|
|
18
|
+
return /*#__PURE__*/ _jsx(_Fragment, {
|
|
19
|
+
children: model
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
23
|
+
style: {
|
|
24
|
+
color: 'var(--theme-elevation-500)',
|
|
25
|
+
fontStyle: 'italic',
|
|
26
|
+
fontFamily: 'inherit'
|
|
27
|
+
},
|
|
28
|
+
title: "The run failed before a specific model was selected — typically a configuration or provider error.",
|
|
29
|
+
children: "Failed before model selection"
|
|
30
|
+
});
|
|
31
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a Payload admin URL for a single document, optionally pinned
|
|
3
|
+
* to a target locale via `?locale=`. Used by every Hub surface that
|
|
4
|
+
* links into a translated document so the user lands on the locale
|
|
5
|
+
* they want to verify (not the source locale).
|
|
6
|
+
*
|
|
7
|
+
* Centralising avoids the 3 drifted copies previously living in
|
|
8
|
+
* UsageTable / AuditPanel / BatchRow / FailureDrawer (none of which
|
|
9
|
+
* appended `?locale=`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function docHref(basePath: string, collectionSlug: string, documentId: string | number, locale?: string | null): string;
|
|
12
|
+
/**
|
|
13
|
+
* Build a Payload admin URL for a global. Globals are addressed by slug
|
|
14
|
+
* only; the locale param works the same way.
|
|
15
|
+
*/
|
|
16
|
+
export declare function globalHref(basePath: string, globalSlug: string, locale?: string | null): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a Payload admin URL for a single document, optionally pinned
|
|
3
|
+
* to a target locale via `?locale=`. Used by every Hub surface that
|
|
4
|
+
* links into a translated document so the user lands on the locale
|
|
5
|
+
* they want to verify (not the source locale).
|
|
6
|
+
*
|
|
7
|
+
* Centralising avoids the 3 drifted copies previously living in
|
|
8
|
+
* UsageTable / AuditPanel / BatchRow / FailureDrawer (none of which
|
|
9
|
+
* appended `?locale=`).
|
|
10
|
+
*/ export function docHref(basePath, collectionSlug, documentId, locale) {
|
|
11
|
+
const base = `${basePath}/admin/collections/${encodeURIComponent(collectionSlug)}/${encodeURIComponent(String(documentId))}`;
|
|
12
|
+
if (locale && locale.length > 0) {
|
|
13
|
+
return `${base}?locale=${encodeURIComponent(locale)}`;
|
|
14
|
+
}
|
|
15
|
+
return base;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build a Payload admin URL for a global. Globals are addressed by slug
|
|
19
|
+
* only; the locale param works the same way.
|
|
20
|
+
*/ export function globalHref(basePath, globalSlug, locale) {
|
|
21
|
+
const base = `${basePath}/admin/globals/${encodeURIComponent(globalSlug)}`;
|
|
22
|
+
if (locale && locale.length > 0) {
|
|
23
|
+
return `${base}?locale=${encodeURIComponent(locale)}`;
|
|
24
|
+
}
|
|
25
|
+
return base;
|
|
26
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a structured error body from a non-OK Response. The plugin's
|
|
3
|
+
* endpoint helper (`endpoints/translation-hub/_helpers.ts:errorResponse`)
|
|
4
|
+
* returns `{ error: { code, message } }` on failure. This returns just
|
|
5
|
+
* the editor-facing `message`; callers wanting the `code` for catalogue
|
|
6
|
+
* rendering (`editorMessageFor(code)`) should use `readResponseErrorBody`.
|
|
7
|
+
*
|
|
8
|
+
* Falls back to a generic friendly message when the body isn't structured —
|
|
9
|
+
* never throws.
|
|
10
|
+
*
|
|
11
|
+
* 1.2.5 change: stopped appending `(${code})` to the message. The code
|
|
12
|
+
* was leaking engineering jargon to editors; callers that need it now
|
|
13
|
+
* pull it via the structured `readResponseErrorBody` helper.
|
|
14
|
+
*/
|
|
15
|
+
export declare function readResponseError(res: Response): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Structured variant. Returns both `code` and `message` so callers can
|
|
18
|
+
* render via the editor-facing catalogue (`editorMessageFor(code)`)
|
|
19
|
+
* with the raw `message` as a disclosure fallback. Use this at every
|
|
20
|
+
* Hub UI fetch site that surfaces the error inside an `<EditorError>`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function readResponseErrorBody(res: Response): Promise<{
|
|
23
|
+
code: string | undefined;
|
|
24
|
+
message: string;
|
|
25
|
+
}>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a structured error body from a non-OK Response. The plugin's
|
|
3
|
+
* endpoint helper (`endpoints/translation-hub/_helpers.ts:errorResponse`)
|
|
4
|
+
* returns `{ error: { code, message } }` on failure. This returns just
|
|
5
|
+
* the editor-facing `message`; callers wanting the `code` for catalogue
|
|
6
|
+
* rendering (`editorMessageFor(code)`) should use `readResponseErrorBody`.
|
|
7
|
+
*
|
|
8
|
+
* Falls back to a generic friendly message when the body isn't structured —
|
|
9
|
+
* never throws.
|
|
10
|
+
*
|
|
11
|
+
* 1.2.5 change: stopped appending `(${code})` to the message. The code
|
|
12
|
+
* was leaking engineering jargon to editors; callers that need it now
|
|
13
|
+
* pull it via the structured `readResponseErrorBody` helper.
|
|
14
|
+
*/ export async function readResponseError(res) {
|
|
15
|
+
const parsed = await readResponseErrorBody(res);
|
|
16
|
+
return parsed.message;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Structured variant. Returns both `code` and `message` so callers can
|
|
20
|
+
* render via the editor-facing catalogue (`editorMessageFor(code)`)
|
|
21
|
+
* with the raw `message` as a disclosure fallback. Use this at every
|
|
22
|
+
* Hub UI fetch site that surfaces the error inside an `<EditorError>`.
|
|
23
|
+
*/ export async function readResponseErrorBody(res) {
|
|
24
|
+
try {
|
|
25
|
+
const body = await res.json();
|
|
26
|
+
if (body && typeof body === 'object') {
|
|
27
|
+
const err = body.error;
|
|
28
|
+
if (err && typeof err.message === 'string' && err.message.length > 0) {
|
|
29
|
+
return {
|
|
30
|
+
code: err.code,
|
|
31
|
+
message: err.message
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
// Body wasn't JSON / stream consumed elsewhere. Fall through.
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
code: undefined,
|
|
40
|
+
message: res.status >= 500 ? 'The server returned an error. Try again, or contact engineering if it keeps happening.' : 'The request couldn’t be completed. Try again, or refresh the page.'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared filter-pill style helper.
|
|
3
|
+
*
|
|
4
|
+
* Used by every filter / range / status pill row in the Translation Hub
|
|
5
|
+
* and BulkRunsHub surfaces (FilterBar, BatchRow drill-down chips,
|
|
6
|
+
* SummaryStrip, StatusStrip, AuditPanel). Extracted to fix v1.2.6
|
|
7
|
+
* BugIndex BR-5 + NEW-21:
|
|
8
|
+
*
|
|
9
|
+
* - Before: active pill bg = `elevation-150` / `-200`, sitting beside
|
|
10
|
+
* inactive pills whose border is also `elevation-150` / `-200`. The
|
|
11
|
+
* adjacent UI non-text contrast was 1.0:1 — active state was only
|
|
12
|
+
* signalled by font-weight. WCAG 1.4.11 requires ≥ 3:1 for
|
|
13
|
+
* state-bearing UI.
|
|
14
|
+
* - After: active pill bg = `elevation-1000` (near-black) + text
|
|
15
|
+
* `elevation-50` (near-white) on light theme. The state contrast vs
|
|
16
|
+
* inactive pill borders is ≥ 7:1, well above the AA non-text bar,
|
|
17
|
+
* and the active pill reads as a distinct chip at a glance even
|
|
18
|
+
* without font-weight signalling.
|
|
19
|
+
*
|
|
20
|
+
* Keep the helper small. Each pill row sets its own padding / font-size
|
|
21
|
+
* to match the surrounding surface — only the colour tokens are unified.
|
|
22
|
+
*/
|
|
23
|
+
import type React from 'react';
|
|
24
|
+
export type FilterPillColors = {
|
|
25
|
+
background: React.CSSProperties['background'];
|
|
26
|
+
color: React.CSSProperties['color'];
|
|
27
|
+
border: React.CSSProperties['border'];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a pill's background / text / border colours from its active
|
|
31
|
+
* state. The active state uses `--theme-elevation-1000` (near-black on
|
|
32
|
+
* light theme, near-white on dark) so it never blends with the inactive
|
|
33
|
+
* pills' borders — fixes BR-5 and NEW-21.
|
|
34
|
+
*/
|
|
35
|
+
export declare function filterPillColors(isActive: boolean): FilterPillColors;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared filter-pill style helper.
|
|
3
|
+
*
|
|
4
|
+
* Used by every filter / range / status pill row in the Translation Hub
|
|
5
|
+
* and BulkRunsHub surfaces (FilterBar, BatchRow drill-down chips,
|
|
6
|
+
* SummaryStrip, StatusStrip, AuditPanel). Extracted to fix v1.2.6
|
|
7
|
+
* BugIndex BR-5 + NEW-21:
|
|
8
|
+
*
|
|
9
|
+
* - Before: active pill bg = `elevation-150` / `-200`, sitting beside
|
|
10
|
+
* inactive pills whose border is also `elevation-150` / `-200`. The
|
|
11
|
+
* adjacent UI non-text contrast was 1.0:1 — active state was only
|
|
12
|
+
* signalled by font-weight. WCAG 1.4.11 requires ≥ 3:1 for
|
|
13
|
+
* state-bearing UI.
|
|
14
|
+
* - After: active pill bg = `elevation-1000` (near-black) + text
|
|
15
|
+
* `elevation-50` (near-white) on light theme. The state contrast vs
|
|
16
|
+
* inactive pill borders is ≥ 7:1, well above the AA non-text bar,
|
|
17
|
+
* and the active pill reads as a distinct chip at a glance even
|
|
18
|
+
* without font-weight signalling.
|
|
19
|
+
*
|
|
20
|
+
* Keep the helper small. Each pill row sets its own padding / font-size
|
|
21
|
+
* to match the surrounding surface — only the colour tokens are unified.
|
|
22
|
+
*/ /**
|
|
23
|
+
* Resolve a pill's background / text / border colours from its active
|
|
24
|
+
* state. The active state uses `--theme-elevation-1000` (near-black on
|
|
25
|
+
* light theme, near-white on dark) so it never blends with the inactive
|
|
26
|
+
* pills' borders — fixes BR-5 and NEW-21.
|
|
27
|
+
*/ export function filterPillColors(isActive) {
|
|
28
|
+
if (isActive) {
|
|
29
|
+
return {
|
|
30
|
+
background: 'var(--theme-elevation-1000)',
|
|
31
|
+
color: 'var(--theme-elevation-50)',
|
|
32
|
+
border: '1px solid var(--theme-elevation-1000)'
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
background: 'transparent',
|
|
37
|
+
color: 'var(--theme-elevation-700)',
|
|
38
|
+
border: '1px solid var(--theme-elevation-200)'
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared cost / duration formatters for Translation Hub + Bulk Translate
|
|
3
|
+
* Runs surfaces. v1.2.6 BugIndex NEW-17 + NEW-18 + NEW-10.
|
|
4
|
+
*
|
|
5
|
+
* Before extracting these, every surface (Hub Overview, Audit, Runs,
|
|
6
|
+
* batch rows, drill-down) rolled its own threshold logic. The result:
|
|
7
|
+
* - Hub Overview "Estimated cost" showed `$0.54`
|
|
8
|
+
* - Audit "Total spend" showed `53.6¢`
|
|
9
|
+
* - Runs "Last 7 days cost" showed `$0.51`
|
|
10
|
+
* - Batch row Cost column showed `12.4¢`
|
|
11
|
+
* - Drill-down unit-detail showed `2.1¢`
|
|
12
|
+
* - Bucket-row duration showed `964m 6s` with no hours carryover
|
|
13
|
+
*
|
|
14
|
+
* Same underlying value (cents, ms), five different formats.
|
|
15
|
+
*
|
|
16
|
+
* The contract here is the only contract going forward. Every cost /
|
|
17
|
+
* duration render site MUST import `formatCost` / `formatDuration`. Do
|
|
18
|
+
* NOT roll new threshold rules at the call site.
|
|
19
|
+
*
|
|
20
|
+
* `formatCost` rule (1.2.8):
|
|
21
|
+
* - All values render as `$X.YY[YY]` (USD, dollar sign always present).
|
|
22
|
+
* - Sub-cent values use up to 4 decimals so editors can tell a
|
|
23
|
+
* 0.46¢ run from a 0.88¢ run — but the unit is consistently $,
|
|
24
|
+
* never the ¢ glyph (it was being mis-read as `$X.YY¢` on dense
|
|
25
|
+
* tables and made per-doc costs look 100× higher than they were).
|
|
26
|
+
* - Values ≥ $0.01 stay at the standard 2-decimal $X.YY form.
|
|
27
|
+
*
|
|
28
|
+
* Wait — that was the OLD rule. The Group F brief locks this in:
|
|
29
|
+
* `$X.XX` with 2 decimals; switch to `Y.Y¢` ONLY when value < $0.01
|
|
30
|
+
* (or, equivalently, < 1¢).
|
|
31
|
+
*
|
|
32
|
+
* So: < $0.01 → `Y.YY¢`, else `$X.XX`.
|
|
33
|
+
*
|
|
34
|
+
* `formatDuration` rule:
|
|
35
|
+
* ms → s → m → h → d, carrying everywhere. Show two units of
|
|
36
|
+
* precision when the next-down unit would otherwise be lost
|
|
37
|
+
* (e.g. `16h 38m`, `5m 16s`, `42s`).
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* Render a USD value with consistent rules.
|
|
41
|
+
*
|
|
42
|
+
* @param usd Dollars (e.g. 0.124 means 12.4 cents). `null` / `undefined`
|
|
43
|
+
* / non-finite → `'—'`. Negative → coerced to `0`.
|
|
44
|
+
* @returns
|
|
45
|
+
* - `'—'` when missing or non-finite
|
|
46
|
+
* - `'$0.00'` when exactly zero
|
|
47
|
+
* - `'$0.YYYY'` (USD, four decimals) when 0 < value < $0.01
|
|
48
|
+
* - `'$X.XX'` (USD, two decimals) otherwise
|
|
49
|
+
*
|
|
50
|
+
* Tests pin the boundaries — see `__tests__/format.test.ts`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatCost(usd: number | null | undefined): string;
|
|
53
|
+
/**
|
|
54
|
+
* Render a duration in ms with full carry-over from ms → s → m → h → d.
|
|
55
|
+
*
|
|
56
|
+
* @param ms Duration in milliseconds. `null` / `undefined` / non-finite
|
|
57
|
+
* → `'—'`. Zero → `'—'` by convention (matches the legacy `fmtUsd`
|
|
58
|
+
* behaviour the call sites relied on). Negative → coerced to `0` →
|
|
59
|
+
* `'—'`.
|
|
60
|
+
* @returns
|
|
61
|
+
* - `'—'` when missing / non-finite / non-positive
|
|
62
|
+
* - `'Nms'` when < 1s
|
|
63
|
+
* - `'N.Ns'` when < 10s (one decimal, e.g. `3.4s`)
|
|
64
|
+
* - `'Ns'` when < 60s
|
|
65
|
+
* - `'Nm Ss'` when < 1h (e.g. `5m 16s`)
|
|
66
|
+
* - `'Nh Mm'` when < 24h (e.g. `16h 38m`)
|
|
67
|
+
* - `'Nd Hh'` when ≥ 24h (e.g. `2d 4h`)
|
|
68
|
+
*
|
|
69
|
+
* The rule is the same one BatchRow.tsx implemented for batch-level
|
|
70
|
+
* durations; lifting it here so BucketRow stops capping at minutes and
|
|
71
|
+
* rendering `964m 6s`. See NEW-18.
|
|
72
|
+
*
|
|
73
|
+
* Tests pin the boundaries — see `__tests__/format.test.ts`.
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatDuration(ms: number | null | undefined): string;
|