@servicetitan/dte-pdf-editor 1.47.0 → 1.49.0

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 +1 @@
1
- {"version":3,"file":"display-condition.d.ts","sourceRoot":"","sources":["../../../src/components/display-conditions/display-condition.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAsB,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAyB,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAE9F,UAAU,qBACN,SAAQ,IAAI,CACR,0BAA0B,EACxB,gBAAgB,GAChB,oBAAoB,GACpB,yBAAyB,GACzB,OAAO,GACP,cAAc,GACd,qBAAqB,GACrB,QAAQ,CACb;IACD,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;CAC9C;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAqCtD,CAAC"}
1
+ {"version":3,"file":"display-condition.d.ts","sourceRoot":"","sources":["../../../src/components/display-conditions/display-condition.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,EAAE,EAAsB,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAyB,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAE9F,UAAU,qBACN,SAAQ,IAAI,CACR,0BAA0B,EACxB,gBAAgB,GAChB,oBAAoB,GACpB,yBAAyB,GACzB,OAAO,GACP,cAAc,GACd,qBAAqB,GACrB,QAAQ,CACb;IACD,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;CAC9C;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAoEtD,CAAC"}
@@ -1,10 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button } from '@servicetitan/anvil2';
2
+ import { Button, Flex, Text } from '@servicetitan/anvil2';
3
3
  import PlusIcon from '@servicetitan/anvil2/assets/icons/material/round/add.svg';
4
+ import DeleteIcon from '@servicetitan/anvil2/assets/icons/material/round/delete.svg';
5
+ import EditIcon from '@servicetitan/anvil2/assets/icons/material/round/edit.svg';
4
6
  import { Fragment, useState } from 'react';
5
7
  import { DisplayConditionModal } from './display-condition-modal';
6
8
  export const DisplayCondition = ({ documentFields, formFieldsByFormId, formFieldsLoadingFormId, forms, initialState, onRequestFormFields, onSave, schema, }) => {
9
+ var _a, _b, _c, _d;
7
10
  const [open, setOpen] = useState(false);
8
- return (_jsxs(Fragment, { children: [_jsx(Button, { appearance: "secondary", className: "full-width", icon: PlusIcon, onClick: () => setOpen(true), children: "Add Display Condition" }), open && (_jsx(DisplayConditionModal, { onClose: () => setOpen(false), onSave: state => onSave({ displayCondition: state !== null && state !== void 0 ? state : undefined }), documentFields: documentFields, formFieldsByFormId: formFieldsByFormId, formFieldsLoadingFormId: formFieldsLoadingFormId, forms: forms, initialState: initialState, onRequestFormFields: onRequestFormFields, schema: schema }))] }));
11
+ const conditionCount = (_d = (_c = (_b = (_a = initialState === null || initialState === void 0 ? void 0 : initialState.groups) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.conditions) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0;
12
+ return (_jsxs(Fragment, { children: [conditionCount === 0 ? (_jsx(Button, { appearance: "secondary", className: "full-width", icon: PlusIcon, onClick: () => setOpen(true), children: "Add Display Condition" })) : (_jsxs(Flex, { gap: 2, justifyContent: "space-between", alignItems: "center", className: "bordered-paper", children: [_jsxs(Flex, { direction: "column", children: [_jsx(Text, { children: (initialState === null || initialState === void 0 ? void 0 : initialState.behavior) === 'show'
13
+ ? 'Show condition configured'
14
+ : 'Hide condition configured' }), _jsx(Text, { size: "small", subdued: true, variant: "body", children: conditionCount === 1
15
+ ? '1 condition is currently applied'
16
+ : `${conditionCount} conditions are currently applied` })] }), _jsxs(Flex, { gap: 2, children: [_jsx(Button, { size: "small", icon: EditIcon, onClick: () => setOpen(true) }), _jsx(Button, { size: "small", icon: DeleteIcon, onClick: () => onSave({ displayCondition: undefined }) })] })] })), open && (_jsx(DisplayConditionModal, { onClose: () => setOpen(false), onSave: state => onSave({ displayCondition: state !== null && state !== void 0 ? state : undefined }), documentFields: documentFields, formFieldsByFormId: formFieldsByFormId, formFieldsLoadingFormId: formFieldsLoadingFormId, forms: forms, initialState: initialState, onRequestFormFields: onRequestFormFields, schema: schema }))] }));
9
17
  };
10
18
  //# sourceMappingURL=display-condition.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"display-condition.js","sourceRoot":"","sources":["../../../src/components/display-conditions/display-condition.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,QAAQ,MAAM,0DAA0D,CAAC;AAChF,OAAO,EAAM,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAA8B,MAAM,2BAA2B,CAAC;AAgB9F,MAAM,CAAC,MAAM,gBAAgB,GAA8B,CAAC,EACxD,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,KAAK,EACL,YAAY,EACZ,mBAAmB,EACnB,MAAM,EACN,MAAM,GACT,EAAE,EAAE;IACD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,OAAO,CACH,MAAC,QAAQ,eACL,KAAC,MAAM,IACH,UAAU,EAAC,WAAW,EACtB,SAAS,EAAC,YAAY,EACtB,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,sCAGvB,EACR,IAAI,IAAI,CACL,KAAC,qBAAqB,IAClB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAC7B,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,SAAS,EAAE,CAAC,EACjE,cAAc,EAAE,cAAc,EAC9B,kBAAkB,EAAE,kBAAkB,EACtC,uBAAuB,EAAE,uBAAuB,EAChD,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,mBAAmB,EAAE,mBAAmB,EACxC,MAAM,EAAE,MAAM,GAChB,CACL,IACM,CACd,CAAC;AACN,CAAC,CAAC"}
1
+ {"version":3,"file":"display-condition.js","sourceRoot":"","sources":["../../../src/components/display-conditions/display-condition.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,QAAQ,MAAM,0DAA0D,CAAC;AAChF,OAAO,UAAU,MAAM,6DAA6D,CAAC;AACrF,OAAO,QAAQ,MAAM,2DAA2D,CAAC;AACjF,OAAO,EAAM,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAA8B,MAAM,2BAA2B,CAAC;AAgB9F,MAAM,CAAC,MAAM,gBAAgB,GAA8B,CAAC,EACxD,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,KAAK,EACL,YAAY,EACZ,mBAAmB,EACnB,MAAM,EACN,MAAM,GACT,EAAE,EAAE;;IACD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,cAAc,GAAG,MAAA,MAAA,MAAA,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,MAAM,0CAAG,CAAC,CAAC,0CAAE,UAAU,0CAAE,MAAM,mCAAI,CAAC,CAAC;IAE1E,OAAO,CACH,MAAC,QAAQ,eACJ,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,CACpB,KAAC,MAAM,IACH,UAAU,EAAC,WAAW,EACtB,SAAS,EAAC,YAAY,EACtB,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,sCAGvB,CACZ,CAAC,CAAC,CAAC,CACA,MAAC,IAAI,IACD,GAAG,EAAE,CAAC,EACN,cAAc,EAAC,eAAe,EAC9B,UAAU,EAAC,QAAQ,EACnB,SAAS,EAAC,gBAAgB,aAE1B,MAAC,IAAI,IAAC,SAAS,EAAC,QAAQ,aACpB,KAAC,IAAI,cACA,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,QAAQ,MAAK,MAAM;oCAC9B,CAAC,CAAC,2BAA2B;oCAC7B,CAAC,CAAC,2BAA2B,GAC9B,EACP,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,EAAC,OAAO,QAAC,OAAO,EAAC,MAAM,YACpC,cAAc,KAAK,CAAC;oCACjB,CAAC,CAAC,kCAAkC;oCACpC,CAAC,CAAC,GAAG,cAAc,mCAAmC,GACvD,IACJ,EACP,MAAC,IAAI,IAAC,GAAG,EAAE,CAAC,aACR,KAAC,MAAM,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAI,EACrE,KAAC,MAAM,IACH,IAAI,EAAC,OAAO,EACZ,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC,GACxD,IACC,IACJ,CACV,EACA,IAAI,IAAI,CACL,KAAC,qBAAqB,IAClB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAC7B,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,SAAS,EAAE,CAAC,EACjE,cAAc,EAAE,cAAc,EAC9B,kBAAkB,EAAE,kBAAkB,EACtC,uBAAuB,EAAE,uBAAuB,EAChD,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,mBAAmB,EAAE,mBAAmB,EACxC,MAAM,EAAE,MAAM,GAChB,CACL,IACM,CACd,CAAC;AACN,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-view-data-model.d.ts","sourceRoot":"","sources":["../../../src/components/pdf-view/pdf-view-data-model.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGlE,UAAU,qBAAqB;IAC3B,KAAK,EAAE,QAAQ,CAAC;IAChB,IAAI,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAGtD,CAAC"}
1
+ {"version":3,"file":"pdf-view-data-model.d.ts","sourceRoot":"","sources":["../../../src/components/pdf-view/pdf-view-data-model.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGlE,UAAU,qBAAqB;IAC3B,KAAK,EAAE,QAAQ,CAAC;IAChB,IAAI,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CActD,CAAC"}
@@ -1,7 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { resolvePdfDataValues } from '../../utils';
2
+ import { nl2br, resolvePdfDataValues } from '../../utils';
3
3
  export const PdfViewDataModel = ({ data, field }) => {
4
4
  const resolvedValue = field.path ? resolvePdfDataValues(data, field.path) : '';
5
- return _jsx("div", { className: "dte-pdf-field-value", children: resolvedValue !== null && resolvedValue !== void 0 ? resolvedValue : '' });
5
+ /*
6
+ * Mirrors Unlayer's `{{ field | safe | nl2br }}` as
7
+ * conversion. The `__html` key and `dangerouslySetInnerHTML` are mandated by React's API.
8
+ */
9
+ return (_jsx("div", { className: "dte-pdf-field-value",
10
+ // eslint-disable-next-line react/no-danger, @typescript-eslint/naming-convention
11
+ dangerouslySetInnerHTML: { __html: nl2br(resolvedValue !== null && resolvedValue !== void 0 ? resolvedValue : '') } }));
6
12
  };
7
13
  //# sourceMappingURL=pdf-view-data-model.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-view-data-model.js","sourceRoot":"","sources":["../../../src/components/pdf-view/pdf-view-data-model.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAOnD,MAAM,CAAC,MAAM,gBAAgB,GAA8B,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;IAC3E,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,OAAO,cAAK,SAAS,EAAC,qBAAqB,YAAE,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,EAAE,GAAO,CAAC;AAC5E,CAAC,CAAC"}
1
+ {"version":3,"file":"pdf-view-data-model.js","sourceRoot":"","sources":["../../../src/components/pdf-view/pdf-view-data-model.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAO1D,MAAM,CAAC,MAAM,gBAAgB,GAA8B,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;IAC3E,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE/E;;;OAGG;IACH,OAAO,CACH,cACI,SAAS,EAAC,qBAAqB;QAC/B,iFAAiF;QACjF,uBAAuB,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,EAAE,CAAC,EAAE,GACjE,CACL,CAAC;AACN,CAAC,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export * from './date.utils';
2
2
  export * from './number.utils';
3
+ export * from './schema.utils';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export * from './date.utils';
2
2
  export * from './number.utils';
3
+ export * from './schema.utils';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * React/HTML equivalent of the Nunjucks `nl2br` filter used by Unlayer's
3
+ * `{{ field | safe | nl2br }}` template. Replaces every `\r\n` or `\n` with `<br />\n`,
4
+ * keeping the original newline so the rendered HTML source still wraps in dev tools.
5
+ */
6
+ export declare const nl2br: (value: string) => string;
7
+ //# sourceMappingURL=schema.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/shared/schema.utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,KAAG,MAErC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * React/HTML equivalent of the Nunjucks `nl2br` filter used by Unlayer's
3
+ * `{{ field | safe | nl2br }}` template. Replaces every `\r\n` or `\n` with `<br />\n`,
4
+ * keeping the original newline so the rendered HTML source still wraps in dev tools.
5
+ */
6
+ export const nl2br = (value) => {
7
+ return value.replace(/\r\n|\n/g, '<br />\n');
8
+ };
9
+ //# sourceMappingURL=schema.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.utils.js","sourceRoot":"","sources":["../../../src/utils/shared/schema.utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAU,EAAE;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AACjD,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/dte-pdf-editor",
3
- "version": "1.47.0",
3
+ "version": "1.49.0",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "typings": "./dist/index.d.ts",
@@ -1,5 +1,7 @@
1
- import { Button } from '@servicetitan/anvil2';
1
+ import { Button, Flex, Text } from '@servicetitan/anvil2';
2
2
  import PlusIcon from '@servicetitan/anvil2/assets/icons/material/round/add.svg';
3
+ import DeleteIcon from '@servicetitan/anvil2/assets/icons/material/round/delete.svg';
4
+ import EditIcon from '@servicetitan/anvil2/assets/icons/material/round/edit.svg';
3
5
  import { FC, Fragment, useState } from 'react';
4
6
  import { PdfField } from '../../interface/types';
5
7
  import { DisplayConditionModal, DisplayConditionModalProps } from './display-condition-modal';
@@ -29,17 +31,48 @@ export const DisplayCondition: FC<DisplayConditionProps> = ({
29
31
  schema,
30
32
  }) => {
31
33
  const [open, setOpen] = useState(false);
34
+ const conditionCount = initialState?.groups?.[0]?.conditions?.length ?? 0;
32
35
 
33
36
  return (
34
37
  <Fragment>
35
- <Button
36
- appearance="secondary"
37
- className="full-width"
38
- icon={PlusIcon}
39
- onClick={() => setOpen(true)}
40
- >
41
- Add Display Condition
42
- </Button>
38
+ {conditionCount === 0 ? (
39
+ <Button
40
+ appearance="secondary"
41
+ className="full-width"
42
+ icon={PlusIcon}
43
+ onClick={() => setOpen(true)}
44
+ >
45
+ Add Display Condition
46
+ </Button>
47
+ ) : (
48
+ <Flex
49
+ gap={2}
50
+ justifyContent="space-between"
51
+ alignItems="center"
52
+ className="bordered-paper"
53
+ >
54
+ <Flex direction="column">
55
+ <Text>
56
+ {initialState?.behavior === 'show'
57
+ ? 'Show condition configured'
58
+ : 'Hide condition configured'}
59
+ </Text>
60
+ <Text size="small" subdued variant="body">
61
+ {conditionCount === 1
62
+ ? '1 condition is currently applied'
63
+ : `${conditionCount} conditions are currently applied`}
64
+ </Text>
65
+ </Flex>
66
+ <Flex gap={2}>
67
+ <Button size="small" icon={EditIcon} onClick={() => setOpen(true)} />
68
+ <Button
69
+ size="small"
70
+ icon={DeleteIcon}
71
+ onClick={() => onSave({ displayCondition: undefined })}
72
+ />
73
+ </Flex>
74
+ </Flex>
75
+ )}
43
76
  {open && (
44
77
  <DisplayConditionModal
45
78
  onClose={() => setOpen(false)}
@@ -1,6 +1,6 @@
1
1
  import { FC } from 'react';
2
2
  import { DataModelValues, PdfField } from '../../interface/types';
3
- import { resolvePdfDataValues } from '../../utils';
3
+ import { nl2br, resolvePdfDataValues } from '../../utils';
4
4
 
5
5
  interface PdfViewDataModelProps {
6
6
  field: PdfField;
@@ -9,5 +9,16 @@ interface PdfViewDataModelProps {
9
9
 
10
10
  export const PdfViewDataModel: FC<PdfViewDataModelProps> = ({ data, field }) => {
11
11
  const resolvedValue = field.path ? resolvePdfDataValues(data, field.path) : '';
12
- return <div className="dte-pdf-field-value">{resolvedValue ?? ''}</div>;
12
+
13
+ /*
14
+ * Mirrors Unlayer's `{{ field | safe | nl2br }}` as
15
+ * conversion. The `__html` key and `dangerouslySetInnerHTML` are mandated by React's API.
16
+ */
17
+ return (
18
+ <div
19
+ className="dte-pdf-field-value"
20
+ // eslint-disable-next-line react/no-danger, @typescript-eslint/naming-convention
21
+ dangerouslySetInnerHTML={{ __html: nl2br(resolvedValue ?? '') }}
22
+ />
23
+ );
13
24
  };
@@ -7,3 +7,10 @@
7
7
  overflow: hidden;
8
8
  text-overflow: ellipsis;
9
9
  }
10
+
11
+ .bordered-paper {
12
+ padding: 12px;
13
+ background-color: var(--color-neutral-0);
14
+ border: 1px solid var(--border-color);
15
+ border-radius: 0.375rem;
16
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './date.utils';
2
2
  export * from './number.utils';
3
+ export * from './schema.utils';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * React/HTML equivalent of the Nunjucks `nl2br` filter used by Unlayer's
3
+ * `{{ field | safe | nl2br }}` template. Replaces every `\r\n` or `\n` with `<br />\n`,
4
+ * keeping the original newline so the rendered HTML source still wraps in dev tools.
5
+ */
6
+ export const nl2br = (value: string): string => {
7
+ return value.replace(/\r\n|\n/g, '<br />\n');
8
+ };