@pdfme/ui 5.3.17 → 5.3.18-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { Template, Size, Plugins, UIProps, UIOptions, PreviewProps } from '@pdfme/common';
1
+ import { Template, Size, UIProps, UIOptions, PluginRegistry, PreviewProps } from '@pdfme/common';
2
2
  export declare abstract class BaseUIClass {
3
3
  protected domContainer: HTMLElement | null;
4
4
  protected template: Template;
@@ -16,7 +16,7 @@ export declare abstract class BaseUIClass {
16
16
  fallback?: boolean | undefined;
17
17
  subset?: boolean | undefined;
18
18
  }>;
19
- protected getPluginsRegistry(): Plugins;
19
+ protected getPluginsRegistry(): PluginRegistry;
20
20
  getOptions(): UIOptions;
21
21
  getTemplate(): import("zod").objectOutputType<{
22
22
  schemas: import("zod").ZodArray<import("zod").ZodArray<import("zod").ZodObject<{
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
- import type { Plugins, Font, Lang, UIOptions } from '@pdfme/common';
2
+ import type { Font, Lang, UIOptions, PluginRegistry } from '@pdfme/common';
3
3
  type Props = {
4
4
  children: React.ReactNode;
5
5
  lang: Lang;
6
6
  font: Font;
7
- plugins: Plugins;
7
+ plugins: PluginRegistry;
8
8
  options: UIOptions;
9
9
  };
10
10
  declare const AppContextProvider: ({ children, lang, font, plugins, options }: Props) => React.JSX.Element;
@@ -1,10 +1,10 @@
1
- import { Plugins, UIOptions } from '@pdfme/common';
1
+ import { PluginRegistry, UIOptions } from '@pdfme/common';
2
2
  export declare const I18nContext: import("react").Context<(key: keyof import("@pdfme/common").Dict, dict?: import("@pdfme/common").Dict) => string>;
3
3
  export declare const FontContext: import("react").Context<Record<string, {
4
4
  data: string | ArrayBuffer | Uint8Array<ArrayBufferLike>;
5
5
  fallback?: boolean | undefined;
6
6
  subset?: boolean | undefined;
7
7
  }>>;
8
- export declare const PluginsRegistry: import("react").Context<Plugins>;
8
+ export declare const PluginsRegistry: import("react").Context<PluginRegistry>;
9
9
  export declare const OptionsContext: import("react").Context<UIOptions>;
10
10
  export declare const CacheContext: import("react").Context<Map<string | number, unknown>>;
@@ -1,4 +1,4 @@
1
- import { Template, BasePdf, SchemaForUI, Size, Plugins } from '@pdfme/common';
1
+ import { Template, BasePdf, SchemaForUI, Size, PluginRegistry } from '@pdfme/common';
2
2
  export declare const uuid: () => string;
3
3
  export declare const debounce: <T extends (...args: unknown[]) => unknown>(cb: T, wait?: number) => T;
4
4
  export declare const round: (number: number, precision: number) => number;
@@ -63,7 +63,7 @@ export declare const changeSchemas: (args: {
63
63
  }[];
64
64
  schemas: SchemaForUI[];
65
65
  basePdf: BasePdf;
66
- pluginsRegistry: Plugins;
66
+ pluginsRegistry: PluginRegistry;
67
67
  pageSize: {
68
68
  width: number;
69
69
  height: number;
@@ -71,3 +71,4 @@ export declare const changeSchemas: (args: {
71
71
  commitSchemas: (newSchemas: SchemaForUI[]) => void;
72
72
  }) => void;
73
73
  export declare const useMaxZoom: () => number;
74
+ export declare const setFontNameRecursively: (obj: Record<string, unknown>, fontName: string, seen?: WeakSet<WeakKey>) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdfme/ui",
3
- "version": "5.3.17",
3
+ "version": "5.3.18-dev.1",
4
4
  "sideEffects": false,
5
5
  "author": "hand-dot",
6
6
  "license": "MIT",
package/src/class.ts CHANGED
@@ -7,9 +7,9 @@ import {
7
7
  Size,
8
8
  Lang,
9
9
  Font,
10
- Plugins,
11
10
  UIProps,
12
11
  UIOptions,
12
+ PluginRegistry,
13
13
  PreviewProps,
14
14
  getDefaultFont,
15
15
  checkUIProps,
@@ -17,6 +17,7 @@ import {
17
17
  checkInputs,
18
18
  checkUIOptions,
19
19
  checkPreviewProps,
20
+ pluginRegistry,
20
21
  } from '@pdfme/common';
21
22
  import { builtInPlugins } from '@pdfme/schemas';
22
23
 
@@ -31,7 +32,7 @@ export abstract class BaseUIClass {
31
32
 
32
33
  private font: Font = getDefaultFont();
33
34
 
34
- private pluginsRegistry: Plugins = builtInPlugins;
35
+ private pluginsRegistry: PluginRegistry = pluginRegistry(builtInPlugins);
35
36
 
36
37
  private options: UIOptions = {};
37
38
 
@@ -70,7 +71,7 @@ export abstract class BaseUIClass {
70
71
  }
71
72
 
72
73
  if (Object.values(plugins).length > 0) {
73
- this.pluginsRegistry = plugins;
74
+ this.pluginsRegistry = pluginRegistry(plugins);
74
75
  }
75
76
  }
76
77
 
@@ -3,13 +3,13 @@ import { ConfigProvider as ThemeConfigProvider } from 'antd';
3
3
  import { I18nContext, FontContext, PluginsRegistry, OptionsContext } from '../contexts.js';
4
4
  import { i18n, getDict } from '../i18n.js';
5
5
  import { defaultTheme } from '../theme.js';
6
- import type { Dict, Plugins, Font, Lang, UIOptions } from '@pdfme/common';
6
+ import type { Dict, Font, Lang, UIOptions, PluginRegistry } from '@pdfme/common';
7
7
 
8
8
  type Props = {
9
9
  children: React.ReactNode;
10
10
  lang: Lang;
11
11
  font: Font;
12
- plugins: Plugins;
12
+ plugins: PluginRegistry;
13
13
  options: UIOptions;
14
14
  };
15
15
 
@@ -335,17 +335,8 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
335
335
  // Create a type-safe array of default schemas
336
336
  const defaultSchemas: Record<string, unknown>[] = [];
337
337
 
338
- // Safely iterate through plugins registry
339
- Object.values(pluginsRegistry).forEach((plugin) => {
340
- if (
341
- plugin &&
342
- typeof plugin === 'object' &&
343
- 'propPanel' in plugin &&
344
- plugin.propPanel &&
345
- typeof plugin.propPanel === 'object' &&
346
- 'defaultSchema' in plugin.propPanel &&
347
- plugin.propPanel.defaultSchema
348
- ) {
338
+ pluginsRegistry.entries().forEach(([, plugin]) => {
339
+ if (plugin.propPanel.defaultSchema) {
349
340
  defaultSchemas.push(plugin.propPanel.defaultSchema as Record<string, unknown>);
350
341
  }
351
342
  });
@@ -1,11 +1,12 @@
1
1
  import React, { useContext, useState, useEffect } from 'react';
2
- import { Schema, Plugin, BasePdf } from '@pdfme/common';
2
+ import { Schema, Plugin, BasePdf, getFallbackFontName } from '@pdfme/common';
3
3
  import { theme, Button } from 'antd';
4
4
  import { useDraggable } from '@dnd-kit/core';
5
5
  import { CSS } from '@dnd-kit/utilities';
6
6
  import Renderer from '../Renderer.js';
7
7
  import { LEFT_SIDEBAR_WIDTH } from '../../constants.js';
8
- import { PluginsRegistry } from '../../contexts.js';
8
+ import { setFontNameRecursively } from '../../helper';
9
+ import { OptionsContext, PluginsRegistry } from '../../contexts.js';
9
10
  import PluginIcon from './PluginIcon.js';
10
11
 
11
12
  const Draggable = (props: {
@@ -16,7 +17,12 @@ const Draggable = (props: {
16
17
  }) => {
17
18
  const { scale, basePdf, plugin } = props;
18
19
  const { token } = theme.useToken();
20
+ const options = useContext(OptionsContext);
19
21
  const defaultSchema = plugin.propPanel.defaultSchema;
22
+ if (options.font) {
23
+ const fontName = getFallbackFontName(options.font);
24
+ setFontNameRecursively(defaultSchema, fontName);
25
+ }
20
26
  const draggable = useDraggable({ id: defaultSchema.type, data: defaultSchema });
21
27
  const { listeners, setNodeRef, attributes, transform, isDragging } = draggable;
22
28
  const style = { transform: CSS.Translate.toString(transform) };
@@ -86,7 +92,7 @@ const LeftSidebar = ({
86
92
  overflow: isDragging ? 'visible' : 'auto',
87
93
  }}
88
94
  >
89
- {Object.entries(pluginsRegistry).map(([label, plugin]) => {
95
+ {pluginsRegistry.entries().map(([label, plugin]) => {
90
96
  if (!plugin?.propPanel.defaultSchema) return null;
91
97
 
92
98
  return (
@@ -39,18 +39,9 @@ const PluginIcon = (props: PluginIconProps) => {
39
39
  const { token } = theme.useToken();
40
40
  const options = useContext(OptionsContext);
41
41
 
42
- // Safely access plugin properties with proper type checking
43
- const defaultSchemaType =
44
- plugin.propPanel &&
45
- typeof plugin.propPanel === 'object' &&
46
- plugin.propPanel.defaultSchema &&
47
- typeof plugin.propPanel.defaultSchema === 'object' &&
48
- 'type' in plugin.propPanel.defaultSchema &&
49
- typeof plugin.propPanel.defaultSchema.type === 'string'
50
- ? plugin.propPanel.defaultSchema.type
51
- : '';
42
+ const schemaType = plugin.propPanel.defaultSchema?.type ?? '';
52
43
 
53
- const icon = options.icons?.[defaultSchemaType] ?? plugin.icon;
44
+ const icon = options.icons?.[schemaType] ?? plugin.icon;
54
45
  const iconStyles = {
55
46
  ...styles,
56
47
  color: token.colorText,
@@ -64,8 +64,8 @@ const DetailView = (props: DetailViewProps) => {
64
64
  ),
65
65
  ButtonGroup: (p) => <ButtonGroupWidget {...p} {...props} options={options} />,
66
66
  };
67
- for (const plugin of Object.values(pluginsRegistry)) {
68
- const widgets = plugin?.propPanel.widgets || {};
67
+ for (const plugin of pluginsRegistry.values()) {
68
+ const widgets = plugin.propPanel.widgets || {};
69
69
  Object.entries(widgets).forEach(([widgetKey, widgetValue]) => {
70
70
  newWidgets[widgetKey] = (p) => (
71
71
  <WidgetRenderer
@@ -171,64 +171,18 @@ const DetailView = (props: DetailViewProps) => {
171
171
  }
172
172
  }, 100);
173
173
 
174
- // Find the active plugin with proper type safety
175
- const activePlugin = Object.values(pluginsRegistry).find((plugin) => {
176
- if (!plugin || typeof plugin !== 'object') return false;
177
- if (!plugin.propPanel || typeof plugin.propPanel !== 'object') return false;
178
- if (!plugin.propPanel.defaultSchema || typeof plugin.propPanel.defaultSchema !== 'object')
179
- return false;
180
-
181
- const defaultSchema = plugin.propPanel.defaultSchema as Record<string, unknown>;
182
- return (
183
- 'type' in defaultSchema &&
184
- typeof defaultSchema.type === 'string' &&
185
- defaultSchema.type === activeSchema.type
186
- );
187
- });
188
-
189
- // Safely access the propPanel schema
190
- const activePropPanelSchema = activePlugin?.propPanel?.schema;
191
- if (!activePropPanelSchema) {
192
- console.error(`[@pdfme/ui] No propPanel.schema for ${activeSchema.type}.
193
- Check this document: https://pdfme.com/docs/custom-schemas`);
174
+ const activePlugin = pluginsRegistry.findByType(activeSchema.type);
175
+ if (!activePlugin) {
176
+ throw Error(`[@pdfme/ui] Failed to find plugin used for ${activeSchema.type}`);
194
177
  }
195
178
 
196
- // Create type-safe options for the type dropdown
197
- // Create a type-safe options array for the dropdown
179
+ const activePropPanelSchema = activePlugin.propPanel.schema;
198
180
  const typeOptions: Array<{ label: string; value: string | undefined }> = [];
199
181
 
200
- // Safely populate the options array
201
- Object.entries(pluginsRegistry).forEach(([label, value]) => {
202
- // Skip invalid plugins
203
- if (!value || typeof value !== 'object') {
204
- typeOptions.push({ label, value: undefined });
205
- return;
206
- }
207
-
208
- if (!('propPanel' in value) || !value.propPanel || typeof value.propPanel !== 'object') {
209
- typeOptions.push({ label, value: undefined });
210
- return;
211
- }
212
-
213
- if (
214
- !('defaultSchema' in value.propPanel) ||
215
- !value.propPanel.defaultSchema ||
216
- typeof value.propPanel.defaultSchema !== 'object'
217
- ) {
218
- typeOptions.push({ label, value: undefined });
219
- return;
220
- }
221
-
222
- // Safely extract the type
223
- const defaultSchema = value.propPanel.defaultSchema as Record<string, unknown>;
224
- let schemaType: string | undefined = undefined;
225
-
226
- if ('type' in defaultSchema && typeof defaultSchema.type === 'string') {
227
- schemaType = defaultSchema.type;
228
- }
229
-
230
- typeOptions.push({ label, value: schemaType });
182
+ pluginsRegistry.entries().forEach(([label, plugin]) => {
183
+ typeOptions.push({ label, value: plugin.propPanel.defaultSchema?.type ?? undefined });
231
184
  });
185
+
232
186
  // Create a safe empty schema as fallback
233
187
  const emptySchema: Record<string, unknown> = {};
234
188
 
@@ -236,15 +190,6 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
236
190
  const defaultSchema: Record<string, unknown> = activePlugin?.propPanel?.defaultSchema
237
191
  ? // Create a safe copy of the schema
238
192
  (() => {
239
- // First check if the defaultSchema is an object
240
- if (
241
- typeof activePlugin.propPanel.defaultSchema !== 'object' ||
242
- activePlugin.propPanel.defaultSchema === null
243
- ) {
244
- return emptySchema;
245
- }
246
-
247
- // Create a safe copy
248
193
  const result: Record<string, unknown> = {};
249
194
 
250
195
  // Only copy properties that exist on the object
@@ -65,26 +65,7 @@ const SelectableSortableContainer = (
65
65
 
66
66
  if (!thisSchema) return <></>;
67
67
 
68
- // Safely extract schema type
69
- const schemaType = typeof thisSchema.type === 'string' ? thisSchema.type : '';
70
-
71
- // Find matching plugin with type-safe approach
72
- const pluginEntry = Object.entries(pluginsRegistry).find(([, plugin]) => {
73
- if (!plugin || typeof plugin !== 'object') return false;
74
- if (!plugin.propPanel || typeof plugin.propPanel !== 'object') return false;
75
- if (!plugin.propPanel.defaultSchema || typeof plugin.propPanel.defaultSchema !== 'object')
76
- return false;
77
-
78
- // Use Record<string, unknown> to safely access properties
79
- const defaultSchema = plugin.propPanel.defaultSchema as Record<string, unknown>;
80
- return (
81
- 'type' in defaultSchema &&
82
- typeof defaultSchema.type === 'string' &&
83
- defaultSchema.type === schemaType
84
- );
85
- });
86
-
87
- const [pluginLabel, activePlugin] = pluginEntry || ['', undefined];
68
+ const [pluginLabel, activePlugin] = pluginsRegistry.findWithLabelByType(thisSchema.type);
88
69
 
89
70
  if (!activePlugin) {
90
71
  return <></>;
@@ -42,26 +42,7 @@ const SelectableSortableItem = ({
42
42
  onClick: (event: React.MouseEvent) => onSelect(schema.id, event.shiftKey),
43
43
  };
44
44
 
45
- // Safely extract schema type
46
- const schemaType = typeof schema.type === 'string' ? schema.type : '';
47
-
48
- // Find matching plugin with type-safe approach
49
- const pluginEntry = Object.entries(pluginsRegistry).find(([, plugin]) => {
50
- if (!plugin || typeof plugin !== 'object') return false;
51
- if (!plugin.propPanel || typeof plugin.propPanel !== 'object') return false;
52
- if (!plugin.propPanel.defaultSchema || typeof plugin.propPanel.defaultSchema !== 'object')
53
- return false;
54
-
55
- // Use Record<string, unknown> to safely access properties
56
- const defaultSchema = plugin.propPanel.defaultSchema as Record<string, unknown>;
57
- return (
58
- 'type' in defaultSchema &&
59
- typeof defaultSchema.type === 'string' &&
60
- defaultSchema.type === schemaType
61
- );
62
- });
63
-
64
- const [pluginLabel, thisPlugin] = pluginEntry || ['', undefined];
45
+ const [pluginLabel, thisPlugin] = pluginsRegistry.findWithLabelByType(schema.type);
65
46
 
66
47
  let status: undefined | 'is-warning' | 'is-danger';
67
48
  if (!schema.name) {
@@ -52,7 +52,7 @@ const useRerenderDependencies = (arg: ReRenderCheckProps) => {
52
52
  } else {
53
53
  return [value, mode, scale, JSON.stringify(schema), optionStr];
54
54
  }
55
- }, [plugin?.uninterruptedEditMode, value, mode, scale, schema, optionStr, plugin]);
55
+ }, [value, mode, scale, schema, optionStr, plugin]);
56
56
  };
57
57
 
58
58
  const Wrapper = ({
@@ -109,17 +109,10 @@ const Renderer = (props: RendererProps) => {
109
109
 
110
110
  const ref = useRef<HTMLDivElement>(null);
111
111
  const _cache = useContext(CacheContext);
112
- // Safely extract schema type
113
- const schemaType = typeof schema.type === 'string' ? schema.type : '';
114
-
115
- // Find plugin with matching schema type using a type-safe approach
116
- const plugin = Object.values(pluginsRegistry || {}).find((plugin) => {
117
- const defaultSchema = plugin?.propPanel?.defaultSchema as Record<string, unknown> | undefined;
118
- return defaultSchema?.type === schemaType;
119
- });
112
+ const plugin = pluginsRegistry.findByType(schema.type);
120
113
 
121
114
  const reRenderDependencies = useRerenderDependencies({
122
- plugin: plugin || ({} as Plugin<Schema>),
115
+ plugin,
123
116
  value,
124
117
  mode,
125
118
  scale,
@@ -154,9 +147,9 @@ const Renderer = (props: RendererProps) => {
154
147
  ref.current.innerHTML = '';
155
148
  }
156
149
  };
157
- }, [plugin?.ui, schema.type, reRenderDependencies]);
150
+ }, reRenderDependencies);
158
151
 
159
- if (!plugin || !plugin.ui) {
152
+ if (!plugin) {
160
153
  console.error(`[@pdfme/ui] Renderer for type ${schema.type} not found.
161
154
  Check this document: https://pdfme.com/docs/custom-schemas`);
162
155
  return <></>;
@@ -25,11 +25,11 @@ const StaticSchema = (props: {
25
25
  key={schema.name}
26
26
  schema={{ ...schema, id: uuid() }}
27
27
  basePdf={basePdf}
28
- value={replacePlaceholders({
28
+ value={schema.readOnly ? replacePlaceholders({
29
29
  content: schema.content || '',
30
30
  variables: { ...input, totalPages, currentPage },
31
31
  schemas,
32
- })}
32
+ }) : schema.content || ''}
33
33
  onChangeHoveringSchemaId={() => {
34
34
  void 0;
35
35
  }}
package/src/contexts.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { createContext } from 'react';
2
2
  import { i18n } from './i18n.js';
3
- import { getDefaultFont, Plugins, UIOptions } from '@pdfme/common';
3
+ import { getDefaultFont, PluginRegistry, pluginRegistry, UIOptions } from '@pdfme/common';
4
4
  import { builtInPlugins } from '@pdfme/schemas';
5
5
 
6
6
  export const I18nContext = createContext(i18n);
7
7
 
8
8
  export const FontContext = createContext(getDefaultFont());
9
9
 
10
- export const PluginsRegistry = createContext<Plugins>(builtInPlugins);
10
+ export const PluginsRegistry = createContext<PluginRegistry>(pluginRegistry(builtInPlugins));
11
11
 
12
12
  export const OptionsContext = createContext<UIOptions>({});
13
13
 
package/src/helper.ts CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  SchemaForUI,
11
11
  Size,
12
12
  isBlankPdf,
13
- Plugins,
13
+ PluginRegistry,
14
14
  } from '@pdfme/common';
15
15
  import { pdf2size } from '@pdfme/converter';
16
16
  import { DEFAULT_MAX_ZOOM, RULER_HEIGHT } from './constants.js';
@@ -452,7 +452,7 @@ const handleTypeChange = (
452
452
  schema: SchemaForUI,
453
453
  key: string,
454
454
  value: unknown,
455
- pluginsRegistry: Plugins,
455
+ pluginsRegistry: PluginRegistry,
456
456
  ) => {
457
457
  if (key !== 'type') return;
458
458
  const keysToKeep = ['id', 'name', 'type', 'position', 'required'];
@@ -461,100 +461,21 @@ const handleTypeChange = (
461
461
  delete schema[key as keyof typeof schema];
462
462
  }
463
463
  });
464
- // Apply attributes from new defaultSchema
465
- // Find the plugin with matching type
466
- const pluginValue = value as string;
467
-
468
- // Define a type-safe approach to find the matching plugin
469
- interface PluginSchema {
470
- type: string;
471
- [key: string]: unknown;
472
- }
473
-
474
- interface PluginType {
475
- propPanel: {
476
- defaultSchema: PluginSchema;
477
- };
478
- }
479
464
 
480
- // Initialize plugin as undefined
481
- let plugin: PluginType | undefined;
482
-
483
- // Safely iterate through plugins to find one with matching type
484
- const pluginEntries = Object.entries(pluginsRegistry);
485
- for (let i = 0; i < pluginEntries.length; i++) {
486
- const [, pluginObj] = pluginEntries[i];
487
-
488
- // Skip invalid plugins
489
- if (!pluginObj || typeof pluginObj !== 'object') continue;
490
-
491
- // Check if propPanel exists and is an object
492
- if (
493
- !('propPanel' in pluginObj) ||
494
- !pluginObj.propPanel ||
495
- typeof pluginObj.propPanel !== 'object'
496
- )
497
- continue;
498
-
499
- // Check if defaultSchema exists and is an object
500
- const propPanel = pluginObj.propPanel as { defaultSchema?: unknown };
501
- if (
502
- !('defaultSchema' in propPanel) ||
503
- !propPanel.defaultSchema ||
504
- typeof propPanel.defaultSchema !== 'object'
505
- )
506
- continue;
507
-
508
- // Safely check if type property exists and matches
509
- const defaultSchema = propPanel.defaultSchema as Record<string, unknown>;
510
- if (!('type' in defaultSchema) || typeof defaultSchema.type !== 'string') continue;
511
-
512
- // Check if the type matches
513
- const schemaType = defaultSchema.type;
514
- if (schemaType === pluginValue) {
515
- // Create a type-safe copy of the plugin
516
- const safeSchema: PluginSchema = {
517
- type: schemaType,
518
- };
519
-
520
- // Copy other properties safely
521
- Object.keys(defaultSchema).forEach((key) => {
522
- if (key !== 'type' && Object.prototype.hasOwnProperty.call(defaultSchema, key)) {
523
- safeSchema[key] = defaultSchema[key];
524
- }
525
- });
526
-
527
- // Found matching plugin with proper typing
528
- plugin = {
529
- propPanel: {
530
- defaultSchema: safeSchema,
531
- },
532
- };
533
- break;
534
- }
535
- }
536
-
537
- const propPanel = plugin?.propPanel;
465
+ const plugin = pluginsRegistry.findByType(value as string);
538
466
 
539
467
  // Apply default schema properties if available
540
- if (propPanel?.defaultSchema) {
541
- // Create a type-safe copy of the default schema
542
- const defaultSchema = propPanel.defaultSchema;
468
+ if (plugin?.propPanel.defaultSchema) {
469
+ const defaultSchema = plugin.propPanel.defaultSchema;
543
470
  const schemaRecord = schema as Record<string, unknown>;
544
471
 
545
472
  // Use a type-safe approach to copy properties
546
473
  for (const key of Object.keys(defaultSchema)) {
547
474
  // Only add properties that don't already exist in the schema
548
475
  if (!Object.prototype.hasOwnProperty.call(schema, key)) {
549
- // Create a safe copy of the property
550
- if (Object.prototype.hasOwnProperty.call(defaultSchema, key)) {
551
- // Get the property value safely
552
- const propertyValue = defaultSchema[key];
553
-
554
- // Only assign if the value is defined
555
- if (propertyValue !== undefined) {
556
- schemaRecord[key] = propertyValue;
557
- }
476
+ const propertyValue = defaultSchema[key];
477
+ if (propertyValue !== undefined) {
478
+ schemaRecord[key] = propertyValue;
558
479
  }
559
480
  }
560
481
  }
@@ -568,7 +489,7 @@ export const changeSchemas = (args: {
568
489
  objs: { key: string; value: unknown; schemaId: string }[];
569
490
  schemas: SchemaForUI[];
570
491
  basePdf: BasePdf;
571
- pluginsRegistry: Plugins;
492
+ pluginsRegistry: PluginRegistry;
572
493
  pageSize: { width: number; height: number };
573
494
  commitSchemas: (newSchemas: SchemaForUI[]) => void;
574
495
  }) => {
@@ -595,3 +516,20 @@ export const useMaxZoom = () => {
595
516
 
596
517
  return options.maxZoom ? options.maxZoom / 100 : DEFAULT_MAX_ZOOM;
597
518
  };
519
+
520
+ export const setFontNameRecursively = (
521
+ obj: Record<string, unknown>,
522
+ fontName: string,
523
+ seen = new WeakSet(),
524
+ ): void => {
525
+ if (!obj || typeof obj !== 'object' || seen.has(obj)) return;
526
+ seen.add(obj);
527
+
528
+ for (const key in obj) {
529
+ if (key === 'fontName' && Object.prototype.hasOwnProperty.call(obj, key) && obj[key] === undefined) {
530
+ obj[key] = fontName;
531
+ } else if (typeof obj[key] === 'object' && obj[key] !== null) {
532
+ setFontNameRecursively(obj[key] as Record<string, unknown>, fontName, seen);
533
+ }
534
+ }
535
+ };