@workbench-kit/shell-react 0.0.2-prototype.0.2.32 → 0.0.2-prototype.0.2.34

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 (52) hide show
  1. package/README.md +32 -0
  2. package/package.json +9 -9
  3. package/src/commands/use-command-descriptors.ts +7 -3
  4. package/src/commands/use-extension-registry-command-descriptors.ts +23 -6
  5. package/src/devtools/use-workbench-devtools-snapshot.ts +39 -14
  6. package/src/devtools/workbench-devtools-snapshot.ts +32 -13
  7. package/src/editor/area.tsx +3 -2
  8. package/src/editor/state-storage.ts +31 -0
  9. package/src/editor/tab-context-menu.ts +8 -8
  10. package/src/editor/use-editor.ts +6 -6
  11. package/src/explorer/context-menu.ts +8 -4
  12. package/src/explorer/view.tsx +4 -3
  13. package/src/extensions/canonical-extension-descriptions.ts +58 -0
  14. package/src/extensions/context-menu.ts +9 -6
  15. package/src/extensions/extension-enablement-context.ts +15 -0
  16. package/src/extensions/extension-enablement-controller.ts +453 -0
  17. package/src/extensions/management-model.ts +111 -47
  18. package/src/extensions/theme-selection-protection.ts +98 -0
  19. package/src/extensions/uninstall-eligibility.ts +103 -0
  20. package/src/extensions/use-extension-management.ts +151 -67
  21. package/src/extensions/view.tsx +4 -0
  22. package/src/field-remap/chrome-labels.ts +87 -2
  23. package/src/field-remap/convert-palette.tsx +164 -18
  24. package/src/field-remap/demo.tsx +48 -3
  25. package/src/field-remap/detail-panel.tsx +6 -5
  26. package/src/field-remap/flow.tsx +341 -155
  27. package/src/field-remap/history.ts +99 -0
  28. package/src/field-remap/index.ts +9 -1
  29. package/src/field-remap/panel.tsx +388 -97
  30. package/src/field-remap/preview-controller.ts +122 -0
  31. package/src/field-remap/preview.tsx +171 -0
  32. package/src/field-remap/view.css +154 -2
  33. package/src/index.ts +16 -1
  34. package/src/management/keybinding-overrides-storage.ts +28 -0
  35. package/src/management/preference-settings-storage.ts +28 -0
  36. package/src/management/settings.tsx +2 -0
  37. package/src/management/use-command-management.ts +31 -26
  38. package/src/management/use-keybinding-management.ts +25 -12
  39. package/src/shell/focused-extension-services.ts +138 -0
  40. package/src/shell/host-shell.tsx +13 -10
  41. package/src/shell/persistence-diagnostic-context.ts +11 -0
  42. package/src/shell/provider.tsx +373 -69
  43. package/src/shell/settings.tsx +25 -16
  44. package/src/shell/shell.tsx +119 -78
  45. package/src/shell/view-host.tsx +23 -22
  46. package/src/storage/local-json-storage.ts +43 -29
  47. package/src/storage/persistence-diagnostics.ts +72 -0
  48. package/src/workbench/appearance-storage.ts +28 -0
  49. package/src/workbench/command-host.tsx +19 -22
  50. package/src/workbench/command-palette.ts +14 -13
  51. package/src/workbench/layout-storage.ts +52 -5
  52. package/src/workbench/use-persisted-appearance.ts +38 -12
@@ -1,22 +1,18 @@
1
- import { useCallback, useEffect, useMemo, useState } from 'react';
1
+ import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react';
2
2
  import {
3
3
  DEFAULT_EXTENSION_CATALOG_TRUST_POLICY,
4
4
  DEFAULT_EXTENSION_INSTALL_TRUST_STORAGE_KEY,
5
- DEFAULT_INSTALLED_EXTENSIONS_STORAGE_KEY,
6
5
  ExtensionInstallApprovalRequiredError,
7
6
  applyExtensionInstallPlanToRecords,
8
7
  assertExtensionCatalogUrlAllowed,
9
8
  loadExtensionInstallTrustRecords,
10
- loadInstalledExtensions,
11
9
  parseExtensionCatalog,
12
10
  recordExtensionInstallTrust,
13
- saveExtensionInstallTrustRecords,
14
- saveInstalledExtensions,
15
- toggleInstalledExtensionEnabled,
11
+ saveExtensionInstallTrustRecordsResult,
16
12
  type ExtensionCatalogEntry,
17
13
  type ExtensionCatalogTrustPolicy,
18
14
  type ExtensionInstallTrustRecord,
19
- type InstalledExtensionRecord,
15
+ type WorkbenchPersistenceDiagnosticHandler,
20
16
  } from '@workbench-kit/workbench-core';
21
17
  import type {
22
18
  ExtensionCatalogBrowseEntry,
@@ -30,61 +26,67 @@ import {
30
26
  createExtensionCatalogBrowseEntries,
31
27
  createExtensionInstallPlanningContext,
32
28
  createExtensionManagementEntries,
29
+ type ExtensionUninstallActionConstraint,
33
30
  } from './management-model.js';
34
31
  import { useWorkbench, type WorkbenchStorageAdapter } from '../shell/provider.js';
32
+ import { useExtensionEnablementController } from './extension-enablement-context.js';
33
+ import type {
34
+ ExtensionEnablementTransitionResult,
35
+ ExtensionUninstallActionResult,
36
+ } from './extension-enablement-controller.js';
37
+ import { useWorkbenchPersistenceDiagnosticHandler } from '../shell/persistence-diagnostic-context.js';
38
+ import {
39
+ reportPersistenceWriteResult,
40
+ usePersistenceDiagnosticHandlerRef,
41
+ } from '../storage/persistence-diagnostics.js';
35
42
 
36
43
  export interface UseExtensionManagementModelOptions {
37
44
  catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined;
38
45
  catalogUrl?: string | undefined;
39
- installedExtensionsStorage?: WorkbenchStorageAdapter | undefined;
40
- installedExtensionsStorageKey?: string | undefined;
41
46
  installTrustStorage?: WorkbenchStorageAdapter | undefined;
42
47
  installTrustStorageKey?: string | undefined;
48
+ onPersistenceDiagnostic?: WorkbenchPersistenceDiagnosticHandler | undefined;
43
49
  }
44
50
 
45
51
  export function useExtensionManagementModel({
46
52
  catalogTrustPolicy = DEFAULT_EXTENSION_CATALOG_TRUST_POLICY,
47
53
  catalogUrl = '/extension-catalog.json',
48
- installedExtensionsStorage,
49
- installedExtensionsStorageKey,
50
54
  installTrustStorage,
51
55
  installTrustStorageKey = DEFAULT_EXTENSION_INSTALL_TRUST_STORAGE_KEY,
56
+ onPersistenceDiagnostic,
52
57
  }: UseExtensionManagementModelOptions = {}) {
53
58
  const workbench = useWorkbench();
54
- const { availableExtensions, extensionRegistry } = workbench;
55
- const resolvedInstalledExtensionsStorage =
56
- installedExtensionsStorage ?? workbench.installedExtensionsStorage;
57
- const resolvedInstalledExtensionsStorageKey =
58
- installedExtensionsStorageKey ??
59
- workbench.installedExtensionsStorageKey ??
60
- DEFAULT_INSTALLED_EXTENSIONS_STORAGE_KEY;
61
- const resolvedInstallTrustStorage = installTrustStorage ?? resolvedInstalledExtensionsStorage;
59
+ const providerPersistenceDiagnostic = useWorkbenchPersistenceDiagnosticHandler();
60
+ const diagnosticHandlerRef = usePersistenceDiagnosticHandlerRef(
61
+ onPersistenceDiagnostic ?? providerPersistenceDiagnostic,
62
+ );
63
+ const extensionEnablement = useExtensionEnablementController();
64
+ const { availableExtensions, extensionCatalog } = workbench;
65
+ const resolvedInstallTrustStorage = installTrustStorage ?? workbench.installedExtensionsStorage;
66
+ const installedRecords = useSyncExternalStore(
67
+ extensionEnablement.subscribeInstalledRecords,
68
+ extensionEnablement.getInstalledRecordsSnapshot,
69
+ extensionEnablement.getInstalledRecordsSnapshot,
70
+ );
62
71
  const [catalogEntries, setCatalogEntries] = useState<readonly ExtensionCatalogEntry[]>([]);
63
72
  const [catalogLoading, setCatalogLoading] = useState(Boolean(catalogUrl));
64
73
  const [catalogError, setCatalogError] = useState<string | undefined>();
65
74
  const [pendingAction, setPendingAction] = useState<
66
75
  ExtensionManagementPendingAction | undefined
67
76
  >();
68
- const [installedRecords, setInstalledRecords] = useState<readonly InstalledExtensionRecord[]>(
69
- () =>
70
- loadInstalledExtensions(
71
- resolvedInstalledExtensionsStorageKey,
72
- resolvedInstalledExtensionsStorage,
73
- ),
74
- );
77
+ const [pendingUninstallEntry, setPendingUninstallEntry] = useState<
78
+ ExtensionManagementEntry | undefined
79
+ >();
80
+ const [uninstallActionConstraint, setUninstallActionConstraint] = useState<
81
+ ExtensionUninstallActionConstraint | undefined
82
+ >();
83
+ const [lastTransition, setLastTransition] = useState<
84
+ ExtensionEnablementTransitionResult | undefined
85
+ >();
75
86
  const [installTrustRecords, setInstallTrustRecords] = useState<
76
87
  readonly ExtensionInstallTrustRecord[]
77
88
  >(() => loadExtensionInstallTrustRecords(installTrustStorageKey, resolvedInstallTrustStorage));
78
89
 
79
- useEffect(() => {
80
- setInstalledRecords(
81
- loadInstalledExtensions(
82
- resolvedInstalledExtensionsStorageKey,
83
- resolvedInstalledExtensionsStorage,
84
- ),
85
- );
86
- }, [resolvedInstalledExtensionsStorage, resolvedInstalledExtensionsStorageKey]);
87
-
88
90
  useEffect(() => {
89
91
  setInstallTrustRecords(
90
92
  loadExtensionInstallTrustRecords(installTrustStorageKey, resolvedInstallTrustStorage),
@@ -138,28 +140,66 @@ export function useExtensionManagementModel({
138
140
  }, [catalogTrustPolicy, catalogUrl]);
139
141
 
140
142
  const installedEntries = useMemo<readonly ExtensionManagementEntry[]>(() => {
141
- return createExtensionManagementEntries({
143
+ const projectedEntries = createExtensionManagementEntries({
142
144
  availableExtensions,
143
- extensionRegistry,
145
+ extensionCatalog,
144
146
  installedRecords,
147
+ transition: lastTransition,
148
+ uninstallActionConstraint,
145
149
  });
146
- }, [availableExtensions, extensionRegistry, installedRecords]);
150
+ if (!pendingUninstallEntry) {
151
+ return projectedEntries;
152
+ }
153
+
154
+ return [
155
+ ...projectedEntries.filter((entry) => entry.id !== pendingUninstallEntry.id),
156
+ pendingUninstallEntry,
157
+ ].sort((left, right) => left.displayName.localeCompare(right.displayName));
158
+ }, [
159
+ availableExtensions,
160
+ extensionCatalog,
161
+ installedRecords,
162
+ lastTransition,
163
+ pendingUninstallEntry,
164
+ uninstallActionConstraint,
165
+ ]);
166
+
167
+ const handleTransition = useCallback(
168
+ (
169
+ result: ExtensionEnablementTransitionResult,
170
+ pendingKind: ExtensionManagementPendingAction['kind'],
171
+ ) => {
172
+ setLastTransition(result);
173
+ if (result.kind !== 'reloadRequired') {
174
+ setPendingAction(undefined);
175
+ return;
176
+ }
177
+
178
+ setPendingAction({ entryId: result.extensionId, kind: pendingKind });
179
+ if (typeof window !== 'undefined') {
180
+ window.requestAnimationFrame(() => {
181
+ window.location.reload();
182
+ });
183
+ }
184
+ },
185
+ [],
186
+ );
147
187
 
148
188
  const browseEntries = useMemo<readonly ExtensionCatalogBrowseEntry[]>(() => {
149
189
  return createExtensionCatalogBrowseEntries({
150
190
  availableExtensions,
151
191
  catalogEntries,
152
- extensionRegistry,
192
+ extensionCatalog,
153
193
  installedRecords,
154
194
  });
155
- }, [availableExtensions, catalogEntries, extensionRegistry, installedRecords]);
195
+ }, [availableExtensions, catalogEntries, extensionCatalog, installedRecords]);
156
196
 
157
197
  const installCatalogEntry = useCallback(
158
198
  (entry: ExtensionCatalogBrowseEntry, options?: ExtensionInstallOptions) => {
159
199
  const installContext = createExtensionInstallPlanningContext({
160
200
  availableExtensions,
161
201
  catalogEntries,
162
- extensionRegistry,
202
+ extensionCatalog,
163
203
  installedRecords,
164
204
  });
165
205
  const plan = createCatalogEntryInstallPlan(entry, installContext);
@@ -178,26 +218,15 @@ export function useExtensionManagementModel({
178
218
  installSources: installContext.installSources,
179
219
  plan,
180
220
  });
181
- saveInstalledExtensions(
182
- next,
183
- resolvedInstalledExtensionsStorageKey,
184
- resolvedInstalledExtensionsStorage,
185
- );
186
- setInstalledRecords(next);
187
- setPendingAction({ entryId: entry.id, kind: 'install' });
188
- if (typeof window !== 'undefined') {
189
- window.requestAnimationFrame(() => {
190
- window.location.reload();
191
- });
192
- }
221
+ handleTransition(extensionEnablement.commitInstalledRecords(next, entry.id), 'install');
193
222
  },
194
223
  [
195
224
  availableExtensions,
196
225
  catalogEntries,
197
- extensionRegistry,
226
+ extensionCatalog,
198
227
  installedRecords,
199
- resolvedInstalledExtensionsStorage,
200
- resolvedInstalledExtensionsStorageKey,
228
+ extensionEnablement,
229
+ handleTransition,
201
230
  ],
202
231
  );
203
232
 
@@ -207,31 +236,58 @@ export function useExtensionManagementModel({
207
236
  return;
208
237
  }
209
238
 
210
- const next = toggleInstalledExtensionEnabled(
211
- entry.id,
212
- enabled,
213
- resolvedInstalledExtensionsStorageKey,
214
- resolvedInstalledExtensionsStorage,
215
- );
216
- setInstalledRecords(next);
217
- setPendingAction({ entryId: entry.id, kind: 'toggle' });
239
+ handleTransition(extensionEnablement.toggleInstalledExtension(entry.id, enabled), 'toggle');
240
+ },
241
+ [extensionEnablement, handleTransition],
242
+ );
243
+
244
+ const uninstallInstalledEntry = useCallback(
245
+ (entry: ExtensionManagementEntry) => {
246
+ if (entry.source !== 'installed' || entry.id.startsWith('workbench-kit.builtin.')) {
247
+ return;
248
+ }
249
+
250
+ const result = extensionEnablement.uninstallInstalledExtension(entry.id);
251
+ if (result.kind === 'blocked' || result.kind === 'ineligibleTarget') {
252
+ setUninstallActionConstraint(toExtensionUninstallActionConstraint(result));
253
+ return;
254
+ }
255
+
256
+ setUninstallActionConstraint(undefined);
257
+ setLastTransition(result);
258
+ if (result.kind !== 'reloadRequired') {
259
+ setPendingUninstallEntry(undefined);
260
+ return;
261
+ }
262
+
263
+ setPendingUninstallEntry(entry);
218
264
  if (typeof window !== 'undefined') {
219
265
  window.requestAnimationFrame(() => {
220
266
  window.location.reload();
221
267
  });
222
268
  }
223
269
  },
224
- [resolvedInstalledExtensionsStorage, resolvedInstalledExtensionsStorageKey],
270
+ [extensionEnablement],
225
271
  );
226
272
 
227
273
  const rememberInstallTrust = useCallback(
228
274
  (entry: ExtensionCatalogBrowseEntry) => {
229
275
  const permissions = entry.installPlan?.permissions ?? [];
230
276
  const next = recordExtensionInstallTrust(entry.id, permissions, installTrustRecords);
231
- saveExtensionInstallTrustRecords(next, installTrustStorageKey, resolvedInstallTrustStorage);
232
277
  setInstallTrustRecords(next);
278
+ const persistence = saveExtensionInstallTrustRecordsResult(
279
+ next,
280
+ installTrustStorageKey,
281
+ resolvedInstallTrustStorage,
282
+ );
283
+ reportPersistenceWriteResult(persistence, diagnosticHandlerRef);
233
284
  },
234
- [installTrustRecords, installTrustStorageKey, resolvedInstallTrustStorage],
285
+ [
286
+ diagnosticHandlerRef,
287
+ installTrustRecords,
288
+ installTrustStorageKey,
289
+ resolvedInstallTrustStorage,
290
+ ],
235
291
  );
236
292
 
237
293
  return {
@@ -242,7 +298,35 @@ export function useExtensionManagementModel({
242
298
  installedEntries,
243
299
  installTrustRecords,
244
300
  pendingAction,
301
+ pendingUninstallEntryId: pendingUninstallEntry?.id,
245
302
  rememberInstallTrust,
246
303
  toggleInstalledEntry,
304
+ uninstallInstalledEntry,
305
+ };
306
+ }
307
+
308
+ function toExtensionUninstallActionConstraint(
309
+ result: Extract<
310
+ ExtensionUninstallActionResult,
311
+ { readonly kind: 'blocked' | 'ineligibleTarget' }
312
+ >,
313
+ ): ExtensionUninstallActionConstraint {
314
+ if (result.kind === 'blocked') {
315
+ return {
316
+ eligibility: {
317
+ dependentExtensionIds: result.dependentExtensionIds,
318
+ kind: result.kind,
319
+ unresolvedExtensionIds: result.unresolvedExtensionIds,
320
+ },
321
+ extensionId: result.extensionId,
322
+ };
323
+ }
324
+ return {
325
+ eligibility: {
326
+ diagnosticExtensionIds: result.diagnosticExtensionIds,
327
+ kind: result.kind,
328
+ reason: result.reason,
329
+ },
330
+ extensionId: result.extensionId,
247
331
  };
248
332
  }
@@ -32,8 +32,10 @@ export function BuiltinExtensionsView({
32
32
  installedEntries,
33
33
  installTrustRecords,
34
34
  pendingAction,
35
+ pendingUninstallEntryId,
35
36
  rememberInstallTrust,
36
37
  toggleInstalledEntry,
38
+ uninstallInstalledEntry,
37
39
  } = useExtensionManagementModel({ catalogTrustPolicy, catalogUrl });
38
40
 
39
41
  const isInstallTrusted = useCallback(
@@ -55,9 +57,11 @@ export function BuiltinExtensionsView({
55
57
  isInstallTrusted={isInstallTrusted}
56
58
  missingExtensionIds={missingExtensionIds}
57
59
  pendingAction={pendingAction}
60
+ pendingUninstallEntryId={pendingUninstallEntryId}
58
61
  onInstall={installCatalogEntry}
59
62
  onRememberInstallTrust={rememberInstallTrust}
60
63
  onToggleEnabled={toggleInstalledEntry}
64
+ onUninstall={uninstallInstalledEntry}
61
65
  />
62
66
  );
63
67
  }
@@ -18,31 +18,76 @@ export interface FieldRemapChromeLabels {
18
18
  readonly convertPaletteDescription: string;
19
19
  readonly convertPaletteAriaLabel: string;
20
20
  readonly convertsListAriaLabel: string;
21
+ /** Additive filter copy. Omitted legacy label objects use the English defaults. */
22
+ readonly convertFilterLabel?: string;
23
+ readonly convertFilterPlaceholder?: string;
24
+ readonly clearConvertFilter?: string;
25
+ readonly noMatchingConverts?: string;
21
26
  readonly placeConvert: string;
27
+ readonly addCombine: string;
28
+ readonly addSplit: string;
22
29
  readonly operatorsTitle: string;
23
30
  readonly operatorsDescription: string;
31
+ readonly addTransform: string;
32
+ readonly editItems: string;
33
+ readonly removeBinding: string;
24
34
  readonly showMinimap: string;
25
35
  readonly hideMinimap: string;
26
36
  readonly showHiddenFields: string;
27
37
  readonly hideHiddenFields: string;
38
+ readonly emptyDetailTitle: string;
39
+ readonly emptyDetailDescription: string;
40
+ /** Additive Flow preview copy. Omitted legacy label objects use English defaults. */
41
+ readonly previewTitle?: string;
42
+ readonly previewLoading?: string;
43
+ readonly previewError?: string;
44
+ readonly previewDocumentResult?: string;
45
+ readonly previewBindingResult?: string;
46
+ readonly previewStepIntermediateUnavailable?: string;
47
+ readonly previewOperatorIntermediateUnavailable?: string;
48
+ readonly previewDraftUnavailable?: string;
49
+ readonly previewSelectionUnavailable?: string;
28
50
  }
29
51
 
30
- export const defaultFieldRemapChromeLabels: FieldRemapChromeLabels = {
52
+ export const defaultFieldRemapChromeLabels = {
31
53
  bindingsTitle: 'Bindings',
32
54
  convertPaletteTitle: 'Convert palette',
33
55
  convertPaletteDescription:
34
56
  'Place a convert first, then wire source → draft → target. Drafts stay off the document until both ports bind.',
35
57
  convertPaletteAriaLabel: 'Convert palette',
36
58
  convertsListAriaLabel: 'Converts',
59
+ convertFilterLabel: 'Filter converts',
60
+ convertFilterPlaceholder: 'Filter by label or id',
61
+ clearConvertFilter: 'Clear convert filter',
62
+ noMatchingConverts: 'No matching converts.',
37
63
  placeConvert: 'Place convert',
64
+ addCombine: 'Add combine',
65
+ addSplit: 'Add split',
38
66
  operatorsTitle: 'n→m operators',
39
67
  operatorsDescription:
40
68
  'Create combine (n→1) or split (1→n), then wire ports or edit in the side rail.',
69
+ addTransform: 'Add convert',
70
+ editItems: 'Edit items',
71
+ removeBinding: 'Remove binding',
41
72
  showMinimap: 'Show minimap',
42
73
  hideMinimap: 'Hide minimap',
43
74
  showHiddenFields: 'Show hidden fields',
44
75
  hideHiddenFields: 'Hide hidden fields',
45
- };
76
+ emptyDetailTitle: 'Start with a convert',
77
+ emptyDetailDescription:
78
+ 'Use the Convert palette to place a convert, then wire source → draft → target. Or select an existing binding / convert note on the canvas.',
79
+ previewTitle: 'Sample preview',
80
+ previewLoading: 'Updating preview…',
81
+ previewError: 'Preview failed',
82
+ previewDocumentResult: 'Final document output',
83
+ previewBindingResult: 'Final binding value',
84
+ previewStepIntermediateUnavailable:
85
+ 'Per-step intermediate values are unavailable; this is the final binding value.',
86
+ previewOperatorIntermediateUnavailable:
87
+ 'Selected-operator intermediate values are unavailable; this is the final document output.',
88
+ previewDraftUnavailable: 'Draft converts are not executable until they become a binding.',
89
+ previewSelectionUnavailable: 'The selected binding or operator is no longer available.',
90
+ } as const satisfies Required<FieldRemapChromeLabels>;
46
91
 
47
92
  /** Stable capability ids for optional `t()` injection (not free prose). */
48
93
  export const fieldRemapChromeLabelKeys = {
@@ -51,13 +96,33 @@ export const fieldRemapChromeLabelKeys = {
51
96
  convertPaletteDescription: 'fieldRemap.convertPaletteDescription',
52
97
  convertPaletteAriaLabel: 'fieldRemap.convertPaletteAriaLabel',
53
98
  convertsListAriaLabel: 'fieldRemap.convertsListAriaLabel',
99
+ convertFilterLabel: 'fieldRemap.convertFilterLabel',
100
+ convertFilterPlaceholder: 'fieldRemap.convertFilterPlaceholder',
101
+ clearConvertFilter: 'fieldRemap.clearConvertFilter',
102
+ noMatchingConverts: 'fieldRemap.noMatchingConverts',
54
103
  placeConvert: 'fieldRemap.placeConvert',
104
+ addCombine: 'fieldRemap.addCombine',
105
+ addSplit: 'fieldRemap.addSplit',
55
106
  operatorsTitle: 'fieldRemap.operatorsTitle',
56
107
  operatorsDescription: 'fieldRemap.operatorsDescription',
108
+ addTransform: 'fieldRemap.addTransform',
109
+ editItems: 'fieldRemap.editItems',
110
+ removeBinding: 'fieldRemap.removeBinding',
57
111
  showMinimap: 'fieldRemap.showMinimap',
58
112
  hideMinimap: 'fieldRemap.hideMinimap',
59
113
  showHiddenFields: 'fieldRemap.showHiddenFields',
60
114
  hideHiddenFields: 'fieldRemap.hideHiddenFields',
115
+ emptyDetailTitle: 'fieldRemap.emptyDetailTitle',
116
+ emptyDetailDescription: 'fieldRemap.emptyDetailDescription',
117
+ previewTitle: 'fieldRemap.previewTitle',
118
+ previewLoading: 'fieldRemap.previewLoading',
119
+ previewError: 'fieldRemap.previewError',
120
+ previewDocumentResult: 'fieldRemap.previewDocumentResult',
121
+ previewBindingResult: 'fieldRemap.previewBindingResult',
122
+ previewStepIntermediateUnavailable: 'fieldRemap.previewStepIntermediateUnavailable',
123
+ previewOperatorIntermediateUnavailable: 'fieldRemap.previewOperatorIntermediateUnavailable',
124
+ previewDraftUnavailable: 'fieldRemap.previewDraftUnavailable',
125
+ previewSelectionUnavailable: 'fieldRemap.previewSelectionUnavailable',
61
126
  } as const satisfies Record<keyof FieldRemapChromeLabels, string>;
62
127
 
63
128
  export function resolveFieldRemapChromeLabels(
@@ -79,12 +144,32 @@ export function resolveFieldRemapChromeLabels(
79
144
  convertPaletteDescription: resolve('convertPaletteDescription'),
80
145
  convertPaletteAriaLabel: resolve('convertPaletteAriaLabel'),
81
146
  convertsListAriaLabel: resolve('convertsListAriaLabel'),
147
+ convertFilterLabel: resolve('convertFilterLabel'),
148
+ convertFilterPlaceholder: resolve('convertFilterPlaceholder'),
149
+ clearConvertFilter: resolve('clearConvertFilter'),
150
+ noMatchingConverts: resolve('noMatchingConverts'),
82
151
  placeConvert: resolve('placeConvert'),
152
+ addCombine: resolve('addCombine'),
153
+ addSplit: resolve('addSplit'),
83
154
  operatorsTitle: resolve('operatorsTitle'),
84
155
  operatorsDescription: resolve('operatorsDescription'),
156
+ addTransform: resolve('addTransform'),
157
+ editItems: resolve('editItems'),
158
+ removeBinding: resolve('removeBinding'),
85
159
  showMinimap: resolve('showMinimap'),
86
160
  hideMinimap: resolve('hideMinimap'),
87
161
  showHiddenFields: resolve('showHiddenFields'),
88
162
  hideHiddenFields: resolve('hideHiddenFields'),
163
+ emptyDetailTitle: resolve('emptyDetailTitle'),
164
+ emptyDetailDescription: resolve('emptyDetailDescription'),
165
+ previewTitle: resolve('previewTitle'),
166
+ previewLoading: resolve('previewLoading'),
167
+ previewError: resolve('previewError'),
168
+ previewDocumentResult: resolve('previewDocumentResult'),
169
+ previewBindingResult: resolve('previewBindingResult'),
170
+ previewStepIntermediateUnavailable: resolve('previewStepIntermediateUnavailable'),
171
+ previewOperatorIntermediateUnavailable: resolve('previewOperatorIntermediateUnavailable'),
172
+ previewDraftUnavailable: resolve('previewDraftUnavailable'),
173
+ previewSelectionUnavailable: resolve('previewSelectionUnavailable'),
89
174
  };
90
175
  }