@parhelia/localization 0.3.12763 → 0.3.12767

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.
@@ -290,7 +290,7 @@ export function LocalizeItemDialog(props) {
290
290
  }, children: [_jsxs(DialogContent, { className: "flex max-h-[900px] min-h-0 max-w-5xl flex-col overflow-visible md:min-h-[700px]", "data-testid": "translation-wizard-dialog", onPointerDownOutside: (e) => e.preventDefault(), onEscapeKeyDown: (e) => e.preventDefault(), "aria-describedby": "translation-wizard-description", style: {
291
291
  width: isMobile ? "calc(100vw - 24px)" : "min(90vw, 1280px)",
292
292
  height: isMobile ? "min(92dvh, 900px)" : "min(85vh, 900px)",
293
- }, children: [_jsxs("div", { className: "flex h-full min-h-0 w-full flex-col overflow-hidden rounded-2xl bg-white", children: [_jsx(StyledDialogTitle, { icon: _jsx(GlobeIcon, { strokeWidth: 1.5 }), title: `Translate · ${currentStep?.name ?? ""}`, subtitle: currentStep?.description ||
293
+ }, children: [_jsxs("div", { className: "flex h-full min-h-0 w-full flex-col overflow-hidden rounded-2xl bg-white", children: [_jsx(StyledDialogTitle, { icon: _jsx(GlobeIcon, { strokeWidth: 1 }), title: `Translate · ${currentStep?.name ?? ""}`, subtitle: currentStep?.description ||
294
294
  "Configure and start translation for your content" }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description ||
295
295
  "Configure and start translation for your content." }), _jsxs("div", { className: "flex flex-1 flex-col min-h-0", children: [_jsx("div", { className: "flex-1 overflow-y-auto min-h-0 ", "data-testid": "translation-wizard-step-content", children: _jsx("div", { className: "h-full relative", children: activeSteps.map((step, index) => {
296
296
  const StepComponent = step.component;
@@ -303,7 +303,7 @@ export function LocalizeItemDialog(props) {
303
303
  if (totalTranslations <= 0)
304
304
  return "Start Translation";
305
305
  return `Start Translation (${totalTranslations}${isStreaming ? "+" : ""})`;
306
- })()) : (_jsxs(_Fragment, { children: [getNextButtonLabel(activeSteps[currentStepIndex + 1]), _jsx(ArrowRightIcon, { className: "h-4 w-4", strokeWidth: 2 })] })) })] })] })] })] }), _jsx(StepIndicatorDots, { steps: activeSteps, currentStepIndex: currentStepIndex })] }), _jsx(AlertDialog, { open: showLargeBatchWarning, onOpenChange: setShowLargeBatchWarning, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsxs(AlertDialogTitle, { className: "flex items-center gap-2", children: [_jsx(AlertTriangleIcon, { className: "h-5 w-5 text-feedback-orange" }), "Large Translation Batch"] }), _jsx(AlertDialogDescription, { children: (() => {
306
+ })()) : (_jsxs(_Fragment, { children: [getNextButtonLabel(activeSteps[currentStepIndex + 1]), _jsx(ArrowRightIcon, { className: "h-4 w-4", strokeWidth: 1 })] })) })] })] })] })] }), _jsx(StepIndicatorDots, { steps: activeSteps, currentStepIndex: currentStepIndex })] }), _jsx(AlertDialog, { open: showLargeBatchWarning, onOpenChange: setShowLargeBatchWarning, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsxs(AlertDialogTitle, { className: "flex items-center gap-2", children: [_jsx(AlertTriangleIcon, { className: "h-5 w-5 text-feedback-orange" }), "Large Translation Batch"] }), _jsx(AlertDialogDescription, { children: (() => {
307
307
  const { itemCount, languageCount, totalTranslations } = calculateTranslationCounts(wizardData);
308
308
  return (_jsxs(_Fragment, { children: ["You are about to start", " ", _jsxs("strong", { children: [totalTranslations, " translations"] }), " (", itemCount, " items \u00D7 ", languageCount, " languages). Large batches may take a significant amount of time to process.", _jsx("br", {}), _jsx("br", {}), "Are you sure you want to continue?"] }));
309
309
  })() })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isSubmitting, children: "Cancel" }), _jsx(AlertDialogAction, { onClick: handleLargeBatchConfirm, disabled: isSubmitting, children: isSubmitting ? "Starting..." : "Continue" })] })] }) })] }));
@@ -242,24 +242,24 @@ export function TranslationServicesPanel() {
242
242
  const translationFolderExists = !!structureState?.translationFolder?.exists;
243
243
  const providersFolderExists = !!structureState?.translationProvidersFolder?.exists;
244
244
  // Build the services list content
245
- const servicesListContent = (_jsxs("div", { className: "flex h-full flex-col gap-4 p-4", "data-testid": "translation-services-panel", children: [_jsx(Card, { icon: _jsx(ListChecksIcon, { strokeWidth: 1, className: "h-5 w-5" }), title: "Prerequisites", description: "Required Sitecore folders for translation settings.", noPadding: true, className: "shrink-0", headerActions: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex items-center gap-1.5 text-xs text-neutral-grey-50", children: translationFolderExists && providersFolderExists ? (_jsxs(_Fragment, { children: [_jsx(CheckCircleIcon, { className: "h-3.5 w-3.5 text-feedback-green", strokeWidth: 1.5 }), "All parent items found"] })) : (_jsxs(_Fragment, { children: [_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-feedback-orange", strokeWidth: 1.5 }), "Parent items missing"] })) }), !providersFolderExists && (_jsxs(Button, { size: "sm", variant: "default", onClick: ensureStructure, disabled: ensuringStructure || structureLoading, children: [ensuringStructure ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "mr-1 h-4 w-4 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1.75, className: "mr-1 h-4 w-4" })), "Ensure items"] }))] }), children: _jsxs("div", { className: "divide-y divide-border-default border-t border-border-default", children: [_jsxs("div", { "data-testid": "translation-structure-folder", className: `flex items-center gap-3 px-3 py-3 text-sm transition-colors ${selectedConfigTarget?.key ===
245
+ const servicesListContent = (_jsxs("div", { className: "flex h-full flex-col gap-4 p-4", "data-testid": "translation-services-panel", children: [_jsx(Card, { icon: _jsx(ListChecksIcon, { strokeWidth: 1, className: "h-5 w-5" }), title: "Prerequisites", description: "Required Sitecore folders for translation settings.", noPadding: true, className: "shrink-0", headerActions: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex items-center gap-1.5 text-xs text-neutral-grey-50", children: translationFolderExists && providersFolderExists ? (_jsxs(_Fragment, { children: [_jsx(CheckCircleIcon, { className: "h-3.5 w-3.5 text-feedback-green", strokeWidth: 1 }), "All parent items found"] })) : (_jsxs(_Fragment, { children: [_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-feedback-orange", strokeWidth: 1 }), "Parent items missing"] })) }), !providersFolderExists && (_jsxs(Button, { size: "sm", variant: "default", onClick: ensureStructure, disabled: ensuringStructure || structureLoading, children: [ensuringStructure ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "mr-1 h-4 w-4 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1, className: "mr-1 h-4 w-4" })), "Ensure items"] }))] }), children: _jsxs("div", { className: "divide-y divide-border-default border-t border-border-default", children: [_jsxs("div", { "data-testid": "translation-structure-folder", className: `flex items-center gap-3 px-3 py-3 text-sm transition-colors ${selectedConfigTarget?.key ===
246
246
  `structure:${structureState?.translationFolder?.itemId}`
247
247
  ? "bg-feedback-blue-light"
248
- : "bg-white"}`, children: [translationFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1.5 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-neutral-grey-100", children: "Translation folder" }), _jsx("div", { className: "mt-0.5 truncate font-mono text-xs text-neutral-grey-50", children: structureSettings.translationFolderPath })] }), translationFolderExists &&
249
- structureState?.translationFolder?.itemId && (_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationFolder.itemId, "Configure: Translation folder"), title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }))] }), _jsxs("div", { "data-testid": "translation-structure-providers-folder", className: `flex items-center gap-3 px-3 py-3 text-sm transition-colors ${selectedConfigTarget?.key ===
248
+ : "bg-white"}`, children: [translationFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-neutral-grey-100", children: "Translation folder" }), _jsx("div", { className: "mt-0.5 truncate font-mono text-xs text-neutral-grey-50", children: structureSettings.translationFolderPath })] }), translationFolderExists &&
249
+ structureState?.translationFolder?.itemId && (_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationFolder.itemId, "Configure: Translation folder"), title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1 }) }))] }), _jsxs("div", { "data-testid": "translation-structure-providers-folder", className: `flex items-center gap-3 px-3 py-3 text-sm transition-colors ${selectedConfigTarget?.key ===
250
250
  `structure:${structureState?.translationProvidersFolder?.itemId}`
251
251
  ? "bg-feedback-blue-light"
252
- : "bg-white"}`, children: [providersFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1.5 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-neutral-grey-100", children: "Translation providers folder" }), _jsx("div", { className: "mt-0.5 truncate font-mono text-xs text-neutral-grey-50", children: structureSettings.translationProvidersPath })] }), providersFolderExists &&
253
- structureState?.translationProvidersFolder?.itemId && (_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationProvidersFolder.itemId, "Configure: Translation Providers folder"), title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }))] })] }) }), _jsxs(Card, { icon: _jsx(LanguagesIcon, { strokeWidth: 1, className: "h-5 w-5" }), title: _jsxs(_Fragment, { children: ["Translation providers", " ", _jsxs("span", { className: "font-normal text-neutral-grey-50", children: ["(", configuredCount, " of ", totalCount, " configured)"] })] }), description: "Translation services registered in Parhelia and their settings.", noPadding: true, className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: [((totalCount === 0 && state === "success") || error) && (_jsxs("div", { className: "border-border-default space-y-2 border-t px-4 py-3", children: [totalCount === 0 && state === "success" && (_jsx("div", { className: "rounded border border-feedback-orange bg-feedback-orange-light p-2 text-xs text-feedback-orange", children: "No translation services are registered in dependency injection. Please check the server configuration." })), error && (_jsx("div", { className: "rounded border border-feedback-red bg-feedback-red-light p-2 text-xs whitespace-pre-wrap text-feedback-red", children: error }))] })), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto border-t border-border-default", "data-testid": "translation-services-providers", children: services.length > 0 && (_jsx("div", { className: "divide-y divide-border-default", children: services.map((service) => {
252
+ : "bg-white"}`, children: [providersFolderExists ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-neutral-grey-100", children: "Translation providers folder" }), _jsx("div", { className: "mt-0.5 truncate font-mono text-xs text-neutral-grey-50", children: structureSettings.translationProvidersPath })] }), providersFolderExists &&
253
+ structureState?.translationProvidersFolder?.itemId && (_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenStructureConfig(structureState.translationProvidersFolder.itemId, "Configure: Translation Providers folder"), title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1 }) }))] })] }) }), _jsxs(Card, { icon: _jsx(LanguagesIcon, { strokeWidth: 1, className: "h-5 w-5" }), title: _jsxs(_Fragment, { children: ["Translation providers", " ", _jsxs("span", { className: "font-normal text-neutral-grey-50", children: ["(", configuredCount, " of ", totalCount, " configured)"] })] }), description: "Translation services registered in Parhelia and their settings.", noPadding: true, className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: [((totalCount === 0 && state === "success") || error) && (_jsxs("div", { className: "border-border-default space-y-2 border-t px-4 py-3", children: [totalCount === 0 && state === "success" && (_jsx("div", { className: "rounded border border-feedback-orange bg-feedback-orange-light p-2 text-xs text-feedback-orange", children: "No translation services are registered in dependency injection. Please check the server configuration." })), error && (_jsx("div", { className: "rounded border border-feedback-red bg-feedback-red-light p-2 text-xs whitespace-pre-wrap text-feedback-red", children: error }))] })), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto border-t border-border-default", "data-testid": "translation-services-providers", children: services.length > 0 && (_jsx("div", { className: "divide-y divide-border-default", children: services.map((service) => {
254
254
  const isSelected = selectedConfigTarget?.key ===
255
255
  `service:${service.serviceName}`;
256
256
  const isConfigured = service.isConfigured;
257
257
  return (_jsxs("div", { className: `group flex items-center gap-3 px-3 py-3 text-sm transition-colors ${isSelected
258
258
  ? "bg-feedback-blue-light"
259
- : "bg-white hover:bg-neutral-grey-5"}`, children: [isConfigured ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1.5 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx("span", { className: "truncate font-medium text-neutral-grey-100", children: service.displayName || service.serviceName }), service.displayName &&
259
+ : "bg-white hover:bg-neutral-grey-5"}`, children: [isConfigured ? (_jsx(CheckCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-green", strokeWidth: 1 })) : (_jsx(AlertCircleIcon, { className: "h-4 w-4 shrink-0 text-feedback-orange", strokeWidth: 1 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx("span", { className: "truncate font-medium text-neutral-grey-100", children: service.displayName || service.serviceName }), service.displayName &&
260
260
  service.displayName !== service.serviceName && (_jsx("span", { className: "shrink-0 rounded bg-neutral-grey-5 badge-pad-sm text-[10px] font-medium text-neutral-grey-50", children: service.serviceName })), !isConfigured && (_jsx("span", { className: "shrink-0 rounded bg-feedback-orange-light badge-pad-sm text-[10px] font-medium text-feedback-orange", children: "Not configured" }))] }), isConfigured &&
261
261
  service.supportedLanguages &&
262
- service.supportedLanguages.length > 0 && (_jsxs("div", { className: "mt-0.5 truncate text-xs text-neutral-grey-50", children: ["Languages: ", service.supportedLanguages.join(", ")] }))] }), _jsx("div", { className: "flex shrink-0 items-center gap-0.5", children: isConfigured && service.settingsItemId ? (_jsxs("div", { className: "flex items-center gap-0.5 opacity-60 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenConfig(service), disabled: service.deleting, title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => deleteSettings(service), className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-50", disabled: service.deleting, title: `Delete settings for ${service.displayName || service.serviceName}`, children: service.deleting ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(DeleteIcon, { size: "md" })) })] })) : (_jsxs(Button, { size: "sm", variant: "default", onClick: () => createSettings(service.serviceName, service.templateId), disabled: service.creating, title: `Create settings using template: ${service.templateName}`, children: [service.creating ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "mr-1 h-3.5 w-3.5 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1.75, className: "mr-1 h-3.5 w-3.5" })), "Create"] })) })] }, service.serviceName));
262
+ service.supportedLanguages.length > 0 && (_jsxs("div", { className: "mt-0.5 truncate text-xs text-neutral-grey-50", children: ["Languages: ", service.supportedLanguages.join(", ")] }))] }), _jsx("div", { className: "flex shrink-0 items-center gap-0.5", children: isConfigured && service.settingsItemId ? (_jsxs("div", { className: "flex items-center gap-0.5 opacity-60 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleOpenConfig(service), disabled: service.deleting, title: "Configure", children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5", strokeWidth: 1 }) }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => deleteSettings(service), className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-50", disabled: service.deleting, title: `Delete settings for ${service.displayName || service.serviceName}`, children: service.deleting ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(DeleteIcon, { size: "md" })) })] })) : (_jsxs(Button, { size: "sm", variant: "default", onClick: () => createSettings(service.serviceName, service.templateId), disabled: service.creating, title: `Create settings using template: ${service.templateName}`, children: [service.creating ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "mr-1 h-3.5 w-3.5 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1, className: "mr-1 h-3.5 w-3.5" })), "Create"] })) })] }, service.serviceName));
263
263
  }) })) })] })] }));
264
264
  // Build splitter panels - only show config panel when a service is selected
265
265
  const panels = selectedConfigTarget?.itemId
@@ -119,9 +119,9 @@ export function LocalizationSetupStep() {
119
119
  ? `${totalCount} service${totalCount !== 1 ? "s" : ""} found, none configured`
120
120
  : state === "error"
121
121
  ? "No services found"
122
- : "Checking..." })] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: checkLocalization, children: [_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-4 w-4" }), "Recheck"] })] }), services.length > 0 && (_jsxs("div", { className: "space-y-2 rounded-lg border border-border-default bg-neutral-grey-5 p-3", children: [_jsx("div", { className: "text-xs font-medium text-neutral-grey-50 tracking-wide", children: "Translation Services" }), services.map((service) => (_jsxs("div", { className: "flex items-center justify-between rounded-md bg-background p-3 shadow-sm border border-border-default", children: [_jsxs("div", { className: "flex items-center gap-2", children: [service.isConfigured ? (_jsx(CheckCircleIcon, { className: "h-3.5 w-3.5 text-[var(--color-feedback-green)]", strokeWidth: 1.5 })) : (_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-[var(--color-feedback-orange)]", strokeWidth: 1.5 })), _jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-neutral-grey-100", children: service.displayName || service.serviceName }), service.displayName &&
122
+ : "Checking..." })] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: checkLocalization, children: [_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-4 w-4" }), "Recheck"] })] }), services.length > 0 && (_jsxs("div", { className: "space-y-2 rounded-lg border border-border-default bg-neutral-grey-5 p-3", children: [_jsx("div", { className: "text-xs font-medium text-neutral-grey-50 tracking-wide", children: "Translation Services" }), services.map((service) => (_jsxs("div", { className: "flex items-center justify-between rounded-md bg-background p-3 shadow-sm border border-border-default", children: [_jsxs("div", { className: "flex items-center gap-2", children: [service.isConfigured ? (_jsx(CheckCircleIcon, { className: "h-3.5 w-3.5 text-[var(--color-feedback-green)]", strokeWidth: 1 })) : (_jsx(AlertCircleIcon, { className: "h-3.5 w-3.5 text-[var(--color-feedback-orange)]", strokeWidth: 1 })), _jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-neutral-grey-100", children: service.displayName || service.serviceName }), service.displayName &&
123
123
  service.displayName !== service.serviceName && (_jsxs("div", { className: "text-xs text-neutral-grey-50", children: ["Service: ", service.serviceName] })), service.isConfigured &&
124
124
  service.supportedLanguages &&
125
- service.supportedLanguages.length > 0 && (_jsxs("div", { className: "text-xs text-neutral-grey-50", children: ["Languages: ", service.supportedLanguages.join(", ")] }))] })] }), !service.isConfigured && (_jsxs(Button, { size: "xs", onClick: () => createSettings(service.serviceName, service.templateId), disabled: service.creating, title: `Create using template: ${service.templateName}`, children: [service.creating ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1.5, className: "h-3 w-3" })), "Create Settings"] }))] }, service.serviceName)))] })), error && (_jsx("div", { className: "rounded-md border border-feedback-orange/30 bg-feedback-orange/10 p-3 text-xs whitespace-pre-wrap text-neutral-grey-100", children: error }))] }) }));
125
+ service.supportedLanguages.length > 0 && (_jsxs("div", { className: "text-xs text-neutral-grey-50", children: ["Languages: ", service.supportedLanguages.join(", ")] }))] })] }), !service.isConfigured && (_jsxs(Button, { size: "xs", onClick: () => createSettings(service.serviceName, service.templateId), disabled: service.creating, title: `Create using template: ${service.templateName}`, children: [service.creating ? (_jsx(RefreshCwIcon, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(PlusIcon, { strokeWidth: 1, className: "h-3 w-3" })), "Create Settings"] }))] }, service.serviceName)))] })), error && (_jsx("div", { className: "rounded-md border border-feedback-orange/30 bg-feedback-orange/10 p-3 text-xs whitespace-pre-wrap text-neutral-grey-100", children: error }))] }) }));
126
126
  }
127
127
  export default LocalizationSetupStep;
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderStep.d.ts","sourceRoot":"","sources":["../../src/steps/ProviderStep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAUjF,OAAO,EAAE,oBAAoB,EAAyB,MAAM,SAAS,CAAC;AAQtE,wBAAgB,YAAY,CAAC,EAC3B,QAAe,EACf,IAAI,EACJ,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE,oBAAoB,qBAqXtB"}
1
+ {"version":3,"file":"ProviderStep.d.ts","sourceRoot":"","sources":["../../src/steps/ProviderStep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAUf,OAAO,EAAE,oBAAoB,EAAyB,MAAM,SAAS,CAAC;AAQtE,wBAAgB,YAAY,CAAC,EAC3B,QAAe,EACf,IAAI,EACJ,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE,oBAAoB,qBAqXtB"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import React, { useCallback, useEffect, useMemo, useRef, useState, } from "react";
3
3
  import { Button, Input, Label, Select, Spinner, Textarea, } from "@parhelia/core";
4
4
  import { RotateCcw } from "lucide-react";
5
5
  import { WizardStepShell } from "./WizardStepShell";
@@ -219,5 +219,5 @@ export function ProviderStep({ isActive = true, data, setData, onStepCompleted,
219
219
  }), options: data.translationProviders.map((provider) => ({
220
220
  value: provider.name,
221
221
  label: provider.displayName || provider.name,
222
- })), placeholder: "Select a provider...", size: "sm", className: "mt-2 w-full", "data-testid": "translation-provider-select" }), isCreateLanguageVersionsOnlyProvider && (_jsx("p", { className: "text-muted-foreground mt-2 text-xs", children: "\"Create Language Versions Only\" will create new language versions without automatic translation." }))] }), supportsPromptCustomization && (_jsxs("div", { children: [_jsxs(Label, { className: "flex cursor-pointer items-start gap-2.5", children: [_jsx("input", { type: "checkbox", checked: enableCustomPrompt, onChange: (e) => handleCustomPromptToggle(e.target.checked), className: "mt-0.5 h-3.5 w-3.5 rounded border-border-default text-[var(--color-highlight-100)] accent-[var(--color-highlight-100)] focus:ring-[var(--color-highlight-100)]", "data-testid": "enable-custom-prompt-checkbox" }), _jsxs("div", { className: "min-w-0", children: [_jsx("span", { className: "block text-[13px] font-medium text-neutral-grey-100", children: "Customize translation prompt (optional)" }), _jsx("span", { className: "text-muted-foreground mt-0.5 block text-xs", children: "Edit the provider prompt before starting translation." })] })] }), enableCustomPrompt && (_jsxs("div", { className: "mt-4 space-y-2", children: [_jsx(Textarea, { id: "custom-prompt-textarea", value: customPrompt, onChange: (e) => setCustomPrompt(e.target.value), className: "text-xs", rows: 8, placeholder: "Enter prompt instructions here...", "data-testid": "custom-prompt-textarea" }), hasDefaultPrompt && (_jsxs(Button, { type: "button", size: "sm", variant: "outline", onClick: handleResetPrompt, disabled: customPrompt === (defaultPrompt || ""), className: "gap-1.5", title: "Reset to the default prompt", "data-testid": "reset-custom-prompt-button", children: [_jsx(ResetIcon, { className: "size-3.5", strokeWidth: 1.5, "aria-hidden": "true" }), "Reset to default"] }))] }))] }))] })] }) }) }));
222
+ })), placeholder: "Select a provider...", size: "sm", className: "mt-2 w-full", "data-testid": "translation-provider-select" }), isCreateLanguageVersionsOnlyProvider && (_jsx("p", { className: "text-muted-foreground mt-2 text-xs", children: "\"Create Language Versions Only\" will create new language versions without automatic translation." }))] }), supportsPromptCustomization && (_jsxs("div", { children: [_jsxs(Label, { className: "flex cursor-pointer items-start gap-2.5", children: [_jsx("input", { type: "checkbox", checked: enableCustomPrompt, onChange: (e) => handleCustomPromptToggle(e.target.checked), className: "mt-0.5 h-3.5 w-3.5 rounded border-border-default text-[var(--color-highlight-100)] accent-[var(--color-highlight-100)] focus:ring-[var(--color-highlight-100)]", "data-testid": "enable-custom-prompt-checkbox" }), _jsxs("div", { className: "min-w-0", children: [_jsx("span", { className: "block text-[13px] font-medium text-neutral-grey-100", children: "Customize translation prompt (optional)" }), _jsx("span", { className: "text-muted-foreground mt-0.5 block text-xs", children: "Edit the provider prompt before starting translation." })] })] }), enableCustomPrompt && (_jsxs("div", { className: "mt-4 space-y-2", children: [_jsx(Textarea, { id: "custom-prompt-textarea", value: customPrompt, onChange: (e) => setCustomPrompt(e.target.value), className: "text-xs", rows: 8, placeholder: "Enter prompt instructions here...", "data-testid": "custom-prompt-textarea" }), hasDefaultPrompt && (_jsxs(Button, { type: "button", size: "sm", variant: "outline", onClick: handleResetPrompt, disabled: customPrompt === (defaultPrompt || ""), className: "gap-1.5", title: "Reset to the default prompt", "data-testid": "reset-custom-prompt-button", children: [_jsx(ResetIcon, { className: "size-3.5", strokeWidth: 1, "aria-hidden": "true" }), "Reset to default"] }))] }))] }))] })] }) }) }));
223
223
  }
@@ -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,sBAgnCjC;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;AAgV1B,wBAAgB,kBAAkB,sBA+mCjC;AAED,eAAO,MAAM,oCAAoC,8BAA8B,CAAC;AAEhF,wBAAgB,8BAA8B,sBA0Y7C"}
@@ -35,7 +35,7 @@ function renderTargetLanguageIcon(language) {
35
35
  }
36
36
  return React.createElement(GlobeIcon, {
37
37
  className: "h-3.5 w-3.5 text-neutral-grey-50",
38
- strokeWidth: 1.5,
38
+ strokeWidth: 1,
39
39
  "aria-hidden": true,
40
40
  });
41
41
  }
@@ -854,7 +854,7 @@ export function TranslationBatches() {
854
854
  if (!canRetry)
855
855
  return;
856
856
  void handleRetryBatch(info);
857
- }, icon: _jsx(RetryIcon, { className: `h-3.5 w-3.5 ${isRetryingBatch ? "animate-spin" : ""}`, strokeWidth: 1.5 }), label: "Retry failed translations", disabled: !canRetry ||
857
+ }, icon: _jsx(RetryIcon, { className: `h-3.5 w-3.5 ${isRetryingBatch ? "animate-spin" : ""}`, strokeWidth: 1 }), label: "Retry failed translations", disabled: !canRetry ||
858
858
  isRetryingBatch ||
859
859
  isLoadingThis ||
860
860
  isAborting })), canAbort && (_jsx(SimpleIconButton, { onClick: (event) => {
@@ -862,7 +862,7 @@ export function TranslationBatches() {
862
862
  if (!canAbort)
863
863
  return;
864
864
  handleAbortBatch(b.id);
865
- }, icon: _jsx(AbortIcon, { className: `h-3.5 w-3.5 ${isAborting ? "animate-spin" : ""}`, strokeWidth: 1.5 }), label: "Abort translation batch", disabled: !canAbort || isAborting }))] }));
865
+ }, icon: _jsx(AbortIcon, { className: `h-3.5 w-3.5 ${isAborting ? "animate-spin" : ""}`, strokeWidth: 1 }), label: "Abort translation batch", disabled: !canAbort || isAborting }))] }));
866
866
  return (_jsxs("div", { "data-testid": `batch-row-${b.id}`, "data-batch-status": testStatus, children: [_jsx("div", { role: "button", tabIndex: 0, className: `group w-full cursor-pointer py-3 text-left transition-colors hover:bg-neutral-grey-5 ${isCompactBatches ? "px-2.5" : "px-4"}`, onClick: () => toggleBatch(b.id), onKeyDown: (e) => {
867
867
  if (e.key === "Enter" || e.key === " ") {
868
868
  e.preventDefault();
@@ -969,7 +969,7 @@ export function TranslationBatchFiltersSidebar() {
969
969
  const filterFieldClass = "flex flex-col gap-1";
970
970
  return (_jsxs("div", { className: "flex h-full min-h-0 flex-col bg-white", "data-testid": "translation-filters-sidebar", children: [_jsx("div", { className: "border-border-default flex shrink-0 flex-col gap-2 border-b px-3 py-3", children: _jsxs(Button, { type: "button", variant: "outline", size: "lg", title: canStartTranslation
971
971
  ? "Start new translation"
972
- : "Open an item to translate", "data-testid": "translation-sidebar-start-new-translation-button", disabled: !canStartTranslation, onClick: handleStartTranslation, className: "border-border-default hover:border-neutral-grey-100 hover:bg-neutral-grey-5 h-9 w-full justify-center gap-3 rounded-md bg-white px-3 text-sm font-medium shadow-none", children: [_jsx("span", { className: "truncate", children: "Start new translation" }), _jsx(PlusIcon, { className: "size-4", strokeWidth: 1.5 })] }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 py-4", children: _jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: filterFieldClass, children: [_jsx("label", { className: filterLabelClass, children: "Date Range" }), _jsx(Select, { className: "w-full bg-white", options: DATE_RANGE_OPTIONS, value: filters.dateRange, onValueChange: (value) => setTranslationBatchFilters((prev) => ({
972
+ : "Open an item to translate", "data-testid": "translation-sidebar-start-new-translation-button", disabled: !canStartTranslation, onClick: handleStartTranslation, className: "border-border-default hover:border-neutral-grey-100 hover:bg-neutral-grey-5 h-9 w-full justify-center gap-3 rounded-md bg-white px-3 text-sm font-medium shadow-none", children: [_jsx("span", { className: "truncate", children: "Start new translation" }), _jsx(PlusIcon, { className: "size-4", strokeWidth: 1 })] }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 py-4", children: _jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: filterFieldClass, children: [_jsx("label", { className: filterLabelClass, children: "Date Range" }), _jsx(Select, { className: "w-full bg-white", options: DATE_RANGE_OPTIONS, value: filters.dateRange, onValueChange: (value) => setTranslationBatchFilters((prev) => ({
973
973
  ...prev,
974
974
  dateRange: value,
975
975
  })), placeholder: "Select date range" })] }), _jsxs("div", { className: filterFieldClass, children: [_jsx("label", { className: filterLabelClass, children: "Status" }), _jsx(Select, { className: "w-full bg-white", options: STATUS_OPTIONS, value: filters.status, onValueChange: (value) => setTranslationBatchFilters((prev) => ({
@@ -1173,7 +1173,7 @@ function BatchProgressIndicator({ value, completedJobs, totalJobs, errorJobs, to
1173
1173
  backgroundColor: toneColor,
1174
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 })] }));
1175
1175
  }
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: "2" }), _jsx("circle", { cx: "20", cy: "20", r: radius, fill: "none", stroke: toneColor, strokeLinecap: "round", strokeWidth: "2", style: {
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
1177
  strokeDasharray: circumference,
1178
1178
  strokeDashoffset: dashOffset,
1179
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 })] }));
@@ -1249,10 +1249,10 @@ function CustomPromptPanel({ prompts }) {
1249
1249
  e.preventDefault();
1250
1250
  setOpenProvider(isOpen ? null : p.provider);
1251
1251
  }
1252
- }, children: [_jsx(SparklesIcon, { className: "h-3 w-3 shrink-0 text-highlight-100", strokeWidth: 1.75 }), _jsx("span", { className: "text-neutral-grey-100", children: "Custom prompt" }), _jsx("span", { className: "text-neutral-grey-15", children: "\u00B7" }), _jsx("span", { children: p.provider }), _jsxs("span", { className: "ml-auto flex items-center gap-2", children: [isOpen && (_jsx(SimpleIconButton, { onClick: (event) => {
1252
+ }, children: [_jsx(SparklesIcon, { className: "h-3 w-3 shrink-0 text-highlight-100", strokeWidth: 1 }), _jsx("span", { className: "text-neutral-grey-100", children: "Custom prompt" }), _jsx("span", { className: "text-neutral-grey-15", children: "\u00B7" }), _jsx("span", { children: p.provider }), _jsxs("span", { className: "ml-auto flex items-center gap-2", children: [isOpen && (_jsx(SimpleIconButton, { onClick: (event) => {
1253
1253
  event.stopPropagation();
1254
1254
  void handleCopy(p.provider, p.prompt);
1255
- }, icon: justCopied ? (_jsx(CheckIcon, { className: "h-3.5 w-3.5", strokeWidth: 1.5 })) : (_jsx(CopyIcon, { className: "h-3.5 w-3.5", strokeWidth: 1.5 })), label: justCopied ? "Copied" : "Copy prompt" })), _jsx(ChevronDownIcon, { className: `h-3.5 w-3.5 text-neutral-grey-100 transition-transform ${isOpen ? "rotate-180" : ""}` })] })] }), isOpen && (_jsx("div", { style: { paddingLeft: "2.5rem" }, className: "pr-3 md:pr-4 pb-3", children: _jsx("pre", { className: "max-h-64 overflow-y-auto whitespace-pre-wrap break-words rounded border border-border-default/50 bg-white p-2 font-mono text-[12px] text-neutral-grey-100", children: p.prompt }) }))] }, p.provider));
1255
+ }, icon: justCopied ? (_jsx(CheckIcon, { className: "h-3.5 w-3.5", strokeWidth: 1 })) : (_jsx(CopyIcon, { className: "h-3.5 w-3.5", strokeWidth: 1 })), label: justCopied ? "Copied" : "Copy prompt" })), _jsx(ChevronDownIcon, { className: `h-3.5 w-3.5 text-neutral-grey-100 transition-transform ${isOpen ? "rotate-180" : ""}` })] })] }), isOpen && (_jsx("div", { style: { paddingLeft: "2.5rem" }, className: "pr-3 md:pr-4 pb-3", children: _jsx("pre", { className: "max-h-64 overflow-y-auto whitespace-pre-wrap break-words rounded border border-border-default/50 bg-white p-2 font-mono text-[12px] text-neutral-grey-100", children: p.prompt }) }))] }, p.provider));
1256
1256
  }) }));
1257
1257
  }
1258
1258
  function BatchItemList({ batchId, batchProvider, jobs, isLoading, expandedItems, languages, currentLanguage, itemFilter, itemIncludeSubitems, statusFilter, batchIsTerminal, batchStartedAtUtc, abortingJobIds, retryingKeys, isMobile = false, onToggleItem, onOpenItem, onAbortJob, onRetryJobs, }) {
@@ -1427,8 +1427,8 @@ function BatchItemList({ batchId, batchProvider, jobs, isLoading, expandedItems,
1427
1427
  if (itemErrorJobs.length === 0)
1428
1428
  return;
1429
1429
  void onRetryJobs(batchId, batchProvider, itemErrorJobs, itemRetryKey);
1430
- }, icon: _jsx(RetryIcon, { className: `h-3.5 w-3.5 ${isRetryingItem ? "animate-spin" : ""}`, strokeWidth: 1.5 }), 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.75, "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
1430
+ }, 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
1432
1432
  ? { overflowWrap: "anywhere" }
1433
1433
  : 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
1434
  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: () => {
@@ -1525,7 +1525,7 @@ function LanguageJobChip({ job, language, batchStartedAtUtc, onOpen, isAborting
1525
1525
  const emptyFieldText = statistics && statistics.emptyFieldCount > 0
1526
1526
  ? `${formatCount(statistics.emptyFieldCount)} empty`
1527
1527
  : null;
1528
- 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.75, "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
1528
+ 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
1529
  ? "Approximate — measured from batch start"
1530
1530
  : 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
1531
  (jobError || jobAborted ? (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parhelia/localization",
3
- "version": "0.3.12763",
3
+ "version": "0.3.12767",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"