treege 3.0.0-beta.19 → 3.0.0-beta.20

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.
package/dist/editor.js CHANGED
@@ -1,5 +1,5 @@
1
- import { T as o } from "./TreegeEditor-BP0R2rMo.js";
2
- import { T as m, u as s } from "./ThemeContext-CQoWKClD.js";
1
+ import { T as o } from "./TreegeEditor-LKN_xeXZ.js";
2
+ import { T as m, u as s } from "./ThemeContext-BIT4DHqC.js";
3
3
  export {
4
4
  m as ThemeProvider,
5
5
  o as TreegeEditor,
package/dist/main.js CHANGED
@@ -1,6 +1,6 @@
1
- import { T as t } from "./TreegeEditor-BP0R2rMo.js";
2
- import { T as u, d as l, g as r, b as o, c as i, i as n, a as d, u as f } from "./ThemeContext-CQoWKClD.js";
3
- import { c as T, d as D, e as I, f as m, g, h as c, D as F, i as R, j as x, k as N, l as S, m as b, n as v, o as h, p as w, q as C, r as z, s as A, v as H, w as k, T as y, b as E, L as G, M as P, J as U, K as V, t as j, x as q, y as B, z as J, A as K, C as L, F as M, G as O, I as Q, E as W, H as X, B as Y, u as Z, a as _ } from "./TreegeRenderer-ClfGb4Mq.js";
1
+ import { T as t } from "./TreegeEditor-LKN_xeXZ.js";
2
+ import { T as u, d as l, g as r, b as i, c as n, i as o, a as d, u as p } from "./ThemeContext-BIT4DHqC.js";
3
+ import { c as T, d as D, e as I, f as m, g, h as c, D as F, i as R, j as N, k as x, l as S, m as b, n as v, o as h, p as w, q as z, r as C, s as H, v as A, w as k, T as y, b as E, L as G, M as P, J as U, K as V, t as j, x as q, y as B, z as J, A as K, C as L, F as M, G as O, I as Q, E as W, H as X, N as Y, O as Z, B as _, u as $, a as ee } from "./TreegeRenderer--ZEq_w_0.js";
4
4
  export {
5
5
  T as DefaultAddressInput,
6
6
  D as DefaultAutocompleteInput,
@@ -10,17 +10,17 @@ export {
10
10
  c as DefaultFileInput,
11
11
  F as DefaultGroup,
12
12
  R as DefaultHiddenInput,
13
- x as DefaultHttpInput,
14
- N as DefaultNumberInput,
13
+ N as DefaultHttpInput,
14
+ x as DefaultNumberInput,
15
15
  S as DefaultPasswordInput,
16
16
  b as DefaultRadioInput,
17
17
  v as DefaultSelectInput,
18
18
  h as DefaultSwitchInput,
19
19
  w as DefaultTextAreaInput,
20
- C as DefaultTextInput,
21
- z as DefaultTimeInput,
22
- A as DefaultTimeRangeInput,
23
- H as Divider,
20
+ z as DefaultTextInput,
21
+ C as DefaultTimeInput,
22
+ H as DefaultTimeRangeInput,
23
+ A as Divider,
24
24
  u as ThemeProvider,
25
25
  k as Title,
26
26
  y as TreegeConfigProvider,
@@ -41,14 +41,16 @@ export {
41
41
  l as getStaticTranslations,
42
42
  r as getTranslatedText,
43
43
  Q as isFieldEmpty,
44
- o as isFlowNode,
45
- i as isGroupNode,
46
- n as isInputNode,
44
+ i as isFlowNode,
45
+ n as isGroupNode,
46
+ o as isInputNode,
47
47
  W as isStartNode,
48
48
  d as isUINode,
49
49
  X as mergeFlows,
50
- Y as serializableToFile,
51
- f as useTheme,
52
- Z as useTreegeConfig,
53
- _ as useTreegeRenderer
50
+ Y as sanitize,
51
+ Z as sanitizeHttpResponse,
52
+ _ as serializableToFile,
53
+ p as useTheme,
54
+ $ as useTreegeConfig,
55
+ ee as useTreegeRenderer
54
56
  };
@@ -39,7 +39,7 @@ export declare const useTreegeRenderer: (flows: Flow | Flow[] | null | undefined
39
39
  setFieldValue: (fieldName: string, value: unknown) => void;
40
40
  setFormErrors: import('react').Dispatch<import('react').SetStateAction<Record<string, string>>>;
41
41
  setMultipleFieldValues: (updates: FormValues) => void;
42
- t: (key?: import('../../../main').Translatable | import('../../../main').TranslationKey | string) => string;
42
+ t: (key?: import('../../../main').Translatable | string) => string;
43
43
  validateForm: (customValidate?: (values: FormValues, visibleNodesList: Node<TreegeNodeData>[]) => Record<string, string>) => {
44
44
  errors: {
45
45
  [x: string]: string;
@@ -1,3 +1,3 @@
1
1
  import { TreegeRendererProps } from '../../../types/renderer';
2
- declare const TreegeRenderer: ({ components, flows, googleApiKey, initialValues, language, onChange, onSubmit, theme, validate, validationMode, }: TreegeRendererProps) => import("react/jsx-runtime").JSX.Element;
2
+ declare const TreegeRenderer: ({ components, flows, googleApiKey, language, onChange, onSubmit, theme, validate, validationMode, initialValues, }: TreegeRendererProps) => import("react/jsx-runtime").JSX.Element;
3
3
  export default TreegeRenderer;
@@ -1,10 +1,12 @@
1
+ import { Translatable } from '../../shared/types/translate';
1
2
  /**
2
3
  * Hook for translating text in the renderer with context-aware language preference.
3
4
  *
4
5
  * This hook uses the language from TreegeRendererContext (or explicit override) and delegates to the shared useTranslate hook.
6
+ * All translations are automatically sanitized to prevent XSS attacks.
5
7
  *
6
8
  * @param language - Optional language override. If not provided, uses language from context.
7
- * @returns A function that translates either a translation key or a Translatable object
9
+ * @returns A function that translates either a translation key or a Translatable object (with XSS protection)
8
10
  *
9
11
  * @example
10
12
  * // Static translation (from translation files)
@@ -12,13 +14,13 @@
12
14
  * const errorMsg = t("validation.required"); // "This field is required"
13
15
  *
14
16
  * @example
15
- * // Dynamic translation (from node data)
17
+ * // Dynamic translation (from node data) - automatically sanitized
16
18
  * const t = useTranslate();
17
- * const label = t(node.data.label); // Translates user-defined content
19
+ * const label = t(node.data.label); // Translates and sanitizes user-defined content
18
20
  *
19
21
  * @example
20
22
  * // With explicit language
21
23
  * const t = useTranslate("fr");
22
24
  * const errorMsg = t("validation.required"); // "Ce champ est requis"
23
25
  */
24
- export declare const useTranslate: (language?: string) => (key?: import('../../main').Translatable | import('../../main').TranslationKey | string) => string;
26
+ export declare const useTranslate: (language?: string) => (key?: Translatable | string) => string;
@@ -13,5 +13,6 @@ export * from './utils/conditions';
13
13
  export * from './utils/file';
14
14
  export * from './utils/flow';
15
15
  export * from './utils/form';
16
+ export * from './utils/sanitize';
16
17
  export { ThemeProvider, useTheme } from '../shared/context/ThemeContext';
17
18
  export { getTranslatedText } from '../shared/utils/translations';
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Configuration for DOMPurify sanitization
3
+ */
4
+ interface SanitizeOptions {
5
+ /**
6
+ * Allow only plain text (strip all HTML tags)
7
+ * @default true
8
+ */
9
+ plainTextOnly?: boolean;
10
+ /**
11
+ * Custom allowed tags (when plainTextOnly is false)
12
+ */
13
+ allowedTags?: string[];
14
+ /**
15
+ * Custom allowed attributes (when plainTextOnly is false)
16
+ */
17
+ allowedAttributes?: string[];
18
+ }
19
+ /**
20
+ * Sanitizes user input to prevent XSS attacks
21
+ *
22
+ * This utility wraps DOMPurify and provides secure defaults for the treege library.
23
+ * It should be used on all user-provided content before rendering, especially:
24
+ * - Labels from node data
25
+ * - Helper text
26
+ * - Placeholder text
27
+ * - Any content from HTTP responses
28
+ *
29
+ * @param input - The string to sanitize
30
+ * @param options - Sanitization options
31
+ * @returns Sanitized string safe for rendering
32
+ *
33
+ * @example
34
+ * // Plain text only (default behavior)
35
+ * sanitize('<script>alert("xss")</script>Hello')
36
+ * // => 'Hello'
37
+ *
38
+ * @example
39
+ * // Allow safe HTML tags
40
+ * sanitize('<b>Bold text</b><script>alert("xss")</script>', { plainTextOnly: false })
41
+ * // => '<b>Bold text</b>'
42
+ *
43
+ * @example
44
+ * // Custom allowed tags
45
+ * sanitize('<a href="http://example.com">Link</a>', {
46
+ * plainTextOnly: false,
47
+ * allowedTags: ['a'],
48
+ * allowedAttributes: ['href']
49
+ * })
50
+ * // => '<a href="http://example.com">Link</a>'
51
+ */
52
+ export declare const sanitize: (input: string | undefined | null, options?: SanitizeOptions) => string;
53
+ /**
54
+ * Sanitizes data from HTTP responses
55
+ *
56
+ * This function recursively sanitizes all string values in an object or array.
57
+ * Useful for cleaning data received from external APIs before displaying it.
58
+ *
59
+ * Protection against:
60
+ * - Circular references: Uses WeakSet to detect and handle circular objects
61
+ * - Deep nesting attacks: Limits recursion depth to prevent DoS
62
+ * - XSS attacks: Sanitizes all string values
63
+ *
64
+ * @param data - The data to sanitize (can be any type)
65
+ * @param options - Sanitization options
66
+ * @param depth - Current recursion depth (internal use)
67
+ * @param seen - WeakSet to track visited objects (internal use)
68
+ * @returns Sanitized data with same structure
69
+ *
70
+ * @example
71
+ * sanitizeHttpResponse({
72
+ * name: 'John <script>xss</script>',
73
+ * nested: { title: 'Hello <b>world</b>' }
74
+ * })
75
+ * // => { name: 'John ', nested: { title: 'Hello <b>world</b>' } }
76
+ *
77
+ * @example
78
+ * // Handles circular references gracefully
79
+ * const obj = { name: 'Test' };
80
+ * obj.self = obj;
81
+ * sanitizeHttpResponse(obj)
82
+ * // => { name: 'Test', self: { name: 'Test' } } // circular ref broken
83
+ */
84
+ export declare const sanitizeHttpResponse: (data: unknown, options?: SanitizeOptions, depth?: number, seen?: WeakSet<object>) => unknown;
85
+ export {};
package/dist/renderer.js CHANGED
@@ -1,12 +1,12 @@
1
- import { c as t, d as s, e as u, f as l, g as r, h as n, D as i, i as o, j as f, k as p, l as d, m as D, n as I, o as T, p as m, q as g, r as c, s as F, v as R, w as v, T as x, b as S, L as b, M as h, J as C, K as w, t as z, x as A, y as H, z as N, A as k, C as y, F as P, G as E, I as G, E as U, H as V, B as j, u as q, a as B } from "./TreegeRenderer-ClfGb4Mq.js";
2
- import { T as K, g as L, u as M } from "./ThemeContext-CQoWKClD.js";
1
+ import { c as t, d as s, e as u, f as l, g as n, h as r, D as i, i as o, j as f, k as p, l as d, m as D, n as I, o as T, p as m, q as g, r as c, s as F, v as R, w as v, T as x, b as S, L as b, M as h, J as z, K as C, t as w, x as H, y as N, z as A, A as k, C as y, F as P, G as E, I as G, E as U, H as V, N as j, O as q, B, u as J, a as K } from "./TreegeRenderer--ZEq_w_0.js";
2
+ import { T as M, g as O, u as Q } from "./ThemeContext-BIT4DHqC.js";
3
3
  export {
4
4
  t as DefaultAddressInput,
5
5
  s as DefaultAutocompleteInput,
6
6
  u as DefaultCheckboxInput,
7
7
  l as DefaultDateInput,
8
- r as DefaultDateRangeInput,
9
- n as DefaultFileInput,
8
+ n as DefaultDateRangeInput,
9
+ r as DefaultFileInput,
10
10
  i as DefaultGroup,
11
11
  o as DefaultHiddenInput,
12
12
  f as DefaultHttpInput,
@@ -20,28 +20,30 @@ export {
20
20
  c as DefaultTimeInput,
21
21
  F as DefaultTimeRangeInput,
22
22
  R as Divider,
23
- K as ThemeProvider,
23
+ M as ThemeProvider,
24
24
  v as Title,
25
25
  x as TreegeConfigProvider,
26
26
  S as TreegeRenderer,
27
27
  b as applyReferenceTransformation,
28
28
  h as calculateReferenceFieldUpdates,
29
- C as checkFormFieldHasValue,
30
- w as convertFormValuesToNamedFormat,
31
- z as defaultInputRenderers,
32
- A as defaultUI,
33
- H as evaluateCondition,
34
- N as evaluateConditions,
29
+ z as checkFormFieldHasValue,
30
+ C as convertFormValuesToNamedFormat,
31
+ w as defaultInputRenderers,
32
+ H as defaultUI,
33
+ N as evaluateCondition,
34
+ A as evaluateConditions,
35
35
  k as fileToSerializable,
36
36
  y as filesToSerializable,
37
37
  P as findStartNode,
38
38
  E as getFlowRenderState,
39
- L as getTranslatedText,
39
+ O as getTranslatedText,
40
40
  G as isFieldEmpty,
41
41
  U as isStartNode,
42
42
  V as mergeFlows,
43
- j as serializableToFile,
44
- M as useTheme,
45
- q as useTreegeConfig,
46
- B as useTreegeRenderer
43
+ j as sanitize,
44
+ q as sanitizeHttpResponse,
45
+ B as serializableToFile,
46
+ Q as useTheme,
47
+ J as useTreegeConfig,
48
+ K as useTreegeRenderer
47
49
  };
@@ -264,11 +264,11 @@ declare const _default: {
264
264
  "selectOption": "اختر خياراً"
265
265
  },
266
266
  "defaultHttpInput": {
267
- "fetchFailed": "فشل في جلب البيانات",
268
- "httpError": "HTTP {status}: {statusText}",
267
+ "fetchFailed": "فشل في جلب البيانات. يرجى التحقق من اتصالك بالشبكة.",
268
+ "httpError": "خطأ HTTP {status}: {statusText}",
269
269
  "noDataAvailable": "لا توجد بيانات متاحة. قم بتكوين \"جلب عند التحميل\" أو أضف معامل بحث.",
270
270
  "noResults": "لم يتم العثور على نتائج.",
271
- "noUrlConfigured": "لم يتم تكوين رابط",
271
+ "noUrlConfigured": "لم يتم تكوين رابط. يرجى إضافة عنوان URL في إعدادات HTTP.",
272
272
  "retry": "إعادة المحاولة",
273
273
  "search": "بحث...",
274
274
  "searching": "جاري البحث...",
@@ -264,11 +264,11 @@ declare const _default: {
264
264
  "selectOption": "Option auswählen"
265
265
  },
266
266
  "defaultHttpInput": {
267
- "fetchFailed": "Fehler beim Abrufen der Daten",
268
- "httpError": "HTTP {status}: {statusText}",
267
+ "fetchFailed": "Fehler beim Abrufen der Daten. Bitte überprüfen Sie Ihre Netzwerkverbindung.",
268
+ "httpError": "HTTP-Fehler {status}: {statusText}",
269
269
  "noDataAvailable": "Keine Daten verfügbar. Konfigurieren Sie \"Beim Laden abrufen\" oder fügen Sie einen Suchparameter hinzu.",
270
270
  "noResults": "Keine Ergebnisse gefunden.",
271
- "noUrlConfigured": "Keine URL konfiguriert",
271
+ "noUrlConfigured": "Keine URL konfiguriert. Bitte fügen Sie eine URL in der HTTP-Konfiguration hinzu.",
272
272
  "retry": "Erneut versuchen",
273
273
  "search": "Suchen...",
274
274
  "searching": "Suche läuft...",
@@ -264,11 +264,11 @@ declare const _default: {
264
264
  "selectOption": "Select an option"
265
265
  },
266
266
  "defaultHttpInput": {
267
- "fetchFailed": "Failed to fetch data",
268
- "httpError": "HTTP {status}: {statusText}",
267
+ "fetchFailed": "Failed to fetch data. Please check your network connection.",
268
+ "httpError": "HTTP Error {status}: {statusText}",
269
269
  "noDataAvailable": "No data available. Configure \"Fetch on mount\" or add a search parameter.",
270
270
  "noResults": "No results found.",
271
- "noUrlConfigured": "No URL configured",
271
+ "noUrlConfigured": "No URL configured. Please add a URL in the HTTP configuration.",
272
272
  "retry": "Retry",
273
273
  "search": "Search...",
274
274
  "searching": "Search...",
@@ -264,11 +264,11 @@ declare const _default: {
264
264
  "selectOption": "Seleccionar una opción"
265
265
  },
266
266
  "defaultHttpInput": {
267
- "fetchFailed": "Error al obtener los datos",
268
- "httpError": "HTTP {status}: {statusText}",
267
+ "fetchFailed": "Error al obtener los datos. Por favor, verifique su conexión de red.",
268
+ "httpError": "Error HTTP {status}: {statusText}",
269
269
  "noDataAvailable": "No hay datos disponibles. Configure \"Cargar al montar\" o agregue un parámetro de búsqueda.",
270
270
  "noResults": "No se encontraron resultados.",
271
- "noUrlConfigured": "No hay URL configurada",
271
+ "noUrlConfigured": "No hay URL configurada. Por favor, agregue una URL en la configuración HTTP.",
272
272
  "retry": "Reintentar",
273
273
  "search": "Buscar...",
274
274
  "searching": "Buscando...",
@@ -264,11 +264,11 @@ declare const _default: {
264
264
  "selectOption": "Sélectionner une option"
265
265
  },
266
266
  "defaultHttpInput": {
267
- "fetchFailed": "Échec de la récupération des données",
268
- "httpError": "HTTP {status} : {statusText}",
267
+ "fetchFailed": "Échec de la récupération des données. Veuillez vérifier votre connexion réseau.",
268
+ "httpError": "Erreur HTTP {status} : {statusText}",
269
269
  "noDataAvailable": "Aucune donnée disponible. Configurez \"Charger au montage\" ou ajoutez un paramètre de recherche.",
270
270
  "noResults": "Aucun résultat trouvé.",
271
- "noUrlConfigured": "Aucune URL configurée",
271
+ "noUrlConfigured": "Aucune URL configurée. Veuillez ajouter une URL dans la configuration HTTP.",
272
272
  "retry": "Réessayer",
273
273
  "search": "Recherche...",
274
274
  "searching": "Recherche...",
@@ -264,11 +264,11 @@ declare const _default: {
264
264
  "selectOption": "Seleziona un'opzione"
265
265
  },
266
266
  "defaultHttpInput": {
267
- "fetchFailed": "Impossibile recuperare i dati",
268
- "httpError": "HTTP {status}: {statusText}",
267
+ "fetchFailed": "Impossibile recuperare i dati. Controlla la tua connessione di rete.",
268
+ "httpError": "Errore HTTP {status}: {statusText}",
269
269
  "noDataAvailable": "Nessun dato disponibile. Configura \"Carica al montaggio\" o aggiungi un parametro di ricerca.",
270
270
  "noResults": "Nessun risultato trovato.",
271
- "noUrlConfigured": "Nessun URL configurato",
271
+ "noUrlConfigured": "Nessun URL configurato. Aggiungi un URL nella configurazione HTTP.",
272
272
  "retry": "Riprova",
273
273
  "search": "Cerca...",
274
274
  "searching": "Ricerca in corso...",
@@ -264,11 +264,11 @@ declare const _default: {
264
264
  "selectOption": "Selecione uma opção"
265
265
  },
266
266
  "defaultHttpInput": {
267
- "fetchFailed": "Falha ao buscar dados",
268
- "httpError": "HTTP {status}: {statusText}",
267
+ "fetchFailed": "Falha ao buscar dados. Por favor, verifique sua conexão de rede.",
268
+ "httpError": "Erro HTTP {status}: {statusText}",
269
269
  "noDataAvailable": "Nenhum dado disponível. Configure \"Buscar na montagem\" ou adicione um parâmetro de pesquisa.",
270
270
  "noResults": "Nenhum resultado encontrado.",
271
- "noUrlConfigured": "Nenhuma URL configurada",
271
+ "noUrlConfigured": "Nenhuma URL configurada. Por favor, adicione uma URL na configuração HTTP.",
272
272
  "retry": "Tentar novamente",
273
273
  "search": "Pesquisar...",
274
274
  "searching": "Pesquisando...",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "treege",
3
3
  "description": "Powerful form generator",
4
4
  "license": "ISC",
5
- "version": "3.0.0-beta.19",
5
+ "version": "3.0.0-beta.20",
6
6
  "type": "module",
7
7
  "types": "./dist/main.d.ts",
8
8
  "module": "./dist/main.js",
@@ -65,6 +65,7 @@
65
65
  "clsx": "^2.1.1",
66
66
  "cmdk": "^1.1.1",
67
67
  "date-fns": "^4.1.0",
68
+ "dompurify": "^3.3.0",
68
69
  "lucide-react": "^0.544.0",
69
70
  "nanoid": "^5.1.6",
70
71
  "next-themes": "^0.4.6",
@@ -81,6 +82,7 @@
81
82
  "@testing-library/react": "^16.3.0",
82
83
  "@testing-library/react-hooks": "^8.0.1",
83
84
  "@tracktor/biome-config-react": "^1.4.0",
85
+ "@types/dompurify": "^3.2.0",
84
86
  "@types/google.maps": "^3.58.1",
85
87
  "@types/node": "^24.5.2",
86
88
  "@types/react": "^19.1.0",