@servicetitan/dte-unlayer 0.153.0 → 0.155.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 (85) hide show
  1. package/dist/display-conditions/ConditionRow.d.ts.map +1 -1
  2. package/dist/display-conditions/ConditionRow.js +111 -95
  3. package/dist/display-conditions/ConditionRow.js.map +1 -1
  4. package/dist/display-conditions/DisplayConditionModal.d.ts +3 -3
  5. package/dist/display-conditions/DisplayConditionModal.d.ts.map +1 -1
  6. package/dist/display-conditions/DisplayConditionModal.js +8 -95
  7. package/dist/display-conditions/DisplayConditionModal.js.map +1 -1
  8. package/dist/display-conditions/useConditionForms.d.ts +22 -0
  9. package/dist/display-conditions/useConditionForms.d.ts.map +1 -0
  10. package/dist/display-conditions/useConditionForms.js +110 -0
  11. package/dist/display-conditions/useConditionForms.js.map +1 -0
  12. package/dist/e-sign-offset/ESignDateSignedOffsetModal.d.ts +11 -0
  13. package/dist/e-sign-offset/ESignDateSignedOffsetModal.d.ts.map +1 -0
  14. package/dist/e-sign-offset/ESignDateSignedOffsetModal.js +192 -0
  15. package/dist/e-sign-offset/ESignDateSignedOffsetModal.js.map +1 -0
  16. package/dist/e-sign-offset/ESignOffsetRuleRow.d.ts +20 -0
  17. package/dist/e-sign-offset/ESignOffsetRuleRow.d.ts.map +1 -0
  18. package/dist/e-sign-offset/ESignOffsetRuleRow.js +87 -0
  19. package/dist/e-sign-offset/ESignOffsetRuleRow.js.map +1 -0
  20. package/dist/e-sign-offset/eSignOffsetController.d.ts +10 -0
  21. package/dist/e-sign-offset/eSignOffsetController.d.ts.map +1 -0
  22. package/dist/e-sign-offset/eSignOffsetController.js +27 -0
  23. package/dist/e-sign-offset/eSignOffsetController.js.map +1 -0
  24. package/dist/editor-core-source.d.ts +2 -2
  25. package/dist/editor-core-source.d.ts.map +1 -1
  26. package/dist/editor-core-source.js +2 -2
  27. package/dist/editor-core-source.js.map +1 -1
  28. package/dist/editor.d.ts.map +1 -1
  29. package/dist/editor.js +8 -0
  30. package/dist/editor.js.map +1 -1
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/merge-tags.d.ts +6 -10
  36. package/dist/merge-tags.d.ts.map +1 -1
  37. package/dist/merge-tags.js +35 -44
  38. package/dist/merge-tags.js.map +1 -1
  39. package/dist/shared/const.d.ts +30 -0
  40. package/dist/shared/const.d.ts.map +1 -1
  41. package/dist/shared/const.js +5 -0
  42. package/dist/shared/const.js.map +1 -1
  43. package/dist/shared/e-sign-offset.d.ts +21 -0
  44. package/dist/shared/e-sign-offset.d.ts.map +1 -0
  45. package/dist/shared/e-sign-offset.js +130 -0
  46. package/dist/shared/e-sign-offset.js.map +1 -0
  47. package/dist/shared/instance-id.d.ts +13 -0
  48. package/dist/shared/instance-id.d.ts.map +1 -0
  49. package/dist/shared/instance-id.js +22 -0
  50. package/dist/shared/instance-id.js.map +1 -0
  51. package/dist/store.d.ts +15 -1
  52. package/dist/store.d.ts.map +1 -1
  53. package/dist/store.js +80 -5
  54. package/dist/store.js.map +1 -1
  55. package/dist/tools.d.ts +18 -0
  56. package/dist/tools.d.ts.map +1 -1
  57. package/dist/tools.js +68 -1
  58. package/dist/tools.js.map +1 -1
  59. package/dist/unlayer-interface.d.ts +11 -1
  60. package/dist/unlayer-interface.d.ts.map +1 -1
  61. package/dist/unlayer-interface.js.map +1 -1
  62. package/dist/unlayer.d.ts.map +1 -1
  63. package/dist/unlayer.js +5 -3
  64. package/dist/unlayer.js.map +1 -1
  65. package/package.json +1 -1
  66. package/src/__tests__/e-sign-offset.test.ts +281 -0
  67. package/src/__tests__/merge-tags.test.ts +98 -76
  68. package/src/__tests__/store.merge-tags.test.ts +186 -0
  69. package/src/display-conditions/ConditionRow.tsx +86 -81
  70. package/src/display-conditions/DisplayConditionModal.tsx +12 -116
  71. package/src/display-conditions/useConditionForms.ts +146 -0
  72. package/src/e-sign-offset/ESignDateSignedOffsetModal.tsx +197 -0
  73. package/src/e-sign-offset/ESignOffsetRuleRow.tsx +101 -0
  74. package/src/e-sign-offset/eSignOffsetController.ts +39 -0
  75. package/src/editor-core-source.ts +2 -2
  76. package/src/editor.tsx +9 -0
  77. package/src/index.ts +1 -2
  78. package/src/merge-tags.ts +41 -60
  79. package/src/shared/const.ts +37 -0
  80. package/src/shared/e-sign-offset.ts +173 -0
  81. package/src/shared/instance-id.ts +23 -0
  82. package/src/store.ts +106 -5
  83. package/src/tools.ts +87 -1
  84. package/src/unlayer-interface.tsx +11 -1
  85. package/src/unlayer.tsx +5 -3
@@ -1,4 +1,4 @@
1
- import { scheduleUnlayerMergeTags, toUnlayerMergeTags } from '../merge-tags';
1
+ import { toUnlayerMergeTags } from '../merge-tags';
2
2
 
3
3
  const customerNameTag = {
4
4
  id: '10',
@@ -75,7 +75,7 @@ describe('toUnlayerMergeTags', () => {
75
75
  name: 'Customer Name',
76
76
  value: '{{Customer.Name | safe | nl2br }}',
77
77
  },
78
- custom_fields: {
78
+ 'custom_fields': {
79
79
  name: 'Custom Fields',
80
80
  mergeTags: {
81
81
  custom_field_12345: {
@@ -124,6 +124,101 @@ describe('toUnlayerMergeTags', () => {
124
124
  });
125
125
  });
126
126
 
127
+ describe('when group is a path', () => {
128
+ const intakeScoreTag = {
129
+ id: 'form-7-abc123',
130
+ name: 'Score',
131
+ propertyPath: '{{ __submission_fields["7"]["abc123"] | safe | nl2br }}',
132
+ group: ['Forms', 'Customer Intake'],
133
+ };
134
+ const intakeNotesTag = {
135
+ id: 'form-7-def456',
136
+ name: 'Notes',
137
+ propertyPath: '{{ __submission_fields["7"]["def456"] | safe | nl2br }}',
138
+ group: ['Forms', 'Customer Intake'],
139
+ };
140
+ const inspectionDateTag = {
141
+ id: 'form-9-fed987',
142
+ name: 'Inspection Date',
143
+ propertyPath: '{{ __submission_fields["9"]["fed987"] | safe | nl2br }}',
144
+ group: ['Forms', 'Inspection'],
145
+ };
146
+
147
+ const subject = () =>
148
+ toUnlayerMergeTags([
149
+ contractTermTag,
150
+ renewalDateTag,
151
+ intakeScoreTag,
152
+ intakeNotesTag,
153
+ inspectionDateTag,
154
+ ]);
155
+
156
+ test('nests one submenu per path segment', () => {
157
+ expect(subject()).toEqual({
158
+ ...groupedCustomFields,
159
+ forms: {
160
+ name: 'Forms',
161
+ mergeTags: {
162
+ customer_intake: {
163
+ name: 'Customer Intake',
164
+ mergeTags: {
165
+ form_7_abc123: {
166
+ name: 'Score',
167
+ value: '{{ __submission_fields["7"]["abc123"] | safe | nl2br }}',
168
+ },
169
+ form_7_def456: {
170
+ name: 'Notes',
171
+ value: '{{ __submission_fields["7"]["def456"] | safe | nl2br }}',
172
+ },
173
+ },
174
+ },
175
+ inspection: {
176
+ name: 'Inspection',
177
+ mergeTags: {
178
+ form_9_fed987: {
179
+ name: 'Inspection Date',
180
+ value: '{{ __submission_fields["9"]["fed987"] | safe | nl2br }}',
181
+ },
182
+ },
183
+ },
184
+ },
185
+ },
186
+ });
187
+ });
188
+
189
+ test('drops blank segments and keeps the remaining path', () => {
190
+ expect(toUnlayerMergeTags([{ ...intakeScoreTag, group: [' ', 'Forms', ''] }])).toEqual({
191
+ forms: {
192
+ name: 'Forms',
193
+ mergeTags: {
194
+ form_7_abc123: {
195
+ name: 'Score',
196
+ value: '{{ __submission_fields["7"]["abc123"] | safe | nl2br }}',
197
+ },
198
+ },
199
+ },
200
+ });
201
+ });
202
+
203
+ test('treats an all-blank path as ungrouped', () => {
204
+ expect(toUnlayerMergeTags([{ ...intakeScoreTag, group: [] }])).toEqual({
205
+ form_7_abc123: {
206
+ name: 'Score',
207
+ value: '{{ __submission_fields["7"]["abc123"] | safe | nl2br }}',
208
+ },
209
+ });
210
+ });
211
+
212
+ test('flattens the path when groups are disabled', () => {
213
+ expect(toUnlayerMergeTags([intakeScoreTag], { groups: false })).toEqual({
214
+ form_7_abc123: {
215
+ name: 'Score',
216
+ value: '{{ __submission_fields["7"]["abc123"] | safe | nl2br }}',
217
+ },
218
+ });
219
+ });
220
+ });
221
+
127
222
  describe('when group is blank', () => {
128
223
  const subject = () =>
129
224
  toUnlayerMergeTags([
@@ -153,7 +248,7 @@ describe('toUnlayerMergeTags', () => {
153
248
  name: 'Customer Name',
154
249
  value: '{{Customer.Name | safe | nl2br }}',
155
250
  },
156
- custom_field_12345: {
251
+ 'custom_field_12345': {
157
252
  name: 'Contract Term',
158
253
  value: '{{ __custom_fields["Contract Term"] | safe | nl2br }}',
159
254
  },
@@ -161,76 +256,3 @@ describe('toUnlayerMergeTags', () => {
161
256
  });
162
257
  });
163
258
  });
164
-
165
- describe('scheduleUnlayerMergeTags', () => {
166
- describe('when grouped tags exist', () => {
167
- const setMergeTags = jest.fn();
168
- const addEventListener = jest.fn();
169
-
170
- beforeEach(() => {
171
- setMergeTags.mockReset();
172
- addEventListener.mockReset();
173
- scheduleUnlayerMergeTags(
174
- { addEventListener, setMergeTags },
175
- [customerNameTag, contractTermTag, renewalDateTag],
176
- );
177
- });
178
-
179
- test('does not apply grouped merge tags until the editor is ready', () => {
180
- expect(setMergeTags).not.toHaveBeenCalled();
181
- expect(addEventListener).toHaveBeenCalledWith('editor:ready', expect.any(Function));
182
- expect(addEventListener).toHaveBeenCalledWith('design:loaded', expect.any(Function));
183
- });
184
-
185
- test('applies grouped merge tags when the editor is ready', () => {
186
- addEventListener.mock.calls[0][1]();
187
-
188
- expect(setMergeTags).toHaveBeenCalledWith({
189
- '10': {
190
- name: 'Customer Name',
191
- value: '{{Customer.Name | safe | nl2br }}',
192
- },
193
- ...groupedCustomFields,
194
- });
195
- });
196
-
197
- test('applies grouped merge tags only once', () => {
198
- addEventListener.mock.calls[0][1]();
199
- addEventListener.mock.calls[1][1]();
200
-
201
- expect(setMergeTags).toHaveBeenCalledTimes(1);
202
- });
203
-
204
- test('retries on design:loaded when setMergeTags throws', () => {
205
- const consoleError = jest.spyOn(console, 'error').mockImplementation(() => undefined);
206
- setMergeTags.mockImplementationOnce(() => {
207
- throw new Error('setMergeTags failed');
208
- });
209
-
210
- addEventListener.mock.calls[0][1]();
211
- addEventListener.mock.calls[1][1]();
212
-
213
- expect(setMergeTags).toHaveBeenCalledTimes(2);
214
- expect(consoleError).toHaveBeenCalledWith(
215
- '[dte-unlayer]',
216
- 'Failed to apply grouped merge tags',
217
- expect.any(Error),
218
- );
219
- consoleError.mockRestore();
220
- });
221
- });
222
-
223
- describe('when tags are missing', () => {
224
- const setMergeTags = jest.fn();
225
- const addEventListener = jest.fn();
226
-
227
- beforeEach(() => {
228
- scheduleUnlayerMergeTags({ addEventListener, setMergeTags }, undefined);
229
- });
230
-
231
- test('does not touch the editor', () => {
232
- expect(setMergeTags).not.toHaveBeenCalled();
233
- expect(addEventListener).not.toHaveBeenCalled();
234
- });
235
- });
236
- });
@@ -0,0 +1,186 @@
1
+ import { UnlayerStore } from '../store';
2
+ import type { CreateUnlayerEditorProps } from '../unlayer-interface';
3
+
4
+ const editorMock = {
5
+ addEventListener: jest.fn(),
6
+ removeEventListener: jest.fn(),
7
+ registerCallback: jest.fn(),
8
+ unregisterCallback: jest.fn(),
9
+ setMergeTags: jest.fn(),
10
+ loadDesign: jest.fn(),
11
+ setBodyValues: jest.fn(),
12
+ };
13
+
14
+ jest.mock('../loadScript', () => ({ loadScript: jest.fn().mockResolvedValue(undefined) }));
15
+ jest.mock('../unlayer', () => ({
16
+ ...jest.requireActual('../unlayer'),
17
+ createUnlayerEditor: jest.fn(() => editorMock),
18
+ }));
19
+
20
+ const customerNameTag = {
21
+ id: '10',
22
+ name: 'Customer Name',
23
+ propertyPath: '{{Customer.Name | safe | nl2br }}',
24
+ };
25
+
26
+ const scoreTag = {
27
+ id: 'form-7-abc',
28
+ name: 'Score',
29
+ propertyPath: '{{ __submission_fields["7"]["abc"] | safe | nl2br }}',
30
+ group: ['Forms', 'Customer Intake'],
31
+ };
32
+
33
+ const flatCustomer = {
34
+ '10': { name: 'Customer Name', value: '{{Customer.Name | safe | nl2br }}' },
35
+ };
36
+
37
+ const groupedScore = {
38
+ forms: {
39
+ name: 'Forms',
40
+ mergeTags: {
41
+ customer_intake: {
42
+ name: 'Customer Intake',
43
+ mergeTags: {
44
+ form_7_abc: {
45
+ name: 'Score',
46
+ value: '{{ __submission_fields["7"]["abc"] | safe | nl2br }}',
47
+ },
48
+ },
49
+ },
50
+ },
51
+ },
52
+ };
53
+
54
+ const fireEditorEvent = (event: string) => {
55
+ editorMock.addEventListener.mock.calls
56
+ .filter(([name]) => name === event)
57
+ .forEach(([, handler]) => handler());
58
+ };
59
+
60
+ describe('UnlayerStore merge tags', () => {
61
+ let store: UnlayerStore;
62
+ let consoleError: jest.SpyInstance;
63
+
64
+ const createStore = (props: Partial<CreateUnlayerEditorProps> = {}) => {
65
+ store = new UnlayerStore({ tools: [], ...props });
66
+ return store;
67
+ };
68
+
69
+ const initStore = async () => {
70
+ (window as any).unlayer = {};
71
+ const container = document.createElement('div');
72
+ container.appendChild(document.createElement('iframe'));
73
+ await store.init(container);
74
+ };
75
+
76
+ beforeEach(() => {
77
+ jest.clearAllMocks();
78
+ consoleError = jest.spyOn(console, 'error').mockImplementation(() => undefined);
79
+ });
80
+
81
+ afterEach(() => {
82
+ store.destroy();
83
+ consoleError.mockRestore();
84
+ });
85
+
86
+ describe('when the editor initializes with merge tags', () => {
87
+ beforeEach(async () => {
88
+ createStore({ mergeTags: [customerNameTag, scoreTag] });
89
+ await initStore();
90
+ });
91
+
92
+ test('does not touch the editor before it is ready', () => {
93
+ expect(editorMock.setMergeTags).not.toHaveBeenCalled();
94
+ });
95
+
96
+ test('applies the grouped shape once on editor:ready', () => {
97
+ fireEditorEvent('editor:ready');
98
+ fireEditorEvent('design:loaded');
99
+
100
+ expect(editorMock.setMergeTags).toHaveBeenCalledTimes(1);
101
+ expect(editorMock.setMergeTags).toHaveBeenCalledWith({
102
+ ...flatCustomer,
103
+ ...groupedScore,
104
+ });
105
+ });
106
+
107
+ test('applies on design:loaded when editor:ready never fires', () => {
108
+ fireEditorEvent('design:loaded');
109
+
110
+ expect(editorMock.setMergeTags).toHaveBeenCalledTimes(1);
111
+ expect(editorMock.setMergeTags).toHaveBeenCalledWith({
112
+ ...flatCustomer,
113
+ ...groupedScore,
114
+ });
115
+ });
116
+
117
+ test('retries on design:loaded when the first apply throws', () => {
118
+ editorMock.setMergeTags.mockImplementationOnce(() => {
119
+ throw new Error('not ready');
120
+ });
121
+
122
+ fireEditorEvent('editor:ready');
123
+ fireEditorEvent('design:loaded');
124
+ fireEditorEvent('design:loaded');
125
+
126
+ expect(editorMock.setMergeTags).toHaveBeenCalledTimes(2);
127
+ expect(consoleError).toHaveBeenCalledWith(
128
+ '[dte-unlayer]',
129
+ 'Failed to apply merge tags',
130
+ expect.any(Error),
131
+ );
132
+ });
133
+ });
134
+
135
+ describe('with setMergeTags', () => {
136
+ describe('when called before the editor is ready', () => {
137
+ beforeEach(async () => {
138
+ createStore({ mergeTags: [customerNameTag] });
139
+ store.unlayerRef.setMergeTags([customerNameTag, scoreTag]);
140
+ await initStore();
141
+ });
142
+
143
+ test('replaces the initial tags and applies once on ready', () => {
144
+ fireEditorEvent('editor:ready');
145
+
146
+ expect(editorMock.setMergeTags).toHaveBeenCalledTimes(1);
147
+ expect(editorMock.setMergeTags).toHaveBeenCalledWith({
148
+ ...flatCustomer,
149
+ ...groupedScore,
150
+ });
151
+ });
152
+ });
153
+
154
+ describe('when called after the editor is ready', () => {
155
+ beforeEach(async () => {
156
+ createStore({ mergeTags: [customerNameTag] });
157
+ await initStore();
158
+ fireEditorEvent('editor:ready');
159
+ editorMock.setMergeTags.mockClear();
160
+ });
161
+
162
+ test('applies immediately', () => {
163
+ store.unlayerRef.setMergeTags([customerNameTag, scoreTag]);
164
+
165
+ expect(editorMock.setMergeTags).toHaveBeenCalledTimes(1);
166
+ expect(editorMock.setMergeTags).toHaveBeenCalledWith({
167
+ ...flatCustomer,
168
+ ...groupedScore,
169
+ });
170
+ });
171
+
172
+ test('does not re-apply on later design:loaded events', () => {
173
+ store.unlayerRef.setMergeTags([customerNameTag, scoreTag]);
174
+ fireEditorEvent('design:loaded');
175
+
176
+ expect(editorMock.setMergeTags).toHaveBeenCalledTimes(1);
177
+ });
178
+
179
+ test('ignores an empty set', () => {
180
+ store.unlayerRef.setMergeTags([]);
181
+
182
+ expect(editorMock.setMergeTags).not.toHaveBeenCalled();
183
+ });
184
+ });
185
+ });
186
+ });
@@ -178,6 +178,8 @@ export function ConditionRow({
178
178
  <Flex direction="column" gap="3" style={{ width: '100%' }}>
179
179
  <div style={{ width: '100%' }}>
180
180
  <Combobox.Select
181
+ flex={1}
182
+ style={{ width: '100%' }}
181
183
  disableClearSelection
182
184
  itemToKey={(item: SourceOption | null) => item?.value ?? ''}
183
185
  itemToString={(item: SourceOption | null) => item?.label ?? ''}
@@ -203,12 +205,7 @@ export function ConditionRow({
203
205
  </Combobox.Content>
204
206
  </Combobox.Select>
205
207
  </div>
206
- <Flex
207
- direction="row"
208
- alignItems="flex-end"
209
- gap="2"
210
- style={{ flexWrap: 'wrap', rowGap: 8, width: '100%' }}
211
- >
208
+ <Flex direction="row" alignItems="flex-end" gap="2" style={{ width: '100%' }}>
212
209
  <div
213
210
  style={{
214
211
  display: 'flex',
@@ -219,89 +216,97 @@ export function ConditionRow({
219
216
  >
220
217
  <Chip label="IF" size="small" />
221
218
  </div>
222
- <Flex flex={1} style={{ minWidth: 160 }}>
223
- <Combobox.Select
224
- flex={1}
225
- style={{ width: '100%' }}
226
- disableClearSelection
227
- itemToKey={(item: DataPointOption | null) => item?.fullKey ?? ''}
228
- itemToString={(item: DataPointOption | null) => item?.title ?? ''}
229
- items={activeDataPointOptions}
230
- selectedItem={selectedDataPoint}
231
- onChange={handleDataPointChange}
232
- >
233
- <Combobox.SelectTrigger
234
- label="Data Point"
235
- placeholder={
236
- currentFormId ? 'Select form field...' : 'Select data point...'
219
+ <Flex
220
+ flex={1}
221
+ direction="row"
222
+ alignItems="flex-end"
223
+ gap="2"
224
+ style={{ minWidth: 0, width: '100%' }}
225
+ >
226
+ <Flex flex={1} style={{ minWidth: 0, width: '100%' }}>
227
+ <Combobox.Select
228
+ flex={1}
229
+ style={{ width: '100%' }}
230
+ disableClearSelection
231
+ itemToKey={(item: DataPointOption | null) => item?.fullKey ?? ''}
232
+ itemToString={(item: DataPointOption | null) => item?.title ?? ''}
233
+ items={activeDataPointOptions}
234
+ selectedItem={selectedDataPoint}
235
+ onChange={handleDataPointChange}
236
+ >
237
+ <Combobox.SelectTrigger
238
+ label="Data Point"
239
+ placeholder={
240
+ currentFormId ? 'Select form field...' : 'Select data point...'
241
+ }
242
+ size="small"
243
+ />
244
+ <Combobox.Content>
245
+ {({ items }: { items: DataPointOption[] }) => (
246
+ <Combobox.List>
247
+ {items.map((item, i) => (
248
+ <Combobox.Item index={i} item={item} key={item.fullKey}>
249
+ {item.title}
250
+ </Combobox.Item>
251
+ ))}
252
+ </Combobox.List>
253
+ )}
254
+ </Combobox.Content>
255
+ </Combobox.Select>
256
+ </Flex>
257
+ <Flex flex={1} style={{ minWidth: 0, width: '100%' }}>
258
+ <Combobox.Select
259
+ flex={1}
260
+ style={{ width: '100%' }}
261
+ disableClearSelection
262
+ itemToKey={(item: OperatorOption | null) => item?.value ?? ''}
263
+ itemToString={(item: OperatorOption | null) => item?.label ?? ''}
264
+ items={operatorItems}
265
+ selectedItem={selectedOperator}
266
+ onChange={(item: OperatorOption | null) =>
267
+ onChange({
268
+ ...condition,
269
+ operator: (item?.value ??
270
+ 'is_equal_to') as SingleCondition['operator'],
271
+ })
237
272
  }
238
- size="small"
239
- />
240
- <Combobox.Content>
241
- {({ items }: { items: DataPointOption[] }) => (
242
- <Combobox.List>
243
- {items.map((item, i) => (
244
- <Combobox.Item index={i} item={item} key={item.fullKey}>
245
- {item.title}
246
- </Combobox.Item>
247
- ))}
248
- </Combobox.List>
249
- )}
250
- </Combobox.Content>
251
- </Combobox.Select>
252
- </Flex>
253
- <Flex flex={1} style={{ minWidth: 160 }}>
254
- <Combobox.Select
255
- flex={1}
256
- style={{ width: '100%' }}
257
- disableClearSelection
258
- itemToKey={(item: OperatorOption | null) => item?.value ?? ''}
259
- itemToString={(item: OperatorOption | null) => item?.label ?? ''}
260
- items={operatorItems}
261
- selectedItem={selectedOperator}
262
- onChange={(item: OperatorOption | null) =>
263
- onChange({
264
- ...condition,
265
- operator: (item?.value ??
266
- 'is_equal_to') as SingleCondition['operator'],
267
- })
268
- }
269
- >
270
- <Combobox.SelectTrigger
271
- label="Condition"
272
- placeholder="Select..."
273
- size="small"
274
- />
275
- <Combobox.Content>
276
- {({ items }: { items: OperatorOption[] }) => (
277
- <Combobox.List>
278
- {items.map((item, i) => (
279
- <Combobox.Item index={i} item={item} key={item.value}>
280
- {item.label}
281
- </Combobox.Item>
282
- ))}
283
- </Combobox.List>
284
- )}
285
- </Combobox.Content>
286
- </Combobox.Select>
287
- </Flex>
288
- {!isValueLess && (
289
- <Flex flex={1} style={{ minWidth: 160 }}>
290
- <LookupValueControl
291
- value={condition.value}
292
- fieldType={fieldType}
293
- lookupSource={selectedDataPoint?.lookupSource}
294
- onChange={value => onChange({ ...condition, value })}
295
- />
273
+ >
274
+ <Combobox.SelectTrigger
275
+ label="Condition"
276
+ placeholder="Select..."
277
+ size="small"
278
+ />
279
+ <Combobox.Content>
280
+ {({ items }: { items: OperatorOption[] }) => (
281
+ <Combobox.List>
282
+ {items.map((item, i) => (
283
+ <Combobox.Item index={i} item={item} key={item.value}>
284
+ {item.label}
285
+ </Combobox.Item>
286
+ ))}
287
+ </Combobox.List>
288
+ )}
289
+ </Combobox.Content>
290
+ </Combobox.Select>
296
291
  </Flex>
297
- )}
292
+ {!isValueLess && (
293
+ <Flex flex="0 0 186px" style={{ minWidth: 0 }}>
294
+ <LookupValueControl
295
+ value={condition.value}
296
+ fieldType={fieldType}
297
+ lookupSource={selectedDataPoint?.lookupSource}
298
+ onChange={value => onChange({ ...condition, value })}
299
+ />
300
+ </Flex>
301
+ )}
302
+ </Flex>
298
303
  {canRemove && (
299
304
  <div
300
305
  style={{
301
306
  display: 'flex',
302
307
  alignItems: 'flex-end',
303
308
  flexShrink: 0,
304
- padding: '4px 8px',
309
+ paddingBottom: 4,
305
310
  }}
306
311
  >
307
312
  <Button