@parhelia/localization 0.1.12570 → 0.1.12585

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 (28) hide show
  1. package/dist/LocalizeItemDialog.d.ts.map +1 -1
  2. package/dist/LocalizeItemDialog.js +13 -17
  3. package/dist/api/discovery.d.ts +1 -4
  4. package/dist/api/discovery.d.ts.map +1 -1
  5. package/dist/api/discovery.js +3 -4
  6. package/dist/hooks/useTranslationWizard.d.ts.map +1 -1
  7. package/dist/hooks/useTranslationWizard.js +3 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +13 -28
  10. package/dist/services/translationService.d.ts +48 -7
  11. package/dist/services/translationService.d.ts.map +1 -1
  12. package/dist/services/translationService.js +3 -0
  13. package/dist/settings/TranslationServicesPanel.d.ts.map +1 -1
  14. package/dist/settings/TranslationServicesPanel.js +111 -42
  15. package/dist/setup/LocalizationSetupStep.d.ts.map +1 -1
  16. package/dist/setup/LocalizationSetupStep.js +8 -7
  17. package/dist/steps/ServiceLanguageSelectionStep.d.ts.map +1 -1
  18. package/dist/steps/ServiceLanguageSelectionStep.js +18 -1
  19. package/dist/steps/SubitemDiscoveryStep.d.ts.map +1 -1
  20. package/dist/steps/SubitemDiscoveryStep.js +95 -181
  21. package/dist/translation-center/BatchTranslationView.d.ts +1 -1
  22. package/dist/translation-center/BatchTranslationView.d.ts.map +1 -1
  23. package/dist/translation-center/BatchTranslationView.js +356 -98
  24. package/dist/translation-center/RecentTranslations.d.ts.map +1 -1
  25. package/dist/translation-center/RecentTranslations.js +20 -13
  26. package/dist/translation-center/TranslationManagement.d.ts.map +1 -1
  27. package/dist/translation-center/TranslationManagement.js +2 -4
  28. package/package.json +10 -11
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useEffect, useState, useRef, useMemo, useCallback } from "react";
3
3
  import { Button, PerfectTree } from "@parhelia/core";
4
4
  import { convertFullItemToStub, convertStubToFullItem } from "@parhelia/core";
5
- import { discoverItemsTree, convertBackendTreeToTreeNodes, flattenPagesFromBackendTrees } from "../api/discovery";
5
+ import { discoverItemsTree, convertBackendTreeToTreeNodes, flattenSelectableItemsFromBackendTrees } from "../api/discovery";
6
6
  // We need to implement a basic Spinner component since it's not in core
7
7
  const Spinner = ({ ...props }) => (_jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-[#9650fb]", ...props }));
8
8
  export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData, editContext, onStepCompleted, setBeforeNextCallback, setFooterActions, requestClose }) {
@@ -15,7 +15,6 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
15
15
  const [userHasInteracted, setUserHasInteracted] = useState(false);
16
16
  const [discoveredCount, setDiscoveredCount] = useState(0);
17
17
  const [totalItemsCount, setTotalItemsCount] = useState(0);
18
- const [translatableItemsCount, setTranslatableItemsCount] = useState(0);
19
18
  const [treeInitialized, setTreeInitialized] = useState(false);
20
19
  const [expandedIds, setExpandedIds] = useState(new Set());
21
20
  // Refs for async safety
@@ -47,26 +46,19 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
47
46
  const nodes = buildTreeNodes(stubs);
48
47
  setTreeNodes(nodes);
49
48
  setExpandedIds(new Set(nodes.map(n => n.key)));
50
- // Count total items and translatable items in the tree
51
49
  const countItems = (nodeList) => {
52
50
  let total = 0;
53
- let translatable = 0;
54
51
  const walk = (nodeList) => {
55
52
  nodeList.forEach(node => {
56
53
  total++;
57
- if (node?.data?.isTranslatable === true) {
58
- translatable++;
59
- }
60
54
  if (node.children)
61
55
  walk(node.children);
62
56
  });
63
57
  };
64
58
  walk(nodeList);
65
- return { total, translatable };
59
+ return total;
66
60
  };
67
- const counts = countItems(nodes);
68
- setTotalItemsCount(counts.total);
69
- setTranslatableItemsCount(counts.translatable);
61
+ setTotalItemsCount(countItems(nodes));
70
62
  setDiscoveryComplete(true);
71
63
  setTreeInitialized(true);
72
64
  return;
@@ -87,11 +79,11 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
87
79
  }, editContext.sessionId ?? undefined);
88
80
  if (!isMountedRef.current)
89
81
  return;
90
- const pages = flattenPagesFromBackendTrees(resp.trees);
82
+ const items = flattenSelectableItemsFromBackendTrees(resp.trees);
91
83
  const language = editContext?.item?.language ??
92
84
  editContext?.currentItemDescriptor?.language ??
93
85
  "en";
94
- const stubs = pages.map(x => ({
86
+ const stubs = items.map(x => ({
95
87
  id: x.id,
96
88
  name: x.name,
97
89
  path: x.path,
@@ -114,26 +106,19 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
114
106
  const nodes = convertBackendTreeToTreeNodes(resp.trees);
115
107
  setTreeNodes(nodes);
116
108
  setExpandedIds(new Set(nodes.map(n => n.key)));
117
- // Count total items and translatable items in the tree
118
109
  const countItems = (nodeList) => {
119
110
  let total = 0;
120
- let translatable = 0;
121
111
  const walk = (nodeList) => {
122
112
  nodeList.forEach(node => {
123
113
  total++;
124
- if (node?.data?.isTranslatable === true) {
125
- translatable++;
126
- }
127
114
  if (node.children)
128
115
  walk(node.children);
129
116
  });
130
117
  };
131
118
  walk(nodeList);
132
- return { total, translatable };
119
+ return total;
133
120
  };
134
- const counts = countItems(nodes);
135
- setTotalItemsCount(counts.total);
136
- setTranslatableItemsCount(counts.translatable);
121
+ setTotalItemsCount(countItems(nodes));
137
122
  setDiscoveryComplete(true);
138
123
  setTreeInitialized(true);
139
124
  }
@@ -158,19 +143,19 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
158
143
  initialSelection = new Set(data.discoveredItems.map(item => item.descriptor.id));
159
144
  }
160
145
  else {
161
- // Default: select all translatable items in the tree
162
- const allTranslatableIds = new Set();
146
+ // Default: select all selectable items in the tree
147
+ const allSelectableIds = new Set();
163
148
  const walk = (nodes) => {
164
149
  nodes.forEach(node => {
165
- if (node?.data?.isTranslatable) {
166
- allTranslatableIds.add(node.key);
150
+ if (node?.data?.isFolder !== true) {
151
+ allSelectableIds.add(node.key);
167
152
  }
168
153
  if (node.children)
169
154
  walk(node.children);
170
155
  });
171
156
  };
172
157
  walk(treeNodes);
173
- initialSelection = allTranslatableIds;
158
+ initialSelection = allSelectableIds;
174
159
  }
175
160
  setSelectedItemIds(initialSelection);
176
161
  }, [isActive, discoveryComplete, treeNodes, data.discoveredItems, userHasInteracted]);
@@ -195,7 +180,7 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
195
180
  const buildNode = (item) => ({
196
181
  key: item.id,
197
182
  label: item.name || item.id,
198
- data: { id: item.id, name: item.name, path: item.path, hasChildren: item.hasChildren },
183
+ data: { id: item.id, name: item.name, path: item.path, isFolder: item.hasLayout !== true, hasChildren: item.hasChildren },
199
184
  children: (childrenMap.get(item.id) || []).map(buildNode)
200
185
  });
201
186
  const originalItemIds = new Set(data.items.map(item => item.descriptor.id));
@@ -205,8 +190,6 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
205
190
  // PerfectTree integrations
206
191
  const expandedKeys = useMemo(() => Array.from(expandedIds), [expandedIds]);
207
192
  const selectedKeys = useMemo(() => Array.from(selectedItemIds), [selectedItemIds]);
208
- // Memoize base item IDs for checkbox rendering
209
- const baseItemIdsForCheckbox = useMemo(() => new Set(data.items.map(item => item.descriptor.id)), [data.items]);
210
193
  const getDescendantIds = (nodeKey) => {
211
194
  const findNode = (nodes) => {
212
195
  for (const node of nodes) {
@@ -234,167 +217,98 @@ export function SubitemDiscoveryStep({ stepIndex, isActive = true, data, setData
234
217
  traverse(node.children);
235
218
  return descendants;
236
219
  };
237
- const getDescendantTranslatableIds = (nodeKey) => {
238
- const findNode = (nodes) => {
239
- for (const node of nodes) {
240
- if (node.key === nodeKey)
241
- return node;
242
- if (node.children) {
243
- const found = findNode(node.children);
244
- if (found)
245
- return found;
246
- }
247
- }
248
- return null;
249
- };
250
- const root = findNode(treeNodes);
251
- if (!root?.children)
252
- return [];
253
- const out = [];
254
- const walk = (children) => {
255
- children.forEach(child => {
256
- const isTranslatable = child?.data?.isTranslatable === true;
257
- if (isTranslatable)
258
- out.push(child.key);
259
- if (child.children)
260
- walk(child.children);
261
- });
262
- };
263
- walk(root.children);
264
- return out;
265
- };
266
220
  const handleCancel = () => {
267
221
  // Simplified cancel - just stop discovery
268
222
  inFlightRef.current = false;
269
223
  setIsDiscovering(false);
270
224
  setDiscoveryComplete(true);
271
225
  };
272
- return (_jsxs("div", { className: "flex flex-col gap-4 p-6 h-full", "data-testid": "subitem-discovery-step", children: [_jsxs("div", { className: "mb-2", children: [_jsx("h3", { className: "text-lg font-semibold text-[var(--color-dark)] mb-1", children: "Discover Subitems" }), _jsx("p", { className: "text-sm text-[var(--color-gray-2)]", children: "Scanning for subitems to include in translation..." })] }), _jsxs("div", { className: "border border-[var(--color-gray-3)] rounded-lg p-4 bg-background min-h-[120px] shadow-sm", "data-testid": "discovery-status-container", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [isDiscovering && _jsx(Spinner, { "data-testid": "discovery-spinner" }), _jsx("span", { className: "font-medium text-[var(--color-dark)]", "data-testid": "discovery-status-text", children: isDiscovering ? 'Discovering subitems...' :
226
+ return (_jsxs("div", { className: "flex min-h-0 flex-col gap-4 p-6", "data-testid": "subitem-discovery-step", children: [_jsxs("div", { className: "mb-2 shrink-0", children: [_jsx("h3", { className: "text-lg font-semibold text-[var(--color-dark)] mb-1", children: "Discover Subitems" }), _jsx("p", { className: "text-sm text-[var(--color-gray-2)]", children: "Scanning for subitems to include in translation..." })] }), _jsxs("div", { className: "flex w-full min-w-0 shrink-0 flex-col rounded-lg border border-[var(--color-gray-3)] bg-background p-4 shadow-sm", "data-testid": "discovery-status-container", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [isDiscovering && _jsx(Spinner, { "data-testid": "discovery-spinner" }), _jsx("span", { className: "font-medium text-[var(--color-dark)]", "data-testid": "discovery-status-text", children: isDiscovering ? 'Discovering subitems...' :
273
227
  discoveryComplete ? 'Discovery Complete' :
274
- 'Ready to discover' })] }), isDiscovering && (_jsx(Button, { size: "sm", variant: "outline", onClick: handleCancel, "data-testid": "discovery-cancel-button", children: "Cancel" }))] }), _jsx("div", { className: "text-sm text-[var(--color-gray-2)] mb-3", "data-testid": "discovery-summary", children: discoveredCount > 0 ? (_jsxs("p", { "data-testid": "discovery-total-count", children: [_jsxs("span", { className: "font-medium text-[#9650fb]", children: [totalItemsCount, " total items found"] }), totalItemsCount !== translatableItemsCount && (_jsxs(_Fragment, { children: [_jsx("br", {}), _jsxs("span", { className: "text-xs text-[var(--color-gray-2)]", children: ["Translatable items: ", translatableItemsCount, " | Non-translatable: ", totalItemsCount - translatableItemsCount] })] })), _jsx("br", {}), _jsxs("span", { className: "text-xs text-[var(--color-gray-2)]", children: ["Original items: ", data.items.length, " | Subitems discovered: ", Math.max(0, totalItemsCount - data.items.length)] }), isDiscovering && (_jsxs(_Fragment, { children: [_jsx("br", {}), _jsx("span", { className: "text-xs text-[var(--color-gray-2)] italic", children: "Item tree will appear when discovery completes" })] }))] })) : (_jsx("p", { className: "text-[var(--color-gray-2)]", children: "No items discovered yet." })) }), _jsx("div", { className: "mt-4 min-h-[400px]", children: !isDiscovering && discoveryComplete && treeInitialized && allDiscoveredItems.length > 0 && treeNodes.length > 0 ? (_jsx("div", { children: _jsxs("div", { className: "border-t border-[var(--color-gray-3)] pt-4", "data-testid": "item-selection-section", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsx("h3", { className: "text-lg font-semibold text-[var(--color-dark)]", children: "Select Items to Translate" }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx("span", { className: "text-sm text-[var(--color-gray-2)]", "data-testid": "selection-summary-header", children: selectedItemIds.size > 0 ? _jsxs(_Fragment, { children: [_jsx("span", { className: "font-medium text-[#9650fb]", children: selectedItemIds.size }), " selected"] }) : "No items selected" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => {
275
- if (!isActive)
276
- return;
277
- // Only select translatable items
278
- const translatableIds = new Set();
279
- const walk = (nodes) => {
280
- nodes.forEach(node => {
281
- if (node?.data?.isTranslatable === true) {
282
- translatableIds.add(node.key);
283
- }
284
- if (node.children)
285
- walk(node.children);
286
- });
287
- };
288
- walk(treeNodes);
289
- setUserHasInteracted(true);
290
- setSelectedItemIds(translatableIds);
291
- onStepCompleted(translatableIds.size > 0);
292
- }, "data-testid": "select-all-items-button", children: "Select All" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => {
228
+ 'Ready to discover' })] }), isDiscovering && (_jsx(Button, { size: "sm", variant: "outline", onClick: handleCancel, "data-testid": "discovery-cancel-button", children: "Cancel" }))] }), _jsx("div", { className: "text-sm text-[var(--color-gray-2)] mb-3", "data-testid": "discovery-summary", children: discoveredCount > 0 ? (_jsxs("p", { "data-testid": "discovery-total-count", children: [_jsxs("span", { className: "font-medium text-[#9650fb]", children: [totalItemsCount, " total items found"] }), _jsx("br", {}), _jsxs("span", { className: "text-xs text-[var(--color-gray-2)]", children: ["Original items: ", data.items.length, " | Subitems discovered: ", Math.max(0, totalItemsCount - data.items.length)] }), isDiscovering && (_jsxs(_Fragment, { children: [_jsx("br", {}), _jsx("span", { className: "text-xs text-[var(--color-gray-2)] italic", children: "Item tree will appear when discovery completes" })] }))] })) : (_jsx("p", { className: "text-[var(--color-gray-2)]", children: "No items discovered yet." })) }), _jsx("div", { className: "mt-4 flex flex-col", children: !isDiscovering && discoveryComplete && treeInitialized && allDiscoveredItems.length > 0 && treeNodes.length > 0 ? (_jsxs("div", { className: "flex w-full min-w-0 flex-col", "data-testid": "item-selection-section", children: [_jsxs("div", { className: "mb-3 flex flex-col gap-2 border-t border-[var(--color-gray-3)] pt-4", children: [_jsx("h3", { className: "text-lg font-semibold text-[var(--color-dark)]", children: "Select Items to Translate" }), _jsx("span", { className: "text-sm text-[var(--color-gray-2)]", "data-testid": "selection-summary-header", children: selectedItemIds.size > 0 ? _jsxs(_Fragment, { children: [_jsx("span", { className: "font-medium text-[#9650fb]", children: selectedItemIds.size }), " selected"] }) : "No items selected" }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Button, { size: "sm", variant: "outline", onClick: () => {
229
+ if (!isActive)
230
+ return;
231
+ const allIds = new Set();
232
+ const walk = (nodes) => {
233
+ nodes.forEach(node => {
234
+ allIds.add(node.key);
235
+ if (node.children)
236
+ walk(node.children);
237
+ });
238
+ };
239
+ walk(treeNodes);
240
+ setUserHasInteracted(true);
241
+ setSelectedItemIds(allIds);
242
+ onStepCompleted(allIds.size > 0);
243
+ }, "data-testid": "select-all-items-button", children: "Select All" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => {
244
+ if (!isActive)
245
+ return;
246
+ setUserHasInteracted(true);
247
+ setSelectedItemIds(new Set());
248
+ onStepCompleted(false);
249
+ }, "data-testid": "select-none-items-button", children: "Select None" })] })] }), _jsx("div", { className: "text-xs text-[var(--color-gray-2)] mb-3", "data-testid": "selection-summary", children: _jsx("span", { children: "Tip: Hold Shift and click a checkbox to toggle all descendants." }) }), treeNodes.length > 0 && (_jsx("div", { className: "h-80 w-full min-w-0 shrink-0 overflow-auto rounded-lg border border-[var(--color-gray-3)] bg-[var(--color-gray-5)]", "data-testid": "item-tree-view", children: _jsx(PerfectTree, { nodes: treeNodes, expandedKeys: expandedKeys, selectedKeys: selectedKeys, onToggleExpand: (key) => {
250
+ setExpandedIds(prev => {
251
+ const next = new Set(prev);
252
+ if (next.has(key))
253
+ next.delete(key);
254
+ else
255
+ next.add(key);
256
+ return next;
257
+ });
258
+ }, onSelect: (key, event) => {
259
+ if (!isActive)
260
+ return; // Don't handle selection when inactive
261
+ setUserHasInteracted(true);
262
+ const targetNode = key;
263
+ const shift = event?.shiftKey === true;
264
+ const next = new Set(selectedItemIds);
265
+ const findNode = (nodes) => {
266
+ for (const n of nodes) {
267
+ if (n.key === targetNode)
268
+ return n;
269
+ if (n.children) {
270
+ const f = findNode(n.children);
271
+ if (f)
272
+ return f;
273
+ }
274
+ }
275
+ return null;
276
+ };
277
+ const n = findNode(treeNodes);
278
+ if (!n)
279
+ return;
280
+ const ids = shift ? [key, ...getDescendantIds(key)] : [key];
281
+ if (!next.has(key))
282
+ ids.forEach((id) => next.add(id));
283
+ else
284
+ ids.forEach((id) => next.delete(id));
285
+ setSelectedItemIds(next);
286
+ // Update completion when user changes selection
287
+ onStepCompleted(next.size > 0);
288
+ }, renderNode: (node) => {
289
+ const isChecked = selectedItemIds.has(node.key);
290
+ const icon = node?.data?.icon;
291
+ return (_jsxs("div", { className: "flex items-center gap-2", children: [icon && (_jsx("img", { src: icon, alt: "", className: "w-4 h-4" })), _jsx("input", { type: "checkbox", checked: isChecked, "data-testid": `tree-item-checkbox-${node.key}`, onMouseDown: (e) => {
292
+ shiftToggleRef.current = e.shiftKey;
293
+ }, onChange: (e) => {
293
294
  if (!isActive)
294
295
  return;
295
296
  setUserHasInteracted(true);
296
- setSelectedItemIds(new Set());
297
- onStepCompleted(false);
298
- }, "data-testid": "select-none-items-button", children: "Select None" })] })] }), _jsx("div", { className: "text-xs text-[var(--color-gray-2)] mb-3", "data-testid": "selection-summary", children: _jsx("span", { children: "Tip: Hold Shift and click a checkbox to toggle all descendants." }) }), treeNodes.length > 0 && (_jsx("div", { className: "border border-[var(--color-gray-3)] rounded-lg h-80 overflow-auto bg-[var(--color-gray-5)]", "data-testid": "item-tree-view", children: _jsx(PerfectTree, { nodes: treeNodes, expandedKeys: expandedKeys, selectedKeys: selectedKeys, onToggleExpand: (key) => {
299
- setExpandedIds(prev => {
300
- const next = new Set(prev);
301
- if (next.has(key))
302
- next.delete(key);
303
- else
304
- next.add(key);
305
- return next;
306
- });
307
- }, onSelect: (key, event) => {
308
- if (!isActive)
309
- return; // Don't handle selection when inactive
310
- setUserHasInteracted(true);
311
- const targetNode = key;
312
- const shift = event?.shiftKey === true;
313
- const next = new Set(selectedItemIds);
314
- // Only select translatable items
315
- const findNode = (nodes) => {
316
- for (const n of nodes) {
317
- if (n.key === targetNode)
318
- return n;
319
- if (n.children) {
320
- const f = findNode(n.children);
321
- if (f)
322
- return f;
323
- }
324
- }
325
- return null;
326
- };
327
- const n = findNode(treeNodes);
328
- const isTranslatable = n?.data?.isTranslatable === true;
329
- if (isTranslatable) {
330
- const ids = shift ? [key, ...getDescendantIds(key)] : [key];
331
- if (!next.has(key))
332
- ids.forEach((id) => next.add(id));
333
- else
334
- ids.forEach((id) => next.delete(id));
335
- }
336
- else {
337
- // Folder row click toggles all descendant translatable items
338
- const translatableIds = getDescendantTranslatableIds(key);
339
- const allSelected = translatableIds.length > 0 && translatableIds.every((id) => next.has(id));
340
- if (allSelected)
341
- translatableIds.forEach((id) => next.delete(id));
342
- else
343
- translatableIds.forEach((id) => next.add(id));
344
- }
345
- setSelectedItemIds(next);
346
- // Update completion when user changes selection
347
- onStepCompleted(next.size > 0);
348
- }, renderNode: (node) => {
349
- const isTranslatable = node?.data?.isTranslatable === true;
350
- const translatableIds = !isTranslatable ? getDescendantTranslatableIds(node.key) : [];
351
- const allSelected = !isTranslatable ? (translatableIds.length > 0 && translatableIds.every((id) => selectedItemIds.has(id))) : false;
352
- const someSelected = !isTranslatable ? (translatableIds.some((id) => selectedItemIds.has(id)) && !allSelected) : false;
353
- // Simple checkbox logic: if it's translatable, check direct selection; otherwise check descendant translatable items
354
- // Base items are treated like any other selected item - if selected, show checked
355
- const isChecked = isTranslatable ? selectedItemIds.has(node.key) : allSelected;
356
- const icon = node?.data?.icon;
357
- return (_jsxs("div", { className: `flex items-center gap-2 ${!isTranslatable ? 'opacity-70' : ''}`, children: [icon && (_jsx("img", { src: icon, alt: "", className: `w-4 h-4 ${!isTranslatable ? 'opacity-50' : ''}` })), _jsx("input", { type: "checkbox", checked: isChecked, disabled: !isTranslatable, "data-testid": `tree-item-checkbox-${node.key}`, ref: (el) => { if (el)
358
- el.indeterminate = someSelected; }, onMouseDown: (e) => {
359
- if (!isTranslatable)
360
- return; // Don't handle mouse down for untranslatable items
361
- shiftToggleRef.current = e.shiftKey;
362
- }, onChange: (e) => {
363
- if (!isActive || !isTranslatable)
364
- return; // Don't handle changes when inactive or untranslatable
365
- setUserHasInteracted(true);
366
- const next = new Set(selectedItemIds);
367
- if (isTranslatable) {
368
- const withDesc = shiftToggleRef.current && (node.children?.length ?? 0) > 0;
369
- const ids = withDesc ? [node.key, ...getDescendantIds(node.key)] : [node.key];
370
- if (e.currentTarget.checked)
371
- ids.forEach((id) => next.add(id));
372
- else
373
- ids.forEach((id) => next.delete(id));
374
- }
375
- else {
376
- const ids = getDescendantTranslatableIds(node.key);
377
- const allSel = ids.length > 0 && ids.every((id) => next.has(id));
378
- if (e.currentTarget.checked && !allSel)
379
- ids.forEach((id) => next.add(id));
380
- else if (!e.currentTarget.checked && allSel)
381
- ids.forEach((id) => next.delete(id));
382
- else {
383
- // Toggle based on current
384
- if (allSel)
385
- ids.forEach((id) => next.delete(id));
386
- else
387
- ids.forEach((id) => next.add(id));
388
- }
389
- }
390
- setSelectedItemIds(next);
391
- shiftToggleRef.current = false;
392
- // Update completion when user changes selection
393
- onStepCompleted(next.size > 0);
394
- } }), _jsx("span", { className: `${!isTranslatable ? 'opacity-70 italic' : ''}`, children: node.label })] }));
395
- } }) }))] }) })) : isDiscovering ? (
297
+ const next = new Set(selectedItemIds);
298
+ const withDesc = shiftToggleRef.current && (node.children?.length ?? 0) > 0;
299
+ const ids = withDesc ? [node.key, ...getDescendantIds(node.key)] : [node.key];
300
+ if (e.currentTarget.checked)
301
+ ids.forEach((id) => next.add(id));
302
+ else
303
+ ids.forEach((id) => next.delete(id));
304
+ setSelectedItemIds(next);
305
+ shiftToggleRef.current = false;
306
+ // Update completion when user changes selection
307
+ onStepCompleted(next.size > 0);
308
+ } }), _jsx("span", { children: node.label })] }));
309
+ } }) }))] })) : isDiscovering ? (
396
310
  // Loading skeleton for discovery results
397
- _jsxs("div", { children: [_jsx("div", { className: "p-3 bg-[#f6eeff] border border-[#9650fb]/20 rounded-lg mb-4", children: _jsx("div", { className: "h-4 bg-[#9650fb]/20 rounded w-64 animate-pulse" }) }), _jsxs("div", { className: "border-t border-[var(--color-gray-3)] pt-4", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsx("div", { className: "h-6 bg-[var(--color-gray-3)] rounded w-48 animate-pulse" }), _jsxs("div", { className: "flex gap-2", children: [_jsx("div", { className: "h-8 bg-[var(--color-gray-3)] rounded w-20 animate-pulse" }), _jsx("div", { className: "h-8 bg-[var(--color-gray-3)] rounded w-20 animate-pulse" })] })] }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-64 mb-3 animate-pulse" }), _jsx("div", { className: "border border-[var(--color-gray-3)] rounded-lg h-80 overflow-auto bg-[var(--color-gray-5)]", children: _jsx("div", { className: "p-3 space-y-2", children: [...Array(8)].map((_, i) => (_jsxs("div", { className: "flex items-center gap-3 animate-pulse", children: [_jsx("div", { className: "h-4 w-4 bg-[var(--color-gray-3)] rounded" }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-48" })] }, i))) }) })] })] })) : (
311
+ _jsxs("div", { className: "flex w-full min-w-0 flex-col", children: [_jsx("div", { className: "p-3 bg-[#f6eeff] border border-[#9650fb]/20 rounded-lg mb-4", children: _jsx("div", { className: "h-4 bg-[#9650fb]/20 rounded w-64 animate-pulse" }) }), _jsxs("div", { className: "border-t border-[var(--color-gray-3)] pt-4", children: [_jsxs("div", { className: "mb-3 flex flex-col gap-2", children: [_jsx("div", { className: "h-6 bg-[var(--color-gray-3)] rounded w-48 animate-pulse" }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-40 animate-pulse" }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx("div", { className: "h-8 bg-[var(--color-gray-3)] rounded w-20 animate-pulse" }), _jsx("div", { className: "h-8 bg-[var(--color-gray-3)] rounded w-20 animate-pulse" })] })] }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-64 mb-3 animate-pulse" }), _jsx("div", { className: "border border-[var(--color-gray-3)] rounded-lg h-80 shrink-0 overflow-auto bg-[var(--color-gray-5)]", children: _jsx("div", { className: "p-3 space-y-2", children: [...Array(8)].map((_, i) => (_jsxs("div", { className: "flex items-center gap-3 animate-pulse", children: [_jsx("div", { className: "h-4 w-4 bg-[var(--color-gray-3)] rounded" }), _jsx("div", { className: "h-4 bg-[var(--color-gray-3)] rounded w-48" })] }, i))) }) })] })] })) : (
398
312
  // Empty state
399
- _jsx("div", { className: "flex items-center justify-center h-80 border border-[var(--color-gray-3)] rounded-lg bg-[var(--color-gray-5)]", children: _jsxs("div", { className: "text-center text-[var(--color-gray-2)]", children: [_jsx("p", { className: "font-medium text-[var(--color-gray-1)]", children: "Ready to discover subitems" }), _jsx("p", { className: "text-sm mt-1", children: "Discovery will start automatically" })] }) })) })] })] }));
313
+ _jsx("div", { className: "flex h-80 shrink-0 items-center justify-center overflow-auto rounded-lg border border-[var(--color-gray-3)] bg-[var(--color-gray-5)]", children: _jsxs("div", { className: "text-center text-[var(--color-gray-2)]", children: [_jsx("p", { className: "font-medium text-[var(--color-gray-1)]", children: "Ready to discover subitems" }), _jsx("p", { className: "text-sm mt-1", children: "Discovery will start automatically" })] }) })) })] })] }));
400
314
  }
@@ -3,6 +3,6 @@ interface BatchTranslationViewProps {
3
3
  batchId: string;
4
4
  onBack?: () => void;
5
5
  }
6
- export declare function BatchTranslationView({ batchId, onBack }: BatchTranslationViewProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function BatchTranslationView({ batchId, onBack, }: BatchTranslationViewProps): import("react/jsx-runtime").JSX.Element;
7
7
  export {};
8
8
  //# sourceMappingURL=BatchTranslationView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BatchTranslationView.d.ts","sourceRoot":"","sources":["../../src/translation-center/BatchTranslationView.tsx"],"names":[],"mappings":"AAyBA,OAAO,qCAAqC,CAAC;AAsB7C,UAAU,yBAAyB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAiCD,wBAAgB,oBAAoB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,yBAAyB,2CAy8BlF"}
1
+ {"version":3,"file":"BatchTranslationView.d.ts","sourceRoot":"","sources":["../../src/translation-center/BatchTranslationView.tsx"],"names":[],"mappings":"AA4CA,OAAO,qCAAqC,CAAC;AA4C7C,UAAU,yBAAyB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAwED,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,GACP,EAAE,yBAAyB,2CAmoD3B"}