@parhelia/localization 0.3.12770 → 0.3.12777

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.
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Dialog, DialogContent, StyledDialogTitle, Button, cn, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@parhelia/core";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
4
4
  import { AlertTriangle as LucideAlertTriangle, ArrowRight as LucideArrowRight, Globe as LucideGlobe, } from "lucide-react";
@@ -1 +1 @@
1
- {"version":3,"file":"LocalizeItemUtils.d.ts","sourceRoot":"","sources":["../src/LocalizeItemUtils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAsDjD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,qBAAqB,EACjC,WAAW,EAAE,eAAe,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAwH5B;AAGD,eAAO,MAAM,mBAAmB,GAC9B,eAAe,MAAM,EAAE,EACvB,mBAAmB,iBAAiB,EAAE,EACtC,WAAW,MAAM,EACjB,MAAM,QAAQ,EACd,qBAAqB,MAAM,+BAkC5B,CAAC"}
1
+ {"version":3,"file":"LocalizeItemUtils.d.ts","sourceRoot":"","sources":["../src/LocalizeItemUtils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAsDjD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,qBAAqB,EACjC,WAAW,EAAE,eAAe,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAwH5B;AAGD,eAAO,MAAM,mBAAmB,kBACf,MAAM,EAAE,qBACJ,iBAAiB,EAAE,aAC3B,MAAM,QACX,QAAQ,uBACO,MAAM,+BAkC5B,CAAC"}
@@ -6,18 +6,6 @@ export type TranslationApiResponse<T> = {
6
6
  error?: string;
7
7
  message?: string;
8
8
  };
9
- export type TranslationRequestResponse = {
10
- jobId: string;
11
- };
12
- export declare function requestTranslation({ itemId, targetLanguage, sourceLanguage, sessionId, provider, metadata, batchId, }: {
13
- itemId: string;
14
- targetLanguage: string;
15
- sourceLanguage: string;
16
- sessionId: string;
17
- provider: string;
18
- metadata: string;
19
- batchId?: string;
20
- }): Promise<import("@parhelia/core").ExecutionResult<TranslationRequestResponse>>;
21
9
  export declare function getTranslationStatus(itemId: string): Promise<import("@parhelia/core").ExecutionResult<TranslationStatus[]>>;
22
10
  export declare function getTranslationProviders(): Promise<import("@parhelia/core").ExecutionResult<TranslationProviderInfo[]>>;
23
11
  export type AvailableTranslationService = {
@@ -101,12 +89,6 @@ export type ListBatchesFilters = {
101
89
  itemIncludeSubitems?: boolean;
102
90
  };
103
91
  export declare function listBatches(take?: number, skip?: number, filters?: ListBatchesFilters): Promise<import("@parhelia/core").ExecutionResult<TranslationBatchInfo[]>>;
104
- export type DeleteBatchResponse = {
105
- success: boolean;
106
- id: string;
107
- deletedJobs: number;
108
- };
109
- export declare function deleteBatch(id: string): Promise<import("@parhelia/core").ExecutionResult<DeleteBatchResponse>>;
110
92
  export type AbortTranslationResponse = {
111
93
  success: boolean;
112
94
  batchId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"translationService.d.ts","sourceRoot":"","sources":["../../src/services/translationService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"translationService.d.ts","sourceRoot":"","sources":["../../src/services/translationService.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,4 @@
1
1
  import { get, post } from "@parhelia/core";
2
- export async function requestTranslation({ itemId, targetLanguage, sourceLanguage, sessionId, provider, metadata, batchId, }) {
3
- return await post("/parhelia/translation/requestTranslation", {
4
- itemId,
5
- targetLanguage,
6
- sourceLanguage,
7
- sessionId,
8
- provider,
9
- metadata,
10
- batchId,
11
- });
12
- }
13
2
  export async function getTranslationStatus(itemId) {
14
3
  return await get(`/parhelia/translation/getTranslations?itemId=${itemId}`);
15
4
  }
@@ -72,11 +61,6 @@ export async function listBatches(take = 100, skip = 0, filters = {}) {
72
61
  params.set("itemIncludeSubitems", "true");
73
62
  return await get(`/parhelia/translation/batches?${params.toString()}`);
74
63
  }
75
- export async function deleteBatch(id) {
76
- return await post("/parhelia/translation/deleteBatch", {
77
- id,
78
- });
79
- }
80
64
  export async function abortJob(id) {
81
65
  return await post("/parhelia/translation/abortJob", { id });
82
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TranslationServicesPanel.d.ts","sourceRoot":"","sources":["../../src/settings/TranslationServicesPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAKN,MAAM,OAAO,CAAC;AA6Df;;;GAGG;AACH,wBAAgB,wBAAwB,sBA4pBvC;AAED,eAAe,wBAAwB,CAAC"}
1
+ {"version":3,"file":"TranslationServicesPanel.d.ts","sourceRoot":"","sources":["../../src/settings/TranslationServicesPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAKN,MAAM,OAAO,CAAC;AA6Df;;;GAGG;AACH,wBAAgB,wBAAwB,sBA4pBvC;eAEc,wBAAwB"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useState, useEffect, } from "react";
3
3
  import { Button, Card, useEditContext, Splitter, ItemConfigPanel, DeleteIcon, } from "@parhelia/core";
4
4
  import { CheckCircle as LucideCheckCircle, AlertCircle as LucideAlertCircle, RefreshCw as LucideRefreshCw, Plus as LucidePlus, Settings as LucideSettings, Languages as LucideLanguages, ListChecks as LucideListChecks, } from "lucide-react";
@@ -1 +1 @@
1
- {"version":3,"file":"LocalizationSetupStep.d.ts","sourceRoot":"","sources":["../../src/setup/LocalizationSetupStep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAgCzE,wBAAgB,qBAAqB,sBA6QpC;AAED,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"LocalizationSetupStep.d.ts","sourceRoot":"","sources":["../../src/setup/LocalizationSetupStep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAgCzE,wBAAgB,qBAAqB,sBA6QpC;eAEc,qBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"TranslationBatches.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationBatches.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAgV1B,wBAAgB,kBAAkB,sBA+mCjC;AAED,eAAO,MAAM,oCAAoC,8BAA8B,CAAC;AAEhF,wBAAgB,8BAA8B,sBA0Y7C"}
1
+ {"version":3,"file":"TranslationBatches.d.ts","sourceRoot":"","sources":["../../src/translation-center/TranslationBatches.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkV1B,wBAAgB,kBAAkB,sBA2mCjC;AAED,eAAO,MAAM,oCAAoC,8BAA8B,CAAC;AAEhF,wBAAgB,8BAA8B,sBA0Y7C"}
@@ -1,8 +1,8 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef, useState, useMemo, useSyncExternalStore, } from "react";
3
3
  import React from "react";
4
4
  import { Button, Badge, Select, Input, UserPicker, Popover, PopoverContent, PopoverTrigger, Tooltip, TooltipContent, TooltipTrigger, ContentTree, PageHeader, fetchItemStubs, searchUsers as searchBackendUsers, useEditContext, getLanguages, SimpleIconButton, WorkspaceHomeView, formatDateTime, } from "@parhelia/core";
5
- import { listBatches, getTranslationProviders, listBatchTranslationJobs, retryBatchTranslation, abortJob, abortBatch, } from "../services/translationService";
5
+ import { listBatches, getTranslationProviders, listBatchTranslationJobs, retryBatchTranslation, abortJob, abortBatch, subscribeToBatch, unsubscribeFromBatch, } from "../services/translationService";
6
6
  import { TRANSLATION_BATCH_STARTED_EVENT, } from "../translationEvents";
7
7
  import { useDebouncedCallback } from "use-debounce";
8
8
  import { X, ChevronDown, Languages, Loader2, Globe, FolderTree, ExternalLink, Check, AlertCircle, CircleStop, Hourglass, Copy, Sparkles, RotateCcw, Plus, } from "lucide-react";
@@ -581,6 +581,22 @@ export function TranslationBatches() {
581
581
  });
582
582
  setExpandedItems(new Set());
583
583
  }, [batchJobs, loadBatchJobs]);
584
+ // Subscribe the current session to the expanded batch so live job-status
585
+ // updates (translation-started/-finished/-error) are delivered here.
586
+ // Without this, NotifyBatchUpdate only reaches the batch initiator's session
587
+ // via an in-memory map — unreliable for long-running/queued jobs (lost on
588
+ // app restart, absent when a different session views the batch), leaving
589
+ // running jobs' statuses stale until a manual reload.
590
+ useEffect(() => {
591
+ const sessionId = editContext?.sessionId;
592
+ if (!sessionId || !expandedBatchId)
593
+ return;
594
+ const batchId = normalizeGuid(expandedBatchId);
595
+ void subscribeToBatch(batchId, sessionId).catch(() => { });
596
+ return () => {
597
+ void unsubscribeFromBatch(batchId, sessionId).catch(() => { });
598
+ };
599
+ }, [expandedBatchId, editContext?.sessionId]);
584
600
  const toggleItem = useCallback((key) => {
585
601
  setExpandedItems((prev) => {
586
602
  const next = new Set(prev);
@@ -766,21 +782,10 @@ export function TranslationBatches() {
766
782
  const languages = languagesCsv
767
783
  ? languagesCsv.split(",")
768
784
  : [];
769
- const completedJobs = info?.completedJobs ?? 0;
770
785
  const errorJobs = info?.errorJobs ?? 0;
771
786
  const anyError = errorJobs > 0;
772
787
  const anyInProgress = isActiveBatchStatus(info?.status);
773
788
  const anyAborted = info?.status === "Aborted";
774
- const progressPct = totalJobs > 0
775
- ? Math.min(100, Math.round((completedJobs / totalJobs) * 100))
776
- : 0;
777
- const progressTone = anyError
778
- ? "error"
779
- : anyAborted
780
- ? "aborted"
781
- : progressPct >= 100
782
- ? "complete"
783
- : "active";
784
789
  const metaParts = [];
785
790
  metaParts.push(_jsxs("span", { className: "text-neutral-grey-100", children: [totalJobs, " translation", totalJobs !== 1 ? "s" : ""] }, "trans"));
786
791
  if (typeof itemsCount === "number") {
@@ -834,6 +839,7 @@ export function TranslationBatches() {
834
839
  })();
835
840
  const isExpanded = expandedBatchId === b.id;
836
841
  const jobs = batchJobs[b.id];
842
+ const statusCounts = computeBatchStatusCounts(info, jobs);
837
843
  const isLoadingThis = loadingJobs.has(b.id);
838
844
  const canRetry = anyError;
839
845
  const canAbort = isActiveBatchStatus(info?.status);
@@ -868,13 +874,13 @@ export function TranslationBatches() {
868
874
  e.preventDefault();
869
875
  toggleBatch(b.id);
870
876
  }
871
- }, children: _jsxs("div", { className: `flex items-start ${isCompactBatches ? "gap-2" : "gap-4"}`, children: [_jsx("div", { className: `shrink-0 text-neutral-grey-100 transition-transform ${isCompactBatches ? "mt-0.5" : "mt-3"} ${isExpanded ? "rotate-180" : ""}`, children: _jsx(ChevronDownIcon, { className: "h-4 w-4" }) }), !isCompactBatches && totalJobs > 0 && (_jsx(BatchProgressIndicator, { value: progressPct, completedJobs: completedJobs, totalJobs: totalJobs, errorJobs: errorJobs, tone: progressTone, testId: `batch-progress-${b.id}` })), _jsxs("div", { className: `flex min-w-0 flex-1 ${isCompactBatches
877
+ }, children: _jsxs("div", { className: `flex items-start ${isCompactBatches ? "gap-2" : "gap-4"}`, children: [_jsx("div", { className: `shrink-0 text-neutral-grey-100 transition-transform ${isCompactBatches ? "mt-0.5" : "mt-3"} ${isExpanded ? "rotate-180" : ""}`, children: _jsx(ChevronDownIcon, { className: "h-4 w-4" }) }), !isCompactBatches && totalJobs > 0 && (_jsx(BatchProgressIndicator, { counts: statusCounts, testId: `batch-progress-${b.id}` })), _jsxs("div", { className: `flex min-w-0 flex-1 ${isCompactBatches
872
878
  ? "flex-col gap-2"
873
879
  : "items-center justify-between gap-3"}`, children: [_jsxs("div", { className: "grid min-w-0 flex-1 grid-cols-[minmax(0,1fr)]", children: [_jsx("span", { className: `min-w-0 text-[14px] font-medium text-neutral-grey-100 ${isCompactBatches
874
880
  ? "whitespace-normal break-words leading-5"
875
881
  : "truncate"}`, style: isCompactBatches
876
882
  ? { overflowWrap: "anywhere" }
877
- : undefined, title: formattedBatchDate, children: batchDisplayName }), _jsx("div", { className: "mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[12px] text-neutral-grey-50", children: desktopMetaParts.map((part, i) => (_jsxs(React.Fragment, { children: [i > 0 && (_jsx("span", { className: "text-neutral-grey-15", children: "\u00B7" })), part] }, i))) }), mobileFooterMetaParts.length > 0 && (_jsx("div", { className: "mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[12px] text-neutral-grey-50", children: mobileFooterMetaParts.map((part, i) => (_jsxs(React.Fragment, { children: [i > 0 && (_jsx("span", { className: "text-neutral-grey-15", children: "\u00B7" })), part] }, `footer-${i}`))) }))] }), isCompactBatches && (_jsxs("div", { className: "mt-2 flex min-w-0 items-center gap-2", children: [totalJobs > 0 && (_jsx("div", { className: "min-w-0 flex-1", children: _jsx(BatchProgressIndicator, { value: progressPct, completedJobs: completedJobs, totalJobs: totalJobs, errorJobs: errorJobs, tone: progressTone, testId: `batch-progress-${b.id}`, variant: "bar" }) })), hasBatchActions && (_jsx("div", { className: "flex shrink-0 items-center gap-1.5", children: batchActions }))] })), !isCompactBatches && hasBatchActions && (_jsx("div", { className: "flex shrink-0 items-center gap-2 self-center", children: batchActions }))] })] }) }), isExpanded && (_jsxs("div", { className: "border-t border-border-default/50", children: [_jsx(CustomPromptPanel, { prompts: parseCustomPrompts(info?.metadata) }), _jsx(BatchItemList, { batchId: b.id, batchProvider: info?.provider, jobs: jobs, isLoading: isLoadingThis, expandedItems: expandedItems, languages: sitecoreLanguages, currentLanguage: editContext?.item?.language, itemFilter: filters.itemIdOrPath.trim(), itemIncludeSubitems: filters.itemIncludeSubitems, statusFilter: filters.status, batchIsTerminal: isTerminalBatchStatus(info?.status), batchStartedAtUtc: info?.startedAtUtc ?? info?.createdAtUtc, abortingJobIds: abortingJobIds, retryingKeys: retryingKeys, isMobile: isMobile, onToggleItem: toggleItem, onOpenItem: openItemInEditor, onAbortJob: handleAbortJob, onRetryJobs: handleRetryJobs })] }))] }, b.id));
883
+ : undefined, title: formattedBatchDate, children: batchDisplayName }), _jsx("div", { className: "mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[12px] text-neutral-grey-50", children: desktopMetaParts.map((part, i) => (_jsxs(React.Fragment, { children: [i > 0 && (_jsx("span", { className: "text-neutral-grey-15", children: "\u00B7" })), part] }, i))) }), mobileFooterMetaParts.length > 0 && (_jsx("div", { className: "mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[12px] text-neutral-grey-50", children: mobileFooterMetaParts.map((part, i) => (_jsxs(React.Fragment, { children: [i > 0 && (_jsx("span", { className: "text-neutral-grey-15", children: "\u00B7" })), part] }, `footer-${i}`))) }))] }), isCompactBatches && (_jsxs("div", { className: "mt-2 flex min-w-0 items-center gap-2", children: [totalJobs > 0 && (_jsx("div", { className: "min-w-0 flex-1", children: _jsx(BatchProgressIndicator, { counts: statusCounts, testId: `batch-progress-${b.id}`, variant: "bar" }) })), hasBatchActions && (_jsx("div", { className: "flex shrink-0 items-center gap-1.5", children: batchActions }))] })), !isCompactBatches && hasBatchActions && (_jsx("div", { className: "flex shrink-0 items-center gap-2 self-center", children: batchActions }))] })] }) }), isExpanded && (_jsxs("div", { className: "border-t border-border-default/50", children: [_jsx(CustomPromptPanel, { prompts: parseCustomPrompts(info?.metadata) }), _jsx(BatchItemList, { batchId: b.id, batchProvider: info?.provider, jobs: jobs, isLoading: isLoadingThis, expandedItems: expandedItems, languages: sitecoreLanguages, currentLanguage: editContext?.item?.language, itemFilter: filters.itemIdOrPath.trim(), itemIncludeSubitems: filters.itemIncludeSubitems, statusFilter: filters.status, batchIsTerminal: isTerminalBatchStatus(info?.status), batchStartedAtUtc: info?.startedAtUtc ?? info?.createdAtUtc, abortingJobIds: abortingJobIds, retryingKeys: retryingKeys, isMobile: isMobile, onToggleItem: toggleItem, onOpenItem: openItemInEditor, onAbortJob: handleAbortJob, onRetryJobs: handleRetryJobs })] }))] }, b.id));
878
884
  }) })] }, dateGroup.label))), hasMore && (_jsx("div", { className: "flex justify-center pt-6", children: _jsx(Button, { variant: "outline", size: "sm", onClick: loadMore, disabled: isLoadingMore, children: isLoadingMore ? (_jsxs(_Fragment, { children: [_jsx(LoaderIcon, { className: "h-4 w-4 animate-spin text-highlight-100" }), "Loading more..."] })) : (_jsxs(_Fragment, { children: [_jsx(ChevronDownIcon, { className: "h-4 w-4" }), "Load More Batches"] })) }) }))] })) }) })] }));
879
885
  }
880
886
  export const TRANSLATION_BATCH_FILTERS_SIDEBAR_ID = "translation-batch-filters";
@@ -1139,44 +1145,102 @@ function formatUsdCost(value) {
1139
1145
  maximumFractionDigits: value > 0 && value < 0.01 ? 6 : 2,
1140
1146
  }).format(value);
1141
1147
  }
1142
- function BatchProgressIndicator({ value, completedJobs, totalJobs, errorJobs, tone, testId, variant = "circle", }) {
1143
- const percent = Math.max(0, Math.min(100, Math.round(value)));
1144
- const radius = 17;
1145
- const circumference = 2 * Math.PI * radius;
1146
- const dashOffset = circumference - (percent / 100) * circumference;
1147
- const hasErrors = errorJobs > 0;
1148
- const toneClass = tone === "complete"
1149
- ? "text-feedback-green"
1150
- : tone === "error"
1151
- ? "text-feedback-red"
1152
- : tone === "aborted"
1153
- ? "text-feedback-orange"
1154
- : "text-neutral-grey-50";
1155
- const toneColor = tone === "complete"
1156
- ? "var(--color-feedback-green)"
1157
- : tone === "error"
1158
- ? "var(--color-feedback-red)"
1159
- : tone === "aborted"
1160
- ? "var(--color-feedback-orange)"
1161
- : "var(--color-neutral-grey-50)";
1162
- const trackColor = tone === "complete"
1163
- ? "var(--color-feedback-green-light)"
1164
- : tone === "error"
1165
- ? "var(--color-feedback-red-light)"
1166
- : tone === "aborted"
1167
- ? "var(--color-feedback-orange-light)"
1168
- : "var(--color-neutral-grey-15)";
1169
- const label = `${percent}% complete (${completedJobs}/${totalJobs} translations${hasErrors ? `, ${errorJobs} failed` : ""})`;
1148
+ // Ring/bar segment colours mirror the language badge colours, softened with a
1149
+ // touch of transparency so the segmented progress reads as a matching set.
1150
+ const BATCH_SEGMENT_COLORS = {
1151
+ succeeded: "color-mix(in srgb, var(--color-feedback-green) 88%, transparent)",
1152
+ failed: "color-mix(in srgb, var(--color-feedback-red) 88%, transparent)",
1153
+ aborted: "color-mix(in srgb, var(--color-feedback-orange) 88%, transparent)",
1154
+ running: "color-mix(in srgb, var(--color-feedback-blue) 88%, transparent)",
1155
+ };
1156
+ function computeBatchStatusCounts(info, jobs) {
1157
+ if (jobs && jobs.length > 0) {
1158
+ const counts = {
1159
+ total: jobs.length,
1160
+ succeeded: 0,
1161
+ failed: 0,
1162
+ aborted: 0,
1163
+ running: 0,
1164
+ pending: 0,
1165
+ };
1166
+ for (const job of jobs) {
1167
+ switch (job.status) {
1168
+ case "Error":
1169
+ counts.failed += 1;
1170
+ break;
1171
+ case "Aborted":
1172
+ counts.aborted += 1;
1173
+ break;
1174
+ case "In Progress":
1175
+ counts.running += 1;
1176
+ break;
1177
+ case "Pending":
1178
+ counts.pending += 1;
1179
+ break;
1180
+ default:
1181
+ counts.succeeded += 1;
1182
+ }
1183
+ }
1184
+ return counts;
1185
+ }
1186
+ // No per-job data yet (collapsed batch): derive what we can from the summary.
1187
+ // Running vs. pending can't be told apart here, so the remainder stays in the
1188
+ // neutral track rather than being guessed as "running".
1189
+ const total = info?.expectedJobs ?? 0;
1190
+ const succeeded = Math.min(total, info?.completedJobs ?? 0);
1191
+ const failed = Math.min(Math.max(0, total - succeeded), info?.errorJobs ?? 0);
1192
+ const remaining = Math.max(0, total - succeeded - failed);
1193
+ const aborted = info?.status === "Aborted" ? remaining : 0;
1194
+ const pending = info?.status === "Aborted" ? 0 : remaining;
1195
+ return { total, succeeded, failed, aborted, running: 0, pending };
1196
+ }
1197
+ function BatchProgressIndicator({ counts, testId, variant = "circle", }) {
1198
+ const { total, succeeded, failed, aborted, running } = counts;
1199
+ const percent = total > 0
1200
+ ? Math.max(0, Math.min(100, Math.round((succeeded / total) * 100)))
1201
+ : 0;
1202
+ const allSucceeded = total > 0 && succeeded === total;
1203
+ // Colour-carrying segments in tooltip order; pending stays in the track.
1204
+ const segments = [
1205
+ { key: "succeeded", count: succeeded, color: BATCH_SEGMENT_COLORS.succeeded },
1206
+ { key: "failed", count: failed, color: BATCH_SEGMENT_COLORS.failed },
1207
+ { key: "aborted", count: aborted, color: BATCH_SEGMENT_COLORS.aborted },
1208
+ { key: "running", count: running, color: BATCH_SEGMENT_COLORS.running },
1209
+ ].filter((seg) => seg.count > 0);
1210
+ // The centre number is the success rate, so it always reads in the success
1211
+ // colour; failed/aborted/running are conveyed by the ring segments instead.
1212
+ const textToneClass = "text-feedback-green";
1213
+ const parts = [`${succeeded}/${total} succeeded`];
1214
+ if (failed > 0)
1215
+ parts.push(`${failed} failed`);
1216
+ if (aborted > 0)
1217
+ parts.push(`${aborted} aborted`);
1218
+ if (running > 0)
1219
+ parts.push(`${running} running`);
1220
+ const label = parts.join(", ");
1170
1221
  if (variant === "bar") {
1171
- return (_jsxs(Tooltip, { delayDuration: 250, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex min-w-0 items-center gap-2", "aria-label": label, "data-testid": testId, children: [_jsx("div", { className: "h-1.5 min-w-0 flex-1 overflow-hidden rounded-full", style: { backgroundColor: trackColor }, children: _jsx("div", { className: "h-full rounded-full transition-[width]", style: {
1172
- width: `${percent}%`,
1173
- backgroundColor: toneColor,
1174
- } }) }), _jsxs("span", { className: `shrink-0 text-[11px] leading-none font-medium tabular-nums ${toneClass}`, children: [percent, "%"] })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: label })] }));
1222
+ return (_jsxs(Tooltip, { delayDuration: 250, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex min-w-0 items-center gap-2", "aria-label": label, "data-testid": testId, children: [_jsx("div", { className: "bg-neutral-grey-15 flex h-1.5 min-w-0 flex-1 overflow-hidden rounded-full", children: total > 0 &&
1223
+ segments.map((seg) => (_jsx("div", { className: "h-full", style: {
1224
+ width: `${(seg.count / total) * 100}%`,
1225
+ backgroundColor: seg.color,
1226
+ } }, seg.key))) }), allSucceeded ? (_jsx(CheckIcon, { className: "text-feedback-green h-3 w-3 shrink-0", style: { strokeWidth: 3 } })) : (_jsxs("span", { className: `shrink-0 text-[11px] leading-none font-medium tabular-nums ${textToneClass}`, children: [percent, "%"] }))] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: label })] }));
1175
1227
  }
1176
- return (_jsxs(Tooltip, { delayDuration: 250, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: `relative h-10 w-10 shrink-0 rounded-full ${tone === "complete" ? "bg-feedback-green-light" : ""}`, "aria-label": label, "data-testid": testId, children: [_jsxs("svg", { className: "h-10 w-10 -rotate-90", viewBox: "0 0 40 40", children: [_jsx("circle", { cx: "20", cy: "20", r: radius, fill: "none", stroke: trackColor, strokeWidth: 1 }), _jsx("circle", { cx: "20", cy: "20", r: radius, fill: "none", stroke: toneColor, strokeLinecap: "round", strokeWidth: 1, style: {
1177
- strokeDasharray: circumference,
1178
- strokeDashoffset: dashOffset,
1179
- } })] }), _jsxs("span", { className: `absolute inset-0 flex items-center justify-center text-[10px] leading-none font-medium tabular-nums ${toneClass}`, children: [percent, "%"] })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: label })] }));
1228
+ const radius = 16;
1229
+ const strokeWidth = 3;
1230
+ const circumference = 2 * Math.PI * radius;
1231
+ const gap = segments.length > 1 ? circumference * 0.02 : 0;
1232
+ let segStart = 0;
1233
+ return (_jsxs(Tooltip, { delayDuration: 250, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "relative h-10 w-10 shrink-0 rounded-full", "aria-label": label, "data-testid": testId, children: [_jsxs("svg", { className: "h-10 w-10 -rotate-90", viewBox: "0 0 40 40", children: [allSucceeded && (_jsx("circle", { cx: "20", cy: "20", r: radius - strokeWidth / 2, fill: "var(--color-feedback-green-light)" })), _jsx("circle", { cx: "20", cy: "20", r: radius, fill: "none", stroke: "var(--color-neutral-grey-15)", strokeWidth: strokeWidth }), total > 0 &&
1234
+ segments.map((seg) => {
1235
+ const segLen = (seg.count / total) * circumference;
1236
+ const dash = Math.max(0, segLen - gap);
1237
+ const dashOffset = -segStart;
1238
+ segStart += segLen;
1239
+ return (_jsx("circle", { cx: "20", cy: "20", r: radius, fill: "none", stroke: seg.color, strokeLinecap: "butt", strokeWidth: strokeWidth, style: {
1240
+ strokeDasharray: `${dash} ${circumference}`,
1241
+ strokeDashoffset: dashOffset,
1242
+ } }, seg.key));
1243
+ })] }), _jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: allSucceeded ? (_jsx(CheckIcon, { className: "text-feedback-green h-4 w-4", style: { strokeWidth: 3 } })) : (_jsxs("span", { className: `text-[10px] leading-none font-medium tabular-nums ${textToneClass}`, children: [percent, "%"] })) })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: label })] }));
1180
1244
  }
1181
1245
  function itemStatusDot(jobs) {
1182
1246
  const hasError = jobs.some((j) => j.status === "Error");
@@ -1186,7 +1250,7 @@ function itemStatusDot(jobs) {
1186
1250
  if (hasError)
1187
1251
  return { cls: "bg-feedback-red", label: "Has errors" };
1188
1252
  if (hasInProgress)
1189
- return { cls: "bg-highlight-100", label: "In progress" };
1253
+ return { cls: "bg-feedback-blue", label: "In progress" };
1190
1254
  if (hasPending)
1191
1255
  return { cls: "bg-neutral-grey-15", label: "Queued" };
1192
1256
  if (hasAborted)
@@ -1428,7 +1492,7 @@ function BatchItemList({ batchId, batchProvider, jobs, isLoading, expandedItems,
1428
1492
  return;
1429
1493
  void onRetryJobs(batchId, batchProvider, itemErrorJobs, itemRetryKey);
1430
1494
  }, icon: _jsx(RetryIcon, { className: `h-3.5 w-3.5 ${isRetryingItem ? "animate-spin" : ""}`, strokeWidth: 1 }), label: "Retry failed translations for this item", disabled: itemErrorJobs.length === 0 || isRetryingItem }) })) : null;
1431
- const itemContent = (_jsxs("div", { className: `flex min-w-0 items-start ${stackLanguageChips ? "gap-2" : "gap-2.5"}`, children: [_jsx("span", { className: "mt-1 shrink-0", children: itemAnyInProgress ? (_jsx(LoaderIcon, { className: "h-3 w-3 animate-spin text-highlight-100" })) : itemIsQueued ? (_jsx(QueuedIcon, { className: "h-3 w-3 text-neutral-grey-50", strokeWidth: 1, "aria-label": "Queued" })) : (_jsx("span", { className: `block h-1.5 w-1.5 rounded-full ${status.cls}`, "aria-hidden": "true" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("span", { className: `block min-w-0 text-[13px] text-neutral-grey-100 ${stackLanguageChips ? "break-words" : "truncate"}`, style: stackLanguageChips
1495
+ const itemContent = (_jsxs("div", { className: `flex min-w-0 items-start ${stackLanguageChips ? "gap-2" : "gap-2.5"}`, children: [_jsx("span", { className: "mt-1 shrink-0", children: itemAnyInProgress ? (_jsx(LoaderIcon, { className: "h-3 w-3 animate-spin text-feedback-blue" })) : itemIsQueued ? (_jsx(QueuedIcon, { className: "h-3 w-3 text-neutral-grey-50", strokeWidth: 1, "aria-label": "Queued" })) : (_jsx("span", { className: `block h-1.5 w-1.5 rounded-full ${status.cls}`, "aria-hidden": "true" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("span", { className: `block min-w-0 text-[13px] text-neutral-grey-100 ${stackLanguageChips ? "break-words" : "truncate"}`, style: stackLanguageChips
1432
1496
  ? { overflowWrap: "anywhere" }
1433
1497
  : undefined, title: titleAttr, children: displayName }), itemPath && (_jsx("div", { className: "whitespace-normal break-words font-mono text-[11px] text-neutral-grey-50", style: { overflowWrap: "anywhere" }, title: titleAttr, children: itemPath })), stackLanguageChips && (_jsx("div", { className: "mt-2", children: languageChips })), stackLanguageChips && retryAction && (_jsx("div", { className: "mt-2 flex justify-start", children: retryAction }))] })] }));
1434
1498
  return (_jsxs("tr", { role: "button", tabIndex: 0, className: `group cursor-pointer transition-colors hover:bg-neutral-grey-5 ${itemIndex > 0 ? "border-t border-border-default/50" : ""}`, onClick: () => {
@@ -1455,7 +1519,7 @@ function LanguageJobChip({ job, language, batchStartedAtUtc, onOpen, isAborting
1455
1519
  : jobAborted
1456
1520
  ? "border-feedback-orange bg-feedback-orange-light text-feedback-orange hover:bg-feedback-orange-light"
1457
1521
  : jobInProgress
1458
- ? "border-highlight-100/30 bg-highlight-10 text-highlight-100 hover:brightness-95"
1522
+ ? "border-feedback-blue/30 bg-feedback-blue-light text-feedback-blue hover:brightness-95"
1459
1523
  : jobPending
1460
1524
  ? "border-border-default bg-neutral-grey-5 text-neutral-grey-50 hover:bg-neutral-grey-5"
1461
1525
  : "border-feedback-green bg-feedback-green-light text-feedback-green hover:border-feedback-green hover:brightness-95";
@@ -1464,7 +1528,7 @@ function LanguageJobChip({ job, language, batchStartedAtUtc, onOpen, isAborting
1464
1528
  : jobAborted
1465
1529
  ? "bg-feedback-orange-light text-feedback-orange"
1466
1530
  : jobInProgress
1467
- ? "bg-highlight-10 text-highlight-100"
1531
+ ? "bg-feedback-blue-light text-feedback-blue"
1468
1532
  : jobPending
1469
1533
  ? "bg-neutral-grey-5 text-neutral-grey-50"
1470
1534
  : "bg-feedback-green-light text-feedback-green";
@@ -1528,12 +1592,7 @@ function LanguageJobChip({ job, language, batchStartedAtUtc, onOpen, isAborting
1528
1592
  return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: `group inline-flex items-center gap-1.5 rounded border badge-pad-sm text-[12px] transition-colors cursor-pointer ${chipCls}`, children: [language?.icon ? (_jsx("img", { src: language.icon, alt: langName, className: "h-3.5 shrink-0" })) : null, _jsx("span", { className: "font-mono tracking-tight", children: job.targetLanguage }), jobInProgress && (_jsx(LoaderIcon, { className: "h-3 w-3 shrink-0 animate-spin" })), jobPending && (_jsx(QueuedIcon, { className: "h-3 w-3 shrink-0", strokeWidth: 1, "aria-label": "Queued" })), jobError && _jsx(AlertCircleIcon, { className: "h-3 w-3 shrink-0" }), !jobInProgress && !jobError && !jobPending && !jobAborted && (_jsx(CheckIcon, { className: "h-3 w-3 shrink-0 text-feedback-green" }))] }) }), _jsxs(PopoverContent, { align: "start", sideOffset: 6, className: "w-[22rem] max-w-[calc(100vw-2rem)] p-0", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border-default px-3 py-2", children: [language?.icon ? (_jsx("img", { src: language.icon, alt: langName, className: "h-4 shrink-0" })) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-[13px] font-medium text-neutral-grey-100 truncate", children: langName }), _jsxs("div", { className: "text-[11px] text-neutral-grey-50 font-mono truncate", children: [job.targetLanguage, job.sourceLanguage ? ` ← ${job.sourceLanguage}` : ""] })] }), _jsxs(Badge, { size: "sm", className: statusBadgeCls, children: [jobInProgress && (_jsx(LoaderIcon, { className: "h-2.5 w-2.5 animate-spin" })), jobStatus || "Unknown"] })] }), _jsxs("dl", { className: "divide-y divide-border-default/60", children: [claimedAtValid && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Claimed" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: formatDateTime(claimedAt) })] })), timestampValid && (jobInProgress || jobPending) && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Updated" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: formatDateTime(timestamp) })] })), durationMs != null && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: jobInProgress || jobPending ? "Running" : "Duration" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", title: durationApproximated
1529
1593
  ? "Approximate — measured from batch start"
1530
1594
  : undefined, children: [durationApproximated ? "~" : "", formatDuration(durationMs)] })] })), statistics && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Fields" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: [fieldText, emptyFieldText ? (_jsxs("span", { className: "ml-1.5 text-neutral-grey-50", children: ["(", emptyFieldText, ")"] })) : null] })] })), statistics && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Text" }), _jsxs("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: [formatCount(statistics.sourceCharacterCount), " chars"] })] })), job.totalCost != null && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Cost" }), _jsx("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: formatUsdCost(job.totalCost) })] })), lastHeartbeatValid && (jobInProgress || jobPending) && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Heartbeat" }), _jsx("dd", { className: "text-[12px] text-neutral-grey-100", children: formatDateTime(lastHeartbeat) })] })), attemptCount > 1 && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Attempts" }), _jsx("dd", { className: "text-[12px] tabular-nums text-neutral-grey-100", children: attemptCount })] })), job.hash && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Hash" }), _jsx("dd", { className: "text-[11px] font-mono text-neutral-grey-100 break-all", children: job.hash })] })), job.message &&
1531
- (jobError || jobAborted ? (
1532
- // Error/abort messages can be long and multi-line (e.g. an external
1533
- // ITranslationService stack trace). Render them in a bounded,
1534
- // scrollable monospace block so the popover stays a sensible size and
1535
- // the original formatting is preserved.
1536
- _jsxs("div", { className: "flex flex-col gap-1 px-3 py-2", children: [_jsx("dt", { className: "text-[10px] tracking-wide text-neutral-grey-50", children: jobError ? "Error" : "Aborted" }), _jsx("dd", { className: `max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-sm bg-neutral-grey-5 p-2 font-mono text-[11px] leading-snug ${jobError ? "text-feedback-red" : "text-feedback-orange"}`, children: job.message })] })) : (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Progress" }), _jsx("dd", { className: "text-[12px] break-words text-neutral-grey-100", children: job.message })] }))), job.batchId && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Batch" }), _jsx("dd", { className: "text-[11px] font-mono text-neutral-grey-50 break-all", children: job.batchId })] }))] }), _jsxs("div", { className: "flex justify-end gap-2 border-t border-border-default px-3 py-2", children: [canAbort && (_jsxs(Button, { size: "sm", variant: "outline", disabled: isAborting, onClick: (e) => {
1595
+ (jobError || jobAborted ? (_jsxs("div", { className: "flex flex-col gap-1 px-3 py-2", children: [_jsx("dt", { className: "text-[10px] tracking-wide text-neutral-grey-50", children: jobError ? "Error" : "Aborted" }), _jsx("dd", { className: `max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-sm bg-neutral-grey-5 p-2 font-mono text-[11px] leading-snug ${jobError ? "text-feedback-red" : "text-feedback-orange"}`, children: job.message })] })) : (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Progress" }), _jsx("dd", { className: "text-[12px] break-words text-neutral-grey-100", children: job.message })] }))), job.batchId && (_jsxs("div", { className: "flex items-baseline gap-3 px-3 py-2", children: [_jsx("dt", { className: "w-20 shrink-0 text-[10px] tracking-wide text-neutral-grey-50", children: "Batch" }), _jsx("dd", { className: "text-[11px] font-mono text-neutral-grey-50 break-all", children: job.batchId })] }))] }), _jsxs("div", { className: "flex justify-end gap-2 border-t border-border-default px-3 py-2", children: [canAbort && (_jsxs(Button, { size: "sm", variant: "outline", disabled: isAborting, onClick: (e) => {
1537
1596
  e.stopPropagation();
1538
1597
  void onAbort?.();
1539
1598
  setOpen(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parhelia/localization",
3
- "version": "0.3.12770",
3
+ "version": "0.3.12777",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -38,7 +38,8 @@
38
38
  "@types/react-dom": "19.2.3",
39
39
  "eslint": "^9.22.0",
40
40
  "tailwindcss": "^4.1.18",
41
- "typescript": "5.8.2"
41
+ "@typescript/native": "npm:typescript@7.0.2",
42
+ "typescript": "npm:@typescript/typescript6@6.0.2"
42
43
  },
43
44
  "dependencies": {
44
45
  "@parhelia/core": "*",