@servicetitan/dte-unlayer 0.94.0 → 0.95.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.
Files changed (68) hide show
  1. package/dist/display-conditions/ConditionGroup.d.ts +12 -0
  2. package/dist/display-conditions/ConditionGroup.d.ts.map +1 -0
  3. package/dist/display-conditions/ConditionGroup.js +181 -0
  4. package/dist/display-conditions/ConditionGroup.js.map +1 -0
  5. package/dist/display-conditions/ConditionGroupsSection.d.ts +11 -0
  6. package/dist/display-conditions/ConditionGroupsSection.d.ts.map +1 -0
  7. package/dist/display-conditions/ConditionGroupsSection.js +71 -0
  8. package/dist/display-conditions/ConditionGroupsSection.js.map +1 -0
  9. package/dist/display-conditions/ConditionRow.d.ts +11 -0
  10. package/dist/display-conditions/ConditionRow.d.ts.map +1 -0
  11. package/dist/display-conditions/ConditionRow.js +206 -0
  12. package/dist/display-conditions/ConditionRow.js.map +1 -0
  13. package/dist/display-conditions/DisplayConditionModal.d.ts +5 -0
  14. package/dist/display-conditions/DisplayConditionModal.d.ts.map +1 -0
  15. package/dist/display-conditions/DisplayConditionModal.js +282 -0
  16. package/dist/display-conditions/DisplayConditionModal.js.map +1 -0
  17. package/dist/display-conditions/SeparatorWithChip.d.ts +6 -0
  18. package/dist/display-conditions/SeparatorWithChip.d.ts.map +1 -0
  19. package/dist/display-conditions/SeparatorWithChip.js +15 -0
  20. package/dist/display-conditions/SeparatorWithChip.js.map +1 -0
  21. package/dist/display-conditions/constants.d.ts +7 -0
  22. package/dist/display-conditions/constants.d.ts.map +1 -0
  23. package/dist/display-conditions/constants.js +22 -0
  24. package/dist/display-conditions/constants.js.map +1 -0
  25. package/dist/display-conditions/displayConditionController.d.ts +9 -0
  26. package/dist/display-conditions/displayConditionController.d.ts.map +1 -0
  27. package/dist/display-conditions/displayConditionController.js +29 -0
  28. package/dist/display-conditions/displayConditionController.js.map +1 -0
  29. package/dist/display-conditions/nunjucks.d.ts +8 -0
  30. package/dist/display-conditions/nunjucks.d.ts.map +1 -0
  31. package/dist/display-conditions/nunjucks.js +448 -0
  32. package/dist/display-conditions/nunjucks.js.map +1 -0
  33. package/dist/display-conditions/schemaDataPoints.d.ts +4 -0
  34. package/dist/display-conditions/schemaDataPoints.d.ts.map +1 -0
  35. package/dist/display-conditions/schemaDataPoints.js +18 -0
  36. package/dist/display-conditions/schemaDataPoints.js.map +1 -0
  37. package/dist/display-conditions/types.d.ts +130 -0
  38. package/dist/display-conditions/types.d.ts.map +1 -0
  39. package/dist/display-conditions/types.js +72 -0
  40. package/dist/display-conditions/types.js.map +1 -0
  41. package/dist/editor-core-source.d.ts +1 -1
  42. package/dist/editor-core-source.d.ts.map +1 -1
  43. package/dist/editor-core-source.js +1 -1
  44. package/dist/editor-core-source.js.map +1 -1
  45. package/dist/editor.d.ts.map +1 -1
  46. package/dist/editor.js +4 -0
  47. package/dist/editor.js.map +1 -1
  48. package/dist/shared/schema.d.ts +2 -0
  49. package/dist/shared/schema.d.ts.map +1 -1
  50. package/dist/shared/schema.js.map +1 -1
  51. package/dist/unlayer.d.ts.map +1 -1
  52. package/dist/unlayer.js +7 -0
  53. package/dist/unlayer.js.map +1 -1
  54. package/package.json +4 -2
  55. package/src/display-conditions/ConditionGroup.tsx +145 -0
  56. package/src/display-conditions/ConditionGroupsSection.tsx +64 -0
  57. package/src/display-conditions/ConditionRow.tsx +185 -0
  58. package/src/display-conditions/DisplayConditionModal.tsx +231 -0
  59. package/src/display-conditions/SeparatorWithChip.tsx +14 -0
  60. package/src/display-conditions/constants.ts +22 -0
  61. package/src/display-conditions/displayConditionController.ts +42 -0
  62. package/src/display-conditions/nunjucks.ts +503 -0
  63. package/src/display-conditions/schemaDataPoints.ts +33 -0
  64. package/src/display-conditions/types.ts +75 -0
  65. package/src/editor-core-source.ts +1 -1
  66. package/src/editor.tsx +2 -0
  67. package/src/shared/schema.ts +2 -0
  68. package/src/unlayer.tsx +9 -0
@@ -0,0 +1,282 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Combobox, Dialog, Flex, Text } from '@servicetitan/anvil2';
3
+ import { useCallback, useEffect, useMemo, useState } from 'react';
4
+ import { createPortal } from 'react-dom';
5
+ import { ConditionGroupsSection } from './ConditionGroupsSection';
6
+ import { defaultGroup, defaultState, MODAL_CONTENT_MAX_HEIGHT } from './constants';
7
+ import { onDisplayCondition } from './displayConditionController';
8
+ import { buildUnlayerDisplayCondition, parseUnlayerDisplayCondition } from './nunjucks';
9
+ import { getSchemaDataPointOptions } from './schemaDataPoints';
10
+ const BEHAVIOR_OPTIONS = [
11
+ {
12
+ label: 'Show',
13
+ value: 'show'
14
+ },
15
+ {
16
+ label: 'Hide',
17
+ value: 'hide'
18
+ }
19
+ ];
20
+ const NUMERIC_VALUE_RE = /^-?(?:\d+\.?\d*|\.\d+)$/;
21
+ export const DisplayConditionModal = (props)=>{
22
+ const [request, setRequest] = useState(null);
23
+ const [isOpen, setIsOpen] = useState(false);
24
+ const [state, setState] = useState(defaultState);
25
+ const dataPointOptions = useMemo(()=>getSchemaDataPointOptions(props.schema), [
26
+ props.schema
27
+ ]);
28
+ const portalTarget = useMemo(()=>{
29
+ if (typeof document === 'undefined') {
30
+ return null;
31
+ }
32
+ return document.body;
33
+ }, []);
34
+ useEffect(()=>{
35
+ return onDisplayCondition((nextRequest)=>{
36
+ setRequest(nextRequest);
37
+ const existing = nextRequest.data;
38
+ const parsed = parseUnlayerDisplayCondition(existing);
39
+ setState(parsed !== null && parsed !== void 0 ? parsed : defaultState());
40
+ setIsOpen(true);
41
+ });
42
+ }, []);
43
+ const handleClose = useCallback(()=>{
44
+ if (request) {
45
+ var _request_data;
46
+ request.done((_request_data = request.data) !== null && _request_data !== void 0 ? _request_data : null);
47
+ setRequest(null);
48
+ }
49
+ setIsOpen(false);
50
+ }, [
51
+ request
52
+ ]);
53
+ const handleSave = useCallback(()=>{
54
+ if (!request) {
55
+ return;
56
+ }
57
+ const condition = buildUnlayerDisplayCondition(state);
58
+ if (condition) {
59
+ request.done(condition);
60
+ } else {
61
+ request.done(null);
62
+ }
63
+ setRequest(null);
64
+ setIsOpen(false);
65
+ }, [
66
+ request,
67
+ state
68
+ ]);
69
+ const updateGroup = useCallback((index, group)=>{
70
+ setState((prev)=>{
71
+ const next = [
72
+ ...prev.groups
73
+ ];
74
+ next[index] = group;
75
+ return {
76
+ ...prev,
77
+ groups: next
78
+ };
79
+ });
80
+ }, []);
81
+ const removeGroup = useCallback((index)=>{
82
+ setState((prev)=>({
83
+ ...prev,
84
+ groups: (()=>{
85
+ const nextGroups = prev.groups.filter((_, i)=>i !== index);
86
+ if (nextGroups.length === 0) {
87
+ return [
88
+ defaultGroup()
89
+ ];
90
+ }
91
+ if (index === 0) {
92
+ const { logicalOperator: unusedOp, ...firstGroup } = nextGroups[0];
93
+ return [
94
+ firstGroup,
95
+ ...nextGroups.slice(1)
96
+ ];
97
+ }
98
+ return nextGroups;
99
+ })()
100
+ }));
101
+ }, []);
102
+ const addGroup = useCallback(()=>{
103
+ setState((prev)=>({
104
+ ...prev,
105
+ groups: [
106
+ ...prev.groups,
107
+ {
108
+ ...defaultGroup(),
109
+ logicalOperator: 'and'
110
+ }
111
+ ]
112
+ }));
113
+ }, []);
114
+ const selectedBehavior = useMemo(()=>{
115
+ var _BEHAVIOR_OPTIONS_find;
116
+ return (_BEHAVIOR_OPTIONS_find = BEHAVIOR_OPTIONS.find((opt)=>opt.value === state.behavior)) !== null && _BEHAVIOR_OPTIONS_find !== void 0 ? _BEHAVIOR_OPTIONS_find : BEHAVIOR_OPTIONS[0];
117
+ }, [
118
+ state.behavior
119
+ ]);
120
+ const handleBehaviorChange = useCallback((item)=>{
121
+ if (item) {
122
+ setState((prev)=>({
123
+ ...prev,
124
+ behavior: item.value
125
+ }));
126
+ }
127
+ }, []);
128
+ const canSave = useMemo(()=>{
129
+ for (const group of state.groups){
130
+ for (const condition of group.conditions){
131
+ var _dataPointOptions_find;
132
+ if (!condition.dataPointKey) {
133
+ return false;
134
+ }
135
+ if (condition.operator === 'is_empty' || condition.operator === 'is_not_empty') {
136
+ continue;
137
+ }
138
+ const trimmedValue = condition.value.trim();
139
+ if (!trimmedValue) {
140
+ return false;
141
+ }
142
+ var _dataPointOptions_find_fieldType;
143
+ const fieldType = (_dataPointOptions_find_fieldType = (_dataPointOptions_find = dataPointOptions.find((opt)=>opt.fullKey === condition.dataPointKey)) === null || _dataPointOptions_find === void 0 ? void 0 : _dataPointOptions_find.fieldType) !== null && _dataPointOptions_find_fieldType !== void 0 ? _dataPointOptions_find_fieldType : 'string';
144
+ if (fieldType === 'number' && !NUMERIC_VALUE_RE.test(trimmedValue)) {
145
+ return false;
146
+ }
147
+ }
148
+ }
149
+ return state.groups.length > 0;
150
+ }, [
151
+ dataPointOptions,
152
+ state.groups
153
+ ]);
154
+ if (!portalTarget || !isOpen) {
155
+ return null;
156
+ }
157
+ return /*#__PURE__*/ createPortal(/*#__PURE__*/ _jsxs(Dialog, {
158
+ open: isOpen,
159
+ onClose: handleClose,
160
+ size: "xlarge",
161
+ children: [
162
+ /*#__PURE__*/ _jsx(Dialog.Header, {
163
+ children: "Rules and Conditions"
164
+ }),
165
+ /*#__PURE__*/ _jsx(Dialog.Content, {
166
+ children: /*#__PURE__*/ _jsxs(Flex, {
167
+ direction: "column",
168
+ gap: "6",
169
+ style: {
170
+ maxHeight: MODAL_CONTENT_MAX_HEIGHT,
171
+ overflowY: 'auto',
172
+ width: '100%'
173
+ },
174
+ children: [
175
+ /*#__PURE__*/ _jsxs(Flex, {
176
+ direction: "column",
177
+ gap: "3",
178
+ style: {
179
+ borderBottom: '1px solid #e0e0e0',
180
+ paddingBottom: 16
181
+ },
182
+ children: [
183
+ /*#__PURE__*/ _jsx(Text, {
184
+ size: "medium",
185
+ variant: "body",
186
+ style: {
187
+ fontWeight: 'bold'
188
+ },
189
+ children: "When conditions are met:"
190
+ }),
191
+ /*#__PURE__*/ _jsxs(Flex, {
192
+ direction: "row",
193
+ alignItems: "center",
194
+ gap: "3",
195
+ style: {
196
+ flexWrap: 'wrap'
197
+ },
198
+ children: [
199
+ /*#__PURE__*/ _jsx(Text, {
200
+ size: "small",
201
+ subdued: true,
202
+ variant: "body",
203
+ children: "Select to show or hide selected component."
204
+ }),
205
+ /*#__PURE__*/ _jsx("div", {
206
+ style: {
207
+ width: 160
208
+ },
209
+ children: /*#__PURE__*/ _jsxs(Combobox, {
210
+ ...{
211
+ disableClearSelection: true
212
+ },
213
+ itemToKey: (item)=>{
214
+ var _item_value;
215
+ return (_item_value = item === null || item === void 0 ? void 0 : item.value) !== null && _item_value !== void 0 ? _item_value : '';
216
+ },
217
+ itemToString: (item)=>{
218
+ var _item_label;
219
+ return (_item_label = item === null || item === void 0 ? void 0 : item.label) !== null && _item_label !== void 0 ? _item_label : '';
220
+ },
221
+ items: [
222
+ ...BEHAVIOR_OPTIONS
223
+ ],
224
+ selectedItem: selectedBehavior,
225
+ onChange: handleBehaviorChange,
226
+ children: [
227
+ /*#__PURE__*/ _jsx(Combobox.SelectTrigger, {
228
+ label: "Behavior",
229
+ placeholder: "Select..."
230
+ }),
231
+ /*#__PURE__*/ _jsx(Combobox.Content, {
232
+ children: ({ items })=>/*#__PURE__*/ _jsx(Combobox.List, {
233
+ children: items.map((item, i)=>/*#__PURE__*/ _jsx(Combobox.Item, {
234
+ index: i,
235
+ item: item,
236
+ children: item.label
237
+ }, item.value))
238
+ })
239
+ })
240
+ ]
241
+ })
242
+ })
243
+ ]
244
+ })
245
+ ]
246
+ }),
247
+ /*#__PURE__*/ _jsx(ConditionGroupsSection, {
248
+ dataPointOptions: dataPointOptions,
249
+ groups: state.groups,
250
+ onAddGroup: addGroup,
251
+ onRemoveGroup: removeGroup,
252
+ onUpdateGroup: updateGroup
253
+ }),
254
+ !canSave && /*#__PURE__*/ _jsx(Text, {
255
+ size: "small",
256
+ subdued: true,
257
+ variant: "body",
258
+ children: "Complete each condition before saving. Data point and value are required, and numeric fields must contain a valid number."
259
+ })
260
+ ]
261
+ })
262
+ }),
263
+ /*#__PURE__*/ _jsxs(Dialog.Footer, {
264
+ sticky: true,
265
+ children: [
266
+ /*#__PURE__*/ _jsx(Dialog.CancelButton, {
267
+ onClick: handleClose,
268
+ children: "Cancel"
269
+ }),
270
+ /*#__PURE__*/ _jsx(Button, {
271
+ appearance: "primary",
272
+ disabled: !canSave,
273
+ onClick: handleSave,
274
+ children: "Save Changes"
275
+ })
276
+ ]
277
+ })
278
+ ]
279
+ }), portalTarget);
280
+ };
281
+
282
+ //# sourceMappingURL=DisplayConditionModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/display-conditions/DisplayConditionModal.tsx"],"sourcesContent":["import { Button, Combobox, Dialog, Flex, Text } from '@servicetitan/anvil2';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ConditionGroupsSection } from './ConditionGroupsSection';\nimport { defaultGroup, defaultState, MODAL_CONTENT_MAX_HEIGHT } from './constants';\nimport { DisplayConditionRequest, onDisplayCondition } from './displayConditionController';\nimport { buildUnlayerDisplayCondition, parseUnlayerDisplayCondition } from './nunjucks';\nimport { getSchemaDataPointOptions } from './schemaDataPoints';\nimport { ConditionGroup as ConditionGroupType, DisplayBehavior } from './types';\n\nconst BEHAVIOR_OPTIONS = [\n { label: 'Show', value: 'show' },\n { label: 'Hide', value: 'hide' },\n] as const;\nconst NUMERIC_VALUE_RE = /^-?(?:\\d+\\.?\\d*|\\.\\d+)$/;\n\ntype BehaviorOption = (typeof BEHAVIOR_OPTIONS)[number];\n\nexport interface DisplayConditionModalProps {\n schema?: import('../shared/schema').SchemaObject;\n}\n\nexport const DisplayConditionModal = (props: DisplayConditionModalProps) => {\n const [request, setRequest] = useState<DisplayConditionRequest | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [state, setState] = useState(defaultState);\n\n const dataPointOptions = useMemo(() => getSchemaDataPointOptions(props.schema), [props.schema]);\n\n const portalTarget = useMemo(() => {\n if (typeof document === 'undefined') {\n return null;\n }\n return document.body;\n }, []);\n\n useEffect(() => {\n return onDisplayCondition(nextRequest => {\n setRequest(nextRequest);\n const existing = nextRequest.data;\n const parsed = parseUnlayerDisplayCondition(existing);\n setState(parsed ?? defaultState());\n setIsOpen(true);\n });\n }, []);\n\n const handleClose = useCallback(() => {\n if (request) {\n request.done(request.data ?? null);\n setRequest(null);\n }\n setIsOpen(false);\n }, [request]);\n\n const handleSave = useCallback(() => {\n if (!request) {\n return;\n }\n const condition = buildUnlayerDisplayCondition(state);\n if (condition) {\n request.done(condition);\n } else {\n request.done(null);\n }\n setRequest(null);\n setIsOpen(false);\n }, [request, state]);\n\n const updateGroup = useCallback((index: number, group: ConditionGroupType) => {\n setState(prev => {\n const next = [...prev.groups];\n next[index] = group;\n return { ...prev, groups: next };\n });\n }, []);\n\n const removeGroup = useCallback((index: number) => {\n setState(prev => ({\n ...prev,\n groups: (() => {\n const nextGroups = prev.groups.filter((_, i) => i !== index);\n if (nextGroups.length === 0) {\n return [defaultGroup()];\n }\n if (index === 0) {\n const { logicalOperator: unusedOp, ...firstGroup } = nextGroups[0];\n return [firstGroup, ...nextGroups.slice(1)];\n }\n return nextGroups;\n })(),\n }));\n }, []);\n\n const addGroup = useCallback(() => {\n setState(prev => ({\n ...prev,\n groups: [...prev.groups, { ...defaultGroup(), logicalOperator: 'and' }],\n }));\n }, []);\n\n const selectedBehavior = useMemo(\n () => BEHAVIOR_OPTIONS.find(opt => opt.value === state.behavior) ?? BEHAVIOR_OPTIONS[0],\n [state.behavior],\n );\n\n const handleBehaviorChange = useCallback((item: BehaviorOption | null) => {\n if (item) {\n setState(prev => ({ ...prev, behavior: item.value as DisplayBehavior }));\n }\n }, []);\n\n const canSave = useMemo(() => {\n for (const group of state.groups) {\n for (const condition of group.conditions) {\n if (!condition.dataPointKey) {\n return false;\n }\n if (condition.operator === 'is_empty' || condition.operator === 'is_not_empty') {\n continue;\n }\n const trimmedValue = condition.value.trim();\n if (!trimmedValue) {\n return false;\n }\n const fieldType =\n dataPointOptions.find(opt => opt.fullKey === condition.dataPointKey)\n ?.fieldType ?? 'string';\n if (fieldType === 'number' && !NUMERIC_VALUE_RE.test(trimmedValue)) {\n return false;\n }\n }\n }\n return state.groups.length > 0;\n }, [dataPointOptions, state.groups]);\n\n if (!portalTarget || !isOpen) {\n return null;\n }\n\n return createPortal(\n <Dialog open={isOpen} onClose={handleClose} size=\"xlarge\">\n <Dialog.Header>Rules and Conditions</Dialog.Header>\n <Dialog.Content>\n <Flex\n direction=\"column\"\n gap=\"6\"\n style={{\n maxHeight: MODAL_CONTENT_MAX_HEIGHT,\n overflowY: 'auto',\n width: '100%',\n }}\n >\n <Flex\n direction=\"column\"\n gap=\"3\"\n style={{\n borderBottom: '1px solid #e0e0e0',\n paddingBottom: 16,\n }}\n >\n <Text size=\"medium\" variant=\"body\" style={{ fontWeight: 'bold' }}>\n When conditions are met:\n </Text>\n <Flex\n direction=\"row\"\n alignItems=\"center\"\n gap=\"3\"\n style={{ flexWrap: 'wrap' }}\n >\n <Text size=\"small\" subdued variant=\"body\">\n Select to show or hide selected component.\n </Text>\n <div style={{ width: 160 }}>\n <Combobox\n {...({ disableClearSelection: true } as object)}\n itemToKey={(item: BehaviorOption | null) => item?.value ?? ''}\n itemToString={(item: BehaviorOption | null) =>\n item?.label ?? ''\n }\n items={[...BEHAVIOR_OPTIONS]}\n selectedItem={selectedBehavior}\n onChange={handleBehaviorChange}\n >\n <Combobox.SelectTrigger\n label=\"Behavior\"\n placeholder=\"Select...\"\n />\n <Combobox.Content>\n {({ items }: { items: BehaviorOption[] }) => (\n <Combobox.List>\n {items.map((item, i) => (\n <Combobox.Item\n index={i}\n item={item}\n key={item.value}\n >\n {item.label}\n </Combobox.Item>\n ))}\n </Combobox.List>\n )}\n </Combobox.Content>\n </Combobox>\n </div>\n </Flex>\n </Flex>\n <ConditionGroupsSection\n dataPointOptions={dataPointOptions}\n groups={state.groups}\n onAddGroup={addGroup}\n onRemoveGroup={removeGroup}\n onUpdateGroup={updateGroup}\n />\n {!canSave && (\n <Text size=\"small\" subdued variant=\"body\">\n Complete each condition before saving. Data point and value are\n required, and numeric fields must contain a valid number.\n </Text>\n )}\n </Flex>\n </Dialog.Content>\n <Dialog.Footer sticky>\n <Dialog.CancelButton onClick={handleClose}>Cancel</Dialog.CancelButton>\n <Button appearance=\"primary\" disabled={!canSave} onClick={handleSave}>\n Save Changes\n </Button>\n </Dialog.Footer>\n </Dialog>,\n portalTarget,\n );\n};\n"],"names":["Button","Combobox","Dialog","Flex","Text","useCallback","useEffect","useMemo","useState","createPortal","ConditionGroupsSection","defaultGroup","defaultState","MODAL_CONTENT_MAX_HEIGHT","onDisplayCondition","buildUnlayerDisplayCondition","parseUnlayerDisplayCondition","getSchemaDataPointOptions","BEHAVIOR_OPTIONS","label","value","NUMERIC_VALUE_RE","DisplayConditionModal","props","request","setRequest","isOpen","setIsOpen","state","setState","dataPointOptions","schema","portalTarget","document","body","nextRequest","existing","data","parsed","handleClose","done","handleSave","condition","updateGroup","index","group","prev","next","groups","removeGroup","nextGroups","filter","_","i","length","logicalOperator","unusedOp","firstGroup","slice","addGroup","selectedBehavior","find","opt","behavior","handleBehaviorChange","item","canSave","conditions","dataPointKey","operator","trimmedValue","trim","fieldType","fullKey","test","open","onClose","size","Header","Content","direction","gap","style","maxHeight","overflowY","width","borderBottom","paddingBottom","variant","fontWeight","alignItems","flexWrap","subdued","div","disableClearSelection","itemToKey","itemToString","items","selectedItem","onChange","SelectTrigger","placeholder","List","map","Item","onAddGroup","onRemoveGroup","onUpdateGroup","Footer","sticky","CancelButton","onClick","appearance","disabled"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface SeparatorWithChipProps {
2
+ label: string;
3
+ color?: string;
4
+ }
5
+ export declare function SeparatorWithChip({ color, label }: Readonly<SeparatorWithChipProps>): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=SeparatorWithChip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SeparatorWithChip.d.ts","sourceRoot":"","sources":["../../src/display-conditions/SeparatorWithChip.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,KAAiB,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,sBAAsB,CAAC,2CAM/F"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Chip, Divider } from '@servicetitan/anvil2';
3
+ export function SeparatorWithChip({ color = '#94a3b8', label }) {
4
+ return /*#__PURE__*/ _jsx(Divider, {
5
+ alignContent: "center",
6
+ spacing: "2",
7
+ children: /*#__PURE__*/ _jsx(Chip, {
8
+ label: label,
9
+ size: "small",
10
+ color: color
11
+ })
12
+ });
13
+ }
14
+
15
+ //# sourceMappingURL=SeparatorWithChip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/display-conditions/SeparatorWithChip.tsx"],"sourcesContent":["import { Chip, Divider } from '@servicetitan/anvil2';\n\nexport interface SeparatorWithChipProps {\n label: string;\n color?: string;\n}\n\nexport function SeparatorWithChip({ color = '#94a3b8', label }: Readonly<SeparatorWithChipProps>) {\n return (\n <Divider alignContent=\"center\" spacing=\"2\">\n <Chip label={label} size=\"small\" color={color} />\n </Divider>\n );\n}\n"],"names":["Chip","Divider","SeparatorWithChip","color","label","alignContent","spacing","size"],"mappings":";AAAA,SAASA,IAAI,EAAEC,OAAO,QAAQ,uBAAuB;AAOrD,OAAO,SAASC,kBAAkB,EAAEC,QAAQ,SAAS,EAAEC,KAAK,EAAoC;IAC5F,qBACI,KAACH;QAAQI,cAAa;QAASC,SAAQ;kBACnC,cAAA,KAACN;YAAKI,OAAOA;YAAOG,MAAK;YAAQJ,OAAOA;;;AAGpD"}
@@ -0,0 +1,7 @@
1
+ import { ConditionGroup, DisplayConditionState, SingleCondition } from './types';
2
+ export declare const generateId: () => string;
3
+ export declare const defaultCondition: () => SingleCondition;
4
+ export declare const defaultGroup: () => ConditionGroup;
5
+ export declare const defaultState: () => DisplayConditionState;
6
+ export declare const MODAL_CONTENT_MAX_HEIGHT = "70vh";
7
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/display-conditions/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEjF,eAAO,MAAM,UAAU,cAAgD,CAAC;AAExE,eAAO,MAAM,gBAAgB,QAAO,eAKlC,CAAC;AAEH,eAAO,MAAM,YAAY,QAAO,cAG9B,CAAC;AAEH,eAAO,MAAM,YAAY,QAAO,qBAG9B,CAAC;AAEH,eAAO,MAAM,wBAAwB,SAAS,CAAC"}
@@ -0,0 +1,22 @@
1
+ export const generateId = ()=>Math.random().toString(36).slice(2, 11);
2
+ export const defaultCondition = ()=>({
3
+ dataPointKey: '',
4
+ id: generateId(),
5
+ operator: 'is_equal_to',
6
+ value: ''
7
+ });
8
+ export const defaultGroup = ()=>({
9
+ conditions: [
10
+ defaultCondition()
11
+ ],
12
+ id: generateId()
13
+ });
14
+ export const defaultState = ()=>({
15
+ behavior: 'show',
16
+ groups: [
17
+ defaultGroup()
18
+ ]
19
+ });
20
+ export const MODAL_CONTENT_MAX_HEIGHT = '70vh';
21
+
22
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/display-conditions/constants.ts"],"sourcesContent":["import { ConditionGroup, DisplayConditionState, SingleCondition } from './types';\n\nexport const generateId = () => Math.random().toString(36).slice(2, 11);\n\nexport const defaultCondition = (): SingleCondition => ({\n dataPointKey: '',\n id: generateId(),\n operator: 'is_equal_to',\n value: '',\n});\n\nexport const defaultGroup = (): ConditionGroup => ({\n conditions: [defaultCondition()],\n id: generateId(),\n});\n\nexport const defaultState = (): DisplayConditionState => ({\n behavior: 'show',\n groups: [defaultGroup()],\n});\n\nexport const MODAL_CONTENT_MAX_HEIGHT = '70vh';\n"],"names":["generateId","Math","random","toString","slice","defaultCondition","dataPointKey","id","operator","value","defaultGroup","conditions","defaultState","behavior","groups","MODAL_CONTENT_MAX_HEIGHT"],"mappings":"AAEA,OAAO,MAAMA,aAAa,IAAMC,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,KAAK,CAAC,GAAG,IAAI;AAExE,OAAO,MAAMC,mBAAmB,IAAwB,CAAA;QACpDC,cAAc;QACdC,IAAIP;QACJQ,UAAU;QACVC,OAAO;IACX,CAAA,EAAG;AAEH,OAAO,MAAMC,eAAe,IAAuB,CAAA;QAC/CC,YAAY;YAACN;SAAmB;QAChCE,IAAIP;IACR,CAAA,EAAG;AAEH,OAAO,MAAMY,eAAe,IAA8B,CAAA;QACtDC,UAAU;QACVC,QAAQ;YAACJ;SAAe;IAC5B,CAAA,EAAG;AAEH,OAAO,MAAMK,2BAA2B,OAAO"}
@@ -0,0 +1,9 @@
1
+ export interface DisplayConditionRequest {
2
+ data: any;
3
+ done: (condition: any) => void;
4
+ }
5
+ type Listener = (request: DisplayConditionRequest) => void;
6
+ export declare const onDisplayCondition: (listener: Listener) => () => void;
7
+ export declare const emitDisplayCondition: (request: DisplayConditionRequest) => void;
8
+ export {};
9
+ //# sourceMappingURL=displayConditionController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"displayConditionController.d.ts","sourceRoot":"","sources":["../../src/display-conditions/displayConditionController.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,IAAI,CAAC;CAClC;AAED,KAAK,QAAQ,GAAG,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAC;AAM3D,eAAO,MAAM,kBAAkB,GAAI,UAAU,QAAQ,eAmBpD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,SAAS,uBAAuB,SASpE,CAAC"}
@@ -0,0 +1,29 @@
1
+ const DISPLAY_CONDITION_EVENT = 'dte:display-condition';
2
+ const displayConditionEvents = new EventTarget();
3
+ let activeListeners = 0;
4
+ export const onDisplayCondition = (listener)=>{
5
+ const handler = (event)=>{
6
+ const detail = event.detail;
7
+ if (!detail) {
8
+ return;
9
+ }
10
+ listener(detail);
11
+ };
12
+ activeListeners += 1;
13
+ displayConditionEvents.addEventListener(DISPLAY_CONDITION_EVENT, handler);
14
+ return ()=>{
15
+ activeListeners = Math.max(0, activeListeners - 1);
16
+ displayConditionEvents.removeEventListener(DISPLAY_CONDITION_EVENT, handler);
17
+ };
18
+ };
19
+ export const emitDisplayCondition = (request)=>{
20
+ if (activeListeners === 0) {
21
+ request.done(request.data);
22
+ return;
23
+ }
24
+ displayConditionEvents.dispatchEvent(new CustomEvent(DISPLAY_CONDITION_EVENT, {
25
+ detail: request
26
+ }));
27
+ };
28
+
29
+ //# sourceMappingURL=displayConditionController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/display-conditions/displayConditionController.ts"],"sourcesContent":["export interface DisplayConditionRequest {\n data: any;\n done: (condition: any) => void;\n}\n\ntype Listener = (request: DisplayConditionRequest) => void;\n\nconst DISPLAY_CONDITION_EVENT = 'dte:display-condition';\nconst displayConditionEvents = new EventTarget();\nlet activeListeners = 0;\n\nexport const onDisplayCondition = (listener: Listener) => {\n const handler = (event: Event) => {\n const detail = (event as CustomEvent<DisplayConditionRequest>).detail;\n if (!detail) {\n return;\n }\n listener(detail);\n };\n\n activeListeners += 1;\n displayConditionEvents.addEventListener(DISPLAY_CONDITION_EVENT, handler as EventListener);\n\n return () => {\n activeListeners = Math.max(0, activeListeners - 1);\n displayConditionEvents.removeEventListener(\n DISPLAY_CONDITION_EVENT,\n handler as EventListener,\n );\n };\n};\n\nexport const emitDisplayCondition = (request: DisplayConditionRequest) => {\n if (activeListeners === 0) {\n request.done(request.data);\n return;\n }\n\n displayConditionEvents.dispatchEvent(\n new CustomEvent<DisplayConditionRequest>(DISPLAY_CONDITION_EVENT, { detail: request }),\n );\n};\n"],"names":["DISPLAY_CONDITION_EVENT","displayConditionEvents","EventTarget","activeListeners","onDisplayCondition","listener","handler","event","detail","addEventListener","Math","max","removeEventListener","emitDisplayCondition","request","done","data","dispatchEvent","CustomEvent"],"mappings":"AAOA,MAAMA,0BAA0B;AAChC,MAAMC,yBAAyB,IAAIC;AACnC,IAAIC,kBAAkB;AAEtB,OAAO,MAAMC,qBAAqB,CAACC;IAC/B,MAAMC,UAAU,CAACC;QACb,MAAMC,SAAS,AAACD,MAA+CC,MAAM;QACrE,IAAI,CAACA,QAAQ;YACT;QACJ;QACAH,SAASG;IACb;IAEAL,mBAAmB;IACnBF,uBAAuBQ,gBAAgB,CAACT,yBAAyBM;IAEjE,OAAO;QACHH,kBAAkBO,KAAKC,GAAG,CAAC,GAAGR,kBAAkB;QAChDF,uBAAuBW,mBAAmB,CACtCZ,yBACAM;IAER;AACJ,EAAE;AAEF,OAAO,MAAMO,uBAAuB,CAACC;IACjC,IAAIX,oBAAoB,GAAG;QACvBW,QAAQC,IAAI,CAACD,QAAQE,IAAI;QACzB;IACJ;IAEAf,uBAAuBgB,aAAa,CAChC,IAAIC,YAAqClB,yBAAyB;QAAEQ,QAAQM;IAAQ;AAE5F,EAAE"}
@@ -0,0 +1,8 @@
1
+ import { DisplayConditionState, UnlayerDisplayCondition } from './types';
2
+ export declare function buildUnlayerDisplayCondition(state: DisplayConditionState): UnlayerDisplayCondition | null;
3
+ /**
4
+ * Parse a saved Unlayer display condition back into modal state for prefilling.
5
+ * Returns null if the condition is missing or cannot be parsed.
6
+ */
7
+ export declare function parseUnlayerDisplayCondition(condition: UnlayerDisplayCondition | null | undefined): DisplayConditionState | null;
8
+ //# sourceMappingURL=nunjucks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nunjucks.d.ts","sourceRoot":"","sources":["../../src/display-conditions/nunjucks.ts"],"names":[],"mappings":"AACA,OAAO,EAIH,qBAAqB,EAGrB,uBAAuB,EAE1B,MAAM,SAAS,CAAC;AAoKjB,wBAAgB,4BAA4B,CACxC,KAAK,EAAE,qBAAqB,GAC7B,uBAAuB,GAAG,IAAI,CAUhC;AA0QD;;;GAGG;AACH,wBAAgB,4BAA4B,CACxC,SAAS,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,GACtD,qBAAqB,GAAG,IAAI,CA4C9B"}