@servicetitan/dte-pdf-editor 1.89.0 → 1.91.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.
- package/dist/components/field-sidebar/data-model-field-type-list.d.ts +12 -1
- package/dist/components/field-sidebar/data-model-field-type-list.d.ts.map +1 -1
- package/dist/components/field-sidebar/data-model-field-type-list.js +29 -9
- package/dist/components/field-sidebar/data-model-field-type-list.js.map +1 -1
- package/dist/components/field-sidebar/field-sidebar.d.ts +5 -0
- package/dist/components/field-sidebar/field-sidebar.d.ts.map +1 -1
- package/dist/components/field-sidebar/field-sidebar.js +7 -10
- package/dist/components/field-sidebar/field-sidebar.js.map +1 -1
- package/dist/components/field-sidebar/form-fields-type-list.d.ts +23 -5
- package/dist/components/field-sidebar/form-fields-type-list.d.ts.map +1 -1
- package/dist/components/field-sidebar/form-fields-type-list.js +20 -5
- package/dist/components/field-sidebar/form-fields-type-list.js.map +1 -1
- package/dist/components/pdf-canvas/pdf-document-renderer.d.ts +0 -1
- package/dist/components/pdf-canvas/pdf-document-renderer.d.ts.map +1 -1
- package/dist/components/pdf-canvas/pdf-document-renderer.js +8 -2
- package/dist/components/pdf-canvas/pdf-document-renderer.js.map +1 -1
- package/dist/constants/menu-group.d.ts +5 -0
- package/dist/constants/menu-group.d.ts.map +1 -1
- package/dist/constants/menu-group.js +5 -2
- package/dist/constants/menu-group.js.map +1 -1
- package/dist/utils/pdf/pdfjs-init.d.ts +1 -1
- package/dist/utils/pdf/pdfjs-init.d.ts.map +1 -1
- package/dist/utils/pdf/pdfjs-init.js +10 -0
- package/dist/utils/pdf/pdfjs-init.js.map +1 -1
- package/package.json +1 -1
- package/src/components/field-sidebar/data-model-field-type-list.tsx +103 -28
- package/src/components/field-sidebar/field-sidebar.tsx +15 -18
- package/src/components/field-sidebar/form-fields-type-list.tsx +109 -94
- package/src/components/pdf-canvas/pdf-document-renderer.tsx +9 -1
- package/src/constants/menu-group.ts +5 -2
- package/src/utils/pdf/pdfjs-init.ts +11 -0
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
|
-
import { type DataModelFieldGroup, type FieldTypeOption } from '../../interface/types';
|
|
2
|
+
import { type DataModelFieldGroup, type FieldTypeOption, type FormInfo } from '../../interface/types';
|
|
3
3
|
interface DataModelFieldTypeListProps {
|
|
4
4
|
dataModelGroups?: DataModelFieldGroup[];
|
|
5
|
+
/**
|
|
6
|
+
* Forms offered as a group after the data model groups. Omitted (or empty) hides the group;
|
|
7
|
+
* `onSelectForm` must be provided for the group to render.
|
|
8
|
+
*/
|
|
9
|
+
forms?: FormInfo[];
|
|
10
|
+
/** The form whose fields are shown in place of the group list; null shows the group list. */
|
|
11
|
+
selectedForm?: FormInfo | null;
|
|
12
|
+
/** Draggable options for `selectedForm`. */
|
|
13
|
+
formFieldOptions?: FieldTypeOption[];
|
|
14
|
+
isLoadingFormFields?: boolean;
|
|
15
|
+
onSelectForm?(form: FormInfo | null): void;
|
|
5
16
|
onDragStart(fieldOption: FieldTypeOption): void;
|
|
6
17
|
onDragEnd(): void;
|
|
7
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-model-field-type-list.d.ts","sourceRoot":"","sources":["../../../src/components/field-sidebar/data-model-field-type-list.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAA+B,MAAM,OAAO,CAAC;AACxD,OAAO,
|
|
1
|
+
{"version":3,"file":"data-model-field-type-list.d.ts","sourceRoot":"","sources":["../../../src/components/field-sidebar/data-model-field-type-list.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAA+B,MAAM,OAAO,CAAC;AACxD,OAAO,EACH,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,QAAQ,EAChB,MAAM,uBAAuB,CAAC;AAK/B,UAAU,2BAA2B;IACjC,eAAe,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACxC;;;OAGG;IACH,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,6FAA6F;IAC7F,YAAY,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;IAC3C,WAAW,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IAChD,SAAS,IAAI,IAAI,CAAC;CACrB;AAKD,eAAO,MAAM,sBAAsB,EAAE,EAAE,CAAC,2BAA2B,CAgHlE,CAAC"}
|
|
@@ -3,23 +3,43 @@ import { Flex, SearchField, Text } from '@servicetitan/anvil2';
|
|
|
3
3
|
import { Fragment, useMemo, useState } from 'react';
|
|
4
4
|
import { getFieldSampleData } from '../../utils';
|
|
5
5
|
import { FieldType } from './field-type';
|
|
6
|
-
|
|
6
|
+
import { FormFieldsPanel, FormsList } from './form-fields-type-list';
|
|
7
|
+
const matchesSearch = (label, searchLower) => label.toLowerCase().includes(searchLower);
|
|
8
|
+
export const DataModelFieldTypeList = ({ dataModelGroups = [], formFieldOptions = [], forms, isLoadingFormFields = false, onDragEnd, onDragStart, onSelectForm, selectedForm = null, }) => {
|
|
7
9
|
const [searchText, setSearchText] = useState('');
|
|
10
|
+
const searchLower = searchText.trim().toLowerCase();
|
|
11
|
+
const showForms = !!(forms === null || forms === void 0 ? void 0 : forms.length) && !!onSelectForm;
|
|
8
12
|
const searchedFieldGroups = useMemo(() => {
|
|
9
|
-
if (!
|
|
13
|
+
if (!searchLower) {
|
|
10
14
|
return dataModelGroups;
|
|
11
15
|
}
|
|
12
|
-
const searchLower = searchText.toLowerCase();
|
|
13
16
|
return dataModelGroups
|
|
14
17
|
.map(group => ({
|
|
15
18
|
...group,
|
|
16
|
-
fields: group.fields.filter(({ label }) => label
|
|
19
|
+
fields: group.fields.filter(({ label }) => matchesSearch(label, searchLower)),
|
|
17
20
|
}))
|
|
18
21
|
.filter(group => group.fields.length > 0);
|
|
19
|
-
}, [dataModelGroups,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
}, [dataModelGroups, searchLower]);
|
|
23
|
+
const searchedForms = useMemo(() => {
|
|
24
|
+
if (!(forms === null || forms === void 0 ? void 0 : forms.length)) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
if (!searchLower) {
|
|
28
|
+
return forms;
|
|
29
|
+
}
|
|
30
|
+
return forms.filter(form => matchesSearch(form.name, searchLower));
|
|
31
|
+
}, [forms, searchLower]);
|
|
32
|
+
const searchedFormFieldOptions = useMemo(() => {
|
|
33
|
+
if (!searchLower) {
|
|
34
|
+
return formFieldOptions;
|
|
35
|
+
}
|
|
36
|
+
return formFieldOptions.filter(option => matchesSearch(option.label, searchLower));
|
|
37
|
+
}, [formFieldOptions, searchLower]);
|
|
38
|
+
const isFormDetail = showForms && !!selectedForm;
|
|
39
|
+
return (_jsxs(Fragment, { children: [_jsx(SearchField, { placeholder: "Search", size: "small", className: "dte-field-sidebar-search", onChange: e => { var _a; return setSearchText((_a = e.target.value) !== null && _a !== void 0 ? _a : ''); } }), _jsx("div", { className: "dte-formula-sidebar-slide-outer", children: _jsxs("div", { className: `dte-formula-sidebar-slide-track${isFormDetail ? ' --detail' : ''}`, children: [_jsxs("div", { className: "dte-formula-sidebar-slide-panel", children: [searchedFieldGroups.map(group => (_jsxs("div", { className: "dte-field-type-group", children: [_jsx(Flex, { alignItems: "center", gap: 1, className: "dte-field-type-group-header", children: _jsx(Text, { variant: "headline", el: "h6", size: "small", children: group.groupName }) }), group.fields.map(fieldOption => {
|
|
40
|
+
const key = `${fieldOption.type}-${group.groupName}-${fieldOption.path}`;
|
|
41
|
+
return (_jsx(FieldType, { onDragEnd: onDragEnd, onDragStart: () => onDragStart(fieldOption), label: fieldOption.label, sampleData: getFieldSampleData(fieldOption.sampleData, fieldOption.fieldType) }, key));
|
|
42
|
+
})] }, group.groupName))), showForms && (searchedForms.length > 0 || !searchLower) && (_jsx(FormsList, { forms: searchedForms, onSelectForm: onSelectForm }))] }), _jsx("div", { className: "dte-formula-sidebar-slide-panel --form-fields", children: isFormDetail && (_jsx(FormFieldsPanel, { form: selectedForm, fieldOptions: searchedFormFieldOptions, hasHiddenFields: formFieldOptions.length > 0 &&
|
|
43
|
+
searchedFormFieldOptions.length === 0, isLoading: isLoadingFormFields, onBack: () => onSelectForm(null), onDragEnd: onDragEnd, onDragStart: onDragStart })) })] }) })] }));
|
|
24
44
|
};
|
|
25
45
|
//# sourceMappingURL=data-model-field-type-list.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-model-field-type-list.js","sourceRoot":"","sources":["../../../src/components/field-sidebar/data-model-field-type-list.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAM,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"data-model-field-type-list.js","sourceRoot":"","sources":["../../../src/components/field-sidebar/data-model-field-type-list.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAM,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAmBrE,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,WAAmB,EAAE,EAAE,CACzD,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAE9C,MAAM,CAAC,MAAM,sBAAsB,GAAoC,CAAC,EACpE,eAAe,GAAG,EAAE,EACpB,gBAAgB,GAAG,EAAE,EACrB,KAAK,EACL,mBAAmB,GAAG,KAAK,EAC3B,SAAS,EACT,WAAW,EACX,YAAY,EACZ,YAAY,GAAG,IAAI,GACtB,EAAE,EAAE;IACD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpD,MAAM,SAAS,GAAG,CAAC,CAAC,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,CAAA,IAAI,CAAC,CAAC,YAAY,CAAC;IAEpD,MAAM,mBAAmB,GAAG,OAAO,CAAC,GAAG,EAAE;QACrC,IAAI,CAAC,WAAW,EAAE,CAAC;YACf,OAAO,eAAe,CAAC;QAC3B,CAAC;QAED,OAAO,eAAe;aACjB,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACX,GAAG,KAAK;YACR,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;SAChF,CAAC,CAAC;aACF,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClD,CAAC,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;IAEnC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,IAAI,CAAC,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,CAAA,EAAE,CAAC;YACjB,OAAO,EAAE,CAAC;QACd,CAAC;QACD,IAAI,CAAC,WAAW,EAAE,CAAC;YACf,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;IACvE,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;IAEzB,MAAM,wBAAwB,GAAG,OAAO,CAAC,GAAG,EAAE;QAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;YACf,OAAO,gBAAgB,CAAC;QAC5B,CAAC;QACD,OAAO,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;IACvF,CAAC,EAAE,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC,CAAC;IAEpC,MAAM,YAAY,GAAG,SAAS,IAAI,CAAC,CAAC,YAAY,CAAC;IAEjD,OAAO,CACH,MAAC,QAAQ,eACL,KAAC,WAAW,IACR,WAAW,EAAC,QAAQ,EACpB,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,0BAA0B,EACpC,QAAQ,EAAE,CAAC,CAAC,EAAE,WAAC,OAAA,aAAa,CAAC,MAAA,CAAC,CAAC,MAAM,CAAC,KAAK,mCAAI,EAAE,CAAC,CAAA,EAAA,GACpD,EACF,cAAK,SAAS,EAAC,iCAAiC,YAC5C,eACI,SAAS,EAAE,kCAAkC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,aAE9E,eAAK,SAAS,EAAC,iCAAiC,aAC3C,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAC9B,eAA2B,SAAS,EAAC,sBAAsB,aACvD,KAAC,IAAI,IACD,UAAU,EAAC,QAAQ,EACnB,GAAG,EAAE,CAAC,EACN,SAAS,EAAC,6BAA6B,YAEvC,KAAC,IAAI,IAAC,OAAO,EAAC,UAAU,EAAC,EAAE,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,YACxC,KAAK,CAAC,SAAS,GACb,GACJ,EACN,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE;4CAC5B,MAAM,GAAG,GAAG,GAAG,WAAW,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;4CACzE,OAAO,CACH,KAAC,SAAS,IAEN,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,EAC3C,KAAK,EAAE,WAAW,CAAC,KAAK,EACxB,UAAU,EAAE,kBAAkB,CAC1B,WAAW,CAAC,UAAU,EACtB,WAAW,CAAC,SAAS,CACxB,IAPI,GAAG,CAQV,CACL,CAAC;wCACN,CAAC,CAAC,KAxBI,KAAK,CAAC,SAAS,CAyBnB,CACT,CAAC,EACD,SAAS,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CACxD,KAAC,SAAS,IAAC,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,GAAI,CAClE,IACC,EAEN,cAAK,SAAS,EAAC,+CAA+C,YACzD,YAAY,IAAI,CACb,KAAC,eAAe,IACZ,IAAI,EAAE,YAAY,EAClB,YAAY,EAAE,wBAAwB,EACtC,eAAe,EACX,gBAAgB,CAAC,MAAM,GAAG,CAAC;oCAC3B,wBAAwB,CAAC,MAAM,KAAK,CAAC,EAEzC,SAAS,EAAE,mBAAmB,EAC9B,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAChC,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,WAAW,GAC1B,CACL,GACC,IACJ,GACJ,IACC,CACd,CAAC;AACN,CAAC,CAAC"}
|
|
@@ -2,6 +2,11 @@ import { FC } from 'react';
|
|
|
2
2
|
import { type DataModelFieldGroup, FieldTypeEnum, type FieldTypeOption, type FormInfo } from '../../interface/types';
|
|
3
3
|
interface FieldSidebarProps {
|
|
4
4
|
dataModelGroups?: DataModelFieldGroup[];
|
|
5
|
+
/**
|
|
6
|
+
* Forms listed as a group inside the Merge Tags tab (alongside the data model groups).
|
|
7
|
+
* Hidden when empty, when `onSelectForm` is missing, or when `hideFields` names
|
|
8
|
+
* `FieldTypeEnum.forms`.
|
|
9
|
+
*/
|
|
5
10
|
forms?: FormInfo[];
|
|
6
11
|
formFieldOptions?: FieldTypeOption[];
|
|
7
12
|
hideFields?: FieldTypeEnum[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/field-sidebar/field-sidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAqB,MAAM,OAAO,CAAC;AAG9C,OAAO,EACH,KAAK,mBAAmB,EACxB,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,QAAQ,EAChB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"field-sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/field-sidebar/field-sidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAqB,MAAM,OAAO,CAAC;AAG9C,OAAO,EACH,KAAK,mBAAmB,EACxB,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,QAAQ,EAChB,MAAM,uBAAuB,CAAC;AAQ/B,UAAU,iBAAiB;IACvB,eAAe,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACxC;;;;OAIG;IACH,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,SAAS,IAAI,IAAI,CAAC;IAClB,WAAW,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IAChD,YAAY,CAAC,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;CAC9C;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAkF9C,CAAC"}
|
|
@@ -10,7 +10,6 @@ import { DataModelFieldTypeList } from './data-model-field-type-list';
|
|
|
10
10
|
import { ESignFieldTypeList } from './e-sign-field-type-list';
|
|
11
11
|
import { FieldMenuGroup } from './field-menu-group';
|
|
12
12
|
import { FillableFieldTypeList } from './fillable-field-type-list';
|
|
13
|
-
import { FormFieldsTypeList } from './form-fields-type-list';
|
|
14
13
|
import { GenericFieldTypeList } from './generic-field-type-list';
|
|
15
14
|
export const FieldSidebar = ({ dataModelGroups = [], formFieldOptions = [], forms, hideFields, isLoadingFormFields = false, onDragEnd, onDragStart, onSelectForm, selectedForm = null, }) => {
|
|
16
15
|
var _a;
|
|
@@ -21,15 +20,13 @@ export const FieldSidebar = ({ dataModelGroups = [], formFieldOptions = [], form
|
|
|
21
20
|
open();
|
|
22
21
|
};
|
|
23
22
|
const filteredMenuGroups = useMemo(() => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
groups = groups.filter(menuGroup => !hideFields.includes(menuGroup.key));
|
|
23
|
+
if (!(hideFields === null || hideFields === void 0 ? void 0 : hideFields.length)) {
|
|
24
|
+
return menuGroups;
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}, [
|
|
33
|
-
return (_jsxs(Flex, { className: "dte-field-sidebar-container skeleton-item", children: [_jsx(FieldMenuGroup, { menuGroups: filteredMenuGroups, onClickMenu: handleActiveFieldTypeChange, activeFieldKey: activeFieldType }), _jsx(Flex, { className: `dte-field-sidebar-content skeleton-item ${isOpen ? '--open' : ''}`, shrink: 0, children: _jsxs(Flex, { className: "dte-field-sidebar-content-inner", children: [_jsx(Text, { variant: "headline", el: "h1", size: "medium", children: (_a = menuGroups.find(group => group.key === activeFieldType)) === null || _a === void 0 ? void 0 : _a.label }), activeFieldType === FieldTypeEnum.fillable && (_jsx(FillableFieldTypeList, { onDragStart: onDragStart, onDragEnd: onDragEnd })), activeFieldType === FieldTypeEnum.eSign && (_jsx(ESignFieldTypeList, { onDragEnd: onDragEnd, onDragStart: onDragStart })), activeFieldType === FieldTypeEnum.dataModel && (_jsx(DataModelFieldTypeList, { dataModelGroups: dataModelGroups, onDragStart: onDragStart, onDragEnd: onDragEnd })), activeFieldType === FieldTypeEnum.forms && forms && onSelectForm && (_jsx(FormFieldsTypeList, { fieldOptions: formFieldOptions, forms: forms, isLoadingFormFields: isLoadingFormFields, onDragEnd: onDragEnd, onDragStart: onDragStart, onSelectForm: onSelectForm, selectedForm: selectedForm })), activeFieldType === FieldTypeEnum.calculated && (_jsx(CalculatedFieldTypeList, { onDragStart: onDragStart, onDragEnd: onDragEnd })), activeFieldType === FieldTypeEnum.generic && (_jsx(GenericFieldTypeList, { onDragStart: onDragStart, onDragEnd: onDragEnd }))] }) }), _jsx(Button, { size: "small", appearance: "ghost", onClick: toggle, className: "dte-field-sidebar-toggler", children: _jsx(Icon, { svg: IconMenuOpen, size: "medium" }) })] }));
|
|
26
|
+
return menuGroups.filter(menuGroup => !hideFields.includes(menuGroup.key));
|
|
27
|
+
}, [hideFields]);
|
|
28
|
+
// The list itself hides the group when there are no forms or no selection handler.
|
|
29
|
+
const visibleForms = (hideFields === null || hideFields === void 0 ? void 0 : hideFields.includes(FieldTypeEnum.forms)) ? undefined : forms;
|
|
30
|
+
return (_jsxs(Flex, { className: "dte-field-sidebar-container skeleton-item", children: [_jsx(FieldMenuGroup, { menuGroups: filteredMenuGroups, onClickMenu: handleActiveFieldTypeChange, activeFieldKey: activeFieldType }), _jsx(Flex, { className: `dte-field-sidebar-content skeleton-item ${isOpen ? '--open' : ''}`, shrink: 0, children: _jsxs(Flex, { className: "dte-field-sidebar-content-inner", children: [_jsx(Text, { variant: "headline", el: "h1", size: "medium", children: (_a = menuGroups.find(group => group.key === activeFieldType)) === null || _a === void 0 ? void 0 : _a.label }), activeFieldType === FieldTypeEnum.fillable && (_jsx(FillableFieldTypeList, { onDragStart: onDragStart, onDragEnd: onDragEnd })), activeFieldType === FieldTypeEnum.eSign && (_jsx(ESignFieldTypeList, { onDragEnd: onDragEnd, onDragStart: onDragStart })), activeFieldType === FieldTypeEnum.dataModel && (_jsx(DataModelFieldTypeList, { dataModelGroups: dataModelGroups, forms: visibleForms, formFieldOptions: formFieldOptions, isLoadingFormFields: isLoadingFormFields, onDragStart: onDragStart, onDragEnd: onDragEnd, onSelectForm: onSelectForm, selectedForm: selectedForm })), activeFieldType === FieldTypeEnum.calculated && (_jsx(CalculatedFieldTypeList, { onDragStart: onDragStart, onDragEnd: onDragEnd })), activeFieldType === FieldTypeEnum.generic && (_jsx(GenericFieldTypeList, { onDragStart: onDragStart, onDragEnd: onDragEnd }))] }) }), _jsx(Button, { size: "small", appearance: "ghost", onClick: toggle, className: "dte-field-sidebar-toggler", children: _jsx(Icon, { svg: IconMenuOpen, size: "medium" }) })] }));
|
|
34
31
|
};
|
|
35
32
|
//# sourceMappingURL=field-sidebar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-sidebar.js","sourceRoot":"","sources":["../../../src/components/field-sidebar/field-sidebar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,YAAY,MAAM,gEAAgE,CAAC;AAC1F,OAAO,EAAM,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAEH,aAAa,GAGhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"field-sidebar.js","sourceRoot":"","sources":["../../../src/components/field-sidebar/field-sidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
2
|
import { type FieldTypeOption, type FormInfo } from '../../interface/types';
|
|
3
|
-
|
|
3
|
+
/** Heading of the Forms group inside the Merge Tags tab. */
|
|
4
|
+
export declare const FORMS_GROUP_NAME = "Forms";
|
|
5
|
+
export interface FormsListProps {
|
|
4
6
|
forms: FormInfo[];
|
|
5
|
-
|
|
7
|
+
/** Rendered when the (possibly search-filtered) list is empty. */
|
|
8
|
+
emptyText?: string;
|
|
9
|
+
onSelectForm(form: FormInfo): void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Root level of the Forms group: one clickable row per form. Selecting a form hands off to
|
|
13
|
+
* `FormFieldsPanel`, which lists that form's draggable fields.
|
|
14
|
+
*/
|
|
15
|
+
export declare const FormsList: FC<FormsListProps>;
|
|
16
|
+
export interface FormFieldsPanelProps {
|
|
17
|
+
form: FormInfo;
|
|
6
18
|
fieldOptions: FieldTypeOption[];
|
|
7
|
-
|
|
8
|
-
|
|
19
|
+
isLoading?: boolean;
|
|
20
|
+
/** Rendered when the form has fields but none match the current search. */
|
|
21
|
+
hasHiddenFields?: boolean;
|
|
22
|
+
onBack(): void;
|
|
9
23
|
onDragEnd(): void;
|
|
10
24
|
onDragStart(fieldOption: FieldTypeOption): void;
|
|
11
25
|
}
|
|
12
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Detail level of the Forms group: a back button naming the form, then its fields as the same
|
|
28
|
+
* draggable rows the data model groups use, so a form field drops onto the PDF like any merge tag.
|
|
29
|
+
*/
|
|
30
|
+
export declare const FormFieldsPanel: FC<FormFieldsPanelProps>;
|
|
13
31
|
//# sourceMappingURL=form-fields-type-list.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-fields-type-list.d.ts","sourceRoot":"","sources":["../../../src/components/field-sidebar/form-fields-type-list.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,EAAE,EAAY,MAAM,OAAO,CAAC;AACrC,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAI5E,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"form-fields-type-list.d.ts","sourceRoot":"","sources":["../../../src/components/field-sidebar/form-fields-type-list.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,EAAE,EAAY,MAAM,OAAO,CAAC;AACrC,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAI5E,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;CACtC;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CAwCxC,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,IAAI,IAAI,CAAC;IACf,SAAS,IAAI,IAAI,CAAC;IAClB,WAAW,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;CACnD;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CAoDpD,CAAC"}
|
|
@@ -5,10 +5,25 @@ import IconArrowForward from '@servicetitan/anvil2/assets/icons/material/round/k
|
|
|
5
5
|
import { Fragment } from 'react';
|
|
6
6
|
import { getFieldSampleData } from '../../utils';
|
|
7
7
|
import { FieldType } from './field-type';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
/** Heading of the Forms group inside the Merge Tags tab. */
|
|
9
|
+
export const FORMS_GROUP_NAME = 'Forms';
|
|
10
|
+
/**
|
|
11
|
+
* Root level of the Forms group: one clickable row per form. Selecting a form hands off to
|
|
12
|
+
* `FormFieldsPanel`, which lists that form's draggable fields.
|
|
13
|
+
*/
|
|
14
|
+
export const FormsList = ({ emptyText = 'No forms configured.', forms, onSelectForm, }) => {
|
|
15
|
+
return (_jsxs("div", { className: "dte-field-type-group", children: [_jsx(Flex, { alignItems: "center", gap: 1, className: "dte-field-type-group-header", children: _jsx(Text, { variant: "headline", el: "h6", size: "small", children: FORMS_GROUP_NAME }) }), forms.length > 0 ? (_jsx("ul", { className: "dte-formula-field-list", role: "listbox", "aria-label": FORMS_GROUP_NAME, children: forms.map(form => (_jsx("li", { role: "option", className: "dte-formula-field-list-item", onMouseDown: e => {
|
|
16
|
+
e.preventDefault();
|
|
17
|
+
onSelectForm(form);
|
|
18
|
+
}, children: _jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [_jsx("span", { className: "dte-text-ellipsis", title: form.name, children: form.name }), _jsx(IconArrowForward, {})] }) }, form.id))) })) : (_jsx(Text, { size: "small", subdued: true, variant: "body", children: emptyText }))] }));
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Detail level of the Forms group: a back button naming the form, then its fields as the same
|
|
22
|
+
* draggable rows the data model groups use, so a form field drops onto the PDF like any merge tag.
|
|
23
|
+
*/
|
|
24
|
+
export const FormFieldsPanel = ({ fieldOptions, form, hasHiddenFields = false, isLoading = false, onBack, onDragEnd, onDragStart, }) => {
|
|
25
|
+
return (_jsxs(Fragment, { children: [_jsx(Button, { style: { width: '100%' }, appearance: "ghost", size: "small", icon: IconArrowBack, title: form.name, onClick: onBack, children: _jsx(Text, { size: "medium", className: "dte-text-ellipsis", style: { fontWeight: 'bold', width: '100%' }, children: form.name }) }), _jsx("div", { className: "dte-field-type-group", children: isLoading ? (_jsx(Text, { size: "small", subdued: true, variant: "body", children: "Loading fields\u2026" })) : fieldOptions.length === 0 ? (_jsx(Text, { size: "small", subdued: true, variant: "body", children: hasHiddenFields
|
|
26
|
+
? 'No fields match the search.'
|
|
27
|
+
: 'No fields on this form.' })) : (fieldOptions.map(option => (_jsx(FieldType, { label: option.label, sampleData: getFieldSampleData(option.sampleData, option.fieldType), onDragEnd: onDragEnd, onDragStart: () => onDragStart(option) }, option.path)))) })] }));
|
|
13
28
|
};
|
|
14
29
|
//# sourceMappingURL=form-fields-type-list.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-fields-type-list.js","sourceRoot":"","sources":["../../../src/components/field-sidebar/form-fields-type-list.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,aAAa,MAAM,0EAA0E,CAAC;AACrG,OAAO,gBAAgB,MAAM,2EAA2E,CAAC;AACzG,OAAO,EAAM,QAAQ,EAAE,MAAM,OAAO,CAAC;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"form-fields-type-list.js","sourceRoot":"","sources":["../../../src/components/field-sidebar/form-fields-type-list.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-document-renderer.d.ts","sourceRoot":"","sources":["../../../src/components/pdf-canvas/pdf-document-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,OAAO,yCAAyC,CAAC;AACjD,OAAO,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"pdf-document-renderer.d.ts","sourceRoot":"","sources":["../../../src/components/pdf-canvas/pdf-document-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,OAAO,yCAAyC,CAAC;AACjD,OAAO,mCAAmC,CAAC;AAW3C,UAAU,wBAAwB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,kBAAkB,CAAC,EAAE,SAAS,CAAC;IAC/B,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;IAChD,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACnE;AAED,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,wBAAwB,CAmE5D,CAAC"}
|
|
@@ -3,7 +3,13 @@ import { Document, Page } from 'react-pdf';
|
|
|
3
3
|
import 'react-pdf/dist/Page/AnnotationLayer.css';
|
|
4
4
|
import 'react-pdf/dist/Page/TextLayer.css';
|
|
5
5
|
import { usePdfDocumentRenderer } from '../../hooks';
|
|
6
|
-
import '../../utils/pdf/pdfjs-init'; // Initialize PDF.js worker at a module load
|
|
6
|
+
import { PDFJS_WASM_URL } from '../../utils/pdf/pdfjs-init'; // Initialize PDF.js worker at a module load
|
|
7
|
+
/*
|
|
8
|
+
* Defined outside the component (per react-pdf's own guidance for `options`) so it's referentially
|
|
9
|
+
* stable across renders - passing a fresh object each render would make react-pdf treat the file as
|
|
10
|
+
* "changed" and reload the document.
|
|
11
|
+
*/
|
|
12
|
+
const documentOptions = { wasmUrl: PDFJS_WASM_URL };
|
|
7
13
|
export const PdfDocumentRenderer = ({ errorPlaceholder, loading, loadingPlaceholder, onDocumentLoadSuccess, onDragOver, onDrop, pageWidth, pdfUrl, }) => {
|
|
8
14
|
const { handleDocumentLoadSuccess: handleLoadSuccess, numPages, pages, } = usePdfDocumentRenderer();
|
|
9
15
|
const handleDocumentLoadSuccess = ({ numPages }) => {
|
|
@@ -19,7 +25,7 @@ export const PdfDocumentRenderer = ({ errorPlaceholder, loading, loadingPlacehol
|
|
|
19
25
|
e.stopPropagation();
|
|
20
26
|
onDragOver === null || onDragOver === void 0 ? void 0 : onDragOver(e);
|
|
21
27
|
};
|
|
22
|
-
return (_jsx(Document, { file: pdfUrl, error: errorPlaceholder, loading: loadingPlaceholder, onLoadSuccess: handleDocumentLoadSuccess, noData: loading ? loadingPlaceholder : undefined, children: pages.map(pageNumber => {
|
|
28
|
+
return (_jsx(Document, { file: pdfUrl, options: documentOptions, error: errorPlaceholder, loading: loadingPlaceholder, onLoadSuccess: handleDocumentLoadSuccess, noData: loading ? loadingPlaceholder : undefined, children: pages.map(pageNumber => {
|
|
23
29
|
return (_jsx("div", { "data-page-number": pageNumber, className: "dte-pdf-document-renderer-page", onDragOver: handlePageDragOver, onDrop: e => handlePageDrop(e, pageNumber), children: _jsx(Page, { loading: loadingPlaceholder, onLoadSuccess: e => {
|
|
24
30
|
if (e._pageIndex + 1 === numPages) {
|
|
25
31
|
onDocumentLoadSuccess === null || onDocumentLoadSuccess === void 0 ? void 0 : onDocumentLoadSuccess(numPages);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-document-renderer.js","sourceRoot":"","sources":["../../../src/components/pdf-canvas/pdf-document-renderer.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,yCAAyC,CAAC;AACjD,OAAO,mCAAmC,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,4BAA4B,CAAC,CAAC,4CAA4C;
|
|
1
|
+
{"version":3,"file":"pdf-document-renderer.js","sourceRoot":"","sources":["../../../src/components/pdf-canvas/pdf-document-renderer.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,yCAAyC,CAAC;AACjD,OAAO,mCAAmC,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC,CAAC,4CAA4C;AAEzG;;;;GAIG;AACH,MAAM,eAAe,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;AAapD,MAAM,CAAC,MAAM,mBAAmB,GAAiC,CAAC,EAC9D,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,MAAM,EACN,SAAS,EACT,MAAM,GACT,EAAE,EAAE;IACD,MAAM,EACF,yBAAyB,EAAE,iBAAiB,EAC5C,QAAQ,EACR,KAAK,GACR,GAAG,sBAAsB,EAAE,CAAC;IAE7B,MAAM,yBAAyB,GAAG,CAAC,EAAE,QAAQ,EAAwB,EAAE,EAAE;QACrE,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,CAA4B,EAAE,UAAkB,EAAE,EAAE;QACxE,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,CAAC,CAAC,eAAe,EAAE,CAAC;QACpB,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAG,CAAC,EAAE,UAAU,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,kBAAkB,GAAG,CAAC,CAA4B,EAAE,EAAE;QACxD,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,CAAC,CAAC,eAAe,EAAE,CAAC;QACpB,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC;IAEF,OAAO,CACH,KAAC,QAAQ,IACL,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,kBAAkB,EAC3B,aAAa,EAAE,yBAAyB,EACxC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,YAE/C,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;YACpB,OAAO,CACH,kCAEsB,UAAU,EAC5B,SAAS,EAAC,gCAAgC,EAC1C,UAAU,EAAE,kBAAkB,EAC9B,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,UAAU,CAAC,YAE1C,KAAC,IAAI,IACD,OAAO,EAAE,kBAAkB,EAC3B,aAAa,EAAE,CAAC,CAAC,EAAE;wBACf,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,KAAK,QAAQ,EAAE,CAAC;4BAChC,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAG,QAAQ,CAAC,CAAC;wBACtC,CAAC;oBACL,CAAC,EACD,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,SAAS,EAChB,eAAe,EAAE,KAAK,EACtB,qBAAqB,EAAE,KAAK,GAC9B,IAjBG,QAAQ,UAAU,EAAE,CAkBvB,CACT,CAAC;QACN,CAAC,CAAC,GACK,CACd,CAAC;AACN,CAAC,CAAC"}
|
|
@@ -4,5 +4,10 @@ export interface MenuGroupModel {
|
|
|
4
4
|
label: string;
|
|
5
5
|
key: FieldTypeEnum;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Sidebar tabs. Forms (`FieldTypeEnum.forms`) has no tab of its own: form fields are offered as a
|
|
9
|
+
* group inside Merge Tags, next to the data model groups. `hideFields: [FieldTypeEnum.forms]` still
|
|
10
|
+
* hides that group.
|
|
11
|
+
*/
|
|
7
12
|
export declare const menuGroups: MenuGroupModel[];
|
|
8
13
|
//# sourceMappingURL=menu-group.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-group.d.ts","sourceRoot":"","sources":["../../src/constants/menu-group.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"menu-group.d.ts","sourceRoot":"","sources":["../../src/constants/menu-group.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,GAAG,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,aAAa,CAAC;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,cAAc,EAkBtC,CAAC"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import IconBorderColor from '@servicetitan/anvil2/assets/icons/material/round/border_color.svg';
|
|
2
2
|
import IconCalculate from '@servicetitan/anvil2/assets/icons/material/round/calculate.svg';
|
|
3
|
-
import IconFactCheck from '@servicetitan/anvil2/assets/icons/material/round/fact_check.svg';
|
|
4
3
|
import IconPhotoSizeSelectSmall from '@servicetitan/anvil2/assets/icons/material/round/photo_size_select_small.svg';
|
|
5
4
|
import IconCommercial from '@servicetitan/anvil2/assets/icons/st/commercial.svg';
|
|
6
5
|
import IconEstimate from '@servicetitan/anvil2/assets/icons/st/estimate.svg';
|
|
7
6
|
import { FieldTypeEnum } from '../interface/types';
|
|
7
|
+
/**
|
|
8
|
+
* Sidebar tabs. Forms (`FieldTypeEnum.forms`) has no tab of its own: form fields are offered as a
|
|
9
|
+
* group inside Merge Tags, next to the data model groups. `hideFields: [FieldTypeEnum.forms]` still
|
|
10
|
+
* hides that group.
|
|
11
|
+
*/
|
|
8
12
|
export const menuGroups = [
|
|
9
13
|
{ svgIcon: IconEstimate, label: 'Merge Tags', key: FieldTypeEnum.dataModel },
|
|
10
14
|
{ svgIcon: IconBorderColor, label: 'E-Sign', key: FieldTypeEnum.eSign },
|
|
@@ -23,6 +27,5 @@ export const menuGroups = [
|
|
|
23
27
|
label: 'Generic Fields',
|
|
24
28
|
key: FieldTypeEnum.generic,
|
|
25
29
|
},
|
|
26
|
-
{ svgIcon: IconFactCheck, label: 'Forms', key: FieldTypeEnum.forms },
|
|
27
30
|
];
|
|
28
31
|
//# sourceMappingURL=menu-group.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-group.js","sourceRoot":"","sources":["../../src/constants/menu-group.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,mEAAmE,CAAC;AAChG,OAAO,aAAa,MAAM,gEAAgE,CAAC;AAC3F,OAAO,
|
|
1
|
+
{"version":3,"file":"menu-group.js","sourceRoot":"","sources":["../../src/constants/menu-group.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,mEAAmE,CAAC;AAChG,OAAO,aAAa,MAAM,gEAAgE,CAAC;AAC3F,OAAO,wBAAwB,MAAM,8EAA8E,CAAC;AACpH,OAAO,cAAc,MAAM,qDAAqD,CAAC;AACjF,OAAO,YAAY,MAAM,mDAAmD,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAQnD;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAqB;IACxC,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,CAAC,SAAS,EAAE;IAC5E,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,CAAC,KAAK,EAAE;IACvE;QACI,OAAO,EAAE,wBAAwB;QACjC,KAAK,EAAE,iBAAiB;QACxB,GAAG,EAAE,aAAa,CAAC,QAAQ;KAC9B;IACD;QACI,OAAO,EAAE,aAAa;QACtB,KAAK,EAAE,mBAAmB;QAC1B,GAAG,EAAE,aAAa,CAAC,UAAU;KAChC;IACD;QACI,OAAO,EAAE,cAAc;QACvB,KAAK,EAAE,gBAAgB;QACvB,GAAG,EAAE,aAAa,CAAC,OAAO;KAC7B;CACJ,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const PDFJS_WASM_URL: string;
|
|
2
2
|
//# sourceMappingURL=pdfjs-init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdfjs-init.d.ts","sourceRoot":"","sources":["../../../src/utils/pdf/pdfjs-init.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"pdfjs-init.d.ts","sourceRoot":"","sources":["../../../src/utils/pdf/pdfjs-init.ts"],"names":[],"mappings":"AAwCA,eAAO,MAAM,cAAc,QAAwD,CAAC"}
|
|
@@ -25,4 +25,14 @@ if (typeof window !== 'undefined' &&
|
|
|
25
25
|
pdfjs.GlobalWorkerOptions.workerSrc === 'pdf.worker.mjs')) {
|
|
26
26
|
pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
27
27
|
}
|
|
28
|
+
/*
|
|
29
|
+
* pdfjs-dist 5.x moved its wasm-backed image codecs (OpenJPEG for JPX/JPEG2000, JBIG2, qcms)
|
|
30
|
+
* out of build/ into a sibling wasm/ directory, gated behind the `wasmUrl` document-load option.
|
|
31
|
+
* That option defaults to null, and the worker builds each fetch path as `${wasmUrl}<file>` -
|
|
32
|
+
* so with no wasmUrl set it literally tries to import "nullopenjpeg_nowasm_fallback.js" and the
|
|
33
|
+
* JPX decoder throws, silently dropping any JPEG2000 image in the PDF. Point it at the same
|
|
34
|
+
* unpkg-hosted version's wasm/ folder (must end with a trailing slash - it's string-concatenated
|
|
35
|
+
* with the filename, not resolved as a URL).
|
|
36
|
+
*/
|
|
37
|
+
export const PDFJS_WASM_URL = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/wasm/`;
|
|
28
38
|
//# sourceMappingURL=pdfjs-init.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdfjs-init.js","sourceRoot":"","sources":["../../../src/utils/pdf/pdfjs-init.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC;;;;;;;;;;;;GAYG;AACH,IACI,OAAO,MAAM,KAAK,WAAW;IAC7B,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,SAAS;QACjC,KAAK,CAAC,mBAAmB,CAAC,SAAS,KAAK,gBAAgB,CAAC,EAC/D,CAAC;IACC,KAAK,CAAC,mBAAmB,CAAC,SAAS,GAAG,gCAAgC,KAAK,CAAC,OAAO,2BAA2B,CAAC;AACnH,CAAC"}
|
|
1
|
+
{"version":3,"file":"pdfjs-init.js","sourceRoot":"","sources":["../../../src/utils/pdf/pdfjs-init.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC;;;;;;;;;;;;GAYG;AACH,IACI,OAAO,MAAM,KAAK,WAAW;IAC7B,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,SAAS;QACjC,KAAK,CAAC,mBAAmB,CAAC,SAAS,KAAK,gBAAgB,CAAC,EAC/D,CAAC;IACC,KAAK,CAAC,mBAAmB,CAAC,SAAS,GAAG,gCAAgC,KAAK,CAAC,OAAO,2BAA2B,CAAC;AACnH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gCAAgC,KAAK,CAAC,OAAO,QAAQ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,37 +1,80 @@
|
|
|
1
1
|
import { Flex, SearchField, Text } from '@servicetitan/anvil2';
|
|
2
2
|
import { FC, Fragment, useMemo, useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type DataModelFieldGroup,
|
|
5
|
+
type FieldTypeOption,
|
|
6
|
+
type FormInfo,
|
|
7
|
+
} from '../../interface/types';
|
|
4
8
|
import { getFieldSampleData } from '../../utils';
|
|
5
9
|
import { FieldType } from './field-type';
|
|
10
|
+
import { FormFieldsPanel, FormsList } from './form-fields-type-list';
|
|
6
11
|
|
|
7
12
|
interface DataModelFieldTypeListProps {
|
|
8
13
|
dataModelGroups?: DataModelFieldGroup[];
|
|
14
|
+
/**
|
|
15
|
+
* Forms offered as a group after the data model groups. Omitted (or empty) hides the group;
|
|
16
|
+
* `onSelectForm` must be provided for the group to render.
|
|
17
|
+
*/
|
|
18
|
+
forms?: FormInfo[];
|
|
19
|
+
/** The form whose fields are shown in place of the group list; null shows the group list. */
|
|
20
|
+
selectedForm?: FormInfo | null;
|
|
21
|
+
/** Draggable options for `selectedForm`. */
|
|
22
|
+
formFieldOptions?: FieldTypeOption[];
|
|
23
|
+
isLoadingFormFields?: boolean;
|
|
24
|
+
onSelectForm?(form: FormInfo | null): void;
|
|
9
25
|
onDragStart(fieldOption: FieldTypeOption): void;
|
|
10
26
|
onDragEnd(): void;
|
|
11
27
|
}
|
|
12
28
|
|
|
29
|
+
const matchesSearch = (label: string, searchLower: string) =>
|
|
30
|
+
label.toLowerCase().includes(searchLower);
|
|
31
|
+
|
|
13
32
|
export const DataModelFieldTypeList: FC<DataModelFieldTypeListProps> = ({
|
|
14
33
|
dataModelGroups = [],
|
|
34
|
+
formFieldOptions = [],
|
|
35
|
+
forms,
|
|
36
|
+
isLoadingFormFields = false,
|
|
15
37
|
onDragEnd,
|
|
16
38
|
onDragStart,
|
|
39
|
+
onSelectForm,
|
|
40
|
+
selectedForm = null,
|
|
17
41
|
}) => {
|
|
18
42
|
const [searchText, setSearchText] = useState('');
|
|
43
|
+
const searchLower = searchText.trim().toLowerCase();
|
|
44
|
+
const showForms = !!forms?.length && !!onSelectForm;
|
|
19
45
|
|
|
20
46
|
const searchedFieldGroups = useMemo(() => {
|
|
21
|
-
if (!
|
|
47
|
+
if (!searchLower) {
|
|
22
48
|
return dataModelGroups;
|
|
23
49
|
}
|
|
24
50
|
|
|
25
|
-
const searchLower = searchText.toLowerCase();
|
|
26
51
|
return dataModelGroups
|
|
27
52
|
.map(group => ({
|
|
28
53
|
...group,
|
|
29
|
-
fields: group.fields.filter(({ label }) =>
|
|
30
|
-
label.toLowerCase().includes(searchLower),
|
|
31
|
-
),
|
|
54
|
+
fields: group.fields.filter(({ label }) => matchesSearch(label, searchLower)),
|
|
32
55
|
}))
|
|
33
56
|
.filter(group => group.fields.length > 0);
|
|
34
|
-
}, [dataModelGroups,
|
|
57
|
+
}, [dataModelGroups, searchLower]);
|
|
58
|
+
|
|
59
|
+
const searchedForms = useMemo(() => {
|
|
60
|
+
if (!forms?.length) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
if (!searchLower) {
|
|
64
|
+
return forms;
|
|
65
|
+
}
|
|
66
|
+
return forms.filter(form => matchesSearch(form.name, searchLower));
|
|
67
|
+
}, [forms, searchLower]);
|
|
68
|
+
|
|
69
|
+
const searchedFormFieldOptions = useMemo(() => {
|
|
70
|
+
if (!searchLower) {
|
|
71
|
+
return formFieldOptions;
|
|
72
|
+
}
|
|
73
|
+
return formFieldOptions.filter(option => matchesSearch(option.label, searchLower));
|
|
74
|
+
}, [formFieldOptions, searchLower]);
|
|
75
|
+
|
|
76
|
+
const isFormDetail = showForms && !!selectedForm;
|
|
77
|
+
|
|
35
78
|
return (
|
|
36
79
|
<Fragment>
|
|
37
80
|
<SearchField
|
|
@@ -40,30 +83,62 @@ export const DataModelFieldTypeList: FC<DataModelFieldTypeListProps> = ({
|
|
|
40
83
|
className="dte-field-sidebar-search"
|
|
41
84
|
onChange={e => setSearchText(e.target.value ?? '')}
|
|
42
85
|
/>
|
|
43
|
-
|
|
44
|
-
<div
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
86
|
+
<div className="dte-formula-sidebar-slide-outer">
|
|
87
|
+
<div
|
|
88
|
+
className={`dte-formula-sidebar-slide-track${isFormDetail ? ' --detail' : ''}`}
|
|
89
|
+
>
|
|
90
|
+
<div className="dte-formula-sidebar-slide-panel">
|
|
91
|
+
{searchedFieldGroups.map(group => (
|
|
92
|
+
<div key={group.groupName} className="dte-field-type-group">
|
|
93
|
+
<Flex
|
|
94
|
+
alignItems="center"
|
|
95
|
+
gap={1}
|
|
96
|
+
className="dte-field-type-group-header"
|
|
97
|
+
>
|
|
98
|
+
<Text variant="headline" el="h6" size="small">
|
|
99
|
+
{group.groupName}
|
|
100
|
+
</Text>
|
|
101
|
+
</Flex>
|
|
102
|
+
{group.fields.map(fieldOption => {
|
|
103
|
+
const key = `${fieldOption.type}-${group.groupName}-${fieldOption.path}`;
|
|
104
|
+
return (
|
|
105
|
+
<FieldType
|
|
106
|
+
key={key}
|
|
107
|
+
onDragEnd={onDragEnd}
|
|
108
|
+
onDragStart={() => onDragStart(fieldOption)}
|
|
109
|
+
label={fieldOption.label}
|
|
110
|
+
sampleData={getFieldSampleData(
|
|
111
|
+
fieldOption.sampleData,
|
|
112
|
+
fieldOption.fieldType,
|
|
113
|
+
)}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
})}
|
|
117
|
+
</div>
|
|
118
|
+
))}
|
|
119
|
+
{showForms && (searchedForms.length > 0 || !searchLower) && (
|
|
120
|
+
<FormsList forms={searchedForms} onSelectForm={onSelectForm} />
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<div className="dte-formula-sidebar-slide-panel --form-fields">
|
|
125
|
+
{isFormDetail && (
|
|
126
|
+
<FormFieldsPanel
|
|
127
|
+
form={selectedForm}
|
|
128
|
+
fieldOptions={searchedFormFieldOptions}
|
|
129
|
+
hasHiddenFields={
|
|
130
|
+
formFieldOptions.length > 0 &&
|
|
131
|
+
searchedFormFieldOptions.length === 0
|
|
132
|
+
}
|
|
133
|
+
isLoading={isLoadingFormFields}
|
|
134
|
+
onBack={() => onSelectForm(null)}
|
|
55
135
|
onDragEnd={onDragEnd}
|
|
56
|
-
onDragStart={
|
|
57
|
-
label={fieldOption.label}
|
|
58
|
-
sampleData={getFieldSampleData(
|
|
59
|
-
fieldOption.sampleData,
|
|
60
|
-
fieldOption.fieldType,
|
|
61
|
-
)}
|
|
136
|
+
onDragStart={onDragStart}
|
|
62
137
|
/>
|
|
63
|
-
)
|
|
64
|
-
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
65
140
|
</div>
|
|
66
|
-
|
|
141
|
+
</div>
|
|
67
142
|
</Fragment>
|
|
68
143
|
);
|
|
69
144
|
};
|
|
@@ -14,11 +14,15 @@ import { DataModelFieldTypeList } from './data-model-field-type-list';
|
|
|
14
14
|
import { ESignFieldTypeList } from './e-sign-field-type-list';
|
|
15
15
|
import { FieldMenuGroup } from './field-menu-group';
|
|
16
16
|
import { FillableFieldTypeList } from './fillable-field-type-list';
|
|
17
|
-
import { FormFieldsTypeList } from './form-fields-type-list';
|
|
18
17
|
import { GenericFieldTypeList } from './generic-field-type-list';
|
|
19
18
|
|
|
20
19
|
interface FieldSidebarProps {
|
|
21
20
|
dataModelGroups?: DataModelFieldGroup[];
|
|
21
|
+
/**
|
|
22
|
+
* Forms listed as a group inside the Merge Tags tab (alongside the data model groups).
|
|
23
|
+
* Hidden when empty, when `onSelectForm` is missing, or when `hideFields` names
|
|
24
|
+
* `FieldTypeEnum.forms`.
|
|
25
|
+
*/
|
|
22
26
|
forms?: FormInfo[];
|
|
23
27
|
formFieldOptions?: FieldTypeOption[];
|
|
24
28
|
hideFields?: FieldTypeEnum[];
|
|
@@ -49,15 +53,14 @@ export const FieldSidebar: FC<FieldSidebarProps> = ({
|
|
|
49
53
|
};
|
|
50
54
|
|
|
51
55
|
const filteredMenuGroups = useMemo(() => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
groups = groups.filter(menuGroup => !hideFields.includes(menuGroup.key));
|
|
56
|
+
if (!hideFields?.length) {
|
|
57
|
+
return menuGroups;
|
|
55
58
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
return menuGroups.filter(menuGroup => !hideFields.includes(menuGroup.key));
|
|
60
|
+
}, [hideFields]);
|
|
61
|
+
|
|
62
|
+
// The list itself hides the group when there are no forms or no selection handler.
|
|
63
|
+
const visibleForms = hideFields?.includes(FieldTypeEnum.forms) ? undefined : forms;
|
|
61
64
|
|
|
62
65
|
return (
|
|
63
66
|
<Flex className="dte-field-sidebar-container skeleton-item">
|
|
@@ -85,17 +88,11 @@ export const FieldSidebar: FC<FieldSidebarProps> = ({
|
|
|
85
88
|
{activeFieldType === FieldTypeEnum.dataModel && (
|
|
86
89
|
<DataModelFieldTypeList
|
|
87
90
|
dataModelGroups={dataModelGroups}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
/>
|
|
91
|
-
)}
|
|
92
|
-
{activeFieldType === FieldTypeEnum.forms && forms && onSelectForm && (
|
|
93
|
-
<FormFieldsTypeList
|
|
94
|
-
fieldOptions={formFieldOptions}
|
|
95
|
-
forms={forms}
|
|
91
|
+
forms={visibleForms}
|
|
92
|
+
formFieldOptions={formFieldOptions}
|
|
96
93
|
isLoadingFormFields={isLoadingFormFields}
|
|
97
|
-
onDragEnd={onDragEnd}
|
|
98
94
|
onDragStart={onDragStart}
|
|
95
|
+
onDragEnd={onDragEnd}
|
|
99
96
|
onSelectForm={onSelectForm}
|
|
100
97
|
selectedForm={selectedForm}
|
|
101
98
|
/>
|
|
@@ -6,112 +6,127 @@ import { type FieldTypeOption, type FormInfo } from '../../interface/types';
|
|
|
6
6
|
import { getFieldSampleData } from '../../utils';
|
|
7
7
|
import { FieldType } from './field-type';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/** Heading of the Forms group inside the Merge Tags tab. */
|
|
10
|
+
export const FORMS_GROUP_NAME = 'Forms';
|
|
11
|
+
|
|
12
|
+
export interface FormsListProps {
|
|
10
13
|
forms: FormInfo[];
|
|
11
|
-
|
|
14
|
+
/** Rendered when the (possibly search-filtered) list is empty. */
|
|
15
|
+
emptyText?: string;
|
|
16
|
+
onSelectForm(form: FormInfo): void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Root level of the Forms group: one clickable row per form. Selecting a form hands off to
|
|
21
|
+
* `FormFieldsPanel`, which lists that form's draggable fields.
|
|
22
|
+
*/
|
|
23
|
+
export const FormsList: FC<FormsListProps> = ({
|
|
24
|
+
emptyText = 'No forms configured.',
|
|
25
|
+
forms,
|
|
26
|
+
onSelectForm,
|
|
27
|
+
}) => {
|
|
28
|
+
return (
|
|
29
|
+
<div className="dte-field-type-group">
|
|
30
|
+
<Flex alignItems="center" gap={1} className="dte-field-type-group-header">
|
|
31
|
+
<Text variant="headline" el="h6" size="small">
|
|
32
|
+
{FORMS_GROUP_NAME}
|
|
33
|
+
</Text>
|
|
34
|
+
</Flex>
|
|
35
|
+
{forms.length > 0 ? (
|
|
36
|
+
<ul className="dte-formula-field-list" role="listbox" aria-label={FORMS_GROUP_NAME}>
|
|
37
|
+
{forms.map(form => (
|
|
38
|
+
<li
|
|
39
|
+
key={form.id}
|
|
40
|
+
role="option"
|
|
41
|
+
className="dte-formula-field-list-item"
|
|
42
|
+
onMouseDown={e => {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
onSelectForm(form);
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
<Flex justifyContent="space-between" alignItems="center">
|
|
48
|
+
<span className="dte-text-ellipsis" title={form.name}>
|
|
49
|
+
{form.name}
|
|
50
|
+
</span>
|
|
51
|
+
<IconArrowForward />
|
|
52
|
+
</Flex>
|
|
53
|
+
</li>
|
|
54
|
+
))}
|
|
55
|
+
</ul>
|
|
56
|
+
) : (
|
|
57
|
+
<Text size="small" subdued variant="body">
|
|
58
|
+
{emptyText}
|
|
59
|
+
</Text>
|
|
60
|
+
)}
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export interface FormFieldsPanelProps {
|
|
66
|
+
form: FormInfo;
|
|
12
67
|
fieldOptions: FieldTypeOption[];
|
|
13
|
-
|
|
14
|
-
|
|
68
|
+
isLoading?: boolean;
|
|
69
|
+
/** Rendered when the form has fields but none match the current search. */
|
|
70
|
+
hasHiddenFields?: boolean;
|
|
71
|
+
onBack(): void;
|
|
15
72
|
onDragEnd(): void;
|
|
16
73
|
onDragStart(fieldOption: FieldTypeOption): void;
|
|
17
74
|
}
|
|
18
75
|
|
|
19
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Detail level of the Forms group: a back button naming the form, then its fields as the same
|
|
78
|
+
* draggable rows the data model groups use, so a form field drops onto the PDF like any merge tag.
|
|
79
|
+
*/
|
|
80
|
+
export const FormFieldsPanel: FC<FormFieldsPanelProps> = ({
|
|
20
81
|
fieldOptions,
|
|
21
|
-
|
|
22
|
-
|
|
82
|
+
form,
|
|
83
|
+
hasHiddenFields = false,
|
|
84
|
+
isLoading = false,
|
|
85
|
+
onBack,
|
|
23
86
|
onDragEnd,
|
|
24
87
|
onDragStart,
|
|
25
|
-
onSelectForm,
|
|
26
|
-
selectedForm,
|
|
27
88
|
}) => {
|
|
28
89
|
return (
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
90
|
+
<Fragment>
|
|
91
|
+
<Button
|
|
92
|
+
style={{ width: '100%' }}
|
|
93
|
+
appearance="ghost"
|
|
94
|
+
size="small"
|
|
95
|
+
icon={IconArrowBack}
|
|
96
|
+
title={form.name}
|
|
97
|
+
onClick={onBack}
|
|
98
|
+
>
|
|
99
|
+
<Text
|
|
100
|
+
size="medium"
|
|
101
|
+
className="dte-text-ellipsis"
|
|
102
|
+
style={{ fontWeight: 'bold', width: '100%' }}
|
|
33
103
|
>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
</ul>
|
|
60
|
-
) : (
|
|
61
|
-
<Text size="small" subdued variant="body">
|
|
62
|
-
No forms configured.
|
|
63
|
-
</Text>
|
|
64
|
-
)}
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
<div className="dte-formula-sidebar-slide-panel --form-fields">
|
|
68
|
-
{selectedForm ? (
|
|
69
|
-
<Fragment>
|
|
70
|
-
<Button
|
|
71
|
-
style={{ width: '100%' }}
|
|
72
|
-
appearance="ghost"
|
|
73
|
-
size="small"
|
|
74
|
-
icon={IconArrowBack}
|
|
75
|
-
title={selectedForm.name}
|
|
76
|
-
onClick={() => onSelectForm(null)}
|
|
77
|
-
>
|
|
78
|
-
<Text
|
|
79
|
-
size="medium"
|
|
80
|
-
className="dte-text-ellipsis"
|
|
81
|
-
style={{ fontWeight: 'bold', width: '100%' }}
|
|
82
|
-
>
|
|
83
|
-
{selectedForm.name}
|
|
84
|
-
</Text>
|
|
85
|
-
</Button>
|
|
86
|
-
<div className="dte-field-type-group">
|
|
87
|
-
{isLoadingFormFields ? (
|
|
88
|
-
<Text size="small" subdued variant="body">
|
|
89
|
-
Loading fields…
|
|
90
|
-
</Text>
|
|
91
|
-
) : fieldOptions.length === 0 ? (
|
|
92
|
-
<Text size="small" subdued variant="body">
|
|
93
|
-
No fields on this form.
|
|
94
|
-
</Text>
|
|
95
|
-
) : (
|
|
96
|
-
fieldOptions.map(option => (
|
|
97
|
-
<FieldType
|
|
98
|
-
key={option.path}
|
|
99
|
-
label={option.label}
|
|
100
|
-
sampleData={getFieldSampleData(
|
|
101
|
-
option.sampleData,
|
|
102
|
-
option.fieldType,
|
|
103
|
-
)}
|
|
104
|
-
onDragEnd={onDragEnd}
|
|
105
|
-
onDragStart={() => onDragStart(option)}
|
|
106
|
-
/>
|
|
107
|
-
))
|
|
108
|
-
)}
|
|
109
|
-
</div>
|
|
110
|
-
</Fragment>
|
|
111
|
-
) : null}
|
|
112
|
-
</div>
|
|
113
|
-
</div>
|
|
104
|
+
{form.name}
|
|
105
|
+
</Text>
|
|
106
|
+
</Button>
|
|
107
|
+
<div className="dte-field-type-group">
|
|
108
|
+
{isLoading ? (
|
|
109
|
+
<Text size="small" subdued variant="body">
|
|
110
|
+
Loading fields…
|
|
111
|
+
</Text>
|
|
112
|
+
) : fieldOptions.length === 0 ? (
|
|
113
|
+
<Text size="small" subdued variant="body">
|
|
114
|
+
{hasHiddenFields
|
|
115
|
+
? 'No fields match the search.'
|
|
116
|
+
: 'No fields on this form.'}
|
|
117
|
+
</Text>
|
|
118
|
+
) : (
|
|
119
|
+
fieldOptions.map(option => (
|
|
120
|
+
<FieldType
|
|
121
|
+
key={option.path}
|
|
122
|
+
label={option.label}
|
|
123
|
+
sampleData={getFieldSampleData(option.sampleData, option.fieldType)}
|
|
124
|
+
onDragEnd={onDragEnd}
|
|
125
|
+
onDragStart={() => onDragStart(option)}
|
|
126
|
+
/>
|
|
127
|
+
))
|
|
128
|
+
)}
|
|
114
129
|
</div>
|
|
115
|
-
</
|
|
130
|
+
</Fragment>
|
|
116
131
|
);
|
|
117
132
|
};
|
|
@@ -3,7 +3,14 @@ import { Document, Page } from 'react-pdf';
|
|
|
3
3
|
import 'react-pdf/dist/Page/AnnotationLayer.css';
|
|
4
4
|
import 'react-pdf/dist/Page/TextLayer.css';
|
|
5
5
|
import { usePdfDocumentRenderer } from '../../hooks';
|
|
6
|
-
import '../../utils/pdf/pdfjs-init'; // Initialize PDF.js worker at a module load
|
|
6
|
+
import { PDFJS_WASM_URL } from '../../utils/pdf/pdfjs-init'; // Initialize PDF.js worker at a module load
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Defined outside the component (per react-pdf's own guidance for `options`) so it's referentially
|
|
10
|
+
* stable across renders - passing a fresh object each render would make react-pdf treat the file as
|
|
11
|
+
* "changed" and reload the document.
|
|
12
|
+
*/
|
|
13
|
+
const documentOptions = { wasmUrl: PDFJS_WASM_URL };
|
|
7
14
|
|
|
8
15
|
interface PdfDocumentRendererProps {
|
|
9
16
|
pdfUrl: string;
|
|
@@ -51,6 +58,7 @@ export const PdfDocumentRenderer: FC<PdfDocumentRendererProps> = ({
|
|
|
51
58
|
return (
|
|
52
59
|
<Document
|
|
53
60
|
file={pdfUrl}
|
|
61
|
+
options={documentOptions}
|
|
54
62
|
error={errorPlaceholder}
|
|
55
63
|
loading={loadingPlaceholder}
|
|
56
64
|
onLoadSuccess={handleDocumentLoadSuccess}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import IconBorderColor from '@servicetitan/anvil2/assets/icons/material/round/border_color.svg';
|
|
2
2
|
import IconCalculate from '@servicetitan/anvil2/assets/icons/material/round/calculate.svg';
|
|
3
|
-
import IconFactCheck from '@servicetitan/anvil2/assets/icons/material/round/fact_check.svg';
|
|
4
3
|
import IconPhotoSizeSelectSmall from '@servicetitan/anvil2/assets/icons/material/round/photo_size_select_small.svg';
|
|
5
4
|
import IconCommercial from '@servicetitan/anvil2/assets/icons/st/commercial.svg';
|
|
6
5
|
import IconEstimate from '@servicetitan/anvil2/assets/icons/st/estimate.svg';
|
|
@@ -12,6 +11,11 @@ export interface MenuGroupModel {
|
|
|
12
11
|
key: FieldTypeEnum;
|
|
13
12
|
}
|
|
14
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Sidebar tabs. Forms (`FieldTypeEnum.forms`) has no tab of its own: form fields are offered as a
|
|
16
|
+
* group inside Merge Tags, next to the data model groups. `hideFields: [FieldTypeEnum.forms]` still
|
|
17
|
+
* hides that group.
|
|
18
|
+
*/
|
|
15
19
|
export const menuGroups: MenuGroupModel[] = [
|
|
16
20
|
{ svgIcon: IconEstimate, label: 'Merge Tags', key: FieldTypeEnum.dataModel },
|
|
17
21
|
{ svgIcon: IconBorderColor, label: 'E-Sign', key: FieldTypeEnum.eSign },
|
|
@@ -30,5 +34,4 @@ export const menuGroups: MenuGroupModel[] = [
|
|
|
30
34
|
label: 'Generic Fields',
|
|
31
35
|
key: FieldTypeEnum.generic,
|
|
32
36
|
},
|
|
33
|
-
{ svgIcon: IconFactCheck, label: 'Forms', key: FieldTypeEnum.forms },
|
|
34
37
|
];
|
|
@@ -28,3 +28,14 @@ if (
|
|
|
28
28
|
) {
|
|
29
29
|
pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* pdfjs-dist 5.x moved its wasm-backed image codecs (OpenJPEG for JPX/JPEG2000, JBIG2, qcms)
|
|
34
|
+
* out of build/ into a sibling wasm/ directory, gated behind the `wasmUrl` document-load option.
|
|
35
|
+
* That option defaults to null, and the worker builds each fetch path as `${wasmUrl}<file>` -
|
|
36
|
+
* so with no wasmUrl set it literally tries to import "nullopenjpeg_nowasm_fallback.js" and the
|
|
37
|
+
* JPX decoder throws, silently dropping any JPEG2000 image in the PDF. Point it at the same
|
|
38
|
+
* unpkg-hosted version's wasm/ folder (must end with a trailing slash - it's string-concatenated
|
|
39
|
+
* with the filename, not resolved as a URL).
|
|
40
|
+
*/
|
|
41
|
+
export const PDFJS_WASM_URL = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/wasm/`;
|