@parhelia/localization 0.1.12903 → 0.1.12905

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/LocalizeItemCommand.d.ts +1 -7
  2. package/dist/LocalizeItemCommand.d.ts.map +1 -1
  3. package/dist/LocalizeItemCommand.js +18 -31
  4. package/dist/LocalizeItemDialog.d.ts.map +1 -1
  5. package/dist/LocalizeItemDialog.js +35 -97
  6. package/dist/LocalizeItemUtils.d.ts +2 -1
  7. package/dist/LocalizeItemUtils.d.ts.map +1 -1
  8. package/dist/LocalizeItemUtils.js +36 -78
  9. package/dist/api/discovery.d.ts +0 -25
  10. package/dist/api/discovery.d.ts.map +1 -1
  11. package/dist/api/discovery.js +2 -106
  12. package/dist/constants.d.ts +15 -0
  13. package/dist/constants.d.ts.map +1 -0
  14. package/dist/constants.js +21 -0
  15. package/dist/hooks/useTranslationWizard.d.ts.map +1 -1
  16. package/dist/hooks/useTranslationWizard.js +3 -3
  17. package/dist/index.d.ts +11 -10
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +32 -36
  20. package/dist/services/translationService.d.ts +10 -41
  21. package/dist/services/translationService.d.ts.map +1 -1
  22. package/dist/services/translationService.js +6 -48
  23. package/dist/settings/TranslationServicesPanel.d.ts.map +1 -1
  24. package/dist/settings/TranslationServicesPanel.js +36 -21
  25. package/dist/setup/LocalizationSetupStep.d.ts.map +1 -1
  26. package/dist/setup/LocalizationSetupStep.js +18 -29
  27. package/dist/sidebar/TranslationSidebar.d.ts.map +1 -1
  28. package/dist/sidebar/TranslationSidebar.js +10 -20
  29. package/dist/steps/MetadataInputStep.d.ts +4 -0
  30. package/dist/steps/MetadataInputStep.d.ts.map +1 -0
  31. package/dist/steps/MetadataInputStep.js +41 -0
  32. package/dist/steps/PromptCustomizationStep.d.ts +1 -1
  33. package/dist/steps/PromptCustomizationStep.d.ts.map +1 -1
  34. package/dist/steps/PromptCustomizationStep.js +56 -159
  35. package/dist/steps/ServiceLanguageSelectionStep.d.ts +1 -6
  36. package/dist/steps/ServiceLanguageSelectionStep.d.ts.map +1 -1
  37. package/dist/steps/ServiceLanguageSelectionStep.js +165 -92
  38. package/dist/steps/SubitemDiscoveryStep.d.ts +3 -0
  39. package/dist/steps/SubitemDiscoveryStep.d.ts.map +1 -0
  40. package/dist/steps/SubitemDiscoveryStep.js +313 -0
  41. package/dist/steps/index.d.ts +5 -0
  42. package/dist/steps/index.d.ts.map +1 -0
  43. package/dist/steps/index.js +4 -0
  44. package/dist/steps/types.d.ts +1 -17
  45. package/dist/steps/types.d.ts.map +1 -1
  46. package/dist/translation-center/BatchTranslationView.d.ts +8 -0
  47. package/dist/translation-center/BatchTranslationView.d.ts.map +1 -0
  48. package/dist/translation-center/BatchTranslationView.js +870 -0
  49. package/dist/translation-center/RecentTranslations.d.ts +2 -0
  50. package/dist/translation-center/RecentTranslations.d.ts.map +1 -0
  51. package/dist/translation-center/RecentTranslations.js +309 -0
  52. package/dist/translation-center/TranslationManagement.d.ts.map +1 -1
  53. package/dist/translation-center/TranslationManagement.js +15 -25
  54. package/dist/types.d.ts +0 -1
  55. package/dist/types.d.ts.map +1 -1
  56. package/dist/utils/createVersions.d.ts +14 -0
  57. package/dist/utils/createVersions.d.ts.map +1 -0
  58. package/dist/utils/createVersions.js +26 -0
  59. package/package.json +1 -1
  60. package/dist/steps/ItemSelectionStep.d.ts +0 -3
  61. package/dist/steps/ItemSelectionStep.d.ts.map +0 -1
  62. package/dist/steps/ItemSelectionStep.js +0 -24
  63. package/dist/steps/ItemSelectionTree.d.ts +0 -13
  64. package/dist/steps/ItemSelectionTree.d.ts.map +0 -1
  65. package/dist/steps/ItemSelectionTree.js +0 -327
  66. package/dist/steps/WizardStepShell.d.ts +0 -17
  67. package/dist/steps/WizardStepShell.d.ts.map +0 -1
  68. package/dist/steps/WizardStepShell.js +0 -11
  69. package/dist/translation-center/TranslationBatches.d.ts +0 -2
  70. package/dist/translation-center/TranslationBatches.d.ts.map +0 -1
  71. package/dist/translation-center/TranslationBatches.js +0 -1180
  72. package/dist/translation-center/TranslationsTitlebar.d.ts +0 -6
  73. package/dist/translation-center/TranslationsTitlebar.d.ts.map +0 -1
  74. package/dist/translation-center/TranslationsTitlebar.js +0 -25
  75. package/dist/translationEvents.d.ts +0 -6
  76. package/dist/translationEvents.d.ts.map +0 -1
  77. package/dist/translationEvents.js +0 -4
@@ -1,14 +1,8 @@
1
- import { Command, CommandContext, CommandData, EditContextType, FullItem } from "@parhelia/core";
2
- import { TranslationDialogResult } from "./steps/types";
1
+ import { Command, CommandContext, CommandData, FullItem } from "@parhelia/core";
3
2
  export type LocalizeItemCommandData = CommandData & {
4
3
  items: FullItem[];
5
4
  };
6
5
  export type LocalizeItemCommandContext = CommandContext<LocalizeItemCommandData>;
7
6
  export type LocalizeItemCommand = Command<LocalizeItemCommandData>;
8
- export declare function openLocalizeItemDialog({ editContext, openDialog, items, }: {
9
- editContext: EditContextType;
10
- openDialog?: EditContextType["openDialog"];
11
- items: FullItem[];
12
- }): Promise<TranslationDialogResult | null>;
13
7
  export declare const localizeItemCommand: LocalizeItemCommand;
14
8
  //# sourceMappingURL=LocalizeItemCommand.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LocalizeItemCommand.d.ts","sourceRoot":"","sources":["../src/LocalizeItemCommand.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EACP,cAAc,EACd,WAAW,EACX,eAAe,EACf,QAAQ,EACT,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAEL,uBAAuB,EACxB,MAAM,eAAe,CAAC;AAQvB,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG;IAClD,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GACpC,cAAc,CAAC,uBAAuB,CAAC,CAAC;AAC1C,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAEnE,wBAAsB,sBAAsB,CAAC,EAC3C,WAAW,EACX,UAAmC,EACnC,KAAK,GACN,EAAE;IACD,WAAW,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IAC3C,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,2CAiCA;AAED,eAAO,MAAM,mBAAmB,EAAE,mBA6BjC,CAAC"}
1
+ {"version":3,"file":"LocalizeItemCommand.d.ts","sourceRoot":"","sources":["../src/LocalizeItemCommand.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAUhF,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG;IAClD,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,cAAc,CAAC,uBAAuB,CAAC,CAAC;AACjF,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAEnE,eAAO,MAAM,mBAAmB,EAAE,mBAgDjC,CAAC"}
@@ -2,35 +2,9 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React from "react";
3
3
  import { Globe as LucideGlobe } from "lucide-react";
4
4
  import { LocalizeItemDialog } from "./LocalizeItemDialog";
5
- import { dispatchTranslationBatchStarted } from "./translationEvents";
6
5
  // Icon wrapper to avoid React 19 JSX type issues with forwardRef components.
7
6
  // Use React.createElement so we don't call the forwardRef objects as functions.
8
7
  const GlobeIcon = (props) => React.createElement(LucideGlobe, props);
9
- export async function openLocalizeItemDialog({ editContext, openDialog = editContext.openDialog, items, }) {
10
- const result = await openDialog(LocalizeItemDialog, {
11
- items,
12
- editContext,
13
- });
14
- // If translation was started (result contains batchId), navigate to the batch view
15
- if (result?.batchId) {
16
- const translationManagementEnabled = editContext?.configuration?.localization
17
- ?.translationManagement !== false;
18
- if (translationManagementEnabled) {
19
- // Synchronous URL update to avoid race with workspace URL sync
20
- const params = new URLSearchParams(window.location.search);
21
- params.set("workspace", "translation-management");
22
- params.set("batchId", result.batchId);
23
- const newUrl = `${window.location.pathname}?${params.toString()}`;
24
- window.history.pushState(null, "", newUrl);
25
- // Now switch the workspace; URL already contains batchId
26
- editContext.switchWorkspace("translation-management");
27
- window.setTimeout(() => {
28
- dispatchTranslationBatchStarted(result.batchId);
29
- }, 0);
30
- }
31
- }
32
- return result;
33
- }
34
8
  export const localizeItemCommand = {
35
9
  id: "localizeItem",
36
10
  label: "Translate",
@@ -40,8 +14,7 @@ export const localizeItemCommand = {
40
14
  return true;
41
15
  }
42
16
  // Check if multi-item is disabled and multiple items are selected
43
- const multiItemEnabled = context.editContext?.configuration?.localization?.multiItem !==
44
- false;
17
+ const multiItemEnabled = context.editContext?.configuration?.localization?.multiItem !== false;
45
18
  if (!multiItemEnabled && context.data.items.length > 1) {
46
19
  return true; // Disable command when multiple items selected in single-item mode
47
20
  }
@@ -52,10 +25,24 @@ export const localizeItemCommand = {
52
25
  if (!items || !items?.length) {
53
26
  return;
54
27
  }
55
- return openLocalizeItemDialog({
28
+ const result = await context.openDialog(LocalizeItemDialog, {
29
+ items: items,
56
30
  editContext: context.editContext,
57
- openDialog: context.openDialog,
58
- items,
59
31
  });
32
+ // If translation was started (result contains batchId), navigate to the batch view
33
+ if (result?.batchId) {
34
+ const translationManagementEnabled = context.editContext?.configuration?.localization?.translationManagement !== false;
35
+ if (translationManagementEnabled) {
36
+ // Synchronous URL update to avoid race with workspace URL sync
37
+ const params = new URLSearchParams(window.location.search);
38
+ params.set("workspace", "translation-management");
39
+ params.set("batchId", result.batchId);
40
+ const newUrl = `${window.location.pathname}?${params.toString()}`;
41
+ window.history.pushState(null, "", newUrl);
42
+ // Now switch the workspace; URL already contains batchId
43
+ context.editContext.switchWorkspace("translation-management");
44
+ }
45
+ }
46
+ return result;
60
47
  },
61
48
  };
@@ -1 +1 @@
1
- {"version":3,"file":"LocalizeItemDialog.d.ts","sourceRoot":"","sources":["../src/LocalizeItemDialog.tsx"],"names":[],"mappings":"AA8BA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAqCvB,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,uBAAuB,GAAG,WAAW,CAAC,uBAAuB,CAAC,2CAugBtE"}
1
+ {"version":3,"file":"LocalizeItemDialog.d.ts","sourceRoot":"","sources":["../src/LocalizeItemDialog.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAuBvB,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,uBAAuB,GAAG,WAAW,CAAC,uBAAuB,CAAC,2CAybtE"}
@@ -1,18 +1,15 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Dialog, DialogContent, StyledDialogTitle, Button, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@parhelia/core";
3
- import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
4
- import { AlertTriangle as LucideAlertTriangle, ArrowRight as LucideArrowRight, Globe as LucideGlobe, } from "lucide-react";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, Button, cn, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@parhelia/core";
3
+ import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ import { AlertTriangle as LucideAlertTriangle } from "lucide-react";
5
5
  import { useTranslationWizard } from "./hooks/useTranslationWizard";
6
- import { performDefaultTranslation, } from "./LocalizeItemUtils";
6
+ import { performDefaultTranslation, generateBatchId } from "./LocalizeItemUtils";
7
7
  const AlertTriangleIcon = LucideAlertTriangle;
8
- const GlobeIcon = LucideGlobe;
9
- const ArrowRightIcon = LucideArrowRight;
10
8
  // Threshold for warning about large batch translations
11
9
  const LARGE_BATCH_WARNING_THRESHOLD = 100;
12
- const getNextButtonLabel = (step) => step?.nextButtonLabel || step?.name || "Next";
13
10
  // Note: DialogButtons is an internal component that might need to be added to core exports
14
11
  // For now, we'll implement it inline
15
- const DialogButtons = ({ children, ...props }) => (_jsx("div", { className: "mt-auto flex shrink-0 items-center gap-3 border-t border-border-default bg-white px-6 py-4", ...props, children: children }));
12
+ const DialogButtons = ({ children, ...props }) => (_jsx("div", { className: "mt-auto flex shrink-0 items-center gap-3 border-t border-gray-3 bg-background px-6 py-4", ...props, children: children }));
16
13
  export function LocalizeItemDialog(props) {
17
14
  const editContext = props.editContext;
18
15
  const configuration = editContext.configuration.translationWizard;
@@ -36,12 +33,7 @@ export function LocalizeItemDialog(props) {
36
33
  // Provide stable callbacks to steps to avoid update loops
37
34
  const lastActionsSigRef = useRef("");
38
35
  const provideFooterActions = useCallback((actions) => {
39
- const normalized = (actions || []).map((a) => ({
40
- key: a.key,
41
- label: a.label,
42
- disabled: !!a.disabled,
43
- signature: a.signature || "",
44
- }));
36
+ const normalized = (actions || []).map(a => ({ key: a.key, label: a.label, disabled: !!a.disabled, signature: a.signature || "" }));
45
37
  const signature = JSON.stringify(normalized);
46
38
  if (signature === lastActionsSigRef.current)
47
39
  return;
@@ -53,6 +45,7 @@ export function LocalizeItemDialog(props) {
53
45
  }, [props.onClose]);
54
46
  // Memoize activeSteps to prevent unnecessary recalculations and new object references
55
47
  // This prevents infinite loops when wizardData changes but skip conditions don't
48
+ // The skip condition for subitem-discovery step checks includeSubitems
56
49
  // The skip condition for prompt-customization step checks serviceCustomData and translationProvider
57
50
  const activeSteps = useMemo(() => {
58
51
  const steps = configuration.steps.filter((step) => !step.skipCondition || !step.skipCondition(wizardData));
@@ -61,13 +54,13 @@ export function LocalizeItemDialog(props) {
61
54
  configuration.steps,
62
55
  wizardData.includeSubitems,
63
56
  wizardData.serviceCustomData,
64
- wizardData.translationProvider,
57
+ wizardData.translationProvider
65
58
  ]); // Depend on what affects skip conditions
66
59
  const currentStep = activeSteps[currentStepIndex];
67
60
  // Refs for stable callbacks - updated during render to avoid dependency issues
68
61
  const currentStepIdRef = useRef(currentStep?.id);
69
62
  const currentStepIndexRef = useRef(currentStepIndex);
70
- const lastSetWizardDataRef = useRef("");
63
+ const lastSetWizardDataRef = useRef('');
71
64
  // Track step changes for logging
72
65
  if (currentStepIdRef.current !== currentStep?.id) {
73
66
  currentStepIdRef.current = currentStep?.id;
@@ -91,7 +84,7 @@ export function LocalizeItemDialog(props) {
91
84
  const isLastStep = currentStepIndex === activeSteps.length - 1;
92
85
  const canProceed = stepCompleted >= currentStepIndex;
93
86
  const handleNext = async () => {
94
- if (beforeNextCallback && typeof beforeNextCallback === "function") {
87
+ if (beforeNextCallback && typeof beforeNextCallback === 'function') {
95
88
  const canProceed = await beforeNextCallback();
96
89
  if (!canProceed)
97
90
  return;
@@ -113,40 +106,13 @@ export function LocalizeItemDialog(props) {
113
106
  switchStep(currentStepIndex - 1);
114
107
  }
115
108
  };
116
- // Calculate translation counts for the Start Translation button and
117
- // the large-batch warning. Sums each selected item plus its streamed
118
- // subitem count (when includeSubitems is on). `isStreaming` is true
119
- // while any selected-and-flagged item is still being counted, so the
120
- // UI can append a "+" to indicate the total is not yet final.
109
+ // Calculate translation counts for large batch warning
121
110
  const calculateTranslationCounts = useCallback((data) => {
111
+ const itemsToTranslate = data.includeSubitems ? data.discoveredItems : data.items;
112
+ const itemCount = itemsToTranslate.length;
122
113
  const languageCount = data.targetLanguages.length;
123
- const subitemCounts = data.subitemCounts ?? {};
124
- let itemCount = 0;
125
- let isStreaming = false;
126
- if (data.selectionTreeItems && data.selectionTreeItems.length > 0) {
127
- for (const entry of data.selectionTreeItems) {
128
- itemCount += 1;
129
- if (!entry.includeSubitems)
130
- continue;
131
- const c = subitemCounts[entry.descriptor.id];
132
- if (c === undefined || c === "loading") {
133
- isStreaming = true;
134
- }
135
- else if (c !== "error") {
136
- itemCount += c.count;
137
- if (!c.complete)
138
- isStreaming = true;
139
- }
140
- }
141
- }
142
- else {
143
- const baseItems = data.discoveredItems && data.discoveredItems.length > 0
144
- ? data.discoveredItems
145
- : data.items;
146
- itemCount = baseItems.length;
147
- }
148
114
  const totalTranslations = itemCount * languageCount;
149
- return { itemCount, languageCount, totalTranslations, isStreaming };
115
+ return { itemCount, languageCount, totalTranslations };
150
116
  }, []);
151
117
  const executeTranslation = useCallback(async () => {
152
118
  setIsSubmitting(true);
@@ -158,36 +124,33 @@ export function LocalizeItemDialog(props) {
158
124
  targetLanguages: currentWizardData.targetLanguages,
159
125
  includeSubitems: currentWizardData.includeSubitems,
160
126
  discoveredItems: currentWizardData.discoveredItems,
161
- selectionTreeItems: currentWizardData.selectionTreeItems,
162
127
  };
163
128
  try {
164
- const translationResult = await performDefaultTranslation(currentWizardData, editContext);
129
+ const batchId = generateBatchId();
130
+ const translationResult = await performDefaultTranslation(currentWizardData, editContext, batchId);
165
131
  // Include batchId in result for navigation to translation management
166
- const resultWithBatch = {
167
- ...result,
168
- batchId: translationResult.batchId,
169
- };
132
+ const resultWithBatch = { ...result, batchId };
170
133
  // Close dialog and let parent component handle navigation to translation management
171
134
  props.onClose?.(resultWithBatch);
172
135
  }
173
136
  catch (error) {
174
137
  // Handle specific error types
175
- if (error.name === "NoTranslationsNeededError") {
138
+ if (error.name === 'NoTranslationsNeededError') {
176
139
  // Show user-friendly message via toast and close dialog
177
- editContext.showToast?.("No translations needed. All selected target languages match the source languages of the items.");
140
+ editContext.showToast?.('No translations needed. All selected target languages match the source languages of the items.');
178
141
  props.onClose?.(result);
179
142
  return;
180
143
  }
181
144
  // For other errors, show toast and stay in dialog
182
- console.error("Translation failed:", error);
183
- const errorMessage = error.message || "Translation request failed. Please try again.";
145
+ console.error('Translation failed:', error);
146
+ const errorMessage = error.message || 'Translation request failed. Please try again.';
184
147
  editContext.showToast?.(errorMessage);
185
148
  // Don't close the dialog - let user try again or cancel
186
149
  }
187
150
  }
188
151
  catch (error) {
189
- console.error("Unexpected error in translation:", error);
190
- editContext.showToast?.("An unexpected error occurred. Please try again.");
152
+ console.error('Unexpected error in translation:', error);
153
+ editContext.showToast?.('An unexpected error occurred. Please try again.');
191
154
  // Don't close the dialog on error
192
155
  }
193
156
  finally {
@@ -218,40 +181,18 @@ export function LocalizeItemDialog(props) {
218
181
  : null;
219
182
  // Serialize metadata for comparison (supports both string and object formats)
220
183
  const metadataKey = newData.metadata
221
- ? typeof newData.metadata === "string"
184
+ ? (typeof newData.metadata === 'string'
222
185
  ? newData.metadata
223
- : JSON.stringify(newData.metadata)
186
+ : JSON.stringify(newData.metadata))
224
187
  : null;
225
188
  const dataKey = JSON.stringify({
226
189
  translationProvider: newData.translationProvider,
227
190
  targetLanguages: [...newData.targetLanguages].sort(),
228
191
  includeSubitems: newData.includeSubitems,
229
- discoveredItemIds: (newData.discoveredItems || [])
230
- .map((item) => item?.descriptor?.id || item?.id)
231
- .filter(Boolean)
232
- .sort(),
192
+ discoveredItemsCount: newData.discoveredItems?.length || 0,
233
193
  itemsCount: newData.items?.length || 0,
234
194
  serviceCustomData: serviceCustomDataKey,
235
195
  metadata: metadataKey,
236
- // batchName must be part of the key — otherwise the PromptCustomizationStep's
237
- // setData({...prev, batchName}) call sees an "unchanged" key here and the
238
- // update is silently dropped, so the user-entered name never reaches submit.
239
- batchName: newData.batchName ?? "",
240
- // subitemCounts must be part of the key — otherwise live count
241
- // updates from the subitem-count stream are silently dropped and
242
- // the Start Translation button can't reflect them.
243
- subitemCounts: newData.subitemCounts
244
- ? Object.keys(newData.subitemCounts)
245
- .sort()
246
- .map((id) => {
247
- const c = newData.subitemCounts[id];
248
- if (c === undefined)
249
- return [id, "missing"];
250
- if (c === "loading" || c === "error")
251
- return [id, c];
252
- return [id, c.count, c.complete];
253
- })
254
- : null,
255
196
  });
256
197
  // Skip if data hasn't actually changed
257
198
  if (lastSetWizardDataRef.current === dataKey) {
@@ -282,21 +223,18 @@ export function LocalizeItemDialog(props) {
282
223
  }, children: [_jsxs(DialogContent, { className: "flex h-[85vh] max-h-[900px] min-h-0 w-[90vw] max-w-5xl flex-col overflow-hidden md:min-h-[700px]", "data-testid": "translation-wizard-dialog", onPointerDownOutside: (e) => e.preventDefault(), onEscapeKeyDown: (e) => e.preventDefault(), "aria-describedby": "translation-wizard-description", style: {
283
224
  width: "min(90vw, 1280px)",
284
225
  height: "min(85vh, 900px)",
285
- }, children: [_jsx(StyledDialogTitle, { icon: _jsx(GlobeIcon, { strokeWidth: 1.5 }), title: `Translate · ${currentStep?.name ?? ""}`, subtitle: currentStep?.description ||
286
- "Configure and start translation for your content" }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description ||
287
- "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) => {
226
+ }, children: [_jsx(DialogHeader, { className: "border-b border-gray-3 bg-background px-6 py-4 pr-14", children: _jsx(DialogTitle, { "data-testid": "translation-wizard-title", children: "Translate" }) }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description || "Configure and start translation for your content." }), _jsx("div", { className: "border-b border-gray-3 bg-background px-6 py-3 pr-14", children: _jsx("div", { "data-testid": "translation-wizard-step-navigation", children: _jsx("div", { className: "flex min-w-0 flex-nowrap items-center overflow-x-auto", children: activeSteps.map((step, index) => {
227
+ const isCurrent = currentStepIndex === index;
228
+ const isCompleted = currentStepIndex > index;
229
+ return (_jsxs(Fragment, { children: [_jsxs("div", { className: "flex shrink-0 items-center gap-2", "data-testid": `step-indicator-${step.id}`, "aria-current": isCurrent ? "step" : undefined, children: [_jsx("div", { className: cn("flex h-7 w-7 shrink-0 items-center justify-center rounded-full border text-sm font-medium transition-colors", isCurrent && "border-theme-secondary bg-theme-secondary-light text-theme-secondary", isCompleted && "border-theme-secondary bg-theme-secondary text-white", !isCurrent && !isCompleted && "border-gray-3 bg-background text-gray-2"), "data-testid": `step-indicator-circle-${step.id}`, "aria-label": step.name, children: isCompleted ? "✓" : index + 1 }), _jsx("span", { className: cn("whitespace-nowrap text-sm transition-colors", isCurrent && "font-medium text-theme-secondary", isCompleted && "text-theme-secondary", !isCurrent && !isCompleted && "text-gray-2"), "data-testid": `step-indicator-label-${step.id}`, children: step.name })] }), index < activeSteps.length - 1 && (_jsx("div", { className: cn("mx-3 h-px w-8 shrink-0 transition-colors", currentStepIndex > index ? "bg-theme-secondary" : "bg-gray-3") }))] }, step.id));
230
+ }) }) }) }), _jsxs("div", { className: "flex flex-1 flex-col min-h-0", children: [_jsx("div", { className: "flex-1 overflow-y-auto min-h-0 bg-[var(--color-gray-5)]", "data-testid": "translation-wizard-step-content", children: _jsx("div", { className: "h-full relative", children: activeSteps.map((step, index) => {
288
231
  const StepComponent = step.component;
289
232
  const isActive = index === currentStepIndex;
290
233
  if (!StepComponent)
291
234
  return null;
292
- return (_jsx("div", { className: "h-full", style: { display: isActive ? "block" : "none" }, "aria-hidden": !isActive, "data-testid": `step-content-${step.id}`, children: _jsx(StepComponent, { stepIndex: index, isActive: isActive, data: wizardData, setData: setWizardDataStable, editContext: editContext, onStepCompleted: (completed) => handleStepCompleted(completed, index), setBeforeNextCallback: isActive ? setBeforeNextCallbackStable : undefined, setFooterActions: isActive ? provideFooterActions : undefined, requestClose: isActive ? requestCloseCb : undefined }) }, step.id));
293
- }) }) }), _jsxs(DialogButtons, { "data-testid": "translation-wizard-dialog-buttons", children: [_jsx(Button, { onClick: () => props.onClose?.(null), variant: "outline", size: "lg", className: "w-auto min-w-24 flex-none", "data-testid": "translation-wizard-cancel-button", children: "Cancel" }), _jsxs("div", { className: "ml-auto flex min-w-0 flex-wrap items-center justify-end gap-3", children: [currentStepIndex > 0 && (_jsx(Button, { onClick: handlePrevious, variant: "outline", size: "lg", className: "w-auto min-w-32 flex-none", "data-testid": "translation-wizard-previous-button", children: "Previous" })), footerActions.map((a) => (_jsx(Button, { onClick: a.onClick, disabled: !!a.disabled, variant: "default", size: "lg", className: "w-auto min-w-32 flex-none", "data-testid": `translation-wizard-footer-action-${a.key}`, children: a.label }, a.key))), _jsx(Button, { onClick: handleNext, disabled: !canProceed || isSubmitting, variant: "default", size: "lg", className: "w-auto min-w-40 flex-none gap-2", "data-testid": "translation-wizard-next-button", children: isSubmitting ? ("Starting...") : isLastStep ? ((() => {
294
- const { totalTranslations, isStreaming } = calculateTranslationCounts(wizardData);
295
- if (totalTranslations <= 0)
296
- return "Start Translation";
297
- return `Start Translation (${totalTranslations}${isStreaming ? "+" : ""})`;
298
- })()) : (_jsxs(_Fragment, { children: [getNextButtonLabel(activeSteps[currentStepIndex + 1]), _jsx(ArrowRightIcon, { className: "h-4 w-4", strokeWidth: 2 })] })) })] })] })] })] }), _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: (() => {
235
+ return (_jsx("div", { className: "h-full", style: { display: isActive ? 'block' : 'none' }, "aria-hidden": !isActive, "data-testid": `step-content-${step.id}`, children: _jsx(StepComponent, { stepIndex: index, isActive: isActive, data: wizardData, setData: setWizardDataStable, editContext: editContext, onStepCompleted: (completed) => handleStepCompleted(completed, index), setBeforeNextCallback: isActive ? setBeforeNextCallbackStable : undefined, setFooterActions: isActive ? provideFooterActions : undefined, requestClose: isActive ? requestCloseCb : undefined }) }, step.id));
236
+ }) }) }), _jsxs(DialogButtons, { "data-testid": "translation-wizard-dialog-buttons", children: [_jsx(Button, { onClick: () => props.onClose?.(null), variant: "outline", size: "default", className: "w-auto min-w-24 flex-none", "data-testid": "translation-wizard-cancel-button", children: "Cancel" }), _jsxs("div", { className: "ml-auto flex min-w-0 flex-wrap items-center justify-end gap-3", children: [currentStepIndex > 0 && (_jsx(Button, { onClick: handlePrevious, variant: "outline", size: "default", className: "w-auto min-w-32 flex-none", "data-testid": "translation-wizard-previous-button", children: "Previous" })), footerActions.map((a) => (_jsx(Button, { onClick: a.onClick, disabled: !!a.disabled, variant: "default", size: "default", className: "w-auto min-w-32 flex-none", "data-testid": `translation-wizard-footer-action-${a.key}`, children: a.label }, a.key))), _jsx(Button, { onClick: handleNext, disabled: !canProceed || isSubmitting, variant: "default", size: "default", className: "w-auto min-w-40 flex-none", "data-testid": "translation-wizard-next-button", children: isSubmitting ? "Starting..." : isLastStep ? "Start Translation" : "Next" })] })] })] })] }), _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-amber-500" }), "Large Translation Batch"] }), _jsx(AlertDialogDescription, { children: (() => {
299
237
  const { itemCount, languageCount, totalTranslations } = calculateTranslationCounts(wizardData);
300
- 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?"] }));
238
+ 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?"] }));
301
239
  })() })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isSubmitting, children: "Cancel" }), _jsx(AlertDialogAction, { onClick: handleLargeBatchConfirm, disabled: isSubmitting, children: isSubmitting ? "Starting..." : "Continue" })] })] }) })] }));
302
240
  }
@@ -2,6 +2,7 @@ import { TranslationStatus } from "./types";
2
2
  import { FullItem } from "@parhelia/core";
3
3
  import { TranslationWizardData } from "./steps/types";
4
4
  import { EditContextType } from "@parhelia/core";
5
+ export declare function generateBatchId(): string;
5
6
  export type StartedTranslation = {
6
7
  itemId: string;
7
8
  targetLanguage: string;
@@ -11,6 +12,6 @@ export type TranslationResult = {
11
12
  started: StartedTranslation[];
12
13
  batchId?: string;
13
14
  };
14
- export declare function performDefaultTranslation(wizardData: TranslationWizardData, editContext: EditContextType): Promise<TranslationResult>;
15
+ export declare function performDefaultTranslation(wizardData: TranslationWizardData, editContext: EditContextType, predefinedBatchId?: string): Promise<TranslationResult>;
15
16
  export declare const defaultTranslateAll: (languageCodes: string[], translationStatus: TranslationStatus[], sessionId: string, item: FullItem, translationProvider: string) => Promise<TranslationResult>;
16
17
  //# sourceMappingURL=LocalizeItemUtils.d.ts.map
@@ -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,CA0I5B;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":"AACA,OAAO,EAAE,iBAAiB,EAAC,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAIjD,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5F,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,EAC5B,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,iBAAiB,CAAC,CAyH5B;AAGD,eAAO,MAAM,mBAAmB,GAAU,eAAe,MAAM,EAAE,EAAE,mBAAmB,iBAAiB,EAAE,EAAE,WAAW,MAAM,EAAE,MAAM,QAAQ,EAAE,qBAAqB,MAAM,+BA0BxK,CAAC"}
@@ -1,43 +1,15 @@
1
- import { requestBatchTranslation, } from "./services/translationService";
2
- import { discoverItemsTree, flattenSelectableItemsFromBackendTrees, } from "./api/discovery";
3
- /**
4
- * Resolve the final list of item IDs to translate, expanding subitems for
5
- * any selection-tree item whose includeSubitems flag is true.
6
- *
7
- * Selection priority:
8
- * 1. `selectionTreeItems` (new model) - per-item flags drive expansion
9
- * 2. `discoveredItems` (legacy fallback) - used as-is
10
- * 3. `items` (initial wizard input) - used as-is
11
- */
12
- async function resolveItemIdsToTranslate(wizardData, sessionId) {
13
- if (wizardData.selectionTreeItems &&
14
- wizardData.selectionTreeItems.length > 0) {
15
- const directIds = [];
16
- const rootsToExpand = [];
17
- for (const entry of wizardData.selectionTreeItems) {
18
- if (entry.includeSubitems) {
19
- rootsToExpand.push(entry.descriptor.id);
20
- }
21
- else {
22
- directIds.push(entry.descriptor.id);
23
- }
24
- }
25
- const expandedIds = [];
26
- if (rootsToExpand.length > 0) {
27
- const language = wizardData.selectionTreeItems[0]?.descriptor.language;
28
- const tree = await discoverItemsTree({ rootItemIds: rootsToExpand, language }, sessionId);
29
- expandedIds.push(...flattenSelectableItemsFromBackendTrees(tree.trees).map((n) => n.id));
30
- }
31
- return Array.from(new Set([...directIds, ...expandedIds]));
32
- }
33
- const fallback = wizardData.discoveredItems && wizardData.discoveredItems.length > 0
34
- ? wizardData.discoveredItems
35
- : wizardData.items;
36
- return fallback.map((item) => item.descriptor.id);
1
+ import { requestBatchTranslation } from "./services/translationService";
2
+ // Shared utility for generating unique batch IDs
3
+ export function generateBatchId() {
4
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}-${performance.now().toString(36).substring(2, 8)}`;
37
5
  }
38
6
  // Unified translation function that handles both single and batch translations
39
7
  // Now always uses batch logic for traceability in recentTranslation view
40
- export async function performDefaultTranslation(wizardData, editContext) {
8
+ export async function performDefaultTranslation(wizardData, editContext, predefinedBatchId) {
9
+ const batchId = predefinedBatchId || generateBatchId();
10
+ const itemsToTranslate = wizardData.includeSubitems
11
+ ? wizardData.discoveredItems
12
+ : wizardData.items;
41
13
  // Build language mappings (source -> target) from the wizard data
42
14
  // The source language is consistent for each target language across all items
43
15
  const languageMappings = [];
@@ -52,19 +24,19 @@ export async function performDefaultTranslation(wizardData, editContext) {
52
24
  targetLanguage: language,
53
25
  });
54
26
  }
55
- // Resolve item IDs, expanding subitems per-item-flag where applicable.
56
- const itemIds = await resolveItemIdsToTranslate(wizardData, editContext.sessionId);
27
+ // Extract item IDs
28
+ const itemIds = itemsToTranslate.map(item => item.descriptor.id);
57
29
  // Validate that we have translation requests to process
58
30
  if (languageMappings.length === 0 || itemIds.length === 0) {
59
- const error = new Error("No translations needed. All selected target languages match the source languages of the items.");
60
- error.name = "NoTranslationsNeededError";
31
+ const error = new Error('No translations needed. All selected target languages match the source languages of the items.');
32
+ error.name = 'NoTranslationsNeededError';
61
33
  throw error;
62
34
  }
63
35
  // Prepare batch metadata including service-specific custom data
64
36
  // Start with wizardData.metadata as an object
65
37
  let metadataObj = {};
66
38
  if (wizardData.metadata) {
67
- if (typeof wizardData.metadata === "string") {
39
+ if (typeof wizardData.metadata === 'string') {
68
40
  try {
69
41
  metadataObj = JSON.parse(wizardData.metadata);
70
42
  }
@@ -72,27 +44,19 @@ export async function performDefaultTranslation(wizardData, editContext) {
72
44
  // Invalid JSON, ignore
73
45
  }
74
46
  }
75
- else if (typeof wizardData.metadata === "object") {
47
+ else if (typeof wizardData.metadata === 'object') {
76
48
  metadataObj = { ...wizardData.metadata };
77
49
  }
78
50
  }
79
- // Embed the user/AI-provided batch name so it surfaces in Recent
80
- // Translations and the batch detail view.
81
- const trimmedName = wizardData.batchName?.trim();
82
- if (trimmedName) {
83
- metadataObj.name = trimmedName;
84
- }
85
- // Merge service-specific custom data (e.g., custom prompts for AI providers)
51
+ // Merge service-specific custom data (e.g., custom prompts for OpenAI)
86
52
  if (wizardData.serviceCustomData && wizardData.serviceCustomData.size > 0) {
87
53
  const serviceData = wizardData.serviceCustomData.get(wizardData.translationProvider);
88
54
  if (serviceData && serviceData.enableCustomPrompt) {
89
- const provider = wizardData.translationProviders.find((p) => p.name === wizardData.translationProvider);
55
+ const provider = wizardData.translationProviders.find(p => p.name === wizardData.translationProvider);
90
56
  const defaultPrompt = provider?.defaultPrompt && provider.defaultPrompt.trim()
91
57
  ? provider.defaultPrompt
92
58
  : null;
93
- const customizationType = serviceData.promptCustomizationType === "replace"
94
- ? "replace"
95
- : "extend";
59
+ const customizationType = serviceData.promptCustomizationType === "replace" ? "replace" : "extend";
96
60
  const rawCustomPrompt = (serviceData.customPrompt || "").trim();
97
61
  let finalCustomPrompt = "";
98
62
  if (rawCustomPrompt) {
@@ -106,37 +70,34 @@ export async function performDefaultTranslation(wizardData, editContext) {
106
70
  metadataObj.serviceCustomData = {
107
71
  [wizardData.translationProvider]: {
108
72
  enableCustomPrompt: serviceData.enableCustomPrompt,
109
- customPrompt: finalCustomPrompt,
110
- },
73
+ customPrompt: finalCustomPrompt
74
+ }
111
75
  };
112
76
  }
113
77
  }
114
78
  // Serialize metadata to JSON string (or undefined if empty)
115
- const batchMetadata = Object.keys(metadataObj).length > 0
116
- ? JSON.stringify(metadataObj)
117
- : undefined;
79
+ const batchMetadata = Object.keys(metadataObj).length > 0 ? JSON.stringify(metadataObj) : undefined;
118
80
  const batchResult = await requestBatchTranslation({
119
81
  sessionId: editContext.sessionId,
82
+ batchId,
120
83
  provider: wizardData.translationProvider,
121
84
  batchMetadata,
122
85
  languageMappings,
123
86
  itemIds,
124
87
  });
125
88
  if (batchResult.type === "error") {
126
- console.error("Translation request failed:", batchResult);
89
+ console.error('Translation request failed:', batchResult);
127
90
  // Throw an error so the caller can handle it (e.g., show a toast)
128
- const errorMessage = batchResult.details ||
129
- batchResult.summary ||
130
- "Translation request failed";
91
+ const errorMessage = batchResult.details || batchResult.summary || 'Translation request failed';
131
92
  const error = new Error(errorMessage);
132
- error.name = "TranslationRequestError";
93
+ error.name = 'TranslationRequestError';
133
94
  throw error;
134
95
  }
135
96
  const batchResponse = batchResult.data;
136
97
  if (!batchResponse) {
137
- console.error("Batch response is undefined");
138
- const error = new Error("Server returned an empty response");
139
- error.name = "TranslationRequestError";
98
+ console.error('Batch response is undefined');
99
+ const error = new Error('Server returned an empty response');
100
+ error.name = 'TranslationRequestError';
140
101
  throw error;
141
102
  }
142
103
  const started = batchResponse.started?.map((result) => ({
@@ -145,9 +106,9 @@ export async function performDefaultTranslation(wizardData, editContext) {
145
106
  jobId: result.jobId,
146
107
  })) || [];
147
108
  if (batchResponse.skipped && batchResponse.skipped.length > 0) {
148
- console.warn("Some translations were skipped:", batchResponse.skipped);
109
+ console.warn('Some translations were skipped:', batchResponse.skipped);
149
110
  }
150
- return { started, batchId: batchResponse.id };
111
+ return { started, batchId };
151
112
  }
152
113
  // Legacy function for backward compatibility
153
114
  export const defaultTranslateAll = async (languageCodes, translationStatus, sessionId, item, translationProvider) => {
@@ -155,24 +116,21 @@ export const defaultTranslateAll = async (languageCodes, translationStatus, sess
155
116
  const wizardData = {
156
117
  items: [item],
157
118
  targetLanguages: languageCodes,
158
- languageData: new Map(languageCodes.map((lang) => {
159
- const status = translationStatus?.find((x) => x.targetLanguage === lang);
160
- return [
161
- lang,
162
- {
119
+ languageData: new Map(languageCodes.map(lang => {
120
+ const status = translationStatus?.find(x => x.targetLanguage === lang);
121
+ return [lang, {
163
122
  name: lang,
164
123
  languageCode: lang,
165
124
  items: [item.descriptor],
166
- translationStatus: status,
167
- },
168
- ];
125
+ translationStatus: status
126
+ }];
169
127
  })),
170
128
  translationProvider,
171
129
  includeSubitems: false,
172
130
  discoveredItems: [],
173
131
  itemMetadata: new Map(),
174
132
  metadata: null,
175
- translationProviders: [],
133
+ translationProviders: []
176
134
  };
177
135
  const editContext = { sessionId };
178
136
  const result = await performDefaultTranslation(wizardData, editContext);
@@ -1,8 +1,3 @@
1
- export declare function suggestBatchName(req: {
2
- itemIds: string[];
3
- targetLanguages: string[];
4
- includeSubitems?: boolean;
5
- }, sessionId?: string): Promise<string | null>;
6
1
  export type DiscoveredItem = {
7
2
  id: string;
8
3
  name: string;
@@ -36,24 +31,4 @@ export type DiscoverItemsTreeResponse = {
36
31
  export declare function discoverItemsTree(req: DiscoverItemsTreeRequest, sessionId?: string): Promise<DiscoverItemsTreeResponse>;
37
32
  export declare function convertBackendTreeToTreeNodes(trees: BackendTreeNode[]): TreeNode[];
38
33
  export declare function flattenSelectableItemsFromBackendTrees(trees: BackendTreeNode[]): DiscoveredItem[];
39
- export type SubitemCountUpdate = {
40
- count: number;
41
- complete: boolean;
42
- };
43
- /**
44
- * Streams the running subitem count for a given root item from the
45
- * backend. The endpoint returns newline-delimited JSON; each parsed line
46
- * triggers `onProgress` so the UI can show the count climbing. Filtered
47
- * server-side via IItemExportFilter + excluded templates.
48
- *
49
- * Pass an `AbortSignal` to cancel mid-stream (e.g. user toggles the
50
- * subitems flag off again).
51
- */
52
- export declare function streamSubitemCount(req: {
53
- itemId: string;
54
- language?: string;
55
- }, onProgress: (update: SubitemCountUpdate) => void, options?: {
56
- sessionId?: string;
57
- signal?: AbortSignal;
58
- }): Promise<number>;
59
34
  //# sourceMappingURL=discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/api/discovery.ts"],"names":[],"mappings":"AAEA,wBAAsB,gBAAgB,CACpC,GAAG,EAAE;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,EACD,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB,CAAC;AAIF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,wBAAwB,EAC7B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,yBAAyB,CAAC,CAYpC;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,eAAe,EAAE,GACvB,QAAQ,EAAE,CAgBZ;AAED,wBAAgB,sCAAsC,CACpD,KAAK,EAAE,eAAe,EAAE,GACvB,cAAc,EAAE,CAclB;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtE;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EAC1C,UAAU,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,EAChD,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACrD,OAAO,CAAC,MAAM,CAAC,CAsEjB"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/api/discovery.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAA;CAAE,CAAC;AAInG,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,wBAAwB,EAC7B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,yBAAyB,CAAC,CAWpC;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,QAAQ,EAAE,CAQlF;AAED,wBAAgB,sCAAsC,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,cAAc,EAAE,CAQjG"}